1 # Copyright (C) 2016 Nippon Telegraph and Telephone Corporation.
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
7 # http://www.apache.org/licenses/LICENSE-2.0
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
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
17 Geneve packet parser/serializer
22 from ryu.lib import stringify
23 from ryu.lib import type_desc
24 from . import packet_base
25 from . import ether_types
31 class geneve(packet_base.PacketBase):
32 """Geneve (RFC draft-ietf-nvo3-geneve-03) header encoder/decoder class.
34 An instance has the following attributes at least.
35 Most of them are same to the on-wire counterparts but in host byte order.
36 __init__ takes the corresponding args in this order.
38 ============== ========================================================
40 ============== ========================================================
42 opt_len The length of the options fields.
43 flags Flag field for OAM packet and Critical options present.
44 protocol Protocol Type field.
45 The Protocol Type is defined as "ETHER TYPES".
46 vni Identifier for unique element of virtual network.
47 options List of ``Option*`` instance.
48 ============== ========================================================
51 _MIN_LEN = struct.calcsize(_HEADER_FMT)
53 # 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
54 # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
55 # |Ver| Opt Len |O|C| Rsvd. | Protocol Type |
56 # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
57 # | Virtual Network Identifier (VNI) | Reserved |
58 # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
59 # | Variable Length Options |
60 # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
63 OAM_PACKET_FLAG = 1 << 7
64 CRITICAL_OPTIONS_FLAG = 1 << 6
66 def __init__(self, version=0, opt_len=0, flags=0,
67 protocol=ether_types.ETH_TYPE_TEB, vni=None, options=None):
68 super(geneve, self).__init__()
70 self.version = version
71 self.opt_len = opt_len
72 assert (flags & 0x3F) == 0
74 self.protocol = protocol
77 assert isinstance(o, Option)
78 self.options = options
82 (ver_opt_len, flags, protocol,
83 vni) = struct.unpack_from(cls._HEADER_FMT, buf)
84 version = ver_opt_len >> 6
85 # The Opt Len field expressed in four byte multiples.
86 opt_len = (ver_opt_len & 0x3F) * 4
88 opt_bin = buf[cls._MIN_LEN:cls._MIN_LEN + opt_len]
91 option, opt_bin = Option.parser(opt_bin)
92 options.append(option)
94 msg = cls(version, opt_len, flags, protocol, vni >> 8, options)
96 from . import ethernet
97 geneve._TYPES = ethernet.ethernet._TYPES
98 geneve.register_packet_type(ethernet.ethernet,
99 ether_types.ETH_TYPE_TEB)
101 return (msg, geneve.get_packet_type(protocol),
102 buf[cls._MIN_LEN + opt_len:])
104 def serialize(self, payload=None, prev=None):
105 tunnel_options = bytearray()
106 for o in self.options:
107 tunnel_options += o.serialize()
108 self.opt_len = len(tunnel_options)
109 # The Opt Len field expressed in four byte multiples.
110 opt_len = self.opt_len // 4
112 return (struct.pack(self._HEADER_FMT,
113 (self.version << 6) | opt_len,
114 self.flags, self.protocol, self.vni << 8)
118 class Option(stringify.StringifyMixin, type_desc.TypeDisp):
122 _OPTION_PACK_STR = "!HBB"
123 _OPTION_LEN = struct.calcsize(_OPTION_PACK_STR)
125 # 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
126 # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
127 # | Option Class | Type |R|R|R| Length |
128 # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
129 # | Variable Option Data |
130 # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
131 def __init__(self, option_class=None, type_=None, length=0):
132 super(Option, self).__init__()
133 if option_class is None or type_ is None:
134 (option_class, type_) = self._rev_lookup_type(self.__class__)
135 self.option_class = option_class
140 def parse_value(cls, buf):
141 # Sub-classes should override this method, if needed.
144 def serialize_value(self):
145 # Sub-classes should override this method, if needed.
149 def parser(cls, buf):
150 (option_class, type_,
151 length) = struct.unpack_from(cls._OPTION_PACK_STR, buf)
153 # The Length field expressed in four byte multiples.
155 subcls = Option._lookup_type((option_class, type_))
158 subcls(option_class=option_class, type_=type_, length=length,
159 **subcls.parse_value(
160 buf[cls._OPTION_LEN:cls._OPTION_LEN + length])),
161 buf[cls._OPTION_LEN + length:])
163 def serialize(self, _payload=None, _prev=None):
164 data = self.serialize_value()
165 self.length = len(data)
166 # The Length field expressed in four byte multiples.
167 length = self.length // 4
169 return (struct.pack(self._OPTION_PACK_STR, int(self.option_class),
170 self.type, length) + data)
173 @Option.register_unknown_type()
174 class OptionDataUnknown(Option):
176 Unknown Option Class and Type specific Option
179 def __init__(self, buf, option_class=None, type_=None, length=0):
180 super(OptionDataUnknown, self).__init__(option_class=option_class,
186 def parse_value(cls, buf):
189 def serialize_value(self):