packet lib: support Provider Backbone Bridges (PBB, IEEE 802.1ah)
Signed-off-by: Yuichi Ito <ito.yuichi0@gmail.com> Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
This commit is contained in:
parent
0cc9c21ccc
commit
3ba951f403
@ -29,6 +29,9 @@ Protocol Header classes
|
||||
.. automodule:: ryu.lib.packet.vlan
|
||||
:members:
|
||||
|
||||
.. automodule:: ryu.lib.packet.pbb
|
||||
:members:
|
||||
|
||||
.. automodule:: ryu.lib.packet.mpls
|
||||
:members:
|
||||
|
||||
|
61
ryu/lib/packet/pbb.py
Normal file
61
ryu/lib/packet/pbb.py
Normal file
@ -0,0 +1,61 @@
|
||||
# Copyright (C) 2013 Nippon Telegraph and Telephone Corporation.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
# implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import struct
|
||||
from ryu.lib.packet import packet_base
|
||||
from ryu.ofproto import ether
|
||||
|
||||
|
||||
class itag(packet_base.PacketBase):
|
||||
"""I-TAG (IEEE 802.1ah-2008) header encoder/decoder class.
|
||||
|
||||
An instance has the following attributes at least.
|
||||
Most of them are same to the on-wire counterparts but in host byte order.
|
||||
__init__ takes the corresponding args in this order.
|
||||
|
||||
============== ====================
|
||||
Attribute Description
|
||||
============== ====================
|
||||
pcp Priority Code Point
|
||||
dei Drop Eligible Indication
|
||||
uca Use Customer Address
|
||||
sid Service Instance ID
|
||||
============== ====================
|
||||
"""
|
||||
|
||||
_PACK_STR = "!I"
|
||||
_MIN_LEN = struct.calcsize(_PACK_STR)
|
||||
|
||||
def __init__(self, pcp=0, dei=0, uca=0, sid=0):
|
||||
super(itag, self).__init__()
|
||||
self.pcp = pcp
|
||||
self.dei = dei
|
||||
self.uca = uca
|
||||
self.sid = sid
|
||||
|
||||
@classmethod
|
||||
def parser(cls, buf):
|
||||
(data, ) = struct.unpack_from(cls._PACK_STR, buf)
|
||||
pcp = data >> 29
|
||||
dei = data >> 28 & 1
|
||||
uca = data >> 27 & 1
|
||||
sid = data & 0x00ffffff
|
||||
from ryu.lib.packet import ethernet
|
||||
return (cls(pcp, dei, uca, sid), ethernet.ethernet,
|
||||
buf[cls._MIN_LEN:])
|
||||
|
||||
def serialize(self, payload, prev):
|
||||
data = self.pcp << 29 | self.dei << 28 | self.uca << 27 | self.sid
|
||||
return struct.pack(self._PACK_STR, data)
|
@ -22,6 +22,7 @@ from . import ipv6
|
||||
from . import lldp
|
||||
from . import slow
|
||||
from . import llc
|
||||
from . import pbb
|
||||
from ryu.ofproto import ether
|
||||
|
||||
|
||||
@ -98,7 +99,9 @@ class svlan(_vlan):
|
||||
Attribute Description
|
||||
============== ====================
|
||||
pcp Priority Code Point
|
||||
cfi Canonical Format Indicator
|
||||
cfi Canonical Format Indicator.
|
||||
In a case to be used as B-TAG,
|
||||
this field means DEI(Drop Eligible Indication).
|
||||
vid VLAN Identifier
|
||||
ethertype EtherType
|
||||
============== ====================
|
||||
@ -120,3 +123,4 @@ vlan.register_packet_type(slow.slow, ether.ETH_TYPE_SLOW)
|
||||
vlan.register_packet_type(llc.llc, ether.ETH_TYPE_IEEE802_3)
|
||||
|
||||
svlan.register_packet_type(vlan, ether.ETH_TYPE_8021Q)
|
||||
svlan.register_packet_type(pbb.itag, ether.ETH_TYPE_8021AH)
|
||||
|
@ -22,4 +22,5 @@ ETH_TYPE_SLOW = 0x8809
|
||||
ETH_TYPE_MPLS = 0x8847
|
||||
ETH_TYPE_8021AD = 0x88a8
|
||||
ETH_TYPE_LLDP = 0x88cc
|
||||
ETH_TYPE_8021AH = 0x88e7
|
||||
ETH_TYPE_IEEE802_3 = 0x05dc
|
||||
|
167
ryu/tests/unit/packet/test_pbb.py
Normal file
167
ryu/tests/unit/packet/test_pbb.py
Normal file
@ -0,0 +1,167 @@
|
||||
# Copyright (C) 2013 Nippon Telegraph and Telephone Corporation.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
# implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import logging
|
||||
import struct
|
||||
import unittest
|
||||
|
||||
from nose.tools import eq_
|
||||
from nose.tools import ok_
|
||||
from nose.tools import raises
|
||||
from ryu.ofproto import ether
|
||||
from ryu.ofproto import inet
|
||||
from ryu.lib.packet import ethernet
|
||||
from ryu.lib.packet import packet
|
||||
from ryu.lib.packet import ipv4
|
||||
from ryu.lib.packet import vlan
|
||||
from ryu.lib.packet import pbb
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class Test_itag(unittest.TestCase):
|
||||
|
||||
pcp = 3
|
||||
dei = 0
|
||||
uca = 1
|
||||
sid = 16770000
|
||||
data = pcp << 29 | dei << 28 | uca << 27 | sid
|
||||
buf = struct.pack(pbb.itag._PACK_STR, data)
|
||||
it = pbb.itag(pcp, dei, uca, sid)
|
||||
|
||||
def setUp(self):
|
||||
pass
|
||||
|
||||
def tearDown(self):
|
||||
pass
|
||||
|
||||
def test_init(self):
|
||||
eq_(self.pcp, self.it.pcp)
|
||||
eq_(self.dei, self.it.dei)
|
||||
eq_(self.uca, self.it.uca)
|
||||
eq_(self.sid, self.it.sid)
|
||||
|
||||
def test_parser(self):
|
||||
_res = pbb.itag.parser(self.buf)
|
||||
if type(_res) is tuple:
|
||||
res = _res[0]
|
||||
else:
|
||||
res = _res
|
||||
eq_(res.pcp, self.pcp)
|
||||
eq_(res.dei, self.dei)
|
||||
eq_(res.uca, self.uca)
|
||||
eq_(res.sid, self.sid)
|
||||
|
||||
def test_serialize(self):
|
||||
data = bytearray()
|
||||
prev = None
|
||||
buf = self.it.serialize(data, prev)
|
||||
res = struct.unpack(pbb.itag._PACK_STR, buf)
|
||||
eq_(res[0], self.data)
|
||||
|
||||
def _build_itag(self):
|
||||
b_src_mac = '00:07:0d:af:f4:54'
|
||||
b_dst_mac = '00:00:00:00:00:00'
|
||||
b_ethertype = ether.ETH_TYPE_8021AD
|
||||
e1 = ethernet.ethernet(b_dst_mac, b_src_mac, b_ethertype)
|
||||
|
||||
b_pcp = 0
|
||||
b_cfi = 0
|
||||
b_vid = 32
|
||||
b_ethertype = ether.ETH_TYPE_8021Q
|
||||
bt = vlan.svlan(b_pcp, b_cfi, b_vid, b_ethertype)
|
||||
|
||||
c_src_mac = '11:11:11:11:11:11'
|
||||
c_dst_mac = 'aa:aa:aa:aa:aa:aa'
|
||||
c_ethertype = ether.ETH_TYPE_8021AD
|
||||
e2 = ethernet.ethernet(c_dst_mac, c_src_mac, c_ethertype)
|
||||
|
||||
s_pcp = 0
|
||||
s_cfi = 0
|
||||
s_vid = 32
|
||||
s_ethertype = ether.ETH_TYPE_8021Q
|
||||
st = vlan.svlan(s_pcp, s_cfi, s_vid, s_ethertype)
|
||||
|
||||
c_pcp = 0
|
||||
c_cfi = 0
|
||||
c_vid = 32
|
||||
c_ethertype = ether.ETH_TYPE_IP
|
||||
ct = vlan.vlan(c_pcp, c_cfi, c_vid, c_ethertype)
|
||||
|
||||
version = 4
|
||||
header_length = 20
|
||||
tos = 0
|
||||
total_length = 24
|
||||
identification = 0x8a5d
|
||||
flags = 0
|
||||
offset = 1480
|
||||
ttl = 64
|
||||
proto = inet.IPPROTO_ICMP
|
||||
csum = 0xa7f2
|
||||
src = '131.151.32.21'
|
||||
dst = '131.151.32.129'
|
||||
option = 'TEST'
|
||||
ip = ipv4.ipv4(version, header_length, tos, total_length,
|
||||
identification, flags, offset, ttl, proto, csum,
|
||||
src, dst, option)
|
||||
|
||||
p = packet.Packet()
|
||||
|
||||
p.add_protocol(e1)
|
||||
p.add_protocol(bt)
|
||||
p.add_protocol(self.it)
|
||||
p.add_protocol(e2)
|
||||
p.add_protocol(st)
|
||||
p.add_protocol(ct)
|
||||
p.add_protocol(ip)
|
||||
p.serialize()
|
||||
|
||||
return p
|
||||
|
||||
def test_build_itag(self):
|
||||
p = self._build_itag()
|
||||
|
||||
e = p.get_protocols(ethernet.ethernet)
|
||||
ok_(e)
|
||||
ok_(isinstance(e, list))
|
||||
eq_(e[0].ethertype, ether.ETH_TYPE_8021AD)
|
||||
eq_(e[1].ethertype, ether.ETH_TYPE_8021AD)
|
||||
|
||||
sv = p.get_protocols(vlan.svlan)
|
||||
ok_(sv)
|
||||
ok_(isinstance(sv, list))
|
||||
eq_(sv[0].ethertype, ether.ETH_TYPE_8021Q)
|
||||
eq_(sv[1].ethertype, ether.ETH_TYPE_8021Q)
|
||||
|
||||
it = p.get_protocol(pbb.itag)
|
||||
ok_(it)
|
||||
|
||||
v = p.get_protocol(vlan.vlan)
|
||||
ok_(v)
|
||||
eq_(v.ethertype, ether.ETH_TYPE_IP)
|
||||
|
||||
ip = p.get_protocol(ipv4.ipv4)
|
||||
ok_(ip)
|
||||
|
||||
eq_(it.pcp, self.pcp)
|
||||
eq_(it.dei, self.dei)
|
||||
eq_(it.uca, self.uca)
|
||||
eq_(it.sid, self.sid)
|
||||
|
||||
@raises(Exception)
|
||||
def test_malformed_itag(self):
|
||||
m_short_buf = self.buf[1:pbb.itag._MIN_LEN]
|
||||
pbb.itag.parser(m_short_buf)
|
Loading…
Reference in New Issue
Block a user