blob: c245bd0fa617a08e6a8f8c26856a6b59b7ace044 [file] [log] [blame]
A R Karthickb7e80902016-05-17 09:38:31 -07001import unittest
2from nose.tools import *
3from nose.twistedtools import reactor, deferred
4from twisted.internet import defer
5from scapy.all import *
6import time, monotonic
7import os, sys
8import tempfile
9import random
10import threading
11import json
12from Stats import Stats
13from OnosCtrl import OnosCtrl
14from DHCP import DHCPTest
15from EapTLS import TLSAuthTest
16from Channels import Channels, IgmpChannel
17from subscriberDb import SubscriberDB
18from threadPool import ThreadPool
A.R Karthick95d044e2016-06-10 18:44:36 -070019from portmaps import g_subscriber_port_map
A R Karthickb7e80902016-05-17 09:38:31 -070020from OltConfig import *
21from OnosFlowCtrl import get_mac
22from CordTestServer import cord_test_onos_restart
23
24log.setLevel('INFO')
25
26class Subscriber(Channels):
27 PORT_TX_DEFAULT = 2
28 PORT_RX_DEFAULT = 1
29 INTF_TX_DEFAULT = 'veth2'
30 INTF_RX_DEFAULT = 'veth0'
31 STATS_RX = 0
32 STATS_TX = 1
33 STATS_JOIN = 2
34 STATS_LEAVE = 3
35 SUBSCRIBER_SERVICES = 'DHCP IGMP TLS'
36 def __init__(self, name = 'sub', service = SUBSCRIBER_SERVICES, port_map = None,
37 num = 1, channel_start = 0,
38 tx_port = PORT_TX_DEFAULT, rx_port = PORT_RX_DEFAULT,
39 iface = INTF_RX_DEFAULT, iface_mcast = INTF_TX_DEFAULT,
40 mcast_cb = None, loginType = 'wireless'):
41 self.tx_port = tx_port
42 self.rx_port = rx_port
43 self.port_map = port_map or g_subscriber_port_map
44 try:
45 self.tx_intf = self.port_map[tx_port]
46 self.rx_intf = self.port_map[rx_port]
47 except:
48 self.tx_intf = self.port_map[self.PORT_TX_DEFAULT]
49 self.rx_intf = self.port_map[self.PORT_RX_DEFAULT]
50
A.R Karthick95d044e2016-06-10 18:44:36 -070051 Channels.__init__(self, num, channel_start = channel_start,
A R Karthickb7e80902016-05-17 09:38:31 -070052 iface = self.rx_intf, iface_mcast = self.tx_intf, mcast_cb = mcast_cb)
53 self.name = name
54 self.service = service
55 self.service_map = {}
56 services = self.service.strip().split(' ')
57 for s in services:
58 self.service_map[s] = True
59 self.loginType = loginType
60 ##start streaming channels
61 self.join_map = {}
62 ##accumulated join recv stats
63 self.join_rx_stats = Stats()
64
65 def has_service(self, service):
66 if self.service_map.has_key(service):
67 return self.service_map[service]
68 if self.service_map.has_key(service.upper()):
69 return self.service_map[service.upper()]
70 return False
71
72 def channel_join_update(self, chan, join_time):
73 self.join_map[chan] = ( Stats(), Stats(), Stats(), Stats() )
74 self.channel_update(chan, self.STATS_JOIN, 1, t = join_time)
75
76 def channel_join(self, chan = 0, delay = 2):
77 '''Join a channel and create a send/recv stats map'''
78 if self.join_map.has_key(chan):
79 del self.join_map[chan]
80 self.delay = delay
81 chan, join_time = self.join(chan)
82 self.channel_join_update(chan, join_time)
83 return chan
84
85 def channel_join_next(self, delay = 2):
86 '''Joins the next channel leaving the last channel'''
87 if self.last_chan:
88 if self.join_map.has_key(self.last_chan):
89 del self.join_map[self.last_chan]
90 self.delay = delay
91 chan, join_time = self.join_next()
92 self.channel_join_update(chan, join_time)
93 return chan
94
95 def channel_jump(self, delay = 2):
96 '''Jumps randomly to the next channel leaving the last channel'''
97 if self.last_chan is not None:
98 if self.join_map.has_key(self.last_chan):
99 del self.join_map[self.last_chan]
100 self.delay = delay
101 chan, join_time = self.jump()
102 self.channel_join_update(chan, join_time)
103 return chan
104
105 def channel_leave(self, chan = 0):
106 if self.join_map.has_key(chan):
107 del self.join_map[chan]
108 self.leave(chan)
109
110 def channel_update(self, chan, stats_type, packets, t=0):
111 if type(chan) == type(0):
112 chan_list = (chan,)
113 else:
114 chan_list = chan
A.R Karthick95d044e2016-06-10 18:44:36 -0700115 for c in chan_list:
A R Karthickb7e80902016-05-17 09:38:31 -0700116 if self.join_map.has_key(c):
117 self.join_map[c][stats_type].update(packets = packets, t = t)
118
119 def channel_receive(self, chan, cb = None, count = 1):
120 log.info('Subscriber %s receiving from group %s, channel %d' %(self.name, self.gaddr(chan), chan))
121 self.recv(chan, cb = cb, count = count)
122
123 def recv_channel_cb(self, pkt):
124 ##First verify that we have received the packet for the joined instance
125 log.debug('Packet received for group %s, subscriber %s' %(pkt[IP].dst, self.name))
126 chan = self.caddr(pkt[IP].dst)
127 assert_equal(chan in self.join_map.keys(), True)
128 recv_time = monotonic.monotonic() * 1000000
129 join_time = self.join_map[chan][self.STATS_JOIN].start
130 delta = recv_time - join_time
131 self.join_rx_stats.update(packets=1, t = delta, usecs = True)
132 self.channel_update(chan, self.STATS_RX, 1, t = delta)
133 log.debug('Packet received in %.3f usecs for group %s after join' %(delta, pkt[IP].dst))
134
135class subscriber_pool:
136
137 def __init__(self, subscriber, test_cbs):
138 self.subscriber = subscriber
139 self.test_cbs = test_cbs
140
141 def pool_cb(self):
142 for cb in self.test_cbs:
143 if cb:
144 cb(self.subscriber)
A.R Karthick95d044e2016-06-10 18:44:36 -0700145
A R Karthickb7e80902016-05-17 09:38:31 -0700146class subscriber_exchange(unittest.TestCase):
147
A.R Karthick95d044e2016-06-10 18:44:36 -0700148 apps = ('org.opencord.aaa', 'org.onosproject.dhcp')
149 olt_apps = () #'org.opencord.cordmcast')
A R Karthickb7e80902016-05-17 09:38:31 -0700150 table_app = 'org.ciena.cordigmp'
151 dhcp_server_config = {
152 "ip": "10.1.11.50",
153 "mac": "ca:fe:ca:fe:ca:fe",
154 "subnet": "255.255.252.0",
155 "broadcast": "10.1.11.255",
156 "router": "10.1.8.1",
157 "domain": "8.8.8.8",
158 "ttl": "63",
159 "delay": "2",
160 "startip": "10.1.11.51",
161 "endip": "10.1.11.100"
162 }
163
164 aaa_loaded = False
165 test_path = os.path.dirname(os.path.realpath(__file__))
A R Karthick4b72d4b2016-06-15 11:09:17 -0700166 table_app_file = os.path.join(test_path, '..', 'apps/ciena-cordigmp-multitable-2.0-SNAPSHOT.oar')
167 app_file = os.path.join(test_path, '..', 'apps/ciena-cordigmp-2.0-SNAPSHOT.oar')
A R Karthickb7e80902016-05-17 09:38:31 -0700168 onos_config_path = os.path.join(test_path, '..', 'setup/onos-config')
169 olt_conf_file = os.path.join(test_path, '..', 'setup/olt_config_multitable.json')
170 cpqd_path = os.path.join(test_path, '..', 'setup')
171 ovs_path = cpqd_path
172 device_id = 'of:' + get_mac('ovsbr0')
A R Karthick4b72d4b2016-06-15 11:09:17 -0700173 device_dict = { "devices" : {
A R Karthickb7e80902016-05-17 09:38:31 -0700174 "{}".format(device_id) : {
175 "basic" : {
A R Karthick4b72d4b2016-06-15 11:09:17 -0700176 "driver" : "pmc-olt"
A R Karthickb7e80902016-05-17 09:38:31 -0700177 }
178 }
179 },
180 }
A R Karthick4b72d4b2016-06-15 11:09:17 -0700181 test_services = ('IGMP',)
A R Karthickb7e80902016-05-17 09:38:31 -0700182
183 @classmethod
184 def setUpClass(cls):
185 '''Load the OLT config and activate relevant apps'''
A R Karthick4b72d4b2016-06-15 11:09:17 -0700186 device_id = cls.start_cpqd(mac = RandMAC()._fix())
187 network_cfg = { "devices" : {
188 "{}".format(device_id) : {
189 "basic" : {
190 "driver" : "pmc-olt"
191 }
192 }
193 },
194 }
195 cls.device_id = device_id
196 ## Restart ONOS with cpqd driver config for OVS
197 cls.start_onos(network_cfg = network_cfg)
A R Karthickb7e80902016-05-17 09:38:31 -0700198 cls.install_app_table()
A R Karthickb7e80902016-05-17 09:38:31 -0700199 cls.olt = OltConfig(olt_conf_file = cls.olt_conf_file)
200 OnosCtrl.cord_olt_config(cls.olt.olt_device_data())
201 cls.port_map, cls.port_list = cls.olt.olt_port_map_multi()
202 cls.activate_apps(cls.apps + cls.olt_apps)
203
204 @classmethod
205 def tearDownClass(cls):
206 '''Deactivate the olt apps and restart OVS back'''
207 apps = cls.olt_apps + ( cls.table_app,)
208 for app in apps:
209 onos_ctrl = OnosCtrl(app)
210 onos_ctrl.deactivate()
211 cls.uninstall_app_table()
A R Karthick4b72d4b2016-06-15 11:09:17 -0700212 cls.remove_onos_config()
A R Karthickb7e80902016-05-17 09:38:31 -0700213 cls.start_ovs()
214
215 @classmethod
216 def activate_apps(cls, apps):
217 for app in apps:
218 onos_ctrl = OnosCtrl(app)
219 status, _ = onos_ctrl.activate()
220 assert_equal(status, True)
221 time.sleep(2)
222
223 @classmethod
224 def install_app_table(cls):
225 ##Uninstall the existing app if any
226 OnosCtrl.uninstall_app(cls.table_app)
227 time.sleep(2)
228 log.info('Installing the multi table app %s for subscriber test' %(cls.table_app_file))
229 OnosCtrl.install_app(cls.table_app_file)
230 time.sleep(3)
231
232 @classmethod
233 def uninstall_app_table(cls):
234 ##Uninstall the table app on class exit
235 OnosCtrl.uninstall_app(cls.table_app)
236 time.sleep(2)
237 log.info('Installing back the cord igmp app %s for subscriber test on exit' %(cls.app_file))
238 OnosCtrl.install_app(cls.app_file)
239
240 @classmethod
241 def start_onos(cls, network_cfg = None):
242 if network_cfg is None:
A R Karthick4b72d4b2016-06-15 11:09:17 -0700243 network_cfg = cls.device_dict
A R Karthickb7e80902016-05-17 09:38:31 -0700244
245 if type(network_cfg) is tuple:
246 res = []
247 for v in network_cfg:
248 res += v.items()
249 config = dict(res)
250 else:
251 config = network_cfg
252 log.info('Restarting ONOS with new network configuration')
253 cfg = json.dumps(config)
254 with open('{}/network-cfg.json'.format(cls.onos_config_path), 'w') as f:
255 f.write(cfg)
256
A R Karthick4b72d4b2016-06-15 11:09:17 -0700257 try:
258 return cord_test_onos_restart()
259 except:
260 return False
261
262 @classmethod
263 def remove_onos_config(cls):
264 try:
265 os.unlink('{}/network-cfg.json'.format(cls.onos_config_path))
266 except: pass
A R Karthickb7e80902016-05-17 09:38:31 -0700267
268 @classmethod
269 def start_cpqd(cls, mac = '00:11:22:33:44:55'):
270 dpid = mac.replace(':', '')
271 cpqd_file = os.sep.join( (cls.cpqd_path, 'cpqd.sh') )
272 cpqd_cmd = '{} {}'.format(cpqd_file, dpid)
273 ret = os.system(cpqd_cmd)
274 assert_equal(ret, 0)
275 time.sleep(10)
A R Karthick4b72d4b2016-06-15 11:09:17 -0700276 device_id = 'of:{}{}'.format('0'*4, dpid)
277 return device_id
A R Karthickb7e80902016-05-17 09:38:31 -0700278
279 @classmethod
280 def start_ovs(cls):
A R Karthick4b72d4b2016-06-15 11:09:17 -0700281 ovs_file = os.sep.join( (cls.ovs_path, 'of-bridge.sh') )
A R Karthickb7e80902016-05-17 09:38:31 -0700282 ret = os.system(ovs_file)
283 assert_equal(ret, 0)
A R Karthick4b72d4b2016-06-15 11:09:17 -0700284 time.sleep(30)
A R Karthickb7e80902016-05-17 09:38:31 -0700285
286 def onos_aaa_load(self):
287 if self.aaa_loaded:
288 return
A.R Karthick95d044e2016-06-10 18:44:36 -0700289 aaa_dict = {'apps' : { 'org.onosproject.aaa' : { 'AAA' : { 'radiusSecret': 'radius_password',
A R Karthickb7e80902016-05-17 09:38:31 -0700290 'radiusIp': '172.17.0.2' } } } }
291 radius_ip = os.getenv('ONOS_AAA_IP') or '172.17.0.2'
292 aaa_dict['apps']['org.onosproject.aaa']['AAA']['radiusIp'] = radius_ip
293 self.onos_load_config('org.onosproject.aaa', aaa_dict)
294 self.aaa_loaded = True
295
296 def onos_dhcp_table_load(self, config = None):
297 dhcp_dict = {'apps' : { 'org.onosproject.dhcp' : { 'dhcp' : copy.copy(self.dhcp_server_config) } } }
298 dhcp_config = dhcp_dict['apps']['org.onosproject.dhcp']['dhcp']
299 if config:
300 for k in config.keys():
301 if dhcp_config.has_key(k):
302 dhcp_config[k] = config[k]
303 self.onos_load_config('org.onosproject.dhcp', dhcp_dict)
304
305 def onos_load_config(self, app, config):
306 status, code = OnosCtrl.config(config)
307 if status is False:
308 log.info('JSON config request for app %s returned status %d' %(app, code))
309 assert_equal(status, True)
310 time.sleep(2)
311
312 def dhcp_sndrcv(self, dhcp, update_seed = False):
313 cip, sip = dhcp.discover(update_seed = update_seed)
314 assert_not_equal(cip, None)
315 assert_not_equal(sip, None)
316 log.info('Got dhcp client IP %s from server %s for mac %s' %
317 (cip, sip, dhcp.get_mac(cip)[0]))
318 return cip,sip
319
320 def dhcp_request(self, subscriber, seed_ip = '10.10.10.1', update_seed = False):
321 config = {'startip':'10.10.10.20', 'endip':'10.10.10.200',
322 'ip':'10.10.10.2', 'mac': "ca:fe:ca:fe:ca:fe",
323 'subnet': '255.255.255.0', 'broadcast':'10.10.10.255', 'router':'10.10.10.1'}
324 self.onos_dhcp_table_load(config)
325 dhcp = DHCPTest(seed_ip = seed_ip, iface = subscriber.iface)
326 cip, sip = self.dhcp_sndrcv(dhcp, update_seed = update_seed)
327 return cip, sip
328
329 def recv_channel_cb(self, pkt):
330 ##First verify that we have received the packet for the joined instance
331 chan = self.subscriber.caddr(pkt[IP].dst)
332 assert_equal(chan in self.subscriber.join_map.keys(), True)
333 recv_time = monotonic.monotonic() * 1000000
334 join_time = self.subscriber.join_map[chan][self.subscriber.STATS_JOIN].start
335 delta = recv_time - join_time
336 self.subscriber.join_rx_stats.update(packets=1, t = delta, usecs = True)
337 self.subscriber.channel_update(chan, self.subscriber.STATS_RX, 1, t = delta)
338 log.debug('Packet received in %.3f usecs for group %s after join' %(delta, pkt[IP].dst))
339 self.test_status = True
340
341 def tls_verify(self, subscriber):
342 if subscriber.has_service('TLS'):
343 time.sleep(2)
A R Karthick4b72d4b2016-06-15 11:09:17 -0700344 tls = TLSAuthTest(intf = subscriber.rx_intf)
A R Karthickb7e80902016-05-17 09:38:31 -0700345 log.info('Running subscriber %s tls auth test' %subscriber.name)
346 tls.runTest()
347 self.test_status = True
348
349 def dhcp_verify(self, subscriber):
A R Karthick4b72d4b2016-06-15 11:09:17 -0700350 if subscriber.has_service('DHCP'):
351 cip, sip = self.dhcp_request(subscriber, update_seed = True)
352 log.info('Subscriber %s got client ip %s from server %s' %(subscriber.name, cip, sip))
353 subscriber.src_list = [cip]
354 self.test_status = True
355 else:
356 subscriber.src_list = ['10.10.10.{}'.format(subscriber.rx_port)]
357 self.test_status = True
A R Karthickb7e80902016-05-17 09:38:31 -0700358
359 def dhcp_jump_verify(self, subscriber):
A R Karthick4b72d4b2016-06-15 11:09:17 -0700360 if subscriber.has_service('DHCP'):
361 cip, sip = self.dhcp_request(subscriber, seed_ip = '10.10.200.1')
362 log.info('Subscriber %s got client ip %s from server %s' %(subscriber.name, cip, sip))
363 subscriber.src_list = [cip]
364 self.test_status = True
365 else:
366 subscriber.src_list = ['10.10.10.{}'.format(subscriber.rx_port)]
367 self.test_status = True
A R Karthickb7e80902016-05-17 09:38:31 -0700368
369 def dhcp_next_verify(self, subscriber):
A R Karthick4b72d4b2016-06-15 11:09:17 -0700370 if subscriber.has_service('DHCP'):
371 cip, sip = self.dhcp_request(subscriber, seed_ip = '10.10.150.1')
372 log.info('Subscriber %s got client ip %s from server %s' %(subscriber.name, cip, sip))
373 subscriber.src_list = [cip]
374 self.test_status = True
375 else:
376 subscriber.src_list = ['10.10.10.{}'.format(subscriber.rx_port)]
377 self.test_status = True
A R Karthickb7e80902016-05-17 09:38:31 -0700378
379 def igmp_verify(self, subscriber):
380 chan = 0
381 if subscriber.has_service('IGMP'):
382 for i in range(5):
383 log.info('Joining channel %d for subscriber %s' %(chan, subscriber.name))
384 subscriber.channel_join(chan, delay = 0)
385 subscriber.channel_receive(chan, cb = subscriber.recv_channel_cb, count = 1)
386 log.info('Leaving channel %d for subscriber %s' %(chan, subscriber.name))
387 subscriber.channel_leave(chan)
388 time.sleep(3)
389 log.info('Interface %s Join RX stats for subscriber %s, %s' %(subscriber.iface, subscriber.name,subscriber.join_rx_stats))
390 self.test_status = True
391
392 def igmp_jump_verify(self, subscriber):
393 if subscriber.has_service('IGMP'):
394 for i in xrange(subscriber.num):
395 log.info('Subscriber %s jumping channel' %subscriber.name)
396 chan = subscriber.channel_jump(delay=0)
397 subscriber.channel_receive(chan, cb = subscriber.recv_channel_cb, count = 1)
398 log.info('Verified receive for channel %d, subscriber %s' %(chan, subscriber.name))
399 time.sleep(3)
400 log.info('Interface %s Jump RX stats for subscriber %s, %s' %(subscriber.iface, subscriber.name, subscriber.join_rx_stats))
401 self.test_status = True
402
403 def igmp_next_verify(self, subscriber):
404 if subscriber.has_service('IGMP'):
405 for i in xrange(subscriber.num):
406 if i:
407 chan = subscriber.channel_join_next(delay=0)
408 else:
409 chan = subscriber.channel_join(i, delay=0)
410 log.info('Joined next channel %d for subscriber %s' %(chan, subscriber.name))
411 subscriber.channel_receive(chan, cb = subscriber.recv_channel_cb, count=1)
412 log.info('Verified receive for channel %d, subscriber %s' %(chan, subscriber.name))
413 time.sleep(3)
414 log.info('Interface %s Join Next RX stats for subscriber %s, %s' %(subscriber.iface, subscriber.name, subscriber.join_rx_stats))
415 self.test_status = True
416
417 def generate_port_list(self, subscribers, channels):
418 return self.port_list[:subscribers]
419
420 def subscriber_load(self, create = True, num = 10, num_channels = 1, channel_start = 0, port_list = []):
421 '''Load the subscriber from the database'''
A R Karthick4b72d4b2016-06-15 11:09:17 -0700422 self.subscriber_db = SubscriberDB(create = create, services = self.test_services)
A R Karthickb7e80902016-05-17 09:38:31 -0700423 if create is True:
424 self.subscriber_db.generate(num)
425 self.subscriber_info = self.subscriber_db.read(num)
426 self.subscriber_list = []
427 if not port_list:
428 port_list = self.generate_port_list(num, num_channels)
429
430 index = 0
431 for info in self.subscriber_info:
A.R Karthick95d044e2016-06-10 18:44:36 -0700432 self.subscriber_list.append(Subscriber(name=info['Name'],
A R Karthickb7e80902016-05-17 09:38:31 -0700433 service=info['Service'],
434 port_map = self.port_map,
435 num=num_channels,
436 channel_start = channel_start,
437 tx_port = port_list[index][0],
438 rx_port = port_list[index][1]))
439 if num_channels > 1:
440 channel_start += num_channels
441 index += 1
442
443 #load the ssm list for all subscriber channels
444 igmpChannel = IgmpChannel()
445 ssm_groups = map(lambda sub: sub.channels, self.subscriber_list)
446 ssm_list = reduce(lambda ssm1, ssm2: ssm1+ssm2, ssm_groups)
447 igmpChannel.igmp_load_ssm_config(ssm_list)
448
A.R Karthick95d044e2016-06-10 18:44:36 -0700449 def subscriber_join_verify( self, num_subscribers = 10, num_channels = 1,
A R Karthickb7e80902016-05-17 09:38:31 -0700450 channel_start = 0, cbs = None, port_list = []):
451 self.test_status = False
452 self.num_subscribers = num_subscribers
453 self.subscriber_load(create = True, num = num_subscribers,
454 num_channels = num_channels, channel_start = channel_start, port_list = port_list)
455 self.onos_aaa_load()
456 self.thread_pool = ThreadPool(min(100, self.num_subscribers), queue_size=1, wait_timeout=1)
457 if cbs is None:
458 cbs = (self.tls_verify, self.dhcp_verify, self.igmp_verify)
459 for subscriber in self.subscriber_list:
460 subscriber.start()
461 pool_object = subscriber_pool(subscriber, cbs)
462 self.thread_pool.addTask(pool_object.pool_cb)
463 self.thread_pool.cleanUpThreads()
464 for subscriber in self.subscriber_list:
465 subscriber.stop()
466 return self.test_status
467
468 def test_subscriber_join_recv(self):
469 """Test subscriber join and receive"""
470 num_subscribers = 5
471 num_channels = 1
A.R Karthick95d044e2016-06-10 18:44:36 -0700472 test_status = self.subscriber_join_verify(num_subscribers = num_subscribers,
A R Karthickb7e80902016-05-17 09:38:31 -0700473 num_channels = num_channels,
474 port_list = self.generate_port_list(num_subscribers, num_channels))
475 assert_equal(test_status, True)
476
477 def test_subscriber_join_jump(self):
A.R Karthick95d044e2016-06-10 18:44:36 -0700478 """Test subscriber join and receive for channel surfing"""
A R Karthickb7e80902016-05-17 09:38:31 -0700479 num_subscribers = 5
A R Karthick4b72d4b2016-06-15 11:09:17 -0700480 num_channels = 5
A.R Karthick95d044e2016-06-10 18:44:36 -0700481 test_status = self.subscriber_join_verify(num_subscribers = num_subscribers,
A R Karthickb7e80902016-05-17 09:38:31 -0700482 num_channels = num_channels,
483 cbs = (self.tls_verify, self.dhcp_jump_verify, self.igmp_jump_verify),
484 port_list = self.generate_port_list(num_subscribers, num_channels))
485 assert_equal(test_status, True)
486
487 def test_subscriber_join_next(self):
488 """Test subscriber join next for channels"""
489 num_subscribers = 5
A R Karthick4b72d4b2016-06-15 11:09:17 -0700490 num_channels = 5
A.R Karthick95d044e2016-06-10 18:44:36 -0700491 test_status = self.subscriber_join_verify(num_subscribers = num_subscribers,
A R Karthickb7e80902016-05-17 09:38:31 -0700492 num_channels = num_channels,
493 cbs = (self.tls_verify, self.dhcp_next_verify, self.igmp_next_verify),
494 port_list = self.generate_port_list(num_subscribers, num_channels))
495 assert_equal(test_status, True)