From aa656ad315767a0c18b40f045d0c68cd940c2f0a Mon Sep 17 00:00:00 2001 From: Julien Fortin Date: Fri, 12 Aug 2022 15:58:02 +0200 Subject: [PATCH] lib: nlcache: merge existing MTU into new netlink object before caching Signed-off-by: Julien Fortin --- ifupdown2/lib/nlcache.py | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/ifupdown2/lib/nlcache.py b/ifupdown2/lib/nlcache.py index 0b7cedb..d94ad7a 100644 --- a/ifupdown2/lib/nlcache.py +++ b/ifupdown2/lib/nlcache.py @@ -2278,7 +2278,7 @@ class NetlinkListenerWithCache(nllistener.NetlinkManagerWithListener, BaseObject raise Exception(error_str) - def tx_nlpacket_get_response_with_error_and_cache_on_ack(self, packet): + def tx_nlpacket_get_response_with_error_and_cache_on_ack(self, packet, ifname=None): """ TX packet and manually cache the object """ @@ -2302,6 +2302,33 @@ class NetlinkListenerWithCache(nllistener.NetlinkManagerWithListener, BaseObject # we can ignore all errors pass + try: + # We might be pre-caching an updated object that is "incomplete". + # i.e. say you have an existing bond in the cache, on ifreload only + # one attribute is updated. Our object 'packet' here will only have + # a couple attributes (but overriding a 'full' object in the cache). + # We need to somehow 'merge' some of the attributes that are not + # updated, otherwise later calls to the cache might return None for + # the missing attributes. MTU is a prime example. + if ifname: + # To minimize the changes each parent function can decide to + # trigger this 'merge' code by provided the optional 'ifname' arg + + # MERGING MTU: + # First check if we are not already setting MTU in this packet + try: + packet_mtu = packet.attributes[Link.IFLA_MTU].value + except Exception: + packet_mtu = None + # Then update 'packet' before caching + if not packet_mtu: + old_packet_mtu = self.cache.get_link_attribute(ifname, Link.IFLA_MTU) + if old_packet_mtu: + packet.add_attribute(Link.IFLA_MTU, old_packet_mtu) + except Exception: + # we can ignore all errors + pass + # Then we can use our normal "add_link" API call to cache the packet # and fill up our additional internal data structures. self.cache.add_link(packet) @@ -3060,7 +3087,7 @@ class NetlinkListenerWithCache(nllistener.NetlinkManagerWithListener, BaseObject Link.IFLA_INFO_DATA: ifla_info_data }) link.build_message(next(self.sequence), self.pid) - return self.tx_nlpacket_get_response_with_error_and_cache_on_ack(link) + return self.tx_nlpacket_get_response_with_error_and_cache_on_ack(link, ifname=ifname) except Exception as e: raise Exception("%s: netlink: cannot create bond with attributes: %s" % (ifname, str(e)))