[tun_pkt]: Wait for AsyncSniffer to init fully (#10346)

Fix for Tunnel packet handler can crash at system startup 
Signed-off-by: Lawrence Lee <lawlee@microsoft.com>
This commit is contained in:
Lawrence Lee 2022-03-30 14:03:29 -07:00 committed by GitHub
parent 1e2e493daa
commit b31df59c7c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -51,6 +51,10 @@ class TunnelPacketHandler(object):
self._portchannel_intfs = None
self.up_portchannels = None
self.netlink_api = IPRoute()
self.sniffer = None
self.self_ip = ''
self.packet_filter = ''
self.sniff_intfs = []
@property
def portchannel_intfs(self):
@ -270,15 +274,22 @@ class TunnelPacketHandler(object):
return True
return False
def listen_for_tunnel_pkts(self):
def start_sniffer(self):
"""
Listens for tunnel packets that are trapped to CPU
These packets may be trapped if there is no neighbor info for the
inner packet destination IP in the hardware.
Starts an AsyncSniffer and waits for it to inititalize fully
"""
self.sniffer = AsyncSniffer(
iface=self.sniff_intfs,
filter=self.packet_filter,
prn=self.ping_inner_dst,
store=0
)
self.sniffer.start()
def _ping_inner_dst(packet):
while not hasattr(self.sniffer, 'stop_cb'):
time.sleep(0.1)
def ping_inner_dst(self, packet):
"""
Pings the inner destination IP for an encapsulated packet
@ -286,7 +297,7 @@ class TunnelPacketHandler(object):
packet: The encapsulated packet received
"""
inner_packet_type = self.get_inner_pkt_type(packet)
if inner_packet_type and packet[IP].dst == self_ip:
if inner_packet_type and packet[IP].dst == self.self_ip:
cmds = ['timeout', '0.2', 'ping', '-c1',
'-W1', '-i0', '-n', '-q']
if inner_packet_type == IPv6:
@ -296,40 +307,35 @@ class TunnelPacketHandler(object):
logger.log_info("Running command '{}'".format(' '.join(cmds)))
subprocess.run(cmds, stdout=subprocess.DEVNULL)
self_ip, peer_ip = self.get_ipinip_tunnel_addrs()
if self_ip is None or peer_ip is None:
def listen_for_tunnel_pkts(self):
"""
Listens for tunnel packets that are trapped to CPU
These packets may be trapped if there is no neighbor info for the
inner packet destination IP in the hardware.
"""
self.self_ip, peer_ip = self.get_ipinip_tunnel_addrs()
if self.self_ip is None or peer_ip is None:
logger.log_notice('Could not get tunnel addresses from '
'config DB, exiting...')
return None
packet_filter = 'host {} and host {}'.format(self_ip, peer_ip)
self.packet_filter = 'host {} and host {}'.format(self.self_ip, peer_ip)
logger.log_notice('Starting tunnel packet handler for {}'
.format(packet_filter))
.format(self.packet_filter))
sniff_intfs = self.get_up_portchannels()
logger.log_info("Listening on interfaces {}".format(sniff_intfs))
self.sniff_intfs = self.get_up_portchannels()
logger.log_info("Listening on interfaces {}".format(self.sniff_intfs))
sniffer = AsyncSniffer(
iface=sniff_intfs,
filter=packet_filter,
prn=_ping_inner_dst,
store=0
)
sniffer.start()
self.start_sniffer()
while True:
msgs = self.wait_for_netlink_msgs()
if self.sniffer_restart_required(msgs):
sniffer.stop()
self.sniffer.stop()
sniff_intfs = self.get_up_portchannels()
logger.log_notice('Restarting tunnel packet handler on '
'interfaces {}'.format(sniff_intfs))
sniffer = AsyncSniffer(
iface=sniff_intfs,
filter=packet_filter,
prn=_ping_inner_dst,
store=0
)
sniffer.start()
self.start_sniffer()
def run(self):
"""