Skip to content

Commit

Permalink
Merge pull request msantos#25 from shun159/feature/lldp_capability_flags
Browse files Browse the repository at this point in the history
Fixed system_capability, port_desc, system_name and system_desc field
  • Loading branch information
msantos committed Mar 18, 2015
2 parents ba00da0 + cd3e9d7 commit bbe0b49
Show file tree
Hide file tree
Showing 3 changed files with 142 additions and 27 deletions.
22 changes: 20 additions & 2 deletions include/pkt_lldp.hrl
Original file line number Diff line number Diff line change
Expand Up @@ -101,8 +101,26 @@

-define(SYSTEM_CAPABILITY, 7).

-record(system_capability, { system = 0 :: non_neg_integer(),
enabled = 0 :: non_neg_integer() }).
-type capability_flag() :: other
| repeater
| bridge
| wlan_access_point
| router
| telephone
| docsis
| station_only.

-define(SYSTEM_CAP_OTHER, 1 bsl 0).
-define(SYSTEM_CAP_REPEATER, 1 bsl 1).
-define(SYSTEM_CAP_BRIDGE, 1 bsl 2).
-define(SYSTEM_CAP_WLANAP, 1 bsl 3).
-define(SYSTEM_CAP_ROUTER, 1 bsl 4).
-define(SYSTEM_CAP_TELEPHONE, 1 bsl 5).
-define(SYSTEM_CAP_DOCSIS, 1 bsl 6).
-define(SYSTEM_CAP_STATION, 1 bsl 7).

-record(system_capability, { system = [] :: [capability_flag()],
enabled = [] :: [capability_flag()] }).
-type system_capability() :: #system_capability{}.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Expand Down
82 changes: 71 additions & 11 deletions src/pkt_lldp.erl
Original file line number Diff line number Diff line change
Expand Up @@ -30,18 +30,20 @@ decode(<<?TTL:7, Length:9, Tail/bytes>>, Acc) ->
decode(Rest, [Pdu | Acc]);
decode(<<?PORT_DESC:7, Length:9,
Value:Length/bytes, Rest/bytes>>, Acc) ->
Pdu = #port_desc{ value = Value },
Pdu = #port_desc{ value = decode_string(Value) },
decode(Rest, [Pdu | Acc]);
decode(<<?SYSTEM_NAME:7, Length:9,
Value:Length/bytes, Rest/bytes>>, Acc) ->
Pdu = #system_name{ value = Value },
Pdu = #system_name{ value = decode_string(Value) },
decode(Rest, [Pdu | Acc]);
decode(<<?SYSTEM_DESC:7, Length:9,
Value:Length/bytes, Rest/bytes>>, Acc) ->
Pdu = #system_desc{ value = Value },
Pdu = #system_desc{ value = decode_string(Value) },
decode(Rest, [Pdu | Acc]);
decode(<<?SYSTEM_CAPABILITY:7, _Length:9, Tail/bytes>>, Acc) ->
<<System:16, Enabled:16, Rest/bytes>> = Tail,
<<SystemBin:16/bits, EnabledBin:16/bits, Rest/bytes>> = Tail,
System = binary_to_flags(system_capability, SystemBin),
Enabled = binary_to_flags(system_capability, EnabledBin),
Pdu = #system_capability{ system = System,
enabled = Enabled },
decode(Rest, [Pdu | Acc]);
Expand Down Expand Up @@ -72,17 +74,22 @@ encode_pdu(#port_id{ subtype = SubType, value = Value }) ->
encode_pdu(#ttl{ value = Value }) ->
<<?TTL:7, 2:9, Value:16>>;
encode_pdu(#port_desc{ value = Value }) ->
Length = byte_size(Value),
<<?PORT_DESC:7, Length:9, Value:Length/bytes>>;
Value2 = encode_string(Value),
Length = byte_size(Value2),
<<?PORT_DESC:7, Length:9, Value2:Length/bytes>>;
encode_pdu(#system_name{ value = Value }) ->
Length = byte_size(Value),
<<?SYSTEM_NAME:7, Length:9, Value:Length/bytes>>;
Value2 = encode_string(Value),
Length = byte_size(Value2),
<<?SYSTEM_NAME:7, Length:9, Value2:Length/bytes>>;
encode_pdu(#system_desc{ value = Value }) ->
Length = byte_size(Value),
<<?SYSTEM_DESC:7, Length:9, Value:Length/bytes>>;
Value2 = encode_string(Value),
Length = byte_size(Value2),
<<?SYSTEM_DESC:7, Length:9, Value2:Length/bytes>>;
encode_pdu(#system_capability{ system = System,
enabled = Enabled }) ->
Value = <<System:16, Enabled:16>>,
SystemBin = flags_to_binary(system_capability, System, 16),
EnabledBin = flags_to_binary(system_capability, Enabled, 16),
Value = <<SystemBin:2/bytes, EnabledBin:2/bytes>>,
<<?SYSTEM_CAPABILITY:7, 4:9, Value:4/bytes>>;
encode_pdu(#management_address{ value = Value }) ->
Length = byte_size(Value),
Expand Down Expand Up @@ -121,6 +128,46 @@ map(port_id, interface_name) -> ?PORT_ID_IFNAME;
map(port_id, agent_circuit_id) -> ?PORT_ID_AGENT_CIRC_ID;
map(port_id, locally_assigned) -> ?PORT_ID_LOCALLY.

% Encode Bitmap flags
flags_to_binary(Type, Flags, BitSize) ->
flags_to_binary(Type, Flags, BitSize, <<0:BitSize>>).

flags_to_binary(_, [], _, Binary) -> Binary;
flags_to_binary(Type, [Flag | Rest], BitSize, Binary) ->
<<FlagsInt:BitSize>> = Binary,
FlagInt = proplists:get_value(Flag, enums(Type)),
FlagsInt2 = FlagsInt bor FlagInt,
flags_to_binary(Type, Rest, BitSize, <<FlagsInt2:BitSize>>).

% Decode Bitmap Flags
binary_to_flags(Type, Binary) ->
BitSize = bit_size(Binary),
<<FlagsInt:BitSize>> = Binary,
Keys = proplists:get_keys(enums(Type)),
binary_to_flags(Type, FlagsInt, Keys, []).

binary_to_flags(_, _, [], Flags) -> lists:reverse(Flags);
binary_to_flags(Type, FlagsInt, [Flag | Rest], Flags) ->
FlagInt = proplists:get_value(Flag, enums(Type)),
case 0 /= FlagInt band FlagsInt of
true ->
binary_to_flags(Type, FlagsInt, Rest, [Flag | Flags]);
false ->
binary_to_flags(Type, FlagsInt, Rest, Flags)
end.

% system capability enums
enums(system_capability) ->
[{ other, ?SYSTEM_CAP_OTHER },
{ repeater, ?SYSTEM_CAP_REPEATER },
{ bridge, ?SYSTEM_CAP_BRIDGE },
{ wlan_access_point, ?SYSTEM_CAP_WLANAP },
{ router, ?SYSTEM_CAP_ROUTER },
{ telephone, ?SYSTEM_CAP_TELEPHONE },
{ docsis, ?SYSTEM_CAP_DOCSIS },
{ station_only, ?SYSTEM_CAP_STATION }].

% padding binary to byte length
pad_to(ByteLen, Binary) ->
BinLength = byte_size(Binary),
case ByteLen > BinLength of
Expand All @@ -130,3 +177,16 @@ pad_to(ByteLen, Binary) ->
false ->
Binary
end.

decode_string(Binary) ->
decode_string(Binary, byte_size(Binary) - 1).

decode_string(Binary, Size) when Size >= 0 ->
case binary:at(Binary, Size) of
0 -> decode_string(Binary, Size - 1);
_ -> binary:part(Binary, 0, Size + 1)
end;
decode_string(_, _) ->
<<>>.

encode_string(Binary) -> <<Binary/bytes, 0:8>>.
65 changes: 51 additions & 14 deletions test/pkt_lldp_tests.erl
Original file line number Diff line number Diff line change
Expand Up @@ -10,23 +10,60 @@ codec_test_() ->
].

packet() ->
<<16#02, 16#09, 16#07, 16#00, 16#00, 16#00, 16#00, 16#00,
16#00, 16#01, 16#23, 16#04, 16#05, 16#07, 16#00, 16#00,
16#00, 16#0c, 16#06, 16#02, 16#00, 16#78, 16#00, 16#00,
16#00, 16#00, 16#00, 16#00, 16#00, 16#00, 16#00, 16#00,
16#00, 16#00, 16#00, 16#00, 16#00, 16#00, 16#00, 16#00,
16#00, 16#00, 16#00, 16#00, 16#00, 16#00, 16#00, 16#00,
16#00, 16#00>>.
<<16#02, 16#07, 16#04, 16#00, 16#01, 16#30, 16#f9, 16#ad,
16#a0, 16#04, 16#04, 16#05, 16#31, 16#2f, 16#31, 16#06,
16#02, 16#00, 16#78, 16#08, 16#17, 16#53, 16#75, 16#6d,
16#6d, 16#69, 16#74, 16#33, 16#30, 16#30, 16#2d, 16#34,
16#38, 16#2d, 16#50, 16#6f, 16#72, 16#74, 16#20, 16#31,
16#30, 16#30, 16#31, 16#00, 16#0a, 16#0d, 16#53, 16#75,
16#6d, 16#6d, 16#69, 16#74, 16#33, 16#30, 16#30, 16#2d,
16#34, 16#38, 16#00, 16#0c, 16#4c, 16#53, 16#75, 16#6d,
16#6d, 16#69, 16#74, 16#33, 16#30, 16#30, 16#2d, 16#34,
16#38, 16#20, 16#2d, 16#20, 16#56, 16#65, 16#72, 16#73,
16#69, 16#6f, 16#6e, 16#20, 16#37, 16#2e, 16#34, 16#65,
16#2e, 16#31, 16#20, 16#28, 16#42, 16#75, 16#69, 16#6c,
16#64, 16#20, 16#35, 16#29, 16#20, 16#62, 16#79, 16#20,
16#52, 16#65, 16#6c, 16#65, 16#61, 16#73, 16#65, 16#5f,
16#4d, 16#61, 16#73, 16#74, 16#65, 16#72, 16#20, 16#30,
16#35, 16#2f, 16#32, 16#37, 16#2f, 16#30, 16#35, 16#20,
16#30, 16#34, 16#3a, 16#35, 16#33, 16#3a, 16#31, 16#31,
16#00, 16#0e, 16#04, 16#00, 16#14, 16#00, 16#14, 16#10,
16#0e, 16#07, 16#06, 16#00, 16#01, 16#30, 16#f9, 16#ad,
16#a0, 16#02, 16#00, 16#00, 16#03, 16#e9, 16#00, 16#fe,
16#07, 16#00, 16#12, 16#0f, 16#02, 16#07, 16#01, 16#00,
16#fe, 16#09, 16#00, 16#12, 16#0f, 16#01, 16#03, 16#6c,
16#00, 16#00, 16#10, 16#fe, 16#09, 16#00, 16#12, 16#0f,
16#03, 16#01, 16#00, 16#00, 16#00, 16#00, 16#fe, 16#06,
16#00, 16#12, 16#0f, 16#04, 16#05, 16#f2, 16#fe, 16#06,
16#00, 16#80, 16#c2, 16#01, 16#01, 16#e8, 16#fe, 16#07,
16#00, 16#80, 16#c2, 16#02, 16#01, 16#00, 16#00, 16#fe,
16#17, 16#00, 16#80, 16#c2, 16#03, 16#01, 16#e8, 16#10,
16#76, 16#32, 16#2d, 16#30, 16#34, 16#38, 16#38, 16#2d,
16#30, 16#33, 16#2d, 16#30, 16#35, 16#30, 16#35, 16#00,
16#fe, 16#05, 16#00, 16#80, 16#c2, 16#04, 16#00, 16#00,
16#00>>.

decode() ->
?_assertEqual({ #lldp{pdus = [#chassis_id{subtype = locally_assigned,
value = <<0,0,0,0,0,0,1,35>>},
#port_id{subtype = locally_assigned,
value = <<0,0,0,12>>},
#ttl{value = 120},
#end_of_lldpdu{}]}, <<>> },
?_assertEqual({{lldp, [{chassis_id,mac_address,<<0,1,48,249,173,160>>},
{port_id,interface_name,<<"1/1">>},
{ttl,120},
{port_desc,<<"Summit300-48-Port 1001">>},
{system_name,<<"Summit300-48">>},
{system_desc,<<"Summit300-48 - Version 7.4e.1 (Build 5) by Release_Master 05/27/05 04:53:11">>},
{system_capability,[router,bridge],[router,bridge]},
{management_address,<<7,6,0,1,48,249,173,160,2,0,0,3,233,0>>},
{organizationally_specific,<<0,18,15,2,7,1,0>>},
{organizationally_specific,<<0,18,15,1,3,108,0,0,16>>},
{organizationally_specific,<<0,18,15,3,1,0,0,0,0>>},
{organizationally_specific,<<0,18,15,4,5,242>>},
{organizationally_specific,<<0,128,194,1,1,232>>},
{organizationally_specific,<<0,128,194,2,1,0,0>>},
{organizationally_specific,<<0,128,194,3,1,232,16,118,
50,45,48,52,56,56,45,48,51,45,48, 53,48,53,0>>},
{organizationally_specific,<<0,128,194,4,0>>},
{end_of_lldpdu}]}, <<>>},
pkt:lldp(packet())).

encode() ->
{Header, _Payload} = pkt:lldp(packet()),
?_assertEqual(pkt_lldp:codec(Header), packet()).
?_assertEqual(pkt:lldp(Header), packet()).

0 comments on commit bbe0b49

Please sign in to comment.