From a7499bb1b10a86e15e2823d1b5ff85e1841f932b Mon Sep 17 00:00:00 2001
From: "watanabe.fumitaka" <watanabe.fumitaka@nttcom.co.jp>
Date: Tue, 23 Jul 2013 14:02:21 +0900
Subject: [PATCH] lib/packet/llc

Signed-off-by: WATANABE Fumitaka <watanabe.fumitaka@nttcom.co.jp>
Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
---
 ryu/lib/packet/llc.py | 315 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 315 insertions(+)
 create mode 100644 ryu/lib/packet/llc.py

diff --git a/ryu/lib/packet/llc.py b/ryu/lib/packet/llc.py
new file mode 100644
index 00000000..5af62ea4
--- /dev/null
+++ b/ryu/lib/packet/llc.py
@@ -0,0 +1,315 @@
+# 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.
+
+
+"""
+Logical Link Control(LLC, IEEE 802.2) parser/serializer
+http://standards.ieee.org/getieee802/download/802.2-1998.pdf
+
+
+LLC format
+
+    +-----------------+--------------+
+    | DSAP address    | 8 bits       |
+    +-----------------+--------------+
+    | SSAP address    | 8 bits       |
+    +-----------------+--------------+
+    | Control         | 8 or 16 bits |
+    +-----------------+--------------+
+
+
+DSAP address field
+
+      LSB
+    +-----+---+---+---+---+---+---+---+
+    | I/G | D | D | D | D | D | D | D |
+    +-----+---+---+---+---+---+---+---+
+     I/G bit = 0 : Individual DSAP
+     I/G bit = 1 : Group DSA
+     D : DSAP address
+
+SSAP address field
+
+      LSB
+    +-----+---+---+---+---+---+---+---+
+    | C/R | S | S | S | S | S | S | S |
+    +-----+---+---+---+---+---+---+---+
+     C/R bit = 0 : Command
+     C/R bit = 1 : Response
+     S : SSAP address
+
+
+Control field
+
+ Information transfer
+ command/response
+ (I-format PDU)
+      1   2   3   4   5   6   7   8    9   10-16
+    +---+---+---+---+---+---+---+---+-----+------+
+    | 0 |           N(S)            | P/F | N(R) |
+    +---+---+---+---+---+---+---+---+-----+------+
+
+ Supervisory
+ commands/responses
+ (S-format PDUs)
+      1   2   3   4   5   6   7   8    9   10-16
+    +---+---+---+---+---+---+---+---+-----+------+
+    | 1   0 | S   S | 0   0   0   0 | P/F | N(R) |
+    +---+---+---+---+---+---+---+---+-----+------+
+
+ Unnumbered
+ commands/responses
+ (U-format PDUs)
+      1   2   3    4    5    6   7    8
+    +---+---+----+---+-----+---+----+---+
+    | 1   1 | M1  M1 | P/F | M2  M2  M2 |
+    +---+---+----+---+-----+---+----+---+
+
+    N(S) : sender send sequence number (Bit 2=lower-order-bit)
+    N(R) : sender receive sequence number (Bit 10=lower-order-bit)
+    S    : supervisory function bit
+    M1/M2: modifier function bit
+    P/F  : poll bit - command LLC PDUs
+           final bit - response LLC PDUs
+
+"""
+
+
+import struct
+from . import bpdu
+from . import packet_base
+
+
+SAP_BDPU = 0x42
+
+
+class llc(packet_base.PacketBase):
+    """LLC(IEEE 802.2) 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
+    =============== ===============================================
+    dsap_addr       Destination service access point address field \
+                    includes I/G bit at least significant bit.
+    ssap_addr       Source service access point address field \
+                    includes C/R bit at least significant bit.
+    control         Control field \
+                    [16 bits for formats that include sequence \
+                    numbering, and 8 bits for formats that do not]. \
+                    Either ryu.lib.packet.llc.ControlFormatI or \
+                    ryu.lib.packet.llc.ControlFormatS or \
+                    ryu.lib.packet.llc.ControlFormatU object.
+    =============== ===============================================
+    """
+
+    _PACK_STR = '!BB'
+    _PACK_LEN = struct.calcsize(_PACK_STR)
+    _CTR_TYPES = {}
+    _CTR_PACK_STR = '!2xB'
+
+    @staticmethod
+    def register_control_type(register_cls):
+        llc._CTR_TYPES[register_cls.TYPE] = register_cls
+        return register_cls
+
+    def __init__(self, dsap_addr, ssap_addr, control):
+        super(llc, self).__init__()
+
+        assert getattr(control, 'TYPE', None) in self._CTR_TYPES
+
+        self.dsap_addr = dsap_addr
+        self.ssap_addr = ssap_addr
+        self.control = control
+
+    @classmethod
+    def parser(cls, buf):
+        assert len(buf) >= cls._PACK_LEN
+        (dsap_addr, ssap_addr) = struct.unpack_from(cls._PACK_STR, buf)
+
+        (control,) = struct.unpack_from(cls._CTR_PACK_STR, buf)
+        ctrl = cls._get_control(control)
+        control, information = ctrl.parser(buf[cls._PACK_LEN:])
+
+        return (cls(dsap_addr, ssap_addr, control),
+                cls.get_packet_type(dsap_addr), information)
+
+    def serialize(self, payload, prev):
+        addr = struct.pack(self._PACK_STR, self.dsap_addr, self.ssap_addr)
+        control = self.control.serialize()
+        return addr + control
+
+    @classmethod
+    def _get_control(cls, buf):
+        key = buf & 0b1 if buf & 0b1 == ControlFormatI.TYPE else buf & 0b11
+        return cls._CTR_TYPES[key]
+
+
+@llc.register_control_type
+class ControlFormatI(object):
+    """LLC sub encoder/decoder class for control I-format field.
+
+    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
+    ======================== ===============================
+    send_sequence_number     sender send sequence number
+    pf_bit                   poll/final bit
+    receive_sequence_number  sender receive sequence number
+    ======================== ===============================
+    """
+    TYPE = 0b0
+    _PACK_STR = '!H'
+    _PACK_LEN = struct.calcsize(_PACK_STR)
+
+    def __init__(self, send_sequence_number=0, pf_bit=0,
+                 receive_sequence_number=0):
+        super(ControlFormatI, self).__init__()
+        self.send_sequence_number = send_sequence_number
+        self.pf_bit = pf_bit
+        self.receive_sequence_number = receive_sequence_number
+
+    @classmethod
+    def parser(cls, buf):
+        assert len(buf) >= cls._PACK_LEN
+        (control,) = struct.unpack_from(cls._PACK_STR, buf)
+        assert (control >> 8) & 0b1 == cls.TYPE
+
+        send_sequence_number = (control >> 9) & 0b1111111
+        pf_bit = (control >> 8) & 0b1
+        receive_sequence_number = (control >> 1) & 0b1111111
+
+        return cls(send_sequence_number, pf_bit,
+                   receive_sequence_number), buf[cls._PACK_LEN:]
+
+    def serialize(self):
+        control = (self.send_sequence_number << 9 |
+                   self.TYPE << 8 |
+                   self.receive_sequence_number << 1 |
+                   self.pf_bit)
+        return struct.pack(self._PACK_STR, control)
+
+
+@llc.register_control_type
+class ControlFormatS(object):
+    """LLC sub encoder/decoder class for control S-format field.
+
+    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
+    ======================== ===============================
+    supervisory_function     supervisory function bit
+    pf_bit                   poll/final bit
+    receive_sequence_number  sender receive sequence number
+    ======================== ===============================
+    """
+
+    TYPE = 0b01
+    _PACK_STR = '!H'
+    _PACK_LEN = struct.calcsize(_PACK_STR)
+
+    def __init__(self, supervisory_function=0, pf_bit=0,
+                 receive_sequence_number=0):
+        super(ControlFormatS, self).__init__()
+        self.supervisory_function = supervisory_function
+        self.pf_bit = pf_bit
+        self.receive_sequence_number = receive_sequence_number
+
+    @classmethod
+    def parser(cls, buf):
+        assert len(buf) >= cls._PACK_LEN
+        (control,) = struct.unpack_from(cls._PACK_STR, buf)
+
+        assert (control >> 8) & 0b11 == cls.TYPE
+        assert (control >> 12) & 0b1111 == 0
+
+        supervisory_function = (control >> 10) & 0b11
+        pf_bit = (control >> 8) & 0b1
+        receive_sequence_number = (control >> 1) & 0b1111111
+
+        return cls(supervisory_function, pf_bit,
+                   receive_sequence_number), buf[cls._PACK_LEN:]
+
+    def serialize(self):
+        control = (self.supervisory_function << 10 |
+                   self.TYPE << 8 |
+                   self.receive_sequence_number << 1 |
+                   self.pf_bit)
+        return struct.pack(self._PACK_STR, control)
+
+
+@llc.register_control_type
+class ControlFormatU(object):
+    """LLC sub encoder/decoder class for control U-format field.
+
+    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
+    ======================== ===============================
+    modifier_function1       modifier function bit
+    pf_bit                   poll/final bit
+    modifier_function2       modifier function bit
+    ======================== ===============================
+    """
+
+    TYPE = 0b11
+    _PACK_STR = '!B'
+    _PACK_LEN = struct.calcsize(_PACK_STR)
+
+    def __init__(self, modifier_function1=0, pf_bit=0, modifier_function2=0):
+        super(ControlFormatU, self).__init__()
+        self.modifier_function1 = modifier_function1
+        self.pf_bit = pf_bit
+        self.modifier_function2 = modifier_function2
+
+    @classmethod
+    def parser(cls, buf):
+        assert len(buf) >= cls._PACK_LEN
+        (control,) = struct.unpack_from(cls._PACK_STR, buf)
+
+        assert control & 0b11 == cls.TYPE
+
+        modifier_function1 = (control >> 2) & 0b11
+        pf_bit = (control >> 4) & 0b1
+        modifier_function2 = (control >> 5) & 0b111
+
+        return cls(modifier_function1, pf_bit,
+                   modifier_function2), buf[cls._PACK_LEN:]
+
+    def serialize(self):
+        control = (self.modifier_function2 << 5 |
+                   self.pf_bit << 4 |
+                   self.modifier_function1 << 2 |
+                   self.TYPE)
+        return struct.pack(self._PACK_STR, control)
+
+
+llc.register_packet_type(bpdu.bpdu, SAP_BDPU)