#!/usr/bin/env python
+from socket import AF_INET, AF_INET6
import unittest
-from framework import VppTestCase, VppTestRunner
-from vpp_object import VppObject
-from vpp_neighbor import VppNeighbor
-from vpp_ip_route import VppIpRoute, VppRoutePath, VppIpTable, \
- VppIpInterfaceAddress, VppIpInterfaceBind, find_route
-from vpp_l2 import VppBridgeDomain, VppBridgeDomainPort, \
- VppBridgeDomainArpEntry, VppL2FibEntry, find_bridge_domain_port
-from vpp_vxlan_gbp_tunnel import *
-from vpp_sub_interface import VppDot1QSubint
-
-from vpp_ip import *
-from vpp_mac import *
-from vpp_papi_provider import L2_PORT_TYPE
-from vpp_papi import VppEnum
-
from scapy.packet import Raw
from scapy.layers.l2 import Ether, ARP, Dot1Q
-from scapy.layers.inet import IP, UDP
-from scapy.layers.inet6 import IPv6, ICMPv6ND_NS, ICMPv6NDOptSrcLLAddr, \
+from scapy.layers.inet import IP, UDP, ICMP
+from scapy.layers.inet6 import IPv6, ICMPv6ND_NS, ICMPv6NDOptSrcLLAddr, \
ICMPv6ND_NA
from scapy.utils6 import in6_getnsma, in6_getnsmac
from scapy.layers.vxlan import VXLAN
-
-from socket import AF_INET, AF_INET6
+from scapy.data import ETH_P_IP, ETH_P_IPV6, ETH_P_ARP
from scapy.utils import inet_pton, inet_ntop
-from util import mactobinary
-from vpp_papi_provider import L2_VTR_OP
+
+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
+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_papi import VppEnum, MACAddress
+from vpp_vxlan_gbp_tunnel import find_vxlan_gbp_tunnel, INDEX_INVALID, \
+ VppVxlanGbpTunnel
+from vpp_neighbor import VppNeighbor
+
+NUM_PKTS = 67
def find_gbp_endpoint(test, sw_if_index=None, ip=None, mac=None):
if ip:
vip = VppIpAddress(ip)
if mac:
- vmac = VppMacAddress(mac)
+ vmac = MACAddress(mac)
eps = test.vapi.gbp_endpoint_dump()
if vip == eip:
return True
if mac:
- if vmac == ep.endpoint.mac:
+ if vmac.packed == ep.endpoint.mac:
return True
return False
GBP Endpoint
"""
- @property
- def bin_mac(self):
- return self.vmac.bytes
-
- @property
- def mac(self):
- return self.vmac.address
-
@property
def mac(self):
- return self.itf.remote_mac
+ return str(self.vmac)
@property
def ip4(self):
self._fip6 = VppIpAddress(fip6)
if mac:
- self.vmac = VppMacAddress(self.itf.remote_mac)
+ self.vmac = MACAddress(self.itf.remote_mac)
else:
- self.vmac = VppMacAddress("00:00:00:00:00:00")
+ self.vmac = MACAddress("00:00:00:00:00:00")
self.flags = flags
self.tun_src = VppIpAddress(tun_src)
res = self._test.vapi.gbp_endpoint_add(
self.itf.sw_if_index,
[self.ip4.encode(), self.ip6.encode()],
- self.vmac.encode(),
- self.epg.epg,
+ self.vmac.packed,
+ self.epg.sclass,
self.flags,
self.tun_src.encode(),
self.tun_dst.encode())
def remove_vpp_config(self):
self._test.vapi.gbp_endpoint_del(self.handle)
- def __str__(self):
- return self.object_id()
-
def object_id(self):
return "gbp-endpoint:[%d==%d:%s:%d]" % (self.handle,
self.itf.sw_if_index,
self.ip4.address,
- self.epg.epg)
+ self.epg.sclass)
def query_vpp_config(self):
return find_gbp_endpoint(self._test,
self._test.vapi.gbp_recirc_add_del(
1,
self.recirc.sw_if_index,
- self.epg.epg,
+ self.epg.sclass,
self.is_ext)
self._test.registry.register(self, self._test.logger)
self._test.vapi.gbp_recirc_add_del(
0,
self.recirc.sw_if_index,
- self.epg.epg,
+ self.epg.sclass,
self.is_ext)
- def __str__(self):
- return self.object_id()
-
def object_id(self):
return "gbp-recirc:[%d]" % (self.recirc.sw_if_index)
return False
+class VppGbpExtItf(VppObject):
+ """
+ GBP ExtItfulation Interface
+ """
+
+ def __init__(self, test, itf, bd, rd):
+ self._test = test
+ self.itf = itf
+ self.bd = bd
+ self.rd = rd
+
+ 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)
+ 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)
+
+ def object_id(self):
+ return "gbp-ext-itf:[%d]" % (self.itf.sw_if_index)
+
+ 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=None, epg=None):
+ type, sw_if_index=None, sclass=None):
self._test = test
self.rd_id = rd.rd_id
self.prefix = VppIpPrefix(address, address_len)
self.type = type
self.sw_if_index = sw_if_index
- self.epg = epg
+ self.sclass = sclass
def add_vpp_config(self):
self._test.vapi.gbp_subnet_add_del(
self.prefix.encode(),
self.type,
sw_if_index=self.sw_if_index if self.sw_if_index else 0xffffffff,
- epg_id=self.epg if self.epg else 0xffff)
+ sclass=self.sclass if self.sclass else 0xffff)
self._test.registry.register(self, self._test.logger)
def remove_vpp_config(self):
self.prefix.encode(),
self.type)
- def __str__(self):
- return self.object_id()
-
def object_id(self):
return "gbp-subnet:[%d-%s]" % (self.rd_id, self.prefix)
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:
+ 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, epg, rd, bd, uplink,
- bvi, bvi_ip4, bvi_ip6=None):
+ 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 = VppIpAddress(bvi_ip4)
self.bvi_ip6 = VppIpAddress(bvi_ip6)
- self.epg = epg
+ self.vnid = vnid
self.bd = bd
self.rd = rd
+ self.sclass = sclass
+ if 0 == self.sclass:
+ self.sclass = 0xffff
+ self.retention = retention
def add_vpp_config(self):
self._test.vapi.gbp_endpoint_group_add(
- self.epg,
+ self.vnid,
+ self.sclass,
self.bd.bd.bd_id,
self.rd.rd_id,
- self.uplink.sw_if_index if self.uplink else INDEX_INVALID)
+ self.uplink.sw_if_index if self.uplink else INDEX_INVALID,
+ self.retention.encode())
self._test.registry.register(self, self._test.logger)
def remove_vpp_config(self):
- self._test.vapi.gbp_endpoint_group_del(
- self.epg)
-
- def __str__(self):
- return self.object_id()
+ self._test.vapi.gbp_endpoint_group_del(self.sclass)
def object_id(self):
- return "gbp-endpoint-group:[%d]" % (self.epg)
+ return "gbp-endpoint-group:[%d]" % (self.vnid)
def query_vpp_config(self):
epgs = self._test.vapi.gbp_endpoint_group_dump()
for epg in epgs:
- if epg.epg.epg_id == self.epg:
+ if epg.epg.vnid == self.vnid:
return True
return False
GBP Bridge Domain
"""
- def __init__(self, test, bd, bvi, uu_flood=None, learn=True):
+ def __init__(self, test, bd, bvi, uu_fwd=None,
+ bm_flood=None, learn=True, uu_drop=False, bm_drop=False):
self._test = test
self.bvi = bvi
- self.uu_flood = uu_flood
+ self.uu_fwd = uu_fwd
+ self.bm_flood = bm_flood
self.bd = bd
e = VppEnum.vl_api_gbp_bridge_domain_flags_t
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
def add_vpp_config(self):
self._test.vapi.gbp_bridge_domain_add(
self.bd.bd_id,
self.learn,
self.bvi.sw_if_index,
- self.uu_flood.sw_if_index if self.uu_flood else INDEX_INVALID)
+ 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)
self._test.registry.register(self, self._test.logger)
def remove_vpp_config(self):
self._test.vapi.gbp_bridge_domain_del(self.bd.bd_id)
- def __str__(self):
- return self.object_id()
-
def object_id(self):
return "gbp-bridge-domain:[%d]" % (self.bd.bd_id)
def remove_vpp_config(self):
self._test.vapi.gbp_route_domain_del(self.rd_id)
- def __str__(self):
- return self.object_id()
-
def object_id(self):
return "gbp-route-domain:[%d]" % (self.rd_id)
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):
+ return {'ip': self.ip.encode(),
+ '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=[]):
+ self.action = action
+ self.hash_mode = hash_mode
+ self.nhs = nhs
+
+ def encode(self):
+ 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}}
+
+
class VppGbpContract(VppObject):
"""
GBP Contract
"""
- def __init__(self, test, src_epg, dst_epg, acl_index):
+ def __init__(self, test, sclass, dclass, acl_index,
+ rules, allowed_ethertypes):
self._test = test
self.acl_index = acl_index
- self.src_epg = src_epg
- self.dst_epg = dst_epg
+ 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 add_vpp_config(self):
- self._test.vapi.gbp_contract_add_del(
+ rules = []
+ for r in self.rules:
+ rules.append(r.encode())
+ r = self._test.vapi.gbp_contract_add_del(
1,
- self.src_epg,
- self.dst_epg,
- self.acl_index)
+ self.sclass,
+ self.dclass,
+ self.acl_index,
+ rules,
+ 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.src_epg,
- self.dst_epg,
- self.acl_index)
-
- def __str__(self):
- return self.object_id()
+ self.sclass,
+ self.dclass,
+ self.acl_index,
+ [],
+ self.allowed_ethertypes)
def object_id(self):
- return "gbp-contract:[%d:%s:%d]" % (self.src_epg,
- self.dst_epg,
+ return "gbp-contract:[%d:%s:%d]" % (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.src_epg == self.src_epg \
- and c.contract.dst_epg == self.dst_epg:
+ if 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):
+ 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 add_vpp_config(self):
r = self._test.vapi.gbp_vxlan_tunnel_add(
self.vni,
self.bd_rd_id,
- self.mode)
+ self.mode,
+ self.src)
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(self.vni)
- def __str__(self):
- return self.object_id()
-
def object_id(self):
- return "gbp-vxlan:%d" % (self.vni)
+ return "gbp-vxlan:%d" % (self.sw_if_index)
def query_vpp_config(self):
return find_gbp_vxlan(self._test, self.vni)
self.acl_index = 4294967295
def create_rule(self, is_ipv6=0, permit_deny=0, proto=-1,
- s_prefix=0, s_ip='\x00\x00\x00\x00', sport_from=0,
- sport_to=65535, d_prefix=0, d_ip='\x00\x00\x00\x00',
+ s_prefix=0, s_ip=b'\x00\x00\x00\x00', sport_from=0,
+ sport_to=65535, d_prefix=0, d_ip=b'\x00\x00\x00\x00',
dport_from=0, dport_to=65535):
if proto == -1 or proto == 0:
sport_to = 0
reply = self._test.vapi.acl_add_replace(self.acl_index,
r=rules,
- tag='GBPTest')
+ tag=b'GBPTest')
self.acl_index = reply.acl_index
return self.acl_index
def remove_vpp_config(self):
self._test.vapi.acl_del(self.acl_index)
- def __str__(self):
- return self.object_id()
-
def object_id(self):
return "gbp-acl:[%d]" % (self.acl_index)
class TestGBP(VppTestCase):
""" GBP Test Case """
+ @property
+ def config_flags(self):
+ return VppEnum.vl_api_nat_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 = VppMacAddress("00:11:22:33:44:55")
+ self.router_mac = MACAddress("00:11:22:33:44:55")
for i in self.pg_interfaces:
i.admin_up()
rx = self.send_and_expect(src, tx, dst)
for r in rx:
- self.assertEqual(r[Ether].src, self.router_mac.address)
+ 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)
rx = self.send_and_expect(src, tx, dst)
for r in rx:
- self.assertEqual(r[Ether].src, self.router_mac.address)
+ 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="")
+ timeout = 0.1
+
+ 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
+
#
# Bridge Domains
#
# 3 EPGs, 2 of which share a BD.
# 2 NAT EPGs, one for floating-IP subnets, the other for internet
#
- epgs = [VppGbpEndpointGroup(self, 220, rd0, gbd1, self.pg4,
- self.loop0,
- "10.0.0.128",
- "2001:10::128"),
- VppGbpEndpointGroup(self, 221, rd0, gbd1, self.pg5,
- self.loop0,
- "10.0.1.128",
- "2001:10:1::128"),
- VppGbpEndpointGroup(self, 222, rd0, gbd2, self.pg6,
- self.loop1,
- "10.0.2.128",
- "2001:10:2::128"),
- VppGbpEndpointGroup(self, 333, rd20, gbd20, self.pg7,
- self.loop2,
- "11.0.0.128",
- "3001::128"),
- VppGbpEndpointGroup(self, 444, 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)]
+ 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]
VppIpInterfaceBind(self, epg.bvi, epg.rd.t6).add_vpp_config()
self.vapi.sw_interface_set_mac_address(
epg.bvi.sw_if_index,
- self.router_mac.bytes)
+ self.router_mac.packed)
# The BVIs are NAT inside interfaces
- self.vapi.nat44_interface_add_del_feature(epg.bvi.sw_if_index,
- is_inside=1,
- is_add=1)
- self.vapi.nat66_add_del_interface(epg.bvi.sw_if_index,
- is_inside=1,
- is_add=1)
+ flags = self.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(
+ is_add=1, flags=flags,
+ sw_if_index=epg.bvi.sw_if_index)
if_ip4 = VppIpInterfaceAddress(self, epg.bvi, epg.bvi_ip4, 32)
if_ip6 = VppIpInterfaceAddress(self, epg.bvi, epg.bvi_ip6, 128)
# add the BD ARP termination entry for BVI IP
epg.bd_arp_ip4 = VppBridgeDomainArpEntry(self, epg.bd.bd,
- self.router_mac.address,
+ str(self.router_mac),
epg.bvi_ip4)
epg.bd_arp_ip6 = VppBridgeDomainArpEntry(self, epg.bd.bd,
- self.router_mac.address,
+ str(self.router_mac),
epg.bvi_ip6)
epg.bd_arp_ip4.add_vpp_config()
epg.bd_arp_ip6.add_vpp_config()
VppIpInterfaceBind(self, recirc.recirc,
recirc.epg.rd.t6).add_vpp_config()
- self.vapi.sw_interface_set_l2_emulation(
- recirc.recirc.sw_if_index)
self.vapi.nat44_interface_add_del_feature(
- recirc.recirc.sw_if_index,
- is_inside=0,
- is_add=1)
+ sw_if_index=recirc.recirc.sw_if_index, is_add=1)
self.vapi.nat66_add_del_interface(
- recirc.recirc.sw_if_index,
- is_inside=0,
- is_add=1)
+ is_add=1,
+ sw_if_index=recirc.recirc.sw_if_index)
recirc.add_vpp_config()
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.af == AF_INET:
- self.vapi.nat44_add_del_static_mapping(ip.bytes,
- fip.bytes,
- vrf_id=0,
- addr_only=1)
+ flags = self.config_flags.NAT_IS_ADDR_ONLY
+ self.vapi.nat44_add_del_static_mapping(
+ is_add=1,
+ local_ip_address=ip.bytes,
+ external_ip_address=fip.bytes,
+ external_sw_if_index=0xFFFFFFFF,
+ vrf_id=0,
+ flags=flags)
else:
- self.vapi.nat66_add_del_static_mapping(ip.bytes,
- fip.bytes,
- vrf_id=0)
+ self.vapi.nat66_add_del_static_mapping(
+ local_ip_address=ip.bytes,
+ external_ip_address=fip.bytes,
+ vrf_id=0, is_add=1)
# VPP EP create ...
ep.add_vpp_config()
# packets to non-local L3 destinations dropped
#
pkt_intra_epg_220_ip4 = (Ether(src=self.pg0.remote_mac,
- dst=self.router_mac.address) /
+ dst=str(self.router_mac)) /
IP(src=eps[0].ip4.address,
dst="10.0.0.99") /
UDP(sport=1234, dport=1234) /
Raw('\xa5' * 100))
pkt_inter_epg_222_ip4 = (Ether(src=self.pg0.remote_mac,
- dst=self.router_mac.address) /
+ dst=str(self.router_mac)) /
IP(src=eps[0].ip4.address,
dst="10.0.1.99") /
UDP(sport=1234, dport=1234) /
Raw('\xa5' * 100))
- self.send_and_assert_no_replies(self.pg0, pkt_intra_epg_220_ip4 * 65)
+ 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=self.router_mac.address) /
+ dst=str(self.router_mac)) /
IPv6(src=eps[0].ip6.address,
dst="2001:10::99") /
UDP(sport=1234, dport=1234) /
Raw('\xa5' * 100))
- self.send_and_assert_no_replies(self.pg0, pkt_inter_epg_222_ip6 * 65)
+ self.send_and_assert_no_replies(self.pg0,
+ pkt_inter_epg_222_ip6 * NUM_PKTS)
#
# Add the subnet routes
s63.add_vpp_config()
self.send_and_expect_bridged(eps[0].itf,
- pkt_intra_epg_220_ip4 * 65,
+ pkt_intra_epg_220_ip4 * NUM_PKTS,
eps[0].epg.uplink)
self.send_and_expect_bridged(eps[0].itf,
- pkt_inter_epg_222_ip4 * 65,
+ pkt_inter_epg_222_ip4 * NUM_PKTS,
eps[0].epg.uplink)
self.send_and_expect_bridged6(eps[0].itf,
- pkt_inter_epg_222_ip6 * 65,
+ pkt_inter_epg_222_ip6 * NUM_PKTS,
eps[0].epg.uplink)
self.logger.info(self.vapi.cli("sh ip fib 11.0.0.2"))
Raw('\xa5' * 100))
self.send_and_expect_bridged(eps[0].itf,
- pkt_intra_epg_220_to_uplink * 65,
+ pkt_intra_epg_220_to_uplink * NUM_PKTS,
eps[0].epg.uplink)
# ... and nowhere else
self.pg1.get_capture(0, timeout=0.1)
Raw('\xa5' * 100))
self.send_and_expect_bridged(eps[2].itf,
- pkt_intra_epg_221_to_uplink * 65,
+ pkt_intra_epg_221_to_uplink * NUM_PKTS,
eps[2].epg.uplink)
#
Raw('\xa5' * 100))
self.send_and_expect_bridged(self.pg4,
- pkt_intra_epg_220_from_uplink * 65,
+ pkt_intra_epg_220_from_uplink * NUM_PKTS,
self.pg0)
#
UDP(sport=1234, dport=1234) /
Raw('\xa5' * 100))
- self.send_and_expect_bridged(self.pg0, pkt_intra_epg * 65, self.pg1)
+ self.send_and_expect_bridged(self.pg0,
+ pkt_intra_epg * NUM_PKTS,
+ self.pg1)
#
- # in the abscense of policy, endpoints in the different EPG
+ # in the absence of policy, endpoints in the different EPG
# cannot communicate
#
pkt_inter_epg_220_to_221 = (Ether(src=self.pg0.remote_mac,
UDP(sport=1234, dport=1234) /
Raw('\xa5' * 100))
pkt_inter_epg_220_to_222 = (Ether(src=self.pg0.remote_mac,
- dst=self.router_mac.address) /
+ dst=str(self.router_mac)) /
IP(src=eps[0].ip4.address,
dst=eps[3].ip4.address) /
UDP(sport=1234, dport=1234) /
Raw('\xa5' * 100))
self.send_and_assert_no_replies(eps[0].itf,
- pkt_inter_epg_220_to_221 * 65)
+ pkt_inter_epg_220_to_221 * NUM_PKTS)
self.send_and_assert_no_replies(eps[0].itf,
- pkt_inter_epg_220_to_222 * 65)
+ pkt_inter_epg_220_to_222 * NUM_PKTS)
#
# A uni-directional contract from EPG 220 -> 221
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])
- c1 = VppGbpContract(self, 220, 221, acl_index)
+ c1 = VppGbpContract(
+ self, epgs[0].sclass, epgs[1].sclass, acl_index,
+ [VppGbpContractRule(
+ VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
+ []),
+ VppGbpContractRule(
+ VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
+ [])],
+ [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,
+ 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 * 65)
+ pkt_inter_epg_220_to_222 * NUM_PKTS)
#
# contract for the return direction
#
- c2 = VppGbpContract(self, 221, 220, acl_index)
+ c2 = VppGbpContract(
+ self, epgs[1].sclass, epgs[0].sclass, acl_index,
+ [VppGbpContractRule(
+ VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
+ []),
+ VppGbpContractRule(
+ VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
+ [])],
+ [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,
+ 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 * 65,
+ 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 * 65)
+ pkt_inter_epg_220_to_222 * NUM_PKTS)
#
# A uni-directional contract from EPG 220 -> 222 'L3 routed'
#
- c3 = VppGbpContract(self, 220, 222, acl_index)
+ c3 = VppGbpContract(
+ self, epgs[0].sclass, epgs[2].sclass, acl_index,
+ [VppGbpContractRule(
+ VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
+ []),
+ VppGbpContractRule(
+ VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
+ [])],
+ [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 * 65,
+ pkt_inter_epg_220_to_222 * NUM_PKTS,
eps[3].itf,
- self.router_mac.address)
+ str(self.router_mac))
#
# remove both contracts, traffic stops in both directions
acl.remove_vpp_config()
self.send_and_assert_no_replies(eps[2].itf,
- pkt_inter_epg_221_to_220 * 65)
+ pkt_inter_epg_221_to_220 * NUM_PKTS)
self.send_and_assert_no_replies(eps[0].itf,
- pkt_inter_epg_220_to_221 * 65)
+ pkt_inter_epg_220_to_221 * NUM_PKTS)
self.send_and_expect_bridged(eps[0].itf,
- pkt_intra_epg * 65,
+ pkt_intra_epg * NUM_PKTS,
eps[1].itf)
#
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,
- epg=epg_nat.epg)
+ 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,
- epg=epg_nat.epg)
+ 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,
- epg=epg_nat.epg)
+ 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,
- epg=epg_nat.epg)
+ 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,
- epg=epg_nat.epg)
+ 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,
- epg=epg_nat.epg)
+ sclass=epg_nat.sclass)
se1.add_vpp_config()
se2.add_vpp_config()
se16.add_vpp_config()
eps[0].fip6))
#
- # From an EP to an outside addess: IN2OUT
+ # From an EP to an outside address: IN2OUT
#
pkt_inter_epg_220_to_global = (Ether(src=self.pg0.remote_mac,
- dst=self.router_mac.address) /
+ dst=str(self.router_mac)) /
IP(src=eps[0].ip4.address,
dst="1.1.1.1") /
UDP(sport=1234, dport=1234) /
# no policy yet
self.send_and_assert_no_replies(eps[0].itf,
- pkt_inter_epg_220_to_global * 65)
+ pkt_inter_epg_220_to_global * NUM_PKTS)
acl2 = VppGbpAcl(self)
rule = acl2.create_rule(permit_deny=1, proto=17, sport_from=1234,
dport_from=1234, dport_to=1234)
acl_index2 = acl2.add_vpp_config([rule, rule2])
- c4 = VppGbpContract(self, 220, 333, acl_index2)
+ c4 = VppGbpContract(
+ self, epgs[0].sclass, epgs[3].sclass, acl_index2,
+ [VppGbpContractRule(
+ VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
+ []),
+ VppGbpContractRule(
+ VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
+ [])],
+ [ETH_P_IP, ETH_P_IPV6])
c4.add_vpp_config()
self.send_and_expect_natted(eps[0].itf,
- pkt_inter_epg_220_to_global * 65,
+ pkt_inter_epg_220_to_global * NUM_PKTS,
self.pg7,
eps[0].fip4.address)
pkt_inter_epg_220_to_global = (Ether(src=self.pg0.remote_mac,
- dst=self.router_mac.address) /
+ dst=str(self.router_mac)) /
IPv6(src=eps[0].ip6.address,
dst="6001::1") /
UDP(sport=1234, dport=1234) /
Raw('\xa5' * 100))
self.send_and_expect_natted6(self.pg0,
- pkt_inter_epg_220_to_global * 65,
+ pkt_inter_epg_220_to_global * NUM_PKTS,
self.pg7,
eps[0].fip6.address)
#
# From a global address to an EP: OUT2IN
#
- pkt_inter_epg_220_from_global = (Ether(src=self.router_mac.address,
+ pkt_inter_epg_220_from_global = (Ether(src=str(self.router_mac),
dst=self.pg0.remote_mac) /
IP(dst=eps[0].fip4.address,
src="1.1.1.1") /
UDP(sport=1234, dport=1234) /
Raw('\xa5' * 100))
- self.send_and_assert_no_replies(self.pg7,
- pkt_inter_epg_220_from_global * 65)
-
- c5 = VppGbpContract(self, 333, 220, acl_index2)
+ self.send_and_assert_no_replies(
+ self.pg7, pkt_inter_epg_220_from_global * NUM_PKTS)
+
+ c5 = VppGbpContract(
+ self, epgs[3].sclass, epgs[0].sclass, acl_index2,
+ [VppGbpContractRule(
+ VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
+ []),
+ VppGbpContractRule(
+ VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
+ [])],
+ [ETH_P_IP, ETH_P_IPV6])
c5.add_vpp_config()
self.send_and_expect_unnatted(self.pg7,
- pkt_inter_epg_220_from_global * 65,
+ pkt_inter_epg_220_from_global * NUM_PKTS,
eps[0].itf,
eps[0].ip4.address)
- pkt_inter_epg_220_from_global = (Ether(src=self.router_mac.address,
+ pkt_inter_epg_220_from_global = (Ether(src=str(self.router_mac),
dst=self.pg0.remote_mac) /
IPv6(dst=eps[0].fip6.address,
src="6001::1") /
UDP(sport=1234, dport=1234) /
Raw('\xa5' * 100))
- self.send_and_expect_unnatted6(self.pg7,
- pkt_inter_epg_220_from_global * 65,
- eps[0].itf,
- eps[0].ip6.address)
+ self.send_and_expect_unnatted6(
+ self.pg7,
+ pkt_inter_epg_220_from_global * NUM_PKTS,
+ eps[0].itf,
+ eps[0].ip6.address)
#
# 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=self.router_mac.address) /
+ dst=str(self.router_mac)) /
IP(src=eps[0].ip4.address,
dst=eps[1].fip4.address) /
UDP(sport=1234, dport=1234) /
Raw('\xa5' * 100))
self.send_and_expect_double_natted(eps[0].itf,
- pkt_intra_epg_220_global * 65,
+ pkt_intra_epg_220_global * NUM_PKTS,
eps[1].itf,
eps[0].fip4.address,
eps[1].ip4.address)
pkt_intra_epg_220_global = (Ether(src=self.pg0.remote_mac,
- dst=self.router_mac.address) /
+ dst=str(self.router_mac)) /
IPv6(src=eps[0].ip6.address,
dst=eps[1].fip6.address) /
UDP(sport=1234, dport=1234) /
Raw('\xa5' * 100))
- self.send_and_expect_double_natted6(eps[0].itf,
- pkt_intra_epg_220_global * 65,
- eps[1].itf,
- eps[0].fip6.address,
- eps[1].ip6.address)
+ self.send_and_expect_double_natted6(
+ eps[0].itf,
+ pkt_intra_epg_220_global * NUM_PKTS,
+ eps[1].itf,
+ eps[0].fip6.address,
+ eps[1].ip6.address)
#
# cleanup
#
for ep in eps:
# del static mappings for each EP from the 10/8 to 11/8 network
- self.vapi.nat44_add_del_static_mapping(ep.ip4.bytes,
- ep.fip4.bytes,
- vrf_id=0,
- addr_only=1,
- is_add=0)
- self.vapi.nat66_add_del_static_mapping(ep.ip6.bytes,
- ep.fip6.bytes,
- vrf_id=0,
- is_add=0)
+ flags = self.config_flags.NAT_IS_ADDR_ONLY
+ self.vapi.nat44_add_del_static_mapping(
+ is_add=0,
+ local_ip_address=ep.ip4.bytes,
+ external_ip_address=ep.fip4.bytes,
+ external_sw_if_index=0xFFFFFFFF,
+ vrf_id=0,
+ flags=flags)
+ self.vapi.nat66_add_del_static_mapping(
+ local_ip_address=ep.ip6.bytes,
+ external_ip_address=ep.fip6.bytes,
+ vrf_id=0, is_add=0)
for epg in epgs:
# IP config on the BVI interfaces
if epg != epgs[0] and epg != epgs[3]:
- self.vapi.nat44_interface_add_del_feature(epg.bvi.sw_if_index,
- is_inside=1,
- is_add=0)
- self.vapi.nat66_add_del_interface(epg.bvi.sw_if_index,
- is_inside=1,
- is_add=0)
+ flags = self.config_flags.NAT_IS_INSIDE
+ self.vapi.nat44_interface_add_del_feature(
+ sw_if_index=epg.bvi.sw_if_index,
+ flags=flags,
+ is_add=0)
+ self.vapi.nat66_add_del_interface(
+ is_add=0, flags=flags,
+ sw_if_index=epg.bvi.sw_if_index)
for recirc in recircs:
- self.vapi.sw_interface_set_l2_emulation(
- recirc.recirc.sw_if_index, enable=0)
self.vapi.nat44_interface_add_del_feature(
- recirc.recirc.sw_if_index,
- is_inside=0,
+ sw_if_index=recirc.recirc.sw_if_index,
is_add=0)
self.vapi.nat66_add_del_interface(
- recirc.recirc.sw_if_index,
- is_inside=0,
- is_add=0)
+ is_add=0,
+ 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):
+ while (n_tries):
+ if not find_gbp_endpoint(self, sw_if_index, ip, mac):
+ return True
+ n_tries = n_tries - 1
+ self.sleep(s_time)
+ self.assertFalse(find_gbp_endpoint(self, sw_if_index, ip, mac))
+ return False
def test_gbp_learn_l2(self):
""" GBP L2 Endpoint Learning """
+ self.vapi.cli("clear errors")
+
+ 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'},
'ip': '10.0.0.2',
'ip6': '2001:10::3'}]
- #
- # lower the inactive threshold so these tests pass in a
- # reasonable amount of time
- #
- self.vapi.gbp_endpoint_learn_set_inactive_threshold(1)
-
#
# IP tables
#
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, self.loop0, self.pg3)
+ gbd1 = VppGbpBridgeDomain(self, bd1, self.loop0, self.pg3, tun_bm)
gbd1.add_vpp_config()
self.logger.info(self.vapi.cli("sh bridge 1 detail"))
#
# The Endpoint-group in which we are learning endpoints
#
- epg_220 = VppGbpEndpointGroup(self, 220, rd1, gbd1,
+ epg_220 = VppGbpEndpointGroup(self, 220, 112, rd1, gbd1,
None, self.loop0,
"10.0.0.128",
- "2001:10::128")
+ "2001:10::128",
+ VppGbpEndpointRetention(2))
epg_220.add_vpp_config()
- epg_330 = VppGbpEndpointGroup(self, 330, rd1, gbd1,
+ epg_330 = VppGbpEndpointGroup(self, 330, 113, rd1, gbd1,
None, self.loop1,
"10.0.1.128",
- "2001:11::128")
+ "2001:11::128",
+ VppGbpEndpointRetention(2))
epg_330.add_vpp_config()
#
# The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
- # leanring enabled
+ # 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)
+ VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L2,
+ self.pg2.local_ip4)
vx_tun_l2_1.add_vpp_config()
#
self.assertTrue(find_route(self, ep.ip4.address, 32, table_id=1))
- # a packet with an sclass from an unknwon EPG
+ # 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,
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)
+
#
# we should not have learnt a new tunnel endpoint, since
# the EPG was not learnt.
self.pg2.remote_hosts[0].ip4,
99))
- # epg is not learnt, becasue the EPG is unknwon
+ # epg 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 knwon EPG
+ # 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=220, flags=0x88) /
+ VXLAN(vni=99, gpid=112, flags=0x88) /
Ether(src=l['mac'], dst=ep.mac) /
IP(src=l['ip'], dst=ep.ip4.address) /
UDP(sport=1234, dport=1234) /
vx_tun_l2_1.sw_if_index,
ip=l['ip']))
+ # self.assert_packet_counter_equal(
+ # '/err/gbp-policy-port/allow-intra-sclass', 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 vxlan-gbp tunnel"))
+ self.logger.info(self.vapi.cli("show ip mfib"))
#
# If we sleep for the threshold time, the learnt endpoints should
# age out
#
- self.sleep(2)
for l in learnt:
- self.assertFalse(find_gbp_endpoint(self,
- tep1_sw_if_index,
- mac=l['mac']))
+ 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):
+ # 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="239.1.1.1") /
+ UDP(sport=1234, dport=48879) /
+ VXLAN(vni=88, 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('\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 knwon EPG
+ # 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=220, flags=0x88, gpflags="D") /
+ VXLAN(vni=99, gpid=112, flags=0x88, gpflags="D") /
Ether(src=l['mac'], dst=ep.mac) /
IP(src=l['ip'], dst=ep.ip4.address) /
UDP(sport=1234, dport=1234) /
Raw('\xa5' * 100))
- rx = self.send_and_expect(self.pg2, p*65, self.pg0)
+ rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
for l in learnt:
self.assertFalse(find_gbp_endpoint(self,
# repeat
#
for l in learnt:
- # a packet with an sclass from a knwon EPG
+ # 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=220, flags=0x88) /
+ VXLAN(vni=99, gpid=112, flags=0x88) /
Ether(src=l['mac'], dst=ep.mac) /
IP(src=l['ip'], dst=ep.ip4.address) /
UDP(sport=1234, dport=1234) /
Raw('\xa5' * 100))
- rx = self.send_and_expect(self.pg2, p*65, 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,
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, 220)
+ 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.sleep(2)
for l in learnt:
- self.assertFalse(find_gbp_endpoint(self,
- vx_tun_l2_1.sw_if_index,
- mac=l['mac']))
+ self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
+ mac=l['mac'])
#
# repeat in the other EPG
# so the packet is cleared for delivery
#
for l in learnt:
- # a packet with an sclass from a knwon EPG
+ # 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=330, flags=0x88, gpflags='A') /
+ VXLAN(vni=99, gpid=113, flags=0x88, gpflags='A') /
Ether(src=l['mac'], dst=ep.mac) /
IP(src=l['ip'], dst=ep.ip4.address) /
UDP(sport=1234, dport=1234) /
Raw('\xa5' * 100))
- rx = self.send_and_expect(self.pg2, p*65, 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,
#
# static EP cannot reach the learnt EPs since there is no contract
+ # only test 1 EP as the others could timeout
#
- self.logger.info(self.vapi.cli("show gbp endpoint"))
- self.logger.info(self.vapi.cli("show l2fib all"))
- for l in learnt:
- p = (Ether(src=ep.mac, dst=l['mac']) /
- IP(dst=l['ip'], src=ep.ip4.address) /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100))
+ p = (Ether(src=ep.mac, dst=l['mac']) /
+ IP(dst=learnt[0]['ip'], src=ep.ip4.address) /
+ UDP(sport=1234, dport=1234) /
+ Raw('\xa5' * 100))
- self.send_and_assert_no_replies(self.pg0, [p], timeout=0.2)
+ 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 knwon EPG
+ # 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=330, flags=0x88, gpflags='A') /
+ VXLAN(vni=99, gpid=113, flags=0x88, gpflags='A') /
Ether(src=l['mac'], dst=ep.mac) /
IP(src=l['ip'], dst=ep.ip4.address) /
UDP(sport=1234, dport=1234) /
Raw('\xa5' * 100))
- rx = self.send_and_expect(self.pg2, p*65, 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,
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])
- c1 = VppGbpContract(self, 220, 330, acl_index)
+ c1 = VppGbpContract(
+ self, epg_220.sclass, epg_330.sclass, acl_index,
+ [VppGbpContractRule(
+ VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
+ []),
+ VppGbpContractRule(
+ VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
+ [])],
+ [ETH_P_IP, ETH_P_IPV6])
c1.add_vpp_config()
for l in learnt:
IP(dst="10.0.0.133", src=ep.ip4.address) /
UDP(sport=1234, dport=1234) /
Raw('\xa5' * 100))
- rxs = self.send_and_expect(ep.itf, [p_uu], gbd1.uu_flood)
-
- #
- # 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()
- bp_bm = VppBridgeDomainPort(self, bd1, tun_bm,
- port_type=L2_PORT_TYPE.NORMAL)
- bp_bm.add_vpp_config()
+ rxs = self.send_and_expect(ep.itf, [p_uu], gbd1.uu_fwd)
self.logger.info(self.vapi.cli("sh bridge 1 detail"))
Raw('\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)
+
#
# Check v6 Endpoints
#
for l in learnt:
- # a packet with an sclass from a knwon EPG
+ # 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=330, flags=0x88, gpflags='A') /
+ VXLAN(vni=99, gpid=113, flags=0x88, gpflags='A') /
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*65, 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,
#
# clean up
#
- self.sleep(2)
for l in learnt:
- self.assertFalse(find_gbp_endpoint(self,
- vx_tun_l2_1.sw_if_index,
- mac=l['mac']))
-
+ 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()
self.logger.info(self.vapi.cli("sh int"))
self.logger.info(self.vapi.cli("sh gbp vxlan"))
- def test_gbp_learn_vlan_l2(self):
- """ GBP L2 Endpoint w/ VLANs"""
-
- 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'}]
+ def test_gbp_contract(self):
+ """ GBP CONTRACTS """
#
- # lower the inactive threshold so these tests pass in a
- # reasonable amount of time
+ # Bridge Domains
#
- self.vapi.gbp_endpoint_learn_set_inactive_threshold(1)
+ 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, self.loop0)
+ gbd2 = VppGbpBridgeDomain(self, bd2, self.loop1)
+
+ gbd1.add_vpp_config()
+ gbd2.add_vpp_config()
#
- # IP tables
+ # Route Domains
#
- gt4 = VppIpTable(self, 1)
+ gt4 = VppIpTable(self, 0)
gt4.add_vpp_config()
- gt6 = VppIpTable(self, 1, is_ip6=True)
+ gt6 = VppIpTable(self, 0, is_ip6=True)
gt6.add_vpp_config()
- rd1 = VppGbpRouteDomain(self, 1, gt4, gt6)
- rd1.add_vpp_config()
+ rd0 = VppGbpRouteDomain(self, 0, gt4, gt6, None, None)
- #
+ rd0.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]:
+ VppIpInterfaceBind(self, epg.bvi, epg.rd.t4).add_vpp_config()
+ VppIpInterfaceBind(self, epg.bvi, epg.rd.t6).add_vpp_config()
+ self.vapi.sw_interface_set_mac_address(
+ epg.bvi.sw_if_index,
+ self.router_mac.packed)
+
+ if_ip4 = VppIpInterfaceAddress(self, epg.bvi, epg.bvi_ip4, 32)
+ if_ip6 = VppIpInterfaceAddress(self, epg.bvi, epg.bvi_ip6, 128)
+ if_ip4.add_vpp_config()
+ if_ip6.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.address,
+ dst=eps[1].ip4.address) /
+ UDP(sport=1234, dport=1234) /
+ Raw('\xa5' * 100))
+
+ self.send_and_expect_bridged(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.address,
+ dst=eps[2].ip4.address) /
+ UDP(sport=1234, dport=1234) /
+ Raw('\xa5' * 100))
+
+ self.send_and_assert_no_replies(self.pg0, pkt_inter_epg_220_to_221)
+
+ #
+ # A uni-directional contract from EPG 220 -> 221
+ #
+ 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])
+ c1 = VppGbpContract(
+ self, epgs[0].sclass, epgs[1].sclass, acl_index,
+ [VppGbpContractRule(
+ VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
+ []),
+ VppGbpContractRule(
+ VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
+ [])],
+ [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.address,
+ dst=eps[3].ip4.address) /
+ UDP(sport=1234, dport=1234) /
+ Raw('\xa5' * 100))
+ self.send_and_assert_no_replies(eps[0].itf,
+ pkt_inter_epg_220_to_222 * 65)
+
+ #
+ # contract for the return direction
+ #
+ c2 = VppGbpContract(
+ self, epgs[1].sclass, epgs[0].sclass, acl_index,
+ [VppGbpContractRule(
+ VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
+ []),
+ VppGbpContractRule(
+ VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
+ [])],
+ [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.address,
+ dst=eps[0].ip4.address) /
+ UDP(sport=1234, dport=1234) /
+ Raw('\xa5' * 100))
+ self.send_and_expect_bridged(eps[2].itf,
+ pkt_inter_epg_221_to_220 * 65,
+ eps[0].itf)
+
+ #
+ # contract between 220 and 222 uni-direction
+ #
+ c3 = VppGbpContract(
+ self, epgs[0].sclass, epgs[2].sclass, acl_index,
+ [VppGbpContractRule(
+ VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
+ []),
+ VppGbpContractRule(
+ VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
+ [])],
+ [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_flags(self):
+ """ GBP BD 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, gt4, gt6)
+ rd1.add_vpp_config()
+
+ #
+ # Pg3 hosts the IP4 UU-flood VXLAN tunnel
+ # Pg4 hosts the IP6 UU-flood VXLAN tunnel
+ #
+ 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, self.loop0, self.pg3, tun_bm,
+ 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)
+ 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 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.address) /
+ UDP(sport=1234, dport=1234) /
+ Raw('\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.address) /
+ UDP(sport=1234, dport=1234) /
+ Raw('\xa5' * 100))
+ 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_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, gt4, gt6)
+ rd1.add_vpp_config()
+
+ #
# Pg2 hosts the vxlan tunnel, hosts on pg2 to act as TEPs
#
self.pg2.config_ip4()
#
vlan_11 = VppDot1QSubint(self, self.pg0, 11)
vlan_11.admin_up()
- self.vapi.sw_interface_set_l2_tag_rewrite(vlan_11.sw_if_index,
- L2_VTR_OP.L2_POP_1,
- 11)
+ 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)
#
# The Endpoint-group in which we are learning endpoints
#
- epg_220 = VppGbpEndpointGroup(self, 220, rd1, gbd1,
+ epg_220 = VppGbpEndpointGroup(self, 220, 441, rd1, gbd1,
None, self.loop0,
"10.0.0.128",
- "2001:10::128")
+ "2001:10::128",
+ VppGbpEndpointRetention(2))
epg_220.add_vpp_config()
#
# The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
- # leanring enabled
+ # 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)
+ VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L2,
+ self.pg2.local_ip4)
vx_tun_l2_1.add_vpp_config()
#
# Send to the static EP
#
for ii, l in enumerate(learnt):
- # a packet with an sclass from a knwon EPG
+ # 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=220, flags=0x88) /
+ VXLAN(vni=99, gpid=441, flags=0x88) /
Ether(src=l['mac'], dst=ep.mac) /
IP(src=l['ip'], dst=ep.ip4.address) /
UDP(sport=1234, dport=1234) /
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, 220)
+ self.assertEqual(rx[VXLAN].gpid, 441)
self.assertEqual(rx[VXLAN].vni, 116)
self.assertTrue(rx[VXLAN].flags.G)
self.assertTrue(rx[VXLAN].flags.Instance)
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"
'ip': '10.0.1.3',
'ip6': '2001:10::3'}]
- #
- # lower the inactive threshold so these tests pass in a
- # reasonable amount of time
- #
- self.vapi.gbp_endpoint_learn_set_inactive_threshold(1)
-
#
# IP tables
#
rd1 = VppGbpRouteDomain(self, 2, t4, t6, tun_ip4_uu, tun_ip6_uu)
rd1.add_vpp_config()
- self.loop0.set_mac(self.router_mac.address)
+ self.loop0.set_mac(self.router_mac)
#
# Bind the BVI to the RD
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"))
- self.logger.info(self.vapi.cli("show l2fib all"))
# ... and has a /32 and /128 applied
ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
#
# The Endpoint-group in which we are learning endpoints
#
- epg_220 = VppGbpEndpointGroup(self, 220, rd1, gbd1,
+ epg_220 = VppGbpEndpointGroup(self, 220, 441, rd1, gbd1,
None, self.loop0,
"10.0.0.128",
- "2001:10::128")
+ "2001:10::128",
+ VppGbpEndpointRetention(2))
epg_220.add_vpp_config()
#
# The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
- # leanring enabled
+ # learning enabled
#
vx_tun_l3 = VppGbpVxlanTunnel(
self, 101, rd1.rd_id,
- VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3)
+ VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
+ self.pg2.local_ip4)
vx_tun_l3.add_vpp_config()
#
# learn some remote IPv4 EPs
#
for ii, l in enumerate(learnt):
- # a packet with an sclass from a knwon EPG
+ # 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=220, flags=0x88) /
+ 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.address) /
UDP(sport=1234, dport=1234) /
UDP(sport=1234, dport=1234) /
Raw('\xa5' * 100))
- rxs = self.send_and_expect(self.pg0, p*1, self.pg2)
+ 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, 220)
+ 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.assertEqual(inner[IP].src, ep.ip4.address)
self.assertEqual(inner[IP].dst, l['ip'])
- self.sleep(2)
for l in learnt:
self.assertFalse(find_gbp_endpoint(self,
tep1_sw_if_index,
# learn some remote IPv6 EPs
#
for ii, l in enumerate(learnt):
- # a packet with an sclass from a knwon EPG
+ # 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=220, flags=0x88) /
+ 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.address) /
UDP(sport=1234, dport=1234) /
UDP(sport=1234, dport=1234) /
Raw('\xa5' * 100))
- rxs = self.send_and_expect(self.pg0, p*65, self.pg2)
+ 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, 220)
+ 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.assertEqual(inner[IPv6].dst, l['ip6'])
self.logger.info(self.vapi.cli("sh gbp endpoint"))
- self.sleep(2)
for l in learnt:
- self.assertFalse(find_gbp_endpoint(self,
- tep1_sw_if_index,
- ip=l['ip']))
+ self.wait_for_ep_timeout(ip=l['ip'])
#
# Static sends to unknown EP with no route
#
# Add a route to static EP's v4 and v6 subnet
- # packets should be send on the v4/v6 uu=fwd interface resp.
+ # packets should be sent on the v4/v6 uu=fwd interface resp.
#
se_10_24 = VppGbpSubnet(
self, rd1, "10.0.0.0", 24,
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, 220)
+ self.assertEqual(rx[VXLAN].gpid, 441)
self.assertEqual(rx[VXLAN].vni, 114)
self.assertTrue(rx[VXLAN].flags.G)
self.assertTrue(rx[VXLAN].flags.Instance)
# learn some remote IPv4 EPs
#
for ii, l in enumerate(learnt):
- # a packet with an sclass from a knwon EPG
+ # 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,
+ IP(src=self.pg2.remote_hosts[2].ip4,
dst=self.pg2.local_ip4) /
UDP(sport=1234, dport=48879) /
- VXLAN(vni=101, gpid=220, flags=0x88) /
+ 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.address) /
UDP(sport=1234, dport=1234) /
tep1_sw_if_index = find_vxlan_gbp_tunnel(
self,
self.pg2.local_ip4,
- self.pg2.remote_hosts[1].ip4,
+ self.pg2.remote_hosts[2].ip4,
vx_tun_l3.vni)
self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
epg_220, None,
"10.0.0.88", "11.0.0.88",
"2001:10::88", "3001::88",
- VppEnum.vl_api_gbp_endpoint_flags_t.REMOTE,
+ ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
self.pg2.local_ip4,
self.pg2.remote_hosts[1].ip4,
mac=None)
epg_220, None,
learnt[0]['ip'], "11.0.0.101",
learnt[0]['ip6'], "3001::101",
- VppEnum.vl_api_gbp_endpoint_flags_t.REMOTE,
+ 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 leanred EP's v4 subnet
+ # 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(
UDP(sport=1234, dport=1234) /
Raw('\xa5' * 100))
- rxs = self.send_and_expect(self.pg0, p*65, self.pg2)
+ 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, 220)
+ 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.assertEqual(inner[IP].dst, ip)
#
- # remove the API remote EPs, they are now UU-fwd
+ # 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.logger.info(self.vapi.cli("show gbp endpoint"))
+ self.assertTrue(find_gbp_endpoint(self, ip=rep_2.ip4.address))
- for ip in ips:
- self.assertFalse(find_gbp_endpoint(self, ip=ip))
+ p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
+ IP(src=ep.ip4.address, dst=rep_2.ip4.address) /
+ UDP(sport=1234, dport=1234) /
+ Raw('\xa5' * 100))
+ rxs = self.send_and_expect(self.pg0, [p], self.pg2)
- p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
- IP(dst=ip, src=ep.ip4.address) /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100))
+ self.assertFalse(find_gbp_endpoint(self, ip=rep_88.ip4.address))
- rxs = self.send_and_expect(self.pg0, [p], self.pg4)
+ p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
+ IP(src=ep.ip4.address, dst=rep_88.ip4.address) /
+ UDP(sport=1234, dport=1234) /
+ Raw('\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.address)
+ self.wait_for_ep_timeout(ip=rep_2.ip4.address)
#
# shutdown with learnt endpoint present
#
- self.logger.info(self.vapi.cli("show gbp endpoint-group"))
+ 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.address) /
+ UDP(sport=1234, dport=1234) /
+ Raw('\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
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, 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 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, self.loop0)
+ gbd1.add_vpp_config()
+
+ bd2 = VppBridgeDomain(self, 2)
+ bd2.add_vpp_config()
+ gbd2 = VppGbpBridgeDomain(self, bd2, self.loop1)
+ gbd2.add_vpp_config()
+
+ # ... and has a /32 and /128 applied
+ ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
+ ip4_addr.add_vpp_config()
+ ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 128)
+ ip6_addr.add_vpp_config()
+ ip4_addr = VppIpInterfaceAddress(self, gbd2.bvi, "10.0.1.128", 32)
+ ip4_addr.add_vpp_config()
+ ip6_addr = VppIpInterfaceAddress(self, gbd2.bvi, "2001:11::128", 128)
+ ip6_addr.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(2))
+ epg_220.add_vpp_config()
+ epg_221 = VppGbpEndpointGroup(self, 221, 441, rd1, gbd2,
+ None, gbd2.bvi,
+ "10.0.1.128",
+ "2001:11::128",
+ VppGbpEndpointRetention(2))
+ epg_221.add_vpp_config()
+ epg_222 = VppGbpEndpointGroup(self, 222, 442, rd1, gbd1,
+ None, gbd1.bvi,
+ "10.0.2.128",
+ "2001:12::128",
+ VppGbpEndpointRetention(2))
+ 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, 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.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(2))
+ epg_320.add_vpp_config()
+ epg_321 = VppGbpEndpointGroup(self, 321, 551, rd1, gbd4,
+ None, gbd2.bvi,
+ "12.0.1.128",
+ "4001:11::128",
+ VppGbpEndpointRetention(2))
+ 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.address, dst=ep3.ip4.address) /
+ UDP(sport=1234, dport=1234) /
+ Raw('\xa5' * 100)),
+ (Ether(src=ep3.mac, dst=ep1.mac) /
+ IP(src=ep3.ip4.address, dst=ep1.ip4.address) /
+ UDP(sport=1234, dport=1234) /
+ Raw('\xa5' * 100))]
+ p6 = [(Ether(src=ep1.mac, dst=ep3.mac) /
+ IPv6(src=ep1.ip6.address, dst=ep3.ip6.address) /
+ UDP(sport=1234, dport=1234) /
+ Raw('\xa5' * 100)),
+ (Ether(src=ep3.mac, dst=ep1.mac) /
+ IPv6(src=ep3.ip6.address, dst=ep1.ip6.address) /
+ UDP(sport=1234, dport=1230) /
+ Raw('\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
+ #
+ 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])
+
+ #
+ # test the src-ip hash mode
+ #
+ c1 = VppGbpContract(
+ self, 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,
+ [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, 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,
+ [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.address)
+ self.assertEqual(rx[IP].dst, ep3.ip4.address)
+
+ 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.address)
+ self.assertEqual(rx[IP].dst, ep1.ip4.address)
+
+ 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.address)
+ self.assertEqual(inner[IPv6].dst, ep3.ip6.address)
+
+ 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.address)
+ self.assertEqual(rx[IPv6].dst, ep1.ip6.address)
+
+ #
+ # 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.address)
+ self.assertEqual(rx[IPv6].dst, ep3.ip6.address)
+
+ #
+ # 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.address)
+ self.assertEqual(inner[IPv6].dst, ep3.ip6.address)
+
+ c1.remove_vpp_config()
+ c2.remove_vpp_config()
+
+ #
+ # test the symmetric hash mode
+ #
+ c1 = VppGbpContract(
+ self, 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,
+ [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, 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,
+ [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.address)
+ self.assertEqual(rx[IP].dst, ep3.ip4.address)
+
+ 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.address)
+ self.assertEqual(rx[IP].dst, ep1.ip4.address)
+
+ #
+ # 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.address, dst=ep2.ip4.address) /
+ UDP(sport=1234, dport=1234) /
+ Raw('\xa5' * 100)),
+ (Ether(src=ep2.mac, dst=str(self.router_mac)) /
+ IP(src=ep2.ip4.address, dst=ep1.ip4.address) /
+ UDP(sport=1234, dport=1234) /
+ Raw('\xa5' * 100))]
+ p6 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
+ IPv6(src=ep1.ip6.address, dst=ep2.ip6.address) /
+ UDP(sport=1234, dport=1234) /
+ Raw('\xa5' * 100)),
+ (Ether(src=ep2.mac, dst=str(self.router_mac)) /
+ IPv6(src=ep2.ip6.address, dst=ep1.ip6.address) /
+ UDP(sport=1234, dport=1234) /
+ Raw('\xa5' * 100))]
+
+ c3 = VppGbpContract(
+ self, 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,
+ [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.address)
+ self.assertEqual(rx[IP].dst, ep2.ip4.address)
+
+ #
+ # learn a remote EP in EPG 221
+ #
+ 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, epg_221.sclass, epg_220.sclass, acl_index,
+ [VppGbpContractRule(
+ VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
+ []),
+ VppGbpContractRule(
+ VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
+ [])],
+ [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.address) /
+ UDP(sport=1234, dport=1234) /
+ Raw('\xa5' * 100))
+
+ rx = self.send_and_expect(self.pg7, [p], self.pg0)
+
+ # 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.address) /
+ UDP(sport=1234, dport=1234) /
+ Raw('\xa5' * 100))
+
+ rx = self.send_and_expect(self.pg7, [p], self.pg0)
+
+ # 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.address, dst="10.0.0.88") /
+ UDP(sport=1234, dport=1234) /
+ Raw('\xa5' * 100))]
+ p6 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
+ IPv6(src=ep1.ip6.address, dst="2001:10::88") /
+ UDP(sport=1234, dport=1234) /
+ Raw('\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.address)
+ 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.address)
+ self.assertEqual(rx[IPv6].dst, "2001:10::88")
+
+ #
+ # test the dst-ip hash mode
+ #
+ c5 = VppGbpContract(
+ self, 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,
+ [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.address)
+ 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.address)
+ self.assertEqual(rx[IPv6].dst, "2001:10::88")
+
+ #
+ # cleanup
+ #
+ 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, 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 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, 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(2))
+ epg_220.add_vpp_config()
+
+ # the BVIs have the subnets applied ...
+ ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 24)
+ ip4_addr.add_vpp_config()
+ ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 64)
+ ip6_addr.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
+ #
+ 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()
+
+ ext_itf = VppGbpExtItf(self, self.loop0, bd1, rd1)
+ 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()
+
+ #
+ # External Endpoints
+ #
+ eep1 = VppGbpEndpoint(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,
+ 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()
+
+ #
+ # 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()
+
+ #
+ # 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.address, 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)
+
+ #
+ # 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('\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('\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('\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.address, 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.address, dst=eep2.ip4.address) /
+ 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)
+
+ #
+ # A subnet reachable through the external EP1
+ #
+ ip_220 = VppIpRoute(self, "10.220.0.0", 24,
+ [VppRoutePath(eep1.ip4.address,
+ 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()
+
+ #
+ # A subnet reachable through the external EP2
+ #
+ ip_221 = VppIpRoute(self, "10.221.0.0", 24,
+ [VppRoutePath(eep2.ip4.address,
+ 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'))
+
+ 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, 4220, 4221, acl_index,
+ [VppGbpContractRule(
+ VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
+ []),
+ VppGbpContractRule(
+ VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
+ [])],
+ [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,
+ [VppGbpContractRule(
+ VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
+ []),
+ VppGbpContractRule(
+ VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
+ [])],
+ [ETH_P_IP, ETH_P_IPV6])
+ c2.add_vpp_config()
+ c3 = VppGbpContract(
+ self, 113, 4220, acl_index,
+ [VppGbpContractRule(
+ VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
+ []),
+ VppGbpContractRule(
+ VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
+ [])],
+ [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('\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('\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.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
+ #
+ 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,
+ 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, 4220, 4222, acl_index,
+ [VppGbpContractRule(
+ VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
+ []),
+ VppGbpContractRule(
+ VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
+ [])],
+ [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")
+
+ #
+ # 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)
+
+ #
+ # cleanup
+ #
+ self.pg7.unconfig_ip4()
+ vlan_100.set_vtr(L2_VTR_OP.L2_DISABLED)
+
if __name__ == '__main__':
unittest.main(testRunner=VppTestRunner)