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