Signed-off-by: Yuichi Ito <ito.yuic...@gmail.com>
---
 ryu/lib/packet/ethernet.py         |    1 +
 ryu/lib/packet/vlan.py             |   49 +++++++++++++++
 ryu/ofproto/ether.py               |    3 +-
 ryu/tests/unit/packet/test_vlan.py |  118 ++++++++++++++++++++++++++++++++++++
 4 files changed, 170 insertions(+), 1 deletion(-)

diff --git a/ryu/lib/packet/ethernet.py b/ryu/lib/packet/ethernet.py
index 2b8c932..7170fce 100644
--- a/ryu/lib/packet/ethernet.py
+++ b/ryu/lib/packet/ethernet.py
@@ -76,4 +76,5 @@ class ethernet(packet_base.PacketBase):
 # copy vlan _TYPES
 ethernet._TYPES = vlan.vlan._TYPES
 ethernet.register_packet_type(vlan.vlan, ether.ETH_TYPE_8021Q)
+ethernet.register_packet_type(vlan.svlan, ether.ETH_TYPE_8021AD)
 ethernet.register_packet_type(mpls.mpls, ether.ETH_TYPE_MPLS)
diff --git a/ryu/lib/packet/vlan.py b/ryu/lib/packet/vlan.py
index e672272..e1360ee 100644
--- a/ryu/lib/packet/vlan.py
+++ b/ryu/lib/packet/vlan.py
@@ -76,9 +76,58 @@ class vlan(packet_base.PacketBase):
         tci = self.pcp << 13 | self.cfi << 12 | self.vid
         return struct.pack(vlan._PACK_STR, tci, self.ethertype)

+
+class svlan(packet_base.PacketBase):
+    """S-VLAN (IEEE 802.1ad) 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 correspondig args in this order.
+
+    ============== ====================
+    Attribute      Description
+    ============== ====================
+    pcp            Priority Code Point
+    cfi            Canonical Format Indicator
+    vid            VLAN Identifier
+    ethertype      EtherType
+    ============== ====================
+    """
+
+    _PACK_STR = "!HH"
+    _MIN_LEN = struct.calcsize(_PACK_STR)
+
+    def __init__(self, pcp=0, cfi=0, vid=0, ethertype=ether.ETH_TYPE_IP):
+        super(svlan, self).__init__()
+        self.pcp = pcp
+        self.cfi = cfi
+        self.vid = vid
+        self.ethertype = ethertype
+
+    @classmethod
+    def get_packet_type(cls, type_):
+        return cls._TYPES.get(type_)
+
+    @classmethod
+    def parser(cls, buf):
+        tci, ethertype = struct.unpack_from(cls._PACK_STR, buf)
+        pcp = tci >> 13
+        cfi = (tci >> 12) & 1
+        vid = tci & ((1 << 12) - 1)
+        return (cls(pcp, cfi, vid, ethertype),
+                cls.get_packet_type(ethertype), buf[cls._MIN_LEN:])
+
+    def serialize(self, payload, prev):
+        tci = self.pcp << 13 | self.cfi << 12 | self.vid
+        return struct.pack(self._PACK_STR, tci, self.ethertype)
+
+
 vlan.register_packet_type(arp.arp, ether.ETH_TYPE_ARP)
 vlan.register_packet_type(ipv4.ipv4, ether.ETH_TYPE_IP)
 vlan.register_packet_type(ipv6.ipv6, ether.ETH_TYPE_IPV6)
 vlan.register_packet_type(lldp.lldp, ether.ETH_TYPE_LLDP)
 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)
diff --git a/ryu/ofproto/ether.py b/ryu/ofproto/ether.py
index f4883a3..9e1539c 100644
--- a/ryu/ofproto/ether.py
+++ b/ryu/ofproto/ether.py
@@ -18,7 +18,8 @@ ETH_TYPE_IP = 0x0800
 ETH_TYPE_ARP = 0x0806
 ETH_TYPE_8021Q = 0x8100
 ETH_TYPE_IPV6 = 0x86dd
-ETH_TYPE_MPLS = 0x8847
 ETH_TYPE_SLOW = 0x8809
+ETH_TYPE_MPLS = 0x8847
+ETH_TYPE_8021AD = 0x88a8
 ETH_TYPE_LLDP = 0x88cc
 ETH_TYPE_IEEE802_3 = 0x05dc
diff --git a/ryu/tests/unit/packet/test_vlan.py 
b/ryu/tests/unit/packet/test_vlan.py
index 6983507..c9aa186 100644
--- a/ryu/tests/unit/packet/test_vlan.py
+++ b/ryu/tests/unit/packet/test_vlan.py
@@ -26,6 +26,7 @@ from ryu.lib.packet.ethernet import ethernet
 from ryu.lib.packet.packet import Packet
 from ryu.lib.packet.ipv4 import ipv4
 from ryu.lib.packet.vlan import vlan
+from ryu.lib.packet.vlan import svlan


 LOG = logging.getLogger('test_vlan')
@@ -136,3 +137,120 @@ class Test_vlan(unittest.TestCase):
     def test_malformed_vlan(self):
         m_short_buf = self.buf[1:vlan._MIN_LEN]
         vlan.parser(m_short_buf)
+
+
+class Test_svlan(unittest.TestCase):
+
+    pcp = 0
+    cfi = 0
+    vid = 32
+    tci = pcp << 15 | cfi << 12 | vid
+    ethertype = ether.ETH_TYPE_8021Q
+
+    buf = pack(svlan._PACK_STR, tci, ethertype)
+
+    sv = svlan(pcp, cfi, vid, ethertype)
+
+    def setUp(self):
+        pass
+
+    def tearDown(self):
+        pass
+
+    def find_protocol(self, pkt, name):
+        for p in pkt.protocols:
+            if p.protocol_name == name:
+                return p
+
+    def test_init(self):
+        eq_(self.pcp, self.sv.pcp)
+        eq_(self.cfi, self.sv.cfi)
+        eq_(self.vid, self.sv.vid)
+        eq_(self.ethertype, self.sv.ethertype)
+
+    def test_parser(self):
+        res, ptype, _ = self.sv.parser(self.buf)
+
+        eq_(res.pcp, self.pcp)
+        eq_(res.cfi, self.cfi)
+        eq_(res.vid, self.vid)
+        eq_(res.ethertype, self.ethertype)
+        eq_(ptype, vlan)
+
+    def test_serialize(self):
+        data = bytearray()
+        prev = None
+        buf = self.sv.serialize(data, prev)
+
+        fmt = svlan._PACK_STR
+        res = struct.unpack(fmt, buf)
+
+        eq_(res[0], self.tci)
+        eq_(res[1], self.ethertype)
+
+    def _build_svlan(self):
+        src_mac = '00:07:0d:af:f4:54'
+        dst_mac = '00:00:00:00:00:00'
+        ethertype = ether.ETH_TYPE_8021AD
+        e = ethernet(dst_mac, src_mac, ethertype)
+
+        pcp = 0
+        cfi = 0
+        vid = 32
+        tci = pcp << 15 | cfi << 12 | vid
+        ethertype = ether.ETH_TYPE_IP
+        v = vlan(pcp, cfi, vid, 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(version, header_length, tos, total_length, identification,
+                  flags, offset, ttl, proto, csum, src, dst, option)
+
+        p = Packet()
+
+        p.add_protocol(e)
+        p.add_protocol(self.sv)
+        p.add_protocol(v)
+        p.add_protocol(ip)
+        p.serialize()
+
+        return p
+
+    def test_build_svlan(self):
+        p = self._build_svlan()
+
+        e = self.find_protocol(p, "ethernet")
+        ok_(e)
+        eq_(e.ethertype, ether.ETH_TYPE_8021AD)
+
+        sv = self.find_protocol(p, "svlan")
+        ok_(sv)
+        eq_(sv.ethertype, ether.ETH_TYPE_8021Q)
+
+        v = self.find_protocol(p, "vlan")
+        ok_(v)
+        eq_(v.ethertype, ether.ETH_TYPE_IP)
+
+        ip = self.find_protocol(p, "ipv4")
+        ok_(ip)
+
+        eq_(sv.pcp, self.pcp)
+        eq_(sv.cfi, self.cfi)
+        eq_(sv.vid, self.vid)
+        eq_(sv.ethertype, self.ethertype)
+
+    @raises(Exception)
+    def test_malformed_svlan(self):
+        m_short_buf = self.buf[1:svlan._MIN_LEN]
+        svlan.parser(m_short_buf)
-- 
1.7.10.4


------------------------------------------------------------------------------
October Webinars: Code for Performance
Free Intel webinars can help you accelerate application performance.
Explore tips for MPI, OpenMP, advanced profiling, and more. Get the most from 
the latest Intel processors and coprocessors. See abstracts and register >
http://pubads.g.doubleclick.net/gampad/clk?id=60135991&iu=/4140/ostg.clktrk
_______________________________________________
Ryu-devel mailing list
Ryu-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/ryu-devel

Reply via email to