require 'pio' describe Pio::LLDP do Then { Pio::LLDP == Pio::Lldp } end describe Pio::Lldp do describe '.new' do context 'with :dpid and :port_number' do Given(:lldp) do Pio::Lldp.new(dpid: 0x192fa7b28d, port_number: 1) end describe '#to_binary' do When(:result) { lldp.to_binary } Then do result == [ # Destination MAC 0x01, 0x80, 0xc2, 0x00, 0x00, 0x0e, # Source MAC 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, # Ethertype 0x88, 0xcc, # Chassis ID TLV 0x02, 0x09, 0x07, 0x00, 0x00, 0x00, 0x19, 0x2f, 0xa7, 0xb2, 0x8d, # Port ID TLV 0x04, 0x05, 0x07, 0x00, 0x00, 0x00, 0x01, # Time to live TLV 0x06, 0x02, 0x00, 0x78, # End of LLDPDU TLV 0x00, 0x00, # Padding 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ].pack('C*') end And { result.size == 64 } end end context 'with :dpid, :port_number and :source_mac' do Given(:lldp) do Pio::Lldp.new( dpid: 0x192fa7b28d, port_number: 1, source_mac: '06:05:04:03:02:01' ) end describe '#to_binary' do When(:result) { lldp.to_binary } Then do result == [ # Destination MAC 0x01, 0x80, 0xc2, 0x00, 0x00, 0x0e, # Source MAC 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, # Ethertype 0x88, 0xcc, # Chassis ID TLV 0x02, 0x09, 0x07, 0x00, 0x00, 0x00, 0x19, 0x2f, 0xa7, 0xb2, 0x8d, # Port ID TLV 0x04, 0x05, 0x07, 0x00, 0x00, 0x00, 0x01, # Time to live TLV 0x06, 0x02, 0x00, 0x78, # End of LLDPDU TLV 0x00, 0x00, # Padding 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ].pack('C*') end And { result.size == 64 } end end context 'with :dpid, :port_number, :source_mac and :destination_mac' do Given(:lldp) do Pio::Lldp.new( dpid: 0x192fa7b28d, port_number: 1, source_mac: '06:05:04:03:02:01', destination_mac: '01:02:03:04:05:06' ) end describe '#to_binary' do When(:result) { lldp.to_binary } Then do result == [ # Destination MAC 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, # Source MAC 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, # Ethertype 0x88, 0xcc, # Chassis ID TLV 0x02, 0x09, 0x07, 0x00, 0x00, 0x00, 0x19, 0x2f, 0xa7, 0xb2, 0x8d, # Port ID TLV 0x04, 0x05, 0x07, 0x00, 0x00, 0x00, 0x01, # Time to live TLV 0x06, 0x02, 0x00, 0x78, # End of LLDPDU TLV 0x00, 0x00, # Padding 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ].pack('C*') end And { result.size == 64 } end end end context '.read' do context 'with a minimum LLDP frame' do Given(:lldp_dump) do [ # Destination MAC 0x01, 0x80, 0xc2, 0x00, 0x00, 0x0e, # Source MAC 0x00, 0x19, 0x2f, 0xa7, 0xb2, 0x8d, # Ethertype 0x88, 0xcc, # Chassis ID TLV 0x02, 0x07, 0x04, 0x00, 0x19, 0x2f, 0xa7, 0xb2, 0x8d, # Port ID TLV 0x04, 0x0d, 0x01, 0x55, 0x70, 0x6c, 0x69, 0x6e, 0x6b, 0x20, 0x74, 0x6f, 0x20, 0x53, 0x31, # Time to live TLV 0x06, 0x02, 0x00, 0x78, # End of LLDPDU TLV 0x00, 0x00 ].pack('C*') end When(:lldp) { Pio::Lldp.read(lldp_dump) } Then { lldp.destination_mac.to_s == '01:80:c2:00:00:0e' } Then { lldp.source_mac.to_s == '00:19:2f:a7:b2:8d' } Then { lldp.ether_type == 0x88cc } Then { lldp.dpid == 0x192fa7b28d } Then { lldp.dpid.class == Fixnum } Then { lldp.chassis_id == 0x192fa7b28d } Then { lldp.port_id == 'Uplink to S1' } Then { lldp.port_number == 'Uplink to S1' } Then { lldp.ttl == 120 } Then { lldp.port_description == nil } Then { lldp.system_name == nil } Then { lldp.system_description == nil } Then { lldp.system_capabilities == nil } Then { lldp.management_address == nil } end context 'with a detailed LLDP frame' do Given(:lldp_dump) do [ # Destination MAC 0x01, 0x80, 0xc2, 0x00, 0x00, 0x0e, # Source MAC 0x00, 0x19, 0x2f, 0xa7, 0xb2, 0x8d, # Ethertype 0x88, 0xcc, # Chassis ID TLV 0x02, 0x07, 0x04, 0x00, 0x19, 0x2f, 0xa7, 0xb2, 0x8d, # Port ID TLV 0x04, 0x0d, 0x01, 0x55, 0x70, 0x6c, 0x69, 0x6e, 0x6b, 0x20, 0x74, 0x6f, 0x20, 0x53, 0x31, # Time to live TLV 0x06, 0x02, 0x00, 0x78, # Port Description 0x08, 0x17, 0x53, 0x75, 0x6d, 0x6d, 0x69, 0x74, 0x33, 0x30, 0x30, 0x2d, 0x34, 0x38, 0x2d, 0x50, 0x6f, 0x72, 0x74, 0x20, 0x31, 0x30, 0x30, 0x31, 0x00, # System Name 0x0a, 0x0d, 0x53, 0x75, 0x6d, 0x6d, 0x69, 0x74, 0x33, 0x30, 0x30, 0x2d, 0x34, 0x38, 0x00, # System Description 0x0c, 0x4c, 0x53, 0x75, 0x6d, 0x6d, 0x69, 0x74, 0x33, 0x30, 0x30, 0x2d, 0x34, 0x38, 0x20, 0x2d, 0x20, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x37, 0x2e, 0x34, 0x65, 0x2e, 0x31, 0x20, 0x28, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x20, 0x35, 0x29, 0x20, 0x62, 0x79, 0x20, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x4d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x20, 0x30, 0x35, 0x2f, 0x32, 0x37, 0x2f, 0x30, 0x35, 0x20, 0x30, 0x34, 0x3a, 0x35, 0x33, 0x3a, 0x31, 0x31, 0x00, # System Capabilities 0x0e, 0x04, 0x00, 0x14, 0x00, 0x14, # Management Address 0x10, 0x0e, 0x07, 0x06, 0x00, 0x01, 0x30, 0xf9, 0xad, 0xa0, 0x02, 0x00, 0x00, 0x03, 0xe9, 0x00, # Organizationally Specific 0xfe, 0x07, 0x00, 0x12, 0x0f, 0x02, 0x07, 0x01, 0x00, # End of LLDPDU TLV 0x00, 0x00 ].pack('C*') end When(:lldp) { Pio::Lldp.read(lldp_dump) } Then { lldp.destination_mac.to_s == '01:80:c2:00:00:0e' } Then { lldp.source_mac.to_s == '00:19:2f:a7:b2:8d' } Then { lldp.ether_type == 0x88cc } Then { lldp.dpid == 0x192fa7b28d } Then { lldp.chassis_id == 0x192fa7b28d } Then { lldp.port_id == 'Uplink to S1' } Then { lldp.port_number == 'Uplink to S1' } Then { lldp.ttl == 120 } Then { lldp.port_description == 'Summit300-48-Port 1001' } Then { lldp.system_name == 'Summit300-48' } Then do lldp.system_description == 'Summit300-48 - Version 7.4e.1 (Build 5) ' \ 'by Release_Master 05/27/05 04:53:11' end Then { lldp.system_capabilities.system_capabilities == 20 } Then { lldp.system_capabilities.enabled_capabilities == 20 } Then do lldp.management_address == [0x00, 0x01, 0x30, 0xf9, 0xad, 0xa0].pack('C*') end Then { lldp.organizationally_specific.oui == 4623 } Then { lldp.organizationally_specific.subtype == 2 } Then { lldp.organizationally_specific.information == "\a\x01" } end context 'with an invalid LLDP frame' do When(:result) { Pio::Lldp.read('') } Then { result == Failure(Pio::ParseError, 'End of file reached') } end end end