From 582842aec81c4d29c76ac71e106bf3dd6523f189 Mon Sep 17 00:00:00 2001 From: Jarrod Johnson Date: Wed, 18 Feb 2026 16:16:22 -0500 Subject: [PATCH 1/2] Add mac and lldp retrieval for SRLinux --- .../confluent/networking/srlinux.py | 34 +++++++++++++++---- 1 file changed, 28 insertions(+), 6 deletions(-) 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 From 08b2e1d0085df2141972627a33fcb29dbc2807b7 Mon Sep 17 00:00:00 2001 From: Jarrod Johnson Date: Wed, 18 Feb 2026 16:53:12 -0500 Subject: [PATCH 2/2] Wire up FDB and LLDP for srlinux --- confluent_server/confluent/networking/lldp.py | 24 +++++++++++++++++++ .../confluent/networking/macmap.py | 9 +++++++ 2 files changed, 33 insertions(+) diff --git a/confluent_server/confluent/networking/lldp.py b/confluent_server/confluent/networking/lldp.py index 4618d071..b6a0e28e 100644 --- a/confluent_server/confluent/networking/lldp.py +++ b/confluent_server/confluent/networking/lldp.py @@ -35,6 +35,7 @@ if __name__ == '__main__': import confluent.config.configmanager as cfm 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 @@ -189,6 +190,10 @@ def detect_backend(switch, verifier): apicheck, retcode = 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) def _extract_neighbor_data_https(switch, user, password, cfm, lldpdata): @@ -203,6 +208,8 @@ 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 _extract_neighbor_data_nxapi(switch, user, password, cfm, lldpdata, wc) + elif backend == 'srlinux': + return _extract_neighbor_data_srlinux(switch, user, password, cfm, lldpdata, wc) @@ -222,6 +229,23 @@ def _extract_neighbor_data_nxapi(switch, user, password, cfm, lldpdata, wc): lldpdata[port] = portdata _neighdata[switch] = lldpdata +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 = wc.grab_json_response('/affluent/lldp/all') diff --git a/confluent_server/confluent/networking/macmap.py b/confluent_server/confluent/networking/macmap.py index 56fb5654..0821c464 100644 --- a/confluent_server/confluent/networking/macmap.py +++ b/confluent_server/confluent/networking/macmap.py @@ -55,6 +55,7 @@ import confluent.log as log import confluent.messages as msg import confluent.noderange as noderange import confluent.networking.nxapi as nxapi +import confluent.networking.srlinux as srlinux import confluent.util as util from eventlet.greenpool import GreenPool import eventlet.green.subprocess as subprocess @@ -162,8 +163,16 @@ def _fast_map_switch(args): return _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") +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 = cli.get_mac_table()