Skip to content

Commit

Permalink
Merge pull request #196 from liwenwu-amazon/primary-intf-name
Browse files Browse the repository at this point in the history
Add logic to dynamically discover primary interface name
  • Loading branch information
liwenwu-amazon authored Oct 8, 2018
2 parents 645535e + b569b59 commit 9a4a018
Show file tree
Hide file tree
Showing 7 changed files with 67 additions and 14 deletions.
2 changes: 1 addition & 1 deletion ipamd/ipamd.go
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ func (c *IPAMContext) nodeInit() error {

primaryIP := net.ParseIP(c.awsClient.GetLocalIPv4())

err = c.networkClient.SetupHostNetwork(vpcCIDR, &primaryIP)
err = c.networkClient.SetupHostNetwork(vpcCIDR, c.awsClient.GetPrimaryENImac(), &primaryIP)
if err != nil {
log.Error("Failed to setup host network", err)
return errors.Wrap(err, "ipamd init: failed to setup host network")
Expand Down
3 changes: 2 additions & 1 deletion ipamd/ipamd_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,8 @@ func TestNodeInit(t *testing.T) {

_, vpcCIDR, _ := net.ParseCIDR(vpcCIDR)
primaryIP := net.ParseIP(ipaddr01)
mockNetwork.EXPECT().SetupHostNetwork(vpcCIDR, &primaryIP).Return(nil)
mockAWS.EXPECT().GetPrimaryENImac().Return("")
mockNetwork.EXPECT().SetupHostNetwork(vpcCIDR, "", &primaryIP).Return(nil)

//primaryENIid
mockAWS.EXPECT().GetPrimaryENI().Return(primaryENIid)
Expand Down
7 changes: 7 additions & 0 deletions pkg/awsutils/awsutils.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,8 @@ type APIs interface {

// GetENILimit returns the number of enis can be attached to an instance
GetENILimit() (int, error)
// GetPrimaryENImac returns the mac address of the primary eni
GetPrimaryENImac() string
}

// EC2InstanceMetadataCache caches instance metadata
Expand Down Expand Up @@ -939,3 +941,8 @@ func (cache *EC2InstanceMetadataCache) GetLocalIPv4() string {
func (cache *EC2InstanceMetadataCache) GetPrimaryENI() string {
return cache.primaryENI
}

// GetPrimaryENIMAC returns the mac address of primary eni
func (cache *EC2InstanceMetadataCache) GetPrimaryENImac() string {
return cache.primaryENImac
}
12 changes: 12 additions & 0 deletions pkg/awsutils/mocks/awsutils_mocks.go

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

10 changes: 5 additions & 5 deletions pkg/networkutils/mocks/network_mocks.go

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

41 changes: 37 additions & 4 deletions pkg/networkutils/network.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ const (
// NetworkAPIs defines the host level and the eni level network related operations
type NetworkAPIs interface {
// SetupNodeNetwork performs node level network configuration
SetupHostNetwork(vpcCIDR *net.IPNet, primaryAddr *net.IP) error
SetupHostNetwork(vpcCIDR *net.IPNet, primaryMAC string, primaryAddr *net.IP) error
// SetupENINetwork performs eni level network configuration
SetupENINetwork(eniIP string, mac string, table int, subnetCIDR string) error
}
Expand Down Expand Up @@ -126,9 +126,34 @@ func isDuplicateRuleAdd(err error) bool {
return strings.Contains(err.Error(), "File exists")
}

// find out the primary interface name
func findPrimaryInterfaceName(primaryMAC string) (string, error) {

log.Debugf("Trying to find primary interface that has mac : %s", primaryMAC)

interfaces, err := net.Interfaces()

if err != nil {
log.Errorf("Failed to read all interfaces: %v", err)
return "", errors.Wrapf(err, "findPrimaryInterfaceName: failed to find interfaces")
}

for _, intf := range interfaces {
log.Debugf("Discovered interface: %v, mac: %v", intf.Name, intf.HardwareAddr)

if strings.Compare(primaryMAC, intf.HardwareAddr.String()) == 0 {
log.Infof("Discovered primary interface: %s", intf.Name)
return intf.Name, nil
}
}

log.Errorf("No primary interface found")
return "", errors.New("no primary interface found")
}

// SetupHostNetwork performs node level network configuration
// TODO : implement ip rule not to 10.0.0.0/16(vpc'subnet) table main priority 1024
func (n *linuxNetwork) SetupHostNetwork(vpcCIDR *net.IPNet, primaryAddr *net.IP) error {
func (n *linuxNetwork) SetupHostNetwork(vpcCIDR *net.IPNet, primaryMAC string, primaryAddr *net.IP) error {
log.Info("Setting up host network")
hostRule := n.netLink.NewRule()
hostRule.Dst = vpcCIDR
Expand All @@ -154,6 +179,12 @@ func (n *linuxNetwork) SetupHostNetwork(vpcCIDR *net.IPNet, primaryAddr *net.IP)
}

if n.nodePortSupportEnabled {

primaryIntf, err := findPrimaryInterfaceName(primaryMAC)

if err != nil {
return errors.Wrapf(err, "failed to SetupHostNetwork")
}
// If node port support is enabled, configure the kernel's reverse path filter check on eth0 for "loose"
// filtering. This is required because
// - NodePorts are exposed on eth0
Expand All @@ -163,9 +194,11 @@ func (n *linuxNetwork) SetupHostNetwork(vpcCIDR *net.IPNet, primaryAddr *net.IP)
// - Thus, it finds the source-based route that leaves via the secondary ENI.
// - In "strict" mode, the RPF check fails because the return path uses a different interface to the incoming
// packet. In "loose" mode, the check passes because some route was found.
const eth0RPFilter = "/proc/sys/net/ipv4/conf/eth0/rp_filter"
primaryIntfRPFilter := "/proc/sys/net/ipv4/conf/" + primaryIntf + "/rp_filter"
const rpFilterLoose = "2"
err := n.setProcSys(eth0RPFilter, rpFilterLoose)

log.Debugf("Setting RPF for primary interface: %s", primaryIntfRPFilter)
err = n.setProcSys(primaryIntfRPFilter, rpFilterLoose)
if err != nil {
return errors.Wrapf(err, "failed to configure eth0 RPF check")
}
Expand Down
6 changes: 3 additions & 3 deletions pkg/networkutils/network_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ func TestSetupHostNetworkNodePortDisabled(t *testing.T) {
mockNetLink.EXPECT().NewRule().Return(&mainENIRule)
mockNetLink.EXPECT().RuleDel(&mainENIRule)

err := ln.SetupHostNetwork(testENINetIPNet, &testENINetIP)
err := ln.SetupHostNetwork(testENINetIPNet, "", &testENINetIP)
assert.NoError(t, err)

assert.Equal(t, map[string]map[string][][]string{
Expand Down Expand Up @@ -181,7 +181,7 @@ func TestSetupHostNetworkNodePortEnabled(t *testing.T) {
mockNetLink.EXPECT().RuleDel(&mainENIRule)
mockNetLink.EXPECT().RuleAdd(&mainENIRule)

err := ln.SetupHostNetwork(testENINetIPNet, &testENINetIP)
err := ln.SetupHostNetwork(testENINetIPNet, "", &testENINetIP)
assert.NoError(t, err)

assert.Equal(t, map[string]map[string][][]string{
Expand Down Expand Up @@ -241,7 +241,7 @@ func (ipt *mockIptables) Delete(table, chainName string, rulespec ...string) err
}
updatedChain = append(updatedChain, r)
}
if ! found {
if !found {
return errors.New("not found")
}
ipt.dataplaneState[table][chainName] = updatedChain
Expand Down

0 comments on commit 9a4a018

Please sign in to comment.