tests: replace pycodestyle with black
[vpp.git] / test / test_pppoe.py
1 #!/usr/bin/env python3
2
3 import socket
4 import unittest
5
6 from scapy.packet import Raw
7 from scapy.layers.l2 import Ether
8 from scapy.layers.ppp import PPPoE, PPPoED, PPP
9 from scapy.layers.inet import IP
10
11 from framework import VppTestCase, VppTestRunner
12 from vpp_ip_route import VppIpRoute, VppRoutePath
13 from vpp_pppoe_interface import VppPppoeInterface
14 from util import ppp, ppc
15
16
17 class TestPPPoE(VppTestCase):
18     """PPPoE Test Case"""
19
20     @classmethod
21     def setUpClass(cls):
22         super(TestPPPoE, cls).setUpClass()
23
24         cls.session_id = 1
25         cls.dst_ip = "100.1.1.100"
26         cls.dst_ipn = socket.inet_pton(socket.AF_INET, cls.dst_ip)
27
28     @classmethod
29     def tearDownClass(cls):
30         super(TestPPPoE, cls).tearDownClass()
31
32     def setUp(self):
33         super(TestPPPoE, self).setUp()
34
35         # create 2 pg interfaces
36         self.create_pg_interfaces(range(3))
37
38         for i in self.pg_interfaces:
39             i.admin_up()
40             i.config_ip4()
41             i.resolve_arp()
42
43     def tearDown(self):
44         super(TestPPPoE, self).tearDown()
45
46         for i in self.pg_interfaces:
47             i.unconfig_ip4()
48             i.admin_down()
49
50     def show_commands_at_teardown(self):
51         self.logger.info(self.vapi.cli("show int"))
52         self.logger.info(self.vapi.cli("show pppoe fib"))
53         self.logger.info(self.vapi.cli("show pppoe session"))
54         self.logger.info(self.vapi.cli("show ip fib"))
55         self.logger.info(self.vapi.cli("show trace"))
56
57     def create_stream_pppoe_discovery(self, src_if, dst_if, client_mac, count=1):
58         packets = []
59         for i in range(count):
60             # create packet info stored in the test case instance
61             info = self.create_packet_info(src_if, dst_if)
62             # convert the info into packet payload
63             payload = self.info_to_payload(info)
64             # create the packet itself
65             p = (
66                 Ether(dst=src_if.local_mac, src=client_mac)
67                 / PPPoED(sessionid=0)
68                 / Raw(payload)
69             )
70             # store a copy of the packet in the packet info
71             info.data = p.copy()
72             # append the packet to the list
73             packets.append(p)
74
75         # return the created packet list
76         return packets
77
78     def create_stream_pppoe_lcp(self, src_if, dst_if, client_mac, session_id, count=1):
79         packets = []
80         for i in range(count):
81             # create packet info stored in the test case instance
82             info = self.create_packet_info(src_if, dst_if)
83             # convert the info into packet payload
84             payload = self.info_to_payload(info)
85             # create the packet itself
86             p = (
87                 Ether(dst=src_if.local_mac, src=client_mac)
88                 / PPPoE(sessionid=session_id)
89                 / PPP(proto=0xC021)
90                 / Raw(payload)
91             )
92             # store a copy of the packet in the packet info
93             info.data = p.copy()
94             # append the packet to the list
95             packets.append(p)
96
97         # return the created packet list
98         return packets
99
100     def create_stream_pppoe_ip4(
101         self, src_if, dst_if, client_mac, session_id, client_ip, count=1
102     ):
103         packets = []
104         for i in range(count):
105             # create packet info stored in the test case instance
106             info = self.create_packet_info(src_if, dst_if)
107             # convert the info into packet payload
108             payload = self.info_to_payload(info)
109             # create the packet itself
110             p = (
111                 Ether(dst=src_if.local_mac, src=client_mac)
112                 / PPPoE(sessionid=session_id)
113                 / PPP(proto=0x0021)
114                 / IP(src=client_ip, dst=self.dst_ip)
115                 / Raw(payload)
116             )
117             # store a copy of the packet in the packet info
118             info.data = p.copy()
119             # append the packet to the list
120             packets.append(p)
121
122         # return the created packet list
123         return packets
124
125     def create_stream_ip4(self, src_if, dst_if, client_ip, dst_ip, count=1):
126         pkts = []
127         for i in range(count):
128             # create packet info stored in the test case instance
129             info = self.create_packet_info(src_if, dst_if)
130             # convert the info into packet payload
131             payload = self.info_to_payload(info)
132             # create the packet itself
133             p = (
134                 Ether(dst=src_if.local_mac, src=src_if.remote_mac)
135                 / IP(src=dst_ip, dst=client_ip)
136                 / Raw(payload)
137             )
138             # store a copy of the packet in the packet info
139             info.data = p.copy()
140             # append the packet to the list
141             pkts.append(p)
142
143         # return the created packet list
144         return pkts
145
146     def verify_decapped_pppoe(self, src_if, capture, sent):
147         self.assertEqual(len(capture), len(sent))
148
149         for i in range(len(capture)):
150             try:
151                 tx = sent[i]
152                 rx = capture[i]
153
154                 tx_ip = tx[IP]
155                 rx_ip = rx[IP]
156
157                 self.assertEqual(rx_ip.src, tx_ip.src)
158                 self.assertEqual(rx_ip.dst, tx_ip.dst)
159
160             except:
161                 self.logger.error(ppp("Rx:", rx))
162                 self.logger.error(ppp("Tx:", tx))
163                 raise
164
165     def verify_encaped_pppoe(self, src_if, capture, sent, session_id):
166
167         self.assertEqual(len(capture), len(sent))
168
169         for i in range(len(capture)):
170             try:
171                 tx = sent[i]
172                 rx = capture[i]
173
174                 tx_ip = tx[IP]
175                 rx_ip = rx[IP]
176
177                 self.assertEqual(rx_ip.src, tx_ip.src)
178                 self.assertEqual(rx_ip.dst, tx_ip.dst)
179
180                 rx_pppoe = rx[PPPoE]
181
182                 self.assertEqual(rx_pppoe.sessionid, session_id)
183
184             except:
185                 self.logger.error(ppp("Rx:", rx))
186                 self.logger.error(ppp("Tx:", tx))
187                 raise
188
189     def test_PPPoE_Decap(self):
190         """PPPoE Decap Test"""
191
192         self.vapi.cli("clear trace")
193
194         #
195         # Add a route that resolves the server's destination
196         #
197         route_sever_dst = VppIpRoute(
198             self,
199             "100.1.1.100",
200             32,
201             [VppRoutePath(self.pg1.remote_ip4, self.pg1.sw_if_index)],
202         )
203         route_sever_dst.add_vpp_config()
204
205         # Send PPPoE Discovery
206         tx0 = self.create_stream_pppoe_discovery(
207             self.pg0, self.pg1, self.pg0.remote_mac
208         )
209         self.pg0.add_stream(tx0)
210         self.pg_start()
211
212         # Send PPPoE PPP LCP
213         tx1 = self.create_stream_pppoe_lcp(
214             self.pg0, self.pg1, self.pg0.remote_mac, self.session_id
215         )
216         self.pg0.add_stream(tx1)
217         self.pg_start()
218
219         # Create PPPoE session
220         pppoe_if = VppPppoeInterface(
221             self, self.pg0.remote_ip4, self.pg0.remote_mac, self.session_id
222         )
223         pppoe_if.add_vpp_config()
224         pppoe_if.set_unnumbered(self.pg0.sw_if_index)
225
226         #
227         # Send tunneled packets that match the created tunnel and
228         # are decapped and forwarded
229         #
230         tx2 = self.create_stream_pppoe_ip4(
231             self.pg0,
232             self.pg1,
233             self.pg0.remote_mac,
234             self.session_id,
235             self.pg0.remote_ip4,
236         )
237         self.pg0.add_stream(tx2)
238
239         self.pg_enable_capture(self.pg_interfaces)
240         self.pg_start()
241
242         rx2 = self.pg1.get_capture(len(tx2))
243         self.verify_decapped_pppoe(self.pg0, rx2, tx2)
244
245         self.logger.info(self.vapi.cli("show pppoe fib"))
246         self.logger.info(self.vapi.cli("show pppoe session"))
247         self.logger.info(self.vapi.cli("show ip fib"))
248
249         #
250         # test case cleanup
251         #
252
253         # Delete PPPoE session
254         pppoe_if.remove_vpp_config()
255
256         # Delete a route that resolves the server's destination
257         route_sever_dst.remove_vpp_config()
258
259     def test_PPPoE_Encap(self):
260         """PPPoE Encap Test"""
261
262         self.vapi.cli("clear trace")
263
264         #
265         # Add a route that resolves the server's destination
266         #
267         route_sever_dst = VppIpRoute(
268             self,
269             "100.1.1.100",
270             32,
271             [VppRoutePath(self.pg1.remote_ip4, self.pg1.sw_if_index)],
272         )
273         route_sever_dst.add_vpp_config()
274
275         # Send PPPoE Discovery
276         tx0 = self.create_stream_pppoe_discovery(
277             self.pg0, self.pg1, self.pg0.remote_mac
278         )
279         self.pg0.add_stream(tx0)
280         self.pg_start()
281
282         # Send PPPoE PPP LCP
283         tx1 = self.create_stream_pppoe_lcp(
284             self.pg0, self.pg1, self.pg0.remote_mac, self.session_id
285         )
286         self.pg0.add_stream(tx1)
287         self.pg_start()
288
289         # Create PPPoE session
290         pppoe_if = VppPppoeInterface(
291             self, self.pg0.remote_ip4, self.pg0.remote_mac, self.session_id
292         )
293         pppoe_if.add_vpp_config()
294         pppoe_if.set_unnumbered(self.pg0.sw_if_index)
295
296         #
297         # Send a packet stream that is routed into the session
298         #  - packets are PPPoE encapped
299         #
300         self.vapi.cli("clear trace")
301         tx2 = self.create_stream_ip4(
302             self.pg1, self.pg0, self.pg0.remote_ip4, self.dst_ip, 65
303         )
304         self.pg1.add_stream(tx2)
305
306         self.pg_enable_capture(self.pg_interfaces)
307         self.pg_start()
308
309         rx2 = self.pg0.get_capture(len(tx2))
310         self.verify_encaped_pppoe(self.pg1, rx2, tx2, self.session_id)
311
312         self.logger.info(self.vapi.cli("show pppoe fib"))
313         self.logger.info(self.vapi.cli("show pppoe session"))
314         self.logger.info(self.vapi.cli("show ip fib"))
315         self.logger.info(self.vapi.cli("show adj"))
316
317         #
318         # test case cleanup
319         #
320
321         # Delete PPPoE session
322         pppoe_if.remove_vpp_config()
323
324         # Delete a route that resolves the server's destination
325         route_sever_dst.remove_vpp_config()
326
327     def test_PPPoE_Add_Twice(self):
328         """PPPoE Add Same Session Twice Test"""
329
330         self.vapi.cli("clear trace")
331
332         #
333         # Add a route that resolves the server's destination
334         #
335         route_sever_dst = VppIpRoute(
336             self,
337             "100.1.1.100",
338             32,
339             [VppRoutePath(self.pg1.remote_ip4, self.pg1.sw_if_index)],
340         )
341         route_sever_dst.add_vpp_config()
342
343         # Send PPPoE Discovery
344         tx0 = self.create_stream_pppoe_discovery(
345             self.pg0, self.pg1, self.pg0.remote_mac
346         )
347         self.pg0.add_stream(tx0)
348         self.pg_start()
349
350         # Send PPPoE PPP LCP
351         tx1 = self.create_stream_pppoe_lcp(
352             self.pg0, self.pg1, self.pg0.remote_mac, self.session_id
353         )
354         self.pg0.add_stream(tx1)
355         self.pg_start()
356
357         # Create PPPoE session
358         pppoe_if = VppPppoeInterface(
359             self, self.pg0.remote_ip4, self.pg0.remote_mac, self.session_id
360         )
361         pppoe_if.add_vpp_config()
362         pppoe_if.set_unnumbered(self.pg0.sw_if_index)
363
364         #
365         # The double create (create the same session twice) should fail,
366         # and we should still be able to use the original
367         #
368         try:
369             pppoe_if.add_vpp_config()
370         except Exception:
371             pass
372         else:
373             self.fail("Double GRE tunnel add does not fail")
374
375         #
376         # test case cleanup
377         #
378
379         # Delete PPPoE session
380         pppoe_if.remove_vpp_config()
381
382         # Delete a route that resolves the server's destination
383         route_sever_dst.remove_vpp_config()
384
385     def test_PPPoE_Del_Twice(self):
386         """PPPoE Delete Same Session Twice Test"""
387
388         self.vapi.cli("clear trace")
389
390         #
391         # Add a route that resolves the server's destination
392         #
393         route_sever_dst = VppIpRoute(
394             self,
395             "100.1.1.100",
396             32,
397             [VppRoutePath(self.pg1.remote_ip4, self.pg1.sw_if_index)],
398         )
399         route_sever_dst.add_vpp_config()
400
401         # Send PPPoE Discovery
402         tx0 = self.create_stream_pppoe_discovery(
403             self.pg0, self.pg1, self.pg0.remote_mac
404         )
405         self.pg0.add_stream(tx0)
406         self.pg_start()
407
408         # Send PPPoE PPP LCP
409         tx1 = self.create_stream_pppoe_lcp(
410             self.pg0, self.pg1, self.pg0.remote_mac, self.session_id
411         )
412         self.pg0.add_stream(tx1)
413         self.pg_start()
414
415         # Create PPPoE session
416         pppoe_if = VppPppoeInterface(
417             self, self.pg0.remote_ip4, self.pg0.remote_mac, self.session_id
418         )
419         pppoe_if.add_vpp_config()
420
421         # Delete PPPoE session
422         pppoe_if.remove_vpp_config()
423
424         #
425         # The double del (del the same session twice) should fail,
426         # and we should still be able to use the original
427         #
428         try:
429             pppoe_if.remove_vpp_config()
430         except Exception:
431             pass
432         else:
433             self.fail("Double GRE tunnel del does not fail")
434
435         #
436         # test case cleanup
437         #
438
439         # Delete a route that resolves the server's destination
440         route_sever_dst.remove_vpp_config()
441
442     def test_PPPoE_Decap_Multiple(self):
443         """PPPoE Decap Multiple Sessions Test"""
444
445         self.vapi.cli("clear trace")
446
447         #
448         # Add a route that resolves the server's destination
449         #
450         route_sever_dst = VppIpRoute(
451             self,
452             "100.1.1.100",
453             32,
454             [VppRoutePath(self.pg1.remote_ip4, self.pg1.sw_if_index)],
455         )
456         route_sever_dst.add_vpp_config()
457
458         # Send PPPoE Discovery 1
459         tx0 = self.create_stream_pppoe_discovery(
460             self.pg0, self.pg1, self.pg0.remote_mac
461         )
462         self.pg0.add_stream(tx0)
463         self.pg_start()
464
465         # Send PPPoE PPP LCP 1
466         tx1 = self.create_stream_pppoe_lcp(
467             self.pg0, self.pg1, self.pg0.remote_mac, self.session_id
468         )
469         self.pg0.add_stream(tx1)
470         self.pg_start()
471
472         # Create PPPoE session 1
473         pppoe_if1 = VppPppoeInterface(
474             self, self.pg0.remote_ip4, self.pg0.remote_mac, self.session_id
475         )
476         pppoe_if1.add_vpp_config()
477         pppoe_if1.set_unnumbered(self.pg0.sw_if_index)
478
479         # Send PPPoE Discovery 2
480         tx3 = self.create_stream_pppoe_discovery(
481             self.pg2, self.pg1, self.pg2.remote_mac
482         )
483         self.pg2.add_stream(tx3)
484         self.pg_start()
485
486         # Send PPPoE PPP LCP 2
487         tx4 = self.create_stream_pppoe_lcp(
488             self.pg2, self.pg1, self.pg2.remote_mac, self.session_id + 1
489         )
490         self.pg2.add_stream(tx4)
491         self.pg_start()
492
493         # Create PPPoE session 2
494         pppoe_if2 = VppPppoeInterface(
495             self, self.pg2.remote_ip4, self.pg2.remote_mac, self.session_id + 1
496         )
497         pppoe_if2.add_vpp_config()
498         pppoe_if2.set_unnumbered(self.pg0.sw_if_index)
499
500         #
501         # Send tunneled packets that match the created tunnel and
502         # are decapped and forwarded
503         #
504         tx2 = self.create_stream_pppoe_ip4(
505             self.pg0,
506             self.pg1,
507             self.pg0.remote_mac,
508             self.session_id,
509             self.pg0.remote_ip4,
510         )
511         self.pg0.add_stream(tx2)
512
513         self.pg_enable_capture(self.pg_interfaces)
514         self.pg_start()
515
516         rx2 = self.pg1.get_capture(len(tx2))
517         self.verify_decapped_pppoe(self.pg0, rx2, tx2)
518
519         tx5 = self.create_stream_pppoe_ip4(
520             self.pg2,
521             self.pg1,
522             self.pg2.remote_mac,
523             self.session_id + 1,
524             self.pg2.remote_ip4,
525         )
526         self.pg2.add_stream(tx5)
527
528         self.pg_enable_capture(self.pg_interfaces)
529         self.pg_start()
530
531         rx5 = self.pg1.get_capture(len(tx5))
532         self.verify_decapped_pppoe(self.pg2, rx5, tx5)
533
534         self.logger.info(self.vapi.cli("show pppoe fib"))
535         self.logger.info(self.vapi.cli("show pppoe session"))
536         self.logger.info(self.vapi.cli("show ip fib"))
537
538         #
539         # test case cleanup
540         #
541
542         # Delete PPPoE session
543         pppoe_if1.remove_vpp_config()
544         pppoe_if2.remove_vpp_config()
545
546         # Delete a route that resolves the server's destination
547         route_sever_dst.remove_vpp_config()
548
549     def test_PPPoE_Encap_Multiple(self):
550         """PPPoE Encap Multiple Sessions Test"""
551
552         self.vapi.cli("clear trace")
553
554         #
555         # Add a route that resolves the server's destination
556         #
557         route_sever_dst = VppIpRoute(
558             self,
559             "100.1.1.100",
560             32,
561             [VppRoutePath(self.pg1.remote_ip4, self.pg1.sw_if_index)],
562         )
563         route_sever_dst.add_vpp_config()
564
565         # Send PPPoE Discovery 1
566         tx0 = self.create_stream_pppoe_discovery(
567             self.pg0, self.pg1, self.pg0.remote_mac
568         )
569         self.pg0.add_stream(tx0)
570         self.pg_start()
571
572         # Send PPPoE PPP LCP 1
573         tx1 = self.create_stream_pppoe_lcp(
574             self.pg0, self.pg1, self.pg0.remote_mac, self.session_id
575         )
576         self.pg0.add_stream(tx1)
577         self.pg_start()
578
579         # Create PPPoE session 1
580         pppoe_if1 = VppPppoeInterface(
581             self, self.pg0.remote_ip4, self.pg0.remote_mac, self.session_id
582         )
583         pppoe_if1.add_vpp_config()
584
585         # Send PPPoE Discovery 2
586         tx3 = self.create_stream_pppoe_discovery(
587             self.pg2, self.pg1, self.pg2.remote_mac
588         )
589         self.pg2.add_stream(tx3)
590         self.pg_start()
591
592         # Send PPPoE PPP LCP 2
593         tx4 = self.create_stream_pppoe_lcp(
594             self.pg2, self.pg1, self.pg2.remote_mac, self.session_id + 1
595         )
596         self.pg2.add_stream(tx4)
597         self.pg_start()
598
599         # Create PPPoE session 2
600         pppoe_if2 = VppPppoeInterface(
601             self, self.pg2.remote_ip4, self.pg2.remote_mac, self.session_id + 1
602         )
603         pppoe_if2.add_vpp_config()
604
605         #
606         # Send a packet stream that is routed into the session
607         #  - packets are PPPoE encapped
608         #
609         self.vapi.cli("clear trace")
610         tx2 = self.create_stream_ip4(
611             self.pg1, self.pg0, self.pg0.remote_ip4, self.dst_ip
612         )
613         self.pg1.add_stream(tx2)
614
615         self.pg_enable_capture(self.pg_interfaces)
616         self.pg_start()
617
618         rx2 = self.pg0.get_capture(len(tx2))
619         self.verify_encaped_pppoe(self.pg1, rx2, tx2, self.session_id)
620
621         tx5 = self.create_stream_ip4(
622             self.pg1, self.pg2, self.pg2.remote_ip4, self.dst_ip
623         )
624         self.pg1.add_stream(tx5)
625
626         self.pg_enable_capture(self.pg_interfaces)
627         self.pg_start()
628
629         rx5 = self.pg2.get_capture(len(tx5))
630         self.verify_encaped_pppoe(self.pg1, rx5, tx5, self.session_id + 1)
631
632         self.logger.info(self.vapi.cli("show pppoe fib"))
633         self.logger.info(self.vapi.cli("show pppoe session"))
634         self.logger.info(self.vapi.cli("show ip fib"))
635
636         #
637         # test case cleanup
638         #
639
640         # Delete PPPoE session
641         pppoe_if1.remove_vpp_config()
642         pppoe_if2.remove_vpp_config()
643
644         # Delete a route that resolves the server's destination
645         route_sever_dst.remove_vpp_config()
646
647
648 if __name__ == "__main__":
649     unittest.main(testRunner=VppTestRunner)