blob: 7b3227b68f5f6bd78c00e572b290bfd55d60b3cd [file] [log] [blame]
Chetan Gaonker25470972016-02-26 08:52:15 -08001import unittest
2from nose.tools import *
3from nose.twistedtools import reactor, deferred
4from twisted.internet import defer
5from scapy.all import *
Chetan Gaonkereb2b24b2016-03-01 14:04:45 -08006import time, monotonic
Chetan Gaonker25470972016-02-26 08:52:15 -08007import os, sys
Chetan Gaonkereb2b24b2016-03-01 14:04:45 -08008import tempfile
Chetan Gaonkereb2b24b2016-03-01 14:04:45 -08009import random
10import threading
Chetan Gaonkere88c95c2016-03-02 05:21:47 -080011from IGMP import *
Chetan Gaonkereb2b24b2016-03-01 14:04:45 -080012from McastTraffic import *
13from Stats import Stats
Chetan Gaonker4a25e2b2016-03-04 14:45:15 -080014from OnosCtrl import OnosCtrl
Chetan Gaonker4eb12072016-03-28 15:04:15 -070015from Channels import IgmpChannel
Chetan Gaonkereb2b24b2016-03-01 14:04:45 -080016log.setLevel('INFO')
Chetan Gaonker25470972016-02-26 08:52:15 -080017
18class IGMPTestState:
19
20 def __init__(self, groups = [], df = None, state = 0):
21 self.df = df
22 self.state = state
23 self.counter = 0
24 self.groups = groups
25 self.group_map = {} ##create a send/recv count map
26 for g in groups:
Chetan Gaonkereb2b24b2016-03-01 14:04:45 -080027 self.group_map[g] = (Stats(), Stats())
28
29 def update(self, group, tx = 0, rx = 0, t = 0):
30 self.counter += 1
Chetan Gaonker25470972016-02-26 08:52:15 -080031 index = 0 if rx == 0 else 1
32 v = tx if rx == 0 else rx
33 if self.group_map.has_key(group):
Chetan Gaonkereb2b24b2016-03-01 14:04:45 -080034 self.group_map[group][index].update(packets = v, t = t)
Chetan Gaonker25470972016-02-26 08:52:15 -080035
36 def update_state(self):
37 self.state = self.state ^ 1
Chetan Gaonker25470972016-02-26 08:52:15 -080038
39class igmp_exchange(unittest.TestCase):
Chetan Gaonkereb2b24b2016-03-01 14:04:45 -080040
Chetan Gaonker8bbc4d52016-03-29 16:59:45 -070041 V_INF1 = 'veth0'
42 V_INF2 = 'veth1'
43 MGROUP1 = '239.1.2.3'
44 MGROUP2 = '239.2.2.3'
45 MMACGROUP1 = "01:00:5e:01:02:03"
46 MMACGROUP2 = "01:00:5e:02:02:03"
47 IGMP_DST_MAC = "01:00:5e:00:01:01"
48 IGMP_SRC_MAC = "5a:e1:ac:ec:4d:a1"
49 IP_SRC = '1.2.3.4'
50 IP_DST = '224.0.1.1'
51 igmp_eth = Ether(dst = IGMP_DST_MAC, src = IGMP_SRC_MAC, type = ETH_P_IP)
52 igmp_ip = IP(dst = IP_DST, src = IP_SRC)
Chetan Gaonkereb2b24b2016-03-01 14:04:45 -080053 IGMP_TEST_TIMEOUT = 5
Chetan Gaonker1f7c3f82016-03-08 12:17:37 -080054 IGMP_QUERY_TIMEOUT = 30
Chetan Gaonkereb2b24b2016-03-01 14:04:45 -080055 MCAST_TRAFFIC_TIMEOUT = 10
Chetan Gaonker4eb12072016-03-28 15:04:15 -070056 PORT_TX_DEFAULT = 2
57 PORT_RX_DEFAULT = 1
Chetan Gaonkereb2b24b2016-03-01 14:04:45 -080058 max_packets = 100
Chetan Gaonker4a25e2b2016-03-04 14:45:15 -080059 app = 'org.onosproject.igmp'
60
61 def setUp(self):
62 ''' Activate the dhcp app'''
63 self.onos_ctrl = OnosCtrl(self.app)
64 status, _ = self.onos_ctrl.activate()
65 assert_equal(status, True)
Chetan Gaonker8bbc4d52016-03-29 16:59:45 -070066 time.sleep(2)
Chetan Gaonker4eb12072016-03-28 15:04:15 -070067 self.igmp_channel = IgmpChannel()
Chetan Gaonker4a25e2b2016-03-04 14:45:15 -080068
69 def teardown(self):
70 '''Deactivate the dhcp app'''
71 self.onos_ctrl.deactivate()
72
73 def onos_load_config(self, config):
74 status, code = self.onos_ctrl.config(config)
75 if status is False:
76 log.info('JSON request returned status %d' %code)
77 assert_equal(status, True)
78 time.sleep(2)
79
Chetan Gaonkereb2b24b2016-03-01 14:04:45 -080080 def onos_ssm_table_load(self, groups, src_list):
81 ssm_dict = {'apps' : { 'org.onosproject.igmp' : { 'ssmTranslate' : [] } } }
82 ssm_xlate_list = ssm_dict['apps']['org.onosproject.igmp']['ssmTranslate']
83 for g in groups:
84 for s in src_list:
85 d = {}
Chetan Gaonker8bbc4d52016-03-29 16:59:45 -070086 d['source'] = s or '0.0.0.0'
Chetan Gaonkereb2b24b2016-03-01 14:04:45 -080087 d['group'] = g
88 ssm_xlate_list.append(d)
Chetan Gaonker4a25e2b2016-03-04 14:45:15 -080089 self.onos_load_config(ssm_dict)
Chetan Gaonker4eb12072016-03-28 15:04:15 -070090 cord_port_map = {}
91 for g in groups:
92 cord_port_map[g] = (self.PORT_TX_DEFAULT, self.PORT_RX_DEFAULT)
93 self.igmp_channel.cord_port_table_load(cord_port_map)
Chetan Gaonker5a5204e2016-03-02 01:35:13 -080094 time.sleep(2)
Chetan Gaonkereb2b24b2016-03-01 14:04:45 -080095
96 def igmp_verify_join(self, igmpStateList):
97 sendState, recvState = igmpStateList
Chetan Gaonker25470972016-02-26 08:52:15 -080098 ## check if the send is received for the groups
Chetan Gaonkereb2b24b2016-03-01 14:04:45 -080099 for g in sendState.groups:
100 tx_stats = sendState.group_map[g][0]
101 tx = tx_stats.count
Chetan Gaonker25470972016-02-26 08:52:15 -0800102 assert_greater(tx, 0)
Chetan Gaonkereb2b24b2016-03-01 14:04:45 -0800103 rx_stats = recvState.group_map[g][1]
104 rx = rx_stats.count
105 assert_greater(rx, 0)
106 log.info('Receive stats %s for group %s' %(rx_stats, g))
107
108 log.info('IGMP test verification success')
Chetan Gaonker25470972016-02-26 08:52:15 -0800109
Chetan Gaonkereb2b24b2016-03-01 14:04:45 -0800110 def igmp_verify_leave(self, igmpStateList, leave_groups):
111 sendState, recvState = igmpStateList[0], igmpStateList[1]
112 ## check if the send is received for the groups
113 for g in sendState.groups:
114 tx_stats = sendState.group_map[g][0]
115 rx_stats = recvState.group_map[g][1]
116 tx = tx_stats.count
117 rx = rx_stats.count
118 assert_greater(tx, 0)
119 if g not in leave_groups:
120 log.info('Received %d packets for group %s' %(rx, g))
121 for g in leave_groups:
122 rx = recvState.group_map[g][1].count
123 assert_equal(rx, 0)
124
125 log.info('IGMP test verification success')
Chetan Gaonker25470972016-02-26 08:52:15 -0800126
Chetan Gaonkereb2b24b2016-03-01 14:04:45 -0800127 def mcast_traffic_timer(self):
128 self.mcastTraffic.stopReceives()
129
130 def send_mcast_cb(self, send_state):
131 for g in send_state.groups:
132 send_state.update(g, tx = 1)
Chetan Gaonker25470972016-02-26 08:52:15 -0800133 return 0
134
Chetan Gaonkereb2b24b2016-03-01 14:04:45 -0800135 ##Runs in the context of twisted reactor thread
Chetan Gaonker25470972016-02-26 08:52:15 -0800136 def igmp_recv(self, igmpState, iface = 'veth0'):
Chetan Gaonkereb2b24b2016-03-01 14:04:45 -0800137 p = self.recv_socket.recv()
138 send_time = float(p.payload.load)
139 recv_time = monotonic.monotonic()
140 #log.info( 'Recv in %.6f secs' %(recv_time - send_time))
141 igmpState.update(p.dst, rx = 1, t = recv_time - send_time)
Chetan Gaonker25470972016-02-26 08:52:15 -0800142 return 0
143
Chetan Gaonker8bbc4d52016-03-29 16:59:45 -0700144 def send_igmp_join(self, groups, src_list = ['1.2.3.4'], ip_pkt = None, iface = 'veth0', delay = 2):
Chetan Gaonkereb2b24b2016-03-01 14:04:45 -0800145 self.onos_ssm_table_load(groups, src_list)
Chetan Gaonker5a5204e2016-03-02 01:35:13 -0800146 igmp = IGMPv3(type = IGMP_TYPE_V3_MEMBERSHIP_REPORT, max_resp_code=30,
Chetan Gaonker8bbc4d52016-03-29 16:59:45 -0700147 gaddr=self.IP_DST)
Chetan Gaonkereb2b24b2016-03-01 14:04:45 -0800148 for g in groups:
Chetan Gaonker5a5204e2016-03-02 01:35:13 -0800149 gr = IGMPv3gr(rtype=IGMP_V3_GR_TYPE_EXCLUDE, mcaddr=g)
150 gr.sources = src_list
151 igmp.grps.append(gr)
Chetan Gaonker8bbc4d52016-03-29 16:59:45 -0700152 if ip_pkt is None:
153 ip_pkt = self.igmp_eth/self.igmp_ip
154 pkt = ip_pkt/igmp
Chetan Gaonker5a5204e2016-03-02 01:35:13 -0800155 IGMPv3.fixup(pkt)
156 sendp(pkt, iface=iface)
Chetan Gaonkereb2b24b2016-03-01 14:04:45 -0800157 if delay != 0:
158 time.sleep(delay)
159
Chetan Gaonker8bbc4d52016-03-29 16:59:45 -0700160 def send_igmp_leave(self, groups, src_list = ['1.2.3.4'], ip_pkt = None, iface = 'veth0', delay = 2):
Chetan Gaonker5a5204e2016-03-02 01:35:13 -0800161 igmp = IGMPv3(type = IGMP_TYPE_V3_MEMBERSHIP_REPORT, max_resp_code=30,
Chetan Gaonker8bbc4d52016-03-29 16:59:45 -0700162 gaddr=self.IP_DST)
Chetan Gaonkereb2b24b2016-03-01 14:04:45 -0800163 for g in groups:
Chetan Gaonker5a5204e2016-03-02 01:35:13 -0800164 gr = IGMPv3gr(rtype=IGMP_V3_GR_TYPE_INCLUDE, mcaddr=g)
165 gr.sources = src_list
166 igmp.grps.append(gr)
Chetan Gaonker8bbc4d52016-03-29 16:59:45 -0700167 if ip_pkt is None:
168 ip_pkt = self.igmp_eth/self.igmp_ip
169 pkt = ip_pkt/igmp
Chetan Gaonker5a5204e2016-03-02 01:35:13 -0800170 IGMPv3.fixup(pkt)
171 sendp(pkt, iface = iface)
Chetan Gaonkereb2b24b2016-03-01 14:04:45 -0800172 if delay != 0:
173 time.sleep(delay)
Chetan Gaonker25470972016-02-26 08:52:15 -0800174
Chetan Gaonkereb2b24b2016-03-01 14:04:45 -0800175 @deferred(timeout=MCAST_TRAFFIC_TIMEOUT+10)
176 def test_igmp_join_verify_traffic(self):
Chetan Gaonker25470972016-02-26 08:52:15 -0800177 groups = ['224.0.1.1', '225.0.0.1']
Chetan Gaonker25470972016-02-26 08:52:15 -0800178 df = defer.Deferred()
179 igmpState = IGMPTestState(groups = groups, df = df)
Chetan Gaonkereb2b24b2016-03-01 14:04:45 -0800180 igmpStateRecv = IGMPTestState(groups = groups, df = df)
181 igmpStateList = (igmpState, igmpStateRecv)
182 mcastTraffic = McastTraffic(groups, iface= 'veth2', cb = self.send_mcast_cb, arg = igmpState)
183 self.df = df
184 self.mcastTraffic = mcastTraffic
185 self.recv_socket = L3PacketSocket(iface = 'veth0', type = ETH_P_IP)
186
187 def igmp_srp_task(stateList):
188 igmpSendState, igmpRecvState = stateList
189 if not mcastTraffic.isRecvStopped():
190 result = self.igmp_recv(igmpRecvState)
191 reactor.callLater(0, igmp_srp_task, stateList)
192 else:
193 self.mcastTraffic.stop()
194 self.recv_socket.close()
195 self.igmp_verify_join(stateList)
196 self.df.callback(0)
197
198 self.send_igmp_join(groups)
199 mcastTraffic.start()
200 self.test_timer = reactor.callLater(self.MCAST_TRAFFIC_TIMEOUT, self.mcast_traffic_timer)
201 reactor.callLater(0, igmp_srp_task, igmpStateList)
Chetan Gaonker25470972016-02-26 08:52:15 -0800202 return df
203
Chetan Gaonkereb2b24b2016-03-01 14:04:45 -0800204 @deferred(timeout=MCAST_TRAFFIC_TIMEOUT+10)
205 def test_igmp_leave_verify_traffic(self):
206 groups = ['224.0.1.10', '225.0.0.10']
207 leave_groups = ['224.0.1.10']
208 df = defer.Deferred()
209 igmpState = IGMPTestState(groups = groups, df = df)
210 igmpStateRecv = IGMPTestState(groups = groups, df = df)
211 igmpStateList = (igmpState, igmpStateRecv)
212 mcastTraffic = McastTraffic(groups, iface= 'veth2', cb = self.send_mcast_cb,
213 arg = igmpState)
214 self.df = df
215 self.mcastTraffic = mcastTraffic
216 self.recv_socket = L3PacketSocket(iface = 'veth0', type = ETH_P_IP)
217
218 def igmp_srp_task(stateList):
219 igmpSendState, igmpRecvState = stateList
220 if not mcastTraffic.isRecvStopped():
221 result = self.igmp_recv(igmpRecvState)
222 reactor.callLater(0, igmp_srp_task, stateList)
223 else:
224 self.mcastTraffic.stop()
225 self.recv_socket.close()
226 self.igmp_verify_leave(stateList, leave_groups)
227 self.df.callback(0)
228
229 self.send_igmp_join(groups)
230 self.send_igmp_leave(leave_groups, delay = 3)
231 mcastTraffic.start()
232 self.test_timer = reactor.callLater(self.MCAST_TRAFFIC_TIMEOUT, self.mcast_traffic_timer)
233 reactor.callLater(0, igmp_srp_task, igmpStateList)
234 return df
235
236 @deferred(timeout=100)
237 def test_igmp_leave_join_loop(self):
238 self.groups = ['226.0.1.1', '227.0.0.1', '228.0.0.1', '229.0.0.1', '230.0.0.1' ]
239 self.src_list = ['3.4.5.6', '7.8.9.10']
240 df = defer.Deferred()
241 self.df = df
242 self.iterations = 0
243 self.num_groups = len(self.groups)
244 self.MAX_TEST_ITERATIONS = 10
245
Chetan Gaonkereb2b24b2016-03-01 14:04:45 -0800246 def igmp_srp_task(v):
247 if self.iterations < self.MAX_TEST_ITERATIONS:
248 if v == 1:
249 ##join test
250 self.num_groups = random.randint(0, len(self.groups))
251 self.send_igmp_join(self.groups[:self.num_groups],
252 src_list = self.src_list,
253 iface = 'veth0', delay = 0)
254 else:
255 self.send_igmp_leave(self.groups[:self.num_groups],
256 src_list = self.src_list,
257 iface = 'veth0', delay = 0)
258 self.iterations += 1
259 v ^= 1
260 reactor.callLater(1.0 + 0.5*self.num_groups,
261 igmp_srp_task, v)
262 else:
263 self.df.callback(0)
264
265 reactor.callLater(0, igmp_srp_task, 1)
266 return df
267
268 def igmp_join_task(self, intf, groups, state, src_list = ['1.2.3.4']):
269 self.onos_ssm_table_load(groups, src_list)
Chetan Gaonker5a5204e2016-03-02 01:35:13 -0800270 igmp = IGMPv3(type = IGMP_TYPE_V3_MEMBERSHIP_REPORT, max_resp_code=30,
Chetan Gaonker8bbc4d52016-03-29 16:59:45 -0700271 gaddr=self.IP_DST)
Chetan Gaonkereb2b24b2016-03-01 14:04:45 -0800272 for g in groups:
Chetan Gaonker5a5204e2016-03-02 01:35:13 -0800273 gr = IGMPv3gr(rtype = IGMP_V3_GR_TYPE_EXCLUDE, mcaddr = g)
274 gr.sources = src_list
275 igmp.grps.append(gr)
276
277 for g in groups:
Chetan Gaonkereb2b24b2016-03-01 14:04:45 -0800278 state.group_map[g][0].update(1, t = monotonic.monotonic())
Chetan Gaonker5a5204e2016-03-02 01:35:13 -0800279
Chetan Gaonker8bbc4d52016-03-29 16:59:45 -0700280 pkt = self.igmp_eth/self.igmp_ip/igmp
Chetan Gaonker5a5204e2016-03-02 01:35:13 -0800281 IGMPv3.fixup(pkt)
282 sendp(pkt, iface=intf)
Chetan Gaonkereb2b24b2016-03-01 14:04:45 -0800283 log.debug('Returning from join task')
284
285 def igmp_recv_task(self, intf, groups, join_state):
286 recv_socket = L3PacketSocket(iface = intf, type = ETH_P_IP)
287 group_map = {}
288 for g in groups:
289 group_map[g] = [0,0]
290
291 while True:
292 p = recv_socket.recv()
293 if p.dst in groups and group_map[p.dst][0] == 0:
294 group_map[p.dst][0] += 1
295 group_map[p.dst][1] = monotonic.monotonic()
296 c = 0
297 for g in groups:
298 c += group_map[g][0]
299 if c == len(groups):
300 break
301 for g in groups:
302 join_start = join_state.group_map[g][0].start
303 recv_time = group_map[g][1] * 1000000
304 delta = (recv_time - join_start)
305 log.info('Join for group %s received in %.3f usecs' %
306 (g, delta))
307
308 recv_socket.close()
309 log.debug('Returning from recv task')
Chetan Gaonker8bbc4d52016-03-29 16:59:45 -0700310
311 def igmp_not_recv_task(self, intf, groups, join_state):
312 recv_socket = L2Socket(iface = intf, type = ETH_P_IP)
313 group_map = {}
314 for g in groups:
315 group_map[g] = [0,0]
316
317 log.info('Should not receive any multicast data')
318 status = 1
319 def igmp_recv_cb(pkt):
320 log.info('Multicast packet %s received for left groups %s' %(pkt[IP].dst, groups))
321 status = 2
322 sniff(prn = igmp_recv_cb, count = 1, lfilter = lambda p: p[IP].dst in groups,
323 timeout = 3, opened_socket = recv_socket)
324 recv_socket.close()
325 return status
326
Chetan Gaonkereb2b24b2016-03-01 14:04:45 -0800327 def group_latency_check(self, groups):
328 tasks = []
329 self.send_igmp_leave(groups = groups)
330 join_state = IGMPTestState(groups = groups)
331 tasks.append(threading.Thread(target=self.igmp_join_task, args = ('veth0', groups, join_state,)))
332 traffic_state = IGMPTestState(groups = groups)
333 mcast_traffic = McastTraffic(groups, iface= 'veth2', cb = self.send_mcast_cb,
334 arg = traffic_state)
335 mcast_traffic.start()
336 tasks.append(threading.Thread(target=self.igmp_recv_task, args = ('veth0', groups, join_state)))
337 for t in tasks:
338 t.start()
339 for t in tasks:
340 t.join()
341
342 mcast_traffic.stop()
343 self.send_igmp_leave(groups = groups)
344 return
345
346 def test_igmp_1group_join_latency(self):
347 groups = ['239.0.1.1']
348 self.group_latency_check(groups)
349
350 def test_igmp_2group_join_latency(self):
351 groups = ['239.0.1.1', '240.0.1.1']
352 self.group_latency_check(groups)
353
354 def test_igmp_Ngroup_join_latency(self):
355 groups = ['239.0.1.1', '240.0.1.1', '241.0.1.1', '242.0.1.1']
356 self.group_latency_check(groups)
357
358
Chetan Gaonker1f7c3f82016-03-08 12:17:37 -0800359 def test_igmp_join_rover(self):
360 '''Keep sending joins across multicast range of addresses'''
361 '''For now, restricting it to 50/100'''
362 s = (224 << 24) | 1
363 #e = (225 << 24) | (255 << 16) | (255 << 16) | 255
Chetan Gaonker8bbc4d52016-03-29 16:59:45 -0700364 e = (224 << 24) | 10
Chetan Gaonker1f7c3f82016-03-08 12:17:37 -0800365 for i in xrange(s, e+1):
366 if i&0xff:
367 ip = '%d.%d.%d.%d'%((i>>24)&0xff, (i>>16)&0xff, (i>>8)&0xff, i&0xff)
368 self.send_igmp_join([ip], delay = 0)
369
370 @deferred(timeout=IGMP_QUERY_TIMEOUT + 10)
371 def test_igmp_query(self):
372 groups = ['224.0.0.1'] ##igmp query group
373 df = defer.Deferred()
374 self.df = df
375 self.recv_socket = L2Socket(iface = 'veth0', type = ETH_P_IP)
376
377 def igmp_query_timeout():
Chetan Gaonker1f7c3f82016-03-08 12:17:37 -0800378 def igmp_query_cb(pkt):
Chetan Gaonkerbd4390f2016-03-09 18:56:52 -0800379 log.info('Got IGMP query packet from %s for %s' %(pkt[IP].src, pkt[IP].dst))
380 assert_equal(pkt[IP].dst, '224.0.0.1')
381
382 sniff(prn = igmp_query_cb, count=1, lfilter = lambda p: p[IP].dst in groups,
383 opened_socket = self.recv_socket)
Chetan Gaonker1f7c3f82016-03-08 12:17:37 -0800384 self.recv_socket.close()
385 self.df.callback(0)
386
387 self.send_igmp_join(groups)
388 self.test_timer = reactor.callLater(self.IGMP_QUERY_TIMEOUT, igmp_query_timeout)
389 return df
390
Chetan Gaonker8bbc4d52016-03-29 16:59:45 -0700391 def igmp_send_joins_different_groups_srclist(self, groups, sources, intf = V_INF1, delay = 2, ip_src = None):
392 g1 = groups[0]
393 g2 = groups[1]
394 sourcelist1 = sources[0]
395 sourcelist2 = sources[1]
396 eth = Ether(dst = self.MMACGROUP1, src = self.IGMP_SRC_MAC, type = ETH_P_IP)
397 src_ip = ip_src or self.IP_SRC
398 ip = IP(dst = g1, src = src_ip)
399 log.info('Sending join message for the group %s' %g1)
400 self.send_igmp_join((g1,), src_list = sourcelist1, ip_pkt = eth/ip, iface = intf, delay = 2)
401 eth = Ether(dst = self.MMACGROUP2, src = self.IGMP_SRC_MAC, type = ETH_P_IP)
402 ip = IP(dst = g2, src = src_ip)
403 log.info('Sending join message for group %s' %g2)
404 self.send_igmp_join((g2,), src_list = sourcelist2, ip_pkt = eth/ip, iface = intf, delay = 2)
405
406 def igmp_joins_leave_functionality(self, again_join = False, df = None):
407 groups1 = (self.MGROUP1,)
408 groups2 = (self.MGROUP2,)
409 self.igmp_send_joins_different_groups_srclist(groups1 + groups2,
410 (['2.2.2.2'], ['2.2.2.2']), intf = self.V_INF1, delay = 2)
411 dst_mac = '01:00:5e:01:02:03'
412 src_ip = '2.2.2.2'
413 if df is None:
414 df = defer.Deferred()
415 igmpState1 = IGMPTestState(groups = groups1, df = df)
416 igmpStateRecv1 = IGMPTestState(groups = groups1, df = df)
417 igmpStateList1 = (igmpState1, igmpStateRecv1)
418
419 igmpState2 = IGMPTestState(groups = groups2, df = df)
420 igmpStateRecv2 = IGMPTestState(groups = groups2, df = df)
421 igmpStateList2 = (igmpState2, igmpStateRecv2)
422 mcastTraffic1 = McastTraffic(groups1, iface= 'veth2', dst_mac = dst_mac,
423 src_ip = src_ip, cb = self.send_mcast_cb,
424 arg = igmpState1)
425 dst_mac = '01:00:5e:02:02:03'
426 src_ip = '2.2.2.2'
427 mcastTraffic2 = McastTraffic(groups2, iface= 'veth2', dst_mac = dst_mac,
428 src_ip = src_ip, cb = self.send_mcast_cb,
429 arg = igmpState2)
430 mcastTraffic1.start()
431 mcastTraffic2.start()
432 join_state1 = IGMPTestState(groups = groups1)
433 join_state2 = IGMPTestState(groups = groups2)
434 target1 = self.igmp_recv_task(self.V_INF1, groups1, join_state1)
435 log.info('Interface is receiving multicast groups %s' %groups1)
436 target2 = self.igmp_recv_task(self.V_INF1, groups2, join_state2)
437 log.info('Interface is receiving multicast groups %s' %groups2)
438 log.info('Interface is sending leave message for groups %s now' %groups2)
439 self.send_igmp_leave(groups = groups2, src_list = ['2.2.2.2'], iface = self.V_INF1, delay = 2)
440 target3 = self.igmp_recv_task(self.V_INF1, groups1, join_state1)
441 target4 = self.igmp_not_recv_task(self.V_INF1, groups2, join_state2)
442 assert target4 == 1, 'EXPECTED FAILURE'
443 if again_join:
444 dst_mac = '01:00:5e:02:02:03'
445 ip_dst = '239.2.2.3'
446 eth = Ether(dst = dst_mac, src = self.IGMP_SRC_MAC, type = ETH_P_IP)
447 ip = IP(dst = ip_dst, src = self.IP_SRC)
448 log.info('Interface sending join message again for the groups %s' %groups2)
449 self.send_igmp_join(groups2, src_list = [src_ip], ip_pkt = eth/ip, iface = self.V_INF1, delay = 2)
450 target5 = self.igmp_recv_task(self.V_INF1, groups2, join_state2)
451 log.info('Interface is receiving multicast groups %s again' %groups2)
452 target6 = self.igmp_recv_task(self.V_INF1, groups1, join_state1)
453 log.info('Interface is still receiving from multicast groups %s' %groups1)
454 else:
455 log.info('Ended test case')
456 mcastTraffic1.stop()
457 mcastTraffic2.stop()
458 self.onos_ctrl.deactivate()
459
460 @deferred(timeout=MCAST_TRAFFIC_TIMEOUT+20)
461 def test_igmp_2joins_1leave_functionality(self):
462 '''This test is subscribing to two channels and sending leave for one channel'''
463 df = defer.Deferred()
464 def test_igmp_2joins_1leave():
465 self.igmp_joins_leave_functionality(again_join = False, df = df)
466 df.callback(0)
467 reactor.callLater(0, test_igmp_2joins_1leave)
468 return df
469
470 @deferred(timeout=MCAST_TRAFFIC_TIMEOUT+25)
471 def test_igmp_2joins_1leave_again_joins_functionality(self):
472 '''This test is subscribing to two channels and sending leave for one channel,again join to the same group'''
473 df = defer.Deferred()
474 def test_igmp_2joins_1leave_join_again():
475 self.igmp_joins_leave_functionality(again_join = True, df = df)
476 df.callback(0)
477 reactor.callLater(0, test_igmp_2joins_1leave_join_again)
478 return df
479
480 def igmp_not_src_list_functionality(self, df = None):
481 groups1 = (self.MGROUP1,)
482 groups2 = (self.MGROUP2,)
483 self.igmp_send_joins_different_groups_srclist(groups1 + groups2,
484 (['2.2.2.2', '3.3.3.3', '4.4.4.4'], ['2.2.2.2', '5.5.5.5']),
485 intf = self.V_INF1, delay = 2)
486 dst_mac = '01:00:5e:01:02:03'
487 src_ip = '6.6.6.6'
488 if df is None:
489 df = defer.Deferred()
490 igmpState1 = IGMPTestState(groups = groups1, df = df)
491 igmpStateRecv1 = IGMPTestState(groups = groups1, df = df)
492 mcastTraffic1 = McastTraffic(groups1, iface = 'veth2', dst_mac = dst_mac,
493 src_ip = src_ip, cb = self.send_mcast_cb, arg = igmpState1)
494 mcastTraffic1.start()
495 join_state1 = IGMPTestState(groups = groups1)
496 target1 = self.igmp_not_recv_task(self.V_INF1, groups1, join_state1)
497 assert target1 == 1, 'EXPECTED FAILURE'
498 log.info('Interface is not receiving from multicast groups %s' %groups1)
499 mcastTraffic1.stop()
500 self.onos_ctrl.deactivate()
501
502 @deferred(timeout=MCAST_TRAFFIC_TIMEOUT+20)
503 def test_igmp_not_src_list_functionality(self):
504 '''This test is sending join with source list A,B,C and exclude A,D'''
505 df = defer.Deferred()
506 def igmp_not_src_list_functionality():
507 self.igmp_not_src_list_functionality(df = df)
508 df.callback(0)
509 reactor.callLater(0, igmp_not_src_list_functionality)
510 return df
511
512 def igmp_change_to_exclude_src_list_functionality(self, df = None):
513 groups1 = (self.MGROUP1,)
514 groups2 = (self.MGROUP2,)
515 self.igmp_send_joins_different_groups_srclist(groups1 + groups2,
516 (['2.2.2.2', '3.3.3.3', '4.4.4.4'], ['2.2.2.2', '5.5.5.5']),
517 intf = self.V_INF1, delay = 2)
518 dst_mac = '01:00:5e:01:02:03'
519 src_ip = '2.2.2.2'
520 if df is None:
521 df = defer.Deferred()
522 igmpState1 = IGMPTestState(groups = groups1, df = df)
523 igmpStateRecv1 = IGMPTestState(groups = groups1, df = df)
524 mcastTraffic1 = McastTraffic(groups1, iface= 'veth2', dst_mac = dst_mac,
525 src_ip = src_ip, cb = self.send_mcast_cb, arg = igmpState1)
526 mcastTraffic1.start()
527 join_state1 = IGMPTestState(groups = groups1)
528 target1 = self.igmp_recv_task(self.V_INF1, groups1, join_state1)
529 self.send_igmp_leave(groups = groups1, src_list = ['2.2.2.2'], iface = self.V_INF1, delay =2)
530 target2 = self.igmp_not_recv_task(self.V_INF1, groups1, join_state1)
531 assert target2 == 1, 'EXPECTED FAILURE'
532 log.info('Interface is not receiving from multicast groups %s after sending CHANGE_TO_EXCLUDE' %groups1)
533 mcastTraffic1.stop()
534 self.onos_ctrl.deactivate()
535
536 @deferred(timeout=MCAST_TRAFFIC_TIMEOUT+10)
537 def test_igmp_change_to_exclude_src_list_functionality(self):
538 '''This test is sending join with source list A,B,C and exclude A,D'''
539 df = defer.Deferred()
540 def igmp_change_to_exclude_src_list_functionality():
541 self.igmp_change_to_exclude_src_list_functionality(df = df)
542 df.callback(0)
543 reactor.callLater(0, igmp_change_to_exclude_src_list_functionality)
544 return df
545
546 def igmp_change_to_include_src_list_functionality(self, df = None):
547 groups1 = (self.MGROUP1,)
548 groups2 = (self.MGROUP2,)
549 self.send_igmp_leave(groups = groups1, src_list = ['2.2.2.2', '3.3.3.3', '4.4.4.4'],
550 iface = self.V_INF1, delay = 2)
551 self.igmp_send_joins_different_groups_srclist(groups1 + groups2,
552 (['2.2.2.2', '3.3.3.3', '4.4.4.4'], ['6.6.6.6', '5.5.5.5']),
553 intf = self.V_INF1, delay = 2)
554 dst_mac = '01:00:5e:01:02:03'
555 src_ip = '2.2.2.2'
556 if df is None:
557 df = defer.Deferred()
558 igmpState1 = IGMPTestState(groups = groups1, df = df)
559 igmpStateRecv1 = IGMPTestState(groups = groups1, df = df)
560 mcastTraffic1 = McastTraffic(groups1, iface= 'veth2', dst_mac = dst_mac,
561 src_ip = src_ip, cb = self.send_mcast_cb, arg = igmpState1)
562 mcastTraffic1.start()
563 join_state1 = IGMPTestState(groups = groups1)
564 target1= self.igmp_not_recv_task(self.V_INF1, groups1, join_state1)
565 assert target1 == 1, 'EXPECTED FAILURE'
566 log.info('Interface is not receiving from multicast groups %s' %groups1)
567 self.igmp_send_joins_different_groups_srclist(groups1 + groups2,
568 (['2.2.2.2', '3.3.3.3', '4.4.4.4'], ['6.6.6.6', '5.5.5.5']),
569 intf = self.V_INF1, delay = 2)
570 target2 = self.igmp_recv_task(self.V_INF1, groups1, join_state1)
571 log.info('Interface is receiving from multicast groups %s after send Change to include message' %groups1)
572 mcastTraffic1.stop()
573 self.onos_ctrl.deactivate()
574
575 @deferred(timeout=MCAST_TRAFFIC_TIMEOUT+10)
576 def test_igmp_change_to_include_src_list_functionality(self):
577 '''This test is sending join with source list A,B,C and exclude D,E'''
578 df = defer.Deferred()
579 def igmp_change_to_include_src_list_functionality():
580 self.igmp_change_to_include_src_list_functionality(df = df)
581 df.callback(0)
582 reactor.callLater(0, igmp_change_to_include_src_list_functionality)
583 return df
584
585 def igmp_new_src_list_functionality(self, df = None):
586 groups1 = (self.MGROUP1,)
587 groups2 = (self.MGROUP2,)
588 self.igmp_send_joins_different_groups_srclist(groups1+groups2,
589 (['2.2.2.2', '3.3.3.3', '4.4.4.4'], ['2.2.2.2', '5.5.5.5']),
590 intf = self.V_INF1, delay = 2)
591 dst_mac = '01:00:5e:01:02:03'
592 src_ip = '6.6.6.6'
593 if df is None:
594 df = defer.Deferred()
595 igmpState1 = IGMPTestState(groups = groups1, df = df)
596 igmpStateRecv1 = IGMPTestState(groups = groups1, df = df)
597 mcastTraffic1 = McastTraffic(groups1, iface= 'veth2', dst_mac = dst_mac,
598 src_ip = src_ip, cb = self.send_mcast_cb, arg = igmpState1)
599 mcastTraffic1.start()
600 join_state1 = IGMPTestState(groups = groups1)
601 target1 = self.igmp_not_recv_task(self.V_INF1, groups1, join_state1)
602 assert target1 == 1, 'EXPECTED FAILURE'
603 log.info('Interface is not receiving from multicast groups %s' %groups1)
604 self.igmp_send_joins_different_groups_srclist(groups1 + groups2,
605 (['6.6.6.6', '3.3.3.3', '4.4.4.4'], ['2.2.2.2', '5.5.5.5']),
606 intf = self.V_INF1, delay = 2)
607 target2 = self.igmp_recv_task(self.V_INF1, groups1, join_state1)
608 log.info('Interface is receiving from multicast groups %s after sending join with new source list' %groups1)
609 mcastTraffic1.stop()
610 self.onos_ctrl.deactivate()
611
612 @deferred(timeout=MCAST_TRAFFIC_TIMEOUT+10)
613 def test_igmp_new_src_list_functionality(self):
614 '''This test is sending join with source list A,B,C and exclude A,D'''
615 df = defer.Deferred()
616 def igmp_new_src_list_functionality():
617 self.igmp_new_src_list_functionality(df = df)
618 df.callback(0)
619 reactor.callLater(0, igmp_new_src_list_functionality)
620 return df
621
622 def igmp_block_old_src_list_functionality(self, df = None):
623 groups1 = (self.MGROUP1,)
624 groups2 = (self.MGROUP2,)
625 groups = groups1 + groups2
626 self.igmp_send_joins_different_groups_srclist(groups,
627 (['2.2.2.2', '3.3.3.3', '4.4.4.4'], ['2.2.2.2', '5.5.5.5']),
628 intf = self.V_INF1, delay = 2)
629 dst_mac = '01:00:5e:02:02:03'
630 src_ip = '5.5.5.5'
631 if df is None:
632 df = defer.Deferred()
633 igmpState1 = IGMPTestState(groups = groups2, df = df)
634 igmpStateRecv1 = IGMPTestState(groups = groups2, df = df)
635 mcastTraffic1 = McastTraffic(groups2, iface= 'veth2', dst_mac = dst_mac,
636 src_ip = src_ip, cb = self.send_mcast_cb, arg = igmpState1)
637 mcastTraffic1.start()
638 join_state1 = IGMPTestState(groups = groups2)
639 target1 = self.igmp_recv_task(self.V_INF1, groups2, join_state1)
640 log.info('Interface is receiving from multicast groups %s' %groups2)
641 self.igmp_send_joins_different_groups_srclist(groups,
642 (['6.6.6.6', '3.3.3.3', '4.4.4.4'], ['2.2.2.2', '7.7.7.7']),
643 intf = self.V_INF1, delay = 2)
644 target2 = self.igmp_not_recv_task(self.V_INF1, groups2, join_state1)
645 assert target2 == 1, 'EXPECTED FAILURE'
646 log.info('Interface is not receiving from multicast groups %s after sending join with block old source list' %groups2)
647 mcastTraffic1.stop()
648 self.onos_ctrl.deactivate()
649
650 @deferred(timeout=MCAST_TRAFFIC_TIMEOUT+20)
651 def test_igmp_block_old_src_list_functionality(self):
652 '''This test is sending join with source list A,B,C and exclude A,D'''
653 df = defer.Deferred()
654 def igmp_block_old_src_list_functionality():
655 self.igmp_block_old_src_list_functionality(df = df)
656 df.callback(0)
657 reactor.callLater(0, igmp_block_old_src_list_functionality)
658 return df
659
660 def igmp_include_empty_src_list_functionality(self, df = None):
661 print'This test is sending join with source list A,B,C and exclude D,F,G'
662 groups1 = (self.MGROUP1,)
663 groups2 = (self.MGROUP2,)
664 groups = groups1 + groups2
665 self.igmp_send_joins_different_groups_srclist(groups,
666 (['2.2.2.2', '3.3.3.3', '4.4.4.4'], ['']),
667 intf = self.V_INF1, delay = 2)
668 dst_mac = '01:00:5e:02:02:03'
669 src_ip = '5.5.5.5'
670 if df is None:
671 df = defer.Deferred()
672 igmpState1 = IGMPTestState(groups = groups2, df = df)
673 igmpStateRecv1 = IGMPTestState(groups = groups2, df = df)
674 mcastTraffic1 = McastTraffic(groups2, iface= 'veth2', dst_mac = dst_mac,
675 src_ip = src_ip, cb = self.send_mcast_cb, arg = igmpState1)
676 mcastTraffic1.start()
677 join_state1 = IGMPTestState(groups = groups2)
678 target1 = self.igmp_not_recv_task(self.V_INF1, groups2, join_state1)
679 assert target1==1, 'EXPECTED FAILURE'
680 log.info('Interface is not receiving from multicast groups %s when we sent join with source list is empty' %groups2)
681 mcastTraffic1.stop()
682 self.onos_ctrl.deactivate()
683
684 @deferred(timeout=MCAST_TRAFFIC_TIMEOUT+20)
685 def ztest_igmp_include_empty_src_list_functionality(self):
686 '''This test is sending join with source list A,B,C and exclude D,F,G'''
687 '''Disabling this test as scapy IGMP doesn't work with empty source lists'''
688 df = defer.Deferred()
689 def igmp_include_empty_src_list_functionality():
690 self.igmp_include_empty_src_list_functionality(df = df)
691 df.callback(0)
692 reactor.callLater(0, igmp_include_empty_src_list_functionality)
693 return df
694
695 def igmp_exclude_empty_src_list_functionality(self, df = None):
696 groups1 = (self.MGROUP1,)
697 groups2 = (self.MGROUP2,)
698 groups = groups1 + groups2
699 self.send_igmp_leave(groups = groups2, src_list = [''], iface = self.V_INF1, delay = 2)
700 dst_mac = '01:00:5e:02:02:03'
701 src_ip = '5.5.5.5'
702 if df is None:
703 df = defer.Deferred()
704 igmpState1 = IGMPTestState(groups = groups2, df = df)
705 igmpStateRecv1 = IGMPTestState(groups = groups2, df = df)
706 mcastTraffic1 = McastTraffic(groups2, iface= 'veth2', dst_mac = dst_mac,
707 src_ip = src_ip, cb = self.send_mcast_cb, arg = igmpState1)
708 mcastTraffic1.start()
709 join_state1 = IGMPTestState(groups = groups2)
710 target1 = self.igmp_recv_task(self.V_INF1, groups2, join_state1)
711 log.info('Interface is receiving multicast groups %s' %groups2)
712 mcastTraffic1.stop()
713 self.onos_ctrl.deactivate()
714
715 @deferred(timeout=MCAST_TRAFFIC_TIMEOUT+20)
716 def ztest_igmp_exclude_empty_src_list_functionality(self):
717 '''This test is sending join with source list A,B,C and exclude D,F,G'''
718 '''Disabling this test case since scapy IGMP doesn't work with empty src list'''
719 df = defer.Deferred()
720 def igmp_exclude_empty_src_list_functionality():
721 self.igmp_exclude_empty_src_list_functionality()
722 df.callback(0)
723 reactor.callLater(0, igmp_exclude_empty_src_list_functionality)
724 return df
725
726 def igmp_join_sourceip_0_0_0_0_functionality(self, df = None):
727 groups1 = (self.MGROUP1,)
728 groups2 = (self.MGROUP2,)
729 groups = groups1 + groups2
730 ip_src = '0.0.0.0'
731 self.igmp_send_joins_different_groups_srclist(groups,
732 (['2.2.2.2', '3.3.3.3', '4.4.4.4'], ['5.5.5.5']),
733 intf = self.V_INF1, delay = 2, ip_src = ip_src)
734 ip_src = self.IP_SRC
735 dst_mac = '01:00:5e:02:02:03'
736 src_ip = '5.5.5.5'
737 if df is None:
738 df = defer.Deferred()
739 igmpState1 = IGMPTestState(groups = groups2, df = df)
740 igmpStateRecv1 = IGMPTestState(groups = groups2, df = df)
741 mcastTraffic1 = McastTraffic(groups2, iface= 'veth2', dst_mac = dst_mac,
742 src_ip = src_ip, cb = self.send_mcast_cb, arg = igmpState1)
743 mcastTraffic1.start()
744 join_state1 = IGMPTestState(groups = groups2)
745 target1 = self.igmp_recv_task(self.V_INF1, groups2, join_state1)
746 log.info('Interface is receiving from multicast groups %s when we sent join with source IP is 0.0.0.0' %groups2)
747 mcastTraffic1.stop()
748 self.onos_ctrl.deactivate()
749
750 @deferred(timeout=MCAST_TRAFFIC_TIMEOUT+20)
751 def test_igmp_join_sourceip_0_0_0_0_functionality(self):
752 '''This test is sending join with source list A,B,C and exclude D,F,G with source IP as 0.0.0.0'''
753 df = defer.Deferred()
754 def igmp_join_sourceip_0_0_0_0_functionality():
755 self.igmp_join_sourceip_0_0_0_0_functionality(df = df)
756 df.callback(0)
757 reactor.callLater(0, igmp_join_sourceip_0_0_0_0_functionality)
758 return df
759