ofp-msgs: Add support for ONF extension messages.
[cascardo/ovs.git] / build-aux / extract-ofp-msgs
index fe92dae..d3c4d4c 100755 (executable)
@@ -6,12 +6,16 @@ import re
 
 line = ""
 
-OFP10_VERSION = 0x01
-OFP11_VERSION = 0x02
-OFP12_VERSION = 0x03
-OFP13_VERSION = 0x04
+# Maps from user-friendly version number to its protocol encoding.
+VERSION = {"1.0": 0x01,
+           "1.1": 0x02,
+           "1.2": 0x03,
+           "1.3": 0x04,
+           "1.4": 0x05,
+           "1.5": 0x06}
 
 NX_VENDOR_ID = 0x00002320
+ONF_VENDOR_ID = 0x4f4e4600
 
 OFPT_VENDOR = 4
 OFPT10_STATS_REQUEST = 16
@@ -20,15 +24,16 @@ OFPT11_STATS_REQUEST = 18
 OFPT11_STATS_REPLY = 19
 OFPST_VENDOR = 0xffff
 
-version_map = {"1.0":     (OFP10_VERSION, OFP10_VERSION),
-               "1.1":     (OFP11_VERSION, OFP11_VERSION),
-               "1.2":     (OFP12_VERSION, OFP12_VERSION),
-               "1.3":     (OFP13_VERSION, OFP13_VERSION),
-               "1.0+":    (OFP10_VERSION, OFP13_VERSION),
-               "1.1+":    (OFP11_VERSION, OFP13_VERSION),
-               "1.2+":    (OFP12_VERSION, OFP13_VERSION),
-               "1.3+":    (OFP13_VERSION, OFP13_VERSION),
-               "1.0-1.1": (OFP10_VERSION, OFP11_VERSION)}
+def decode_version_range(range):
+    if range in VERSION:
+        return (VERSION[range], VERSION[range])
+    elif range.endswith('+'):
+        return (VERSION[range[:-1]], max(VERSION.values()))
+    elif range == '<all>':
+        return (0x01, 0xff)
+    else:
+        a, b = re.match(r'^([^-]+)-([^-]+)$', range).groups()
+        return (VERSION[a], VERSION[b])
 
 def get_line():
     global line
@@ -99,11 +104,11 @@ def extract_ofp_msgs(output_file_name):
         while not comment.endswith('*/'):
             get_line()
             if line.startswith('/*') or not line or line.isspace():
-                fatal("unexpected syntax within error")
+                fatal("unexpected syntax within message")
             comment += ' %s' % line.lstrip('* \t').rstrip(' \t\r\n')
         comment = comment[:-2].rstrip()
 
-        m = re.match(r'([A-Z]+) ([-.+\d]+) \((\d+)\): ([^.]+)\.$', comment)
+        m = re.match(r'([A-Z]+) ([-.+\d]+|<all>) \((\d+)\): ([^.]+)\.$', comment)
         if not m:
             fatal("unexpected syntax between messages")
         type_, versions, number, contents = m.groups()
@@ -117,7 +122,7 @@ def extract_ofp_msgs(output_file_name):
         vinfix, name = m.groups()
         rawname = 'OFPRAW_%s%s_%s' % (type_, vinfix, name)
 
-        min_version, max_version = version_map[versions]
+        min_version, max_version = decode_version_range(versions)
 
         human_name = '%s_%s' % (type_, name)
         if type_.endswith('ST'):
@@ -135,38 +140,54 @@ def extract_ofp_msgs(output_file_name):
                 if number == OFPT_VENDOR:
                     fatal("OFPT (%d) is used for vendor extensions"
                           % number)
-                elif (version == OFP10_VERSION
+                elif (version == VERSION["1.0"]
                       and (number == OFPT10_STATS_REQUEST
                            or number == OFPT10_STATS_REPLY)):
                     fatal("OFPT 1.0 (%d) is used for stats messages"
                           % number)
-                elif (version != OFP10_VERSION
+                elif (version != VERSION["1.0"]
                       and (number == OFPT11_STATS_REQUEST
                            or number == OFPT11_STATS_REPLY)):
                     fatal("OFPT 1.1+ (%d) is used for stats messages"
                           % number)
                 hdrs = (version, number, 0, 0, 0)
             elif type_ == 'OFPST' and name.endswith('_REQUEST'):
-                if version == OFP10_VERSION:
+                if version == VERSION["1.0"]:
                     hdrs = (version, OFPT10_STATS_REQUEST, number, 0, 0)
                 else:
                     hdrs = (version, OFPT11_STATS_REQUEST, number, 0, 0)
             elif type_ == 'OFPST' and name.endswith('_REPLY'):
-                if version == OFP10_VERSION:
+                if version == VERSION["1.0"]:
                     hdrs = (version, OFPT10_STATS_REPLY, number, 0, 0)
                 else:
                     hdrs = (version, OFPT11_STATS_REPLY, number, 0, 0)
+            elif type_ == 'ONFT':
+                hdrs = (version, OFPT_VENDOR, 0, ONF_VENDOR_ID, number)
+            elif type_ == 'ONFST' and name.endswith('_REQUEST'):
+                if version == VERSION["1.0"]:
+                    hdrs = (version, OFPT10_STATS_REQUEST, OFPST_VENDOR,
+                            ONF_VENDOR_ID, number)
+                else:
+                    hdrs = (version, OFPT11_STATS_REQUEST, OFPST_VENDOR,
+                            ONF_VENDOR_ID, number)
+            elif type_ == 'ONFST' and name.endswith('_REPLY'):
+                if version == VERSION["1.0"]:
+                    hdrs = (version, OFPT10_STATS_REPLY, OFPST_VENDOR,
+                            ONF_VENDOR_ID, number)
+                else:
+                    hdrs = (version, OFPT11_STATS_REPLY, OFPST_VENDOR,
+                            ONF_VENDOR_ID, number)
             elif type_ == 'NXT':
                 hdrs = (version, OFPT_VENDOR, 0, NX_VENDOR_ID, number)
             elif type_ == 'NXST' and name.endswith('_REQUEST'):
-                if version == OFP10_VERSION:
+                if version == VERSION["1.0"]:
                     hdrs = (version, OFPT10_STATS_REQUEST, OFPST_VENDOR,
                             NX_VENDOR_ID, number)
                 else:
                     hdrs = (version, OFPT11_STATS_REQUEST, OFPST_VENDOR,
                             NX_VENDOR_ID, number)
             elif type_ == 'NXST' and name.endswith('_REPLY'):
-                if version == OFP10_VERSION:
+                if version == VERSION["1.0"]:
                     hdrs = (version, OFPT10_STATS_REPLY, OFPST_VENDOR,
                             NX_VENDOR_ID, number)
                 else:
@@ -225,6 +246,7 @@ def extract_ofp_msgs(output_file_name):
         if re.match('enum ofptype', line):
             break
 
+    all_types = []
     while True:
         get_line()
         if re.match(r'\s*/?\*', line) or line.isspace():
@@ -259,6 +281,8 @@ def extract_ofp_msgs(output_file_name):
                       % (raw, all_raws[raw]["ofptype"]))
             all_raws[raw]["ofptype"] = ofptype
 
+        all_types.append(all_raws[raws[0]]["human_name"])
+
     input_file.close()
 
     if n_errors:
@@ -302,7 +326,7 @@ def extract_ofp_msgs(output_file_name):
         if r['type'].endswith("ST"):
             for hdrs in r['hdrs']:
                 op_hdrs = list(hdrs)
-                if hdrs[0] == OFP10_VERSION:
+                if hdrs[0] == VERSION["1.0"]:
                     if hdrs[1] == OFPT10_STATS_REQUEST:
                         op_hdrs[1] = OFPT10_STATS_REPLY
                     elif hdrs[1] == OFPT10_STATS_REPLY:
@@ -325,6 +349,12 @@ def extract_ofp_msgs(output_file_name):
                               % r["human_name"])
     output.append("};")
 
+    output.append("");
+    output.append("static const char *type_names[] = {");
+    for t in all_types:
+        output.append("    \"%s\"," % t)
+    output.append("};")
+
     if n_errors:
         sys.exit(1)
 
@@ -335,7 +365,7 @@ if __name__ == '__main__':
     if '--help' in sys.argv:
         usage()
     elif len(sys.argv) != 3:
-        sys.stderr.write("exactly one non-option arguments required; "
+        sys.stderr.write("exactly two non-option arguments required; "
                          "use --help for help\n")
         sys.exit(1)
     else: