fib: Glean on NBMA interface points to drop
[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 test_gre(self):
455         """ GRE IPv4 tunnel Tests """
456
457         #
458         # Create an L3 GRE tunnel.
459         #  - set it admin up
460         #  - assign an IP Addres
461         #  - Add a route via the tunnel
462         #
463         gre_if = VppGreInterface(self,
464                                  self.pg0.local_ip4,
465                                  "1.1.1.2")
466         gre_if.add_vpp_config()
467
468         #
469         # The double create (create the same tunnel twice) should fail,
470         # and we should still be able to use the original
471         #
472         try:
473             gre_if.add_vpp_config()
474         except Exception:
475             pass
476         else:
477             self.fail("Double GRE tunnel add does not fail")
478
479         gre_if.admin_up()
480         gre_if.config_ip4()
481
482         route_via_tun = VppIpRoute(self, "4.4.4.4", 32,
483                                    [VppRoutePath("0.0.0.0",
484                                                  gre_if.sw_if_index)])
485
486         route_via_tun.add_vpp_config()
487
488         #
489         # Send a packet stream that is routed into the tunnel
490         #  - they are all dropped since the tunnel's destintation IP
491         #    is unresolved - or resolves via the default route - which
492         #    which is a drop.
493         #
494         tx = self.create_stream_ip4(self.pg0, "5.5.5.5", "4.4.4.4")
495
496         self.send_and_assert_no_replies(self.pg0, tx)
497
498         #
499         # Add a route that resolves the tunnel's destination
500         #
501         route_tun_dst = VppIpRoute(self, "1.1.1.2", 32,
502                                    [VppRoutePath(self.pg0.remote_ip4,
503                                                  self.pg0.sw_if_index)])
504         route_tun_dst.add_vpp_config()
505
506         #
507         # Send a packet stream that is routed into the tunnel
508         #  - packets are GRE encapped
509         #
510         tx = self.create_stream_ip4(self.pg0, "5.5.5.5", "4.4.4.4")
511         rx = self.send_and_expect(self.pg0, tx, self.pg0)
512         self.verify_tunneled_4o4(self.pg0, rx, tx,
513                                  self.pg0.local_ip4, "1.1.1.2")
514
515         #
516         # Send tunneled packets that match the created tunnel and
517         # are decapped and forwarded
518         #
519         tx = self.create_tunnel_stream_4o4(self.pg0,
520                                            "1.1.1.2",
521                                            self.pg0.local_ip4,
522                                            self.pg0.local_ip4,
523                                            self.pg0.remote_ip4)
524         rx = self.send_and_expect(self.pg0, tx, self.pg0)
525         self.verify_decapped_4o4(self.pg0, rx, tx)
526
527         #
528         # Send tunneled packets that do not match the tunnel's src
529         #
530         self.vapi.cli("clear trace")
531         tx = self.create_tunnel_stream_4o4(self.pg0,
532                                            "1.1.1.3",
533                                            self.pg0.local_ip4,
534                                            self.pg0.local_ip4,
535                                            self.pg0.remote_ip4)
536         self.send_and_assert_no_replies(
537             self.pg0, tx,
538             remark="GRE packets forwarded despite no SRC address match")
539
540         #
541         # Configure IPv6 on the PG interface so we can route IPv6
542         # packets
543         #
544         self.pg0.config_ip6()
545         self.pg0.resolve_ndp()
546
547         #
548         # Send IPv6 tunnel encapslated packets
549         #  - dropped since IPv6 is not enabled on the tunnel
550         #
551         tx = self.create_tunnel_stream_6o4(self.pg0,
552                                            "1.1.1.2",
553                                            self.pg0.local_ip4,
554                                            self.pg0.local_ip6,
555                                            self.pg0.remote_ip6)
556         self.send_and_assert_no_replies(self.pg0, tx,
557                                         "IPv6 GRE packets forwarded "
558                                         "despite IPv6 not enabled on tunnel")
559
560         #
561         # Enable IPv6 on the tunnel
562         #
563         gre_if.config_ip6()
564
565         #
566         # Send IPv6 tunnel encapslated packets
567         #  - forwarded since IPv6 is enabled on the tunnel
568         #
569         tx = self.create_tunnel_stream_6o4(self.pg0,
570                                            "1.1.1.2",
571                                            self.pg0.local_ip4,
572                                            self.pg0.local_ip6,
573                                            self.pg0.remote_ip6)
574         rx = self.send_and_expect(self.pg0, tx, self.pg0)
575         self.verify_decapped_6o4(self.pg0, rx, tx)
576
577         #
578         # Send v6 packets for v4 encap
579         #
580         route6_via_tun = VppIpRoute(
581             self, "2001::1", 128,
582             [VppRoutePath("::",
583                           gre_if.sw_if_index,
584                           proto=DpoProto.DPO_PROTO_IP6)])
585         route6_via_tun.add_vpp_config()
586
587         tx = self.create_stream_ip6(self.pg0, "2001::2", "2001::1")
588         rx = self.send_and_expect(self.pg0, tx, self.pg0)
589
590         self.verify_tunneled_6o4(self.pg0, rx, tx,
591                                  self.pg0.local_ip4, "1.1.1.2")
592
593         #
594         # test case cleanup
595         #
596         route_tun_dst.remove_vpp_config()
597         route_via_tun.remove_vpp_config()
598         route6_via_tun.remove_vpp_config()
599         gre_if.remove_vpp_config()
600
601         self.pg0.unconfig_ip6()
602
603     def test_gre6(self):
604         """ GRE IPv6 tunnel Tests """
605
606         self.pg1.config_ip6()
607         self.pg1.resolve_ndp()
608
609         #
610         # Create an L3 GRE tunnel.
611         #  - set it admin up
612         #  - assign an IP Address
613         #  - Add a route via the tunnel
614         #
615         gre_if = VppGreInterface(self,
616                                  self.pg2.local_ip6,
617                                  "1002::1")
618         gre_if.add_vpp_config()
619         gre_if.admin_up()
620         gre_if.config_ip6()
621
622         route_via_tun = VppIpRoute(self, "4004::1", 128,
623                                    [VppRoutePath("0::0",
624                                                  gre_if.sw_if_index)])
625
626         route_via_tun.add_vpp_config()
627
628         #
629         # Send a packet stream that is routed into the tunnel
630         #  - they are all dropped since the tunnel's destintation IP
631         #    is unresolved - or resolves via the default route - which
632         #    which is a drop.
633         #
634         tx = self.create_stream_ip6(self.pg2, "5005::1", "4004::1")
635         self.send_and_assert_no_replies(
636             self.pg2, tx,
637             "GRE packets forwarded without DIP resolved")
638
639         #
640         # Add a route that resolves the tunnel's destination
641         #
642         route_tun_dst = VppIpRoute(self, "1002::1", 128,
643                                    [VppRoutePath(self.pg2.remote_ip6,
644                                                  self.pg2.sw_if_index)])
645         route_tun_dst.add_vpp_config()
646
647         #
648         # Send a packet stream that is routed into the tunnel
649         #  - packets are GRE encapped
650         #
651         tx = self.create_stream_ip6(self.pg2, "5005::1", "4004::1")
652         rx = self.send_and_expect(self.pg2, tx, self.pg2)
653         self.verify_tunneled_6o6(self.pg2, rx, tx,
654                                  self.pg2.local_ip6, "1002::1")
655
656         #
657         # Test decap. decapped packets go out pg1
658         #
659         tx = self.create_tunnel_stream_6o6(self.pg2,
660                                            "1002::1",
661                                            self.pg2.local_ip6,
662                                            "2001::1",
663                                            self.pg1.remote_ip6)
664         rx = self.send_and_expect(self.pg2, tx, self.pg1)
665
666         #
667         # RX'd packet is UDP over IPv6, test the GRE header is gone.
668         #
669         self.assertFalse(rx[0].haslayer(GRE))
670         self.assertEqual(rx[0][IPv6].dst, self.pg1.remote_ip6)
671
672         #
673         # Send v4 over v6
674         #
675         route4_via_tun = VppIpRoute(self, "1.1.1.1", 32,
676                                     [VppRoutePath("0.0.0.0",
677                                                   gre_if.sw_if_index)])
678         route4_via_tun.add_vpp_config()
679
680         tx = self.create_stream_ip4(self.pg0, "1.1.1.2", "1.1.1.1")
681         rx = self.send_and_expect(self.pg0, tx, self.pg2)
682
683         self.verify_tunneled_4o6(self.pg0, rx, tx,
684                                  self.pg2.local_ip6, "1002::1")
685
686         #
687         # test case cleanup
688         #
689         route_tun_dst.remove_vpp_config()
690         route_via_tun.remove_vpp_config()
691         route4_via_tun.remove_vpp_config()
692         gre_if.remove_vpp_config()
693
694         self.pg2.unconfig_ip6()
695         self.pg1.unconfig_ip6()
696
697     def test_gre_vrf(self):
698         """ GRE tunnel VRF Tests """
699
700         #
701         # Create an L3 GRE tunnel whose destination is in the non-default
702         # table. The underlay is thus non-default - the overlay is still
703         # the default.
704         #  - set it admin up
705         #  - assign an IP Addres
706         #
707         gre_if = VppGreInterface(self, self.pg1.local_ip4,
708                                  "2.2.2.2",
709                                  outer_table_id=1)
710         gre_if.add_vpp_config()
711         gre_if.admin_up()
712         gre_if.config_ip4()
713
714         #
715         # Add a route via the tunnel - in the overlay
716         #
717         route_via_tun = VppIpRoute(self, "9.9.9.9", 32,
718                                    [VppRoutePath("0.0.0.0",
719                                                  gre_if.sw_if_index)])
720         route_via_tun.add_vpp_config()
721
722         #
723         # Add a route that resolves the tunnel's destination - in the
724         # underlay table
725         #
726         route_tun_dst = VppIpRoute(self, "2.2.2.2", 32, table_id=1,
727                                    paths=[VppRoutePath(self.pg1.remote_ip4,
728                                                        self.pg1.sw_if_index)])
729         route_tun_dst.add_vpp_config()
730
731         #
732         # Send a packet stream that is routed into the tunnel
733         # packets are sent in on pg0 which is in the default table
734         #  - packets are GRE encapped
735         #
736         self.vapi.cli("clear trace")
737         tx = self.create_stream_ip4(self.pg0, "5.5.5.5", "9.9.9.9")
738         rx = self.send_and_expect(self.pg0, tx, self.pg1)
739         self.verify_tunneled_4o4(self.pg1, rx, tx,
740                                  self.pg1.local_ip4, "2.2.2.2")
741
742         #
743         # Send tunneled packets that match the created tunnel and
744         # are decapped and forwarded. This tests the decap lookup
745         # does not happen in the encap table
746         #
747         self.vapi.cli("clear trace")
748         tx = self.create_tunnel_stream_4o4(self.pg1,
749                                            "2.2.2.2",
750                                            self.pg1.local_ip4,
751                                            self.pg0.local_ip4,
752                                            self.pg0.remote_ip4)
753         rx = self.send_and_expect(self.pg1, tx, self.pg0)
754         self.verify_decapped_4o4(self.pg0, rx, tx)
755
756         #
757         # Send tunneled packets that match the created tunnel
758         # but arrive on an interface that is not in the tunnel's
759         # encap VRF, these are dropped.
760         # IP enable the interface so they aren't dropped due to
761         # IP not being enabled.
762         #
763         self.pg2.config_ip4()
764         self.vapi.cli("clear trace")
765         tx = self.create_tunnel_stream_4o4(self.pg2,
766                                            "2.2.2.2",
767                                            self.pg1.local_ip4,
768                                            self.pg0.local_ip4,
769                                            self.pg0.remote_ip4)
770         rx = self.send_and_assert_no_replies(
771             self.pg2, tx,
772             "GRE decap packets in wrong VRF")
773
774         self.pg2.unconfig_ip4()
775
776         #
777         # test case cleanup
778         #
779         route_tun_dst.remove_vpp_config()
780         route_via_tun.remove_vpp_config()
781         gre_if.remove_vpp_config()
782
783     def test_gre_l2(self):
784         """ GRE tunnel L2 Tests """
785
786         #
787         # Add routes to resolve the tunnel destinations
788         #
789         route_tun1_dst = VppIpRoute(self, "2.2.2.2", 32,
790                                     [VppRoutePath(self.pg0.remote_ip4,
791                                                   self.pg0.sw_if_index)])
792         route_tun2_dst = VppIpRoute(self, "2.2.2.3", 32,
793                                     [VppRoutePath(self.pg0.remote_ip4,
794                                                   self.pg0.sw_if_index)])
795
796         route_tun1_dst.add_vpp_config()
797         route_tun2_dst.add_vpp_config()
798
799         #
800         # Create 2 L2 GRE tunnels and x-connect them
801         #
802         gre_if1 = VppGreInterface(self, self.pg0.local_ip4,
803                                   "2.2.2.2",
804                                   type=(VppEnum.vl_api_gre_tunnel_type_t.
805                                         GRE_API_TUNNEL_TYPE_TEB))
806         gre_if2 = VppGreInterface(self, self.pg0.local_ip4,
807                                   "2.2.2.3",
808                                   type=(VppEnum.vl_api_gre_tunnel_type_t.
809                                         GRE_API_TUNNEL_TYPE_TEB))
810         gre_if1.add_vpp_config()
811         gre_if2.add_vpp_config()
812
813         gre_if1.admin_up()
814         gre_if2.admin_up()
815
816         self.vapi.sw_interface_set_l2_xconnect(gre_if1.sw_if_index,
817                                                gre_if2.sw_if_index,
818                                                enable=1)
819         self.vapi.sw_interface_set_l2_xconnect(gre_if2.sw_if_index,
820                                                gre_if1.sw_if_index,
821                                                enable=1)
822
823         #
824         # Send in tunnel encapped L2. expect out tunnel encapped L2
825         # in both directions
826         #
827         tx = self.create_tunnel_stream_l2o4(self.pg0,
828                                             "2.2.2.2",
829                                             self.pg0.local_ip4)
830         rx = self.send_and_expect(self.pg0, tx, self.pg0)
831         self.verify_tunneled_l2o4(self.pg0, rx, tx,
832                                   self.pg0.local_ip4,
833                                   "2.2.2.3")
834
835         tx = self.create_tunnel_stream_l2o4(self.pg0,
836                                             "2.2.2.3",
837                                             self.pg0.local_ip4)
838         rx = self.send_and_expect(self.pg0, tx, self.pg0)
839         self.verify_tunneled_l2o4(self.pg0, rx, tx,
840                                   self.pg0.local_ip4,
841                                   "2.2.2.2")
842
843         self.vapi.sw_interface_set_l2_xconnect(gre_if1.sw_if_index,
844                                                gre_if2.sw_if_index,
845                                                enable=0)
846         self.vapi.sw_interface_set_l2_xconnect(gre_if2.sw_if_index,
847                                                gre_if1.sw_if_index,
848                                                enable=0)
849
850         #
851         # Create a VLAN sub-interfaces on the GRE TEB interfaces
852         # then x-connect them
853         #
854         gre_if_11 = VppDot1QSubint(self, gre_if1, 11)
855         gre_if_12 = VppDot1QSubint(self, gre_if2, 12)
856
857         # gre_if_11.add_vpp_config()
858         # gre_if_12.add_vpp_config()
859
860         gre_if_11.admin_up()
861         gre_if_12.admin_up()
862
863         self.vapi.sw_interface_set_l2_xconnect(gre_if_11.sw_if_index,
864                                                gre_if_12.sw_if_index,
865                                                enable=1)
866         self.vapi.sw_interface_set_l2_xconnect(gre_if_12.sw_if_index,
867                                                gre_if_11.sw_if_index,
868                                                enable=1)
869
870         #
871         # Configure both to pop thier respective VLAN tags,
872         # so that during the x-coonect they will subsequently push
873         #
874         self.vapi.l2_interface_vlan_tag_rewrite(
875             sw_if_index=gre_if_12.sw_if_index, vtr_op=L2_VTR_OP.L2_POP_1,
876             push_dot1q=12)
877         self.vapi.l2_interface_vlan_tag_rewrite(
878             sw_if_index=gre_if_11.sw_if_index, vtr_op=L2_VTR_OP.L2_POP_1,
879             push_dot1q=11)
880
881         #
882         # Send traffic in both directiond - expect the VLAN tags to
883         # be swapped.
884         #
885         tx = self.create_tunnel_stream_vlano4(self.pg0,
886                                               "2.2.2.2",
887                                               self.pg0.local_ip4,
888                                               11)
889         rx = self.send_and_expect(self.pg0, tx, self.pg0)
890         self.verify_tunneled_vlano4(self.pg0, rx, tx,
891                                     self.pg0.local_ip4,
892                                     "2.2.2.3",
893                                     12)
894
895         tx = self.create_tunnel_stream_vlano4(self.pg0,
896                                               "2.2.2.3",
897                                               self.pg0.local_ip4,
898                                               12)
899         rx = self.send_and_expect(self.pg0, tx, self.pg0)
900         self.verify_tunneled_vlano4(self.pg0, rx, tx,
901                                     self.pg0.local_ip4,
902                                     "2.2.2.2",
903                                     11)
904
905         #
906         # Cleanup Test resources
907         #
908         gre_if_11.remove_vpp_config()
909         gre_if_12.remove_vpp_config()
910         gre_if1.remove_vpp_config()
911         gre_if2.remove_vpp_config()
912         route_tun1_dst.add_vpp_config()
913         route_tun2_dst.add_vpp_config()
914
915     def test_gre_loop(self):
916         """ GRE tunnel loop Tests """
917
918         #
919         # Create an L3 GRE tunnel.
920         #  - set it admin up
921         #  - assign an IP Addres
922         #
923         gre_if = VppGreInterface(self,
924                                  self.pg0.local_ip4,
925                                  "1.1.1.2")
926         gre_if.add_vpp_config()
927         gre_if.admin_up()
928         gre_if.config_ip4()
929
930         #
931         # add a route to the tunnel's destination that points
932         # through the tunnel, hence forming a loop in the forwarding
933         # graph
934         #
935         route_dst = VppIpRoute(self, "1.1.1.2", 32,
936                                [VppRoutePath("0.0.0.0",
937                                              gre_if.sw_if_index)])
938         route_dst.add_vpp_config()
939
940         #
941         # packets to the tunnels destination should be dropped
942         #
943         tx = self.create_stream_ip4(self.pg0, "1.1.1.1", "1.1.1.2")
944         self.send_and_assert_no_replies(self.pg2, tx)
945
946         self.logger.info(self.vapi.ppcli("sh adj 7"))
947
948         #
949         # break the loop
950         #
951         route_dst.modify([VppRoutePath(self.pg1.remote_ip4,
952                                        self.pg1.sw_if_index)])
953         route_dst.add_vpp_config()
954
955         rx = self.send_and_expect(self.pg0, tx, self.pg1)
956
957         #
958         # a good route throught the tunnel to check it restacked
959         #
960         route_via_tun_2 = VppIpRoute(self, "2.2.2.2", 32,
961                                      [VppRoutePath("0.0.0.0",
962                                                    gre_if.sw_if_index)])
963         route_via_tun_2.add_vpp_config()
964
965         tx = self.create_stream_ip4(self.pg0, "2.2.2.3", "2.2.2.2")
966         rx = self.send_and_expect(self.pg0, tx, self.pg1)
967         self.verify_tunneled_4o4(self.pg1, rx, tx,
968                                  self.pg0.local_ip4, "1.1.1.2")
969
970         #
971         # cleanup
972         #
973         route_via_tun_2.remove_vpp_config()
974         gre_if.remove_vpp_config()
975
976     def test_mgre(self):
977         """ mGRE IPv4 tunnel Tests """
978
979         for itf in self.pg_interfaces[3:]:
980             #
981             # one underlay nh for each overlay/tunnel peer
982             #
983             itf.generate_remote_hosts(4)
984             itf.configure_ipv4_neighbors()
985
986             #
987             # Create an L3 GRE tunnel.
988             #  - set it admin up
989             #  - assign an IP Addres
990             #  - Add a route via the tunnel
991             #
992             gre_if = VppGreInterface(self,
993                                      itf.local_ip4,
994                                      "0.0.0.0",
995                                      mode=(VppEnum.vl_api_gre_tunnel_mode_t.
996                                            GRE_API_TUNNEL_MODE_MP))
997             gre_if.add_vpp_config()
998             gre_if.admin_up()
999             gre_if.config_ip4()
1000             gre_if.generate_remote_hosts(4)
1001
1002             self.logger.info(self.vapi.cli("sh adj"))
1003             self.logger.info(self.vapi.cli("sh ip fib"))
1004
1005             #
1006             # for-each peer
1007             #
1008             for ii in range(1, 4):
1009                 route_addr = "4.4.4.%d" % ii
1010
1011                 #
1012                 # route traffic via the peer
1013                 #
1014                 route_via_tun = VppIpRoute(
1015                     self, route_addr, 32,
1016                     [VppRoutePath(gre_if._remote_hosts[ii].ip4,
1017                                   gre_if.sw_if_index)])
1018                 route_via_tun.add_vpp_config()
1019
1020                 #
1021                 # Add a NHRP entry resolves the peer
1022                 #
1023                 nhrp = VppNhrp(self, gre_if,
1024                                gre_if._remote_hosts[ii].ip4,
1025                                itf._remote_hosts[ii].ip4)
1026                 nhrp.add_vpp_config()
1027
1028                 #
1029                 # Send a packet stream that is routed into the tunnel
1030                 #  - packets are GRE encapped
1031                 #
1032                 tx = self.create_stream_ip4(self.pg0, "5.5.5.5", route_addr)
1033                 rx = self.send_and_expect(self.pg0, tx, itf)
1034                 self.verify_tunneled_4o4(self.pg0, rx, tx,
1035                                          itf.local_ip4,
1036                                          gre_if._remote_hosts[ii].ip4)
1037
1038                 #
1039                 # delete and re-add the NHRP
1040                 #
1041                 nhrp.remove_vpp_config()
1042                 self.send_and_assert_no_replies(self.pg0, tx)
1043
1044                 nhrp.add_vpp_config()
1045                 rx = self.send_and_expect(self.pg0, tx, itf)
1046                 self.verify_tunneled_4o4(self.pg0, rx, tx,
1047                                          itf.local_ip4,
1048                                          gre_if._remote_hosts[ii].ip4)
1049
1050             gre_if.admin_down()
1051             gre_if.unconfig_ip4()
1052
1053
1054 if __name__ == '__main__':
1055     unittest.main(testRunner=VppTestRunner)