Signed-off-by: Yuichi Ito <[email protected]>
---
ryu/lib/packet/ethernet.py | 1 +
ryu/lib/packet/vlan.py | 76 +++++++++++++++++------
ryu/ofproto/ether.py | 3 +-
ryu/tests/unit/packet/test_vlan.py | 118 ++++++++++++++++++++++++++++++++++++
4 files changed, 178 insertions(+), 20 deletions(-)
diff --git a/ryu/lib/packet/ethernet.py b/ryu/lib/packet/ethernet.py
index 349a352..e63ffee 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 8930197..2f0e256 100644
--- a/ryu/lib/packet/vlan.py
+++ b/ryu/lib/packet/vlan.py
@@ -13,6 +13,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+import abc
import struct
from . import packet_base
from . import arp
@@ -24,7 +25,35 @@ from . import llc
from ryu.ofproto import ether
-class vlan(packet_base.PacketBase):
+class _vlan(packet_base.PacketBase):
+
+ __metaclass__ = abc.ABCMeta
+ _PACK_STR = "!HH"
+ _MIN_LEN = struct.calcsize(_PACK_STR)
+
+ @abc.abstractmethod
+ def __init__(self, pcp, cfi, vid, ethertype):
+ super(_vlan, self).__init__()
+ self.pcp = pcp
+ self.cfi = cfi
+ self.vid = vid
+ self.ethertype = ethertype
+
+ @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),
+ vlan.get_packet_type(ethertype), buf[vlan._MIN_LEN:])
+
+ def serialize(self, payload, prev):
+ tci = self.pcp << 13 | self.cfi << 12 | self.vid
+ return struct.pack(vlan._PACK_STR, tci, self.ethertype)
+
+
+class vlan(_vlan):
"""VLAN (IEEE 802.1Q) header encoder/decoder class.
An instance has the following attributes at least.
@@ -41,15 +70,8 @@ class vlan(packet_base.PacketBase):
============== ====================
"""
- _PACK_STR = "!HH"
- _MIN_LEN = struct.calcsize(_PACK_STR)
-
def __init__(self, pcp=0, cfi=0, vid=0, ethertype=ether.ETH_TYPE_IP):
- super(vlan, self).__init__()
- self.pcp = pcp
- self.cfi = cfi
- self.vid = vid
- self.ethertype = ethertype
+ super(vlan, self).__init__(pcp, cfi, vid, ethertype)
@classmethod
def get_packet_type(cls, type_):
@@ -63,18 +85,32 @@ class vlan(packet_base.PacketBase):
type_ = ether.ETH_TYPE_IEEE802_3
return cls._TYPES.get(type_)
+
+class svlan(_vlan):
+ """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 corresponding args in this order.
+
+ ============== ====================
+ Attribute Description
+ ============== ====================
+ pcp Priority Code Point
+ cfi Canonical Format Indicator
+ vid VLAN Identifier
+ ethertype EtherType
+ ============== ====================
+ """
+
+ def __init__(self, pcp=0, cfi=0, vid=0, ethertype=ether.ETH_TYPE_8021Q):
+ super(svlan, self).__init__(pcp, cfi, vid, ethertype)
+
@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),
- vlan.get_packet_type(ethertype), buf[vlan._MIN_LEN:])
+ def get_packet_type(cls, type_):
+ return cls._TYPES.get(type_)
- def serialize(self, payload, prev):
- tci = self.pcp << 13 | self.cfi << 12 | self.vid
- return struct.pack(vlan._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)
@@ -82,3 +118,5 @@ 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
------------------------------------------------------------------------------
Android is increasing in popularity, but the open development platform that
developers love is also attractive to malware creators. Download this white
paper to learn more about secure code signing practices that can help keep
Android apps secure.
http://pubads.g.doubleclick.net/gampad/clk?id=65839951&iu=/4140/ostg.clktrk
_______________________________________________
Ryu-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/ryu-devel