|
@@ -44,6 +44,7 @@ O = {
|
|
|
}
|
|
}
|
|
|
POE_STD = '1.3.6.1.2.1.105.1.1.1.1.1' # RFC 3621 pethPsePortAdminEnable
|
|
POE_STD = '1.3.6.1.2.1.105.1.1.1.1.1' # RFC 3621 pethPsePortAdminEnable
|
|
|
POE_HW_JUDGE = '1.3.6.1.4.1.2011.5.25.195.4.1.2' # HUAWEI-POE-MIB hwPoePortJudgeIsSupport (TruthValue)
|
|
POE_HW_JUDGE = '1.3.6.1.4.1.2011.5.25.195.4.1.2' # HUAWEI-POE-MIB hwPoePortJudgeIsSupport (TruthValue)
|
|
|
|
|
+POE_ENTITY = '1.3.6.1.2.1.47.1.1.1.1.2' # ENTITY-MIB entPhysicalDescr (model description)
|
|
|
def parse(lines, base):
|
|
def parse(lines, base):
|
|
|
out = []
|
|
out = []
|
|
|
for ln in lines:
|
|
for ln in lines:
|
|
@@ -66,13 +67,26 @@ def collect(t):
|
|
|
iftype = n1('ifType'); ifadmin = n1('ifAdmin'); ifoper = n1('ifOper')
|
|
iftype = n1('ifType'); ifadmin = n1('ifAdmin'); ifoper = n1('ifOper')
|
|
|
ifspeed = n1('ifSpeed'); ifhigh = n1('ifHighSpeed'); lastchg = n1('ifLastChange')
|
|
ifspeed = n1('ifSpeed'); ifhigh = n1('ifHighSpeed'); lastchg = n1('ifLastChange')
|
|
|
conn = n1('ifConnector'); dup = n1('duplex')
|
|
conn = n1('ifConnector'); dup = n1('duplex')
|
|
|
- # PoE capability: standard RFC 3621 PSE table, plus Huawei's TruthValue
|
|
|
|
|
- # capability table. A row in the standard table means a PSE port exists;
|
|
|
|
|
- # Huawei reports true(1)/false(2) for each interface. This is capability,
|
|
|
|
|
- # not current PD power, so it stays stable when no device is attached.
|
|
|
|
|
|
|
+ # PoE capability: standard RFC 3621 PSE table, Huawei's TruthValue
|
|
|
|
|
+ # capability table, and finally the ENTITY-MIB model description. Some
|
|
|
|
|
+ # Huawei firmware hides the HUAWEI-POE-MIB subtree from SNMP views even
|
|
|
|
|
+ # though the switch is a PoE+ model; the entity description still contains
|
|
|
|
|
+ # the exact model (for example "S5735-L24P4XE-A-V2 ... PoE+"), so it is a
|
|
|
|
|
+ # reliable capability fallback. This is capability, not current PD power.
|
|
|
std_poe = parse(walk(args, ip, POE_STD), POE_STD)
|
|
std_poe = parse(walk(args, ip, POE_STD), POE_STD)
|
|
|
hw_poe = parse(walk(args, ip, POE_HW_JUDGE), POE_HW_JUDGE)
|
|
hw_poe = parse(walk(args, ip, POE_HW_JUDGE), POE_HW_JUDGE)
|
|
|
poe = bool(std_poe) or any(num(v) == 1 for _, v in hw_poe)
|
|
poe = bool(std_poe) or any(num(v) == 1 for _, v in hw_poe)
|
|
|
|
|
+ poe_source = 'std' if std_poe else ('huawei' if poe else '')
|
|
|
|
|
+ poe_model = ''
|
|
|
|
|
+ if not poe:
|
|
|
|
|
+ ent_poe = parse(walk(args, ip, POE_ENTITY), POE_ENTITY)
|
|
|
|
|
+ for _, v in ent_poe:
|
|
|
|
|
+ txt = strval(v)
|
|
|
|
|
+ if 'POE' in txt.upper() or 'PSE' in txt.upper():
|
|
|
|
|
+ poe = True
|
|
|
|
|
+ poe_source = 'entity'
|
|
|
|
|
+ poe_model = txt
|
|
|
|
|
+ break
|
|
|
# FDB per port -> count and sample macs
|
|
# FDB per port -> count and sample macs
|
|
|
bpif = {num(s.split('.')[-1]): num(v) for s, v in parse(walk(args, ip, O['bpIf']), O['bpIf'])}
|
|
bpif = {num(s.split('.')[-1]): num(v) for s, v in parse(walk(args, ip, O['bpIf']), O['bpIf'])}
|
|
|
st = {num(s.split('.')[-1]): num(v) for s, v in parse(walk(args, ip, O['fdbStatus']), O['fdbStatus'])}
|
|
st = {num(s.split('.')[-1]): num(v) for s, v in parse(walk(args, ip, O['fdbStatus']), O['fdbStatus'])}
|
|
@@ -90,7 +104,8 @@ def collect(t):
|
|
|
d.update({'ok': True, 'ifname': ifname, 'ifdescr': ifdescr, 'ifalias': ifalias, 'iftype': iftype,
|
|
d.update({'ok': True, 'ifname': ifname, 'ifdescr': ifdescr, 'ifalias': ifalias, 'iftype': iftype,
|
|
|
'ifadmin': ifadmin, 'ifoper': ifoper, 'ifspeed': ifspeed, 'ifhigh': ifhigh,
|
|
'ifadmin': ifadmin, 'ifoper': ifoper, 'ifspeed': ifspeed, 'ifhigh': ifhigh,
|
|
|
'lastchg': lastchg, 'conn': conn, 'dup': dup, 'mac_cnt': dict(mac_cnt),
|
|
'lastchg': lastchg, 'conn': conn, 'dup': dup, 'mac_cnt': dict(mac_cnt),
|
|
|
- 'mac_by_if': {k: v for k, v in mac_by_if.items()}, 'poe': poe})
|
|
|
|
|
|
|
+ 'mac_by_if': {k: v for k, v in mac_by_if.items()}, 'poe': poe,
|
|
|
|
|
+ 'poe_source': poe_source, 'poe_model': poe_model})
|
|
|
return d
|
|
return d
|
|
|
|
|
|
|
|
def main():
|
|
def main():
|