]> git.proxmox.com Git - mirror_ifupdown2.git/blame - ifupdown2/addons/address.py
addons: address: ifquery-running: add hwaddress support
[mirror_ifupdown2.git] / ifupdown2 / addons / address.py
CommitLineData
35681c06 1#!/usr/bin/env python3
15ef32ea 2#
d486dd0d 3# Copyright 2014-2017 Cumulus Networks, Inc. All rights reserved.
15ef32ea
RP
4# Author: Roopa Prabhu, roopa@cumulusnetworks.com
5#
6
007cae35 7import socket
b99c724a
AB
8import json
9import time
10import subprocess
007cae35 11
8126ef0c
JF
12from distutils.util import strtobool
13
15ef32ea 14try:
3eb08b79 15 from ifupdown2.lib.addon import AddonWithIpBlackList
223ba5af
JF
16 from ifupdown2.nlmanager.nlmanager import Link
17
d486dd0d
JF
18 from ifupdown2.ifupdown.iface import *
19 from ifupdown2.ifupdown.utils import utils
d486dd0d
JF
20
21 from ifupdown2.ifupdownaddons.dhclient import dhclient
d486dd0d
JF
22 from ifupdown2.ifupdownaddons.modulebase import moduleBase
23
0e936c3f
JF
24 import ifupdown2.nlmanager.ipnetwork as ipnetwork
25
d486dd0d
JF
26 import ifupdown2.ifupdown.statemanager as statemanager
27 import ifupdown2.ifupdown.policymanager as policymanager
28 import ifupdown2.ifupdown.ifupdownflags as ifupdownflags
29 import ifupdown2.ifupdown.ifupdownconfig as ifupdownconfig
bd441a51 30except (ImportError, ModuleNotFoundError):
3eb08b79 31 from lib.addon import AddonWithIpBlackList
223ba5af
JF
32 from nlmanager.nlmanager import Link
33
15ef32ea 34 from ifupdown.iface import *
82908a2d 35 from ifupdown.utils import utils
d486dd0d 36
15ef32ea 37 from ifupdownaddons.dhclient import dhclient
d486dd0d
JF
38 from ifupdownaddons.modulebase import moduleBase
39
0e936c3f
JF
40 import nlmanager.ipnetwork as ipnetwork
41
d486dd0d 42 import ifupdown.statemanager as statemanager
84f33af6 43 import ifupdown.policymanager as policymanager
fc5e1735 44 import ifupdown.ifupdownflags as ifupdownflags
d486dd0d
JF
45 import ifupdown.ifupdownconfig as ifupdownconfig
46
15ef32ea 47
3eb08b79 48class address(AddonWithIpBlackList, moduleBase):
15ef32ea
RP
49 """ ifupdown2 addon module to configure address, mtu, hwaddress, alias
50 (description) on an interface """
51
223ba5af
JF
52 _modinfo = {
53 'mhelp': 'address configuration module for interfaces',
54 'attrs': {
55 'address': {
56 'help': 'The address of the interface. The format of the '
57 'address depends on the protocol. It is a dotted '
58 'quad for IP and a sequence of hexadecimal halfwords '
59 'separated by colons for IPv6. The ADDRESS may be '
60 'followed by a slash and a decimal number which '
61 'encodes the network prefix length.',
62 'validvals': ['<ipv4/prefixlen>', '<ipv6/prefixlen>'],
63 'multiline': True,
64 'example': [
65 'address 10.0.12.3/24',
66 'address 2000:1000:1000:1000:3::5/128'
67 ]
68 },
69 'netmask': {
70 'help': 'Address netmask',
71 'example': ['netmask 255.255.255.0'],
72 'compat': True
73 },
eb6ad1f7
AB
74 'dad-attempts': {
75 'help': 'Number of attempts to settle DAD (0 to disable DAD). '
76 'To use this feature, the ipv6_dad_handling_enabled '
77 'module global must be set to true',
78 'example': ['dad-attempts 0'],
79 'default': '60',
80 },
81 'dad-interval': {
82 'help': 'DAD state polling interval in seconds. '
83 'To use this feature, the ipv6_dad_handling_enabled '
84 'module global must be set to true',
85 'example': ['dad-interval 0.5'],
86 'default': '0.1',
87 },
223ba5af
JF
88 'broadcast': {
89 'help': 'The broadcast address on the interface.',
90 'validvals': ['<ipv4>'],
91 'example': ['broadcast 10.0.1.255']
92 },
93 'scope': {
94 'help': 'The scope of the area where this address is valid. '
95 'The available scopes are listed in file /etc/iproute2/rt_scopes. '
96 'Predefined scope values are: '
97 'global - the address is globally valid. '
98 'site - (IPv6 only, deprecated) the address is site local, i.e. it is valid inside this site. '
99 'link - the address is link local, i.e. it is valid only on this device. '
100 'host - the address is valid only inside this host.',
101 'validvals': ['universe', 'site', 'link', 'host', 'nowhere'],
102 'example': ['scope host']
103 },
104 'preferred-lifetime': {
105 'help': 'The preferred lifetime of this address; see section '
106 '5.5.4 of RFC 4862. When it expires, the address is '
107 'no longer used for new outgoing connections. '
108 'Defaults to forever.',
109 'validrange': ['0', '65535'],
110 'example': [
111 'preferred-lifetime forever',
112 'preferred-lifetime 10'
113 ]
114 },
115 'pointopoint': {
116 'help': 'Set the remote IP address for a point-to-point link',
117 'validvals': ['<ipv4/prefixlen>', '<ipv6/prefixlen>'],
118 'example': [
119 'pointopoint 10.10.10.42/32'
120 ]
121 },
122 'gateway': {
123 'help': 'Default gateway',
124 'validvals': ['<ipv4>', '<ipv6>'],
125 'multiline': True,
126 'example': ['gateway 255.255.255.0']
127 },
128 'mtu': {
129 'help': 'Interface MTU (maximum transmission unit)',
130 'validrange': ['552', '9216'],
131 'example': ['mtu 1600'],
132 'default': '1500'
133 },
134 'hwaddress': {
135 'help': 'Hardware address (mac)',
136 'validvals': ['<mac>'],
137 'example': ['hwaddress 44:38:39:00:27:b8']
138 },
139 'alias': {
140 'help': 'description/alias: give the device a symbolic name for easy reference.',
141 'example': ['alias testnetwork']
142 },
143 'address-purge': {
144 'help': 'Purge existing addresses. By default any existing '
145 'ip addresses on an interface are purged to match '
146 'persistant addresses in the interfaces file. Set '
147 'this attribute to \'no\' if you want to preserve '
148 'existing addresses',
149 'validvals': ['yes', 'no'],
150 'default': 'yes',
151 'example': ['address-purge yes/no']
152 },
153 'clagd-vxlan-anycast-ip': {
154 'help': 'Anycast local IP address for dual connected VxLANs',
155 'validvals': ['<ipv4>'],
156 'example': ['clagd-vxlan-anycast-ip 36.0.0.11']
157 },
158 'ip-forward': {
159 'help': 'ip forwarding flag',
160 'validvals': ['on', 'off', 'yes', 'no', '0', '1'],
161 'default': 'off',
162 'example': ['ip-forward off']
163 },
164 'ip6-forward': {
165 'help': 'ipv6 forwarding flag',
166 'validvals': ['on', 'off', 'yes', 'no', '0', '1'],
167 'default': 'off',
168 'example': ['ip6-forward off']
169 },
170 'mpls-enable': {
171 'help': 'mpls enable flag',
172 'validvals': ['yes', 'no'],
173 'default': 'no',
174 'example': ['mpls-enable yes']
175 },
176 'ipv6-addrgen': {
177 'help': 'enable disable ipv6 link addrgenmode',
178 'validvals': ['on', 'off'],
179 'default': 'on',
180 'example': [
181 'ipv6-addrgen on',
182 'ipv6-addrgen off'
183 ]
184 },
185 'arp-accept': {
186 'help': 'Allow gratuitous arp to update arp table',
187 'validvals': ['on', 'off', 'yes', 'no', '0', '1'],
188 'default': 'off',
189 'example': ['arp-accept on']
190 },
191 }
192 }
193
194 DEFAULT_MTU_STRING = "1500"
15ef32ea
RP
195
196 def __init__(self, *args, **kargs):
3eb08b79 197 AddonWithIpBlackList.__init__(self)
15ef32ea 198 moduleBase.__init__(self, *args, **kargs)
8e113d63 199 self._bridge_fdb_query_cache = {}
d486dd0d
JF
200 self.ipforward = policymanager.policymanager_api.get_attr_default(module_name=self.__class__.__name__, attr='ip-forward')
201 self.ip6forward = policymanager.policymanager_api.get_attr_default(module_name=self.__class__.__name__, attr='ip6-forward')
202 self.ifaces_defaults = policymanager.policymanager_api.get_iface_defaults(module_name=self.__class__.__name__)
203 self.enable_l3_iface_forwarding_checks = utils.get_boolean_from_string(
204 policymanager.policymanager_api.get_module_globals(
205 self.__class__.__name__,
206 'enable_l3_iface_forwarding_checks'
207 )
208 )
f4764e0f
AB
209 self.ipv6_dad_handling_enabled = utils.get_boolean_from_string(
210 policymanager.policymanager_api.get_module_globals(
211 self.__class__.__name__,
212 'ipv6_dad_handling_enabled'
213 ),
214 default=False
215 )
9f30b2cc 216
90937759 217 self.default_mtu = str(self.__policy_get_default_mtu())
cbda6dda
JF
218 self.default_mgmt_intf_mtu = self.__policy_get_mgmt_intf_mtu()
219 if not self.default_mgmt_intf_mtu:
220 self.default_mgmt_intf_mtu = self.default_mtu
221 self.default_mgmt_intf_mtu_int = self.default_mtu_int
222 self.max_mtu = self.__policy_get_max_mtu()
9f30b2cc 223
0e936c3f 224 self.default_loopback_addresses = (ipnetwork.IPNetwork('127.0.0.1/8'), ipnetwork.IPNetwork('::1/128'))
d486dd0d 225
8b57a467
JF
226 self.l3_intf_arp_accept = utils.get_boolean_from_string(
227 policymanager.policymanager_api.get_module_globals(
228 module_name=self.__class__.__name__,
229 attr='l3_intf_arp_accept'
230 ),
8126ef0c 231 default=0
8b57a467
JF
232 )
233
8126ef0c
JF
234 try:
235 l3_intf_arp_accept_str = policymanager.policymanager_api.get_module_globals(
236 module_name=self.__class__.__name__,
237 attr="l3_intf_arp_accept"
238 )
239 try:
240 self.l3_intf_arp_accept = int(l3_intf_arp_accept_str)
241 except:
242 self.l3_intf_arp_accept = int(strtobool(l3_intf_arp_accept_str))
243 except:
244 self.l3_intf_arp_accept = 0
245
9d505185
JF
246 self.l3_intf_default_gateway_set_onlink = utils.get_boolean_from_string(
247 policymanager.policymanager_api.get_module_globals(
248 module_name=self.__class__.__name__,
249 attr='l3_intf_default_gateway_set_onlink'
250 ),
251 default=True
252 )
253
20eab2b1
JF
254 self.check_l3_svi_ip_forwarding = utils.get_boolean_from_string(policymanager.policymanager_api.get_module_globals(
255 module_name=self.__class__.__name__,
256 attr="check_l3_svi_ip_forwarding")
257 )
258
223ba5af
JF
259 def __policy_get_default_mtu(self):
260 default_mtu = policymanager.policymanager_api.get_attr_default(
261 module_name=self.__class__.__name__,
262 attr="mtu"
263 )
264
265 if not default_mtu:
266 default_mtu = self.DEFAULT_MTU_STRING
267
268 try:
269 self.default_mtu_int = int(default_mtu)
270 except ValueError as e:
271 self.logger.error("address: invalid default mtu \"%s\" set via policy: %s" % (default_mtu, str(e)))
272 default_mtu = self.DEFAULT_MTU_STRING
273 self.default_mtu_int = int(self.DEFAULT_MTU_STRING)
274
275 self.logger.info("address: using default mtu %s" % default_mtu)
276
277 return default_mtu
278
279 def __policy_get_max_mtu(self):
280 max_mtu = policymanager.policymanager_api.get_module_globals(module_name=self.__class__.__name__, attr="max_mtu")
281 if max_mtu:
282 try:
283 max_mtu_int = int(max_mtu)
284 self.logger.info("address: using max mtu %s" % self.max_mtu)
285 return max_mtu_int
286 except ValueError as e:
287 self.logger.warning("address: policy max_mtu: %s" % str(e))
288 else:
289 self.logger.info("address: max_mtu undefined")
290 return 0
291
cbda6dda
JF
292 def __policy_get_mgmt_intf_mtu(self):
293 default_mgmt_mtu = policymanager.policymanager_api.get_module_globals(
294 module_name=self.__class__.__name__,
295 attr="mgmt_intf_mtu")
296 self.default_mgmt_mtu_int = None
297
298 if not default_mgmt_mtu:
299 return None
300
301 try:
302 self.default_mgmt_mtu_int = int(default_mgmt_mtu)
303 except ValueError as e:
304 self.logger.error("address: invalid default mgmt mtu \"%s\" set via policy: %s" % (default_mgmt_mtu, str(e)))
305 default_mgmt_mtu = self.DEFAULT_MTU_STRING
306 self.default_mgmt_mtu_int = int(self.DEFAULT_MTU_STRING)
307
308 self.logger.info("address: using default mgmt interface mtu %s" % default_mgmt_mtu)
309
310 return default_mgmt_mtu
311
09096420 312 def syntax_check(self, ifaceobj, ifaceobj_getfunc=None):
20eab2b1 313 self.syntax_check_l3_svi_ip_forward(ifaceobj)
22b49c28 314 return (self.syntax_check_multiple_gateway(ifaceobj)
09096420 315 and self.syntax_check_addr_allowed_on(ifaceobj, True)
d486dd0d
JF
316 and self.syntax_check_mtu(ifaceobj, ifaceobj_getfunc)
317 and self.syntax_check_sysctls(ifaceobj)
20eab2b1 318 and self.syntax_check_enable_l3_iface_forwardings(ifaceobj, ifaceobj_getfunc, syntax_check=True))
0b34071b
JF
319
320 def syntax_check_l3_svi_ip_forward(self, ifaceobj):
20eab2b1
JF
321 """ enabled via policy: 'check_l3_svi_ip_forwarding' """
322
323 if not self.check_l3_svi_ip_forwarding:
324 return True
325
0b34071b
JF
326 if ifaceobj.link_kind & ifaceLinkKind.VLAN and ifaceobj.link_privflags & ifaceLinkPrivFlags.VRF_SLAVE:
327 ip_forward = ifaceobj.get_attr_value_first("ip-forward")
328
329 if ip_forward and not utils.get_boolean_from_string(ip_forward):
20eab2b1 330 self.logger.error("%s: misconfiguration: disabling ip4 forwarding on an l3-svi is not allowed" % ifaceobj.name)
0b34071b
JF
331 return False
332
333 ip6_forward = ifaceobj.get_attr_value_first("ip6-forward")
334
335 if ip6_forward and not utils.get_boolean_from_string(ip6_forward):
20eab2b1 336 self.logger.error("%s: misconfiguration: disabling ip6 forwarding on an l3-svi is not allowed" % ifaceobj.name)
0b34071b
JF
337 return False
338
339 return True
d486dd0d
JF
340
341 def syntax_check_enable_l3_iface_forwardings(self, ifaceobj, ifaceobj_getfunc, syntax_check=False):
342 if (self.enable_l3_iface_forwarding_checks
343 and (ifaceobj.link_kind & ifaceLinkKind.VLAN
344 or ifaceobj.link_kind & ifaceLinkKind.BRIDGE)
345 and not ifaceobj.link_privflags & ifaceLinkPrivFlags.BRIDGE_PORT):
346
347 ifname = ifaceobj.name
348 vlan_addr = None
349 vlan_ipforward_off = None
350
351 for obj in ifaceobj_getfunc(ifname) or [ifaceobj]:
352 if not vlan_addr:
353 vlan_addr = obj.get_attr_value('address')
354
355 if not vlan_ipforward_off:
356 ip_forward_value = obj.get_attr_value_first('ip-forward')
357
358 if ip_forward_value and not utils.get_boolean_from_string(ip_forward_value):
359 vlan_ipforward_off = True
360
361 if vlan_addr and vlan_ipforward_off:
362 if syntax_check:
363 raise Exception(
364 'configuring ip-forward off and ip address(es) (%s) is not compatible'
365 % (', '.join(vlan_addr))
366 )
367 else:
368 raise Exception(
369 '%s: configuring ip-forward off and ip address(es) (%s) is not compatible'
370 % (ifname, ', '.join(vlan_addr))
371 )
372
373 return True
374
375 def syntax_check_sysctls(self, ifaceobj):
376 result = True
377 bridge_port = (ifaceobj.link_privflags & ifaceLinkPrivFlags.BRIDGE_PORT)
378 ipforward = ifaceobj.get_attr_value_first('ip-forward')
379 if bridge_port and ipforward:
380 result = False
381 self.log_error('%s: \'ip-forward\' is not supported for '
382 'bridge port' %ifaceobj.name)
383 ip6forward = ifaceobj.get_attr_value_first('ip6-forward')
384 if bridge_port and ip6forward:
385 result = False
386 self.log_error('%s: \'ip6-forward\' is not supported for '
387 'bridge port' %ifaceobj.name)
388 return result
09096420
RP
389
390 def syntax_check_mtu(self, ifaceobj, ifaceobj_getfunc):
223ba5af
JF
391 mtu_str = ifaceobj.get_attr_value_first('mtu')
392 if mtu_str:
393 try:
394 mtu_int = int(mtu_str)
395 except ValueError as e:
396 self.logger.warning("%s: invalid mtu %s: %s" % (ifaceobj.name, mtu_str, str(e)))
397 return False
398 return self._check_mtu_config(ifaceobj, mtu_str, mtu_int, ifaceobj_getfunc, syntaxcheck=True)
09096420 399 return True
22b49c28
JF
400
401 def syntax_check_addr_allowed_on(self, ifaceobj, syntax_check=False):
402 if ifaceobj.get_attr_value('address'):
403 return utils.is_addr_ip_allowed_on(ifaceobj, syntax_check=syntax_check)
404 return True
405
0e936c3f
JF
406 def _syntax_check_multiple_gateway(self, family, found, addr, version):
407 if ipnetwork.IPNetwork(addr).version == version:
38365d4a
JF
408 if found:
409 raise Exception('%s: multiple gateways for %s family'
410 % (addr, family))
411 return True
412 return False
413
22b49c28 414 def syntax_check_multiple_gateway(self, ifaceobj):
38365d4a
JF
415 result = True
416 inet = False
417 inet6 = False
418 gateways = ifaceobj.get_attr_value('gateway')
419 for addr in gateways if gateways else []:
420 try:
0e936c3f 421 if self._syntax_check_multiple_gateway('inet', inet, addr, 4):
38365d4a 422 inet = True
0e936c3f 423 if self._syntax_check_multiple_gateway('inet6', inet6, addr, 6):
38365d4a
JF
424 inet6 = True
425 except Exception as e:
426 self.logger.warning('%s: address: %s' % (ifaceobj.name, str(e)))
427 result = False
428 return result
429
75afe2a7
RP
430 def _address_valid(self, addrs):
431 if not addrs:
432 return False
3b01ed76
JF
433 if any([True if a[:7] != '0.0.0.0'
434 else False for a in addrs]):
75afe2a7
RP
435 return True
436 return False
437
428206bf 438 def _get_hwaddress(self, ifaceobj):
d486dd0d 439 return utils.strip_hwaddress(ifaceobj.get_attr_value_first('hwaddress'))
428206bf 440
4e0f16d0 441 def _process_bridge(self, ifaceobj, up, hwaddress, old_mac_addr=None):
75afe2a7 442 addrs = ifaceobj.get_attr_value_first('address')
45db39f6
AD
443 arp_accept = ifaceobj.get_attr_value_first('arp-accept')
444 arp_accept = utils.boolean_support_binary(arp_accept)
75afe2a7 445 is_vlan_dev_on_vlan_aware_bridge = False
223ba5af 446 is_bridge = self.cache.get_link_kind(ifaceobj.name) == 'bridge'
75afe2a7 447 if not is_bridge:
d486dd0d
JF
448 if ifaceobj.link_kind & ifaceLinkKind.VLAN:
449 bridgename = ifaceobj.lowerifaces[0]
450 vlan = self._get_vlan_id(ifaceobj)
223ba5af
JF
451 is_vlan_dev_on_vlan_aware_bridge = self.cache.bridge_is_vlan_aware(bridgename)
452 if ((is_bridge and not self.cache.bridge_is_vlan_aware(ifaceobj.name))
8c2c9f26 453 or is_vlan_dev_on_vlan_aware_bridge):
8b57a467
JF
454 if self._address_valid(addrs):
455 if self.l3_intf_arp_accept:
456 if up:
457 self.write_file('/proc/sys/net/ipv4/conf/%s' % ifaceobj.name +
8126ef0c 458 '/arp_accept', str(self.l3_intf_arp_accept))
8b57a467
JF
459 else:
460 self.write_file('/proc/sys/net/ipv4/conf/%s' % ifaceobj.name +
461 '/arp_accept', '0')
462 else:
45db39f6 463 self.write_file('/proc/sys/net/ipv4/conf/%s/arp_accept' % ifaceobj.name, arp_accept)
75afe2a7 464 if hwaddress and is_vlan_dev_on_vlan_aware_bridge:
1db0cb7a
JF
465 if old_mac_addr:
466 # corner case, first the user's /e/n/i is configured without 'hwaddress', then it is used to fix the svi
467 # mac address. The current code only checks for the statemanager for old 'hwaddress' attribute but
468 # couldn't find any. Now we save the mac addr before updating it, so we can later clear it from the fdb.
469 try:
4e0f16d0
JF
470 if utils.mac_str_to_int(old_mac_addr) != utils.mac_str_to_int(hwaddress):
471 self.iproute2.bridge_fdb_del(bridgename, old_mac_addr, vlan)
1db0cb7a
JF
472 except:
473 pass
15897163
JF
474 if up:
475 # check statemanager to delete the old entry if necessary
476 try:
477 for old_obj in statemanager.statemanager_api.get_ifaceobjs(ifaceobj.name) or []:
478 old_hwaddress = old_obj.get_attr_value_first("hwaddress")
223ba5af 479 if old_hwaddress and utils.mac_str_to_int(old_hwaddress) != utils.mac_str_to_int(hwaddress):
1db0cb7a
JF
480 if old_hwaddress != old_mac_addr:
481 self.iproute2.bridge_fdb_del(bridgename, old_hwaddress, vlan)
15897163 482 break
3218f49d 483 except Exception:
15897163 484 pass
223ba5af 485 self.iproute2.bridge_fdb_add(bridgename, hwaddress, vlan)
15897163 486 else:
223ba5af 487 self.iproute2.bridge_fdb_del(bridgename, hwaddress, vlan)
cb46a208 488
223ba5af 489 def __get_ip_addr_with_attributes(self, ifaceobj_list, ifname):
0e936c3f 490 user_config_ip_addrs_list = []
0582f185 491
223ba5af 492 try:
01a65536 493 for ifaceobj in ifaceobj_list or []:
0582f185 494
223ba5af 495 user_addrs = ifaceobj.get_attr_value("address")
0582f185 496
223ba5af
JF
497 if not user_addrs:
498 continue
499
500 if not self.syntax_check_addr_allowed_on(ifaceobj, syntax_check=False):
501 return False, None
502
503 for index, addr in enumerate(user_addrs):
504 addr_attributes = {}
505 addr_obj = None
506
507 # convert the ip from string to IPNetwork object
508 if "/" in addr:
0e936c3f 509 addr_obj = ipnetwork.IPNetwork(addr)
8de397ef 510 else:
223ba5af
JF
511 netmask = ifaceobj.get_attr_value_n("netmask", index)
512
513 if netmask:
0e936c3f 514 addr_obj = ipnetwork.IPNetwork(addr, netmask)
223ba5af 515 else:
0e936c3f 516 addr_obj = ipnetwork.IPNetwork(addr)
223ba5af 517
3fd6c201 518 for attr_name in ("broadcast", "scope", "preferred-lifetime"):
223ba5af
JF
519 attr_value = ifaceobj.get_attr_value_n(attr_name, index)
520 if attr_value:
521 addr_attributes[attr_name] = attr_value
522
523 pointopoint = ifaceobj.get_attr_value_n("pointopoint", index)
524 try:
525 if pointopoint:
0e936c3f 526 addr_attributes["pointopoint"] = ipnetwork.IPNetwork(pointopoint)
223ba5af
JF
527 except Exception as e:
528 self.logger.warning("%s: pointopoint %s: %s" % (ifaceobj.name, pointopoint, str(e)))
529
530 user_config_ip_addrs_list.append((addr_obj, addr_attributes))
531 except Exception as e:
01a65536 532 self.log_error("%s: convert string ip address into IPNetwork object: %s" % (ifname, str(e)), ifaceobj)
223ba5af
JF
533 return False, None
534
535 return True, user_config_ip_addrs_list
536
537 def __add_ip_addresses_with_attributes(self, ifaceobj, ifname, user_config_ip_addrs):
190cf3e6 538 ipv6_is_disabled = None
beaffab6
AB
539 nodad = False
540 if self.ipv6_dad_handling_enabled:
541 nodad = ifaceobj.get_attr_value_first('dad-attempts') == '0'
190cf3e6 542
e90c33ca
JF
543 for ip, attributes in user_config_ip_addrs:
544 try:
190cf3e6
JF
545 if ip.version == 6 and ipv6_is_disabled is None:
546 # check (only once) if ipv6 is disabled on this device
547 proc_path = "/proc/sys/net/ipv6/conf/%s/disable_ipv6" % ifname
548 ipv6_is_disabled = utils.get_boolean_from_string(self.read_file_oneline(proc_path))
549
550 if ipv6_is_disabled:
551 # enable ipv6
552 self.write_file(proc_path, "0")
553
3eb08b79
JF
554 # check if ip is not blacklisted
555 self.ip_blacklist_check(ifname, ip)
556
223ba5af
JF
557 if attributes:
558 self.netlink.addr_add(
559 ifname, ip,
560 scope=attributes.get("scope"),
561 peer=attributes.get("pointopoint"),
562 broadcast=attributes.get("broadcast"),
beaffab6
AB
563 preferred_lifetime=attributes.get("preferred-lifetime"),
564 nodad=nodad
223ba5af 565 )
77021aa1 566 else:
beaffab6 567 self.netlink.addr_add(ifname, ip, nodad=nodad)
e90c33ca
JF
568 except Exception as e:
569 self.log_error(str(e), ifaceobj, raise_error=False)
77021aa1 570
223ba5af
JF
571 @staticmethod
572 def __add_loopback_anycast_ip_to_running_ip_addr_list(ifaceobjlist):
573 """
574 if anycast address is configured on 'lo' and is in running
575 config add it to newaddrs so that ifreload doesn't wipe it out
576 :param ifaceobjlist:
577 :param running_ip_addrs:
578 """
579 anycast_ip_addr = None
0582f185 580
223ba5af
JF
581 for ifaceobj in ifaceobjlist:
582 anycast_addr = ifaceobj.get_attr_value_first("clagd-vxlan-anycast-ip")
583 if anycast_addr:
0e936c3f 584 anycast_ip_addr = ipnetwork.IPNetwork(anycast_addr)
223ba5af 585
0e936c3f 586 return anycast_ip_addr
223ba5af
JF
587
588 def process_addresses(self, ifaceobj, ifaceobj_getfunc=None, force_reapply=False):
589 squash_addr_config = ifupdownconfig.config.get("addr_config_squash", "0") == "1"
590
591 if squash_addr_config and not ifaceobj.flags & ifaceobj.YOUNGEST_SIBLING:
0582f185
RP
592 return
593
223ba5af
JF
594 ifname = ifaceobj.name
595 purge_addresses = utils.get_boolean_from_string(ifaceobj.get_attr_value_first("address-purge"), default=True)
596
597 if not squash_addr_config and ifaceobj.flags & iface.HAS_SIBLINGS:
598 # if youngest sibling and squash addr is not set
599 # print a warning that addresses will not be purged
600 if ifaceobj.flags & iface.YOUNGEST_SIBLING:
601 self.logger.warning("%s: interface has multiple iface stanzas, skip purging existing addresses" % ifname)
602 purge_addresses = False
0582f185
RP
603
604 if squash_addr_config and ifaceobj.flags & iface.HAS_SIBLINGS:
223ba5af 605 ifaceobj_list = ifaceobj_getfunc(ifname)
0582f185 606 else:
223ba5af 607 ifaceobj_list = [ifaceobj]
d486dd0d 608
223ba5af 609 addr_supported, user_config_ip_addrs_list = self.__get_ip_addr_with_attributes(ifaceobj_list, ifname)
d486dd0d 610
0582f185
RP
611 if not addr_supported:
612 return
0582f185 613
223ba5af
JF
614 if not ifupdownflags.flags.PERFMODE and purge_addresses:
615 # if perfmode is not set and purge addresses is set to True
0582f185 616 # lets purge addresses not in the config
223ba5af
JF
617 anycast_ip = None
618
0e936c3f 619 running_ip_addrs = self.cache.get_managed_ip_addresses(ifname, ifaceobj_list)
0582f185 620
223ba5af
JF
621 if ifaceobj.link_privflags & ifaceLinkPrivFlags.LOOPBACK:
622 anycast_ip = self.__add_loopback_anycast_ip_to_running_ip_addr_list(ifaceobj_list)
0582f185 623
223ba5af 624 user_ip4, user_ip6, ordered_user_configured_ips = self.order_user_configured_addrs(user_config_ip_addrs_list)
d486dd0d 625
223ba5af 626 if ordered_user_configured_ips == running_ip_addrs or self.compare_running_ips_and_user_config(user_ip4, user_ip6, running_ip_addrs):
77021aa1 627 if force_reapply:
223ba5af 628 self.__add_ip_addresses_with_attributes(ifaceobj, ifname, user_config_ip_addrs_list)
15ef32ea
RP
629 return
630 try:
223ba5af 631 # if primary address is not same, there is no need to keep any, reset all addresses.
0e936c3f 632 if ordered_user_configured_ips and running_ip_addrs and ordered_user_configured_ips[0] != running_ip_addrs[0]:
223ba5af 633 self.logger.info("%s: primary ip changed (from %s to %s) we need to purge all ip addresses and re-add them"
0e936c3f 634 % (ifname, ordered_user_configured_ips[0], running_ip_addrs[0]))
d486dd0d 635 skip_addrs = []
15ef32ea 636 else:
223ba5af
JF
637 skip_addrs = ordered_user_configured_ips
638
639 if anycast_ip:
640 skip_addrs.append(anycast_ip)
641
0e936c3f 642 for addr in running_ip_addrs:
d486dd0d
JF
643 if addr in skip_addrs:
644 continue
0e936c3f 645 self.netlink.addr_del(ifname, addr)
3b01ed76 646 except Exception as e:
15ef32ea 647 self.log_warn(str(e))
223ba5af 648 if not user_config_ip_addrs_list:
15ef32ea 649 return
223ba5af
JF
650 self.__add_ip_addresses_with_attributes(ifaceobj, ifname, user_config_ip_addrs_list)
651
d486dd0d
JF
652 def compare_running_ips_and_user_config(self, user_ip4, user_ip6, running_addrs):
653 """
654 We need to compare the user config ips and the running ips.
655 ip4 ordering matters (primary etc) but ip6 order doesn't matter
656
657 this function replaces the strict comparison previously in place
658 if newaddrs == running_addrs ?
659
660 We will compare if the ip4 ordering is correct, then check if all
661 ip6 are present in the list (without checking the ordering)
662 """
663 if (user_ip4 or user_ip6) and not running_addrs:
664 return False
665 elif running_addrs and not user_ip4 and not user_ip6:
666 return False
667 elif not running_addrs and not user_ip4 and not user_ip6:
668 return True
669
670 len_ip4 = len(user_ip4)
671 len_running_addrs = len(running_addrs)
672
673 if len_ip4 > len_running_addrs:
674 return False
675
676 i = 0
677 while i < len_ip4:
678 if user_ip4[i] != running_addrs[i]:
679 return False
680 i += 1
681
682 if len_ip4 > 0:
683 running_ip6 = running_addrs[len_ip4:]
684 else:
685 running_ip6 = running_addrs
686
687 i = 0
688 len_ip6 = len(user_ip6)
689
690 for ip6 in running_ip6:
691 if ip6 not in user_ip6:
692 return False
693 i += 1
694
695 return i == len_ip6
696
223ba5af
JF
697 @staticmethod
698 def order_user_configured_addrs(user_config_addrs):
d486dd0d
JF
699 ip4 = []
700 ip6 = []
701
223ba5af
JF
702 for a, _ in user_config_addrs:
703 if a.version == 6:
0e936c3f 704 ip6.append(a)
d486dd0d 705 else:
0e936c3f 706 ip4.append(a)
d486dd0d
JF
707
708 return ip4, ip6, ip4 + ip6
709
710 def _delete_gateway(self, ifaceobj, gateways, vrf, metric):
711 for del_gw in gateways:
0232d1bb 712 try:
223ba5af 713 self.iproute2.route_del_gateway(ifaceobj.name, del_gw, vrf, metric)
5b666749
JF
714 except Exception as e:
715 self.logger.debug('%s: %s' % (ifaceobj.name, str(e)))
d486dd0d
JF
716
717 def _add_delete_gateway(self, ifaceobj, gateways=[], prev_gw=[]):
718 vrf = ifaceobj.get_attr_value_first('vrf')
719 metric = ifaceobj.get_attr_value_first('metric')
720 self._delete_gateway(ifaceobj, list(set(prev_gw) - set(gateways)),
721 vrf, metric)
4b875c17 722 for add_gw in gateways:
0232d1bb 723 try:
223ba5af 724 self.iproute2.route_add_gateway(ifaceobj.name, add_gw, vrf, metric, onlink=self.l3_intf_default_gateway_set_onlink)
5b666749
JF
725 except Exception as e:
726 self.log_error('%s: %s' % (ifaceobj.name, str(e)))
0232d1bb
N
727
728 def _get_prev_gateway(self, ifaceobj, gateways):
729 ipv = []
730 saved_ifaceobjs = statemanager.statemanager_api.get_ifaceobjs(ifaceobj.name)
731 if not saved_ifaceobjs:
732 return ipv
733 prev_gateways = saved_ifaceobjs[0].get_attr_value('gateway')
734 if not prev_gateways:
735 return ipv
736 return prev_gateways
737
223ba5af 738 def _check_mtu_config(self, ifaceobj, mtu_str, mtu_int, ifaceobj_getfunc, syntaxcheck=False):
8d1e346f
RP
739 retval = True
740 if (ifaceobj.link_kind & ifaceLinkKind.BRIDGE):
741 if syntaxcheck:
c46af1c9 742 self.logger.warning('%s: bridge inherits mtu from its ports. There is no need to assign mtu on a bridge' %ifaceobj.name)
8d1e346f
RP
743 retval = False
744 else:
9f30b2cc 745 self.logger.info('%s: bridge inherits mtu from its ports. There is no need to assign mtu on a bridge' %ifaceobj.name)
8d1e346f
RP
746 elif ifaceobj_getfunc:
747 if ((ifaceobj.link_privflags & ifaceLinkPrivFlags.BOND_SLAVE) and
748 ifaceobj.upperifaces):
9f30b2cc
RP
749 masterobj = ifaceobj_getfunc(ifaceobj.upperifaces[0])
750 if masterobj:
751 master_mtu = masterobj[0].get_attr_value_first('mtu')
223ba5af
JF
752 if master_mtu and master_mtu != mtu_str:
753 log_msg = ("%s: bond slave mtu %s is different from bond master %s mtu %s. "
754 "There is no need to configure mtu on a bond slave." %
755 (ifaceobj.name, mtu_str, masterobj[0].name, master_mtu))
8d1e346f 756 if syntaxcheck:
c46af1c9 757 self.logger.warning(log_msg)
8d1e346f
RP
758 retval = False
759 else:
223ba5af 760 self.logger.info(log_msg)
8d1e346f
RP
761 elif ((ifaceobj.link_kind & ifaceLinkKind.VLAN) and
762 ifaceobj.lowerifaces):
763 lowerobj = ifaceobj_getfunc(ifaceobj.lowerifaces[0])
764 if lowerobj:
765 if syntaxcheck:
223ba5af 766 lowerdev_mtu = int(lowerobj[0].get_attr_value_first('mtu') or 0)
8d1e346f 767 else:
223ba5af
JF
768 lowerdev_mtu = self.cache.get_link_mtu(lowerobj[0].name) # return type: int
769 if lowerdev_mtu and mtu_int > lowerdev_mtu:
c46af1c9 770 self.logger.warning('%s: vlan dev mtu %s is greater than lower realdev %s mtu %s'
223ba5af 771 %(ifaceobj.name, mtu_str, lowerobj[0].name, lowerdev_mtu))
8d1e346f
RP
772 retval = False
773 elif (not lowerobj[0].link_kind and
774 not (lowerobj[0].link_privflags & ifaceLinkPrivFlags.LOOPBACK) and
223ba5af 775 not lowerdev_mtu and self.default_mtu and (mtu_int > self.default_mtu_int)):
8d1e346f 776 # only check default mtu on lower device which is a physical interface
c46af1c9 777 self.logger.warning('%s: vlan dev mtu %s is greater than lower realdev %s mtu %s'
223ba5af 778 %(ifaceobj.name, mtu_str, lowerobj[0].name, self.default_mtu))
8d1e346f 779 retval = False
223ba5af 780 if self.max_mtu and mtu_int > self.max_mtu:
c46af1c9 781 self.logger.warning('%s: specified mtu %s is greater than max mtu %s'
223ba5af 782 %(ifaceobj.name, mtu_str, self.max_mtu))
8d1e346f
RP
783 retval = False
784 return retval
785
223ba5af 786 def _propagate_mtu_to_upper_devs(self, ifaceobj, mtu_str, mtu_int, ifaceobj_getfunc):
8d1e346f
RP
787 if (not ifaceobj.upperifaces or
788 (ifaceobj.link_privflags & ifaceLinkPrivFlags.BOND_SLAVE) or
789 (ifaceobj.link_privflags & ifaceLinkPrivFlags.VRF_SLAVE) or
790 (ifaceobj.link_privflags & ifaceLinkPrivFlags.BRIDGE_PORT)):
791 return
792 for u in ifaceobj.upperifaces:
793 upperobjs = ifaceobj_getfunc(u)
794 if (not upperobjs or
795 not (upperobjs[0].link_kind & ifaceLinkKind.VLAN)):
796 continue
797 # only adjust mtu for vlan devices on ifaceobj
798 umtu = upperobjs[0].get_attr_value_first('mtu')
799 if not umtu:
223ba5af
JF
800 running_mtu = self.cache.get_link_mtu(upperobjs[0].name)
801 if not running_mtu or running_mtu != mtu_int:
802 self.sysfs.link_set_mtu(u, mtu_str=mtu_str, mtu_int=mtu_int)
8d1e346f 803
223ba5af
JF
804 def _process_mtu_config_mtu_valid(self, ifaceobj, ifaceobj_getfunc, mtu_str, mtu_int):
805 if not self._check_mtu_config(ifaceobj, mtu_str, mtu_int, ifaceobj_getfunc):
806 return
807
808 if mtu_int != self.cache.get_link_mtu(ifaceobj.name):
809 self.sysfs.link_set_mtu(ifaceobj.name, mtu_str=mtu_str, mtu_int=mtu_int)
810
811 if (not ifupdownflags.flags.ALL and
8d1e346f 812 not ifaceobj.link_kind and
d486dd0d 813 ifupdownconfig.config.get('adjust_logical_dev_mtu', '1') != '0'):
223ba5af
JF
814 # This is additional cost to us, so do it only when
815 # ifupdown2 is called on a particular interface and
816 # it is a physical interface
817 self._propagate_mtu_to_upper_devs(ifaceobj, mtu_str, mtu_int, ifaceobj_getfunc)
818 return
819
820 def _process_mtu_config_mtu_none(self, ifaceobj):
cbda6dda
JF
821
822 if (ifaceobj.link_privflags & ifaceLinkPrivFlags.MGMT_INTF):
823 return
824
223ba5af 825 cached_link_mtu = self.cache.get_link_mtu(ifaceobj.name)
9f30b2cc
RP
826
827 if ifaceobj.link_kind:
19ee2b11 828 # bonds, vxlan and custom devices (like dummy) need an explicit set of mtu.
9f30b2cc 829 # bridges don't need mtu set
223ba5af
JF
830 if ifaceobj.link_kind & ifaceLinkKind.BOND \
831 or ifaceobj.link_kind & ifaceLinkKind.VXLAN \
a3df9e69 832 or ifaceobj.link_kind & ifaceLinkKind.BRIDGE \
223ba5af
JF
833 or ifaceobj.link_kind & ifaceLinkKind.OTHER:
834 if cached_link_mtu != self.default_mtu_int:
835 self.sysfs.link_set_mtu(ifaceobj.name, mtu_str=self.default_mtu, mtu_int=self.default_mtu_int)
9f30b2cc 836 return
223ba5af 837
d486dd0d 838 if (ifupdownconfig.config.get('adjust_logical_dev_mtu', '1') != '0'
9f30b2cc
RP
839 and ifaceobj.lowerifaces):
840 # set vlan interface mtu to lower device mtu
841 if (ifaceobj.link_kind & ifaceLinkKind.VLAN):
d486dd0d 842 lower_iface = ifaceobj.lowerifaces[0]
223ba5af 843 lower_iface_mtu_int = self.cache.get_link_mtu(lower_iface)
d486dd0d 844
223ba5af
JF
845 if lower_iface_mtu_int != cached_link_mtu:
846 self.sysfs.link_set_mtu(ifaceobj.name, mtu_str=str(lower_iface_mtu_int), mtu_int=lower_iface_mtu_int)
9f30b2cc
RP
847
848 elif (not (ifaceobj.name == 'lo') and not ifaceobj.link_kind and
849 not (ifaceobj.link_privflags & ifaceLinkPrivFlags.BOND_SLAVE) and
850 self.default_mtu):
851 # logical devices like bridges and vlan devices rely on mtu
852 # from their lower devices. ie mtu travels from
853 # lower devices to upper devices. For bonds mtu travels from
854 # upper to lower devices. running mtu depends on upper and
855 # lower device mtu. With all this implicit mtu
856 # config by the kernel in play, we try to be cautious here
857 # on which devices we want to reset mtu to default.
858 # essentially only physical interfaces which are not bond slaves
223ba5af
JF
859 if cached_link_mtu != self.default_mtu_int:
860 self.sysfs.link_set_mtu(ifaceobj.name, mtu_str=self.default_mtu, mtu_int=self.default_mtu_int)
9f30b2cc 861
d486dd0d
JF
862 def _set_bridge_forwarding(self, ifaceobj):
863 """ set ip forwarding to 0 if bridge interface does not have a
864 ip nor svi """
2185a108 865 ifname = ifaceobj.name
223ba5af
JF
866
867 netconf_ipv4_forwarding = self.cache.get_netconf_forwarding(socket.AF_INET, ifname)
868 netconf_ipv6_forwarding = self.cache.get_netconf_forwarding(socket.AF_INET6, ifname)
869
69825bb4 870 if not ifaceobj.upperifaces and not ifaceobj.get_attr_value('address') and (ifaceobj.addr_method and "dhcp" not in ifaceobj.addr_method):
223ba5af 871 if netconf_ipv4_forwarding:
2185a108 872 self.sysctl_write_forwarding_value_to_proc(ifname, "ipv4", 0)
223ba5af 873 if netconf_ipv6_forwarding:
2185a108 874 self.sysctl_write_forwarding_value_to_proc(ifname, "ipv6", 0)
d486dd0d 875 else:
223ba5af 876 if not netconf_ipv4_forwarding:
2185a108 877 self.sysctl_write_forwarding_value_to_proc(ifname, "ipv4", 1)
223ba5af 878 if not netconf_ipv6_forwarding:
2185a108
JF
879 self.sysctl_write_forwarding_value_to_proc(ifname, "ipv6", 1)
880
2185a108
JF
881 def sysctl_write_forwarding_value_to_proc(self, ifname, family, value):
882 self.write_file("/proc/sys/net/%s/conf/%s/forwarding" % (family, ifname), "%s\n" % value)
d486dd0d
JF
883
884 def _sysctl_config(self, ifaceobj):
885 setting_default_value = False
886 mpls_enable = ifaceobj.get_attr_value_first('mpls-enable');
887 if not mpls_enable:
888 setting_default_value = True
889 mpls_enable = self.get_mod_subattr('mpls-enable', 'default')
890 mpls_enable = utils.boolean_support_binary(mpls_enable)
891 # File read has been used for better performance
892 # instead of using sysctl command
893 if ifupdownflags.flags.PERFMODE:
894 running_mpls_enable = '0'
895 else:
223ba5af 896 running_mpls_enable = str(self.cache.get_netconf_mpls_input(ifaceobj.name))
d486dd0d
JF
897
898 if mpls_enable != running_mpls_enable:
899 try:
900 self.sysctl_set('net.mpls.conf.%s.input'
901 %('/'.join(ifaceobj.name.split("."))),
902 mpls_enable)
903 except Exception as e:
904 if not setting_default_value:
905 ifaceobj.status = ifaceStatus.ERROR
906 self.logger.error('%s: %s' %(ifaceobj.name, str(e)))
907
908 if (ifaceobj.link_kind & ifaceLinkKind.BRIDGE):
909 self._set_bridge_forwarding(ifaceobj)
910 return
911 if not self.syntax_check_sysctls(ifaceobj):
912 return
0b34071b
JF
913 if not self.syntax_check_l3_svi_ip_forward(ifaceobj):
914 return
915
d486dd0d
JF
916 ipforward = ifaceobj.get_attr_value_first('ip-forward')
917 ip6forward = ifaceobj.get_attr_value_first('ip6-forward')
918 if ifupdownflags.flags.PERFMODE:
919 if ipforward:
920 self.sysctl_set('net.ipv4.conf.%s.forwarding'
921 %('/'.join(ifaceobj.name.split("."))),
922 utils.boolean_support_binary(ipforward))
923 if ip6forward:
924 self.sysctl_set('net.ipv6.conf.%s.forwarding'
925 %('/'.join(ifaceobj.name.split("."))),
926 utils.boolean_support_binary(ip6forward))
927 return
928 bridge_port = ifaceobj.link_privflags & ifaceLinkPrivFlags.BRIDGE_PORT
929 if bridge_port:
930 if ipforward:
931 self.log_error('%s: \'ip-forward\' is not supported for '
932 'bridge port' %ifaceobj.name)
933 if ip6forward:
934 self.log_error('%s: \'ip6-forward\' is not supported for '
935 'bridge port' %ifaceobj.name)
936 return
52712b1a
AD
937 setting_default_value = False
938 if not ipforward:
939 setting_default_value = True
34de8712
AD
940 ipforward = self.ipforward
941 if ipforward:
942 ipforward = int(utils.get_boolean_from_string(ipforward))
943 running_ipforward = self.cache.get_netconf_forwarding(socket.AF_INET, ifaceobj.name)
944 if ipforward != running_ipforward:
945 try:
946 self.sysctl_set('net.ipv4.conf.%s.forwarding'
947 %('/'.join(ifaceobj.name.split("."))),
948 ipforward)
949 except Exception as e:
950 if not setting_default_value:
951 ifaceobj.status = ifaceStatus.ERROR
952 self.logger.error('%s: %s' %(ifaceobj.name, str(e)))
52712b1a
AD
953
954 setting_default_value = False
34de8712 955
52712b1a
AD
956 if not ip6forward:
957 setting_default_value = True
34de8712
AD
958 ip6forward = self.ip6forward
959
960 if ip6forward:
961 ip6forward = int(utils.get_boolean_from_string(ip6forward))
962 running_ip6forward = self.cache.get_netconf_forwarding(socket.AF_INET6, ifaceobj.name)
963 if ip6forward != running_ip6forward:
964 try:
965 self.sysctl_set('net.ipv6.conf.%s.forwarding'
966 %('/'.join(ifaceobj.name.split("."))),
967 ip6forward)
968 except Exception as e:
969 # There is chance of ipv6 being removed because of,
970 # for example, setting mtu < 1280
971 # In such cases, log error only if user has configured
972 # ip6-forward
973 if not setting_default_value:
974 ifaceobj.status = ifaceStatus.ERROR
975 self.logger.error('%s: %s' %(ifaceobj.name, str(e)))
d486dd0d
JF
976
977 def process_mtu(self, ifaceobj, ifaceobj_getfunc):
8994bdd3
AD
978
979 if ifaceobj.link_privflags & ifaceLinkPrivFlags.OPENVSWITCH:
980 return
981
223ba5af
JF
982 mtu_str = ifaceobj.get_attr_value_first('mtu')
983 mtu_from_policy = False
d486dd0d 984
223ba5af 985 if not mtu_str:
cbda6dda
JF
986 if (ifaceobj.link_privflags & ifaceLinkPrivFlags.MGMT_INTF):
987 mtu_str = self.default_mgmt_intf_mtu
988 if not mtu_str:
989 mtu_str = self.ifaces_defaults.get(ifaceobj.name, {}).get('mtu')
990
223ba5af 991 mtu_from_policy = True
d486dd0d 992
223ba5af
JF
993 if mtu_str:
994 try:
995 mtu_int = int(mtu_str)
996 except Exception as e:
997 if mtu_from_policy:
998 self.logger.warning("%s: invalid MTU value from policy file (iface_defaults): %s" % (ifaceobj.name, str(e)))
999 else:
1000 self.logger.warning("%s: invalid MTU value: %s" % (ifaceobj.name, str(e)))
1001 return
d486dd0d 1002
223ba5af
JF
1003 self._process_mtu_config_mtu_valid(ifaceobj, ifaceobj_getfunc, mtu_str, mtu_int)
1004 else:
1005 self._process_mtu_config_mtu_none(ifaceobj)
d486dd0d 1006
3fc54eef 1007 def up_ipv6_addrgen(self, ifaceobj):
007cae35
JF
1008 user_configured_ipv6_addrgen = ifaceobj.get_attr_value_first('ipv6-addrgen')
1009
b306a8b6
JF
1010 if not user_configured_ipv6_addrgen and ifupdownflags.flags.PERFMODE:
1011 # no need to go further during perfmode (boot)
1012 return
1013
223ba5af 1014 if not user_configured_ipv6_addrgen and ifaceobj.addr_method in ["dhcp", "ppp"]:
cd890b06
JF
1015 return
1016
007cae35 1017 if not user_configured_ipv6_addrgen:
17da0561
JF
1018 # if user didn't configure ipv6-addrgen, should we reset to default?
1019 user_configured_ipv6_addrgen = self.get_attr_default_value('ipv6-addrgen')
007cae35
JF
1020
1021 ipv6_addrgen_nl = {
1022 'on': 0,
1023 'yes': 0,
1024 '0': 0,
1025 'off': 1,
1026 'no': 1,
1027 '1': 1
1028 }.get(user_configured_ipv6_addrgen.lower(), None)
1029
1030 if ipv6_addrgen_nl is not None:
223ba5af
JF
1031 self.iproute2.batch_start()
1032 self.iproute2.link_set_ipv6_addrgen(ifaceobj.name, ipv6_addrgen_nl, link_created=True)
1033 self.iproute2.batch_commit()
007cae35
JF
1034 # link_create=False will flush the addr cache of that intf
1035 else:
1036 self.logger.warning('%s: invalid value "%s" for attribute ipv6-addrgen' % (ifaceobj.name, user_configured_ipv6_addrgen))
3fc54eef 1037
223ba5af
JF
1038 def _pre_up(self, ifaceobj, ifaceobj_getfunc=None):
1039 if not self.cache.link_exists(ifaceobj.name):
15ef32ea 1040 return
2ff98bb9 1041
d486dd0d
JF
1042 if not self.syntax_check_enable_l3_iface_forwardings(ifaceobj, ifaceobj_getfunc):
1043 return
1044
223ba5af
JF
1045 #
1046 # alias
1047 #
1048 self.sysfs.link_set_alias(ifaceobj.name, ifaceobj.get_attr_value_first("alias"))
2ff98bb9 1049
d486dd0d
JF
1050 self._sysctl_config(ifaceobj)
1051
68d9fee0 1052 addr_method = ifaceobj.addr_method
77021aa1 1053 force_reapply = False
15ef32ea
RP
1054 try:
1055 # release any stale dhcp addresses if present
223ba5af 1056 if (addr_method not in ["dhcp", "ppp"] and not ifupdownflags.flags.PERFMODE and
15ef32ea
RP
1057 not (ifaceobj.flags & iface.HAS_SIBLINGS)):
1058 # if not running in perf mode and ifaceobj does not have
1059 # any sibling iface objects, kill any stale dhclient
1060 # processes
75afe2a7 1061 dhclientcmd = dhclient()
7c1135ea 1062 if dhclientcmd.is_running(ifaceobj.name):
15ef32ea
RP
1063 # release any dhcp leases
1064 dhclientcmd.release(ifaceobj.name)
223ba5af 1065 self.cache.force_address_flush_family(ifaceobj.name, socket.AF_INET)
77021aa1 1066 force_reapply = True
7c1135ea 1067 elif dhclientcmd.is_running6(ifaceobj.name):
15ef32ea 1068 dhclientcmd.release6(ifaceobj.name)
223ba5af 1069 self.cache.force_address_flush_family(ifaceobj.name, socket.AF_INET6)
77021aa1 1070 force_reapply = True
3218f49d 1071 except Exception:
15ef32ea 1072 pass
8e113d63 1073
2c152f83 1074 self.process_mtu(ifaceobj, ifaceobj_getfunc)
3fc54eef
JF
1075 self.up_ipv6_addrgen(ifaceobj)
1076
77054f7f 1077 if addr_method not in ["dhcp", "ppp"]:
223ba5af 1078 self.process_addresses(ifaceobj, ifaceobj_getfunc, force_reapply)
2e2dcdaf
JF
1079 else:
1080 # remove old addresses added by ifupdown2
1081 # (if intf was moved from static config to dhcp)
1082 for old_ifaceobj in statemanager.statemanager_api.get_ifaceobjs(ifaceobj.name) or []:
1083 for addr in old_ifaceobj.get_attr_value("address") or []:
a3f9506e 1084 self.netlink.addr_del(ifaceobj.name, ipnetwork.IPNetwork(addr))
d486dd0d 1085
13e22530 1086
093ffa00 1087 try:
223ba5af 1088 # Handle special things on a bridge
4e0f16d0 1089 self._process_bridge(ifaceobj, True, *self.process_hwaddress(ifaceobj))
3b01ed76 1090 except Exception as e:
223ba5af 1091 self.log_error('%s: %s' % (ifaceobj.name, str(e)), ifaceobj)
d1477c4b 1092
b99c724a
AB
1093 def _settle_dad(self, ifaceobj, ips):
1094 """ Settle dad for any given ips """
1095 def ip_addr_list(what):
1096 raw = json.loads(utils.exec_commandl([
1097 'ip', '-j', '-o', '-6', 'address', 'list', 'dev',
1098 ifaceobj.name, what
1099 ]))
1100 addr_infos = (x for t in raw for x in t.get('addr_info', []))
1101 ip_list = [f'{x["local"]}/{x["prefixlen"]}' for x in addr_infos if x]
1102 return ip_list
1103
1104 def get_param(key, default=None):
1105 return (ifaceobj.get_attr_value_first(key)
1106 or policymanager.policymanager_api.get_iface_default(
1107 self.__class__.__name__, ifaceobj.name, key)
1108 or default)
1109
1110 interval = float(get_param('dad-interval', '0.1')) # 0.1: ifupdown default value
1111 attempts = int(get_param('dad-attempts', '60')) # 60: ifupdown default value
1112 if not attempts or not ips:
1113 return
1114 try:
1115 for _attempt in range(0, attempts):
1116 tentative = ip_addr_list('tentative')
1117 if all(str(ip) not in tentative for ip in ips):
1118 break
cccf76e4 1119 self.logger.info("%s: dad-interval: sleeping for %s" % (ifaceobj.name, interval))
b99c724a
AB
1120 time.sleep(interval)
1121 else:
1122 timeout = ','.join(ip for ip in ips if str(ip) not in tentative)
1123 self.logger.warning('address: %s: dad timeout "%s"', ifaceobj.name, timeout)
1124 return
1125 failure = ip_addr_list('dadfailed')
1126 if failure:
1127 self.logger.warning('address: %s: dad failure "%s"', ifaceobj.name, ','.join(failure))
1128 except subprocess.CalledProcessError as exc:
1129 self.logger.error('address: %s: could not settle dad %s', ifaceobj.name, str(exc))
1130
d594fb86
AB
1131 def _get_ifaceobjs(self, ifaceobj, ifaceobj_getfunc):
1132 squash_addr_config = ifupdownconfig.config.get("addr_config_squash", "0") == "1"
1133 if not squash_addr_config:
1134 return [ifaceobj] # no squash, returns current ifaceobj
1135 if not ifaceobj.flags & ifaceobj.YOUNGEST_SIBLING:
1136 return [] # when squash is present, work only on the youngest sibling
1137 if ifaceobj.flags & iface.HAS_SIBLINGS:
1138 return ifaceobj_getfunc(ifaceobj.name) # get sibling interfaces
1139 return [ifaceobj]
1140
223ba5af 1141 def _up(self, ifaceobj, ifaceobj_getfunc=None):
d1477c4b
JF
1142 gateways = ifaceobj.get_attr_value('gateway')
1143 if not gateways:
1144 gateways = []
1145 prev_gw = self._get_prev_gateway(ifaceobj, gateways)
1146 self._add_delete_gateway(ifaceobj, gateways, prev_gw)
d594fb86
AB
1147 # settle dad
1148 if not self.ipv6_dad_handling_enabled:
1149 return
21a7bd2d
AB
1150 if not self.cache.link_exists(ifaceobj.name):
1151 return
d594fb86
AB
1152 ifname = ifaceobj.name
1153 ifaceobjs = self._get_ifaceobjs(ifaceobj, ifaceobj_getfunc)
1154 addr_supported, user_addrs_list = self.__get_ip_addr_with_attributes(ifaceobjs, ifname)
1155 if not addr_supported:
1156 return
1157 self._settle_dad(ifaceobj, [ip for ip, _ in user_addrs_list if ip.version == 6])
d1477c4b 1158
223ba5af
JF
1159 def process_hwaddress(self, ifaceobj):
1160 hwaddress = self._get_hwaddress(ifaceobj)
d1477c4b 1161
223ba5af
JF
1162 if not hwaddress:
1163 if ifaceobj.link_kind & ifaceLinkKind.VLAN:
1164 # When hwaddress is removed from vlan config
1165 # we should go back to system or bridge mac
1166 for lower in ifaceobj.lowerifaces:
1167 if self.cache.get_link_kind(lower) == "bridge":
1168 hwaddress = self.cache.get_link_address(lower)
1169 break
1170 if not hwaddress:
4e0f16d0 1171 return None, None
223ba5af 1172 else:
4e0f16d0 1173 return None, None
707aeb73 1174
223ba5af
JF
1175 if not ifupdownflags.flags.PERFMODE: # system is clean
1176 running_hwaddress = self.cache.get_link_address(ifaceobj.name)
1177 else:
1178 running_hwaddress = None
1179
1db0cb7a
JF
1180 old_mac_addr = None
1181
859b8643
JF
1182 hwaddress_int = utils.mac_str_to_int(hwaddress)
1183
1184 if hwaddress_int != utils.mac_str_to_int(running_hwaddress):
223ba5af
JF
1185 slave_down = False
1186 if ifaceobj.link_kind & ifaceLinkKind.BOND:
1187 # if bond, down all the slaves
1188 if ifaceobj.lowerifaces:
1189 for l in ifaceobj.lowerifaces:
1190 self.netlink.link_down(l)
1191 slave_down = True
1192 try:
859b8643 1193 self.netlink.link_set_address(ifaceobj.name, hwaddress, hwaddress_int)
1db0cb7a 1194 old_mac_addr = running_hwaddress
223ba5af
JF
1195 finally:
1196 if slave_down:
1197 for l in ifaceobj.lowerifaces:
1198 self.netlink.link_up(l)
15ef32ea 1199
4e0f16d0 1200 return hwaddress, old_mac_addr
1db0cb7a 1201
0582f185 1202 def _down(self, ifaceobj, ifaceobj_getfunc=None):
15ef32ea 1203 try:
223ba5af 1204 if not self.cache.link_exists(ifaceobj.name):
15ef32ea 1205 return
68d9fee0 1206 addr_method = ifaceobj.addr_method
77054f7f 1207 if addr_method not in ["dhcp", "ppp"]:
aa052170
N
1208 if ifaceobj.get_attr_value_first('address-purge')=='no':
1209 addrlist = ifaceobj.get_attr_value('address')
223ba5af
JF
1210 for addr in addrlist or []:
1211 self.netlink.addr_del(ifaceobj.name, addr)
d486dd0d
JF
1212 elif not ifaceobj.link_kind:
1213 # for logical interfaces we don't need to remove the ip addresses
1214 # kernel will do it for us on 'ip link del'
223ba5af
JF
1215 if ifaceobj_getfunc:
1216 ifaceobj_list = ifaceobj_getfunc(ifaceobj.name) or [ifaceobj]
1217 else:
1218 ifaceobj_list = [ifaceobj]
1219
0e936c3f 1220 for addr in self.cache.get_managed_ip_addresses(ifaceobj.name, ifaceobj_list):
223ba5af
JF
1221 self.netlink.addr_del(ifaceobj.name, addr)
1222
d486dd0d
JF
1223 gateways = ifaceobj.get_attr_value('gateway')
1224 if gateways:
1225 self._delete_gateway(ifaceobj, gateways,
1226 ifaceobj.get_attr_value_first('vrf'),
1227 ifaceobj.get_attr_value_first('metric'))
223ba5af
JF
1228
1229 #
1230 # mtu --
1231 # If device is not a logical intf and has its MTU configured by
1232 # ifupdown2. If this MTU is different from our default mtu,
1233 # if so we need to reset it back to default.
1234 if not ifaceobj.link_kind and self.default_mtu and ifaceobj.get_attr_value_first('mtu') and self.cache.get_link_mtu(ifaceobj.name) != self.default_mtu_int:
1235 self.sysfs.link_set_mtu(ifaceobj.name, mtu_str=self.default_mtu, mtu_int=self.default_mtu_int)
1236
1237 #
1238 # alias
1239 # only reset alias on non-logical device
1240 if not ifaceobj.link_kind:
1241 alias = ifaceobj.get_attr_value_first("alias")
1242 if alias:
1243 self.sysfs.link_set_alias(ifaceobj.name, None) # None to reset alias.
1244
75afe2a7
RP
1245 # XXX hwaddress reset cannot happen because we dont know last
1246 # address.
1247
1248 # Handle special things on a bridge
4e0f16d0
JF
1249 hwaddress = self._get_hwaddress(ifaceobj)
1250 if not hwaddress:
1251 hwaddress = self.cache.get_link_address(ifaceobj.name)
1252 self._process_bridge(ifaceobj, False, hwaddress, None)
3b01ed76 1253 except Exception as e:
bcf11b14
RP
1254 self.logger.debug('%s : %s' %(ifaceobj.name, str(e)))
1255 pass
15ef32ea 1256
8e113d63
RP
1257 def _get_bridge_fdbs(self, bridgename, vlan):
1258 fdbs = self._bridge_fdb_query_cache.get(bridgename)
1259 if not fdbs:
223ba5af 1260 fdbs = self.iproute2.bridge_fdb_show_dev(bridgename)
8e113d63
RP
1261 if not fdbs:
1262 return
1263 self._bridge_fdb_query_cache[bridgename] = fdbs
1264 return fdbs.get(vlan)
1265
1266 def _check_addresses_in_bridge(self, ifaceobj, hwaddress):
1267 """ If the device is a bridge, make sure the addresses
1268 are in the bridge """
d486dd0d
JF
1269 if ifaceobj.link_kind & ifaceLinkKind.VLAN:
1270 bridgename = ifaceobj.lowerifaces[0]
1271 vlan = self._get_vlan_id(ifaceobj)
223ba5af
JF
1272 if self.cache.bridge_is_vlan_aware(bridgename):
1273 fdb_addrs = [utils.mac_str_to_int(fdb_addr) for fdb_addr in self._get_bridge_fdbs(bridgename, str(vlan))]
d1477c4b 1274 if not fdb_addrs:
223ba5af
JF
1275 return False
1276 hwaddress_int = utils.mac_str_to_int(hwaddress)
d1477c4b
JF
1277 if hwaddress_int not in fdb_addrs:
1278 return False
8e113d63
RP
1279 return True
1280
d486dd0d
JF
1281 def _query_sysctl(self, ifaceobj, ifaceobjcurr):
1282 bridge_port = ifaceobj.link_privflags & ifaceLinkPrivFlags.BRIDGE_PORT
1283 ipforward = ifaceobj.get_attr_value_first('ip-forward')
1284 if ipforward:
1285 if bridge_port:
1286 ifaceobjcurr.status = ifaceStatus.ERROR
1287 ifaceobjcurr.status_str = ('\'ip-forward\' not supported ' +
1288 'for bridge port')
1289 ifaceobjcurr.update_config_with_status('ip-forward', 1, None)
1290 else:
223ba5af 1291 running_ipforward = self.cache.get_netconf_forwarding(socket.AF_INET, ifaceobj.name)
307e814c
JF
1292 config_ipforward = utils.get_boolean_from_string(ipforward)
1293 ifaceobjcurr.update_config_with_status(
1294 'ip-forward',
1295 'on' if running_ipforward else 'off',
1296 running_ipforward != config_ipforward
1297 )
d486dd0d
JF
1298
1299 ip6forward = ifaceobj.get_attr_value_first('ip6-forward')
1300 if ip6forward:
1301 if bridge_port:
1302 ifaceobjcurr.status = ifaceStatus.ERROR
1303 ifaceobjcurr.status_str = ('\'ip6-forward\' not supported ' +
1304 'for bridge port')
1305 ifaceobjcurr.update_config_with_status('ip6-forward', 1, None)
1306 else:
223ba5af 1307 running_ip6forward = self.cache.get_netconf_forwarding(socket.AF_INET6, ifaceobj.name)
307e814c
JF
1308 config_ip6forward = utils.get_boolean_from_string(ip6forward)
1309 ifaceobjcurr.update_config_with_status(
1310 'ip6-forward',
1311 'on' if running_ip6forward else 'off',
1312 running_ip6forward != config_ip6forward
1313 )
d486dd0d
JF
1314 mpls_enable = ifaceobj.get_attr_value_first('mpls-enable');
1315 if mpls_enable:
223ba5af 1316 running_mpls_enable = utils.get_yesno_from_onezero(str(self.cache.get_netconf_mpls_input(ifaceobj.name)))
d486dd0d
JF
1317 ifaceobjcurr.update_config_with_status('mpls-enable',
1318 running_mpls_enable,
1319 mpls_enable != running_mpls_enable)
1320 return
1321
007cae35
JF
1322 def query_check_ipv6_addrgen(self, ifaceobj, ifaceobjcurr):
1323 ipv6_addrgen = ifaceobj.get_attr_value_first('ipv6-addrgen')
1324
1325 if not ipv6_addrgen:
1326 return
1327
1328 if ipv6_addrgen in utils._string_values:
1329 ifaceobjcurr.update_config_with_status(
1330 'ipv6-addrgen',
1331 ipv6_addrgen,
223ba5af 1332 utils.get_boolean_from_string(ipv6_addrgen) == self.cache.get_link_ipv6_addrgen_mode(ifaceobj.name)
007cae35
JF
1333 )
1334 else:
1335 ifaceobjcurr.update_config_with_status('ipv6-addrgen', ipv6_addrgen, 1)
1336
0582f185 1337 def _query_check(self, ifaceobj, ifaceobjcurr, ifaceobj_getfunc=None):
223ba5af
JF
1338 """
1339 TODO: Check broadcast address, scope, etc
1340 """
15ef32ea 1341 runningaddrsdict = None
223ba5af 1342 if not self.cache.link_exists(ifaceobj.name):
15ef32ea
RP
1343 self.logger.debug('iface %s not found' %ifaceobj.name)
1344 return
007cae35
JF
1345
1346 self.query_check_ipv6_addrgen(ifaceobj, ifaceobjcurr)
1347
16d854b4 1348 addr_method = ifaceobj.addr_method
15ef32ea 1349 self.query_n_update_ifaceobjcurr_attr(ifaceobj, ifaceobjcurr,
223ba5af 1350 'mtu', self.cache.get_link_mtu_str)
428206bf 1351 hwaddress = self._get_hwaddress(ifaceobj)
8e113d63 1352 if hwaddress:
223ba5af
JF
1353 rhwaddress = self.cache.get_link_address(ifaceobj.name)
1354 if not rhwaddress or utils.mac_str_to_int(rhwaddress) != utils.mac_str_to_int(hwaddress):
8e113d63
RP
1355 ifaceobjcurr.update_config_with_status('hwaddress', rhwaddress,
1356 1)
1357 elif not self._check_addresses_in_bridge(ifaceobj, hwaddress):
1358 # XXX: hw address is not in bridge
1359 ifaceobjcurr.update_config_with_status('hwaddress', rhwaddress,
1360 1)
1361 ifaceobjcurr.status_str = 'bridge fdb error'
1362 else:
1363 ifaceobjcurr.update_config_with_status('hwaddress', rhwaddress,
1364 0)
15ef32ea 1365 self.query_n_update_ifaceobjcurr_attr(ifaceobj, ifaceobjcurr,
223ba5af 1366 'alias', self.cache.get_link_alias)
0e936c3f 1367
d486dd0d 1368 self._query_sysctl(ifaceobj, ifaceobjcurr)
9a6a3050 1369
0e936c3f
JF
1370 self._query_check_address(ifaceobj, ifaceobjcurr, ifaceobj_getfunc)
1371
1372 def _query_check_address(self, ifaceobj, ifaceobjcurr, ifaceobj_getfunc):
1373 """ ifquery-check: attribute: "address" """
1374 if ifaceobj.addr_method in ["dhcp", "ppp"]:
1375 return
223ba5af
JF
1376
1377 if ifaceobj_getfunc:
1378 ifaceobj_list = ifaceobj_getfunc(ifaceobj.name)
1379 else:
1380 ifaceobj_list = [ifaceobj]
1381
0e936c3f
JF
1382 intf_running_addrs = self.cache.get_managed_ip_addresses(ifaceobj.name, ifaceobj_list)
1383 user_config_addrs = self.cache.get_user_configured_addresses([ifaceobj])
223ba5af
JF
1384
1385 try:
0e936c3f 1386 clagd_vxlan_anycast_ip = ipnetwork.IPNetwork(ifaceobj.get_attr_value_first("clagd-vxlan-anycast-ip"))
223ba5af
JF
1387
1388 if clagd_vxlan_anycast_ip in intf_running_addrs:
1389 user_config_addrs.append(clagd_vxlan_anycast_ip)
3218f49d 1390 except Exception:
223ba5af 1391 pass
15ef32ea
RP
1392
1393 # Set ifaceobjcurr method and family
1394 ifaceobjcurr.addr_method = ifaceobj.addr_method
1395 ifaceobjcurr.addr_family = ifaceobj.addr_family
223ba5af
JF
1396
1397 if not intf_running_addrs and not user_config_addrs:
1398 # The device doesn't have any ips configured and the
1399 # the user didn't specify any ip in the configuration file
15ef32ea 1400 return
223ba5af
JF
1401
1402 for address in user_config_addrs:
1403 ifaceobjcurr.update_config_with_status('address', str(address), address not in intf_running_addrs)
1404 try:
1405 intf_running_addrs.remove(address)
3218f49d 1406 except Exception:
223ba5af
JF
1407 pass
1408
0e936c3f
JF
1409 # if any ip address is left in 'intf_running_addrs' it means that they
1410 # used to be configured by ifupdown2 but not anymore. The entry was
1411 # removed from the configuration file but the IP is still configured on
1412 # the device, so we need to mark them as FAIL (we will only mark them
1413 # as failure on the first sibling).
223ba5af
JF
1414 if ifaceobj.flags & iface.HAS_SIBLINGS:
1415 if not ifaceobj.flags & iface.YOUNGEST_SIBLING:
1416 return
1417
0e936c3f 1418 all_stanza_user_config_ip = self.cache.get_user_configured_addresses(ifaceobj_list)
223ba5af
JF
1419
1420 for address in intf_running_addrs:
1421 if address not in all_stanza_user_config_ip:
1422 ifaceobjcurr.update_config_with_status('address', str(address), 1)
1423
007cae35 1424 def query_running_ipv6_addrgen(self, ifaceobjrunning):
223ba5af 1425 ipv6_addrgen = self.cache.get_link_ipv6_addrgen_mode(ifaceobjrunning.name)
007cae35
JF
1426
1427 if ipv6_addrgen:
1428 ifaceobjrunning.update_config('ipv6-addrgen', 'off')
1429
0582f185 1430 def _query_running(self, ifaceobjrunning, ifaceobj_getfunc=None):
223ba5af 1431 if not self.cache.link_exists(ifaceobjrunning.name):
15ef32ea 1432 self.logger.debug('iface %s not found' %ifaceobjrunning.name)
15ef32ea 1433 return
007cae35
JF
1434
1435 self.query_running_ipv6_addrgen(ifaceobjrunning)
1436
15ef32ea
RP
1437 dhclientcmd = dhclient()
1438 if (dhclientcmd.is_running(ifaceobjrunning.name) or
1439 dhclientcmd.is_running6(ifaceobjrunning.name)):
1440 # If dhcp is configured on the interface, we skip it
84f33af6 1441 return
223ba5af 1442
0e936c3f 1443 intf_running_addrs = self.cache.get_ip_addresses(ifaceobjrunning.name) or []
223ba5af
JF
1444
1445 if self.cache.link_is_loopback(ifaceobjrunning.name):
1446 for default_addr in self.default_loopback_addresses:
1447 try:
1448 intf_running_addrs.remove(default_addr)
3218f49d 1449 except Exception:
223ba5af 1450 pass
004d1e65 1451 ifaceobjrunning.addr_family.append('inet')
15ef32ea 1452 ifaceobjrunning.addr_method = 'loopback'
223ba5af
JF
1453
1454 for addr in intf_running_addrs:
580a567b 1455 ifaceobjrunning.update_config('address', str(addr))
223ba5af
JF
1456
1457 mtu = self.cache.get_link_mtu_str(ifaceobjrunning.name)
15ef32ea
RP
1458 if (mtu and
1459 (ifaceobjrunning.name == 'lo' and mtu != '16436') or
1460 (ifaceobjrunning.name != 'lo' and
1461 mtu != self.get_mod_subattr('mtu', 'default'))):
1462 ifaceobjrunning.update_config('mtu', mtu)
223ba5af
JF
1463
1464 alias = self.cache.get_link_alias(ifaceobjrunning.name)
84f33af6 1465 if alias:
15ef32ea
RP
1466 ifaceobjrunning.update_config('alias', alias)
1467
63155c61
JF
1468 ifaceobjrunning.update_config("hwaddress", self.cache.get_link_address(ifaceobjrunning.name))
1469
223ba5af
JF
1470 _run_ops = {
1471 'pre-up': _pre_up,
1472 'up': _up,
1473 'down': _down,
1474 'query-checkcurr': _query_check,
1475 'query-running': _query_running
1476 }
15ef32ea
RP
1477
1478 def get_ops(self):
1479 """ returns list of ops supported by this module """
3b01ed76 1480 return list(self._run_ops.keys())
15ef32ea 1481
6e16e5ae 1482 def run(self, ifaceobj, operation, query_ifaceobj=None, ifaceobj_getfunc=None):
15ef32ea
RP
1483 """ run address configuration on the interface object passed as argument
1484
1485 Args:
1486 **ifaceobj** (object): iface object
1487
1488 **operation** (str): any of 'up', 'down', 'query-checkcurr',
1489 'query-running'
1490 Kwargs:
1491 query_ifaceobj (object): query check ifaceobject. This is only
1492 valid when op is 'query-checkcurr'. It is an object same as
1493 ifaceobj, but contains running attribute values and its config
1494 status. The modules can use it to return queried running state
1495 of interfaces. status is success if the running state is same
1496 as user required state in ifaceobj. error otherwise.
1497 """
8e113d63
RP
1498 if ifaceobj.type == ifaceType.BRIDGE_VLAN:
1499 return
15ef32ea
RP
1500 op_handler = self._run_ops.get(operation)
1501 if not op_handler:
1502 return
15ef32ea 1503 if operation == 'query-checkcurr':
0582f185
RP
1504 op_handler(self, ifaceobj, query_ifaceobj,
1505 ifaceobj_getfunc=ifaceobj_getfunc)
15ef32ea 1506 else:
0582f185
RP
1507 op_handler(self, ifaceobj,
1508 ifaceobj_getfunc=ifaceobj_getfunc)