Move the YAML config to be compatible with vppcfg's config file

This commit is contained in:
Pim van Pelt
2022-07-10 09:45:57 +00:00
parent 3be732e6ab
commit b024a3e96b
3 changed files with 90 additions and 58 deletions

View File

@ -36,7 +36,7 @@ optional arguments:
-h, --help show this help message and exit
-a ADDRESS Location of the SNMPd agent (unix-path or host:port), default localhost:705
-p PERIOD Period to poll VPP, default 30 (seconds)
-c CONFIG Optional YAML configuration file, default empty
-c CONFIG Optional vppcfg YAML configuration file, default empty
-d Enable debug, default False
## Install
@ -45,32 +45,43 @@ sudo cp dist/vpp-snmp-agent /usr/sbin/
## Configuration file
A simple convenience configfile can provide a mapping between VPP interface names, Linux Control Plane
interface names, and descriptions. An example:
This SNMP Agent will read a [vppcfg](https://github.com/pimvanpelt/vppcfg) configuration file,
which provides a mapping between VPP interface names, Linux Control Plane interface names, and
descriptions. From the upstream `vppcfg` configuration file, it will only consume the `interfaces`
block, and ignore the rest. An example snippet:
```
interfaces:
"TenGigabitEthernet6/0/0":
description: "Infra: xsw0.chrma0:2"
lcp: "xe1-0"
"TenGigabitEthernet6/0/0.3102":
description: "Infra: QinQ to L2 Provider"
lcp: "xe1-0.3102"
"TenGigabitEthernet6/0/0.310211":
description: "Cust: Customer IP Transit"
lcp: "xe1-0.3102.11"
GigabitEthernet3/0/0:
description: "Infra: Some interface"
lcp: e0
mtu: 9000
sub-interfaces:
100:
description: "Cust: Some sub-interface"
200:
description: "Cust: Some sub-interface with LCP"
lcp: e0.200
20011:
description: "Cust: Some QinQ sub-interface with LCP"
encapsulation:
dot1q: 200
inner-dot1q: 11
exact-match: true
lcp: e0.200.11
```
This configuration file is completely optional. If the `-c` flag is empty, or it's set but the file does
not exist, the Agent will simply enumerate all interfaces, and set the `ifAlias` OID to the same value as
the `ifName`. However, if the config file is read, it will change the behavior as follows:
* The `ifAlias` OID for an interface will be set to the `description` field.
* Any `tapNN` interface names from VPP will be matched to their PHY by looking up their Linux Control Plane
interface. The `ifName` field will be rewritten to the _LIP_ `host-if`. For example, `tap3` above will
become `xe1-0` while `tap3.310211` will become `xe1-0.3102.11`.
* The `ifAlias` OID for a PHY will be set to the `description` field.
* The `ifAlias` OID for a TAP will be set to the string `LCP ` followed by its PHY `ifName`. For example,
`xe1-0.3102.11` will become `LCP TenGigabitEthernet6/0/0.310211 (tap9)`
interface:
* The `ifName` field will be rewritten to the _LIP_ `host-if`, which is specified by the `lcp`
field. For example, `tap3` above will become `e0` while `tap3.20011` will become `e0.200.11`.
* The `ifAlias` OID for a TAP will be set to the string `LCP ` followed by its PHY `ifName`. For example,
`e0.200.11` will become `LCP GigabitEthernet3/0/0.20011 (tap3)`
## SNMPd config

View File

@ -26,13 +26,28 @@ def get_phy_by_sw_if_index(ifaces, sw_if_index):
def get_lcp_by_host_sw_if_index(lcp, host_sw_if_index):
try:
for k,v in lcp.items():
if v['host_sw_if_index'] == host_sw_if_index:
if v.host_sw_if_index == host_sw_if_index:
return v
except:
pass
return None
def get_description_by_ifname(config, ifname):
try:
for phy_name, phy in config['interfaces'].items():
if ifname == phy_name:
return phy['description']
if 'sub-interfaces' in phy:
for sub_id, sub_int in config['interfaces'][phy_name]['sub-interfaces'].items():
sub_ifname = "%s.%d" % (phy_name, sub_id)
if ifname == sub_ifname:
return sub_int['description']
except:
pass
return None
class MyAgent(agentx.Agent):
def setup(self):
global vppstat, vpp, logger, args
@ -110,11 +125,10 @@ class MyAgent(agentx.Agent):
host_sw_if_index = ifaces[ifname].sw_if_index
lip = get_lcp_by_host_sw_if_index(lcp, host_sw_if_index)
if lip:
phy = get_phy_by_sw_if_index(ifaces, lip['phy_sw_if_index'])
self.logger.debug("LIP: %s PHY: %s" % (lip, phy))
if phy:
ifName = self.config['interfaces'][phy.interface_name]['lcp']
phy = get_phy_by_sw_if_index(ifaces, lip.phy_sw_if_index)
ifName = lip.host_if_name
self.logger.debug("Setting ifName of %s to '%s'" % (ifname, ifName))
if phy:
ifAlias = "LCP %s (%s)" % (phy.interface_name,ifname)
self.logger.debug("Setting ifAlias of %s to '%s'" % (ifname, ifAlias))
except:
@ -216,11 +230,14 @@ class MyAgent(agentx.Agent):
if self.config and not ifAlias:
try:
ifAlias = self.config['interfaces'][ifname]['description']
self.logger.debug("Setting ifAlias of %s to '%s'" % (ifname, ifAlias))
descr = get_description_by_ifname(self.config, ifname)
if descr:
self.logger.debug("Setting ifAlias of %s to config description '%s'" % (ifname, descr))
ifAlias = descr
except:
pass
if not ifAlias:
self.logger.debug("Setting ifAlias of %s to ifname %s" % (ifname, ifname))
ifAlias = ifname
ds.set('1.3.6.1.2.1.31.1.1.1.18.%u' % (idx), 'str', ifAlias)
ds.set('1.3.6.1.2.1.31.1.1.1.19.%u' % (idx), 'ticks', 0) # Hardcode to Timeticks: (0) 0:00:00.00
@ -232,7 +249,7 @@ def main():
parser = argparse.ArgumentParser(formatter_class=argparse.RawTextHelpFormatter)
parser.add_argument('-a', dest='address', default="localhost:705", type=str, help="""Location of the SNMPd agent (unix-path or host:port), default localhost:705""")
parser.add_argument('-p', dest='period', type=int, default=30, help="""Period to poll VPP, default 30 (seconds)""")
parser.add_argument('-c', dest='config', type=str, help="""Optional YAML configuration file, default empty""")
parser.add_argument('-c', dest='config', type=str, help="""Optional vppcfg YAML configuration file, default empty""")
parser.add_argument('-d', dest='debug', action='store_true', help="""Enable debug, default False""")
args = parser.parse_args()

View File

@ -4,8 +4,9 @@
block_cipher = None
a = Analysis(['vpp-snmp-agent.py'],
pathex=['/home/pim/src/vpp-snmp-agentx'],
a = Analysis(
['vpp-snmp-agent.py'],
pathex=[],
binaries=[],
datas=[],
hiddenimports=[],
@ -16,11 +17,12 @@ a = Analysis(['vpp-snmp-agent.py'],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=block_cipher,
noarchive=False)
pyz = PYZ(a.pure, a.zipped_data,
cipher=block_cipher)
noarchive=False,
)
pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher)
exe = EXE(pyz,
exe = EXE(
pyz,
a.scripts,
a.binaries,
a.zipfiles,
@ -35,6 +37,8 @@ exe = EXE(pyz,
runtime_tmpdir=None,
console=True,
disable_windowed_traceback=False,
argv_emulation=False,
target_arch=None,
codesign_identity=None,
entitlements_file=None )
entitlements_file=None,
)