Skip to content

Commit

Permalink
pyloxi: generate instruction classes
Browse files Browse the repository at this point in the history
  • Loading branch information
rlane committed May 3, 2013
1 parent d367a24 commit e02314c
Show file tree
Hide file tree
Showing 5 changed files with 118 additions and 3 deletions.
7 changes: 4 additions & 3 deletions lang_python.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
message.py # Message classes
util.py # Utility functions
of11: ... # (code generation incomplete)
instruction.py # Instruction classes
of12: ... # (code generation incomplete)
oxm.py # OXM classes
of13: ... # (code generation incomplete)
Expand Down Expand Up @@ -75,9 +76,9 @@

modules = {
1: ["action", "common", "const", "message", "util"],
2: ["action", "common", "const", "message", "util"],
3: ["action", "common", "const", "message", "oxm", "util"],
4: ["action", "common", "const", "message", "meter_band", "oxm", "util"],
2: ["action", "common", "const", "instruction", "message", "util"],
3: ["action", "common", "const", "instruction", "message", "oxm", "util"],
4: ["action", "common", "const", "instruction", "message", "meter_band", "oxm", "util"],
}

def make_gen(name, version):
Expand Down
10 changes: 10 additions & 0 deletions py_gen/codegen.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@ def get_type_values(cls, version):
type_values['type'] = 1
elif utils.class_is_meter_band(cls):
type_values['type'] = util.constant_for_value(version, "ofp_meter_band_type", util.primary_wire_type(cls, version))
elif utils.class_is_instruction(cls):
type_values['type'] = util.constant_for_value(version, "ofp_instruction_type", util.primary_wire_type(cls, version))

return type_values

Expand All @@ -117,6 +119,8 @@ def build_ofclasses(version):
pyname = cls[7:]
elif utils.class_is_meter_band(cls):
pyname = cls[14:]
elif utils.class_is_instruction(cls):
pyname = cls[15:]
else:
pyname = cls[3:]

Expand Down Expand Up @@ -176,6 +180,7 @@ def generate_common(out, name, version):
ofclasses = [x for x in build_ofclasses(version)
if not utils.class_is_message(x.name)
and not utils.class_is_action(x.name)
and not utils.class_is_instruction(x.name)
and not utils.class_is_meter_band(x.name)
and not utils.class_is_oxm(x.name)
and not utils.class_is_list(x.name)]
Expand All @@ -193,6 +198,11 @@ def generate_const(out, name, version):
groups[group] = items
util.render_template(out, 'const.py', version=version, groups=groups)

def generate_instruction(out, name, version):
ofclasses = [x for x in build_ofclasses(version)
if utils.class_is_instruction(x.name)]
util.render_template(out, 'instruction.py', ofclasses=ofclasses, version=version)

def generate_message(out, name, version):
ofclasses = [x for x in build_ofclasses(version)
if utils.class_is_message(x.name)]
Expand Down
3 changes: 3 additions & 0 deletions py_gen/templates/init.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@
:: include('_autogen.py')

import action, common, const, message
:: if version >= 2:
import instruction
:: #endif
:: if version >= 3:
import oxm
:: #endif
Expand Down
68 changes: 68 additions & 0 deletions py_gen/templates/instruction.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
:: # 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.
::
:: import itertools
:: import of_g
:: include('_copyright.py')

:: include('_autogen.py')

import struct
import action
import const
import util
import loxi.generic_util
import loxi

def unpack_list(reader):
def deserializer(reader, typ):
parser = parsers.get(typ)
if not parser: raise loxi.ProtocolError("unknown instruction type %d" % typ)
return parser(reader)
return loxi.generic_util.unpack_list_tlv16(reader, deserializer)

class Instruction(object):
type = None # override in subclass
pass

:: for ofclass in ofclasses:
:: include('_ofclass.py', ofclass=ofclass, superclass="Instruction")

:: #endfor

parsers = {
:: sort_key = lambda x: x.type_members[0].value
:: msgtype_groups = itertools.groupby(sorted(ofclasses, key=sort_key), sort_key)
:: for (k, v) in msgtype_groups:
:: v = list(v)
:: if len(v) == 1:
${k} : ${v[0].pyname}.unpack,
:: else:
${k} : parse_${k[12:].lower()},
:: #endif
:: #endfor
}
33 changes: 33 additions & 0 deletions py_gen/tests/of13.py
Original file line number Diff line number Diff line change
Expand Up @@ -885,6 +885,39 @@ def test_oxm_ipv6_dst_pack(self):
])
self.assertEquals(expected, obj.pack())

class TestInstructions(unittest.TestCase):
def test_goto_table(self):
obj = ofp.instruction.goto_table(table_id=5)
buf = ''.join([
'\x00\x01', # type
'\x00\x08', # length
'\x05', # table_id
'\x00' * 3, # pad
])
test_serialization(obj, buf)

def test_write_metadata(self):
# TODO
pass

def test_write_actions(self):
# TODO
pass

def test_apply_actions(self):
# TODO
pass

def test_clear_actions(self):
# TODO
pass

def test_meter(self):
# TODO
pass

# TODO test experimenter instructions

class TestAllOF13(unittest.TestCase):
"""
Round-trips every class through serialization/deserialization.
Expand Down

0 comments on commit e02314c

Please sign in to comment.