2
0
mirror of https://github.com/xcat2/confluent.git synced 2025-03-18 17:37:45 +00:00

Change to built in neigh fetch

Rather than outsource, slowly,
to ip neigh for this frequent task,
call netlink directly.
This commit is contained in:
Jarrod Johnson 2021-08-24 11:54:13 -04:00
parent 06cfd408fc
commit 69b58836f6

View File

@ -19,8 +19,9 @@
# use ip neigh for the moment
import confluent.util as util
import eventlet.green.subprocess as subprocess
import os
import eventlet.green.socket as socket
import struct
neightable = {}
neightime = 0
@ -33,29 +34,40 @@ _validmac = re.compile('..:..:..:..:..:..')
def update_neigh():
global neightable
global neightime
neightable = {}
if os.name == 'nt':
return
ipn = subprocess.Popen(['ip', 'neigh'], stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
(neighdata, err) = ipn.communicate()
neighdata = util.stringify(neighdata)
for entry in neighdata.split('\n'):
entry = entry.split(' ')
if len(entry) < 5 or not entry[4]:
continue
if entry[0] in ('192.168.0.100', '192.168.70.100', '192.168.70.125'):
# Note that these addresses are common static ip addresses
# that are hopelessly ambiguous if there are many
# so ignore such entries and move on
# ideally the system network steers clear of this landmine of
# a subnet, but just in case
continue
if not _validmac.match(entry[4]):
continue
neightable[entry[0]] = entry[4]
neightime = os.times()[4]
s = socket.socket(socket.AF_NETLINK, socket.SOCK_RAW, socket.NETLINK_ROUTE)
s.bind((0, 0))
# RTM_GETNEIGH
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)
while True:
pdata = s.recv(65536)
v = memoryview(pdata)
if struct.unpack('H', v[4:6])[0] == 3:
break
while len(v):
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])
if typ == 1: # only handle unicast entries
curraddr = None
currip = None
rta = v[16+hlen:length]
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())])
elif rtatyp == 1: # ip address
currip = socket.inet_ntop(fam, rta[4:rtalen].tobytes())
rta = rta[rtalen:]
if not rtalen:
if curraddr and currip:
neightable[currip] = curraddr
break
v = v[length:]
def refresh_neigh():