| # 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 involving LOXI naming conventions |
| |
| Utility functions for OpenFlow class generation |
| |
| These may need to be sorted out into language specific functions |
| """ |
| |
| import re |
| import sys |
| |
| import loxi_globals |
| from generic_utils import find, memoize |
| |
| ## |
| # Class types: |
| # |
| # Virtual |
| # A virtual class is one which does not have an explicit wire |
| # representation. For example, an inheritance super class |
| # or a list type. |
| # |
| # List |
| # A list of objects of some other type |
| # |
| # TLV16 |
| # The wire represenation starts with 16-bit type and length fields |
| # |
| # OXM |
| # An extensible match object |
| # |
| # Message |
| # A top level OpenFlow message |
| # |
| # |
| |
| class NoneClass(object): |
| def is_instanceof(self, x): |
| return False |
| none_item = NoneClass() |
| |
| def _unified_by_name(cls): |
| c = loxi_globals.unified.class_by_name(cls) |
| return c if c is not None else none_item |
| |
| @memoize |
| def class_is_message(cls): |
| """ |
| Return True if cls is a message object based on info in unified |
| """ |
| if cls == "of_header": |
| return False |
| else: |
| return _unified_by_name(cls).is_instanceof("of_header") |
| |
| def class_is_tlv16(cls): |
| """ |
| Return True if cls_name is an object which uses uint16 for type and length |
| """ |
| if cls.find("of_action") == 0: # Includes of_action_id classes |
| return True |
| if cls.find("of_instruction") == 0: |
| return True |
| if cls.find("of_queue_prop") == 0: |
| return True |
| if cls.find("of_table_feature_prop") == 0: |
| return True |
| # *sigh* |
| if cls.find("of_meter_band_stats") == 0: # NOT A TLV |
| return False |
| if cls.find("of_meter_band") == 0: |
| return True |
| if cls.find("of_hello_elem") == 0: |
| return True |
| if cls == "of_match_v3": |
| return True |
| if cls == "of_match_v4": |
| return True |
| return False |
| |
| def class_is_u16_len(cls): |
| """ |
| Return True if cls_name is an object which uses initial uint16 length |
| """ |
| return cls in ["of_group_desc_stats_entry", "of_group_stats_entry", |
| "of_flow_stats_entry", "of_bucket", "of_table_features"] |
| |
| def class_is_oxm(cls): |
| """ |
| Return True if cls_name is an OXM object |
| """ |
| return _unified_by_name(cls).is_instanceof("of_oxm") |
| |
| def class_is_action(cls): |
| """ |
| Return True if cls_name is an action object |
| |
| Note that action_id is not an action object, though it has |
| the same header. It looks like an action header, but the type |
| is used to identify a kind of action, it does not indicate the |
| type of the object following. |
| """ |
| return _unified_by_name(cls).is_instanceof("of_action") |
| |
| def class_is_action_id(cls): |
| """ |
| Return True if cls_name is an action object |
| |
| Note that action_id is not an action object, though it has |
| the same header. It looks like an action header, but the type |
| is used to identify a kind of action, it does not indicate the |
| type of the object following. |
| """ |
| return _unified_by_name(cls).is_instanceof("of_action_id") |
| |
| def class_is_instruction(cls): |
| """ |
| Return True if cls_name is an instruction object |
| """ |
| return _unified_by_name(cls).is_instanceof("of_instruction") |
| |
| def class_is_meter_band(cls): |
| """ |
| Return True if cls_name is an instruction object |
| """ |
| return _unified_by_name(cls).is_instanceof("of_meter_band") |
| |
| def class_is_hello_elem(cls): |
| """ |
| Return True if cls_name is an instruction object |
| """ |
| return _unified_by_name(cls).is_instanceof("of_hello_elem") |
| |
| def class_is_queue_prop(cls): |
| """ |
| Return True if cls_name is a queue_prop object |
| """ |
| return _unified_by_name(cls).is_instanceof("of_queue_prop") |
| |
| def class_is_table_feature_prop(cls): |
| """ |
| Return True if cls_name is a queue_prop object |
| """ |
| return _unified_by_name(cls).is_instanceof("of_table_feature_prop") |
| |
| def class_is_stats_message(cls): |
| """ |
| Return True if cls_name is a message object based on info in unified |
| """ |
| u = _unified_by_name(cls) |
| return u.is_instanceof("of_stats_request") or u.ir_instanceof("of_stats_reply") |
| |
| def class_is_list(cls): |
| """ |
| Return True if cls_name is a list object |
| """ |
| return (cls.find("of_list_") == 0) |
| |
| def type_is_of_object(m_type): |
| """ |
| Return True if m_type is an OF object type |
| """ |
| # Remove _t from the type id and see if key for unified class |
| return _unified_by_name(re.sub(r'_t$', '', m_type)) != none_item |
| |
| @memoize |
| def lookup_ir_wiretype(oftype, version): |
| """ if of is a reference to an enum in ir, resolve it to the wiretype |
| declared in that enum. Else return oftype """ |
| enums = loxi_globals.ir[version].enums |
| enum = find(lambda e: e.name == oftype, enums) |
| if enum and 'wire_type' in enum.params: |
| return enum.params['wire_type'] |
| else: |
| return oftype |