in pkg/networkutils/network.go [254:355]
func (n *linuxNetwork) SetupHostNetwork(vpcv4CIDRs []string, primaryMAC string, primaryAddr *net.IP, enablePodENI bool,
v4Enabled bool, v6Enabled bool) error {
log.Info("Setting up host network... ")
var err error
primaryIntf := "eth0"
//RP Filter setting is only needed if IPv4 mode is enabled.
if v4Enabled && 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
// - The kernel's RPF check happens after incoming packets to NodePorts are DNATted to the pod IP.
// - For pods assigned to secondary ENIs, the routing table includes source-based routing. When the kernel does
// the RPF check, it looks up the route using the pod IP as the source.
// - 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.
primaryIntfRPFilter := "net/ipv4/conf/" + primaryIntf + "/rp_filter"
const rpFilterLoose = "2"
if n.shouldConfigureRpFilter {
log.Debugf("Setting RPF for primary interface: %s", primaryIntfRPFilter)
err = n.procSys.Set(primaryIntfRPFilter, rpFilterLoose)
if err != nil {
return errors.Wrapf(err, "failed to configure %s RPF check", primaryIntf)
}
} else {
log.Infof("Skip updating RPF for primary interface: %s", primaryIntfRPFilter)
}
}
link, err := linkByMac(primaryMAC, n.netLink, retryLinkByMacInterval)
if err != nil {
return errors.Wrapf(err, "setupHostNetwork: failed to find the link primary ENI with MAC address %s", primaryMAC)
}
if err = n.netLink.LinkSetMTU(link, n.mtu); err != nil {
return errors.Wrapf(err, "setupHostNetwork: failed to set MTU to %d for %s", n.mtu, primaryIntf)
}
ipFamily := unix.AF_INET
if v6Enabled {
ipFamily = unix.AF_INET6
if err := n.enableIPv6(); err != nil {
return errors.Wrapf(err, "failed to enable IPv6")
}
}
// If node port support is enabled, add a rule that will force force marked traffic out of the main ENI. We then
// add iptables rules below that will mark traffic that needs this special treatment. In particular NodePort
// traffic always comes in via the main ENI but response traffic would go out of the pod's assigned ENI if we
// didn't handle it specially. This is because the routing decision is done before the NodePort's DNAT is
// reversed so, to the routing table, it looks like the traffic is pod traffic instead of NodePort traffic.
// Note: With v6 PD mode support, all the pods will be behind Primary ENI of the node and so we might not even need
// to mark the packets entering via Primary ENI for NodePort support.
mainENIRule := n.netLink.NewRule()
mainENIRule.Mark = int(n.mainENIMark)
mainENIRule.Mask = int(n.mainENIMark)
mainENIRule.Table = mainRoutingTable
mainENIRule.Priority = hostRulePriority
mainENIRule.Family = ipFamily
// If this is a restart, cleanup previous rule first
err = n.netLink.RuleDel(mainENIRule)
if err != nil && !containsNoSuchRule(err) {
log.Errorf("Failed to cleanup old main ENI rule: %v", err)
return errors.Wrapf(err, "host network setup: failed to delete old main ENI rule")
}
if n.nodePortSupportEnabled {
err = n.netLink.RuleAdd(mainENIRule)
if err != nil {
log.Errorf("Failed to add host main ENI rule: %v", err)
return errors.Wrapf(err, "host network setup: failed to add main ENI rule")
}
}
// If we want per pod ENIs, we need to give pod ENIs veth bridges a lower priority that the local table,
// or the rp_filter check will fail.
// Note: Per Pod Security Group is not supported for V6 yet. So, cordoning off the PPSG rule (for now)
// with v4 specific check.
if v4Enabled && enablePodENI {
localRule := n.netLink.NewRule()
localRule.Table = localRouteTable
localRule.Priority = localRulePriority
// Add new rule with higher priority
err := n.netLink.RuleAdd(localRule)
if err != nil && !isRuleExistsError(err) {
return errors.Wrap(err, "ChangeLocalRulePriority: unable to update local rule priority")
}
// Delete the priority 0 rule
localRule.Priority = 0
err = n.netLink.RuleDel(localRule)
if err != nil && !containsNoSuchRule(err) {
return errors.Wrap(err, "ChangeLocalRulePriority: failed to delete priority 0 local rule")
}
}
return n.updateHostIptablesRules(vpcv4CIDRs, primaryMAC, primaryAddr, v4Enabled, v6Enabled)
}