proxy_arp is a configuration of the NIC that, when enabled, will use its own MAC address to respond to ARP requests from non-self IPs.

A common use is when two hosts’ IPs are in the same network segment, but the Layer 2 is not working, you can use an additional host as a proxy, and turn on proxy_arp on this host’s NIC to act as an intermediate proxy to open the network. The following figure shows.


Turning on proxy_arp for the NIC is also simple.

echo 1 > /proc/sys/net/ipv4/conf/veth1/proxy_arp

calico is a network plugin that uses a routing scheme to get through the network, and as a k8s cni, it also uses proxy_arp as a part of getting through the route. Before we look at how calico uses proxy_arp, let’s look at how flannel’s host-gw uses routing to get through the pod network.

flannel host-gw routing scheme

A common way for pods on two Layer 2 interworking hosts to access each other via routing is a host-gw pattern similar to flannel. The traffic path is as follows.

  • There is a bridge on each host, and the pods access to the bridge through the veth pair.
  • The pod uses the bridge’s ip as the gateway. This way, when the pod accesses the IPs of other network segments, the traffic will reach the bridge.
  • Once the traffic reaches the bridge, it can be forwarded to the peer host according to the routing table on the host.
  • The peer host also forwards traffic from the bridge to the pod based on the routing table.


calico’s routing scheme

Compared to the flannel host-gw mode, calico takes a more subtle approach and omits the bridge.

One end of its veth pair is inside the pod, set to the pod’s IP, and the other end is in the host, with no IP set and no access to the bridge, but with proxy_arp=1 set.

The pod has the following routing table inside the pod.

default via dev veth2 dev veth2 scope link is a special IP segment that will only appear within the host. However, this IP is not important here, it is just a special value chosen to prevent conflicts. When the Pod wants to access other IPs, if the IP is in the same network segment, then it needs to get the MAC address of that IP. If it is not in the same segment, then according to the routing table, it has to get the IP address of the gateway. So no matter what, the arp request will reach veth1 in the figure below.

Because veth1 has proxy_arp=1 set, it returns its own MAC address, and then the Pod’s traffic is sent to the host’s network stack. Once it reaches the network stack, it is forwarded to the host on the other side, just like flannel host-gw.

Once the traffic reaches the peer host, unlike flannel host-gw, the host sets the route for the pod directly on the host.

1 dev veth1 scope link

That is, it is sent directly from veth1 to the pod.

sent directly from veth1 to the pod