]>
git.proxmox.com Git - ovs.git/blob - build-aux/extract-ofp-actions
9 # Map from OpenFlow version number to version ID used in ofp_header.
10 version_map
= {"1.0": 0x01,
16 version_reverse_map
= dict((v
, k
) for (k
, v
) in version_map
.items())
18 # Map from vendor name to the length of the action header.
19 vendor_map
= {"OF": (0x00000000, 4),
20 "ONF": (0x4f4e4600, 10),
21 "NX": (0x00002320, 10)}
23 # Basic types used in action arguments.
25 types
['uint8_t'] = {"size": 1, "align": 1, "ntoh": None, "hton": None}
26 types
['ovs_be16'] = {"size": 2, "align": 2, "ntoh": "ntohs", "hton": "htons"}
27 types
['ovs_be32'] = {"size": 4, "align": 4, "ntoh": "ntohl", "hton": "htonl"}
28 types
['ovs_be64'] = {"size": 8, "align": 8, "ntoh": "ntohll", "hton": "htonll"}
29 types
['uint16_t'] = {"size": 2, "align": 2, "ntoh": None, "hton": None}
30 types
['uint32_t'] = {"size": 4, "align": 4, "ntoh": None, "hton": None}
31 types
['uint64_t'] = {"size": 8, "align": 8, "ntoh": None, "hton": None}
38 return int((x
+ (y
- 1)) / y
) * y
45 input_file
= open(file_name
)
52 line
= input_file
.readline()
55 fatal("unexpected end of input")
61 sys
.stderr
.write("%s:%d: %s\n" % (file_name
, line_number
, msg
))
69 argv0
= os
.path
.basename(sys
.argv
[0])
71 %(argv0)s, for extracting OpenFlow action data
72 usage: %(argv0)s OFP_ACTIONS.C [--prototypes | --definitions]
74 This program reads ofp-actions.c to obtain information about OpenFlow
75 actions. With --prototypes, it outputs on stdout a set of prototypes to
76 #include early in ofp-actions.c. With --definitions, it outputs on stdout
77 a set of definitions to #include late in ofp-actions.c
79 OFP_ACTIONS.C should point to lib/ofp-actions.c.\
80 ''' % {"argv0": argv0
})
83 def extract_ofp_actions(fn
, definitions
):
89 for code
, size
in vendor_map
.values():
99 if re
.match('enum ofp_raw_action_type {', line
):
104 if line
.startswith('/*') or not line
or line
.isspace():
106 elif re
.match('}', line
):
109 if not line
.lstrip().startswith('/*'):
110 fatal("unexpected syntax between actions")
112 comment
= line
.lstrip()[2:].strip()
113 while not comment
.endswith('*/'):
115 if line
.startswith('/*') or not line
or line
.isspace():
116 fatal("unexpected syntax within action")
117 comment
+= ' %s' % line
.lstrip('* \t').rstrip(' \t\r\n')
118 comment
= re
.sub('\[[^]]*\]', '', comment
)
119 comment
= comment
[:-2].rstrip()
121 m
= re
.match('([^:]+):\s+(.*)$', comment
)
123 fatal("unexpected syntax between actions")
126 argtypes
= m
.group(2).strip().replace('.', '', 1)
128 if 'VLMFF' in argtypes
:
129 arg_vl_mff_map
= True
131 arg_vl_mff_map
= False
132 argtype
= argtypes
.replace('VLMFF', '', 1).rstrip()
135 m
= re
.match(r
'\s+(([A-Z]+)_RAW([0-9]*)_([A-Z0-9_]+)),?', line
)
137 fatal("syntax error expecting enum value")
141 fatal("%s specified twice" % enum
)
145 for dst
in dsts
.split(', '):
146 m
= re
.match(r
'([A-Z]+)([0-9.]+)(\+|-[0-9.]+)?(?:\((\d+)\))(?: is deprecated \(([^)]+)\))?$', dst
)
148 fatal("%r: syntax error in destination" % dst
)
149 vendor_name
= m
.group(1)
150 version1_name
= m
.group(2)
151 version2_name
= m
.group(3)
152 type_
= int(m
.group(4))
153 deprecation
= m
.group(5)
155 if vendor_name
not in vendor_map
:
156 fatal("%s: unknown vendor" % vendor_name
)
157 vendor
= vendor_map
[vendor_name
][0]
159 if version1_name
not in version_map
:
160 fatal("%s: unknown OpenFlow version" % version1_name
)
161 v1
= version_map
[version1_name
]
163 if version2_name
is None:
165 elif version2_name
== "+":
166 v2
= max(version_map
.values())
167 elif version2_name
[1:] not in version_map
:
168 fatal("%s: unknown OpenFlow version" % version2_name
[1:])
170 v2
= version_map
[version2_name
[1:]]
173 fatal("%s%s: %s precedes %s"
174 % (version1_name
, version2_name
,
175 version2_name
, version1_name
))
177 for version
in range(v1
, v2
+ 1):
178 domain
[vendor
].setdefault(type_
, {})
179 if version
in domain
[vendor
][type_
]:
180 v
= domain
[vendor
][type_
][version
]
181 msg
= "%#x,%d in OF%s means both %s and %s" % (
182 vendor
, type_
, version_reverse_map
[version
],
184 error("%s: %s." % (dst
, msg
))
185 sys
.stderr
.write("%s:%d: %s: Here is the location "
186 "of the previous definition.\n"
187 % (v
["file_name"], v
["line_number"],
191 header_len
= vendor_map
[vendor_name
][1]
193 base_argtype
= argtype
.replace(', ..', '', 1)
194 if base_argtype
in types
:
195 arg_align
= types
[base_argtype
]['align']
196 arg_len
= types
[base_argtype
]['size']
197 arg_ofs
= round_up(header_len
, arg_align
)
198 min_length
= round_up(arg_ofs
+ arg_len
,
200 elif base_argtype
== 'void':
201 min_length
= round_up(header_len
, OFP_ACTION_ALIGN
)
204 elif re
.match(r
'struct [a-zA-Z0-9_]+$', base_argtype
):
205 min_length
= 'sizeof(%s)' % base_argtype
206 arg_structs
.add(base_argtype
)
209 # should also emit OFP_ACTION_ALIGN assertion
211 fatal("bad argument type %s" % argtype
)
213 ellipsis
= argtype
!= base_argtype
215 max_length
= '65536 - OFP_ACTION_ALIGN'
217 max_length
= min_length
219 info
= {"enum": enum
, # 0
220 "deprecation": deprecation
, # 1
221 "file_name": file_name
, # 2
222 "line_number": line_number
, # 3
223 "min_length": min_length
, # 4
224 "max_length": max_length
, # 5
225 "arg_ofs": arg_ofs
, # 6
226 "arg_len": arg_len
, # 7
227 "base_argtype": base_argtype
, # 8
228 "arg_vl_mff_map": arg_vl_mff_map
, # 9
229 "version": version
, # 10
231 domain
[vendor
][type_
][version
] = info
233 enums
.setdefault(enum
, [])
234 enums
[enum
].append(info
)
242 /* Generated automatically; do not modify! -*- buffer-read-only: t -*- */
246 print("/* Verify that structs used as actions are reasonable sizes. */")
247 for s
in sorted(arg_structs
):
248 print("BUILD_ASSERT_DECL(sizeof(%s) %% OFP_ACTION_ALIGN == 0);" % s
)
250 print("\nstatic struct ofpact_raw_instance all_raw_instances[] = {")
251 for vendor
in domain
:
252 for type_
in domain
[vendor
]:
253 for version
in domain
[vendor
][type_
]:
254 d
= domain
[vendor
][type_
][version
]
255 print(" { { 0x%08x, %2d, 0x%02x }, " % (
256 vendor
, type_
, version
))
257 print(" %s," % d
["enum"])
258 print(" HMAP_NODE_NULL_INITIALIZER,")
259 print(" HMAP_NODE_NULL_INITIALIZER,")
260 print(" %s," % d
["min_length"])
261 print(" %s," % d
["max_length"])
262 print(" %s," % d
["arg_ofs"])
263 print(" %s," % d
["arg_len"])
264 print(" \"%s\"," % re
.sub('_RAW[0-9]*', '', d
["enum"], 1))
266 print(" \"%s\"," % re
.sub(r
'(["\\])', r
'\\\1', d
["deprecation"]))
272 for versions
in enums
.values():
273 need_ofp_version
= False
275 assert v
["arg_len"] == versions
[0]["arg_len"]
276 assert v
["base_argtype"] == versions
[0]["base_argtype"]
277 if (v
["min_length"] != versions
[0]["min_length"] or
278 v
["arg_ofs"] != versions
[0]["arg_ofs"] or
279 v
["type"] != versions
[0]["type"]):
280 need_ofp_version
= True
281 base_argtype
= versions
[0]["base_argtype"]
283 decl
= "static inline "
284 if base_argtype
.startswith('struct'):
285 decl
+= "%s *" %base_argtype
288 decl
+= "\nput_%s(struct ofpbuf *openflow" % versions
[0]["enum"].replace('_RAW', '', 1)
290 decl
+= ", enum ofp_version version"
291 if base_argtype
!= 'void' and not base_argtype
.startswith('struct'):
292 decl
+= ", %s arg" % base_argtype
297 if base_argtype
.startswith('struct'):
299 decl
+= "ofpact_put_raw(openflow, "
303 decl
+= "%s" % versions
[0]["version"]
304 decl
+= ", %s, " % versions
[0]["enum"]
305 if base_argtype
.startswith('struct') or base_argtype
== 'void':
308 ntoh
= types
[base_argtype
]['ntoh']
310 decl
+= "%s(arg)" % ntoh
323 ofpact_decode(const struct ofp_action_header *a, enum ofp_raw_action_type raw,
324 enum ofp_version version, uint64_t arg,
325 const struct vl_mff_map *vl_mff_map,
326 uint64_t *tlv_bitmap, struct ofpbuf *out)
330 for versions
in enums
.values():
331 enum
= versions
[0]["enum"]
332 print(" case %s:" % enum
)
333 base_argtype
= versions
[0]["base_argtype"]
334 arg_vl_mff_map
= versions
[0]["arg_vl_mff_map"]
335 if base_argtype
== 'void':
336 print(" return decode_%s(out);" % enum
)
338 if base_argtype
.startswith('struct'):
339 arg
= "ALIGNED_CAST(const %s *, a)" % base_argtype
341 hton
= types
[base_argtype
]['hton']
343 arg
= "%s(arg)" % hton
347 print(" return decode_%s(%s, version, vl_mff_map, tlv_bitmap, out);" % (enum
, arg
))
349 print(" return decode_%s(%s, version, out);" % (enum
, arg
))
358 for versions
in enums
.values():
359 enum
= versions
[0]["enum"]
360 prototype
= "static enum ofperr decode_%s(" % enum
361 base_argtype
= versions
[0]["base_argtype"]
362 arg_vl_mff_map
= versions
[0]["arg_vl_mff_map"]
363 if base_argtype
!= 'void':
364 if base_argtype
.startswith('struct'):
365 prototype
+= "const %s *, enum ofp_version, " % base_argtype
367 prototype
+= "%s, enum ofp_version, " % base_argtype
369 prototype
+= 'const struct vl_mff_map *, uint64_t *, '
370 prototype
+= "struct ofpbuf *);"
374 static enum ofperr ofpact_decode(const struct ofp_action_header *,
375 enum ofp_raw_action_type raw,
376 enum ofp_version version,
377 uint64_t arg, const struct vl_mff_map *vl_mff_map,
378 uint64_t *tlv_bitmap, struct ofpbuf *out);
381 if __name__
== '__main__':
382 if '--help' in sys
.argv
:
384 elif len(sys
.argv
) != 3:
385 sys
.stderr
.write("exactly two arguments required; "
386 "use --help for help\n")
388 elif sys
.argv
[2] == '--prototypes':
389 extract_ofp_actions(sys
.argv
[1], False)
390 elif sys
.argv
[2] == '--definitions':
391 extract_ofp_actions(sys
.argv
[1], True)
393 sys
.stderr
.write("invalid arguments; use --help for help\n")