"bridge": "mynet0",
"isGateway": true,
"ipMasq": true,
+ "hairpinMode": true,
"ipam": {
"type": "host-local",
"subnet": "10.10.0.0/16"
* `isGateway` (boolean, optional): assign an IP address to the bridge. Defaults to false.
* `ipMasq` (boolean, optional): set up IP Masquerade on the host for traffic originating from this network and destined outside of it. Defaults to false.
* `mtu` (integer, optional): explicitly set MTU to the specified value. Defaults to the value chosen by the kernel.
+* `hairpinMode` (boolean, optional): set hairpin mode for interfaces on the bridge. Defaults to false.
* `ipam` (dictionary, required): IPAM configuration to be used for this network.
type NetConf struct {
types.NetConf
- BrName string `json:"bridge"`
- IsGW bool `json:"isGateway"`
- IPMasq bool `json:"ipMasq"`
- MTU int `json:"mtu"`
+ BrName string `json:"bridge"`
+ IsGW bool `json:"isGateway"`
+ IPMasq bool `json:"ipMasq"`
+ MTU int `json:"mtu"`
+ HairpinMode bool `json:"hairpinMode"`
}
func init() {
return br, nil
}
-func setupVeth(netns string, br *netlink.Bridge, ifName string, mtu int) error {
+func setupVeth(netns string, br *netlink.Bridge, ifName string, mtu int, hairpinMode bool) error {
var hostVethName string
err := ns.WithNetNSPath(netns, false, func(hostNS *os.File) error {
return fmt.Errorf("failed to connect %q to bridge %v: %v", hostVethName, br.Attrs().Name, err)
}
+ // set hairpin mode
+ if err = netlink.LinkSetHairpin(hostVeth, hairpinMode); err != nil {
+ return fmt.Errorf("failed to setup hairpin mode for %v: %v", hostVethName, err)
+ }
+
return nil
}
return err
}
- if err = setupVeth(args.Netns, br, args.IfName, n.MTU); err != nil {
+ if err = setupVeth(args.Netns, br, args.IfName, n.MTU, n.HairpinMode); err != nil {
return err
}