blob: c71545527e1755e4a9f3d94ce8749520c2160c9c [file] [log] [blame]
# 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 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,
),
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,
),
)
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)
# Generate list of OXM names from the unified classes
oxm_names = [x[7:] for x in of_g.unified.keys() if
x.startswith('of_oxm_') and
x.find('masked') < 0 and
x.find('header') < 0]
# Check that all OXMs are in the match members
for key in oxm_names:
if not key in of_match_members:
if not (key.find("_masked") > 0):
debug("Key %s in OXM, not of_match_members" % key)
sys.exit(1)
if not key[:-7] in of_match_members:
debug("Key %s in OXM, but %s not in of_match_members"
% (key, key[:-7]))
sys.exit(1)
# Check that all match members are in the OXMs
for key in of_match_members:
if not key in oxm_names:
debug("Key %s in of_match_members, not in OXM" % key)
sys.exit(1)
oxm_type = of_g.unified['of_oxm_%s' % key]['union']['value']['m_type']
if of_match_members[key]["m_type"] != oxm_type:
debug("Type mismatch for key %s in oxm data: %s vs %s" %
(key, of_match_members[key]["m_type"], oxm_type))
sys.exit(1)