[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._portchannel_intfs = None
self.up_portchannels = None self.up_portchannels = None
self.netlink_api = IPRoute() self.netlink_api = IPRoute()
self.sniffer = None
self.self_ip = ''
self.packet_filter = ''
self.sniff_intfs = []
@property @property
def portchannel_intfs(self): def portchannel_intfs(self):
@ -270,6 +274,39 @@ class TunnelPacketHandler(object):
return True return True
return False return False
def start_sniffer(self):
"""
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()
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
Args:
packet: The encapsulated packet received
"""
inner_packet_type = self.get_inner_pkt_type(packet)
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:
cmds.append('-6')
dst_ip = packet[IP].payload[inner_packet_type].dst
cmds.append(dst_ip)
logger.log_info("Running command '{}'".format(' '.join(cmds)))
subprocess.run(cmds, stdout=subprocess.DEVNULL)
def listen_for_tunnel_pkts(self): def listen_for_tunnel_pkts(self):
""" """
Listens for tunnel packets that are trapped to CPU Listens for tunnel packets that are trapped to CPU
@ -277,59 +314,28 @@ class TunnelPacketHandler(object):
These packets may be trapped if there is no neighbor info for the These packets may be trapped if there is no neighbor info for the
inner packet destination IP in the hardware. inner packet destination IP in the hardware.
""" """
self.self_ip, peer_ip = self.get_ipinip_tunnel_addrs()
def _ping_inner_dst(packet): if self.self_ip is None or peer_ip is None:
"""
Pings the inner destination IP for an encapsulated packet
Args:
packet: The encapsulated packet received
"""
inner_packet_type = self.get_inner_pkt_type(packet)
if inner_packet_type and packet[IP].dst == self_ip:
cmds = ['timeout', '0.2', 'ping', '-c1',
'-W1', '-i0', '-n', '-q']
if inner_packet_type == IPv6:
cmds.append('-6')
dst_ip = packet[IP].payload[inner_packet_type].dst
cmds.append(dst_ip)
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:
logger.log_notice('Could not get tunnel addresses from ' logger.log_notice('Could not get tunnel addresses from '
'config DB, exiting...') 'config DB, exiting...')
return None 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 {}' logger.log_notice('Starting tunnel packet handler for {}'
.format(packet_filter)) .format(self.packet_filter))
sniff_intfs = self.get_up_portchannels() self.sniff_intfs = self.get_up_portchannels()
logger.log_info("Listening on interfaces {}".format(sniff_intfs)) logger.log_info("Listening on interfaces {}".format(self.sniff_intfs))
sniffer = AsyncSniffer( self.start_sniffer()
iface=sniff_intfs,
filter=packet_filter,
prn=_ping_inner_dst,
store=0
)
sniffer.start()
while True: while True:
msgs = self.wait_for_netlink_msgs() msgs = self.wait_for_netlink_msgs()
if self.sniffer_restart_required(msgs): if self.sniffer_restart_required(msgs):
sniffer.stop() self.sniffer.stop()
sniff_intfs = self.get_up_portchannels() sniff_intfs = self.get_up_portchannels()
logger.log_notice('Restarting tunnel packet handler on ' logger.log_notice('Restarting tunnel packet handler on '
'interfaces {}'.format(sniff_intfs)) 'interfaces {}'.format(sniff_intfs))
sniffer = AsyncSniffer( self.start_sniffer()
iface=sniff_intfs,
filter=packet_filter,
prn=_ping_inner_dst,
store=0
)
sniffer.start()
def run(self): def run(self):
""" """