message: support setting fields with keyword arguments to the constructor
This enables creation of messages in a tree-like fashion.
The basic test module has been converted to the new API.
diff --git a/tests/basic.py b/tests/basic.py
index 0aefe73..43b7de4 100644
--- a/tests/basic.py
+++ b/tests/basic.py
@@ -53,8 +53,7 @@
Test echo response with short string data
"""
def runTest(self):
- request = message.echo_request()
- request.data = 'OpenFlow Will Rule The World'
+ request = message.echo_request(data='OpenFlow Will Rule The World')
response, pkt = self.controller.transact(request)
self.assertTrue(response is not None,
"Did not get echo reply (with data)")
@@ -203,9 +202,8 @@
(simple_eth_packet(pktlen=40), "tiny Ethernet packet")]:
logging.info("PKT OUT test with %s, port %s" % (opt, dp_port))
- msg = message.packet_out()
- msg.in_port = ofp.OFPP_NONE
- msg.data = str(outpkt)
+ msg = message.packet_out(in_port=ofp.OFPP_NONE,
+ data=str(outpkt))
act = action.action_output()
act.port = dp_port
msg.actions.add(act)
@@ -258,9 +256,8 @@
dp_ports = of_ports[0:num_ports]
logging.info("PKT OUT test with " + opt +
", ports " + str(dp_ports))
- msg = message.packet_out()
- msg.in_port = ofp.OFPP_NONE
- msg.data = str(outpkt)
+ msg = message.packet_out(in_port=ofp.OFPP_NONE,
+ data=str(outpkt))
act = action.action_output()
for i in range(0,num_ports):
act.port = dp_ports[i]
@@ -289,9 +286,8 @@
self.controller.message_send(request)
logging.info("Sending flow request")
- request = message.flow_stats_request()
- request.out_port = ofp.OFPP_NONE
- request.table_id = 0xff
+ request = message.flow_stats_request(out_port=ofp.OFPP_NONE,
+ table_id=0xff)
request.match.wildcards = 0 # ofp.OFPFW_ALL
response, pkt = self.controller.transact(request)
self.assertTrue(response is not None,
diff --git a/tools/munger/scripts/message_gen.py b/tools/munger/scripts/message_gen.py
index 1c627c1..34036d3 100644
--- a/tools/munger/scripts/message_gen.py
+++ b/tools/munger/scripts/message_gen.py
@@ -296,7 +296,7 @@
_p1('"""')
print
- _p1("def __init__(self):")
+ _p1("def __init__(self, **kwargs):")
if has_core_members:
_p2(parent + ".__init__(self)")
_p2("self.header = ofp_header()")
@@ -308,6 +308,11 @@
_p2('self.' + list_var + ' = ' + list_type + '()')
if has_string:
_p2('self.data = ""')
+ _p2('for (k, v) in kwargs.items():')
+ _p3('if hasattr(self, k):')
+ _p4('setattr(self, k, v)')
+ _p3('else:')
+ _p4('raise NameError("field %s does not exist in %s" % (k, self.__class__))')
print """
@@ -528,12 +533,17 @@
\"""
Wrapper class for --TYPE-- stats request message
\"""
- def __init__(self):
+ def __init__(self, **kwargs):
self.header = ofp_header()
ofp_stats_request.__init__(self)
ofp_--TYPE--_stats_request.__init__(self)
self.header.type = OFPT_STATS_REQUEST
self.type = --STATS_NAME--
+ for (k, v) in kwargs.items():
+ if hasattr(self, k):
+ setattr(self, k, v)
+ else:
+ raise NameError("field %s does not exist in %s" % (k, self.__class__))
def pack(self, assertstruct=True):
self.header.length = len(self)