From 1ad6ecd556423c12ffe6c1dabacff9b5c1adafb2 Mon Sep 17 00:00:00 2001 From: Onur Filiz Date: Fri, 2 Aug 2019 13:54:10 -0700 Subject: [PATCH] vpc-shared-eni: Enable IP forwarding and ARP proxy when using L3 mode --- network/ipcfg/ip.go | 49 +++++++++++++++++++ .../vpc-shared-eni/network/bridge_linux.go | 32 +++++++++++- 2 files changed, 80 insertions(+), 1 deletion(-) create mode 100644 network/ipcfg/ip.go diff --git a/network/ipcfg/ip.go b/network/ipcfg/ip.go new file mode 100644 index 00000000..a1d04545 --- /dev/null +++ b/network/ipcfg/ip.go @@ -0,0 +1,49 @@ +// Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"). You may +// not use this file except in compliance with the License. A copy of the +// License is located at +// +// http://aws.amazon.com/apache2.0/ +// +// or in the "license" file accompanying this file. This file is distributed +// on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either +// express or implied. See the License for the specific language governing +// permissions and limitations under the License. + +package ipcfg + +import ( + "bytes" + "fmt" + "io/ioutil" + "strconv" +) + +const ( + ipv4Forwarding = "/proc/sys/net/ipv4/conf/%s/forwarding" + ipv4ProxyARP = "/proc/sys/net/ipv4/conf/%s/proxy_arp" +) + +// SetIPv4Forwarding sets the IPv4 forwarding property of an interface to the given value. +func SetIPv4Forwarding(ifName string, value int) error { + return set(fmt.Sprintf(ipv4Forwarding, ifName), value) +} + +// SetIPv4ProxyARP sets the IPv4 proxy ARP property of an interface to the given value. +func SetIPv4ProxyARP(ifName string, value int) error { + return set(fmt.Sprintf(ipv4ProxyARP, ifName), value) +} + +// Set sets a system variable to the given value. +func set(name string, value int) error { + valueStr := strconv.Itoa(value) + + // Do not rewrite if the value is already set. + currValue, err := ioutil.ReadFile(name) + if err == nil && bytes.Equal(bytes.TrimSpace(currValue), []byte(valueStr)) { + return nil + } + + return ioutil.WriteFile(name, []byte(valueStr), 0644) +} diff --git a/plugins/vpc-shared-eni/network/bridge_linux.go b/plugins/vpc-shared-eni/network/bridge_linux.go index 32c74d42..39778438 100644 --- a/plugins/vpc-shared-eni/network/bridge_linux.go +++ b/plugins/vpc-shared-eni/network/bridge_linux.go @@ -20,6 +20,7 @@ import ( "github.com/aws/amazon-vpc-cni-plugins/network/ebtables" "github.com/aws/amazon-vpc-cni-plugins/network/eni" + "github.com/aws/amazon-vpc-cni-plugins/network/ipcfg" "github.com/aws/amazon-vpc-cni-plugins/network/netns" "github.com/aws/amazon-vpc-cni-plugins/network/vpc" "github.com/aws/amazon-vpc-cni-plugins/plugins/vpc-shared-eni/config" @@ -456,8 +457,10 @@ func (nb *BridgeBuilder) createBridge( return 0, err } - // Setup bridge layer2 configuration. if bridgeType == config.BridgeTypeL2 { + // In layer2 configuration, the bridge inherits shared ENI's IP address and default route. + // Frames are switched between veth pairs and the shared ENI. + // Assign IP address to bridge. log.Infof("Assigning IP address %v to bridge link %s.", ipAddress, bridgeName) address := &netlink.Addr{IPNet: ipAddress} @@ -485,6 +488,33 @@ func (nb *BridgeBuilder) createBridge( log.Errorf("Failed to add IP route %+v: %v.", route, err) return 0, err } + } else { + // In layer3 configuration, the IP address and default route remain on the shared ENI. + // IP datagrams are routed between the bridge and the shared ENI. + + // Bridge proxies ARP requests originating from veth pairs to the VPC. + log.Infof("Enabling IPv4 proxy ARP on %s.", bridgeName) + err = ipcfg.SetIPv4ProxyARP(bridgeName, 1) + if err != nil { + log.Errorf("Failed to enable IPv4 proxy ARP on %s: %v.", bridgeName, err) + return 0, err + } + + // Enable IPv4 forwarding on the bridge and shared ENI, so that IP datagrams can be + // routed between them. + log.Infof("Enabling IPv4 forwarding on %s.", bridgeName) + err = ipcfg.SetIPv4Forwarding(bridgeName, 1) + if err != nil { + log.Errorf("Failed to enable IPv4 forwarding on %s: %v.", bridgeName, err) + return 0, err + } + + log.Infof("Enabling IPv4 forwarding on %s.", sharedENI.GetLinkName()) + err = ipcfg.SetIPv4Forwarding(sharedENI.GetLinkName(), 1) + if err != nil { + log.Errorf("Failed to enable IPv4 forwarding on %s: %v.", sharedENI.GetLinkName(), err) + return 0, err + } } return bridgeLink.Attrs().Index, nil