From 3f4bceecaa67a1f20c7ec6243d0c883ff815f531 Mon Sep 17 00:00:00 2001 From: IWAMOTO Toshihiro Date: Tue, 18 Apr 2017 15:04:06 +0900 Subject: [PATCH] of_interface: allow install_instructions to accept string actions Other than the of_interface methods, today we are forced to use ovs_lib methods to program flows, which call ovs-ofctl in turn. Let's make install_instructions accept string actions regardless of of_interface driver. Related-bug: #1672340 Change-Id: Ie2fdeab1f4ac567ef336abae03768e43f426311a --- .../agent/openflow/native/ofswitch.py | 11 +++++++++++ .../agent/openflow/ovs_ofctl/ofswitch.py | 7 +++++++ neutron/tests/functional/agent/test_ovs_flows.py | 16 ++++++++++++++++ 3 files changed, 34 insertions(+) diff --git a/neutron/plugins/ml2/drivers/openvswitch/agent/openflow/native/ofswitch.py b/neutron/plugins/ml2/drivers/openvswitch/agent/openflow/native/ofswitch.py index 5592f27de4d..788ba05cb0a 100644 --- a/neutron/plugins/ml2/drivers/openvswitch/agent/openflow/native/ofswitch.py +++ b/neutron/plugins/ml2/drivers/openvswitch/agent/openflow/native/ofswitch.py @@ -22,6 +22,9 @@ from oslo_utils import excutils from oslo_utils import timeutils import ryu.app.ofctl.api as ofctl_api import ryu.exception as ryu_exc +from ryu.lib import ofctl_string +from ryu.ofproto import ofproto_parser +import six from neutron._i18n import _, _LW from neutron.agent.common import ovs_lib @@ -192,6 +195,14 @@ class OpenFlowSwitchMixin(object): match=None, **match_kwargs): (dp, ofp, ofpp) = self._get_dp() match = self._match(ofp, ofpp, match, **match_kwargs) + if isinstance(instructions, six.string_types): + # NOTE: instructions must be str for the ofctl of_interface. + # After the ofctl driver is removed, a deprecation warning + # could be added here. + jsonlist = ofctl_string.ofp_instruction_from_str( + ofp, instructions) + instructions = ofproto_parser.ofp_instruction_from_jsondict( + dp, jsonlist) msg = ofpp.OFPFlowMod(dp, table_id=table_id, cookie=self.default_cookie, diff --git a/neutron/plugins/ml2/drivers/openvswitch/agent/openflow/ovs_ofctl/ofswitch.py b/neutron/plugins/ml2/drivers/openvswitch/agent/openflow/ovs_ofctl/ofswitch.py index 4a407a1a588..4cb0a1bf3df 100644 --- a/neutron/plugins/ml2/drivers/openvswitch/agent/openflow/ovs_ofctl/ofswitch.py +++ b/neutron/plugins/ml2/drivers/openvswitch/agent/openflow/ovs_ofctl/ofswitch.py @@ -75,6 +75,13 @@ class OpenFlowSwitchMixin(object): actions="drop", **self._conv_args(kwargs)) + def install_instructions(self, instructions, + table_id=0, priority=0, **kwargs): + self.add_flow(table=table_id, + priority=priority, + actions=instructions, + **self._conv_args(kwargs)) + def uninstall_flows(self, **kwargs): # NOTE(yamamoto): super() points to ovs_lib.OVSBridge. # See ovs_bridge.py how this class is actually used. diff --git a/neutron/tests/functional/agent/test_ovs_flows.py b/neutron/tests/functional/agent/test_ovs_flows.py index 5e0161f5248..7cb15fbc980 100644 --- a/neutron/tests/functional/agent/test_ovs_flows.py +++ b/neutron/tests/functional/agent/test_ovs_flows.py @@ -450,3 +450,19 @@ class OVSFlowTestCase(OVSAgentTestBase): trace = self._run_trace(self.tun_br.br_name, test_packet) self.assertEqual(" unchanged", trace["Final flow"]) self.assertIn("drop", trace["Datapath actions"]) + + def test_install_instructions_str(self): + kwargs = {'in_port': 345, 'vlan_tci': 0x1123} + dst_p = self.useFixture( + net_helpers.OVSPortFixture(self.br_tun, self.namespace)).port + dst_ofp = self.br_tun.get_port_ofport(dst_p.name) + self.br_tun.install_instructions("pop_vlan,output:%d" % dst_ofp, + priority=10, **kwargs) + trace = self._run_trace(self.br_tun.br_name, + "in_port=%(in_port)d,dl_src=12:34:56:78:aa:bb," + "dl_dst=24:12:56:78:aa:bb,dl_type=0x0800," + "nw_src=192.168.0.1,nw_dst=192.168.0.2," + "nw_proto=1,nw_tos=0,nw_ttl=128," + "icmp_type=8,icmp_code=0,vlan_tci=%(vlan_tci)d" + % kwargs) + self.assertIn("pop_vlan,", trace["Datapath actions"])