| 
									
										
										
										
											2011-01-12 13:42:50 -08:00
										 |  |  | #! /usr/bin/python | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import sys | 
					
						
							|  |  |  | import os.path | 
					
						
							|  |  |  | import re | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | macros = {} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-24 13:49:40 -07:00
										 |  |  | # Map from OpenFlow version number to version ID used in ofp_header. | 
					
						
							|  |  |  | version_map = {"1.0": 0x01, | 
					
						
							|  |  |  |                "1.1": 0x02, | 
					
						
							|  |  |  |                "1.2": 0x03, | 
					
						
							| 
									
										
										
										
											2014-03-03 15:22:32 +02:00
										 |  |  |                "1.3": 0x04, | 
					
						
							| 
									
										
										
										
											2014-05-07 13:42:24 -07:00
										 |  |  |                "1.4": 0x05, | 
					
						
							|  |  |  |                "1.5": 0x06} | 
					
						
							| 
									
										
										
										
											2013-06-24 13:49:40 -07:00
										 |  |  | version_reverse_map = dict((v, k) for (k, v) in version_map.iteritems()) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-01-12 13:42:50 -08:00
										 |  |  | token = None | 
					
						
							|  |  |  | line = "" | 
					
						
							|  |  |  | idRe = "[a-zA-Z_][a-zA-Z_0-9]*" | 
					
						
							|  |  |  | tokenRe = "#?" + idRe + "|[0-9]+|." | 
					
						
							|  |  |  | inComment = False | 
					
						
							|  |  |  | inDirective = False | 
					
						
							| 
									
										
										
										
											2012-01-12 15:48:19 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-24 13:49:40 -07:00
										 |  |  | def open_file(fn): | 
					
						
							|  |  |  |     global fileName | 
					
						
							|  |  |  |     global inputFile | 
					
						
							|  |  |  |     global lineNumber | 
					
						
							|  |  |  |     fileName = fn | 
					
						
							|  |  |  |     inputFile = open(fileName) | 
					
						
							|  |  |  |     lineNumber = 0 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def tryGetLine(): | 
					
						
							|  |  |  |     global inputFile | 
					
						
							| 
									
										
										
										
											2012-01-12 15:48:19 -08:00
										 |  |  |     global line | 
					
						
							|  |  |  |     global lineNumber | 
					
						
							|  |  |  |     line = inputFile.readline() | 
					
						
							|  |  |  |     lineNumber += 1 | 
					
						
							| 
									
										
										
										
											2013-06-24 13:49:40 -07:00
										 |  |  |     return line != "" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def getLine(): | 
					
						
							|  |  |  |     if not tryGetLine(): | 
					
						
							| 
									
										
										
										
											2012-01-12 15:48:19 -08:00
										 |  |  |         fatal("unexpected end of input") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-01-12 13:42:50 -08:00
										 |  |  | def getToken(): | 
					
						
							|  |  |  |     global token | 
					
						
							|  |  |  |     global line | 
					
						
							|  |  |  |     global inComment | 
					
						
							|  |  |  |     global inDirective | 
					
						
							|  |  |  |     while True: | 
					
						
							|  |  |  |         line = line.lstrip() | 
					
						
							|  |  |  |         if line != "": | 
					
						
							|  |  |  |             if line.startswith("/*"): | 
					
						
							|  |  |  |                 inComment = True | 
					
						
							|  |  |  |                 line = line[2:] | 
					
						
							|  |  |  |             elif inComment: | 
					
						
							|  |  |  |                 commentEnd = line.find("*/") | 
					
						
							|  |  |  |                 if commentEnd < 0: | 
					
						
							|  |  |  |                     line = "" | 
					
						
							|  |  |  |                 else: | 
					
						
							|  |  |  |                     inComment = False | 
					
						
							|  |  |  |                     line = line[commentEnd + 2:] | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 match = re.match(tokenRe, line) | 
					
						
							|  |  |  |                 token = match.group(0) | 
					
						
							|  |  |  |                 line = line[len(token):] | 
					
						
							|  |  |  |                 if token.startswith('#'): | 
					
						
							|  |  |  |                     inDirective = True | 
					
						
							|  |  |  |                 elif token in macros and not inDirective: | 
					
						
							|  |  |  |                     line = macros[token] + line | 
					
						
							|  |  |  |                     continue | 
					
						
							|  |  |  |                 return True | 
					
						
							|  |  |  |         elif inDirective: | 
					
						
							|  |  |  |             token = "$" | 
					
						
							|  |  |  |             inDirective = False | 
					
						
							|  |  |  |             return True | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             global lineNumber | 
					
						
							|  |  |  |             line = inputFile.readline() | 
					
						
							|  |  |  |             lineNumber += 1 | 
					
						
							|  |  |  |             while line.endswith("\\\n"): | 
					
						
							|  |  |  |                 line = line[:-2] + inputFile.readline() | 
					
						
							|  |  |  |                 lineNumber += 1 | 
					
						
							|  |  |  |             if line == "": | 
					
						
							|  |  |  |                 if token == None: | 
					
						
							|  |  |  |                     fatal("unexpected end of input") | 
					
						
							|  |  |  |                 token = None | 
					
						
							|  |  |  |                 return False | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-26 13:46:35 -07:00
										 |  |  | n_errors = 0 | 
					
						
							|  |  |  | def error(msg): | 
					
						
							|  |  |  |     global n_errors | 
					
						
							| 
									
										
										
										
											2012-01-12 15:48:19 -08:00
										 |  |  |     sys.stderr.write("%s:%d: %s\n" % (fileName, lineNumber, msg)) | 
					
						
							| 
									
										
										
										
											2012-03-26 13:46:35 -07:00
										 |  |  |     n_errors += 1 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def fatal(msg): | 
					
						
							|  |  |  |     error(msg) | 
					
						
							| 
									
										
										
										
											2011-01-12 13:42:50 -08:00
										 |  |  |     sys.exit(1) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def skipDirective(): | 
					
						
							|  |  |  |     getToken() | 
					
						
							|  |  |  |     while token != '$': | 
					
						
							|  |  |  |         getToken() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def isId(s): | 
					
						
							|  |  |  |     return re.match(idRe + "$", s) != None | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def forceId(): | 
					
						
							|  |  |  |     if not isId(token): | 
					
						
							|  |  |  |         fatal("identifier expected") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def forceInteger(): | 
					
						
							|  |  |  |     if not re.match('[0-9]+$', token): | 
					
						
							|  |  |  |         fatal("integer expected") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def match(t): | 
					
						
							|  |  |  |     if token == t: | 
					
						
							|  |  |  |         getToken() | 
					
						
							|  |  |  |         return True | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  |         return False | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def forceMatch(t): | 
					
						
							|  |  |  |     if not match(t): | 
					
						
							|  |  |  |         fatal("%s expected" % t) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def parseTaggedName(): | 
					
						
							|  |  |  |     assert token in ('struct', 'union') | 
					
						
							|  |  |  |     name = token | 
					
						
							|  |  |  |     getToken() | 
					
						
							|  |  |  |     forceId() | 
					
						
							|  |  |  |     name = "%s %s" % (name, token) | 
					
						
							|  |  |  |     getToken() | 
					
						
							|  |  |  |     return name | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def print_enum(tag, constants, storage_class): | 
					
						
							| 
									
										
										
										
											2013-03-22 19:48:15 +01:00
										 |  |  |     print (""" | 
					
						
							| 
									
										
										
										
											2011-01-12 13:42:50 -08:00
										 |  |  | %(storage_class)sconst char * | 
					
						
							|  |  |  | %(tag)s_to_string(uint16_t value) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     switch (value) {\ | 
					
						
							|  |  |  | """ % {"tag": tag, | 
					
						
							|  |  |  |        "bufferlen": len(tag) + 32, | 
					
						
							| 
									
										
										
										
											2013-03-22 19:48:15 +01:00
										 |  |  |        "storage_class": storage_class}) | 
					
						
							| 
									
										
										
										
											2011-01-12 13:42:50 -08:00
										 |  |  |     for constant in constants: | 
					
						
							| 
									
										
										
										
											2013-03-22 19:48:15 +01:00
										 |  |  |         print ("    case %s: return \"%s\";" % (constant, constant)) | 
					
						
							|  |  |  |     print ("""\ | 
					
						
							| 
									
										
										
										
											2011-01-12 13:42:50 -08:00
										 |  |  |     } | 
					
						
							|  |  |  |     return NULL; | 
					
						
							|  |  |  | }\ | 
					
						
							| 
									
										
										
										
											2013-03-22 19:48:15 +01:00
										 |  |  | """ % {"tag": tag}) | 
					
						
							| 
									
										
										
										
											2011-01-12 13:42:50 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | def usage(): | 
					
						
							|  |  |  |     argv0 = os.path.basename(sys.argv[0]) | 
					
						
							| 
									
										
										
										
											2013-03-22 19:48:15 +01:00
										 |  |  |     print ('''\ | 
					
						
							| 
									
										
										
										
											2011-01-12 13:42:50 -08:00
										 |  |  | %(argv0)s, for extracting OpenFlow error codes from header files | 
					
						
							| 
									
										
										
										
											2013-06-24 13:49:40 -07:00
										 |  |  | usage: %(argv0)s ERROR_HEADER VENDOR_HEADER | 
					
						
							| 
									
										
										
										
											2011-01-12 13:42:50 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-24 13:49:40 -07:00
										 |  |  | This program reads VENDOR_HEADER to obtain OpenFlow vendor (aka | 
					
						
							|  |  |  | experimenter IDs), then ERROR_HEADER to obtain OpenFlow error number. | 
					
						
							|  |  |  | It outputs a C source file for translating OpenFlow error codes into | 
					
						
							|  |  |  | strings. | 
					
						
							| 
									
										
										
										
											2011-01-12 13:42:50 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-24 13:49:40 -07:00
										 |  |  | ERROR_HEADER should point to lib/ofp-errors.h. | 
					
						
							|  |  |  | VENDOR_HEADER should point to include/openflow/openflow-common.h. | 
					
						
							|  |  |  | The output is suitable for use as lib/ofp-errors.inc.\ | 
					
						
							| 
									
										
										
										
											2013-03-22 19:48:15 +01:00
										 |  |  | ''' % {"argv0": argv0}) | 
					
						
							| 
									
										
										
										
											2011-01-12 13:42:50 -08:00
										 |  |  |     sys.exit(0) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-24 13:49:40 -07:00
										 |  |  | def extract_vendor_ids(fn): | 
					
						
							|  |  |  |     global vendor_map | 
					
						
							|  |  |  |     vendor_map = {} | 
					
						
							|  |  |  |     vendor_loc = {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     open_file(fn) | 
					
						
							|  |  |  |     while tryGetLine(): | 
					
						
							|  |  |  |         m = re.match(r'#define\s+([A-Z0-9_]+)_VENDOR_ID\s+(0x[0-9a-fA-F]+|[0-9]+)', line) | 
					
						
							|  |  |  |         if not m: | 
					
						
							|  |  |  |             continue | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         name = m.group(1) | 
					
						
							|  |  |  |         id_ = int(m.group(2), 0) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if name in vendor_map: | 
					
						
							|  |  |  |             error("%s: duplicate definition of vendor" % name) | 
					
						
							|  |  |  |             sys.stderr.write("%s: Here is the location of the previous " | 
					
						
							|  |  |  |                              "definition.\n" % vendor_loc[name]) | 
					
						
							|  |  |  |             sys.exit(1) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         vendor_map[name] = id_ | 
					
						
							|  |  |  |         vendor_loc[name] = "%s:%d" % (fileName, lineNumber) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if not vendor_map: | 
					
						
							|  |  |  |         fatal("%s: no vendor definitions found" % fn) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     inputFile.close() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     vendor_reverse_map = {} | 
					
						
							|  |  |  |     for name, id_ in vendor_map.items(): | 
					
						
							|  |  |  |         if id_ in vendor_reverse_map: | 
					
						
							|  |  |  |             fatal("%s: duplicate vendor id for vendors %s and %s" | 
					
						
							|  |  |  |                   % (id_, vendor_reverse_map[id_], name)) | 
					
						
							|  |  |  |         vendor_reverse_map[id_] = name | 
					
						
							| 
									
										
										
										
											2013-06-25 11:26:41 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-24 13:49:40 -07:00
										 |  |  | def extract_ofp_errors(fn): | 
					
						
							| 
									
										
										
										
											2011-01-12 13:42:50 -08:00
										 |  |  |     error_types = {} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-01-12 15:48:19 -08:00
										 |  |  |     comments = [] | 
					
						
							|  |  |  |     names = [] | 
					
						
							|  |  |  |     domain = {} | 
					
						
							|  |  |  |     reverse = {} | 
					
						
							| 
									
										
										
										
											2013-06-24 13:49:40 -07:00
										 |  |  |     for domain_name in version_map.values(): | 
					
						
							| 
									
										
										
										
											2012-01-12 15:48:19 -08:00
										 |  |  |         domain[domain_name] = {} | 
					
						
							|  |  |  |         reverse[domain_name] = {} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-26 13:46:35 -07:00
										 |  |  |     n_errors = 0 | 
					
						
							|  |  |  |     expected_errors = {} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-24 13:49:40 -07:00
										 |  |  |     open_file(fn) | 
					
						
							| 
									
										
										
										
											2012-01-12 15:48:19 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-24 13:49:40 -07:00
										 |  |  |     while True: | 
					
						
							|  |  |  |         getLine() | 
					
						
							|  |  |  |         if re.match('enum ofperr', line): | 
					
						
							|  |  |  |             break | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     while True: | 
					
						
							|  |  |  |         getLine() | 
					
						
							|  |  |  |         if line.startswith('/*') or not line or line.isspace(): | 
					
						
							|  |  |  |             continue | 
					
						
							|  |  |  |         elif re.match('}', line): | 
					
						
							|  |  |  |             break | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if not line.lstrip().startswith('/*'): | 
					
						
							|  |  |  |             fatal("unexpected syntax between errors") | 
					
						
							| 
									
										
										
										
											2012-01-12 15:48:19 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-24 13:49:40 -07:00
										 |  |  |         comment = line.lstrip()[2:].strip() | 
					
						
							|  |  |  |         while not comment.endswith('*/'): | 
					
						
							| 
									
										
										
										
											2012-01-12 15:48:19 -08:00
										 |  |  |             getLine() | 
					
						
							|  |  |  |             if line.startswith('/*') or not line or line.isspace(): | 
					
						
							| 
									
										
										
										
											2013-06-24 13:49:40 -07:00
										 |  |  |                 fatal("unexpected syntax within error") | 
					
						
							|  |  |  |             comment += ' %s' % line.lstrip('* \t').rstrip(' \t\r\n') | 
					
						
							|  |  |  |         comment = comment[:-2].rstrip() | 
					
						
							| 
									
										
										
										
											2012-03-26 13:46:35 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-24 13:49:40 -07:00
										 |  |  |         m = re.match('Expected: (.*)\.$', comment) | 
					
						
							|  |  |  |         if m: | 
					
						
							|  |  |  |             expected_errors[m.group(1)] = (fileName, lineNumber) | 
					
						
							|  |  |  |             continue | 
					
						
							| 
									
										
										
										
											2012-03-26 13:46:35 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-24 13:49:40 -07:00
										 |  |  |         m = re.match('((?:.(?!\.  ))+.)\.  (.*)$', comment) | 
					
						
							|  |  |  |         if not m: | 
					
						
							|  |  |  |             fatal("unexpected syntax between errors") | 
					
						
							| 
									
										
										
										
											2012-03-26 13:46:35 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-24 13:49:40 -07:00
										 |  |  |         dsts, comment = m.groups() | 
					
						
							| 
									
										
										
										
											2012-01-12 15:48:19 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-24 13:49:40 -07:00
										 |  |  |         getLine() | 
					
						
							|  |  |  |         m = re.match('\s+(?:OFPERR_([A-Z0-9_]+))(\s*=\s*OFPERR_OFS)?,', | 
					
						
							|  |  |  |                      line) | 
					
						
							|  |  |  |         if not m: | 
					
						
							|  |  |  |             fatal("syntax error expecting enum value") | 
					
						
							| 
									
										
										
										
											2012-01-12 15:48:19 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-24 13:49:40 -07:00
										 |  |  |         enum = m.group(1) | 
					
						
							|  |  |  |         if enum in names: | 
					
						
							|  |  |  |             fatal("%s specified twice" % enum) | 
					
						
							| 
									
										
										
										
											2012-01-12 15:48:19 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-24 13:49:40 -07:00
										 |  |  |         comments.append(re.sub('\[[^]]*\]', '', comment)) | 
					
						
							|  |  |  |         names.append(enum) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         for dst in dsts.split(', '): | 
					
						
							|  |  |  |             m = re.match(r'([A-Z]+)([0-9.]+)(\+|-[0-9.]+)?\((\d+)(?:,(\d+))?\)$', dst) | 
					
						
							|  |  |  |             if not m: | 
					
						
							|  |  |  |                 fatal("%r: syntax error in destination" % dst) | 
					
						
							|  |  |  |             vendor_name = m.group(1) | 
					
						
							|  |  |  |             version1_name = m.group(2) | 
					
						
							|  |  |  |             version2_name = m.group(3) | 
					
						
							|  |  |  |             type_ = int(m.group(4)) | 
					
						
							|  |  |  |             if m.group(5): | 
					
						
							|  |  |  |                 code = int(m.group(5)) | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 code = None | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if vendor_name not in vendor_map: | 
					
						
							|  |  |  |                 fatal("%s: unknown vendor" % vendor_name) | 
					
						
							|  |  |  |             vendor = vendor_map[vendor_name] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if version1_name not in version_map: | 
					
						
							|  |  |  |                 fatal("%s: unknown OpenFlow version" % version1_name) | 
					
						
							|  |  |  |             v1 = version_map[version1_name] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if version2_name is None: | 
					
						
							|  |  |  |                 v2 = v1 | 
					
						
							|  |  |  |             elif version2_name == "+": | 
					
						
							|  |  |  |                 v2 = max(version_map.values()) | 
					
						
							|  |  |  |             elif version2_name[1:] not in version_map: | 
					
						
							|  |  |  |                 fatal("%s: unknown OpenFlow version" % version2_name[1:]) | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 v2 = version_map[version2_name[1:]] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if v2 < v1: | 
					
						
							|  |  |  |                 fatal("%s%s: %s precedes %s" | 
					
						
							|  |  |  |                       % (version1_name, version2_name, | 
					
						
							|  |  |  |                          version2_name, version1_name)) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-08-21 10:38:15 -07:00
										 |  |  |             if vendor == vendor_map['OF']: | 
					
						
							|  |  |  |                 # All standard OpenFlow errors have a type and a code. | 
					
						
							|  |  |  |                 if code is None: | 
					
						
							|  |  |  |                     fatal("%s: %s domain requires code" % (dst, vendor_name)) | 
					
						
							|  |  |  |             elif vendor == vendor_map['NX']: | 
					
						
							|  |  |  |                 # Before OpenFlow 1.2, OVS used a Nicira extension to | 
					
						
							|  |  |  |                 # define errors that included a type and a code. | 
					
						
							|  |  |  |                 # | 
					
						
							|  |  |  |                 # In OpenFlow 1.2 and later, Nicira extension errors | 
					
						
							|  |  |  |                 # are defined using the OpenFlow experimenter error | 
					
						
							|  |  |  |                 # mechanism that includes a type but not a code. | 
					
						
							|  |  |  |                 if v1 < version_map['1.2'] or v2 < version_map['1.2']: | 
					
						
							|  |  |  |                     if code is None: | 
					
						
							|  |  |  |                         fatal("%s: NX1.0 and NX1.1 domains require code" | 
					
						
							|  |  |  |                               % (dst, vendor_name)) | 
					
						
							| 
									
										
										
										
											2013-06-24 13:49:40 -07:00
										 |  |  |                 if v1 >= version_map['1.2'] or v2 >= version_map['1.2']: | 
					
						
							|  |  |  |                     if code is not None: | 
					
						
							|  |  |  |                         fatal("%s: NX1.2+ domains do not have codes" % dst) | 
					
						
							| 
									
										
										
										
											2014-08-21 10:38:15 -07:00
										 |  |  |             else: | 
					
						
							|  |  |  |                 # Experimenter extension error for OF1.2+ only. | 
					
						
							|  |  |  |                 if v1 < version_map['1.2']: | 
					
						
							|  |  |  |                     fatal("%s: %s domain not supported before OF1.2" | 
					
						
							|  |  |  |                           % (dst, vendor_name)) | 
					
						
							| 
									
										
										
										
											2013-06-24 13:49:40 -07:00
										 |  |  |                 if code is not None: | 
					
						
							| 
									
										
										
										
											2014-08-21 10:38:15 -07:00
										 |  |  |                     fatal("%s: %s domains do not have codes" | 
					
						
							|  |  |  |                           % (dst, vendor_name)) | 
					
						
							|  |  |  |             if code is None: | 
					
						
							|  |  |  |                 code = 0 | 
					
						
							| 
									
										
										
										
											2013-06-24 13:49:40 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |             for version in range(v1, v2 + 1): | 
					
						
							|  |  |  |                 domain[version].setdefault(vendor, {}) | 
					
						
							|  |  |  |                 domain[version][vendor].setdefault(type_, {}) | 
					
						
							|  |  |  |                 if code in domain[version][vendor][type_]: | 
					
						
							|  |  |  |                     msg = "%#x,%d,%d in OF%s means both %s and %s" % ( | 
					
						
							|  |  |  |                         vendor, type_, code, version_reverse_map[version], | 
					
						
							|  |  |  |                         domain[version][vendor][type_][code][0], enum) | 
					
						
							|  |  |  |                     if msg in expected_errors: | 
					
						
							|  |  |  |                         del expected_errors[msg] | 
					
						
							| 
									
										
										
										
											2012-03-26 13:46:35 -07:00
										 |  |  |                     else: | 
					
						
							| 
									
										
										
										
											2013-06-24 13:49:40 -07:00
										 |  |  |                         error("%s: %s." % (dst, msg)) | 
					
						
							|  |  |  |                         sys.stderr.write("%s:%d: %s: Here is the location " | 
					
						
							|  |  |  |                                          "of the previous definition.\n" | 
					
						
							|  |  |  |                                          % (domain[version][vendor][type_][code][1], | 
					
						
							|  |  |  |                                             domain[version][vendor][type_][code][2], | 
					
						
							|  |  |  |                                             dst)) | 
					
						
							|  |  |  |                 else: | 
					
						
							|  |  |  |                     domain[version][vendor][type_][code] = (enum, fileName, | 
					
						
							|  |  |  |                                                    lineNumber) | 
					
						
							| 
									
										
										
										
											2012-03-26 13:46:35 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-24 13:49:40 -07:00
										 |  |  |                 assert enum not in reverse[version] | 
					
						
							|  |  |  |                 reverse[version][enum] = (vendor, type_, code) | 
					
						
							| 
									
										
										
										
											2012-01-12 15:48:19 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-24 13:49:40 -07:00
										 |  |  |     inputFile.close() | 
					
						
							| 
									
										
										
										
											2011-01-12 13:42:50 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-22 19:48:15 +01:00
										 |  |  |     for fn, ln in expected_errors.values(): | 
					
						
							| 
									
										
										
										
											2012-03-26 13:46:35 -07:00
										 |  |  |         sys.stderr.write("%s:%d: expected duplicate not used.\n" % (fn, ln)) | 
					
						
							|  |  |  |         n_errors += 1 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if n_errors: | 
					
						
							|  |  |  |         sys.exit(1) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-22 19:48:15 +01:00
										 |  |  |     print ("""\ | 
					
						
							| 
									
										
										
										
											2012-01-12 15:48:19 -08:00
										 |  |  | /* Generated automatically; do not modify!     -*- buffer-read-only: t -*- */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define OFPERR_N_ERRORS %d | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct ofperr_domain { | 
					
						
							|  |  |  |     const char *name; | 
					
						
							|  |  |  |     uint8_t version; | 
					
						
							| 
									
										
										
										
											2013-06-24 13:49:40 -07:00
										 |  |  |     enum ofperr (*decode)(uint32_t vendor, uint16_t type, uint16_t code); | 
					
						
							|  |  |  |     struct triplet errors[OFPERR_N_ERRORS]; | 
					
						
							| 
									
										
										
										
											2012-01-12 15:48:19 -08:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static const char *error_names[OFPERR_N_ERRORS] = { | 
					
						
							|  |  |  | %s | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static const char *error_comments[OFPERR_N_ERRORS] = { | 
					
						
							|  |  |  | %s | 
					
						
							|  |  |  | };\ | 
					
						
							|  |  |  | """ % (len(names), | 
					
						
							|  |  |  |        '\n'.join('    "%s",' % name for name in names), | 
					
						
							|  |  |  |        '\n'.join('    "%s",' % re.sub(r'(["\\])', r'\\\1', comment) | 
					
						
							| 
									
										
										
										
											2013-03-22 19:48:15 +01:00
										 |  |  |                  for comment in comments))) | 
					
						
							| 
									
										
										
										
											2012-01-12 15:48:19 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def output_domain(map, name, description, version): | 
					
						
							| 
									
										
										
										
											2013-03-22 19:48:15 +01:00
										 |  |  |         print (""" | 
					
						
							| 
									
										
										
										
											2012-01-12 15:48:19 -08:00
										 |  |  | static enum ofperr | 
					
						
							| 
									
										
										
										
											2013-06-24 13:49:40 -07:00
										 |  |  | %s_decode(uint32_t vendor, uint16_t type, uint16_t code) | 
					
						
							| 
									
										
										
										
											2012-01-12 15:48:19 -08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2013-06-24 13:49:40 -07:00
										 |  |  |     switch (((uint64_t) vendor << 32) | (type << 16) | code) {""" % name) | 
					
						
							| 
									
										
										
										
											2012-03-26 13:46:35 -07:00
										 |  |  |         found = set() | 
					
						
							| 
									
										
										
										
											2012-01-12 15:48:19 -08:00
										 |  |  |         for enum in names: | 
					
						
							|  |  |  |             if enum not in map: | 
					
						
							|  |  |  |                 continue | 
					
						
							| 
									
										
										
										
											2013-06-24 13:49:40 -07:00
										 |  |  |             vendor, type_, code = map[enum] | 
					
						
							|  |  |  |             value = (vendor << 32) | (type_ << 16) | code | 
					
						
							| 
									
										
										
										
											2012-03-26 13:46:35 -07:00
										 |  |  |             if value in found: | 
					
						
							|  |  |  |                 continue | 
					
						
							|  |  |  |             found.add(value) | 
					
						
							| 
									
										
										
										
											2013-06-24 13:49:40 -07:00
										 |  |  |             if vendor: | 
					
						
							|  |  |  |                 vendor_s = "(%#xULL << 32) | " % vendor | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 vendor_s = "" | 
					
						
							|  |  |  |             print ("    case %s(%d << 16) | %d:" % (vendor_s, type_, code)) | 
					
						
							| 
									
										
										
										
											2013-03-22 19:48:15 +01:00
										 |  |  |             print ("        return OFPERR_%s;" % enum) | 
					
						
							|  |  |  |         print ("""\ | 
					
						
							| 
									
										
										
										
											2011-01-12 13:42:50 -08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2012-01-12 15:48:19 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     return 0; | 
					
						
							| 
									
										
										
										
											2013-03-22 19:48:15 +01:00
										 |  |  | }""") | 
					
						
							| 
									
										
										
										
											2012-01-12 15:48:19 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-22 19:48:15 +01:00
										 |  |  |         print (""" | 
					
						
							| 
									
										
										
										
											2012-08-01 16:01:49 +09:00
										 |  |  | static const struct ofperr_domain %s = { | 
					
						
							| 
									
										
										
										
											2012-01-12 15:48:19 -08:00
										 |  |  |     "%s", | 
					
						
							|  |  |  |     %d, | 
					
						
							|  |  |  |     %s_decode, | 
					
						
							| 
									
										
										
										
											2013-03-22 19:48:15 +01:00
										 |  |  |     {""" % (name, description, version, name)) | 
					
						
							| 
									
										
										
										
											2012-01-12 15:48:19 -08:00
										 |  |  |         for enum in names: | 
					
						
							|  |  |  |             if enum in map: | 
					
						
							| 
									
										
										
										
											2013-06-24 13:49:40 -07:00
										 |  |  |                 vendor, type_, code = map[enum] | 
					
						
							| 
									
										
										
										
											2012-01-12 15:48:19 -08:00
										 |  |  |                 if code == None: | 
					
						
							|  |  |  |                     code = -1 | 
					
						
							| 
									
										
										
										
											2013-06-24 13:49:40 -07:00
										 |  |  |                 print "        { %#8x, %2d, %3d }, /* %s */" % (vendor, type_, code, enum) | 
					
						
							| 
									
										
										
										
											2012-01-12 15:48:19 -08:00
										 |  |  |             else: | 
					
						
							| 
									
										
										
										
											2013-06-24 13:49:40 -07:00
										 |  |  |                 print ("        {       -1, -1,  -1 }, /* %s */" % enum) | 
					
						
							| 
									
										
										
										
											2013-03-22 19:48:15 +01:00
										 |  |  |         print ("""\ | 
					
						
							| 
									
										
										
										
											2012-01-12 15:48:19 -08:00
										 |  |  |     }, | 
					
						
							| 
									
										
										
										
											2013-03-22 19:48:15 +01:00
										 |  |  | };""") | 
					
						
							| 
									
										
										
										
											2012-01-12 15:48:19 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-24 13:49:40 -07:00
										 |  |  |     for version_name, id_ in version_map.items(): | 
					
						
							|  |  |  |         var = 'ofperr_of' + re.sub('[^A-Za-z0-9_]', '', version_name) | 
					
						
							|  |  |  |         description = "OpenFlow %s" % version_name | 
					
						
							|  |  |  |         output_domain(reverse[id_], var, description, id_) | 
					
						
							| 
									
										
										
										
											2011-01-12 13:42:50 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | if __name__ == '__main__': | 
					
						
							|  |  |  |     if '--help' in sys.argv: | 
					
						
							|  |  |  |         usage() | 
					
						
							| 
									
										
										
										
											2013-06-24 13:49:40 -07:00
										 |  |  |     elif len(sys.argv) != 3: | 
					
						
							|  |  |  |         sys.stderr.write("exactly two non-options arguments required; " | 
					
						
							| 
									
										
										
										
											2011-01-12 13:42:50 -08:00
										 |  |  |                          "use --help for help\n") | 
					
						
							|  |  |  |         sys.exit(1) | 
					
						
							|  |  |  |     else: | 
					
						
							| 
									
										
										
										
											2013-06-24 13:49:40 -07:00
										 |  |  |         extract_vendor_ids(sys.argv[2]) | 
					
						
							|  |  |  |         extract_ofp_errors(sys.argv[1]) |