[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,6 +274,39 @@ class TunnelPacketHandler(object):
return True
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):
"""
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
inner packet destination IP in the hardware.
"""
def _ping_inner_dst(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_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:
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):
"""