Send both gratuitous ARP REQUESTs and REPLYs
Due to a linux kernel bug [1], network peers risk missing a gratuitous arp update. This can be safely worked around by enabling arp_accept for network interfaces that may receive those ARP packets [2]. Sadly, due to another kernel bug [3], gratuitous ARP packets that we send are not honoured by arp_accept. If we switch from REPLY to REQUEST packets, then all recent kernels should enforce ARP table entry override on gARP received. REPLYs are left for backwards compatibility in case some network peers honor REPLYs and not REQUESTs. [1] https://patchwork.ozlabs.org/patch/760372/ [2] https://bugs.launchpad.net/fuel/+bug/1456272 [3] https://patchwork.ozlabs.org/patch/760373/ Related-Bug: #1690165 Change-Id: Iacd01875bf1299ff68fb5d1009d72088270320bb
This commit is contained in:
parent
96c5dd6a2b
commit
82831b9d8d
@ -1062,26 +1062,33 @@ def _arping(ns_name, iface_name, address, count, log_exception):
|
||||
time.sleep(2)
|
||||
first = False
|
||||
|
||||
# Pass -w to set timeout to ensure exit if interface removed while
|
||||
# running
|
||||
arping_cmd = ['arping', '-A', '-I', iface_name, '-c', 1,
|
||||
'-w', 1.5, address]
|
||||
try:
|
||||
ip_wrapper = IPWrapper(namespace=ns_name)
|
||||
# Since arping is used to send gratuitous ARP, a response is not
|
||||
# expected. In some cases (no response) and with some platforms
|
||||
# (>=Ubuntu 14.04), arping exit code can be 1.
|
||||
ip_wrapper.netns.execute(arping_cmd, extra_ok_codes=[1])
|
||||
except Exception as exc:
|
||||
msg = _("Failed sending gratuitous ARP "
|
||||
"to %(addr)s on %(iface)s in namespace %(ns)s: %(err)s")
|
||||
logger_method = LOG.exception
|
||||
if not log_exception:
|
||||
logger_method = LOG.warning
|
||||
logger_method(msg, {'addr': address,
|
||||
'iface': iface_name,
|
||||
'ns': ns_name,
|
||||
'err': exc})
|
||||
# some Linux kernels* don't honour REPLYs. Send both gratuitous REQUEST
|
||||
# and REPLY packets (REQUESTs are left for backwards compatibility for
|
||||
# in case if some network peers, vice versa, honor REPLYs and not
|
||||
# REQUESTs)
|
||||
#
|
||||
# * https://patchwork.ozlabs.org/patch/763016/
|
||||
for arg in ('-U', '-A'):
|
||||
arping_cmd = ['arping', arg, '-I', iface_name, '-c', 1,
|
||||
# Pass -w to set timeout to ensure exit if interface
|
||||
# removed while running
|
||||
'-w', 1.5, address]
|
||||
try:
|
||||
ip_wrapper = IPWrapper(namespace=ns_name)
|
||||
# Since arping is used to send gratuitous ARP, a response is
|
||||
# not expected. In some cases (no response) and with some
|
||||
# platforms (>=Ubuntu 14.04), arping exit code can be 1.
|
||||
ip_wrapper.netns.execute(arping_cmd, extra_ok_codes=[1])
|
||||
except Exception as exc:
|
||||
msg = _("Failed sending gratuitous ARP to %(addr)s on "
|
||||
"%(iface)s in namespace %(ns)s: %(err)s")
|
||||
logger_method = LOG.exception
|
||||
if not log_exception:
|
||||
logger_method = LOG.warning
|
||||
logger_method(msg, {'addr': address,
|
||||
'iface': iface_name,
|
||||
'ns': ns_name,
|
||||
'err': exc})
|
||||
|
||||
|
||||
def send_ip_addr_adv_notif(
|
||||
|
@ -1674,13 +1674,14 @@ class TestArpPing(TestIPCmdBase):
|
||||
ip_wrapper = mIPWrapper(namespace=mock.sentinel.ns_name)
|
||||
|
||||
# Just test that arping is called with the right arguments
|
||||
arping_cmd = ['arping', '-A',
|
||||
'-I', mock.sentinel.iface_name,
|
||||
'-c', 1,
|
||||
'-w', mock.ANY,
|
||||
address]
|
||||
ip_wrapper.netns.execute.assert_any_call(arping_cmd,
|
||||
extra_ok_codes=[1])
|
||||
for arg in ('-A', '-U'):
|
||||
arping_cmd = ['arping', arg,
|
||||
'-I', mock.sentinel.iface_name,
|
||||
'-c', 1,
|
||||
'-w', mock.ANY,
|
||||
address]
|
||||
ip_wrapper.netns.execute.assert_any_call(arping_cmd,
|
||||
extra_ok_codes=[1])
|
||||
|
||||
@mock.patch('eventlet.spawn_n')
|
||||
def test_no_ipv6_addr_notif(self, spawn_n):
|
||||
|
Loading…
Reference in New Issue
Block a user