Configure ARP cache to react more quickly to MAC address changes

When an IP address was reused by a new container, other containers
could experience delays of many seconds the first time they tried to
talk to that new container before successful communication would
occur.  This delay came from three sources related to ARP cache
behaviour:

- The kernel would take a while to decide that an ARP mapping was
  stale due to lack of positive evidence (due to the
  base_reachable_time default of 30s)

- Even once an ARP mapping was considered stale, the kernel would wait
  a few seconds before sending an ARP request, in the hope that a
  higher layer (e.g. TCP) would confirm the ARP entry (due to the
  delay_first_probe default of 5s)

- When the kernel sent out an ARP request to update a stale entry,
  initial attempts would unicast the request to the old MAC address
  before resorting to broadcast (due to the ucast_solicit default of
  3)

This change reduces all these values, so that any delays
are a few seconds.

For most workloads, this should not greatly increase the amount
of ARP traffic, because communication via TCP is often sufficient
to confirm ARP entries.  And one unicast ARP request is still sent
just in case.

Unfortunately, there's a fixed-but-only-recently bug in the kernel
that means that changing base_reachable_time can take a while to take
effect:
<https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=4bf6980dd0328530783fd657c776e3719b421d30>.
This means that a container will continue to use a long reachable_time
delay for the first few minutes of its life.
This commit is contained in:
David Wragg committed 2015-03-16 15:12:27 +00:00
1 parent e8ed9c707d
commit 11af544071
1 file changed
+14 -3
+14 -3
View File
@@ -148,6 +148,12 @@ create_bridge() {
fi
ip link set dev $BRIDGE up
# Configure the ARP cache parameters on the bridge interface for
# the sake of 'weave expose'
echo 5 >/proc/sys/net/ipv4/neigh/$BRIDGE/base_reachable_time
echo 2 >/proc/sys/net/ipv4/neigh/$BRIDGE/delay_first_probe_time
echo 1 >/proc/sys/net/ipv4/neigh/$BRIDGE/ucast_solicit
}
destroy_bridge() {
@@ -235,10 +241,15 @@ connect_container_to_bridge() {
return 1
fi
if ! ip netns exec $NETNS ip link set $GUEST_IFNAME name $CONTAINER_IFNAME ; then
if ! ip netns exec $NETNS sh -c "\
ip link set $GUEST_IFNAME name $CONTAINER_IFNAME &&
echo 5 >/proc/sys/net/ipv4/neigh/$CONTAINER_IFNAME/base_reachable_time &&
echo 2 >/proc/sys/net/ipv4/neigh/$CONTAINER_IFNAME/delay_first_probe_time &&
echo 1 >/proc/sys/net/ipv4/neigh/$CONTAINER_IFNAME/ucast_solicit" ; then
# failed after we assigned the veth to the container's
# namespace
ip netns exec $NETNS ip link del $GUEST_IFNAME type veth || true
# namespace, and we don't know if it was renamed or not.
ip netns exec $NETNS ip link del $GUEST_IFNAME type veth 2>/dev/null || true
ip netns exec $NETNS ip link del $CONTAINER_IFNAME type veth 2>/dev/null || true
return 1
fi
}