def process_input_file(filename): """ Process an input file Does not modify global state. @param filename The input filename @returns An OFInput object """ # Parse the input file try: with open(filename, 'r') as f: ast = parser.parse(f.read()) except pyparsing.ParseBaseException as e: print "Parse error in %s: %s" % (os.path.basename(filename), str(e)) sys.exit(1) # Create the OFInput from the AST try: ofinput = frontend.create_ofinput(ast) except frontend.InputError as e: print "Error in %s: %s" % (os.path.basename(filename), str(e)) sys.exit(1) return ofinput
def test_inheritance(self): ast = parser.parse(""" #version 1 struct of_queue_prop { uint16_t type == ?; uint16_t len; pad(4); }; struct of_queue_prop_min_rate : of_queue_prop { uint16_t type == 1; uint16_t len; pad(4); uint16_t rate; pad(6); }; """) # Not testing the parser, just making sure the AST is what we expect expected_ast = [ ['metadata', 'version', '1'], [ 'struct', 'of_queue_prop', [], None, [['discriminator', ['scalar', 'uint16_t'], 'type'], ['data', ['scalar', 'uint16_t'], 'len'], ['pad', 4]] ], [ 'struct', 'of_queue_prop_min_rate', [], 'of_queue_prop', [['type', ['scalar', 'uint16_t'], 'type', 1], ['data', ['scalar', 'uint16_t'], 'len'], ['pad', 4], ['data', ['scalar', 'uint16_t'], 'rate'], ['pad', 6]] ], ] self.assertEquals(expected_ast, ast) ofinput = frontend.create_ofinput(ast) expected_classes = [ OFClass(name='of_queue_prop', superclass=None, members=[ OFDiscriminatorMember('type', 'uint16_t'), OFLengthMember('len', 'uint16_t'), OFPadMember(4) ], virtual=True, params={}), OFClass(name='of_queue_prop_min_rate', superclass='of_queue_prop', members=[ OFTypeMember('type', 'uint16_t', 1), OFLengthMember('len', 'uint16_t'), OFPadMember(4), OFDataMember('rate', 'uint16_t'), OFPadMember(6) ], virtual=False, params={}), ] self.assertEquals(expected_classes, ofinput.classes)
def test_inheritance(self): ast = parser.parse(""" #version 1 struct of_queue_prop { uint16_t type == ?; uint16_t len; pad(4); }; struct of_queue_prop_min_rate : of_queue_prop { uint16_t type == 1; uint16_t len; pad(4); uint16_t rate; pad(6); }; """) # Not testing the parser, just making sure the AST is what we expect expected_ast = [ ['metadata', 'version', '1'], ['struct', 'of_queue_prop', [], None, [ ['discriminator', ['scalar', 'uint16_t'], 'type'], ['data', ['scalar', 'uint16_t'], 'len'], ['pad', 4]]], ['struct', 'of_queue_prop_min_rate', [], 'of_queue_prop', [ ['type', ['scalar', 'uint16_t'], 'type', 1], ['data', ['scalar', 'uint16_t'], 'len'], ['pad', 4], ['data', ['scalar', 'uint16_t'], 'rate'], ['pad', 6]]], ] self.assertEquals(expected_ast, ast) ofinput = frontend.create_ofinput(ast) expected_classes = [ OFClass(name='of_queue_prop', superclass=None, members=[ OFDiscriminatorMember('type', 'uint16_t'), OFLengthMember('len', 'uint16_t'), OFPadMember(4)], virtual=True, params={}), OFClass(name='of_queue_prop_min_rate', superclass='of_queue_prop', members= [ OFTypeMember('type', 'uint16_t', 1), OFLengthMember('len', 'uint16_t'), OFPadMember(4), OFDataMember('rate', 'uint16_t'), OFPadMember(6)], virtual=False, params= {}), ] self.assertEquals(expected_classes, ofinput.classes)
def test_field_length(self): ast = parser.parse(""" #version 1 struct of_test_entry { uint32_t x; }; struct of_test { uint16_t list_len == length(list); list(of_test_entry_t) list; }; """) # Not testing the parser, just making sure the AST is what we expect expected_ast = [ ['metadata', 'version', '1'], [ 'struct', 'of_test_entry', [], None, [['data', ['scalar', 'uint32_t'], 'x']] ], [ 'struct', 'of_test', [], None, [['field_length', ['scalar', 'uint16_t'], 'list_len', 'list'], ['data', ['list', 'list(of_test_entry_t)'], 'list']] ] ] self.assertEqual(expected_ast, ast) ofinput = frontend.create_ofinput("standard-1.0", ast) expected_classes = [ OFClass(name='of_test_entry', superclass=None, virtual=False, params={}, members=[OFDataMember('x', 'uint32_t')]), OFClass(name='of_test', superclass=None, virtual=False, params={}, members=[ OFFieldLengthMember('list_len', 'uint16_t', 'list'), OFDataMember('list', 'list(of_test_entry_t)') ]) ] self.assertEqual(expected_classes, ofinput.classes)
def test_field_length(self): ast = parser.parse(""" #version 1 struct of_test_entry { uint32_t x; }; struct of_test { uint16_t list_len == length(list); list(of_test_entry_t) list; }; """) # Not testing the parser, just making sure the AST is what we expect expected_ast = [ ['metadata', 'version', '1'], ['struct', 'of_test_entry', [], None, [ ['data', ['scalar', 'uint32_t'], 'x']]], ['struct', 'of_test', [], None, [ ['field_length', ['scalar', 'uint16_t'], 'list_len', 'list'], ['data', ['list', 'list(of_test_entry_t)'], 'list']]] ] self.assertEquals(expected_ast, ast) ofinput = frontend.create_ofinput("standard-1.0", ast) expected_classes = [ OFClass(name='of_test_entry', superclass=None, virtual=False, params={}, members=[ OFDataMember('x', 'uint32_t')]), OFClass(name='of_test', superclass=None, virtual=False, params={}, members=[ OFFieldLengthMember('list_len', 'uint16_t', 'list'), OFDataMember('list', 'list(of_test_entry_t)')]) ] self.assertEquals(expected_classes, ofinput.classes)
def test_simple(self): ast = parser.parse(""" #version 1 enum ofp_port_config { OFPPC_PORT_DOWN = 0x1, OFPPC_NO_STP = 0x2, OFPPC_NO_RECV = 0x4, OFPPC_NO_RECV_STP = 0x8, OFPPC_NO_FLOOD = 0x10, OFPPC_NO_FWD = 0x20, OFPPC_NO_PACKET_IN = 0x40, }; #version 2 struct of_echo_reply(align=8) { uint8_t version; uint8_t type == 3; uint16_t length; uint32_t xid; of_octets_t data; }; enum ofp_queue_op_failed_code(wire_type=uint32, bitmask=False, complete=True) { OFPQOFC_BAD_PORT = 0, OFPQOFC_BAD_QUEUE = 1, OFPQOFC_EPERM = 2, }; struct of_packet_queue { uint32_t queue_id; uint16_t len; pad(2); list(of_queue_prop_t) properties; }; """) # Not testing the parser, just making sure the AST is what we expect expected_ast = [ ['metadata', 'version', '1'], ['enum', 'ofp_port_config', [], [ ['OFPPC_PORT_DOWN', [], 1], ['OFPPC_NO_STP', [], 2], ['OFPPC_NO_RECV', [], 4], ['OFPPC_NO_RECV_STP', [], 8], ['OFPPC_NO_FLOOD', [], 16], ['OFPPC_NO_FWD', [], 32], ['OFPPC_NO_PACKET_IN', [], 64]]], ['metadata', 'version', '2'], ['struct', 'of_echo_reply', [['align', '8']], None, [ ['data', ['scalar', 'uint8_t'], 'version'], ['type', ['scalar', 'uint8_t'], 'type', 3], ['data', ['scalar', 'uint16_t'], 'length'], ['data', ['scalar', 'uint32_t'], 'xid'], ['data', ['scalar', 'of_octets_t'], 'data']]], ['enum', 'ofp_queue_op_failed_code', [['wire_type', 'uint32'], ['bitmask','False'], ['complete', 'True']], [ ['OFPQOFC_BAD_PORT', [], 0], ['OFPQOFC_BAD_QUEUE', [], 1], ['OFPQOFC_EPERM', [], 2]]], ['struct', 'of_packet_queue', [], None, [ ['data', ['scalar', 'uint32_t'], 'queue_id'], ['data', ['scalar', 'uint16_t'], 'len'], ['pad', 2], ['data', ['list', 'list(of_queue_prop_t)'], 'properties']]], ] self.assertEquals(expected_ast, ast) ofinput = frontend.create_ofinput(ast) self.assertEquals(set([1, 2]), ofinput.wire_versions) expected_classes = [ OFClass(name='of_echo_reply', superclass=None, members=[ OFDataMember('version', 'uint8_t'), # XXX OFTypeMember('type', 'uint8_t', 3), OFLengthMember('length', 'uint16_t'), OFDataMember('xid', 'uint32_t'), OFDataMember('data', 'of_octets_t')], virtual=False, params={'align': '8'}), OFClass(name='of_packet_queue', superclass=None, members=[ OFDataMember('queue_id', 'uint32_t'), OFLengthMember('len', 'uint16_t'), OFPadMember(2), OFDataMember('properties', 'list(of_queue_prop_t)')], virtual=False, params={}), ] self.assertEquals(expected_classes, ofinput.classes) expected_enums = [ OFEnum(name='ofp_port_config', entries=[ OFEnumEntry('OFPPC_PORT_DOWN', 1, {}), OFEnumEntry('OFPPC_NO_STP', 2, {}), OFEnumEntry('OFPPC_NO_RECV', 4, {}), OFEnumEntry('OFPPC_NO_RECV_STP', 8, {}), OFEnumEntry('OFPPC_NO_FLOOD', 16, {}), OFEnumEntry('OFPPC_NO_FWD', 32, {}), OFEnumEntry('OFPPC_NO_PACKET_IN', 64, {})], params={}), OFEnum(name='ofp_queue_op_failed_code', entries=[ OFEnumEntry('OFPQOFC_BAD_PORT', 0, {}), OFEnumEntry('OFPQOFC_BAD_QUEUE', 1, {}), OFEnumEntry('OFPQOFC_EPERM', 2, {})], params={'wire_type': 'uint32', 'bitmask': 'False', 'complete': 'True'}), ] self.assertEquals(expected_enums, ofinput.enums)
def test_simple(self): ast = parser.parse(""" #version 1 enum ofp_port_config { OFPPC_PORT_DOWN = 0x1, OFPPC_NO_STP = 0x2, OFPPC_NO_RECV = 0x4, OFPPC_NO_RECV_STP = 0x8, OFPPC_NO_FLOOD = 0x10, OFPPC_NO_FWD = 0x20, OFPPC_NO_PACKET_IN = 0x40, }; #version 2 struct of_echo_reply(align=8) { uint8_t version; uint8_t type == 3; uint16_t length; uint32_t xid; of_octets_t data; }; enum ofp_queue_op_failed_code(wire_type=uint32, bitmask=False, complete=True) { OFPQOFC_BAD_PORT = 0, OFPQOFC_BAD_QUEUE = 1, OFPQOFC_EPERM = 2, }; struct of_packet_queue { uint32_t queue_id; uint16_t len; pad(2); list(of_queue_prop_t) properties; }; """) # Not testing the parser, just making sure the AST is what we expect expected_ast = [ ['metadata', 'version', '1'], [ 'enum', 'ofp_port_config', [], [['OFPPC_PORT_DOWN', [], 1], ['OFPPC_NO_STP', [], 2], ['OFPPC_NO_RECV', [], 4], ['OFPPC_NO_RECV_STP', [], 8], ['OFPPC_NO_FLOOD', [], 16], ['OFPPC_NO_FWD', [], 32], ['OFPPC_NO_PACKET_IN', [], 64]] ], ['metadata', 'version', '2'], [ 'struct', 'of_echo_reply', [['align', '8']], None, [['data', ['scalar', 'uint8_t'], 'version'], ['type', ['scalar', 'uint8_t'], 'type', 3], ['data', ['scalar', 'uint16_t'], 'length'], ['data', ['scalar', 'uint32_t'], 'xid'], ['data', ['scalar', 'of_octets_t'], 'data']] ], [ 'enum', 'ofp_queue_op_failed_code', [['wire_type', 'uint32'], ['bitmask', 'False'], ['complete', 'True']], [['OFPQOFC_BAD_PORT', [], 0], ['OFPQOFC_BAD_QUEUE', [], 1], ['OFPQOFC_EPERM', [], 2]] ], [ 'struct', 'of_packet_queue', [], None, [['data', ['scalar', 'uint32_t'], 'queue_id'], ['data', ['scalar', 'uint16_t'], 'len'], ['pad', 2], ['data', ['list', 'list(of_queue_prop_t)'], 'properties']] ], ] self.assertEquals(expected_ast, ast) ofinput = frontend.create_ofinput(ast) self.assertEquals(set([1, 2]), ofinput.wire_versions) expected_classes = [ OFClass( name='of_echo_reply', superclass=None, members=[ OFDataMember('version', 'uint8_t'), # XXX OFTypeMember('type', 'uint8_t', 3), OFLengthMember('length', 'uint16_t'), OFDataMember('xid', 'uint32_t'), OFDataMember('data', 'of_octets_t') ], virtual=False, params={'align': '8'}), OFClass(name='of_packet_queue', superclass=None, members=[ OFDataMember('queue_id', 'uint32_t'), OFLengthMember('len', 'uint16_t'), OFPadMember(2), OFDataMember('properties', 'list(of_queue_prop_t)') ], virtual=False, params={}), ] self.assertEquals(expected_classes, ofinput.classes) expected_enums = [ OFEnum(name='ofp_port_config', entries=[ OFEnumEntry('OFPPC_PORT_DOWN', 1, {}), OFEnumEntry('OFPPC_NO_STP', 2, {}), OFEnumEntry('OFPPC_NO_RECV', 4, {}), OFEnumEntry('OFPPC_NO_RECV_STP', 8, {}), OFEnumEntry('OFPPC_NO_FLOOD', 16, {}), OFEnumEntry('OFPPC_NO_FWD', 32, {}), OFEnumEntry('OFPPC_NO_PACKET_IN', 64, {}) ], params={}), OFEnum(name='ofp_queue_op_failed_code', entries=[ OFEnumEntry('OFPQOFC_BAD_PORT', 0, {}), OFEnumEntry('OFPQOFC_BAD_QUEUE', 1, {}), OFEnumEntry('OFPQOFC_EPERM', 2, {}) ], params={ 'wire_type': 'uint32', 'bitmask': 'False', 'complete': 'True' }), ] self.assertEquals(expected_enums, ofinput.enums)
def test_simple(self): ast = parser.parse(""" #version 1 enum ofp_port_config { OFPPC_PORT_DOWN = 0x1, OFPPC_NO_STP = 0x2, OFPPC_NO_RECV = 0x4, OFPPC_NO_RECV_STP = 0x8, OFPPC_NO_FLOOD = 0x10, OFPPC_NO_FWD = 0x20, OFPPC_NO_PACKET_IN = 0x40, }; #version 2 struct of_echo_reply { uint8_t version; uint8_t type == 3; uint16_t length; uint32_t xid; of_octets_t data; }; enum ofp_queue_op_failed_code { OFPQOFC_BAD_PORT = 0, OFPQOFC_BAD_QUEUE = 1, OFPQOFC_EPERM = 2, }; struct of_packet_queue { uint32_t queue_id; uint16_t len; pad(2); list(of_queue_prop_t) properties; }; """) # Not testing the parser, just making sure the AST is what we expect expected_ast = [ ['metadata', 'version', '1'], ['enum', 'ofp_port_config', [ ['OFPPC_PORT_DOWN', 1], ['OFPPC_NO_STP', 2], ['OFPPC_NO_RECV', 4], ['OFPPC_NO_RECV_STP', 8], ['OFPPC_NO_FLOOD', 16], ['OFPPC_NO_FWD', 32], ['OFPPC_NO_PACKET_IN', 64]]], ['metadata', 'version', '2'], ['struct', 'of_echo_reply', [ ['data', 'uint8_t', 'version'], ['type', 'uint8_t', 'type', 3], ['data', 'uint16_t', 'length'], ['data', 'uint32_t', 'xid'], ['data', 'of_octets_t', 'data']]], ['enum', 'ofp_queue_op_failed_code', [ ['OFPQOFC_BAD_PORT', 0], ['OFPQOFC_BAD_QUEUE', 1], ['OFPQOFC_EPERM', 2]]], ['struct', 'of_packet_queue', [ ['data', 'uint32_t', 'queue_id'], ['data', 'uint16_t', 'len'], ['pad', 2], ['data', 'list(of_queue_prop_t)', 'properties']]], ] self.assertEquals(expected_ast, ast) ofinput = frontend.create_ofinput(ast) self.assertEquals(set([1, 2]), ofinput.wire_versions) expected_classes = [ OFClass('of_echo_reply', [ OFDataMember('version', 'uint8_t'), # XXX OFTypeMember('type', 'uint8_t', 3), OFLengthMember('length', 'uint16_t'), OFDataMember('xid', 'uint32_t'), OFDataMember('data', 'of_octets_t')]), OFClass('of_packet_queue', [ OFDataMember('queue_id', 'uint32_t'), OFLengthMember('len', 'uint16_t'), OFPadMember(2), OFDataMember('properties', 'list(of_queue_prop_t)')]), ] self.assertEquals(expected_classes, ofinput.classes) expected_enums = [ OFEnum('ofp_port_config', [ ('OFPPC_PORT_DOWN', 1), ('OFPPC_NO_STP', 2), ('OFPPC_NO_RECV', 4), ('OFPPC_NO_RECV_STP', 8), ('OFPPC_NO_FLOOD', 16), ('OFPPC_NO_FWD', 32), ('OFPPC_NO_PACKET_IN', 64)]), OFEnum('ofp_queue_op_failed_code', [ ('OFPQOFC_BAD_PORT', 0), ('OFPQOFC_BAD_QUEUE', 1), ('OFPQOFC_EPERM', 2)]), ] self.assertEquals(expected_enums, ofinput.enums)