]>
git.proxmox.com Git - mirror_ovs.git/blob - build-aux/extract-ofp-msgs
9 # Maps from user-friendly version number to its protocol encoding.
10 VERSION
= {"1.0": 0x01,
17 NX_VENDOR_ID
= 0x00002320
18 ONF_VENDOR_ID
= 0x4f4e4600
21 OFPT10_STATS_REQUEST
= 16
22 OFPT10_STATS_REPLY
= 17
23 OFPT11_STATS_REQUEST
= 18
24 OFPT11_STATS_REPLY
= 19
27 def decode_version_range(range):
29 return (VERSION
[range], VERSION
[range])
30 elif range.endswith('+'):
31 return (VERSION
[range[:-1]], max(VERSION
.values()))
32 elif range == '<all>':
35 a
, b
= re
.match(r
'^([^-]+)-([^-]+)$', range).groups()
36 return (VERSION
[a
], VERSION
[b
])
41 line
= input_file
.readline()
44 fatal("unexpected end of input")
49 sys
.stderr
.write("%s:%d: %s\n" % (file_name
, line_number
, msg
))
57 argv0
= os
.path
.basename(sys
.argv
[0])
59 %(argv0)s, for extracting OpenFlow message types from header files
60 usage: %(argv0)s INPUT OUTPUT
61 where INPUT is the name of the input header file
62 and OUTPUT is the output file name.
63 Despite OUTPUT, the output is written to stdout, and the OUTPUT argument
64 only controls #line directives in the output.\
65 ''' % {"argv0": argv0
}
69 m
= re
.match(r
'(.*) up to (.*)', s
)
71 struct
, member
= m
.groups()
72 return "offsetof(%s, %s)" % (struct
, member
)
74 return "sizeof(%s)" % s
76 def extract_ofp_msgs(output_file_name
):
85 if re
.match('enum ofpraw', line
):
90 first_line_number
= line_number
91 here
= '%s:%d' % (file_name
, line_number
)
92 if (line
.startswith('/*')
93 or line
.startswith(' *')
97 elif re
.match('}', line
):
100 if not line
.lstrip().startswith('/*'):
101 fatal("unexpected syntax between ofpraw types")
103 comment
= line
.lstrip()[2:].strip()
104 while not comment
.endswith('*/'):
106 if line
.startswith('/*') or not line
or line
.isspace():
107 fatal("unexpected syntax within message")
108 comment
+= ' %s' % line
.lstrip('* \t').rstrip(' \t\r\n')
109 comment
= comment
[:-2].rstrip()
111 m
= re
.match(r
'([A-Z]+) ([-.+\d]+|<all>) \((\d+)\): ([^.]+)\.$', comment
)
113 fatal("unexpected syntax between messages")
114 type_
, versions
, number
, contents
= m
.groups()
118 m
= re
.match('\s+(?:OFPRAW_%s)(\d*)_([A-Z0-9_]+),?$' % type_
,
121 fatal("syntax error expecting OFPRAW_ enum")
122 vinfix
, name
= m
.groups()
123 rawname
= 'OFPRAW_%s%s_%s' % (type_
, vinfix
, name
)
125 min_version
, max_version
= decode_version_range(versions
)
127 human_name
= '%s_%s' % (type_
, name
)
128 if type_
.endswith('ST'):
129 if rawname
.endswith('_REQUEST'):
130 human_name
= human_name
[:-8] + " request"
131 elif rawname
.endswith('_REPLY'):
132 human_name
= human_name
[:-6] + " reply"
134 fatal("%s messages are statistics but %s doesn't end "
135 "in _REQUEST or _REPLY" % (type_
, rawname
))
138 for version
in range(min_version
, max_version
+ 1):
140 if number
== OFPT_VENDOR
:
141 fatal("OFPT (%d) is used for vendor extensions"
143 elif (version
== VERSION
["1.0"]
144 and (number
== OFPT10_STATS_REQUEST
145 or number
== OFPT10_STATS_REPLY
)):
146 fatal("OFPT 1.0 (%d) is used for stats messages"
148 elif (version
!= VERSION
["1.0"]
149 and (number
== OFPT11_STATS_REQUEST
150 or number
== OFPT11_STATS_REPLY
)):
151 fatal("OFPT 1.1+ (%d) is used for stats messages"
153 hdrs
= (version
, number
, 0, 0, 0)
154 elif type_
== 'OFPST' and name
.endswith('_REQUEST'):
155 if version
== VERSION
["1.0"]:
156 hdrs
= (version
, OFPT10_STATS_REQUEST
, number
, 0, 0)
158 hdrs
= (version
, OFPT11_STATS_REQUEST
, number
, 0, 0)
159 elif type_
== 'OFPST' and name
.endswith('_REPLY'):
160 if version
== VERSION
["1.0"]:
161 hdrs
= (version
, OFPT10_STATS_REPLY
, number
, 0, 0)
163 hdrs
= (version
, OFPT11_STATS_REPLY
, number
, 0, 0)
165 hdrs
= (version
, OFPT_VENDOR
, 0, ONF_VENDOR_ID
, number
)
166 elif type_
== 'ONFST' and name
.endswith('_REQUEST'):
167 if version
== VERSION
["1.0"]:
168 hdrs
= (version
, OFPT10_STATS_REQUEST
, OFPST_VENDOR
,
169 ONF_VENDOR_ID
, number
)
171 hdrs
= (version
, OFPT11_STATS_REQUEST
, OFPST_VENDOR
,
172 ONF_VENDOR_ID
, number
)
173 elif type_
== 'ONFST' and name
.endswith('_REPLY'):
174 if version
== VERSION
["1.0"]:
175 hdrs
= (version
, OFPT10_STATS_REPLY
, OFPST_VENDOR
,
176 ONF_VENDOR_ID
, number
)
178 hdrs
= (version
, OFPT11_STATS_REPLY
, OFPST_VENDOR
,
179 ONF_VENDOR_ID
, number
)
181 hdrs
= (version
, OFPT_VENDOR
, 0, NX_VENDOR_ID
, number
)
182 elif type_
== 'NXST' and name
.endswith('_REQUEST'):
183 if version
== VERSION
["1.0"]:
184 hdrs
= (version
, OFPT10_STATS_REQUEST
, OFPST_VENDOR
,
185 NX_VENDOR_ID
, number
)
187 hdrs
= (version
, OFPT11_STATS_REQUEST
, OFPST_VENDOR
,
188 NX_VENDOR_ID
, number
)
189 elif type_
== 'NXST' and name
.endswith('_REPLY'):
190 if version
== VERSION
["1.0"]:
191 hdrs
= (version
, OFPT10_STATS_REPLY
, OFPST_VENDOR
,
192 NX_VENDOR_ID
, number
)
194 hdrs
= (version
, OFPT11_STATS_REPLY
, OFPST_VENDOR
,
195 NX_VENDOR_ID
, number
)
197 fatal("type '%s' unknown" % type_
)
200 error("Duplicate message definition for %s." % str(hdrs
))
201 sys
.stderr
.write("%s: Here is the location "
202 "of the previous definition.\n"
204 all_hdrs
[hdrs
] = here
205 these_hdrs
.append(hdrs
)
208 if contents
== 'void':
212 for c
in [s
.strip() for s
in contents
.split(",")]:
214 if extra_multiple
== '0':
215 extra_multiple
= make_sizeof(c
[:-2])
217 error("Cannot have multiple [] elements")
219 min_body_elem
.append(c
)
222 min_body
= " + ".join([make_sizeof(s
)
223 for s
in min_body_elem
])
225 if extra_multiple
== '0':
226 error("Must specify contents (use 'void' if empty)")
229 if rawname
in all_raws
:
230 fatal("%s: Duplicate name" % rawname
)
232 all_raws
[rawname
] = {"hdrs": these_hdrs
,
233 "min_version": min_version
,
234 "max_version": max_version
,
235 "min_body": min_body
,
236 "extra_multiple": extra_multiple
,
238 "human_name": human_name
,
239 "line": first_line_number
}
240 all_raws_order
.append(rawname
)
246 if re
.match('enum ofptype', line
):
251 if re
.match(r
'\s*/?\*', line
) or line
.isspace():
253 elif re
.match('}', line
):
256 if not re
.match(r
'\s*OFPTYPE_.*/\*', line
):
257 fatal("unexpected syntax between OFPTYPE_ definitions")
259 syntax
= line
.strip()
260 while not syntax
.endswith('*/'):
262 if not line
.strip().startswith('*'):
263 fatal("unexpected syntax within OFPTYPE_ definition")
264 syntax
+= ' %s' % line
.strip().lstrip('* \t')
265 syntax
= syntax
.strip()
267 m
= re
.match(r
'(OFPTYPE_[A-Z0-9_]+),\s*/\* (.*) \*/', syntax
)
269 fatal("syntax error in OFPTYPE_ definition")
271 ofptype
, raws_
= m
.groups()
272 raws
= [s
.rstrip('.') for s
in raws_
.split()]
274 if not re
.match('OFPRAW_[A-Z0-9_]+$', raw
):
275 fatal("%s: invalid OFPRAW_* name syntax" % raw
)
276 if raw
not in all_raws
:
277 fatal("%s: not a declared OFPRAW_* name" % raw
)
278 if "ofptype" in all_raws
[raw
]:
279 fatal("%s: already part of %s"
280 % (raw
, all_raws
[raw
]["ofptype"]))
281 all_raws
[raw
]["ofptype"] = ofptype
289 output
.append("/* Generated automatically; do not modify! "
290 "-*- buffer-read-only: t -*- */")
293 for raw
in all_raws_order
:
295 output
.append("static struct raw_instance %s_instances[] = {"
297 for hdrs
in r
['hdrs']:
298 output
.append(" { {0, NULL}, {%d, %d, %d, 0x%x, %d}, %s, 0 },"
305 output
.append("static struct raw_info raw_infos[] = {")
306 for raw
in all_raws_order
:
308 if "ofptype" not in r
:
309 error("%s: no defined OFPTYPE_" % raw
)
312 output
.append(" %s_instances," % raw
.lower())
313 output
.append(" %d, %d," % (r
["min_version"], r
["max_version"]))
314 output
.append("#line %s \"%s\"" % (r
["line"], file_name
))
315 output
.append(" %s," % r
["min_body"])
316 output
.append("#line %s \"%s\"" % (r
["line"], file_name
))
317 output
.append(" %s," % r
["extra_multiple"])
318 output
.append("#line %s \"%s\"" % (len(output
) + 2, output_file_name
))
319 output
.append(" %s," % r
["ofptype"])
320 output
.append(" \"%s\"," % r
["human_name"])
323 if r
['type'].endswith("ST"):
324 for hdrs
in r
['hdrs']:
326 if hdrs
[0] == VERSION
["1.0"]:
327 if hdrs
[1] == OFPT10_STATS_REQUEST
:
328 op_hdrs
[1] = OFPT10_STATS_REPLY
329 elif hdrs
[1] == OFPT10_STATS_REPLY
:
330 op_hdrs
[1] = OFPT10_STATS_REQUEST
334 if hdrs
[1] == OFPT11_STATS_REQUEST
:
335 op_hdrs
[1] = OFPT11_STATS_REPLY
336 elif hdrs
[1] == OFPT11_STATS_REPLY
:
337 op_hdrs
[1] = OFPT11_STATS_REQUEST
340 if tuple(op_hdrs
) not in all_hdrs
:
341 if r
["human_name"].endswith("request"):
342 fatal("%s has no corresponding reply"
345 fatal("%s has no corresponding request"
355 if __name__
== '__main__':
356 if '--help' in sys
.argv
:
358 elif len(sys
.argv
) != 3:
359 sys
.stderr
.write("exactly two non-option arguments required; "
360 "use --help for help\n")
366 file_name
= sys
.argv
[1]
367 input_file
= open(file_name
)
370 for line
in extract_ofp_msgs(sys
.argv
[2]):