Second part of a BVI refactor

The handling of BVI is awkward, with the autoderived interface name
"bviXX" based on the bridgedomain bd_id. Lots of special casing happens
on account of this decision, and to make matters worse there is poor
interaction (leading to VPP crashes) when BVIs and Loopbacks are used
at the same time: https://lists.fd.io/g/vpp-dev/message/21116

In this commit, I reintroduce the ability to set bridgedomain virtual
interfaces by means of the 'bvi' keyword. The 'bvi' must:
- be a Loopback interface
- must be used at most once (bvi_unique())

When pruning, I now need to prune bridgedomains before pruning
loopbacks, because any given loopback might be a BVI for a bridge. So,
I'll remove the loop/BVI from the bridge (by setting it to L3) and only
then removing the loopback from VPP.

In the reconciler, remove BVIs that have changed in prune_bridgedomains()
and set it in sync_bridgedomains().
This commit is contained in:
Pim van Pelt
2022-03-27 20:39:19 +00:00
parent 850b982f2a
commit 2415d30c0a
8 changed files with 97 additions and 4 deletions

View File

@ -69,12 +69,12 @@ class Reconciler():
if not self.prune_lcps():
self.logger.warning("Could not prune LCPs from VPP")
ret = False
if not self.prune_loopbacks():
self.logger.warning("Could not prune Loopbacks from VPP")
ret = False
if not self.prune_bridgedomains():
self.logger.warning("Could not prune BridgeDomains from VPP")
ret = False
if not self.prune_loopbacks():
self.logger.warning("Could not prune Loopbacks from VPP")
ret = False
if not self.prune_l2xcs():
self.logger.warning("Could not prune L2 Cross Connects from VPP")
ret = False
@ -165,11 +165,16 @@ class Reconciler():
members = []
if not config_iface:
for member in bridge.sw_if_details:
if member.sw_if_index == bridge.bvi_sw_if_index:
continue
member_iface = self.vpp.config['interfaces'][member.sw_if_index]
member_ifname = member_iface.interface_name
if member_iface.sub_id > 0:
self.logger.info("1> set interface l2 tag-rewrite %s disable" % member_ifname)
self.logger.info("1> set interface l3 %s" % member_ifname)
if bridge.bvi_sw_if_index in self.vpp.config['interfaces']:
bviname = self.vpp.config['interfaces'][bridge.bvi_sw_if_index].interface_name
self.logger.info("1> set interface l3 %s" % bviname)
self.logger.info("1> create bridge-domain %d del" % idx)
else:
self.logger.debug("BridgeDomain OK: %s" % (bridgename))
@ -179,6 +184,11 @@ class Reconciler():
if interface.is_sub(self.cfg, member_ifname):
self.logger.info("1> set interface l2 tag-rewrite %s disable" % member_ifname)
self.logger.info("1> set interface l3 %s" % member_ifname)
if 'bvi' in config_iface:
bviname = self.vpp.config['interfaces'][bridge.bvi_sw_if_index].interface_name
if bviname != config_iface['bvi']:
self.logger.info("2> set interface l3 %s" % bviname)
return True
def prune_l2xcs(self):
@ -736,6 +746,12 @@ class Reconciler():
config_bridge_ifname, config_bridge_iface = bridgedomain.get_by_name(self.cfg, "bd%d"%instance)
if not 'interfaces' in config_bridge_iface:
continue
if 'bvi' in config_bridge_iface:
bviname = config_bridge_iface['bvi']
if bviname in self.vpp.config['interface_names'] and self.vpp.config['interface_names'][bviname].sw_if_index == bvi_sw_if_index:
continue
self.logger.info("1> set interface l2 bridge %s %d bvi" % (bviname, instance))
for member_ifname in config_bridge_iface['interfaces']:
member_ifname, member_iface = interface.get_by_name(self.cfg, member_ifname)
if not member_ifname in bridge_members: