aa7cfd04e7
Type: fix otherwise if two packets arrive with the same source address but from different VRFs, then they are treated as the same and they use the same LB and thus share the same fate. but the lookup, when done, results in two different LBs, and hence the fate can be different. Signed-off-by: Neale Ranns <neale@graphiant.com> Change-Id: Id6e16f7c577a561d9ddd7066339fa4385361d07f
231 lines
6.8 KiB
Python
231 lines
6.8 KiB
Python
"""
|
|
IP Types
|
|
|
|
"""
|
|
import logging
|
|
|
|
from ipaddress import ip_address
|
|
from socket import AF_INET, AF_INET6
|
|
from vpp_papi import VppEnum
|
|
from vpp_object import VppObject
|
|
try:
|
|
text_type = unicode
|
|
except NameError:
|
|
text_type = str
|
|
|
|
_log = logging.getLogger(__name__)
|
|
|
|
|
|
class DpoProto:
|
|
DPO_PROTO_IP4 = 0
|
|
DPO_PROTO_IP6 = 1
|
|
DPO_PROTO_MPLS = 2
|
|
DPO_PROTO_ETHERNET = 3
|
|
DPO_PROTO_BIER = 4
|
|
DPO_PROTO_NSH = 5
|
|
|
|
|
|
INVALID_INDEX = 0xffffffff
|
|
|
|
|
|
def get_dpo_proto(addr):
|
|
if ip_address(addr).version == 6:
|
|
return DpoProto.DPO_PROTO_IP6
|
|
else:
|
|
return DpoProto.DPO_PROTO_IP4
|
|
|
|
|
|
class VppIpAddressUnion():
|
|
def __init__(self, addr):
|
|
self.addr = addr
|
|
self.ip_addr = ip_address(text_type(self.addr))
|
|
|
|
def encode(self):
|
|
if self.version == 6:
|
|
return {'ip6': self.ip_addr}
|
|
else:
|
|
return {'ip4': self.ip_addr}
|
|
|
|
@property
|
|
def version(self):
|
|
return self.ip_addr.version
|
|
|
|
@property
|
|
def address(self):
|
|
return self.addr
|
|
|
|
@property
|
|
def length(self):
|
|
return self.ip_addr.max_prefixlen
|
|
|
|
@property
|
|
def bytes(self):
|
|
return self.ip_addr.packed
|
|
|
|
def __eq__(self, other):
|
|
if isinstance(other, self.__class__):
|
|
return self.ip_addr == other.ip_addr
|
|
elif hasattr(other, "ip4") and hasattr(other, "ip6"):
|
|
# vl_api_address_union_t
|
|
if 4 == self.version:
|
|
return self.ip_addr == other.ip4
|
|
else:
|
|
return self.ip_addr == other.ip6
|
|
else:
|
|
raise Exception("Comparing VppIpAddressUnions:%s"
|
|
" with incomparable type: %s",
|
|
self, other)
|
|
|
|
def __ne__(self, other):
|
|
return not (self == other)
|
|
|
|
def __str__(self):
|
|
return str(self.ip_addr)
|
|
|
|
|
|
class VppIpMPrefix():
|
|
def __init__(self, saddr, gaddr, glen):
|
|
self.saddr = saddr
|
|
self.gaddr = gaddr
|
|
self.glen = glen
|
|
if ip_address(self.saddr).version != \
|
|
ip_address(self.gaddr).version:
|
|
raise ValueError('Source and group addresses must be of the '
|
|
'same address family.')
|
|
|
|
def encode(self):
|
|
return {
|
|
'af': ip_address(self.gaddr).vapi_af,
|
|
'grp_address': {
|
|
ip_address(self.gaddr).vapi_af_name: self.gaddr
|
|
},
|
|
'src_address': {
|
|
ip_address(self.saddr).vapi_af_name: self.saddr
|
|
},
|
|
'grp_address_length': self.glen,
|
|
}
|
|
|
|
@property
|
|
def length(self):
|
|
return self.glen
|
|
|
|
@property
|
|
def version(self):
|
|
return ip_address(self.gaddr).version
|
|
|
|
def __str__(self):
|
|
return "(%s,%s)/%d" % (self.saddr, self.gaddr, self.glen)
|
|
|
|
def __eq__(self, other):
|
|
if isinstance(other, self.__class__):
|
|
return (self.glen == other.glen and
|
|
self.saddr == other.gaddr and
|
|
self.saddr == other.saddr)
|
|
elif (hasattr(other, "grp_address_length") and
|
|
hasattr(other, "grp_address") and
|
|
hasattr(other, "src_address")):
|
|
# vl_api_mprefix_t
|
|
if 4 == self.version:
|
|
return (self.glen == other.grp_address_length and
|
|
self.gaddr == str(other.grp_address.ip4) and
|
|
self.saddr == str(other.src_address.ip4))
|
|
else:
|
|
return (self.glen == other.grp_address_length and
|
|
self.gaddr == str(other.grp_address.ip6) and
|
|
self.saddr == str(other.src_address.ip6))
|
|
return NotImplemented
|
|
|
|
|
|
class VppIpPuntPolicer(VppObject):
|
|
def __init__(self, test, policer_index, is_ip6=False):
|
|
self._test = test
|
|
self._policer_index = policer_index
|
|
self._is_ip6 = is_ip6
|
|
|
|
def add_vpp_config(self):
|
|
self._test.vapi.ip_punt_police(policer_index=self._policer_index,
|
|
is_ip6=self._is_ip6, is_add=True)
|
|
|
|
def remove_vpp_config(self):
|
|
self._test.vapi.ip_punt_police(policer_index=self._policer_index,
|
|
is_ip6=self._is_ip6, is_add=False)
|
|
|
|
def query_vpp_config(self):
|
|
NotImplemented
|
|
|
|
|
|
class VppIpPuntRedirect(VppObject):
|
|
def __init__(self, test, rx_index, tx_index, nh_addr):
|
|
self._test = test
|
|
self._rx_index = rx_index
|
|
self._tx_index = tx_index
|
|
self._nh_addr = ip_address(nh_addr)
|
|
|
|
def encode(self):
|
|
return {"rx_sw_if_index": self._rx_index,
|
|
"tx_sw_if_index": self._tx_index, "nh": self._nh_addr}
|
|
|
|
def add_vpp_config(self):
|
|
self._test.vapi.ip_punt_redirect(punt=self.encode(), is_add=True)
|
|
self._test.registry.register(self, self._test.logger)
|
|
return self
|
|
|
|
def remove_vpp_config(self):
|
|
self._test.vapi.ip_punt_redirect(punt=self.encode(), is_add=False)
|
|
|
|
def get_vpp_config(self):
|
|
is_ipv6 = True if self._nh_addr.version == 6 else False
|
|
return self._test.vapi.ip_punt_redirect_dump(
|
|
sw_if_index=self._rx_index, is_ipv6=is_ipv6)
|
|
|
|
def query_vpp_config(self):
|
|
if self.get_vpp_config():
|
|
return True
|
|
return False
|
|
|
|
|
|
class VppIpPathMtu(VppObject):
|
|
def __init__(self, test, nh, pmtu, table_id=0):
|
|
self._test = test
|
|
self.nh = nh
|
|
self.pmtu = pmtu
|
|
self.table_id = table_id
|
|
|
|
def add_vpp_config(self):
|
|
self._test.vapi.ip_path_mtu_update(pmtu={'nh': self.nh,
|
|
'table_id': self.table_id,
|
|
'path_mtu': self.pmtu})
|
|
self._test.registry.register(self, self._test.logger)
|
|
return self
|
|
|
|
def modify(self, pmtu):
|
|
self.pmtu = pmtu
|
|
self._test.vapi.ip_path_mtu_update(pmtu={'nh': self.nh,
|
|
'table_id': self.table_id,
|
|
'path_mtu': self.pmtu})
|
|
return self
|
|
|
|
def remove_vpp_config(self):
|
|
self._test.vapi.ip_path_mtu_update(pmtu={'nh': self.nh,
|
|
'table_id': self.table_id,
|
|
'path_mtu': 0})
|
|
|
|
def query_vpp_config(self):
|
|
ds = list(self._test.vapi.vpp.details_iter(
|
|
self._test.vapi.ip_path_mtu_get))
|
|
|
|
for d in ds:
|
|
if self.nh == str(d.pmtu.nh) \
|
|
and self.table_id == d.pmtu.table_id \
|
|
and self.pmtu == d.pmtu.path_mtu:
|
|
return True
|
|
return False
|
|
|
|
def object_id(self):
|
|
return ("ip-path-mtu-%d-%s-%d" % (self.table_id,
|
|
self.nh,
|
|
self.pmtu))
|
|
|
|
def __str__(self):
|
|
return self.object_id()
|