blob: 365468be84f817a40ea0298adf926c36805565a0 [file] [log] [blame]
Zsolt Haraszti656ecc62016-12-28 15:08:23 -08001#
2# Copyright 2016 the original author or authors.
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15#
16
17from unittest import TestCase, main
18
19from scapy.layers.inet import IP
20from scapy.layers.l2 import Ether, Dot1Q, EAPOL
21
22from ponsim import PonSim
23from voltha.extensions.IGMP import IGMP_TYPE_V3_MEMBERSHIP_REPORT, IGMPv3gr, \
24 IGMPv3, IGMP_TYPE_MEMBERSHIP_QUERY
25from voltha.extensions.IGMP import IGMP_V3_GR_TYPE_EXCLUDE
26from voltha.protos import third_party
27from voltha.core.flow_decomposer import *
28_ = third_party
29
30
31class TestPonSim(TestCase):
32
33 def setUp(self):
34 self.output = []
35 self.pon = PonSim(onus=2, egress_fun=lambda port, frame:
36 self.output.append((port, frame)))
37
38 def reset_output(self):
39 while self.output:
40 self.output.pop()
41
42 def ingress_frame(self, frame, ports=None):
43 if ports is None:
44 ports = self.pon.get_ports()
45 if isinstance(ports, int):
46 ports = [ports]
47 for port in ports:
48 self.pon.ingress(port, frame)
49
50 def assert_dont_pass(self, frame, ports=None):
51 self.reset_output()
52 self.ingress_frame(frame, ports)
53 self.assertEqual(self.output, [])
54
55 def assert_untagged_frames_dont_pass(self, ports=None):
56 self.assert_dont_pass(Ether(), ports=ports)
57
58 def test_basics(self):
59 self.assertEqual(self.pon.get_ports(), [0, 128, 129])
60
61 def test_by_default_no_traffic_passes(self):
62 self.assert_untagged_frames_dont_pass()
63
64 def test_downstream_unicast_forwarding(self):
65
66 self.pon.olt_install_flows([
67 mk_flow_stat(
68 match_fields=[in_port(2), vlan_vid(4096 + 1000)],
69 actions=[pop_vlan(), output(1)]
70 )
71 ])
72 self.pon.onu_install_flows(128, [
73 mk_flow_stat(
74 match_fields=[in_port(1), vlan_vid(4096 + 128)],
75 actions=[set_field(vlan_vid(4096 + 0)), output(2)]
76 )
77 ])
78
79 # untagged frames shall not get through
80 self.assert_untagged_frames_dont_pass()
81
82 # incorrect single- or double-tagged frames don't pass
83 self.assert_dont_pass(Ether() / Dot1Q(vlan=1000) / IP())
84 self.assert_dont_pass(Ether() / Dot1Q(vlan=128) / IP())
85 self.assert_dont_pass(
86 Ether() / Dot1Q(vlan=128) / Dot1Q(vlan=1000) / IP())
87 self.assert_dont_pass(
88 Ether() / Dot1Q(vlan=1000) / Dot1Q(vlan=129) / IP())
89
90 # properly tagged downstream frame gets through and pops up at port 128
91 # as untagged
92 kw = dict(src='00:00:00:11:11:11', dst='00:00:00:22:22:22')
93 in_frame = Ether(**kw) / Dot1Q(vlan=1000) / Dot1Q(vlan=128) / IP()
94 out_frame = Ether(**kw) / Dot1Q(vlan=0) / IP()
95
96 self.ingress_frame(in_frame)
97 self.assertEqual(self.output, [(128, out_frame)])
98
99 def test_upstream_unicast_forwarding(self):
100
101 self.pon.onu_install_flows(128, [
102 mk_flow_stat(
103 match_fields=[in_port(2), vlan_vid(4096 + 0)],
104 actions=[set_field(vlan_vid(4096 + 128)), output(1)]
105 )
106 ])
107 self.pon.olt_install_flows([
108 mk_flow_stat(
109 match_fields=[in_port(1), vlan_vid(4096 + 128)],
110 actions=[push_vlan(0x8100), set_field(vlan_vid(4096 + 1000)),
111 output(2)]
112 )
113 ])
114
115 # untagged frames shall not get through
116 self.assert_untagged_frames_dont_pass()
117
118 # incorrect single- or double-tagged frames don't pass
119 self.assert_dont_pass(Ether() / Dot1Q(vlan=1000) / IP())
120 self.assert_dont_pass(Ether() / Dot1Q(vlan=128) / IP())
121 self.assert_dont_pass(
122 Ether() / Dot1Q(vlan=1000) / Dot1Q(vlan=128) / IP())
123 self.assert_dont_pass(
124 Ether() / Dot1Q(vlan=129) / Dot1Q(vlan=1000) / IP())
125
126 # properly tagged downstream frame gets through and pops up at port 128
127 # as untagged
128 kw = dict(src='00:00:00:11:11:11', dst='00:00:00:22:22:22')
129 in_frame = Ether(**kw) / Dot1Q(vlan=0) / IP()
130 out_frame = Ether(**kw) / Dot1Q(vlan=1000) / Dot1Q(vlan=128) / IP()
131
132 self.ingress_frame(in_frame)
133 self.assertEqual(self.output, [(0, out_frame)])
134
135
136 def setup_all_flows(self):
137
138 self.pon.olt_install_flows([
139 mk_flow_stat(
140 priority=2000,
141 match_fields=[in_port(2), vlan_vid(4096 + 4000), vlan_pcp(0)],
142 actions=[pop_vlan(), output(1)]
143 ),
144 mk_flow_stat(
145 priority=2000,
146 match_fields=[in_port(1), eth_type(0x888e)],
147 actions=[push_vlan(0x8100), set_field(vlan_vid(4096 + 4000)),
148 output(2)]
149 ),
150 mk_flow_stat(
151 priority=1000,
152 match_fields=[in_port(1), eth_type(0x800), ip_proto(2)],
153 actions=[push_vlan(0x8100), set_field(vlan_vid(4096 + 4000)),
154 output(2)]
155 ),
156 mk_flow_stat(
157 priority=1000,
158 match_fields=[in_port(1), eth_type(0x800), ip_proto(17),
159 udp_dst(67)],
160 actions=[push_vlan(0x8100), set_field(vlan_vid(4096 + 4000)),
161 output(2)]
162 ),
163 mk_flow_stat(
164 priority=1000,
165 match_fields=[in_port(2), vlan_vid(4096 + 140)],
166 actions=[pop_vlan(), output(1)]
167 ),
168 mk_flow_stat(
169 priority=500,
170 match_fields=[in_port(2), vlan_vid(4096 + 1000)],
171 actions=[pop_vlan(), output(1)]
172 ),
173 mk_flow_stat(
174 priority=500,
175 match_fields=[in_port(1), vlan_vid(4096 + 128)],
176 actions=[
177 push_vlan(0x8100), set_field(vlan_vid(4096 + 1000)),
178 output(2)]
179 ),
180 mk_flow_stat(
181 priority=500,
182 match_fields=[in_port(1), vlan_vid(4096 + 129)],
183 actions=[
184 push_vlan(0x8100), set_field(vlan_vid(4096 + 1000)),
185 output(2)]
186 ),
187 ])
188
189 self.pon.onu_install_flows(128, [
190 mk_flow_stat(
191 priority=500,
192 match_fields=[in_port(2), vlan_vid(4096 + 0)],
193 actions=[
194 set_field(vlan_vid(4096 + 128)), output(1)]
195 ),
196 mk_flow_stat(
197 priority=1000,
198 match_fields=[
199 in_port(1), eth_type(0x800), ipv4_dst(0xe4010102)],
200 actions=[output(2)]
201 ),
202 mk_flow_stat(
203 priority=1000,
204 match_fields=[
205 in_port(1), eth_type(0x800), ipv4_dst(0xe4010104)],
206 actions=[output(2)]
207 ),
208 mk_flow_stat(
209 priority=500,
210 match_fields=[in_port(1), vlan_vid(4096 + 128)],
211 actions=[set_field(vlan_vid(4096 + 0)), output(2)]
212 ),
213 mk_flow_stat(
214 priority=500,
215 match_fields=[in_port(2), vlan_vid(0)],
216 actions=[push_vlan(0x8100), set_field(vlan_vid(4096 + 128)),
217 output(1)]
218 )
219 ])
220
221 self.pon.onu_install_flows(129, [
222 mk_flow_stat(
223 priority=500,
224 match_fields=[in_port(2), vlan_vid(4096 + 0)],
225 actions=[
226 set_field(vlan_vid(4096 + 129)), output(1)]
227 ),
228 mk_flow_stat(
229 priority=1000,
230 match_fields=[
231 in_port(1), eth_type(0x800), ipv4_dst(0xe4010103)],
232 actions=[output(2)]
233 ),
234 mk_flow_stat(
235 priority=1000,
236 match_fields=[
237 in_port(1), eth_type(0x800), ipv4_dst(0xe4010104)],
238 actions=[output(2)]
239 ),
240 mk_flow_stat(
241 priority=500,
242 match_fields=[in_port(1), vlan_vid(4096 + 129)],
243 actions=[set_field(vlan_vid(4096 + 0)), output(2)]
244 ),
245 mk_flow_stat(
246 priority=500,
247 match_fields=[in_port(2), vlan_vid(0)],
248 actions=[push_vlan(0x8100), set_field(vlan_vid(4096 + 129)),
249 output(1)]
250 )
251 ])
252
253 def test_combo_block_untagged_downstream(self):
254 self.setup_all_flows()
255 self.assert_untagged_frames_dont_pass(ports=0)
256
257 def test_eapol_in(self):
258 self.setup_all_flows()
259 kw = dict(src='00:00:00:11:11:11', dst='00:00:00:22:22:22')
260 in_frame = Ether(**kw) / EAPOL(type=1)
261 out_frame1 = Ether(**kw) / Dot1Q(vlan=4000) / Dot1Q(vlan=128) / EAPOL(type=1)
262 out_frame2 = Ether(**kw) / Dot1Q(vlan=4000) / Dot1Q(vlan=129) / EAPOL(type=1)
263 self.ingress_frame(in_frame)
264 self.assertEqual(self.output, [(0, out_frame1), (0, out_frame2)])
265
266 def test_eapol_out(self):
267 self.setup_all_flows()
268 kw = dict(src='00:00:00:11:11:11', dst='00:00:00:22:22:22')
269 in_frame1 = Ether(**kw) / Dot1Q(vlan=4000) / Dot1Q(vlan=128) / EAPOL(type=1)
270 in_frame2 = Ether(**kw) / Dot1Q(vlan=4000) / Dot1Q(vlan=129) / EAPOL(type=1)
271 out_frame = Ether(**kw) / Dot1Q(vlan=0) / EAPOL(type=1)
272 self.ingress_frame(in_frame1)
273 self.ingress_frame(in_frame2)
274 self.assertEqual(self.output, [(128, out_frame), (129, out_frame)])
275
276 def test_igmp_in(self):
277 self.setup_all_flows()
278 kw = dict(src='00:00:00:11:11:11', dst='00:00:00:22:22:22')
279 mr = IGMPv3(type=IGMP_TYPE_V3_MEMBERSHIP_REPORT, max_resp_code=30,
280 gaddr="224.0.0.1")
281 mr.grps = [
282 IGMPv3gr(rtype=IGMP_V3_GR_TYPE_EXCLUDE, mcaddr="228.1.1.3")]
283
284 in_frame = Ether(**kw) / IP() / mr
285 out_frame1 = Ether(**kw) / Dot1Q(vlan=4000) / Dot1Q(vlan=128) /\
286 in_frame.payload.copy()
287 out_frame2 = Ether(**kw) / Dot1Q(vlan=4000) / Dot1Q(vlan=129) /\
288 in_frame.payload.copy()
289 self.ingress_frame(in_frame)
290 self.assertEqual(self.output, [(0, out_frame1), (0, out_frame2)])
291
292 def test_igmp_out(self):
293 self.setup_all_flows()
294 kw = dict(src='00:00:00:11:11:11', dst='00:00:00:22:22:22')
295 mq = IGMPv3(type=IGMP_TYPE_MEMBERSHIP_QUERY, max_resp_code=120)
296 in_frame1 = Ether(**kw) / Dot1Q(vlan=4000) / Dot1Q(vlan=128) /\
297 IP() / mq.copy()
298 in_frame2 = Ether(**kw) / Dot1Q(vlan=4000) / Dot1Q(vlan=129) /\
299 IP() / mq.copy()
300 out_frame = Ether(**kw) / Dot1Q(vlan=0) / IP() / mq.copy()
301 self.ingress_frame(in_frame1)
302 self.ingress_frame(in_frame2)
303 self.assertEqual(self.output, [(128, out_frame), (129, out_frame)])
304
305 def test_combo_downstream_unicast_onu1(self):
306 self.setup_all_flows()
307 kw = dict(src='00:00:00:11:11:11', dst='00:00:00:22:22:22')
308 in_frame = Ether(**kw) / Dot1Q(vlan=1000) / Dot1Q(vlan=128) / IP()
309 out_frame = Ether(**kw) / Dot1Q(vlan=0) / IP()
310 self.reset_output()
311 self.ingress_frame(in_frame, ports=0)
312 self.assertEqual(self.output, [(128, out_frame)])
313
314 def test_combo_downstream_unicast_onu2(self):
315 self.setup_all_flows()
316 kw = dict(src='00:00:00:11:11:11', dst='00:00:00:22:22:22')
317 in_frame = Ether(**kw) / Dot1Q(vlan=1000) / Dot1Q(vlan=129) / IP()
318 out_frame = Ether(**kw) / Dot1Q(vlan=0) / IP()
319 self.reset_output()
320 self.ingress_frame(in_frame, ports=0)
321 self.assertEqual(self.output, [(129, out_frame)])
322
323 def test_combo_upstream_unicast_onu1(self):
324 self.setup_all_flows()
325 kw = dict(src='00:00:00:11:11:11', dst='00:00:00:22:22:22')
326 in_frame = Ether(**kw) / Dot1Q(vlan=1000) / Dot1Q(vlan=128) / IP()
327 out_frame = Ether(**kw) / Dot1Q(vlan=0) / IP()
328 self.ingress_frame(in_frame)
329 self.assertEqual(self.output, [(128, out_frame)])
330
331 def test_combo_upstream_unicast_onu2(self):
332 self.setup_all_flows()
333 kw = dict(src='00:00:00:11:11:11', dst='00:00:00:22:22:22')
334 in_frame = Ether(**kw) / Dot1Q(vlan=1000) / Dot1Q(vlan=129) / IP()
335 out_frame = Ether(**kw) / Dot1Q(vlan=0) / IP()
336 self.ingress_frame(in_frame)
337 self.assertEqual(self.output, [(129, out_frame)])
338
339 def test_combo_multicast_stream1(self):
340 self.setup_all_flows()
341 kw = dict(src='00:00:00:11:11:11', dst='00:00:00:22:22:22')
342 in_frame = Ether(**kw) / Dot1Q(vlan=140) / IP(dst='228.1.1.1')
343 self.ingress_frame(in_frame)
344 self.assertEqual(self.output, [])
345
346 def test_combo_multicast_stream2(self):
347 self.setup_all_flows()
348 kw = dict(src='00:00:00:11:11:11', dst='00:00:00:22:22:22')
349 in_frame = Ether(**kw) / Dot1Q(vlan=140) / IP(dst='228.1.1.2')
350 out_frame = Ether(**kw) / IP(dst='228.1.1.2')
351 self.ingress_frame(in_frame)
352 self.assertEqual(self.output, [(128, out_frame),])
353
354 def test_combo_multicast_stream3(self):
355 self.setup_all_flows()
356 kw = dict(src='00:00:00:11:11:11', dst='00:00:00:22:22:22')
357 in_frame = Ether(**kw) / Dot1Q(vlan=140) / IP(dst='228.1.1.3')
358 out_frame = Ether(**kw) / IP(dst='228.1.1.3')
359 self.ingress_frame(in_frame)
360 self.assertEqual(self.output, [(129, out_frame),])
361
362 def test_combo_multicast_stream4(self):
363 self.setup_all_flows()
364 kw = dict(src='00:00:00:11:11:11', dst='00:00:00:22:22:22')
365 in_frame = Ether(**kw) / Dot1Q(vlan=140) / IP(dst='228.1.1.4')
366 out_frame = Ether(**kw) / IP(dst='228.1.1.4')
367 self.ingress_frame(in_frame)
368 self.assertEqual(self.output, [(128, out_frame), (129, out_frame)])
369
370
371if __name__ == '__main__':
372 main()