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