Skip to content

Commit fa63d35

Browse files
tammeladavem330
authored andcommitted
selftests: tc-testing: rework namespaces and devices setup
As mentioned in the TC Workshop 0x17, our recent changes to tdc broke downstream CI systems like tuxsuite. The issue is the classic problem with rcu/workqueue objects where you can miss them if not enough wall time has passed. The latter is subjective to the system and kernel config, in my machine could be nanoseconds while in another could be microseconds or more. In order to make the suite deterministic, poll for the existence of the objects in a reasonable manner. Talking netlink directly is the the best solution in order to avoid paying the cost of multiple 'fork()' calls, so introduce a netlink based setup routine using pyroute2. We leave the iproute2 one as a fallback when pyroute2 is not available. Also rework the iproute2 side to mimic the netlink routine where it creates DEV0 as the peer of DEV1 and moves DEV1 into the net namespace. This way when the namespace is deleted DEV0 is also deleted automatically, leaving no margin for resource leaks. Another bonus of this change is that our setup time sped up by a factor of 2 when using netlink. Signed-off-by: Pedro Tammela <pctammela@mojatatu.com> Reviewed-by: Simon Horman <horms@kernel.org> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 9ffa01c commit fa63d35

File tree

1 file changed

+49
-20
lines changed
  • tools/testing/selftests/tc-testing/plugin-lib

1 file changed

+49
-20
lines changed

tools/testing/selftests/tc-testing/plugin-lib/nsPlugin.py

Lines changed: 49 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,14 @@
99

1010
from tdc_config import *
1111

12+
try:
13+
from pyroute2 import netns
14+
from pyroute2 import IPRoute
15+
netlink = True
16+
except ImportError:
17+
netlink = False
18+
print("!!! Consider installing pyroute2 !!!")
19+
1220
def prepare_suite(obj, test):
1321
original = obj.args.NAMES
1422

@@ -28,7 +36,10 @@ def prepare_suite(obj, test):
2836
shadow['DEV2'] = original['DEV2']
2937
obj.args.NAMES = shadow
3038

31-
obj._ns_create()
39+
if netlink == True:
40+
obj._nl_ns_create()
41+
else:
42+
obj._ns_create()
3243

3344
# Make sure the netns is visible in the fs
3445
while True:
@@ -67,7 +78,6 @@ def pre_case(self, caseinfo, test_skip):
6778
if test_skip:
6879
return
6980

70-
7181
def post_case(self):
7282
if self.args.verbose:
7383
print('{}.post_case'.format(self.sub_class))
@@ -119,34 +129,55 @@ def adjust_command(self, stage, command):
119129
print('adjust_command: return command [{}]'.format(command))
120130
return command
121131

122-
def _ports_create_cmds(self):
123-
cmds = []
132+
def _nl_ns_create(self):
133+
ns = self.args.NAMES["NS"];
134+
dev0 = self.args.NAMES["DEV0"];
135+
dev1 = self.args.NAMES["DEV1"];
136+
dummy = self.args.NAMES["DUMMY"];
124137

125-
cmds.append(self._replace_keywords('link add $DEV0 type veth peer name $DEV1'))
126-
cmds.append(self._replace_keywords('link set $DEV0 up'))
127-
cmds.append(self._replace_keywords('link add $DUMMY type dummy'))
128-
129-
return cmds
130-
131-
def _ports_create(self):
132-
self._exec_cmd_batched('pre', self._ports_create_cmds())
133-
134-
def _ports_destroy_cmd(self):
135-
return self._replace_keywords('link del $DEV0')
136-
137-
def _ports_destroy(self):
138-
self._exec_cmd('post', self._ports_destroy_cmd())
138+
if self.args.verbose:
139+
print('{}._nl_ns_create'.format(self.sub_class))
140+
141+
netns.create(ns)
142+
netns.pushns(newns=ns)
143+
with IPRoute() as ip:
144+
ip.link('add', ifname=dev1, kind='veth', peer={'ifname': dev0, 'net_ns_fd':'/proc/1/ns/net'})
145+
ip.link('add', ifname=dummy, kind='dummy')
146+
while True:
147+
try:
148+
dev1_idx = ip.link_lookup(ifname=dev1)[0]
149+
dummy_idx = ip.link_lookup(ifname=dummy)[0]
150+
ip.link('set', index=dev1_idx, state='up')
151+
ip.link('set', index=dummy_idx, state='up')
152+
break
153+
except:
154+
time.sleep(0.1)
155+
continue
156+
netns.popns()
157+
158+
with IPRoute() as ip:
159+
while True:
160+
try:
161+
dev0_idx = ip.link_lookup(ifname=dev0)[0]
162+
ip.link('set', index=dev0_idx, state='up')
163+
break
164+
except:
165+
time.sleep(0.1)
166+
continue
139167

140168
def _ns_create_cmds(self):
141169
cmds = []
142170

143171
ns = self.args.NAMES['NS']
144172

145173
cmds.append(self._replace_keywords('netns add {}'.format(ns)))
174+
cmds.append(self._replace_keywords('link add $DEV1 type veth peer name $DEV0'))
146175
cmds.append(self._replace_keywords('link set $DEV1 netns {}'.format(ns)))
176+
cmds.append(self._replace_keywords('link add $DUMMY type dummy'.format(ns)))
147177
cmds.append(self._replace_keywords('link set $DUMMY netns {}'.format(ns)))
148178
cmds.append(self._replace_keywords('netns exec {} $IP link set $DEV1 up'.format(ns)))
149179
cmds.append(self._replace_keywords('netns exec {} $IP link set $DUMMY up'.format(ns)))
180+
cmds.append(self._replace_keywords('link set $DEV0 up'.format(ns)))
150181

151182
if self.args.device:
152183
cmds.append(self._replace_keywords('link set $DEV2 netns {}'.format(ns)))
@@ -159,7 +190,6 @@ def _ns_create(self):
159190
Create the network namespace in which the tests will be run and set up
160191
the required network devices for it.
161192
'''
162-
self._ports_create()
163193
self._exec_cmd_batched('pre', self._ns_create_cmds())
164194

165195
def _ns_destroy_cmd(self):
@@ -171,7 +201,6 @@ def _ns_destroy(self):
171201
devices as well)
172202
'''
173203
self._exec_cmd('post', self._ns_destroy_cmd())
174-
self._ports_destroy()
175204

176205
@cached_property
177206
def _proc(self):

0 commit comments

Comments
 (0)