diff --git a/pkg/agent/ipassigner/ip_assigner_linux.go b/pkg/agent/ipassigner/ip_assigner_linux.go index 80e976c8e2c..f106307e04a 100644 --- a/pkg/agent/ipassigner/ip_assigner_linux.go +++ b/pkg/agent/ipassigner/ip_assigner_linux.go @@ -28,6 +28,7 @@ import ( "antrea.io/antrea/pkg/agent/ipassigner/responder" "antrea.io/antrea/pkg/agent/util" + "antrea.io/antrea/pkg/agent/util/sysctl" ) // ipAssigner creates a dummy device and assigns IPs to it. @@ -43,7 +44,9 @@ type ipAssigner struct { // assignIPs caches the IPs that are assigned to the dummy device. // TODO: Add a goroutine to ensure that the cache is in sync with the IPs assigned to the dummy device in case the // IPs are removed by users accidentally. - assignedIPs sets.String + assignedIPs sets.String + // arpIgnore is the max value of conf/{all,interface}/arp_ignore for transport interface + arpIgnore int mutex sync.RWMutex arpResponder responder.Responder ndpResponder responder.Responder @@ -60,6 +63,11 @@ func NewIPAssigner(nodeTransportInterface string, dummyDeviceName string) (*ipAs assignedIPs: sets.NewString(), } if ipv4 != nil { + arpIgnore, err := getARPIgnoreForInterface(externalInterface.Name) + if err != nil { + return nil, err + } + a.arpIgnore = arpIgnore arpResonder, err := responder.NewARPResponder(externalInterface) if err != nil { return nil, fmt.Errorf("failed to create ARP responder for link %s: %v", externalInterface.Name, err) @@ -86,6 +94,22 @@ func NewIPAssigner(nodeTransportInterface string, dummyDeviceName string) (*ipAs return a, nil } +func getARPIgnoreForInterface(iface string) (int, error) { + arpIgnoreAll, err := sysctl.GetSysctlNet("ipv4/conf/all/arp_ignore") + if err != nil { + return 0, fmt.Errorf("failed to get arp_ignore for all interfaces: %w", err) + } + arpIgnore, err := sysctl.GetSysctlNet(fmt.Sprintf("ipv4/conf/%s/arp_ignore", iface)) + if err != nil { + return 0, fmt.Errorf("failed to get arp_ignore for %s: %w", iface, err) + } + if arpIgnore > arpIgnoreAll { + return arpIgnore, nil + } + return arpIgnoreAll, nil + +} + // ensureDummyDevice creates the dummy device if it doesn't exist. func ensureDummyDevice(deviceName string) (netlink.Link, error) { link, err := netlink.LinkByName(deviceName) @@ -210,11 +234,9 @@ func (a *ipAssigner) AssignedIPs() sets.String { // Run starts the ARP responder and NDP responder. func (a *ipAssigner) Run(ch <-chan struct{}) { - // Start the ARP responder only when the dummy device is not created. The kernel will handle ARP requests - // for IPs assigned to the dummy devices by default. - // TODO: Check the arp_ignore sysctl parameter of the transport interface to determine whether to start - // the ARP responder or not. - if a.dummyDevice == nil && a.arpResponder != nil { + // Start the ARP responder if the dummy device does not exist or + // arp_ignore of the transport interface has value other than 0. + if (a.arpIgnore > 0 || a.dummyDevice == nil) && a.arpResponder != nil { go a.arpResponder.Run(ch) } if a.ndpResponder != nil { diff --git a/test/e2e/infra/vagrant/Vagrantfile b/test/e2e/infra/vagrant/Vagrantfile index 8f087ad5cd1..7723dadcfba 100644 --- a/test/e2e/infra/vagrant/Vagrantfile +++ b/test/e2e/infra/vagrant/Vagrantfile @@ -1,6 +1,6 @@ VAGRANTFILE_API_VERSION = "2" -NUM_WORKERS = 1 +NUM_WORKERS = 2 MODE = ENV['K8S_IP_FAMILY'] || "v4" if MODE != "v4" && MODE != "v6" && MODE != "dual"