backing up
[vsorcdistro/.git] / ryu / build / lib.linux-armv7l-2.7 / ryu / lib / packet / geneve.py
1 # Copyright (C) 2016 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
16 """
17 Geneve packet parser/serializer
18 """
19
20 import struct
21
22 from ryu.lib import stringify
23 from ryu.lib import type_desc
24 from . import packet_base
25 from . import ether_types
26
27
28 UDP_DST_PORT = 6081
29
30
31 class geneve(packet_base.PacketBase):
32     """Geneve (RFC draft-ietf-nvo3-geneve-03) header encoder/decoder class.
33
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.
37
38     ============== ========================================================
39     Attribute      Description
40     ============== ========================================================
41     version        Version.
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     ============== ========================================================
49     """
50     _HEADER_FMT = "!BBHI"
51     _MIN_LEN = struct.calcsize(_HEADER_FMT)
52
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     # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
61
62     # Flags
63     OAM_PACKET_FLAG = 1 << 7
64     CRITICAL_OPTIONS_FLAG = 1 << 6
65
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__()
69
70         self.version = version
71         self.opt_len = opt_len
72         assert (flags & 0x3F) == 0
73         self.flags = flags
74         self.protocol = protocol
75         self.vni = vni
76         for o in options:
77             assert isinstance(o, Option)
78         self.options = options
79
80     @classmethod
81     def parser(cls, buf):
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
87
88         opt_bin = buf[cls._MIN_LEN:cls._MIN_LEN + opt_len]
89         options = []
90         while opt_bin:
91             option, opt_bin = Option.parser(opt_bin)
92             options.append(option)
93
94         msg = cls(version, opt_len, flags, protocol, vni >> 8, options)
95
96         from . import ethernet
97         geneve._TYPES = ethernet.ethernet._TYPES
98         geneve.register_packet_type(ethernet.ethernet,
99                                     ether_types.ETH_TYPE_TEB)
100
101         return (msg, geneve.get_packet_type(protocol),
102                 buf[cls._MIN_LEN + opt_len:])
103
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
111
112         return (struct.pack(self._HEADER_FMT,
113                             (self.version << 6) | opt_len,
114                             self.flags, self.protocol, self.vni << 8)
115                 + tunnel_options)
116
117
118 class Option(stringify.StringifyMixin, type_desc.TypeDisp):
119     """
120     Tunnel Options
121     """
122     _OPTION_PACK_STR = "!HBB"
123     _OPTION_LEN = struct.calcsize(_OPTION_PACK_STR)
124
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
136         self.type = type_
137         self.length = length
138
139     @classmethod
140     def parse_value(cls, buf):
141         # Sub-classes should override this method, if needed.
142         return {}
143
144     def serialize_value(self):
145         # Sub-classes should override this method, if needed.
146         return b''
147
148     @classmethod
149     def parser(cls, buf):
150         (option_class, type_,
151          length) = struct.unpack_from(cls._OPTION_PACK_STR, buf)
152
153         # The Length field expressed in four byte multiples.
154         length *= 4
155         subcls = Option._lookup_type((option_class, type_))
156
157         return (
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:])
162
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
168
169         return (struct.pack(self._OPTION_PACK_STR, int(self.option_class),
170                             self.type, length) + data)
171
172
173 @Option.register_unknown_type()
174 class OptionDataUnknown(Option):
175     """
176     Unknown Option Class and Type specific Option
177     """
178
179     def __init__(self, buf, option_class=None, type_=None, length=0):
180         super(OptionDataUnknown, self).__init__(option_class=option_class,
181                                                 type_=type_,
182                                                 length=length)
183         self.buf = buf
184
185     @classmethod
186     def parse_value(cls, buf):
187         return {"buf": buf}
188
189     def serialize_value(self):
190         return self.buf