diff --git a/confluent_server/confluent/networking/lldp.py b/confluent_server/confluent/networking/lldp.py index 55b33745..3f453ede 100644 --- a/confluent_server/confluent/networking/lldp.py +++ b/confluent_server/confluent/networking/lldp.py @@ -36,6 +36,7 @@ if __name__ == '__main__': import asyncio import base64 import confluent.networking.nxapi as nxapi +import confluent.networking.srlinux as srlinux import confluent.exceptions as exc import confluent.log as log import confluent.messages as msg @@ -190,6 +191,10 @@ async def detect_backend(switch, verifier): apicheck, retcode = await wc.grab_json_response_with_status('/api/') if retcode == 400 and apicheck.startswith(b'{"imdata":['): _fastbackends[switch] = 'nxapi' + else: + rsp = wc.grab_json_response_with_status('/jsonrpc', {'dummy': 'data'}, returnheaders=True) + if rsp[1] == 401 and rsp[2].get('WWW-Authenticate', '').startswith('Basic realm="SRLinux"'): + _fastbackends[switch] = 'srlinux' return _fastbackends.get(switch, None) async def _extract_neighbor_data_https(switch, user, password, cfm, lldpdata): @@ -204,6 +209,8 @@ async def _extract_neighbor_data_https(switch, user, password, cfm, lldpdata): return _extract_neighbor_data_affluent(switch, user, password, cfm, lldpdata, wc) elif backend == 'nxapi': return await _extract_neighbor_data_nxapi(switch, user, password, cfm, lldpdata, wc) + elif backend == 'srlinux': + return _extract_neighbor_data_srlinux(switch, user, password, cfm, lldpdata, wc) @@ -223,7 +230,24 @@ async def _extract_neighbor_data_nxapi(switch, user, password, cfm, lldpdata, wc lldpdata[port] = portdata _neighdata[switch] = lldpdata -async def _extract_neighbor_data_affluent(switch, user, password, cfm, lldpdata, wc): +async def _extract_neighbor_data_srlinux(switch, user, password, cfm, lldpdata, wc): + cli = srlinux.SRLinuxClient(switch, user, password, cfm) + lldpinfo = cli.get_lldp() + for port in lldpinfo: + portdata = lldpinfo[port] + peerid = '{0}.{1}'.format( + portdata.get('peerchassisid', '').replace(':', '-').replace('/', '-'), + portdata.get('peerportid', '').replace(':', '-').replace('/', '-'), + ) + portdata['peerid'] = peerid + _extract_extended_desc(portdata, portdata['peerdescription'], True) + portdata['switch'] = switch + _neighbypeerid[peerid] = portdata + lldpdata[port] = portdata + _neighdata[switch] = lldpdata + + +def _extract_neighbor_data_affluent(switch, user, password, cfm, lldpdata, wc): wc.set_basic_credentials(user, password) neighdata = await wc.grab_json_response('/affluent/lldp/all') chassisid = neighdata['chassis']['id'] diff --git a/confluent_server/confluent/networking/macmap.py b/confluent_server/confluent/networking/macmap.py index a969b789..426486f3 100644 --- a/confluent_server/confluent/networking/macmap.py +++ b/confluent_server/confluent/networking/macmap.py @@ -55,6 +55,7 @@ import confluent.messages as msg import confluent.noderange as noderange import confluent.tasks as tasks import confluent.networking.nxapi as nxapi +import confluent.networking.srlinux as srlinux import confluent.util as util import fcntl import msgpack @@ -158,9 +159,17 @@ async def _fast_map_switch(args): return await _affluent_map_switch(switch, password, user, cfgm, macdata) elif backend == 'nxapi': return _nxapi_map_switch(switch, password, user, cfgm) + elif backend == 'srlinux': + return _srlinux_map_switch(switch, password, user, cfgm) raise Exception("No fast backend match") -async def _nxapi_map_switch(switch, password, user, cfgm): +async def _srlinux_map_switch(switch, password, user, cfgm): + cli = srlinux.SRLinuxClient(switch, user, password, cfgm) + mt = cli.get_mac_table() + _macsbyswitch[switch] = mt + _fast_backend_fixup(mt, switch) + +def _nxapi_map_switch(switch, password, user, cfgm): cli = nxapi.NxApiClient(switch, user, password, cfgm) mt = await cli.get_mac_table() _macsbyswitch[switch] = mt diff --git a/confluent_server/confluent/networking/srlinux.py b/confluent_server/confluent/networking/srlinux.py index 38f9d62e..d4216ee2 100644 --- a/confluent_server/confluent/networking/srlinux.py +++ b/confluent_server/confluent/networking/srlinux.py @@ -191,14 +191,19 @@ class SRLinuxClient: def get_mac_table(self): macdict = {} - response = self._get_state('/network-instance') + response = self._get_state('/network-instance/bridge-table/mac-table/mac') for datum in response: for niname in datum: for nin in datum[niname]: - if nin.get('type', '').endswith('mac-vrf'): - mactable = nin.get('bridge-table', {}).get('mac-table', {}) - #TODO: process mac table - + btable = nin.get('bridge-table', {}) + for btab in btable: + macs = btable[btab].get('mac', []) + for macent in macs: + macaddr = macent.get('address', None) + if macaddr: + macport = macent.get('destination', None) + if macport: + macdict.setdefault(macport, []).append(macaddr) return macdict def get_lldp(self): @@ -207,7 +212,24 @@ class SRLinuxClient: response = self._get_state('/system/lldp/interface') for datum in response: for intfname in datum: - #TODO: actually process LLDP data + lldpallinfo = datum[intfname] + for lldpdatum in lldpallinfo: + myportname = lldpdatum.get('name', None) + for neighinfo in lldpdatum.get('neighbor', []): + peerdesc = neighinfo.get('system-description', 'Unknown') + peername = neighinfo.get('system-name', 'Unknown') + peerchassisid = neighinfo.get('chassis-id', 'Unknown') + peerportid = neighinfo.get('port-id', 'Unknown') + lldpinfo = { + 'verified': True, # Data provided with authentication over TLS + 'peerdescription': peerdesc, + 'peername': peername, + 'peerchassisid': peerchassisid, + 'peerportid': peerportid, + 'portid': myportname, + 'port': myportname, + } + lldpbyport[myportname] = lldpinfo return lldpbyport