]> git.proxmox.com Git - mirror_ifupdown2.git/blob - ifupdown2/addons/address.py
readd support for self.ipforward
[mirror_ifupdown2.git] / ifupdown2 / addons / address.py
1 #!/usr/bin/python
2 #
3 # Copyright 2014-2017 Cumulus Networks, Inc. All rights reserved.
4 # Author: Roopa Prabhu, roopa@cumulusnetworks.com
5 #
6
7 import socket
8
9 from ipaddr import IPNetwork, IPv4Network, IPv6Network, _BaseV6
10
11 try:
12 from ifupdown2.ifupdown.iface import *
13 from ifupdown2.ifupdown.utils import utils
14 from ifupdown2.ifupdown.netlink import netlink
15
16 from ifupdown2.ifupdownaddons.dhclient import dhclient
17 from ifupdown2.ifupdownaddons.LinkUtils import LinkUtils
18 from ifupdown2.ifupdownaddons.modulebase import moduleBase
19
20 import ifupdown2.ifupdown.statemanager as statemanager
21 import ifupdown2.ifupdown.policymanager as policymanager
22 import ifupdown2.ifupdown.ifupdownflags as ifupdownflags
23 import ifupdown2.ifupdown.ifupdownconfig as ifupdownconfig
24 except ImportError:
25 from ifupdown.iface import *
26 from ifupdown.utils import utils
27 from ifupdown.netlink import netlink
28
29 from ifupdownaddons.dhclient import dhclient
30 from ifupdownaddons.LinkUtils import LinkUtils
31 from ifupdownaddons.modulebase import moduleBase
32
33 import ifupdown.statemanager as statemanager
34 import ifupdown.policymanager as policymanager
35 import ifupdown.ifupdownflags as ifupdownflags
36 import ifupdown.ifupdownconfig as ifupdownconfig
37
38
39 class address(moduleBase):
40 """ ifupdown2 addon module to configure address, mtu, hwaddress, alias
41 (description) on an interface """
42
43 _modinfo = {'mhelp' : 'address configuration module for interfaces',
44 'attrs': {
45 'address' :
46 {'help' : 'ipv4 or ipv6 addresses',
47 'validvals' : ['<ipv4/prefixlen>', '<ipv6/prefixlen>'],
48 'multiline' : True,
49 'example' : ['address 10.0.12.3/24',
50 'address 2000:1000:1000:1000:3::5/128']},
51 'netmask' :
52 {'help': 'netmask',
53 'example' : ['netmask 255.255.255.0'],
54 'compat' : True},
55 'broadcast' :
56 {'help': 'broadcast address',
57 'validvals' : ['<ipv4>', ],
58 'example' : ['broadcast 10.0.1.255']},
59 'scope' :
60 {'help': 'scope',
61 'validvals' : ['universe', 'site', 'link', 'host', 'nowhere'],
62 'example' : ['scope host']},
63 'preferred-lifetime' :
64 {'help': 'preferred lifetime',
65 'validrange' : ['0', '65535'],
66 'example' : ['preferred-lifetime forever',
67 'preferred-lifetime 10']},
68 'gateway' :
69 {'help': 'default gateway',
70 'validvals' : ['<ipv4>', '<ipv6>'],
71 'multiline' : True,
72 'example' : ['gateway 255.255.255.0']},
73 'mtu' :
74 { 'help': 'interface mtu',
75 'validrange' : ['552', '9216'],
76 'example' : ['mtu 1600'],
77 'default' : '1500'},
78 'hwaddress' :
79 {'help' : 'hw address',
80 'validvals' : ['<mac>',],
81 'example': ['hwaddress 44:38:39:00:27:b8']},
82 'alias' :
83 { 'help': 'description/alias',
84 'example' : ['alias testnetwork']},
85 'address-purge' :
86 { 'help': 'purge existing addresses. By default ' +
87 'any existing ip addresses on an interface are ' +
88 'purged to match persistant addresses in the ' +
89 'interfaces file. Set this attribute to \'no\'' +
90 'if you want to preserve existing addresses',
91 'validvals' : ['yes', 'no'],
92 'default' : 'yes',
93 'example' : ['address-purge yes/no']},
94 'clagd-vxlan-anycast-ip' :
95 { 'help' : 'Anycast local IP address for ' +
96 'dual connected VxLANs',
97 'validvals' : ['<ipv4>', ],
98 'example' : ['clagd-vxlan-anycast-ip 36.0.0.11']},
99 'ip-forward' :
100 { 'help': 'ip forwarding flag',
101 'validvals': ['on', 'off', 'yes', 'no', '0', '1'],
102 'default' : 'off',
103 'example' : ['ip-forward off']},
104 'ip6-forward' :
105 { 'help': 'ipv6 forwarding flag',
106 'validvals': ['on', 'off', 'yes', 'no', '0', '1'],
107 'default' : 'off',
108 'example' : ['ip6-forward off']},
109 'mpls-enable' :
110 { 'help': 'mpls enable flag',
111 'validvals': ['yes', 'no'],
112 'default' : 'no',
113 'example' : ['mpls-enable yes']},
114 'ipv6-addrgen': {
115 'help': 'enable disable ipv6 link addrgenmode',
116 'validvals': ['on', 'off'],
117 'default': 'on',
118 'example': [
119 'ipv6-addrgen on',
120 'ipv6-addrgen off'
121 ]
122 }
123 }}
124
125 def __init__(self, *args, **kargs):
126 moduleBase.__init__(self, *args, **kargs)
127 self.ipcmd = None
128 self._bridge_fdb_query_cache = {}
129 self.default_mtu = policymanager.policymanager_api.get_attr_default(module_name=self.__class__.__name__, attr='mtu')
130 self.max_mtu = policymanager.policymanager_api.get_module_globals(module_name=self.__class__.__name__, attr='max_mtu')
131 self.ipforward = policymanager.policymanager_api.get_attr_default(module_name=self.__class__.__name__, attr='ip-forward')
132 self.ip6forward = policymanager.policymanager_api.get_attr_default(module_name=self.__class__.__name__, attr='ip6-forward')
133 self.ifaces_defaults = policymanager.policymanager_api.get_iface_defaults(module_name=self.__class__.__name__)
134 self.enable_l3_iface_forwarding_checks = utils.get_boolean_from_string(
135 policymanager.policymanager_api.get_module_globals(
136 self.__class__.__name__,
137 'enable_l3_iface_forwarding_checks'
138 )
139 )
140
141 if not self.default_mtu:
142 self.default_mtu = '1500'
143
144 self.logger.info('address: using default mtu %s' %self.default_mtu)
145
146 if self.max_mtu:
147 self.logger.info('address: using max mtu %s' %self.max_mtu)
148
149 self.lower_iface_mtu_checked_list = list()
150
151 self.l3_intf_arp_accept = utils.get_boolean_from_string(
152 policymanager.policymanager_api.get_module_globals(
153 module_name=self.__class__.__name__,
154 attr='l3_intf_arp_accept'
155 ),
156 default=False
157 )
158
159 self.l3_intf_default_gateway_set_onlink = utils.get_boolean_from_string(
160 policymanager.policymanager_api.get_module_globals(
161 module_name=self.__class__.__name__,
162 attr='l3_intf_default_gateway_set_onlink'
163 ),
164 default=True
165 )
166
167 def syntax_check(self, ifaceobj, ifaceobj_getfunc=None):
168 return (self.syntax_check_multiple_gateway(ifaceobj)
169 and self.syntax_check_addr_allowed_on(ifaceobj, True)
170 and self.syntax_check_mtu(ifaceobj, ifaceobj_getfunc)
171 and self.syntax_check_sysctls(ifaceobj)
172 and self.syntax_check_enable_l3_iface_forwardings(ifaceobj, ifaceobj_getfunc, syntax_check=True))
173
174 def syntax_check_enable_l3_iface_forwardings(self, ifaceobj, ifaceobj_getfunc, syntax_check=False):
175 if (self.enable_l3_iface_forwarding_checks
176 and (ifaceobj.link_kind & ifaceLinkKind.VLAN
177 or ifaceobj.link_kind & ifaceLinkKind.BRIDGE)
178 and not ifaceobj.link_privflags & ifaceLinkPrivFlags.BRIDGE_PORT):
179
180 ifname = ifaceobj.name
181 vlan_addr = None
182 vlan_ipforward_off = None
183
184 for obj in ifaceobj_getfunc(ifname) or [ifaceobj]:
185 if not vlan_addr:
186 vlan_addr = obj.get_attr_value('address')
187
188 if not vlan_ipforward_off:
189 ip_forward_value = obj.get_attr_value_first('ip-forward')
190
191 if ip_forward_value and not utils.get_boolean_from_string(ip_forward_value):
192 vlan_ipforward_off = True
193
194 if vlan_addr and vlan_ipforward_off:
195 if syntax_check:
196 raise Exception(
197 'configuring ip-forward off and ip address(es) (%s) is not compatible'
198 % (', '.join(vlan_addr))
199 )
200 else:
201 raise Exception(
202 '%s: configuring ip-forward off and ip address(es) (%s) is not compatible'
203 % (ifname, ', '.join(vlan_addr))
204 )
205
206 return True
207
208 def syntax_check_sysctls(self, ifaceobj):
209 result = True
210 bridge_port = (ifaceobj.link_privflags & ifaceLinkPrivFlags.BRIDGE_PORT)
211 ipforward = ifaceobj.get_attr_value_first('ip-forward')
212 if bridge_port and ipforward:
213 result = False
214 self.log_error('%s: \'ip-forward\' is not supported for '
215 'bridge port' %ifaceobj.name)
216 ip6forward = ifaceobj.get_attr_value_first('ip6-forward')
217 if bridge_port and ip6forward:
218 result = False
219 self.log_error('%s: \'ip6-forward\' is not supported for '
220 'bridge port' %ifaceobj.name)
221 return result
222
223 def syntax_check_mtu(self, ifaceobj, ifaceobj_getfunc):
224 mtu = ifaceobj.get_attr_value_first('mtu')
225 if mtu:
226 return self._check_mtu_config(ifaceobj, mtu, ifaceobj_getfunc,
227 syntaxcheck=True)
228 return True
229
230 def syntax_check_addr_allowed_on(self, ifaceobj, syntax_check=False):
231 if ifaceobj.get_attr_value('address'):
232 return utils.is_addr_ip_allowed_on(ifaceobj, syntax_check=syntax_check)
233 return True
234
235 def _syntax_check_multiple_gateway(self, family, found, addr, type_obj):
236 if type(IPNetwork(addr)) == type_obj:
237 if found:
238 raise Exception('%s: multiple gateways for %s family'
239 % (addr, family))
240 return True
241 return False
242
243 def syntax_check_multiple_gateway(self, ifaceobj):
244 result = True
245 inet = False
246 inet6 = False
247 gateways = ifaceobj.get_attr_value('gateway')
248 for addr in gateways if gateways else []:
249 try:
250 if self._syntax_check_multiple_gateway('inet', inet, addr,
251 IPv4Network):
252 inet = True
253 if self._syntax_check_multiple_gateway('inet6', inet6, addr,
254 IPv6Network):
255 inet6 = True
256 except Exception as e:
257 self.logger.warning('%s: address: %s' % (ifaceobj.name, str(e)))
258 result = False
259 return result
260
261 def _address_valid(self, addrs):
262 if not addrs:
263 return False
264 if any(map(lambda a: True if a[:7] != '0.0.0.0'
265 else False, addrs)):
266 return True
267 return False
268
269 def _get_hwaddress(self, ifaceobj):
270 return utils.strip_hwaddress(ifaceobj.get_attr_value_first('hwaddress'))
271
272 def _process_bridge(self, ifaceobj, up):
273 hwaddress = self._get_hwaddress(ifaceobj)
274 addrs = ifaceobj.get_attr_value_first('address')
275 is_vlan_dev_on_vlan_aware_bridge = False
276 is_bridge = self.ipcmd.is_bridge(ifaceobj.name)
277 if not is_bridge:
278 if ifaceobj.link_kind & ifaceLinkKind.VLAN:
279 bridgename = ifaceobj.lowerifaces[0]
280 vlan = self._get_vlan_id(ifaceobj)
281 is_vlan_dev_on_vlan_aware_bridge = self.ipcmd.bridge_is_vlan_aware(bridgename)
282 if ((is_bridge and not self.ipcmd.bridge_is_vlan_aware(ifaceobj.name))
283 or is_vlan_dev_on_vlan_aware_bridge):
284 if self._address_valid(addrs):
285 if self.l3_intf_arp_accept:
286 if up:
287 self.write_file('/proc/sys/net/ipv4/conf/%s' % ifaceobj.name +
288 '/arp_accept', '1')
289 else:
290 self.write_file('/proc/sys/net/ipv4/conf/%s' % ifaceobj.name +
291 '/arp_accept', '0')
292 else:
293 self.write_file('/proc/sys/net/ipv4/conf/%s/arp_accept' % ifaceobj.name, '0')
294 if hwaddress and is_vlan_dev_on_vlan_aware_bridge:
295 if up:
296 self.ipcmd.bridge_fdb_add(bridgename, hwaddress, vlan)
297 else:
298 self.ipcmd.bridge_fdb_del(bridgename, hwaddress, vlan)
299
300 def _get_anycast_addr(self, ifaceobjlist):
301 for ifaceobj in ifaceobjlist:
302 anycast_addr = ifaceobj.get_attr_value_first('clagd-vxlan-anycast-ip')
303 if anycast_addr:
304 anycast_addr = anycast_addr+'/32'
305 return anycast_addr
306 return None
307
308 def _inet_address_convert_to_cidr(self, ifaceobjlist):
309 newaddrs = []
310 newaddr_attrs = {}
311
312 for ifaceobj in ifaceobjlist:
313 addrs = ifaceobj.get_attr_value('address')
314 if not addrs:
315 continue
316
317 if not self.syntax_check_addr_allowed_on(ifaceobj,
318 syntax_check=False):
319 return (False, newaddrs, newaddr_attrs)
320 # If user address is not in CIDR notation, convert them to CIDR
321 for addr_index in range(0, len(addrs)):
322 addr = addrs[addr_index]
323 newaddr = addr
324 if '/' in addr:
325 newaddrs.append(addr)
326 else:
327 netmask = ifaceobj.get_attr_value_n('netmask', addr_index)
328 if netmask:
329 prefixlen = IPNetwork('%s' %addr +
330 '/%s' %netmask).prefixlen
331 newaddr = addr + '/%s' %prefixlen
332 else:
333 # we are here because there is no slash (/xx) and no netmask
334 # just let IPNetwork handle the ipv4 or ipv6 address mask
335 prefixlen = IPNetwork(addr).prefixlen
336 newaddr = addr + '/%s' %prefixlen
337 newaddrs.append(newaddr)
338
339 attrs = {}
340 for a in ['broadcast', 'pointopoint', 'scope',
341 'preferred-lifetime']:
342 aval = ifaceobj.get_attr_value_n(a, addr_index)
343 if aval:
344 attrs[a] = aval
345
346 if attrs:
347 newaddr_attrs[newaddr]= attrs
348 return (True, newaddrs, newaddr_attrs)
349
350 def _inet_address_list_config(self, ifaceobj, newaddrs, newaddr_attrs):
351 for addr_index in range(0, len(newaddrs)):
352 try:
353 if newaddr_attrs:
354 self.ipcmd.addr_add(ifaceobj.name, newaddrs[addr_index],
355 newaddr_attrs.get(newaddrs[addr_index],
356 {}).get('broadcast'),
357 newaddr_attrs.get(newaddrs[addr_index],
358 {}).get('pointopoint'),
359 newaddr_attrs.get(newaddrs[addr_index],
360 {}).get('scope'),
361 newaddr_attrs.get(newaddrs[addr_index],
362 {}).get('preferred-lifetime'))
363 else:
364 self.ipcmd.addr_add(ifaceobj.name, newaddrs[addr_index])
365 except Exception, e:
366 self.log_error(str(e), ifaceobj)
367
368 def _inet_address_config(self, ifaceobj, ifaceobj_getfunc=None,
369 force_reapply=False):
370 squash_addr_config = (True if \
371 ifupdownconfig.config.get('addr_config_squash', \
372 '0') == '1' else False)
373
374 if (squash_addr_config and
375 not (ifaceobj.flags & ifaceobj.YOUNGEST_SIBLING)):
376 return
377
378 purge_addresses = ifaceobj.get_attr_value_first('address-purge')
379 if not purge_addresses:
380 purge_addresses = 'yes'
381
382 if squash_addr_config and ifaceobj.flags & iface.HAS_SIBLINGS:
383 ifaceobjlist = ifaceobj_getfunc(ifaceobj.name)
384 else:
385 ifaceobjlist = [ifaceobj]
386
387 module_name = self.__class__.__name__
388 ifname = ifaceobj.name
389
390 (addr_supported, newaddrs, newaddr_attrs) = self._inet_address_convert_to_cidr(ifaceobjlist)
391 newaddrs = utils.get_ip_objs(module_name, ifname, newaddrs)
392
393 if not addr_supported:
394 return
395 if (not squash_addr_config and (ifaceobj.flags & iface.HAS_SIBLINGS)):
396 # if youngest sibling and squash addr is not set
397 # print a warning that addresses will not be purged
398 if (ifaceobj.flags & iface.YOUNGEST_SIBLING):
399 self.logger.warn('%s: interface has multiple ' %ifaceobj.name +
400 'iface stanzas, skip purging existing addresses')
401 purge_addresses = 'no'
402
403 if not ifupdownflags.flags.PERFMODE and purge_addresses == 'yes':
404 # if perfmode is not set and purge addresses is not set to 'no'
405 # lets purge addresses not in the config
406 runningaddrs = self.ipcmd.get_running_addrs(ifaceobj, details=False)
407
408 # if anycast address is configured on 'lo' and is in running config
409 # add it to newaddrs so that ifreload doesn't wipe it out
410 anycast_addr = utils.get_normalized_ip_addr(ifaceobj.name, self._get_anycast_addr(ifaceobjlist))
411
412 if runningaddrs and anycast_addr and anycast_addr in runningaddrs:
413 newaddrs.append(anycast_addr)
414
415 user_ip4, user_ip6, newaddrs = self.order_user_configured_addrs(newaddrs)
416
417 if newaddrs == runningaddrs or self.compare_running_ips_and_user_config(user_ip4, user_ip6, runningaddrs):
418 if force_reapply:
419 self._inet_address_list_config(ifaceobj, newaddrs, newaddr_attrs)
420 return
421 try:
422 # if primary address is not same, there is no need to keep any.
423 # reset all addresses
424 if newaddrs and runningaddrs and newaddrs[0] != runningaddrs[0]:
425 skip_addrs = []
426 else:
427 skip_addrs = newaddrs or []
428 for addr in runningaddrs or []:
429 if addr in skip_addrs:
430 continue
431 self.ipcmd.addr_del(ifaceobj.name, addr)
432 except Exception, e:
433 self.log_warn(str(e))
434 if not newaddrs:
435 return
436 self._inet_address_list_config(ifaceobj, newaddrs, newaddr_attrs)
437
438 def compare_running_ips_and_user_config(self, user_ip4, user_ip6, running_addrs):
439 """
440 We need to compare the user config ips and the running ips.
441 ip4 ordering matters (primary etc) but ip6 order doesn't matter
442
443 this function replaces the strict comparison previously in place
444 if newaddrs == running_addrs ?
445
446 We will compare if the ip4 ordering is correct, then check if all
447 ip6 are present in the list (without checking the ordering)
448 """
449 if (user_ip4 or user_ip6) and not running_addrs:
450 return False
451 elif running_addrs and not user_ip4 and not user_ip6:
452 return False
453 elif not running_addrs and not user_ip4 and not user_ip6:
454 return True
455
456 len_ip4 = len(user_ip4)
457 len_running_addrs = len(running_addrs)
458
459 if len_ip4 > len_running_addrs:
460 return False
461
462 i = 0
463 while i < len_ip4:
464 if user_ip4[i] != running_addrs[i]:
465 return False
466 i += 1
467
468 if len_ip4 > 0:
469 running_ip6 = running_addrs[len_ip4:]
470 else:
471 running_ip6 = running_addrs
472
473 i = 0
474 len_ip6 = len(user_ip6)
475
476 for ip6 in running_ip6:
477 if ip6 not in user_ip6:
478 return False
479 i += 1
480
481 return i == len_ip6
482
483 def order_user_configured_addrs(self, user_config_addrs):
484 ip4 = []
485 ip6 = []
486
487 for a in user_config_addrs:
488 if isinstance(a, _BaseV6):
489 ip6.append(str(a))
490 else:
491 ip4.append(str(a))
492
493 return ip4, ip6, ip4 + ip6
494
495 def _delete_gateway(self, ifaceobj, gateways, vrf, metric):
496 for del_gw in gateways:
497 try:
498 self.ipcmd.route_del_gateway(ifaceobj.name, del_gw, vrf, metric)
499 except Exception as e:
500 self.logger.debug('%s: %s' % (ifaceobj.name, str(e)))
501
502 def _add_delete_gateway(self, ifaceobj, gateways=[], prev_gw=[]):
503 vrf = ifaceobj.get_attr_value_first('vrf')
504 metric = ifaceobj.get_attr_value_first('metric')
505 self._delete_gateway(ifaceobj, list(set(prev_gw) - set(gateways)),
506 vrf, metric)
507 for add_gw in gateways:
508 try:
509 self.ipcmd.route_add_gateway(ifaceobj.name, add_gw, vrf, metric, onlink=self.l3_intf_default_gateway_set_onlink)
510 except Exception as e:
511 self.log_error('%s: %s' % (ifaceobj.name, str(e)))
512
513 def _get_prev_gateway(self, ifaceobj, gateways):
514 ipv = []
515 saved_ifaceobjs = statemanager.statemanager_api.get_ifaceobjs(ifaceobj.name)
516 if not saved_ifaceobjs:
517 return ipv
518 prev_gateways = saved_ifaceobjs[0].get_attr_value('gateway')
519 if not prev_gateways:
520 return ipv
521 return prev_gateways
522
523 def _check_mtu_config(self, ifaceobj, mtu, ifaceobj_getfunc, syntaxcheck=False):
524 retval = True
525 if (ifaceobj.link_kind & ifaceLinkKind.BRIDGE):
526 if syntaxcheck:
527 self.logger.warn('%s: bridge inherits mtu from its ports. There is no need to assign mtu on a bridge' %ifaceobj.name)
528 retval = False
529 else:
530 self.logger.info('%s: bridge inherits mtu from its ports. There is no need to assign mtu on a bridge' %ifaceobj.name)
531 elif ifaceobj_getfunc:
532 if ((ifaceobj.link_privflags & ifaceLinkPrivFlags.BOND_SLAVE) and
533 ifaceobj.upperifaces):
534 masterobj = ifaceobj_getfunc(ifaceobj.upperifaces[0])
535 if masterobj:
536 master_mtu = masterobj[0].get_attr_value_first('mtu')
537 if master_mtu and master_mtu != mtu:
538 if syntaxcheck:
539 self.logger.warn('%s: bond slave mtu %s is different from bond master %s mtu %s. There is no need to configure mtu on a bond slave.' %(ifaceobj.name, mtu, masterobj[0].name, master_mtu))
540 retval = False
541 else:
542 self.logger.info('%s: bond slave mtu %s is different from bond master %s mtu %s. There is no need to configure mtu on a bond slave.' %(ifaceobj.name, mtu, masterobj[0].name, master_mtu))
543 elif ((ifaceobj.link_kind & ifaceLinkKind.VLAN) and
544 ifaceobj.lowerifaces):
545 lowerobj = ifaceobj_getfunc(ifaceobj.lowerifaces[0])
546 if lowerobj:
547 if syntaxcheck:
548 lowerdev_mtu = lowerobj[0].get_attr_value_first('mtu')
549 else:
550 lowerdev_mtu = self.ipcmd.link_get_mtu_sysfs(lowerobj[0].name)
551 if lowerdev_mtu and int(mtu) > int(lowerdev_mtu):
552 self.logger.warn('%s: vlan dev mtu %s is greater than lower realdev %s mtu %s'
553 %(ifaceobj.name, mtu, lowerobj[0].name, lowerdev_mtu))
554 retval = False
555 elif (not lowerobj[0].link_kind and
556 not (lowerobj[0].link_privflags & ifaceLinkPrivFlags.LOOPBACK) and
557 not lowerdev_mtu and self.default_mtu and
558 (int(mtu) > int(self.default_mtu))):
559 # only check default mtu on lower device which is a physical interface
560 self.logger.warn('%s: vlan dev mtu %s is greater than lower realdev %s mtu %s'
561 %(ifaceobj.name, mtu, lowerobj[0].name, self.default_mtu))
562 retval = False
563 if self.max_mtu and mtu > self.max_mtu:
564 self.logger.warn('%s: specified mtu %s is greater than max mtu %s'
565 %(ifaceobj.name, mtu, self.max_mtu))
566 retval = False
567 return retval
568
569 def _propagate_mtu_to_upper_devs(self, ifaceobj, mtu, ifaceobj_getfunc):
570 if (not ifaceobj.upperifaces or
571 (ifaceobj.link_privflags & ifaceLinkPrivFlags.BOND_SLAVE) or
572 (ifaceobj.link_privflags & ifaceLinkPrivFlags.VRF_SLAVE) or
573 (ifaceobj.link_privflags & ifaceLinkPrivFlags.BRIDGE_PORT)):
574 return
575 for u in ifaceobj.upperifaces:
576 upperobjs = ifaceobj_getfunc(u)
577 if (not upperobjs or
578 not (upperobjs[0].link_kind & ifaceLinkKind.VLAN)):
579 continue
580 # only adjust mtu for vlan devices on ifaceobj
581 umtu = upperobjs[0].get_attr_value_first('mtu')
582 if not umtu:
583 running_mtu = self.ipcmd.link_get_mtu(upperobjs[0].name)
584 if not running_mtu or (running_mtu != mtu):
585 self.ipcmd.link_set(u, 'mtu', mtu)
586
587 def _process_mtu_config(self, ifaceobj, ifaceobj_getfunc, mtu):
588 if mtu:
589 if not self._check_mtu_config(ifaceobj, mtu, ifaceobj_getfunc):
590 return
591 cached_running_mtu = self.ipcmd.link_get_mtu(ifaceobj.name)
592 running_mtu = self.ipcmd.link_get_mtu_sysfs(ifaceobj.name)
593 if not running_mtu or (running_mtu and running_mtu != mtu):
594 force = cached_running_mtu != running_mtu
595 self.ipcmd.link_set(ifaceobj.name, 'mtu', mtu, force=force)
596 if (not ifupdownflags.flags.ALL and
597 not ifaceobj.link_kind and
598 ifupdownconfig.config.get('adjust_logical_dev_mtu', '1') != '0'):
599 # This is additional cost to us, so do it only when
600 # ifupdown2 is called on a particular interface and
601 # it is a physical interface
602 self._propagate_mtu_to_upper_devs(ifaceobj, mtu, ifaceobj_getfunc)
603 return
604
605 if ifaceobj.link_kind:
606 # bonds and vxlan devices need an explicit set of mtu.
607 # bridges don't need mtu set
608 if (ifaceobj.link_kind & ifaceLinkKind.BOND or
609 ifaceobj.link_kind & ifaceLinkKind.VXLAN):
610 running_mtu = self.ipcmd.link_get_mtu(ifaceobj.name)
611 if (self.default_mtu and running_mtu != self.default_mtu):
612 self.ipcmd.link_set(ifaceobj.name, 'mtu', self.default_mtu)
613 return
614 if (ifupdownconfig.config.get('adjust_logical_dev_mtu', '1') != '0'
615 and ifaceobj.lowerifaces):
616 # set vlan interface mtu to lower device mtu
617 if (ifaceobj.link_kind & ifaceLinkKind.VLAN):
618 lower_iface = ifaceobj.lowerifaces[0]
619 if lower_iface not in self.lower_iface_mtu_checked_list:
620 lower_iface_mtu = self.ipcmd.link_get_mtu_sysfs(lower_iface)
621 self.ipcmd.cache_update([lower_iface, 'mtu'], lower_iface_mtu)
622 self.lower_iface_mtu_checked_list.append(lower_iface)
623 else:
624 lower_iface_mtu = self.ipcmd.link_get_mtu(lower_iface)
625
626 if lower_iface_mtu != self.ipcmd.link_get_mtu_sysfs(ifaceobj.name):
627 self.ipcmd.link_set_mtu(ifaceobj.name, lower_iface_mtu)
628
629 elif (not (ifaceobj.name == 'lo') and not ifaceobj.link_kind and
630 not (ifaceobj.link_privflags & ifaceLinkPrivFlags.BOND_SLAVE) and
631 self.default_mtu):
632 # logical devices like bridges and vlan devices rely on mtu
633 # from their lower devices. ie mtu travels from
634 # lower devices to upper devices. For bonds mtu travels from
635 # upper to lower devices. running mtu depends on upper and
636 # lower device mtu. With all this implicit mtu
637 # config by the kernel in play, we try to be cautious here
638 # on which devices we want to reset mtu to default.
639 # essentially only physical interfaces which are not bond slaves
640 running_mtu = self.ipcmd.link_get_mtu(ifaceobj.name)
641 if running_mtu != self.default_mtu:
642 self.ipcmd.link_set(ifaceobj.name, 'mtu', self.default_mtu)
643
644 def _set_bridge_forwarding(self, ifaceobj):
645 """ set ip forwarding to 0 if bridge interface does not have a
646 ip nor svi """
647 ifname = ifaceobj.name
648 if not ifaceobj.upperifaces and not ifaceobj.get_attr_value('address'):
649 if self.sysctl_get_forwarding_value_from_proc(ifname, "ipv4") == '1':
650 self.sysctl_write_forwarding_value_to_proc(ifname, "ipv4", 0)
651 if self.sysctl_get_forwarding_value_from_proc(ifname, "ipv6") == '1':
652 self.sysctl_write_forwarding_value_to_proc(ifname, "ipv6", 0)
653 else:
654 if self.sysctl_get_forwarding_value_from_proc(ifname, "ipv4") == '0':
655 self.sysctl_write_forwarding_value_to_proc(ifname, "ipv4", 1)
656 if self.sysctl_get_forwarding_value_from_proc(ifname, "ipv6") == '0':
657 self.sysctl_write_forwarding_value_to_proc(ifname, "ipv6", 1)
658
659 def sysctl_get_forwarding_value_from_proc(self, ifname, family):
660 return self.read_file_oneline("/proc/sys/net/%s/conf/%s/forwarding" % (family, ifname))
661
662 def sysctl_write_forwarding_value_to_proc(self, ifname, family, value):
663 self.write_file("/proc/sys/net/%s/conf/%s/forwarding" % (family, ifname), "%s\n" % value)
664
665 def _sysctl_config(self, ifaceobj):
666 setting_default_value = False
667 mpls_enable = ifaceobj.get_attr_value_first('mpls-enable');
668 if not mpls_enable:
669 setting_default_value = True
670 mpls_enable = self.get_mod_subattr('mpls-enable', 'default')
671 mpls_enable = utils.boolean_support_binary(mpls_enable)
672 # File read has been used for better performance
673 # instead of using sysctl command
674 if ifupdownflags.flags.PERFMODE:
675 running_mpls_enable = '0'
676 else:
677 running_mpls_enable = self.read_file_oneline(
678 '/proc/sys/net/mpls/conf/%s/input'
679 % ifaceobj.name
680 )
681
682 if mpls_enable != running_mpls_enable:
683 try:
684 self.sysctl_set('net.mpls.conf.%s.input'
685 %('/'.join(ifaceobj.name.split("."))),
686 mpls_enable)
687 except Exception as e:
688 if not setting_default_value:
689 ifaceobj.status = ifaceStatus.ERROR
690 self.logger.error('%s: %s' %(ifaceobj.name, str(e)))
691
692 if (ifaceobj.link_kind & ifaceLinkKind.BRIDGE):
693 self._set_bridge_forwarding(ifaceobj)
694 return
695 if not self.syntax_check_sysctls(ifaceobj):
696 return
697 ipforward = ifaceobj.get_attr_value_first('ip-forward')
698 ip6forward = ifaceobj.get_attr_value_first('ip6-forward')
699 if ifupdownflags.flags.PERFMODE:
700 if ipforward:
701 self.sysctl_set('net.ipv4.conf.%s.forwarding'
702 %('/'.join(ifaceobj.name.split("."))),
703 utils.boolean_support_binary(ipforward))
704 if ip6forward:
705 self.sysctl_set('net.ipv6.conf.%s.forwarding'
706 %('/'.join(ifaceobj.name.split("."))),
707 utils.boolean_support_binary(ip6forward))
708 return
709 bridge_port = ifaceobj.link_privflags & ifaceLinkPrivFlags.BRIDGE_PORT
710 if bridge_port:
711 if ipforward:
712 self.log_error('%s: \'ip-forward\' is not supported for '
713 'bridge port' %ifaceobj.name)
714 if ip6forward:
715 self.log_error('%s: \'ip6-forward\' is not supported for '
716 'bridge port' %ifaceobj.name)
717 return
718
719 setting_default_value = False
720 if not ipforward:
721 setting_default_value = True
722 ipforward = self.ipforward
723
724 if ipforward:
725 ipforward = utils.boolean_support_binary(ipforward)
726 # File read has been used for better performance
727 # instead of using sysctl command
728 running_ipforward = self.read_file_oneline(
729 '/proc/sys/net/ipv4/conf/%s/forwarding'
730 %ifaceobj.name)
731
732 if ipforward != running_ipforward:
733 try:
734
735 self.sysctl_set('net.ipv4.conf.%s.forwarding'
736 %('/'.join(ifaceobj.name.split("."))),
737 ipforward)
738 except Exception as e:
739 if not setting_default_value:
740 ifaceobj.status = ifaceStatus.ERROR
741 self.logger.error('%s: %s' %(ifaceobj.name, str(e)))
742
743
744 setting_default_value = False
745 if not ip6forward:
746 setting_default_value = True
747 ip6forward = self.ip6forward
748
749 if ip6forward:
750 ip6forward = utils.boolean_support_binary(ip6forward)
751 # File read has been used for better performance
752 # instead of using sysctl command
753 running_ip6forward = self.read_file_oneline(
754 '/proc/sys/net/ipv6/conf/%s/forwarding'
755 %ifaceobj.name)
756 if ip6forward != running_ip6forward:
757 try:
758 self.sysctl_set('net.ipv6.conf.%s.forwarding'
759 %('/'.join(ifaceobj.name.split("."))),
760 ip6forward)
761 except Exception as e:
762 # There is chance of ipv6 being removed because of,
763 # for example, setting mtu < 1280
764 # In such cases, log error only if user has configured
765 # ip6-forward
766 if not setting_default_value:
767 ifaceobj.status = ifaceStatus.ERROR
768 self.logger.error('%s: %s' %(ifaceobj.name, str(e)))
769
770 def process_mtu(self, ifaceobj, ifaceobj_getfunc):
771 mtu = ifaceobj.get_attr_value_first('mtu')
772
773 if not mtu:
774 default_iface_mtu = self.ifaces_defaults.get(ifaceobj.name, {}).get('mtu')
775
776 if default_iface_mtu:
777 try:
778 mtu = default_iface_mtu
779 int(default_iface_mtu)
780 except Exception as e:
781 self.logger.warning('%s: MTU value from policy file: %s' % (ifaceobj.name, str(e)))
782 return
783
784 self._process_mtu_config(ifaceobj, ifaceobj_getfunc, mtu)
785
786 def up_ipv6_addrgen(self, ifaceobj):
787 user_configured_ipv6_addrgen = ifaceobj.get_attr_value_first('ipv6-addrgen')
788
789 if not user_configured_ipv6_addrgen and ifupdownflags.flags.PERFMODE:
790 # no need to go further during perfmode (boot)
791 return
792
793 if not user_configured_ipv6_addrgen and ifaceobj.addr_method == 'dhcp':
794 return
795
796 if not user_configured_ipv6_addrgen:
797 # if user didn't configure ipv6-addrgen, should we reset to default?
798 user_configured_ipv6_addrgen = self.get_attr_default_value('ipv6-addrgen')
799
800 ipv6_addrgen_nl = {
801 'on': 0,
802 'yes': 0,
803 '0': 0,
804 'off': 1,
805 'no': 1,
806 '1': 1
807 }.get(user_configured_ipv6_addrgen.lower(), None)
808
809 if ipv6_addrgen_nl is not None:
810 self.ipcmd.ipv6_addrgen(ifaceobj.name, ipv6_addrgen_nl, link_created=True)
811 # link_create=False will flush the addr cache of that intf
812 else:
813 self.logger.warning('%s: invalid value "%s" for attribute ipv6-addrgen' % (ifaceobj.name, user_configured_ipv6_addrgen))
814
815 def _up(self, ifaceobj, ifaceobj_getfunc=None):
816 if not self.ipcmd.link_exists(ifaceobj.name):
817 return
818
819 if not self.syntax_check_enable_l3_iface_forwardings(ifaceobj, ifaceobj_getfunc):
820 return
821
822 alias = ifaceobj.get_attr_value_first('alias')
823 current_alias = self.ipcmd.link_get_alias(ifaceobj.name)
824 if alias and alias != current_alias:
825 self.ipcmd.link_set_alias(ifaceobj.name, alias)
826 elif not alias and current_alias:
827 self.ipcmd.link_set_alias(ifaceobj.name, '')
828
829 self._sysctl_config(ifaceobj)
830
831 addr_method = ifaceobj.addr_method
832 force_reapply = False
833 try:
834 # release any stale dhcp addresses if present
835 if (addr_method not in ["dhcp", "ppp"] and not ifupdownflags.flags.PERFMODE and
836 not (ifaceobj.flags & iface.HAS_SIBLINGS)):
837 # if not running in perf mode and ifaceobj does not have
838 # any sibling iface objects, kill any stale dhclient
839 # processes
840 dhclientcmd = dhclient()
841 if dhclientcmd.is_running(ifaceobj.name):
842 # release any dhcp leases
843 dhclientcmd.release(ifaceobj.name)
844 force_reapply = True
845 elif dhclientcmd.is_running6(ifaceobj.name):
846 dhclientcmd.release6(ifaceobj.name)
847 force_reapply = True
848 except:
849 pass
850
851 self.ipcmd.batch_start()
852 self.up_ipv6_addrgen(ifaceobj)
853
854 if addr_method not in ["dhcp", "ppp"]:
855 self._inet_address_config(ifaceobj, ifaceobj_getfunc,
856 force_reapply)
857
858 self.process_mtu(ifaceobj, ifaceobj_getfunc)
859
860 try:
861 self.ipcmd.batch_commit()
862 except Exception as e:
863 self.log_error('%s: %s' % (ifaceobj.name, str(e)), ifaceobj, raise_error=False)
864
865 try:
866 hwaddress = self._get_hwaddress(ifaceobj)
867 if hwaddress:
868 running_hwaddress = None
869 if not ifupdownflags.flags.PERFMODE: # system is clean
870 running_hwaddress = self.ipcmd.link_get_hwaddress(ifaceobj.name)
871 if hwaddress != running_hwaddress:
872 slave_down = False
873 netlink.link_set_updown(ifaceobj.name, "down")
874 if ifaceobj.link_kind & ifaceLinkKind.BOND:
875 # if bond, down all the slaves
876 if ifaceobj.lowerifaces:
877 for l in ifaceobj.lowerifaces:
878 netlink.link_set_updown(l, "down")
879 slave_down = True
880 try:
881 self.ipcmd.link_set(ifaceobj.name, 'address', hwaddress)
882 finally:
883 netlink.link_set_updown(ifaceobj.name, "up")
884 if slave_down:
885 for l in ifaceobj.lowerifaces:
886 netlink.link_set_updown(l, "up")
887
888 # Handle special things on a bridge
889 self._process_bridge(ifaceobj, True)
890 except Exception, e:
891 self.log_error('%s: %s' %(ifaceobj.name, str(e)), ifaceobj)
892
893 gateways = ifaceobj.get_attr_value('gateway')
894 if not gateways:
895 gateways = []
896 prev_gw = self._get_prev_gateway(ifaceobj, gateways)
897 self._add_delete_gateway(ifaceobj, gateways, prev_gw)
898
899 def _down(self, ifaceobj, ifaceobj_getfunc=None):
900 try:
901 if not self.ipcmd.link_exists(ifaceobj.name):
902 return
903 addr_method = ifaceobj.addr_method
904 if addr_method not in ["dhcp", "ppp"]:
905 if ifaceobj.get_attr_value_first('address-purge')=='no':
906 addrlist = ifaceobj.get_attr_value('address')
907 for addr in addrlist:
908 self.ipcmd.addr_del(ifaceobj.name, addr)
909 #self.ipcmd.addr_del(ifaceobj.name, ifaceobj.get_attr_value('address')[0])
910 elif not ifaceobj.link_kind:
911 # for logical interfaces we don't need to remove the ip addresses
912 # kernel will do it for us on 'ip link del'
913 self.ipcmd.del_addr_all(ifaceobj.name)
914 gateways = ifaceobj.get_attr_value('gateway')
915 if gateways:
916 self._delete_gateway(ifaceobj, gateways,
917 ifaceobj.get_attr_value_first('vrf'),
918 ifaceobj.get_attr_value_first('metric'))
919 mtu = ifaceobj.get_attr_value_first('mtu')
920 if (not ifaceobj.link_kind and mtu and
921 self.default_mtu and (mtu != self.default_mtu)):
922 self.ipcmd.link_set(ifaceobj.name, 'mtu', self.default_mtu)
923 alias = ifaceobj.get_attr_value_first('alias')
924 if alias:
925 self.write_file('/sys/class/net/%s/ifalias' % ifaceobj.name, '\n')
926 # XXX hwaddress reset cannot happen because we dont know last
927 # address.
928
929 # Handle special things on a bridge
930 self._process_bridge(ifaceobj, False)
931 except Exception, e:
932 self.logger.debug('%s : %s' %(ifaceobj.name, str(e)))
933 pass
934
935 def _get_iface_addresses(self, ifaceobj):
936 addrlist = ifaceobj.get_attr_value('address')
937 outaddrlist = []
938
939 if not addrlist: return None
940 for addrindex in range(0, len(addrlist)):
941 addr = addrlist[addrindex]
942 netmask = ifaceobj.get_attr_value_n('netmask', addrindex)
943 if netmask:
944 prefixlen = IPNetwork('%s' %addr +
945 '/%s' %netmask).prefixlen
946 addr = addr + '/%s' %prefixlen
947 outaddrlist.append(addr)
948 return outaddrlist
949
950 def _get_bridge_fdbs(self, bridgename, vlan):
951 fdbs = self._bridge_fdb_query_cache.get(bridgename)
952 if not fdbs:
953 fdbs = self.ipcmd.bridge_fdb_show_dev(bridgename)
954 if not fdbs:
955 return
956 self._bridge_fdb_query_cache[bridgename] = fdbs
957 return fdbs.get(vlan)
958
959 def _check_addresses_in_bridge(self, ifaceobj, hwaddress):
960 """ If the device is a bridge, make sure the addresses
961 are in the bridge """
962 if ifaceobj.link_kind & ifaceLinkKind.VLAN:
963 bridgename = ifaceobj.lowerifaces[0]
964 vlan = self._get_vlan_id(ifaceobj)
965 if self.ipcmd.bridge_is_vlan_aware(bridgename):
966 fdb_addrs = self._get_bridge_fdbs(bridgename, str(vlan))
967 if not fdb_addrs or hwaddress not in fdb_addrs:
968 return False
969 return True
970
971 def _query_sysctl(self, ifaceobj, ifaceobjcurr):
972 bridge_port = ifaceobj.link_privflags & ifaceLinkPrivFlags.BRIDGE_PORT
973 ipforward = ifaceobj.get_attr_value_first('ip-forward')
974 if ipforward:
975 if bridge_port:
976 ifaceobjcurr.status = ifaceStatus.ERROR
977 ifaceobjcurr.status_str = ('\'ip-forward\' not supported ' +
978 'for bridge port')
979 ifaceobjcurr.update_config_with_status('ip-forward', 1, None)
980 else:
981 running_ipforward = self.read_file_oneline(
982 '/proc/sys/net/ipv4/conf/%s/forwarding'
983 %ifaceobj.name)
984 running_ipforward = utils.get_boolean_from_string(running_ipforward)
985 config_ipforward = utils.get_boolean_from_string(ipforward)
986 ifaceobjcurr.update_config_with_status(
987 'ip-forward',
988 'on' if running_ipforward else 'off',
989 running_ipforward != config_ipforward
990 )
991
992 ip6forward = ifaceobj.get_attr_value_first('ip6-forward')
993 if ip6forward:
994 if bridge_port:
995 ifaceobjcurr.status = ifaceStatus.ERROR
996 ifaceobjcurr.status_str = ('\'ip6-forward\' not supported ' +
997 'for bridge port')
998 ifaceobjcurr.update_config_with_status('ip6-forward', 1, None)
999 else:
1000 running_ip6forward = self.read_file_oneline(
1001 '/proc/sys/net/ipv6/conf/%s/forwarding'
1002 %ifaceobj.name)
1003 running_ip6forward = utils.get_boolean_from_string(running_ip6forward)
1004 config_ip6forward = utils.get_boolean_from_string(ip6forward)
1005 ifaceobjcurr.update_config_with_status(
1006 'ip6-forward',
1007 'on' if running_ip6forward else 'off',
1008 running_ip6forward != config_ip6forward
1009 )
1010 mpls_enable = ifaceobj.get_attr_value_first('mpls-enable');
1011 if mpls_enable:
1012 running_mpls_enable = self.read_file_oneline(
1013 '/proc/sys/net/mpls/conf/%s/input'
1014 %ifaceobj.name)
1015 running_mpls_enable = utils.get_yesno_from_onezero(
1016 running_mpls_enable)
1017 ifaceobjcurr.update_config_with_status('mpls-enable',
1018 running_mpls_enable,
1019 mpls_enable != running_mpls_enable)
1020 return
1021
1022 def query_check_ipv6_addrgen(self, ifaceobj, ifaceobjcurr):
1023 ipv6_addrgen = ifaceobj.get_attr_value_first('ipv6-addrgen')
1024
1025 if not ipv6_addrgen:
1026 return
1027
1028 if ipv6_addrgen in utils._string_values:
1029 ifaceobjcurr.update_config_with_status(
1030 'ipv6-addrgen',
1031 ipv6_addrgen,
1032 utils.get_boolean_from_string(ipv6_addrgen) == self.ipcmd.get_ipv6_addrgen_mode(ifaceobj.name)
1033 )
1034 else:
1035 ifaceobjcurr.update_config_with_status('ipv6-addrgen', ipv6_addrgen, 1)
1036
1037 def _query_check(self, ifaceobj, ifaceobjcurr, ifaceobj_getfunc=None):
1038 runningaddrsdict = None
1039 if not self.ipcmd.link_exists(ifaceobj.name):
1040 self.logger.debug('iface %s not found' %ifaceobj.name)
1041 return
1042
1043 self.query_check_ipv6_addrgen(ifaceobj, ifaceobjcurr)
1044
1045 addr_method = ifaceobj.addr_method
1046 self.query_n_update_ifaceobjcurr_attr(ifaceobj, ifaceobjcurr,
1047 'mtu', self.ipcmd.link_get_mtu)
1048 hwaddress = self._get_hwaddress(ifaceobj)
1049 if hwaddress:
1050 rhwaddress = self.ipcmd.link_get_hwaddress(ifaceobj.name)
1051 if not rhwaddress or rhwaddress != hwaddress:
1052 ifaceobjcurr.update_config_with_status('hwaddress', rhwaddress,
1053 1)
1054 elif not self._check_addresses_in_bridge(ifaceobj, hwaddress):
1055 # XXX: hw address is not in bridge
1056 ifaceobjcurr.update_config_with_status('hwaddress', rhwaddress,
1057 1)
1058 ifaceobjcurr.status_str = 'bridge fdb error'
1059 else:
1060 ifaceobjcurr.update_config_with_status('hwaddress', rhwaddress,
1061 0)
1062 self.query_n_update_ifaceobjcurr_attr(ifaceobj, ifaceobjcurr,
1063 'alias', self.ipcmd.link_get_alias)
1064 self._query_sysctl(ifaceobj, ifaceobjcurr)
1065 # compare addresses
1066 if addr_method in ["dhcp", "ppp"]:
1067 return
1068 addrs = utils.get_normalized_ip_addr(ifaceobj.name,
1069 self._get_iface_addresses(ifaceobj))
1070 runningaddrsdict = self.ipcmd.get_running_addrs(ifaceobj)
1071 # if anycast address is configured on 'lo' and is in running config
1072 # add it to addrs so that query_check doesn't fail
1073 anycast_addr = utils.get_normalized_ip_addr(ifaceobj.name, ifaceobj.get_attr_value_first('clagd-vxlan-anycast-ip'))
1074 if anycast_addr:
1075 anycast_addr = anycast_addr+'/32'
1076 if runningaddrsdict and anycast_addr and runningaddrsdict.get(anycast_addr):
1077 addrs.append(anycast_addr)
1078
1079 # Set ifaceobjcurr method and family
1080 ifaceobjcurr.addr_method = ifaceobj.addr_method
1081 ifaceobjcurr.addr_family = ifaceobj.addr_family
1082 if not runningaddrsdict and not addrs:
1083 return
1084 runningaddrs = runningaddrsdict.keys() if runningaddrsdict else []
1085 # Add /32 netmask to configured address without netmask.
1086 # This may happen on interfaces where pointopoint is used.
1087 runningaddrs = [ addr if '/' in addr else addr + '/32' for addr in runningaddrs]
1088 if runningaddrs != addrs:
1089 runningaddrsset = set(runningaddrs) if runningaddrs else set([])
1090 addrsset = set(addrs) if addrs else set([])
1091 if (ifaceobj.flags & iface.HAS_SIBLINGS):
1092 if not addrsset:
1093 return
1094 # only check for addresses present in running config
1095 addrsdiff = addrsset.difference(runningaddrsset)
1096 for addr in addrs:
1097 if addr in addrsdiff:
1098 ifaceobjcurr.update_config_with_status('address',
1099 addr, 1)
1100 else:
1101 ifaceobjcurr.update_config_with_status('address',
1102 addr, 0)
1103 else:
1104 addrsdiff = addrsset.symmetric_difference(runningaddrsset)
1105 for addr in addrsset.union(runningaddrsset):
1106 if addr in addrsdiff:
1107 ifaceobjcurr.update_config_with_status('address',
1108 addr, 1)
1109 else:
1110 ifaceobjcurr.update_config_with_status('address',
1111 addr, 0)
1112 elif addrs:
1113 [ifaceobjcurr.update_config_with_status('address',
1114 addr, 0) for addr in addrs]
1115 #XXXX Check broadcast address, scope, etc
1116 return
1117
1118 def query_running_ipv6_addrgen(self, ifaceobjrunning):
1119 ipv6_addrgen = self.ipcmd.get_ipv6_addrgen_mode(ifaceobjrunning.name)
1120
1121 if ipv6_addrgen:
1122 ifaceobjrunning.update_config('ipv6-addrgen', 'off')
1123
1124 def _query_running(self, ifaceobjrunning, ifaceobj_getfunc=None):
1125 if not self.ipcmd.link_exists(ifaceobjrunning.name):
1126 self.logger.debug('iface %s not found' %ifaceobjrunning.name)
1127 return
1128
1129 self.query_running_ipv6_addrgen(ifaceobjrunning)
1130
1131 dhclientcmd = dhclient()
1132 if (dhclientcmd.is_running(ifaceobjrunning.name) or
1133 dhclientcmd.is_running6(ifaceobjrunning.name)):
1134 # If dhcp is configured on the interface, we skip it
1135 return
1136 isloopback = self.ipcmd.link_isloopback(ifaceobjrunning.name)
1137 if isloopback:
1138 default_addrs = ['127.0.0.1/8', '::1/128']
1139 ifaceobjrunning.addr_family.append('inet')
1140 ifaceobjrunning.addr_method = 'loopback'
1141 else:
1142 default_addrs = []
1143 runningaddrsdict = self.ipcmd.get_running_addrs(ifaceobjrunning)
1144 if runningaddrsdict:
1145 [ifaceobjrunning.update_config('address', addr)
1146 for addr, addrattrs in runningaddrsdict.items()
1147 if addr not in default_addrs]
1148 mtu = self.ipcmd.link_get_mtu(ifaceobjrunning.name)
1149 if (mtu and
1150 (ifaceobjrunning.name == 'lo' and mtu != '16436') or
1151 (ifaceobjrunning.name != 'lo' and
1152 mtu != self.get_mod_subattr('mtu', 'default'))):
1153 ifaceobjrunning.update_config('mtu', mtu)
1154 alias = self.ipcmd.link_get_alias(ifaceobjrunning.name)
1155 if alias:
1156 ifaceobjrunning.update_config('alias', alias)
1157
1158 ipforward = self.read_file_oneline(
1159 '/proc/sys/net/ipv4/conf/%s/forwarding'
1160 %ifaceobjrunning.name)
1161
1162
1163 _run_ops = {'up' : _up,
1164 'down' : _down,
1165 'query-checkcurr' : _query_check,
1166 'query-running' : _query_running }
1167
1168 def get_ops(self):
1169 """ returns list of ops supported by this module """
1170 return self._run_ops.keys()
1171
1172 def _init_command_handlers(self):
1173 if not self.ipcmd:
1174 self.ipcmd = LinkUtils()
1175
1176 def run(self, ifaceobj, operation, query_ifaceobj=None, ifaceobj_getfunc=None):
1177 """ run address configuration on the interface object passed as argument
1178
1179 Args:
1180 **ifaceobj** (object): iface object
1181
1182 **operation** (str): any of 'up', 'down', 'query-checkcurr',
1183 'query-running'
1184 Kwargs:
1185 query_ifaceobj (object): query check ifaceobject. This is only
1186 valid when op is 'query-checkcurr'. It is an object same as
1187 ifaceobj, but contains running attribute values and its config
1188 status. The modules can use it to return queried running state
1189 of interfaces. status is success if the running state is same
1190 as user required state in ifaceobj. error otherwise.
1191 """
1192 if ifaceobj.type == ifaceType.BRIDGE_VLAN:
1193 return
1194 op_handler = self._run_ops.get(operation)
1195 if not op_handler:
1196 return
1197 self._init_command_handlers()
1198 if operation == 'query-checkcurr':
1199 op_handler(self, ifaceobj, query_ifaceobj,
1200 ifaceobj_getfunc=ifaceobj_getfunc)
1201 else:
1202 op_handler(self, ifaceobj,
1203 ifaceobj_getfunc=ifaceobj_getfunc)