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