Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bridge proxy arp #1744

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 49 additions & 0 deletions drivers/bridge/bridge.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ type networkConfiguration struct {
EnableIPv6 bool
EnableIPMasquerade bool
EnableICC bool
EnableProxyArp bool
Mtu int
DefaultBindingIP net.IP
DefaultBridge bool
Expand Down Expand Up @@ -240,6 +241,10 @@ func (c *networkConfiguration) fromLabels(labels map[string]string) error {
if c.DefaultBindingIP = net.ParseIP(value); c.DefaultBindingIP == nil {
return parseErr(label, value, "nil ip")
}
case EnableProxyArp:
if c.EnableProxyArp, err = strconv.ParseBool(value); err != nil {
return parseErr(label, value, err.Error())
}
case netlabel.ContainerIfacePrefix:
c.ContainerIfacePrefix = value
}
Expand Down Expand Up @@ -449,6 +454,7 @@ func parseNetworkGenericOptions(data interface{}) (*networkConfiguration, error)
config = &networkConfiguration{
EnableICC: true,
EnableIPMasquerade: true,
EnableProxyArp: false,
}
err = config.fromLabels(opt)
case options.Generic:
Expand Down Expand Up @@ -1043,6 +1049,49 @@ func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo,
}
}

// The bridge proxy arp feature requires three things to happen:
// 1) Set the proxyarpwifi flag on the container side bridge port to disable ARP packet flooding.
// 2) Generate an arp entry in the host's ARP table mapping the containers IP address to its MAC.
// 3) Generate a static FDB entry for the containers MAC address.

if config.EnableProxyArp {

BridgeIF, err := d.nlh.LinkByName(config.BridgeName)
if err != nil {
return fmt.Errorf("could not find interface with destination name %s: %v", config.BridgeName, err)
}

err = d.nlh.LinkSetBrProxyArpWiFi(host, true)
if err != nil {
return fmt.Errorf("unable to set BridgeProxyArp mode on %s: %v", hostIfName, err)
}

nlnh := &netlink.Neigh{
IP: endpoint.addr.IP,
HardwareAddr: endpoint.macAddress,
}

// Generate the permanent arp entry.
nlnh.State = netlink.NUD_PERMANENT
nlnh.LinkIndex = BridgeIF.Attrs().Index

if err := d.nlh.NeighSet(nlnh); err != nil {
return fmt.Errorf("Failed to add neighbor entry: %v", err)
}
logrus.Debugf("An arp entry has been created: Interface=%s Ip=%s MAC=%s", config.BridgeName, nlnh.IP, nlnh.HardwareAddr)

// Generate the static fdb entry.
nlnh.State = netlink.NUD_NOARP
nlnh.Flags = netlink.NTF_MASTER
nlnh.Family = syscall.AF_BRIDGE
nlnh.LinkIndex = host.Attrs().Index

if err := d.nlh.NeighSet(nlnh); err != nil {
return fmt.Errorf("Failed to add fdb entry: %v", err)
}
logrus.Debugf("An fdb entry has been created: Interface=%s MAC=%s", hostIfName, nlnh.HardwareAddr)
}

// Up the host interface after finishing all netlink configuration
if err = d.nlh.LinkSetUp(host); err != nil {
return fmt.Errorf("could not set link up for host interface %s: %v", hostIfName, err)
Expand Down
5 changes: 5 additions & 0 deletions drivers/bridge/bridge_store.go
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ func (ncfg *networkConfiguration) MarshalJSON() ([]byte, error) {
nMap["EnableIPv6"] = ncfg.EnableIPv6
nMap["EnableIPMasquerade"] = ncfg.EnableIPMasquerade
nMap["EnableICC"] = ncfg.EnableICC
nMap["EnableProxyArp"] = ncfg.EnableProxyArp
nMap["Mtu"] = ncfg.Mtu
nMap["Internal"] = ncfg.Internal
nMap["DefaultBridge"] = ncfg.DefaultBridge
Expand Down Expand Up @@ -201,6 +202,10 @@ func (ncfg *networkConfiguration) UnmarshalJSON(b []byte) error {
ncfg.BridgeIfaceCreator = ifaceCreator(v.(float64))
}

if v, ok := nMap["EnableProxyArp"]; ok {
ncfg.EnableProxyArp = v.(bool)
}

return nil
}

Expand Down
56 changes: 56 additions & 0 deletions drivers/bridge/bridge_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,7 @@ func TestCreateFullOptionsLabels(t *testing.T) {
DefaultBridge: "true",
EnableICC: "true",
EnableIPMasquerade: "true",
EnableProxyArp: "true",
DefaultBindingIP: bndIPs,
}

Expand Down Expand Up @@ -319,6 +320,10 @@ func TestCreateFullOptionsLabels(t *testing.T) {
t.Fatal("incongruent EnableIPMasquerade in bridge network")
}

if !nw.config.EnableProxyArp {
t.Fatal("incongruent EnableProxyArp in bridge network")
}

bndIP := net.ParseIP(bndIPs)
if !bndIP.Equal(nw.config.DefaultBindingIP) {
t.Fatalf("Unexpected: %v", nw.config.DefaultBindingIP)
Expand Down Expand Up @@ -1071,3 +1076,54 @@ func TestCreateWithExistingBridge(t *testing.T) {
t.Fatal("Deleting bridge network that using existing bridge interface unexpectedly deleted the bridge interface")
}
}

func TestProxyArp(t *testing.T) {
if !testutils.IsRunningInContainer() {
defer testutils.SetupTestOSContext(t)()
}
d := newDriver()

err := d.configure(nil)
if err != nil {
t.Fatalf("Failed to setup driver config: %v", err)
}

netconfig := &networkConfiguration{BridgeName: DefaultBridgeName, EnableProxyArp: true, DefaultBridge: true}
genericOption := make(map[string]interface{})
genericOption[netlabel.GenericData] = netconfig

ipdList := getIPv4Data(t, "")

err = d.CreateNetwork("ProxyArpTest", genericOption, nil, ipdList, nil)
if err != nil {
t.Fatalf("Bridge creation failed: %v", err)
}

te := newTestEndpoint(ipdList[0].Pool, 10)
err = d.CreateEndpoint("ProxyArpTest", "ep", te.Interface(), nil)
if err != nil {
t.Fatalf("Failed to create endpoint: %v", err)
}

BridgeIF, err := netlink.LinkByName(DefaultBridgeName)
if err != nil {
t.Fatalf("Failed to lookup bridge interface: %v", err)
}

dump, err := netlink.NeighList(BridgeIF.Attrs().Index, 0)
if err != nil {
t.Errorf("Failed to NeighList: %v", err)
}

FoundNeigh := 0
for _, v := range dump {
if v.State&netlink.NUD_PERMANENT != 0 &&
bytes.Equal(te.iface.mac, v.HardwareAddr) &&
te.iface.addr.IP.Equal(v.IP) {
FoundNeigh++
}
}
if FoundNeigh != 1 {
t.Errorf("Expected a single match in the neighbor table got %d matches", FoundNeigh)
}
}
3 changes: 3 additions & 0 deletions drivers/bridge/labels.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,7 @@ const (

// DefaultBridge label
DefaultBridge = "com.docker.network.bridge.default_bridge"

// EnableProxyArp label
EnableProxyArp = "com.docker.network.bridge.proxyarp"
)
16 changes: 7 additions & 9 deletions vendor.conf
Original file line number Diff line number Diff line change
Expand Up @@ -10,32 +10,30 @@ github.com/codegangsta/cli a65b733b303f0055f8d324d805f393cd3e7a7904
github.com/coreos/etcd 925d1d74cec8c3b169c52fd4b2dc234a35934fce
github.com/coreos/go-systemd b4a58d95188dd092ae20072bac14cece0e67c388
github.com/deckarep/golang-set ef32fa3046d9f249d399f98ebaf9be944430fd1d

github.com/docker/docker 9c96768eae4b3a65147b47a55c850c103ab8972d
github.com/docker/go-connections 34b5052da6b11e27f5f2e357b38b571ddddd3928
github.com/docker/go-events 2e7d352816128aa84f4d29b2a21d400133701a0d
github.com/docker/go-units 8e2d4523730c73120e10d4652f36ad6010998f4e
github.com/docker/libkv 1d8431073ae03cdaedb198a89722f3aab6d418ef

github.com/godbus/dbus 5f6efc7ef2759c81b7ba876593971bfce311eab3
github.com/gogo/protobuf 8d70fb3182befc465c4a1eac8ad4d38ff49778e2
github.com/golang/protobuf/proto f7137ae6b19afbfd61a94b746fda3b3fe0491874
github.com/golang/protobuf f7137ae6b19afbfd61a94b746fda3b3fe0491874
github.com/gorilla/context 215affda49addc4c8ef7e2534915df2c8c35c6cd
github.com/gorilla/mux 8096f47503459bcc74d1f4c487b7e6e42e5746b5
github.com/hashicorp/consul/api 954aec66231b79c161a4122b023fbcad13047f79
github.com/hashicorp/go-msgpack/codec 71c2886f5a673a35f909803f38ece5810165097b
github.com/hashicorp/consul 954aec66231b79c161a4122b023fbcad13047f79
github.com/hashicorp/go-msgpack 71c2886f5a673a35f909803f38ece5810165097b
github.com/hashicorp/go-multierror 2167c8ec40776024589f483a6b836489e47e1049
github.com/hashicorp/memberlist 88ac4de0d1a0ca6def284b571342db3b777a4c37
github.com/hashicorp/serf 598c54895cc5a7b1a24a398d635e8c0ea0959870
github.com/mattn/go-shellwords 525bedee691b5a8df547cb5cf9f86b7fb1883e24
github.com/miekg/dns d27455715200c7d3e321a1e5cadb27c9ee0b0f02
github.com/opencontainers/runc/libcontainer ba1568de399395774ad84c2ace65937814c542ed
github.com/samuel/go-zookeeper/zk d0e0d8e11f318e000a8cc434616d69e329edc374
github.com/opencontainers/runc ba1568de399395774ad84c2ace65937814c542ed
github.com/samuel/go-zookeeper d0e0d8e11f318e000a8cc434616d69e329edc374
github.com/seccomp/libseccomp-golang 1b506fc7c24eec5a3693cdcbed40d9c226cfc6a1
github.com/stretchr/testify dab07ac62d4905d3e48d17dc549c684ac3b7c15a
github.com/syndtr/gocapability/capability 2c00daeb6c3b45114c80ac44119e7b8801fdd852
github.com/syndtr/gocapability 2c00daeb6c3b45114c80ac44119e7b8801fdd852
github.com/ugorji/go f1f1a805ed361a0e078bb537e4ea78cd37dcf065
github.com/vishvananda/netlink 1e86b2bee5b6a7d377e4c02bb7f98209d6a7297c
github.com/vishvananda/netlink b71e0bb214aebd980216cb2516e8bd7bca9e9672
github.com/vishvananda/netns 604eaf189ee867d8c147fafc28def2394e878d25
golang.org/x/net c427ad74c6d7a814201695e9ffde0c5d400a7674
golang.org/x/sys 8f0908ab3b2457e2e15403d3697c9ef5cb4b57a9
Expand Down
12 changes: 7 additions & 5 deletions vendor/github.com/vishvananda/netlink/addr.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 15 additions & 1 deletion vendor/github.com/vishvananda/netlink/addr_linux.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 0 additions & 4 deletions vendor/github.com/vishvananda/netlink/filter_linux.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

22 changes: 19 additions & 3 deletions vendor/github.com/vishvananda/netlink/link_linux.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

29 changes: 29 additions & 0 deletions vendor/github.com/vishvananda/netlink/nl/addr_linux.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion vendor/github.com/vishvananda/netlink/nl/link_linux.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading