2
0
mirror of https://github.com/xcat2/confluent.git synced 2025-01-27 11:30:06 +00:00

Refactor neighutil

Stick to bytes in the expensive part, only convert to and from
presentation form on lookup need.

Convert all external calls to a unified lookup logic.
This commit is contained in:
Jarrod Johnson 2021-08-24 16:19:41 -04:00
parent 797465b3eb
commit 4f4d02d68f
3 changed files with 50 additions and 46 deletions

View File

@ -106,12 +106,9 @@ def _parse_slp_packet(packet, peer, rsps, xidmap):
addr = peer[0]
if '%' in addr:
addr = addr[:addr.index('%')]
mac = None
if addr not in neighutil.neightable:
neighutil.update_neigh()
if addr in neighutil.neightable:
identifier = neighutil.neightable[addr]
mac = identifier
mac = neighutil.get_hwaddr(addr)
if mac:
identifier = mac
else:
identifier = addr
if (identifier, parsed['xid']) in rsps:
@ -254,7 +251,6 @@ def _grab_rsps(socks, rsps, interval, xidmap):
while r:
for s in r:
(rsp, peer) = s.recvfrom(9000)
neighutil.refresh_neigh()
_parse_slp_packet(rsp, peer, rsps, xidmap)
res = select.select(socks, (), (), interval)
if not res:
@ -415,11 +411,12 @@ def rescan(handler):
known_peers = set([])
for scanned in scan():
for addr in scanned['addresses']:
ip = addr[0].partition('%')[0] # discard scope if present
if ip not in neighutil.neightable:
continue
if addr in known_peers:
break
ip = addr[0].partition('%')[0] # discard scope if present
macaddr = neighutil.get_hwaddr(ip)
if not macaddr:
continue
known_peers.add(addr)
else:
handler(scanned)
@ -484,12 +481,10 @@ def snoop(handler, protocol=None):
ip = peer[0].partition('%')[0]
if peer in known_peers:
continue
if ip not in neighutil.neightable:
neighutil.update_neigh()
if ip not in neighutil.neightable:
mac = neighutil.get_hwaddr(ip)
if not mac:
continue
known_peers.add(peer)
mac = neighutil.neightable[ip]
if mac in peerbymacaddress:
peerbymacaddress[mac]['addresses'].append(peer)
else:
@ -541,13 +536,12 @@ def active_scan(handler, protocol=None):
known_peers = set([])
for scanned in scan():
for addr in scanned['addresses']:
ip = addr[0].partition('%')[0] # discard scope if present
if ip not in neighutil.neightable:
neighutil.update_neigh()
if ip not in neighutil.neightable:
continue
if addr in known_peers:
break
ip = addr[0].partition('%')[0] # discard scope if present
macaddr = neighutil.get_hwaddr(ip)
if not macaddr:
continue
known_peers.add(addr)
else:
scanned['protocol'] = protocol

View File

@ -61,13 +61,12 @@ def active_scan(handler, protocol=None):
known_peers = set([])
for scanned in scan(['urn:dmtf-org:service:redfish-rest:1']):
for addr in scanned['addresses']:
ip = addr[0].partition('%')[0] # discard scope if present
if ip not in neighutil.neightable:
neighutil.update_neigh()
if ip not in neighutil.neightable:
continue
if addr in known_peers:
break
ip = addr[0].partition('%')[0] # discard scope if present
hwaddr = neighutil.get_hwaddr(ip)
if not hwaddr:
continue
known_peers.add(addr)
else:
scanned['protocol'] = protocol
@ -134,11 +133,9 @@ def snoop(handler, byehandler=None, protocol=None, uuidlookup=None):
ip = peer[0].partition('%')[0]
if peer in known_peers:
continue
if ip not in neighutil.neightable:
neighutil.update_neigh()
if ip not in neighutil.neightable:
mac = neighutil.get_hwaddr(ip)
if not mac:
continue
mac = neighutil.neightable[ip]
known_peers.add(peer)
newmacs.add(mac)
if mac in peerbymacaddress:
@ -284,7 +281,6 @@ def _find_service(service, target):
while r:
for s in r:
(rsp, peer) = s.recvfrom(9000)
neighutil.refresh_neigh()
_parse_ssdp(peer, rsp, peerdata)
timeout = deadline - util.monotonic_time()
if timeout < 0:
@ -316,11 +312,9 @@ def _parse_ssdp(peer, rsp, peerdata):
ip = peer[0].partition('%')[0]
nid = ip
mac = None
if ip not in neighutil.neightable:
neighutil.update_neigh()
if ip in neighutil.neightable:
nid = neighutil.neightable[ip]
mac = nid
mac = neighutil.get_hwaddr(ip)
if mac:
nid = mac
headlines = rsp.split(b'\r\n')
try:
_, code, _ = headlines[0].split(b' ', 2)

View File

@ -20,6 +20,7 @@
import confluent.util as util
import os
import eventlet.semaphore as semaphore
import eventlet.green.socket as socket
import struct
@ -28,10 +29,9 @@ neightime = 0
import re
_validmac = re.compile('..:..:..:..:..:..')
neighlock = semaphore.Semaphore()
def update_neigh():
def _update_neigh():
global neightable
global neightime
neightime = os.times()[4]
@ -41,6 +41,7 @@ def update_neigh():
nlhdr = b'\x1c\x00\x00\x00\x1e\x00\x01\x03\x00\x00\x00\x00\x00\x00\x00\x00'
ndmsg= b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
s.sendall(nlhdr + ndmsg)
neightable = {}
while True:
pdata = s.recv(65536)
v = memoryview(pdata)
@ -50,7 +51,7 @@ def update_neigh():
length, typ = struct.unpack('IH', v[:6])
if typ == 28:
hlen = struct.calcsize('BIHBB')
fam, idx, state, flags, typ = struct.unpack('BIHBB', v[16:16+hlen])
_, idx, state, flags, typ = struct.unpack('BIHBB', v[16:16+hlen])
if typ == 1: # only handle unicast entries
curraddr = None
currip = None
@ -58,10 +59,11 @@ def update_neigh():
while len(rta):
rtalen, rtatyp = struct.unpack('HH', rta[:4])
if rtatyp == 2: # hwaddr
hwlen = rtalen - 4
curraddr = ':'.join(['{:02x}'.format(x) for x in bytearray(rta[4:rtalen].tobytes())])
curraddr = rta[4:rtalen].tobytes() # ':'.join(['{:02x}'.format(x) for x in bytearray(rta[4:rtalen].tobytes())])
if len(curraddr) == 20:
curraddr = curraddr[12:]
elif rtatyp == 1: # ip address
currip = socket.inet_ntop(fam, rta[4:rtalen].tobytes())
currip = rta[4:rtalen].tobytes() # socket.inet_ntop(fam, rta[4:rtalen].tobytes())
rta = rta[rtalen:]
if not rtalen:
if curraddr and currip:
@ -70,9 +72,23 @@ def update_neigh():
v = v[length:]
def refresh_neigh():
global neightime
def get_hwaddr(ipaddr):
hwaddr = None
if os.name == 'nt':
return
if os.times()[4] > (neightime + 30):
update_neigh()
return hwaddr
if ':' in ipaddr:
ipaddr = socket.inet_pton(socket.AF_INET6, ipaddr)
elif '.' in ipaddr:
ipaddr = socket.inet_pton(socket.AF_INET, ipaddr)
with neighlock:
updated = False
if os.times()[4] > (neightime + 30):
_update_neigh()
updated = True
hwaddr = neightable.get(ipaddr, None)
if not hwaddr and not updated:
_update_neigh()
hwaddr = neightable.get(ipaddr, None)
if hwaddr:
hwaddr = ':'.join(['{:02x}'.format(x) for x in bytearray(hwaddr)])
return hwaddr