1 # Copyright (C) 2013-2015 Nippon Telegraph and Telephone Corporation.
2 # Copyright (C) 2013-2015 YAMAMOTO Takashi <yamamoto at valinux co jp>
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at
8 # http://www.apache.org/licenses/LICENSE-2.0
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
17 # there are two representations of value and mask this module deal with.
20 # (value, mask) or value. the latter means no mask.
21 # value and mask are strings.
24 # value and mask are on-wire bytes.
25 # mask is None if no mask.
27 # There are two types of OXM/NXM headers.
29 # 32-bit OXM/NXM header
30 # +-------------------------------+-------------+-+---------------+
31 # | class | field |m| length |
32 # +-------------------------------+-------------+-+---------------+
34 # 64-bit experimenter OXM header
35 # +-------------------------------+-------------+-+---------------+
36 # | class (OFPXMC_EXPERIMENTER) | field |m| length |
37 # +-------------------------------+-------------+-+---------------+
39 # +---------------------------------------------------------------+
41 # NOTE: OpenFlow Spec 1.5 mandates that Experimenter OXMs encode
42 # the experimenter type in the oxm_field field of the OXM header
45 # NOTE: EXT-256 had a variation of experimenter OXM header.
46 # It has been rectified since then. Currently this implementation
47 # supports only the old version.
49 # ONF EXT-256 (old, exp_type = 2560)
50 # +-------------------------------+-------------+-+---------------+
51 # | class (OFPXMC_EXPERIMENTER) | ????? |m| length |
52 # +-------------------------------+-------------+-+---------------+
53 # | experimenter ID (ONF_EXPERIMENTER_ID) |
54 # +-------------------------------+---------------+---------------+
55 # | exp_type (PBB_UCA=2560) | pbb_uca |
56 # +-------------------------------+---------------+
58 # ONF EXT-256 (new, oxm_field = 41)
59 # +-------------------------------+-------------+-+---------------+
60 # | class (OFPXMC_EXPERIMENTER) | PBB_UCA=41 |m| length |
61 # +-------------------------------+-------------+-+---------------+
62 # | experimenter ID (ONF_EXPERIMENTER_ID) |
63 # +-------------------------------+---------------+---------------+
64 # | reserved, should be zero | pbb_uca |
65 # +-------------------------------+---------------+
67 from ryu.ofproto.oxx_fields import (
68 _get_field_info_by_name,
79 from ryu.ofproto import ofproto_common
82 OFPXMC_NXM_0 = 0 # Nicira Extended Match (NXM_OF_)
83 OFPXMC_NXM_1 = 1 # Nicira Extended Match (NXM_NX_)
84 OFPXMC_OPENFLOW_BASIC = 0x8000
85 OFPXMC_PACKET_REGS = 0x8001
86 OFPXMC_EXPERIMENTER = 0xffff
89 class _OxmClass(object):
90 def __init__(self, name, num, type_):
93 self.oxm_type = num | (self._class << 7)
94 # TODO(yamamoto): Clean this up later.
95 # Probably when we drop EXT-256 style experimenter OXMs.
96 self.num = self.oxm_type
100 class OpenFlowBasic(_OxmClass):
101 _class = OFPXMC_OPENFLOW_BASIC
104 class PacketRegs(_OxmClass):
105 _class = OFPXMC_PACKET_REGS
108 class _Experimenter(_OxmClass):
109 _class = OFPXMC_EXPERIMENTER
111 def __init__(self, name, num, type_):
112 super(_Experimenter, self).__init__(name, num, type_)
113 self.num = (self.experimenter_id, self.oxm_type)
114 self.exp_type = self.oxm_field
117 class ONFExperimenter(_Experimenter):
118 experimenter_id = ofproto_common.ONF_EXPERIMENTER_ID
121 class OldONFExperimenter(_Experimenter):
122 # This class is for the old version of EXT-256
123 experimenter_id = ofproto_common.ONF_EXPERIMENTER_ID
125 def __init__(self, name, num, type_):
126 super(OldONFExperimenter, self).__init__(name, 0, type_)
127 self.num = (self.experimenter_id, num)
131 class NiciraExperimenter(_Experimenter):
132 experimenter_id = ofproto_common.NX_EXPERIMENTER_ID
135 class NiciraNshExperimenter(_Experimenter):
136 experimenter_id = ofproto_common.NX_NSH_EXPERIMENTER_ID
139 class NiciraExtended0(_OxmClass):
140 """Nicira Extended Match (NXM_0)
142 NXM header format is same as 32-bit (non-experimenter) OXMs.
145 _class = OFPXMC_NXM_0
148 class NiciraExtended1(_OxmClass):
149 """Nicira Extended Match (NXM_1)
151 NXM header format is same as 32-bit (non-experimenter) OXMs.
154 _class = OFPXMC_NXM_1
157 def generate(modname):
161 mod = sys.modules[modname]
166 for i in mod.oxm_types:
167 if isinstance(i.num, tuple):
169 if i._class != OFPXMC_OPENFLOW_BASIC:
174 add_attr('OFPXMT_OFB_' + uk, ofpxmt)
175 add_attr('OXM_OF_' + uk, mod.oxm_tlv_header(ofpxmt, td.size))
176 add_attr('OXM_OF_' + uk + '_W', mod.oxm_tlv_header_w(ofpxmt, td.size))
178 # 'oxx' indicates the OpenFlow Extensible class type.
179 # eg.) 'oxm' indicates that this class is OXM class.
181 name_to_field = dict((f.name, f) for f in mod.oxm_types)
182 num_to_field = dict((f.num, f) for f in mod.oxm_types)
184 # create functions by using oxx_fields module.
185 add_attr('oxm_get_field_info_by_name',
186 functools.partial(_get_field_info_by_name, oxx, name_to_field))
187 add_attr('oxm_from_user',
188 functools.partial(_from_user, oxx, name_to_field))
189 add_attr('oxm_from_user_header',
190 functools.partial(_from_user_header, oxx, name_to_field))
191 add_attr('oxm_to_user',
192 functools.partial(_to_user, oxx, num_to_field))
193 add_attr('oxm_to_user_header',
194 functools.partial(_to_user_header, oxx, num_to_field))
195 add_attr('_oxm_field_desc', # oxx is not required
196 functools.partial(_field_desc, num_to_field))
197 add_attr('oxm_normalize_user',
198 functools.partial(_normalize_user, oxx, mod))
199 add_attr('oxm_parse', # oxx is not required
200 functools.partial(_parse, mod))
201 add_attr('oxm_parse_header', # oxx is not required
202 functools.partial(_parse_header, mod))
203 add_attr('oxm_serialize',
204 functools.partial(_serialize, oxx, mod))
205 add_attr('oxm_serialize_header',
206 functools.partial(_serialize_header, oxx, mod))
208 add_attr('oxm_to_jsondict', _to_jsondict)
209 add_attr('oxm_from_jsondict', _from_jsondict)
212 def _to_jsondict(k, uv):
213 if isinstance(uv, tuple):
218 return {"OXMTlv": {"field": k, "value": value, "mask": mask}}
221 def _from_jsondict(j):
225 mask = tlv.get('mask')