]> git.proxmox.com Git - mirror_ifupdown2.git/blobdiff - ifupdown2/addons/address.py
Merge pull request #121 from aderumier/arpaccept
[mirror_ifupdown2.git] / ifupdown2 / addons / address.py
index a2f86f3b9edf5d1f40bcba55b06738a560357919..a8ef1e25fe38a5132bc2443c54fb5392ce7295a9 100644 (file)
@@ -96,6 +96,11 @@ class address(moduleBase):
                               'dual connected VxLANs',
                               'validvals' : ['<ipv4>', ],
                               'example'  : ['clagd-vxlan-anycast-ip 36.0.0.11']},
+                      'arp-accept' :
+                            { 'help': 'Allow gratuitous arp to update arp table',
+                              'validvals': ['on', 'off', 'yes', 'no', '0', '1'],
+                              'default' : 'off',
+                              'example' : ['arp-accept on']},
                       'ip-forward' :
                             { 'help': 'ip forwarding flag',
                               'validvals': ['on', 'off', 'yes', 'no', '0', '1'],
@@ -272,6 +277,8 @@ class address(moduleBase):
     def _process_bridge(self, ifaceobj, up):
         hwaddress = self._get_hwaddress(ifaceobj)
         addrs = ifaceobj.get_attr_value_first('address')
+        arp_accept = ifaceobj.get_attr_value_first('arp-accept')
+        arp_accept = utils.boolean_support_binary(arp_accept)
         is_vlan_dev_on_vlan_aware_bridge = False
         is_bridge = self.ipcmd.is_bridge(ifaceobj.name)
         if not is_bridge:
@@ -290,12 +297,21 @@ class address(moduleBase):
                         self.write_file('/proc/sys/net/ipv4/conf/%s' % ifaceobj.name +
                                         '/arp_accept', '0')
                 else:
-                    self.write_file('/proc/sys/net/ipv4/conf/%s/arp_accept' % ifaceobj.name, '0')
+                    self.write_file('/proc/sys/net/ipv4/conf/%s/arp_accept' % ifaceobj.name, arp_accept)
         if hwaddress and is_vlan_dev_on_vlan_aware_bridge:
-           if up:
-              self.ipcmd.bridge_fdb_add(bridgename, hwaddress, vlan)
-           else:
-              self.ipcmd.bridge_fdb_del(bridgename, hwaddress, vlan)
+            if up:
+                # check statemanager to delete the old entry if necessary
+                try:
+                    for old_obj in statemanager.statemanager_api.get_ifaceobjs(ifaceobj.name) or []:
+                        old_hwaddress = old_obj.get_attr_value_first("hwaddress")
+                        if old_hwaddress and self.ipcmd.mac_str_to_int(old_hwaddress) != self.ipcmd.mac_str_to_int(hwaddress):
+                            self.ipcmd.bridge_fdb_del(bridgename, old_hwaddress, vlan)
+                            break
+                except:
+                    pass
+                self.ipcmd.bridge_fdb_add(bridgename, hwaddress, vlan)
+            else:
+                self.ipcmd.bridge_fdb_del(bridgename, hwaddress, vlan)
 
     def _get_anycast_addr(self, ifaceobjlist):
         for ifaceobj in ifaceobjlist:
@@ -603,10 +619,12 @@ class address(moduleBase):
             return
 
         if ifaceobj.link_kind:
-            # bonds and vxlan devices need an explicit set of mtu.
+            # bonds, vxlan and custom devices (like dummy) need an explicit set of mtu.
             # bridges don't need mtu set
             if (ifaceobj.link_kind & ifaceLinkKind.BOND or
-                ifaceobj.link_kind & ifaceLinkKind.VXLAN):
+                ifaceobj.link_kind & ifaceLinkKind.VXLAN or
+                ifaceobj.link_kind & ifaceLinkKind.OTHER
+            ):
                 running_mtu = self.ipcmd.link_get_mtu(ifaceobj.name)
                 if (self.default_mtu and running_mtu != self.default_mtu):
                     self.ipcmd.link_set(ifaceobj.name, 'mtu', self.default_mtu)
@@ -716,6 +734,11 @@ class address(moduleBase):
                                'bridge port' %ifaceobj.name)
             return
 
+        setting_default_value = False
+        if not ipforward:
+            setting_default_value = True
+            ipforward = self.ipforward
+
         if ipforward:
             ipforward = utils.boolean_support_binary(ipforward)
             # File read has been used for better performance
@@ -731,8 +754,15 @@ class address(moduleBase):
                                     %('/'.join(ifaceobj.name.split("."))),
                                     ipforward)
                 except Exception as e:
-                    ifaceobj.status = ifaceStatus.ERROR
-                    self.logger.error('%s: %s' %(ifaceobj.name, str(e)))
+                    if not setting_default_value:
+                        ifaceobj.status = ifaceStatus.ERROR
+                        self.logger.error('%s: %s' %(ifaceobj.name, str(e)))
+
+
+        setting_default_value = False
+        if not ip6forward:
+            setting_default_value = True
+            ip6forward = self.ip6forward
 
         if ip6forward:
             ip6forward = utils.boolean_support_binary(ip6forward)
@@ -751,8 +781,9 @@ class address(moduleBase):
                     # for example, setting mtu < 1280
                     # In such cases, log error only if user has configured
                     # ip6-forward
-                    ifaceobj.status = ifaceStatus.ERROR
-                    self.logger.error('%s: %s' %(ifaceobj.name, str(e)))
+                    if not setting_default_value:
+                        ifaceobj.status = ifaceStatus.ERROR
+                        self.logger.error('%s: %s' %(ifaceobj.name, str(e)))
 
     def process_mtu(self, ifaceobj, ifaceobj_getfunc):
         mtu = ifaceobj.get_attr_value_first('mtu')
@@ -841,6 +872,12 @@ class address(moduleBase):
         if addr_method not in ["dhcp", "ppp"]:
             self._inet_address_config(ifaceobj, ifaceobj_getfunc,
                                       force_reapply)
+        else:
+            # remove old addresses added by ifupdown2
+            # (if intf was moved from static config to dhcp)
+            for old_ifaceobj in statemanager.statemanager_api.get_ifaceobjs(ifaceobj.name) or []:
+                for addr in old_ifaceobj.get_attr_value("address") or []:
+                    self.ipcmd.addr_del(ifaceobj.name, addr)
 
         self.process_mtu(ifaceobj, ifaceobj_getfunc)
 
@@ -849,13 +886,25 @@ class address(moduleBase):
         except Exception as e:
             self.log_error('%s: %s' % (ifaceobj.name, str(e)), ifaceobj, raise_error=False)
 
+        self.up_hwaddress(ifaceobj)
+
+        gateways = ifaceobj.get_attr_value('gateway')
+        if not gateways:
+            gateways = []
+        prev_gw = self._get_prev_gateway(ifaceobj, gateways)
+        self._add_delete_gateway(ifaceobj, gateways, prev_gw)
+
+    def up_hwaddress(self, ifaceobj):
         try:
             hwaddress = self._get_hwaddress(ifaceobj)
+
             if hwaddress:
-                running_hwaddress = None
-                if not ifupdownflags.flags.PERFMODE: # system is clean
+                if not ifupdownflags.flags.PERFMODE:  # system is clean
                     running_hwaddress = self.ipcmd.link_get_hwaddress(ifaceobj.name)
-                if hwaddress != running_hwaddress:
+                else:
+                    running_hwaddress = None
+
+                if self.ipcmd.mac_str_to_int(running_hwaddress) != self.ipcmd.mac_str_to_int(hwaddress):
                     slave_down = False
                     netlink.link_set_updown(ifaceobj.name, "down")
                     if ifaceobj.link_kind & ifaceLinkKind.BOND:
@@ -865,7 +914,7 @@ class address(moduleBase):
                                 netlink.link_set_updown(l, "down")
                             slave_down = True
                     try:
-                        self.ipcmd.link_set(ifaceobj.name, 'address', hwaddress)
+                        self.ipcmd.link_set_hwaddress(ifaceobj.name, hwaddress, force=True)
                     finally:
                         netlink.link_set_updown(ifaceobj.name, "up")
                         if slave_down:
@@ -875,13 +924,7 @@ class address(moduleBase):
             # Handle special things on a bridge
             self._process_bridge(ifaceobj, True)
         except Exception, e:
-            self.log_error('%s: %s' %(ifaceobj.name, str(e)), ifaceobj)
-
-        gateways = ifaceobj.get_attr_value('gateway')
-        if not gateways:
-            gateways = []
-        prev_gw = self._get_prev_gateway(ifaceobj, gateways)
-        self._add_delete_gateway(ifaceobj, gateways, prev_gw)
+            self.log_error('%s: %s' % (ifaceobj.name, str(e)), ifaceobj)
 
     def _down(self, ifaceobj, ifaceobj_getfunc=None):
         try:
@@ -950,9 +993,12 @@ class address(moduleBase):
             bridgename = ifaceobj.lowerifaces[0]
             vlan = self._get_vlan_id(ifaceobj)
             if self.ipcmd.bridge_is_vlan_aware(bridgename):
-                fdb_addrs = self._get_bridge_fdbs(bridgename, str(vlan))
-                if not fdb_addrs or hwaddress not in fdb_addrs:
-                   return False
+                fdb_addrs = [self.ipcmd.mac_str_to_int(fdb_addr) for fdb_addr in self._get_bridge_fdbs(bridgename, str(vlan))]
+                if not fdb_addrs:
+                    return False
+                hwaddress_int = self.ipcmd.mac_str_to_int(hwaddress)
+                if hwaddress_int not in fdb_addrs:
+                    return False
         return True
 
     def _query_sysctl(self, ifaceobj, ifaceobjcurr):
@@ -1035,7 +1081,7 @@ class address(moduleBase):
         hwaddress = self._get_hwaddress(ifaceobj)
         if hwaddress:
             rhwaddress = self.ipcmd.link_get_hwaddress(ifaceobj.name)
-            if not rhwaddress  or rhwaddress != hwaddress:
+            if not rhwaddress or self.ipcmd.mac_str_to_int(rhwaddress) != self.ipcmd.mac_str_to_int(hwaddress):
                ifaceobjcurr.update_config_with_status('hwaddress', rhwaddress,
                        1)
             elif not self._check_addresses_in_bridge(ifaceobj, hwaddress):