+ #
+ # Config related to each of the EPGs
+ #
+ for epg in epgs:
+ # IP config on the BVI interfaces
+ if epg != epgs[1] and epg != epgs[4]:
+ epg.bvi.set_table_ip4(epg.rd)
+ epg.bvi.set_table_ip6(epg.rd)
+
+ # The BVIs are NAT inside interfaces
+ self.vapi.nat44_interface_add_del_feature(epg.bvi.sw_if_index,
+ is_inside=1,
+ is_add=1)
+ # self.vapi.nat66_add_del_interface(epg.bvi.sw_if_index,
+ # is_inside=1,
+ # is_add=1)
+
+ self.vapi.sw_interface_add_del_address(epg.bvi.sw_if_index,
+ epg.bvi_ip4_n,
+ 32)
+ self.vapi.sw_interface_add_del_address(epg.bvi.sw_if_index,
+ epg.bvi_ip6_n,
+ 128,
+ is_ipv6=1)
+
+ # EPG uplink interfaces in the BD
+ epg.uplink.set_table_ip4(epg.rd)
+ self.vapi.sw_interface_set_l2_bridge(epg.uplink.sw_if_index,
+ epg.bd)
+
+ # add the BD ARP termination entry for BVI IP
+ self.vapi.bd_ip_mac_add_del(bd_id=epg.bd,
+ mac=mactobinary(self.router_mac),
+ ip=epg.bvi_ip4_n,
+ is_ipv6=0,
+ is_add=1)
+ self.vapi.bd_ip_mac_add_del(bd_id=epg.bd,
+ mac=mactobinary(self.router_mac),
+ ip=epg.bvi_ip6_n,
+ is_ipv6=1,
+ is_add=1)
+
+ # epg[1] shares the same BVI to epg[0]
+ if epg != epgs[1] and epg != epgs[4]:
+ # BVI in BD
+ self.vapi.sw_interface_set_l2_bridge(epg.bvi.sw_if_index,
+ epg.bd,
+ bvi=1)
+ # BVI L2 FIB entry
+ self.vapi.l2fib_add_del(self.router_mac,
+ epg.bd,
+ epg.bvi.sw_if_index,
+ is_add=1, bvi_mac=1)
+
+ # EPG in VPP
+ epg.add_vpp_config()
+
+ for recirc in recircs:
+ # EPG's ingress recirculation interface maps to its RD
+ recirc.recirc.set_table_ip4(recirc.epg.rd)
+
+ # in the bridge to allow DVR. L2 emulation to punt to L3
+ self.vapi.sw_interface_set_l2_bridge(recirc.recirc.sw_if_index,
+ recirc.epg.bd)
+ self.vapi.sw_interface_set_l2_emulation(
+ recirc.recirc.sw_if_index)
+
+ if recirc.is_ext:
+ # recirc interfaces on NAT EPGs are outside and an
+ # output feature
+ self.vapi.nat44_interface_add_del_output_feature(
+ recirc.recirc.sw_if_index,
+ is_inside=0,
+ is_add=1)
+ else:
+ self.vapi.nat44_interface_add_del_feature(
+ recirc.recirc.sw_if_index,
+ is_inside=0,
+ is_add=1)
+ # self.vapi.nat66_add_del_interface(
+ # recirc.recirc.sw_if_index,
+ # is_inside=0,
+ # is_add=1)
+
+ recirc.add_vpp_config()
+
+ ep_routes = []
+ ep_arps = []
+ for ep in eps:
+ self.pg_enable_capture(self.pg_interfaces)
+ self.pg_start()
+ #
+ # routes to the endpoints. We need these since there are no
+ # adj-fibs due to the fact the the BVI address has /32 and
+ # the subnet is not attached.
+ #
+ r = VppIpRoute(self, ep.ip, 32,
+ [VppRoutePath(ep.ip,
+ ep.epg.bvi.sw_if_index,
+ proto=ep.proto)],
+ is_ip6=ep.is_ip6)
+ r.add_vpp_config()
+ ep_routes.append(r)
+
+ #
+ # ARP entries for the endpoints
+ #
+ a = VppNeighbor(self,
+ ep.epg.bvi.sw_if_index,
+ ep.itf.remote_mac,
+ ep.ip, af=ep.af)
+ a.add_vpp_config()
+ ep_arps.append(a)
+
+ # add each EP itf to the its BD
+ self.vapi.sw_interface_set_l2_bridge(ep.itf.sw_if_index,
+ ep.epg.bd)
+
+ # add the BD ARP termination entry
+ self.vapi.bd_ip_mac_add_del(bd_id=ep.epg.bd,
+ mac=ep.bin_mac,
+ ip=ep.ip_n,
+ is_ipv6=0,
+ is_add=1)
+
+ # L2 FIB entry
+ self.vapi.l2fib_add_del(ep.mac,
+ ep.epg.bd,
+ ep.itf.sw_if_index,
+ is_add=1)
+
+ # Add static mappings for each EP from the 10/8 to 11/8 network
+ if ep.af == AF_INET:
+ self.vapi.nat44_add_del_static_mapping(ep.ip_n,
+ ep.floating_ip_n,
+ vrf_id=0,
+ addr_only=1)
+ # else:
+ # self.vapi.nat66_add_del_static_mapping(ep.ip_n,
+ # ep.floating_ip_n,
+ # vrf_id=20)
+
+ # VPP EP create ...
+ ep.add_vpp_config()
+
+ # ... results in a Gratuitous ARP/ND on the EPG's uplink
+ rx = ep.epg.uplink.get_capture(1, timeout=0.2)
+
+ if ep.is_ip6:
+ self.assertTrue(rx[0].haslayer(ICMPv6ND_NA))
+ self.assertEqual(rx[0][ICMPv6ND_NA].tgt, ep.ip)
+ else:
+ self.assertTrue(rx[0].haslayer(ARP))
+ self.assertEqual(rx[0][ARP].psrc, ep.ip)
+ self.assertEqual(rx[0][ARP].pdst, ep.ip)
+
+ # add the BD ARP termination entry for floating IP
+ self.vapi.bd_ip_mac_add_del(bd_id=epg_nat.bd,
+ mac=ep.bin_mac,
+ ip=ep.floating_ip_n,
+ is_ipv6=0,
+ is_add=1)
+
+ # floating IPs route via EPG recirc
+ r = VppIpRoute(self, ep.floating_ip, 32,
+ [VppRoutePath(ep.floating_ip,
+ ep.recirc.recirc.sw_if_index,
+ is_dvr=1,
+ proto=ep.proto)],
+ table_id=20,
+ is_ip6=ep.is_ip6)
+ r.add_vpp_config()
+ ep_routes.append(r)
+
+ # L2 FIB entries in the NAT EPG BD to bridge the packets from
+ # the outside direct to the internal EPG
+ self.vapi.l2fib_add_del(ep.mac,
+ epg_nat.bd,
+ ep.recirc.recirc.sw_if_index,
+ is_add=1)