tunnel: Common types for IP tunnels
[vpp.git] / test / test_gre.py
1 #!/usr/bin/env python3
2
3 import unittest
4
5 import scapy.compat
6 from scapy.packet import Raw
7 from scapy.layers.l2 import Ether, Dot1Q, GRE
8 from scapy.layers.inet import IP, UDP
9 from scapy.layers.inet6 import IPv6
10 from scapy.volatile import RandMAC, RandIP
11
12 from framework import VppTestCase, VppTestRunner
13 from vpp_sub_interface import L2_VTR_OP, VppDot1QSubint
14 from vpp_gre_interface import VppGreInterface
15 from vpp_nhrp import VppNhrp
16 from vpp_ip import DpoProto
17 from vpp_ip_route import VppIpRoute, VppRoutePath, VppIpTable, FibPathProto
18 from util import ppp, ppc
19 from vpp_papi import VppEnum
20
21
22 class TestGREInputNodes(VppTestCase):
23     """ GRE Input Nodes Test Case """
24
25     def setUp(self):
26         super(TestGREInputNodes, self).setUp()
27
28         # create 3 pg interfaces - set one in a non-default table.
29         self.create_pg_interfaces(range(1))
30
31         for i in self.pg_interfaces:
32             i.admin_up()
33             i.config_ip4()
34
35     def tearDown(self):
36         for i in self.pg_interfaces:
37             i.unconfig_ip4()
38             i.admin_down()
39         super(TestGREInputNodes, self).tearDown()
40
41     def test_gre_input_node(self):
42         """ GRE gre input nodes not registerd unless configured """
43         pkt = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
44                IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4) /
45                GRE())
46
47         self.pg0.add_stream(pkt)
48         self.pg_start()
49         # no tunnel created, gre-input not registered
50         err = self.statistics.get_counter(
51             '/err/ip4-input/unknown ip protocol')[0]
52         self.assertEqual(err, 1)
53         err_count = err
54
55         # create gre tunnel
56         gre_if = VppGreInterface(self, self.pg0.local_ip4, "1.1.1.2")
57         gre_if.add_vpp_config()
58
59         self.pg0.add_stream(pkt)
60         self.pg_start()
61         # tunnel created, gre-input registered
62         err = self.statistics.get_counter(
63             '/err/ip4-input/unknown ip protocol')[0]
64         # expect no new errors
65         self.assertEqual(err, err_count)
66
67
68 class TestGRE(VppTestCase):
69     """ GRE Test Case """
70
71     @classmethod
72     def setUpClass(cls):
73         super(TestGRE, cls).setUpClass()
74
75     @classmethod
76     def tearDownClass(cls):
77         super(TestGRE, cls).tearDownClass()
78
79     def setUp(self):
80         super(TestGRE, self).setUp()
81
82         # create 3 pg interfaces - set one in a non-default table.
83         self.create_pg_interfaces(range(5))
84
85         self.tbl = VppIpTable(self, 1)
86         self.tbl.add_vpp_config()
87         self.pg1.set_table_ip4(1)
88
89         for i in self.pg_interfaces:
90             i.admin_up()
91
92         self.pg0.config_ip4()
93         self.pg0.resolve_arp()
94         self.pg1.config_ip4()
95         self.pg1.resolve_arp()
96         self.pg2.config_ip6()
97         self.pg2.resolve_ndp()
98         self.pg3.config_ip4()
99         self.pg3.resolve_arp()
100         self.pg4.config_ip4()
101         self.pg4.resolve_arp()
102
103     def tearDown(self):
104         for i in self.pg_interfaces:
105             i.unconfig_ip4()
106             i.unconfig_ip6()
107             i.admin_down()
108         self.pg1.set_table_ip4(0)
109         super(TestGRE, self).tearDown()
110
111     def create_stream_ip4(self, src_if, src_ip, dst_ip):
112         pkts = []
113         for i in range(0, 257):
114             info = self.create_packet_info(src_if, src_if)
115             payload = self.info_to_payload(info)
116             p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
117                  IP(src=src_ip, dst=dst_ip) /
118                  UDP(sport=1234, dport=1234) /
119                  Raw(payload))
120             info.data = p.copy()
121             pkts.append(p)
122         return pkts
123
124     def create_stream_ip6(self, src_if, src_ip, dst_ip):
125         pkts = []
126         for i in range(0, 257):
127             info = self.create_packet_info(src_if, src_if)
128             payload = self.info_to_payload(info)
129             p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
130                  IPv6(src=src_ip, dst=dst_ip) /
131                  UDP(sport=1234, dport=1234) /
132                  Raw(payload))
133             info.data = p.copy()
134             pkts.append(p)
135         return pkts
136
137     def create_tunnel_stream_4o4(self, src_if,
138                                  tunnel_src, tunnel_dst,
139                                  src_ip, dst_ip):
140         pkts = []
141         for i in range(0, 257):
142             info = self.create_packet_info(src_if, src_if)
143             payload = self.info_to_payload(info)
144             p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
145                  IP(src=tunnel_src, dst=tunnel_dst) /
146                  GRE() /
147                  IP(src=src_ip, dst=dst_ip) /
148                  UDP(sport=1234, dport=1234) /
149                  Raw(payload))
150             info.data = p.copy()
151             pkts.append(p)
152         return pkts
153
154     def create_tunnel_stream_6o4(self, src_if,
155                                  tunnel_src, tunnel_dst,
156                                  src_ip, dst_ip):
157         pkts = []
158         for i in range(0, 257):
159             info = self.create_packet_info(src_if, src_if)
160             payload = self.info_to_payload(info)
161             p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
162                  IP(src=tunnel_src, dst=tunnel_dst) /
163                  GRE() /
164                  IPv6(src=src_ip, dst=dst_ip) /
165                  UDP(sport=1234, dport=1234) /
166                  Raw(payload))
167             info.data = p.copy()
168             pkts.append(p)
169         return pkts
170
171     def create_tunnel_stream_6o6(self, src_if,
172                                  tunnel_src, tunnel_dst,
173                                  src_ip, dst_ip):
174         pkts = []
175         for i in range(0, 257):
176             info = self.create_packet_info(src_if, src_if)
177             payload = self.info_to_payload(info)
178             p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
179                  IPv6(src=tunnel_src, dst=tunnel_dst) /
180                  GRE() /
181                  IPv6(src=src_ip, dst=dst_ip) /
182                  UDP(sport=1234, dport=1234) /
183                  Raw(payload))
184             info.data = p.copy()
185             pkts.append(p)
186         return pkts
187
188     def create_tunnel_stream_l2o4(self, src_if,
189                                   tunnel_src, tunnel_dst):
190         pkts = []
191         for i in range(0, 257):
192             info = self.create_packet_info(src_if, src_if)
193             payload = self.info_to_payload(info)
194             p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
195                  IP(src=tunnel_src, dst=tunnel_dst) /
196                  GRE() /
197                  Ether(dst=RandMAC('*:*:*:*:*:*'),
198                        src=RandMAC('*:*:*:*:*:*')) /
199                  IP(src=scapy.compat.raw(RandIP()),
200                     dst=scapy.compat.raw(RandIP())) /
201                  UDP(sport=1234, dport=1234) /
202                  Raw(payload))
203             info.data = p.copy()
204             pkts.append(p)
205         return pkts
206
207     def create_tunnel_stream_vlano4(self, src_if,
208                                     tunnel_src, tunnel_dst, vlan):
209         pkts = []
210         for i in range(0, 257):
211             info = self.create_packet_info(src_if, src_if)
212             payload = self.info_to_payload(info)
213             p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
214                  IP(src=tunnel_src, dst=tunnel_dst) /
215                  GRE() /
216                  Ether(dst=RandMAC('*:*:*:*:*:*'),
217                        src=RandMAC('*:*:*:*:*:*')) /
218                  Dot1Q(vlan=vlan) /
219                  IP(src=scapy.compat.raw(RandIP()),
220                     dst=scapy.compat.raw(RandIP())) /
221                  UDP(sport=1234, dport=1234) /
222                  Raw(payload))
223             info.data = p.copy()
224             pkts.append(p)
225         return pkts
226
227     def verify_tunneled_4o4(self, src_if, capture, sent,
228                             tunnel_src, tunnel_dst):
229
230         self.assertEqual(len(capture), len(sent))
231
232         for i in range(len(capture)):
233             try:
234                 tx = sent[i]
235                 rx = capture[i]
236
237                 tx_ip = tx[IP]
238                 rx_ip = rx[IP]
239
240                 self.assertEqual(rx_ip.src, tunnel_src)
241                 self.assertEqual(rx_ip.dst, tunnel_dst)
242
243                 rx_gre = rx[GRE]
244                 rx_ip = rx_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_tunneled_6o6(self, src_if, capture, sent,
257                             tunnel_src, tunnel_dst):
258
259         self.assertEqual(len(capture), len(sent))
260
261         for i in range(len(capture)):
262             try:
263                 tx = sent[i]
264                 rx = capture[i]
265
266                 tx_ip = tx[IPv6]
267                 rx_ip = rx[IPv6]
268
269                 self.assertEqual(rx_ip.src, tunnel_src)
270                 self.assertEqual(rx_ip.dst, tunnel_dst)
271
272                 rx_gre = GRE(scapy.compat.raw(rx_ip[IPv6].payload))
273                 rx_ip = rx_gre[IPv6]
274
275                 self.assertEqual(rx_ip.src, tx_ip.src)
276                 self.assertEqual(rx_ip.dst, tx_ip.dst)
277
278             except:
279                 self.logger.error(ppp("Rx:", rx))
280                 self.logger.error(ppp("Tx:", tx))
281                 raise
282
283     def verify_tunneled_4o6(self, src_if, capture, sent,
284                             tunnel_src, tunnel_dst):
285
286         self.assertEqual(len(capture), len(sent))
287
288         for i in range(len(capture)):
289             try:
290                 tx = sent[i]
291                 rx = capture[i]
292
293                 rx_ip = rx[IPv6]
294
295                 self.assertEqual(rx_ip.src, tunnel_src)
296                 self.assertEqual(rx_ip.dst, tunnel_dst)
297
298                 rx_gre = GRE(scapy.compat.raw(rx_ip[IPv6].payload))
299                 tx_ip = tx[IP]
300                 rx_ip = rx_gre[IP]
301
302                 self.assertEqual(rx_ip.src, tx_ip.src)
303                 self.assertEqual(rx_ip.dst, tx_ip.dst)
304
305             except:
306                 self.logger.error(ppp("Rx:", rx))
307                 self.logger.error(ppp("Tx:", tx))
308                 raise
309
310     def verify_tunneled_6o4(self, src_if, capture, sent,
311                             tunnel_src, tunnel_dst):
312
313         self.assertEqual(len(capture), len(sent))
314
315         for i in range(len(capture)):
316             try:
317                 tx = sent[i]
318                 rx = capture[i]
319
320                 rx_ip = rx[IP]
321
322                 self.assertEqual(rx_ip.src, tunnel_src)
323                 self.assertEqual(rx_ip.dst, tunnel_dst)
324
325                 rx_gre = GRE(scapy.compat.raw(rx_ip[IP].payload))
326                 rx_ip = rx_gre[IPv6]
327                 tx_ip = tx[IPv6]
328
329                 self.assertEqual(rx_ip.src, tx_ip.src)
330                 self.assertEqual(rx_ip.dst, tx_ip.dst)
331
332             except:
333                 self.logger.error(ppp("Rx:", rx))
334                 self.logger.error(ppp("Tx:", tx))
335                 raise
336
337     def verify_tunneled_l2o4(self, src_if, capture, sent,
338                              tunnel_src, tunnel_dst):
339         self.assertEqual(len(capture), len(sent))
340
341         for i in range(len(capture)):
342             try:
343                 tx = sent[i]
344                 rx = capture[i]
345
346                 tx_ip = tx[IP]
347                 rx_ip = rx[IP]
348
349                 self.assertEqual(rx_ip.src, tunnel_src)
350                 self.assertEqual(rx_ip.dst, tunnel_dst)
351
352                 rx_gre = rx[GRE]
353                 rx_l2 = rx_gre[Ether]
354                 rx_ip = rx_l2[IP]
355                 tx_gre = tx[GRE]
356                 tx_l2 = tx_gre[Ether]
357                 tx_ip = tx_l2[IP]
358
359                 self.assertEqual(rx_ip.src, tx_ip.src)
360                 self.assertEqual(rx_ip.dst, tx_ip.dst)
361                 # bridged, not L3 forwarded, so no TTL decrement
362                 self.assertEqual(rx_ip.ttl, tx_ip.ttl)
363
364             except:
365                 self.logger.error(ppp("Rx:", rx))
366                 self.logger.error(ppp("Tx:", tx))
367                 raise
368
369     def verify_tunneled_vlano4(self, src_if, capture, sent,
370                                tunnel_src, tunnel_dst, vlan):
371         try:
372             self.assertEqual(len(capture), len(sent))
373         except:
374             ppc("Unexpected packets captured:", capture)
375             raise
376
377         for i in range(len(capture)):
378             try:
379                 tx = sent[i]
380                 rx = capture[i]
381
382                 tx_ip = tx[IP]
383                 rx_ip = rx[IP]
384
385                 self.assertEqual(rx_ip.src, tunnel_src)
386                 self.assertEqual(rx_ip.dst, tunnel_dst)
387
388                 rx_gre = rx[GRE]
389                 rx_l2 = rx_gre[Ether]
390                 rx_vlan = rx_l2[Dot1Q]
391                 rx_ip = rx_l2[IP]
392
393                 self.assertEqual(rx_vlan.vlan, vlan)
394
395                 tx_gre = tx[GRE]
396                 tx_l2 = tx_gre[Ether]
397                 tx_ip = tx_l2[IP]
398
399                 self.assertEqual(rx_ip.src, tx_ip.src)
400                 self.assertEqual(rx_ip.dst, tx_ip.dst)
401                 # bridged, not L3 forwarded, so no TTL decrement
402                 self.assertEqual(rx_ip.ttl, tx_ip.ttl)
403
404             except:
405                 self.logger.error(ppp("Rx:", rx))
406                 self.logger.error(ppp("Tx:", tx))
407                 raise
408
409     def verify_decapped_4o4(self, src_if, capture, sent):
410         self.assertEqual(len(capture), len(sent))
411
412         for i in range(len(capture)):
413             try:
414                 tx = sent[i]
415                 rx = capture[i]
416
417                 tx_ip = tx[IP]
418                 rx_ip = rx[IP]
419                 tx_gre = tx[GRE]
420                 tx_ip = tx_gre[IP]
421
422                 self.assertEqual(rx_ip.src, tx_ip.src)
423                 self.assertEqual(rx_ip.dst, tx_ip.dst)
424                 # IP processing post pop has decremented the TTL
425                 self.assertEqual(rx_ip.ttl + 1, tx_ip.ttl)
426
427             except:
428                 self.logger.error(ppp("Rx:", rx))
429                 self.logger.error(ppp("Tx:", tx))
430                 raise
431
432     def verify_decapped_6o4(self, src_if, capture, sent):
433         self.assertEqual(len(capture), len(sent))
434
435         for i in range(len(capture)):
436             try:
437                 tx = sent[i]
438                 rx = capture[i]
439
440                 tx_ip = tx[IP]
441                 rx_ip = rx[IPv6]
442                 tx_gre = tx[GRE]
443                 tx_ip = tx_gre[IPv6]
444
445                 self.assertEqual(rx_ip.src, tx_ip.src)
446                 self.assertEqual(rx_ip.dst, tx_ip.dst)
447                 self.assertEqual(rx_ip.hlim + 1, tx_ip.hlim)
448
449             except:
450                 self.logger.error(ppp("Rx:", rx))
451                 self.logger.error(ppp("Tx:", tx))
452                 raise
453
454     def verify_decapped_6o6(self, src_if, capture, sent):
455         self.assertEqual(len(capture), len(sent))
456
457         for i in range(len(capture)):
458             try:
459                 tx = sent[i]
460                 rx = capture[i]
461
462                 tx_ip = tx[IPv6]
463                 rx_ip = rx[IPv6]
464                 tx_gre = tx[GRE]
465                 tx_ip = tx_gre[IPv6]
466
467                 self.assertEqual(rx_ip.src, tx_ip.src)
468                 self.assertEqual(rx_ip.dst, tx_ip.dst)
469                 self.assertEqual(rx_ip.hlim + 1, tx_ip.hlim)
470
471             except:
472                 self.logger.error(ppp("Rx:", rx))
473                 self.logger.error(ppp("Tx:", tx))
474                 raise
475
476     def test_gre(self):
477         """ GRE IPv4 tunnel Tests """
478
479         #
480         # Create an L3 GRE tunnel.
481         #  - set it admin up
482         #  - assign an IP Addres
483         #  - Add a route via the tunnel
484         #
485         gre_if = VppGreInterface(self,
486                                  self.pg0.local_ip4,
487                                  "1.1.1.2")
488         gre_if.add_vpp_config()
489
490         #
491         # The double create (create the same tunnel twice) should fail,
492         # and we should still be able to use the original
493         #
494         try:
495             gre_if.add_vpp_config()
496         except Exception:
497             pass
498         else:
499             self.fail("Double GRE tunnel add does not fail")
500
501         gre_if.admin_up()
502         gre_if.config_ip4()
503
504         route_via_tun = VppIpRoute(self, "4.4.4.4", 32,
505                                    [VppRoutePath("0.0.0.0",
506                                                  gre_if.sw_if_index)])
507
508         route_via_tun.add_vpp_config()
509
510         #
511         # Send a packet stream that is routed into the tunnel
512         #  - they are all dropped since the tunnel's destintation IP
513         #    is unresolved - or resolves via the default route - which
514         #    which is a drop.
515         #
516         tx = self.create_stream_ip4(self.pg0, "5.5.5.5", "4.4.4.4")
517
518         self.send_and_assert_no_replies(self.pg0, tx)
519
520         #
521         # Add a route that resolves the tunnel's destination
522         #
523         route_tun_dst = VppIpRoute(self, "1.1.1.2", 32,
524                                    [VppRoutePath(self.pg0.remote_ip4,
525                                                  self.pg0.sw_if_index)])
526         route_tun_dst.add_vpp_config()
527
528         #
529         # Send a packet stream that is routed into the tunnel
530         #  - packets are GRE encapped
531         #
532         tx = self.create_stream_ip4(self.pg0, "5.5.5.5", "4.4.4.4")
533         rx = self.send_and_expect(self.pg0, tx, self.pg0)
534         self.verify_tunneled_4o4(self.pg0, rx, tx,
535                                  self.pg0.local_ip4, "1.1.1.2")
536
537         #
538         # Send tunneled packets that match the created tunnel and
539         # are decapped and forwarded
540         #
541         tx = self.create_tunnel_stream_4o4(self.pg0,
542                                            "1.1.1.2",
543                                            self.pg0.local_ip4,
544                                            self.pg0.local_ip4,
545                                            self.pg0.remote_ip4)
546         rx = self.send_and_expect(self.pg0, tx, self.pg0)
547         self.verify_decapped_4o4(self.pg0, rx, tx)
548
549         #
550         # Send tunneled packets that do not match the tunnel's src
551         #
552         self.vapi.cli("clear trace")
553         tx = self.create_tunnel_stream_4o4(self.pg0,
554                                            "1.1.1.3",
555                                            self.pg0.local_ip4,
556                                            self.pg0.local_ip4,
557                                            self.pg0.remote_ip4)
558         self.send_and_assert_no_replies(
559             self.pg0, tx,
560             remark="GRE packets forwarded despite no SRC address match")
561
562         #
563         # Configure IPv6 on the PG interface so we can route IPv6
564         # packets
565         #
566         self.pg0.config_ip6()
567         self.pg0.resolve_ndp()
568
569         #
570         # Send IPv6 tunnel encapslated packets
571         #  - dropped since IPv6 is not enabled on the tunnel
572         #
573         tx = self.create_tunnel_stream_6o4(self.pg0,
574                                            "1.1.1.2",
575                                            self.pg0.local_ip4,
576                                            self.pg0.local_ip6,
577                                            self.pg0.remote_ip6)
578         self.send_and_assert_no_replies(self.pg0, tx,
579                                         "IPv6 GRE packets forwarded "
580                                         "despite IPv6 not enabled on tunnel")
581
582         #
583         # Enable IPv6 on the tunnel
584         #
585         gre_if.config_ip6()
586
587         #
588         # Send IPv6 tunnel encapslated packets
589         #  - forwarded since IPv6 is enabled on the tunnel
590         #
591         tx = self.create_tunnel_stream_6o4(self.pg0,
592                                            "1.1.1.2",
593                                            self.pg0.local_ip4,
594                                            self.pg0.local_ip6,
595                                            self.pg0.remote_ip6)
596         rx = self.send_and_expect(self.pg0, tx, self.pg0)
597         self.verify_decapped_6o4(self.pg0, rx, tx)
598
599         #
600         # Send v6 packets for v4 encap
601         #
602         route6_via_tun = VppIpRoute(
603             self, "2001::1", 128,
604             [VppRoutePath("::",
605                           gre_if.sw_if_index,
606                           proto=DpoProto.DPO_PROTO_IP6)])
607         route6_via_tun.add_vpp_config()
608
609         tx = self.create_stream_ip6(self.pg0, "2001::2", "2001::1")
610         rx = self.send_and_expect(self.pg0, tx, self.pg0)
611
612         self.verify_tunneled_6o4(self.pg0, rx, tx,
613                                  self.pg0.local_ip4, "1.1.1.2")
614
615         #
616         # test case cleanup
617         #
618         route_tun_dst.remove_vpp_config()
619         route_via_tun.remove_vpp_config()
620         route6_via_tun.remove_vpp_config()
621         gre_if.remove_vpp_config()
622
623         self.pg0.unconfig_ip6()
624
625     def test_gre6(self):
626         """ GRE IPv6 tunnel Tests """
627
628         self.pg1.config_ip6()
629         self.pg1.resolve_ndp()
630
631         #
632         # Create an L3 GRE tunnel.
633         #  - set it admin up
634         #  - assign an IP Address
635         #  - Add a route via the tunnel
636         #
637         gre_if = VppGreInterface(self,
638                                  self.pg2.local_ip6,
639                                  "1002::1")
640         gre_if.add_vpp_config()
641         gre_if.admin_up()
642         gre_if.config_ip6()
643
644         route_via_tun = VppIpRoute(self, "4004::1", 128,
645                                    [VppRoutePath("0::0",
646                                                  gre_if.sw_if_index)])
647
648         route_via_tun.add_vpp_config()
649
650         #
651         # Send a packet stream that is routed into the tunnel
652         #  - they are all dropped since the tunnel's destintation IP
653         #    is unresolved - or resolves via the default route - which
654         #    which is a drop.
655         #
656         tx = self.create_stream_ip6(self.pg2, "5005::1", "4004::1")
657         self.send_and_assert_no_replies(
658             self.pg2, tx,
659             "GRE packets forwarded without DIP resolved")
660
661         #
662         # Add a route that resolves the tunnel's destination
663         #
664         route_tun_dst = VppIpRoute(self, "1002::1", 128,
665                                    [VppRoutePath(self.pg2.remote_ip6,
666                                                  self.pg2.sw_if_index)])
667         route_tun_dst.add_vpp_config()
668
669         #
670         # Send a packet stream that is routed into the tunnel
671         #  - packets are GRE encapped
672         #
673         tx = self.create_stream_ip6(self.pg2, "5005::1", "4004::1")
674         rx = self.send_and_expect(self.pg2, tx, self.pg2)
675         self.verify_tunneled_6o6(self.pg2, rx, tx,
676                                  self.pg2.local_ip6, "1002::1")
677
678         #
679         # Test decap. decapped packets go out pg1
680         #
681         tx = self.create_tunnel_stream_6o6(self.pg2,
682                                            "1002::1",
683                                            self.pg2.local_ip6,
684                                            "2001::1",
685                                            self.pg1.remote_ip6)
686         rx = self.send_and_expect(self.pg2, tx, self.pg1)
687
688         #
689         # RX'd packet is UDP over IPv6, test the GRE header is gone.
690         #
691         self.assertFalse(rx[0].haslayer(GRE))
692         self.assertEqual(rx[0][IPv6].dst, self.pg1.remote_ip6)
693
694         #
695         # Send v4 over v6
696         #
697         route4_via_tun = VppIpRoute(self, "1.1.1.1", 32,
698                                     [VppRoutePath("0.0.0.0",
699                                                   gre_if.sw_if_index)])
700         route4_via_tun.add_vpp_config()
701
702         tx = self.create_stream_ip4(self.pg0, "1.1.1.2", "1.1.1.1")
703         rx = self.send_and_expect(self.pg0, tx, self.pg2)
704
705         self.verify_tunneled_4o6(self.pg0, rx, tx,
706                                  self.pg2.local_ip6, "1002::1")
707
708         #
709         # test case cleanup
710         #
711         route_tun_dst.remove_vpp_config()
712         route_via_tun.remove_vpp_config()
713         route4_via_tun.remove_vpp_config()
714         gre_if.remove_vpp_config()
715
716         self.pg2.unconfig_ip6()
717         self.pg1.unconfig_ip6()
718
719     def test_gre_vrf(self):
720         """ GRE tunnel VRF Tests """
721
722         #
723         # Create an L3 GRE tunnel whose destination is in the non-default
724         # table. The underlay is thus non-default - the overlay is still
725         # the default.
726         #  - set it admin up
727         #  - assign an IP Addres
728         #
729         gre_if = VppGreInterface(self, self.pg1.local_ip4,
730                                  "2.2.2.2",
731                                  outer_table_id=1)
732         gre_if.add_vpp_config()
733         gre_if.admin_up()
734         gre_if.config_ip4()
735
736         #
737         # Add a route via the tunnel - in the overlay
738         #
739         route_via_tun = VppIpRoute(self, "9.9.9.9", 32,
740                                    [VppRoutePath("0.0.0.0",
741                                                  gre_if.sw_if_index)])
742         route_via_tun.add_vpp_config()
743
744         #
745         # Add a route that resolves the tunnel's destination - in the
746         # underlay table
747         #
748         route_tun_dst = VppIpRoute(self, "2.2.2.2", 32, table_id=1,
749                                    paths=[VppRoutePath(self.pg1.remote_ip4,
750                                                        self.pg1.sw_if_index)])
751         route_tun_dst.add_vpp_config()
752
753         #
754         # Send a packet stream that is routed into the tunnel
755         # packets are sent in on pg0 which is in the default table
756         #  - packets are GRE encapped
757         #
758         self.vapi.cli("clear trace")
759         tx = self.create_stream_ip4(self.pg0, "5.5.5.5", "9.9.9.9")
760         rx = self.send_and_expect(self.pg0, tx, self.pg1)
761         self.verify_tunneled_4o4(self.pg1, rx, tx,
762                                  self.pg1.local_ip4, "2.2.2.2")
763
764         #
765         # Send tunneled packets that match the created tunnel and
766         # are decapped and forwarded. This tests the decap lookup
767         # does not happen in the encap table
768         #
769         self.vapi.cli("clear trace")
770         tx = self.create_tunnel_stream_4o4(self.pg1,
771                                            "2.2.2.2",
772                                            self.pg1.local_ip4,
773                                            self.pg0.local_ip4,
774                                            self.pg0.remote_ip4)
775         rx = self.send_and_expect(self.pg1, tx, self.pg0)
776         self.verify_decapped_4o4(self.pg0, rx, tx)
777
778         #
779         # Send tunneled packets that match the created tunnel
780         # but arrive on an interface that is not in the tunnel's
781         # encap VRF, these are dropped.
782         # IP enable the interface so they aren't dropped due to
783         # IP not being enabled.
784         #
785         self.pg2.config_ip4()
786         self.vapi.cli("clear trace")
787         tx = self.create_tunnel_stream_4o4(self.pg2,
788                                            "2.2.2.2",
789                                            self.pg1.local_ip4,
790                                            self.pg0.local_ip4,
791                                            self.pg0.remote_ip4)
792         rx = self.send_and_assert_no_replies(
793             self.pg2, tx,
794             "GRE decap packets in wrong VRF")
795
796         self.pg2.unconfig_ip4()
797
798         #
799         # test case cleanup
800         #
801         route_tun_dst.remove_vpp_config()
802         route_via_tun.remove_vpp_config()
803         gre_if.remove_vpp_config()
804
805     def test_gre_l2(self):
806         """ GRE tunnel L2 Tests """
807
808         #
809         # Add routes to resolve the tunnel destinations
810         #
811         route_tun1_dst = VppIpRoute(self, "2.2.2.2", 32,
812                                     [VppRoutePath(self.pg0.remote_ip4,
813                                                   self.pg0.sw_if_index)])
814         route_tun2_dst = VppIpRoute(self, "2.2.2.3", 32,
815                                     [VppRoutePath(self.pg0.remote_ip4,
816                                                   self.pg0.sw_if_index)])
817
818         route_tun1_dst.add_vpp_config()
819         route_tun2_dst.add_vpp_config()
820
821         #
822         # Create 2 L2 GRE tunnels and x-connect them
823         #
824         gre_if1 = VppGreInterface(self, self.pg0.local_ip4,
825                                   "2.2.2.2",
826                                   type=(VppEnum.vl_api_gre_tunnel_type_t.
827                                         GRE_API_TUNNEL_TYPE_TEB))
828         gre_if2 = VppGreInterface(self, self.pg0.local_ip4,
829                                   "2.2.2.3",
830                                   type=(VppEnum.vl_api_gre_tunnel_type_t.
831                                         GRE_API_TUNNEL_TYPE_TEB))
832         gre_if1.add_vpp_config()
833         gre_if2.add_vpp_config()
834
835         gre_if1.admin_up()
836         gre_if2.admin_up()
837
838         self.vapi.sw_interface_set_l2_xconnect(gre_if1.sw_if_index,
839                                                gre_if2.sw_if_index,
840                                                enable=1)
841         self.vapi.sw_interface_set_l2_xconnect(gre_if2.sw_if_index,
842                                                gre_if1.sw_if_index,
843                                                enable=1)
844
845         #
846         # Send in tunnel encapped L2. expect out tunnel encapped L2
847         # in both directions
848         #
849         tx = self.create_tunnel_stream_l2o4(self.pg0,
850                                             "2.2.2.2",
851                                             self.pg0.local_ip4)
852         rx = self.send_and_expect(self.pg0, tx, self.pg0)
853         self.verify_tunneled_l2o4(self.pg0, rx, tx,
854                                   self.pg0.local_ip4,
855                                   "2.2.2.3")
856
857         tx = self.create_tunnel_stream_l2o4(self.pg0,
858                                             "2.2.2.3",
859                                             self.pg0.local_ip4)
860         rx = self.send_and_expect(self.pg0, tx, self.pg0)
861         self.verify_tunneled_l2o4(self.pg0, rx, tx,
862                                   self.pg0.local_ip4,
863                                   "2.2.2.2")
864
865         self.vapi.sw_interface_set_l2_xconnect(gre_if1.sw_if_index,
866                                                gre_if2.sw_if_index,
867                                                enable=0)
868         self.vapi.sw_interface_set_l2_xconnect(gre_if2.sw_if_index,
869                                                gre_if1.sw_if_index,
870                                                enable=0)
871
872         #
873         # Create a VLAN sub-interfaces on the GRE TEB interfaces
874         # then x-connect them
875         #
876         gre_if_11 = VppDot1QSubint(self, gre_if1, 11)
877         gre_if_12 = VppDot1QSubint(self, gre_if2, 12)
878
879         # gre_if_11.add_vpp_config()
880         # gre_if_12.add_vpp_config()
881
882         gre_if_11.admin_up()
883         gre_if_12.admin_up()
884
885         self.vapi.sw_interface_set_l2_xconnect(gre_if_11.sw_if_index,
886                                                gre_if_12.sw_if_index,
887                                                enable=1)
888         self.vapi.sw_interface_set_l2_xconnect(gre_if_12.sw_if_index,
889                                                gre_if_11.sw_if_index,
890                                                enable=1)
891
892         #
893         # Configure both to pop thier respective VLAN tags,
894         # so that during the x-coonect they will subsequently push
895         #
896         self.vapi.l2_interface_vlan_tag_rewrite(
897             sw_if_index=gre_if_12.sw_if_index, vtr_op=L2_VTR_OP.L2_POP_1,
898             push_dot1q=12)
899         self.vapi.l2_interface_vlan_tag_rewrite(
900             sw_if_index=gre_if_11.sw_if_index, vtr_op=L2_VTR_OP.L2_POP_1,
901             push_dot1q=11)
902
903         #
904         # Send traffic in both directiond - expect the VLAN tags to
905         # be swapped.
906         #
907         tx = self.create_tunnel_stream_vlano4(self.pg0,
908                                               "2.2.2.2",
909                                               self.pg0.local_ip4,
910                                               11)
911         rx = self.send_and_expect(self.pg0, tx, self.pg0)
912         self.verify_tunneled_vlano4(self.pg0, rx, tx,
913                                     self.pg0.local_ip4,
914                                     "2.2.2.3",
915                                     12)
916
917         tx = self.create_tunnel_stream_vlano4(self.pg0,
918                                               "2.2.2.3",
919                                               self.pg0.local_ip4,
920                                               12)
921         rx = self.send_and_expect(self.pg0, tx, self.pg0)
922         self.verify_tunneled_vlano4(self.pg0, rx, tx,
923                                     self.pg0.local_ip4,
924                                     "2.2.2.2",
925                                     11)
926
927         #
928         # Cleanup Test resources
929         #
930         gre_if_11.remove_vpp_config()
931         gre_if_12.remove_vpp_config()
932         gre_if1.remove_vpp_config()
933         gre_if2.remove_vpp_config()
934         route_tun1_dst.add_vpp_config()
935         route_tun2_dst.add_vpp_config()
936
937     def test_gre_loop(self):
938         """ GRE tunnel loop Tests """
939
940         #
941         # Create an L3 GRE tunnel.
942         #  - set it admin up
943         #  - assign an IP Addres
944         #
945         gre_if = VppGreInterface(self,
946                                  self.pg0.local_ip4,
947                                  "1.1.1.2")
948         gre_if.add_vpp_config()
949         gre_if.admin_up()
950         gre_if.config_ip4()
951
952         #
953         # add a route to the tunnel's destination that points
954         # through the tunnel, hence forming a loop in the forwarding
955         # graph
956         #
957         route_dst = VppIpRoute(self, "1.1.1.2", 32,
958                                [VppRoutePath("0.0.0.0",
959                                              gre_if.sw_if_index)])
960         route_dst.add_vpp_config()
961
962         #
963         # packets to the tunnels destination should be dropped
964         #
965         tx = self.create_stream_ip4(self.pg0, "1.1.1.1", "1.1.1.2")
966         self.send_and_assert_no_replies(self.pg2, tx)
967
968         self.logger.info(self.vapi.ppcli("sh adj 7"))
969
970         #
971         # break the loop
972         #
973         route_dst.modify([VppRoutePath(self.pg1.remote_ip4,
974                                        self.pg1.sw_if_index)])
975         route_dst.add_vpp_config()
976
977         rx = self.send_and_expect(self.pg0, tx, self.pg1)
978
979         #
980         # a good route throught the tunnel to check it restacked
981         #
982         route_via_tun_2 = VppIpRoute(self, "2.2.2.2", 32,
983                                      [VppRoutePath("0.0.0.0",
984                                                    gre_if.sw_if_index)])
985         route_via_tun_2.add_vpp_config()
986
987         tx = self.create_stream_ip4(self.pg0, "2.2.2.3", "2.2.2.2")
988         rx = self.send_and_expect(self.pg0, tx, self.pg1)
989         self.verify_tunneled_4o4(self.pg1, rx, tx,
990                                  self.pg0.local_ip4, "1.1.1.2")
991
992         #
993         # cleanup
994         #
995         route_via_tun_2.remove_vpp_config()
996         gre_if.remove_vpp_config()
997
998     def test_mgre(self):
999         """ mGRE IPv4 tunnel Tests """
1000
1001         for itf in self.pg_interfaces[3:]:
1002             #
1003             # one underlay nh for each overlay/tunnel peer
1004             #
1005             itf.generate_remote_hosts(4)
1006             itf.configure_ipv4_neighbors()
1007
1008             #
1009             # Create an L3 GRE tunnel.
1010             #  - set it admin up
1011             #  - assign an IP Addres
1012             #  - Add a route via the tunnel
1013             #
1014             gre_if = VppGreInterface(self,
1015                                      itf.local_ip4,
1016                                      "0.0.0.0",
1017                                      mode=(VppEnum.vl_api_tunnel_mode_t.
1018                                            TUNNEL_API_MODE_MP))
1019             gre_if.add_vpp_config()
1020             gre_if.admin_up()
1021             gre_if.config_ip4()
1022             gre_if.generate_remote_hosts(4)
1023
1024             self.logger.info(self.vapi.cli("sh adj"))
1025             self.logger.info(self.vapi.cli("sh ip fib"))
1026
1027             #
1028             # ensure we don't match to the tunnel if the source address
1029             # is all zeros
1030             #
1031             tx = self.create_tunnel_stream_4o4(self.pg0,
1032                                                "0.0.0.0",
1033                                                itf.local_ip4,
1034                                                self.pg0.local_ip4,
1035                                                self.pg0.remote_ip4)
1036             self.send_and_assert_no_replies(self.pg0, tx)
1037
1038             #
1039             # for-each peer
1040             #
1041             for ii in range(1, 4):
1042                 route_addr = "4.4.4.%d" % ii
1043
1044                 #
1045                 # route traffic via the peer
1046                 #
1047                 route_via_tun = VppIpRoute(
1048                     self, route_addr, 32,
1049                     [VppRoutePath(gre_if._remote_hosts[ii].ip4,
1050                                   gre_if.sw_if_index)])
1051                 route_via_tun.add_vpp_config()
1052
1053                 #
1054                 # Add a NHRP entry resolves the peer
1055                 #
1056                 nhrp = VppNhrp(self, gre_if,
1057                                gre_if._remote_hosts[ii].ip4,
1058                                itf._remote_hosts[ii].ip4)
1059                 nhrp.add_vpp_config()
1060
1061                 #
1062                 # Send a packet stream that is routed into the tunnel
1063                 #  - packets are GRE encapped
1064                 #
1065                 tx_e = self.create_stream_ip4(self.pg0, "5.5.5.5", route_addr)
1066                 rx = self.send_and_expect(self.pg0, tx_e, itf)
1067                 self.verify_tunneled_4o4(self.pg0, rx, tx_e,
1068                                          itf.local_ip4,
1069                                          gre_if._remote_hosts[ii].ip4)
1070
1071                 tx_i = self.create_tunnel_stream_4o4(self.pg0,
1072                                                      itf._remote_hosts[ii].ip4,
1073                                                      itf.local_ip4,
1074                                                      self.pg0.local_ip4,
1075                                                      self.pg0.remote_ip4)
1076                 rx = self.send_and_expect(self.pg0, tx_i, self.pg0)
1077                 self.verify_decapped_4o4(self.pg0, rx, tx_i)
1078
1079                 #
1080                 # delete and re-add the NHRP
1081                 #
1082                 nhrp.remove_vpp_config()
1083                 self.send_and_assert_no_replies(self.pg0, tx_e)
1084                 self.send_and_assert_no_replies(self.pg0, tx_i)
1085
1086                 nhrp.add_vpp_config()
1087                 rx = self.send_and_expect(self.pg0, tx_e, itf)
1088                 self.verify_tunneled_4o4(self.pg0, rx, tx_e,
1089                                          itf.local_ip4,
1090                                          gre_if._remote_hosts[ii].ip4)
1091                 rx = self.send_and_expect(self.pg0, tx_i, self.pg0)
1092                 self.verify_decapped_4o4(self.pg0, rx, tx_i)
1093
1094             gre_if.admin_down()
1095             gre_if.unconfig_ip4()
1096
1097     def test_mgre6(self):
1098         """ mGRE IPv6 tunnel Tests """
1099
1100         self.pg0.config_ip6()
1101         self.pg0.resolve_ndp()
1102
1103         for itf in self.pg_interfaces[3:]:
1104             #
1105             # one underlay nh for each overlay/tunnel peer
1106             #
1107             itf.config_ip6()
1108             itf.generate_remote_hosts(4)
1109             itf.configure_ipv6_neighbors()
1110
1111             #
1112             # Create an L3 GRE tunnel.
1113             #  - set it admin up
1114             #  - assign an IP Addres
1115             #  - Add a route via the tunnel
1116             #
1117             gre_if = VppGreInterface(self,
1118                                      itf.local_ip6,
1119                                      "::",
1120                                      mode=(VppEnum.vl_api_tunnel_mode_t.
1121                                            TUNNEL_API_MODE_MP))
1122             gre_if.add_vpp_config()
1123             gre_if.admin_up()
1124             gre_if.config_ip6()
1125             gre_if.generate_remote_hosts(4)
1126
1127             #
1128             # for-each peer
1129             #
1130             for ii in range(1, 4):
1131                 route_addr = "4::%d" % ii
1132
1133                 #
1134                 # route traffic via the peer
1135                 #
1136                 route_via_tun = VppIpRoute(
1137                     self, route_addr, 128,
1138                     [VppRoutePath(gre_if._remote_hosts[ii].ip6,
1139                                   gre_if.sw_if_index)])
1140                 route_via_tun.add_vpp_config()
1141
1142                 #
1143                 # Add a NHRP entry resolves the peer
1144                 #
1145                 nhrp = VppNhrp(self, gre_if,
1146                                gre_if._remote_hosts[ii].ip6,
1147                                itf._remote_hosts[ii].ip6)
1148                 nhrp.add_vpp_config()
1149
1150                 #
1151                 # Send a packet stream that is routed into the tunnel
1152                 #  - packets are GRE encapped
1153                 #
1154                 tx_e = self.create_stream_ip6(self.pg0, "5::5", route_addr)
1155                 rx = self.send_and_expect(self.pg0, tx_e, itf)
1156                 self.verify_tunneled_6o6(self.pg0, rx, tx_e,
1157                                          itf.local_ip6,
1158                                          gre_if._remote_hosts[ii].ip6)
1159                 tx_i = self.create_tunnel_stream_6o6(self.pg0,
1160                                                      itf._remote_hosts[ii].ip6,
1161                                                      itf.local_ip6,
1162                                                      self.pg0.local_ip6,
1163                                                      self.pg0.remote_ip6)
1164                 rx = self.send_and_expect(self.pg0, tx_i, self.pg0)
1165                 self.verify_decapped_6o6(self.pg0, rx, tx_i)
1166
1167                 #
1168                 # delete and re-add the NHRP
1169                 #
1170                 nhrp.remove_vpp_config()
1171                 self.send_and_assert_no_replies(self.pg0, tx_e)
1172
1173                 nhrp.add_vpp_config()
1174                 rx = self.send_and_expect(self.pg0, tx_e, itf)
1175                 self.verify_tunneled_6o6(self.pg0, rx, tx_e,
1176                                          itf.local_ip6,
1177                                          gre_if._remote_hosts[ii].ip6)
1178                 rx = self.send_and_expect(self.pg0, tx_i, self.pg0)
1179                 self.verify_decapped_6o6(self.pg0, rx, tx_i)
1180
1181             gre_if.admin_down()
1182             gre_if.unconfig_ip4()
1183             itf.unconfig_ip6()
1184         self.pg0.unconfig_ip6()
1185
1186
1187 if __name__ == '__main__':
1188     unittest.main(testRunner=VppTestRunner)