| # 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] = value |
| for ident, value in defines_list: |
| full_ident_list[ident] = value |
| |
| # 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 = eval(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 eval(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 = eval(value_str))) |
| |
| return rv_list |
| |
| |
| |
| |