blob: 26dbac1f50a191a9b4d05b7f6fea0ba33946ae63 [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 Utilities related to processing OF header files
#
import re
import sys
import os
import c_parse_utils
import loxi_utils.py_utils as py_utils
import translation
from generic_utils import *
import copy
# Silently ignore idents matching any of these
ignore_idents = [
"OFPXMT_OFB_", "OFPFMF_", "OXM_OF_", "OFPXMT_",
"OPENFLOW_OPENFLOW_H", "OFP_ASSERT", "OFP_PACKED", "OFP_VERSION"
]
def warn_unmapped_ident(ident, t_name="enum"):
for ignore_ident in ignore_idents:
if re.match(ignore_ident, ident):
return
log("Skipping ident %s. Did not map %s identifier to LOXI" %
(ident, t_name))
def fixup_values(ident, value, version, ident_list):
"""
Fix up values for LOXI reasons
Translate defintions that refer to other identifiers
This is really just needed for the special case of OFPFW in 1.0 and 1.1.
Also, LOXI is aware of the change in type of port numbers, so
translate those here.
"""
value_string = str(value).strip()
if ident.find("OFPP_") == 0 and version == of_g.VERSION_1_0:
value_string = "0x%x" % (int(value, 0) + 0xffff0000)
if ident == 'OFP_VLAN_NONE' and version > of_g.VERSION_1_0:
value_string = '0'
# Otherwise, if no reference to a wildcard value, all done
if value_string.find("OFPFW") < 0:
return value_string
for ident, id_value in ident_list.items():
id_value_string = "(" + str(id_value).strip() + ")"
# If the identifier has (, etc., ignore it; not handling params
if ident.find("(") >= 0:
continue
value_string = re.sub(ident, id_value_string, value_string)
return value_string
def get_enum_dict(version, contents):
"""
Given openflow.h input, create a dict for its enums
@param contents The raw contents of the C file
The dict returned is indexed by LOXI identifier. Each entry is a
DotDict with three keys, value, ofp_name and ofp_group. The value is an
int value when possible, otherwise a string. The ofp_name is the original
name from the openflow header file. The ofp_group is the enum type.
"""
rv_list = {}
version_ref = of_g.short_version_names[version]
enum_list = c_parse_utils.extract_enums(contents)
defines_list = c_parse_utils.extract_defines(contents)
# First generate a list of all original idents and values for translation
full_ident_list = {}
for enum in enum_list:
(name, values) = c_parse_utils.extract_enum_vals(enum)
for (ident, value) in values:
full_ident_list[ident] = str(value).strip()
for ident, value in defines_list:
full_ident_list[ident] = str(value).strip()
# Process enum idents
for enum in enum_list:
(name, values) = c_parse_utils.extract_enum_vals(enum)
for (ident, value) in values:
loxi_name = translation.loxi_name(ident)
if not loxi_name:
warn_unmapped_ident(ident)
continue
if loxi_name in rv_list:
sys.stderr.write("\nError: %s in ident list already\n" %
loxi_name)
sys.exit(1)
value_str = fixup_values(ident, value, version, full_ident_list)
log("Adding LOXI identifier %s from name %s" % (loxi_name, ident))
rv_list[loxi_name] = py_utils.DotDict(dict(
ofp_name = ident,
ofp_group = name,
value = value_str))
for ident, value in defines_list:
loxi_name = translation.loxi_name(ident)
if not loxi_name:
warn_unmapped_ident(ident, "macro defn")
continue
value_str = fixup_values(ident, value, version, full_ident_list)
if loxi_name in rv_list:
if value_str != rv_list[loxi_name].value:
sys.stderr.write("""
ERROR: IDENT COLLISION. Version %s, LOXI Ident %s.
New ofp_name %s, value %s.
Previous ofp_name %s, value %s,
""" % (version_ref, loxi_name, ident, value_str,
rv_list[loxi_name].ofp_name), rv_list[loxi_name].value)
sys.exit(1)
else:
log("Ignoring redundant entry %s, mapping to %s" %
(ident, loxi_name))
rv_list[loxi_name] = py_utils.DotDict(dict(
ofp_name = ident,
ofp_group = "macro_definitions",
value = value_str))
return rv_list