[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:
parent
1e2e493daa
commit
b31df59c7c
@ -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):
|
||||||
"""
|
"""
|
||||||
|
Reference in New Issue
Block a user