Initial import
LoxiGen is the work of several developers, not just myself.
diff --git a/loxi_front_end/match.py b/loxi_front_end/match.py
new file mode 100644
index 0000000..4ab3126
--- /dev/null
+++ b/loxi_front_end/match.py
@@ -0,0 +1,488 @@
+# Copyright 2013, Big Switch Networks, Inc.
+#
+# LoxiGen is licensed under the Eclipse Public License, version 1.0 (EPL), with
+# the following special exception:
+#
+# LOXI Exception
+#
+# As a special exception to the terms of the EPL, you may distribute libraries
+# generated by LoxiGen (LoxiGen Libraries) under the terms of your choice, provided
+# that copyright and licensing notices generated by LoxiGen are not altered or removed
+# from the LoxiGen Libraries and the notice provided below is (i) included in
+# the LoxiGen Libraries, if distributed in source code form and (ii) included in any
+# documentation for the LoxiGen Libraries, if distributed in binary form.
+#
+# Notice: "Copyright 2013, Big Switch Networks, Inc. This library was generated by the LoxiGen Compiler."
+#
+# You may not use this file except in compliance with the EPL or LOXI Exception. You may obtain
+# a copy of the EPL at:
+#
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# EPL for the specific language governing permissions and limitations
+# under the EPL.
+
+# @brief Match data representation
+#
+# @fixme This still has lots of C specific code that should be moved into c_gen
+
+import sys
+import of_g
+from generic_utils import *
+import oxm
+import loxi_utils.loxi_utils as loxi_utils
+
+#
+# Use 1.2 match semantics for common case
+#
+# Generate maps between generic match and version specific matches
+# Generate dump functions for generic match
+# Generate dump functions for version specific matches
+
+## @var of_match_members
+# The dictionary from unified match members to type and indexing info
+#
+# 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,
+ ),
+ ipv4_src = dict(
+ name="ipv4_src",
+ m_type="uint32_t",
+ v1_wc_shift=8,
+ print_type="PRIx32",
+ conditions="is_ipv4(match)",
+ takes_mask_in_spec=True,
+ order=300,
+ ),
+ ipv4_dst = dict(
+ name="ipv4_dst",
+ m_type="uint32_t",
+ v1_wc_shift=14,
+ print_type="PRIx32",
+ conditions="is_ipv4(match)",
+ takes_mask_in_spec=True,
+ order=301,
+ ),
+ 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,
+ ),
+
+ 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=250,
+ ),
+
+ arp_spa = dict(
+ name="arp_spa",
+ m_type="uint32_t",
+ print_type="PRIx32",
+ conditions="is_arp(match)",
+ takes_mask_in_spec=True,
+ order=251,
+ ),
+ arp_tpa = dict(
+ name="arp_tpa",
+ m_type="uint32_t",
+ print_type="PRIx32",
+ conditions="is_arp(match)",
+ takes_mask_in_spec=True,
+ order=252,
+ ),
+
+ 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=253,
+ ),
+ 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=254,
+ ),
+
+ ipv6_src = dict(
+ name="ipv6_src",
+ m_type="of_ipv6_t",
+ print_type="\"p\"",
+ conditions="is_ipv6(match)",
+ takes_mask_in_spec=True,
+ order=350,
+ ),
+ ipv6_dst = dict(
+ name="ipv6_dst",
+ m_type="of_ipv6_t",
+ print_type="\"p\"",
+ conditions="is_ipv6(match)",
+ takes_mask_in_spec=True,
+ order=351,
+ ),
+
+ 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=360,
+ ),
+
+ icmpv6_type = dict(
+ name="icmpv6_type",
+ m_type="uint8_t",
+ print_type="PRIx8",
+ conditions="is_icmp_v6(match)",
+ takes_mask_in_spec=False,
+ order=440,
+ ),
+ icmpv6_code = dict(
+ name="icmpv6_code",
+ m_type="uint8_t",
+ print_type="PRIx8",
+ conditions="is_icmp_v6(match)",
+ takes_mask_in_spec=False,
+ order=441,
+ ),
+
+ ipv6_nd_target = dict(
+ name="ipv6_nd_target",
+ m_type="of_ipv6_t",
+ print_type="\"p\"",
+ conditions="", # fixme
+ takes_mask_in_spec=False,
+ order=442,
+ ),
+
+ 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=443,
+ ),
+ 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=444,
+ ),
+
+ mpls_label = dict(
+ name="mpls_label",
+ m_type="uint32_t",
+ v2_wc_shift=8,
+ print_type="PRIx32",
+ conditions="",
+ takes_mask_in_spec=False,
+ order=500,
+ ),
+ mpls_tc = dict(
+ name="mpls_tc",
+ m_type="uint8_t",
+ v2_wc_shift=9,
+ print_type="PRIx8",
+ conditions="",
+ takes_mask_in_spec=False,
+ order=501,
+ ),
+)
+
+match_keys_sorted = of_match_members.keys()
+match_keys_sorted.sort(key=lambda entry:of_match_members[entry]["order"])
+
+of_v1_keys = [
+ "eth_dst",
+ "eth_src",
+ "eth_type",
+ "in_port",
+ "ipv4_dst",
+ "ip_proto",
+ "ipv4_src",
+ "ip_dscp",
+ "tcp_dst", # Means UDP too for 1.0 and 1.1
+ "tcp_src", # Means UDP too for 1.0 and 1.1
+ "vlan_pcp",
+ "vlan_vid"
+ ]
+
+of_v2_keys = [
+ "eth_dst",
+ "eth_src",
+ "eth_type",
+ "in_port",
+ "ipv4_dst",
+ "ip_proto",
+ "ipv4_src",
+ "ip_dscp",
+ "tcp_dst", # Means UDP too for 1.0 and 1.1
+ "tcp_src", # Means UDP too for 1.0 and 1.1
+ "vlan_pcp",
+ "vlan_vid",
+ "mpls_label",
+ "mpls_tc",
+ "metadata"
+ ]
+
+of_v2_full_mask = [
+ "eth_dst",
+ "eth_src",
+ "ipv4_dst",
+ "ipv4_src",
+ "metadata"
+ ]
+
+def oxm_index(key):
+ """
+ What's the index called for a match key
+ """
+ return "OF_OXM_INDEX_" + key.upper()
+
+##
+# Check that all members in the hash are recognized as match keys
+def match_sanity_check():
+ count = 0
+ for match_v in ["of_match_v1", "of_match_v2"]:
+ count += 1
+ for mm in of_g.unified[match_v][count]["members"]:
+ key = mm["name"]
+ if key.find("_mask") >= 0:
+ continue
+ if loxi_utils.skip_member_name(key):
+ continue
+ if key == "wildcards":
+ continue
+ if not key in of_match_members:
+ print "Key %s not found in match struct, v %s" % (key, match_v)
+ sys.exit(1)
+
+ # Check oxm list and the list above
+ for key in oxm.oxm_types:
+ if not key in of_match_members:
+ if not (key.find("_masked") > 0):
+ debug("Key %s in oxm.oxm_types, not of_match_members" % key)
+ sys.exit(1)
+ if not key[:-7] in of_match_members:
+ debug("Key %s in oxm.oxm_types, but %s not in of_match_members"
+ % (key, key[:-7]))
+ sys.exit(1)
+
+ for key in of_match_members:
+ if not key in oxm.oxm_types:
+ debug("Key %s in of_match_members, not in oxm.oxm_types" % key)
+ sys.exit(1)
+ if of_match_members[key]["m_type"] != oxm.oxm_types[key]:
+ debug("Type mismatch for key %s in oxm data: %s vs %s" %
+ (key, of_match_members[key]["m_type"], oxm.oxm_types[key]))
+ sys.exit(1)
+
+