diff --git a/Documentation/bridge.md b/Documentation/bridge.md index bda5ac5c..f9c7f2c4 100644 --- a/Documentation/bridge.md +++ b/Documentation/bridge.md @@ -19,6 +19,7 @@ If the bridge is missing, the plugin will create one on first use and, if gatewa "bridge": "mynet0", "isGateway": true, "ipMasq": true, + "hairpinMode": true, "ipam": { "type": "host-local", "subnet": "10.10.0.0/16" @@ -34,4 +35,5 @@ If the bridge is missing, the plugin will create one on first use and, if gatewa * `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. diff --git a/plugins/main/bridge/bridge.go b/plugins/main/bridge/bridge.go index 77c52156..9082b05f 100644 --- a/plugins/main/bridge/bridge.go +++ b/plugins/main/bridge/bridge.go @@ -36,10 +36,11 @@ const defaultBrName = "cni0" 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() { @@ -123,7 +124,7 @@ func ensureBridge(brName string, mtu int) (*netlink.Bridge, error) { 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 { @@ -151,6 +152,11 @@ func setupVeth(netns string, br *netlink.Bridge, ifName string, mtu int) 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 } @@ -180,7 +186,7 @@ func cmdAdd(args *skel.CmdArgs) error { 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 }