• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1% LLDP test campaign
2
3#
4# execute test:
5# > test/run_tests -P "load_contrib('lldp')" -t test/contrib/lldp.uts
6#
7
8+ Basic layer handling
9= build basic LLDP frames
10
11frm = Ether(src='01:01:01:01:01:01', dst=LLDP_NEAREST_BRIDGE_MAC)/ \
12      LLDPDUChassisID(subtype=LLDPDUChassisID.SUBTYPE_MAC_ADDRESS, id=b'\x06\x05\x04\x03\x02\x01') / \
13      LLDPDUPortID(subtype=LLDPDUPortID.SUBTYPE_MAC_ADDRESS, id=b'\x01\x02\x03\x04\x05\x06')/\
14      LLDPDUTimeToLive()/\
15      LLDPDUSystemName(system_name='mate')/\
16      LLDPDUSystemCapabilities(telephone_available=1, router_available=1, telephone_enabled=1)/\
17      LLDPDUManagementAddress(
18            management_address_subtype=LLDPDUManagementAddress.SUBTYPE_MANAGEMENT_ADDRESS_IPV4,
19            management_address='1.2.3.4',
20            interface_numbering_subtype=LLDPDUManagementAddress.SUBTYPE_INTERFACE_NUMBER_IF_INDEX,
21            interface_number=23,
22            object_id='abcd') / \
23      LLDPDUEndOfLLDPDU()
24
25frm = frm.build()
26frm = Ether(frm)
27
28= build: check length calculation (#GH3107)
29
30frame = Ether(src='aa:bb:cc:dd:ee:ff', dst='11:22:33:44:55:66') / \
31        LLDPDUChassisID(subtype=0x04, id='aa:bb:cc:dd:ee:ff') / \
32        LLDPDUPortID(subtype=0x05, id='1') / \
33        LLDPDUTimeToLive(ttl=5) / \
34        LLDPDUManagementAddress(management_address_subtype=0x01, management_address=socket.inet_aton('192.168.0.10'))
35data = b'\x11"3DUf\xaa\xbb\xcc\xdd\xee\xff\x88\xcc\x02\x07\x04\xaa\xbb\xcc\xdd\xee\xff\x04\x02\x051\x06\x02\x00\x05\x10\x0c\x05\x01\xc0\xa8\x00\n\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
36assert bytes(frame) == data
37
38= add padding if required
39
40conf.contribs['LLDP'].strict_mode_disable()
41frm = Ether(src='01:01:01:01:01:01', dst=LLDP_NEAREST_BRIDGE_MAC) / \
42      LLDPDUPortID(subtype=LLDPDUPortID.SUBTYPE_INTERFACE_NAME, id='eth0') / \
43      LLDPDUChassisID(subtype=LLDPDUChassisID.SUBTYPE_MAC_ADDRESS, id='06:05:04:03:02:01') / \
44      LLDPDUTimeToLive() / \
45      LLDPDUEndOfLLDPDU()
46assert len(raw(frm)) == 60
47assert len(raw(Ether(raw(frm))[Padding])) == 24
48
49frm = Ether(src='01:01:01:01:01:01', dst=LLDP_NEAREST_BRIDGE_MAC) / \
50      LLDPDUPortID(subtype=LLDPDUPortID.SUBTYPE_INTERFACE_NAME, id='eth012345678901234567890123') / \
51      LLDPDUChassisID(subtype=LLDPDUChassisID.SUBTYPE_MAC_ADDRESS, id='06:05:04:03:02:01') / \
52      LLDPDUTimeToLive() / \
53      LLDPDUEndOfLLDPDU()
54assert (len(raw(frm)) == 60)
55assert (len(raw(Ether(raw(frm))[Padding])) == 1)
56
57frm = Ether(src='01:01:01:01:01:01', dst=LLDP_NEAREST_BRIDGE_MAC) / \
58      LLDPDUPortID(subtype=LLDPDUPortID.SUBTYPE_INTERFACE_NAME, id='eth0123456789012345678901234') / \
59      LLDPDUChassisID(subtype=LLDPDUChassisID.SUBTYPE_MAC_ADDRESS, id='06:05:04:03:02:01') / \
60      LLDPDUTimeToLive() / \
61      LLDPDUEndOfLLDPDU()
62assert (len(raw(frm)) == 60)
63try:
64      Ether(raw(frm))[Padding]
65      assert False
66except IndexError:
67      pass
68
69= Dissection: PtopoChassisIdType == chasIdPtopoGenAddr(5)
70
71data = hex_bytes("0180c200000e00192fa7b28d88cc0206050101020304040d0155706c696e6b20746f205331060200780a0c53322e636973636f2e636f6d0cbe436973636f20494f5320536f6674776172652c20433335363020536f667477617265202843333536302d414456495053455256494345534b392d4d292c2056657273696f6e2031322e322834342953452c2052454c4541534520534f4654574152452028666331290a436f707972696768742028632920313938362d3230303820627920436973636f2053797374656d732c20496e632e0a436f6d70696c6564205361742030352d4a616e2d30382030303a3135206279207765696c697508134769676162697445746865726e6574302f31330e0400140004fe060080c2010001fe0900120f0103c03600100000")
72pkt = Ether(data)
73
74assert pkt.family == 1
75assert pkt.id == "1.2.3.4"
76
77= Advanced test: check definitions and length of complex IDs
78
79pkt = Ether()/LLDPDUChassisID(id="ff:dd:ee:bb:aa:99", subtype=0x04)/LLDPDUPortID(subtype=0x03, id="aa:bb:cc:dd:ee:ff")/LLDPDUTimeToLive(ttl=120)/LLDPDUEndOfLLDPDU()
80pkt = Ether(raw(pkt))
81assert pkt[LLDPDUChassisID].fields_desc[2].i2s == LLDPDUChassisID.LLDP_CHASSIS_ID_TLV_SUBTYPES
82assert pkt[LLDPDUPortID].fields_desc[2].i2s == LLDPDUPortID.LLDP_PORT_ID_TLV_SUBTYPES
83assert pkt[LLDPDUChassisID]._length == 7
84assert pkt[LLDPDUPortID]._length == 7
85
86= Network families / addresses in IDs
87
88# IPv4
89
90pkt = Ether()/LLDPDUChassisID(subtype=0x05, family=1, id="1.1.1.1")/LLDPDUPortID(subtype=0x04, family=1, id="2.2.2.2")/LLDPDUTimeToLive()/LLDPDUEndOfLLDPDU()
91pkt = Ether(raw(pkt))
92assert pkt[LLDPDUChassisID].id == "1.1.1.1"
93assert pkt[LLDPDUPortID].id == "2.2.2.2"
94
95pkt = Ether(hex_bytes(b'ffffffffffff0242ac11000288cc02060501010101010406040102020202060200140000'))
96assert pkt[LLDPDUChassisID].id == "1.1.1.1"
97assert pkt[LLDPDUPortID].id == "2.2.2.2"
98
99try:
100      pkt = Ether()/LLDPDUChassisID(subtype=0x05, family=1, id="2001::abcd")/LLDPDUPortID()/LLDPDUTimeToLive()/LLDPDUEndOfLLDPDU()
101      assert False
102except (socket.gaierror, AssertionError):
103      pass
104
105try:
106      pkt = Ether()/LLDPDUChassisID()/LLDPDUPortID(subtype=0x04, family=1, id="2001::abcd")/LLDPDUTimeToLive()/LLDPDUEndOfLLDPDU()
107      assert False
108except (socket.gaierror, AssertionError):
109      pass
110
111# IPv6
112
113pkt = Ether()/LLDPDUChassisID(subtype=0x05, family=2, id="1111::2222")/LLDPDUPortID(subtype=0x04, family=2, id="2001::abcd")/LLDPDUTimeToLive()/LLDPDUEndOfLLDPDU()
114pkt = Ether(raw(pkt))
115assert pkt[LLDPDUChassisID].id == "1111::2222"
116assert pkt[LLDPDUPortID].id == "2001::abcd"
117
118pkt = Ether(hex_bytes(b'ffffffffffff0242ac11000288cc0212050211110000000000000000000000002222041204022001000000000000000000000000abcd060200140000'))
119assert pkt[LLDPDUChassisID].id == "1111::2222"
120assert pkt[LLDPDUPortID].id == "2001::abcd"
121
122try:
123      pkt = Ether()/LLDPDUChassisID(subtype=0x05, family=2, id="1.1.1.1")/LLDPDUPortID()/LLDPDUTimeToLive()/LLDPDUEndOfLLDPDU()
124      assert False
125except (socket.gaierror, AssertionError):
126      pass
127
128try:
129      pkt = Ether()/LLDPDUChassisID()/LLDPDUPortID(subtype=0x04, family=2, id="1.1.1.1")/LLDPDUTimeToLive()/LLDPDUEndOfLLDPDU()
130      assert False
131except (socket.gaierror, AssertionError):
132      pass
133
134# Other
135
136pkt = Ether()/LLDPDUChassisID(subtype=0x05, id=b"\x00\x07\xab")/LLDPDUPortID(subtype=0x04, id=b"\x07\xaa\xbb\xcc")/LLDPDUTimeToLive()/LLDPDUEndOfLLDPDU()
137pkt = Ether(raw(pkt))
138assert pkt[LLDPDUChassisID].id == b"\x00\x07\xab"
139assert pkt[LLDPDUPortID].id == b"\x07\xaa\xbb\xcc"
140
141pkt = Ether(hex_bytes(b'ffffffffffff0242ac11000288cc020505000007ab0406040007aabbcc060200140000'))
142assert pkt[LLDPDUChassisID].id == b"\x00\x07\xab"
143assert pkt[LLDPDUPortID].id == b"\x07\xaa\xbb\xcc"
144
145+ strict mode handling - build
146= basic frame structure
147
148conf.contribs['LLDP'].strict_mode_enable()
149
150# invalid length in LLDPDUEndOfLLDPDU
151try:
152      frm = Ether()/LLDPDUChassisID(id='slartibart')/LLDPDUPortID(id='42')/LLDPDUTimeToLive()/LLDPDUEndOfLLDPDU(_length=8)
153      frm.build()
154      assert False
155except LLDPInvalidLengthField:
156      pass
157
158# missing chassis id
159try:
160      frm = Ether()/LLDPDUChassisID()/LLDPDUPortID(id='42')/LLDPDUTimeToLive()/LLDPDUEndOfLLDPDU()
161      frm.build()
162      assert False
163except LLDPInvalidLengthField:
164      pass
165
166# missing management address
167try:
168      frm = Ether()/LLDPDUChassisID(id='slartibart')/LLDPDUPortID(id='42')/LLDPDUTimeToLive()/LLDPDUManagementAddress()/LLDPDUEndOfLLDPDU()
169      frm.build()
170      assert False
171except LLDPInvalidLengthField:
172      pass
173
174+ strict mode handling - dissect
175= basic frame structure
176
177conf.contribs['LLDP'].strict_mode_enable()
178# missing PortIDTLV
179try:
180      frm = Ether() / LLDPDUChassisID(id='slartibart') / LLDPDUTimeToLive() / LLDPDUEndOfLLDPDU()
181      Ether(frm.build())
182      assert False
183except LLDPInvalidFrameStructure:
184      pass
185
186# invalid order
187try:
188      frm = Ether() / LLDPDUPortID(id='42') / LLDPDUChassisID(id='slartibart') / LLDPDUTimeToLive() / LLDPDUEndOfLLDPDU()
189      Ether(frm.build())
190      assert False
191except LLDPInvalidFrameStructure:
192      pass
193
194# layer LLDPDUPortID occurs twice
195try:
196      frm = Ether() / LLDPDUChassisID(id='slartibart') / LLDPDUPortID(id='42') / LLDPDUPortID(id='23')  / LLDPDUTimeToLive() / LLDPDUEndOfLLDPDU()
197      Ether(frm.build())
198      assert False
199except LLDPInvalidFrameStructure:
200      pass
201
202# missing LLDPDUEndOfLLDPDU
203try:
204      frm = Ether() / LLDPDUChassisID(id='slartibart') / LLDPDUPortID(id='42') / \
205            LLDPDUPortID(id='23') / LLDPDUTimeToLive() / LLDPDUEndOfLLDPDU()
206      Ether(frm.build())
207      assert False
208except LLDPInvalidFrameStructure:
209      pass
210
211conf.contribs['LLDP'].strict_mode_disable()
212frm = Ether()/LLDPDUChassisID()/LLDPDUTimeToLive()/LLDPDUEndOfLLDPDU()
213frm = Ether(frm.build())
214
215= length fields / value sizes checks
216
217conf.contribs['LLDP'].strict_mode_enable()
218# missing chassis id => invalid length
219try:
220      frm = Ether() / LLDPDUChassisID() / LLDPDUPortID(id='42') / LLDPDUTimeToLive() / LLDPDUEndOfLLDPDU()
221      Ether(frm.build())
222      assert False
223except LLDPInvalidLengthField:
224      pass
225
226# invalid length in LLDPDUEndOfLLDPDU
227try:
228      frm = Ether()/LLDPDUChassisID(id='slartibart')/LLDPDUPortID(id='42')/LLDPDUTimeToLive()/LLDPDUEndOfLLDPDU(_length=8)
229      Ether(frm.build())
230      assert False
231except LLDPInvalidLengthField:
232      pass
233
234# invalid management address
235try:
236      frm = Ether() / LLDPDUChassisID(id='slartibart') / LLDPDUPortID(id='42') / LLDPDUTimeToLive() / LLDPDUManagementAddress() / LLDPDUEndOfLLDPDU()
237      Ether(frm.build())
238      assert False
239except LLDPInvalidLengthField:
240      pass
241
242conf.contribs['LLDP'].strict_mode_disable()
243
244frm = Ether() / LLDPDUChassisID(id='slartibart') / LLDPDUPortID(id='42') / LLDPDUTimeToLive() / LLDPDUEndOfLLDPDU()
245frm = Ether(frm.build())
246
247frm = Ether() / LLDPDUChassisID() / LLDPDUPortID() / LLDPDUTimeToLive() / LLDPDUEndOfLLDPDU(_length=8)
248frm = Ether(frm.build())
249
250= test attribute values
251
252conf.contribs['LLDP'].strict_mode_enable()
253
254frm = Ether(src='01:01:01:01:01:01', dst=LLDP_NEAREST_BRIDGE_MAC)/ \
255      LLDPDUChassisID(subtype=LLDPDUChassisID.SUBTYPE_MAC_ADDRESS, id='06:05:04:03:02:01') / \
256      LLDPDUPortID(subtype=LLDPDUPortID.SUBTYPE_MAC_ADDRESS, id='01:02:03:04:05:06')/\
257      LLDPDUTimeToLive()/\
258      LLDPDUSystemName(system_name='things will')/\
259      LLDPDUSystemCapabilities(telephone_available=1,
260                               router_available=1,
261                               telephone_enabled=1,
262                               router_enabled=1)/\
263      LLDPDUManagementAddress(
264            management_address_subtype=LLDPDUManagementAddress.SUBTYPE_MANAGEMENT_ADDRESS_IPV4,
265            management_address='1.2.3.4',
266            interface_numbering_subtype=LLDPDUManagementAddress.SUBTYPE_INTERFACE_NUMBER_IF_INDEX,
267            interface_number=23,
268            object_id='burn') / \
269      LLDPDUSystemDescription(description='without tests.') / \
270      LLDPDUPortDescription(description='always!') / \
271      LLDPDUEndOfLLDPDU()
272
273frm = Ether(frm.build())
274
275assert frm[LLDPDUChassisID].id == '06:05:04:03:02:01'
276assert frm[LLDPDUPortID].id == '01:02:03:04:05:06'
277sys_capabilities = frm[LLDPDUSystemCapabilities]
278assert sys_capabilities.reserved_5_available == 0
279assert sys_capabilities.reserved_4_available == 0
280assert sys_capabilities.reserved_3_available == 0
281assert sys_capabilities.reserved_2_available == 0
282assert sys_capabilities.reserved_1_available == 0
283assert sys_capabilities.two_port_mac_relay_available == 0
284assert sys_capabilities.s_vlan_component_available == 0
285assert sys_capabilities.c_vlan_component_available == 0
286assert sys_capabilities.station_only_available == 0
287assert sys_capabilities.docsis_cable_device_available == 0
288assert sys_capabilities.telephone_available == 1
289assert sys_capabilities.router_available == 1
290assert sys_capabilities.wlan_access_point_available == 0
291assert sys_capabilities.mac_bridge_available == 0
292assert sys_capabilities.repeater_available == 0
293assert sys_capabilities.other_available == 0
294assert sys_capabilities.reserved_5_enabled == 0
295assert sys_capabilities.reserved_4_enabled == 0
296assert sys_capabilities.reserved_3_enabled == 0
297assert sys_capabilities.reserved_2_enabled == 0
298assert sys_capabilities.reserved_1_enabled == 0
299assert sys_capabilities.two_port_mac_relay_enabled == 0
300assert sys_capabilities.s_vlan_component_enabled == 0
301assert sys_capabilities.c_vlan_component_enabled == 0
302assert sys_capabilities.station_only_enabled == 0
303assert sys_capabilities.docsis_cable_device_enabled == 0
304assert sys_capabilities.telephone_enabled == 1
305assert sys_capabilities.router_enabled == 1
306assert sys_capabilities.wlan_access_point_enabled == 0
307assert sys_capabilities.mac_bridge_enabled == 0
308assert sys_capabilities.repeater_enabled == 0
309assert sys_capabilities.other_enabled == 0
310assert frm[LLDPDUManagementAddress].management_address == b'1.2.3.4'
311assert frm[LLDPDUSystemName].system_name == b'things will'
312assert frm[LLDPDUManagementAddress].object_id == b'burn'
313assert frm[LLDPDUSystemDescription].description == b'without tests.'
314assert frm[LLDPDUPortDescription].description == b'always!'
315
316+ organisation specific layers
317
318= ThreeBytesEnumField tests
319
320three_b_enum_field = ThreeBytesEnumField('test', 0x00,
321                                         {
322                                             0x0e: 'fourteen',
323                                             0x00: 'zero',
324                                             0x5566: 'five-six',
325                                             0x0e0000: 'fourteen-zero-zero',
326                                             0x0e0100: 'fourteen-one-zero',
327                                             0x112233: '1#2#3'
328                                         })
329
330assert three_b_enum_field.i2repr(None, 0) == 'zero'
331assert three_b_enum_field.i2repr(None, 0x0e) == 'fourteen'
332assert three_b_enum_field.i2repr(None, 0x5566) == 'five-six'
333assert three_b_enum_field.i2repr(None, 0x112233) == '1#2#3'
334assert three_b_enum_field.i2repr(None, 0x0e0000) == 'fourteen-zero-zero'
335assert three_b_enum_field.i2repr(None, 0x0e0100) == 'fourteen-one-zero'
336assert three_b_enum_field.i2repr(None, 0x01) == '1'
337assert three_b_enum_field.i2repr(None, 0x49763) == '300899'
338
339= LLDPDUGenericOrganisationSpecific tests
340
341frm = Ether(src='01:01:01:01:01:01', dst=LLDP_NEAREST_BRIDGE_MAC)/\
342      LLDPDUChassisID(subtype=LLDPDUChassisID.SUBTYPE_MAC_ADDRESS, id=b'\x06\x05\x04\x03\x02\x01')/\
343      LLDPDUPortID(subtype=LLDPDUPortID.SUBTYPE_MAC_ADDRESS, id=b'\x01\x02\x03\x04\x05\x06')/\
344      LLDPDUTimeToLive()/\
345      LLDPDUGenericOrganisationSpecific(org_code=LLDPDUGenericOrganisationSpecific.ORG_UNIQUE_CODE_PNO,
346                                        subtype=0x42,
347                                        data=b'FooBar'*5
348                                        )/\
349      LLDPDUEndOfLLDPDU()
350
351frm = frm.build()
352frm = Ether(frm)
353org_spec_layer = frm[LLDPDUGenericOrganisationSpecific]
354assert org_spec_layer
355assert org_spec_layer._type == 127
356assert org_spec_layer.org_code == LLDPDUGenericOrganisationSpecific.ORG_UNIQUE_CODE_PNO
357assert org_spec_layer.subtype == 0x42
358assert org_spec_layer._length == 34
359
360l="A" * 24
361c=LLDPDUChassisID.SUBTYPE_CHASSIS_COMPONENT
362p=LLDPDUPortID.SUBTYPE_MAC_ADDRESS
363frm = Ether(dst=LLDP_NEAREST_BRIDGE_MAC)/  \
364    LLDPDUChassisID(subtype=c, id=l)/      \
365    LLDPDUPortID(subtype=p, id=l)/         \
366    LLDPDUTimeToLive(ttl=2)/               \
367    LLDPDUEndOfLLDPDU()
368
369try:
370    frm = frm.build()
371except:
372    assert False
373
374+ Power via MDI
375~ tshark
376
377= Define check_tshark function
378
379def check_tshark(pkt, frame_type, selector):
380    import tempfile, os
381    fd, pcapfilename = tempfile.mkstemp()
382    wrpcap(pcapfilename, pkt)
383    rv = tcpdump(pcapfilename, prog=conf.prog.tshark, getfd=True,
384                 args=['-Y', frame_type, '-T', 'fields', '-e', selector], dump=True, wait=True)
385    os.close(fd)
386    os.unlink(pcapfilename)
387    return rv.decode("utf8").strip()
388
389= Power via MDI tests
390
391frm = Ether(src='01:01:01:01:01:01', dst=LLDP_NEAREST_BRIDGE_MAC)/\
392      LLDPDUChassisID(subtype=LLDPDUChassisID.SUBTYPE_MAC_ADDRESS, id=b'\x06\x05\x04\x03\x02\x01')/\
393      LLDPDUPortID(subtype=LLDPDUPortID.SUBTYPE_MAC_ADDRESS, id=b'\x01\x02\x03\x04\x05\x06')/\
394      LLDPDUTimeToLive()/\
395      LLDPDUGenericOrganisationSpecific(org_code=LLDPDUGenericOrganisationSpecific.ORG_UNIQUE_CODE_PNO,
396                                        subtype=0x42,
397                                        data=b'FooBar'*5
398                                        )/\
399      LLDPDUPowerViaMDI(MDI_power_support='PSE MDI power enabled+PSE MDI power supported',
400                        PSE_power_pair='alt B',
401                        power_class='class 3')/\
402      LLDPDUEndOfLLDPDU()
403
404frm = frm.build()
405frm = Ether(frm)
406poe_layer = frm[LLDPDUPowerViaMDI]
407# Legacy PoE TLV is not supported by WireShark
408assert poe_layer
409assert poe_layer._type == 127
410assert int(check_tshark(frm, "lldp", "lldp.tlv.type").split(',')[-2], 0) == 127
411assert poe_layer.org_code == LLDPDUGenericOrganisationSpecific.ORG_UNIQUE_CODE_IEEE_802_3
412assert int(check_tshark(frm, "lldp", "lldp.orgtlv.oui").split(',')[-1], 0) == 4623
413assert poe_layer.subtype == 2
414assert int(check_tshark(frm, "lldp", "lldp.ieee.802_3.subtype"), 0) == 0x02
415assert poe_layer._length == 7
416assert int(check_tshark(frm, "lldp", "lldp.tlv.len").split(',')[-2], 0) == 7
417assert poe_layer.MDI_power_support == 6
418assert int(check_tshark(frm, "lldp", "lldp.ieee.802_3.mdi_power_support"), 0) == 6
419assert poe_layer.PSE_power_pair == 2
420assert int(check_tshark(frm, "lldp", "lldp.ieee.802_3.mdi_pse_pair"), 0) == 2
421assert poe_layer.power_class == 4
422assert int(check_tshark(frm, "lldp", "lldp.ieee.802_3.mdi_power_class"), 0) == 4
423
424
425frm = Ether(src='01:01:01:01:01:01', dst=LLDP_NEAREST_BRIDGE_MAC)/\
426            LLDPDUChassisID(subtype=LLDPDUChassisID.SUBTYPE_MAC_ADDRESS, id=b'\x06\x05\x04\x03\x02\x01')/\
427            LLDPDUPortID(subtype=LLDPDUPortID.SUBTYPE_MAC_ADDRESS, id=b'\x01\x02\x03\x04\x05\x06')/\
428            LLDPDUTimeToLive()/\
429            LLDPDUGenericOrganisationSpecific(org_code=LLDPDUGenericOrganisationSpecific.ORG_UNIQUE_CODE_PNO,
430                                              subtype=0x42,
431                                              data=b'FooBar'*5
432                                              )
433# invalid length
434try:
435    Ether((frm/
436           LLDPDUPowerViaMDI(_length=8)/
437           LLDPDUEndOfLLDPDU()).build())
438    assert False
439except LLDPInvalidLengthField:
440    pass
441
442= Power via MDI with DDL classification extension tests
443
444frm = Ether(src='01:01:01:01:01:01', dst=LLDP_NEAREST_BRIDGE_MAC)/\
445      LLDPDUChassisID(subtype=LLDPDUChassisID.SUBTYPE_MAC_ADDRESS, id=b'\x06\x05\x04\x03\x02\x01')/\
446      LLDPDUPortID(subtype=LLDPDUPortID.SUBTYPE_MAC_ADDRESS, id=b'\x01\x02\x03\x04\x05\x06')/\
447      LLDPDUTimeToLive()/\
448      LLDPDUGenericOrganisationSpecific(org_code=LLDPDUGenericOrganisationSpecific.ORG_UNIQUE_CODE_PNO,
449                                        subtype=0x42,
450                                        data=b'FooBar'*5
451                                        )/\
452      LLDPDUPowerViaMDIDDL(MDI_power_support='PSE pairs controlled+PSE MDI power enabled',
453                           PSE_power_pair='alt A',
454                           power_class='class 4 and above',
455			   power_type_no='type 2',
456                           power_type_dir='PSE',
457			   power_source='backup source',
458			   power_prio='high',
459			   PD_requested_power=2.21111,
460			   PSE_allocated_power=1.521212121)/\
461      LLDPDUEndOfLLDPDU()
462
463frm = frm.build()
464frm = Ether(frm)
465poe_layer = frm[LLDPDUPowerViaMDIDDL]
466assert poe_layer
467assert poe_layer._type == 127
468assert int(check_tshark(frm, "lldp", "lldp.tlv.type").split(',')[-2], 0) == 127
469assert poe_layer.org_code == LLDPDUGenericOrganisationSpecific.ORG_UNIQUE_CODE_IEEE_802_3
470assert int(check_tshark(frm, "lldp", "lldp.orgtlv.oui").split(',')[-1], 0) == 4623
471assert poe_layer.subtype == 2
472assert int(check_tshark(frm, "lldp", "lldp.ieee.802_3.subtype"), 0) == 0x02
473assert poe_layer._length == 12
474assert int(check_tshark(frm, "lldp", "lldp.tlv.len").split(',')[-2], 0) == 12
475assert poe_layer.MDI_power_support == 12
476assert int(check_tshark(frm, "lldp", "lldp.ieee.802_3.mdi_power_support"), 0) == 12
477assert poe_layer.PSE_power_pair == 1
478assert int(check_tshark(frm, "lldp", "lldp.ieee.802_3.mdi_pse_pair"), 0) == 1
479# NOTE: wireshark mixes power_prio and PD_4PID fields. Result will be incerrect if PD_4PID==1
480assert poe_layer.power_class == 5
481assert int(check_tshark(frm, "lldp", "lldp.ieee.802_3.mdi_power_class"), 0) == 5
482assert poe_layer.power_type_no == 0
483assert poe_layer.power_type_dir == 0
484assert int(check_tshark(frm, "lldp", "lldp.ieee.802_3.mdi_power_type"), 0) == 0
485assert poe_layer.power_source == 0b10
486assert int(check_tshark(frm, "lldp", "lldp.ieee.802_3.mdi_power_source"), 0) == 0b10
487assert poe_layer.power_prio == 0b10
488assert int(check_tshark(frm, "lldp", "lldp.ieee.802_3.mdi_power_priority"), 0) == 0b10
489assert poe_layer.PD_requested_power == 2.2
490assert int(check_tshark(frm, "lldp", "lldp.ieee.802_3.mdi_pde_requested"), 0) == 22
491assert poe_layer.PSE_allocated_power == 1.5
492assert int(check_tshark(frm, "lldp", "lldp.ieee.802_3.mdi_pse_allocated"), 0) == 15
493
494
495frm = Ether(src='01:01:01:01:01:01', dst=LLDP_NEAREST_BRIDGE_MAC)/\
496            LLDPDUChassisID(subtype=LLDPDUChassisID.SUBTYPE_MAC_ADDRESS, id=b'\x06\x05\x04\x03\x02\x01')/\
497            LLDPDUPortID(subtype=LLDPDUPortID.SUBTYPE_MAC_ADDRESS, id=b'\x01\x02\x03\x04\x05\x06')/\
498            LLDPDUTimeToLive()/\
499            LLDPDUGenericOrganisationSpecific(org_code=LLDPDUGenericOrganisationSpecific.ORG_UNIQUE_CODE_PNO,
500                                              subtype=0x42,
501                                              data=b'FooBar'*5
502                                              )
503# invalid length
504try:
505    Ether((frm/
506           LLDPDUPowerViaMDIDDL(_length=8)/
507           LLDPDUEndOfLLDPDU()).build())
508    assert False
509except LLDPInvalidLengthField:
510    pass
511
512# invalid power
513try:
514    Ether((frm/
515           LLDPDUPowerViaMDIDDL(PD_requested_power=100)/
516           LLDPDUEndOfLLDPDU()).build())
517    assert False
518except LLDPInvalidFieldValue:
519    pass
520
521try:
522    Ether((frm/
523           LLDPDUPowerViaMDIDDL(PSE_allocated_power=100)/
524           LLDPDUEndOfLLDPDU()).build())
525    assert False
526except LLDPInvalidFieldValue:
527    pass
528
529= Power via MDI with DDL classification and Type 3 and 4 extensions tests
530
531frm = Ether(src='01:01:01:01:01:01', dst=LLDP_NEAREST_BRIDGE_MAC)/\
532      LLDPDUChassisID(subtype=LLDPDUChassisID.SUBTYPE_MAC_ADDRESS, id=b'\x06\x05\x04\x03\x02\x01')/\
533      LLDPDUPortID(subtype=LLDPDUPortID.SUBTYPE_MAC_ADDRESS, id=b'\x01\x02\x03\x04\x05\x06')/\
534      LLDPDUTimeToLive()/\
535      LLDPDUGenericOrganisationSpecific(org_code=LLDPDUGenericOrganisationSpecific.ORG_UNIQUE_CODE_PNO,
536                                        subtype=0x42,
537                                        data=b'FooBar'*5
538                                        )/\
539      LLDPDUPowerViaMDIType34(MDI_power_support='port class PSE+PSE pairs controlled+PSE MDI power enabled',
540                              PSE_power_pair='alt B',
541                              power_class='class 2',
542                              power_type_no='type 1',
543                              power_type_dir='PD',
544                              power_source='PSE and local',
545                              PD_4PID='not supported',
546                              power_prio='low',
547                              PD_requested_power=12.21111,
548                              PSE_allocated_power=11.521212121,
549                              PD_requested_power_mode_A=2.3,
550                              PD_requested_power_mode_B=3.3,
551                              PD_allocated_power_alt_A=3.1,
552                              PD_allocated_power_alt_B=0.5,
553                              PSE_powering_status='4-pair powering single-signature PD',
554                              PD_powered_status='powered single-signature PD',
555                              PD_power_pair_ext='both alts',
556                              dual_signature_class_mode_A='class 4',
557                              dual_signature_class_mode_B='class 2',
558                              power_class_ext='dual-signature pd',
559                              power_type_ext='type 4 single-signature PD',
560                              PD_load='dual-signature and electrically isolated',
561                              PSE_max_available_power=33.333,
562                              autoclass='autoclass completed+autoclass request',
563                              power_down_req='power down',
564                              power_down_time=123)/\
565    LLDPDUEndOfLLDPDU()
566
567frm = frm.build()
568frm = Ether(frm)
569poe_layer = frm[LLDPDUPowerViaMDIType34]
570assert poe_layer
571assert poe_layer._type == 127
572assert int(check_tshark(frm, "lldp", "lldp.tlv.type").split(',')[-2], 0) == 127
573assert poe_layer.org_code == LLDPDUGenericOrganisationSpecific.ORG_UNIQUE_CODE_IEEE_802_3
574assert int(check_tshark(frm, "lldp", "lldp.orgtlv.oui").split(',')[-1], 0) == 4623
575assert poe_layer.subtype == 2
576assert int(check_tshark(frm, "lldp", "lldp.ieee.802_3.subtype"), 0) == 0x02
577assert poe_layer._length == 29
578assert int(check_tshark(frm, "lldp", "lldp.tlv.len").split(',')[-2], 0) == 29
579assert poe_layer.MDI_power_support == 13
580assert int(check_tshark(frm, "lldp", "lldp.ieee.802_3.mdi_power_support"), 0) == 13
581assert poe_layer.PSE_power_pair == 2
582assert int(check_tshark(frm, "lldp", "lldp.ieee.802_3.mdi_pse_pair"), 0) == 2
583# NOTE: wireshark mixes power_prio and PD_4PID fields. Result will be incerrect if PD_4PID==1
584assert poe_layer.PD_4PID == 0
585assert poe_layer.power_class == 3
586assert int(check_tshark(frm, "lldp", "lldp.ieee.802_3.mdi_power_class"), 0) == 3
587assert poe_layer.power_type_no == 1
588assert poe_layer.power_type_dir == 1
589assert int(check_tshark(frm, "lldp", "lldp.ieee.802_3.mdi_power_type"), 0) == 3
590assert poe_layer.power_source == 0b11
591assert int(check_tshark(frm, "lldp", "lldp.ieee.802_3.mdi_power_source"), 0) == 0b11
592assert poe_layer.power_prio == 0b11
593assert int(check_tshark(frm, "lldp", "lldp.ieee.802_3.mdi_power_priority"), 0) == 0b11
594assert poe_layer.PD_requested_power == 12.2
595assert int(check_tshark(frm, "lldp", "lldp.ieee.802_3.mdi_pde_requested"), 0) == 122
596assert poe_layer.PSE_allocated_power == 11.5
597assert int(check_tshark(frm, "lldp", "lldp.ieee.802_3.mdi_pse_allocated"), 0) == 115
598assert poe_layer.PD_requested_power_mode_A == 2.3
599assert int(check_tshark(frm, "lldp", "lldp.ieee.802_3.bt_ds_pd_requested_power_value_mode_a"), 0) == 23
600assert poe_layer.PD_requested_power_mode_B == 3.3
601assert int(check_tshark(frm, "lldp", "lldp.ieee.802_3.bt_ds_pd_requested_power_value_mode_b"), 0) == 33
602assert poe_layer.PD_allocated_power_alt_A == 3.1
603assert int(check_tshark(frm, "lldp", "lldp.ieee.802_3.bt_ds_pse_allocated_power_value_alt_a"), 0) == 31
604assert poe_layer.PD_allocated_power_alt_B == 0.5
605assert int(check_tshark(frm, "lldp", "lldp.ieee.802_3.bt_ds_pse_allocated_power_value_alt_b"), 0) == 5
606assert poe_layer.PSE_powering_status == 2
607assert int(check_tshark(frm, "lldp", "lldp.ieee.802_3.bt_pse_powering_status"), 0) == 2
608assert poe_layer.PD_powered_status == 1
609assert int(check_tshark(frm, "lldp", "lldp.ieee.802_3.bt_pd_powered_status"), 0) == 1
610assert poe_layer.PD_power_pair_ext == 3
611assert int(check_tshark(frm, "lldp", "lldp.ieee.802_3.bt_pse_power_pairs_ext"), 0) == 3
612assert poe_layer.dual_signature_class_mode_A == 4
613assert int(check_tshark(frm, "lldp", "lldp.ieee.802_3.bt_ds_pwr_class_ext_a"), 0) == 4
614assert poe_layer.dual_signature_class_mode_B == 2
615assert int(check_tshark(frm, "lldp", "lldp.ieee.802_3.bt_ds_pwr_class_ext_b"), 0) == 2
616assert poe_layer.power_class_ext == 15
617assert int(check_tshark(frm, "lldp", "lldp.ieee.802_3.bt_pwr_class_ext_"), 0) == 15
618assert poe_layer.power_type_ext == 4
619assert int(check_tshark(frm, "lldp", "lldp.ieee.802_3.bt_power_type_ext"), 0) == 4
620assert poe_layer.PD_load == 1
621assert poe_layer.PSE_max_available_power == 33.3
622assert int(check_tshark(frm, "lldp", "lldp.ieee.802_3.bt_pse_maximum_available_power_value"), 0) == 333
623assert poe_layer.autoclass == 3
624assert int(check_tshark(frm, "lldp", "lldp.ieee.802_3.bt_autoclass"), 0) == 3
625assert poe_layer.power_down_req == 0x1d
626assert int(check_tshark(frm, "lldp", "lldp.ieee.802_3.bt_power_down_request"), 0) == 0x1d
627assert poe_layer.power_down_time == 123
628assert int(check_tshark(frm, "lldp", "lldp.ieee.802_3.bt_power_down_time"), 0) == 123
629
630
631frm = Ether(src='01:01:01:01:01:01', dst=LLDP_NEAREST_BRIDGE_MAC)/\
632            LLDPDUChassisID(subtype=LLDPDUChassisID.SUBTYPE_MAC_ADDRESS, id=b'\x06\x05\x04\x03\x02\x01')/\
633            LLDPDUPortID(subtype=LLDPDUPortID.SUBTYPE_MAC_ADDRESS, id=b'\x01\x02\x03\x04\x05\x06')/\
634            LLDPDUTimeToLive()/\
635            LLDPDUGenericOrganisationSpecific(org_code=LLDPDUGenericOrganisationSpecific.ORG_UNIQUE_CODE_PNO,
636                                              subtype=0x42,
637                                              data=b'FooBar'*5
638                                              )
639# invalid length
640try:
641    Ether((frm/
642           LLDPDUPowerViaMDIType34(_length=8)/
643           LLDPDUEndOfLLDPDU()).build())
644    assert False
645except LLDPInvalidLengthField:
646    pass
647
648# invalid power
649try:
650    Ether((frm/
651           LLDPDUPowerViaMDIType34(PD_requested_power=100)/
652           LLDPDUEndOfLLDPDU()).build())
653    assert False
654except LLDPInvalidFieldValue:
655    pass
656
657try:
658    Ether((frm/
659           LLDPDUPowerViaMDIType34(PSE_allocated_power=100)/
660           LLDPDUEndOfLLDPDU()).build())
661    assert False
662except LLDPInvalidFieldValue:
663    pass
664
665try:
666    Ether((frm/
667           LLDPDUPowerViaMDIType34(PD_requested_power_mode_A=50)/
668           LLDPDUEndOfLLDPDU()).build())
669    assert False
670except LLDPInvalidFieldValue:
671    pass
672
673try:
674    Ether((frm/
675           LLDPDUPowerViaMDIType34(PD_requested_power_mode_B=50)/
676           LLDPDUEndOfLLDPDU()).build())
677    assert False
678except LLDPInvalidFieldValue:
679    pass
680
681try:
682    Ether((frm/
683           LLDPDUPowerViaMDIType34(PD_allocated_power_alt_A=50)/
684           LLDPDUEndOfLLDPDU()).build())
685    assert False
686except LLDPInvalidFieldValue:
687    pass
688
689try:
690    Ether((frm/
691           LLDPDUPowerViaMDIType34(PD_allocated_power_alt_B=50)/
692           LLDPDUEndOfLLDPDU()).build())
693    assert False
694except LLDPInvalidFieldValue:
695    pass
696
697try:
698    Ether((frm/
699           LLDPDUPowerViaMDIType34(PSE_max_available_power=100)/
700           LLDPDUEndOfLLDPDU()).build())
701    assert False
702except LLDPInvalidFieldValue:
703    pass
704
705# invalid time
706try:
707    Ether((frm/
708           LLDPDUPowerViaMDIType34(power_down_time=(1<<18))/
709           LLDPDUEndOfLLDPDU()).build())
710    assert False
711except LLDPInvalidFieldValue:
712    pass
713
714= Power via MDI measurements tests
715
716import struct
717
718frm = Ether(src='01:01:01:01:01:01', dst=LLDP_NEAREST_BRIDGE_MAC)/\
719    LLDPDUChassisID(subtype=LLDPDUChassisID.SUBTYPE_MAC_ADDRESS, id=b'\x06\x05\x04\x03\x02\x01')/\
720    LLDPDUPortID(subtype=LLDPDUPortID.SUBTYPE_MAC_ADDRESS, id=b'\x01\x02\x03\x04\x05\x06')/\
721    LLDPDUTimeToLive()/\
722    LLDPDUGenericOrganisationSpecific(org_code=LLDPDUGenericOrganisationSpecific.ORG_UNIQUE_CODE_PNO,
723                                      subtype=0x42,
724                                      data=b'FooBar'*5
725                                      )/\
726    LLDPDUPowerViaMDIMeasure(support='power+current',
727                             source='mode B',
728                             request='energy+voltage+current',
729                             valid='power',
730                             voltage_uncertainty=52.25,
731                             current_uncertainty=3.211,
732                             power_uncertainty=140,
733                             energy_uncertainty=2600,
734                             voltage_measurement=22.123,
735                             current_measurement=3.2121,
736                             power_measurement=123.12,
737                             energy_measurement=21123400,
738                             power_price_index='not available')/\
739    LLDPDUEndOfLLDPDU()
740
741frm = frm.build()
742frm = Ether(frm)
743poe_layer = frm[LLDPDUPowerViaMDIMeasure]
744poe_layer_raw = raw(poe_layer)
745
746# PoE measure TLV is not supported by WireShark
747
748assert poe_layer
749assert poe_layer._type == 127
750assert poe_layer.org_code == LLDPDUGenericOrganisationSpecific.ORG_UNIQUE_CODE_IEEE_802_3
751assert poe_layer.subtype == 8
752assert poe_layer._length == 26
753assert poe_layer.support == 0b0110
754assert poe_layer.source == 0b10
755assert poe_layer.request == 0b1101
756assert poe_layer.valid == 0b0010
757assert poe_layer.voltage_uncertainty == 52.25
758assert struct.unpack(">H", poe_layer_raw[8:10])[0] == 52250
759assert poe_layer.current_uncertainty == 3.211
760assert struct.unpack(">H", poe_layer_raw[10:12])[0] == 32110
761assert poe_layer.power_uncertainty == 140
762assert struct.unpack(">H", poe_layer_raw[12:14])[0] == 14000
763assert poe_layer.energy_uncertainty == 2600
764assert struct.unpack(">H", poe_layer_raw[14:16])[0] == 26
765assert poe_layer.voltage_measurement == 22.123
766assert struct.unpack(">H", poe_layer_raw[16:18])[0] == 22123
767assert poe_layer.current_measurement == 3.2121
768assert struct.unpack(">H", poe_layer_raw[18:20])[0] == 32121
769assert poe_layer.power_measurement == 123.12
770assert struct.unpack(">H", poe_layer_raw[20:22])[0] == 12312
771assert poe_layer.energy_measurement == 21123400
772assert struct.unpack(">I", poe_layer_raw[22:26])[0] == 211234
773assert poe_layer.power_price_index == 0xffff
774
775frm = Ether(src='01:01:01:01:01:01', dst=LLDP_NEAREST_BRIDGE_MAC)/\
776            LLDPDUChassisID(subtype=LLDPDUChassisID.SUBTYPE_MAC_ADDRESS, id=b'\x06\x05\x04\x03\x02\x01')/\
777            LLDPDUPortID(subtype=LLDPDUPortID.SUBTYPE_MAC_ADDRESS, id=b'\x01\x02\x03\x04\x05\x06')/\
778            LLDPDUTimeToLive()/\
779            LLDPDUGenericOrganisationSpecific(org_code=LLDPDUGenericOrganisationSpecific.ORG_UNIQUE_CODE_PNO,
780                                              subtype=0x42,
781                                              data=b'FooBar'*5
782                                              )
783# invalid length
784try:
785    Ether((frm/
786           LLDPDUPowerViaMDIMeasure(_length=8)/
787           LLDPDUEndOfLLDPDU()).build())
788    assert False
789except LLDPInvalidLengthField:
790    pass
791
792# invalid voltage
793try:
794    Ether((frm/
795           LLDPDUPowerViaMDIMeasure(voltage_uncertainty=500)/
796           LLDPDUEndOfLLDPDU()).build())
797    assert False
798except LLDPInvalidFieldValue:
799    pass
800
801try:
802    Ether((frm/
803           LLDPDUPowerViaMDIMeasure(voltage_measurement=500)/
804           LLDPDUEndOfLLDPDU()).build())
805    assert False
806except LLDPInvalidFieldValue:
807    pass
808
809# invalid current
810try:
811    Ether((frm/
812           LLDPDUPowerViaMDIMeasure(current_uncertainty=500)/
813           LLDPDUEndOfLLDPDU()).build())
814    assert False
815except LLDPInvalidFieldValue:
816    pass
817
818try:
819    Ether((frm/
820           LLDPDUPowerViaMDIMeasure(current_measurement=500)/
821           LLDPDUEndOfLLDPDU()).build())
822    assert False
823except LLDPInvalidFieldValue:
824    pass
825
826# invalid energy
827try:
828    Ether((frm/
829           LLDPDUPowerViaMDIMeasure(energy_uncertainty=66000000)/
830           LLDPDUEndOfLLDPDU()).build())
831    assert False
832except LLDPInvalidFieldValue:
833    pass
834
835# invalid power
836try:
837    Ether((frm/
838           LLDPDUPowerViaMDIMeasure(power_uncertainty=5000)/
839           LLDPDUEndOfLLDPDU()).build())
840    assert False
841except LLDPInvalidFieldValue:
842    pass
843
844try:
845    Ether((frm/
846           LLDPDUPowerViaMDIMeasure(power_measurement=5000)/
847           LLDPDUEndOfLLDPDU()).build())
848    assert False
849except LLDPInvalidFieldValue:
850    pass
851
852# invalid power price index
853try:
854    Ether((frm/
855           LLDPDUPowerViaMDIMeasure(power_price_index=150)/
856           LLDPDUEndOfLLDPDU()).build())
857    assert False
858except LLDPInvalidFieldValue:
859    pass
860