Tests: Raise exception if API cli_inband command fails.
[vpp.git] / test / test_gbp.py
1 #!/usr/bin/env python
2
3 from socket import AF_INET, AF_INET6
4 import unittest
5
6 from scapy.packet import Raw
7 from scapy.layers.l2 import Ether, ARP, Dot1Q
8 from scapy.layers.inet import IP, UDP, ICMP
9 from scapy.layers.inet6 import IPv6, ICMPv6ND_NS, ICMPv6NDOptSrcLLAddr, \
10     ICMPv6ND_NA
11 from scapy.utils6 import in6_getnsma, in6_getnsmac
12 from scapy.layers.vxlan import VXLAN
13 from scapy.data import ETH_P_IP, ETH_P_IPV6, ETH_P_ARP
14 from scapy.utils import inet_pton, inet_ntop
15
16 from framework import VppTestCase, VppTestRunner
17 from vpp_object import VppObject
18 from vpp_interface import VppInterface
19 from vpp_ip_route import VppIpRoute, VppRoutePath, VppIpTable, \
20     VppIpInterfaceAddress, VppIpInterfaceBind, find_route
21 from vpp_l2 import VppBridgeDomain, VppBridgeDomainPort, \
22     VppBridgeDomainArpEntry, VppL2FibEntry, find_bridge_domain_port, VppL2Vtr
23 from vpp_sub_interface import L2_VTR_OP, VppDot1QSubint
24 from vpp_ip import VppIpAddress, VppIpPrefix
25 from vpp_papi import VppEnum, MACAddress
26 from vpp_vxlan_gbp_tunnel import find_vxlan_gbp_tunnel, INDEX_INVALID, \
27     VppVxlanGbpTunnel
28 from vpp_neighbor import VppNeighbor
29
30 NUM_PKTS = 67
31
32
33 def find_gbp_endpoint(test, sw_if_index=None, ip=None, mac=None):
34     if ip:
35         vip = VppIpAddress(ip)
36     if mac:
37         vmac = MACAddress(mac)
38
39     eps = test.vapi.gbp_endpoint_dump()
40
41     for ep in eps:
42         if sw_if_index:
43             if ep.endpoint.sw_if_index != sw_if_index:
44                 continue
45         if ip:
46             for eip in ep.endpoint.ips:
47                 if vip == eip:
48                     return True
49         if mac:
50             if vmac.packed == ep.endpoint.mac:
51                 return True
52     return False
53
54
55 def find_gbp_vxlan(test, vni):
56     ts = test.vapi.gbp_vxlan_tunnel_dump()
57     for t in ts:
58         if t.tunnel.vni == vni:
59             return True
60     return False
61
62
63 class VppGbpEndpoint(VppObject):
64     """
65     GBP Endpoint
66     """
67
68     @property
69     def mac(self):
70         return str(self.vmac)
71
72     @property
73     def ip4(self):
74         return self._ip4
75
76     @property
77     def fip4(self):
78         return self._fip4
79
80     @property
81     def ip6(self):
82         return self._ip6
83
84     @property
85     def fip6(self):
86         return self._fip6
87
88     @property
89     def ips(self):
90         return [self.ip4, self.ip6]
91
92     @property
93     def fips(self):
94         return [self.fip4, self.fip6]
95
96     def __init__(self, test, itf, epg, recirc, ip4, fip4, ip6, fip6,
97                  flags=0,
98                  tun_src="0.0.0.0",
99                  tun_dst="0.0.0.0",
100                  mac=True):
101         self._test = test
102         self.itf = itf
103         self.epg = epg
104         self.recirc = recirc
105
106         self._ip4 = VppIpAddress(ip4)
107         self._fip4 = VppIpAddress(fip4)
108         self._ip6 = VppIpAddress(ip6)
109         self._fip6 = VppIpAddress(fip6)
110
111         if mac:
112             self.vmac = MACAddress(self.itf.remote_mac)
113         else:
114             self.vmac = MACAddress("00:00:00:00:00:00")
115
116         self.flags = flags
117         self.tun_src = VppIpAddress(tun_src)
118         self.tun_dst = VppIpAddress(tun_dst)
119
120     def add_vpp_config(self):
121         res = self._test.vapi.gbp_endpoint_add(
122             self.itf.sw_if_index,
123             [self.ip4.encode(), self.ip6.encode()],
124             self.vmac.packed,
125             self.epg.sclass,
126             self.flags,
127             self.tun_src.encode(),
128             self.tun_dst.encode())
129         self.handle = res.handle
130         self._test.registry.register(self, self._test.logger)
131
132     def remove_vpp_config(self):
133         self._test.vapi.gbp_endpoint_del(self.handle)
134
135     def object_id(self):
136         return "gbp-endpoint:[%d==%d:%s:%d]" % (self.handle,
137                                                 self.itf.sw_if_index,
138                                                 self.ip4.address,
139                                                 self.epg.sclass)
140
141     def query_vpp_config(self):
142         return find_gbp_endpoint(self._test,
143                                  self.itf.sw_if_index,
144                                  self.ip4.address)
145
146
147 class VppGbpRecirc(VppObject):
148     """
149     GBP Recirculation Interface
150     """
151
152     def __init__(self, test, epg, recirc, is_ext=False):
153         self._test = test
154         self.recirc = recirc
155         self.epg = epg
156         self.is_ext = is_ext
157
158     def add_vpp_config(self):
159         self._test.vapi.gbp_recirc_add_del(
160             1,
161             self.recirc.sw_if_index,
162             self.epg.sclass,
163             self.is_ext)
164         self._test.registry.register(self, self._test.logger)
165
166     def remove_vpp_config(self):
167         self._test.vapi.gbp_recirc_add_del(
168             0,
169             self.recirc.sw_if_index,
170             self.epg.sclass,
171             self.is_ext)
172
173     def object_id(self):
174         return "gbp-recirc:[%d]" % (self.recirc.sw_if_index)
175
176     def query_vpp_config(self):
177         rs = self._test.vapi.gbp_recirc_dump()
178         for r in rs:
179             if r.recirc.sw_if_index == self.recirc.sw_if_index:
180                 return True
181         return False
182
183
184 class VppGbpExtItf(VppObject):
185     """
186     GBP ExtItfulation Interface
187     """
188
189     def __init__(self, test, itf, bd, rd):
190         self._test = test
191         self.itf = itf
192         self.bd = bd
193         self.rd = rd
194
195     def add_vpp_config(self):
196         self._test.vapi.gbp_ext_itf_add_del(
197             1,
198             self.itf.sw_if_index,
199             self.bd.bd_id,
200             self.rd.rd_id)
201         self._test.registry.register(self, self._test.logger)
202
203     def remove_vpp_config(self):
204         self._test.vapi.gbp_ext_itf_add_del(
205             0,
206             self.itf.sw_if_index,
207             self.bd.bd_id,
208             self.rd.rd_id)
209
210     def object_id(self):
211         return "gbp-ext-itf:[%d]" % (self.itf.sw_if_index)
212
213     def query_vpp_config(self):
214         rs = self._test.vapi.gbp_ext_itf_dump()
215         for r in rs:
216             if r.ext_itf.sw_if_index == self.itf.sw_if_index:
217                 return True
218         return False
219
220
221 class VppGbpSubnet(VppObject):
222     """
223     GBP Subnet
224     """
225
226     def __init__(self, test, rd, address, address_len,
227                  type, sw_if_index=None, sclass=None):
228         self._test = test
229         self.rd_id = rd.rd_id
230         self.prefix = VppIpPrefix(address, address_len)
231         self.type = type
232         self.sw_if_index = sw_if_index
233         self.sclass = sclass
234
235     def add_vpp_config(self):
236         self._test.vapi.gbp_subnet_add_del(
237             1,
238             self.rd_id,
239             self.prefix.encode(),
240             self.type,
241             sw_if_index=self.sw_if_index if self.sw_if_index else 0xffffffff,
242             sclass=self.sclass if self.sclass else 0xffff)
243         self._test.registry.register(self, self._test.logger)
244
245     def remove_vpp_config(self):
246         self._test.vapi.gbp_subnet_add_del(
247             0,
248             self.rd_id,
249             self.prefix.encode(),
250             self.type)
251
252     def object_id(self):
253         return "gbp-subnet:[%d-%s]" % (self.rd_id, self.prefix)
254
255     def query_vpp_config(self):
256         ss = self._test.vapi.gbp_subnet_dump()
257         for s in ss:
258             if s.subnet.rd_id == self.rd_id and \
259                     s.subnet.type == self.type and \
260                     s.subnet.prefix == self.prefix:
261                 return True
262         return False
263
264
265 class VppGbpEndpointRetention(object):
266     def __init__(self, remote_ep_timeout=0xffffffff):
267         self.remote_ep_timeout = remote_ep_timeout
268
269     def encode(self):
270         return {'remote_ep_timeout': self.remote_ep_timeout}
271
272
273 class VppGbpEndpointGroup(VppObject):
274     """
275     GBP Endpoint Group
276     """
277
278     def __init__(self, test, vnid, sclass, rd, bd, uplink,
279                  bvi, bvi_ip4, bvi_ip6=None,
280                  retention=VppGbpEndpointRetention()):
281         self._test = test
282         self.uplink = uplink
283         self.bvi = bvi
284         self.bvi_ip4 = VppIpAddress(bvi_ip4)
285         self.bvi_ip6 = VppIpAddress(bvi_ip6)
286         self.vnid = vnid
287         self.bd = bd
288         self.rd = rd
289         self.sclass = sclass
290         if 0 == self.sclass:
291             self.sclass = 0xffff
292         self.retention = retention
293
294     def add_vpp_config(self):
295         self._test.vapi.gbp_endpoint_group_add(
296             self.vnid,
297             self.sclass,
298             self.bd.bd.bd_id,
299             self.rd.rd_id,
300             self.uplink.sw_if_index if self.uplink else INDEX_INVALID,
301             self.retention.encode())
302         self._test.registry.register(self, self._test.logger)
303
304     def remove_vpp_config(self):
305         self._test.vapi.gbp_endpoint_group_del(self.sclass)
306
307     def object_id(self):
308         return "gbp-endpoint-group:[%d]" % (self.vnid)
309
310     def query_vpp_config(self):
311         epgs = self._test.vapi.gbp_endpoint_group_dump()
312         for epg in epgs:
313             if epg.epg.vnid == self.vnid:
314                 return True
315         return False
316
317
318 class VppGbpBridgeDomain(VppObject):
319     """
320     GBP Bridge Domain
321     """
322
323     def __init__(self, test, bd, bvi, uu_fwd=None,
324                  bm_flood=None, learn=True, uu_drop=False, bm_drop=False):
325         self._test = test
326         self.bvi = bvi
327         self.uu_fwd = uu_fwd
328         self.bm_flood = bm_flood
329         self.bd = bd
330
331         e = VppEnum.vl_api_gbp_bridge_domain_flags_t
332         if (learn):
333             self.learn = e.GBP_BD_API_FLAG_NONE
334         else:
335             self.learn = e.GBP_BD_API_FLAG_DO_NOT_LEARN
336         if (uu_drop):
337             self.learn |= e.GBP_BD_API_FLAG_UU_FWD_DROP
338         if (bm_drop):
339             self.learn |= e.GBP_BD_API_FLAG_MCAST_DROP
340
341     def add_vpp_config(self):
342         self._test.vapi.gbp_bridge_domain_add(
343             self.bd.bd_id,
344             self.learn,
345             self.bvi.sw_if_index,
346             self.uu_fwd.sw_if_index if self.uu_fwd else INDEX_INVALID,
347             self.bm_flood.sw_if_index if self.bm_flood else INDEX_INVALID)
348         self._test.registry.register(self, self._test.logger)
349
350     def remove_vpp_config(self):
351         self._test.vapi.gbp_bridge_domain_del(self.bd.bd_id)
352
353     def object_id(self):
354         return "gbp-bridge-domain:[%d]" % (self.bd.bd_id)
355
356     def query_vpp_config(self):
357         bds = self._test.vapi.gbp_bridge_domain_dump()
358         for bd in bds:
359             if bd.bd.bd_id == self.bd.bd_id:
360                 return True
361         return False
362
363
364 class VppGbpRouteDomain(VppObject):
365     """
366     GBP Route Domain
367     """
368
369     def __init__(self, test, rd_id, t4, t6, ip4_uu=None, ip6_uu=None):
370         self._test = test
371         self.rd_id = rd_id
372         self.t4 = t4
373         self.t6 = t6
374         self.ip4_uu = ip4_uu
375         self.ip6_uu = ip6_uu
376
377     def add_vpp_config(self):
378         self._test.vapi.gbp_route_domain_add(
379             self.rd_id,
380             self.t4.table_id,
381             self.t6.table_id,
382             self.ip4_uu.sw_if_index if self.ip4_uu else INDEX_INVALID,
383             self.ip6_uu.sw_if_index if self.ip6_uu else INDEX_INVALID)
384         self._test.registry.register(self, self._test.logger)
385
386     def remove_vpp_config(self):
387         self._test.vapi.gbp_route_domain_del(self.rd_id)
388
389     def object_id(self):
390         return "gbp-route-domain:[%d]" % (self.rd_id)
391
392     def query_vpp_config(self):
393         rds = self._test.vapi.gbp_route_domain_dump()
394         for rd in rds:
395             if rd.rd.rd_id == self.rd_id:
396                 return True
397         return False
398
399
400 class VppGbpContractNextHop():
401     def __init__(self, mac, bd, ip, rd):
402         self.mac = mac
403         self.ip = ip
404         self.bd = bd
405         self.rd = rd
406
407     def encode(self):
408         return {'ip': self.ip.encode(),
409                 'mac': self.mac.packed,
410                 'bd_id': self.bd.bd.bd_id,
411                 'rd_id': self.rd.rd_id}
412
413
414 class VppGbpContractRule():
415     def __init__(self, action, hash_mode, nhs=[]):
416         self.action = action
417         self.hash_mode = hash_mode
418         self.nhs = nhs
419
420     def encode(self):
421         nhs = []
422         for nh in self.nhs:
423             nhs.append(nh.encode())
424         while len(nhs) < 8:
425             nhs.append({})
426         return {'action': self.action,
427                 'nh_set': {
428                     'hash_mode': self.hash_mode,
429                     'n_nhs': len(self.nhs),
430                     'nhs': nhs}}
431
432
433 class VppGbpContract(VppObject):
434     """
435     GBP Contract
436     """
437
438     def __init__(self, test, sclass, dclass, acl_index,
439                  rules, allowed_ethertypes):
440         self._test = test
441         self.acl_index = acl_index
442         self.sclass = sclass
443         self.dclass = dclass
444         self.rules = rules
445         self.allowed_ethertypes = allowed_ethertypes
446         while (len(self.allowed_ethertypes) < 16):
447             self.allowed_ethertypes.append(0)
448
449     def add_vpp_config(self):
450         rules = []
451         for r in self.rules:
452             rules.append(r.encode())
453         r = self._test.vapi.gbp_contract_add_del(
454             1,
455             self.sclass,
456             self.dclass,
457             self.acl_index,
458             rules,
459             self.allowed_ethertypes)
460         self.stats_index = r.stats_index
461         self._test.registry.register(self, self._test.logger)
462
463     def remove_vpp_config(self):
464         self._test.vapi.gbp_contract_add_del(
465             0,
466             self.sclass,
467             self.dclass,
468             self.acl_index,
469             [],
470             self.allowed_ethertypes)
471
472     def object_id(self):
473         return "gbp-contract:[%d:%s:%d]" % (self.sclass,
474                                             self.dclass,
475                                             self.acl_index)
476
477     def query_vpp_config(self):
478         cs = self._test.vapi.gbp_contract_dump()
479         for c in cs:
480             if c.contract.sclass == self.sclass \
481                     and c.contract.dclass == self.dclass:
482                 return True
483         return False
484
485     def get_drop_stats(self):
486         c = self._test.statistics.get_counter("/net/gbp/contract/drop")
487         return c[0][self.stats_index]
488
489     def get_permit_stats(self):
490         c = self._test.statistics.get_counter("/net/gbp/contract/permit")
491         return c[0][self.stats_index]
492
493
494 class VppGbpVxlanTunnel(VppInterface):
495     """
496     GBP VXLAN tunnel
497     """
498
499     def __init__(self, test, vni, bd_rd_id, mode, src):
500         super(VppGbpVxlanTunnel, self).__init__(test)
501         self._test = test
502         self.vni = vni
503         self.bd_rd_id = bd_rd_id
504         self.mode = mode
505         self.src = src
506
507     def add_vpp_config(self):
508         r = self._test.vapi.gbp_vxlan_tunnel_add(
509             self.vni,
510             self.bd_rd_id,
511             self.mode,
512             self.src)
513         self.set_sw_if_index(r.sw_if_index)
514         self._test.registry.register(self, self._test.logger)
515
516     def remove_vpp_config(self):
517         self._test.vapi.gbp_vxlan_tunnel_del(self.vni)
518
519     def object_id(self):
520         return "gbp-vxlan:%d" % (self.sw_if_index)
521
522     def query_vpp_config(self):
523         return find_gbp_vxlan(self._test, self.vni)
524
525
526 class VppGbpAcl(VppObject):
527     """
528     GBP Acl
529     """
530
531     def __init__(self, test):
532         self._test = test
533         self.acl_index = 4294967295
534
535     def create_rule(self, is_ipv6=0, permit_deny=0, proto=-1,
536                     s_prefix=0, s_ip=b'\x00\x00\x00\x00', sport_from=0,
537                     sport_to=65535, d_prefix=0, d_ip=b'\x00\x00\x00\x00',
538                     dport_from=0, dport_to=65535):
539         if proto == -1 or proto == 0:
540             sport_to = 0
541             dport_to = sport_to
542         elif proto == 1 or proto == 58:
543             sport_to = 255
544             dport_to = sport_to
545         rule = ({'is_permit': permit_deny, 'is_ipv6': is_ipv6, 'proto': proto,
546                  'srcport_or_icmptype_first': sport_from,
547                  'srcport_or_icmptype_last': sport_to,
548                  'src_ip_prefix_len': s_prefix,
549                  'src_ip_addr': s_ip,
550                  'dstport_or_icmpcode_first': dport_from,
551                  'dstport_or_icmpcode_last': dport_to,
552                  'dst_ip_prefix_len': d_prefix,
553                  'dst_ip_addr': d_ip})
554         return rule
555
556     def add_vpp_config(self, rules):
557
558         reply = self._test.vapi.acl_add_replace(self.acl_index,
559                                                 r=rules,
560                                                 tag=b'GBPTest')
561         self.acl_index = reply.acl_index
562         return self.acl_index
563
564     def remove_vpp_config(self):
565         self._test.vapi.acl_del(self.acl_index)
566
567     def object_id(self):
568         return "gbp-acl:[%d]" % (self.acl_index)
569
570     def query_vpp_config(self):
571         cs = self._test.vapi.acl_dump()
572         for c in cs:
573             if c.acl_index == self.acl_index:
574                 return True
575         return False
576
577
578 class TestGBP(VppTestCase):
579     """ GBP Test Case """
580
581     @property
582     def config_flags(self):
583         return VppEnum.vl_api_nat_config_flags_t
584
585     @classmethod
586     def setUpClass(cls):
587         super(TestGBP, cls).setUpClass()
588
589     @classmethod
590     def tearDownClass(cls):
591         super(TestGBP, cls).tearDownClass()
592
593     def setUp(self):
594         super(TestGBP, self).setUp()
595
596         self.create_pg_interfaces(range(9))
597         self.create_loopback_interfaces(8)
598
599         self.router_mac = MACAddress("00:11:22:33:44:55")
600
601         for i in self.pg_interfaces:
602             i.admin_up()
603         for i in self.lo_interfaces:
604             i.admin_up()
605
606     def tearDown(self):
607         for i in self.pg_interfaces:
608             i.admin_down()
609
610         super(TestGBP, self).tearDown()
611
612     def send_and_expect_bridged(self, src, tx, dst):
613         rx = self.send_and_expect(src, tx, dst)
614
615         for r in rx:
616             self.assertEqual(r[Ether].src, tx[0][Ether].src)
617             self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
618             self.assertEqual(r[IP].src, tx[0][IP].src)
619             self.assertEqual(r[IP].dst, tx[0][IP].dst)
620         return rx
621
622     def send_and_expect_bridged6(self, src, tx, dst):
623         rx = self.send_and_expect(src, tx, dst)
624
625         for r in rx:
626             self.assertEqual(r[Ether].src, tx[0][Ether].src)
627             self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
628             self.assertEqual(r[IPv6].src, tx[0][IPv6].src)
629             self.assertEqual(r[IPv6].dst, tx[0][IPv6].dst)
630         return rx
631
632     def send_and_expect_routed(self, src, tx, dst, src_mac):
633         rx = self.send_and_expect(src, tx, dst)
634
635         for r in rx:
636             self.assertEqual(r[Ether].src, src_mac)
637             self.assertEqual(r[Ether].dst, dst.remote_mac)
638             self.assertEqual(r[IP].src, tx[0][IP].src)
639             self.assertEqual(r[IP].dst, tx[0][IP].dst)
640         return rx
641
642     def send_and_expect_natted(self, src, tx, dst, src_ip):
643         rx = self.send_and_expect(src, tx, dst)
644
645         for r in rx:
646             self.assertEqual(r[Ether].src, tx[0][Ether].src)
647             self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
648             self.assertEqual(r[IP].src, src_ip)
649             self.assertEqual(r[IP].dst, tx[0][IP].dst)
650         return rx
651
652     def send_and_expect_natted6(self, src, tx, dst, src_ip):
653         rx = self.send_and_expect(src, tx, dst)
654
655         for r in rx:
656             self.assertEqual(r[Ether].src, tx[0][Ether].src)
657             self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
658             self.assertEqual(r[IPv6].src, src_ip)
659             self.assertEqual(r[IPv6].dst, tx[0][IPv6].dst)
660         return rx
661
662     def send_and_expect_unnatted(self, src, tx, dst, dst_ip):
663         rx = self.send_and_expect(src, tx, dst)
664
665         for r in rx:
666             self.assertEqual(r[Ether].src, tx[0][Ether].src)
667             self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
668             self.assertEqual(r[IP].dst, dst_ip)
669             self.assertEqual(r[IP].src, tx[0][IP].src)
670         return rx
671
672     def send_and_expect_unnatted6(self, src, tx, dst, dst_ip):
673         rx = self.send_and_expect(src, tx, dst)
674
675         for r in rx:
676             self.assertEqual(r[Ether].src, tx[0][Ether].src)
677             self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
678             self.assertEqual(r[IPv6].dst, dst_ip)
679             self.assertEqual(r[IPv6].src, tx[0][IPv6].src)
680         return rx
681
682     def send_and_expect_double_natted(self, src, tx, dst, src_ip, dst_ip):
683         rx = self.send_and_expect(src, tx, dst)
684
685         for r in rx:
686             self.assertEqual(r[Ether].src, str(self.router_mac))
687             self.assertEqual(r[Ether].dst, dst.remote_mac)
688             self.assertEqual(r[IP].dst, dst_ip)
689             self.assertEqual(r[IP].src, src_ip)
690         return rx
691
692     def send_and_expect_double_natted6(self, src, tx, dst, src_ip, dst_ip):
693         rx = self.send_and_expect(src, tx, dst)
694
695         for r in rx:
696             self.assertEqual(r[Ether].src, str(self.router_mac))
697             self.assertEqual(r[Ether].dst, dst.remote_mac)
698             self.assertEqual(r[IPv6].dst, dst_ip)
699             self.assertEqual(r[IPv6].src, src_ip)
700         return rx
701
702     def send_and_expect_no_arp(self, src, tx, dst):
703         self.pg_send(src, tx)
704         dst.get_capture(0, timeout=1)
705         dst.assert_nothing_captured(remark="")
706         timeout = 0.1
707
708     def send_and_expect_arp(self, src, tx, dst):
709         rx = self.send_and_expect(src, tx, dst)
710
711         for r in rx:
712             self.assertEqual(r[Ether].src, tx[0][Ether].src)
713             self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
714             self.assertEqual(r[ARP].psrc, tx[0][ARP].psrc)
715             self.assertEqual(r[ARP].pdst, tx[0][ARP].pdst)
716             self.assertEqual(r[ARP].hwsrc, tx[0][ARP].hwsrc)
717             self.assertEqual(r[ARP].hwdst, tx[0][ARP].hwdst)
718         return rx
719
720     def test_gbp(self):
721         """ Group Based Policy """
722
723         ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
724
725         #
726         # Bridge Domains
727         #
728         bd1 = VppBridgeDomain(self, 1)
729         bd2 = VppBridgeDomain(self, 2)
730         bd20 = VppBridgeDomain(self, 20)
731
732         bd1.add_vpp_config()
733         bd2.add_vpp_config()
734         bd20.add_vpp_config()
735
736         gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0)
737         gbd2 = VppGbpBridgeDomain(self, bd2, self.loop1)
738         gbd20 = VppGbpBridgeDomain(self, bd20, self.loop2)
739
740         gbd1.add_vpp_config()
741         gbd2.add_vpp_config()
742         gbd20.add_vpp_config()
743
744         #
745         # Route Domains
746         #
747         gt4 = VppIpTable(self, 0)
748         gt4.add_vpp_config()
749         gt6 = VppIpTable(self, 0, is_ip6=True)
750         gt6.add_vpp_config()
751         nt4 = VppIpTable(self, 20)
752         nt4.add_vpp_config()
753         nt6 = VppIpTable(self, 20, is_ip6=True)
754         nt6.add_vpp_config()
755
756         rd0 = VppGbpRouteDomain(self, 0, gt4, gt6, None, None)
757         rd20 = VppGbpRouteDomain(self, 20, nt4, nt6, None, None)
758
759         rd0.add_vpp_config()
760         rd20.add_vpp_config()
761
762         #
763         # 3 EPGs, 2 of which share a BD.
764         # 2 NAT EPGs, one for floating-IP subnets, the other for internet
765         #
766         epgs = [VppGbpEndpointGroup(self, 220, 1220, rd0, gbd1,
767                                     self.pg4, self.loop0,
768                                     "10.0.0.128", "2001:10::128"),
769                 VppGbpEndpointGroup(self, 221, 1221, rd0, gbd1,
770                                     self.pg5, self.loop0,
771                                     "10.0.1.128", "2001:10:1::128"),
772                 VppGbpEndpointGroup(self, 222, 1222, rd0, gbd2,
773                                     self.pg6, self.loop1,
774                                     "10.0.2.128", "2001:10:2::128"),
775                 VppGbpEndpointGroup(self, 333, 1333, rd20, gbd20,
776                                     self.pg7, self.loop2,
777                                     "11.0.0.128", "3001::128"),
778                 VppGbpEndpointGroup(self, 444, 1444, rd20, gbd20,
779                                     self.pg8, self.loop2,
780                                     "11.0.0.129", "3001::129")]
781         recircs = [VppGbpRecirc(self, epgs[0], self.loop3),
782                    VppGbpRecirc(self, epgs[1], self.loop4),
783                    VppGbpRecirc(self, epgs[2], self.loop5),
784                    VppGbpRecirc(self, epgs[3], self.loop6, is_ext=True),
785                    VppGbpRecirc(self, epgs[4], self.loop7, is_ext=True)]
786
787         epg_nat = epgs[3]
788         recirc_nat = recircs[3]
789
790         #
791         # 4 end-points, 2 in the same subnet, 3 in the same BD
792         #
793         eps = [VppGbpEndpoint(self, self.pg0,
794                               epgs[0], recircs[0],
795                               "10.0.0.1", "11.0.0.1",
796                               "2001:10::1", "3001::1"),
797                VppGbpEndpoint(self, self.pg1,
798                               epgs[0], recircs[0],
799                               "10.0.0.2", "11.0.0.2",
800                               "2001:10::2", "3001::2"),
801                VppGbpEndpoint(self, self.pg2,
802                               epgs[1], recircs[1],
803                               "10.0.1.1", "11.0.0.3",
804                               "2001:10:1::1", "3001::3"),
805                VppGbpEndpoint(self, self.pg3,
806                               epgs[2], recircs[2],
807                               "10.0.2.1", "11.0.0.4",
808                               "2001:10:2::1", "3001::4")]
809
810         #
811         # Config related to each of the EPGs
812         #
813         for epg in epgs:
814             # IP config on the BVI interfaces
815             if epg != epgs[1] and epg != epgs[4]:
816                 VppIpInterfaceBind(self, epg.bvi, epg.rd.t4).add_vpp_config()
817                 VppIpInterfaceBind(self, epg.bvi, epg.rd.t6).add_vpp_config()
818                 self.vapi.sw_interface_set_mac_address(
819                     epg.bvi.sw_if_index,
820                     self.router_mac.packed)
821
822                 # The BVIs are NAT inside interfaces
823                 flags = self.config_flags.NAT_IS_INSIDE
824                 self.vapi.nat44_interface_add_del_feature(
825                     sw_if_index=epg.bvi.sw_if_index,
826                     flags=flags, is_add=1)
827                 self.vapi.nat66_add_del_interface(
828                     is_add=1, flags=flags,
829                     sw_if_index=epg.bvi.sw_if_index)
830
831             if_ip4 = VppIpInterfaceAddress(self, epg.bvi, epg.bvi_ip4, 32)
832             if_ip6 = VppIpInterfaceAddress(self, epg.bvi, epg.bvi_ip6, 128)
833             if_ip4.add_vpp_config()
834             if_ip6.add_vpp_config()
835
836             # EPG uplink interfaces in the RD
837             VppIpInterfaceBind(self, epg.uplink, epg.rd.t4).add_vpp_config()
838             VppIpInterfaceBind(self, epg.uplink, epg.rd.t6).add_vpp_config()
839
840             # add the BD ARP termination entry for BVI IP
841             epg.bd_arp_ip4 = VppBridgeDomainArpEntry(self, epg.bd.bd,
842                                                      str(self.router_mac),
843                                                      epg.bvi_ip4)
844             epg.bd_arp_ip6 = VppBridgeDomainArpEntry(self, epg.bd.bd,
845                                                      str(self.router_mac),
846                                                      epg.bvi_ip6)
847             epg.bd_arp_ip4.add_vpp_config()
848             epg.bd_arp_ip6.add_vpp_config()
849
850             # EPG in VPP
851             epg.add_vpp_config()
852
853         for recirc in recircs:
854             # EPG's ingress recirculation interface maps to its RD
855             VppIpInterfaceBind(self, recirc.recirc,
856                                recirc.epg.rd.t4).add_vpp_config()
857             VppIpInterfaceBind(self, recirc.recirc,
858                                recirc.epg.rd.t6).add_vpp_config()
859
860             self.vapi.nat44_interface_add_del_feature(
861                 sw_if_index=recirc.recirc.sw_if_index, is_add=1)
862             self.vapi.nat66_add_del_interface(
863                 is_add=1,
864                 sw_if_index=recirc.recirc.sw_if_index)
865
866             recirc.add_vpp_config()
867
868         for recirc in recircs:
869             self.assertTrue(find_bridge_domain_port(self,
870                                                     recirc.epg.bd.bd.bd_id,
871                                                     recirc.recirc.sw_if_index))
872
873         for ep in eps:
874             self.pg_enable_capture(self.pg_interfaces)
875             self.pg_start()
876             #
877             # routes to the endpoints. We need these since there are no
878             # adj-fibs due to the fact the the BVI address has /32 and
879             # the subnet is not attached.
880             #
881             for (ip, fip) in zip(ep.ips, ep.fips):
882                 # Add static mappings for each EP from the 10/8 to 11/8 network
883                 if ip.af == AF_INET:
884                     flags = self.config_flags.NAT_IS_ADDR_ONLY
885                     self.vapi.nat44_add_del_static_mapping(
886                         is_add=1,
887                         local_ip_address=ip.bytes,
888                         external_ip_address=fip.bytes,
889                         external_sw_if_index=0xFFFFFFFF,
890                         vrf_id=0,
891                         flags=flags)
892                 else:
893                     self.vapi.nat66_add_del_static_mapping(
894                         local_ip_address=ip.bytes,
895                         external_ip_address=fip.bytes,
896                         vrf_id=0, is_add=1)
897
898             # VPP EP create ...
899             ep.add_vpp_config()
900
901             self.logger.info(self.vapi.cli("sh gbp endpoint"))
902
903             # ... results in a Gratuitous ARP/ND on the EPG's uplink
904             rx = ep.epg.uplink.get_capture(len(ep.ips), timeout=0.2)
905
906             for ii, ip in enumerate(ep.ips):
907                 p = rx[ii]
908
909                 if ip.is_ip6:
910                     self.assertTrue(p.haslayer(ICMPv6ND_NA))
911                     self.assertEqual(p[ICMPv6ND_NA].tgt, ip.address)
912                 else:
913                     self.assertTrue(p.haslayer(ARP))
914                     self.assertEqual(p[ARP].psrc, ip.address)
915                     self.assertEqual(p[ARP].pdst, ip.address)
916
917             # add the BD ARP termination entry for floating IP
918             for fip in ep.fips:
919                 ba = VppBridgeDomainArpEntry(self, epg_nat.bd.bd, ep.mac, fip)
920                 ba.add_vpp_config()
921
922                 # floating IPs route via EPG recirc
923                 r = VppIpRoute(self, fip.address, fip.length,
924                                [VppRoutePath(fip.address,
925                                              ep.recirc.recirc.sw_if_index,
926                                              is_dvr=1,
927                                              proto=fip.dpo_proto)],
928                                table_id=20,
929                                is_ip6=fip.is_ip6)
930                 r.add_vpp_config()
931
932             # L2 FIB entries in the NAT EPG BD to bridge the packets from
933             # the outside direct to the internal EPG
934             lf = VppL2FibEntry(self, epg_nat.bd.bd, ep.mac,
935                                ep.recirc.recirc, bvi_mac=0)
936             lf.add_vpp_config()
937
938         #
939         # ARP packets for unknown IP are sent to the EPG uplink
940         #
941         pkt_arp = (Ether(dst="ff:ff:ff:ff:ff:ff",
942                          src=self.pg0.remote_mac) /
943                    ARP(op="who-has",
944                        hwdst="ff:ff:ff:ff:ff:ff",
945                        hwsrc=self.pg0.remote_mac,
946                        pdst="10.0.0.88",
947                        psrc="10.0.0.99"))
948
949         self.vapi.cli("clear trace")
950         self.pg0.add_stream(pkt_arp)
951
952         self.pg_enable_capture(self.pg_interfaces)
953         self.pg_start()
954
955         rxd = epgs[0].uplink.get_capture(1)
956
957         #
958         # ARP/ND packets get a response
959         #
960         pkt_arp = (Ether(dst="ff:ff:ff:ff:ff:ff",
961                          src=self.pg0.remote_mac) /
962                    ARP(op="who-has",
963                        hwdst="ff:ff:ff:ff:ff:ff",
964                        hwsrc=self.pg0.remote_mac,
965                        pdst=epgs[0].bvi_ip4.address,
966                        psrc=eps[0].ip4.address))
967
968         self.send_and_expect(self.pg0, [pkt_arp], self.pg0)
969
970         nsma = in6_getnsma(inet_pton(AF_INET6, eps[0].ip6.address))
971         d = inet_ntop(AF_INET6, nsma)
972         pkt_nd = (Ether(dst=in6_getnsmac(nsma),
973                         src=self.pg0.remote_mac) /
974                   IPv6(dst=d, src=eps[0].ip6.address) /
975                   ICMPv6ND_NS(tgt=epgs[0].bvi_ip6.address) /
976                   ICMPv6NDOptSrcLLAddr(lladdr=self.pg0.remote_mac))
977         self.send_and_expect(self.pg0, [pkt_nd], self.pg0)
978
979         #
980         # broadcast packets are flooded
981         #
982         pkt_bcast = (Ether(dst="ff:ff:ff:ff:ff:ff",
983                            src=self.pg0.remote_mac) /
984                      IP(src=eps[0].ip4.address, dst="232.1.1.1") /
985                      UDP(sport=1234, dport=1234) /
986                      Raw('\xa5' * 100))
987
988         self.vapi.cli("clear trace")
989         self.pg0.add_stream(pkt_bcast)
990
991         self.pg_enable_capture(self.pg_interfaces)
992         self.pg_start()
993
994         rxd = eps[1].itf.get_capture(1)
995         self.assertEqual(rxd[0][Ether].dst, pkt_bcast[Ether].dst)
996         rxd = epgs[0].uplink.get_capture(1)
997         self.assertEqual(rxd[0][Ether].dst, pkt_bcast[Ether].dst)
998
999         #
1000         # packets to non-local L3 destinations dropped
1001         #
1002         pkt_intra_epg_220_ip4 = (Ether(src=self.pg0.remote_mac,
1003                                        dst=str(self.router_mac)) /
1004                                  IP(src=eps[0].ip4.address,
1005                                     dst="10.0.0.99") /
1006                                  UDP(sport=1234, dport=1234) /
1007                                  Raw('\xa5' * 100))
1008         pkt_inter_epg_222_ip4 = (Ether(src=self.pg0.remote_mac,
1009                                        dst=str(self.router_mac)) /
1010                                  IP(src=eps[0].ip4.address,
1011                                     dst="10.0.1.99") /
1012                                  UDP(sport=1234, dport=1234) /
1013                                  Raw('\xa5' * 100))
1014
1015         self.send_and_assert_no_replies(self.pg0,
1016                                         pkt_intra_epg_220_ip4 * NUM_PKTS)
1017
1018         pkt_inter_epg_222_ip6 = (Ether(src=self.pg0.remote_mac,
1019                                        dst=str(self.router_mac)) /
1020                                  IPv6(src=eps[0].ip6.address,
1021                                       dst="2001:10::99") /
1022                                  UDP(sport=1234, dport=1234) /
1023                                  Raw('\xa5' * 100))
1024         self.send_and_assert_no_replies(self.pg0,
1025                                         pkt_inter_epg_222_ip6 * NUM_PKTS)
1026
1027         #
1028         # Add the subnet routes
1029         #
1030         s41 = VppGbpSubnet(
1031             self, rd0, "10.0.0.0", 24,
1032             VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1033         s42 = VppGbpSubnet(
1034             self, rd0, "10.0.1.0", 24,
1035             VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1036         s43 = VppGbpSubnet(
1037             self, rd0, "10.0.2.0", 24,
1038             VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1039         s61 = VppGbpSubnet(
1040             self, rd0, "2001:10::1", 64,
1041             VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1042         s62 = VppGbpSubnet(
1043             self, rd0, "2001:10:1::1", 64,
1044             VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1045         s63 = VppGbpSubnet(
1046             self, rd0, "2001:10:2::1", 64,
1047             VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
1048         s41.add_vpp_config()
1049         s42.add_vpp_config()
1050         s43.add_vpp_config()
1051         s61.add_vpp_config()
1052         s62.add_vpp_config()
1053         s63.add_vpp_config()
1054
1055         self.send_and_expect_bridged(eps[0].itf,
1056                                      pkt_intra_epg_220_ip4 * NUM_PKTS,
1057                                      eps[0].epg.uplink)
1058         self.send_and_expect_bridged(eps[0].itf,
1059                                      pkt_inter_epg_222_ip4 * NUM_PKTS,
1060                                      eps[0].epg.uplink)
1061         self.send_and_expect_bridged6(eps[0].itf,
1062                                       pkt_inter_epg_222_ip6 * NUM_PKTS,
1063                                       eps[0].epg.uplink)
1064
1065         self.logger.info(self.vapi.cli("sh ip fib 11.0.0.2"))
1066         self.logger.info(self.vapi.cli("sh gbp endpoint-group"))
1067         self.logger.info(self.vapi.cli("sh gbp endpoint"))
1068         self.logger.info(self.vapi.cli("sh gbp recirc"))
1069         self.logger.info(self.vapi.cli("sh int"))
1070         self.logger.info(self.vapi.cli("sh int addr"))
1071         self.logger.info(self.vapi.cli("sh int feat loop6"))
1072         self.logger.info(self.vapi.cli("sh vlib graph ip4-gbp-src-classify"))
1073         self.logger.info(self.vapi.cli("sh int feat loop3"))
1074         self.logger.info(self.vapi.cli("sh int feat pg0"))
1075
1076         #
1077         # Packet destined to unknown unicast is sent on the epg uplink ...
1078         #
1079         pkt_intra_epg_220_to_uplink = (Ether(src=self.pg0.remote_mac,
1080                                              dst="00:00:00:33:44:55") /
1081                                        IP(src=eps[0].ip4.address,
1082                                           dst="10.0.0.99") /
1083                                        UDP(sport=1234, dport=1234) /
1084                                        Raw('\xa5' * 100))
1085
1086         self.send_and_expect_bridged(eps[0].itf,
1087                                      pkt_intra_epg_220_to_uplink * NUM_PKTS,
1088                                      eps[0].epg.uplink)
1089         # ... and nowhere else
1090         self.pg1.get_capture(0, timeout=0.1)
1091         self.pg1.assert_nothing_captured(remark="Flood onto other VMS")
1092
1093         pkt_intra_epg_221_to_uplink = (Ether(src=self.pg2.remote_mac,
1094                                              dst="00:00:00:33:44:66") /
1095                                        IP(src=eps[0].ip4.address,
1096                                           dst="10.0.0.99") /
1097                                        UDP(sport=1234, dport=1234) /
1098                                        Raw('\xa5' * 100))
1099
1100         self.send_and_expect_bridged(eps[2].itf,
1101                                      pkt_intra_epg_221_to_uplink * NUM_PKTS,
1102                                      eps[2].epg.uplink)
1103
1104         #
1105         # Packets from the uplink are forwarded in the absence of a contract
1106         #
1107         pkt_intra_epg_220_from_uplink = (Ether(src="00:00:00:33:44:55",
1108                                                dst=self.pg0.remote_mac) /
1109                                          IP(src=eps[0].ip4.address,
1110                                             dst="10.0.0.99") /
1111                                          UDP(sport=1234, dport=1234) /
1112                                          Raw('\xa5' * 100))
1113
1114         self.send_and_expect_bridged(self.pg4,
1115                                      pkt_intra_epg_220_from_uplink * NUM_PKTS,
1116                                      self.pg0)
1117
1118         #
1119         # in the absence of policy, endpoints in the same EPG
1120         # can communicate
1121         #
1122         pkt_intra_epg = (Ether(src=self.pg0.remote_mac,
1123                                dst=self.pg1.remote_mac) /
1124                          IP(src=eps[0].ip4.address,
1125                             dst=eps[1].ip4.address) /
1126                          UDP(sport=1234, dport=1234) /
1127                          Raw('\xa5' * 100))
1128
1129         self.send_and_expect_bridged(self.pg0,
1130                                      pkt_intra_epg * NUM_PKTS,
1131                                      self.pg1)
1132
1133         #
1134         # in the absence of policy, endpoints in the different EPG
1135         # cannot communicate
1136         #
1137         pkt_inter_epg_220_to_221 = (Ether(src=self.pg0.remote_mac,
1138                                           dst=self.pg2.remote_mac) /
1139                                     IP(src=eps[0].ip4.address,
1140                                        dst=eps[2].ip4.address) /
1141                                     UDP(sport=1234, dport=1234) /
1142                                     Raw('\xa5' * 100))
1143         pkt_inter_epg_221_to_220 = (Ether(src=self.pg2.remote_mac,
1144                                           dst=self.pg0.remote_mac) /
1145                                     IP(src=eps[2].ip4.address,
1146                                        dst=eps[0].ip4.address) /
1147                                     UDP(sport=1234, dport=1234) /
1148                                     Raw('\xa5' * 100))
1149         pkt_inter_epg_220_to_222 = (Ether(src=self.pg0.remote_mac,
1150                                           dst=str(self.router_mac)) /
1151                                     IP(src=eps[0].ip4.address,
1152                                        dst=eps[3].ip4.address) /
1153                                     UDP(sport=1234, dport=1234) /
1154                                     Raw('\xa5' * 100))
1155
1156         self.send_and_assert_no_replies(eps[0].itf,
1157                                         pkt_inter_epg_220_to_221 * NUM_PKTS)
1158         self.send_and_assert_no_replies(eps[0].itf,
1159                                         pkt_inter_epg_220_to_222 * NUM_PKTS)
1160
1161         #
1162         # A uni-directional contract from EPG 220 -> 221
1163         #
1164         acl = VppGbpAcl(self)
1165         rule = acl.create_rule(permit_deny=1, proto=17)
1166         rule2 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
1167         acl_index = acl.add_vpp_config([rule, rule2])
1168         c1 = VppGbpContract(
1169             self, epgs[0].sclass, epgs[1].sclass, acl_index,
1170             [VppGbpContractRule(
1171                 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1172                 []),
1173                 VppGbpContractRule(
1174                     VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1175                     [])],
1176             [ETH_P_IP, ETH_P_IPV6])
1177         c1.add_vpp_config()
1178
1179         self.send_and_expect_bridged(eps[0].itf,
1180                                      pkt_inter_epg_220_to_221 * NUM_PKTS,
1181                                      eps[2].itf)
1182         self.send_and_assert_no_replies(eps[0].itf,
1183                                         pkt_inter_epg_220_to_222 * NUM_PKTS)
1184
1185         #
1186         # contract for the return direction
1187         #
1188         c2 = VppGbpContract(
1189             self, epgs[1].sclass, epgs[0].sclass, acl_index,
1190             [VppGbpContractRule(
1191                 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1192                 []),
1193                 VppGbpContractRule(
1194                     VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1195                     [])],
1196             [ETH_P_IP, ETH_P_IPV6])
1197         c2.add_vpp_config()
1198
1199         self.send_and_expect_bridged(eps[0].itf,
1200                                      pkt_inter_epg_220_to_221 * NUM_PKTS,
1201                                      eps[2].itf)
1202         self.send_and_expect_bridged(eps[2].itf,
1203                                      pkt_inter_epg_221_to_220 * NUM_PKTS,
1204                                      eps[0].itf)
1205
1206         ds = c2.get_drop_stats()
1207         self.assertEqual(ds['packets'], 0)
1208         ps = c2.get_permit_stats()
1209         self.assertEqual(ps['packets'], NUM_PKTS)
1210
1211         #
1212         # the contract does not allow non-IP
1213         #
1214         pkt_non_ip_inter_epg_220_to_221 = (Ether(src=self.pg0.remote_mac,
1215                                                  dst=self.pg2.remote_mac) /
1216                                            ARP())
1217         self.send_and_assert_no_replies(eps[0].itf,
1218                                         pkt_non_ip_inter_epg_220_to_221 * 17)
1219
1220         #
1221         # check that inter group is still disabled for the groups
1222         # not in the contract.
1223         #
1224         self.send_and_assert_no_replies(eps[0].itf,
1225                                         pkt_inter_epg_220_to_222 * NUM_PKTS)
1226
1227         #
1228         # A uni-directional contract from EPG 220 -> 222 'L3 routed'
1229         #
1230         c3 = VppGbpContract(
1231             self, epgs[0].sclass, epgs[2].sclass, acl_index,
1232             [VppGbpContractRule(
1233                 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1234                 []),
1235                 VppGbpContractRule(
1236                     VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1237                     [])],
1238             [ETH_P_IP, ETH_P_IPV6])
1239         c3.add_vpp_config()
1240
1241         self.logger.info(self.vapi.cli("sh gbp contract"))
1242
1243         self.send_and_expect_routed(eps[0].itf,
1244                                     pkt_inter_epg_220_to_222 * NUM_PKTS,
1245                                     eps[3].itf,
1246                                     str(self.router_mac))
1247
1248         #
1249         # remove both contracts, traffic stops in both directions
1250         #
1251         c2.remove_vpp_config()
1252         c1.remove_vpp_config()
1253         c3.remove_vpp_config()
1254         acl.remove_vpp_config()
1255
1256         self.send_and_assert_no_replies(eps[2].itf,
1257                                         pkt_inter_epg_221_to_220 * NUM_PKTS)
1258         self.send_and_assert_no_replies(eps[0].itf,
1259                                         pkt_inter_epg_220_to_221 * NUM_PKTS)
1260         self.send_and_expect_bridged(eps[0].itf,
1261                                      pkt_intra_epg * NUM_PKTS,
1262                                      eps[1].itf)
1263
1264         #
1265         # EPs to the outside world
1266         #
1267
1268         # in the EP's RD an external subnet via the NAT EPG's recirc
1269         se1 = VppGbpSubnet(
1270             self, rd0, "0.0.0.0", 0,
1271             VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1272             sw_if_index=recirc_nat.recirc.sw_if_index,
1273             sclass=epg_nat.sclass)
1274         se2 = VppGbpSubnet(
1275             self, rd0, "11.0.0.0", 8,
1276             VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1277             sw_if_index=recirc_nat.recirc.sw_if_index,
1278             sclass=epg_nat.sclass)
1279         se16 = VppGbpSubnet(
1280             self, rd0, "::", 0,
1281             VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1282             sw_if_index=recirc_nat.recirc.sw_if_index,
1283             sclass=epg_nat.sclass)
1284         # in the NAT RD an external subnet via the NAT EPG's uplink
1285         se3 = VppGbpSubnet(
1286             self, rd20, "0.0.0.0", 0,
1287             VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1288             sw_if_index=epg_nat.uplink.sw_if_index,
1289             sclass=epg_nat.sclass)
1290         se36 = VppGbpSubnet(
1291             self, rd20, "::", 0,
1292             VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1293             sw_if_index=epg_nat.uplink.sw_if_index,
1294             sclass=epg_nat.sclass)
1295         se4 = VppGbpSubnet(
1296             self, rd20, "11.0.0.0", 8,
1297             VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
1298             sw_if_index=epg_nat.uplink.sw_if_index,
1299             sclass=epg_nat.sclass)
1300         se1.add_vpp_config()
1301         se2.add_vpp_config()
1302         se16.add_vpp_config()
1303         se3.add_vpp_config()
1304         se36.add_vpp_config()
1305         se4.add_vpp_config()
1306
1307         self.logger.info(self.vapi.cli("sh ip fib 0.0.0.0/0"))
1308         self.logger.info(self.vapi.cli("sh ip fib 11.0.0.1"))
1309         self.logger.info(self.vapi.cli("sh ip6 fib ::/0"))
1310         self.logger.info(self.vapi.cli("sh ip6 fib %s" %
1311                                        eps[0].fip6))
1312
1313         #
1314         # From an EP to an outside address: IN2OUT
1315         #
1316         pkt_inter_epg_220_to_global = (Ether(src=self.pg0.remote_mac,
1317                                              dst=str(self.router_mac)) /
1318                                        IP(src=eps[0].ip4.address,
1319                                           dst="1.1.1.1") /
1320                                        UDP(sport=1234, dport=1234) /
1321                                        Raw('\xa5' * 100))
1322
1323         # no policy yet
1324         self.send_and_assert_no_replies(eps[0].itf,
1325                                         pkt_inter_epg_220_to_global * NUM_PKTS)
1326
1327         acl2 = VppGbpAcl(self)
1328         rule = acl2.create_rule(permit_deny=1, proto=17, sport_from=1234,
1329                                 sport_to=1234, dport_from=1234, dport_to=1234)
1330         rule2 = acl2.create_rule(is_ipv6=1, permit_deny=1, proto=17,
1331                                  sport_from=1234, sport_to=1234,
1332                                  dport_from=1234, dport_to=1234)
1333
1334         acl_index2 = acl2.add_vpp_config([rule, rule2])
1335         c4 = VppGbpContract(
1336             self, epgs[0].sclass, epgs[3].sclass, acl_index2,
1337             [VppGbpContractRule(
1338                 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1339                 []),
1340                 VppGbpContractRule(
1341                     VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1342                     [])],
1343             [ETH_P_IP, ETH_P_IPV6])
1344         c4.add_vpp_config()
1345
1346         self.send_and_expect_natted(eps[0].itf,
1347                                     pkt_inter_epg_220_to_global * NUM_PKTS,
1348                                     self.pg7,
1349                                     eps[0].fip4.address)
1350
1351         pkt_inter_epg_220_to_global = (Ether(src=self.pg0.remote_mac,
1352                                              dst=str(self.router_mac)) /
1353                                        IPv6(src=eps[0].ip6.address,
1354                                             dst="6001::1") /
1355                                        UDP(sport=1234, dport=1234) /
1356                                        Raw('\xa5' * 100))
1357
1358         self.send_and_expect_natted6(self.pg0,
1359                                      pkt_inter_epg_220_to_global * NUM_PKTS,
1360                                      self.pg7,
1361                                      eps[0].fip6.address)
1362
1363         #
1364         # From a global address to an EP: OUT2IN
1365         #
1366         pkt_inter_epg_220_from_global = (Ether(src=str(self.router_mac),
1367                                                dst=self.pg0.remote_mac) /
1368                                          IP(dst=eps[0].fip4.address,
1369                                             src="1.1.1.1") /
1370                                          UDP(sport=1234, dport=1234) /
1371                                          Raw('\xa5' * 100))
1372
1373         self.send_and_assert_no_replies(
1374             self.pg7, pkt_inter_epg_220_from_global * NUM_PKTS)
1375
1376         c5 = VppGbpContract(
1377             self, epgs[3].sclass, epgs[0].sclass, acl_index2,
1378             [VppGbpContractRule(
1379                 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1380                 []),
1381                 VppGbpContractRule(
1382                     VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1383                     [])],
1384             [ETH_P_IP, ETH_P_IPV6])
1385         c5.add_vpp_config()
1386
1387         self.send_and_expect_unnatted(self.pg7,
1388                                       pkt_inter_epg_220_from_global * NUM_PKTS,
1389                                       eps[0].itf,
1390                                       eps[0].ip4.address)
1391
1392         pkt_inter_epg_220_from_global = (Ether(src=str(self.router_mac),
1393                                                dst=self.pg0.remote_mac) /
1394                                          IPv6(dst=eps[0].fip6.address,
1395                                               src="6001::1") /
1396                                          UDP(sport=1234, dport=1234) /
1397                                          Raw('\xa5' * 100))
1398
1399         self.send_and_expect_unnatted6(
1400             self.pg7,
1401             pkt_inter_epg_220_from_global * NUM_PKTS,
1402             eps[0].itf,
1403             eps[0].ip6.address)
1404
1405         #
1406         # From a local VM to another local VM using resp. public addresses:
1407         #  IN2OUT2IN
1408         #
1409         pkt_intra_epg_220_global = (Ether(src=self.pg0.remote_mac,
1410                                           dst=str(self.router_mac)) /
1411                                     IP(src=eps[0].ip4.address,
1412                                        dst=eps[1].fip4.address) /
1413                                     UDP(sport=1234, dport=1234) /
1414                                     Raw('\xa5' * 100))
1415
1416         self.send_and_expect_double_natted(eps[0].itf,
1417                                            pkt_intra_epg_220_global * NUM_PKTS,
1418                                            eps[1].itf,
1419                                            eps[0].fip4.address,
1420                                            eps[1].ip4.address)
1421
1422         pkt_intra_epg_220_global = (Ether(src=self.pg0.remote_mac,
1423                                           dst=str(self.router_mac)) /
1424                                     IPv6(src=eps[0].ip6.address,
1425                                          dst=eps[1].fip6.address) /
1426                                     UDP(sport=1234, dport=1234) /
1427                                     Raw('\xa5' * 100))
1428
1429         self.send_and_expect_double_natted6(
1430             eps[0].itf,
1431             pkt_intra_epg_220_global * NUM_PKTS,
1432             eps[1].itf,
1433             eps[0].fip6.address,
1434             eps[1].ip6.address)
1435
1436         #
1437         # cleanup
1438         #
1439         for ep in eps:
1440             # del static mappings for each EP from the 10/8 to 11/8 network
1441             flags = self.config_flags.NAT_IS_ADDR_ONLY
1442             self.vapi.nat44_add_del_static_mapping(
1443                 is_add=0,
1444                 local_ip_address=ep.ip4.bytes,
1445                 external_ip_address=ep.fip4.bytes,
1446                 external_sw_if_index=0xFFFFFFFF,
1447                 vrf_id=0,
1448                 flags=flags)
1449             self.vapi.nat66_add_del_static_mapping(
1450                 local_ip_address=ep.ip6.bytes,
1451                 external_ip_address=ep.fip6.bytes,
1452                 vrf_id=0, is_add=0)
1453
1454         for epg in epgs:
1455             # IP config on the BVI interfaces
1456             if epg != epgs[0] and epg != epgs[3]:
1457                 flags = self.config_flags.NAT_IS_INSIDE
1458                 self.vapi.nat44_interface_add_del_feature(
1459                     sw_if_index=epg.bvi.sw_if_index,
1460                     flags=flags,
1461                     is_add=0)
1462                 self.vapi.nat66_add_del_interface(
1463                     is_add=0, flags=flags,
1464                     sw_if_index=epg.bvi.sw_if_index)
1465
1466         for recirc in recircs:
1467             self.vapi.nat44_interface_add_del_feature(
1468                 sw_if_index=recirc.recirc.sw_if_index,
1469                 is_add=0)
1470             self.vapi.nat66_add_del_interface(
1471                 is_add=0,
1472                 sw_if_index=recirc.recirc.sw_if_index)
1473
1474     def wait_for_ep_timeout(self, sw_if_index=None, ip=None, mac=None,
1475                             n_tries=100, s_time=1):
1476         while (n_tries):
1477             if not find_gbp_endpoint(self, sw_if_index, ip, mac):
1478                 return True
1479             n_tries = n_tries - 1
1480             self.sleep(s_time)
1481         self.assertFalse(find_gbp_endpoint(self, sw_if_index, ip, mac))
1482         return False
1483
1484     def test_gbp_learn_l2(self):
1485         """ GBP L2 Endpoint Learning """
1486
1487         self.vapi.cli("clear errors")
1488
1489         ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
1490         learnt = [{'mac': '00:00:11:11:11:01',
1491                    'ip': '10.0.0.1',
1492                    'ip6': '2001:10::2'},
1493                   {'mac': '00:00:11:11:11:02',
1494                    'ip': '10.0.0.2',
1495                    'ip6': '2001:10::3'}]
1496
1497         #
1498         # IP tables
1499         #
1500         gt4 = VppIpTable(self, 1)
1501         gt4.add_vpp_config()
1502         gt6 = VppIpTable(self, 1, is_ip6=True)
1503         gt6.add_vpp_config()
1504
1505         rd1 = VppGbpRouteDomain(self, 1, gt4, gt6)
1506         rd1.add_vpp_config()
1507
1508         #
1509         # Pg2 hosts the vxlan tunnel, hosts on pg2 to act as TEPs
1510         # Pg3 hosts the IP4 UU-flood VXLAN tunnel
1511         # Pg4 hosts the IP6 UU-flood VXLAN tunnel
1512         #
1513         self.pg2.config_ip4()
1514         self.pg2.resolve_arp()
1515         self.pg2.generate_remote_hosts(4)
1516         self.pg2.configure_ipv4_neighbors()
1517         self.pg3.config_ip4()
1518         self.pg3.resolve_arp()
1519         self.pg4.config_ip4()
1520         self.pg4.resolve_arp()
1521
1522         #
1523         # Add a mcast destination VXLAN-GBP tunnel for B&M traffic
1524         #
1525         tun_bm = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
1526                                    "239.1.1.1", 88,
1527                                    mcast_itf=self.pg4)
1528         tun_bm.add_vpp_config()
1529
1530         #
1531         # a GBP bridge domain with a BVI and a UU-flood interface
1532         #
1533         bd1 = VppBridgeDomain(self, 1)
1534         bd1.add_vpp_config()
1535         gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0, self.pg3, tun_bm)
1536         gbd1.add_vpp_config()
1537
1538         self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1539         self.logger.info(self.vapi.cli("sh gbp bridge"))
1540
1541         # ... and has a /32 applied
1542         ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
1543         ip_addr.add_vpp_config()
1544
1545         #
1546         # The Endpoint-group in which we are learning endpoints
1547         #
1548         epg_220 = VppGbpEndpointGroup(self, 220, 112, rd1, gbd1,
1549                                       None, self.loop0,
1550                                       "10.0.0.128",
1551                                       "2001:10::128",
1552                                       VppGbpEndpointRetention(2))
1553         epg_220.add_vpp_config()
1554         epg_330 = VppGbpEndpointGroup(self, 330, 113, rd1, gbd1,
1555                                       None, self.loop1,
1556                                       "10.0.1.128",
1557                                       "2001:11::128",
1558                                       VppGbpEndpointRetention(2))
1559         epg_330.add_vpp_config()
1560
1561         #
1562         # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
1563         # learning enabled
1564         #
1565         vx_tun_l2_1 = VppGbpVxlanTunnel(
1566             self, 99, bd1.bd_id,
1567             VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L2,
1568             self.pg2.local_ip4)
1569         vx_tun_l2_1.add_vpp_config()
1570
1571         #
1572         # A static endpoint that the learnt endpoints are trying to
1573         # talk to
1574         #
1575         ep = VppGbpEndpoint(self, self.pg0,
1576                             epg_220, None,
1577                             "10.0.0.127", "11.0.0.127",
1578                             "2001:10::1", "3001::1")
1579         ep.add_vpp_config()
1580
1581         self.assertTrue(find_route(self, ep.ip4.address, 32, table_id=1))
1582
1583         # a packet with an sclass from an unknown EPG
1584         p = (Ether(src=self.pg2.remote_mac,
1585                    dst=self.pg2.local_mac) /
1586              IP(src=self.pg2.remote_hosts[0].ip4,
1587                 dst=self.pg2.local_ip4) /
1588              UDP(sport=1234, dport=48879) /
1589              VXLAN(vni=99, gpid=88, flags=0x88) /
1590              Ether(src=learnt[0]["mac"], dst=ep.mac) /
1591              IP(src=learnt[0]["ip"], dst=ep.ip4.address) /
1592              UDP(sport=1234, dport=1234) /
1593              Raw('\xa5' * 100))
1594
1595         self.send_and_assert_no_replies(self.pg2, p)
1596
1597         self.logger.info(self.vapi.cli("sh error"))
1598         # self.assert_packet_counter_equal(
1599         #    '/err/gbp-policy-port/drop-no-contract', 1)
1600
1601         #
1602         # we should not have learnt a new tunnel endpoint, since
1603         # the EPG was not learnt.
1604         #
1605         self.assertEqual(INDEX_INVALID,
1606                          find_vxlan_gbp_tunnel(self,
1607                                                self.pg2.local_ip4,
1608                                                self.pg2.remote_hosts[0].ip4,
1609                                                99))
1610
1611         # epg is not learnt, because the EPG is unknown
1612         self.assertEqual(len(self.vapi.gbp_endpoint_dump()), 1)
1613
1614         #
1615         # Learn new EPs from IP packets
1616         #
1617         for ii, l in enumerate(learnt):
1618             # a packet with an sclass from a known EPG
1619             # arriving on an unknown TEP
1620             p = (Ether(src=self.pg2.remote_mac,
1621                        dst=self.pg2.local_mac) /
1622                  IP(src=self.pg2.remote_hosts[1].ip4,
1623                     dst=self.pg2.local_ip4) /
1624                  UDP(sport=1234, dport=48879) /
1625                  VXLAN(vni=99, gpid=112, flags=0x88) /
1626                  Ether(src=l['mac'], dst=ep.mac) /
1627                  IP(src=l['ip'], dst=ep.ip4.address) /
1628                  UDP(sport=1234, dport=1234) /
1629                  Raw('\xa5' * 100))
1630
1631             rx = self.send_and_expect(self.pg2, [p], self.pg0)
1632
1633             # the new TEP
1634             tep1_sw_if_index = find_vxlan_gbp_tunnel(
1635                 self,
1636                 self.pg2.local_ip4,
1637                 self.pg2.remote_hosts[1].ip4,
1638                 99)
1639             self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
1640
1641             #
1642             # the EP is learnt via the learnt TEP
1643             # both from its MAC and its IP
1644             #
1645             self.assertTrue(find_gbp_endpoint(self,
1646                                               vx_tun_l2_1.sw_if_index,
1647                                               mac=l['mac']))
1648             self.assertTrue(find_gbp_endpoint(self,
1649                                               vx_tun_l2_1.sw_if_index,
1650                                               ip=l['ip']))
1651
1652         # self.assert_packet_counter_equal(
1653         #    '/err/gbp-policy-port/allow-intra-sclass', 2)
1654
1655         self.logger.info(self.vapi.cli("show gbp endpoint"))
1656         self.logger.info(self.vapi.cli("show gbp vxlan"))
1657         self.logger.info(self.vapi.cli("show ip mfib"))
1658
1659         #
1660         # If we sleep for the threshold time, the learnt endpoints should
1661         # age out
1662         #
1663         for l in learnt:
1664             self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1665                                      mac=l['mac'])
1666
1667         #
1668         # Learn new EPs from GARP packets received on the BD's mcast tunnel
1669         #
1670         for ii, l in enumerate(learnt):
1671             # a packet with an sclass from a known EPG
1672             # arriving on an unknown TEP
1673             p = (Ether(src=self.pg2.remote_mac,
1674                        dst=self.pg2.local_mac) /
1675                  IP(src=self.pg2.remote_hosts[1].ip4,
1676                     dst="239.1.1.1") /
1677                  UDP(sport=1234, dport=48879) /
1678                  VXLAN(vni=88, gpid=112, flags=0x88) /
1679                  Ether(src=l['mac'], dst="ff:ff:ff:ff:ff:ff") /
1680                  ARP(op="who-has",
1681                      psrc=l['ip'], pdst=l['ip'],
1682                      hwsrc=l['mac'], hwdst="ff:ff:ff:ff:ff:ff"))
1683
1684             rx = self.send_and_expect(self.pg4, [p], self.pg0)
1685
1686             # the new TEP
1687             tep1_sw_if_index = find_vxlan_gbp_tunnel(
1688                 self,
1689                 self.pg2.local_ip4,
1690                 self.pg2.remote_hosts[1].ip4,
1691                 99)
1692             self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
1693
1694             #
1695             # the EP is learnt via the learnt TEP
1696             # both from its MAC and its IP
1697             #
1698             self.assertTrue(find_gbp_endpoint(self,
1699                                               vx_tun_l2_1.sw_if_index,
1700                                               mac=l['mac']))
1701             self.assertTrue(find_gbp_endpoint(self,
1702                                               vx_tun_l2_1.sw_if_index,
1703                                               ip=l['ip']))
1704
1705         #
1706         # wait for the learnt endpoints to age out
1707         #
1708         for l in learnt:
1709             self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1710                                      mac=l['mac'])
1711
1712         #
1713         # Learn new EPs from L2 packets
1714         #
1715         for ii, l in enumerate(learnt):
1716             # a packet with an sclass from a known EPG
1717             # arriving on an unknown TEP
1718             p = (Ether(src=self.pg2.remote_mac,
1719                        dst=self.pg2.local_mac) /
1720                  IP(src=self.pg2.remote_hosts[1].ip4,
1721                     dst=self.pg2.local_ip4) /
1722                  UDP(sport=1234, dport=48879) /
1723                  VXLAN(vni=99, gpid=112, flags=0x88) /
1724                  Ether(src=l['mac'], dst=ep.mac) /
1725                  Raw('\xa5' * 100))
1726
1727             rx = self.send_and_expect(self.pg2, [p], self.pg0)
1728
1729             # the new TEP
1730             tep1_sw_if_index = find_vxlan_gbp_tunnel(
1731                 self,
1732                 self.pg2.local_ip4,
1733                 self.pg2.remote_hosts[1].ip4,
1734                 99)
1735             self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
1736
1737             #
1738             # the EP is learnt via the learnt TEP
1739             # both from its MAC and its IP
1740             #
1741             self.assertTrue(find_gbp_endpoint(self,
1742                                               vx_tun_l2_1.sw_if_index,
1743                                               mac=l['mac']))
1744
1745         self.logger.info(self.vapi.cli("show gbp endpoint"))
1746         self.logger.info(self.vapi.cli("show gbp vxlan"))
1747         self.logger.info(self.vapi.cli("show vxlan-gbp tunnel"))
1748
1749         #
1750         # wait for the learnt endpoints to age out
1751         #
1752         for l in learnt:
1753             self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1754                                      mac=l['mac'])
1755
1756         #
1757         # repeat. the do not learn bit is set so the EPs are not learnt
1758         #
1759         for l in learnt:
1760             # a packet with an sclass from a known EPG
1761             p = (Ether(src=self.pg2.remote_mac,
1762                        dst=self.pg2.local_mac) /
1763                  IP(src=self.pg2.remote_hosts[1].ip4,
1764                     dst=self.pg2.local_ip4) /
1765                  UDP(sport=1234, dport=48879) /
1766                  VXLAN(vni=99, gpid=112, flags=0x88, gpflags="D") /
1767                  Ether(src=l['mac'], dst=ep.mac) /
1768                  IP(src=l['ip'], dst=ep.ip4.address) /
1769                  UDP(sport=1234, dport=1234) /
1770                  Raw('\xa5' * 100))
1771
1772             rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
1773
1774         for l in learnt:
1775             self.assertFalse(find_gbp_endpoint(self,
1776                                                vx_tun_l2_1.sw_if_index,
1777                                                mac=l['mac']))
1778
1779         #
1780         # repeat
1781         #
1782         for l in learnt:
1783             # a packet with an sclass from a known EPG
1784             p = (Ether(src=self.pg2.remote_mac,
1785                        dst=self.pg2.local_mac) /
1786                  IP(src=self.pg2.remote_hosts[1].ip4,
1787                     dst=self.pg2.local_ip4) /
1788                  UDP(sport=1234, dport=48879) /
1789                  VXLAN(vni=99, gpid=112, flags=0x88) /
1790                  Ether(src=l['mac'], dst=ep.mac) /
1791                  IP(src=l['ip'], dst=ep.ip4.address) /
1792                  UDP(sport=1234, dport=1234) /
1793                  Raw('\xa5' * 100))
1794
1795             rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
1796
1797             self.assertTrue(find_gbp_endpoint(self,
1798                                               vx_tun_l2_1.sw_if_index,
1799                                               mac=l['mac']))
1800
1801         #
1802         # Static EP replies to dynamics
1803         #
1804         self.logger.info(self.vapi.cli("sh l2fib bd_id 1"))
1805         for l in learnt:
1806             p = (Ether(src=ep.mac, dst=l['mac']) /
1807                  IP(dst=l['ip'], src=ep.ip4.address) /
1808                  UDP(sport=1234, dport=1234) /
1809                  Raw('\xa5' * 100))
1810
1811             rxs = self.send_and_expect(self.pg0, p * 17, self.pg2)
1812
1813             for rx in rxs:
1814                 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
1815                 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
1816                 self.assertEqual(rx[UDP].dport, 48879)
1817                 # the UDP source port is a random value for hashing
1818                 self.assertEqual(rx[VXLAN].gpid, 112)
1819                 self.assertEqual(rx[VXLAN].vni, 99)
1820                 self.assertTrue(rx[VXLAN].flags.G)
1821                 self.assertTrue(rx[VXLAN].flags.Instance)
1822                 self.assertTrue(rx[VXLAN].gpflags.A)
1823                 self.assertFalse(rx[VXLAN].gpflags.D)
1824
1825         for l in learnt:
1826             self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1827                                      mac=l['mac'])
1828
1829         #
1830         # repeat in the other EPG
1831         # there's no contract between 220 and 330, but the A-bit is set
1832         # so the packet is cleared for delivery
1833         #
1834         for l in learnt:
1835             # a packet with an sclass from a known EPG
1836             p = (Ether(src=self.pg2.remote_mac,
1837                        dst=self.pg2.local_mac) /
1838                  IP(src=self.pg2.remote_hosts[1].ip4,
1839                     dst=self.pg2.local_ip4) /
1840                  UDP(sport=1234, dport=48879) /
1841                  VXLAN(vni=99, gpid=113, flags=0x88, gpflags='A') /
1842                  Ether(src=l['mac'], dst=ep.mac) /
1843                  IP(src=l['ip'], dst=ep.ip4.address) /
1844                  UDP(sport=1234, dport=1234) /
1845                  Raw('\xa5' * 100))
1846
1847             rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
1848
1849             self.assertTrue(find_gbp_endpoint(self,
1850                                               vx_tun_l2_1.sw_if_index,
1851                                               mac=l['mac']))
1852
1853         #
1854         # static EP cannot reach the learnt EPs since there is no contract
1855         # only test 1 EP as the others could timeout
1856         #
1857         p = (Ether(src=ep.mac, dst=l['mac']) /
1858              IP(dst=learnt[0]['ip'], src=ep.ip4.address) /
1859              UDP(sport=1234, dport=1234) /
1860              Raw('\xa5' * 100))
1861
1862         self.send_and_assert_no_replies(self.pg0, [p])
1863
1864         #
1865         # refresh the entries after the check for no replies above
1866         #
1867         for l in learnt:
1868             # a packet with an sclass from a known EPG
1869             p = (Ether(src=self.pg2.remote_mac,
1870                        dst=self.pg2.local_mac) /
1871                  IP(src=self.pg2.remote_hosts[1].ip4,
1872                     dst=self.pg2.local_ip4) /
1873                  UDP(sport=1234, dport=48879) /
1874                  VXLAN(vni=99, gpid=113, flags=0x88, gpflags='A') /
1875                  Ether(src=l['mac'], dst=ep.mac) /
1876                  IP(src=l['ip'], dst=ep.ip4.address) /
1877                  UDP(sport=1234, dport=1234) /
1878                  Raw('\xa5' * 100))
1879
1880             rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
1881
1882             self.assertTrue(find_gbp_endpoint(self,
1883                                               vx_tun_l2_1.sw_if_index,
1884                                               mac=l['mac']))
1885
1886         #
1887         # Add the contract so they can talk
1888         #
1889         acl = VppGbpAcl(self)
1890         rule = acl.create_rule(permit_deny=1, proto=17)
1891         rule2 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
1892         acl_index = acl.add_vpp_config([rule, rule2])
1893         c1 = VppGbpContract(
1894             self, epg_220.sclass, epg_330.sclass, acl_index,
1895             [VppGbpContractRule(
1896                 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1897                 []),
1898                 VppGbpContractRule(
1899                     VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
1900                     [])],
1901             [ETH_P_IP, ETH_P_IPV6])
1902         c1.add_vpp_config()
1903
1904         for l in learnt:
1905             p = (Ether(src=ep.mac, dst=l['mac']) /
1906                  IP(dst=l['ip'], src=ep.ip4.address) /
1907                  UDP(sport=1234, dport=1234) /
1908                  Raw('\xa5' * 100))
1909
1910             self.send_and_expect(self.pg0, [p], self.pg2)
1911
1912         #
1913         # send UU packets from the local EP
1914         #
1915         self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1916         self.logger.info(self.vapi.cli("sh gbp bridge"))
1917         p_uu = (Ether(src=ep.mac, dst="00:11:11:11:11:11") /
1918                 IP(dst="10.0.0.133", src=ep.ip4.address) /
1919                 UDP(sport=1234, dport=1234) /
1920                 Raw('\xa5' * 100))
1921         rxs = self.send_and_expect(ep.itf, [p_uu], gbd1.uu_fwd)
1922
1923         self.logger.info(self.vapi.cli("sh bridge 1 detail"))
1924
1925         p_bm = (Ether(src=ep.mac, dst="ff:ff:ff:ff:ff:ff") /
1926                 IP(dst="10.0.0.133", src=ep.ip4.address) /
1927                 UDP(sport=1234, dport=1234) /
1928                 Raw('\xa5' * 100))
1929         rxs = self.send_and_expect_only(ep.itf, [p_bm], tun_bm.mcast_itf)
1930
1931         for rx in rxs:
1932             self.assertEqual(rx[IP].src, self.pg4.local_ip4)
1933             self.assertEqual(rx[IP].dst, "239.1.1.1")
1934             self.assertEqual(rx[UDP].dport, 48879)
1935             # the UDP source port is a random value for hashing
1936             self.assertEqual(rx[VXLAN].gpid, 112)
1937             self.assertEqual(rx[VXLAN].vni, 88)
1938             self.assertTrue(rx[VXLAN].flags.G)
1939             self.assertTrue(rx[VXLAN].flags.Instance)
1940             self.assertFalse(rx[VXLAN].gpflags.A)
1941             self.assertFalse(rx[VXLAN].gpflags.D)
1942
1943         #
1944         # Check v6 Endpoints
1945         #
1946         for l in learnt:
1947             # a packet with an sclass from a known EPG
1948             p = (Ether(src=self.pg2.remote_mac,
1949                        dst=self.pg2.local_mac) /
1950                  IP(src=self.pg2.remote_hosts[1].ip4,
1951                     dst=self.pg2.local_ip4) /
1952                  UDP(sport=1234, dport=48879) /
1953                  VXLAN(vni=99, gpid=113, flags=0x88, gpflags='A') /
1954                  Ether(src=l['mac'], dst=ep.mac) /
1955                  IPv6(src=l['ip6'], dst=ep.ip6.address) /
1956                  UDP(sport=1234, dport=1234) /
1957                  Raw('\xa5' * 100))
1958
1959             rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
1960
1961             self.assertTrue(find_gbp_endpoint(self,
1962                                               vx_tun_l2_1.sw_if_index,
1963                                               mac=l['mac']))
1964
1965         #
1966         # L3 Endpoint Learning
1967         #  - configured on the bridge's BVI
1968         #
1969
1970         #
1971         # clean up
1972         #
1973         for l in learnt:
1974             self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
1975                                      mac=l['mac'])
1976         self.pg2.unconfig_ip4()
1977         self.pg3.unconfig_ip4()
1978         self.pg4.unconfig_ip4()
1979
1980         self.logger.info(self.vapi.cli("sh int"))
1981         self.logger.info(self.vapi.cli("sh gbp vxlan"))
1982
1983     def test_gbp_contract(self):
1984         """ GBP CONTRACTS """
1985
1986         #
1987         # Bridge Domains
1988         #
1989         bd1 = VppBridgeDomain(self, 1, arp_term=0)
1990         bd2 = VppBridgeDomain(self, 2, arp_term=0)
1991
1992         bd1.add_vpp_config()
1993         bd2.add_vpp_config()
1994
1995         gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0)
1996         gbd2 = VppGbpBridgeDomain(self, bd2, self.loop1)
1997
1998         gbd1.add_vpp_config()
1999         gbd2.add_vpp_config()
2000
2001         #
2002         # Route Domains
2003         #
2004         gt4 = VppIpTable(self, 0)
2005         gt4.add_vpp_config()
2006         gt6 = VppIpTable(self, 0, is_ip6=True)
2007         gt6.add_vpp_config()
2008
2009         rd0 = VppGbpRouteDomain(self, 0, gt4, gt6, None, None)
2010
2011         rd0.add_vpp_config()
2012
2013         #
2014         # 3 EPGs, 2 of which share a BD.
2015         #
2016         epgs = [VppGbpEndpointGroup(self, 220, 1220, rd0, gbd1,
2017                                     None, self.loop0,
2018                                     "10.0.0.128", "2001:10::128"),
2019                 VppGbpEndpointGroup(self, 221, 1221, rd0, gbd1,
2020                                     None, self.loop0,
2021                                     "10.0.1.128", "2001:10:1::128"),
2022                 VppGbpEndpointGroup(self, 222, 1222, rd0, gbd2,
2023                                     None, self.loop1,
2024                                     "10.0.2.128", "2001:10:2::128")]
2025         #
2026         # 4 end-points, 2 in the same subnet, 3 in the same BD
2027         #
2028         eps = [VppGbpEndpoint(self, self.pg0,
2029                               epgs[0], None,
2030                               "10.0.0.1", "11.0.0.1",
2031                               "2001:10::1", "3001::1"),
2032                VppGbpEndpoint(self, self.pg1,
2033                               epgs[0], None,
2034                               "10.0.0.2", "11.0.0.2",
2035                               "2001:10::2", "3001::2"),
2036                VppGbpEndpoint(self, self.pg2,
2037                               epgs[1], None,
2038                               "10.0.1.1", "11.0.0.3",
2039                               "2001:10:1::1", "3001::3"),
2040                VppGbpEndpoint(self, self.pg3,
2041                               epgs[2], None,
2042                               "10.0.2.1", "11.0.0.4",
2043                               "2001:10:2::1", "3001::4")]
2044
2045         #
2046         # Config related to each of the EPGs
2047         #
2048         for epg in epgs:
2049             # IP config on the BVI interfaces
2050             if epg != epgs[1]:
2051                 VppIpInterfaceBind(self, epg.bvi, epg.rd.t4).add_vpp_config()
2052                 VppIpInterfaceBind(self, epg.bvi, epg.rd.t6).add_vpp_config()
2053                 self.vapi.sw_interface_set_mac_address(
2054                     epg.bvi.sw_if_index,
2055                     self.router_mac.packed)
2056
2057             if_ip4 = VppIpInterfaceAddress(self, epg.bvi, epg.bvi_ip4, 32)
2058             if_ip6 = VppIpInterfaceAddress(self, epg.bvi, epg.bvi_ip6, 128)
2059             if_ip4.add_vpp_config()
2060             if_ip6.add_vpp_config()
2061
2062             # add the BD ARP termination entry for BVI IP
2063             epg.bd_arp_ip4 = VppBridgeDomainArpEntry(self, epg.bd.bd,
2064                                                      str(self.router_mac),
2065                                                      epg.bvi_ip4)
2066             epg.bd_arp_ip4.add_vpp_config()
2067
2068             # EPG in VPP
2069             epg.add_vpp_config()
2070
2071         #
2072         # config ep
2073         #
2074         for ep in eps:
2075             ep.add_vpp_config()
2076
2077         self.logger.info(self.vapi.cli("show gbp endpoint"))
2078         self.logger.info(self.vapi.cli("show interface"))
2079         self.logger.info(self.vapi.cli("show br"))
2080
2081         #
2082         # Intra epg allowed without contract
2083         #
2084         pkt_intra_epg_220_to_220 = (Ether(src=self.pg0.remote_mac,
2085                                           dst=self.pg1.remote_mac) /
2086                                     IP(src=eps[0].ip4.address,
2087                                        dst=eps[1].ip4.address) /
2088                                     UDP(sport=1234, dport=1234) /
2089                                     Raw('\xa5' * 100))
2090
2091         self.send_and_expect_bridged(self.pg0,
2092                                      pkt_intra_epg_220_to_220 * 65,
2093                                      self.pg1)
2094
2095         #
2096         # Inter epg denied without contract
2097         #
2098         pkt_inter_epg_220_to_221 = (Ether(src=self.pg0.remote_mac,
2099                                           dst=self.pg2.remote_mac) /
2100                                     IP(src=eps[0].ip4.address,
2101                                        dst=eps[2].ip4.address) /
2102                                     UDP(sport=1234, dport=1234) /
2103                                     Raw('\xa5' * 100))
2104
2105         self.send_and_assert_no_replies(self.pg0, pkt_inter_epg_220_to_221)
2106
2107         #
2108         # A uni-directional contract from EPG 220 -> 221
2109         #
2110         acl = VppGbpAcl(self)
2111         rule = acl.create_rule(permit_deny=1, proto=17)
2112         rule2 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
2113         acl_index = acl.add_vpp_config([rule, rule2])
2114         c1 = VppGbpContract(
2115             self, epgs[0].sclass, epgs[1].sclass, acl_index,
2116             [VppGbpContractRule(
2117                 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2118                 []),
2119              VppGbpContractRule(
2120                  VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2121                  [])],
2122             [ETH_P_IP, ETH_P_IPV6])
2123         c1.add_vpp_config()
2124
2125         self.send_and_expect_bridged(eps[0].itf,
2126                                      pkt_inter_epg_220_to_221 * 65,
2127                                      eps[2].itf)
2128
2129         pkt_inter_epg_220_to_222 = (Ether(src=self.pg0.remote_mac,
2130                                           dst=str(self.router_mac)) /
2131                                     IP(src=eps[0].ip4.address,
2132                                        dst=eps[3].ip4.address) /
2133                                     UDP(sport=1234, dport=1234) /
2134                                     Raw('\xa5' * 100))
2135         self.send_and_assert_no_replies(eps[0].itf,
2136                                         pkt_inter_epg_220_to_222 * 65)
2137
2138         #
2139         # contract for the return direction
2140         #
2141         c2 = VppGbpContract(
2142             self, epgs[1].sclass, epgs[0].sclass, acl_index,
2143             [VppGbpContractRule(
2144                 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2145                 []),
2146              VppGbpContractRule(
2147                  VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2148                  [])],
2149             [ETH_P_IP, ETH_P_IPV6])
2150         c2.add_vpp_config()
2151
2152         self.send_and_expect_bridged(eps[0].itf,
2153                                      pkt_inter_epg_220_to_221 * 65,
2154                                      eps[2].itf)
2155         pkt_inter_epg_221_to_220 = (Ether(src=self.pg2.remote_mac,
2156                                           dst=self.pg0.remote_mac) /
2157                                     IP(src=eps[2].ip4.address,
2158                                        dst=eps[0].ip4.address) /
2159                                     UDP(sport=1234, dport=1234) /
2160                                     Raw('\xa5' * 100))
2161         self.send_and_expect_bridged(eps[2].itf,
2162                                      pkt_inter_epg_221_to_220 * 65,
2163                                      eps[0].itf)
2164
2165         #
2166         # contract between 220 and 222 uni-direction
2167         #
2168         c3 = VppGbpContract(
2169             self, epgs[0].sclass, epgs[2].sclass, acl_index,
2170             [VppGbpContractRule(
2171                 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2172                 []),
2173              VppGbpContractRule(
2174                  VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
2175                  [])],
2176             [ETH_P_IP, ETH_P_IPV6])
2177         c3.add_vpp_config()
2178
2179         self.send_and_expect(eps[0].itf,
2180                              pkt_inter_epg_220_to_222 * 65,
2181                              eps[3].itf)
2182
2183         c3.remove_vpp_config()
2184         c1.remove_vpp_config()
2185         c2.remove_vpp_config()
2186         acl.remove_vpp_config()
2187
2188     def test_gbp_bd_flags(self):
2189         """ GBP BD FLAGS """
2190
2191         #
2192         # IP tables
2193         #
2194         gt4 = VppIpTable(self, 1)
2195         gt4.add_vpp_config()
2196         gt6 = VppIpTable(self, 1, is_ip6=True)
2197         gt6.add_vpp_config()
2198
2199         rd1 = VppGbpRouteDomain(self, 1, gt4, gt6)
2200         rd1.add_vpp_config()
2201
2202         #
2203         # Pg3 hosts the IP4 UU-flood VXLAN tunnel
2204         # Pg4 hosts the IP6 UU-flood VXLAN tunnel
2205         #
2206         self.pg3.config_ip4()
2207         self.pg3.resolve_arp()
2208         self.pg4.config_ip4()
2209         self.pg4.resolve_arp()
2210
2211         #
2212         # Add a mcast destination VXLAN-GBP tunnel for B&M traffic
2213         #
2214         tun_bm = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
2215                                    "239.1.1.1", 88,
2216                                    mcast_itf=self.pg4)
2217         tun_bm.add_vpp_config()
2218
2219         #
2220         # a GBP bridge domain with a BVI and a UU-flood interface
2221         #
2222         bd1 = VppBridgeDomain(self, 1)
2223         bd1.add_vpp_config()
2224
2225         gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0, self.pg3, tun_bm,
2226                                   uu_drop=True, bm_drop=True)
2227         gbd1.add_vpp_config()
2228
2229         self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2230         self.logger.info(self.vapi.cli("sh gbp bridge"))
2231
2232         # ... and has a /32 applied
2233         ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2234         ip_addr.add_vpp_config()
2235
2236         #
2237         # The Endpoint-group
2238         #
2239         epg_220 = VppGbpEndpointGroup(self, 220, 112, rd1, gbd1,
2240                                       None, self.loop0,
2241                                       "10.0.0.128",
2242                                       "2001:10::128",
2243                                       VppGbpEndpointRetention(2))
2244         epg_220.add_vpp_config()
2245
2246         ep = VppGbpEndpoint(self, self.pg0,
2247                             epg_220, None,
2248                             "10.0.0.127", "11.0.0.127",
2249                             "2001:10::1", "3001::1")
2250         ep.add_vpp_config()
2251         #
2252         # send UU/BM packet from the local EP with UU drop and BM drop enabled
2253         # in bd
2254         #
2255         self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2256         self.logger.info(self.vapi.cli("sh gbp bridge"))
2257         p_uu = (Ether(src=ep.mac, dst="00:11:11:11:11:11") /
2258                 IP(dst="10.0.0.133", src=ep.ip4.address) /
2259                 UDP(sport=1234, dport=1234) /
2260                 Raw('\xa5' * 100))
2261         self.send_and_assert_no_replies(ep.itf, [p_uu])
2262
2263         p_bm = (Ether(src=ep.mac, dst="ff:ff:ff:ff:ff:ff") /
2264                 IP(dst="10.0.0.133", src=ep.ip4.address) /
2265                 UDP(sport=1234, dport=1234) /
2266                 Raw('\xa5' * 100))
2267         self.send_and_assert_no_replies(ep.itf, [p_bm])
2268
2269         self.pg3.unconfig_ip4()
2270         self.pg4.unconfig_ip4()
2271
2272         self.logger.info(self.vapi.cli("sh int"))
2273
2274     def test_gbp_learn_vlan_l2(self):
2275         """ GBP L2 Endpoint w/ VLANs"""
2276
2277         ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
2278         learnt = [{'mac': '00:00:11:11:11:01',
2279                    'ip': '10.0.0.1',
2280                    'ip6': '2001:10::2'},
2281                   {'mac': '00:00:11:11:11:02',
2282                    'ip': '10.0.0.2',
2283                    'ip6': '2001:10::3'}]
2284
2285         #
2286         # IP tables
2287         #
2288         gt4 = VppIpTable(self, 1)
2289         gt4.add_vpp_config()
2290         gt6 = VppIpTable(self, 1, is_ip6=True)
2291         gt6.add_vpp_config()
2292
2293         rd1 = VppGbpRouteDomain(self, 1, gt4, gt6)
2294         rd1.add_vpp_config()
2295
2296         #
2297         # Pg2 hosts the vxlan tunnel, hosts on pg2 to act as TEPs
2298         #
2299         self.pg2.config_ip4()
2300         self.pg2.resolve_arp()
2301         self.pg2.generate_remote_hosts(4)
2302         self.pg2.configure_ipv4_neighbors()
2303         self.pg3.config_ip4()
2304         self.pg3.resolve_arp()
2305
2306         #
2307         # The EP will be on a vlan sub-interface
2308         #
2309         vlan_11 = VppDot1QSubint(self, self.pg0, 11)
2310         vlan_11.admin_up()
2311         self.vapi.l2_interface_vlan_tag_rewrite(
2312             sw_if_index=vlan_11.sw_if_index, vtr_op=L2_VTR_OP.L2_POP_1,
2313             push_dot1q=11)
2314
2315         bd_uu_fwd = VppVxlanGbpTunnel(self, self.pg3.local_ip4,
2316                                       self.pg3.remote_ip4, 116)
2317         bd_uu_fwd.add_vpp_config()
2318
2319         #
2320         # a GBP bridge domain with a BVI and a UU-flood interface
2321         # The BD is marked as do not learn, so no endpoints are ever
2322         # learnt in this BD.
2323         #
2324         bd1 = VppBridgeDomain(self, 1)
2325         bd1.add_vpp_config()
2326         gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0, bd_uu_fwd,
2327                                   learn=False)
2328         gbd1.add_vpp_config()
2329
2330         self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2331         self.logger.info(self.vapi.cli("sh gbp bridge"))
2332
2333         # ... and has a /32 applied
2334         ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2335         ip_addr.add_vpp_config()
2336
2337         #
2338         # The Endpoint-group in which we are learning endpoints
2339         #
2340         epg_220 = VppGbpEndpointGroup(self, 220, 441, rd1, gbd1,
2341                                       None, self.loop0,
2342                                       "10.0.0.128",
2343                                       "2001:10::128",
2344                                       VppGbpEndpointRetention(2))
2345         epg_220.add_vpp_config()
2346
2347         #
2348         # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
2349         # learning enabled
2350         #
2351         vx_tun_l2_1 = VppGbpVxlanTunnel(
2352             self, 99, bd1.bd_id,
2353             VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L2,
2354             self.pg2.local_ip4)
2355         vx_tun_l2_1.add_vpp_config()
2356
2357         #
2358         # A static endpoint that the learnt endpoints are trying to
2359         # talk to
2360         #
2361         ep = VppGbpEndpoint(self, vlan_11,
2362                             epg_220, None,
2363                             "10.0.0.127", "11.0.0.127",
2364                             "2001:10::1", "3001::1")
2365         ep.add_vpp_config()
2366
2367         self.assertTrue(find_route(self, ep.ip4.address, 32, table_id=1))
2368
2369         #
2370         # Send to the static EP
2371         #
2372         for ii, l in enumerate(learnt):
2373             # a packet with an sclass from a known EPG
2374             # arriving on an unknown TEP
2375             p = (Ether(src=self.pg2.remote_mac,
2376                        dst=self.pg2.local_mac) /
2377                  IP(src=self.pg2.remote_hosts[1].ip4,
2378                     dst=self.pg2.local_ip4) /
2379                  UDP(sport=1234, dport=48879) /
2380                  VXLAN(vni=99, gpid=441, flags=0x88) /
2381                  Ether(src=l['mac'], dst=ep.mac) /
2382                  IP(src=l['ip'], dst=ep.ip4.address) /
2383                  UDP(sport=1234, dport=1234) /
2384                  Raw('\xa5' * 100))
2385
2386             rxs = self.send_and_expect(self.pg2, [p], self.pg0)
2387
2388             #
2389             # packet to EP has the EP's vlan tag
2390             #
2391             for rx in rxs:
2392                 self.assertEqual(rx[Dot1Q].vlan, 11)
2393
2394             #
2395             # the EP is not learnt since the BD setting prevents it
2396             # also no TEP too
2397             #
2398             self.assertFalse(find_gbp_endpoint(self,
2399                                                vx_tun_l2_1.sw_if_index,
2400                                                mac=l['mac']))
2401             self.assertEqual(INDEX_INVALID,
2402                              find_vxlan_gbp_tunnel(
2403                                  self,
2404                                  self.pg2.local_ip4,
2405                                  self.pg2.remote_hosts[1].ip4,
2406                                  99))
2407
2408         self.assertEqual(len(self.vapi.gbp_endpoint_dump()), 1)
2409
2410         #
2411         # static to remotes
2412         # we didn't learn the remotes so they are sent to the UU-fwd
2413         #
2414         for l in learnt:
2415             p = (Ether(src=ep.mac, dst=l['mac']) /
2416                  Dot1Q(vlan=11) /
2417                  IP(dst=l['ip'], src=ep.ip4.address) /
2418                  UDP(sport=1234, dport=1234) /
2419                  Raw('\xa5' * 100))
2420
2421             rxs = self.send_and_expect(self.pg0, p * 17, self.pg3)
2422
2423             for rx in rxs:
2424                 self.assertEqual(rx[IP].src, self.pg3.local_ip4)
2425                 self.assertEqual(rx[IP].dst, self.pg3.remote_ip4)
2426                 self.assertEqual(rx[UDP].dport, 48879)
2427                 # the UDP source port is a random value for hashing
2428                 self.assertEqual(rx[VXLAN].gpid, 441)
2429                 self.assertEqual(rx[VXLAN].vni, 116)
2430                 self.assertTrue(rx[VXLAN].flags.G)
2431                 self.assertTrue(rx[VXLAN].flags.Instance)
2432                 self.assertFalse(rx[VXLAN].gpflags.A)
2433                 self.assertFalse(rx[VXLAN].gpflags.D)
2434
2435         self.pg2.unconfig_ip4()
2436         self.pg3.unconfig_ip4()
2437
2438     def test_gbp_learn_l3(self):
2439         """ GBP L3 Endpoint Learning """
2440
2441         self.vapi.cli("set logging class gbp level debug")
2442
2443         ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
2444         routed_dst_mac = "00:0c:0c:0c:0c:0c"
2445         routed_src_mac = "00:22:bd:f8:19:ff"
2446
2447         learnt = [{'mac': '00:00:11:11:11:02',
2448                    'ip': '10.0.1.2',
2449                    'ip6': '2001:10::2'},
2450                   {'mac': '00:00:11:11:11:03',
2451                    'ip': '10.0.1.3',
2452                    'ip6': '2001:10::3'}]
2453
2454         #
2455         # IP tables
2456         #
2457         t4 = VppIpTable(self, 1)
2458         t4.add_vpp_config()
2459         t6 = VppIpTable(self, 1, True)
2460         t6.add_vpp_config()
2461
2462         tun_ip4_uu = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
2463                                        self.pg4.remote_ip4, 114)
2464         tun_ip6_uu = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
2465                                        self.pg4.remote_ip4, 116)
2466         tun_ip4_uu.add_vpp_config()
2467         tun_ip6_uu.add_vpp_config()
2468
2469         rd1 = VppGbpRouteDomain(self, 2, t4, t6, tun_ip4_uu, tun_ip6_uu)
2470         rd1.add_vpp_config()
2471
2472         self.loop0.set_mac(self.router_mac)
2473
2474         #
2475         # Bind the BVI to the RD
2476         #
2477         VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
2478         VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
2479
2480         #
2481         # Pg2 hosts the vxlan tunnel
2482         # hosts on pg2 to act as TEPs
2483         # pg3 is BD uu-fwd
2484         # pg4 is RD uu-fwd
2485         #
2486         self.pg2.config_ip4()
2487         self.pg2.resolve_arp()
2488         self.pg2.generate_remote_hosts(4)
2489         self.pg2.configure_ipv4_neighbors()
2490         self.pg3.config_ip4()
2491         self.pg3.resolve_arp()
2492         self.pg4.config_ip4()
2493         self.pg4.resolve_arp()
2494
2495         #
2496         # a GBP bridge domain with a BVI and a UU-flood interface
2497         #
2498         bd1 = VppBridgeDomain(self, 1)
2499         bd1.add_vpp_config()
2500         gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0, self.pg3)
2501         gbd1.add_vpp_config()
2502
2503         self.logger.info(self.vapi.cli("sh bridge 1 detail"))
2504         self.logger.info(self.vapi.cli("sh gbp bridge"))
2505         self.logger.info(self.vapi.cli("sh gbp route"))
2506
2507         # ... and has a /32 and /128 applied
2508         ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2509         ip4_addr.add_vpp_config()
2510         ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 128)
2511         ip6_addr.add_vpp_config()
2512
2513         #
2514         # The Endpoint-group in which we are learning endpoints
2515         #
2516         epg_220 = VppGbpEndpointGroup(self, 220, 441, rd1, gbd1,
2517                                       None, self.loop0,
2518                                       "10.0.0.128",
2519                                       "2001:10::128",
2520                                       VppGbpEndpointRetention(2))
2521         epg_220.add_vpp_config()
2522
2523         #
2524         # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
2525         # learning enabled
2526         #
2527         vx_tun_l3 = VppGbpVxlanTunnel(
2528             self, 101, rd1.rd_id,
2529             VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
2530             self.pg2.local_ip4)
2531         vx_tun_l3.add_vpp_config()
2532
2533         #
2534         # A static endpoint that the learnt endpoints are trying to
2535         # talk to
2536         #
2537         ep = VppGbpEndpoint(self, self.pg0,
2538                             epg_220, None,
2539                             "10.0.0.127", "11.0.0.127",
2540                             "2001:10::1", "3001::1")
2541         ep.add_vpp_config()
2542
2543         #
2544         # learn some remote IPv4 EPs
2545         #
2546         for ii, l in enumerate(learnt):
2547             # a packet with an sclass from a known EPG
2548             # arriving on an unknown TEP
2549             p = (Ether(src=self.pg2.remote_mac,
2550                        dst=self.pg2.local_mac) /
2551                  IP(src=self.pg2.remote_hosts[1].ip4,
2552                     dst=self.pg2.local_ip4) /
2553                  UDP(sport=1234, dport=48879) /
2554                  VXLAN(vni=101, gpid=441, flags=0x88) /
2555                  Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2556                  IP(src=l['ip'], dst=ep.ip4.address) /
2557                  UDP(sport=1234, dport=1234) /
2558                  Raw('\xa5' * 100))
2559
2560             rx = self.send_and_expect(self.pg2, [p], self.pg0)
2561
2562             # the new TEP
2563             tep1_sw_if_index = find_vxlan_gbp_tunnel(
2564                 self,
2565                 self.pg2.local_ip4,
2566                 self.pg2.remote_hosts[1].ip4,
2567                 vx_tun_l3.vni)
2568             self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2569
2570             # endpoint learnt via the parent GBP-vxlan interface
2571             self.assertTrue(find_gbp_endpoint(self,
2572                                               vx_tun_l3._sw_if_index,
2573                                               ip=l['ip']))
2574
2575         #
2576         # Static IPv4 EP replies to learnt
2577         #
2578         for l in learnt:
2579             p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2580                  IP(dst=l['ip'], src=ep.ip4.address) /
2581                  UDP(sport=1234, dport=1234) /
2582                  Raw('\xa5' * 100))
2583
2584             rxs = self.send_and_expect(self.pg0, p * 1, self.pg2)
2585
2586             for rx in rxs:
2587                 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2588                 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2589                 self.assertEqual(rx[UDP].dport, 48879)
2590                 # the UDP source port is a random value for hashing
2591                 self.assertEqual(rx[VXLAN].gpid, 441)
2592                 self.assertEqual(rx[VXLAN].vni, 101)
2593                 self.assertTrue(rx[VXLAN].flags.G)
2594                 self.assertTrue(rx[VXLAN].flags.Instance)
2595                 self.assertTrue(rx[VXLAN].gpflags.A)
2596                 self.assertFalse(rx[VXLAN].gpflags.D)
2597
2598                 inner = rx[VXLAN].payload
2599
2600                 self.assertEqual(inner[Ether].src, routed_src_mac)
2601                 self.assertEqual(inner[Ether].dst, routed_dst_mac)
2602                 self.assertEqual(inner[IP].src, ep.ip4.address)
2603                 self.assertEqual(inner[IP].dst, l['ip'])
2604
2605         for l in learnt:
2606             self.assertFalse(find_gbp_endpoint(self,
2607                                                tep1_sw_if_index,
2608                                                ip=l['ip']))
2609
2610         #
2611         # learn some remote IPv6 EPs
2612         #
2613         for ii, l in enumerate(learnt):
2614             # a packet with an sclass from a known EPG
2615             # arriving on an unknown TEP
2616             p = (Ether(src=self.pg2.remote_mac,
2617                        dst=self.pg2.local_mac) /
2618                  IP(src=self.pg2.remote_hosts[1].ip4,
2619                     dst=self.pg2.local_ip4) /
2620                  UDP(sport=1234, dport=48879) /
2621                  VXLAN(vni=101, gpid=441, flags=0x88) /
2622                  Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2623                  IPv6(src=l['ip6'], dst=ep.ip6.address) /
2624                  UDP(sport=1234, dport=1234) /
2625                  Raw('\xa5' * 100))
2626
2627             rx = self.send_and_expect(self.pg2, [p], self.pg0)
2628
2629             # the new TEP
2630             tep1_sw_if_index = find_vxlan_gbp_tunnel(
2631                 self,
2632                 self.pg2.local_ip4,
2633                 self.pg2.remote_hosts[1].ip4,
2634                 vx_tun_l3.vni)
2635             self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2636
2637             self.logger.info(self.vapi.cli("show gbp bridge"))
2638             self.logger.info(self.vapi.cli("show vxlan-gbp tunnel"))
2639             self.logger.info(self.vapi.cli("show gbp vxlan"))
2640             self.logger.info(self.vapi.cli("show int addr"))
2641
2642             # endpoint learnt via the TEP
2643             self.assertTrue(find_gbp_endpoint(self, ip=l['ip6']))
2644
2645         self.logger.info(self.vapi.cli("show gbp endpoint"))
2646         self.logger.info(self.vapi.cli("show ip fib index 1 %s" % l['ip']))
2647
2648         #
2649         # Static EP replies to learnt
2650         #
2651         for l in learnt:
2652             p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2653                  IPv6(dst=l['ip6'], src=ep.ip6.address) /
2654                  UDP(sport=1234, dport=1234) /
2655                  Raw('\xa5' * 100))
2656
2657             rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
2658
2659             for rx in rxs:
2660                 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2661                 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2662                 self.assertEqual(rx[UDP].dport, 48879)
2663                 # the UDP source port is a random value for hashing
2664                 self.assertEqual(rx[VXLAN].gpid, 441)
2665                 self.assertEqual(rx[VXLAN].vni, 101)
2666                 self.assertTrue(rx[VXLAN].flags.G)
2667                 self.assertTrue(rx[VXLAN].flags.Instance)
2668                 self.assertTrue(rx[VXLAN].gpflags.A)
2669                 self.assertFalse(rx[VXLAN].gpflags.D)
2670
2671                 inner = rx[VXLAN].payload
2672
2673                 self.assertEqual(inner[Ether].src, routed_src_mac)
2674                 self.assertEqual(inner[Ether].dst, routed_dst_mac)
2675                 self.assertEqual(inner[IPv6].src, ep.ip6.address)
2676                 self.assertEqual(inner[IPv6].dst, l['ip6'])
2677
2678         self.logger.info(self.vapi.cli("sh gbp endpoint"))
2679         for l in learnt:
2680             self.wait_for_ep_timeout(ip=l['ip'])
2681
2682         #
2683         # Static sends to unknown EP with no route
2684         #
2685         p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2686              IP(dst="10.0.0.99", src=ep.ip4.address) /
2687              UDP(sport=1234, dport=1234) /
2688              Raw('\xa5' * 100))
2689
2690         self.send_and_assert_no_replies(self.pg0, [p])
2691
2692         #
2693         # Add a route to static EP's v4 and v6 subnet
2694         #  packets should be sent on the v4/v6 uu=fwd interface resp.
2695         #
2696         se_10_24 = VppGbpSubnet(
2697             self, rd1, "10.0.0.0", 24,
2698             VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT)
2699         se_10_24.add_vpp_config()
2700
2701         p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2702              IP(dst="10.0.0.99", src=ep.ip4.address) /
2703              UDP(sport=1234, dport=1234) /
2704              Raw('\xa5' * 100))
2705
2706         rxs = self.send_and_expect(self.pg0, [p], self.pg4)
2707         for rx in rxs:
2708             self.assertEqual(rx[IP].src, self.pg4.local_ip4)
2709             self.assertEqual(rx[IP].dst, self.pg4.remote_ip4)
2710             self.assertEqual(rx[UDP].dport, 48879)
2711             # the UDP source port is a random value for hashing
2712             self.assertEqual(rx[VXLAN].gpid, 441)
2713             self.assertEqual(rx[VXLAN].vni, 114)
2714             self.assertTrue(rx[VXLAN].flags.G)
2715             self.assertTrue(rx[VXLAN].flags.Instance)
2716             # policy is not applied to packets sent to the uu-fwd interfaces
2717             self.assertFalse(rx[VXLAN].gpflags.A)
2718             self.assertFalse(rx[VXLAN].gpflags.D)
2719
2720         #
2721         # learn some remote IPv4 EPs
2722         #
2723         for ii, l in enumerate(learnt):
2724             # a packet with an sclass from a known EPG
2725             # arriving on an unknown TEP
2726             p = (Ether(src=self.pg2.remote_mac,
2727                        dst=self.pg2.local_mac) /
2728                  IP(src=self.pg2.remote_hosts[2].ip4,
2729                     dst=self.pg2.local_ip4) /
2730                  UDP(sport=1234, dport=48879) /
2731                  VXLAN(vni=101, gpid=441, flags=0x88) /
2732                  Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2733                  IP(src=l['ip'], dst=ep.ip4.address) /
2734                  UDP(sport=1234, dport=1234) /
2735                  Raw('\xa5' * 100))
2736
2737             rx = self.send_and_expect(self.pg2, [p], self.pg0)
2738
2739             # the new TEP
2740             tep1_sw_if_index = find_vxlan_gbp_tunnel(
2741                 self,
2742                 self.pg2.local_ip4,
2743                 self.pg2.remote_hosts[2].ip4,
2744                 vx_tun_l3.vni)
2745             self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
2746
2747             # endpoint learnt via the parent GBP-vxlan interface
2748             self.assertTrue(find_gbp_endpoint(self,
2749                                               vx_tun_l3._sw_if_index,
2750                                               ip=l['ip']))
2751
2752         #
2753         # Add a remote endpoint from the API
2754         #
2755         rep_88 = VppGbpEndpoint(self, vx_tun_l3,
2756                                 epg_220, None,
2757                                 "10.0.0.88", "11.0.0.88",
2758                                 "2001:10::88", "3001::88",
2759                                 ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
2760                                 self.pg2.local_ip4,
2761                                 self.pg2.remote_hosts[1].ip4,
2762                                 mac=None)
2763         rep_88.add_vpp_config()
2764
2765         #
2766         # Add a remote endpoint from the API that matches an existing one
2767         #
2768         rep_2 = VppGbpEndpoint(self, vx_tun_l3,
2769                                epg_220, None,
2770                                learnt[0]['ip'], "11.0.0.101",
2771                                learnt[0]['ip6'], "3001::101",
2772                                ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
2773                                self.pg2.local_ip4,
2774                                self.pg2.remote_hosts[1].ip4,
2775                                mac=None)
2776         rep_2.add_vpp_config()
2777
2778         #
2779         # Add a route to the learned EP's v4 subnet
2780         #  packets should be send on the v4/v6 uu=fwd interface resp.
2781         #
2782         se_10_1_24 = VppGbpSubnet(
2783             self, rd1, "10.0.1.0", 24,
2784             VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT)
2785         se_10_1_24.add_vpp_config()
2786
2787         self.logger.info(self.vapi.cli("show gbp endpoint"))
2788
2789         ips = ["10.0.0.88", learnt[0]['ip']]
2790         for ip in ips:
2791             p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2792                  IP(dst=ip, src=ep.ip4.address) /
2793                  UDP(sport=1234, dport=1234) /
2794                  Raw('\xa5' * 100))
2795
2796             rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
2797
2798             for rx in rxs:
2799                 self.assertEqual(rx[IP].src, self.pg2.local_ip4)
2800                 self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
2801                 self.assertEqual(rx[UDP].dport, 48879)
2802                 # the UDP source port is a random value for hashing
2803                 self.assertEqual(rx[VXLAN].gpid, 441)
2804                 self.assertEqual(rx[VXLAN].vni, 101)
2805                 self.assertTrue(rx[VXLAN].flags.G)
2806                 self.assertTrue(rx[VXLAN].flags.Instance)
2807                 self.assertTrue(rx[VXLAN].gpflags.A)
2808                 self.assertFalse(rx[VXLAN].gpflags.D)
2809
2810                 inner = rx[VXLAN].payload
2811
2812                 self.assertEqual(inner[Ether].src, routed_src_mac)
2813                 self.assertEqual(inner[Ether].dst, routed_dst_mac)
2814                 self.assertEqual(inner[IP].src, ep.ip4.address)
2815                 self.assertEqual(inner[IP].dst, ip)
2816
2817         #
2818         # remove the API remote EPs, only API sourced is gone, the DP
2819         # learnt one remains
2820         #
2821         rep_88.remove_vpp_config()
2822         rep_2.remove_vpp_config()
2823
2824         self.assertTrue(find_gbp_endpoint(self, ip=rep_2.ip4.address))
2825
2826         p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2827              IP(src=ep.ip4.address, dst=rep_2.ip4.address) /
2828              UDP(sport=1234, dport=1234) /
2829              Raw('\xa5' * 100))
2830         rxs = self.send_and_expect(self.pg0, [p], self.pg2)
2831
2832         self.assertFalse(find_gbp_endpoint(self, ip=rep_88.ip4.address))
2833
2834         p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
2835              IP(src=ep.ip4.address, dst=rep_88.ip4.address) /
2836              UDP(sport=1234, dport=1234) /
2837              Raw('\xa5' * 100))
2838         rxs = self.send_and_expect(self.pg0, [p], self.pg4)
2839
2840         #
2841         # to appease the testcase we cannot have the registered EP still
2842         # present (because it's DP learnt) when the TC ends so wait until
2843         # it is removed
2844         #
2845         self.wait_for_ep_timeout(ip=rep_88.ip4.address)
2846         self.wait_for_ep_timeout(ip=rep_2.ip4.address)
2847
2848         #
2849         # shutdown with learnt endpoint present
2850         #
2851         p = (Ether(src=self.pg2.remote_mac,
2852                    dst=self.pg2.local_mac) /
2853              IP(src=self.pg2.remote_hosts[1].ip4,
2854                 dst=self.pg2.local_ip4) /
2855              UDP(sport=1234, dport=48879) /
2856              VXLAN(vni=101, gpid=441, flags=0x88) /
2857              Ether(src=l['mac'], dst="00:00:00:11:11:11") /
2858              IP(src=learnt[1]['ip'], dst=ep.ip4.address) /
2859              UDP(sport=1234, dport=1234) /
2860              Raw('\xa5' * 100))
2861
2862         rx = self.send_and_expect(self.pg2, [p], self.pg0)
2863
2864         # endpoint learnt via the parent GBP-vxlan interface
2865         self.assertTrue(find_gbp_endpoint(self,
2866                                           vx_tun_l3._sw_if_index,
2867                                           ip=l['ip']))
2868
2869         #
2870         # TODO
2871         # remote endpoint becomes local
2872         #
2873         self.pg2.unconfig_ip4()
2874         self.pg3.unconfig_ip4()
2875         self.pg4.unconfig_ip4()
2876
2877     def test_gbp_redirect(self):
2878         """ GBP Endpoint Redirect """
2879
2880         self.vapi.cli("set logging class gbp level debug")
2881
2882         ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
2883         routed_dst_mac = "00:0c:0c:0c:0c:0c"
2884         routed_src_mac = "00:22:bd:f8:19:ff"
2885
2886         learnt = [{'mac': '00:00:11:11:11:02',
2887                    'ip': '10.0.1.2',
2888                    'ip6': '2001:10::2'},
2889                   {'mac': '00:00:11:11:11:03',
2890                    'ip': '10.0.1.3',
2891                    'ip6': '2001:10::3'}]
2892
2893         #
2894         # IP tables
2895         #
2896         t4 = VppIpTable(self, 1)
2897         t4.add_vpp_config()
2898         t6 = VppIpTable(self, 1, True)
2899         t6.add_vpp_config()
2900
2901         rd1 = VppGbpRouteDomain(self, 2, t4, t6)
2902         rd1.add_vpp_config()
2903
2904         self.loop0.set_mac(self.router_mac)
2905
2906         #
2907         # Bind the BVI to the RD
2908         #
2909         VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
2910         VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
2911
2912         #
2913         # Pg7 hosts a BD's UU-fwd
2914         #
2915         self.pg7.config_ip4()
2916         self.pg7.resolve_arp()
2917
2918         #
2919         # a GBP bridge domains for the EPs
2920         #
2921         bd1 = VppBridgeDomain(self, 1)
2922         bd1.add_vpp_config()
2923         gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0)
2924         gbd1.add_vpp_config()
2925
2926         bd2 = VppBridgeDomain(self, 2)
2927         bd2.add_vpp_config()
2928         gbd2 = VppGbpBridgeDomain(self, bd2, self.loop1)
2929         gbd2.add_vpp_config()
2930
2931         # ... and has a /32 and /128 applied
2932         ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
2933         ip4_addr.add_vpp_config()
2934         ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 128)
2935         ip6_addr.add_vpp_config()
2936         ip4_addr = VppIpInterfaceAddress(self, gbd2.bvi, "10.0.1.128", 32)
2937         ip4_addr.add_vpp_config()
2938         ip6_addr = VppIpInterfaceAddress(self, gbd2.bvi, "2001:11::128", 128)
2939         ip6_addr.add_vpp_config()
2940
2941         #
2942         # The Endpoint-groups in which we are learning endpoints
2943         #
2944         epg_220 = VppGbpEndpointGroup(self, 220, 440, rd1, gbd1,
2945                                       None, gbd1.bvi,
2946                                       "10.0.0.128",
2947                                       "2001:10::128",
2948                                       VppGbpEndpointRetention(2))
2949         epg_220.add_vpp_config()
2950         epg_221 = VppGbpEndpointGroup(self, 221, 441, rd1, gbd2,
2951                                       None, gbd2.bvi,
2952                                       "10.0.1.128",
2953                                       "2001:11::128",
2954                                       VppGbpEndpointRetention(2))
2955         epg_221.add_vpp_config()
2956         epg_222 = VppGbpEndpointGroup(self, 222, 442, rd1, gbd1,
2957                                       None, gbd1.bvi,
2958                                       "10.0.2.128",
2959                                       "2001:12::128",
2960                                       VppGbpEndpointRetention(2))
2961         epg_222.add_vpp_config()
2962
2963         #
2964         # a GBP bridge domains for the SEPs
2965         #
2966         bd_uu1 = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
2967                                    self.pg7.remote_ip4, 116)
2968         bd_uu1.add_vpp_config()
2969         bd_uu2 = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
2970                                    self.pg7.remote_ip4, 117)
2971         bd_uu2.add_vpp_config()
2972
2973         bd3 = VppBridgeDomain(self, 3)
2974         bd3.add_vpp_config()
2975         gbd3 = VppGbpBridgeDomain(self, bd3, self.loop2, bd_uu1, learn=False)
2976         gbd3.add_vpp_config()
2977         bd4 = VppBridgeDomain(self, 4)
2978         bd4.add_vpp_config()
2979         gbd4 = VppGbpBridgeDomain(self, bd4, self.loop3, bd_uu2, learn=False)
2980         gbd4.add_vpp_config()
2981
2982         #
2983         # EPGs in which the service endpoints exist
2984         #
2985         epg_320 = VppGbpEndpointGroup(self, 320, 550, rd1, gbd3,
2986                                       None, gbd1.bvi,
2987                                       "12.0.0.128",
2988                                       "4001:10::128",
2989                                       VppGbpEndpointRetention(2))
2990         epg_320.add_vpp_config()
2991         epg_321 = VppGbpEndpointGroup(self, 321, 551, rd1, gbd4,
2992                                       None, gbd2.bvi,
2993                                       "12.0.1.128",
2994                                       "4001:11::128",
2995                                       VppGbpEndpointRetention(2))
2996         epg_321.add_vpp_config()
2997
2998         #
2999         # three local endpoints
3000         #
3001         ep1 = VppGbpEndpoint(self, self.pg0,
3002                              epg_220, None,
3003                              "10.0.0.1", "11.0.0.1",
3004                              "2001:10::1", "3001:10::1")
3005         ep1.add_vpp_config()
3006         ep2 = VppGbpEndpoint(self, self.pg1,
3007                              epg_221, None,
3008                              "10.0.1.1", "11.0.1.1",
3009                              "2001:11::1", "3001:11::1")
3010         ep2.add_vpp_config()
3011         ep3 = VppGbpEndpoint(self, self.pg2,
3012                              epg_222, None,
3013                              "10.0.2.2", "11.0.2.2",
3014                              "2001:12::1", "3001:12::1")
3015         ep3.add_vpp_config()
3016
3017         #
3018         # service endpoints
3019         #
3020         sep1 = VppGbpEndpoint(self, self.pg3,
3021                               epg_320, None,
3022                               "12.0.0.1", "13.0.0.1",
3023                               "4001:10::1", "5001:10::1")
3024         sep1.add_vpp_config()
3025         sep2 = VppGbpEndpoint(self, self.pg4,
3026                               epg_320, None,
3027                               "12.0.0.2", "13.0.0.2",
3028                               "4001:10::2", "5001:10::2")
3029         sep2.add_vpp_config()
3030         sep3 = VppGbpEndpoint(self, self.pg5,
3031                               epg_321, None,
3032                               "12.0.1.1", "13.0.1.1",
3033                               "4001:11::1", "5001:11::1")
3034         sep3.add_vpp_config()
3035         # this EP is not installed immediately
3036         sep4 = VppGbpEndpoint(self, self.pg6,
3037                               epg_321, None,
3038                               "12.0.1.2", "13.0.1.2",
3039                               "4001:11::2", "5001:11::2")
3040
3041         #
3042         # an L2 switch packet between local EPs in different EPGs
3043         #  different dest ports on each so the are LB hashed differently
3044         #
3045         p4 = [(Ether(src=ep1.mac, dst=ep3.mac) /
3046                IP(src=ep1.ip4.address, dst=ep3.ip4.address) /
3047                UDP(sport=1234, dport=1234) /
3048                Raw('\xa5' * 100)),
3049               (Ether(src=ep3.mac, dst=ep1.mac) /
3050                IP(src=ep3.ip4.address, dst=ep1.ip4.address) /
3051                UDP(sport=1234, dport=1234) /
3052                Raw('\xa5' * 100))]
3053         p6 = [(Ether(src=ep1.mac, dst=ep3.mac) /
3054                IPv6(src=ep1.ip6.address, dst=ep3.ip6.address) /
3055                UDP(sport=1234, dport=1234) /
3056                Raw('\xa5' * 100)),
3057               (Ether(src=ep3.mac, dst=ep1.mac) /
3058                IPv6(src=ep3.ip6.address, dst=ep1.ip6.address) /
3059                UDP(sport=1234, dport=1230) /
3060                Raw('\xa5' * 100))]
3061
3062         # should be dropped since no contract yet
3063         self.send_and_assert_no_replies(self.pg0, [p4[0]])
3064         self.send_and_assert_no_replies(self.pg0, [p6[0]])
3065
3066         #
3067         # Add a contract with a rule to load-balance redirect via SEP1 and SEP2
3068         # one of the next-hops is via an EP that is not known
3069         #
3070         acl = VppGbpAcl(self)
3071         rule4 = acl.create_rule(permit_deny=1, proto=17)
3072         rule6 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
3073         acl_index = acl.add_vpp_config([rule4, rule6])
3074
3075         #
3076         # test the src-ip hash mode
3077         #
3078         c1 = VppGbpContract(
3079             self, epg_220.sclass, epg_222.sclass, acl_index,
3080             [VppGbpContractRule(
3081                 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3082                 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3083                 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3084                                        sep1.ip4, sep1.epg.rd),
3085                  VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3086                                        sep2.ip4, sep2.epg.rd)]),
3087                 VppGbpContractRule(
3088                     VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3089                     VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3090                     [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3091                                            sep3.ip6, sep3.epg.rd),
3092                      VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3093                                            sep4.ip6, sep4.epg.rd)])],
3094             [ETH_P_IP, ETH_P_IPV6])
3095         c1.add_vpp_config()
3096
3097         c2 = VppGbpContract(
3098             self, epg_222.sclass, epg_220.sclass, acl_index,
3099             [VppGbpContractRule(
3100                 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3101                 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3102                 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3103                                        sep1.ip4, sep1.epg.rd),
3104                  VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3105                                        sep2.ip4, sep2.epg.rd)]),
3106                 VppGbpContractRule(
3107                     VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3108                     VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
3109                     [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3110                                            sep3.ip6, sep3.epg.rd),
3111                      VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3112                                            sep4.ip6, sep4.epg.rd)])],
3113             [ETH_P_IP, ETH_P_IPV6])
3114         c2.add_vpp_config()
3115
3116         #
3117         # send again with the contract preset, now packets arrive
3118         # at SEP1 or SEP2 depending on the hashing
3119         #
3120         rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3121
3122         for rx in rxs:
3123             self.assertEqual(rx[Ether].src, routed_src_mac)
3124             self.assertEqual(rx[Ether].dst, sep1.mac)
3125             self.assertEqual(rx[IP].src, ep1.ip4.address)
3126             self.assertEqual(rx[IP].dst, ep3.ip4.address)
3127
3128         rxs = self.send_and_expect(self.pg2, p4[1] * 17, sep2.itf)
3129
3130         for rx in rxs:
3131             self.assertEqual(rx[Ether].src, routed_src_mac)
3132             self.assertEqual(rx[Ether].dst, sep2.mac)
3133             self.assertEqual(rx[IP].src, ep3.ip4.address)
3134             self.assertEqual(rx[IP].dst, ep1.ip4.address)
3135
3136         rxs = self.send_and_expect(self.pg0, p6[0] * 17, self.pg7)
3137
3138         for rx in rxs:
3139             self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3140             self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3141             self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3142             self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
3143             self.assertEqual(rx[VXLAN].vni, 117)
3144             self.assertTrue(rx[VXLAN].flags.G)
3145             self.assertTrue(rx[VXLAN].flags.Instance)
3146             # redirect policy has been applied
3147             self.assertTrue(rx[VXLAN].gpflags.A)
3148             self.assertFalse(rx[VXLAN].gpflags.D)
3149
3150             inner = rx[VXLAN].payload
3151
3152             self.assertEqual(inner[Ether].src, routed_src_mac)
3153             self.assertEqual(inner[Ether].dst, sep4.mac)
3154             self.assertEqual(inner[IPv6].src, ep1.ip6.address)
3155             self.assertEqual(inner[IPv6].dst, ep3.ip6.address)
3156
3157         rxs = self.send_and_expect(self.pg2, p6[1] * 17, sep3.itf)
3158
3159         for rx in rxs:
3160             self.assertEqual(rx[Ether].src, routed_src_mac)
3161             self.assertEqual(rx[Ether].dst, sep3.mac)
3162             self.assertEqual(rx[IPv6].src, ep3.ip6.address)
3163             self.assertEqual(rx[IPv6].dst, ep1.ip6.address)
3164
3165         #
3166         # programme the unknown EP
3167         #
3168         sep4.add_vpp_config()
3169
3170         rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep4.itf)
3171
3172         for rx in rxs:
3173             self.assertEqual(rx[Ether].src, routed_src_mac)
3174             self.assertEqual(rx[Ether].dst, sep4.mac)
3175             self.assertEqual(rx[IPv6].src, ep1.ip6.address)
3176             self.assertEqual(rx[IPv6].dst, ep3.ip6.address)
3177
3178         #
3179         # and revert back to unprogrammed
3180         #
3181         sep4.remove_vpp_config()
3182
3183         rxs = self.send_and_expect(self.pg0, p6[0] * 17, self.pg7)
3184
3185         for rx in rxs:
3186             self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3187             self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3188             self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3189             self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
3190             self.assertEqual(rx[VXLAN].vni, 117)
3191             self.assertTrue(rx[VXLAN].flags.G)
3192             self.assertTrue(rx[VXLAN].flags.Instance)
3193             # redirect policy has been applied
3194             self.assertTrue(rx[VXLAN].gpflags.A)
3195             self.assertFalse(rx[VXLAN].gpflags.D)
3196
3197             inner = rx[VXLAN].payload
3198
3199             self.assertEqual(inner[Ether].src, routed_src_mac)
3200             self.assertEqual(inner[Ether].dst, sep4.mac)
3201             self.assertEqual(inner[IPv6].src, ep1.ip6.address)
3202             self.assertEqual(inner[IPv6].dst, ep3.ip6.address)
3203
3204         c1.remove_vpp_config()
3205         c2.remove_vpp_config()
3206
3207         #
3208         # test the symmetric hash mode
3209         #
3210         c1 = VppGbpContract(
3211             self, epg_220.sclass, epg_222.sclass, acl_index,
3212             [VppGbpContractRule(
3213                 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3214                 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3215                 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3216                                        sep1.ip4, sep1.epg.rd),
3217                  VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3218                                        sep2.ip4, sep2.epg.rd)]),
3219                 VppGbpContractRule(
3220                     VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3221                     VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3222                     [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3223                                            sep3.ip6, sep3.epg.rd),
3224                      VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3225                                            sep4.ip6, sep4.epg.rd)])],
3226             [ETH_P_IP, ETH_P_IPV6])
3227         c1.add_vpp_config()
3228
3229         c2 = VppGbpContract(
3230             self, epg_222.sclass, epg_220.sclass, acl_index,
3231             [VppGbpContractRule(
3232                 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3233                 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3234                 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3235                                        sep1.ip4, sep1.epg.rd),
3236                  VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3237                                        sep2.ip4, sep2.epg.rd)]),
3238                 VppGbpContractRule(
3239                     VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3240                     VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3241                     [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3242                                            sep3.ip6, sep3.epg.rd),
3243                      VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3244                                            sep4.ip6, sep4.epg.rd)])],
3245             [ETH_P_IP, ETH_P_IPV6])
3246         c2.add_vpp_config()
3247
3248         #
3249         # send again with the contract preset, now packets arrive
3250         # at SEP1 for both directions
3251         #
3252         rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3253
3254         for rx in rxs:
3255             self.assertEqual(rx[Ether].src, routed_src_mac)
3256             self.assertEqual(rx[Ether].dst, sep1.mac)
3257             self.assertEqual(rx[IP].src, ep1.ip4.address)
3258             self.assertEqual(rx[IP].dst, ep3.ip4.address)
3259
3260         rxs = self.send_and_expect(self.pg2, p4[1] * 17, sep1.itf)
3261
3262         for rx in rxs:
3263             self.assertEqual(rx[Ether].src, routed_src_mac)
3264             self.assertEqual(rx[Ether].dst, sep1.mac)
3265             self.assertEqual(rx[IP].src, ep3.ip4.address)
3266             self.assertEqual(rx[IP].dst, ep1.ip4.address)
3267
3268         #
3269         # programme the unknown EP for the L3 tests
3270         #
3271         sep4.add_vpp_config()
3272
3273         #
3274         # an L3 switch packet between local EPs in different EPGs
3275         #  different dest ports on each so the are LB hashed differently
3276         #
3277         p4 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3278                IP(src=ep1.ip4.address, dst=ep2.ip4.address) /
3279                UDP(sport=1234, dport=1234) /
3280                Raw('\xa5' * 100)),
3281               (Ether(src=ep2.mac, dst=str(self.router_mac)) /
3282                IP(src=ep2.ip4.address, dst=ep1.ip4.address) /
3283                UDP(sport=1234, dport=1234) /
3284                Raw('\xa5' * 100))]
3285         p6 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3286                IPv6(src=ep1.ip6.address, dst=ep2.ip6.address) /
3287                UDP(sport=1234, dport=1234) /
3288                Raw('\xa5' * 100)),
3289               (Ether(src=ep2.mac, dst=str(self.router_mac)) /
3290                IPv6(src=ep2.ip6.address, dst=ep1.ip6.address) /
3291                UDP(sport=1234, dport=1234) /
3292                Raw('\xa5' * 100))]
3293
3294         c3 = VppGbpContract(
3295             self, epg_220.sclass, epg_221.sclass, acl_index,
3296             [VppGbpContractRule(
3297                 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3298                 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3299                 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3300                                        sep1.ip4, sep1.epg.rd),
3301                  VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3302                                        sep2.ip4, sep2.epg.rd)]),
3303                 VppGbpContractRule(
3304                     VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3305                     VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
3306                     [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3307                                            sep3.ip6, sep3.epg.rd),
3308                      VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3309                                            sep4.ip6, sep4.epg.rd)])],
3310             [ETH_P_IP, ETH_P_IPV6])
3311         c3.add_vpp_config()
3312
3313         rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3314
3315         for rx in rxs:
3316             self.assertEqual(rx[Ether].src, routed_src_mac)
3317             self.assertEqual(rx[Ether].dst, sep1.mac)
3318             self.assertEqual(rx[IP].src, ep1.ip4.address)
3319             self.assertEqual(rx[IP].dst, ep2.ip4.address)
3320
3321         #
3322         # learn a remote EP in EPG 221
3323         #
3324         vx_tun_l3 = VppGbpVxlanTunnel(
3325             self, 444, rd1.rd_id,
3326             VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
3327             self.pg2.local_ip4)
3328         vx_tun_l3.add_vpp_config()
3329
3330         c4 = VppGbpContract(
3331             self, epg_221.sclass, epg_220.sclass, acl_index,
3332             [VppGbpContractRule(
3333                 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3334                 []),
3335                 VppGbpContractRule(
3336                     VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3337                     [])],
3338             [ETH_P_IP, ETH_P_IPV6])
3339         c4.add_vpp_config()
3340
3341         p = (Ether(src=self.pg7.remote_mac,
3342                    dst=self.pg7.local_mac) /
3343              IP(src=self.pg7.remote_ip4,
3344                 dst=self.pg7.local_ip4) /
3345              UDP(sport=1234, dport=48879) /
3346              VXLAN(vni=444, gpid=441, flags=0x88) /
3347              Ether(src="00:22:22:22:22:33", dst=str(self.router_mac)) /
3348              IP(src="10.0.0.88", dst=ep1.ip4.address) /
3349              UDP(sport=1234, dport=1234) /
3350              Raw('\xa5' * 100))
3351
3352         rx = self.send_and_expect(self.pg7, [p], self.pg0)
3353
3354         # endpoint learnt via the parent GBP-vxlan interface
3355         self.assertTrue(find_gbp_endpoint(self,
3356                                           vx_tun_l3._sw_if_index,
3357                                           ip="10.0.0.88"))
3358
3359         p = (Ether(src=self.pg7.remote_mac,
3360                    dst=self.pg7.local_mac) /
3361              IP(src=self.pg7.remote_ip4,
3362                 dst=self.pg7.local_ip4) /
3363              UDP(sport=1234, dport=48879) /
3364              VXLAN(vni=444, gpid=441, flags=0x88) /
3365              Ether(src="00:22:22:22:22:33", dst=str(self.router_mac)) /
3366              IPv6(src="2001:10::88", dst=ep1.ip6.address) /
3367              UDP(sport=1234, dport=1234) /
3368              Raw('\xa5' * 100))
3369
3370         rx = self.send_and_expect(self.pg7, [p], self.pg0)
3371
3372         # endpoint learnt via the parent GBP-vxlan interface
3373         self.assertTrue(find_gbp_endpoint(self,
3374                                           vx_tun_l3._sw_if_index,
3375                                           ip="2001:10::88"))
3376
3377         #
3378         # L3 switch from local to remote EP
3379         #
3380         p4 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3381                IP(src=ep1.ip4.address, dst="10.0.0.88") /
3382                UDP(sport=1234, dport=1234) /
3383                Raw('\xa5' * 100))]
3384         p6 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
3385                IPv6(src=ep1.ip6.address, dst="2001:10::88") /
3386                UDP(sport=1234, dport=1234) /
3387                Raw('\xa5' * 100))]
3388
3389         rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3390
3391         for rx in rxs:
3392             self.assertEqual(rx[Ether].src, routed_src_mac)
3393             self.assertEqual(rx[Ether].dst, sep1.mac)
3394             self.assertEqual(rx[IP].src, ep1.ip4.address)
3395             self.assertEqual(rx[IP].dst, "10.0.0.88")
3396
3397         rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep4.itf)
3398
3399         for rx in rxs:
3400             self.assertEqual(rx[Ether].src, routed_src_mac)
3401             self.assertEqual(rx[Ether].dst, sep4.mac)
3402             self.assertEqual(rx[IPv6].src, ep1.ip6.address)
3403             self.assertEqual(rx[IPv6].dst, "2001:10::88")
3404
3405         #
3406         # test the dst-ip hash mode
3407         #
3408         c5 = VppGbpContract(
3409             self, epg_220.sclass, epg_221.sclass, acl_index,
3410             [VppGbpContractRule(
3411                 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3412                 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
3413                 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
3414                                        sep1.ip4, sep1.epg.rd),
3415                  VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
3416                                        sep2.ip4, sep2.epg.rd)]),
3417                 VppGbpContractRule(
3418                     VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
3419                     VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
3420                     [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
3421                                            sep3.ip6, sep3.epg.rd),
3422                      VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
3423                                            sep4.ip6, sep4.epg.rd)])],
3424             [ETH_P_IP, ETH_P_IPV6])
3425         c5.add_vpp_config()
3426
3427         rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
3428
3429         for rx in rxs:
3430             self.assertEqual(rx[Ether].src, routed_src_mac)
3431             self.assertEqual(rx[Ether].dst, sep1.mac)
3432             self.assertEqual(rx[IP].src, ep1.ip4.address)
3433             self.assertEqual(rx[IP].dst, "10.0.0.88")
3434
3435         rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep3.itf)
3436
3437         for rx in rxs:
3438             self.assertEqual(rx[Ether].src, routed_src_mac)
3439             self.assertEqual(rx[Ether].dst, sep3.mac)
3440             self.assertEqual(rx[IPv6].src, ep1.ip6.address)
3441             self.assertEqual(rx[IPv6].dst, "2001:10::88")
3442
3443         #
3444         # cleanup
3445         #
3446         self.pg7.unconfig_ip4()
3447
3448     def test_gbp_l3_out(self):
3449         """ GBP L3 Out """
3450
3451         ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
3452         self.vapi.cli("set logging class gbp level debug")
3453
3454         routed_dst_mac = "00:0c:0c:0c:0c:0c"
3455         routed_src_mac = "00:22:bd:f8:19:ff"
3456
3457         #
3458         # IP tables
3459         #
3460         t4 = VppIpTable(self, 1)
3461         t4.add_vpp_config()
3462         t6 = VppIpTable(self, 1, True)
3463         t6.add_vpp_config()
3464
3465         rd1 = VppGbpRouteDomain(self, 2, t4, t6)
3466         rd1.add_vpp_config()
3467
3468         self.loop0.set_mac(self.router_mac)
3469
3470         #
3471         # Bind the BVI to the RD
3472         #
3473         VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
3474         VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
3475
3476         #
3477         # Pg7 hosts a BD's BUM
3478         # Pg1 some other l3 interface
3479         #
3480         self.pg7.config_ip4()
3481         self.pg7.resolve_arp()
3482
3483         #
3484         # a multicast vxlan-gbp tunnel for broadcast in the BD
3485         #
3486         tun_bm = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
3487                                    "239.1.1.1", 88,
3488                                    mcast_itf=self.pg7)
3489         tun_bm.add_vpp_config()
3490
3491         #
3492         # a GBP external bridge domains for the EPs
3493         #
3494         bd1 = VppBridgeDomain(self, 1)
3495         bd1.add_vpp_config()
3496         gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0, None, tun_bm)
3497         gbd1.add_vpp_config()
3498
3499         #
3500         # The Endpoint-groups in which the external endpoints exist
3501         #
3502         epg_220 = VppGbpEndpointGroup(self, 220, 113, rd1, gbd1,
3503                                       None, gbd1.bvi,
3504                                       "10.0.0.128",
3505                                       "2001:10::128",
3506                                       VppGbpEndpointRetention(2))
3507         epg_220.add_vpp_config()
3508
3509         # the BVIs have the subnets applied ...
3510         ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 24)
3511         ip4_addr.add_vpp_config()
3512         ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 64)
3513         ip6_addr.add_vpp_config()
3514
3515         # ... which are L3-out subnets
3516         l3o_1 = VppGbpSubnet(
3517             self, rd1, "10.0.0.0", 24,
3518             VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3519             sclass=113)
3520         l3o_1.add_vpp_config()
3521
3522         #
3523         # an external interface attached to the outside world and the
3524         # external BD
3525         #
3526         vlan_100 = VppDot1QSubint(self, self.pg0, 100)
3527         vlan_100.admin_up()
3528         VppL2Vtr(self, vlan_100, L2_VTR_OP.L2_POP_1).add_vpp_config()
3529         vlan_101 = VppDot1QSubint(self, self.pg0, 101)
3530         vlan_101.admin_up()
3531         VppL2Vtr(self, vlan_101, L2_VTR_OP.L2_POP_1).add_vpp_config()
3532
3533         ext_itf = VppGbpExtItf(self, self.loop0, bd1, rd1)
3534         ext_itf.add_vpp_config()
3535
3536         #
3537         # an unicast vxlan-gbp for inter-RD traffic
3538         #
3539         vx_tun_l3 = VppGbpVxlanTunnel(
3540             self, 444, rd1.rd_id,
3541             VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
3542             self.pg2.local_ip4)
3543         vx_tun_l3.add_vpp_config()
3544
3545         #
3546         # External Endpoints
3547         #
3548         eep1 = VppGbpEndpoint(self, vlan_100,
3549                               epg_220, None,
3550                               "10.0.0.1", "11.0.0.1",
3551                               "2001:10::1", "3001::1",
3552                               ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
3553         eep1.add_vpp_config()
3554         eep2 = VppGbpEndpoint(self, vlan_101,
3555                               epg_220, None,
3556                               "10.0.0.2", "11.0.0.2",
3557                               "2001:10::2", "3001::2",
3558                               ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
3559         eep2.add_vpp_config()
3560
3561         #
3562         # A remote external endpoint
3563         #
3564         rep = VppGbpEndpoint(self, vx_tun_l3,
3565                              epg_220, None,
3566                              "10.0.0.101", "11.0.0.101",
3567                              "2001:10::101", "3001::101",
3568                              ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
3569                              self.pg7.local_ip4,
3570                              self.pg7.remote_ip4,
3571                              mac=None)
3572         rep.add_vpp_config()
3573
3574         #
3575         # ARP packet from External EPs are accepted and replied to
3576         #
3577         p_arp = (Ether(src=eep1.mac, dst="ff:ff:ff:ff:ff:ff") /
3578                  Dot1Q(vlan=100) /
3579                  ARP(op="who-has",
3580                      psrc=eep1.ip4.address, pdst="10.0.0.128",
3581                      hwsrc=eep1.mac, hwdst="ff:ff:ff:ff:ff:ff"))
3582         rxs = self.send_and_expect(self.pg0, p_arp * 1, self.pg0)
3583
3584         #
3585         # packets destined to unknown addresses in the BVI's subnet
3586         # are ARP'd for
3587         #
3588         p4 = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3589               Dot1Q(vlan=100) /
3590               IP(src="10.0.0.1", dst="10.0.0.88") /
3591               UDP(sport=1234, dport=1234) /
3592               Raw('\xa5' * 100))
3593         p6 = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3594               Dot1Q(vlan=100) /
3595               IPv6(src="2001:10::1", dst="2001:10::88") /
3596               UDP(sport=1234, dport=1234) /
3597               Raw('\xa5' * 100))
3598
3599         rxs = self.send_and_expect(self.pg0, p4 * 1, self.pg7)
3600
3601         for rx in rxs:
3602             self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3603             # self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3604             self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3605             self.assertEqual(rx[IP].dst, "239.1.1.1")
3606             self.assertEqual(rx[VXLAN].vni, 88)
3607             self.assertTrue(rx[VXLAN].flags.G)
3608             self.assertTrue(rx[VXLAN].flags.Instance)
3609             # policy was applied to the original IP packet
3610             self.assertEqual(rx[VXLAN].gpid, 113)
3611             self.assertTrue(rx[VXLAN].gpflags.A)
3612             self.assertFalse(rx[VXLAN].gpflags.D)
3613
3614             inner = rx[VXLAN].payload
3615
3616             self.assertTrue(inner.haslayer(ARP))
3617
3618         #
3619         # remote to external
3620         #
3621         p = (Ether(src=self.pg7.remote_mac,
3622                    dst=self.pg7.local_mac) /
3623              IP(src=self.pg7.remote_ip4,
3624                 dst=self.pg7.local_ip4) /
3625              UDP(sport=1234, dport=48879) /
3626              VXLAN(vni=444, gpid=113, flags=0x88) /
3627              Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
3628              IP(src="10.0.0.101", dst="10.0.0.1") /
3629              UDP(sport=1234, dport=1234) /
3630              Raw('\xa5' * 100))
3631
3632         rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
3633
3634         #
3635         # local EP pings router
3636         #
3637         p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3638              Dot1Q(vlan=100) /
3639              IP(src=eep1.ip4.address, dst="10.0.0.128") /
3640              ICMP(type='echo-request'))
3641
3642         rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
3643
3644         for rx in rxs:
3645             self.assertEqual(rx[Ether].src, str(self.router_mac))
3646             self.assertEqual(rx[Ether].dst, eep1.mac)
3647             self.assertEqual(rx[Dot1Q].vlan, 100)
3648
3649         #
3650         # local EP pings other local EP
3651         #
3652         p = (Ether(src=eep1.mac, dst=eep2.mac) /
3653              Dot1Q(vlan=100) /
3654              IP(src=eep1.ip4.address, dst=eep2.ip4.address) /
3655              ICMP(type='echo-request'))
3656
3657         rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
3658
3659         for rx in rxs:
3660             self.assertEqual(rx[Ether].src, eep1.mac)
3661             self.assertEqual(rx[Ether].dst, eep2.mac)
3662             self.assertEqual(rx[Dot1Q].vlan, 101)
3663
3664         #
3665         # A subnet reachable through the external EP1
3666         #
3667         ip_220 = VppIpRoute(self, "10.220.0.0", 24,
3668                             [VppRoutePath(eep1.ip4.address,
3669                                           eep1.epg.bvi.sw_if_index)],
3670                             table_id=t4.table_id)
3671         ip_220.add_vpp_config()
3672
3673         l3o_220 = VppGbpSubnet(
3674             self, rd1, "10.220.0.0", 24,
3675             VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3676             sclass=4220)
3677         l3o_220.add_vpp_config()
3678
3679         #
3680         # A subnet reachable through the external EP2
3681         #
3682         ip_221 = VppIpRoute(self, "10.221.0.0", 24,
3683                             [VppRoutePath(eep2.ip4.address,
3684                                           eep2.epg.bvi.sw_if_index)],
3685                             table_id=t4.table_id)
3686         ip_221.add_vpp_config()
3687
3688         l3o_221 = VppGbpSubnet(
3689             self, rd1, "10.221.0.0", 24,
3690             VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3691             sclass=4221)
3692         l3o_221.add_vpp_config()
3693
3694         #
3695         # ping between hosts in remote subnets
3696         #  dropped without a contract
3697         #
3698         p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3699              Dot1Q(vlan=100) /
3700              IP(src="10.220.0.1", dst="10.221.0.1") /
3701              ICMP(type='echo-request'))
3702
3703         rxs = self.send_and_assert_no_replies(self.pg0, p * 1)
3704
3705         #
3706         # contract for the external nets to communicate
3707         #
3708         acl = VppGbpAcl(self)
3709         rule4 = acl.create_rule(permit_deny=1, proto=17)
3710         rule6 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
3711         acl_index = acl.add_vpp_config([rule4, rule6])
3712
3713         c1 = VppGbpContract(
3714             self, 4220, 4221, acl_index,
3715             [VppGbpContractRule(
3716                 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3717                 []),
3718                 VppGbpContractRule(
3719                     VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3720                     [])],
3721             [ETH_P_IP, ETH_P_IPV6])
3722         c1.add_vpp_config()
3723
3724         #
3725         # Contracts allowing ext-net 200 to talk with external EPs
3726         #
3727         c2 = VppGbpContract(
3728             self, 4220, 113, acl_index,
3729             [VppGbpContractRule(
3730                 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3731                 []),
3732                 VppGbpContractRule(
3733                     VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3734                     [])],
3735             [ETH_P_IP, ETH_P_IPV6])
3736         c2.add_vpp_config()
3737         c3 = VppGbpContract(
3738             self, 113, 4220, acl_index,
3739             [VppGbpContractRule(
3740                 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3741                 []),
3742                 VppGbpContractRule(
3743                     VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3744                     [])],
3745             [ETH_P_IP, ETH_P_IPV6])
3746         c3.add_vpp_config()
3747
3748         #
3749         # ping between hosts in remote subnets
3750         #
3751         p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3752              Dot1Q(vlan=100) /
3753              IP(src="10.220.0.1", dst="10.221.0.1") /
3754              UDP(sport=1234, dport=1234) /
3755              Raw('\xa5' * 100))
3756
3757         rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
3758
3759         for rx in rxs:
3760             self.assertEqual(rx[Ether].src, str(self.router_mac))
3761             self.assertEqual(rx[Ether].dst, eep2.mac)
3762             self.assertEqual(rx[Dot1Q].vlan, 101)
3763
3764         # we did not learn these external hosts
3765         self.assertFalse(find_gbp_endpoint(self, ip="10.220.0.1"))
3766         self.assertFalse(find_gbp_endpoint(self, ip="10.221.0.1"))
3767
3768         #
3769         # from remote external EP to local external EP
3770         #
3771         p = (Ether(src=self.pg7.remote_mac,
3772                    dst=self.pg7.local_mac) /
3773              IP(src=self.pg7.remote_ip4,
3774                 dst=self.pg7.local_ip4) /
3775              UDP(sport=1234, dport=48879) /
3776              VXLAN(vni=444, gpid=113, flags=0x88) /
3777              Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
3778              IP(src="10.0.0.101", dst="10.220.0.1") /
3779              UDP(sport=1234, dport=1234) /
3780              Raw('\xa5' * 100))
3781
3782         rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
3783
3784         #
3785         # ping from an external host to the remote external EP
3786         #
3787         p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3788              Dot1Q(vlan=100) /
3789              IP(src="10.220.0.1", dst=rep.ip4.address) /
3790              UDP(sport=1234, dport=1234) /
3791              Raw('\xa5' * 100))
3792
3793         rxs = self.send_and_expect(self.pg0, p * 1, self.pg7)
3794
3795         for rx in rxs:
3796             self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3797             # self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3798             self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3799             self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
3800             self.assertEqual(rx[VXLAN].vni, 444)
3801             self.assertTrue(rx[VXLAN].flags.G)
3802             self.assertTrue(rx[VXLAN].flags.Instance)
3803             # the sclass of the ext-net the packet came from
3804             self.assertEqual(rx[VXLAN].gpid, 4220)
3805             # policy was applied to the original IP packet
3806             self.assertTrue(rx[VXLAN].gpflags.A)
3807             # since it's an external host the reciever should not learn it
3808             self.assertTrue(rx[VXLAN].gpflags.D)
3809             inner = rx[VXLAN].payload
3810             self.assertEqual(inner[IP].src, "10.220.0.1")
3811             self.assertEqual(inner[IP].dst, rep.ip4.address)
3812
3813         #
3814         # An external subnet reachable via the remote external EP
3815         #
3816
3817         #
3818         # first the VXLAN-GBP tunnel over which it is reached
3819         #
3820         vx_tun_r = VppVxlanGbpTunnel(
3821             self, self.pg7.local_ip4,
3822             self.pg7.remote_ip4, 445,
3823             mode=(VppEnum.vl_api_vxlan_gbp_api_tunnel_mode_t.
3824                   VXLAN_GBP_API_TUNNEL_MODE_L3))
3825         vx_tun_r.add_vpp_config()
3826         VppIpInterfaceBind(self, vx_tun_r, t4).add_vpp_config()
3827
3828         self.logger.info(self.vapi.cli("sh vxlan-gbp tunnel"))
3829
3830         #
3831         # then the special adj to resolve through on that tunnel
3832         #
3833         n1 = VppNeighbor(self,
3834                          vx_tun_r.sw_if_index,
3835                          "00:0c:0c:0c:0c:0c",
3836                          self.pg7.remote_ip4)
3837         n1.add_vpp_config()
3838
3839         #
3840         # the route via the adj above
3841         #
3842         ip_222 = VppIpRoute(self, "10.222.0.0", 24,
3843                             [VppRoutePath(self.pg7.remote_ip4,
3844                                           vx_tun_r.sw_if_index)],
3845                             table_id=t4.table_id)
3846         ip_222.add_vpp_config()
3847
3848         l3o_222 = VppGbpSubnet(
3849             self, rd1, "10.222.0.0", 24,
3850             VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
3851             sclass=4222)
3852         l3o_222.add_vpp_config()
3853
3854         #
3855         # ping between hosts in local and remote external subnets
3856         #  dropped without a contract
3857         #
3858         p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3859              Dot1Q(vlan=100) /
3860              IP(src="10.220.0.1", dst="10.222.0.1") /
3861              UDP(sport=1234, dport=1234) /
3862              Raw('\xa5' * 100))
3863
3864         rxs = self.send_and_assert_no_replies(self.pg0, p * 1)
3865
3866         #
3867         # Add contracts ext-nets for 220 -> 222
3868         #
3869         c4 = VppGbpContract(
3870             self, 4220, 4222, acl_index,
3871             [VppGbpContractRule(
3872                 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3873                 []),
3874                 VppGbpContractRule(
3875                     VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
3876                     [])],
3877             [ETH_P_IP, ETH_P_IPV6])
3878         c4.add_vpp_config()
3879
3880         #
3881         # ping from host in local to remote external subnets
3882         #
3883         p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
3884              Dot1Q(vlan=100) /
3885              IP(src="10.220.0.1", dst="10.222.0.1") /
3886              UDP(sport=1234, dport=1234) /
3887              Raw('\xa5' * 100))
3888
3889         rxs = self.send_and_expect(self.pg0, p * 3, self.pg7)
3890
3891         for rx in rxs:
3892             self.assertEqual(rx[Ether].src, self.pg7.local_mac)
3893             self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
3894             self.assertEqual(rx[IP].src, self.pg7.local_ip4)
3895             self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
3896             self.assertEqual(rx[VXLAN].vni, 445)
3897             self.assertTrue(rx[VXLAN].flags.G)
3898             self.assertTrue(rx[VXLAN].flags.Instance)
3899             # the sclass of the ext-net the packet came from
3900             self.assertEqual(rx[VXLAN].gpid, 4220)
3901             # policy was applied to the original IP packet
3902             self.assertTrue(rx[VXLAN].gpflags.A)
3903             # since it's an external host the reciever should not learn it
3904             self.assertTrue(rx[VXLAN].gpflags.D)
3905             inner = rx[VXLAN].payload
3906             self.assertEqual(inner[Ether].dst, "00:0c:0c:0c:0c:0c")
3907             self.assertEqual(inner[IP].src, "10.220.0.1")
3908             self.assertEqual(inner[IP].dst, "10.222.0.1")
3909
3910         #
3911         # ping from host in remote to local external subnets
3912         # there's no contract for this, but the A bit is set.
3913         #
3914         p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
3915              IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
3916              UDP(sport=1234, dport=48879) /
3917              VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
3918              Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
3919              IP(src="10.222.0.1", dst="10.220.0.1") /
3920              UDP(sport=1234, dport=1234) /
3921              Raw('\xa5' * 100))
3922
3923         rxs = self.send_and_expect(self.pg7, p * 3, self.pg0)
3924         self.assertFalse(find_gbp_endpoint(self, ip="10.222.0.1"))
3925
3926         #
3927         # ping from host in remote to remote external subnets
3928         #   this is dropped by reflection check.
3929         #
3930         p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
3931              IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
3932              UDP(sport=1234, dport=48879) /
3933              VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
3934              Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
3935              IP(src="10.222.0.1", dst="10.222.0.2") /
3936              UDP(sport=1234, dport=1234) /
3937              Raw('\xa5' * 100))
3938
3939         rxs = self.send_and_assert_no_replies(self.pg7, p * 3)
3940
3941         #
3942         # cleanup
3943         #
3944         self.pg7.unconfig_ip4()
3945         vlan_100.set_vtr(L2_VTR_OP.L2_DISABLED)
3946
3947
3948 if __name__ == '__main__':
3949     unittest.main(testRunner=VppTestRunner)