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