GRE: API update
[vpp.git] / test / test_gre.py
1 #!/usr/bin/env python
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_ip import DpoProto
16 from vpp_ip_route import VppIpRoute, VppRoutePath, VppIpTable
17 from util import ppp, ppc
18 from vpp_papi import VppEnum
19
20
21 class TestGRE(VppTestCase):
22     """ GRE Test Case """
23
24     @classmethod
25     def setUpClass(cls):
26         super(TestGRE, cls).setUpClass()
27
28     @classmethod
29     def tearDownClass(cls):
30         super(TestGRE, cls).tearDownClass()
31
32     def setUp(self):
33         super(TestGRE, self).setUp()
34
35         # create 3 pg interfaces - set one in a non-default table.
36         self.create_pg_interfaces(range(3))
37
38         self.tbl = VppIpTable(self, 1)
39         self.tbl.add_vpp_config()
40         self.pg1.set_table_ip4(1)
41
42         for i in self.pg_interfaces:
43             i.admin_up()
44
45         self.pg0.config_ip4()
46         self.pg0.resolve_arp()
47         self.pg1.config_ip4()
48         self.pg1.resolve_arp()
49         self.pg2.config_ip6()
50         self.pg2.resolve_ndp()
51
52     def tearDown(self):
53         for i in self.pg_interfaces:
54             i.unconfig_ip4()
55             i.unconfig_ip6()
56             i.admin_down()
57         self.pg1.set_table_ip4(0)
58         super(TestGRE, self).tearDown()
59
60     def create_stream_ip4(self, src_if, src_ip, dst_ip):
61         pkts = []
62         for i in range(0, 257):
63             info = self.create_packet_info(src_if, src_if)
64             payload = self.info_to_payload(info)
65             p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
66                  IP(src=src_ip, dst=dst_ip) /
67                  UDP(sport=1234, dport=1234) /
68                  Raw(payload))
69             info.data = p.copy()
70             pkts.append(p)
71         return pkts
72
73     def create_stream_ip6(self, src_if, src_ip, dst_ip):
74         pkts = []
75         for i in range(0, 257):
76             info = self.create_packet_info(src_if, src_if)
77             payload = self.info_to_payload(info)
78             p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
79                  IPv6(src=src_ip, dst=dst_ip) /
80                  UDP(sport=1234, dport=1234) /
81                  Raw(payload))
82             info.data = p.copy()
83             pkts.append(p)
84         return pkts
85
86     def create_tunnel_stream_4o4(self, src_if,
87                                  tunnel_src, tunnel_dst,
88                                  src_ip, dst_ip):
89         pkts = []
90         for i in range(0, 257):
91             info = self.create_packet_info(src_if, src_if)
92             payload = self.info_to_payload(info)
93             p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
94                  IP(src=tunnel_src, dst=tunnel_dst) /
95                  GRE() /
96                  IP(src=src_ip, dst=dst_ip) /
97                  UDP(sport=1234, dport=1234) /
98                  Raw(payload))
99             info.data = p.copy()
100             pkts.append(p)
101         return pkts
102
103     def create_tunnel_stream_6o4(self, src_if,
104                                  tunnel_src, tunnel_dst,
105                                  src_ip, dst_ip):
106         pkts = []
107         for i in range(0, 257):
108             info = self.create_packet_info(src_if, src_if)
109             payload = self.info_to_payload(info)
110             p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
111                  IP(src=tunnel_src, dst=tunnel_dst) /
112                  GRE() /
113                  IPv6(src=src_ip, dst=dst_ip) /
114                  UDP(sport=1234, dport=1234) /
115                  Raw(payload))
116             info.data = p.copy()
117             pkts.append(p)
118         return pkts
119
120     def create_tunnel_stream_6o6(self, src_if,
121                                  tunnel_src, tunnel_dst,
122                                  src_ip, dst_ip):
123         pkts = []
124         for i in range(0, 257):
125             info = self.create_packet_info(src_if, src_if)
126             payload = self.info_to_payload(info)
127             p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
128                  IPv6(src=tunnel_src, dst=tunnel_dst) /
129                  GRE() /
130                  IPv6(src=src_ip, dst=dst_ip) /
131                  UDP(sport=1234, dport=1234) /
132                  Raw(payload))
133             info.data = p.copy()
134             pkts.append(p)
135         return pkts
136
137     def create_tunnel_stream_l2o4(self, src_if,
138                                   tunnel_src, tunnel_dst):
139         pkts = []
140         for i in range(0, 257):
141             info = self.create_packet_info(src_if, src_if)
142             payload = self.info_to_payload(info)
143             p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
144                  IP(src=tunnel_src, dst=tunnel_dst) /
145                  GRE() /
146                  Ether(dst=RandMAC('*:*:*:*:*:*'),
147                        src=RandMAC('*:*:*:*:*:*')) /
148                  IP(src=scapy.compat.raw(RandIP()),
149                     dst=scapy.compat.raw(RandIP())) /
150                  UDP(sport=1234, dport=1234) /
151                  Raw(payload))
152             info.data = p.copy()
153             pkts.append(p)
154         return pkts
155
156     def create_tunnel_stream_vlano4(self, src_if,
157                                     tunnel_src, tunnel_dst, vlan):
158         pkts = []
159         for i in range(0, 257):
160             info = self.create_packet_info(src_if, src_if)
161             payload = self.info_to_payload(info)
162             p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
163                  IP(src=tunnel_src, dst=tunnel_dst) /
164                  GRE() /
165                  Ether(dst=RandMAC('*:*:*:*:*:*'),
166                        src=RandMAC('*:*:*:*:*:*')) /
167                  Dot1Q(vlan=vlan) /
168                  IP(src=scapy.compat.raw(RandIP()),
169                     dst=scapy.compat.raw(RandIP())) /
170                  UDP(sport=1234, dport=1234) /
171                  Raw(payload))
172             info.data = p.copy()
173             pkts.append(p)
174         return pkts
175
176     def verify_tunneled_4o4(self, src_if, capture, sent,
177                             tunnel_src, tunnel_dst):
178
179         self.assertEqual(len(capture), len(sent))
180
181         for i in range(len(capture)):
182             try:
183                 tx = sent[i]
184                 rx = capture[i]
185
186                 tx_ip = tx[IP]
187                 rx_ip = rx[IP]
188
189                 self.assertEqual(rx_ip.src, tunnel_src)
190                 self.assertEqual(rx_ip.dst, tunnel_dst)
191
192                 rx_gre = rx[GRE]
193                 rx_ip = rx_gre[IP]
194
195                 self.assertEqual(rx_ip.src, tx_ip.src)
196                 self.assertEqual(rx_ip.dst, tx_ip.dst)
197                 # IP processing post pop has decremented the TTL
198                 self.assertEqual(rx_ip.ttl + 1, tx_ip.ttl)
199
200             except:
201                 self.logger.error(ppp("Rx:", rx))
202                 self.logger.error(ppp("Tx:", tx))
203                 raise
204
205     def verify_tunneled_6o6(self, src_if, capture, sent,
206                             tunnel_src, tunnel_dst):
207
208         self.assertEqual(len(capture), len(sent))
209
210         for i in range(len(capture)):
211             try:
212                 tx = sent[i]
213                 rx = capture[i]
214
215                 tx_ip = tx[IPv6]
216                 rx_ip = rx[IPv6]
217
218                 self.assertEqual(rx_ip.src, tunnel_src)
219                 self.assertEqual(rx_ip.dst, tunnel_dst)
220
221                 rx_gre = GRE(scapy.compat.raw(rx_ip[IPv6].payload))
222                 rx_ip = rx_gre[IPv6]
223
224                 self.assertEqual(rx_ip.src, tx_ip.src)
225                 self.assertEqual(rx_ip.dst, tx_ip.dst)
226
227             except:
228                 self.logger.error(ppp("Rx:", rx))
229                 self.logger.error(ppp("Tx:", tx))
230                 raise
231
232     def verify_tunneled_4o6(self, src_if, capture, sent,
233                             tunnel_src, tunnel_dst):
234
235         self.assertEqual(len(capture), len(sent))
236
237         for i in range(len(capture)):
238             try:
239                 tx = sent[i]
240                 rx = capture[i]
241
242                 rx_ip = rx[IPv6]
243
244                 self.assertEqual(rx_ip.src, tunnel_src)
245                 self.assertEqual(rx_ip.dst, tunnel_dst)
246
247                 rx_gre = GRE(scapy.compat.raw(rx_ip[IPv6].payload))
248                 tx_ip = tx[IP]
249                 rx_ip = rx_gre[IP]
250
251                 self.assertEqual(rx_ip.src, tx_ip.src)
252                 self.assertEqual(rx_ip.dst, tx_ip.dst)
253
254             except:
255                 self.logger.error(ppp("Rx:", rx))
256                 self.logger.error(ppp("Tx:", tx))
257                 raise
258
259     def verify_tunneled_6o4(self, src_if, capture, sent,
260                             tunnel_src, tunnel_dst):
261
262         self.assertEqual(len(capture), len(sent))
263
264         for i in range(len(capture)):
265             try:
266                 tx = sent[i]
267                 rx = capture[i]
268
269                 rx_ip = rx[IP]
270
271                 self.assertEqual(rx_ip.src, tunnel_src)
272                 self.assertEqual(rx_ip.dst, tunnel_dst)
273
274                 rx_gre = GRE(scapy.compat.raw(rx_ip[IP].payload))
275                 rx_ip = rx_gre[IPv6]
276                 tx_ip = tx[IPv6]
277
278                 self.assertEqual(rx_ip.src, tx_ip.src)
279                 self.assertEqual(rx_ip.dst, tx_ip.dst)
280
281             except:
282                 self.logger.error(ppp("Rx:", rx))
283                 self.logger.error(ppp("Tx:", tx))
284                 raise
285
286     def verify_tunneled_l2o4(self, src_if, capture, sent,
287                              tunnel_src, tunnel_dst):
288         self.assertEqual(len(capture), len(sent))
289
290         for i in range(len(capture)):
291             try:
292                 tx = sent[i]
293                 rx = capture[i]
294
295                 tx_ip = tx[IP]
296                 rx_ip = rx[IP]
297
298                 self.assertEqual(rx_ip.src, tunnel_src)
299                 self.assertEqual(rx_ip.dst, tunnel_dst)
300
301                 rx_gre = rx[GRE]
302                 rx_l2 = rx_gre[Ether]
303                 rx_ip = rx_l2[IP]
304                 tx_gre = tx[GRE]
305                 tx_l2 = tx_gre[Ether]
306                 tx_ip = tx_l2[IP]
307
308                 self.assertEqual(rx_ip.src, tx_ip.src)
309                 self.assertEqual(rx_ip.dst, tx_ip.dst)
310                 # bridged, not L3 forwarded, so no TTL decrement
311                 self.assertEqual(rx_ip.ttl, tx_ip.ttl)
312
313             except:
314                 self.logger.error(ppp("Rx:", rx))
315                 self.logger.error(ppp("Tx:", tx))
316                 raise
317
318     def verify_tunneled_vlano4(self, src_if, capture, sent,
319                                tunnel_src, tunnel_dst, vlan):
320         try:
321             self.assertEqual(len(capture), len(sent))
322         except:
323             ppc("Unexpected packets captured:", capture)
324             raise
325
326         for i in range(len(capture)):
327             try:
328                 tx = sent[i]
329                 rx = capture[i]
330
331                 tx_ip = tx[IP]
332                 rx_ip = rx[IP]
333
334                 self.assertEqual(rx_ip.src, tunnel_src)
335                 self.assertEqual(rx_ip.dst, tunnel_dst)
336
337                 rx_gre = rx[GRE]
338                 rx_l2 = rx_gre[Ether]
339                 rx_vlan = rx_l2[Dot1Q]
340                 rx_ip = rx_l2[IP]
341
342                 self.assertEqual(rx_vlan.vlan, vlan)
343
344                 tx_gre = tx[GRE]
345                 tx_l2 = tx_gre[Ether]
346                 tx_ip = tx_l2[IP]
347
348                 self.assertEqual(rx_ip.src, tx_ip.src)
349                 self.assertEqual(rx_ip.dst, tx_ip.dst)
350                 # bridged, not L3 forwarded, so no TTL decrement
351                 self.assertEqual(rx_ip.ttl, tx_ip.ttl)
352
353             except:
354                 self.logger.error(ppp("Rx:", rx))
355                 self.logger.error(ppp("Tx:", tx))
356                 raise
357
358     def verify_decapped_4o4(self, src_if, capture, sent):
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                 tx_gre = tx[GRE]
369                 tx_ip = tx_gre[IP]
370
371                 self.assertEqual(rx_ip.src, tx_ip.src)
372                 self.assertEqual(rx_ip.dst, tx_ip.dst)
373                 # IP processing post pop has decremented the TTL
374                 self.assertEqual(rx_ip.ttl + 1, tx_ip.ttl)
375
376             except:
377                 self.logger.error(ppp("Rx:", rx))
378                 self.logger.error(ppp("Tx:", tx))
379                 raise
380
381     def verify_decapped_6o4(self, src_if, capture, sent):
382         self.assertEqual(len(capture), len(sent))
383
384         for i in range(len(capture)):
385             try:
386                 tx = sent[i]
387                 rx = capture[i]
388
389                 tx_ip = tx[IP]
390                 rx_ip = rx[IPv6]
391                 tx_gre = tx[GRE]
392                 tx_ip = tx_gre[IPv6]
393
394                 self.assertEqual(rx_ip.src, tx_ip.src)
395                 self.assertEqual(rx_ip.dst, tx_ip.dst)
396                 self.assertEqual(rx_ip.hlim + 1, tx_ip.hlim)
397
398             except:
399                 self.logger.error(ppp("Rx:", rx))
400                 self.logger.error(ppp("Tx:", tx))
401                 raise
402
403     def test_gre(self):
404         """ GRE IPv4 tunnel Tests """
405
406         #
407         # Create an L3 GRE tunnel.
408         #  - set it admin up
409         #  - assign an IP Addres
410         #  - Add a route via the tunnel
411         #
412         gre_if = VppGreInterface(self,
413                                  self.pg0.local_ip4,
414                                  "1.1.1.2")
415         gre_if.add_vpp_config()
416
417         #
418         # The double create (create the same tunnel twice) should fail,
419         # and we should still be able to use the original
420         #
421         try:
422             gre_if.add_vpp_config()
423         except Exception:
424             pass
425         else:
426             self.fail("Double GRE tunnel add does not fail")
427
428         gre_if.admin_up()
429         gre_if.config_ip4()
430
431         route_via_tun = VppIpRoute(self, "4.4.4.4", 32,
432                                    [VppRoutePath("0.0.0.0",
433                                                  gre_if.sw_if_index)])
434
435         route_via_tun.add_vpp_config()
436
437         #
438         # Send a packet stream that is routed into the tunnel
439         #  - they are all dropped since the tunnel's destintation IP
440         #    is unresolved - or resolves via the default route - which
441         #    which is a drop.
442         #
443         tx = self.create_stream_ip4(self.pg0, "5.5.5.5", "4.4.4.4")
444
445         self.send_and_assert_no_replies(self.pg0, tx)
446
447         #
448         # Add a route that resolves the tunnel's destination
449         #
450         route_tun_dst = VppIpRoute(self, "1.1.1.2", 32,
451                                    [VppRoutePath(self.pg0.remote_ip4,
452                                                  self.pg0.sw_if_index)])
453         route_tun_dst.add_vpp_config()
454
455         #
456         # Send a packet stream that is routed into the tunnel
457         #  - packets are GRE encapped
458         #
459         tx = self.create_stream_ip4(self.pg0, "5.5.5.5", "4.4.4.4")
460         rx = self.send_and_expect(self.pg0, tx, self.pg0)
461         self.verify_tunneled_4o4(self.pg0, rx, tx,
462                                  self.pg0.local_ip4, "1.1.1.2")
463
464         #
465         # Send tunneled packets that match the created tunnel and
466         # are decapped and forwarded
467         #
468         tx = self.create_tunnel_stream_4o4(self.pg0,
469                                            "1.1.1.2",
470                                            self.pg0.local_ip4,
471                                            self.pg0.local_ip4,
472                                            self.pg0.remote_ip4)
473         rx = self.send_and_expect(self.pg0, tx, self.pg0)
474         self.verify_decapped_4o4(self.pg0, rx, tx)
475
476         #
477         # Send tunneled packets that do not match the tunnel's src
478         #
479         self.vapi.cli("clear trace")
480         tx = self.create_tunnel_stream_4o4(self.pg0,
481                                            "1.1.1.3",
482                                            self.pg0.local_ip4,
483                                            self.pg0.local_ip4,
484                                            self.pg0.remote_ip4)
485         self.send_and_assert_no_replies(
486             self.pg0, tx,
487             remark="GRE packets forwarded despite no SRC address match")
488
489         #
490         # Configure IPv6 on the PG interface so we can route IPv6
491         # packets
492         #
493         self.pg0.config_ip6()
494         self.pg0.resolve_ndp()
495
496         #
497         # Send IPv6 tunnel encapslated packets
498         #  - dropped since IPv6 is not enabled on the tunnel
499         #
500         tx = self.create_tunnel_stream_6o4(self.pg0,
501                                            "1.1.1.2",
502                                            self.pg0.local_ip4,
503                                            self.pg0.local_ip6,
504                                            self.pg0.remote_ip6)
505         self.send_and_assert_no_replies(self.pg0, tx,
506                                         "IPv6 GRE packets forwarded "
507                                         "despite IPv6 not enabled on tunnel")
508
509         #
510         # Enable IPv6 on the tunnel
511         #
512         gre_if.config_ip6()
513
514         #
515         # Send IPv6 tunnel encapslated packets
516         #  - forwarded since IPv6 is enabled on the tunnel
517         #
518         tx = self.create_tunnel_stream_6o4(self.pg0,
519                                            "1.1.1.2",
520                                            self.pg0.local_ip4,
521                                            self.pg0.local_ip6,
522                                            self.pg0.remote_ip6)
523         rx = self.send_and_expect(self.pg0, tx, self.pg0)
524         self.verify_decapped_6o4(self.pg0, rx, tx)
525
526         #
527         # Send v6 packets for v4 encap
528         #
529         route6_via_tun = VppIpRoute(
530             self, "2001::1", 128,
531             [VppRoutePath("::",
532                           gre_if.sw_if_index,
533                           proto=DpoProto.DPO_PROTO_IP6)],
534             is_ip6=1)
535         route6_via_tun.add_vpp_config()
536
537         tx = self.create_stream_ip6(self.pg0, "2001::2", "2001::1")
538         rx = self.send_and_expect(self.pg0, tx, self.pg0)
539
540         self.verify_tunneled_6o4(self.pg0, rx, tx,
541                                  self.pg0.local_ip4, "1.1.1.2")
542
543         #
544         # test case cleanup
545         #
546         route_tun_dst.remove_vpp_config()
547         route_via_tun.remove_vpp_config()
548         route6_via_tun.remove_vpp_config()
549         gre_if.remove_vpp_config()
550
551         self.pg0.unconfig_ip6()
552
553     def test_gre6(self):
554         """ GRE IPv6 tunnel Tests """
555
556         self.pg1.config_ip6()
557         self.pg1.resolve_ndp()
558
559         #
560         # Create an L3 GRE tunnel.
561         #  - set it admin up
562         #  - assign an IP Address
563         #  - Add a route via the tunnel
564         #
565         gre_if = VppGreInterface(self,
566                                  self.pg2.local_ip6,
567                                  "1002::1")
568         gre_if.add_vpp_config()
569         gre_if.admin_up()
570         gre_if.config_ip6()
571
572         route_via_tun = VppIpRoute(
573             self, "4004::1", 128,
574             [VppRoutePath("0::0",
575                           gre_if.sw_if_index,
576                           proto=DpoProto.DPO_PROTO_IP6)],
577             is_ip6=1)
578
579         route_via_tun.add_vpp_config()
580
581         #
582         # Send a packet stream that is routed into the tunnel
583         #  - they are all dropped since the tunnel's destintation IP
584         #    is unresolved - or resolves via the default route - which
585         #    which is a drop.
586         #
587         tx = self.create_stream_ip6(self.pg2, "5005::1", "4004::1")
588         self.send_and_assert_no_replies(
589             self.pg2, tx,
590             "GRE packets forwarded without DIP resolved")
591
592         #
593         # Add a route that resolves the tunnel's destination
594         #
595         route_tun_dst = VppIpRoute(
596             self, "1002::1", 128,
597             [VppRoutePath(self.pg2.remote_ip6,
598                           self.pg2.sw_if_index,
599                           proto=DpoProto.DPO_PROTO_IP6)],
600             is_ip6=1)
601         route_tun_dst.add_vpp_config()
602
603         #
604         # Send a packet stream that is routed into the tunnel
605         #  - packets are GRE encapped
606         #
607         tx = self.create_stream_ip6(self.pg2, "5005::1", "4004::1")
608         rx = self.send_and_expect(self.pg2, tx, self.pg2)
609         self.verify_tunneled_6o6(self.pg2, rx, tx,
610                                  self.pg2.local_ip6, "1002::1")
611
612         #
613         # Test decap. decapped packets go out pg1
614         #
615         tx = self.create_tunnel_stream_6o6(self.pg2,
616                                            "1002::1",
617                                            self.pg2.local_ip6,
618                                            "2001::1",
619                                            self.pg1.remote_ip6)
620         rx = self.send_and_expect(self.pg2, tx, self.pg1)
621
622         #
623         # RX'd packet is UDP over IPv6, test the GRE header is gone.
624         #
625         self.assertFalse(rx[0].haslayer(GRE))
626         self.assertEqual(rx[0][IPv6].dst, self.pg1.remote_ip6)
627
628         #
629         # Send v4 over v6
630         #
631         route4_via_tun = VppIpRoute(self, "1.1.1.1", 32,
632                                     [VppRoutePath("0.0.0.0",
633                                                   gre_if.sw_if_index)])
634         route4_via_tun.add_vpp_config()
635
636         tx = self.create_stream_ip4(self.pg0, "1.1.1.2", "1.1.1.1")
637         rx = self.send_and_expect(self.pg0, tx, self.pg2)
638
639         self.verify_tunneled_4o6(self.pg0, rx, tx,
640                                  self.pg2.local_ip6, "1002::1")
641
642         #
643         # test case cleanup
644         #
645         route_tun_dst.remove_vpp_config()
646         route_via_tun.remove_vpp_config()
647         route4_via_tun.remove_vpp_config()
648         gre_if.remove_vpp_config()
649
650         self.pg2.unconfig_ip6()
651         self.pg1.unconfig_ip6()
652
653     def test_gre_vrf(self):
654         """ GRE tunnel VRF Tests """
655
656         #
657         # Create an L3 GRE tunnel whose destination is in the non-default
658         # table. The underlay is thus non-default - the overlay is still
659         # the default.
660         #  - set it admin up
661         #  - assign an IP Addres
662         #
663         gre_if = VppGreInterface(self, self.pg1.local_ip4,
664                                  "2.2.2.2",
665                                  outer_fib_id=1)
666         gre_if.add_vpp_config()
667         gre_if.admin_up()
668         gre_if.config_ip4()
669
670         #
671         # Add a route via the tunnel - in the overlay
672         #
673         route_via_tun = VppIpRoute(self, "9.9.9.9", 32,
674                                    [VppRoutePath("0.0.0.0",
675                                                  gre_if.sw_if_index)])
676         route_via_tun.add_vpp_config()
677
678         #
679         # Add a route that resolves the tunnel's destination - in the
680         # underlay table
681         #
682         route_tun_dst = VppIpRoute(self, "2.2.2.2", 32, table_id=1,
683                                    paths=[VppRoutePath(self.pg1.remote_ip4,
684                                                        self.pg1.sw_if_index)])
685         route_tun_dst.add_vpp_config()
686
687         #
688         # Send a packet stream that is routed into the tunnel
689         # packets are sent in on pg0 which is in the default table
690         #  - packets are GRE encapped
691         #
692         self.vapi.cli("clear trace")
693         tx = self.create_stream_ip4(self.pg0, "5.5.5.5", "9.9.9.9")
694         rx = self.send_and_expect(self.pg0, tx, self.pg1)
695         self.verify_tunneled_4o4(self.pg1, rx, tx,
696                                  self.pg1.local_ip4, "2.2.2.2")
697
698         #
699         # Send tunneled packets that match the created tunnel and
700         # are decapped and forwarded. This tests the decap lookup
701         # does not happen in the encap table
702         #
703         self.vapi.cli("clear trace")
704         tx = self.create_tunnel_stream_4o4(self.pg1,
705                                            "2.2.2.2",
706                                            self.pg1.local_ip4,
707                                            self.pg0.local_ip4,
708                                            self.pg0.remote_ip4)
709         rx = self.send_and_expect(self.pg1, tx, self.pg0)
710         self.verify_decapped_4o4(self.pg0, rx, tx)
711
712         #
713         # Send tunneled packets that match the created tunnel
714         # but arrive on an interface that is not in the tunnel's
715         # encap VRF, these are dropped.
716         # IP enable the interface so they aren't dropped due to
717         # IP not being enabled.
718         #
719         self.pg2.config_ip4()
720         self.vapi.cli("clear trace")
721         tx = self.create_tunnel_stream_4o4(self.pg2,
722                                            "2.2.2.2",
723                                            self.pg1.local_ip4,
724                                            self.pg0.local_ip4,
725                                            self.pg0.remote_ip4)
726         rx = self.send_and_assert_no_replies(
727             self.pg2, tx,
728             "GRE decap packets in wrong VRF")
729
730         self.pg2.unconfig_ip4()
731
732         #
733         # test case cleanup
734         #
735         route_tun_dst.remove_vpp_config()
736         route_via_tun.remove_vpp_config()
737         gre_if.remove_vpp_config()
738
739     def test_gre_l2(self):
740         """ GRE tunnel L2 Tests """
741
742         #
743         # Add routes to resolve the tunnel destinations
744         #
745         route_tun1_dst = VppIpRoute(self, "2.2.2.2", 32,
746                                     [VppRoutePath(self.pg0.remote_ip4,
747                                                   self.pg0.sw_if_index)])
748         route_tun2_dst = VppIpRoute(self, "2.2.2.3", 32,
749                                     [VppRoutePath(self.pg0.remote_ip4,
750                                                   self.pg0.sw_if_index)])
751
752         route_tun1_dst.add_vpp_config()
753         route_tun2_dst.add_vpp_config()
754
755         #
756         # Create 2 L2 GRE tunnels and x-connect them
757         #
758         gre_if1 = VppGreInterface(self, self.pg0.local_ip4,
759                                   "2.2.2.2",
760                                   type=(VppEnum.vl_api_gre_tunnel_type_t.
761                                         GRE_API_TUNNEL_TYPE_TEB))
762         gre_if2 = VppGreInterface(self, self.pg0.local_ip4,
763                                   "2.2.2.3",
764                                   type=(VppEnum.vl_api_gre_tunnel_type_t.
765                                         GRE_API_TUNNEL_TYPE_TEB))
766         gre_if1.add_vpp_config()
767         gre_if2.add_vpp_config()
768
769         gre_if1.admin_up()
770         gre_if2.admin_up()
771
772         self.vapi.sw_interface_set_l2_xconnect(gre_if1.sw_if_index,
773                                                gre_if2.sw_if_index,
774                                                enable=1)
775         self.vapi.sw_interface_set_l2_xconnect(gre_if2.sw_if_index,
776                                                gre_if1.sw_if_index,
777                                                enable=1)
778
779         #
780         # Send in tunnel encapped L2. expect out tunnel encapped L2
781         # in both directions
782         #
783         tx = self.create_tunnel_stream_l2o4(self.pg0,
784                                             "2.2.2.2",
785                                             self.pg0.local_ip4)
786         rx = self.send_and_expect(self.pg0, tx, self.pg0)
787         self.verify_tunneled_l2o4(self.pg0, rx, tx,
788                                   self.pg0.local_ip4,
789                                   "2.2.2.3")
790
791         tx = self.create_tunnel_stream_l2o4(self.pg0,
792                                             "2.2.2.3",
793                                             self.pg0.local_ip4)
794         rx = self.send_and_expect(self.pg0, tx, self.pg0)
795         self.verify_tunneled_l2o4(self.pg0, rx, tx,
796                                   self.pg0.local_ip4,
797                                   "2.2.2.2")
798
799         self.vapi.sw_interface_set_l2_xconnect(gre_if1.sw_if_index,
800                                                gre_if2.sw_if_index,
801                                                enable=0)
802         self.vapi.sw_interface_set_l2_xconnect(gre_if2.sw_if_index,
803                                                gre_if1.sw_if_index,
804                                                enable=0)
805
806         #
807         # Create a VLAN sub-interfaces on the GRE TEB interfaces
808         # then x-connect them
809         #
810         gre_if_11 = VppDot1QSubint(self, gre_if1, 11)
811         gre_if_12 = VppDot1QSubint(self, gre_if2, 12)
812
813         # gre_if_11.add_vpp_config()
814         # gre_if_12.add_vpp_config()
815
816         gre_if_11.admin_up()
817         gre_if_12.admin_up()
818
819         self.vapi.sw_interface_set_l2_xconnect(gre_if_11.sw_if_index,
820                                                gre_if_12.sw_if_index,
821                                                enable=1)
822         self.vapi.sw_interface_set_l2_xconnect(gre_if_12.sw_if_index,
823                                                gre_if_11.sw_if_index,
824                                                enable=1)
825
826         #
827         # Configure both to pop thier respective VLAN tags,
828         # so that during the x-coonect they will subsequently push
829         #
830         self.vapi.l2_interface_vlan_tag_rewrite(
831             sw_if_index=gre_if_12.sw_if_index, vtr_op=L2_VTR_OP.L2_POP_1,
832             push_dot1q=12)
833         self.vapi.l2_interface_vlan_tag_rewrite(
834             sw_if_index=gre_if_11.sw_if_index, vtr_op=L2_VTR_OP.L2_POP_1,
835             push_dot1q=11)
836
837         #
838         # Send traffic in both directiond - expect the VLAN tags to
839         # be swapped.
840         #
841         tx = self.create_tunnel_stream_vlano4(self.pg0,
842                                               "2.2.2.2",
843                                               self.pg0.local_ip4,
844                                               11)
845         rx = self.send_and_expect(self.pg0, tx, self.pg0)
846         self.verify_tunneled_vlano4(self.pg0, rx, tx,
847                                     self.pg0.local_ip4,
848                                     "2.2.2.3",
849                                     12)
850
851         tx = self.create_tunnel_stream_vlano4(self.pg0,
852                                               "2.2.2.3",
853                                               self.pg0.local_ip4,
854                                               12)
855         rx = self.send_and_expect(self.pg0, tx, self.pg0)
856         self.verify_tunneled_vlano4(self.pg0, rx, tx,
857                                     self.pg0.local_ip4,
858                                     "2.2.2.2",
859                                     11)
860
861         #
862         # Cleanup Test resources
863         #
864         gre_if_11.remove_vpp_config()
865         gre_if_12.remove_vpp_config()
866         gre_if1.remove_vpp_config()
867         gre_if2.remove_vpp_config()
868         route_tun1_dst.add_vpp_config()
869         route_tun2_dst.add_vpp_config()
870
871     def test_gre_loop(self):
872         """ GRE tunnel loop Tests """
873
874         #
875         # Create an L3 GRE tunnel.
876         #  - set it admin up
877         #  - assign an IP Addres
878         #
879         gre_if = VppGreInterface(self,
880                                  self.pg0.local_ip4,
881                                  "1.1.1.2")
882         gre_if.add_vpp_config()
883         gre_if.admin_up()
884         gre_if.config_ip4()
885
886         #
887         # add a route to the tunnel's destination that points
888         # through the tunnel, hence forming a loop in the forwarding
889         # graph
890         #
891         route_dst = VppIpRoute(self, "1.1.1.2", 32,
892                                [VppRoutePath("0.0.0.0",
893                                              gre_if.sw_if_index)])
894         route_dst.add_vpp_config()
895
896         #
897         # packets to the tunnels destination should be dropped
898         #
899         tx = self.create_stream_ip4(self.pg0, "1.1.1.1", "1.1.1.2")
900         self.send_and_assert_no_replies(self.pg2, tx)
901
902         self.logger.info(self.vapi.ppcli("sh adj 7"))
903
904         #
905         # break the loop
906         #
907         route_dst.modify([VppRoutePath(self.pg1.remote_ip4,
908                                        self.pg1.sw_if_index)])
909         route_dst.add_vpp_config()
910
911         rx = self.send_and_expect(self.pg0, tx, self.pg1)
912
913         #
914         # a good route throught the tunnel to check it restacked
915         #
916         route_via_tun_2 = VppIpRoute(self, "2.2.2.2", 32,
917                                      [VppRoutePath("0.0.0.0",
918                                                    gre_if.sw_if_index)])
919         route_via_tun_2.add_vpp_config()
920
921         tx = self.create_stream_ip4(self.pg0, "2.2.2.3", "2.2.2.2")
922         rx = self.send_and_expect(self.pg0, tx, self.pg1)
923         self.verify_tunneled_4o4(self.pg1, rx, tx,
924                                  self.pg0.local_ip4, "1.1.1.2")
925
926         #
927         # cleanup
928         #
929         route_via_tun_2.remove_vpp_config()
930         gre_if.remove_vpp_config()
931
932
933 if __name__ == '__main__':
934     unittest.main(testRunner=VppTestRunner)