Skip to content

Commit 3081217

Browse files
author
Hui Kang
committed
Check openflow(OF) rules on each hyperviors after binding lports
- use ovs-appctl to trace flow matches in the tables Signed-off-by: Hui Kang <[email protected]>
1 parent b8aee2f commit 3081217

File tree

4 files changed

+86
-8
lines changed

4 files changed

+86
-8
lines changed

rally_ovs/plugins/ovs/ovsclients.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,18 @@ def get_lswitch_info(info):
102102
return lswitches
103103

104104

105+
def get_of_in_port(of_port_list_raw, port_name_full):
106+
# NOTE (huikang): the max length of portname shown in ovs-ofctl show is 15
107+
port_name = port_name_full[0:15]
108+
lines = of_port_list_raw.splitlines()
109+
line = ""
110+
for line in lines:
111+
if (line.find(port_name) >= 0):
112+
break
113+
position = line.find("(")
114+
return line[:position]
115+
116+
105117
def set_colval_args(*col_values):
106118
args = []
107119
for entry in col_values:

rally_ovs/plugins/ovs/ovsclients_impl.py

Lines changed: 33 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,12 @@
1515
import pipes
1616
import sys
1717
import itertools
18-
import pipes
18+
import StringIO
19+
from rally.common import logging
1920
from rally_ovs.plugins.ovs.ovsclients import *
2021
from rally_ovs.plugins.ovs.utils import get_ssh_from_credential
2122

23+
LOG = logging.getLogger(__name__)
2224

2325
@configure("ssh")
2426
class SshClient(OvsClient):
@@ -167,7 +169,7 @@ def acl_del(self, lswitch):
167169

168170
def show(self, lswitch=None):
169171
params = [lswitch] if lswitch else []
170-
stdout = StringIO()
172+
stdout = StringIO.StringIO()
171173
self.run("show", args=params, stdout=stdout)
172174
output = stdout.getvalue()
173175

@@ -203,7 +205,7 @@ def set_sandbox(self, sandbox, install_method="sandbox"):
203205
self.sandbox = sandbox
204206
self.install_method = install_method
205207

206-
def run(self, cmd, opts=[], args=[]):
208+
def run(self, ovs_cmd, cmd, opts=[], args=[], stdout=sys.stdout):
207209
self.cmds = self.cmds or []
208210

209211
# TODO: tested with non batch_mode only for docker
@@ -213,16 +215,16 @@ def run(self, cmd, opts=[], args=[]):
213215
if self.sandbox and self.batch_mode == False:
214216
if self.install_method == "sandbox":
215217
self.cmds.append(". %s/sandbox.rc" % self.sandbox)
216-
cmd = itertools.chain(["ovs-vsctl"], opts, [cmd], args)
218+
cmd = itertools.chain([ovs_cmd], opts, [cmd], args)
217219
self.cmds.append(" ".join(cmd))
218220
elif self.install_method == "docker":
219-
self.cmds.append("sudo docker exec %s ovs-vsctl " % self.sandbox + cmd + " " + " ".join(args))
221+
self.cmds.append("sudo docker exec %s " % self.sandbox + ovs_cmd + cmd + " " + " ".join(args))
220222

221223
if self.batch_mode:
222224
return
223225

224226
self.ssh.run("\n".join(self.cmds),
225-
stdout=sys.stdout, stderr=sys.stderr)
227+
stdout=stdout, stderr=sys.stderr)
226228

227229
self.cmds = None
228230

@@ -242,13 +244,36 @@ def flush(self):
242244

243245
def add_port(self, bridge, port, may_exist=True):
244246
opts = ['--may-exist'] if may_exist else None
245-
self.run('add-port', opts, [bridge, port])
247+
self.run(" ovs-vsctl ", 'add-port', opts, [bridge, port])
246248

247249

248250
def db_set(self, table, record, *col_values):
249251
args = [table, record]
250252
args += set_colval_args(*col_values)
251-
self.run("set", args=args)
253+
self.run(" ovs-vsctl ", "set", args=args)
254+
255+
def of_check(self, bridge, port, mac_addr, may_exist=True):
256+
in_port = ""
257+
stdout = StringIO.StringIO()
258+
self.run(" ovs-ofctl ", "show br-int", stdout=stdout)
259+
show_br_int_output = stdout.getvalue()
260+
in_port = get_of_in_port(show_br_int_output, port)
261+
LOG.info("Check port: in_port: %s; mac: %s" % (in_port.strip(), mac_addr))
262+
appctl_cmd = " ofproto/trace br-int in_port=" + in_port.strip()
263+
appctl_cmd += ",dl_src=" + mac_addr
264+
appctl_cmd += ",dl_dst=00:00:00:00:00:03 -generate "
265+
self.run(" ovs-appctl ", appctl_cmd, stdout=stdout)
266+
of_trace_output = stdout.getvalue()
267+
268+
# NOTE(HuiKang): if success, the flow goes through table 1 to table
269+
# 32. However, since we use sandbox, table 32 seems not setup
270+
# correctly. Therefore after table 34, the datapath action is
271+
# Datapath actions: 100. If failed, the datapatch action is "drop"
272+
for line in of_trace_output.splitlines():
273+
if (line.find("Datapath actions") >= 0):
274+
if (line.find("drop") >= 0):
275+
return False
276+
return True
252277

253278
def create_client(self):
254279
print "********* call OvnNbctl.create_client"

rally_ovs/plugins/ovs/scenarios/ovn.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ def _create_lswitches(self, lswitch_create_args):
3838

3939
print("create lswitch")
4040
self.RESOURCE_NAME_FORMAT = "lswitch_XXXXXX_XXXXXX"
41+
self.port_mac = dict()
4142

4243
amount = lswitch_create_args.get("amount", 1)
4344
batch = lswitch_create_args.get("batch", amount)
@@ -124,6 +125,7 @@ def _create_lports(self, lswitch, lport_create_args = [], lport_amount=1):
124125
ovn_nbctl.enable_batch_mode()
125126

126127
base_mac = [i[:2] for i in self.task["uuid"].split('-')]
128+
base_mac[0] = str(hex(int(base_mac[0], 16) & 254))
127129
base_mac[3:] = ['00']*3
128130

129131

@@ -138,6 +140,7 @@ def _create_lports(self, lswitch, lport_create_args = [], lport_amount=1):
138140

139141
ovn_nbctl.lport_set_addresses(name, [mac, ip])
140142
ovn_nbctl.lport_set_port_security(name, mac)
143+
self.port_mac[name] = mac
141144

142145
lports.append(lport)
143146

@@ -251,6 +254,43 @@ def _create_networks(self, network_create_args):
251254
return lswitches
252255

253256

257+
@atomic.action_timer("ovn_network.of_check_port")
258+
def _of_check_ports(self, lports, sandboxes, port_bind_args):
259+
port_bind_args = port_bind_args or {}
260+
wait_up = port_bind_args.get("wait_up", False)
261+
262+
sandbox_num = len(sandboxes)
263+
lport_num = len(lports)
264+
lport_per_sandbox = (lport_num + sandbox_num - 1) / sandbox_num
265+
266+
LOG.info("Checking OF lports method: %s" % self.install_method)
267+
install_method = self.install_method
268+
269+
j = 0
270+
for i in range(0, len(lports), lport_per_sandbox):
271+
lport_slice = lports[i:i+lport_per_sandbox]
272+
273+
sandbox = sandboxes[j]["name"]
274+
farm = sandboxes[j]["farm"]
275+
ovs_vsctl = self.farm_clients(farm, "ovs-vsctl")
276+
ovs_vsctl.set_sandbox(sandbox, install_method)
277+
ovs_vsctl.enable_batch_mode()
278+
279+
for lport in lport_slice:
280+
port_name = lport["name"]
281+
282+
LOG.info("of check %s to %s on %s" % (port_name, sandbox, farm))
283+
284+
# check if OF rules installed correctly
285+
mac_addr = self.port_mac[port_name]
286+
of_check = ovs_vsctl.of_check('br-int', port_name, mac_addr)
287+
if of_check is False:
288+
LOG.info("Return false" )
289+
raise exceptions.NotFoundException(message="openflow rule")
290+
291+
ovs_vsctl.flush()
292+
j += 1
293+
254294

255295
@atomic.action_timer("ovn_network.bind_port")
256296
def _bind_ports(self, lports, sandboxes, port_bind_args):

rally_ovs/plugins/ovs/scenarios/ovn_network.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ def create_and_bind_ports(self,
4545
for lswitch in lswitches:
4646
lports = self._create_lports(lswitch, port_create_args, ports_per_network)
4747
self._bind_ports(lports, sandboxes, port_bind_args)
48+
self._of_check_ports(lports, sandboxes, port_bind_args)
4849

4950

5051
def bind_ports(self):

0 commit comments

Comments
 (0)