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
+ 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, ETH_P_ARP
from vpp_object import VppObject
from vpp_interface import VppInterface
from vpp_ip_route import VppIpRoute, VppRoutePath, VppIpTable, \
- VppIpInterfaceAddress, VppIpInterfaceBind, find_route
+ 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 VppIpAddress, VppIpPrefix
+from vpp_ip import VppIpAddress, VppIpPrefix, DpoProto
from vpp_papi import VppEnum, MACAddress
from vpp_vxlan_gbp_tunnel import find_vxlan_gbp_tunnel, INDEX_INVALID, \
VppVxlanGbpTunnel
from vpp_neighbor import VppNeighbor
+try:
+ text_type = unicode
+except NameError:
+ text_type = str
NUM_PKTS = 67
-def find_gbp_endpoint(test, sw_if_index=None, ip=None, mac=None):
+def find_gbp_endpoint(test, sw_if_index=None, ip=None, mac=None,
+ tep=None, sclass=None):
if ip:
vip = VppIpAddress(ip)
if mac:
eps = test.vapi.gbp_endpoint_dump()
for ep in eps:
+ if tep:
+ src = VppIpAddress(tep[0])
+ dst = VppIpAddress(tep[1])
+ if src != ep.endpoint.tun.src or dst != 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 ip:
for eip in ep.endpoint.ips:
if vip == eip:
if mac:
if vmac.packed == ep.endpoint.mac:
return True
+
return False
GBP ExtItfulation Interface
"""
- def __init__(self, test, itf, bd, rd):
+ 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 add_vpp_config(self):
self._test.vapi.gbp_ext_itf_add_del(
- 1,
- self.itf.sw_if_index,
- self.bd.bd_id,
- self.rd.rd_id)
+ 1, self.itf.sw_if_index, self.bd.bd_id, self.rd.rd_id, self.flags)
self._test.registry.register(self, self._test.logger)
def remove_vpp_config(self):
self._test.vapi.gbp_ext_itf_add_del(
- 0,
- self.itf.sw_if_index,
- self.bd.bd_id,
- self.rd.rd_id)
+ 0, self.itf.sw_if_index, self.bd.bd_id, self.rd.rd_id, self.flags)
def object_id(self):
- return "gbp-ext-itf:[%d]" % (self.itf.sw_if_index)
+ 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()
GBP Bridge Domain
"""
- def __init__(self, test, bd, bvi, uu_fwd=None,
- bm_flood=None, learn=True, uu_drop=False, bm_drop=False):
+ def __init__(self, test, bd, rd, bvi, uu_fwd=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
- if (learn):
- self.learn = e.GBP_BD_API_FLAG_NONE
- else:
- self.learn = e.GBP_BD_API_FLAG_DO_NOT_LEARN
- if (uu_drop):
- self.learn |= e.GBP_BD_API_FLAG_UU_FWD_DROP
- if (bm_drop):
- self.learn |= e.GBP_BD_API_FLAG_MCAST_DROP
+
+ 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 add_vpp_config(self):
self._test.vapi.gbp_bridge_domain_add(
self.bd.bd_id,
- self.learn,
+ self.rd.rd_id,
+ self.flags,
self.bvi.sw_if_index,
self.uu_fwd.sw_if_index if self.uu_fwd else INDEX_INVALID,
self.bm_flood.sw_if_index if self.bm_flood else INDEX_INVALID)
GBP Route Domain
"""
- def __init__(self, test, rd_id, t4, t6, ip4_uu=None, ip6_uu=None):
+ 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
def add_vpp_config(self):
self._test.vapi.gbp_route_domain_add(
self.rd_id,
+ self.scope,
self.t4.table_id,
self.t6.table_id,
self.ip4_uu.sw_if_index if self.ip4_uu else INDEX_INVALID,
class VppGbpContractRule():
- def __init__(self, action, hash_mode, nhs=[]):
+ def __init__(self, action, hash_mode, nhs=None):
self.action = action
self.hash_mode = hash_mode
- self.nhs = nhs
+ self.nhs = [] if nhs is None else nhs
def encode(self):
nhs = []
'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, sclass, dclass, acl_index,
+ def __init__(self, test, scope, sclass, dclass, acl_index,
rules, allowed_ethertypes):
self._test = test
+ if not isinstance(rules, list):
+ raise ValueError("'rules' must be a list.")
+ if not isinstance(allowed_ethertypes, list):
+ raise ValueError("'allowed_ethertypes' must be a list.")
+ self.scope = scope
self.acl_index = acl_index
self.sclass = sclass
self.dclass = dclass
for r in self.rules:
rules.append(r.encode())
r = self._test.vapi.gbp_contract_add_del(
- 1,
- self.sclass,
- self.dclass,
- self.acl_index,
- rules,
- self.allowed_ethertypes)
+ is_add=1,
+ contract={
+ '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})
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(
- 0,
- self.sclass,
- self.dclass,
- self.acl_index,
- [],
- self.allowed_ethertypes)
+ is_add=0,
+ contract={
+ 'acl_index': self.acl_index,
+ 'scope': self.scope,
+ 'sclass': self.sclass,
+ 'dclass': self.dclass,
+ 'n_rules': 0,
+ 'rules': [],
+ 'n_ether_types': len(self.allowed_ethertypes),
+ 'allowed_ethertypes': self.allowed_ethertypes})
def object_id(self):
- return "gbp-contract:[%d:%s:%d]" % (self.sclass,
- self.dclass,
- self.acl_index)
+ 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.sclass == self.sclass \
- and c.contract.dclass == self.dclass:
+ if c.contract.scope == self.scope \
+ and c.contract.sclass == self.sclass \
+ and c.contract.dclass == self.dclass:
return True
return False
def add_vpp_config(self, rules):
- reply = self._test.vapi.acl_add_replace(self.acl_index,
+ reply = self._test.vapi.acl_add_replace(acl_index=self.acl_index,
r=rules,
tag=b'GBPTest')
self.acl_index = reply.acl_index
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()
+ 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)
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)
ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
- #
- # 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, self.loop0)
- gbd2 = VppGbpBridgeDomain(self, bd2, self.loop1)
- gbd20 = VppGbpBridgeDomain(self, bd20, self.loop2)
-
- gbd1.add_vpp_config()
- gbd2.add_vpp_config()
- gbd20.add_vpp_config()
-
#
# Route Domains
#
nt6 = VppIpTable(self, 20, is_ip6=True)
nt6.add_vpp_config()
- rd0 = VppGbpRouteDomain(self, 0, gt4, gt6, None, None)
- rd20 = VppGbpRouteDomain(self, 20, nt4, nt6, None, None)
+ 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
# 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.bvi_ip4.address)
epg.bd_arp_ip6 = VppBridgeDomainArpEntry(self, epg.bd.bd,
str(self.router_mac),
- epg.bvi_ip6)
+ epg.bvi_ip6.address)
epg.bd_arp_ip4.add_vpp_config()
epg.bd_arp_ip6.add_vpp_config()
# 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 = VppBridgeDomainArpEntry(self, epg_nat.bd.bd, ep.mac,
+ fip.address)
ba.add_vpp_config()
# floating IPs route via EPG recirc
- r = VppIpRoute(self, fip.address, fip.length,
- [VppRoutePath(fip.address,
- ep.recirc.recirc.sw_if_index,
- is_dvr=1,
- proto=fip.dpo_proto)],
- table_id=20,
- is_ip6=fip.is_ip6)
+ r = VppIpRoute(
+ self, fip.address, fip.length,
+ [VppRoutePath(fip.address,
+ ep.recirc.recirc.sw_if_index,
+ type=FibPathType.FIB_PATH_TYPE_DVR,
+ proto=fip.dpo_proto)],
+ table_id=20)
r.add_vpp_config()
# L2 FIB entries in the NAT EPG BD to bridge the packets from
rule2 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
acl_index = acl.add_vpp_config([rule, rule2])
c1 = VppGbpContract(
- self, epgs[0].sclass, epgs[1].sclass, acl_index,
+ self, 400, epgs[0].sclass, epgs[1].sclass, 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()
# contract for the return direction
#
c2 = VppGbpContract(
- self, epgs[1].sclass, epgs[0].sclass, acl_index,
+ self, 400, epgs[1].sclass, epgs[0].sclass, 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()
# A uni-directional contract from EPG 220 -> 222 'L3 routed'
#
c3 = VppGbpContract(
- self, epgs[0].sclass, epgs[2].sclass, acl_index,
+ self, 400, epgs[0].sclass, epgs[2].sclass, 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()
acl_index2 = acl2.add_vpp_config([rule, rule2])
c4 = VppGbpContract(
- self, epgs[0].sclass, epgs[3].sclass, acl_index2,
+ self, 400, epgs[0].sclass, epgs[3].sclass, acl_index2,
[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.pg7, pkt_inter_epg_220_from_global * NUM_PKTS)
c5 = VppGbpContract(
- self, epgs[3].sclass, epgs[0].sclass, acl_index2,
+ self, 400, epgs[3].sclass, epgs[0].sclass, acl_index2,
[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()
sw_if_index=recirc.recirc.sw_if_index)
def wait_for_ep_timeout(self, sw_if_index=None, ip=None, mac=None,
- n_tries=100, s_time=1):
+ tep=None, n_tries=100, s_time=1):
while (n_tries):
- if not find_gbp_endpoint(self, sw_if_index, ip, mac):
+ if not find_gbp_endpoint(self, sw_if_index, ip, mac, tep=tep):
return True
n_tries = n_tries - 1
self.sleep(s_time)
def test_gbp_learn_l2(self):
""" GBP L2 Endpoint Learning """
- self.vapi.cli("clear errors")
+ 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',
gt6 = VppIpTable(self, 1, is_ip6=True)
gt6.add_vpp_config()
- rd1 = VppGbpRouteDomain(self, 1, gt4, gt6)
+ rd1 = VppGbpRouteDomain(self, 1, 401, gt4, gt6)
rd1.add_vpp_config()
#
#
bd1 = VppBridgeDomain(self, 1)
bd1.add_vpp_config()
- gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0, self.pg3, tun_bm)
+ 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.send_and_assert_no_replies(self.pg2, p)
self.logger.info(self.vapi.cli("sh error"))
- # self.assert_packet_counter_equal(
- # '/err/gbp-policy-port/drop-no-contract', 1)
+ 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
self.pg2.remote_hosts[0].ip4,
99))
- # epg is not learnt, because the EPG is unknown
+ # ep is not learnt, because the EPG is unknown
self.assertEqual(len(self.vapi.gbp_endpoint_dump()), 1)
#
vx_tun_l2_1.sw_if_index,
ip=l['ip']))
- # self.assert_packet_counter_equal(
- # '/err/gbp-policy-port/allow-intra-sclass', 2)
+ 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"))
# Learn new EPs from GARP packets received on the BD's mcast tunnel
#
for ii, l in enumerate(learnt):
- # a packet with an sclass from a known EPG
- # arriving on an unknown TEP
+ # 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, gpid=112, flags=0x88) /
+ 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'],
#
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=0x88) /
+ VXLAN(vni=99, gpid=112, flags=0xc8) /
Ether(src=l['mac'], dst=ep.mac) /
IP(src=l['ip'], dst=ep.ip4.address) /
UDP(sport=1234, dport=1234) /
rule2 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
acl_index = acl.add_vpp_config([rule, rule2])
c1 = VppGbpContract(
- self, epg_220.sclass, epg_330.sclass, acl_index,
+ self, 401, epg_220.sclass, epg_330.sclass, 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,
- [])],
+ 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()
#
# send UU packets from the local EP
#
- 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 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.address) /
UDP(sport=1234, dport=1234) /
self.assertFalse(rx[VXLAN].gpflags.A)
self.assertFalse(rx[VXLAN].gpflags.D)
+ acl = VppGbpAcl(self)
+ rule = acl.create_rule(permit_deny=1, proto=17)
+ rule2 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
+ acl_index = acl.add_vpp_config([rule, rule2])
+ c2 = VppGbpContract(
+ self, 401, epg_330.sclass, epg_220.sclass, 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
+ # Check v6 Endpoints learning
#
for l in learnt:
# a packet with an sclass from a known EPG
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') /
+ VXLAN(vni=99, gpid=113, flags=0x88) /
Ether(src=l['mac'], dst=ep.mac) /
IPv6(src=l['ip6'], dst=ep.ip6.address) /
UDP(sport=1234, dport=1234) /
Raw('\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,
- mac=l['mac']))
+ 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.address) /
+ UDP(sport=1234, dport=1234) /
+ Raw('\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.address) /
+ UDP(sport=1234, dport=1234) /
+ Raw('\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.address) /
+ UDP(sport=1234, dport=1234) /
+ Raw('\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]))
#
- # L3 Endpoint Learning
- # - configured on the bridge's BVI
+ # 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.address) /
+ UDP(sport=1234, dport=1234) /
+ Raw('\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
self.pg3.unconfig_ip4()
self.pg4.unconfig_ip4()
- self.logger.info(self.vapi.cli("sh int"))
- self.logger.info(self.vapi.cli("sh gbp vxlan"))
-
def test_gbp_contract(self):
- """ GBP CONTRACTS """
+ """ 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.add_vpp_config()
bd2.add_vpp_config()
- gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0)
- gbd2 = VppGbpBridgeDomain(self, bd2, self.loop1)
+ gbd1 = VppGbpBridgeDomain(self, bd1, rd0, self.loop0)
+ gbd2 = VppGbpBridgeDomain(self, bd2, rd0, self.loop1)
gbd1.add_vpp_config()
gbd2.add_vpp_config()
- #
- # 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, gt4, gt6, None, None)
-
- rd0.add_vpp_config()
-
#
# 3 EPGs, 2 of which share a BD.
#
# 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.bvi_ip4.address)
epg.bd_arp_ip4.add_vpp_config()
# EPG in VPP
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.address,
+ dst=eps[1].ip6.address) /
+ UDP(sport=1234, dport=1234) /
+ Raw('\xa5' * 100))
+
+ self.send_and_expect_bridged6(self.pg0,
+ pkt_intra_epg_220_to_220 * 65,
+ self.pg1)
+
#
# Inter epg denied without contract
#
acl = VppGbpAcl(self)
rule = acl.create_rule(permit_deny=1, proto=17)
rule2 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
- acl_index = acl.add_vpp_config([rule, rule2])
+ rule3 = acl.create_rule(permit_deny=1, proto=1)
+ acl_index = acl.add_vpp_config([rule, rule2, rule3])
c1 = VppGbpContract(
- self, epgs[0].sclass, epgs[1].sclass, acl_index,
+ self, 400, epgs[0].sclass, epgs[1].sclass, 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_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.address,
+ dst=epgs[1].bvi_ip4.address) /
+ 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.address,
+ dst=epgs[1].bvi_ip6.address) /
+ ICMPv6EchoRequest())
+
+ self.send_and_expect(self.pg0, [pkt_router_ping_220_to_221], self.pg0)
+
#
# contract for the return direction
#
c2 = VppGbpContract(
- self, epgs[1].sclass, epgs[0].sclass, acl_index,
+ self, 400, epgs[1].sclass, epgs[0].sclass, 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[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.address,
+ dst=eps[0].ip4.address) /
+ UDP(sport=1234, dport=1234) /
+ Raw('\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.address,
+ dst=eps[0].ip6.address) /
+ UDP(sport=1234, dport=1234) /
+ Raw('\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, epgs[0].sclass, epgs[2].sclass, acl_index,
+ self, 400, epgs[0].sclass, epgs[2].sclass, 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()
c2.remove_vpp_config()
acl.remove_vpp_config()
- def test_gbp_bd_flags(self):
- """ GBP BD FLAGS """
+ def test_gbp_bd_drop_flags(self):
+ """ GBP BD drop flags """
#
# IP tables
gt6 = VppIpTable(self, 1, is_ip6=True)
gt6.add_vpp_config()
- rd1 = VppGbpRouteDomain(self, 1, gt4, gt6)
+ rd1 = VppGbpRouteDomain(self, 1, 401, gt4, gt6)
rd1.add_vpp_config()
#
- # Pg3 hosts the IP4 UU-flood VXLAN tunnel
- # Pg4 hosts the IP6 UU-flood VXLAN tunnel
+ # a GBP bridge domain with a BVI only
#
- self.pg3.config_ip4()
- self.pg3.resolve_arp()
- self.pg4.config_ip4()
- self.pg4.resolve_arp()
+ bd1 = VppBridgeDomain(self, 1)
+ bd1.add_vpp_config()
- #
- # 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, self.loop0, self.pg3, tun_bm,
+ gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0,
+ None, None,
uu_drop=True, bm_drop=True)
gbd1.add_vpp_config()
"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.send_and_assert_no_replies(ep.itf, [p_bm])
self.pg3.unconfig_ip4()
- self.pg4.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)
+ ip_addr.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.address, 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"""
gt6 = VppIpTable(self, 1, is_ip6=True)
gt6.add_vpp_config()
- rd1 = VppGbpRouteDomain(self, 1, gt4, gt6)
+ rd1 = VppGbpRouteDomain(self, 1, 401, gt4, gt6)
rd1.add_vpp_config()
#
#
bd1 = VppBridgeDomain(self, 1)
bd1.add_vpp_config()
- gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0, bd_uu_fwd,
+ gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0, bd_uu_fwd,
learn=False)
gbd1.add_vpp_config()
tun_ip4_uu.add_vpp_config()
tun_ip6_uu.add_vpp_config()
- rd1 = VppGbpRouteDomain(self, 2, t4, t6, tun_ip4_uu, tun_ip6_uu)
+ rd1 = VppGbpRouteDomain(self, 2, 401, t4, t6, tun_ip4_uu, tun_ip6_uu)
rd1.add_vpp_config()
self.loop0.set_mac(self.router_mac)
#
bd1 = VppBridgeDomain(self, 1)
bd1.add_vpp_config()
- gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0, self.pg3)
+ gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0, self.pg3)
gbd1.add_vpp_config()
self.logger.info(self.vapi.cli("sh bridge 1 detail"))
epg_220.add_vpp_config()
#
- # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
- # learning enabled
+ # The VXLAN GBP tunnel is in L3 mode with learning enabled
#
vx_tun_l3 = VppGbpVxlanTunnel(
self, 101, rd1.rd_id,
#
# Add a route to static EP's v4 and v6 subnet
- # packets should be sent on the v4/v6 uu=fwd interface resp.
#
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.address, src=ep.ip4.address) /
+ UDP(sport=1234, dport=1234) /
+ Raw('\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.address, src=ep.ip6.address) /
+ UDP(sport=1234, dport=1234) /
+ Raw('\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.address) /
UDP(sport=1234, dport=1234) /
"2001:10::88", "3001::88",
ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
self.pg2.local_ip4,
- self.pg2.remote_hosts[1].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,
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[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.wait_for_ep_timeout(ip=rep_88.ip4.address)
self.wait_for_ep_timeout(ip=rep_2.ip4.address)
+ #
+ # 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.address) /
+ UDP(sport=1234, dport=1234) /
+ Raw('\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.address,
+ 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.address) /
+ UDP(sport=1234, dport=1234) /
+ Raw('\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.address,
+ 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
#
t6 = VppIpTable(self, 1, True)
t6.add_vpp_config()
- rd1 = VppGbpRouteDomain(self, 2, t4, t6)
+ rd1 = VppGbpRouteDomain(self, 2, 402, t4, t6)
rd1.add_vpp_config()
self.loop0.set_mac(self.router_mac)
#
bd1 = VppBridgeDomain(self, 1)
bd1.add_vpp_config()
- gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0)
+ gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0)
gbd1.add_vpp_config()
bd2 = VppBridgeDomain(self, 2)
bd2.add_vpp_config()
- gbd2 = VppGbpBridgeDomain(self, bd2, self.loop1)
+ gbd2 = VppGbpBridgeDomain(self, bd2, rd1, self.loop1)
gbd2.add_vpp_config()
# ... and has a /32 and /128 applied
bd3 = VppBridgeDomain(self, 3)
bd3.add_vpp_config()
- gbd3 = VppGbpBridgeDomain(self, bd3, self.loop2, bd_uu1, learn=False)
+ 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, self.loop3, bd_uu2, learn=False)
+ gbd4 = VppGbpBridgeDomain(self, bd4, rd1, self.loop3,
+ bd_uu2, learn=False)
gbd4.add_vpp_config()
#
# test the src-ip hash mode
#
c1 = VppGbpContract(
- self, epg_220.sclass, epg_222.sclass, acl_index,
+ self, 402, epg_220.sclass, epg_222.sclass, 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,
c1.add_vpp_config()
c2 = VppGbpContract(
- self, epg_222.sclass, epg_220.sclass, acl_index,
+ self, 402, epg_222.sclass, epg_220.sclass, 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,
# test the symmetric hash mode
#
c1 = VppGbpContract(
- self, epg_220.sclass, epg_222.sclass, acl_index,
+ self, 402, epg_220.sclass, epg_222.sclass, 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,
c1.add_vpp_config()
c2 = VppGbpContract(
- self, epg_222.sclass, epg_220.sclass, acl_index,
+ self, 402, epg_222.sclass, epg_220.sclass, 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,
Raw('\xa5' * 100))]
c3 = VppGbpContract(
- self, epg_220.sclass, epg_221.sclass, acl_index,
+ self, 402, epg_220.sclass, epg_221.sclass, 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,
#
# 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,
vx_tun_l3.add_vpp_config()
c4 = VppGbpContract(
- self, epg_221.sclass, epg_220.sclass, acl_index,
+ self, 402, epg_221.sclass, epg_220.sclass, acl_index,
[VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
- []),
+ 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_PERMIT,
- [])],
+ 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()
UDP(sport=1234, dport=1234) /
Raw('\xa5' * 100))
- rx = self.send_and_expect(self.pg7, [p], self.pg0)
+ # 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.address)
# endpoint learnt via the parent GBP-vxlan interface
self.assertTrue(find_gbp_endpoint(self,
UDP(sport=1234, dport=1234) /
Raw('\xa5' * 100))
- rx = self.send_and_expect(self.pg7, [p], self.pg0)
+ # 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.address)
# endpoint learnt via the parent GBP-vxlan interface
self.assertTrue(find_gbp_endpoint(self,
# test the dst-ip hash mode
#
c5 = VppGbpContract(
- self, epg_220.sclass, epg_221.sclass, acl_index,
+ self, 402, epg_220.sclass, epg_221.sclass, 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,
self.assertEqual(rx[IPv6].src, ep1.ip6.address)
self.assertEqual(rx[IPv6].dst, "2001:10::88")
+ #
+ # redirect to 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()
+
+ #
+ # redirect from local l3out to remote (known, then unknown) SEP
+ #
+
+ # add local l3out
+ # the external bd
+ self.loop4.set_mac(self.router_mac)
+ VppIpInterfaceBind(self, self.loop4, t4).add_vpp_config()
+ 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(2))
+ eepg.add_vpp_config()
+ # add subnets to BVI
+ VppIpInterfaceAddress(
+ self,
+ gebd.bvi,
+ "10.1.0.128",
+ 24).add_vpp_config()
+ VppIpInterfaceAddress(
+ self,
+ gebd.bvi,
+ "2001:10:1::128",
+ 64).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.address, 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.address, 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.address, 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.address, 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()
+
+ # 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('\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('\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_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)
+
+ #
+ # redirect remote EP to remote 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_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.address) /
+ UDP(sport=1234, dport=1234) /
+ Raw('\xa5' * 100)),
+ (base /
+ IPv6(src="2001:10::100", dst=ep3.ip6.address) /
+ UDP(sport=1234, dport=1234) /
+ Raw('\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
#
t6 = VppIpTable(self, 1, True)
t6.add_vpp_config()
- rd1 = VppGbpRouteDomain(self, 2, t4, t6)
+ rd1 = VppGbpRouteDomain(self, 2, 55, t4, t6)
rd1.add_vpp_config()
self.loop0.set_mac(self.router_mac)
#
bd1 = VppBridgeDomain(self, 1)
bd1.add_vpp_config()
- gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0, None, tun_bm)
+ gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0, None, tun_bm)
gbd1.add_vpp_config()
#
# an external interface attached to the outside world and the
# external BD
#
- vlan_100 = VppDot1QSubint(self, self.pg0, 100)
- vlan_100.admin_up()
- VppL2Vtr(self, vlan_100, L2_VTR_OP.L2_POP_1).add_vpp_config()
- vlan_101 = VppDot1QSubint(self, self.pg0, 101)
- vlan_101.admin_up()
- VppL2Vtr(self, vlan_101, L2_VTR_OP.L2_POP_1).add_vpp_config()
+ 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
- vlan_102 = VppDot1QSubint(self, self.pg0, 102)
- vlan_102.admin_up()
-
- ext_itf = VppGbpExtItf(self, self.loop0, bd1, rd1)
- ext_itf.add_vpp_config()
#
# an unicast vxlan-gbp for inter-RD traffic
#
# External Endpoints
#
- eep1 = VppGbpEndpoint(self, vlan_100,
+ 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, vlan_101,
+ 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, vlan_102,
+ eep3 = VppGbpEndpoint(self, self.vlan_102,
epg_220, None,
"10.0.0.3", "11.0.0.3",
"2001:10::3", "3001::3",
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
#
#
# ARP packet from host in remote subnet are accepted and replied to
#
- p_arp = (Ether(src=vlan_102.remote_mac, dst="ff:ff:ff:ff:ff:ff") /
+ p_arp = (Ether(src=eep3.mac, dst="ff:ff:ff:ff:ff:ff") /
Dot1Q(vlan=102) /
ARP(op="who-has",
- psrc="10.0.0.17", pdst="10.0.0.128",
- hwsrc=vlan_102.remote_mac, hwdst="ff:ff:ff:ff:ff:ff"))
+ psrc=eep3.ip4.address, 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)
#
for rx in rxs:
self.assertEqual(rx[Ether].src, str(self.router_mac))
- self.assertEqual(rx[Ether].dst, vlan_102.remote_mac)
+ self.assertEqual(rx[Ether].dst, self.vlan_102.remote_mac)
#
- # A subnet reachable through the external EP1
+ # A ip4 subnet reachable through the external EP1
#
ip_220 = VppIpRoute(self, "10.220.0.0", 24,
[VppRoutePath(eep1.ip4.address,
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.address,
+ 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(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)
+ self.send_and_assert_no_replies(self.pg0, p * 1)
#
# contract for the external nets to communicate
rule6 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
acl_index = acl.add_vpp_config([rule4, rule6])
- c1 = VppGbpContract(
- self, 4220, 4221, acl_index,
+ #
+ # A contract with the wrong scope is not matched
+ #
+ c_44 = VppGbpContract(
+ self, 44, 4220, 4221, acl_index,
[VppGbpContractRule(
VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
[]),
VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
[])],
[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_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, 4220, 113, acl_index,
+ self, 55, 4220, 113, 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, 113, 4220, acl_index,
+ self, 55, 113, 4220, 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()
# 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('\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_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('\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('\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('\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('\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('\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('\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('\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('\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.address, dst="10.220.0.1") /
+ UDP(sport=1234, dport=1234) /
+ Raw('\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.address, dst="10:220::1") /
+ UDP(sport=1234, dport=1234) /
+ Raw('\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.address,
+ eep1.epg.bvi.sw_if_index),
+ VppRoutePath(eep2.ip4.address,
+ 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.address,
+ eep1.epg.bvi.sw_if_index),
+ VppRoutePath(eep2.ip6.address,
+ 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.address, dst="10:20::1") /
+ UDP(sport=1234, dport=1234) /
+ Raw('\xa5' * 100)),
+ (Ether(src=lep1.mac, dst=str(self.router_mac)) /
+ Dot1Q(vlan=144) /
+ IPv6(src=lep1.ip6.address, dst="10:20::1") /
+ UDP(sport=124, dport=1230) /
+ Raw('\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.address, dst="10.20.0.1") /
+ UDP(sport=1235, dport=1235) /
+ Raw('\xa5' * 100)),
+ (Ether(src=lep1.mac, dst=str(self.router_mac)) /
+ Dot1Q(vlan=144) /
+ IP(src=lep1.ip4.address, dst="10.20.0.1") /
+ UDP(sport=124, dport=1230) /
+ Raw('\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
+ #
+ VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
+ 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(2))
+ epg_220.add_vpp_config()
+
+ # the BVIs have the subnet applied ...
+ ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 24)
+ ip4_addr.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('\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
+ #
+ acl = VppGbpAcl(self)
+ rule4 = acl.create_rule(permit_deny=1, proto=17)
+ rule6 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
+ acl_index = acl.add_vpp_config([rule4, rule6])
+
+ c1 = VppGbpContract(
+ self, 55, 4220, 4221, 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_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_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('\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.address, dst="10.220.0.1") /
+ UDP(sport=1234, dport=1234) /
+ Raw('\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.address) /
+ UDP(sport=1234, dport=1234) /
+ Raw('\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.address)
+
+ #
+ # An external subnet reachable via the remote external EP
+ #
+
#
# first the VXLAN-GBP tunnel over which it is reached
#
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=eep1.mac, dst=str(self.router_mac)) /
+ 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) /
# Add contracts ext-nets for 220 -> 222
#
c4 = VppGbpContract(
- self, 4220, 4222, acl_index,
+ self, 55, 4220, 4222, 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)) /
+ 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) /
#
# 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()
- vlan_100.set_vtr(L2_VTR_OP.L2_DISABLED)
if __name__ == '__main__':