Merge into master from pull request #274:
loci: generate match tables from the IR (https://github.com/floodlight/loxigen/pull/274)
diff --git a/c_gen/c_test_gen.py b/c_gen/c_test_gen.py
index 5501ed3..aff1ca6 100644
--- a/c_gen/c_test_gen.py
+++ b/c_gen/c_test_gen.py
@@ -271,10 +271,8 @@
""")
- populate_match_version(1, match.of_v1_keys)
- populate_match_version(2, match.of_v2_keys)
- populate_match_version(3, match.match_keys_sorted)
- populate_match_version(4, match.match_keys_sorted)
+ for wire_version, match_keys in match.match_keys.items():
+ populate_match_version(wire_version, match_keys)
out.write("""
if (value % 2) {
diff --git a/c_gen/match.py b/c_gen/match.py
index a7da751..7b7dcce 100644
--- a/c_gen/match.py
+++ b/c_gen/match.py
@@ -33,6 +33,7 @@
import c_gen.of_g_legacy as of_g
from generic_utils import *
import c_gen.loxi_utils_legacy as loxi_utils
+import loxi_globals
#
# Use 1.2 match semantics for common case
@@ -47,512 +48,13 @@
# Keys:
# name The unified name used for the member
# m_type The data type used for the object in unified structure
-# print_type The id to use when printing
-# conditions The condition underwhich the field could occur TBD
-# takes_mask_in_spec Shown as taking mask in OF 1.2 spec; IGNORED NOW
# order Used to define an order for readability
# v1_wc_shift The WC shift in OF 1.0
# v2_wc_shift The WC shift in OF 1.1
#
-# Unless noted otherwise, class is 0x8000, OFPXMC_OPENFLOW_BASIC
# We use the 1.2 names and alias older names
-# Conditions:
-# is_ipv4(_m): ((_m)->eth_type == 0x0800)
-# is_ipv6(_m): ((_m)->eth_type == 0x86dd)
-# is_ip(_m): (is_ipv4(_m) || is_ipv6(_m))
-# is_arp(_m): ((_m)->eth_type == 0x0806)
-# is_tcp(_m): (is_ip(_m) && ((_m)->ip_proto == 6))
-# is_udp(_m): (is_ip(_m) && ((_m)->ip_proto == 17))
-# is_sctp(_m): (is_ip(_m) && ((_m)->ip_proto == 132))
-# is_icmpv4(_m): (is_ipv4(_m) && ((_m)->ip_proto == 1))
-# is_icmpv6(_m): (is_ipv6(_m) && ((_m)->ip_proto == 58))
-#
-of_match_members = dict(
- in_port = dict(
- name="in_port",
- m_type="of_port_no_t",
- print_type="PRIx32",
- conditions="",
- v1_wc_shift=0,
- v2_wc_shift=0,
- takes_mask_in_spec=False,
- order=100,
- ),
- in_phy_port = dict(
- name="in_phy_port",
- m_type="of_port_no_t",
- print_type="PRIx32",
- conditions="", # OXM_OF_IN_PORT must be present
- takes_mask_in_spec=False,
- order=101,
- ),
- metadata = dict(
- name="metadata",
- m_type="uint64_t",
- print_type="PRIx64",
- conditions="",
- takes_mask_in_spec=True,
- order=102,
- ),
-
- eth_dst = dict(
- name="eth_dst",
- m_type="of_mac_addr_t",
- v1_wc_shift=3,
- print_type="\"p\"",
- conditions="",
- takes_mask_in_spec=True,
- order=200,
- ),
- eth_src = dict(
- name="eth_src",
- m_type="of_mac_addr_t",
- v1_wc_shift=2,
- print_type="\"p\"",
- conditions="",
- takes_mask_in_spec=True,
- order=201,
- ),
- eth_type = dict(
- name="eth_type",
- m_type="uint16_t",
- v1_wc_shift=4,
- v2_wc_shift=3,
- print_type="PRIx16",
- conditions="",
- takes_mask_in_spec=False,
- order=203,
- ),
- vlan_vid = dict( # FIXME: Semantics changed in 1.2
- # Use CFI bit to indicate tag presence
- name="vlan_vid",
- m_type="uint16_t",
- v1_wc_shift=1,
- v2_wc_shift=1,
- print_type="PRIx16",
- conditions="",
- takes_mask_in_spec=True,
- order=210,
- ),
- vlan_pcp = dict(
- name="vlan_pcp",
- m_type="uint8_t",
- v1_wc_shift=20,
- v2_wc_shift=2,
- print_type="PRIx8",
- conditions="",
- takes_mask_in_spec=False,
- order=211,
- ),
-
- ip_dscp = dict(
- name="ip_dscp",
- m_type="uint8_t",
- v1_wc_shift=21,
- v2_wc_shift=4,
- print_type="PRIx8",
- conditions="is_ip(match)",
- takes_mask_in_spec=False,
- order=310,
- ),
- ip_ecn = dict(
- name="ip_ecn",
- m_type="uint8_t",
- print_type="PRIx8",
- conditions="is_ip(match)",
- takes_mask_in_spec=False,
- order=311,
- ),
- ip_proto = dict(
- name="ip_proto",
- m_type="uint8_t",
- v1_wc_shift=5,
- v2_wc_shift=5,
- print_type="PRIx8",
- conditions="is_ip(match)",
- takes_mask_in_spec=False,
- order=320,
- ),
- ipv4_src = dict(
- name="ipv4_src",
- m_type="of_ipv4_t",
- v1_wc_shift=8,
- print_type="PRIx32",
- conditions="is_ipv4(match)",
- takes_mask_in_spec=True,
- order=330,
- ),
- ipv4_dst = dict(
- name="ipv4_dst",
- m_type="of_ipv4_t",
- v1_wc_shift=14,
- print_type="PRIx32",
- conditions="is_ipv4(match)",
- takes_mask_in_spec=True,
- order=331,
- ),
-
- tcp_dst = dict(
- name="tcp_dst",
- m_type="uint16_t",
- v1_wc_shift=7,
- v2_wc_shift=7,
- print_type="PRIx16",
- conditions="is_tcp(match)",
- takes_mask_in_spec=False,
- order=400,
- ),
- tcp_src = dict(
- name="tcp_src",
- m_type="uint16_t",
- v1_wc_shift=6,
- v2_wc_shift=6,
- print_type="PRIx16",
- conditions="is_tcp(match)",
- takes_mask_in_spec=False,
- order=401,
- ),
-
- udp_dst = dict(
- name="udp_dst",
- m_type="uint16_t",
- print_type="PRIx16",
- conditions="is_udp(match)",
- takes_mask_in_spec=False,
- order=410,
- ),
- udp_src = dict(
- name="udp_src",
- m_type="uint16_t",
- print_type="PRIx16",
- conditions="is_udp(match)",
- takes_mask_in_spec=False,
- order=411,
- ),
-
- sctp_dst = dict(
- name="sctp_dst",
- m_type="uint16_t",
- print_type="PRIx16",
- conditions="is_sctp(match)",
- takes_mask_in_spec=False,
- order=420,
- ),
- sctp_src = dict(
- name="sctp_src",
- m_type="uint16_t",
- print_type="PRIx16",
- conditions="is_sctp(match)",
- takes_mask_in_spec=False,
- order=421,
- ),
-
- icmpv4_type = dict(
- name="icmpv4_type",
- m_type="uint8_t",
- print_type="PRIx8",
- conditions="is_icmp_v4(match)",
- takes_mask_in_spec=False,
- order=430,
- ),
- icmpv4_code = dict(
- name="icmpv4_code",
- m_type="uint8_t",
- print_type="PRIx8",
- conditions="is_icmp_v4(match)",
- takes_mask_in_spec=False,
- order=431,
- ),
-
- arp_op = dict(
- name="arp_op",
- m_type="uint16_t",
- print_type="PRIx16",
- conditions="is_arp(match)",
- takes_mask_in_spec=False,
- order=450,
- ),
-
- arp_spa = dict(
- name="arp_spa",
- m_type="uint32_t",
- print_type="PRIx32",
- conditions="is_arp(match)",
- takes_mask_in_spec=True,
- order=451,
- ),
- arp_tpa = dict(
- name="arp_tpa",
- m_type="uint32_t",
- print_type="PRIx32",
- conditions="is_arp(match)",
- takes_mask_in_spec=True,
- order=452,
- ),
-
- arp_sha = dict(
- name="arp_sha",
- m_type="of_mac_addr_t",
- print_type="\"p\"",
- conditions="is_arp(match)",
- takes_mask_in_spec=False,
- order=453,
- ),
- arp_tha = dict(
- name="arp_tha",
- m_type="of_mac_addr_t",
- print_type="\"p\"",
- conditions="is_arp(match)",
- takes_mask_in_spec=False,
- order=454,
- ),
-
- ipv6_src = dict(
- name="ipv6_src",
- m_type="of_ipv6_t",
- print_type="\"p\"",
- conditions="is_ipv6(match)",
- takes_mask_in_spec=True,
- order=500,
- ),
- ipv6_dst = dict(
- name="ipv6_dst",
- m_type="of_ipv6_t",
- print_type="\"p\"",
- conditions="is_ipv6(match)",
- takes_mask_in_spec=True,
- order=501,
- ),
-
- ipv6_flabel = dict(
- name="ipv6_flabel",
- m_type="uint32_t",
- print_type="PRIx32",
- conditions="is_ipv6(match)",
- takes_mask_in_spec=False, # Comment in openflow.h says True
- order=502,
- ),
-
- icmpv6_type = dict(
- name="icmpv6_type",
- m_type="uint8_t",
- print_type="PRIx8",
- conditions="is_icmp_v6(match)",
- takes_mask_in_spec=False,
- order=510,
- ),
- icmpv6_code = dict(
- name="icmpv6_code",
- m_type="uint8_t",
- print_type="PRIx8",
- conditions="is_icmp_v6(match)",
- takes_mask_in_spec=False,
- order=511,
- ),
-
- ipv6_nd_target = dict(
- name="ipv6_nd_target",
- m_type="of_ipv6_t",
- print_type="\"p\"",
- conditions="", # fixme
- takes_mask_in_spec=False,
- order=512,
- ),
-
- ipv6_nd_sll = dict(
- name="ipv6_nd_sll",
- m_type="of_mac_addr_t",
- print_type="\"p\"",
- conditions="", # fixme
- takes_mask_in_spec=False,
- order=520,
- ),
- ipv6_nd_tll = dict(
- name="ipv6_nd_tll",
- m_type="of_mac_addr_t",
- print_type="\"p\"",
- conditions="", # fixme
- takes_mask_in_spec=False,
- order=521,
- ),
-
- mpls_label = dict(
- name="mpls_label",
- m_type="uint32_t",
- v2_wc_shift=8,
- print_type="PRIx32",
- conditions="",
- takes_mask_in_spec=False,
- order=600,
- ),
- mpls_tc = dict(
- name="mpls_tc",
- m_type="uint8_t",
- v2_wc_shift=9,
- print_type="PRIx8",
- conditions="",
- takes_mask_in_spec=False,
- order=601,
- ),
-
- bsn_in_ports_128 = dict(
- name="bsn_in_ports_128",
- m_type="of_bitmap_128_t",
- v2_wc_shift=9,
- print_type="p",
- conditions="",
- takes_mask_in_spec=True,
- order=1000,
- ),
-
- bsn_lag_id = dict(
- name="bsn_lag_id",
- m_type="uint32_t",
- print_type="PRIu32",
- conditions="",
- takes_mask_in_spec=False,
- order=1001,
- ),
-
- bsn_vrf = dict(
- name="bsn_vrf",
- m_type="uint32_t",
- print_type="PRIu32",
- conditions="",
- takes_mask_in_spec=False,
- order=1002,
- ),
-
- bsn_global_vrf_allowed = dict(
- name="bsn_global_vrf_allowed",
- m_type="uint8_t",
- print_type="PRIu8",
- conditions="",
- takes_mask_in_spec=False,
- order=1003,
- ),
-
- bsn_l3_interface_class_id = dict(
- name="bsn_l3_interface_class_id",
- m_type="uint32_t",
- print_type="PRIu32",
- conditions="",
- takes_mask_in_spec=True,
- order=1003,
- ),
-
- bsn_l3_src_class_id = dict(
- name="bsn_l3_src_class_id",
- m_type="uint32_t",
- print_type="PRIu32",
- conditions="",
- takes_mask_in_spec=True,
- order=1004,
- ),
-
- bsn_l3_dst_class_id = dict(
- name="bsn_l3_dst_class_id",
- m_type="uint32_t",
- print_type="PRIu32",
- conditions="",
- takes_mask_in_spec=True,
- order=1005,
- ),
-
- bsn_egr_port_group_id = dict(
- name="bsn_egr_port_group_id",
- m_type="uint32_t",
- print_type="PRIu32",
- conditions="",
- takes_mask_in_spec=True,
- order=1006,
- ),
-
- bsn_udf0 = dict(
- name="bsn_udf0",
- m_type="uint32_t",
- print_type="PRIu32",
- conditions="",
- takes_mask_in_spec=True,
- order=1010,
- ),
-
- bsn_udf1 = dict(
- name="bsn_udf1",
- m_type="uint32_t",
- print_type="PRIu32",
- conditions="",
- takes_mask_in_spec=True,
- order=1010,
- ),
-
- bsn_udf2 = dict(
- name="bsn_udf2",
- m_type="uint32_t",
- print_type="PRIu32",
- conditions="",
- takes_mask_in_spec=True,
- order=1010,
- ),
-
- bsn_udf3 = dict(
- name="bsn_udf3",
- m_type="uint32_t",
- print_type="PRIu32",
- conditions="",
- takes_mask_in_spec=True,
- order=1010,
- ),
-
- bsn_udf4 = dict(
- name="bsn_udf4",
- m_type="uint32_t",
- print_type="PRIu32",
- conditions="",
- takes_mask_in_spec=True,
- order=1010,
- ),
-
- bsn_udf5 = dict(
- name="bsn_udf5",
- m_type="uint32_t",
- print_type="PRIu32",
- conditions="",
- takes_mask_in_spec=True,
- order=1010,
- ),
-
- bsn_udf6 = dict(
- name="bsn_udf6",
- m_type="uint32_t",
- print_type="PRIu32",
- conditions="",
- takes_mask_in_spec=True,
- order=1010,
- ),
-
- bsn_udf7 = dict(
- name="bsn_udf7",
- m_type="uint32_t",
- print_type="PRIu32",
- conditions="",
- takes_mask_in_spec=True,
- order=1010,
- ),
-
- bsn_tcp_flags = dict(
- name="bsn_tcp_flags",
- m_type="uint16_t",
- print_type="PRIx16",
- conditions="",
- takes_mask_in_spec=True,
- order=1010,
- ),
-)
-
-match_keys_sorted = of_match_members.keys()
-match_keys_sorted.sort(key=lambda entry:of_match_members[entry]["order"])
+of_match_members = dict()
of_v1_keys = [
"eth_dst",
@@ -569,6 +71,21 @@
"vlan_vid"
]
+v1_wc_shifts = dict(
+ in_port=0,
+ vlan_vid=1,
+ eth_src=2,
+ eth_dst=3,
+ eth_type=4,
+ ip_proto=5,
+ tcp_src=6,
+ tcp_dst=7,
+ ipv4_src=8,
+ ipv4_dst=14,
+ vlan_pcp=20,
+ ip_dscp=21,
+)
+
of_v2_keys = [
"eth_dst",
"eth_src",
@@ -595,6 +112,69 @@
"metadata"
]
+v2_wc_shifts = dict(
+ in_port=0,
+ vlan_vid=1,
+ vlan_pcp=2,
+ eth_type=3,
+ ip_dscp=4,
+ ip_proto=5,
+ tcp_src=6,
+ tcp_dst=7,
+ mpls_label=8,
+ mpls_tc=9,
+)
+
+# Map from wire version to list of match keys for that version
+match_keys = {
+ 1: of_v1_keys,
+ 2: of_v2_keys,
+ 3: [],
+ 4: [],
+}
+
+# Complete list of match keys, sorted by the standard order
+match_keys_sorted = []
+
+# Generate the of_match_members, match_keys, and match_keys_sorted
+# datastructures from the IR and the v1/v2 tables above
+def build():
+ for uclass in loxi_globals.unified.classes:
+ if not uclass.is_oxm or uclass.name == 'of_oxm':
+ continue
+ if uclass.name.endswith('_masked'):
+ continue
+
+ name = uclass.name[7:] # of_oxm_*
+ value_member = uclass.member_by_name('value')
+ type_len = uclass.member_by_name('type_len').value
+
+ # Order match keys by their type_len
+ if (type_len & 0xffff0000) == 0x80000000:
+ # OpenFlow Basic comes first
+ order = type_len & 0x0000ffff
+ else:
+ order = type_len
+
+ match_member = dict(
+ name=name,
+ m_type=value_member.oftype,
+ order=order)
+ if name in v1_wc_shifts:
+ match_member['v1_wc_shift'] = v1_wc_shifts[name]
+ if name in v2_wc_shifts:
+ match_member['v2_wc_shift'] = v2_wc_shifts[name]
+
+ of_match_members[name] = match_member
+
+ for version in uclass.version_classes:
+ assert name not in match_keys[version.wire_version]
+ match_keys[version.wire_version].append(name)
+
+ match_keys_sorted.extend(
+ sorted(of_match_members.keys(),
+ key=lambda entry:of_match_members[entry]["order"]))
+
##
# Check that all members in the hash are recognized as match keys
def match_sanity_check():
diff --git a/lang_c.py b/lang_c.py
index 24ccc06..8e153fe 100644
--- a/lang_c.py
+++ b/lang_c.py
@@ -41,6 +41,7 @@
import c_gen.c_show_gen as c_show_gen
import c_gen.util
import c_gen.codegen
+import c_gen.match
import loxi_utils.loxi_utils as loxi_utils
import template_utils
@@ -112,6 +113,7 @@
}
def generate(install_dir):
+ c_gen.match.build()
build_of_g.initialize_versions()
build_of_g.build_ordered_classes()
build_of_g.populate_type_maps()