aboutsummaryrefslogtreecommitdiffstats
path: root/src/plugins/gbp
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/gbp')
-rw-r--r--src/plugins/gbp/test/test_gbp.py5926
1 files changed, 0 insertions, 5926 deletions
diff --git a/src/plugins/gbp/test/test_gbp.py b/src/plugins/gbp/test/test_gbp.py
deleted file mode 100644
index 21d0770cf66..00000000000
--- a/src/plugins/gbp/test/test_gbp.py
+++ /dev/null
@@ -1,5926 +0,0 @@
-#!/usr/bin/env python3
-import typing
-from socket import AF_INET6, inet_pton, inet_ntop
-import unittest
-from ipaddress import ip_address, IPv4Network, IPv6Network
-
-from scapy.packet import Raw
-from scapy.layers.l2 import Ether, ARP, Dot1Q
-from scapy.layers.inet import IP, UDP, ICMP
-from scapy.layers.inet6 import (
- IPv6,
- ICMPv6ND_NS,
- ICMPv6NDOptSrcLLAddr,
- ICMPv6ND_NA,
- ICMPv6EchoRequest,
-)
-from scapy.utils6 import in6_getnsma, in6_getnsmac
-from scapy.layers.vxlan import VXLAN
-from scapy.data import ETH_P_IP, ETH_P_IPV6
-
-from framework import tag_fixme_vpp_workers
-from framework import VppTestCase, VppTestRunner
-from vpp_object import VppObject
-from vpp_interface import VppInterface
-from vpp_ip_route import (
- VppIpRoute,
- VppRoutePath,
- VppIpTable,
- VppIpInterfaceAddress,
- VppIpInterfaceBind,
- find_route,
- FibPathProto,
- FibPathType,
-)
-from vpp_l2 import (
- VppBridgeDomain,
- VppBridgeDomainPort,
- VppBridgeDomainArpEntry,
- VppL2FibEntry,
- find_bridge_domain_port,
- VppL2Vtr,
-)
-from vpp_sub_interface import L2_VTR_OP, VppDot1QSubint
-from vpp_ip import DpoProto, get_dpo_proto
-from vpp_papi import VppEnum, MACAddress
-from vpp_vxlan_gbp_tunnel import find_vxlan_gbp_tunnel, INDEX_INVALID, \
- VppVxlanGbpTunnel
-from vpp_neighbor import VppNeighbor
-from vpp_acl import AclRule, VppAcl
-
-NUM_PKTS = 67
-
-
-def find_gbp_endpoint(test, sw_if_index=None, ip=None, mac=None,
- tep=None, sclass=None, flags=None):
- if ip:
- vip = ip
- if mac:
- vmac = MACAddress(mac)
-
- eps = test.vapi.gbp_endpoint_dump()
-
- for ep in eps:
- if tep:
- src = tep[0]
- dst = tep[1]
- if src != str(ep.endpoint.tun.src) or \
- dst != str(ep.endpoint.tun.dst):
- continue
- if sw_if_index:
- if ep.endpoint.sw_if_index != sw_if_index:
- continue
- if sclass:
- if ep.endpoint.sclass != sclass:
- continue
- if flags:
- if flags != (flags & ep.endpoint.flags):
- continue
- if ip:
- for eip in ep.endpoint.ips:
- if vip == str(eip):
- return True
- if mac:
- if vmac == ep.endpoint.mac:
- return True
-
- return False
-
-
-def find_gbp_vxlan(test: VppTestCase, vni):
- ts = test.vapi.gbp_vxlan_tunnel_dump()
- for t in ts:
- if t.tunnel.vni == vni:
- return True
- return False
-
-
-class VppGbpEndpoint(VppObject):
- """
- GBP Endpoint
- """
-
- @property
- def mac(self):
- return str(self.vmac)
-
- @property
- def ip4(self):
- return self._ip4
-
- @property
- def fip4(self):
- return self._fip4
-
- @property
- def ip6(self):
- return self._ip6
-
- @property
- def fip6(self):
- return self._fip6
-
- @property
- def ips(self):
- return [self.ip4, self.ip6]
-
- @property
- def fips(self):
- return [self.fip4, self.fip6]
-
- def __init__(self, test, itf, epg, recirc, ip4, fip4, ip6, fip6,
- flags=0,
- tun_src="0.0.0.0",
- tun_dst="0.0.0.0",
- mac=True):
- self._test = test
- self.itf = itf
- self.handle = None
- self.epg = epg
- self.recirc = recirc
-
- self._ip4 = ip4
- self._fip4 = fip4
- self._ip6 = ip6
- self._fip6 = fip6
-
- if mac:
- self.vmac = MACAddress(self.itf.remote_mac)
- else:
- self.vmac = MACAddress("00:00:00:00:00:00")
-
- self.flags = flags
- self.tun_src = tun_src
- self.tun_dst = tun_dst
-
- def encode(self):
- ips = [self.ip4, self.ip6]
- return {
- "sw_if_index": self.itf.sw_if_index,
- "ips": ips,
- "n_ips": len(ips),
- "mac": self.vmac.packed,
- "sclass": self.epg.sclass,
- "flags": self.flags,
- "tun": {
- "src": self.tun_src,
- "dst": self.tun_dst,
- },
- }
-
- def add_vpp_config(self):
- res = self._test.vapi.gbp_endpoint_add(
- endpoint=self.encode(),
- )
- self.handle = res.handle
- self._test.registry.register(self, self._test.logger)
-
- def remove_vpp_config(self):
- self._test.vapi.gbp_endpoint_del(handle=self.handle)
-
- def object_id(self):
- return "gbp-endpoint:[%d==%d:%s:%d]" % (self.handle,
- self.itf.sw_if_index,
- self.ip4,
- self.epg.sclass)
-
- def query_vpp_config(self):
- return find_gbp_endpoint(self._test,
- self.itf.sw_if_index,
- self.ip4)
-
-
-class VppGbpRecirc(VppObject):
- """
- GBP Recirculation Interface
- """
-
- def __init__(self, test, epg, recirc, is_ext=False):
- self._test = test
- self.recirc = recirc
- self.epg = epg
- self.is_ext = is_ext
-
- def encode(self):
- return {
- "is_ext": self.is_ext,
- "sw_if_index": self.recirc.sw_if_index,
- "sclass": self.epg.sclass,
- }
-
- def add_vpp_config(self):
- self._test.vapi.gbp_recirc_add_del(
- 1,
- recirc=self.encode(),
- )
- self._test.registry.register(self, self._test.logger)
-
- def remove_vpp_config(self):
- self._test.vapi.gbp_recirc_add_del(
- 0,
- recirc=self.encode(),
- )
-
- def object_id(self):
- return "gbp-recirc:[%d]" % (self.recirc.sw_if_index)
-
- def query_vpp_config(self):
- rs = self._test.vapi.gbp_recirc_dump()
- for r in rs:
- if r.recirc.sw_if_index == self.recirc.sw_if_index:
- return True
- return False
-
-
-class VppGbpExtItf(VppObject):
- """
- GBP ExtItfulation Interface
- """
-
- def __init__(self, test, itf, bd, rd, anon=False):
- self._test = test
- self.itf = itf
- self.bd = bd
- self.rd = rd
- self.flags = 1 if anon else 0
-
- def encode(self):
- return {
- "sw_if_index": self.itf.sw_if_index,
- "bd_id": self.bd.bd_id,
- "rd_id": self.rd.rd_id,
- "flags": self.flags,
- }
-
- def add_vpp_config(self):
- self._test.vapi.gbp_ext_itf_add_del(
- 1,
- ext_itf=self.encode(),
- )
- self._test.registry.register(self, self._test.logger)
-
- def remove_vpp_config(self):
- self._test.vapi.gbp_ext_itf_add_del(
- 0,
- ext_itf=self.encode(),
- )
-
- def object_id(self):
- return "gbp-ext-itf:[%d]%s" % (self.itf.sw_if_index,
- " [anon]" if self.flags else "")
-
- def query_vpp_config(self):
- rs = self._test.vapi.gbp_ext_itf_dump()
- for r in rs:
- if r.ext_itf.sw_if_index == self.itf.sw_if_index:
- return True
- return False
-
-
-class VppGbpSubnet(VppObject):
- """
- GBP Subnet
- """
-
- def __init__(self, test, rd, address, address_len,
- type, sw_if_index=0xffffffff, sclass=0xffff):
- # TODO: replace hardcoded defaults when vpp_papi supports
- # defaults in typedefs
- self._test = test
- self.rd_id = rd.rd_id
- a = ip_address(address)
- if 4 == a.version:
- self.prefix = IPv4Network("%s/%d" % (address, address_len),
- strict=False)
- else:
- self.prefix = IPv6Network("%s/%d" % (address, address_len),
- strict=False)
- self.type = type
- self.sw_if_index = sw_if_index
- self.sclass = sclass
-
- def encode(self):
- return {
- "type": self.type,
- "sw_if_index": self.sw_if_index,
- "sclass": self.sclass,
- "prefix": self.prefix,
- "rd_id": self.rd_id,
- }
-
- def add_vpp_config(self):
- self._test.vapi.gbp_subnet_add_del(
- is_add=1,
- subnet=self.encode(),
- )
- self._test.registry.register(self, self._test.logger)
-
- def remove_vpp_config(self):
- self._test.vapi.gbp_subnet_add_del(
- is_add=0,
- subnet=self.encode()
- )
-
- def object_id(self):
- return "gbp-subnet:[%d-%s]" % (self.rd_id, self.prefix)
-
- def query_vpp_config(self):
- ss = self._test.vapi.gbp_subnet_dump()
- for s in ss:
- if s.subnet.rd_id == self.rd_id and \
- s.subnet.type == self.type and \
- s.subnet.prefix == self.prefix:
- return True
- return False
-
-
-class VppGbpEndpointRetention(object):
- def __init__(self, remote_ep_timeout=0xffffffff):
- self.remote_ep_timeout = remote_ep_timeout
-
- def encode(self):
- return {'remote_ep_timeout': self.remote_ep_timeout}
-
-
-class VppGbpEndpointGroup(VppObject):
- """
- GBP Endpoint Group
- """
-
- def __init__(self, test, vnid, sclass, rd, bd, uplink,
- bvi, bvi_ip4, bvi_ip6=None,
- retention=VppGbpEndpointRetention()):
- self._test = test
- self.uplink = uplink
- self.bvi = bvi
- self.bvi_ip4 = bvi_ip4
- self.bvi_ip6 = bvi_ip6
- self.vnid = vnid
- self.bd = bd # VppGbpBridgeDomain
- self.rd = rd
- self.sclass = sclass
- if 0 == self.sclass:
- self.sclass = 0xffff
- self.retention = retention
-
- def encode(self) -> dict:
- return {
- "uplink_sw_if_index": self.uplink.sw_if_index
- if self.uplink else INDEX_INVALID,
- "bd_id": self.bd.bd.bd_id,
- "rd_id": self.rd.rd_id,
- "vnid": self.vnid,
- "sclass": self.sclass,
- "retention": self.retention.encode(),
- }
-
- def add_vpp_config(self):
- self._test.vapi.gbp_endpoint_group_add(epg=self.encode())
- self._test.registry.register(self, self._test.logger)
-
- def remove_vpp_config(self):
- self._test.vapi.gbp_endpoint_group_del(sclass=self.sclass)
-
- def object_id(self) -> str:
- return "gbp-endpoint-group:[%d]" % (self.vnid)
-
- def query_vpp_config(self) -> bool:
- epgs = self._test.vapi.gbp_endpoint_group_dump()
- for epg in epgs:
- if epg.epg.vnid == self.vnid:
- return True
- return False
-
-
-class VppGbpBridgeDomain(VppObject):
- """
- GBP Bridge Domain
- """
-
- def __init__(self, test, bd, rd, bvi,
- uu_fwd: typing.Optional[VppVxlanGbpTunnel] = None,
- bm_flood=None, learn=True,
- uu_drop=False, bm_drop=False,
- ucast_arp=False):
- self._test = test
- self.bvi = bvi
- self.uu_fwd = uu_fwd
- self.bm_flood = bm_flood
- self.bd = bd
- self.rd = rd
-
- e = VppEnum.vl_api_gbp_bridge_domain_flags_t
-
- self.flags = e.GBP_BD_API_FLAG_NONE
- if not learn:
- self.flags |= e.GBP_BD_API_FLAG_DO_NOT_LEARN
- if uu_drop:
- self.flags |= e.GBP_BD_API_FLAG_UU_FWD_DROP
- if bm_drop:
- self.flags |= e.GBP_BD_API_FLAG_MCAST_DROP
- if ucast_arp:
- self.flags |= e.GBP_BD_API_FLAG_UCAST_ARP
-
- def encode(self) -> dict:
- return {
- "flags": self.flags,
- "bvi_sw_if_index": self.bvi.sw_if_index,
- "uu_fwd_sw_if_index": self.uu_fwd.sw_if_index
- if self.uu_fwd else INDEX_INVALID,
- "bm_flood_sw_if_index": self.bm_flood.sw_if_index
- if self.bm_flood else INDEX_INVALID,
- "bd_id": self.bd.bd_id,
- "rd_id": self.rd.rd_id,
- }
-
- def add_vpp_config(self):
- self._test.vapi.gbp_bridge_domain_add(
- bd=self.encode(),
- )
- self._test.registry.register(self, self._test.logger)
-
- def remove_vpp_config(self):
- self._test.vapi.gbp_bridge_domain_del(bd_id=self.bd.bd_id)
-
- def object_id(self) -> str:
- return "gbp-bridge-domain:[%d]" % (self.bd.bd_id)
-
- def query_vpp_config(self) -> bool:
- bds = self._test.vapi.gbp_bridge_domain_dump()
- for bd in bds:
- if bd.bd.bd_id == self.bd.bd_id:
- return True
- return False
-
-
-class VppGbpRouteDomain(VppObject):
- """
- GBP Route Domain
- """
-
- def __init__(self, test, rd_id, scope, t4, t6, ip4_uu=None, ip6_uu=None):
- self._test = test
- self.rd_id = rd_id
- self.scope = scope
- self.t4 = t4
- self.t6 = t6
- self.ip4_uu = ip4_uu
- self.ip6_uu = ip6_uu
-
- def encode(self) -> dict:
- return {
- "rd_id": self.rd_id,
- "scope": self.scope,
- "ip4_table_id": self.t4.table_id,
- "ip6_table_id": self.t6.table_id,
- "ip4_uu_sw_if_index": self.ip4_uu.sw_if_index
- if self.ip4_uu else INDEX_INVALID,
- "ip6_uu_sw_if_index": self.ip6_uu.sw_if_index
- if self.ip6_uu else INDEX_INVALID,
-
- }
-
- def add_vpp_config(self):
- self._test.vapi.gbp_route_domain_add(
- rd=self.encode(),
- )
- self._test.registry.register(self, self._test.logger)
-
- def remove_vpp_config(self):
- self._test.vapi.gbp_route_domain_del(rd_id=self.rd_id)
-
- def object_id(self):
- return "gbp-route-domain:[%d]" % (self.rd_id)
-
- def query_vpp_config(self):
- rds = self._test.vapi.gbp_route_domain_dump()
- for rd in rds:
- if rd.rd.rd_id == self.rd_id:
- return True
- return False
-
-
-class VppGbpContractNextHop:
- def __init__(self, mac, bd, ip, rd):
- self.mac = mac
- self.ip = ip
- self.bd = bd
- self.rd = rd
-
- def encode(self) -> dict:
- return {
- "ip": self.ip,
- "mac": self.mac.packed,
- "bd_id": self.bd.bd.bd_id,
- "rd_id": self.rd.rd_id,
- }
-
-
-class VppGbpContractRule:
- def __init__(self, action, hash_mode, nhs=None):
- self.action = action
- self.hash_mode = hash_mode
- self.nhs = [] if nhs is None else nhs
-
- def encode(self) -> dict:
- nhs = []
- for nh in self.nhs:
- nhs.append(nh.encode())
- while len(nhs) < 8:
- nhs.append({})
- return {'action': self.action,
- 'nh_set': {
- 'hash_mode': self.hash_mode,
- 'n_nhs': len(self.nhs),
- 'nhs': nhs}}
-
- def __repr__(self):
- return '<VppGbpContractRule action=%s, hash_mode=%s>' % (
- self.action, self.hash_mode)
-
-
-class VppGbpContract(VppObject):
- """
- GBP Contract
- """
-
- def __init__(self, test, scope, sclass, dclass, acl_index,
- rules: list, allowed_ethertypes: list):
- self._test = test
- self.scope = scope
- self.acl_index = acl_index
- self.sclass = sclass
- self.dclass = dclass
- self.rules = rules
- self.allowed_ethertypes = allowed_ethertypes
- while (len(self.allowed_ethertypes) < 16):
- self.allowed_ethertypes.append(0)
-
- def encode(self) -> dict:
- rules = []
- for r in self.rules:
- rules.append(r.encode())
- return {
- 'acl_index': self.acl_index,
- 'scope': self.scope,
- 'sclass': self.sclass,
- 'dclass': self.dclass,
- 'n_rules': len(rules),
- 'rules': rules,
- 'n_ether_types': len(self.allowed_ethertypes),
- 'allowed_ethertypes': self.allowed_ethertypes,
- }
-
- def add_vpp_config(self):
- r = self._test.vapi.gbp_contract_add_del(
- is_add=1,
- contract=self.encode()
- )
-
- self.stats_index = r.stats_index
- self._test.registry.register(self, self._test.logger)
-
- def remove_vpp_config(self):
- self._test.vapi.gbp_contract_add_del(
- is_add=0,
- contract=self.encode(),
- )
-
- def object_id(self):
- return "gbp-contract:[%d:%d:%d:%d]" % (self.scope,
- self.sclass,
- self.dclass,
- self.acl_index)
-
- def query_vpp_config(self):
- cs = self._test.vapi.gbp_contract_dump()
- for c in cs:
- if c.contract.scope == self.scope \
- and c.contract.sclass == self.sclass \
- and c.contract.dclass == self.dclass:
- return True
- return False
-
- def get_drop_stats(self):
- c = self._test.statistics.get_counter("/net/gbp/contract/drop")
- return c[0][self.stats_index]
-
- def get_permit_stats(self):
- c = self._test.statistics.get_counter("/net/gbp/contract/permit")
- return c[0][self.stats_index]
-
-
-class VppGbpVxlanTunnel(VppInterface):
- """
- GBP VXLAN tunnel
- """
-
- def __init__(self, test, vni, bd_rd_id, mode, src):
- super(VppGbpVxlanTunnel, self).__init__(test)
- self._test = test
- self.vni = vni
- self.bd_rd_id = bd_rd_id
- self.mode = mode
- self.src = src
-
- def encode(self) -> dict:
- return {
- "vni": self.vni,
- "mode": self.mode,
- "bd_rd_id": self.bd_rd_id,
- "src": self.src,
- }
-
- def add_vpp_config(self):
- r = self._test.vapi.gbp_vxlan_tunnel_add(
- tunnel=self.encode(),
- )
- self.set_sw_if_index(r.sw_if_index)
- self._test.registry.register(self, self._test.logger)
-
- def remove_vpp_config(self):
- self._test.vapi.gbp_vxlan_tunnel_del(vni=self.vni)
-
- def object_id(self):
- return "gbp-vxlan:%d" % (self.sw_if_index)
-
- def query_vpp_config(self):
- return find_gbp_vxlan(self._test, self.vni)
-
-
-@tag_fixme_vpp_workers
-class TestGBP(VppTestCase):
- """ GBP Test Case """
-
- @property
- def nat_config_flags(self):
- return VppEnum.vl_api_nat_config_flags_t
-
- @property
- def nat44_config_flags(self):
- return VppEnum.vl_api_nat44_config_flags_t
-
- @classmethod
- def setUpClass(cls):
- super(TestGBP, cls).setUpClass()
-
- @classmethod
- def tearDownClass(cls):
- super(TestGBP, cls).tearDownClass()
-
- def setUp(self):
- super(TestGBP, self).setUp()
-
- self.create_pg_interfaces(range(9))
- self.create_loopback_interfaces(8)
-
- self.router_mac = MACAddress("00:11:22:33:44:55")
-
- for i in self.pg_interfaces:
- i.admin_up()
- for i in self.lo_interfaces:
- i.admin_up()
-
- self.vlan_100 = VppDot1QSubint(self, self.pg0, 100)
- self.vlan_100.admin_up()
- self.vlan_101 = VppDot1QSubint(self, self.pg0, 101)
- self.vlan_101.admin_up()
- self.vlan_102 = VppDot1QSubint(self, self.pg0, 102)
- self.vlan_102.admin_up()
-
- def tearDown(self):
- for i in self.pg_interfaces:
- i.admin_down()
- super(TestGBP, self).tearDown()
- for i in self.lo_interfaces:
- i.remove_vpp_config()
- self.lo_interfaces = []
- self.vlan_102.remove_vpp_config()
- self.vlan_101.remove_vpp_config()
- self.vlan_100.remove_vpp_config()
-
- def send_and_expect_bridged(self, src, tx, dst):
- rx = self.send_and_expect(src, tx, dst)
-
- for r in rx:
- self.assertEqual(r[Ether].src, tx[0][Ether].src)
- self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
- self.assertEqual(r[IP].src, tx[0][IP].src)
- self.assertEqual(r[IP].dst, tx[0][IP].dst)
- return rx
-
- def send_and_expect_bridged6(self, src, tx, dst):
- rx = self.send_and_expect(src, tx, dst)
-
- for r in rx:
- self.assertEqual(r[Ether].src, tx[0][Ether].src)
- self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
- self.assertEqual(r[IPv6].src, tx[0][IPv6].src)
- self.assertEqual(r[IPv6].dst, tx[0][IPv6].dst)
- return rx
-
- def send_and_expect_routed(self, src, tx, dst, src_mac):
- rx = self.send_and_expect(src, tx, dst)
-
- for r in rx:
- self.assertEqual(r[Ether].src, src_mac)
- self.assertEqual(r[Ether].dst, dst.remote_mac)
- self.assertEqual(r[IP].src, tx[0][IP].src)
- self.assertEqual(r[IP].dst, tx[0][IP].dst)
- return rx
-
- def send_and_expect_routed6(self, src, tx, dst, src_mac):
- rx = self.send_and_expect(src, tx, dst)
-
- for r in rx:
- self.assertEqual(r[Ether].src, src_mac)
- self.assertEqual(r[Ether].dst, dst.remote_mac)
- self.assertEqual(r[IPv6].src, tx[0][IPv6].src)
- self.assertEqual(r[IPv6].dst, tx[0][IPv6].dst)
- return rx
-
- def send_and_expect_natted(self, src, tx, dst, src_ip):
- rx = self.send_and_expect(src, tx, dst)
-
- for r in rx:
- self.assertEqual(r[Ether].src, tx[0][Ether].src)
- self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
- self.assertEqual(r[IP].src, src_ip)
- self.assertEqual(r[IP].dst, tx[0][IP].dst)
- return rx
-
- def send_and_expect_natted6(self, src, tx, dst, src_ip):
- rx = self.send_and_expect(src, tx, dst)
-
- for r in rx:
- self.assertEqual(r[Ether].src, tx[0][Ether].src)
- self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
- self.assertEqual(r[IPv6].src, src_ip)
- self.assertEqual(r[IPv6].dst, tx[0][IPv6].dst)
- return rx
-
- def send_and_expect_unnatted(self, src, tx, dst, dst_ip):
- rx = self.send_and_expect(src, tx, dst)
-
- for r in rx:
- self.assertEqual(r[Ether].src, tx[0][Ether].src)
- self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
- self.assertEqual(r[IP].dst, dst_ip)
- self.assertEqual(r[IP].src, tx[0][IP].src)
- return rx
-
- def send_and_expect_unnatted6(self, src, tx, dst, dst_ip):
- rx = self.send_and_expect(src, tx, dst)
-
- for r in rx:
- self.assertEqual(r[Ether].src, tx[0][Ether].src)
- self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
- self.assertEqual(r[IPv6].dst, dst_ip)
- self.assertEqual(r[IPv6].src, tx[0][IPv6].src)
- return rx
-
- def send_and_expect_double_natted(self, src, tx, dst, src_ip, dst_ip):
- rx = self.send_and_expect(src, tx, dst)
-
- for r in rx:
- self.assertEqual(r[Ether].src, str(self.router_mac))
- self.assertEqual(r[Ether].dst, dst.remote_mac)
- self.assertEqual(r[IP].dst, dst_ip)
- self.assertEqual(r[IP].src, src_ip)
- return rx
-
- def send_and_expect_double_natted6(self, src, tx, dst, src_ip, dst_ip):
- rx = self.send_and_expect(src, tx, dst)
-
- for r in rx:
- self.assertEqual(r[Ether].src, str(self.router_mac))
- self.assertEqual(r[Ether].dst, dst.remote_mac)
- self.assertEqual(r[IPv6].dst, dst_ip)
- self.assertEqual(r[IPv6].src, src_ip)
- return rx
-
- def send_and_expect_no_arp(self, src, tx, dst):
- self.pg_send(src, tx)
- dst.get_capture(0, timeout=1)
- dst.assert_nothing_captured(remark="")
-
- def send_and_expect_arp(self, src, tx, dst):
- rx = self.send_and_expect(src, tx, dst)
-
- for r in rx:
- self.assertEqual(r[Ether].src, tx[0][Ether].src)
- self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
- self.assertEqual(r[ARP].psrc, tx[0][ARP].psrc)
- self.assertEqual(r[ARP].pdst, tx[0][ARP].pdst)
- self.assertEqual(r[ARP].hwsrc, tx[0][ARP].hwsrc)
- self.assertEqual(r[ARP].hwdst, tx[0][ARP].hwdst)
- return rx
-
- def test_gbp(self):
- """ Group Based Policy """
-
- ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
-
- #
- # Route Domains
- #
- gt4 = VppIpTable(self, 0)
- gt4.add_vpp_config()
- gt6 = VppIpTable(self, 0, is_ip6=True)
- gt6.add_vpp_config()
- nt4 = VppIpTable(self, 20)
- nt4.add_vpp_config()
- nt6 = VppIpTable(self, 20, is_ip6=True)
- nt6.add_vpp_config()
-
- rd0 = VppGbpRouteDomain(self, 0, 400, gt4, gt6, None, None)
- rd20 = VppGbpRouteDomain(self, 20, 420, nt4, nt6, None, None)
-
- rd0.add_vpp_config()
- rd20.add_vpp_config()
-
- #
- # Bridge Domains
- #
- bd1 = VppBridgeDomain(self, 1)
- bd2 = VppBridgeDomain(self, 2)
- bd20 = VppBridgeDomain(self, 20)
-
- bd1.add_vpp_config()
- bd2.add_vpp_config()
- bd20.add_vpp_config()
-
- gbd1 = VppGbpBridgeDomain(self, bd1, rd0, self.loop0)
- gbd2 = VppGbpBridgeDomain(self, bd2, rd0, self.loop1)
- gbd20 = VppGbpBridgeDomain(self, bd20, rd20, self.loop2)
-
- gbd1.add_vpp_config()
- gbd2.add_vpp_config()
- gbd20.add_vpp_config()
-
- #
- # 3 EPGs, 2 of which share a BD.
- # 2 NAT EPGs, one for floating-IP subnets, the other for internet
- #
- epgs = [VppGbpEndpointGroup(self, 220, 1220, rd0, gbd1,
- self.pg4, self.loop0,
- "10.0.0.128", "2001:10::128"),
- VppGbpEndpointGroup(self, 221, 1221, rd0, gbd1,
- self.pg5, self.loop0,
- "10.0.1.128", "2001:10:1::128"),
- VppGbpEndpointGroup(self, 222, 1222, rd0, gbd2,
- self.pg6, self.loop1,
- "10.0.2.128", "2001:10:2::128"),
- VppGbpEndpointGroup(self, 333, 1333, rd20, gbd20,
- self.pg7, self.loop2,
- "11.0.0.128", "3001::128"),
- VppGbpEndpointGroup(self, 444, 1444, rd20, gbd20,
- self.pg8, self.loop2,
- "11.0.0.129", "3001::129")]
- recircs = [VppGbpRecirc(self, epgs[0], self.loop3),
- VppGbpRecirc(self, epgs[1], self.loop4),
- VppGbpRecirc(self, epgs[2], self.loop5),
- VppGbpRecirc(self, epgs[3], self.loop6, is_ext=True),
- VppGbpRecirc(self, epgs[4], self.loop7, is_ext=True)]
-
- epg_nat = epgs[3]
- recirc_nat = recircs[3]
-
- #
- # 4 end-points, 2 in the same subnet, 3 in the same BD
- #
- eps = [VppGbpEndpoint(self, self.pg0,
- epgs[0], recircs[0],
- "10.0.0.1", "11.0.0.1",
- "2001:10::1", "3001::1"),
- VppGbpEndpoint(self, self.pg1,
- epgs[0], recircs[0],
- "10.0.0.2", "11.0.0.2",
- "2001:10::2", "3001::2"),
- VppGbpEndpoint(self, self.pg2,
- epgs[1], recircs[1],
- "10.0.1.1", "11.0.0.3",
- "2001:10:1::1", "3001::3"),
- VppGbpEndpoint(self, self.pg3,
- epgs[2], recircs[2],
- "10.0.2.1", "11.0.0.4",
- "2001:10:2::1", "3001::4")]
-
- self.vapi.nat44_ed_plugin_enable_disable(enable=1)
- self.vapi.nat66_plugin_enable_disable(enable=1)
-
- #
- # 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]:
- b4 = VppIpInterfaceBind(self, epg.bvi,
- epg.rd.t4).add_vpp_config()
- b6 = VppIpInterfaceBind(self, epg.bvi,
- epg.rd.t6).add_vpp_config()
- epg.bvi.set_mac(self.router_mac)
-
- # The BVIs are NAT inside interfaces
- flags = self.nat_config_flags.NAT_IS_INSIDE
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=epg.bvi.sw_if_index,
- flags=flags, is_add=1)
- self.vapi.nat66_add_del_interface(
- sw_if_index=epg.bvi.sw_if_index,
- flags=flags, is_add=1)
-
- if_ip4 = VppIpInterfaceAddress(self, epg.bvi,
- epg.bvi_ip4, 32,
- bind=b4).add_vpp_config()
- if_ip6 = VppIpInterfaceAddress(self, epg.bvi,
- epg.bvi_ip6, 128,
- bind=b6).add_vpp_config()
-
- # EPG uplink interfaces in the RD
- VppIpInterfaceBind(self, epg.uplink, epg.rd.t4).add_vpp_config()
- VppIpInterfaceBind(self, epg.uplink, epg.rd.t6).add_vpp_config()
-
- # add the BD ARP termination entry for BVI IP
- epg.bd_arp_ip4 = VppBridgeDomainArpEntry(self, epg.bd.bd,
- str(self.router_mac),
- epg.bvi_ip4)
- epg.bd_arp_ip6 = VppBridgeDomainArpEntry(self, epg.bd.bd,
- str(self.router_mac),
- epg.bvi_ip6)
- epg.bd_arp_ip4.add_vpp_config()
- epg.bd_arp_ip6.add_vpp_config()
-
- # EPG in VPP
- epg.add_vpp_config()
-
- for recirc in recircs:
- # EPG's ingress recirculation interface maps to its RD
- VppIpInterfaceBind(self, recirc.recirc,
- recirc.epg.rd.t4).add_vpp_config()
- VppIpInterfaceBind(self, recirc.recirc,
- recirc.epg.rd.t6).add_vpp_config()
-
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=recirc.recirc.sw_if_index, is_add=1)
- self.vapi.nat66_add_del_interface(
- sw_if_index=recirc.recirc.sw_if_index, is_add=1)
-
- recirc.add_vpp_config()
-
- for recirc in recircs:
- self.assertTrue(find_bridge_domain_port(self,
- recirc.epg.bd.bd.bd_id,
- recirc.recirc.sw_if_index))
-
- 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.
- #
- for (ip, fip) in zip(ep.ips, ep.fips):
- # Add static mappings for each EP from the 10/8 to 11/8 network
- if ip_address(ip).version == 4:
- flags = self.nat_config_flags.NAT_IS_ADDR_ONLY
- self.vapi.nat44_add_del_static_mapping(
- is_add=1,
- local_ip_address=ip,
- external_ip_address=fip,
- external_sw_if_index=0xFFFFFFFF,
- vrf_id=0,
- flags=flags)
- else:
- self.vapi.nat66_add_del_static_mapping(
- local_ip_address=ip,
- external_ip_address=fip,
- vrf_id=0, is_add=1)
-
- # VPP EP create ...
- ep.add_vpp_config()
-
- self.logger.info(self.vapi.cli("sh gbp endpoint"))
-
- # ... results in a Gratuitous ARP/ND on the EPG's uplink
- rx = ep.epg.uplink.get_capture(len(ep.ips), timeout=0.2)
-
- for ii, ip in enumerate(ep.ips):
- p = rx[ii]
-
- if ip_address(ip).version == 6:
- self.assertTrue(p.haslayer(ICMPv6ND_NA))
- self.assertEqual(p[ICMPv6ND_NA].tgt, ip)
- else:
- self.assertTrue(p.haslayer(ARP))
- self.assertEqual(p[ARP].psrc, ip)
- self.assertEqual(p[ARP].pdst, ip)
-
- # add the BD ARP termination entry for floating IP
- for fip in ep.fips:
- ba = VppBridgeDomainArpEntry(self, epg_nat.bd.bd, ep.mac,
- fip)
- ba.add_vpp_config()
-
- # floating IPs route via EPG recirc
- r = VppIpRoute(
- self, fip, ip_address(fip).max_prefixlen,
- [VppRoutePath(fip,
- ep.recirc.recirc.sw_if_index,
- type=FibPathType.FIB_PATH_TYPE_DVR,
- proto=get_dpo_proto(fip))],
- table_id=20)
- r.add_vpp_config()
-
- # L2 FIB entries in the NAT EPG BD to bridge the packets from
- # the outside direct to the internal EPG
- lf = VppL2FibEntry(self, epg_nat.bd.bd, ep.mac,
- ep.recirc.recirc, bvi_mac=0)
- lf.add_vpp_config()
-
- #
- # ARP packets for unknown IP are sent to the EPG uplink
- #
- pkt_arp = (Ether(dst="ff:ff:ff:ff:ff:ff",
- src=self.pg0.remote_mac) /
- ARP(op="who-has",
- hwdst="ff:ff:ff:ff:ff:ff",
- hwsrc=self.pg0.remote_mac,
- pdst="10.0.0.88",
- psrc="10.0.0.99"))
-
- self.vapi.cli("clear trace")
- self.pg0.add_stream(pkt_arp)
-
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
-
- rxd = epgs[0].uplink.get_capture(1)
-
- #
- # ARP/ND packets get a response
- #
- pkt_arp = (Ether(dst="ff:ff:ff:ff:ff:ff",
- src=self.pg0.remote_mac) /
- ARP(op="who-has",
- hwdst="ff:ff:ff:ff:ff:ff",
- hwsrc=self.pg0.remote_mac,
- pdst=epgs[0].bvi_ip4,
- psrc=eps[0].ip4))
-
- self.send_and_expect(self.pg0, [pkt_arp], self.pg0)
-
- nsma = in6_getnsma(inet_pton(AF_INET6, eps[0].ip6))
- d = inet_ntop(AF_INET6, nsma)
- pkt_nd = (Ether(dst=in6_getnsmac(nsma),
- src=self.pg0.remote_mac) /
- IPv6(dst=d, src=eps[0].ip6) /
- ICMPv6ND_NS(tgt=epgs[0].bvi_ip6) /
- ICMPv6NDOptSrcLLAddr(lladdr=self.pg0.remote_mac))
- self.send_and_expect(self.pg0, [pkt_nd], self.pg0)
-
- #
- # broadcast packets are flooded
- #
- pkt_bcast = (Ether(dst="ff:ff:ff:ff:ff:ff",
- src=self.pg0.remote_mac) /
- IP(src=eps[0].ip4, dst="232.1.1.1") /
- UDP(sport=1234, dport=1234) /
- Raw(b'\xa5' * 100))
-
- self.vapi.cli("clear trace")
- self.pg0.add_stream(pkt_bcast)
-
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
-
- rxd = eps[1].itf.get_capture(1)
- self.assertEqual(rxd[0][Ether].dst, pkt_bcast[Ether].dst)
- rxd = epgs[0].uplink.get_capture(1)
- self.assertEqual(rxd[0][Ether].dst, pkt_bcast[Ether].dst)
-
- #
- # packets to non-local L3 destinations dropped
- #
- pkt_intra_epg_220_ip4 = (Ether(src=self.pg0.remote_mac,
- dst=str(self.router_mac)) /
- IP(src=eps[0].ip4,
- dst="10.0.0.99") /
- UDP(sport=1234, dport=1234) /
- Raw(b'\xa5' * 100))
- pkt_inter_epg_222_ip4 = (Ether(src=self.pg0.remote_mac,
- dst=str(self.router_mac)) /
- IP(src=eps[0].ip4,
- dst="10.0.1.99") /
- UDP(sport=1234, dport=1234) /
- Raw(b'\xa5' * 100))
-
- self.send_and_assert_no_replies(self.pg0,
- pkt_intra_epg_220_ip4 * NUM_PKTS)
-
- pkt_inter_epg_222_ip6 = (Ether(src=self.pg0.remote_mac,
- dst=str(self.router_mac)) /
- IPv6(src=eps[0].ip6,
- dst="2001:10::99") /
- UDP(sport=1234, dport=1234) /
- Raw(b'\xa5' * 100))
- self.send_and_assert_no_replies(self.pg0,
- pkt_inter_epg_222_ip6 * NUM_PKTS)
-
- #
- # Add the subnet routes
- #
- s41 = VppGbpSubnet(
- self, rd0, "10.0.0.0", 24,
- VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
- s42 = VppGbpSubnet(
- self, rd0, "10.0.1.0", 24,
- VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
- s43 = VppGbpSubnet(
- self, rd0, "10.0.2.0", 24,
- VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
- s61 = VppGbpSubnet(
- self, rd0, "2001:10::1", 64,
- VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
- s62 = VppGbpSubnet(
- self, rd0, "2001:10:1::1", 64,
- VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
- s63 = VppGbpSubnet(
- self, rd0, "2001:10:2::1", 64,
- VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
- s41.add_vpp_config()
- s42.add_vpp_config()
- s43.add_vpp_config()
- s61.add_vpp_config()
- s62.add_vpp_config()
- s63.add_vpp_config()
-
- self.send_and_expect_bridged(eps[0].itf,
- pkt_intra_epg_220_ip4 * NUM_PKTS,
- eps[0].epg.uplink)
- self.send_and_expect_bridged(eps[0].itf,
- pkt_inter_epg_222_ip4 * NUM_PKTS,
- eps[0].epg.uplink)
- self.send_and_expect_bridged6(eps[0].itf,
- pkt_inter_epg_222_ip6 * NUM_PKTS,
- eps[0].epg.uplink)
-
- self.logger.info(self.vapi.cli("sh ip fib 11.0.0.2"))
- self.logger.info(self.vapi.cli("sh gbp endpoint-group"))
- self.logger.info(self.vapi.cli("sh gbp endpoint"))
- self.logger.info(self.vapi.cli("sh gbp recirc"))
- self.logger.info(self.vapi.cli("sh int"))
- self.logger.info(self.vapi.cli("sh int addr"))
- self.logger.info(self.vapi.cli("sh int feat loop6"))
- self.logger.info(self.vapi.cli("sh vlib graph ip4-gbp-src-classify"))
- self.logger.info(self.vapi.cli("sh int feat loop3"))
- self.logger.info(self.vapi.cli("sh int feat pg0"))
-
- #
- # Packet destined to unknown unicast is sent on the epg uplink ...
- #
- pkt_intra_epg_220_to_uplink = (Ether(src=self.pg0.remote_mac,
- dst="00:00:00:33:44:55") /
- IP(src=eps[0].ip4,
- dst="10.0.0.99") /
- UDP(sport=1234, dport=1234) /
- Raw(b'\xa5' * 100))
-
- self.send_and_expect_bridged(eps[0].itf,
- pkt_intra_epg_220_to_uplink * NUM_PKTS,
- eps[0].epg.uplink)
- # ... and nowhere else
- self.pg1.get_capture(0, timeout=0.1)
- self.pg1.assert_nothing_captured(remark="Flood onto other VMS")
-
- pkt_intra_epg_221_to_uplink = (Ether(src=self.pg2.remote_mac,
- dst="00:00:00:33:44:66") /
- IP(src=eps[0].ip4,
- dst="10.0.0.99") /
- UDP(sport=1234, dport=1234) /
- Raw(b'\xa5' * 100))
-
- self.send_and_expect_bridged(eps[2].itf,
- pkt_intra_epg_221_to_uplink * NUM_PKTS,
- eps[2].epg.uplink)
-
- #
- # Packets from the uplink are forwarded in the absence of a contract
- #
- pkt_intra_epg_220_from_uplink = (Ether(src="00:00:00:33:44:55",
- dst=self.pg0.remote_mac) /
- IP(src=eps[0].ip4,
- dst="10.0.0.99") /
- UDP(sport=1234, dport=1234) /
- Raw(b'\xa5' * 100))
-
- self.send_and_expect_bridged(self.pg4,
- pkt_intra_epg_220_from_uplink * NUM_PKTS,
- self.pg0)
-
- #
- # in the absence of policy, endpoints in the same EPG
- # can communicate
- #
- pkt_intra_epg = (Ether(src=self.pg0.remote_mac,
- dst=self.pg1.remote_mac) /
- IP(src=eps[0].ip4,
- dst=eps[1].ip4) /
- UDP(sport=1234, dport=1234) /
- Raw(b'\xa5' * 100))
-
- self.send_and_expect_bridged(self.pg0,
- pkt_intra_epg * NUM_PKTS,
- self.pg1)
-
- #
- # in the absence of policy, endpoints in the different EPG
- # cannot communicate
- #
- pkt_inter_epg_220_to_221 = (Ether(src=self.pg0.remote_mac,
- dst=self.pg2.remote_mac) /
- IP(src=eps[0].ip4,
- dst=eps[2].ip4) /
- UDP(sport=1234, dport=1234) /
- Raw(b'\xa5' * 100))
- pkt_inter_epg_221_to_220 = (Ether(src=self.pg2.remote_mac,
- dst=self.pg0.remote_mac) /
- IP(src=eps[2].ip4,
- dst=eps[0].ip4) /
- UDP(sport=1234, dport=1234) /
- Raw(b'\xa5' * 100))
- pkt_inter_epg_220_to_222 = (Ether(src=self.pg0.remote_mac,
- dst=str(self.router_mac)) /
- IP(src=eps[0].ip4,
- dst=eps[3].ip4) /
- UDP(sport=1234, dport=1234) /
- Raw(b'\xa5' * 100))
-
- self.send_and_assert_no_replies(eps[0].itf,
- pkt_inter_epg_220_to_221 * NUM_PKTS)
- self.send_and_assert_no_replies(eps[0].itf,
- pkt_inter_epg_220_to_222 * NUM_PKTS)
-
- #
- # A uni-directional contract from EPG 220 -> 221
- #
- rule = AclRule(is_permit=1, proto=17)
- rule2 = AclRule(src_prefix=IPv6Network((0, 0)),
- dst_prefix=IPv6Network((0, 0)), is_permit=1, proto=17)
- acl = VppAcl(self, rules=[rule, rule2])
- acl.add_vpp_config()
-
- c1 = VppGbpContract(
- self, 400, epgs[0].sclass, epgs[1].sclass, acl.acl_index,
- [VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
- []),
- VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
- [])],
- [ETH_P_IP, ETH_P_IPV6])
- c1.add_vpp_config()
-
- self.send_and_expect_bridged(eps[0].itf,
- pkt_inter_epg_220_to_221 * NUM_PKTS,
- eps[2].itf)
- self.send_and_assert_no_replies(eps[0].itf,
- pkt_inter_epg_220_to_222 * NUM_PKTS)
-
- #
- # contract for the return direction
- #
- c2 = VppGbpContract(
- self, 400, epgs[1].sclass, epgs[0].sclass, acl.acl_index,
- [VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
- []),
- VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
- [])],
- [ETH_P_IP, ETH_P_IPV6])
- c2.add_vpp_config()
-
- self.send_and_expect_bridged(eps[0].itf,
- pkt_inter_epg_220_to_221 * NUM_PKTS,
- eps[2].itf)
- self.send_and_expect_bridged(eps[2].itf,
- pkt_inter_epg_221_to_220 * NUM_PKTS,
- eps[0].itf)
-
- ds = c2.get_drop_stats()
- self.assertEqual(ds['packets'], 0)
- ps = c2.get_permit_stats()
- self.assertEqual(ps['packets'], NUM_PKTS)
-
- #
- # the contract does not allow non-IP
- #
- pkt_non_ip_inter_epg_220_to_221 = (Ether(src=self.pg0.remote_mac,
- dst=self.pg2.remote_mac) /
- ARP())
- self.send_and_assert_no_replies(eps[0].itf,
- pkt_non_ip_inter_epg_220_to_221 * 17)
-
- #
- # check that inter group is still disabled for the groups
- # not in the contract.
- #
- self.send_and_assert_no_replies(eps[0].itf,
- pkt_inter_epg_220_to_222 * NUM_PKTS)
-
- #
- # A uni-directional contract from EPG 220 -> 222 'L3 routed'
- #
- c3 = VppGbpContract(
- self, 400, epgs[0].sclass, epgs[2].sclass, acl.acl_index,
- [VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
- []),
- VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
- [])],
- [ETH_P_IP, ETH_P_IPV6])
- c3.add_vpp_config()
-
- self.logger.info(self.vapi.cli("sh gbp contract"))
-
- self.send_and_expect_routed(eps[0].itf,
- pkt_inter_epg_220_to_222 * NUM_PKTS,
- eps[3].itf,
- str(self.router_mac))
- #
- # remove both contracts, traffic stops in both directions
- #
- c2.remove_vpp_config()
- c1.remove_vpp_config()
- c3.remove_vpp_config()
- acl.remove_vpp_config()
-
- self.send_and_assert_no_replies(eps[2].itf,
- pkt_inter_epg_221_to_220 * NUM_PKTS)
- self.send_and_assert_no_replies(eps[0].itf,
- pkt_inter_epg_220_to_221 * NUM_PKTS)
- self.send_and_expect_bridged(eps[0].itf,
- pkt_intra_epg * NUM_PKTS,
- eps[1].itf)
-
- #
- # EPs to the outside world
- #
-
- # in the EP's RD an external subnet via the NAT EPG's recirc
- se1 = VppGbpSubnet(
- self, rd0, "0.0.0.0", 0,
- VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
- sw_if_index=recirc_nat.recirc.sw_if_index,
- sclass=epg_nat.sclass)
- se2 = VppGbpSubnet(
- self, rd0, "11.0.0.0", 8,
- VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
- sw_if_index=recirc_nat.recirc.sw_if_index,
- sclass=epg_nat.sclass)
- se16 = VppGbpSubnet(
- self, rd0, "::", 0,
- VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
- sw_if_index=recirc_nat.recirc.sw_if_index,
- sclass=epg_nat.sclass)
- # in the NAT RD an external subnet via the NAT EPG's uplink
- se3 = VppGbpSubnet(
- self, rd20, "0.0.0.0", 0,
- VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
- sw_if_index=epg_nat.uplink.sw_if_index,
- sclass=epg_nat.sclass)
- se36 = VppGbpSubnet(
- self, rd20, "::", 0,
- VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
- sw_if_index=epg_nat.uplink.sw_if_index,
- sclass=epg_nat.sclass)
- se4 = VppGbpSubnet(
- self, rd20, "11.0.0.0", 8,
- VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
- sw_if_index=epg_nat.uplink.sw_if_index,
- sclass=epg_nat.sclass)
- se1.add_vpp_config()
- se2.add_vpp_config()
- se16.add_vpp_config()
- se3.add_vpp_config()
- se36.add_vpp_config()
- se4.add_vpp_config()
-
- self.logger.info(self.vapi.cli("sh ip fib 0.0.0.0/0"))
- self.logger.info(self.vapi.cli("sh ip fib 11.0.0.1"))
- self.logger.info(self.vapi.cli("sh ip6 fib ::/0"))
- self.logger.info(self.vapi.cli("sh ip6 fib %s" %
- eps[0].fip6))
-
- #
- # From an EP to an outside address: IN2OUT
- #
- pkt_inter_epg_220_to_global = (Ether(src=self.pg0.remote_mac,
- dst=str(self.router_mac)) /
- IP(src=eps[0].ip4,
- dst="1.1.1.1") /
- UDP(sport=1234, dport=1234) /
- Raw(b'\xa5' * 100))
-
- # no policy yet
- self.send_and_assert_no_replies(eps[0].itf,
- pkt_inter_epg_220_to_global * NUM_PKTS)
- rule = AclRule(is_permit=1, proto=17, ports=1234)
- rule2 = AclRule(is_permit=1, proto=17, ports=1234,
- src_prefix=IPv6Network((0, 0)),
- dst_prefix=IPv6Network((0, 0)))
- acl2 = VppAcl(self, rules=[rule, rule2])
- acl2.add_vpp_config()
-
- c4 = VppGbpContract(
- self, 400, epgs[0].sclass, epgs[3].sclass, acl2.acl_index,
- [VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
- []),
- VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
- [])],
- [ETH_P_IP, ETH_P_IPV6])
- c4.add_vpp_config()
-
- self.send_and_expect_natted(eps[0].itf,
- pkt_inter_epg_220_to_global * NUM_PKTS,
- self.pg7,
- eps[0].fip4)
-
- pkt_inter_epg_220_to_global = (Ether(src=self.pg0.remote_mac,
- dst=str(self.router_mac)) /
- IPv6(src=eps[0].ip6,
- dst="6001::1") /
- UDP(sport=1234, dport=1234) /
- Raw(b'\xa5' * 100))
-
- self.send_and_expect_natted6(self.pg0,
- pkt_inter_epg_220_to_global * NUM_PKTS,
- self.pg7,
- eps[0].fip6)
- #
- # From a global address to an EP: OUT2IN
- #
- pkt_inter_epg_220_from_global = (Ether(src=str(self.router_mac),
- dst=self.pg0.remote_mac) /
- IP(dst=eps[0].fip4,
- src="1.1.1.1") /
- UDP(sport=1234, dport=1234) /
- Raw(b'\xa5' * 100))
-
- self.send_and_assert_no_replies(
- self.pg7, pkt_inter_epg_220_from_global * NUM_PKTS)
-
- c5 = VppGbpContract(
- self, 400, epgs[3].sclass, epgs[0].sclass, acl2.acl_index,
- [VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
- []),
- VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
- [])],
- [ETH_P_IP, ETH_P_IPV6])
- c5.add_vpp_config()
-
- self.send_and_expect_unnatted(self.pg7,
- pkt_inter_epg_220_from_global * NUM_PKTS,
- eps[0].itf,
- eps[0].ip4)
-
- pkt_inter_epg_220_from_global = (Ether(src=str(self.router_mac),
- dst=self.pg0.remote_mac) /
- IPv6(dst=eps[0].fip6,
- src="6001::1") /
- UDP(sport=1234, dport=1234) /
- Raw(b'\xa5' * 100))
-
- self.send_and_expect_unnatted6(
- self.pg7,
- pkt_inter_epg_220_from_global * NUM_PKTS,
- eps[0].itf,
- eps[0].ip6)
-
- #
- # From a local VM to another local VM using resp. public addresses:
- # IN2OUT2IN
- #
- pkt_intra_epg_220_global = (Ether(src=self.pg0.remote_mac,
- dst=str(self.router_mac)) /
- IP(src=eps[0].ip4,
- dst=eps[1].fip4) /
- UDP(sport=1234, dport=1234) /
- Raw(b'\xa5' * 100))
-
- self.send_and_expect_double_natted(eps[0].itf,
- pkt_intra_epg_220_global * NUM_PKTS,
- eps[1].itf,
- eps[0].fip4,
- eps[1].ip4)
-
- pkt_intra_epg_220_global = (Ether(src=self.pg0.remote_mac,
- dst=str(self.router_mac)) /
- IPv6(src=eps[0].ip6,
- dst=eps[1].fip6) /
- UDP(sport=1234, dport=1234) /
- Raw(b'\xa5' * 100))
-
- self.send_and_expect_double_natted6(
- eps[0].itf,
- pkt_intra_epg_220_global * NUM_PKTS,
- eps[1].itf,
- eps[0].fip6,
- eps[1].ip6)
-
- #
- # cleanup
- #
- self.vapi.nat44_ed_plugin_enable_disable(enable=0)
- self.vapi.nat66_plugin_enable_disable(enable=0)
-
- def wait_for_ep_timeout(self, sw_if_index=None, ip=None, mac=None,
- tep=None, n_tries=100, s_time=1):
- # only learnt EP can timeout
- ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
- flags = ep_flags.GBP_API_ENDPOINT_FLAG_LEARNT
- while (n_tries):
- if not find_gbp_endpoint(self, sw_if_index, ip, mac, tep=tep,
- flags=flags):
- return True
- n_tries = n_tries - 1
- self.sleep(s_time)
- self.assertFalse(find_gbp_endpoint(self, sw_if_index, ip, mac, tep=tep,
- flags=flags))
- return False
-
- def test_gbp_learn_l2(self):
- """ GBP L2 Endpoint Learning """
-
- drop_no_contract = self.statistics.get_err_counter(
- '/err/gbp-policy-port/drop-no-contract')
- allow_intra_class = self.statistics.get_err_counter(
- '/err/gbp-policy-port/allow-intra-sclass')
-
- ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
- learnt = [{'mac': '00:00:11:11:11:01',
- 'ip': '10.0.0.1',
- 'ip6': '2001:10::2'},
- {'mac': '00:00:11:11:11:02',
- 'ip': '10.0.0.2',
- 'ip6': '2001:10::3'}]
-
- #
- # IP tables
- #
- gt4 = VppIpTable(self, 1)
- gt4.add_vpp_config()
- gt6 = VppIpTable(self, 1, is_ip6=True)
- gt6.add_vpp_config()
-
- rd1 = VppGbpRouteDomain(self, 1, 401, gt4, gt6)
- rd1.add_vpp_config()
-
- #
- # Pg2 hosts the vxlan tunnel, hosts on pg2 to act as TEPs
- # Pg3 hosts the IP4 UU-flood VXLAN tunnel
- # Pg4 hosts the IP6 UU-flood VXLAN tunnel
- #
- self.pg2.config_ip4()
- self.pg2.resolve_arp()
- self.pg2.generate_remote_hosts(4)
- self.pg2.configure_ipv4_neighbors()
- self.pg3.config_ip4()
- self.pg3.resolve_arp()
- self.pg4.config_ip4()
- self.pg4.resolve_arp()
-
- #
- # Add a mcast destination VXLAN-GBP tunnel for B&M traffic
- #
- tun_bm = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
- "239.1.1.1", 88,
- mcast_itf=self.pg4)
- tun_bm.add_vpp_config()
-
- #
- # a GBP bridge domain with a BVI and a UU-flood interface
- #
- bd1 = VppBridgeDomain(self, 1)
- bd1.add_vpp_config()
- gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0,
- self.pg3, tun_bm)
- gbd1.add_vpp_config()
-
- self.logger.info(self.vapi.cli("sh bridge 1 detail"))
- self.logger.info(self.vapi.cli("sh gbp bridge"))
-
- # ... and has a /32 applied
- ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
- ip_addr.add_vpp_config()
-
- #
- # The Endpoint-group in which we are learning endpoints
- #
- epg_220 = VppGbpEndpointGroup(self, 220, 112, rd1, gbd1,
- None, self.loop0,
- "10.0.0.128",
- "2001:10::128",
- VppGbpEndpointRetention(4))
- epg_220.add_vpp_config()
- epg_330 = VppGbpEndpointGroup(self, 330, 113, rd1, gbd1,
- None, self.loop1,
- "10.0.1.128",
- "2001:11::128",
- VppGbpEndpointRetention(4))
- epg_330.add_vpp_config()
-
- #
- # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
- # learning enabled
- #
- vx_tun_l2_1 = VppGbpVxlanTunnel(
- self, 99, bd1.bd_id,
- VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L2,
- self.pg2.local_ip4)
- vx_tun_l2_1.add_vpp_config()
-
- #
- # A static endpoint that the learnt endpoints are trying to
- # talk to
- #
- ep = VppGbpEndpoint(self, self.pg0,
- epg_220, None,
- "10.0.0.127", "11.0.0.127",
- "2001:10::1", "3001::1")
- ep.add_vpp_config()
-
- self.assertTrue(find_route(self, ep.ip4, 32, table_id=1))
-
- # a packet with an sclass from an unknown EPG
- p = (Ether(src=self.pg2.remote_mac,
- dst=self.pg2.local_mac) /
- IP(src=self.pg2.remote_hosts[0].ip4,
- dst=self.pg2.local_ip4) /
- UDP(sport=1234, dport=48879) /
- VXLAN(vni=99, gpid=88, flags=0x88) /
- Ether(src=learnt[0]["mac"], dst=ep.mac) /
- IP(src=learnt[0]["ip"], dst=ep.ip4) /
- UDP(sport=1234, dport=1234) /
- Raw(b'\xa5' * 100))
-
- self.send_and_assert_no_replies(self.pg2, p)
-
- self.logger.info(self.vapi.cli("sh error"))
- self.assert_error_counter_equal(
- '/err/gbp-policy-port/drop-no-contract',
- drop_no_contract + 1)
-
- #
- # we should not have learnt a new tunnel endpoint, since
- # the EPG was not learnt.
- #
- self.assertEqual(INDEX_INVALID,
- find_vxlan_gbp_tunnel(self,
- self.pg2.local_ip4,
- self.pg2.remote_hosts[0].ip4,
- 99))
-
- # ep is not learnt, because the EPG is unknown
- self.assertEqual(len(self.vapi.gbp_endpoint_dump()), 1)
-
- #
- # Learn new EPs from IP packets
- #
- for ii, l in enumerate(learnt):
- # a packet with an sclass from a known EPG
- # arriving on an unknown TEP
- p = (Ether(src=self.pg2.remote_mac,
- dst=self.pg2.local_mac) /
- IP(src=self.pg2.remote_hosts[1].ip4,
- dst=self.pg2.local_ip4) /
- UDP(sport=1234, dport=48879) /
- VXLAN(vni=99, gpid=112, flags=0x88) /
- Ether(src=l['mac'], dst=ep.mac) /
- IP(src=l['ip'], dst=ep.ip4) /
- UDP(sport=1234, dport=1234) /
- Raw(b'\xa5' * 100))
-
- rx = self.send_and_expect(self.pg2, [p], self.pg0)
-
- # the new TEP
- tep1_sw_if_index = find_vxlan_gbp_tunnel(
- self,
- self.pg2.local_ip4,
- self.pg2.remote_hosts[1].ip4,
- 99)
- self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
-
- #
- # the EP is learnt via the learnt TEP
- # both from its MAC and its IP
- #
- self.assertTrue(find_gbp_endpoint(self,
- vx_tun_l2_1.sw_if_index,
- mac=l['mac']))
- self.assertTrue(find_gbp_endpoint(self,
- vx_tun_l2_1.sw_if_index,
- ip=l['ip']))
-
- self.assert_error_counter_equal(
- '/err/gbp-policy-port/allow-intra-sclass',
- allow_intra_class + 2)
-
- self.logger.info(self.vapi.cli("show gbp endpoint"))
- self.logger.info(self.vapi.cli("show gbp vxlan"))
- self.logger.info(self.vapi.cli("show ip mfib"))
-
- #
- # If we sleep for the threshold time, the learnt endpoints should
- # age out
- #
- for l in learnt:
- self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
- mac=l['mac'])
-
- #
- # Learn new EPs from GARP packets received on the BD's mcast tunnel
- #
- for ii, l in enumerate(learnt):
- # add some junk in the reserved field of the vxlan-header
- # next to the VNI. we should accept since reserved bits are
- # ignored on rx.
- p = (Ether(src=self.pg2.remote_mac,
- dst=self.pg2.local_mac) /
- IP(src=self.pg2.remote_hosts[1].ip4,
- dst="239.1.1.1") /
- UDP(sport=1234, dport=48879) /
- VXLAN(vni=88, reserved2=0x80, gpid=112, flags=0x88) /
- Ether(src=l['mac'], dst="ff:ff:ff:ff:ff:ff") /
- ARP(op="who-has",
- psrc=l['ip'], pdst=l['ip'],
- hwsrc=l['mac'], hwdst="ff:ff:ff:ff:ff:ff"))
-
- rx = self.send_and_expect(self.pg4, [p], self.pg0)
-
- # the new TEP
- tep1_sw_if_index = find_vxlan_gbp_tunnel(
- self,
- self.pg2.local_ip4,
- self.pg2.remote_hosts[1].ip4,
- 99)
- self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
-
- #
- # the EP is learnt via the learnt TEP
- # both from its MAC and its IP
- #
- self.assertTrue(find_gbp_endpoint(self,
- vx_tun_l2_1.sw_if_index,
- mac=l['mac']))
- self.assertTrue(find_gbp_endpoint(self,
- vx_tun_l2_1.sw_if_index,
- ip=l['ip']))
-
- #
- # wait for the learnt endpoints to age out
- #
- for l in learnt:
- self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
- mac=l['mac'])
-
- #
- # Learn new EPs from L2 packets
- #
- for ii, l in enumerate(learnt):
- # a packet with an sclass from a known EPG
- # arriving on an unknown TEP
- p = (Ether(src=self.pg2.remote_mac,
- dst=self.pg2.local_mac) /
- IP(src=self.pg2.remote_hosts[1].ip4,
- dst=self.pg2.local_ip4) /
- UDP(sport=1234, dport=48879) /
- VXLAN(vni=99, gpid=112, flags=0x88) /
- Ether(src=l['mac'], dst=ep.mac) /
- Raw(b'\xa5' * 100))
-
- rx = self.send_and_expect(self.pg2, [p], self.pg0)
-
- # the new TEP
- tep1_sw_if_index = find_vxlan_gbp_tunnel(
- self,
- self.pg2.local_ip4,
- self.pg2.remote_hosts[1].ip4,
- 99)
- self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
-
- #
- # the EP is learnt via the learnt TEP
- # both from its MAC and its IP
- #
- self.assertTrue(find_gbp_endpoint(self,
- vx_tun_l2_1.sw_if_index,
- mac=l['mac']))
-
- self.logger.info(self.vapi.cli("show gbp endpoint"))
- self.logger.info(self.vapi.cli("show gbp vxlan"))
- self.logger.info(self.vapi.cli("show vxlan-gbp tunnel"))
-
- #
- # wait for the learnt endpoints to age out
- #
- for l in learnt:
- self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
- mac=l['mac'])
-
- #
- # repeat. the do not learn bit is set so the EPs are not learnt
- #
- for l in learnt:
- # a packet with an sclass from a known EPG
- p = (Ether(src=self.pg2.remote_mac,
- dst=self.pg2.local_mac) /
- IP(src=self.pg2.remote_hosts[1].ip4,
- dst=self.pg2.local_ip4) /
- UDP(sport=1234, dport=48879) /
- VXLAN(vni=99, gpid=112, flags=0x88, gpflags="D") /
- Ether(src=l['mac'], dst=ep.mac) /
- IP(src=l['ip'], dst=ep.ip4) /
- UDP(sport=1234, dport=1234) /
- Raw(b'\xa5' * 100))
-
- rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
-
- for l in learnt:
- self.assertFalse(find_gbp_endpoint(self,
- vx_tun_l2_1.sw_if_index,
- mac=l['mac']))
-
- #
- # repeat
- #
- for l in learnt:
- # a packet with an sclass from a known EPG
- # set a reserved bit in addition to the G and I
- # reserved bits should not be checked on rx.
- p = (Ether(src=self.pg2.remote_mac,
- dst=self.pg2.local_mac) /
- IP(src=self.pg2.remote_hosts[1].ip4,
- dst=self.pg2.local_ip4) /
- UDP(sport=1234, dport=48879) /
- VXLAN(vni=99, gpid=112, flags=0xc8) /
- Ether(src=l['mac'], dst=ep.mac) /
- IP(src=l['ip'], dst=ep.ip4) /
- UDP(sport=1234, dport=1234) /
- Raw(b'\xa5' * 100))
-
- rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
-
- self.assertTrue(find_gbp_endpoint(self,
- vx_tun_l2_1.sw_if_index,
- mac=l['mac']))
-
- #
- # Static EP replies to dynamics
- #
- self.logger.info(self.vapi.cli("sh l2fib bd_id 1"))
- for l in learnt:
- p = (Ether(src=ep.mac, dst=l['mac']) /
- IP(dst=l['ip'], src=ep.ip4) /
- UDP(sport=1234, dport=1234) /
- Raw(b'\xa5' * 100))
-
- rxs = self.send_and_expect(self.pg0, p * 17, self.pg2)
-
- for rx in rxs:
- self.assertEqual(rx[IP].src, self.pg2.local_ip4)
- self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
- self.assertEqual(rx[UDP].dport, 48879)
- # the UDP source port is a random value for hashing
- self.assertEqual(rx[VXLAN].gpid, 112)
- self.assertEqual(rx[VXLAN].vni, 99)
- self.assertTrue(rx[VXLAN].flags.G)
- self.assertTrue(rx[VXLAN].flags.Instance)
- self.assertTrue(rx[VXLAN].gpflags.A)
- self.assertFalse(rx[VXLAN].gpflags.D)
-
- for l in learnt:
- self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
- mac=l['mac'])
-
- #
- # repeat in the other EPG
- # there's no contract between 220 and 330, but the A-bit is set
- # so the packet is cleared for delivery
- #
- for l in learnt:
- # a packet with an sclass from a known EPG
- p = (Ether(src=self.pg2.remote_mac,
- dst=self.pg2.local_mac) /
- IP(src=self.pg2.remote_hosts[1].ip4,
- dst=self.pg2.local_ip4) /
- UDP(sport=1234, dport=48879) /
- VXLAN(vni=99, gpid=113, flags=0x88, gpflags='A') /
- Ether(src=l['mac'], dst=ep.mac) /
- IP(src=l['ip'], dst=ep.ip4) /
- UDP(sport=1234, dport=1234) /
- Raw(b'\xa5' * 100))
-
- rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
-
- self.assertTrue(find_gbp_endpoint(self,
- vx_tun_l2_1.sw_if_index,
- mac=l['mac']))
-
- #
- # static EP cannot reach the learnt EPs since there is no contract
- # only test 1 EP as the others could timeout
- #
- p = (Ether(src=ep.mac, dst=l['mac']) /
- IP(dst=learnt[0]['ip'], src=ep.ip4) /
- UDP(sport=1234, dport=1234) /
- Raw(b'\xa5' * 100))
-
- self.send_and_assert_no_replies(self.pg0, [p])
-
- #
- # refresh the entries after the check for no replies above
- #
- for l in learnt:
- # a packet with an sclass from a known EPG
- p = (Ether(src=self.pg2.remote_mac,
- dst=self.pg2.local_mac) /
- IP(src=self.pg2.remote_hosts[1].ip4,
- dst=self.pg2.local_ip4) /
- UDP(sport=1234, dport=48879) /
- VXLAN(vni=99, gpid=113, flags=0x88, gpflags='A') /
- Ether(src=l['mac'], dst=ep.mac) /
- IP(src=l['ip'], dst=ep.ip4) /
- UDP(sport=1234, dport=1234) /
- Raw(b'\xa5' * 100))
-
- rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
-
- self.assertTrue(find_gbp_endpoint(self,
- vx_tun_l2_1.sw_if_index,
- mac=l['mac']))
-
- #
- # Add the contract so they can talk
- #
- rule = AclRule(is_permit=1, proto=17)
- rule2 = AclRule(src_prefix=IPv6Network((0, 0)),
- dst_prefix=IPv6Network((0, 0)), is_permit=1, proto=17)
- acl = VppAcl(self, rules=[rule, rule2])
- acl.add_vpp_config()
-
- c1 = VppGbpContract(
- self, 401, epg_220.sclass, epg_330.sclass, acl.acl_index,
- [VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
- []),
- VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
- [])],
- [ETH_P_IP, ETH_P_IPV6])
- c1.add_vpp_config()
-
- for l in learnt:
- p = (Ether(src=ep.mac, dst=l['mac']) /
- IP(dst=l['ip'], src=ep.ip4) /
- UDP(sport=1234, dport=1234) /
- Raw(b'\xa5' * 100))
-
- self.send_and_expect(self.pg0, [p], self.pg2)
-
- #
- # send UU packets from the local EP
- #
- self.logger.info(self.vapi.cli("sh gbp bridge"))
- self.logger.info(self.vapi.cli("sh bridge-domain 1 detail"))
- p_uu = (Ether(src=ep.mac, dst="00:11:11:11:11:11") /
- IP(dst="10.0.0.133", src=ep.ip4) /
- UDP(sport=1234, dport=1234) /
- Raw(b'\xa5' * 100))
- rxs = self.send_and_expect(ep.itf, [p_uu], gbd1.uu_fwd)
-
- self.logger.info(self.vapi.cli("sh bridge 1 detail"))
-
- p_bm = (Ether(src=ep.mac, dst="ff:ff:ff:ff:ff:ff") /
- IP(dst="10.0.0.133", src=ep.ip4) /
- UDP(sport=1234, dport=1234) /
- Raw(b'\xa5' * 100))
- rxs = self.send_and_expect_only(ep.itf, [p_bm], tun_bm.mcast_itf)
-
- for rx in rxs:
- self.assertEqual(rx[IP].src, self.pg4.local_ip4)
- self.assertEqual(rx[IP].dst, "239.1.1.1")
- self.assertEqual(rx[UDP].dport, 48879)
- # the UDP source port is a random value for hashing
- self.assertEqual(rx[VXLAN].gpid, 112)
- self.assertEqual(rx[VXLAN].vni, 88)
- self.assertTrue(rx[VXLAN].flags.G)
- self.assertTrue(rx[VXLAN].flags.Instance)
- self.assertFalse(rx[VXLAN].gpflags.A)
- self.assertFalse(rx[VXLAN].gpflags.D)
-
- rule = AclRule(is_permit=1, proto=17)
- rule2 = AclRule(src_prefix=IPv6Network((0, 0)),
- dst_prefix=IPv6Network((0, 0)), is_permit=1, proto=17)
- acl = VppAcl(self, rules=[rule, rule2])
- acl.add_vpp_config()
-
- c2 = VppGbpContract(
- self, 401, epg_330.sclass, epg_220.sclass, acl.acl_index,
- [VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
- []),
- VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
- [])],
- [ETH_P_IP, ETH_P_IPV6])
- c2.add_vpp_config()
-
- for l in learnt:
- self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
- mac=l['mac'])
- #
- # Check v6 Endpoints learning
- #
- for l in learnt:
- # a packet with an sclass from a known EPG
- p = (Ether(src=self.pg2.remote_mac,
- dst=self.pg2.local_mac) /
- IP(src=self.pg2.remote_hosts[1].ip4,
- dst=self.pg2.local_ip4) /
- UDP(sport=1234, dport=48879) /
- VXLAN(vni=99, gpid=113, flags=0x88) /
- Ether(src=l['mac'], dst=ep.mac) /
- IPv6(src=l['ip6'], dst=ep.ip6) /
- UDP(sport=1234, dport=1234) /
- Raw(b'\xa5' * 100))
-
- rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
- rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
-
- self.assertTrue(find_gbp_endpoint(
- self,
- vx_tun_l2_1.sw_if_index,
- ip=l['ip6'],
- tep=[self.pg2.local_ip4,
- self.pg2.remote_hosts[1].ip4]))
-
- self.logger.info(self.vapi.cli("sh int"))
- self.logger.info(self.vapi.cli("sh vxlan-gbp tunnel"))
- self.logger.info(self.vapi.cli("sh gbp vxlan"))
- self.logger.info(self.vapi.cli("sh gbp endpoint"))
- self.logger.info(self.vapi.cli("sh gbp interface"))
-
- #
- # EP moves to a different TEP
- #
- for l in learnt:
- # a packet with an sclass from a known EPG
- p = (Ether(src=self.pg2.remote_mac,
- dst=self.pg2.local_mac) /
- IP(src=self.pg2.remote_hosts[2].ip4,
- dst=self.pg2.local_ip4) /
- UDP(sport=1234, dport=48879) /
- VXLAN(vni=99, gpid=113, flags=0x88) /
- Ether(src=l['mac'], dst=ep.mac) /
- IPv6(src=l['ip6'], dst=ep.ip6) /
- UDP(sport=1234, dport=1234) /
- Raw(b'\xa5' * 100))
-
- rx = self.send_and_expect(self.pg2, p * 1, self.pg0)
- rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
-
- self.assertTrue(find_gbp_endpoint(
- self,
- vx_tun_l2_1.sw_if_index,
- sclass=113,
- mac=l['mac'],
- tep=[self.pg2.local_ip4,
- self.pg2.remote_hosts[2].ip4]))
-
- #
- # v6 remote EP reachability
- #
- for l in learnt:
- p = (Ether(src=ep.mac, dst=l['mac']) /
- IPv6(dst=l['ip6'], src=ep.ip6) /
- UDP(sport=1234, dport=1234) /
- Raw(b'\xa5' * 100))
-
- rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
-
- for rx in rxs:
- self.assertEqual(rx[IP].src, self.pg2.local_ip4)
- self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[2].ip4)
- self.assertEqual(rx[UDP].dport, 48879)
- # the UDP source port is a random value for hashing
- self.assertEqual(rx[VXLAN].gpid, 112)
- self.assertEqual(rx[VXLAN].vni, 99)
- self.assertTrue(rx[VXLAN].flags.G)
- self.assertTrue(rx[VXLAN].flags.Instance)
- self.assertTrue(rx[VXLAN].gpflags.A)
- self.assertFalse(rx[VXLAN].gpflags.D)
- self.assertEqual(rx[IPv6].dst, l['ip6'])
-
- #
- # EP changes sclass
- #
- for l in learnt:
- # a packet with an sclass from a known EPG
- p = (Ether(src=self.pg2.remote_mac,
- dst=self.pg2.local_mac) /
- IP(src=self.pg2.remote_hosts[2].ip4,
- dst=self.pg2.local_ip4) /
- UDP(sport=1234, dport=48879) /
- VXLAN(vni=99, gpid=112, flags=0x88) /
- Ether(src=l['mac'], dst=ep.mac) /
- IPv6(src=l['ip6'], dst=ep.ip6) /
- UDP(sport=1234, dport=1234) /
- Raw(b'\xa5' * 100))
-
- rx = self.send_and_expect(self.pg2, p * 1, self.pg0)
- rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
-
- self.assertTrue(find_gbp_endpoint(
- self,
- vx_tun_l2_1.sw_if_index,
- mac=l['mac'],
- sclass=112,
- tep=[self.pg2.local_ip4,
- self.pg2.remote_hosts[2].ip4]))
-
- #
- # check reachability and contract intra-epg
- #
- allow_intra_class = self.statistics.get_err_counter(
- '/err/gbp-policy-mac/allow-intra-sclass')
-
- for l in learnt:
- p = (Ether(src=ep.mac, dst=l['mac']) /
- IPv6(dst=l['ip6'], src=ep.ip6) /
- UDP(sport=1234, dport=1234) /
- Raw(b'\xa5' * 100))
-
- rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
-
- for rx in rxs:
- self.assertEqual(rx[IP].src, self.pg2.local_ip4)
- self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[2].ip4)
- self.assertEqual(rx[UDP].dport, 48879)
- self.assertEqual(rx[VXLAN].gpid, 112)
- self.assertEqual(rx[VXLAN].vni, 99)
- self.assertTrue(rx[VXLAN].flags.G)
- self.assertTrue(rx[VXLAN].flags.Instance)
- self.assertTrue(rx[VXLAN].gpflags.A)
- self.assertFalse(rx[VXLAN].gpflags.D)
- self.assertEqual(rx[IPv6].dst, l['ip6'])
-
- allow_intra_class += NUM_PKTS
-
- self.assert_error_counter_equal(
- '/err/gbp-policy-mac/allow-intra-sclass',
- allow_intra_class)
-
- #
- # clean up
- #
- for l in learnt:
- self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
- mac=l['mac'])
- self.pg2.unconfig_ip4()
- self.pg3.unconfig_ip4()
- self.pg4.unconfig_ip4()
-
- def test_gbp_contract(self):
- """ GBP Contracts """
-
- #
- # Route Domains
- #
- gt4 = VppIpTable(self, 0)
- gt4.add_vpp_config()
- gt6 = VppIpTable(self, 0, is_ip6=True)
- gt6.add_vpp_config()
-
- rd0 = VppGbpRouteDomain(self, 0, 400, gt4, gt6, None, None)
-
- rd0.add_vpp_config()
-
- #
- # Bridge Domains
- #
- bd1 = VppBridgeDomain(self, 1, arp_term=0)
- bd2 = VppBridgeDomain(self, 2, arp_term=0)
-
- bd1.add_vpp_config()
- bd2.add_vpp_config()
-
- gbd1 = VppGbpBridgeDomain(self, bd1, rd0, self.loop0)
- gbd2 = VppGbpBridgeDomain(self, bd2, rd0, self.loop1)
-
- gbd1.add_vpp_config()
- gbd2.add_vpp_config()
-
- #
- # 3 EPGs, 2 of which share a BD.
- #
- epgs = [VppGbpEndpointGroup(self, 220, 1220, rd0, gbd1,
- None, self.loop0,
- "10.0.0.128", "2001:10::128"),
- VppGbpEndpointGroup(self, 221, 1221, rd0, gbd1,
- None, self.loop0,
- "10.0.1.128", "2001:10:1::128"),
- VppGbpEndpointGroup(self, 222, 1222, rd0, gbd2,
- None, self.loop1,
- "10.0.2.128", "2001:10:2::128")]
- #
- # 4 end-points, 2 in the same subnet, 3 in the same BD
- #
- eps = [VppGbpEndpoint(self, self.pg0,
- epgs[0], None,
- "10.0.0.1", "11.0.0.1",
- "2001:10::1", "3001::1"),
- VppGbpEndpoint(self, self.pg1,
- epgs[0], None,
- "10.0.0.2", "11.0.0.2",
- "2001:10::2", "3001::2"),
- VppGbpEndpoint(self, self.pg2,
- epgs[1], None,
- "10.0.1.1", "11.0.0.3",
- "2001:10:1::1", "3001::3"),
- VppGbpEndpoint(self, self.pg3,
- epgs[2], None,
- "10.0.2.1", "11.0.0.4",
- "2001:10:2::1", "3001::4")]
-
- #
- # Config related to each of the EPGs
- #
- for epg in epgs:
- # IP config on the BVI interfaces
- if epg != epgs[1]:
- b4 = VppIpInterfaceBind(self, epg.bvi,
- epg.rd.t4).add_vpp_config()
- b6 = VppIpInterfaceBind(self, epg.bvi,
- epg.rd.t6).add_vpp_config()
- epg.bvi.set_mac(self.router_mac)
-
- if_ip4 = VppIpInterfaceAddress(self, epg.bvi,
- epg.bvi_ip4, 32,
- bind=b4).add_vpp_config()
- if_ip6 = VppIpInterfaceAddress(self, epg.bvi,
- epg.bvi_ip6, 128,
- bind=b6).add_vpp_config()
-
- # add the BD ARP termination entry for BVI IP
- epg.bd_arp_ip4 = VppBridgeDomainArpEntry(self, epg.bd.bd,
- str(self.router_mac),
- epg.bvi_ip4)
- epg.bd_arp_ip4.add_vpp_config()
-
- # EPG in VPP
- epg.add_vpp_config()
-
- #
- # config ep
- #
- for ep in eps:
- ep.add_vpp_config()
-
- self.logger.info(self.vapi.cli("show gbp endpoint"))
- self.logger.info(self.vapi.cli("show interface"))
- self.logger.info(self.vapi.cli("show br"))
-
- #
- # Intra epg allowed without contract
- #
- pkt_intra_epg_220_to_220 = (Ether(src=self.pg0.remote_mac,
- dst=self.pg1.remote_mac) /
- IP(src=eps[0].ip4,
- dst=eps[1].ip4) /
- UDP(sport=1234, dport=1234) /
- Raw(b'\xa5' * 100))
-
- self.send_and_expect_bridged(self.pg0,
- pkt_intra_epg_220_to_220 * 65,
- self.pg1)
-
- pkt_intra_epg_220_to_220 = (Ether(src=self.pg0.remote_mac,
- dst=self.pg1.remote_mac) /
- IPv6(src=eps[0].ip6,
- dst=eps[1].ip6) /
- UDP(sport=1234, dport=1234) /
- Raw(b'\xa5' * 100))
-
- self.send_and_expect_bridged6(self.pg0,
- pkt_intra_epg_220_to_220 * 65,
- self.pg1)
-
- #
- # Inter epg denied without contract
- #
- pkt_inter_epg_220_to_221 = (Ether(src=self.pg0.remote_mac,
- dst=self.pg2.remote_mac) /
- IP(src=eps[0].ip4,
- dst=eps[2].ip4) /
- UDP(sport=1234, dport=1234) /
- Raw(b'\xa5' * 100))
-
- self.send_and_assert_no_replies(self.pg0, pkt_inter_epg_220_to_221)
-
- #
- # A uni-directional contract from EPG 220 -> 221
- #
- rule = AclRule(is_permit=1, proto=17)
- rule2 = AclRule(src_prefix=IPv6Network((0, 0)),
- dst_prefix=IPv6Network((0, 0)), is_permit=1, proto=17)
- rule3 = AclRule(is_permit=1, proto=1)
- acl = VppAcl(self, rules=[rule, rule2, rule3])
- acl.add_vpp_config()
-
- c1 = VppGbpContract(
- self, 400, epgs[0].sclass, epgs[1].sclass, acl.acl_index,
- [VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
- []),
- VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
- []),
- VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
- [])],
- [ETH_P_IP, ETH_P_IPV6])
- c1.add_vpp_config()
-
- self.send_and_expect_bridged(eps[0].itf,
- pkt_inter_epg_220_to_221 * 65,
- eps[2].itf)
-
- pkt_inter_epg_220_to_222 = (Ether(src=self.pg0.remote_mac,
- dst=str(self.router_mac)) /
- IP(src=eps[0].ip4,
- dst=eps[3].ip4) /
- UDP(sport=1234, dport=1234) /
- Raw(b'\xa5' * 100))
- self.send_and_assert_no_replies(eps[0].itf,
- pkt_inter_epg_220_to_222 * 65)
-
- #
- # ping router IP in different BD
- #
- pkt_router_ping_220_to_221 = (Ether(src=self.pg0.remote_mac,
- dst=str(self.router_mac)) /
- IP(src=eps[0].ip4,
- dst=epgs[1].bvi_ip4) /
- ICMP(type='echo-request'))
-
- self.send_and_expect(self.pg0, [pkt_router_ping_220_to_221], self.pg0)
-
- pkt_router_ping_220_to_221 = (Ether(src=self.pg0.remote_mac,
- dst=str(self.router_mac)) /
- IPv6(src=eps[0].ip6,
- dst=epgs[1].bvi_ip6) /
- ICMPv6EchoRequest())
-
- self.send_and_expect(self.pg0, [pkt_router_ping_220_to_221], self.pg0)
-
- #
- # contract for the return direction
- #
- c2 = VppGbpContract(
- self, 400, epgs[1].sclass, epgs[0].sclass, acl.acl_index,
- [VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
- []),
- VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
- [])],
- [ETH_P_IP, ETH_P_IPV6])
- c2.add_vpp_config()
-
- self.send_and_expect_bridged(eps[0].itf,
- pkt_inter_epg_220_to_221 * 65,
- eps[2].itf)
- pkt_inter_epg_221_to_220 = (Ether(src=self.pg2.remote_mac,
- dst=self.pg0.remote_mac) /
- IP(src=eps[2].ip4,
- dst=eps[0].ip4) /
- UDP(sport=1234, dport=1234) /
- Raw(b'\xa5' * 100))
- self.send_and_expect_bridged(eps[2].itf,
- pkt_inter_epg_221_to_220 * 65,
- eps[0].itf)
- pkt_inter_epg_221_to_220 = (Ether(src=self.pg2.remote_mac,
- dst=str(self.router_mac)) /
- IP(src=eps[2].ip4,
- dst=eps[0].ip4) /
- UDP(sport=1234, dport=1234) /
- Raw(b'\xa5' * 100))
- self.send_and_expect_routed(eps[2].itf,
- pkt_inter_epg_221_to_220 * 65,
- eps[0].itf,
- str(self.router_mac))
- pkt_inter_epg_221_to_220 = (Ether(src=self.pg2.remote_mac,
- dst=str(self.router_mac)) /
- IPv6(src=eps[2].ip6,
- dst=eps[0].ip6) /
- UDP(sport=1234, dport=1234) /
- Raw(b'\xa5' * 100))
- self.send_and_expect_routed6(eps[2].itf,
- pkt_inter_epg_221_to_220 * 65,
- eps[0].itf,
- str(self.router_mac))
-
- #
- # contract between 220 and 222 uni-direction
- #
- c3 = VppGbpContract(
- self, 400, epgs[0].sclass, epgs[2].sclass, acl.acl_index,
- [VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
- []),
- VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
- [])],
- [ETH_P_IP, ETH_P_IPV6])
- c3.add_vpp_config()
-
- self.send_and_expect(eps[0].itf,
- pkt_inter_epg_220_to_222 * 65,
- eps[3].itf)
-
- c3.remove_vpp_config()
- c1.remove_vpp_config()
- c2.remove_vpp_config()
- acl.remove_vpp_config()
-
- def test_gbp_bd_drop_flags(self):
- """ GBP BD drop flags """
-
- #
- # IP tables
- #
- gt4 = VppIpTable(self, 1)
- gt4.add_vpp_config()
- gt6 = VppIpTable(self, 1, is_ip6=True)
- gt6.add_vpp_config()
-
- rd1 = VppGbpRouteDomain(self, 1, 401, gt4, gt6)
- rd1.add_vpp_config()
-
- #
- # a GBP bridge domain with a BVI only
- #
- bd1 = VppBridgeDomain(self, 1)
- bd1.add_vpp_config()
-
- gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0,
- None, None,
- uu_drop=True, bm_drop=True)
- gbd1.add_vpp_config()
-
- self.logger.info(self.vapi.cli("sh bridge 1 detail"))
- self.logger.info(self.vapi.cli("sh gbp bridge"))
-
- # ... and has a /32 applied
- ip_addr = VppIpInterfaceAddress(self, gbd1.bvi,
- "10.0.0.128", 32).add_vpp_config()
-
- #
- # The Endpoint-group
- #
- epg_220 = VppGbpEndpointGroup(self, 220, 112, rd1, gbd1,
- None, self.loop0,
- "10.0.0.128",
- "2001:10::128",
- VppGbpEndpointRetention(3))
- epg_220.add_vpp_config()
-
- ep = VppGbpEndpoint(self, self.pg0,
- epg_220, None,
- "10.0.0.127", "11.0.0.127",
- "2001:10::1", "3001::1")
- ep.add_vpp_config()
-
- #
- # send UU/BM packet from the local EP with UU drop and BM drop enabled
- # in bd
- #
- self.logger.info(self.vapi.cli("sh bridge 1 detail"))
- self.logger.info(self.vapi.cli("sh gbp bridge"))
- p_uu = (Ether(src=ep.mac, dst="00:11:11:11:11:11") /
- IP(dst="10.0.0.133", src=ep.ip4) /
- UDP(sport=1234, dport=1234) /
- Raw(b'\xa5' * 100))
- self.send_and_assert_no_replies(ep.itf, [p_uu])
-
- p_bm = (Ether(src=ep.mac, dst="ff:ff:ff:ff:ff:ff") /
- IP(dst="10.0.0.133", src=ep.ip4) /
- UDP(sport=1234, dport=1234) /
- Raw(b'\xa5' * 100))
- self.send_and_assert_no_replies(ep.itf, [p_bm])
-
- self.pg3.unconfig_ip4()
-
- self.logger.info(self.vapi.cli("sh int"))
-
- def test_gbp_bd_arp_flags(self):
- """ GBP BD arp flags """
-
- #
- # IP tables
- #
- gt4 = VppIpTable(self, 1)
- gt4.add_vpp_config()
- gt6 = VppIpTable(self, 1, is_ip6=True)
- gt6.add_vpp_config()
-
- rd1 = VppGbpRouteDomain(self, 1, 401, gt4, gt6)
- rd1.add_vpp_config()
-
- #
- # Pg4 hosts the IP6 UU-flood VXLAN tunnel
- #
- self.pg4.config_ip4()
- self.pg4.resolve_arp()
-
- #
- # Add a mcast destination VXLAN-GBP tunnel for B&M traffic
- #
- tun_uu = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
- "239.1.1.1", 88,
- mcast_itf=self.pg4)
- tun_uu.add_vpp_config()
-
- #
- # a GBP bridge domain with a BVI and a UU-flood interface
- #
- bd1 = VppBridgeDomain(self, 1)
- bd1.add_vpp_config()
-
- gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0,
- tun_uu, None,
- ucast_arp=True)
- gbd1.add_vpp_config()
-
- # ... and has a /32 applied
- ip_addr = VppIpInterfaceAddress(self, gbd1.bvi,
- "10.0.0.128", 32).add_vpp_config()
-
- #
- # The Endpoint-group
- #
- epg_220 = VppGbpEndpointGroup(self, 220, 112, rd1, gbd1,
- None, self.loop0,
- "10.0.0.128",
- "2001:10::128",
- VppGbpEndpointRetention(2))
- epg_220.add_vpp_config()
-
- ep = VppGbpEndpoint(self, self.pg0,
- epg_220, None,
- "10.0.0.127", "11.0.0.127",
- "2001:10::1", "3001::1")
- ep.add_vpp_config()
-
- #
- # send ARP packet from the local EP expect it on the uu interface
- #
- self.logger.info(self.vapi.cli("sh bridge 1 detail"))
- self.logger.info(self.vapi.cli("sh gbp bridge"))
- p_arp = (Ether(src=ep.mac, dst="ff:ff:ff:ff:ff:ff") /
- ARP(op="who-has",
- psrc=ep.ip4, pdst="10.0.0.99",
- hwsrc=ep.mac,
- hwdst="ff:ff:ff:ff:ff:ff"))
- self.send_and_expect(ep.itf, [p_arp], self.pg4)
-
- self.pg4.unconfig_ip4()
-
- def test_gbp_learn_vlan_l2(self):
- """ GBP L2 Endpoint w/ VLANs"""
-
- ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
- learnt = [{'mac': '00:00:11:11:11:01',
- 'ip': '10.0.0.1',
- 'ip6': '2001:10::2'},
- {'mac': '00:00:11:11:11:02',
- 'ip': '10.0.0.2',
- 'ip6': '2001:10::3'}]
-
- #
- # IP tables
- #
- gt4 = VppIpTable(self, 1)
- gt4.add_vpp_config()
- gt6 = VppIpTable(self, 1, is_ip6=True)
- gt6.add_vpp_config()
-
- rd1 = VppGbpRouteDomain(self, 1, 401, gt4, gt6)
- rd1.add_vpp_config()
-
- #
- # Pg2 hosts the vxlan tunnel, hosts on pg2 to act as TEPs
- #
- self.pg2.config_ip4()
- self.pg2.resolve_arp()
- self.pg2.generate_remote_hosts(4)
- self.pg2.configure_ipv4_neighbors()
- self.pg3.config_ip4()
- self.pg3.resolve_arp()
-
- #
- # The EP will be on a vlan sub-interface
- #
- vlan_11 = VppDot1QSubint(self, self.pg0, 11)
- vlan_11.admin_up()
- self.vapi.l2_interface_vlan_tag_rewrite(
- sw_if_index=vlan_11.sw_if_index, vtr_op=L2_VTR_OP.L2_POP_1,
- push_dot1q=11)
-
- bd_uu_fwd = VppVxlanGbpTunnel(self, self.pg3.local_ip4,
- self.pg3.remote_ip4, 116)
- bd_uu_fwd.add_vpp_config()
-
- #
- # a GBP bridge domain with a BVI and a UU-flood interface
- # The BD is marked as do not learn, so no endpoints are ever
- # learnt in this BD.
- #
- bd1 = VppBridgeDomain(self, 1)
- bd1.add_vpp_config()
- gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0, bd_uu_fwd,
- learn=False)
- gbd1.add_vpp_config()
-
- self.logger.info(self.vapi.cli("sh bridge 1 detail"))
- self.logger.info(self.vapi.cli("sh gbp bridge"))
-
- # ... and has a /32 applied
- ip_addr = VppIpInterfaceAddress(self, gbd1.bvi,
- "10.0.0.128", 32).add_vpp_config()
-
- #
- # The Endpoint-group in which we are learning endpoints
- #
- epg_220 = VppGbpEndpointGroup(self, 220, 441, rd1, gbd1,
- None, self.loop0,
- "10.0.0.128",
- "2001:10::128",
- VppGbpEndpointRetention(4))
- epg_220.add_vpp_config()
-
- #
- # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
- # learning enabled
- #
- vx_tun_l2_1 = VppGbpVxlanTunnel(
- self, 99, bd1.bd_id,
- VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L2,
- self.pg2.local_ip4)
- vx_tun_l2_1.add_vpp_config()
-
- #
- # A static endpoint that the learnt endpoints are trying to
- # talk to
- #
- ep = VppGbpEndpoint(self, vlan_11,
- epg_220, None,
- "10.0.0.127", "11.0.0.127",
- "2001:10::1", "3001::1")
- ep.add_vpp_config()
-
- self.assertTrue(find_route(self, ep.ip4, 32, table_id=1))
-
- #
- # Send to the static EP
- #
- for ii, l in enumerate(learnt):
- # a packet with an sclass from a known EPG
- # arriving on an unknown TEP
- p = (Ether(src=self.pg2.remote_mac,
- dst=self.pg2.local_mac) /
- IP(src=self.pg2.remote_hosts[1].ip4,
- dst=self.pg2.local_ip4) /
- UDP(sport=1234, dport=48879) /
- VXLAN(vni=99, gpid=441, flags=0x88) /
- Ether(src=l['mac'], dst=ep.mac) /
- IP(src=l['ip'], dst=ep.ip4) /
- UDP(sport=1234, dport=1234) /
- Raw(b'\xa5' * 100))
-
- rxs = self.send_and_expect(self.pg2, [p], self.pg0)
-
- #
- # packet to EP has the EP's vlan tag
- #
- for rx in rxs:
- self.assertEqual(rx[Dot1Q].vlan, 11)
-
- #
- # the EP is not learnt since the BD setting prevents it
- # also no TEP too
- #
- self.assertFalse(find_gbp_endpoint(self,
- vx_tun_l2_1.sw_if_index,
- mac=l['mac']))
- self.assertEqual(INDEX_INVALID,
- find_vxlan_gbp_tunnel(
- self,
- self.pg2.local_ip4,
- self.pg2.remote_hosts[1].ip4,
- 99))
-
- self.assertEqual(len(self.vapi.gbp_endpoint_dump()), 1)
-
- #
- # static to remotes
- # we didn't learn the remotes so they are sent to the UU-fwd
- #
- for l in learnt:
- p = (Ether(src=ep.mac, dst=l['mac']) /
- Dot1Q(vlan=11) /
- IP(dst=l['ip'], src=ep.ip4) /
- UDP(sport=1234, dport=1234) /
- Raw(b'\xa5' * 100))
-
- rxs = self.send_and_expect(self.pg0, p * 17, self.pg3)
-
- for rx in rxs:
- self.assertEqual(rx[IP].src, self.pg3.local_ip4)
- self.assertEqual(rx[IP].dst, self.pg3.remote_ip4)
- self.assertEqual(rx[UDP].dport, 48879)
- # the UDP source port is a random value for hashing
- self.assertEqual(rx[VXLAN].gpid, 441)
- self.assertEqual(rx[VXLAN].vni, 116)
- self.assertTrue(rx[VXLAN].flags.G)
- self.assertTrue(rx[VXLAN].flags.Instance)
- self.assertFalse(rx[VXLAN].gpflags.A)
- self.assertFalse(rx[VXLAN].gpflags.D)
-
- self.pg2.unconfig_ip4()
- self.pg3.unconfig_ip4()
-
- def test_gbp_learn_l3(self):
- """ GBP L3 Endpoint Learning """
-
- self.vapi.cli("set logging class gbp level debug")
-
- ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
- routed_dst_mac = "00:0c:0c:0c:0c:0c"
- routed_src_mac = "00:22:bd:f8:19:ff"
-
- learnt = [{'mac': '00:00:11:11:11:02',
- 'ip': '10.0.1.2',
- 'ip6': '2001:10::2'},
- {'mac': '00:00:11:11:11:03',
- 'ip': '10.0.1.3',
- 'ip6': '2001:10::3'}]
-
- #
- # IP tables
- #
- t4 = VppIpTable(self, 1)
- t4.add_vpp_config()
- t6 = VppIpTable(self, 1, True)
- t6.add_vpp_config()
-
- tun_ip4_uu = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
- self.pg4.remote_ip4, 114)
- tun_ip6_uu = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
- self.pg4.remote_ip4, 116)
- tun_ip4_uu.add_vpp_config()
- tun_ip6_uu.add_vpp_config()
-
- rd1 = VppGbpRouteDomain(self, 2, 401, t4, t6, tun_ip4_uu, tun_ip6_uu)
- rd1.add_vpp_config()
-
- self.loop0.set_mac(self.router_mac)
-
- #
- # Bind the BVI to the RD
- #
- b4 = VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
- b6 = VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
-
- #
- # Pg2 hosts the vxlan tunnel
- # hosts on pg2 to act as TEPs
- # pg3 is BD uu-fwd
- # pg4 is RD uu-fwd
- #
- self.pg2.config_ip4()
- self.pg2.resolve_arp()
- self.pg2.generate_remote_hosts(4)
- self.pg2.configure_ipv4_neighbors()
- self.pg3.config_ip4()
- self.pg3.resolve_arp()
- self.pg4.config_ip4()
- self.pg4.resolve_arp()
-
- #
- # a GBP bridge domain with a BVI and a UU-flood interface
- #
- bd1 = VppBridgeDomain(self, 1)
- bd1.add_vpp_config()
- gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0, self.pg3)
- gbd1.add_vpp_config()
-
- self.logger.info(self.vapi.cli("sh bridge 1 detail"))
- self.logger.info(self.vapi.cli("sh gbp bridge"))
- self.logger.info(self.vapi.cli("sh gbp route"))
-
- # ... and has a /32 and /128 applied
- ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi,
- "10.0.0.128", 32,
- bind=b4).add_vpp_config()
- ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi,
- "2001:10::128", 128,
- bind=b6).add_vpp_config()
-
- #
- # The Endpoint-group in which we are learning endpoints
- #
- epg_220 = VppGbpEndpointGroup(self, 220, 441, rd1, gbd1,
- None, self.loop0,
- "10.0.0.128",
- "2001:10::128",
- VppGbpEndpointRetention(4))
- epg_220.add_vpp_config()
-
- #
- # The VXLAN GBP tunnel is in L3 mode with learning enabled
- #
- vx_tun_l3 = VppGbpVxlanTunnel(
- self, 101, rd1.rd_id,
- VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
- self.pg2.local_ip4)
- vx_tun_l3.add_vpp_config()
-
- #
- # A static endpoint that the learnt endpoints are trying to
- # talk to
- #
- ep = VppGbpEndpoint(self, self.pg0,
- epg_220, None,
- "10.0.0.127", "11.0.0.127",
- "2001:10::1", "3001::1")
- ep.add_vpp_config()
-
- #
- # learn some remote IPv4 EPs
- #
- for ii, l in enumerate(learnt):
- # a packet with an sclass from a known EPG
- # arriving on an unknown TEP
- p = (Ether(src=self.pg2.remote_mac,
- dst=self.pg2.local_mac) /
- IP(src=self.pg2.remote_hosts[1].ip4,
- dst=self.pg2.local_ip4) /
- UDP(sport=1234, dport=48879) /
- VXLAN(vni=101, gpid=441, flags=0x88) /
- Ether(src=l['mac'], dst="00:00:00:11:11:11") /
- IP(src=l['ip'], dst=ep.ip4) /
- UDP(sport=1234, dport=1234) /
- Raw(b'\xa5' * 100))
-
- rx = self.send_and_expect(self.pg2, [p], self.pg0)
-
- # the new TEP
- tep1_sw_if_index = find_vxlan_gbp_tunnel(
- self,
- self.pg2.local_ip4,
- self.pg2.remote_hosts[1].ip4,
- vx_tun_l3.vni)
- self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
-
- # endpoint learnt via the parent GBP-vxlan interface
- self.assertTrue(find_gbp_endpoint(self,
- vx_tun_l3._sw_if_index,
- ip=l['ip']))
-
- #
- # Static IPv4 EP replies to learnt
- #
- for l in learnt:
- p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
- IP(dst=l['ip'], src=ep.ip4) /
- UDP(sport=1234, dport=1234) /
- Raw(b'\xa5' * 100))
-
- rxs = self.send_and_expect(self.pg0, p * 1, self.pg2)
-
- for rx in rxs:
- self.assertEqual(rx[IP].src, self.pg2.local_ip4)
- self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
- self.assertEqual(rx[UDP].dport, 48879)
- # the UDP source port is a random value for hashing
- self.assertEqual(rx[VXLAN].gpid, 441)
- self.assertEqual(rx[VXLAN].vni, 101)
- self.assertTrue(rx[VXLAN].flags.G)
- self.assertTrue(rx[VXLAN].flags.Instance)
- self.assertTrue(rx[VXLAN].gpflags.A)
- self.assertFalse(rx[VXLAN].gpflags.D)
-
- inner = rx[VXLAN].payload
-
- self.assertEqual(inner[Ether].src, routed_src_mac)
- self.assertEqual(inner[Ether].dst, routed_dst_mac)
- self.assertEqual(inner[IP].src, ep.ip4)
- self.assertEqual(inner[IP].dst, l['ip'])
-
- for l in learnt:
- self.assertFalse(find_gbp_endpoint(self,
- tep1_sw_if_index,
- ip=l['ip']))
-
- #
- # learn some remote IPv6 EPs
- #
- for ii, l in enumerate(learnt):
- # a packet with an sclass from a known EPG
- # arriving on an unknown TEP
- p = (Ether(src=self.pg2.remote_mac,
- dst=self.pg2.local_mac) /
- IP(src=self.pg2.remote_hosts[1].ip4,
- dst=self.pg2.local_ip4) /
- UDP(sport=1234, dport=48879) /
- VXLAN(vni=101, gpid=441, flags=0x88) /
- Ether(src=l['mac'], dst="00:00:00:11:11:11") /
- IPv6(src=l['ip6'], dst=ep.ip6) /
- UDP(sport=1234, dport=1234) /
- Raw(b'\xa5' * 100))
-
- rx = self.send_and_expect(self.pg2, [p], self.pg0)
-
- # the new TEP
- tep1_sw_if_index = find_vxlan_gbp_tunnel(
- self,
- self.pg2.local_ip4,
- self.pg2.remote_hosts[1].ip4,
- vx_tun_l3.vni)
- self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
-
- self.logger.info(self.vapi.cli("show gbp bridge"))
- self.logger.info(self.vapi.cli("show vxlan-gbp tunnel"))
- self.logger.info(self.vapi.cli("show gbp vxlan"))
- self.logger.info(self.vapi.cli("show int addr"))
-
- # endpoint learnt via the TEP
- self.assertTrue(find_gbp_endpoint(self, ip=l['ip6']))
-
- self.logger.info(self.vapi.cli("show gbp endpoint"))
- self.logger.info(self.vapi.cli("show ip fib index 1 %s" % l['ip']))
-
- #
- # Static EP replies to learnt
- #
- for l in learnt:
- p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
- IPv6(dst=l['ip6'], src=ep.ip6) /
- UDP(sport=1234, dport=1234) /
- Raw(b'\xa5' * 100))
-
- rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
-
- for rx in rxs:
- self.assertEqual(rx[IP].src, self.pg2.local_ip4)
- self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
- self.assertEqual(rx[UDP].dport, 48879)
- # the UDP source port is a random value for hashing
- self.assertEqual(rx[VXLAN].gpid, 441)
- self.assertEqual(rx[VXLAN].vni, 101)
- self.assertTrue(rx[VXLAN].flags.G)
- self.assertTrue(rx[VXLAN].flags.Instance)
- self.assertTrue(rx[VXLAN].gpflags.A)
- self.assertFalse(rx[VXLAN].gpflags.D)
-
- inner = rx[VXLAN].payload
-
- self.assertEqual(inner[Ether].src, routed_src_mac)
- self.assertEqual(inner[Ether].dst, routed_dst_mac)
- self.assertEqual(inner[IPv6].src, ep.ip6)
- self.assertEqual(inner[IPv6].dst, l['ip6'])
-
- self.logger.info(self.vapi.cli("sh gbp endpoint"))
- for l in learnt:
- self.wait_for_ep_timeout(ip=l['ip'])
-
- #
- # Static sends to unknown EP with no route
- #
- p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
- IP(dst="10.0.0.99", src=ep.ip4) /
- UDP(sport=1234, dport=1234) /
- Raw(b'\xa5' * 100))
-
- self.send_and_assert_no_replies(self.pg0, [p])
-
- #
- # Add a route to static EP's v4 and v6 subnet
- #
- se_10_24 = VppGbpSubnet(
- self, rd1, "10.0.0.0", 24,
- VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT)
- se_10_24.add_vpp_config()
-
- #
- # static pings router
- #
- p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
- IP(dst=epg_220.bvi_ip4, src=ep.ip4) /
- UDP(sport=1234, dport=1234) /
- Raw(b'\xa5' * 100))
-
- self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg0)
-
- p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
- IPv6(dst=epg_220.bvi_ip6, src=ep.ip6) /
- UDP(sport=1234, dport=1234) /
- Raw(b'\xa5' * 100))
-
- self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg0)
-
- #
- # packets to address in the subnet are sent on the uu-fwd
- #
- p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
- IP(dst="10.0.0.99", src=ep.ip4) /
- UDP(sport=1234, dport=1234) /
- Raw(b'\xa5' * 100))
-
- rxs = self.send_and_expect(self.pg0, [p], self.pg4)
- for rx in rxs:
- self.assertEqual(rx[IP].src, self.pg4.local_ip4)
- self.assertEqual(rx[IP].dst, self.pg4.remote_ip4)
- self.assertEqual(rx[UDP].dport, 48879)
- # the UDP source port is a random value for hashing
- self.assertEqual(rx[VXLAN].gpid, 441)
- self.assertEqual(rx[VXLAN].vni, 114)
- self.assertTrue(rx[VXLAN].flags.G)
- self.assertTrue(rx[VXLAN].flags.Instance)
- # policy is not applied to packets sent to the uu-fwd interfaces
- self.assertFalse(rx[VXLAN].gpflags.A)
- self.assertFalse(rx[VXLAN].gpflags.D)
-
- #
- # learn some remote IPv4 EPs
- #
- for ii, l in enumerate(learnt):
- # a packet with an sclass from a known EPG
- # arriving on an unknown TEP
- p = (Ether(src=self.pg2.remote_mac,
- dst=self.pg2.local_mac) /
- IP(src=self.pg2.remote_hosts[2].ip4,
- dst=self.pg2.local_ip4) /
- UDP(sport=1234, dport=48879) /
- VXLAN(vni=101, gpid=441, flags=0x88) /
- Ether(src=l['mac'], dst="00:00:00:11:11:11") /
- IP(src=l['ip'], dst=ep.ip4) /
- UDP(sport=1234, dport=1234) /
- Raw(b'\xa5' * 100))
-
- rx = self.send_and_expect(self.pg2, [p], self.pg0)
-
- # the new TEP
- tep1_sw_if_index = find_vxlan_gbp_tunnel(
- self,
- self.pg2.local_ip4,
- self.pg2.remote_hosts[2].ip4,
- vx_tun_l3.vni)
- self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
-
- # endpoint learnt via the parent GBP-vxlan interface
- self.assertTrue(find_gbp_endpoint(self,
- vx_tun_l3._sw_if_index,
- ip=l['ip']))
-
- #
- # Add a remote endpoint from the API
- #
- rep_88 = VppGbpEndpoint(self, vx_tun_l3,
- epg_220, None,
- "10.0.0.88", "11.0.0.88",
- "2001:10::88", "3001::88",
- ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
- self.pg2.local_ip4,
- self.pg2.remote_hosts[2].ip4,
- mac=None)
- rep_88.add_vpp_config()
-
- #
- # Add a remote endpoint from the API that matches an existing one
- # this is a lower priority, hence the packet is sent to the DP leanrt
- # TEP
- #
- rep_2 = VppGbpEndpoint(self, vx_tun_l3,
- epg_220, None,
- learnt[0]['ip'], "11.0.0.101",
- learnt[0]['ip6'], "3001::101",
- ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
- self.pg2.local_ip4,
- self.pg2.remote_hosts[1].ip4,
- mac=None)
- rep_2.add_vpp_config()
-
- #
- # Add a route to the learned EP's v4 subnet
- # packets should be send on the v4/v6 uu=fwd interface resp.
- #
- se_10_1_24 = VppGbpSubnet(
- self, rd1, "10.0.1.0", 24,
- VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT)
- se_10_1_24.add_vpp_config()
-
- self.logger.info(self.vapi.cli("show gbp endpoint"))
-
- ips = ["10.0.0.88", learnt[0]['ip']]
- for ip in ips:
- p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
- IP(dst=ip, src=ep.ip4) /
- UDP(sport=1234, dport=1234) /
- Raw(b'\xa5' * 100))
-
- rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
-
- for rx in rxs:
- self.assertEqual(rx[IP].src, self.pg2.local_ip4)
- self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[2].ip4)
- self.assertEqual(rx[UDP].dport, 48879)
- # the UDP source port is a random value for hashing
- self.assertEqual(rx[VXLAN].gpid, 441)
- self.assertEqual(rx[VXLAN].vni, 101)
- self.assertTrue(rx[VXLAN].flags.G)
- self.assertTrue(rx[VXLAN].flags.Instance)
- self.assertTrue(rx[VXLAN].gpflags.A)
- self.assertFalse(rx[VXLAN].gpflags.D)
-
- inner = rx[VXLAN].payload
-
- self.assertEqual(inner[Ether].src, routed_src_mac)
- self.assertEqual(inner[Ether].dst, routed_dst_mac)
- self.assertEqual(inner[IP].src, ep.ip4)
- self.assertEqual(inner[IP].dst, ip)
-
- #
- # remove the API remote EPs, only API sourced is gone, the DP
- # learnt one remains
- #
- rep_88.remove_vpp_config()
- rep_2.remove_vpp_config()
-
- self.assertTrue(find_gbp_endpoint(self, ip=rep_2.ip4))
-
- p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
- IP(src=ep.ip4, dst=rep_2.ip4) /
- UDP(sport=1234, dport=1234) /
- Raw(b'\xa5' * 100))
- rxs = self.send_and_expect(self.pg0, [p], self.pg2)
-
- self.assertFalse(find_gbp_endpoint(self, ip=rep_88.ip4))
-
- p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
- IP(src=ep.ip4, dst=rep_88.ip4) /
- UDP(sport=1234, dport=1234) /
- Raw(b'\xa5' * 100))
- rxs = self.send_and_expect(self.pg0, [p], self.pg4)
-
- #
- # to appease the testcase we cannot have the registered EP still
- # present (because it's DP learnt) when the TC ends so wait until
- # it is removed
- #
- self.wait_for_ep_timeout(ip=rep_88.ip4)
- self.wait_for_ep_timeout(ip=rep_2.ip4)
-
- #
- # Same as above, learn a remote EP via CP and DP
- # this time remove the DP one first. expect the CP data to remain
- #
- rep_3 = VppGbpEndpoint(self, vx_tun_l3,
- epg_220, None,
- "10.0.1.4", "11.0.0.103",
- "2001::10:3", "3001::103",
- ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
- self.pg2.local_ip4,
- self.pg2.remote_hosts[1].ip4,
- mac=None)
- rep_3.add_vpp_config()
-
- p = (Ether(src=self.pg2.remote_mac,
- dst=self.pg2.local_mac) /
- IP(src=self.pg2.remote_hosts[2].ip4,
- dst=self.pg2.local_ip4) /
- UDP(sport=1234, dport=48879) /
- VXLAN(vni=101, gpid=441, flags=0x88) /
- Ether(src=l['mac'], dst="00:00:00:11:11:11") /
- IP(src="10.0.1.4", dst=ep.ip4) /
- UDP(sport=1234, dport=1234) /
- Raw(b'\xa5' * 100))
- rxs = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
-
- self.assertTrue(find_gbp_endpoint(self,
- vx_tun_l3._sw_if_index,
- ip=rep_3.ip4,
- tep=[self.pg2.local_ip4,
- self.pg2.remote_hosts[2].ip4]))
-
- p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
- IP(dst="10.0.1.4", src=ep.ip4) /
- UDP(sport=1234, dport=1234) /
- Raw(b'\xa5' * 100))
- rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
-
- # host 2 is the DP learned TEP
- for rx in rxs:
- self.assertEqual(rx[IP].src, self.pg2.local_ip4)
- self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[2].ip4)
-
- self.wait_for_ep_timeout(ip=rep_3.ip4,
- tep=[self.pg2.local_ip4,
- self.pg2.remote_hosts[2].ip4])
-
- rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
-
- # host 1 is the CP learned TEP
- for rx in rxs:
- self.assertEqual(rx[IP].src, self.pg2.local_ip4)
- self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
-
- #
- # shutdown with learnt endpoint present
- #
- p = (Ether(src=self.pg2.remote_mac,
- dst=self.pg2.local_mac) /
- IP(src=self.pg2.remote_hosts[1].ip4,
- dst=self.pg2.local_ip4) /
- UDP(sport=1234, dport=48879) /
- VXLAN(vni=101, gpid=441, flags=0x88) /
- Ether(src=l['mac'], dst="00:00:00:11:11:11") /
- IP(src=learnt[1]['ip'], dst=ep.ip4) /
- UDP(sport=1234, dport=1234) /
- Raw(b'\xa5' * 100))
-
- rx = self.send_and_expect(self.pg2, [p], self.pg0)
-
- # endpoint learnt via the parent GBP-vxlan interface
- self.assertTrue(find_gbp_endpoint(self,
- vx_tun_l3._sw_if_index,
- ip=l['ip']))
-
- #
- # TODO
- # remote endpoint becomes local
- #
- self.pg2.unconfig_ip4()
- self.pg3.unconfig_ip4()
- self.pg4.unconfig_ip4()
-
- def test_gbp_redirect(self):
- """ GBP Endpoint Redirect """
-
- self.vapi.cli("set logging class gbp level debug")
-
- ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
- routed_dst_mac = "00:0c:0c:0c:0c:0c"
- routed_src_mac = "00:22:bd:f8:19:ff"
-
- learnt = [{'mac': '00:00:11:11:11:02',
- 'ip': '10.0.1.2',
- 'ip6': '2001:10::2'},
- {'mac': '00:00:11:11:11:03',
- 'ip': '10.0.1.3',
- 'ip6': '2001:10::3'}]
-
- #
- # IP tables
- #
- t4 = VppIpTable(self, 1)
- t4.add_vpp_config()
- t6 = VppIpTable(self, 1, True)
- t6.add_vpp_config()
-
- rd1 = VppGbpRouteDomain(self, 2, 402, t4, t6)
- rd1.add_vpp_config()
-
- self.loop0.set_mac(self.router_mac)
-
- #
- # Bind the BVI to the RD
- #
- b_ip4 = VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
- b_ip6 = VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
-
- #
- # Pg7 hosts a BD's UU-fwd
- #
- self.pg7.config_ip4()
- self.pg7.resolve_arp()
-
- #
- # a GBP bridge domains for the EPs
- #
- bd1 = VppBridgeDomain(self, 1)
- bd1.add_vpp_config()
- gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0)
- gbd1.add_vpp_config()
-
- bd2 = VppBridgeDomain(self, 2)
- bd2.add_vpp_config()
- gbd2 = VppGbpBridgeDomain(self, bd2, rd1, self.loop1)
- gbd2.add_vpp_config()
-
- # ... and has a /32 and /128 applied
- ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi,
- "10.0.0.128", 32,
- bind=b_ip4).add_vpp_config()
- ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi,
- "2001:10::128", 128,
- bind=b_ip6).add_vpp_config()
- ip4_addr = VppIpInterfaceAddress(self, gbd2.bvi,
- "10.0.1.128", 32).add_vpp_config()
- ip6_addr = VppIpInterfaceAddress(self, gbd2.bvi,
- "2001:11::128", 128).add_vpp_config()
-
- #
- # The Endpoint-groups in which we are learning endpoints
- #
- epg_220 = VppGbpEndpointGroup(self, 220, 440, rd1, gbd1,
- None, gbd1.bvi,
- "10.0.0.128",
- "2001:10::128",
- VppGbpEndpointRetention(60))
- epg_220.add_vpp_config()
- epg_221 = VppGbpEndpointGroup(self, 221, 441, rd1, gbd2,
- None, gbd2.bvi,
- "10.0.1.128",
- "2001:11::128",
- VppGbpEndpointRetention(60))
- epg_221.add_vpp_config()
- epg_222 = VppGbpEndpointGroup(self, 222, 442, rd1, gbd1,
- None, gbd1.bvi,
- "10.0.2.128",
- "2001:12::128",
- VppGbpEndpointRetention(60))
- epg_222.add_vpp_config()
-
- #
- # a GBP bridge domains for the SEPs
- #
- bd_uu1 = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
- self.pg7.remote_ip4, 116)
- bd_uu1.add_vpp_config()
- bd_uu2 = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
- self.pg7.remote_ip4, 117)
- bd_uu2.add_vpp_config()
-
- bd3 = VppBridgeDomain(self, 3)
- bd3.add_vpp_config()
- gbd3 = VppGbpBridgeDomain(self, bd3, rd1, self.loop2,
- bd_uu1, learn=False)
- gbd3.add_vpp_config()
- bd4 = VppBridgeDomain(self, 4)
- bd4.add_vpp_config()
- gbd4 = VppGbpBridgeDomain(self, bd4, rd1, self.loop3,
- bd_uu2, learn=False)
- gbd4.add_vpp_config()
-
- #
- # EPGs in which the service endpoints exist
- #
- epg_320 = VppGbpEndpointGroup(self, 320, 550, rd1, gbd3,
- None, gbd1.bvi,
- "12.0.0.128",
- "4001:10::128",
- VppGbpEndpointRetention(60))
- epg_320.add_vpp_config()
- epg_321 = VppGbpEndpointGroup(self, 321, 551, rd1, gbd4,
- None, gbd2.bvi,
- "12.0.1.128",
- "4001:11::128",
- VppGbpEndpointRetention(60))
- epg_321.add_vpp_config()
-
- #
- # three local endpoints
- #
- ep1 = VppGbpEndpoint(self, self.pg0,
- epg_220, None,
- "10.0.0.1", "11.0.0.1",
- "2001:10::1", "3001:10::1")
- ep1.add_vpp_config()
- ep2 = VppGbpEndpoint(self, self.pg1,
- epg_221, None,
- "10.0.1.1", "11.0.1.1",
- "2001:11::1", "3001:11::1")
- ep2.add_vpp_config()
- ep3 = VppGbpEndpoint(self, self.pg2,
- epg_222, None,
- "10.0.2.2", "11.0.2.2",
- "2001:12::1", "3001:12::1")
- ep3.add_vpp_config()
-
- #
- # service endpoints
- #
- sep1 = VppGbpEndpoint(self, self.pg3,
- epg_320, None,
- "12.0.0.1", "13.0.0.1",
- "4001:10::1", "5001:10::1")
- sep1.add_vpp_config()
- sep2 = VppGbpEndpoint(self, self.pg4,
- epg_320, None,
- "12.0.0.2", "13.0.0.2",
- "4001:10::2", "5001:10::2")
- sep2.add_vpp_config()
- sep3 = VppGbpEndpoint(self, self.pg5,
- epg_321, None,
- "12.0.1.1", "13.0.1.1",
- "4001:11::1", "5001:11::1")
- sep3.add_vpp_config()
- # this EP is not installed immediately
- sep4 = VppGbpEndpoint(self, self.pg6,
- epg_321, None,
- "12.0.1.2", "13.0.1.2",
- "4001:11::2", "5001:11::2")
-
- #
- # an L2 switch packet between local EPs in different EPGs
- # different dest ports on each so the are LB hashed differently
- #
- p4 = [(Ether(src=ep1.mac, dst=ep3.mac) /
- IP(src=ep1.ip4, dst=ep3.ip4) /
- UDP(sport=1234, dport=1234) /
- Raw(b'\xa5' * 100)),
- (Ether(src=ep3.mac, dst=ep1.mac) /
- IP(src=ep3.ip4, dst=ep1.ip4) /
- UDP(sport=1234, dport=1234) /
- Raw(b'\xa5' * 100))]
- p6 = [(Ether(src=ep1.mac, dst=ep3.mac) /
- IPv6(src=ep1.ip6, dst=ep3.ip6) /
- UDP(sport=1234, dport=1234) /
- Raw(b'\xa5' * 100)),
- (Ether(src=ep3.mac, dst=ep1.mac) /
- IPv6(src=ep3.ip6, dst=ep1.ip6) /
- UDP(sport=1234, dport=1230) /
- Raw(b'\xa5' * 100))]
-
- # should be dropped since no contract yet
- self.send_and_assert_no_replies(self.pg0, [p4[0]])
- self.send_and_assert_no_replies(self.pg0, [p6[0]])
-
- #
- # Add a contract with a rule to load-balance redirect via SEP1 and SEP2
- # one of the next-hops is via an EP that is not known
- #
- rule4 = AclRule(is_permit=1, proto=17)
- rule6 = AclRule(src_prefix=IPv6Network((0, 0)),
- dst_prefix=IPv6Network((0, 0)), is_permit=1, proto=17)
- acl = VppAcl(self, rules=[rule4, rule6])
- acl.add_vpp_config()
-
- #
- # test the src-ip hash mode
- #
- c1 = VppGbpContract(
- self, 402, epg_220.sclass, epg_222.sclass, acl.acl_index,
- [VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
- [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
- sep1.ip4, sep1.epg.rd),
- VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
- sep2.ip4, sep2.epg.rd)]),
- VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
- [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
- sep3.ip6, sep3.epg.rd),
- VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
- sep4.ip6, sep4.epg.rd)])],
- [ETH_P_IP, ETH_P_IPV6])
- c1.add_vpp_config()
-
- c2 = VppGbpContract(
- self, 402, epg_222.sclass, epg_220.sclass, acl.acl_index,
- [VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
- [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
- sep1.ip4, sep1.epg.rd),
- VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
- sep2.ip4, sep2.epg.rd)]),
- VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
- [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
- sep3.ip6, sep3.epg.rd),
- VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
- sep4.ip6, sep4.epg.rd)])],
- [ETH_P_IP, ETH_P_IPV6])
- c2.add_vpp_config()
-
- #
- # send again with the contract preset, now packets arrive
- # at SEP1 or SEP2 depending on the hashing
- #
- rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
-
- for rx in rxs:
- self.assertEqual(rx[Ether].src, routed_src_mac)
- self.assertEqual(rx[Ether].dst, sep1.mac)
- self.assertEqual(rx[IP].src, ep1.ip4)
- self.assertEqual(rx[IP].dst, ep3.ip4)
-
- rxs = self.send_and_expect(self.pg2, p4[1] * 17, sep2.itf)
-
- for rx in rxs:
- self.assertEqual(rx[Ether].src, routed_src_mac)
- self.assertEqual(rx[Ether].dst, sep2.mac)
- self.assertEqual(rx[IP].src, ep3.ip4)
- self.assertEqual(rx[IP].dst, ep1.ip4)
-
- rxs = self.send_and_expect(self.pg0, p6[0] * 17, self.pg7)
-
- for rx in rxs:
- self.assertEqual(rx[Ether].src, self.pg7.local_mac)
- self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
- self.assertEqual(rx[IP].src, self.pg7.local_ip4)
- self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
- self.assertEqual(rx[VXLAN].vni, 117)
- self.assertTrue(rx[VXLAN].flags.G)
- self.assertTrue(rx[VXLAN].flags.Instance)
- # redirect policy has been applied
- self.assertTrue(rx[VXLAN].gpflags.A)
- self.assertFalse(rx[VXLAN].gpflags.D)
-
- inner = rx[VXLAN].payload
-
- self.assertEqual(inner[Ether].src, routed_src_mac)
- self.assertEqual(inner[Ether].dst, sep4.mac)
- self.assertEqual(inner[IPv6].src, ep1.ip6)
- self.assertEqual(inner[IPv6].dst, ep3.ip6)
-
- rxs = self.send_and_expect(self.pg2, p6[1] * 17, sep3.itf)
-
- for rx in rxs:
- self.assertEqual(rx[Ether].src, routed_src_mac)
- self.assertEqual(rx[Ether].dst, sep3.mac)
- self.assertEqual(rx[IPv6].src, ep3.ip6)
- self.assertEqual(rx[IPv6].dst, ep1.ip6)
-
- #
- # programme the unknown EP
- #
- sep4.add_vpp_config()
-
- rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep4.itf)
-
- for rx in rxs:
- self.assertEqual(rx[Ether].src, routed_src_mac)
- self.assertEqual(rx[Ether].dst, sep4.mac)
- self.assertEqual(rx[IPv6].src, ep1.ip6)
- self.assertEqual(rx[IPv6].dst, ep3.ip6)
-
- #
- # and revert back to unprogrammed
- #
- sep4.remove_vpp_config()
-
- rxs = self.send_and_expect(self.pg0, p6[0] * 17, self.pg7)
-
- for rx in rxs:
- self.assertEqual(rx[Ether].src, self.pg7.local_mac)
- self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
- self.assertEqual(rx[IP].src, self.pg7.local_ip4)
- self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
- self.assertEqual(rx[VXLAN].vni, 117)
- self.assertTrue(rx[VXLAN].flags.G)
- self.assertTrue(rx[VXLAN].flags.Instance)
- # redirect policy has been applied
- self.assertTrue(rx[VXLAN].gpflags.A)
- self.assertFalse(rx[VXLAN].gpflags.D)
-
- inner = rx[VXLAN].payload
-
- self.assertEqual(inner[Ether].src, routed_src_mac)
- self.assertEqual(inner[Ether].dst, sep4.mac)
- self.assertEqual(inner[IPv6].src, ep1.ip6)
- self.assertEqual(inner[IPv6].dst, ep3.ip6)
-
- c1.remove_vpp_config()
- c2.remove_vpp_config()
-
- #
- # test the symmetric hash mode
- #
- c1 = VppGbpContract(
- self, 402, epg_220.sclass, epg_222.sclass, acl.acl_index,
- [VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
- [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
- sep1.ip4, sep1.epg.rd),
- VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
- sep2.ip4, sep2.epg.rd)]),
- VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
- [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
- sep3.ip6, sep3.epg.rd),
- VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
- sep4.ip6, sep4.epg.rd)])],
- [ETH_P_IP, ETH_P_IPV6])
- c1.add_vpp_config()
-
- c2 = VppGbpContract(
- self, 402, epg_222.sclass, epg_220.sclass, acl.acl_index,
- [VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
- [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
- sep1.ip4, sep1.epg.rd),
- VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
- sep2.ip4, sep2.epg.rd)]),
- VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
- [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
- sep3.ip6, sep3.epg.rd),
- VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
- sep4.ip6, sep4.epg.rd)])],
- [ETH_P_IP, ETH_P_IPV6])
- c2.add_vpp_config()
-
- #
- # send again with the contract preset, now packets arrive
- # at SEP1 for both directions
- #
- rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
-
- for rx in rxs:
- self.assertEqual(rx[Ether].src, routed_src_mac)
- self.assertEqual(rx[Ether].dst, sep1.mac)
- self.assertEqual(rx[IP].src, ep1.ip4)
- self.assertEqual(rx[IP].dst, ep3.ip4)
-
- rxs = self.send_and_expect(self.pg2, p4[1] * 17, sep1.itf)
-
- for rx in rxs:
- self.assertEqual(rx[Ether].src, routed_src_mac)
- self.assertEqual(rx[Ether].dst, sep1.mac)
- self.assertEqual(rx[IP].src, ep3.ip4)
- self.assertEqual(rx[IP].dst, ep1.ip4)
-
- #
- # programme the unknown EP for the L3 tests
- #
- sep4.add_vpp_config()
-
- #
- # an L3 switch packet between local EPs in different EPGs
- # different dest ports on each so the are LB hashed differently
- #
- p4 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
- IP(src=ep1.ip4, dst=ep2.ip4) /
- UDP(sport=1234, dport=1234) /
- Raw(b'\xa5' * 100)),
- (Ether(src=ep2.mac, dst=str(self.router_mac)) /
- IP(src=ep2.ip4, dst=ep1.ip4) /
- UDP(sport=1234, dport=1234) /
- Raw(b'\xa5' * 100))]
- p6 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
- IPv6(src=ep1.ip6, dst=ep2.ip6) /
- UDP(sport=1234, dport=1234) /
- Raw(b'\xa5' * 100)),
- (Ether(src=ep2.mac, dst=str(self.router_mac)) /
- IPv6(src=ep2.ip6, dst=ep1.ip6) /
- UDP(sport=1234, dport=1234) /
- Raw(b'\xa5' * 100))]
-
- c3 = VppGbpContract(
- self, 402, epg_220.sclass, epg_221.sclass, acl.acl_index,
- [VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
- [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
- sep1.ip4, sep1.epg.rd),
- VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
- sep2.ip4, sep2.epg.rd)]),
- VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
- [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
- sep3.ip6, sep3.epg.rd),
- VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
- sep4.ip6, sep4.epg.rd)])],
- [ETH_P_IP, ETH_P_IPV6])
- c3.add_vpp_config()
-
- rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
-
- for rx in rxs:
- self.assertEqual(rx[Ether].src, routed_src_mac)
- self.assertEqual(rx[Ether].dst, sep1.mac)
- self.assertEqual(rx[IP].src, ep1.ip4)
- self.assertEqual(rx[IP].dst, ep2.ip4)
-
- #
- # learn a remote EP in EPG 221
- # packets coming from unknown remote EPs will be leant & redirected
- #
- vx_tun_l3 = VppGbpVxlanTunnel(
- self, 444, rd1.rd_id,
- VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
- self.pg2.local_ip4)
- vx_tun_l3.add_vpp_config()
-
- c4 = VppGbpContract(
- self, 402, epg_221.sclass, epg_220.sclass, acl.acl_index,
- [VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
- [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
- sep1.ip4, sep1.epg.rd),
- VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
- sep2.ip4, sep2.epg.rd)]),
- VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
- [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
- sep3.ip6, sep3.epg.rd),
- VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
- sep4.ip6, sep4.epg.rd)])],
- [ETH_P_IP, ETH_P_IPV6])
- c4.add_vpp_config()
-
- p = (Ether(src=self.pg7.remote_mac,
- dst=self.pg7.local_mac) /
- IP(src=self.pg7.remote_ip4,
- dst=self.pg7.local_ip4) /
- UDP(sport=1234, dport=48879) /
- VXLAN(vni=444, gpid=441, flags=0x88) /
- Ether(src="00:22:22:22:22:33", dst=str(self.router_mac)) /
- IP(src="10.0.0.88", dst=ep1.ip4) /
- UDP(sport=1234, dport=1234) /
- Raw(b'\xa5' * 100))
-
- # unknown remote EP to local EP redirected
- rxs = self.send_and_expect(self.pg7, [p], sep1.itf)
-
- for rx in rxs:
- self.assertEqual(rx[Ether].src, routed_src_mac)
- self.assertEqual(rx[Ether].dst, sep1.mac)
- self.assertEqual(rx[IP].src, "10.0.0.88")
- self.assertEqual(rx[IP].dst, ep1.ip4)
-
- # endpoint learnt via the parent GBP-vxlan interface
- self.assertTrue(find_gbp_endpoint(self,
- vx_tun_l3._sw_if_index,
- ip="10.0.0.88"))
-
- p = (Ether(src=self.pg7.remote_mac,
- dst=self.pg7.local_mac) /
- IP(src=self.pg7.remote_ip4,
- dst=self.pg7.local_ip4) /
- UDP(sport=1234, dport=48879) /
- VXLAN(vni=444, gpid=441, flags=0x88) /
- Ether(src="00:22:22:22:22:33", dst=str(self.router_mac)) /
- IPv6(src="2001:10::88", dst=ep1.ip6) /
- UDP(sport=1234, dport=1234) /
- Raw(b'\xa5' * 100))
-
- # unknown remote EP to local EP redirected (ipv6)
- rxs = self.send_and_expect(self.pg7, [p], sep3.itf)
-
- for rx in rxs:
- self.assertEqual(rx[Ether].src, routed_src_mac)
- self.assertEqual(rx[Ether].dst, sep3.mac)
- self.assertEqual(rx[IPv6].src, "2001:10::88")
- self.assertEqual(rx[IPv6].dst, ep1.ip6)
-
- # endpoint learnt via the parent GBP-vxlan interface
- self.assertTrue(find_gbp_endpoint(self,
- vx_tun_l3._sw_if_index,
- ip="2001:10::88"))
-
- #
- # L3 switch from local to remote EP
- #
- p4 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
- IP(src=ep1.ip4, dst="10.0.0.88") /
- UDP(sport=1234, dport=1234) /
- Raw(b'\xa5' * 100))]
- p6 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
- IPv6(src=ep1.ip6, dst="2001:10::88") /
- UDP(sport=1234, dport=1234) /
- Raw(b'\xa5' * 100))]
-
- rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
-
- for rx in rxs:
- self.assertEqual(rx[Ether].src, routed_src_mac)
- self.assertEqual(rx[Ether].dst, sep1.mac)
- self.assertEqual(rx[IP].src, ep1.ip4)
- self.assertEqual(rx[IP].dst, "10.0.0.88")
-
- rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep4.itf)
-
- for rx in rxs:
- self.assertEqual(rx[Ether].src, routed_src_mac)
- self.assertEqual(rx[Ether].dst, sep4.mac)
- self.assertEqual(rx[IPv6].src, ep1.ip6)
- self.assertEqual(rx[IPv6].dst, "2001:10::88")
-
- #
- # test the dst-ip hash mode
- #
- c5 = VppGbpContract(
- self, 402, epg_220.sclass, epg_221.sclass, acl.acl_index,
- [VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
- [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
- sep1.ip4, sep1.epg.rd),
- VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
- sep2.ip4, sep2.epg.rd)]),
- VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
- [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
- sep3.ip6, sep3.epg.rd),
- VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
- sep4.ip6, sep4.epg.rd)])],
- [ETH_P_IP, ETH_P_IPV6])
- c5.add_vpp_config()
-
- rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
-
- for rx in rxs:
- self.assertEqual(rx[Ether].src, routed_src_mac)
- self.assertEqual(rx[Ether].dst, sep1.mac)
- self.assertEqual(rx[IP].src, ep1.ip4)
- self.assertEqual(rx[IP].dst, "10.0.0.88")
-
- rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep3.itf)
-
- for rx in rxs:
- self.assertEqual(rx[Ether].src, routed_src_mac)
- self.assertEqual(rx[Ether].dst, sep3.mac)
- self.assertEqual(rx[IPv6].src, ep1.ip6)
- self.assertEqual(rx[IPv6].dst, "2001:10::88")
-
- #
- # a programmed remote SEP in EPG 320
- #
-
- # gbp vxlan tunnel for the remote SEP
- vx_tun_l3_sep = VppGbpVxlanTunnel(
- self, 555, rd1.rd_id,
- VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
- self.pg2.local_ip4)
- vx_tun_l3_sep.add_vpp_config()
-
- # remote SEP
- sep5 = VppGbpEndpoint(self, vx_tun_l3_sep,
- epg_320, None,
- "12.0.0.10", "13.0.0.10",
- "4001:10::10", "5001:10::10",
- ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
- self.pg7.local_ip4,
- self.pg7.remote_ip4,
- mac=None)
- sep5.add_vpp_config()
-
- #
- # local l3out redirect tests
- #
-
- # add local l3out
- # the external bd
- self.loop4.set_mac(self.router_mac)
- b_lo4_ip4 = VppIpInterfaceBind(self, self.loop4, t4).add_vpp_config()
- b_lo4_ip6 = VppIpInterfaceBind(self, self.loop4, t6).add_vpp_config()
- ebd = VppBridgeDomain(self, 100)
- ebd.add_vpp_config()
- gebd = VppGbpBridgeDomain(self, ebd, rd1, self.loop4, None, None)
- gebd.add_vpp_config()
- # the external epg
- eepg = VppGbpEndpointGroup(self, 888, 765, rd1, gebd,
- None, gebd.bvi,
- "10.1.0.128",
- "2001:10:1::128",
- VppGbpEndpointRetention(60))
- eepg.add_vpp_config()
- # add subnets to BVI
- VppIpInterfaceAddress(
- self,
- gebd.bvi,
- "10.1.0.128",
- 24, bind=b_lo4_ip4).add_vpp_config()
- VppIpInterfaceAddress(
- self,
- gebd.bvi,
- "2001:10:1::128",
- 64, bind=b_lo4_ip6).add_vpp_config()
- # ... which are L3-out subnets
- VppGbpSubnet(self, rd1, "10.1.0.0", 24,
- VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
- sclass=765).add_vpp_config()
- VppGbpSubnet(self, rd1, "2001:10:1::128", 64,
- VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
- sclass=765).add_vpp_config()
- # external endpoints
- VppL2Vtr(self, self.vlan_100, L2_VTR_OP.L2_POP_1).add_vpp_config()
- eep1 = VppGbpEndpoint(self, self.vlan_100, eepg, None, "10.1.0.1",
- "11.1.0.1", "2001:10:1::1", "3001:10:1::1",
- ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
- eep1.add_vpp_config()
- VppL2Vtr(self, self.vlan_101, L2_VTR_OP.L2_POP_1).add_vpp_config()
- eep2 = VppGbpEndpoint(self, self.vlan_101, eepg, None, "10.1.0.2",
- "11.1.0.2", "2001:10:1::2", "3001:10:1::2",
- ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
- eep2.add_vpp_config()
-
- # external subnets reachable though eep1 and eep2 respectively
- VppIpRoute(self, "10.220.0.0", 24,
- [VppRoutePath(eep1.ip4, eep1.epg.bvi.sw_if_index)],
- table_id=t4.table_id).add_vpp_config()
- VppGbpSubnet(self, rd1, "10.220.0.0", 24,
- VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
- sclass=4220).add_vpp_config()
- VppIpRoute(self, "10:220::", 64,
- [VppRoutePath(eep1.ip6, eep1.epg.bvi.sw_if_index)],
- table_id=t6.table_id).add_vpp_config()
- VppGbpSubnet(self, rd1, "10:220::", 64,
- VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
- sclass=4220).add_vpp_config()
- VppIpRoute(self, "10.221.0.0", 24,
- [VppRoutePath(eep2.ip4, eep2.epg.bvi.sw_if_index)],
- table_id=t4.table_id).add_vpp_config()
- VppGbpSubnet(self, rd1, "10.221.0.0", 24,
- VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
- sclass=4221).add_vpp_config()
- VppIpRoute(self, "10:221::", 64,
- [VppRoutePath(eep2.ip6, eep2.epg.bvi.sw_if_index)],
- table_id=t6.table_id).add_vpp_config()
- VppGbpSubnet(self, rd1, "10:221::", 64,
- VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
- sclass=4221).add_vpp_config()
-
- #
- # l3out redirect to remote (known, then unknown) SEP
- #
-
- # packets from 1 external subnet to the other
- p = [(Ether(src=eep1.mac, dst=self.router_mac) /
- Dot1Q(vlan=100) /
- IP(src="10.220.0.17", dst="10.221.0.65") /
- UDP(sport=1234, dport=1234) /
- Raw(b'\xa5' * 100)),
- (Ether(src=eep1.mac, dst=self.router_mac) /
- Dot1Q(vlan=100) /
- IPv6(src="10:220::17", dst="10:221::65") /
- UDP(sport=1234, dport=1234) /
- Raw(b'\xa5' * 100))]
-
- # packets should be dropped in absence of contract
- self.send_and_assert_no_replies(self.pg0, p)
-
- # contract redirecting to sep5
- VppGbpContract(
- self, 402, 4220, 4221, acl.acl_index,
- [VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
- [VppGbpContractNextHop(sep5.vmac, sep5.epg.bd,
- sep5.ip4, sep5.epg.rd)]),
- VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
- [VppGbpContractNextHop(sep5.vmac, sep5.epg.bd,
- sep5.ip6, sep5.epg.rd)])],
- [ETH_P_IP, ETH_P_IPV6]).add_vpp_config()
-
- rxs = self.send_and_expect(self.pg0, p, self.pg7)
-
- for rx, tx in zip(rxs, p):
- self.assertEqual(rx[Ether].src, self.pg7.local_mac)
- self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
- self.assertEqual(rx[IP].src, self.pg7.local_ip4)
- self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
- # this should use the programmed remote leaf TEP
- self.assertEqual(rx[VXLAN].vni, 555)
- self.assertEqual(rx[VXLAN].gpid, 4220)
- self.assertTrue(rx[VXLAN].flags.G)
- self.assertTrue(rx[VXLAN].flags.Instance)
- # redirect policy has been applied
- self.assertTrue(rx[VXLAN].gpflags.A)
- self.assertTrue(rx[VXLAN].gpflags.D)
- rxip = rx[VXLAN][Ether].payload
- txip = tx[Dot1Q].payload
- self.assertEqual(rxip.src, txip.src)
- self.assertEqual(rxip.dst, txip.dst)
-
- # remote SEP: it is now an unknown remote SEP and should go
- # to spine proxy
- sep5.remove_vpp_config()
-
- rxs = self.send_and_expect(self.pg0, p, self.pg7)
-
- for rx, tx in zip(rxs, p):
- self.assertEqual(rx[Ether].src, self.pg7.local_mac)
- self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
- self.assertEqual(rx[IP].src, self.pg7.local_ip4)
- self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
- # this should use the spine proxy TEP
- self.assertEqual(rx[VXLAN].vni, epg_320.bd.uu_fwd.vni)
- self.assertEqual(rx[VXLAN].gpid, 4220)
- self.assertTrue(rx[VXLAN].flags.G)
- self.assertTrue(rx[VXLAN].flags.Instance)
- # redirect policy has been applied
- self.assertTrue(rx[VXLAN].gpflags.A)
- self.assertTrue(rx[VXLAN].gpflags.D)
- rxip = rx[VXLAN][Ether].payload
- txip = tx[Dot1Q].payload
- self.assertEqual(rxip.src, txip.src)
- self.assertEqual(rxip.dst, txip.dst)
-
- #
- # l3out redirect to local SEP
- #
-
- # change the contract between l3out to redirect to local SEPs
- # instead of remote SEP
- VppGbpContract(
- self, 402, 4220, 4221, acl.acl_index,
- [VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
- [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
- sep1.ip4, sep1.epg.rd)]),
- VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
- [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
- sep1.ip6, sep1.epg.rd)])],
- [ETH_P_IP, ETH_P_IPV6]).add_vpp_config()
-
- rxs = self.send_and_expect(self.pg0, p, sep1.itf)
- for rx, tx in zip(rxs, p):
- self.assertEqual(rx[Ether].src, routed_src_mac)
- self.assertEqual(rx[Ether].dst, sep1.mac)
- rxip = rx[Ether].payload
- txip = tx[Ether].payload
- self.assertEqual(rxip.src, txip.src)
- self.assertEqual(rxip.dst, txip.dst)
-
- #
- # redirect remote EP to remote (known then unknown) SEP
- #
-
- # remote SEP known again
- sep5.add_vpp_config()
-
- # contract to redirect to learnt SEP
- VppGbpContract(
- self, 402, epg_221.sclass, epg_222.sclass, acl.acl_index,
- [VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
- [VppGbpContractNextHop(sep5.vmac, sep5.epg.bd,
- sep5.ip4, sep5.epg.rd)]),
- VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
- [VppGbpContractNextHop(sep5.vmac, sep5.epg.bd,
- sep5.ip6, sep5.epg.rd)])],
- [ETH_P_IP, ETH_P_IPV6]).add_vpp_config()
-
- # packets from unknown EP 221 to known EP in EPG 222
- # should be redirected to known remote SEP
- base = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
- IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
- UDP(sport=1234, dport=48879) /
- VXLAN(vni=444, gpid=441, flags=0x88) /
- Ether(src="00:22:22:22:22:44", dst=str(self.router_mac)))
- p = [(base /
- IP(src="10.0.1.100", dst=ep3.ip4) /
- UDP(sport=1234, dport=1234) /
- Raw(b'\xa5' * 100)),
- (base /
- IPv6(src="2001:10::100", dst=ep3.ip6) /
- UDP(sport=1234, dport=1234) /
- Raw(b'\xa5' * 100))]
-
- # unknown remote EP to local EP redirected to known remote SEP
- rxs = self.send_and_expect(self.pg7, p, self.pg7)
-
- for rx, tx in zip(rxs, p):
- self.assertEqual(rx[Ether].src, self.pg7.local_mac)
- self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
- self.assertEqual(rx[IP].src, self.pg7.local_ip4)
- self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
- # this should use the programmed remote leaf TEP
- self.assertEqual(rx[VXLAN].vni, 555)
- self.assertEqual(rx[VXLAN].gpid, epg_221.sclass)
- self.assertTrue(rx[VXLAN].flags.G)
- self.assertTrue(rx[VXLAN].flags.Instance)
- # redirect policy has been applied
- self.assertTrue(rx[VXLAN].gpflags.A)
- self.assertFalse(rx[VXLAN].gpflags.D)
- rxip = rx[VXLAN][Ether].payload
- txip = tx[VXLAN][Ether].payload
- self.assertEqual(rxip.src, txip.src)
- self.assertEqual(rxip.dst, txip.dst)
-
- # endpoint learnt via the parent GBP-vxlan interface
- self.assertTrue(find_gbp_endpoint(self,
- vx_tun_l3._sw_if_index,
- ip="10.0.1.100"))
- self.assertTrue(find_gbp_endpoint(self,
- vx_tun_l3._sw_if_index,
- ip="2001:10::100"))
-
- # remote SEP: it is now an unknown remote SEP and should go
- # to spine proxy
- sep5.remove_vpp_config()
-
- # remote EP (coming from spine proxy) to local EP redirected to
- # known remote SEP
- rxs = self.send_and_expect(self.pg7, p, self.pg7)
-
- for rx, tx in zip(rxs, p):
- self.assertEqual(rx[Ether].src, self.pg7.local_mac)
- self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
- self.assertEqual(rx[IP].src, self.pg7.local_ip4)
- self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
- # this should use the spine proxy TEP
- self.assertEqual(rx[VXLAN].vni, epg_320.bd.uu_fwd.vni)
- self.assertEqual(rx[VXLAN].gpid, epg_221.sclass)
- self.assertTrue(rx[VXLAN].flags.G)
- self.assertTrue(rx[VXLAN].flags.Instance)
- # redirect policy has been applied
- self.assertTrue(rx[VXLAN].gpflags.A)
- self.assertFalse(rx[VXLAN].gpflags.D)
- rxip = rx[VXLAN][Ether].payload
- txip = tx[VXLAN][Ether].payload
- self.assertEqual(rxip.src, txip.src)
- self.assertEqual(rxip.dst, txip.dst)
-
- #
- # cleanup
- #
- self.pg7.unconfig_ip4()
-
- def test_gbp_redirect_extended(self):
- """ GBP Endpoint Redirect Extended """
-
- self.vapi.cli("set logging class gbp level debug")
-
- ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
- routed_dst_mac = "00:0c:0c:0c:0c:0c"
- routed_src_mac = "00:22:bd:f8:19:ff"
-
- learnt = [{'mac': '00:00:11:11:11:02',
- 'ip': '10.0.1.2',
- 'ip6': '2001:10::2'},
- {'mac': '00:00:11:11:11:03',
- 'ip': '10.0.1.3',
- 'ip6': '2001:10::3'}]
-
- #
- # IP tables
- #
- t4 = VppIpTable(self, 1)
- t4.add_vpp_config()
- t6 = VppIpTable(self, 1, True)
- t6.add_vpp_config()
-
- # create IPv4 and IPv6 RD UU VxLAN-GBP TEP and bind them to the right
- # VRF
- rd_uu4 = VppVxlanGbpTunnel(
- self,
- self.pg7.local_ip4,
- self.pg7.remote_ip4,
- 114,
- mode=(VppEnum.vl_api_vxlan_gbp_api_tunnel_mode_t.
- VXLAN_GBP_API_TUNNEL_MODE_L3))
- rd_uu4.add_vpp_config()
- VppIpInterfaceBind(self, rd_uu4, t4).add_vpp_config()
-
- rd_uu6 = VppVxlanGbpTunnel(
- self,
- self.pg7.local_ip4,
- self.pg7.remote_ip4,
- 115,
- mode=(VppEnum.vl_api_vxlan_gbp_api_tunnel_mode_t.
- VXLAN_GBP_API_TUNNEL_MODE_L3))
- rd_uu6.add_vpp_config()
- VppIpInterfaceBind(self, rd_uu6, t4).add_vpp_config()
-
- rd1 = VppGbpRouteDomain(self, 2, 402, t4, t6, rd_uu4, rd_uu6)
- rd1.add_vpp_config()
-
- self.loop0.set_mac(self.router_mac)
- self.loop1.set_mac(self.router_mac)
- self.loop2.set_mac(self.router_mac)
-
- #
- # Bind the BVI to the RD
- #
- b_lo0_ip4 = VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
- b_lo0_ip6 = VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
- b_lo1_ip4 = VppIpInterfaceBind(self, self.loop1, t4).add_vpp_config()
- b_lo1_ip6 = VppIpInterfaceBind(self, self.loop1, t6).add_vpp_config()
- b_lo2_ip4 = VppIpInterfaceBind(self, self.loop2, t4).add_vpp_config()
- b_lo2_ip6 = VppIpInterfaceBind(self, self.loop2, t6).add_vpp_config()
-
- #
- # Pg7 hosts a BD's UU-fwd
- #
- self.pg7.config_ip4()
- self.pg7.resolve_arp()
-
- #
- # a GBP bridge domains for the EPs
- #
- bd1 = VppBridgeDomain(self, 1)
- bd1.add_vpp_config()
- gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0)
- gbd1.add_vpp_config()
-
- bd2 = VppBridgeDomain(self, 2)
- bd2.add_vpp_config()
- gbd2 = VppGbpBridgeDomain(self, bd2, rd1, self.loop1)
- gbd2.add_vpp_config()
-
- # ... and has a /32 and /128 applied
- ip4_addr1 = VppIpInterfaceAddress(self, gbd1.bvi,
- "10.0.0.128", 32,
- bind=b_lo0_ip4).add_vpp_config()
- ip6_addr1 = VppIpInterfaceAddress(self, gbd1.bvi,
- "2001:10::128", 128,
- bind=b_lo0_ip6).add_vpp_config()
- ip4_addr2 = VppIpInterfaceAddress(self, gbd2.bvi,
- "10.0.1.128", 32,
- bind=b_lo1_ip4).add_vpp_config()
- ip6_addr2 = VppIpInterfaceAddress(self, gbd2.bvi,
- "2001:11::128", 128,
- bind=b_lo1_ip6).add_vpp_config()
-
- #
- # The Endpoint-groups
- #
- epg_220 = VppGbpEndpointGroup(self, 220, 440, rd1, gbd1,
- None, gbd1.bvi,
- "10.0.0.128",
- "2001:10::128",
- VppGbpEndpointRetention(60))
- epg_220.add_vpp_config()
- epg_221 = VppGbpEndpointGroup(self, 221, 441, rd1, gbd2,
- None, gbd2.bvi,
- "10.0.1.128",
- "2001:11::128",
- VppGbpEndpointRetention(60))
- epg_221.add_vpp_config()
-
- #
- # a GBP bridge domains for the SEPs
- #
- bd_uu3 = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
- self.pg7.remote_ip4, 116)
- bd_uu3.add_vpp_config()
-
- bd3 = VppBridgeDomain(self, 3)
- bd3.add_vpp_config()
- gbd3 = VppGbpBridgeDomain(self, bd3, rd1, self.loop2,
- bd_uu3, learn=False)
- gbd3.add_vpp_config()
-
- ip4_addr3 = VppIpInterfaceAddress(self, gbd3.bvi,
- "12.0.0.128", 32,
- bind=b_lo2_ip4).add_vpp_config()
- ip6_addr3 = VppIpInterfaceAddress(self, gbd3.bvi,
- "4001:10::128", 128,
- bind=b_lo2_ip6).add_vpp_config()
-
- #
- # self.logger.info(self.vapi.cli("show gbp bridge"))
- # self.logger.info(self.vapi.cli("show vxlan-gbp tunnel"))
- # self.logger.info(self.vapi.cli("show gbp vxlan"))
- # self.logger.info(self.vapi.cli("show int addr"))
- #
-
- #
- # EPGs in which the service endpoints exist
- #
- epg_320 = VppGbpEndpointGroup(self, 320, 550, rd1, gbd3,
- None, gbd3.bvi,
- "12.0.0.128",
- "4001:10::128",
- VppGbpEndpointRetention(60))
- epg_320.add_vpp_config()
-
- #
- # endpoints
- #
- ep1 = VppGbpEndpoint(self, self.pg0,
- epg_220, None,
- "10.0.0.1", "11.0.0.1",
- "2001:10::1", "3001:10::1")
- ep1.add_vpp_config()
- ep2 = VppGbpEndpoint(self, self.pg1,
- epg_221, None,
- "10.0.1.1", "11.0.1.1",
- "2001:11::1", "3001:11::1")
- ep2.add_vpp_config()
-
- #
- # service endpoints
- #
- sep1 = VppGbpEndpoint(self, self.pg3,
- epg_320, None,
- "12.0.0.1", "13.0.0.1",
- "4001:10::1", "5001:10::1")
- sep2 = VppGbpEndpoint(self, self.pg4,
- epg_320, None,
- "12.0.0.2", "13.0.0.2",
- "4001:10::2", "5001:10::2")
-
- # sep1 and sep2 are not added to config yet
- # they are unknown for now
-
- #
- # add routes to EPG subnets
- #
- VppGbpSubnet(self, rd1, "10.0.0.0", 24,
- VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT
- ).add_vpp_config()
- VppGbpSubnet(self, rd1, "10.0.1.0", 24,
- VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT
- ).add_vpp_config()
-
- #
- # Local host to known local host in different BD
- # with SFC contract (source and destination are in
- # one node and service endpoint in another node)
- #
- p4 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
- IP(src=ep1.ip4, dst=ep2.ip4) /
- UDP(sport=1234, dport=1234) /
- Raw(b'\xa5' * 100)),
- (Ether(src=ep2.mac, dst=str(self.router_mac)) /
- IP(src=ep2.ip4, dst=ep1.ip4) /
- UDP(sport=1234, dport=1234) /
- Raw(b'\xa5' * 100))]
- p6 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
- IPv6(src=ep1.ip6, dst=ep2.ip6) /
- UDP(sport=1234, dport=1234) /
- Raw(b'\xa5' * 100)),
- (Ether(src=ep2.mac, dst=str(self.router_mac)) /
- IPv6(src=ep2.ip6, dst=ep1.ip6) /
- UDP(sport=1234, dport=1230) /
- Raw(b'\xa5' * 100))]
-
- # should be dropped since no contract yet
- self.send_and_assert_no_replies(self.pg0, [p4[0]])
- self.send_and_assert_no_replies(self.pg0, [p6[0]])
-
- #
- # Add a contract with a rule to load-balance redirect via SEP1 and SEP2
- # one of the next-hops is via an EP that is not known
- #
- rule4 = AclRule(is_permit=1, proto=17)
- rule6 = AclRule(src_prefix=IPv6Network((0, 0)),
- dst_prefix=IPv6Network((0, 0)), is_permit=1, proto=17)
- acl = VppAcl(self, rules=[rule4, rule6])
- acl.add_vpp_config()
-
- #
- # test the src-ip hash mode
- #
- c1 = VppGbpContract(
- self, 402, epg_220.sclass, epg_221.sclass, acl.acl_index,
- [VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
- [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
- sep1.ip4, sep1.epg.rd)]),
- VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
- [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
- sep1.ip6, sep1.epg.rd)])],
- [ETH_P_IP, ETH_P_IPV6])
- c1.add_vpp_config()
-
- c2 = VppGbpContract(
- self, 402, epg_221.sclass, epg_220.sclass, acl.acl_index,
- [VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
- [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
- sep1.ip4, sep1.epg.rd)]),
- VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
- [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
- sep1.ip6, sep1.epg.rd)])],
- [ETH_P_IP, ETH_P_IPV6])
- c2.add_vpp_config()
-
- # ep1 <--> ep2 redirected through sep1
- # sep1 is unknown
- # packet is redirected to sep bd and then go through sep bd UU
-
- rxs = self.send_and_expect(self.pg0, p4[0] * 17, self.pg7)
-
- for rx in rxs:
- self.assertEqual(rx[Ether].src, self.pg7.local_mac)
- self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
- self.assertEqual(rx[IP].src, self.pg7.local_ip4)
- self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
- self.assertEqual(rx[VXLAN].vni, 116)
- self.assertTrue(rx[VXLAN].flags.G)
- self.assertTrue(rx[VXLAN].flags.Instance)
- # redirect policy has been applied
- self.assertTrue(rx[VXLAN].gpflags.A)
- self.assertFalse(rx[VXLAN].gpflags.D)
-
- inner = rx[VXLAN].payload
-
- self.assertEqual(inner[Ether].src, routed_src_mac)
- self.assertEqual(inner[Ether].dst, sep1.mac)
- self.assertEqual(inner[IP].src, ep1.ip4)
- self.assertEqual(inner[IP].dst, ep2.ip4)
-
- rxs = self.send_and_expect(self.pg1, p4[1] * 17, self.pg7)
-
- for rx in rxs:
- self.assertEqual(rx[Ether].src, self.pg7.local_mac)
- self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
- self.assertEqual(rx[IP].src, self.pg7.local_ip4)
- self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
- self.assertEqual(rx[VXLAN].vni, 116)
- self.assertTrue(rx[VXLAN].flags.G)
- self.assertTrue(rx[VXLAN].flags.Instance)
- # redirect policy has been applied
- self.assertTrue(rx[VXLAN].gpflags.A)
- self.assertFalse(rx[VXLAN].gpflags.D)
-
- inner = rx[VXLAN].payload
-
- self.assertEqual(inner[Ether].src, routed_src_mac)
- self.assertEqual(inner[Ether].dst, sep1.mac)
- self.assertEqual(inner[IP].src, ep2.ip4)
- self.assertEqual(inner[IP].dst, ep1.ip4)
-
- rxs = self.send_and_expect(self.pg0, p6[0] * 17, self.pg7)
-
- for rx in rxs:
- self.assertEqual(rx[Ether].src, self.pg7.local_mac)
- self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
- self.assertEqual(rx[IP].src, self.pg7.local_ip4)
- self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
- self.assertEqual(rx[VXLAN].vni, 116)
- self.assertTrue(rx[VXLAN].flags.G)
- self.assertTrue(rx[VXLAN].flags.Instance)
- # redirect policy has been applied
- inner = rx[VXLAN].payload
-
- self.assertEqual(inner[Ether].src, routed_src_mac)
- self.assertEqual(inner[Ether].dst, sep1.mac)
- self.assertEqual(inner[IPv6].src, ep1.ip6)
- self.assertEqual(inner[IPv6].dst, ep2.ip6)
-
- rxs = self.send_and_expect(self.pg1, p6[1] * 17, self.pg7)
-
- for rx in rxs:
- self.assertEqual(rx[Ether].src, self.pg7.local_mac)
- self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
- self.assertEqual(rx[IP].src, self.pg7.local_ip4)
- self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
- self.assertEqual(rx[VXLAN].vni, 116)
- self.assertTrue(rx[VXLAN].flags.G)
- self.assertTrue(rx[VXLAN].flags.Instance)
- # redirect policy has been applied
- self.assertTrue(rx[VXLAN].gpflags.A)
- self.assertFalse(rx[VXLAN].gpflags.D)
-
- inner = rx[VXLAN].payload
-
- self.assertEqual(inner[Ether].src, routed_src_mac)
- self.assertEqual(inner[Ether].dst, sep1.mac)
- self.assertEqual(inner[IPv6].src, ep2.ip6)
- self.assertEqual(inner[IPv6].dst, ep1.ip6)
-
- # configure sep1: it is now local
- # packets between ep1 and ep2 are redirected locally
- sep1.add_vpp_config()
-
- rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
-
- for rx in rxs:
- self.assertEqual(rx[Ether].src, routed_src_mac)
- self.assertEqual(rx[Ether].dst, sep1.mac)
- self.assertEqual(rx[IP].src, ep1.ip4)
- self.assertEqual(rx[IP].dst, ep2.ip4)
-
- rxs = self.send_and_expect(self.pg1, p6[1] * 17, sep1.itf)
-
- for rx in rxs:
- self.assertEqual(rx[Ether].src, routed_src_mac)
- self.assertEqual(rx[Ether].dst, sep1.mac)
- self.assertEqual(rx[IPv6].src, ep2.ip6)
- self.assertEqual(rx[IPv6].dst, ep1.ip6)
-
- # packet coming from the l2 spine-proxy to sep1
- p = (Ether(src=self.pg7.remote_mac,
- dst=self.pg7.local_mac) /
- IP(src=self.pg7.remote_ip4,
- dst=self.pg7.local_ip4) /
- UDP(sport=1234, dport=48879) /
- VXLAN(vni=116, gpid=440, gpflags=0x08, flags=0x88) /
- Ether(src=str(self.router_mac), dst=sep1.mac) /
- IP(src=ep1.ip4, dst=ep2.ip4) /
- UDP(sport=1234, dport=1234) /
- Raw(b'\xa5' * 100))
-
- rxs = self.send_and_expect(self.pg7, [p] * 17, sep1.itf)
-
- for rx in rxs:
- self.assertEqual(rx[Ether].src, str(self.router_mac))
- self.assertEqual(rx[Ether].dst, sep1.mac)
- self.assertEqual(rx[IP].src, ep1.ip4)
- self.assertEqual(rx[IP].dst, ep2.ip4)
-
- # contract for SEP to communicate with dst EP
- c3 = VppGbpContract(
- self, 402, epg_320.sclass, epg_221.sclass, acl.acl_index,
- [VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC),
- VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC)],
- [ETH_P_IP, ETH_P_IPV6])
- c3.add_vpp_config()
-
- # temporarily remove ep2, so that ep2 is remote & unknown
- ep2.remove_vpp_config()
-
- # packet going back from sep1 to its original dest (ep2)
- # as ep2 is now unknown (see above), it must go through
- # the rd UU (packet is routed)
-
- p1 = (Ether(src=sep1.mac, dst=self.router_mac) /
- IP(src=ep1.ip4, dst=ep2.ip4) /
- UDP(sport=1234, dport=1234) /
- Raw(b'\xa5' * 100))
-
- rxs = self.send_and_expect(self.pg3, [p1] * 17, self.pg7)
-
- for rx in rxs:
- self.assertEqual(rx[Ether].src, self.pg7.local_mac)
- self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
- self.assertEqual(rx[IP].src, self.pg7.local_ip4)
- self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
- self.assertEqual(rx[VXLAN].vni, 114)
- self.assertTrue(rx[VXLAN].flags.G)
- self.assertTrue(rx[VXLAN].flags.Instance)
- # redirect policy has been applied
- inner = rx[VXLAN].payload
- self.assertEqual(inner[Ether].src, routed_src_mac)
- self.assertEqual(inner[Ether].dst, routed_dst_mac)
- self.assertEqual(inner[IP].src, ep1.ip4)
- self.assertEqual(inner[IP].dst, ep2.ip4)
-
- self.logger.info(self.vapi.cli("show bridge 3 detail"))
- sep1.remove_vpp_config()
-
- self.logger.info(self.vapi.cli("show bridge 1 detail"))
- self.logger.info(self.vapi.cli("show bridge 2 detail"))
-
- # re-add ep2: it is local again :)
- ep2.add_vpp_config()
-
- # packet coming back from the remote sep through rd UU
- p2 = (Ether(src=self.pg7.remote_mac,
- dst=self.pg7.local_mac) /
- IP(src=self.pg7.remote_ip4,
- dst=self.pg7.local_ip4) /
- UDP(sport=1234, dport=48879) /
- VXLAN(vni=114, gpid=441, gpflags=0x09, flags=0x88) /
- Ether(src=str(self.router_mac), dst=self.router_mac) /
- IP(src=ep1.ip4, dst=ep2.ip4) /
- UDP(sport=1234, dport=1234) /
- Raw(b'\xa5' * 100))
-
- rxs = self.send_and_expect(self.pg7, [p2], self.pg1)
-
- for rx in rxs:
- self.assertEqual(rx[Ether].src, str(self.router_mac))
- self.assertEqual(rx[Ether].dst, self.pg1.remote_mac)
- self.assertEqual(rx[IP].src, ep1.ip4)
- self.assertEqual(rx[IP].dst, ep2.ip4)
-
- #
- # bd_uu2.add_vpp_config()
- #
-
- #
- # cleanup
- #
- c1.remove_vpp_config()
- c2.remove_vpp_config()
- c3.remove_vpp_config()
- self.pg7.unconfig_ip4()
-
- def test_gbp_l3_out(self):
- """ GBP L3 Out """
-
- ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
- self.vapi.cli("set logging class gbp level debug")
-
- routed_dst_mac = "00:0c:0c:0c:0c:0c"
- routed_src_mac = "00:22:bd:f8:19:ff"
-
- #
- # IP tables
- #
- t4 = VppIpTable(self, 1)
- t4.add_vpp_config()
- t6 = VppIpTable(self, 1, True)
- t6.add_vpp_config()
-
- rd1 = VppGbpRouteDomain(self, 2, 55, t4, t6)
- rd1.add_vpp_config()
-
- self.loop0.set_mac(self.router_mac)
-
- #
- # Bind the BVI to the RD
- #
- b_ip4 = VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
- b_ip6 = VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
-
- #
- # Pg7 hosts a BD's BUM
- # Pg1 some other l3 interface
- #
- self.pg7.config_ip4()
- self.pg7.resolve_arp()
-
- #
- # a multicast vxlan-gbp tunnel for broadcast in the BD
- #
- tun_bm = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
- "239.1.1.1", 88,
- mcast_itf=self.pg7)
- tun_bm.add_vpp_config()
-
- #
- # a GBP external bridge domains for the EPs
- #
- bd1 = VppBridgeDomain(self, 1)
- bd1.add_vpp_config()
- gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0, None, tun_bm)
- gbd1.add_vpp_config()
-
- #
- # The Endpoint-groups in which the external endpoints exist
- #
- epg_220 = VppGbpEndpointGroup(self, 220, 113, rd1, gbd1,
- None, gbd1.bvi,
- "10.0.0.128",
- "2001:10::128",
- VppGbpEndpointRetention(4))
- epg_220.add_vpp_config()
-
- # the BVIs have the subnets applied ...
- ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128",
- 24, bind=b_ip4).add_vpp_config()
- ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128",
- 64, bind=b_ip6).add_vpp_config()
-
- # ... which are L3-out subnets
- l3o_1 = VppGbpSubnet(
- self, rd1, "10.0.0.0", 24,
- VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
- sclass=113)
- l3o_1.add_vpp_config()
-
- #
- # an external interface attached to the outside world and the
- # external BD
- #
- VppL2Vtr(self, self.vlan_100, L2_VTR_OP.L2_POP_1).add_vpp_config()
- VppL2Vtr(self, self.vlan_101, L2_VTR_OP.L2_POP_1).add_vpp_config()
- vlan_144 = VppDot1QSubint(self, self.pg0, 144)
- vlan_144.admin_up()
- # vlan_102 is not poped
-
- #
- # an unicast vxlan-gbp for inter-RD traffic
- #
- vx_tun_l3 = VppGbpVxlanTunnel(
- self, 444, rd1.rd_id,
- VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
- self.pg2.local_ip4)
- vx_tun_l3.add_vpp_config()
-
- #
- # External Endpoints
- #
- eep1 = VppGbpEndpoint(self, self.vlan_100,
- epg_220, None,
- "10.0.0.1", "11.0.0.1",
- "2001:10::1", "3001::1",
- ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
- eep1.add_vpp_config()
- eep2 = VppGbpEndpoint(self, self.vlan_101,
- epg_220, None,
- "10.0.0.2", "11.0.0.2",
- "2001:10::2", "3001::2",
- ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
- eep2.add_vpp_config()
- eep3 = VppGbpEndpoint(self, self.vlan_102,
- epg_220, None,
- "10.0.0.3", "11.0.0.3",
- "2001:10::3", "3001::3",
- ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
- eep3.add_vpp_config()
-
- #
- # A remote external endpoint
- #
- rep = VppGbpEndpoint(self, vx_tun_l3,
- epg_220, None,
- "10.0.0.101", "11.0.0.101",
- "2001:10::101", "3001::101",
- ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
- self.pg7.local_ip4,
- self.pg7.remote_ip4,
- mac=None)
- rep.add_vpp_config()
-
- #
- # EP1 impersonating EP3 is dropped
- #
- p = (Ether(src=eep1.mac, dst="ff:ff:ff:ff:ff:ff") /
- Dot1Q(vlan=100) /
- ARP(op="who-has",
- psrc="10.0.0.3", pdst="10.0.0.128",
- hwsrc=eep1.mac, hwdst="ff:ff:ff:ff:ff:ff"))
- self.send_and_assert_no_replies(self.pg0, p)
-
- #
- # ARP packet from External EPs are accepted and replied to
- #
- p_arp = (Ether(src=eep1.mac, dst="ff:ff:ff:ff:ff:ff") /
- Dot1Q(vlan=100) /
- ARP(op="who-has",
- psrc=eep1.ip4, pdst="10.0.0.128",
- hwsrc=eep1.mac, hwdst="ff:ff:ff:ff:ff:ff"))
- rxs = self.send_and_expect(self.pg0, p_arp * 1, self.pg0)
-
- #
- # ARP packet from host in remote subnet are accepted and replied to
- #
- p_arp = (Ether(src=eep3.mac, dst="ff:ff:ff:ff:ff:ff") /
- Dot1Q(vlan=102) /
- ARP(op="who-has",
- psrc=eep3.ip4, pdst="10.0.0.128",
- hwsrc=eep3.mac, hwdst="ff:ff:ff:ff:ff:ff"))
- rxs = self.send_and_expect(self.pg0, p_arp * 1, self.pg0)
-
- #
- # packets destined to unknown addresses in the BVI's subnet
- # are ARP'd for
- #
- p4 = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
- Dot1Q(vlan=100) /
- IP(src="10.0.0.1", dst="10.0.0.88") /
- UDP(sport=1234, dport=1234) /
- Raw(b'\xa5' * 100))
- p6 = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
- Dot1Q(vlan=100) /
- IPv6(src="2001:10::1", dst="2001:10::88") /
- UDP(sport=1234, dport=1234) /
- Raw(b'\xa5' * 100))
-
- rxs = self.send_and_expect(self.pg0, p4 * 1, self.pg7)
-
- for rx in rxs:
- self.assertEqual(rx[Ether].src, self.pg7.local_mac)
- # self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
- self.assertEqual(rx[IP].src, self.pg7.local_ip4)
- self.assertEqual(rx[IP].dst, "239.1.1.1")
- self.assertEqual(rx[VXLAN].vni, 88)
- self.assertTrue(rx[VXLAN].flags.G)
- self.assertTrue(rx[VXLAN].flags.Instance)
- # policy was applied to the original IP packet
- self.assertEqual(rx[VXLAN].gpid, 113)
- self.assertTrue(rx[VXLAN].gpflags.A)
- self.assertFalse(rx[VXLAN].gpflags.D)
-
- inner = rx[VXLAN].payload
-
- self.assertTrue(inner.haslayer(ARP))
-
- #
- # remote to external
- #
- p = (Ether(src=self.pg7.remote_mac,
- dst=self.pg7.local_mac) /
- IP(src=self.pg7.remote_ip4,
- dst=self.pg7.local_ip4) /
- UDP(sport=1234, dport=48879) /
- VXLAN(vni=444, gpid=113, flags=0x88) /
- Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
- IP(src="10.0.0.101", dst="10.0.0.1") /
- UDP(sport=1234, dport=1234) /
- Raw(b'\xa5' * 100))
-
- rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
-
- #
- # local EP pings router
- #
- p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
- Dot1Q(vlan=100) /
- IP(src=eep1.ip4, dst="10.0.0.128") /
- ICMP(type='echo-request'))
-
- rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
-
- for rx in rxs:
- self.assertEqual(rx[Ether].src, str(self.router_mac))
- self.assertEqual(rx[Ether].dst, eep1.mac)
- self.assertEqual(rx[Dot1Q].vlan, 100)
-
- #
- # local EP pings other local EP
- #
- p = (Ether(src=eep1.mac, dst=eep2.mac) /
- Dot1Q(vlan=100) /
- IP(src=eep1.ip4, dst=eep2.ip4) /
- ICMP(type='echo-request'))
-
- rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
-
- for rx in rxs:
- self.assertEqual(rx[Ether].src, eep1.mac)
- self.assertEqual(rx[Ether].dst, eep2.mac)
- self.assertEqual(rx[Dot1Q].vlan, 101)
-
- #
- # local EP pings router w/o vlan tag poped
- #
- p = (Ether(src=eep3.mac, dst=str(self.router_mac)) /
- Dot1Q(vlan=102) /
- IP(src=eep3.ip4, dst="10.0.0.128") /
- ICMP(type='echo-request'))
-
- rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
-
- for rx in rxs:
- self.assertEqual(rx[Ether].src, str(self.router_mac))
- self.assertEqual(rx[Ether].dst, self.vlan_102.remote_mac)
-
- #
- # A ip4 subnet reachable through the external EP1
- #
- ip_220 = VppIpRoute(self, "10.220.0.0", 24,
- [VppRoutePath(eep1.ip4,
- eep1.epg.bvi.sw_if_index)],
- table_id=t4.table_id)
- ip_220.add_vpp_config()
-
- l3o_220 = VppGbpSubnet(
- self, rd1, "10.220.0.0", 24,
- VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
- sclass=4220)
- l3o_220.add_vpp_config()
-
- #
- # An ip6 subnet reachable through the external EP1
- #
- ip6_220 = VppIpRoute(self, "10:220::", 64,
- [VppRoutePath(eep1.ip6,
- eep1.epg.bvi.sw_if_index)],
- table_id=t6.table_id)
- ip6_220.add_vpp_config()
-
- l3o6_220 = VppGbpSubnet(
- self, rd1, "10:220::", 64,
- VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
- sclass=4220)
- l3o6_220.add_vpp_config()
-
- #
- # A subnet reachable through the external EP2
- #
- ip_221 = VppIpRoute(self, "10.221.0.0", 24,
- [VppRoutePath(eep2.ip4,
- eep2.epg.bvi.sw_if_index)],
- table_id=t4.table_id)
- ip_221.add_vpp_config()
-
- l3o_221 = VppGbpSubnet(
- self, rd1, "10.221.0.0", 24,
- VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
- sclass=4221)
- l3o_221.add_vpp_config()
-
- #
- # ping between hosts in remote subnets
- # dropped without a contract
- #
- p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
- Dot1Q(vlan=100) /
- IP(src="10.220.0.1", dst="10.221.0.1") /
- ICMP(type='echo-request'))
-
- self.send_and_assert_no_replies(self.pg0, p * 1)
-
- #
- # contract for the external nets to communicate
- #
- rule4 = AclRule(is_permit=1, proto=17)
- rule6 = AclRule(src_prefix=IPv6Network((0, 0)),
- dst_prefix=IPv6Network((0, 0)), is_permit=1, proto=17)
- acl = VppAcl(self, rules=[rule4, rule6])
- acl.add_vpp_config()
-
- #
- # A contract with the wrong scope is not matched
- #
- c_44 = VppGbpContract(
- self, 44, 4220, 4221, acl.acl_index,
- [VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
- []),
- VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
- [])],
- [ETH_P_IP, ETH_P_IPV6])
- c_44.add_vpp_config()
- self.send_and_assert_no_replies(self.pg0, p * 1)
-
- c1 = VppGbpContract(
- self, 55, 4220, 4221, acl.acl_index,
- [VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
- []),
- VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
- [])],
- [ETH_P_IP, ETH_P_IPV6])
- c1.add_vpp_config()
-
- #
- # Contracts allowing ext-net 200 to talk with external EPs
- #
- c2 = VppGbpContract(
- self, 55, 4220, 113, acl.acl_index,
- [VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
- []),
- VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
- [])],
- [ETH_P_IP, ETH_P_IPV6])
- c2.add_vpp_config()
- c3 = VppGbpContract(
- self, 55, 113, 4220, acl.acl_index,
- [VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
- []),
- VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
- [])],
- [ETH_P_IP, ETH_P_IPV6])
- c3.add_vpp_config()
-
- #
- # ping between hosts in remote subnets
- #
- p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
- Dot1Q(vlan=100) /
- IP(src="10.220.0.1", dst="10.221.0.1") /
- UDP(sport=1234, dport=1234) /
- Raw(b'\xa5' * 100))
-
- rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
-
- for rx in rxs:
- self.assertEqual(rx[Ether].src, str(self.router_mac))
- self.assertEqual(rx[Ether].dst, eep2.mac)
- self.assertEqual(rx[Dot1Q].vlan, 101)
-
- # we did not learn these external hosts
- self.assertFalse(find_gbp_endpoint(self, ip="10.220.0.1"))
- self.assertFalse(find_gbp_endpoint(self, ip="10.221.0.1"))
-
- #
- # from remote external EP to local external EP
- #
- p = (Ether(src=self.pg7.remote_mac,
- dst=self.pg7.local_mac) /
- IP(src=self.pg7.remote_ip4,
- dst=self.pg7.local_ip4) /
- UDP(sport=1234, dport=48879) /
- VXLAN(vni=444, gpid=113, flags=0x88) /
- Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
- IP(src="10.0.0.101", dst="10.220.0.1") /
- UDP(sport=1234, dport=1234) /
- Raw(b'\xa5' * 100))
-
- rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
-
- #
- # ping from an external host to the remote external EP
- #
- p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
- Dot1Q(vlan=100) /
- IP(src="10.220.0.1", dst=rep.ip4) /
- UDP(sport=1234, dport=1234) /
- Raw(b'\xa5' * 100))
-
- rxs = self.send_and_expect(self.pg0, p * 1, self.pg7)
-
- for rx in rxs:
- self.assertEqual(rx[Ether].src, self.pg7.local_mac)
- # self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
- self.assertEqual(rx[IP].src, self.pg7.local_ip4)
- self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
- self.assertEqual(rx[VXLAN].vni, 444)
- self.assertTrue(rx[VXLAN].flags.G)
- self.assertTrue(rx[VXLAN].flags.Instance)
- # the sclass of the ext-net the packet came from
- self.assertEqual(rx[VXLAN].gpid, 4220)
- # policy was applied to the original IP packet
- self.assertTrue(rx[VXLAN].gpflags.A)
- # since it's an external host the reciever should not learn it
- self.assertTrue(rx[VXLAN].gpflags.D)
- inner = rx[VXLAN].payload
- self.assertEqual(inner[IP].src, "10.220.0.1")
- self.assertEqual(inner[IP].dst, rep.ip4)
-
- #
- # An external subnet reachable via the remote external EP
- #
-
- #
- # first the VXLAN-GBP tunnel over which it is reached
- #
- vx_tun_r1 = VppVxlanGbpTunnel(
- self, self.pg7.local_ip4,
- self.pg7.remote_ip4, 445,
- mode=(VppEnum.vl_api_vxlan_gbp_api_tunnel_mode_t.
- VXLAN_GBP_API_TUNNEL_MODE_L3))
- vx_tun_r1.add_vpp_config()
- VppIpInterfaceBind(self, vx_tun_r1, t4).add_vpp_config()
-
- self.logger.info(self.vapi.cli("sh vxlan-gbp tunnel"))
-
- #
- # then the special adj to resolve through on that tunnel
- #
- n1 = VppNeighbor(self,
- vx_tun_r1.sw_if_index,
- "00:0c:0c:0c:0c:0c",
- self.pg7.remote_ip4)
- n1.add_vpp_config()
-
- #
- # the route via the adj above
- #
- ip_222 = VppIpRoute(self, "10.222.0.0", 24,
- [VppRoutePath(self.pg7.remote_ip4,
- vx_tun_r1.sw_if_index)],
- table_id=t4.table_id)
- ip_222.add_vpp_config()
-
- l3o_222 = VppGbpSubnet(
- self, rd1, "10.222.0.0", 24,
- VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
- sclass=4222)
- l3o_222.add_vpp_config()
-
- #
- # ping between hosts in local and remote external subnets
- # dropped without a contract
- #
- p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
- Dot1Q(vlan=100) /
- IP(src="10.220.0.1", dst="10.222.0.1") /
- UDP(sport=1234, dport=1234) /
- Raw(b'\xa5' * 100))
-
- rxs = self.send_and_assert_no_replies(self.pg0, p * 1)
-
- #
- # Add contracts ext-nets for 220 -> 222
- #
- c4 = VppGbpContract(
- self, 55, 4220, 4222, acl.acl_index,
- [VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
- []),
- VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
- [])],
- [ETH_P_IP, ETH_P_IPV6])
- c4.add_vpp_config()
-
- #
- # ping from host in local to remote external subnets
- #
- p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
- Dot1Q(vlan=100) /
- IP(src="10.220.0.1", dst="10.222.0.1") /
- UDP(sport=1234, dport=1234) /
- Raw(b'\xa5' * 100))
-
- rxs = self.send_and_expect(self.pg0, p * 3, self.pg7)
-
- for rx in rxs:
- self.assertEqual(rx[Ether].src, self.pg7.local_mac)
- self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
- self.assertEqual(rx[IP].src, self.pg7.local_ip4)
- self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
- self.assertEqual(rx[VXLAN].vni, 445)
- self.assertTrue(rx[VXLAN].flags.G)
- self.assertTrue(rx[VXLAN].flags.Instance)
- # the sclass of the ext-net the packet came from
- self.assertEqual(rx[VXLAN].gpid, 4220)
- # policy was applied to the original IP packet
- self.assertTrue(rx[VXLAN].gpflags.A)
- # since it's an external host the reciever should not learn it
- self.assertTrue(rx[VXLAN].gpflags.D)
- inner = rx[VXLAN].payload
- self.assertEqual(inner[Ether].dst, "00:0c:0c:0c:0c:0c")
- self.assertEqual(inner[IP].src, "10.220.0.1")
- self.assertEqual(inner[IP].dst, "10.222.0.1")
-
- #
- # make the external subnet ECMP
- #
- vx_tun_r2 = VppVxlanGbpTunnel(
- self, self.pg7.local_ip4,
- self.pg7.remote_ip4, 446,
- mode=(VppEnum.vl_api_vxlan_gbp_api_tunnel_mode_t.
- VXLAN_GBP_API_TUNNEL_MODE_L3))
- vx_tun_r2.add_vpp_config()
- VppIpInterfaceBind(self, vx_tun_r2, t4).add_vpp_config()
-
- self.logger.info(self.vapi.cli("sh vxlan-gbp tunnel"))
-
- n2 = VppNeighbor(self,
- vx_tun_r2.sw_if_index,
- "00:0c:0c:0c:0c:0c",
- self.pg7.remote_ip4)
- n2.add_vpp_config()
-
- ip_222.modify([VppRoutePath(self.pg7.remote_ip4,
- vx_tun_r1.sw_if_index),
- VppRoutePath(self.pg7.remote_ip4,
- vx_tun_r2.sw_if_index)])
-
- #
- # now expect load-balance
- #
- p = [(Ether(src=eep1.mac, dst=str(self.router_mac)) /
- Dot1Q(vlan=100) /
- IP(src="10.220.0.1", dst="10.222.0.1") /
- UDP(sport=1234, dport=1234) /
- Raw(b'\xa5' * 100)),
- (Ether(src=eep1.mac, dst=str(self.router_mac)) /
- Dot1Q(vlan=100) /
- IP(src="10.220.0.1", dst="10.222.0.1") /
- UDP(sport=1222, dport=1235) /
- Raw(b'\xa5' * 100))]
-
- rxs = self.send_and_expect(self.pg0, p, self.pg7)
-
- self.assertEqual(rxs[0][VXLAN].vni, 445)
- self.assertEqual(rxs[1][VXLAN].vni, 446)
-
- #
- # Same LB test for v6
- #
- n3 = VppNeighbor(self,
- vx_tun_r1.sw_if_index,
- "00:0c:0c:0c:0c:0c",
- self.pg7.remote_ip6)
- n3.add_vpp_config()
- n4 = VppNeighbor(self,
- vx_tun_r2.sw_if_index,
- "00:0c:0c:0c:0c:0c",
- self.pg7.remote_ip6)
- n4.add_vpp_config()
-
- ip_222_6 = VppIpRoute(self, "10:222::", 64,
- [VppRoutePath(self.pg7.remote_ip6,
- vx_tun_r1.sw_if_index),
- VppRoutePath(self.pg7.remote_ip6,
- vx_tun_r2.sw_if_index)],
- table_id=t6.table_id)
- ip_222_6.add_vpp_config()
-
- l3o_222_6 = VppGbpSubnet(
- self, rd1, "10:222::", 64,
- VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
- sclass=4222)
- l3o_222_6.add_vpp_config()
-
- p = [(Ether(src=eep1.mac, dst=str(self.router_mac)) /
- Dot1Q(vlan=100) /
- IPv6(src="10:220::1", dst="10:222::1") /
- UDP(sport=1234, dport=1234) /
- Raw(b'\xa5' * 100)),
- (Ether(src=eep1.mac, dst=str(self.router_mac)) /
- Dot1Q(vlan=100) /
- IPv6(src="10:220::1", dst="10:222::1") /
- UDP(sport=7777, dport=8881) /
- Raw(b'\xa5' * 100))]
-
- self.logger.info(self.vapi.cli("sh ip6 fib 10:222::1"))
- rxs = self.send_and_expect(self.pg0, p, self.pg7)
-
- self.assertEqual(rxs[0][VXLAN].vni, 445)
- self.assertEqual(rxs[1][VXLAN].vni, 446)
-
- #
- # ping from host in remote to local external subnets
- # there's no contract for this, but the A bit is set.
- #
- p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
- IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
- UDP(sport=1234, dport=48879) /
- VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
- Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
- IP(src="10.222.0.1", dst="10.220.0.1") /
- UDP(sport=1234, dport=1234) /
- Raw(b'\xa5' * 100))
-
- rxs = self.send_and_expect(self.pg7, p * 3, self.pg0)
- self.assertFalse(find_gbp_endpoint(self, ip="10.222.0.1"))
-
- #
- # ping from host in remote to remote external subnets
- # this is dropped by reflection check.
- #
- p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
- IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
- UDP(sport=1234, dport=48879) /
- VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
- Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
- IP(src="10.222.0.1", dst="10.222.0.2") /
- UDP(sport=1234, dport=1234) /
- Raw(b'\xa5' * 100))
-
- rxs = self.send_and_assert_no_replies(self.pg7, p * 3)
-
- p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
- IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
- UDP(sport=1234, dport=48879) /
- VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
- Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
- IPv6(src="10:222::1", dst="10:222::2") /
- UDP(sport=1234, dport=1234) /
- Raw(b'\xa5' * 100))
-
- rxs = self.send_and_assert_no_replies(self.pg7, p * 3)
-
- #
- # local EP
- #
- lep1 = VppGbpEndpoint(self, vlan_144,
- epg_220, None,
- "10.0.0.44", "11.0.0.44",
- "2001:10::44", "3001::44")
- lep1.add_vpp_config()
-
- #
- # local EP to local ip4 external subnet
- #
- p = (Ether(src=lep1.mac, dst=str(self.router_mac)) /
- Dot1Q(vlan=144) /
- IP(src=lep1.ip4, dst="10.220.0.1") /
- UDP(sport=1234, dport=1234) /
- Raw(b'\xa5' * 100))
-
- rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
-
- for rx in rxs:
- self.assertEqual(rx[Ether].src, str(self.router_mac))
- self.assertEqual(rx[Ether].dst, eep1.mac)
- self.assertEqual(rx[Dot1Q].vlan, 100)
-
- #
- # local EP to local ip6 external subnet
- #
- p = (Ether(src=lep1.mac, dst=str(self.router_mac)) /
- Dot1Q(vlan=144) /
- IPv6(src=lep1.ip6, dst="10:220::1") /
- UDP(sport=1234, dport=1234) /
- Raw(b'\xa5' * 100))
-
- rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
-
- for rx in rxs:
- self.assertEqual(rx[Ether].src, str(self.router_mac))
- self.assertEqual(rx[Ether].dst, eep1.mac)
- self.assertEqual(rx[Dot1Q].vlan, 100)
-
- #
- # ip4 and ip6 subnets that load-balance
- #
- ip_20 = VppIpRoute(self, "10.20.0.0", 24,
- [VppRoutePath(eep1.ip4,
- eep1.epg.bvi.sw_if_index),
- VppRoutePath(eep2.ip4,
- eep2.epg.bvi.sw_if_index)],
- table_id=t4.table_id)
- ip_20.add_vpp_config()
-
- l3o_20 = VppGbpSubnet(
- self, rd1, "10.20.0.0", 24,
- VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
- sclass=4220)
- l3o_20.add_vpp_config()
-
- ip6_20 = VppIpRoute(self, "10:20::", 64,
- [VppRoutePath(eep1.ip6,
- eep1.epg.bvi.sw_if_index),
- VppRoutePath(eep2.ip6,
- eep2.epg.bvi.sw_if_index)],
- table_id=t6.table_id)
- ip6_20.add_vpp_config()
-
- l3o6_20 = VppGbpSubnet(
- self, rd1, "10:20::", 64,
- VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
- sclass=4220)
- l3o6_20.add_vpp_config()
-
- self.logger.info(self.vapi.cli("sh ip fib 10.20.0.1"))
- self.logger.info(self.vapi.cli("sh ip6 fib 10:20::1"))
-
- # two ip6 packets whose port are chosen so they load-balance
- p = [(Ether(src=lep1.mac, dst=str(self.router_mac)) /
- Dot1Q(vlan=144) /
- IPv6(src=lep1.ip6, dst="10:20::1") /
- UDP(sport=1234, dport=1234) /
- Raw(b'\xa5' * 100)),
- (Ether(src=lep1.mac, dst=str(self.router_mac)) /
- Dot1Q(vlan=144) /
- IPv6(src=lep1.ip6, dst="10:20::1") /
- UDP(sport=124, dport=1230) /
- Raw(b'\xa5' * 100))]
-
- rxs = self.send_and_expect(self.pg0, p, self.pg0, 2)
-
- self.assertEqual(rxs[0][Dot1Q].vlan, 101)
- self.assertEqual(rxs[1][Dot1Q].vlan, 100)
-
- # two ip4 packets whose port are chosen so they load-balance
- p = [(Ether(src=lep1.mac, dst=str(self.router_mac)) /
- Dot1Q(vlan=144) /
- IP(src=lep1.ip4, dst="10.20.0.1") /
- UDP(sport=1235, dport=1235) /
- Raw(b'\xa5' * 100)),
- (Ether(src=lep1.mac, dst=str(self.router_mac)) /
- Dot1Q(vlan=144) /
- IP(src=lep1.ip4, dst="10.20.0.1") /
- UDP(sport=124, dport=1230) /
- Raw(b'\xa5' * 100))]
-
- rxs = self.send_and_expect(self.pg0, p, self.pg0, 2)
-
- self.assertEqual(rxs[0][Dot1Q].vlan, 101)
- self.assertEqual(rxs[1][Dot1Q].vlan, 100)
-
- #
- # cleanup
- #
- ip_222.remove_vpp_config()
- self.pg7.unconfig_ip4()
- self.vlan_101.set_vtr(L2_VTR_OP.L2_DISABLED)
- self.vlan_100.set_vtr(L2_VTR_OP.L2_DISABLED)
-
- def test_gbp_anon_l3_out(self):
- """ GBP Anonymous L3 Out """
-
- ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
- self.vapi.cli("set logging class gbp level debug")
-
- routed_dst_mac = "00:0c:0c:0c:0c:0c"
- routed_src_mac = "00:22:bd:f8:19:ff"
-
- #
- # IP tables
- #
- t4 = VppIpTable(self, 1)
- t4.add_vpp_config()
- t6 = VppIpTable(self, 1, True)
- t6.add_vpp_config()
-
- rd1 = VppGbpRouteDomain(self, 2, 55, t4, t6)
- rd1.add_vpp_config()
-
- self.loop0.set_mac(self.router_mac)
-
- #
- # Bind the BVI to the RD
- #
- bind_l0_ip4 = VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
- bind_l0_ip6 = VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
-
- #
- # Pg7 hosts a BD's BUM
- # Pg1 some other l3 interface
- #
- self.pg7.config_ip4()
- self.pg7.resolve_arp()
-
- #
- # a GBP external bridge domains for the EPs
- #
- bd1 = VppBridgeDomain(self, 1)
- bd1.add_vpp_config()
- gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0, None, None)
- gbd1.add_vpp_config()
-
- #
- # The Endpoint-groups in which the external endpoints exist
- #
- epg_220 = VppGbpEndpointGroup(self, 220, 113, rd1, gbd1,
- None, gbd1.bvi,
- "10.0.0.128",
- "2001:10::128",
- VppGbpEndpointRetention(4))
- epg_220.add_vpp_config()
-
- # the BVIs have the subnet applied ...
- ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi,
- "10.0.0.128", 24,
- bind=bind_l0_ip4).add_vpp_config()
-
- # ... which is an Anonymous L3-out subnets
- l3o_1 = VppGbpSubnet(
- self, rd1, "10.0.0.0", 24,
- VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_ANON_L3_OUT,
- sclass=113)
- l3o_1.add_vpp_config()
-
- #
- # an external interface attached to the outside world and the
- # external BD
- #
- VppL2Vtr(self, self.vlan_100, L2_VTR_OP.L2_POP_1).add_vpp_config()
- VppL2Vtr(self, self.vlan_101, L2_VTR_OP.L2_POP_1).add_vpp_config()
-
- #
- # vlan_100 and vlan_101 are anonymous l3-out interfaces
- #
- ext_itf = VppGbpExtItf(self, self.vlan_100, bd1, rd1, anon=True)
- ext_itf.add_vpp_config()
- ext_itf = VppGbpExtItf(self, self.vlan_101, bd1, rd1, anon=True)
- ext_itf.add_vpp_config()
-
- #
- # an unicast vxlan-gbp for inter-RD traffic
- #
- vx_tun_l3 = VppGbpVxlanTunnel(
- self, 444, rd1.rd_id,
- VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
- self.pg2.local_ip4)
- vx_tun_l3.add_vpp_config()
-
- #
- # A remote external endpoint
- #
- rep = VppGbpEndpoint(self, vx_tun_l3,
- epg_220, None,
- "10.0.0.201", "11.0.0.201",
- "2001:10::201", "3001::101",
- ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
- self.pg7.local_ip4,
- self.pg7.remote_ip4,
- mac=None)
- rep.add_vpp_config()
-
- #
- # ARP packet from host in external subnet are accepted, flooded and
- # replied to. We expect 2 packets:
- # - APR request flooded over the other vlan subif
- # - ARP reply from BVI
- #
- p_arp = (Ether(src=self.vlan_100.remote_mac,
- dst="ff:ff:ff:ff:ff:ff") /
- Dot1Q(vlan=100) /
- ARP(op="who-has",
- psrc="10.0.0.100",
- pdst="10.0.0.128",
- hwsrc=self.vlan_100.remote_mac,
- hwdst="ff:ff:ff:ff:ff:ff"))
- rxs = self.send_and_expect(self.pg0, p_arp * 1, self.pg0, n_rx=2)
-
- p_arp = (Ether(src=self.vlan_101.remote_mac,
- dst="ff:ff:ff:ff:ff:ff") /
- Dot1Q(vlan=101) /
- ARP(op="who-has",
- psrc='10.0.0.101',
- pdst="10.0.0.128",
- hwsrc=self.vlan_101.remote_mac,
- hwdst="ff:ff:ff:ff:ff:ff"))
- rxs = self.send_and_expect(self.pg0, p_arp * 1, self.pg0, n_rx=2)
-
- #
- # remote to external
- #
- p = (Ether(src=self.pg7.remote_mac,
- dst=self.pg7.local_mac) /
- IP(src=self.pg7.remote_ip4,
- dst=self.pg7.local_ip4) /
- UDP(sport=1234, dport=48879) /
- VXLAN(vni=vx_tun_l3.vni, gpid=epg_220.sclass, flags=0x88) /
- Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
- IP(src=str(rep.ip4), dst="10.0.0.100") /
- UDP(sport=1234, dport=1234) /
- Raw(b'\xa5' * 100))
- rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
-
- #
- # local EP pings router
- #
- p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
- Dot1Q(vlan=100) /
- IP(src="10.0.0.100", dst="10.0.0.128") /
- ICMP(type='echo-request'))
- rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
-
- for rx in rxs:
- self.assertEqual(rx[Ether].src, str(self.router_mac))
- self.assertEqual(rx[Ether].dst, self.vlan_100.remote_mac)
- self.assertEqual(rx[Dot1Q].vlan, 100)
-
- #
- # local EP pings other local EP
- #
- p = (Ether(src=self.vlan_100.remote_mac,
- dst=self.vlan_101.remote_mac) /
- Dot1Q(vlan=100) /
- IP(src="10.0.0.100", dst="10.0.0.101") /
- ICMP(type='echo-request'))
- rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
-
- for rx in rxs:
- self.assertEqual(rx[Ether].src, self.vlan_100.remote_mac)
- self.assertEqual(rx[Ether].dst, self.vlan_101.remote_mac)
- self.assertEqual(rx[Dot1Q].vlan, 101)
-
- #
- # A subnet reachable through an external router on vlan 100
- #
- ip_220 = VppIpRoute(self, "10.220.0.0", 24,
- [VppRoutePath("10.0.0.100",
- epg_220.bvi.sw_if_index)],
- table_id=t4.table_id)
- ip_220.add_vpp_config()
-
- l3o_220 = VppGbpSubnet(
- self, rd1, "10.220.0.0", 24,
- # note: this a "regular" L3 out subnet (not connected)
- VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
- sclass=4220)
- l3o_220.add_vpp_config()
-
- #
- # A subnet reachable through an external router on vlan 101
- #
- ip_221 = VppIpRoute(self, "10.221.0.0", 24,
- [VppRoutePath("10.0.0.101",
- epg_220.bvi.sw_if_index)],
- table_id=t4.table_id)
- ip_221.add_vpp_config()
-
- l3o_221 = VppGbpSubnet(
- self, rd1, "10.221.0.0", 24,
- # note: this a "regular" L3 out subnet (not connected)
- VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
- sclass=4221)
- l3o_221.add_vpp_config()
-
- #
- # ping between hosts in remote subnets
- # dropped without a contract
- #
- p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
- Dot1Q(vlan=100) /
- IP(src="10.220.0.1", dst="10.221.0.1") /
- ICMP(type='echo-request'))
-
- rxs = self.send_and_assert_no_replies(self.pg0, p * 1)
-
- #
- # contract for the external nets to communicate
- #
- rule4 = AclRule(is_permit=1, proto=17)
- rule6 = AclRule(src_prefix=IPv6Network((0, 0)),
- dst_prefix=IPv6Network((0, 0)), is_permit=1, proto=17)
- acl = VppAcl(self, rules=[rule4, rule6])
- acl.add_vpp_config()
-
- c1 = VppGbpContract(
- self, 55, 4220, 4221, acl.acl_index,
- [VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
- []),
- VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
- [])],
- [ETH_P_IP, ETH_P_IPV6])
- c1.add_vpp_config()
-
- #
- # Contracts allowing ext-net 200 to talk with external EPs
- #
- c2 = VppGbpContract(
- self, 55, 4220, 113, acl.acl_index,
- [VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
- []),
- VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
- [])],
- [ETH_P_IP, ETH_P_IPV6])
- c2.add_vpp_config()
- c3 = VppGbpContract(
- self, 55, 113, 4220, acl.acl_index,
- [VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
- []),
- VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
- [])],
- [ETH_P_IP, ETH_P_IPV6])
- c3.add_vpp_config()
-
- #
- # ping between hosts in remote subnets
- #
- p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
- Dot1Q(vlan=100) /
- IP(src="10.220.0.1", dst="10.221.0.1") /
- UDP(sport=1234, dport=1234) /
- Raw(b'\xa5' * 100))
-
- rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
-
- for rx in rxs:
- self.assertEqual(rx[Ether].src, str(self.router_mac))
- self.assertEqual(rx[Ether].dst, self.vlan_101.remote_mac)
- self.assertEqual(rx[Dot1Q].vlan, 101)
-
- # we did not learn these external hosts
- self.assertFalse(find_gbp_endpoint(self, ip="10.220.0.1"))
- self.assertFalse(find_gbp_endpoint(self, ip="10.221.0.1"))
-
- #
- # from remote external EP to local external EP
- #
- p = (Ether(src=self.pg7.remote_mac,
- dst=self.pg7.local_mac) /
- IP(src=self.pg7.remote_ip4,
- dst=self.pg7.local_ip4) /
- UDP(sport=1234, dport=48879) /
- VXLAN(vni=444, gpid=113, flags=0x88) /
- Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
- IP(src=rep.ip4, dst="10.220.0.1") /
- UDP(sport=1234, dport=1234) /
- Raw(b'\xa5' * 100))
-
- rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
-
- #
- # ping from an external host to the remote external EP
- #
- p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
- Dot1Q(vlan=100) /
- IP(src="10.220.0.1", dst=rep.ip4) /
- UDP(sport=1234, dport=1234) /
- Raw(b'\xa5' * 100))
-
- rxs = self.send_and_expect(self.pg0, p * 1, self.pg7)
-
- for rx in rxs:
- self.assertEqual(rx[Ether].src, self.pg7.local_mac)
- # self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
- self.assertEqual(rx[IP].src, self.pg7.local_ip4)
- self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
- self.assertEqual(rx[VXLAN].vni, 444)
- self.assertTrue(rx[VXLAN].flags.G)
- self.assertTrue(rx[VXLAN].flags.Instance)
- # the sclass of the ext-net the packet came from
- self.assertEqual(rx[VXLAN].gpid, 4220)
- # policy was applied to the original IP packet
- self.assertTrue(rx[VXLAN].gpflags.A)
- # since it's an external host the reciever should not learn it
- self.assertTrue(rx[VXLAN].gpflags.D)
- inner = rx[VXLAN].payload
- self.assertEqual(inner[IP].src, "10.220.0.1")
- self.assertEqual(inner[IP].dst, rep.ip4)
-
- #
- # An external subnet reachable via the remote external EP
- #
-
- #
- # first the VXLAN-GBP tunnel over which it is reached
- #
- vx_tun_r = VppVxlanGbpTunnel(
- self, self.pg7.local_ip4,
- self.pg7.remote_ip4, 445,
- mode=(VppEnum.vl_api_vxlan_gbp_api_tunnel_mode_t.
- VXLAN_GBP_API_TUNNEL_MODE_L3))
- vx_tun_r.add_vpp_config()
- VppIpInterfaceBind(self, vx_tun_r, t4).add_vpp_config()
-
- self.logger.info(self.vapi.cli("sh vxlan-gbp tunnel"))
-
- #
- # then the special adj to resolve through on that tunnel
- #
- n1 = VppNeighbor(self,
- vx_tun_r.sw_if_index,
- "00:0c:0c:0c:0c:0c",
- self.pg7.remote_ip4)
- n1.add_vpp_config()
-
- #
- # the route via the adj above
- #
- ip_222 = VppIpRoute(self, "10.222.0.0", 24,
- [VppRoutePath(self.pg7.remote_ip4,
- vx_tun_r.sw_if_index)],
- table_id=t4.table_id)
- ip_222.add_vpp_config()
-
- l3o_222 = VppGbpSubnet(
- self, rd1, "10.222.0.0", 24,
- # note: this a "regular" l3out subnet (not connected)
- VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
- sclass=4222)
- l3o_222.add_vpp_config()
-
- #
- # ping between hosts in local and remote external subnets
- # dropped without a contract
- #
- p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
- Dot1Q(vlan=100) /
- IP(src="10.220.0.1", dst="10.222.0.1") /
- UDP(sport=1234, dport=1234) /
- Raw(b'\xa5' * 100))
-
- rxs = self.send_and_assert_no_replies(self.pg0, p * 1)
-
- #
- # Add contracts ext-nets for 220 -> 222
- #
- c4 = VppGbpContract(
- self, 55, 4220, 4222, acl.acl_index,
- [VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
- []),
- VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
- [])],
- [ETH_P_IP, ETH_P_IPV6])
- c4.add_vpp_config()
-
- #
- # ping from host in local to remote external subnets
- #
- p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
- Dot1Q(vlan=100) /
- IP(src="10.220.0.1", dst="10.222.0.1") /
- UDP(sport=1234, dport=1234) /
- Raw(b'\xa5' * 100))
-
- rxs = self.send_and_expect(self.pg0, p * 3, self.pg7)
-
- for rx in rxs:
- self.assertEqual(rx[Ether].src, self.pg7.local_mac)
- self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
- self.assertEqual(rx[IP].src, self.pg7.local_ip4)
- self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
- self.assertEqual(rx[VXLAN].vni, 445)
- self.assertTrue(rx[VXLAN].flags.G)
- self.assertTrue(rx[VXLAN].flags.Instance)
- # the sclass of the ext-net the packet came from
- self.assertEqual(rx[VXLAN].gpid, 4220)
- # policy was applied to the original IP packet
- self.assertTrue(rx[VXLAN].gpflags.A)
- # since it's an external host the reciever should not learn it
- self.assertTrue(rx[VXLAN].gpflags.D)
- inner = rx[VXLAN].payload
- self.assertEqual(inner[Ether].dst, "00:0c:0c:0c:0c:0c")
- self.assertEqual(inner[IP].src, "10.220.0.1")
- self.assertEqual(inner[IP].dst, "10.222.0.1")
-
- #
- # ping from host in remote to local external subnets
- # there's no contract for this, but the A bit is set.
- #
- p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
- IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
- UDP(sport=1234, dport=48879) /
- VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
- Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
- IP(src="10.222.0.1", dst="10.220.0.1") /
- UDP(sport=1234, dport=1234) /
- Raw(b'\xa5' * 100))
-
- rxs = self.send_and_expect(self.pg7, p * 3, self.pg0)
- self.assertFalse(find_gbp_endpoint(self, ip="10.222.0.1"))
-
- #
- # ping from host in remote to remote external subnets
- # this is dropped by reflection check.
- #
- p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
- IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
- UDP(sport=1234, dport=48879) /
- VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
- Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
- IP(src="10.222.0.1", dst="10.222.0.2") /
- UDP(sport=1234, dport=1234) /
- Raw(b'\xa5' * 100))
-
- rxs = self.send_and_assert_no_replies(self.pg7, p * 3)
-
- #
- # cleanup
- #
- self.vlan_101.set_vtr(L2_VTR_OP.L2_DISABLED)
- self.vlan_100.set_vtr(L2_VTR_OP.L2_DISABLED)
- self.pg7.unconfig_ip4()
- # make sure the programmed EP is no longer learnt from DP
- self.wait_for_ep_timeout(sw_if_index=rep.itf.sw_if_index, ip=rep.ip4)
-
-
-if __name__ == '__main__':
- unittest.main(testRunner=VppTestRunner)