make test: filter IPv6 RAs out by default
[vpp.git] / test / test_gre.py
1 #!/usr/bin/env python
2
3 import unittest
4 from logging import *
5
6 from framework import VppTestCase, VppTestRunner
7 from vpp_sub_interface import VppDot1QSubint
8 from vpp_gre_interface import VppGreInterface
9 from vpp_ip_route import IpRoute, RoutePath
10 from vpp_papi_provider import L2_VTR_OP
11
12 from scapy.packet import Raw
13 from scapy.layers.l2 import Ether, Dot1Q, GRE
14 from scapy.layers.inet import IP, UDP
15 from scapy.layers.inet6 import IPv6
16 from scapy.volatile import RandMAC, RandIP
17
18 from util import ppp, ppc
19
20
21 class TestGRE(VppTestCase):
22     """ GRE Test Case """
23
24     @classmethod
25     def setUpClass(cls):
26         super(TestGRE, cls).setUpClass()
27
28     def setUp(self):
29         super(TestGRE, self).setUp()
30
31         # create 2 pg interfaces - set one in a non-default table.
32         self.create_pg_interfaces(range(2))
33
34         self.pg1.set_table_ip4(1)
35         for i in self.pg_interfaces:
36             i.admin_up()
37             i.config_ip4()
38             i.resolve_arp()
39
40     def tearDown(self):
41         super(TestGRE, self).tearDown()
42
43     def create_stream_ip4(self, src_if, src_ip, dst_ip):
44         pkts = []
45         for i in range(0, 257):
46             info = self.create_packet_info(src_if.sw_if_index,
47                                            src_if.sw_if_index)
48             payload = self.info_to_payload(info)
49             p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
50                  IP(src=src_ip, dst=dst_ip) /
51                  UDP(sport=1234, dport=1234) /
52                  Raw(payload))
53             info.data = p.copy()
54             pkts.append(p)
55         return pkts
56
57     def create_tunnel_stream_4o4(self, src_if,
58                                  tunnel_src, tunnel_dst,
59                                  src_ip, dst_ip):
60         pkts = []
61         for i in range(0, 257):
62             info = self.create_packet_info(src_if.sw_if_index,
63                                            src_if.sw_if_index)
64             payload = self.info_to_payload(info)
65             p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
66                  IP(src=tunnel_src, dst=tunnel_dst) /
67                  GRE() /
68                  IP(src=src_ip, dst=dst_ip) /
69                  UDP(sport=1234, dport=1234) /
70                  Raw(payload))
71             info.data = p.copy()
72             pkts.append(p)
73         return pkts
74
75     def create_tunnel_stream_6o4(self, src_if,
76                                  tunnel_src, tunnel_dst,
77                                  src_ip, dst_ip):
78         pkts = []
79         for i in range(0, 257):
80             info = self.create_packet_info(src_if.sw_if_index,
81                                            src_if.sw_if_index)
82             payload = self.info_to_payload(info)
83             p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
84                  IP(src=tunnel_src, dst=tunnel_dst) /
85                  GRE() /
86                  IPv6(src=src_ip, dst=dst_ip) /
87                  UDP(sport=1234, dport=1234) /
88                  Raw(payload))
89             info.data = p.copy()
90             pkts.append(p)
91         return pkts
92
93     def create_tunnel_stream_l2o4(self, src_if,
94                                   tunnel_src, tunnel_dst):
95         pkts = []
96         for i in range(0, 257):
97             info = self.create_packet_info(src_if.sw_if_index,
98                                            src_if.sw_if_index)
99             payload = self.info_to_payload(info)
100             p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
101                  IP(src=tunnel_src, dst=tunnel_dst) /
102                  GRE() /
103                  Ether(dst=RandMAC('*:*:*:*:*:*'),
104                        src=RandMAC('*:*:*:*:*:*')) /
105                  IP(src=str(RandIP()), dst=str(RandIP())) /
106                  UDP(sport=1234, dport=1234) /
107                  Raw(payload))
108             info.data = p.copy()
109             pkts.append(p)
110         return pkts
111
112     def create_tunnel_stream_vlano4(self, src_if,
113                                     tunnel_src, tunnel_dst, vlan):
114         pkts = []
115         for i in range(0, 257):
116             info = self.create_packet_info(src_if.sw_if_index,
117                                            src_if.sw_if_index)
118             payload = self.info_to_payload(info)
119             p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
120                  IP(src=tunnel_src, dst=tunnel_dst) /
121                  GRE() /
122                  Ether(dst=RandMAC('*:*:*:*:*:*'),
123                        src=RandMAC('*:*:*:*:*:*')) /
124                  Dot1Q(vlan=vlan) /
125                  IP(src=str(RandIP()), dst=str(RandIP())) /
126                  UDP(sport=1234, dport=1234) /
127                  Raw(payload))
128             info.data = p.copy()
129             pkts.append(p)
130         return pkts
131
132     def verify_tunneled_4o4(self, src_if, capture, sent,
133                             tunnel_src, tunnel_dst):
134
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, tunnel_src)
146                 self.assertEqual(rx_ip.dst, tunnel_dst)
147
148                 rx_gre = rx[GRE]
149                 rx_ip = rx_gre[IP]
150
151                 self.assertEqual(rx_ip.src, tx_ip.src)
152                 self.assertEqual(rx_ip.dst, tx_ip.dst)
153                 # IP processing post pop has decremented the TTL
154                 self.assertEqual(rx_ip.ttl + 1, tx_ip.ttl)
155
156             except:
157                 self.logger.error(ppp("Rx:", rx))
158                 self.logger.error(ppp("Tx:", tx))
159                 raise
160
161     def verify_tunneled_l2o4(self, src_if, capture, sent,
162                              tunnel_src, tunnel_dst):
163         self.assertEqual(len(capture), len(sent))
164
165         for i in range(len(capture)):
166             try:
167                 tx = sent[i]
168                 rx = capture[i]
169
170                 tx_ip = tx[IP]
171                 rx_ip = rx[IP]
172
173                 self.assertEqual(rx_ip.src, tunnel_src)
174                 self.assertEqual(rx_ip.dst, tunnel_dst)
175
176                 rx_gre = rx[GRE]
177                 rx_l2 = rx_gre[Ether]
178                 rx_ip = rx_l2[IP]
179                 tx_gre = tx[GRE]
180                 tx_l2 = tx_gre[Ether]
181                 tx_ip = tx_l2[IP]
182
183                 self.assertEqual(rx_ip.src, tx_ip.src)
184                 self.assertEqual(rx_ip.dst, tx_ip.dst)
185                 # bridged, not L3 forwarded, so no TTL decrement
186                 self.assertEqual(rx_ip.ttl, tx_ip.ttl)
187
188             except:
189                 self.logger.error(ppp("Rx:", rx))
190                 self.logger.error(ppp("Tx:", tx))
191                 raise
192
193     def verify_tunneled_vlano4(self, src_if, capture, sent,
194                                tunnel_src, tunnel_dst, vlan):
195         try:
196             self.assertEqual(len(capture), len(sent))
197         except:
198             ppc("Unexpected packets captured:", capture)
199             raise
200
201         for i in range(len(capture)):
202             try:
203                 tx = sent[i]
204                 rx = capture[i]
205
206                 tx_ip = tx[IP]
207                 rx_ip = rx[IP]
208
209                 self.assertEqual(rx_ip.src, tunnel_src)
210                 self.assertEqual(rx_ip.dst, tunnel_dst)
211
212                 rx_gre = rx[GRE]
213                 rx_l2 = rx_gre[Ether]
214                 rx_vlan = rx_l2[Dot1Q]
215                 rx_ip = rx_l2[IP]
216
217                 self.assertEqual(rx_vlan.vlan, vlan)
218
219                 tx_gre = tx[GRE]
220                 tx_l2 = tx_gre[Ether]
221                 tx_ip = tx_l2[IP]
222
223                 self.assertEqual(rx_ip.src, tx_ip.src)
224                 self.assertEqual(rx_ip.dst, tx_ip.dst)
225                 # bridged, not L3 forwarded, so no TTL decrement
226                 self.assertEqual(rx_ip.ttl, tx_ip.ttl)
227
228             except:
229                 self.logger.error(ppp("Rx:", rx))
230                 self.logger.error(ppp("Tx:", tx))
231                 raise
232
233     def verify_decapped_4o4(self, src_if, capture, sent):
234         self.assertEqual(len(capture), len(sent))
235
236         for i in range(len(capture)):
237             try:
238                 tx = sent[i]
239                 rx = capture[i]
240
241                 tx_ip = tx[IP]
242                 rx_ip = rx[IP]
243                 tx_gre = tx[GRE]
244                 tx_ip = tx_gre[IP]
245
246                 self.assertEqual(rx_ip.src, tx_ip.src)
247                 self.assertEqual(rx_ip.dst, tx_ip.dst)
248                 # IP processing post pop has decremented the TTL
249                 self.assertEqual(rx_ip.ttl + 1, tx_ip.ttl)
250
251             except:
252                 self.logger.error(ppp("Rx:", rx))
253                 self.logger.error(ppp("Tx:", tx))
254                 raise
255
256     def verify_decapped_6o4(self, src_if, capture, sent):
257         self.assertEqual(len(capture), len(sent))
258
259         for i in range(len(capture)):
260             try:
261                 tx = sent[i]
262                 rx = capture[i]
263
264                 tx_ip = tx[IP]
265                 rx_ip = rx[IPv6]
266                 tx_gre = tx[GRE]
267                 tx_ip = tx_gre[IPv6]
268
269                 self.assertEqual(rx_ip.src, tx_ip.src)
270                 self.assertEqual(rx_ip.dst, tx_ip.dst)
271                 self.assertEqual(rx_ip.hlim + 1, tx_ip.hlim)
272
273             except:
274                 self.logger.error(ppp("Rx:", rx))
275                 self.logger.error(ppp("Tx:", tx))
276                 raise
277
278     def test_gre(self):
279         """ GRE tunnel Tests """
280
281         #
282         # Create an L3 GRE tunnel.
283         #  - set it admin up
284         #  - assign an IP Addres
285         #  - Add a route via the tunnel
286         #
287         gre_if = VppGreInterface(self,
288                                  self.pg0.local_ip4,
289                                  "1.1.1.2")
290         gre_if.add_vpp_config()
291
292         #
293         # The double create (create the same tunnel twice) should fail,
294         # and we should still be able to use the original
295         #
296         try:
297             gre_if.add_vpp_config()
298         except Exception:
299             pass
300         else:
301             self.fail("Double GRE tunnel add does not fail")
302
303         gre_if.admin_up()
304         gre_if.config_ip4()
305
306         route_via_tun = IpRoute(self, "4.4.4.4", 32,
307                                 [RoutePath("0.0.0.0", gre_if.sw_if_index)])
308
309         route_via_tun.add_vpp_config()
310
311         #
312         # Send a packet stream that is routed into the tunnel
313         #  - they are all dropped since the tunnel's desintation IP
314         #    is unresolved - or resolves via the default route - which
315         #    which is a drop.
316         #
317         tx = self.create_stream_ip4(self.pg0, "5.5.5.5", "4.4.4.4")
318         self.pg0.add_stream(tx)
319
320         self.pg_enable_capture(self.pg_interfaces)
321         self.pg_start()
322
323         self.pg0.assert_nothing_captured(
324             remark="GRE packets forwarded without DIP resolved")
325
326         #
327         # Add a route that resolves the tunnel's destination
328         #
329         route_tun_dst = IpRoute(self, "1.1.1.2", 32,
330                                 [RoutePath(self.pg0.remote_ip4,
331                                            self.pg0.sw_if_index)])
332         route_tun_dst.add_vpp_config()
333
334         #
335         # Send a packet stream that is routed into the tunnel
336         #  - packets are GRE encapped
337         #
338         self.vapi.cli("clear trace")
339         tx = self.create_stream_ip4(self.pg0, "5.5.5.5", "4.4.4.4")
340         self.pg0.add_stream(tx)
341
342         self.pg_enable_capture(self.pg_interfaces)
343         self.pg_start()
344
345         rx = self.pg0.get_capture()
346         self.verify_tunneled_4o4(self.pg0, rx, tx,
347                                  self.pg0.local_ip4, "1.1.1.2")
348
349         #
350         # Send tunneled packets that match the created tunnel and
351         # are decapped and forwarded
352         #
353         self.vapi.cli("clear trace")
354         tx = self.create_tunnel_stream_4o4(self.pg0,
355                                            "1.1.1.2",
356                                            self.pg0.local_ip4,
357                                            self.pg0.local_ip4,
358                                            self.pg0.remote_ip4)
359         self.pg0.add_stream(tx)
360
361         self.pg_enable_capture(self.pg_interfaces)
362         self.pg_start()
363
364         rx = self.pg0.get_capture()
365         self.verify_decapped_4o4(self.pg0, rx, tx)
366
367         #
368         # Send tunneled packets that do not match the tunnel's src
369         #
370         self.vapi.cli("clear trace")
371         tx = self.create_tunnel_stream_4o4(self.pg0,
372                                            "1.1.1.3",
373                                            self.pg0.local_ip4,
374                                            self.pg0.local_ip4,
375                                            self.pg0.remote_ip4)
376         self.pg0.add_stream(tx)
377
378         self.pg_enable_capture(self.pg_interfaces)
379         self.pg_start()
380
381         self.pg0.assert_nothing_captured(
382             remark="GRE packets forwarded despite no SRC address match")
383
384         #
385         # Configure IPv6 on the PG interface so we can route IPv6
386         # packets
387         #
388         self.pg0.config_ip6()
389         self.pg0.resolve_ndp()
390
391         #
392         # Send IPv6 tunnel encapslated packets
393         #  - dropped since IPv6 is not enabled on the tunnel
394         #
395         self.vapi.cli("clear trace")
396         tx = self.create_tunnel_stream_6o4(self.pg0,
397                                            "1.1.1.2",
398                                            self.pg0.local_ip4,
399                                            self.pg0.local_ip6,
400                                            self.pg0.remote_ip6)
401         self.pg0.add_stream(tx)
402
403         self.pg_enable_capture(self.pg_interfaces)
404         self.pg_start()
405
406         self.pg0.assert_nothing_captured(remark="IPv6 GRE packets forwarded "
407                                          "despite IPv6 not enabled on tunnel")
408
409         #
410         # Enable IPv6 on the tunnel
411         #
412         gre_if.config_ip6()
413
414         #
415         # Send IPv6 tunnel encapslated packets
416         #  - forwarded since IPv6 is enabled on the tunnel
417         #
418         self.vapi.cli("clear trace")
419         tx = self.create_tunnel_stream_6o4(self.pg0,
420                                            "1.1.1.2",
421                                            self.pg0.local_ip4,
422                                            self.pg0.local_ip6,
423                                            self.pg0.remote_ip6)
424         self.pg0.add_stream(tx)
425
426         self.pg_enable_capture(self.pg_interfaces)
427         self.pg_start()
428
429         rx = self.pg0.get_capture()
430         self.verify_decapped_6o4(self.pg0, rx, tx)
431
432         #
433         # test case cleanup
434         #
435         route_tun_dst.remove_vpp_config()
436         route_via_tun.remove_vpp_config()
437         gre_if.remove_vpp_config()
438
439         self.pg0.unconfig_ip6()
440
441     def test_gre_vrf(self):
442         """ GRE tunnel VRF Tests """
443
444         #
445         # Create an L3 GRE tunnel whose destination is in the non-default
446         # table. The underlay is thus non-default - the overlay is still
447         # the default.
448         #  - set it admin up
449         #  - assign an IP Addres
450         #
451         gre_if = VppGreInterface(self, self.pg1.local_ip4,
452                                  "2.2.2.2",
453                                  outer_fib_id=1)
454         gre_if.add_vpp_config()
455         gre_if.admin_up()
456         gre_if.config_ip4()
457
458         #
459         # Add a route via the tunnel - in the overlay
460         #
461         route_via_tun = IpRoute(self, "9.9.9.9", 32,
462                                 [RoutePath("0.0.0.0", gre_if.sw_if_index)])
463         route_via_tun.add_vpp_config()
464
465         #
466         # Add a route that resolves the tunnel's destination - in the
467         # underlay table
468         #
469         route_tun_dst = IpRoute(self, "2.2.2.2", 32, table_id=1,
470                                 paths=[RoutePath(self.pg1.remote_ip4,
471                                                  self.pg1.sw_if_index)])
472         route_tun_dst.add_vpp_config()
473
474         #
475         # Send a packet stream that is routed into the tunnel
476         # packets are sent in on pg0 which is in the default table
477         #  - packets are GRE encapped
478         #
479         self.vapi.cli("clear trace")
480         tx = self.create_stream_ip4(self.pg0, "5.5.5.5", "9.9.9.9")
481         self.pg0.add_stream(tx)
482
483         self.pg_enable_capture(self.pg_interfaces)
484         self.pg_start()
485
486         rx = self.pg1.get_capture()
487         self.verify_tunneled_4o4(self.pg1, rx, tx,
488                                  self.pg1.local_ip4, "2.2.2.2")
489
490         #
491         # Send tunneled packets that match the created tunnel and
492         # are decapped and forwarded. This tests the decap lookup
493         # does not happen in the encap table
494         #
495         self.vapi.cli("clear trace")
496         tx = self.create_tunnel_stream_4o4(self.pg1,
497                                            "2.2.2.2",
498                                            self.pg1.local_ip4,
499                                            self.pg0.local_ip4,
500                                            self.pg0.remote_ip4)
501         self.pg1.add_stream(tx)
502
503         self.pg_enable_capture(self.pg_interfaces)
504         self.pg_start()
505
506         rx = self.pg0.get_capture()
507         self.verify_decapped_4o4(self.pg0, rx, tx)
508
509         #
510         # test case cleanup
511         #
512         route_tun_dst.remove_vpp_config()
513         route_via_tun.remove_vpp_config()
514         gre_if.remove_vpp_config()
515
516     def test_gre_l2(self):
517         """ GRE tunnel L2 Tests """
518
519         #
520         # Add routes to resolve the tunnel destinations
521         #
522         route_tun1_dst = IpRoute(self, "2.2.2.2", 32,
523                                  [RoutePath(self.pg0.remote_ip4,
524                                             self.pg0.sw_if_index)])
525         route_tun2_dst = IpRoute(self, "2.2.2.3", 32,
526                                  [RoutePath(self.pg0.remote_ip4,
527                                             self.pg0.sw_if_index)])
528
529         route_tun1_dst.add_vpp_config()
530         route_tun2_dst.add_vpp_config()
531
532         #
533         # Create 2 L2 GRE tunnels and x-connect them
534         #
535         gre_if1 = VppGreInterface(self, self.pg0.local_ip4,
536                                   "2.2.2.2",
537                                   is_teb=1)
538         gre_if2 = VppGreInterface(self, self.pg0.local_ip4,
539                                   "2.2.2.3",
540                                   is_teb=1)
541         gre_if1.add_vpp_config()
542         gre_if2.add_vpp_config()
543
544         gre_if1.admin_up()
545         gre_if2.admin_up()
546
547         self.vapi.sw_interface_set_l2_xconnect(gre_if1.sw_if_index,
548                                                gre_if2.sw_if_index,
549                                                enable=1)
550         self.vapi.sw_interface_set_l2_xconnect(gre_if2.sw_if_index,
551                                                gre_if1.sw_if_index,
552                                                enable=1)
553
554         #
555         # Send in tunnel encapped L2. expect out tunnel encapped L2
556         # in both directions
557         #
558         self.vapi.cli("clear trace")
559         tx = self.create_tunnel_stream_l2o4(self.pg0,
560                                             "2.2.2.2",
561                                             self.pg0.local_ip4)
562         self.pg0.add_stream(tx)
563
564         self.pg_enable_capture(self.pg_interfaces)
565         self.pg_start()
566
567         rx = self.pg0.get_capture()
568         self.verify_tunneled_l2o4(self.pg0, rx, tx,
569                                   self.pg0.local_ip4,
570                                   "2.2.2.3")
571
572         self.vapi.cli("clear trace")
573         tx = self.create_tunnel_stream_l2o4(self.pg0,
574                                             "2.2.2.3",
575                                             self.pg0.local_ip4)
576         self.pg0.add_stream(tx)
577
578         self.pg_enable_capture(self.pg_interfaces)
579         self.pg_start()
580
581         rx = self.pg0.get_capture()
582         self.verify_tunneled_l2o4(self.pg0, rx, tx,
583                                   self.pg0.local_ip4,
584                                   "2.2.2.2")
585
586         self.vapi.sw_interface_set_l2_xconnect(gre_if1.sw_if_index,
587                                                gre_if2.sw_if_index,
588                                                enable=0)
589         self.vapi.sw_interface_set_l2_xconnect(gre_if2.sw_if_index,
590                                                gre_if1.sw_if_index,
591                                                enable=0)
592
593         #
594         # Create a VLAN sub-interfaces on the GRE TEB interfaces
595         # then x-connect them
596         #
597         gre_if_11 = VppDot1QSubint(self, gre_if1, 11)
598         gre_if_12 = VppDot1QSubint(self, gre_if2, 12)
599
600         # gre_if_11.add_vpp_config()
601         # gre_if_12.add_vpp_config()
602
603         gre_if_11.admin_up()
604         gre_if_12.admin_up()
605
606         self.vapi.sw_interface_set_l2_xconnect(gre_if_11.sw_if_index,
607                                                gre_if_12.sw_if_index,
608                                                enable=1)
609         self.vapi.sw_interface_set_l2_xconnect(gre_if_12.sw_if_index,
610                                                gre_if_11.sw_if_index,
611                                                enable=1)
612
613         #
614         # Configure both to pop thier respective VLAN tags,
615         # so that during the x-coonect they will subsequently push
616         #
617         self.vapi.sw_interface_set_l2_tag_rewrite(gre_if_12.sw_if_index,
618                                                   L2_VTR_OP.L2_POP_1,
619                                                   12)
620         self.vapi.sw_interface_set_l2_tag_rewrite(gre_if_11.sw_if_index,
621                                                   L2_VTR_OP.L2_POP_1,
622                                                   11)
623
624         #
625         # Send traffic in both directiond - expect the VLAN tags to
626         # be swapped.
627         #
628         self.vapi.cli("clear trace")
629         tx = self.create_tunnel_stream_vlano4(self.pg0,
630                                               "2.2.2.2",
631                                               self.pg0.local_ip4,
632                                               11)
633         self.pg0.add_stream(tx)
634
635         self.pg_enable_capture(self.pg_interfaces)
636         self.pg_start()
637
638         rx = self.pg0.get_capture()
639         self.verify_tunneled_vlano4(self.pg0, rx, tx,
640                                     self.pg0.local_ip4,
641                                     "2.2.2.3",
642                                     12)
643
644         self.vapi.cli("clear trace")
645         tx = self.create_tunnel_stream_vlano4(self.pg0,
646                                               "2.2.2.3",
647                                               self.pg0.local_ip4,
648                                               12)
649         self.pg0.add_stream(tx)
650
651         self.pg_enable_capture(self.pg_interfaces)
652         self.pg_start()
653
654         rx = self.pg0.get_capture()
655         self.verify_tunneled_vlano4(self.pg0, rx, tx,
656                                     self.pg0.local_ip4,
657                                     "2.2.2.2",
658                                     11)
659
660         #
661         # Cleanup Test resources
662         #
663         gre_if_11.remove_vpp_config()
664         gre_if_12.remove_vpp_config()
665         gre_if1.remove_vpp_config()
666         gre_if2.remove_vpp_config()
667         route_tun1_dst.add_vpp_config()
668         route_tun2_dst.add_vpp_config()
669
670
671 if __name__ == '__main__':
672     unittest.main(testRunner=VppTestRunner)