Sync Phase: Implement MTU syncing (for both packet MTU and Max Frame Size)
This commit is contained in:
@ -303,6 +303,22 @@ class Reconciler():
|
|||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
def __tap_is_lcp(self, sw_if_index):
|
||||||
|
""" Returns True if the given sw_if_index is a TAP interface belonging to an LCP,
|
||||||
|
or False otherwise."""
|
||||||
|
if not sw_if_index in self.vpp.config['interfaces']:
|
||||||
|
return False
|
||||||
|
|
||||||
|
vpp_iface = self.vpp.config['interfaces'][sw_if_index]
|
||||||
|
if not vpp_iface.interface_dev_type=="virtio":
|
||||||
|
return False
|
||||||
|
|
||||||
|
match = False
|
||||||
|
for idx, lcp in self.vpp.config['lcps'].items():
|
||||||
|
if vpp_iface.sw_if_index == lcp.host_sw_if_index:
|
||||||
|
match = True
|
||||||
|
return match
|
||||||
|
|
||||||
def prune_sub_interfaces(self):
|
def prune_sub_interfaces(self):
|
||||||
""" Remove interfaces from VPP if they are not in the config. Start with inner-most (QinQ/QinAD), then
|
""" Remove interfaces from VPP if they are not in the config. Start with inner-most (QinQ/QinAD), then
|
||||||
Dot1Q/Dot1AD."""
|
Dot1Q/Dot1AD."""
|
||||||
@ -313,12 +329,7 @@ class Reconciler():
|
|||||||
if vpp_iface.sub_number_of_tags != numtags:
|
if vpp_iface.sub_number_of_tags != numtags:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
## Skip TAP interfaces belonging to an LCP
|
if self.__tap_is_lcp(vpp_iface.sw_if_index):
|
||||||
skip = False
|
|
||||||
for idx, lcp in self.vpp.config['lcps'].items():
|
|
||||||
if vpp_iface.sw_if_index == lcp.host_sw_if_index:
|
|
||||||
skip = True
|
|
||||||
if skip:
|
|
||||||
continue
|
continue
|
||||||
|
|
||||||
config_ifname, config_iface = interface.get_by_name(self.cfg, vpp_ifname)
|
config_ifname, config_iface = interface.get_by_name(self.cfg, vpp_ifname)
|
||||||
@ -550,17 +561,12 @@ class Reconciler():
|
|||||||
""" Set admin-state down for all interfaces that are not in the config. """
|
""" Set admin-state down for all interfaces that are not in the config. """
|
||||||
for ifname in self.vpp.get_qinx_interfaces() + self.vpp.get_dot1x_interfaces() + self.vpp.get_bondethernets() + self.vpp.get_phys() + self.vpp.get_vxlan_tunnels() + self.vpp.get_bvis() + self.vpp.get_loopbacks():
|
for ifname in self.vpp.get_qinx_interfaces() + self.vpp.get_dot1x_interfaces() + self.vpp.get_bondethernets() + self.vpp.get_phys() + self.vpp.get_vxlan_tunnels() + self.vpp.get_bvis() + self.vpp.get_loopbacks():
|
||||||
if not ifname in interface.get_interfaces(self.cfg):
|
if not ifname in interface.get_interfaces(self.cfg):
|
||||||
iface = self.vpp.config['interface_names'][ifname]
|
vpp_iface = self.vpp.config['interface_names'][ifname]
|
||||||
|
|
||||||
## Skip TAP interfaces belonging to an LCP
|
if self.__tap_is_lcp(vpp_iface.sw_if_index):
|
||||||
skip = False
|
|
||||||
for idx, lcp in self.vpp.config['lcps'].items():
|
|
||||||
if iface.sw_if_index == lcp.host_sw_if_index:
|
|
||||||
skip = True
|
|
||||||
if skip:
|
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if iface.flags & 1: # IF_STATUS_API_FLAG_ADMIN_UP
|
if vpp_iface.flags & 1: # IF_STATUS_API_FLAG_ADMIN_UP
|
||||||
self.logger.info("1> set interface state %s down" % ifname)
|
self.logger.info("1> set interface state %s down" % ifname)
|
||||||
|
|
||||||
return True
|
return True
|
||||||
@ -741,21 +747,6 @@ class Reconciler():
|
|||||||
bondmac_changed = True
|
bondmac_changed = True
|
||||||
bondmac = member_iface.l2_address
|
bondmac = member_iface.l2_address
|
||||||
self.logger.info("1> bond add %s %s" % (vpp_ifname, member_iface.interface_name))
|
self.logger.info("1> bond add %s %s" % (vpp_ifname, member_iface.interface_name))
|
||||||
if member_iface.link_mtu != config_mtu:
|
|
||||||
self.logger.info("2> set interface state %s down" % (member_iface.interface_name))
|
|
||||||
self.logger.info("2> set interface mtu %d %s" % (config_mtu, member_iface.interface_name))
|
|
||||||
self.logger.info("2> set interface state %s up" % (member_iface.interface_name))
|
|
||||||
elif not member_iface.flags & 1: # IF_STATUS_API_FLAG_ADMIN_UP
|
|
||||||
self.logger.info("3> set interface state %s up" % (member_iface.interface_name))
|
|
||||||
if bond_iface.link_mtu < config_mtu:
|
|
||||||
self.logger.warning("%s has a Max Frame Size (%d) lower than desired MTU (%d), this is unsupported" %
|
|
||||||
(vpp_ifname, bond_iface.link_mtu, config_mtu))
|
|
||||||
|
|
||||||
if bond_iface.mtu[0] != config_mtu:
|
|
||||||
## NOTE(pim) - VPP does not allow the link_mtu to change on a BondEthernet, so it can be the
|
|
||||||
## case that packet MTU > link_mtu if the desired MTU > 9000. This is because BondEthernets
|
|
||||||
## are always created with link_mtu 9000.
|
|
||||||
self.logger.info("4> set interface mtu packet %d %s" % (config_mtu, bond_iface.interface_name))
|
|
||||||
|
|
||||||
config_ifname, config_iface = interface.get_by_name(self.cfg, vpp_ifname)
|
config_ifname, config_iface = interface.get_by_name(self.cfg, vpp_ifname)
|
||||||
if bondmac_changed and 'lcp' in config_iface:
|
if bondmac_changed and 'lcp' in config_iface:
|
||||||
@ -788,10 +779,98 @@ class Reconciler():
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
def sync_l2xcs(self):
|
def sync_l2xcs(self):
|
||||||
return False
|
for ifname in interface.get_l2xc_interfaces(self.cfg):
|
||||||
|
config_ifname, config_iface = interface.get_by_name(self.cfg, ifname)
|
||||||
|
rx_iface = self.vpp.config['interface_names'][config_ifname]
|
||||||
|
tx_iface = self.vpp.config['interface_names'][config_iface['l2xc']]
|
||||||
|
l2xc_changed = False
|
||||||
|
if not rx_iface.sw_if_index in self.vpp.config['l2xcs']:
|
||||||
|
self.logger.info("1> set interface l2 xconnect %s %s" % (rx_iface.interface_name, tx_iface.interface_name))
|
||||||
|
l2xc_changed = True
|
||||||
|
elif not tx_iface.sw_if_index == self.vpp.config['l2xcs'][rx_iface.sw_if_index].tx_sw_if_index:
|
||||||
|
self.logger.info("2> set interface l2 xconnect %s %s" % (rx_iface.interface_name, tx_iface.interface_name))
|
||||||
|
l2xc_changed = True
|
||||||
|
if l2xc_changed and rx_iface.sub_number_of_tags > 0:
|
||||||
|
self.logger.info("3> set interface l2 tag-rewrite %s pop %d" % (rx_iface.interface_name, rx_iface.sub_number_of_tags))
|
||||||
|
return True
|
||||||
|
|
||||||
|
def sync_mtu_direction(self, shrink=True):
|
||||||
|
if shrink:
|
||||||
|
tag_list = [ 2, 1, 0 ]
|
||||||
|
else:
|
||||||
|
tag_list = [ 0, 1, 2 ]
|
||||||
|
|
||||||
|
for numtags in tag_list:
|
||||||
|
for idx, vpp_iface in self.vpp.config['interfaces'].items():
|
||||||
|
if vpp_iface.sub_number_of_tags != numtags:
|
||||||
|
continue
|
||||||
|
if vpp_iface.interface_dev_type=='local':
|
||||||
|
continue
|
||||||
|
if self.__tap_is_lcp(vpp_iface.sw_if_index):
|
||||||
|
continue
|
||||||
|
|
||||||
|
if vpp_iface.interface_dev_type=='Loopback':
|
||||||
|
config_ifname, config_iface = loopback.get_by_name(self.cfg, vpp_iface.interface_name)
|
||||||
|
elif vpp_iface.interface_dev_type=='BVI':
|
||||||
|
config_ifname, config_iface = bridgedomain.get_by_bvi_name(self.cfg, vpp_iface.interface_name)
|
||||||
|
else:
|
||||||
|
config_ifname, config_iface = interface.get_by_name(self.cfg, vpp_iface.interface_name)
|
||||||
|
if not config_iface:
|
||||||
|
self.logger.warning("Interface %s exists in VPP but not in config, this is dangerous" % vpp_iface.interface_name)
|
||||||
|
continue
|
||||||
|
|
||||||
|
config_mtu = 1500
|
||||||
|
if 'mtu' in config_iface:
|
||||||
|
config_mtu = config_iface['mtu']
|
||||||
|
|
||||||
|
if shrink and config_mtu < vpp_iface.mtu[0]:
|
||||||
|
self.logger.info("shrink 1> set interface mtu packet %d %s" % (config_mtu, vpp_iface.interface_name))
|
||||||
|
elif not shrink and config_mtu > vpp_iface.mtu[0]:
|
||||||
|
self.logger.info("grow 2> set interface mtu packet %d %s" % (config_mtu, vpp_iface.interface_name))
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
def sync_link_mtu(self):
|
||||||
|
for idx, vpp_iface in self.vpp.config['interfaces'].items():
|
||||||
|
if vpp_iface.sub_number_of_tags != 0:
|
||||||
|
continue
|
||||||
|
if vpp_iface.interface_dev_type in ['local', 'Loopback', 'BVI', 'VXLAN', 'virtio']:
|
||||||
|
continue
|
||||||
|
|
||||||
|
config_ifname, config_iface = interface.get_by_name(self.cfg, vpp_iface.interface_name)
|
||||||
|
if not config_iface:
|
||||||
|
self.logger.warning("Interface %s exists in VPP but not in config, this is dangerous" % vpp_iface.interface_name)
|
||||||
|
continue
|
||||||
|
config_mtu = interface.get_mtu(self.cfg, vpp_iface.interface_name)
|
||||||
|
|
||||||
|
if vpp_iface.interface_dev_type=='bond' and vpp_iface.link_mtu < config_mtu:
|
||||||
|
self.logger.warning("%s has a Max Frame Size (%d) lower than desired MTU (%d), this is unsupported" %
|
||||||
|
(vpp_iface.interface_name, vpp_iface.link_mtu, config_mtu))
|
||||||
|
continue
|
||||||
|
|
||||||
|
if interface.is_phy(self.cfg, vpp_iface.interface_name) and config_mtu != vpp_iface.link_mtu:
|
||||||
|
## If the interface is up, temporarily down it in order to change the Max Frame Size
|
||||||
|
if vpp_iface.flags & 1: # IF_STATUS_API_FLAG_ADMIN_UP
|
||||||
|
self.logger.info("2> set interface state %s down" % (vpp_iface.interface_name))
|
||||||
|
|
||||||
|
self.logger.info("2> set interface mtu %d %s" % (config_mtu, vpp_iface.interface_name))
|
||||||
|
|
||||||
|
if vpp_iface.flags & 1: # IF_STATUS_API_FLAG_ADMIN_UP
|
||||||
|
self.logger.info("2> set interface state %s up" % (vpp_iface.interface_name))
|
||||||
|
return True
|
||||||
|
|
||||||
def sync_mtu(self):
|
def sync_mtu(self):
|
||||||
return False
|
ret = True
|
||||||
|
if not self.sync_link_mtu():
|
||||||
|
self.logger.warning("Could not sync interface Max Frame Size in VPP")
|
||||||
|
ret = False
|
||||||
|
if not self.sync_mtu_direction(shrink=True):
|
||||||
|
self.logger.warning("Could not sync shrinking interface MTU in VPP")
|
||||||
|
ret = False
|
||||||
|
if not self.sync_mtu_direction(shrink=False):
|
||||||
|
self.logger.warning("Could not sync growing interface MTU in VPP")
|
||||||
|
ret = False
|
||||||
|
return ret
|
||||||
|
|
||||||
def sync_addresses(self):
|
def sync_addresses(self):
|
||||||
return False
|
return False
|
||||||
|
Reference in New Issue
Block a user