From: Steven Webster Date: Wed, 30 Aug 2017 05:43:54 +0000 (-0400) Subject: client: add show interfaces command (#240) X-Git-Tag: 0.9.9~19 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=a54f6012efff77c966f533b8ef35b8627e3c8212;p=thirdparty%2Flldpd.git client: add show interfaces command (#240) There are several lldpcli configure commands that take port name(s) as an optional parameter. Currently, it is not possible to verify interface specific configuration for lldpd without access to a neighbour switch/host or packet capture. It would be useful to have a show interfaces command, similar to the show neighbors command that allows a user/agent to query the local TLV information. This commit leverages the existing port display infrastructure to enable display of local interfaces. There are a few differences: - Do not display the chassis RID, as the local index is always 0 - Show TTL as a seperate TLV based on tx_hold, tx_interval config, as internally the port TTL atom info is 0, and the chassis TTL atom info has been depreciated. --- diff --git a/src/client/client.h b/src/client/client.h index e3ee3525..8da3e3fe 100644 --- a/src/client/client.h +++ b/src/client/client.h @@ -131,6 +131,8 @@ void display_interfaces_stats(lldpctl_conn_t *, struct writer *, struct cmd_env *); void display_interface_stats(lldpctl_conn_t *, struct writer *, lldpctl_atom_t *); +void display_local_interfaces(lldpctl_conn_t *, struct writer *, + struct cmd_env *, int, int); diff --git a/src/client/display.c b/src/client/display.c index cbd0e31a..27698903 100644 --- a/src/client/display.c +++ b/src/client/display.c @@ -349,7 +349,8 @@ display_port(struct writer *w, lldpctl_atom_t *port, int details) tag_datatag(w, "descr", "PortDescr", lldpctl_atom_get_str(port, lldpctl_k_port_descr)); - if (details) + if (details && + lldpctl_atom_get_int(port, lldpctl_k_port_ttl) > 0) tag_datatag(w, "ttl", "TTL", lldpctl_atom_get_str(port, lldpctl_k_port_ttl)); @@ -473,6 +474,38 @@ display_port(struct writer *w, lldpctl_atom_t *port, int details) tag_end(w); } +static void +display_local_ttl(struct writer *w, lldpctl_conn_t *conn, int details) +{ + char *ttl; + long int tx_hold; + long int tx_interval; + + lldpctl_atom_t *configuration; + configuration = lldpctl_get_configuration(conn); + if (!configuration) { + log_warnx("lldpctl", "not able to get configuration. %s", + lldpctl_last_strerror(conn)); + return; + } + + tx_hold = lldpctl_atom_get_int(configuration, lldpctl_k_config_tx_hold); + tx_interval = lldpctl_atom_get_int(configuration, lldpctl_k_config_tx_interval); + + if (asprintf(&ttl, "%lu", tx_hold*tx_interval) == -1) { + log_warnx("lldpctl", "not enough memory to build TTL."); + goto end; + } + + tag_start(w, "ttl", "TTL"); + tag_attr(w, "ttl", "", ttl); + tag_end(w); + free(ttl); +end: + lldpctl_atom_dec_ref(configuration); + return; +} + static void display_vlans(struct writer *w, lldpctl_atom_t *port) { @@ -582,43 +615,51 @@ display_local_chassis(lldpctl_conn_t *conn, struct writer *w, void display_interface(lldpctl_conn_t *conn, struct writer *w, int hidden, - lldpctl_atom_t *iface, lldpctl_atom_t *neighbor, int details, int protocol) + lldpctl_atom_t *iface, lldpctl_atom_t *port, int details, int protocol) { + int local = 0; + if (!hidden && - lldpctl_atom_get_int(neighbor, lldpctl_k_port_hidden)) + lldpctl_atom_get_int(port, lldpctl_k_port_hidden)) return; /* user might have specified protocol to filter on display */ if ((protocol != LLDPD_MODE_MAX) && - (protocol != lldpctl_atom_get_int(neighbor, lldpctl_k_port_protocol))) + (protocol != lldpctl_atom_get_int(port, lldpctl_k_port_protocol))) return; - lldpctl_atom_t *chassis = lldpctl_atom_get(neighbor, lldpctl_k_port_chassis); + /* Infer local / remote port from the port index (remote == 0) */ + local = lldpctl_atom_get_int(port, lldpctl_k_port_index)>0?1:0; + + lldpctl_atom_t *chassis = lldpctl_atom_get(port, lldpctl_k_port_chassis); tag_start(w, "interface", "Interface"); tag_attr(w, "name", "", lldpctl_atom_get_str(iface, lldpctl_k_interface_name)); tag_attr(w, "via" , "via", - lldpctl_atom_get_str(neighbor, lldpctl_k_port_protocol)); + lldpctl_atom_get_str(port, lldpctl_k_port_protocol)); if (details > DISPLAY_BRIEF) { - tag_attr(w, "rid" , "RID", - lldpctl_atom_get_str(chassis, lldpctl_k_chassis_index)); + if (!local) + tag_attr(w, "rid" , "RID", + lldpctl_atom_get_str(chassis, lldpctl_k_chassis_index)); tag_attr(w, "age" , "Time", - display_age(lldpctl_atom_get_int(neighbor, lldpctl_k_port_age))); + display_age(lldpctl_atom_get_int(port, lldpctl_k_port_age))); } display_chassis(w, chassis, details); - display_port(w, neighbor, details); + display_port(w, port, details); + if (details && local) + display_local_ttl(w, conn, details); if (details == DISPLAY_DETAILS) { - display_vlans(w, neighbor); - display_ppvids(w, neighbor); - display_pids(w, neighbor); - display_med(w, neighbor, chassis); + display_vlans(w, port); + display_ppvids(w, port); + display_pids(w, port); + display_med(w, port, chassis); } lldpctl_atom_dec_ref(chassis); - display_custom_tlvs(w, neighbor); + display_custom_tlvs(w, port); tag_end(w); } @@ -675,6 +716,34 @@ display_interfaces(lldpctl_conn_t *conn, struct writer *w, tag_end(w); } + +/** + * Display information about local interfaces. + * + * @param conn Connection to lldpd. + * @param w Writer. + * @param hidden Whatever to show hidden ports. + * @param env Environment from which we may find the list of ports. + * @param details Level of details we need (DISPLAY_*). + */ +void +display_local_interfaces(lldpctl_conn_t *conn, struct writer *w, + struct cmd_env *env, + int hidden, int details) +{ + lldpctl_atom_t *iface; + int protocol = LLDPD_MODE_MAX; + + tag_start(w, "lldp", "LLDP interfaces"); + while ((iface = cmd_iterate_on_interfaces(conn, env))) { + lldpctl_atom_t *port; + port = lldpctl_get_port(iface); + display_interface(conn, w, hidden, iface, port, details, protocol); + lldpctl_atom_dec_ref(port); + } + tag_end(w); + } + void display_stat(struct writer *w, const char *tag, const char *descr, long unsigned int cnt) diff --git a/src/client/lldpcli.8.in b/src/client/lldpcli.8.in index 7dceb684..300587fd 100644 --- a/src/client/lldpcli.8.in +++ b/src/client/lldpcli.8.in @@ -134,6 +134,26 @@ one or several ports, the information displayed is limited to the given list of ports. .Ed +.Cd show interfaces +.Op ports Ar ethX Op ,... +.Op Cd details | summary +.Op Cd hidden +.Bd -ragged -offset XXXXXX +Display information about each local interface known by +.Xr lldpd 8 +daemon. With +.Cd summary , +only the name and the port description of each local interface will be +displayed. On the other hand, with +.Cd details , +all available information will be displayed, giving a verbose +view. When using +.Cd hidden , +also display local ports hidden by the smart filter. When specifying +one or several ports, the information displayed is limited to the +given list of ports. +.Ed + .Cd show chassis .Op Cd details | summary .Bd -ragged -offset XXXXXX diff --git a/src/client/show.c b/src/client/show.c index fa704b86..8ba8acb4 100644 --- a/src/client/show.c +++ b/src/client/show.c @@ -48,6 +48,35 @@ cmd_show_neighbors(struct lldpctl_conn_t *conn, struct writer *w, return 1; } +/** + * Show interfaces. + * + * The environment will contain the following keys: + * - C{ports} list of ports we want to restrict showing. + * - C{hidden} if we should show hidden ports. + * - C{summary} if we want to show only a summary + * - C{detailed} for a detailed overview + */ +static int +cmd_show_interfaces(struct lldpctl_conn_t *conn, struct writer *w, + struct cmd_env *env, void *arg) +{ + log_debug("lldpctl", "show interfaces data (%s) %s hidden interfaces", + cmdenv_get(env, "summary")?"summary": + cmdenv_get(env, "detailed")?"detailed": + "normal", cmdenv_get(env, "hidden")?"with":"without"); + if (cmdenv_get(env, "ports")) + log_debug("lldpctl", "restrict to the following ports: %s", + cmdenv_get(env, "ports")); + + display_local_interfaces(conn, w, env, !!cmdenv_get(env, "hidden"), + cmdenv_get(env, "summary")?DISPLAY_BRIEF: + cmdenv_get(env, "detailed")?DISPLAY_DETAILS: + DISPLAY_NORMAL); + + return 1; +} + /** * Show chassis. * @@ -286,6 +315,12 @@ register_commands_show(struct cmd_node *root) "Show neighbors data", NULL, NULL, NULL); + struct cmd_node *interfaces = commands_new( + show, + "interfaces", + "Show interfaces data", + NULL, NULL, NULL); + struct cmd_node *chassis = commands_new( show, "chassis", @@ -306,6 +341,15 @@ register_commands_show(struct cmd_node *root) register_common_commands(neighbors, 1); + /* Interfaces data */ + commands_new(interfaces, + NEWLINE, + "Show interfaces data", + NULL, cmd_show_interfaces, NULL); + + cmd_restrict_ports(interfaces); + register_common_commands(interfaces, 0); + /* Chassis data */ commands_new(chassis, NEWLINE, diff --git a/src/daemon/lldpd.c b/src/daemon/lldpd.c index 4d3c273c..6603d604 100644 --- a/src/daemon/lldpd.c +++ b/src/daemon/lldpd.c @@ -1038,6 +1038,7 @@ lldpd_send(struct lldpd_hardware *hardware) cfg->g_protocols[i].name); cfg->g_protocols[i].send(cfg, hardware); + hardware->h_lport.p_protocol = cfg->g_protocols[i].mode; sent++; break; } diff --git a/tests/integration/test_basic.py b/tests/integration/test_basic.py index 3b23242c..1b92ef10 100644 --- a/tests/integration/test_basic.py +++ b/tests/integration/test_basic.py @@ -45,6 +45,46 @@ def test_several_neighbors(lldpd, lldpcli, links, namespaces, neighbors): 'ns-{}.example.com'.format(i) +def test_one_interface(lldpd1, lldpd, lldpcli, namespaces): + with namespaces(2): + lldpd() + with namespaces(1): + out = lldpcli("-f", "keyvalue", "show", "interfaces") + assert out['lldp.eth0.chassis.descr'].startswith( + "Spectacular GNU/Linux 2016 Linux") + assert 'lldp.eth0.age' in out + assert 'lldp.eth0.chassis.Router.enabled' in out + assert 'lldp.eth0.chassis.Station.enabled' in out + del out['lldp.eth0.age'] + del out['lldp.eth0.chassis.descr'] + del out['lldp.eth0.chassis.Router.enabled'] + del out['lldp.eth0.chassis.Station.enabled'] + assert out == {"lldp.eth0.via": "unknown", + "lldp.eth0.chassis.mac": "00:00:00:00:00:01", + "lldp.eth0.chassis.name": "ns-1.example.com", + "lldp.eth0.chassis.mgmt-ip": "fe80::200:ff:fe00:1", + "lldp.eth0.chassis.Bridge.enabled": "off", + "lldp.eth0.chassis.Wlan.enabled": "off", + "lldp.eth0.port.mac": "00:00:00:00:00:01", + "lldp.eth0.port.descr": "eth0", + "lldp.eth0.ttl.ttl": "120"} + +@pytest.mark.parametrize("interfaces", (5, 10, 20)) +def test_several_interfaces(lldpd, lldpcli, links, namespaces, interfaces): + for i in range(2, interfaces + 1): + links(namespaces(1), namespaces(i)) + for i in range(1, interfaces + 1): + with namespaces(i): + lldpd() + with namespaces(1): + out = lldpcli("-f", "keyvalue", "show", "interfaces") + for i in range(2, interfaces + 1): + assert out['lldp.eth{}.chassis.mac'.format((i - 2)*2)] == \ + '00:00:00:00:00:01' + assert out['lldp.eth{}.port.mac'.format((i - 2)*2)] == \ + '00:00:00:00:00:{num:02x}'.format(num=(i - 2)*2 + 1) + + def test_overrided_description(lldpd1, lldpd, lldpcli, namespaces): with namespaces(2): lldpd("-S", "Modified description") diff --git a/tests/integration/test_lldpcli.py b/tests/integration/test_lldpcli.py index dd5b2d71..aafafd63 100644 --- a/tests/integration/test_lldpcli.py +++ b/tests/integration/test_lldpcli.py @@ -1,4 +1,5 @@ import pytest +import shlex import time import re import platform @@ -14,20 +15,9 @@ def uname(): platform.version(), platform.machine()) - -def test_text_output(lldpd1, lldpd, lldpcli, namespaces, uname): - with namespaces(2): - lldpd() - with namespaces(1): - result = lldpcli("show", "neighbors", "details") - assert result.returncode == 0 - if 'Dot3' in pytest.config.lldpd.features: - dot3 = """ - PMD autoneg: supported: no, enabled: no - MAU oper type: 10GigBaseCX4 - X copper over 8 pair 100-Ohm balanced cable""" - else: - dot3 = "" - expected = """------------------------------------------------------------------------------- +@pytest.mark.parametrize("command, expected", [ + ("neighbors", + """------------------------------------------------------------------------------- LLDP neighbors: ------------------------------------------------------------------------------- Interface: eth0, via: LLDP, RID: 1, Time: 0 day, 00:00:{seconds} @@ -45,8 +35,48 @@ Interface: eth0, via: LLDP, RID: 1, Time: 0 day, 00:00:{seconds} PortDescr: eth1 TTL: 120{dot3} ------------------------------------------------------------------------------- -""" +"""), + ("interfaces", + """------------------------------------------------------------------------------- +LLDP interfaces: +------------------------------------------------------------------------------- +Interface: eth0, via: unknown, Time: {time} + Chassis: + ChassisID: mac 00:00:00:00:00:01 + SysName: ns-1.example.com + SysDescr: Spectacular GNU/Linux 2016 {uname} + MgmtIP: fe80::200:ff:fe00:1 + Capability: Bridge, off + Capability: Router, {router} + Capability: Wlan, off + Capability: Station, {station} + Port: + PortID: mac 00:00:00:00:00:01 + PortDescr: eth0{dot3} + TTL: 120 +------------------------------------------------------------------------------- +""")], ids=["neighbors", "interfaces"]) +def test_text_output(lldpd1, lldpd, lldpcli, namespaces, uname, command, + expected): + with namespaces(2): + lldpd() + with namespaces(1): + result = lldpcli( + *shlex.split("show {} details".format(command))) + assert result.returncode == 0 out = result.stdout.decode('ascii') + + if 'Dot3' in pytest.config.lldpd.features: + dot3 = """ + PMD autoneg: supported: no, enabled: no + MAU oper type: 10GigBaseCX4 - X copper over 8 pair 100-Ohm balanced cable""" + else: + dot3 = "" + + out = result.stdout.decode('ascii') + time = re.search(r'^Interface: .*Time: (.*)$', + out, + re.MULTILINE).group(1) seconds = re.search(r'^Interface: .*(\d\d)$', out, re.MULTILINE).group(1) @@ -58,55 +88,78 @@ Interface: eth0, via: LLDP, RID: 1, Time: 0 day, 00:00:{seconds} re.MULTILINE).group(1) out = re.sub(r' *$', '', out, flags=re.MULTILINE) assert out == expected.format(seconds=seconds, + time=time, router=router, station=station, uname=uname, dot3=dot3) - @pytest.mark.skipif('JSON' not in pytest.config.lldpcli.outputs, reason="JSON not supported") -def test_json_output(lldpd1, lldpd, lldpcli, namespaces, uname): +@pytest.mark.parametrize("command, expected", [ + ("neighbors", + {"lldp": { + "interface": { + "eth0": { + "via": "LLDP", + "rid": "1", + "chassis": { + "ns-2.example.com": { + "id": { + "type": "mac", + "value": "00:00:00:00:00:02"}, + "descr": "Spectacular GNU/Linux 2016 {}".format(uname), + "mgmt-ip": "fe80::200:ff:fe00:2", + "capability": [ + {"type": "Bridge", "enabled": False}, + {"type": "Wlan", "enabled": False},]}}, + "port": { + "id": { + "type": "mac", + "value": "00:00:00:00:00:02"}, + "descr": "eth1", + "ttl": "120"}}}}}), + ("interfaces", + {"lldp": { + "interface": { + "eth0": { + "via": "unknown", + "chassis": { + "ns-1.example.com": { + "id": { + "type": "mac", + "value": "00:00:00:00:00:01"}, + "descr": "Spectacular GNU/Linux 2016 {}".format(uname), + "mgmt-ip": "fe80::200:ff:fe00:1", + "capability": [ + {"type": "Bridge", "enabled": False}, + {"type": "Wlan", "enabled": False},]}}, + "port": { + "id": { + "type": "mac", + "value": "00:00:00:00:00:01"}, + "descr": "eth0"}, + "ttl": { + "ttl": "120"}}}}})], ids=["neighbors", "interfaces"]) +def test_json_output(lldpd1, lldpd, lldpcli, namespaces, uname, command, + expected): with namespaces(2): lldpd() with namespaces(1): - result = lldpcli("-f", "json", "show", "neighbors", "details") + result = lldpcli( + *shlex.split("-f json show {} details".format(command))) assert result.returncode == 0 out = result.stdout.decode('ascii') j = json.loads(out) eth0 = j['lldp']['interface']['eth0'] + name = next(k for k,v in eth0['chassis'].items() if k.startswith('ns')) del eth0['age'] - del eth0['chassis']['ns-2.example.com']['capability'][3] - del eth0['chassis']['ns-2.example.com']['capability'][1] - expected = {"lldp": { - "interface": {"eth0": { - "via": "LLDP", - "rid": "1", - "chassis": { - "ns-2.example.com": { - "id": { - "type": "mac", - "value": "00:00:00:00:00:02" - }, - "descr": "Spectacular GNU/Linux 2016 {}".format(uname), - "mgmt-ip": "fe80::200:ff:fe00:2", - "capability": [ - {"type": "Bridge", "enabled": False}, - {"type": "Wlan", "enabled": False}, - ] - } - }, - "port": { - "id": { - "type": "mac", - "value": "00:00:00:00:00:02" - }, - "descr": "eth1", - "ttl": "120" - } - }} - }} + del eth0['chassis'][name]['capability'][3] + del eth0['chassis'][name]['capability'][1] + + descr = "Spectacular GNU/Linux 2016 {}".format(uname) + expected['lldp']['interface']['eth0']['chassis'][name]["descr"] = descr if 'Dot3' in pytest.config.lldpd.features: expected['lldp']['interface']['eth0']['port']['auto-negotiation'] = { @@ -114,25 +167,14 @@ def test_json_output(lldpd1, lldpd, lldpcli, namespaces, uname): "supported": False, "current": "10GigBaseCX4 - X copper over 8 pair 100-Ohm balanced cable" } - assert j == expected + assert j == expected @pytest.mark.skipif('JSON' not in pytest.config.lldpcli.outputs, reason="JSON not supported") -def test_json0_output(lldpd1, lldpd, lldpcli, namespaces, uname): - with namespaces(2): - lldpd() - with namespaces(1): - result = lldpcli("-f", "json0", "show", "neighbors", "details") - assert result.returncode == 0 - out = result.stdout.decode('ascii') - j = json.loads(out) - - eth0 = j['lldp'][0]['interface'][0] - del eth0['age'] - del eth0['chassis'][0]['capability'][3] - del eth0['chassis'][0]['capability'][1] - expected = {"lldp": [{ +@pytest.mark.parametrize("command, expected", [ + ("neighbors", + {"lldp": [{ "interface": [{ "name": "eth0", "via": "LLDP", @@ -159,7 +201,53 @@ def test_json0_output(lldpd1, lldpd, lldpcli, namespaces, uname): "ttl": [{"value": "120"}] }] }]} - ]} + ]}), + ("interfaces", + {"lldp": [{ + "interface": [{ + "name": "eth0", + "via": "unknown", + "chassis": [{ + "id": [{ + "type": "mac", + "value": "00:00:00:00:00:01" + }], + "name": [{"value": "ns-1.example.com"}], + "descr": [{"value": "Spectacular GNU/Linux 2016 {}".format(uname)}], + "mgmt-ip": [{"value": "fe80::200:ff:fe00:1"}], + "capability": [ + {"type": "Bridge", "enabled": False}, + {"type": "Wlan", "enabled": False}, + ]} + ], + "port": [{ + "id": [{ + "type": "mac", + "value": "00:00:00:00:00:01" + }], + "descr": [{"value": "eth0"}] + }], + "ttl": [{"ttl": "120"}] + }]} + ]})], ids=["neighbors", "interfaces"]) +def test_json0_output(lldpd1, lldpd, lldpcli, namespaces, uname, command, + expected): + with namespaces(2): + lldpd() + with namespaces(1): + result = lldpcli( + *shlex.split("-f json0 show {} details".format(command))) + assert result.returncode == 0 + out = result.stdout.decode('ascii') + j = json.loads(out) + + eth0 = j['lldp'][0]['interface'][0] + del eth0['age'] + del eth0['chassis'][0]['capability'][3] + del eth0['chassis'][0]['capability'][1] + + descr = "Spectacular GNU/Linux 2016 {}".format(uname) + expected['lldp'][0]['interface'][0]['chassis'][0]["descr"][0]['value'] = descr if 'Dot3' in pytest.config.lldpd.features: expected['lldp'][0]['interface'][0]['port'][0]['auto-negotiation'] = [{ @@ -173,28 +261,9 @@ def test_json0_output(lldpd1, lldpd, lldpcli, namespaces, uname): @pytest.mark.skipif('XML' not in pytest.config.lldpcli.outputs, reason="XML not supported") -def test_xml_output(lldpd1, lldpd, lldpcli, namespaces, uname): - with namespaces(2): - lldpd() - with namespaces(1): - result = lldpcli("-f", "xml", "show", "neighbors", "details") - assert result.returncode == 0 - out = result.stdout.decode('ascii') - xml = ET.fromstring(out) - - age = xml.findall('./interface[1]')[0].attrib['age'] - router = xml.findall("./interface[1]/chassis/" - "capability[@type='Router']")[0].attrib['enabled'] - station = xml.findall("./interface[1]/chassis/" - "capability[@type='Station']")[0].attrib['enabled'] - if 'Dot3' in pytest.config.lldpd.features: - dot3 = """ - - 10GigBaseCX4 - X copper over 8 pair 100-Ohm balanced cable - """ - else: - dot3 = "" - expected = ET.fromstring(""" +@pytest.mark.parametrize("command, expected", [ + ("neighbors", +""" @@ -214,11 +283,57 @@ def test_xml_output(lldpd1, lldpd, lldpcli, namespaces, uname): - """.format(age=age, - router=router, - station=station, - uname=uname, - dot3=dot3)) +"""), +("interfaces", +""" + + + + 00:00:00:00:00:01 + ns-1.example.com + Spectacular GNU/Linux 2016 {uname} + fe80::200:ff:fe00:1 + + + + + + + 00:00:00:00:00:01 + eth0{dot3} + + + + +""")], ids=["neighbors", "interfaces"]) +def test_xml_output(lldpd1, lldpd, lldpcli, namespaces, uname, command, + expected): + with namespaces(2): + lldpd() + with namespaces(1): + result = lldpcli( + *shlex.split("-f xml show {} details".format(command))) + assert result.returncode == 0 + out = result.stdout.decode('ascii') + xml = ET.fromstring(out) + + age = xml.findall('./interface[1]')[0].attrib['age'] + router = xml.findall("./interface[1]/chassis/" + "capability[@type='Router']")[0].attrib['enabled'] + station = xml.findall("./interface[1]/chassis/" + "capability[@type='Station']")[0].attrib['enabled'] + if 'Dot3' in pytest.config.lldpd.features: + dot3 = """ + + 10GigBaseCX4 - X copper over 8 pair 100-Ohm balanced cable + """ + else: + dot3 = "" + expected = ET.fromstring(expected.format(age=age, + router=router, + station=station, + uname=uname, + dot3=dot3)) assert ET.tostring(xml) == ET.tostring(expected) @@ -233,6 +348,9 @@ def test_configure_one_port(lldpd1, lldpd, lldpcli, namespaces, links): "spare class class-3").split()) assert result.returncode == 0 time.sleep(3) + out = lldpcli("-f", "keyvalue", "show", "interfaces", "details") + assert 'lldp.eth1.port.power.device-type' not in out + assert out['lldp.eth3.port.power.device-type'] == 'PSE' with namespaces(1): out = lldpcli("-f", "keyvalue", "show", "neighbors", "details") assert out['lldp.eth0.port.descr'] == 'eth1' @@ -251,6 +369,8 @@ def test_new_port_take_default(lldpd1, lldpd, lldpcli, namespaces, links): "spare class class-3").split()) assert result.returncode == 0 time.sleep(3) + out = lldpcli("-f", "keyvalue", "show", "interfaces", "details") + assert out['lldp.eth1.port.power.device-type'] == 'PSE' with namespaces(1): # Check this worked out = lldpcli("-f", "keyvalue", "show", "neighbors", "details") @@ -262,6 +382,9 @@ def test_new_port_take_default(lldpd1, lldpd, lldpcli, namespaces, links): out = lldpcli("-f", "keyvalue", "show", "neighbors", "details") assert out['lldp.eth2.port.descr'] == 'eth3' assert out['lldp.eth2.port.power.device-type'] == 'PSE' + with namespaces(2): + out = lldpcli("-f", "keyvalue", "show", "interfaces", "details") + assert out['lldp.eth3.port.power.device-type'] == 'PSE' @pytest.mark.skipif('Dot3' not in pytest.config.lldpd.features, @@ -279,6 +402,8 @@ def test_port_keep_configuration(lldpd1, lldpd, lldpcli, namespaces, links): time.sleep(4) links.up('eth3') time.sleep(4) + out = lldpcli("-f", "keyvalue", "show", "interfaces", "details") + assert out['lldp.eth3.port.power.device-type'] == 'PSE' with namespaces(1): out = lldpcli("-f", "keyvalue", "show", "neighbors", "details") assert out['lldp.eth2.port.descr'] == 'eth3' @@ -364,5 +489,7 @@ def test_return_code(lldpd1, lldpcli, namespaces): with namespaces(1): result = lldpcli("show", "neighbors") assert result.returncode == 0 + result = lldpcli("show", "interfaces") + assert result.returncode == 0 result = lldpcli("unknown", "command") assert result.returncode == 1