diff options
author | watanabe.fumitaka <watanabe.fumitaka@nttcom.co.jp> | 2013-07-23 14:02:21 +0900 |
---|---|---|
committer | FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> | 2013-07-31 19:41:00 +0900 |
commit | a7499bb1b10a86e15e2823d1b5ff85e1841f932b (patch) | |
tree | 23f9fd0ba2b72debf95893b2e4a41f3ad38f637c | |
parent | a3492f1276d884fad492c563c1906300294111b5 (diff) |
lib/packet/llc
Signed-off-by: WATANABE Fumitaka <watanabe.fumitaka@nttcom.co.jp>
Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
-rw-r--r-- | ryu/lib/packet/llc.py | 315 |
1 files changed, 315 insertions, 0 deletions
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) |