Skip to content
Closed
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
48 changes: 48 additions & 0 deletions drivers/bridge/bridge.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ type networkConfiguration struct {
BridgeName string
EnableIPv6 bool
EnableIPMasquerade bool
NDPProxyInterface string
EnableICC bool
Mtu int
DefaultBindingIP net.IP
Expand Down Expand Up @@ -215,6 +216,8 @@ func (c *networkConfiguration) fromLabels(labels map[string]string) error {
if c.EnableIPMasquerade, err = strconv.ParseBool(value); err != nil {
return parseErr(label, value, err.Error())
}
case NDPProxyInterface:
c.NDPProxyInterface = value
case EnableICC:
if c.EnableICC, err = strconv.ParseBool(value); err != nil {
return parseErr(label, value, err.Error())
Expand Down Expand Up @@ -680,6 +683,7 @@ func (d *driver) createNetwork(config *networkConfiguration) error {
bridgeSetup.queueStep(setupBridgeIPv4)

enableIPv6Forwarding := d.config.EnableIPForwarding && config.AddressIPv6 != nil
enableNDPProxying := config.NDPProxyInterface != "" && config.AddressIPv6 != nil

// Conditionally queue setup steps depending on configuration values.
for _, step := range []struct {
Expand All @@ -699,6 +703,9 @@ func (d *driver) createNetwork(config *networkConfiguration) error {
// Enable IPv6 Forwarding
{enableIPv6Forwarding, setupIPv6Forwarding},

// Enable NDP Proxying
{enableNDPProxying, setupNDPProxying},

// Setup Loopback Adresses Routing
{!d.config.EnableUserlandProxy, setupLoopbackAdressesRouting},

Expand Down Expand Up @@ -1019,6 +1026,27 @@ func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo,
}
}

// Add a neighbor proxy if using NDP proxying
if config.NDPProxyInterface != "" && config.EnableIPv6 {
link, err := d.nlh.LinkByName(config.NDPProxyInterface)
if err != nil {
return fmt.Errorf("could not find link for ndp proxy interface %q: %v", config.NDPProxyInterface, err)
}
neighbor := netlink.Neigh{
LinkIndex: link.Attrs().Index,
Family: netlink.FAMILY_V6,
State: netlink.NUD_PERMANENT,
Type: netlink.NDA_UNSPEC,
Flags: netlink.NTF_PROXY,
IP: endpoint.addrv6.IP,
HardwareAddr: endpoint.macAddress,
}
if err := d.nlh.NeighAdd(&neighbor); err != nil {
logrus.Warnf("could not add the neighbor proxy: %v", err)
return err
}
}

if err = d.storeUpdate(endpoint); err != nil {
return fmt.Errorf("failed to save bridge endpoint %s to store: %v", endpoint.id[0:7], err)
}
Expand Down Expand Up @@ -1077,6 +1105,26 @@ func (d *driver) DeleteEndpoint(nid, eid string) error {
}
}()

// Try removal of neighbor proxy. Discard error: it is a best effort.
// Also make sure defer does not see this error either.
if n.config.NDPProxyInterface != "" && n.config.EnableIPv6 {
link, err := d.nlh.LinkByName(n.config.NDPProxyInterface)
if err != nil {
Logrus.Warnf("could not remove ndp neighbour, because could not find link for ndp proxy interface %q: %v", config.NDPProxyInterface, err)
} else {
neighbor := netlink.Neigh{
LinkIndex: link.Attrs().Index,
Family: netlink.FAMILY_V6,
State: netlink.NUD_PERMANENT,
Type: netlink.NDA_UNSPEC,
Flags: netlink.NTF_PROXY,
IP: ep.addrv6.IP,
HardwareAddr: ep.macAddress,
}
d.nlh.NeighDel(&neighbor)
}
}

// Try removal of link. Discard error: it is a best effort.
// Also make sure defer does not see this error either.
if link, err := d.nlh.LinkByName(ep.srcName); err == nil {
Expand Down
4 changes: 4 additions & 0 deletions drivers/bridge/bridge_store.go
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ func (ncfg *networkConfiguration) MarshalJSON() ([]byte, error) {
nMap["BridgeName"] = ncfg.BridgeName
nMap["EnableIPv6"] = ncfg.EnableIPv6
nMap["EnableIPMasquerade"] = ncfg.EnableIPMasquerade
nMap["NDPProxyInterface"] = ncfg.NDPProxyInterface
nMap["EnableICC"] = ncfg.EnableICC
nMap["Mtu"] = ncfg.Mtu
nMap["Internal"] = ncfg.Internal
Expand Down Expand Up @@ -185,6 +186,9 @@ func (ncfg *networkConfiguration) UnmarshalJSON(b []byte) error {
ncfg.BridgeName = nMap["BridgeName"].(string)
ncfg.EnableIPv6 = nMap["EnableIPv6"].(bool)
ncfg.EnableIPMasquerade = nMap["EnableIPMasquerade"].(bool)
if v, ok := nMap["NDPProxyInterface"]; ok {
ncfg.NDPProxyInterface = v.(string)
}
ncfg.EnableICC = nMap["EnableICC"].(bool)
ncfg.Mtu = int(nMap["Mtu"].(float64))
if v, ok := nMap["Internal"]; ok {
Expand Down
23 changes: 23 additions & 0 deletions drivers/bridge/bridge_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
"github.com/docker/libnetwork/options"
"github.com/docker/libnetwork/testutils"
"github.com/docker/libnetwork/types"
"github.com/vishvananda/netlink"
)

func init() {
Expand Down Expand Up @@ -269,13 +270,15 @@ func TestCreateFullOptionsLabels(t *testing.T) {
gwV6s := "2001:db8:2600:2700:2800::25/80"
nwV6, _ := types.ParseCIDR(nwV6s)
gwV6, _ := types.ParseCIDR(gwV6s)
ndpPxyIface := "lo"

labels := map[string]string{
BridgeName: DefaultBridgeName,
DefaultBridge: "true",
EnableICC: "true",
EnableIPMasquerade: "true",
DefaultBindingIP: bndIPs,
NDPProxyInterface: ndpPxyIface,
}

netOption := make(map[string]interface{})
Expand Down Expand Up @@ -318,6 +321,10 @@ func TestCreateFullOptionsLabels(t *testing.T) {
t.Fatalf("incongruent EnableIPMasquerade in bridge network")
}

if nw.config.NDPProxyInterface != ndpPxyIface {
t.Fatalf("incongruend NDPProxyInterface in bridge network")
}

bndIP := net.ParseIP(bndIPs)
if !bndIP.Equal(nw.config.DefaultBindingIP) {
t.Fatalf("Unexpected: %v", nw.config.DefaultBindingIP)
Expand Down Expand Up @@ -347,6 +354,22 @@ func TestCreateFullOptionsLabels(t *testing.T) {
if te.Interface().AddressIPv6().IP.String() != "2001:db8:2600:2700:2800:aabb:ccdd:eeff" {
t.Fatalf("Unexpected endpoint IPv6 address: %v", te.Interface().AddressIPv6().IP)
}

// Check that the neighbor proxy was created by trying to delete it,
// because netlink.NeighList currently can't list proxies.
link, _ := d.nlh.LinkByName(ndpPxyIface)
err = d.nlh.NeighDel(&netlink.Neigh{
LinkIndex: link.Attrs().Index,
Family: netlink.FAMILY_V6,
State: netlink.NUD_PERMANENT,
Type: netlink.NDA_UNSPEC,
Flags: netlink.NTF_PROXY,
IP: te.Interface().AddressIPv6().IP,
HardwareAddr: te.Interface().MacAddress(),
})
if err != nil {
t.Fatalf("Cannot delete neighbor proxy, suggesting it wasn't created: %v", err)
}
}

func TestCreate(t *testing.T) {
Expand Down
3 changes: 3 additions & 0 deletions drivers/bridge/labels.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ const (
// EnableIPMasquerade label for bridge driver
EnableIPMasquerade = "com.docker.network.bridge.enable_ip_masquerade"

// NDPProxyInterface label for bridge driver
NDPProxyInterface = "com.docker.network.bridge.ndp_proxy_interface"

// EnableICC label
EnableICC = "com.docker.network.bridge.enable_icc"

Expand Down
30 changes: 30 additions & 0 deletions drivers/bridge/setup_ipv6.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ const (
ipv6ForwardConfPerm = 0644
ipv6ForwardConfDefault = "/proc/sys/net/ipv6/conf/default/forwarding"
ipv6ForwardConfAll = "/proc/sys/net/ipv6/conf/all/forwarding"
ndpProxyConfPerm = 0644
ndpProxyConfDefault = "/proc/sys/net/ipv6/conf/default/proxy_ndp"
)

func init() {
Expand Down Expand Up @@ -117,3 +119,31 @@ func setupIPv6Forwarding(config *networkConfiguration, i *bridgeInterface) error

return nil
}

func setupNDPProxying(config *networkConfiguration, i *bridgeInterface) error {
// Get current NDP default proxying setup
ndpProxyDataDefault, err := ioutil.ReadFile(ndpProxyConfDefault)
if err != nil {
return fmt.Errorf("Cannot read NDP default proxying setup: %v", err)
}
// Enable NDP default proxying only if it is not already enabled
if ndpProxyDataDefault[0] != '1' {
if err := ioutil.WriteFile(ndpProxyConfDefault, []byte{'1', '\n'}, ndpProxyConfPerm); err != nil {
logrus.Warnf("Unable to enable NDP default proxying: %v", err)
}
}

// Get interface with proxy_ndp enabled.
ndpProxyConfPath := fmt.Sprintf("/proc/sys/net/ipv6/conf/%s/proxy_ndp", config.NDPProxyInterface)
if err != nil {
return fmt.Errorf("Unable to enable NDP proxying for interface %s: %v", config.NDPProxyInterface,err)
}
// Enable NDP proxying only if it is not already enabled
if ndpProxyConfPerm[0] != '1' {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This won't build

if err := ioutil.WriteFile(ndpProxyConfPath, []byte{'1', '\n'}, ndpProxyConfPerm); err != nil {
logrus.Warnf("Unable to enable NDP proxying for interface %s: %v", config.NDPProxyInterface,err)
}
}

return nil
}