fib: fib api updates

Enhance the route add/del APIs to take a set of paths rather than just one.
Most unicast routing protocols calcualte all the available paths in one
run of the algorithm so updating all the paths at once is beneficial for the client.
two knobs control the behaviour:
  is_multipath - if set the the set of paths passed will be added to those
                 that already exist, otherwise the set will replace them.
  is_add - add or remove the set

is_add=0, is_multipath=1 and an empty set, results in deleting the route.

It is also considerably faster to add multiple paths at once, than one at a time:

vat# ip_add_del_route 1.1.1.1/32 count 100000 multipath via 10.10.10.11
100000 routes in .572240 secs, 174751.80 routes/sec
vat# ip_add_del_route 1.1.1.1/32 count 100000 multipath via 10.10.10.12
100000 routes in .528383 secs, 189256.54 routes/sec
vat# ip_add_del_route 1.1.1.1/32 count 100000 multipath via 10.10.10.13
100000 routes in .757131 secs, 132077.52 routes/sec
vat# ip_add_del_route 1.1.1.1/32 count 100000 multipath via 10.10.10.14
100000 routes in .878317 secs, 113854.12 routes/sec

vat# ip_route_add_del 1.1.1.1/32 count 100000 multipath via 10.10.10.11 via 10.10.10.12 via 10.10.10.13 via 10.10.10.14
100000 routes in .900212 secs, 111084.93 routes/sec

Change-Id: I416b93f7684745099c1adb0b33edac58c9339c1a
Signed-off-by: Neale Ranns <neale.ranns@cisco.com>
Signed-off-by: Ole Troan <ot@cisco.com>
Signed-off-by: Paul Vinciguerra <pvinci@vinciconsulting.com>
This commit is contained in:
Neale Ranns
2018-05-01 05:17:55 -07:00
committed by Ole Trøan
parent 39baa32186
commit 097fa66b98
133 changed files with 4883 additions and 5081 deletions

View File

@ -34,9 +34,9 @@ class VppIpAddressUnion():
def encode(self):
if self.version == 6:
return {'ip6': self.ip_addr.packed}
return {'ip6': self.ip_addr}
else:
return {'ip4': self.ip_addr.packed}
return {'ip4': self.ip_addr}
@property
def version(self):
@ -69,6 +69,9 @@ class VppIpAddressUnion():
self, other)
return NotImplemented
def __str__(self):
return str(self.ip_addr)
class VppIpAddress():
def __init__(self, addr):
@ -153,10 +156,19 @@ class VppIpPrefix():
self.addr = VppIpAddress(addr)
self.len = len
def __eq__(self, other):
if self.address == other.address and self.len == other.len:
return True
return False
def encode(self):
return {'address': self.addr.encode(),
'address_length': self.len}
@property
def version(self):
return self.addr.version
@property
def address(self):
return self.addr.address
@ -191,12 +203,12 @@ class VppIpPrefix():
class VppIpMPrefix():
def __init__(self, saddr, gaddr, len):
def __init__(self, saddr, gaddr, glen):
self.saddr = saddr
self.gaddr = gaddr
self.len = len
self.ip_saddr = ip_address(text_type(self.saddr))
self.ip_gaddr = ip_address(text_type(self.gaddr))
self.glen = glen
self.ip_saddr = VppIpAddressUnion(text_type(self.saddr))
self.ip_gaddr = VppIpAddressUnion(text_type(self.gaddr))
if self.ip_saddr.version != self.ip_gaddr.version:
raise ValueError('Source and group addresses must be of the '
'same address family.')
@ -205,15 +217,58 @@ class VppIpMPrefix():
if 6 == self.ip_saddr.version:
prefix = {
'af': VppEnum.vl_api_address_family_t.ADDRESS_IP6,
'grp_address': {'ip6': self.ip_gaddr.packed},
'src_address': {'ip6': self.ip_saddr.packed},
'grp_address_length': self.len,
'grp_address': {
'ip6': self.gaddr
},
'src_address': {
'ip6': self.saddr
},
'grp_address_length': self.glen,
}
else:
prefix = {
'af': VppEnum.vl_api_address_family_t.ADDRESS_IP4,
'grp_address': {'ip4': self.ip_gaddr.packed},
'src_address': {'ip4': self.ip_saddr.packed},
'grp_address_length': self.len,
'grp_address': {
'ip4': self.gaddr
},
'src_address': {
'ip4': self.saddr
},
'grp_address_length': self.glen,
}
return prefix
@property
def length(self):
return self.glen
@property
def version(self):
return self.ip_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.ip_saddr == other.ip_gaddr and
self.ip_saddr == other.ip_saddr)
elif (hasattr(other, "grp_address_length") and
hasattr(other, "grp_address") and
hasattr(other, "src_address")):
# vl_api_mprefix_t
if 4 == self.ip_saddr.version:
if self.glen == other.grp_address_length and \
self.gaddr == str(other.grp_address.ip4) and \
self.saddr == str(other.src_address.ip4):
return True
return False
else:
return (self.glen == other.grp_address_length and
self.gaddr == other.grp_address.ip6 and
self.saddr == other.src_address.ip6)
else:
raise Exception("Comparing VppIpPrefix:%s with unknown type: %s" %
(self, other))
return False