blob: 7f002dfd49f3414068313727e50c6aef631ec315 [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
A R Karthick65c4d722016-07-18 14:20:17 -070012import requests
A R Karthickb7e80902016-05-17 09:38:31 -070013from Stats import Stats
14from OnosCtrl import OnosCtrl
15from DHCP import DHCPTest
16from EapTLS import TLSAuthTest
17from Channels import Channels, IgmpChannel
18from subscriberDb import SubscriberDB
19from threadPool import ThreadPool
A.R Karthick95d044e2016-06-10 18:44:36 -070020from portmaps import g_subscriber_port_map
A R Karthickb7e80902016-05-17 09:38:31 -070021from OltConfig import *
A R Karthickb7e80902016-05-17 09:38:31 -070022from 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 Karthick338268f2016-06-21 17:12:13 -070051 log.info('Subscriber %s, rx interface %s, uplink interface %s' %(name, self.rx_intf, self.tx_intf))
A.R Karthick95d044e2016-06-10 18:44:36 -070052 Channels.__init__(self, num, channel_start = channel_start,
A R Karthickb7e80902016-05-17 09:38:31 -070053 iface = self.rx_intf, iface_mcast = self.tx_intf, mcast_cb = mcast_cb)
54 self.name = name
55 self.service = service
56 self.service_map = {}
57 services = self.service.strip().split(' ')
58 for s in services:
59 self.service_map[s] = True
60 self.loginType = loginType
61 ##start streaming channels
62 self.join_map = {}
63 ##accumulated join recv stats
64 self.join_rx_stats = Stats()
A R Karthick338268f2016-06-21 17:12:13 -070065 self.recv_timeout = False
A R Karthickb7e80902016-05-17 09:38:31 -070066
67 def has_service(self, service):
68 if self.service_map.has_key(service):
69 return self.service_map[service]
70 if self.service_map.has_key(service.upper()):
71 return self.service_map[service.upper()]
72 return False
73
74 def channel_join_update(self, chan, join_time):
75 self.join_map[chan] = ( Stats(), Stats(), Stats(), Stats() )
76 self.channel_update(chan, self.STATS_JOIN, 1, t = join_time)
77
78 def channel_join(self, chan = 0, delay = 2):
79 '''Join a channel and create a send/recv stats map'''
80 if self.join_map.has_key(chan):
81 del self.join_map[chan]
82 self.delay = delay
83 chan, join_time = self.join(chan)
84 self.channel_join_update(chan, join_time)
85 return chan
86
87 def channel_join_next(self, delay = 2):
88 '''Joins the next channel leaving the last channel'''
89 if self.last_chan:
90 if self.join_map.has_key(self.last_chan):
91 del self.join_map[self.last_chan]
92 self.delay = delay
93 chan, join_time = self.join_next()
94 self.channel_join_update(chan, join_time)
95 return chan
96
97 def channel_jump(self, delay = 2):
98 '''Jumps randomly to the next channel leaving the last channel'''
99 if self.last_chan is not None:
100 if self.join_map.has_key(self.last_chan):
101 del self.join_map[self.last_chan]
102 self.delay = delay
103 chan, join_time = self.jump()
104 self.channel_join_update(chan, join_time)
105 return chan
106
107 def channel_leave(self, chan = 0):
108 if self.join_map.has_key(chan):
109 del self.join_map[chan]
110 self.leave(chan)
111
112 def channel_update(self, chan, stats_type, packets, t=0):
113 if type(chan) == type(0):
114 chan_list = (chan,)
115 else:
116 chan_list = chan
A.R Karthick95d044e2016-06-10 18:44:36 -0700117 for c in chan_list:
A R Karthickb7e80902016-05-17 09:38:31 -0700118 if self.join_map.has_key(c):
119 self.join_map[c][stats_type].update(packets = packets, t = t)
120
A R Karthick338268f2016-06-21 17:12:13 -0700121 def channel_receive(self, chan, cb = None, count = 1, timeout = 5):
122 log.info('Subscriber %s on port %s receiving from group %s, channel %d' %
123 (self.name, self.rx_intf, self.gaddr(chan), chan))
124 r = self.recv(chan, cb = cb, count = count, timeout = timeout)
125 if self.recv_timeout:
126 ##Negative test case is disabled for now
127 assert_equal(len(r), 0)
A R Karthickb7e80902016-05-17 09:38:31 -0700128
129 def recv_channel_cb(self, pkt):
130 ##First verify that we have received the packet for the joined instance
A R Karthick338268f2016-06-21 17:12:13 -0700131 log.info('Packet received for group %s, subscriber %s, port %s' %
132 (pkt[IP].dst, self.name, self.rx_intf))
133 if self.recv_timeout:
134 return
A R Karthickb7e80902016-05-17 09:38:31 -0700135 chan = self.caddr(pkt[IP].dst)
136 assert_equal(chan in self.join_map.keys(), True)
137 recv_time = monotonic.monotonic() * 1000000
138 join_time = self.join_map[chan][self.STATS_JOIN].start
139 delta = recv_time - join_time
140 self.join_rx_stats.update(packets=1, t = delta, usecs = True)
141 self.channel_update(chan, self.STATS_RX, 1, t = delta)
142 log.debug('Packet received in %.3f usecs for group %s after join' %(delta, pkt[IP].dst))
143
144class subscriber_pool:
145
146 def __init__(self, subscriber, test_cbs):
147 self.subscriber = subscriber
148 self.test_cbs = test_cbs
149
150 def pool_cb(self):
151 for cb in self.test_cbs:
152 if cb:
153 cb(self.subscriber)
A.R Karthick95d044e2016-06-10 18:44:36 -0700154
A R Karthickb7e80902016-05-17 09:38:31 -0700155class subscriber_exchange(unittest.TestCase):
156
A.R Karthick95d044e2016-06-10 18:44:36 -0700157 apps = ('org.opencord.aaa', 'org.onosproject.dhcp')
158 olt_apps = () #'org.opencord.cordmcast')
A R Karthickb7e80902016-05-17 09:38:31 -0700159 table_app = 'org.ciena.cordigmp'
160 dhcp_server_config = {
161 "ip": "10.1.11.50",
162 "mac": "ca:fe:ca:fe:ca:fe",
163 "subnet": "255.255.252.0",
164 "broadcast": "10.1.11.255",
165 "router": "10.1.8.1",
166 "domain": "8.8.8.8",
167 "ttl": "63",
168 "delay": "2",
169 "startip": "10.1.11.51",
170 "endip": "10.1.11.100"
171 }
172
173 aaa_loaded = False
174 test_path = os.path.dirname(os.path.realpath(__file__))
A R Karthick4b72d4b2016-06-15 11:09:17 -0700175 table_app_file = os.path.join(test_path, '..', 'apps/ciena-cordigmp-multitable-2.0-SNAPSHOT.oar')
176 app_file = os.path.join(test_path, '..', 'apps/ciena-cordigmp-2.0-SNAPSHOT.oar')
A R Karthickb7e80902016-05-17 09:38:31 -0700177 onos_config_path = os.path.join(test_path, '..', 'setup/onos-config')
A R Karthickb03cecd2016-07-27 10:27:55 -0700178 olt_conf_file = os.path.join(test_path, '..', 'setup/olt_config.json')
A R Karthickb7e80902016-05-17 09:38:31 -0700179 cpqd_path = os.path.join(test_path, '..', 'setup')
180 ovs_path = cpqd_path
A R Karthick65c4d722016-07-18 14:20:17 -0700181 test_services = ('IGMP', 'TRAFFIC')
A R Karthick338268f2016-06-21 17:12:13 -0700182 num_joins = 0
183 num_subscribers = 0
184 num_channels = 0
185 recv_timeout = False
A R Karthickb7e80902016-05-17 09:38:31 -0700186
187 @classmethod
A R Karthickd44cea12016-07-20 12:16:41 -0700188 def load_device_id(cls):
A R Karthickb03cecd2016-07-27 10:27:55 -0700189 '''Configure the device id'''
190 did = OnosCtrl.get_device_id()
A R Karthickd44cea12016-07-20 12:16:41 -0700191 #Set the default config
192 cls.device_id = did
193 cls.device_dict = { "devices" : {
194 "{}".format(did) : {
195 "basic" : {
196 "driver" : "pmc-olt"
197 }
198 }
199 },
200 }
201 return did
202
203 @classmethod
A R Karthickb7e80902016-05-17 09:38:31 -0700204 def setUpClass(cls):
205 '''Load the OLT config and activate relevant apps'''
A R Karthickd44cea12016-07-20 12:16:41 -0700206 did = cls.load_device_id()
A R Karthick4b72d4b2016-06-15 11:09:17 -0700207 network_cfg = { "devices" : {
A R Karthickd44cea12016-07-20 12:16:41 -0700208 "{}".format(did) : {
A R Karthick4b72d4b2016-06-15 11:09:17 -0700209 "basic" : {
210 "driver" : "pmc-olt"
211 }
212 }
213 },
214 }
A R Karthick4b72d4b2016-06-15 11:09:17 -0700215 ## Restart ONOS with cpqd driver config for OVS
216 cls.start_onos(network_cfg = network_cfg)
A R Karthickb7e80902016-05-17 09:38:31 -0700217 cls.install_app_table()
A R Karthickb7e80902016-05-17 09:38:31 -0700218 cls.olt = OltConfig(olt_conf_file = cls.olt_conf_file)
219 OnosCtrl.cord_olt_config(cls.olt.olt_device_data())
A R Karthickb03cecd2016-07-27 10:27:55 -0700220 cls.port_map, cls.port_list = cls.olt.olt_port_map()
A R Karthickb7e80902016-05-17 09:38:31 -0700221 cls.activate_apps(cls.apps + cls.olt_apps)
222
223 @classmethod
224 def tearDownClass(cls):
225 '''Deactivate the olt apps and restart OVS back'''
226 apps = cls.olt_apps + ( cls.table_app,)
227 for app in apps:
228 onos_ctrl = OnosCtrl(app)
229 onos_ctrl.deactivate()
230 cls.uninstall_app_table()
A R Karthicke0f33fa2016-06-22 13:36:02 -0700231 cls.start_onos(network_cfg = {})
A R Karthickb7e80902016-05-17 09:38:31 -0700232
233 @classmethod
234 def activate_apps(cls, apps):
235 for app in apps:
236 onos_ctrl = OnosCtrl(app)
237 status, _ = onos_ctrl.activate()
238 assert_equal(status, True)
239 time.sleep(2)
240
241 @classmethod
242 def install_app_table(cls):
243 ##Uninstall the existing app if any
244 OnosCtrl.uninstall_app(cls.table_app)
245 time.sleep(2)
246 log.info('Installing the multi table app %s for subscriber test' %(cls.table_app_file))
247 OnosCtrl.install_app(cls.table_app_file)
248 time.sleep(3)
249
250 @classmethod
251 def uninstall_app_table(cls):
252 ##Uninstall the table app on class exit
253 OnosCtrl.uninstall_app(cls.table_app)
254 time.sleep(2)
255 log.info('Installing back the cord igmp app %s for subscriber test on exit' %(cls.app_file))
256 OnosCtrl.install_app(cls.app_file)
257
258 @classmethod
259 def start_onos(cls, network_cfg = None):
A R Karthick65c4d722016-07-18 14:20:17 -0700260 v = bool(int(os.getenv('ONOS_RESTART_DISABLED', 0)))
261 if v:
262 log.info('ONOS restart is disabled. Skipping ONOS restart')
263 return
A R Karthickb7e80902016-05-17 09:38:31 -0700264 if network_cfg is None:
A R Karthick4b72d4b2016-06-15 11:09:17 -0700265 network_cfg = cls.device_dict
A R Karthickb7e80902016-05-17 09:38:31 -0700266
267 if type(network_cfg) is tuple:
268 res = []
269 for v in network_cfg:
270 res += v.items()
271 config = dict(res)
272 else:
273 config = network_cfg
274 log.info('Restarting ONOS with new network configuration')
A R Karthick338268f2016-06-21 17:12:13 -0700275 return cord_test_onos_restart(config = config)
A R Karthick4b72d4b2016-06-15 11:09:17 -0700276
277 @classmethod
278 def remove_onos_config(cls):
279 try:
280 os.unlink('{}/network-cfg.json'.format(cls.onos_config_path))
281 except: pass
A R Karthickb7e80902016-05-17 09:38:31 -0700282
283 @classmethod
284 def start_cpqd(cls, mac = '00:11:22:33:44:55'):
285 dpid = mac.replace(':', '')
286 cpqd_file = os.sep.join( (cls.cpqd_path, 'cpqd.sh') )
287 cpqd_cmd = '{} {}'.format(cpqd_file, dpid)
288 ret = os.system(cpqd_cmd)
289 assert_equal(ret, 0)
290 time.sleep(10)
A R Karthick4b72d4b2016-06-15 11:09:17 -0700291 device_id = 'of:{}{}'.format('0'*4, dpid)
292 return device_id
A R Karthickb7e80902016-05-17 09:38:31 -0700293
294 @classmethod
295 def start_ovs(cls):
A R Karthick4b72d4b2016-06-15 11:09:17 -0700296 ovs_file = os.sep.join( (cls.ovs_path, 'of-bridge.sh') )
A R Karthickb7e80902016-05-17 09:38:31 -0700297 ret = os.system(ovs_file)
298 assert_equal(ret, 0)
A R Karthick4b72d4b2016-06-15 11:09:17 -0700299 time.sleep(30)
A R Karthickb7e80902016-05-17 09:38:31 -0700300
301 def onos_aaa_load(self):
302 if self.aaa_loaded:
303 return
A.R Karthick95d044e2016-06-10 18:44:36 -0700304 aaa_dict = {'apps' : { 'org.onosproject.aaa' : { 'AAA' : { 'radiusSecret': 'radius_password',
A R Karthickb7e80902016-05-17 09:38:31 -0700305 'radiusIp': '172.17.0.2' } } } }
306 radius_ip = os.getenv('ONOS_AAA_IP') or '172.17.0.2'
307 aaa_dict['apps']['org.onosproject.aaa']['AAA']['radiusIp'] = radius_ip
308 self.onos_load_config('org.onosproject.aaa', aaa_dict)
309 self.aaa_loaded = True
310
311 def onos_dhcp_table_load(self, config = None):
312 dhcp_dict = {'apps' : { 'org.onosproject.dhcp' : { 'dhcp' : copy.copy(self.dhcp_server_config) } } }
313 dhcp_config = dhcp_dict['apps']['org.onosproject.dhcp']['dhcp']
314 if config:
315 for k in config.keys():
316 if dhcp_config.has_key(k):
317 dhcp_config[k] = config[k]
318 self.onos_load_config('org.onosproject.dhcp', dhcp_dict)
319
320 def onos_load_config(self, app, config):
321 status, code = OnosCtrl.config(config)
322 if status is False:
323 log.info('JSON config request for app %s returned status %d' %(app, code))
324 assert_equal(status, True)
325 time.sleep(2)
326
327 def dhcp_sndrcv(self, dhcp, update_seed = False):
328 cip, sip = dhcp.discover(update_seed = update_seed)
329 assert_not_equal(cip, None)
330 assert_not_equal(sip, None)
331 log.info('Got dhcp client IP %s from server %s for mac %s' %
332 (cip, sip, dhcp.get_mac(cip)[0]))
333 return cip,sip
334
335 def dhcp_request(self, subscriber, seed_ip = '10.10.10.1', update_seed = False):
336 config = {'startip':'10.10.10.20', 'endip':'10.10.10.200',
337 'ip':'10.10.10.2', 'mac': "ca:fe:ca:fe:ca:fe",
338 'subnet': '255.255.255.0', 'broadcast':'10.10.10.255', 'router':'10.10.10.1'}
339 self.onos_dhcp_table_load(config)
340 dhcp = DHCPTest(seed_ip = seed_ip, iface = subscriber.iface)
341 cip, sip = self.dhcp_sndrcv(dhcp, update_seed = update_seed)
342 return cip, sip
343
344 def recv_channel_cb(self, pkt):
345 ##First verify that we have received the packet for the joined instance
346 chan = self.subscriber.caddr(pkt[IP].dst)
347 assert_equal(chan in self.subscriber.join_map.keys(), True)
348 recv_time = monotonic.monotonic() * 1000000
349 join_time = self.subscriber.join_map[chan][self.subscriber.STATS_JOIN].start
350 delta = recv_time - join_time
351 self.subscriber.join_rx_stats.update(packets=1, t = delta, usecs = True)
352 self.subscriber.channel_update(chan, self.subscriber.STATS_RX, 1, t = delta)
353 log.debug('Packet received in %.3f usecs for group %s after join' %(delta, pkt[IP].dst))
354 self.test_status = True
355
A R Karthick65c4d722016-07-18 14:20:17 -0700356 def traffic_verify(self, subscriber):
357 if subscriber.has_service('TRAFFIC'):
358 url = 'http://www.google.com'
359 resp = requests.get(url)
360 self.test_status = resp.ok
361 if resp.ok == False:
362 log.info('Subscriber %s failed get from url %s with status code %d'
363 %(subscriber.name, url, resp.status_code))
364 else:
365 log.info('GET request from %s succeeded for subscriber %s'
366 %(url, subscriber.name))
367
A R Karthickb7e80902016-05-17 09:38:31 -0700368 def tls_verify(self, subscriber):
369 if subscriber.has_service('TLS'):
370 time.sleep(2)
A R Karthick4b72d4b2016-06-15 11:09:17 -0700371 tls = TLSAuthTest(intf = subscriber.rx_intf)
A R Karthickb7e80902016-05-17 09:38:31 -0700372 log.info('Running subscriber %s tls auth test' %subscriber.name)
373 tls.runTest()
374 self.test_status = True
375
376 def dhcp_verify(self, subscriber):
A R Karthick4b72d4b2016-06-15 11:09:17 -0700377 if subscriber.has_service('DHCP'):
378 cip, sip = self.dhcp_request(subscriber, update_seed = True)
379 log.info('Subscriber %s got client ip %s from server %s' %(subscriber.name, cip, sip))
380 subscriber.src_list = [cip]
381 self.test_status = True
382 else:
383 subscriber.src_list = ['10.10.10.{}'.format(subscriber.rx_port)]
384 self.test_status = True
A R Karthickb7e80902016-05-17 09:38:31 -0700385
386 def dhcp_jump_verify(self, subscriber):
A R Karthick4b72d4b2016-06-15 11:09:17 -0700387 if subscriber.has_service('DHCP'):
388 cip, sip = self.dhcp_request(subscriber, seed_ip = '10.10.200.1')
389 log.info('Subscriber %s got client ip %s from server %s' %(subscriber.name, cip, sip))
390 subscriber.src_list = [cip]
391 self.test_status = True
392 else:
393 subscriber.src_list = ['10.10.10.{}'.format(subscriber.rx_port)]
394 self.test_status = True
A R Karthickb7e80902016-05-17 09:38:31 -0700395
396 def dhcp_next_verify(self, subscriber):
A R Karthick4b72d4b2016-06-15 11:09:17 -0700397 if subscriber.has_service('DHCP'):
398 cip, sip = self.dhcp_request(subscriber, seed_ip = '10.10.150.1')
399 log.info('Subscriber %s got client ip %s from server %s' %(subscriber.name, cip, sip))
400 subscriber.src_list = [cip]
401 self.test_status = True
402 else:
403 subscriber.src_list = ['10.10.10.{}'.format(subscriber.rx_port)]
404 self.test_status = True
A R Karthickb7e80902016-05-17 09:38:31 -0700405
406 def igmp_verify(self, subscriber):
407 chan = 0
408 if subscriber.has_service('IGMP'):
A R Karthick338268f2016-06-21 17:12:13 -0700409 ##We wait for all the subscribers to join before triggering leaves
410 if subscriber.rx_port > 1:
411 time.sleep(5)
412 subscriber.channel_join(chan, delay = 0)
413 self.num_joins += 1
414 while self.num_joins < self.num_subscribers:
415 time.sleep(5)
416 log.info('All subscribers have joined the channel')
417 for i in range(10):
418 subscriber.channel_receive(chan, cb = subscriber.recv_channel_cb, count = 10)
A R Karthickb7e80902016-05-17 09:38:31 -0700419 log.info('Leaving channel %d for subscriber %s' %(chan, subscriber.name))
420 subscriber.channel_leave(chan)
A R Karthick338268f2016-06-21 17:12:13 -0700421 time.sleep(5)
A R Karthickb7e80902016-05-17 09:38:31 -0700422 log.info('Interface %s Join RX stats for subscriber %s, %s' %(subscriber.iface, subscriber.name,subscriber.join_rx_stats))
A R Karthick338268f2016-06-21 17:12:13 -0700423 #Should not receive packets for this subscriber
424 self.recv_timeout = True
425 subscriber.recv_timeout = True
426 subscriber.channel_receive(chan, cb = subscriber.recv_channel_cb, count = 10)
427 subscriber.recv_timeout = False
428 self.recv_timeout = False
429 log.info('Joining channel %d for subscriber %s' %(chan, subscriber.name))
430 subscriber.channel_join(chan, delay = 0)
A R Karthickb7e80902016-05-17 09:38:31 -0700431 self.test_status = True
432
433 def igmp_jump_verify(self, subscriber):
434 if subscriber.has_service('IGMP'):
435 for i in xrange(subscriber.num):
436 log.info('Subscriber %s jumping channel' %subscriber.name)
437 chan = subscriber.channel_jump(delay=0)
438 subscriber.channel_receive(chan, cb = subscriber.recv_channel_cb, count = 1)
439 log.info('Verified receive for channel %d, subscriber %s' %(chan, subscriber.name))
440 time.sleep(3)
441 log.info('Interface %s Jump RX stats for subscriber %s, %s' %(subscriber.iface, subscriber.name, subscriber.join_rx_stats))
442 self.test_status = True
443
444 def igmp_next_verify(self, subscriber):
445 if subscriber.has_service('IGMP'):
446 for i in xrange(subscriber.num):
447 if i:
448 chan = subscriber.channel_join_next(delay=0)
449 else:
450 chan = subscriber.channel_join(i, delay=0)
451 log.info('Joined next channel %d for subscriber %s' %(chan, subscriber.name))
452 subscriber.channel_receive(chan, cb = subscriber.recv_channel_cb, count=1)
453 log.info('Verified receive for channel %d, subscriber %s' %(chan, subscriber.name))
454 time.sleep(3)
455 log.info('Interface %s Join Next RX stats for subscriber %s, %s' %(subscriber.iface, subscriber.name, subscriber.join_rx_stats))
456 self.test_status = True
457
458 def generate_port_list(self, subscribers, channels):
459 return self.port_list[:subscribers]
460
461 def subscriber_load(self, create = True, num = 10, num_channels = 1, channel_start = 0, port_list = []):
462 '''Load the subscriber from the database'''
A R Karthick4b72d4b2016-06-15 11:09:17 -0700463 self.subscriber_db = SubscriberDB(create = create, services = self.test_services)
A R Karthickb7e80902016-05-17 09:38:31 -0700464 if create is True:
465 self.subscriber_db.generate(num)
466 self.subscriber_info = self.subscriber_db.read(num)
467 self.subscriber_list = []
468 if not port_list:
469 port_list = self.generate_port_list(num, num_channels)
470
471 index = 0
472 for info in self.subscriber_info:
A.R Karthick95d044e2016-06-10 18:44:36 -0700473 self.subscriber_list.append(Subscriber(name=info['Name'],
A R Karthickb7e80902016-05-17 09:38:31 -0700474 service=info['Service'],
475 port_map = self.port_map,
476 num=num_channels,
477 channel_start = channel_start,
478 tx_port = port_list[index][0],
479 rx_port = port_list[index][1]))
480 if num_channels > 1:
481 channel_start += num_channels
482 index += 1
483
484 #load the ssm list for all subscriber channels
485 igmpChannel = IgmpChannel()
486 ssm_groups = map(lambda sub: sub.channels, self.subscriber_list)
487 ssm_list = reduce(lambda ssm1, ssm2: ssm1+ssm2, ssm_groups)
488 igmpChannel.igmp_load_ssm_config(ssm_list)
489
A.R Karthick95d044e2016-06-10 18:44:36 -0700490 def subscriber_join_verify( self, num_subscribers = 10, num_channels = 1,
A R Karthickb7e80902016-05-17 09:38:31 -0700491 channel_start = 0, cbs = None, port_list = []):
492 self.test_status = False
493 self.num_subscribers = num_subscribers
494 self.subscriber_load(create = True, num = num_subscribers,
495 num_channels = num_channels, channel_start = channel_start, port_list = port_list)
496 self.onos_aaa_load()
497 self.thread_pool = ThreadPool(min(100, self.num_subscribers), queue_size=1, wait_timeout=1)
A R Karthick338268f2016-06-21 17:12:13 -0700498 chan_leave = False #for single channel, multiple subscribers
A R Karthickb7e80902016-05-17 09:38:31 -0700499 if cbs is None:
A R Karthick65c4d722016-07-18 14:20:17 -0700500 cbs = (self.tls_verify, self.dhcp_verify, self.igmp_verify, self.traffic_verify)
A R Karthick338268f2016-06-21 17:12:13 -0700501 chan_leave = True
A R Karthickb7e80902016-05-17 09:38:31 -0700502 for subscriber in self.subscriber_list:
503 subscriber.start()
504 pool_object = subscriber_pool(subscriber, cbs)
505 self.thread_pool.addTask(pool_object.pool_cb)
506 self.thread_pool.cleanUpThreads()
507 for subscriber in self.subscriber_list:
508 subscriber.stop()
A R Karthick338268f2016-06-21 17:12:13 -0700509 if chan_leave is True:
510 subscriber.channel_leave(0)
511 self.num_subscribers = 0
A R Karthickb7e80902016-05-17 09:38:31 -0700512 return self.test_status
513
514 def test_subscriber_join_recv(self):
ChetanGaonkerf9c2f8b2016-07-19 15:49:41 -0700515 """Test subscriber join and receive for channel surfing"""
A R Karthick338268f2016-06-21 17:12:13 -0700516 self.num_subscribers = 5
517 self.num_channels = 1
518 test_status = self.subscriber_join_verify(num_subscribers = self.num_subscribers,
519 num_channels = self.num_channels,
520 port_list = self.generate_port_list(self.num_subscribers,
521 self.num_channels))
A R Karthickb7e80902016-05-17 09:38:31 -0700522 assert_equal(test_status, True)
523
524 def test_subscriber_join_jump(self):
A.R Karthick95d044e2016-06-10 18:44:36 -0700525 """Test subscriber join and receive for channel surfing"""
A R Karthick338268f2016-06-21 17:12:13 -0700526 self.num_subscribers = 5
527 self.num_channels = 10
528 test_status = self.subscriber_join_verify(num_subscribers = self.num_subscribers,
529 num_channels = self.num_channels,
A R Karthick65c4d722016-07-18 14:20:17 -0700530 cbs = (self.tls_verify, self.dhcp_jump_verify,
531 self.igmp_jump_verify, self.traffic_verify),
A R Karthick338268f2016-06-21 17:12:13 -0700532 port_list = self.generate_port_list(self.num_subscribers,
533 self.num_channels))
A R Karthickb7e80902016-05-17 09:38:31 -0700534 assert_equal(test_status, True)
535
536 def test_subscriber_join_next(self):
ChetanGaonkerf9c2f8b2016-07-19 15:49:41 -0700537 """Test subscriber join next for channel surfing"""
A R Karthick338268f2016-06-21 17:12:13 -0700538 self.num_subscribers = 5
539 self.num_channels = 10
540 test_status = self.subscriber_join_verify(num_subscribers = self.num_subscribers,
541 num_channels = self.num_channels,
A R Karthick65c4d722016-07-18 14:20:17 -0700542 cbs = (self.tls_verify, self.dhcp_next_verify,
543 self.igmp_next_verify, self.traffic_verify),
A R Karthick338268f2016-06-21 17:12:13 -0700544 port_list = self.generate_port_list(self.num_subscribers,
545 self.num_channels))
A R Karthickb7e80902016-05-17 09:38:31 -0700546 assert_equal(test_status, True)