Move the YAML config to be compatible with vppcfg's config file
This commit is contained in:
43
README.md
43
README.md
@ -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.
|
||||
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,
|
||||
`xe1-0.3102.11` will become `LCP TenGigabitEthernet6/0/0.310211 (tap9)`
|
||||
`e0.200.11` will become `LCP GigabitEthernet3/0/0.20011 (tap3)`
|
||||
|
||||
## SNMPd config
|
||||
|
||||
|
@ -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()
|
||||
|
@ -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,
|
||||
)
|
||||
|
Reference in New Issue
Block a user