Skip to content

Commit

Permalink
Merge pull request #4 from esl/pbb
Browse files Browse the repository at this point in the history
Add PBB support
  • Loading branch information
konradkaplita committed Dec 18, 2012
2 parents 48afc52 + 281d898 commit 8865467
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 62 deletions.
40 changes: 18 additions & 22 deletions include/pkt.hrl
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@
-define(ETH_P_MPLS_UNI, 16#8847).
-define(ETH_P_MPLS_MULTI, 16#8848).
-define(ETH_P_ALL, 16#0300).
-define(ETH_PBB, 16#88A8).
-define(ETH_PBB_SERVICE_ENCAP, 16#88E7).
-define(ETH_P_PBB_B, 16#88A8).
-define(ETH_P_PBB_I, 16#88E7).

-define(ARPHRD_ETHER, 1).
-define(ARPHRD_IEEE80211, 801).
Expand Down Expand Up @@ -158,26 +158,22 @@
crc = 0
}).

%% A ether header for PBB needs http://en.wikipedia.org/wiki/IEEE_802.1ah-2008
%% It is merged together with service encapsulation header which follows it
%% normally, to simplify decoding and encoding
%% see http://www.carrierethernetstudyguide.org/MEF SG/pages/2transport/studyguide_2-1-1-3.html
-record(pbb_ether, {
dhost = <<0,0,0,0,0,0>>
, shost = <<0,0,0,0,0,0>>
, type = ?ETH_PBB
, b_tag % B-TAG
, b_vid = 0 % B-VID, backbone VLAn indicator (12 bit)
%%-------------
%% A service encapsulation header for PBB
%% merged with ethernet PBB header for simplicity
%%-------------
, encap_type = ?ETH_PBB_SERVICE_ENCAP
, encap_flag_pcp % prio, drop eligible indicator (DEI), no customer address (NCA)
, encap_flag_dei
, encap_flag_reserved
, encap_i_sid % Service Instance VLAN ID (24 bit)
}).
-record(pbb, {
%% Backbone
b_dhost = <<0,0,0,0,0,0>>, %% Destination Address
b_shost = <<0,0,0,0,0,0>>, %% Source Address
b_type = ?ETH_P_PBB_B,
b_pcp, %% Priority Code Point
b_dei, %% Drop Eligibility Identifier
b_vid = 0, %% VLAN Identifier
%% Service Instance
i_type = ?ETH_P_PBB_I,
i_pcp, %% Priority Code Point
i_dei, %% Drop Eligibility Identifier
i_uca, %% Use Customer Addresses
i_reserved = <<0:3>>,
i_sid %% Service Instance VLAN ID
}).

-record(ieee802_1q_tag, {
pcp = 0,
Expand Down
83 changes: 43 additions & 40 deletions src/pkt.erl
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
-export([
encapsulate/1,
decapsulate/1,
decapsulate_pbb/1,
decapsulate_dlt/2
]).

Expand Down Expand Up @@ -65,6 +66,7 @@
-type proto() :: tcp | udp | sctp | icmp | icmpv6 | raw | unsupported.
-type header() :: #linux_cooked{} |
#null{} |
#pbb{} |
#ether{} |
#arp{} |
#ieee802_1q_tag{} |
Expand Down Expand Up @@ -156,13 +158,15 @@ encapsulate(EtherType, [#mpls_tag{mode = Mode} = MPLSTag | Packet], Binary) ->
encapsulate(EtherType, [#ether{} = Ether | Packet], Binary) ->
EtherBinary = ether(fill_ether_type(Ether, EtherType)),
encapsulate(ether, Packet, << EtherBinary/binary, Binary/binary >>);
%% we ignore ethertype here because PBB header has fixed ethertype
encapsulate(_EtherType, [#pbb_ether{} = PBBEther | Packet], Binary) ->
Binary2 = encode_pbb_ether(PBBEther),
encapsulate(ether, Packet, << Binary2/binary, Binary/binary >>).
encapsulate(ether, [#pbb{} = PBB | Packet], Binary) ->
PBBBinary = pbb(PBB),
encapsulate(pbb, Packet, << PBBBinary/binary, Binary/binary >>).

%%% Decapsulate ----------------------------------------------------------------

decapsulate_pbb(Data) when is_binary(Data) ->
decapsulate({pbb, Data}, []).

decapsulate_dlt(Dlt, Data) ->
decapsulate({link_type(Dlt), Data}, []).

Expand All @@ -171,8 +175,7 @@ decapsulate({DLT, Data}) when is_integer(DLT) ->
decapsulate({DLT, Data}) when is_atom(DLT) ->
decapsulate({DLT, Data}, []);

%% Initial call, assumes that packet has ether or pbb_ether header
%% then unwinds other subheaders and payload with recursive calls
%% Initial call
decapsulate(Data) when is_binary(Data) ->
decapsulate({ether, Data}, []).

Expand All @@ -188,9 +191,13 @@ decapsulate({null, Data}, Packet) when byte_size(Data) >= 16 ->
decapsulate({linux_cooked, Data}, Packet) when byte_size(Data) >= 16 ->
{Hdr, Payload} = linux_cooked(Data),
decapsulate({ether_type(Hdr#linux_cooked.pro), Payload}, [Hdr|Packet]);
decapsulate({ether, Data}, Packet) when byte_size(Data) >= ?ETHERHDRLEN ->

decapsulate({pbb, Data}, Packet) ->
{Hdr, Payload} = pbb(Data),
decapsulate({ether, Payload}, [Hdr | Packet]);
decapsulate({ether, Data}, Packet) ->
{Hdr, Payload} = ether(Data),
decapsulate({ether_type(Hdr#ether.type), Payload}, [Hdr|Packet]);
decapsulate({ether_type(Hdr#ether.type), Payload}, [Hdr | Packet]);

decapsulate({ieee802_1q_tag, Data}, Packet) ->
{Tag, Payload} = ieee802_1q_tag(Data),
Expand Down Expand Up @@ -369,33 +376,13 @@ linux_cooked(#linux_cooked{
%% Ethernet
%%

%% @doc Decode PBB ether header here, because it can appear in place of regular
%% ethernet header
ether(<< %% PBB ethernet header
Dhost:6/bytes, Shost:6/bytes, ?ETH_PBB:16, PCPDE:4, BVid:12,
%% service encapsulation header, merged with PBB ether for simplicity
?ETH_PBB_SERVICE_ENCAP:16, EncapFlagPCP:3, EncapFlagDEI:1,
EncapFlagRes:4, EncapISID:24,
%% rest of data to be cut off
Rest/binary>>) ->
{#pbb_ether{
dhost = Dhost, shost = Shost,
%% type = ?ETH_PBB,
b_tag = PCPDE,
b_vid = BVid,
%% encap_type = ?ETH_PBB_SERVICE_ENCAP,
encap_flag_pcp = EncapFlagPCP,
encap_flag_dei = EncapFlagDEI,
encap_flag_reserved = EncapFlagRes,
encap_i_sid = EncapISID
}, Rest};

%% @doc Regular ethernet header
%% @doc Regular ethernet or PBB header
ether(<<Dhost:6/bytes, Shost:6/bytes, Type:16, Payload/binary>>) ->
%% Len = byte_size(Packet) - 4,
%% <<Payload:Len/bytes, CRC:4/bytes>> = Packet,
{#ether{
dhost = Dhost, shost = Shost,
dhost = Dhost,
shost = Shost,
type = Type
}, Payload};

Expand All @@ -406,16 +393,32 @@ ether(#ether{
<<Dhost:6/bytes, Shost:6/bytes, Type:16>>.

%%
%% PBB Ethernet Header
%% decode_* function is merged with ether/1 look up
%% PBB
%%
encode_pbb_ether(#pbb_ether{ dhost = Dhost, shost = Shost, type = Type,
b_tag = BTag, b_vid = BVid, %% encap_type = EType,
encap_flag_pcp = EPCP, encap_flag_dei = EDEI,
encap_flag_reserved = ERes, encap_i_sid = EISID}) ->
<<Dhost:6/bytes, Shost:6/bytes, Type:16, BTag:4, BVid:12,
%% service encapsulation header, merged with PBB ether for simplicity
?ETH_PBB_SERVICE_ENCAP:16, EPCP:3, EDEI:1, ERes:4, EISID:24>>.
pbb(<<Dhost:6/bytes, Shost:6/bytes, ?ETH_P_PBB_B:16, BPcp:3, BDei:1, BVid:12,
?ETH_P_PBB_I:16, IPcp:3, IDei:1, IUca:1, IRsrv:3, ISid:24,
Payload/binary>>) ->
{#pbb{
b_dhost = Dhost,
b_shost = Shost,
b_type = ?ETH_P_PBB_B,
b_pcp = BPcp,
b_dei = BDei,
b_vid = BVid,
i_type = ?ETH_P_PBB_I,
i_pcp = IPcp,
i_dei = IDei,
i_uca = IUca,
i_reserved = IRsrv,
i_sid = ISid
}, Payload};

pbb(#pbb{b_dhost = Dhost, b_shost = Shost,
b_pcp = BPcp, b_dei = BDei, b_vid = BVid,
i_pcp = IPcp, i_dei = IDei, i_uca = IUca,
i_reserved = IRsrv, i_sid = ISid}) ->
<<Dhost:6/bytes, Shost:6/bytes, ?ETH_P_PBB_B:16, BPcp:3, BDei:1, BVid:12,
?ETH_P_PBB_I:16, IPcp:3, IDei:1, IUca:1, IRsrv:3, ISid:24>>.

%%
%% MPLS
Expand Down

0 comments on commit 8865467

Please sign in to comment.