1# Copyright (C) 2012 Nippon Telegraph and Telephone Corporation. 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# http://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 12# implied. 13# See the License for the specific language governing permissions and 14# limitations under the License. 15 16import struct 17from . import packet_base 18from . import vlan 19from . import mpls 20from . import ether_types as ether 21from ryu.lib import addrconv 22from ryu.lib.pack_utils import msg_pack_into 23 24 25class ethernet(packet_base.PacketBase): 26 """Ethernet header encoder/decoder class. 27 28 An instance has the following attributes at least. 29 MAC addresses are represented as a string like '08:60:6e:7f:74:e7'. 30 __init__ takes the corresponding args in this order. 31 32 ============== ==================== ===================== 33 Attribute Description Example 34 ============== ==================== ===================== 35 dst destination address 'ff:ff:ff:ff:ff:ff' 36 src source address '08:60:6e:7f:74:e7' 37 ethertype ether type 0x0800 38 ============== ==================== ===================== 39 """ 40 41 _PACK_STR = '!6s6sH' 42 _MIN_LEN = struct.calcsize(_PACK_STR) 43 _MIN_PAYLOAD_LEN = 46 44 _TYPE = { 45 'ascii': [ 46 'src', 'dst' 47 ] 48 } 49 50 def __init__(self, dst='ff:ff:ff:ff:ff:ff', src='00:00:00:00:00:00', 51 ethertype=ether.ETH_TYPE_IP): 52 super(ethernet, self).__init__() 53 self.dst = dst 54 self.src = src 55 self.ethertype = ethertype 56 57 @classmethod 58 def parser(cls, buf): 59 dst, src, ethertype = struct.unpack_from(cls._PACK_STR, buf) 60 return (cls(addrconv.mac.bin_to_text(dst), 61 addrconv.mac.bin_to_text(src), ethertype), 62 ethernet.get_packet_type(ethertype), 63 buf[ethernet._MIN_LEN:]) 64 65 def serialize(self, payload, prev): 66 # Append padding if the payload is less than 46 bytes long 67 pad_len = self._MIN_PAYLOAD_LEN - len(payload) 68 if pad_len > 0: 69 payload.extend(b'\x00' * pad_len) 70 71 return struct.pack(ethernet._PACK_STR, 72 addrconv.mac.text_to_bin(self.dst), 73 addrconv.mac.text_to_bin(self.src), 74 self.ethertype) 75 76 @classmethod 77 def get_packet_type(cls, type_): 78 """Override method for the ethernet IEEE802.3 Length/Type 79 field (self.ethertype). 80 81 If the value of Length/Type field is less than or equal to 82 1500 decimal(05DC hexadecimal), it means Length interpretation 83 and be passed to the LLC sublayer.""" 84 if type_ <= ether.ETH_TYPE_IEEE802_3: 85 type_ = ether.ETH_TYPE_IEEE802_3 86 return cls._TYPES.get(type_) 87 88 89# copy vlan _TYPES 90ethernet._TYPES = vlan.vlan._TYPES 91ethernet.register_packet_type(vlan.vlan, ether.ETH_TYPE_8021Q) 92ethernet.register_packet_type(vlan.svlan, ether.ETH_TYPE_8021AD) 93ethernet.register_packet_type(mpls.mpls, ether.ETH_TYPE_MPLS) 94