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