]> git.proxmox.com Git - mirror_ifupdown2.git/blob - ifupdown2/addons/address.py
f088d5fda7fab9a3d1861617af1dfcf7c929c16f
[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, vxlan and custom devices (like dummy) 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 or
610 ifaceobj.link_kind & ifaceLinkKind.OTHER
611 ):
612 running_mtu = self.ipcmd.link_get_mtu(ifaceobj.name)
613 if (self.default_mtu and running_mtu != self.default_mtu):
614 self.ipcmd.link_set(ifaceobj.name, 'mtu', self.default_mtu)
615 return
616 if (ifupdownconfig.config.get('adjust_logical_dev_mtu', '1') != '0'
617 and ifaceobj.lowerifaces):
618 # set vlan interface mtu to lower device mtu
619 if (ifaceobj.link_kind & ifaceLinkKind.VLAN):
620 lower_iface = ifaceobj.lowerifaces[0]
621 if lower_iface not in self.lower_iface_mtu_checked_list:
622 lower_iface_mtu = self.ipcmd.link_get_mtu_sysfs(lower_iface)
623 self.ipcmd.cache_update([lower_iface, 'mtu'], lower_iface_mtu)
624 self.lower_iface_mtu_checked_list.append(lower_iface)
625 else:
626 lower_iface_mtu = self.ipcmd.link_get_mtu(lower_iface)
627
628 if lower_iface_mtu != self.ipcmd.link_get_mtu_sysfs(ifaceobj.name):
629 self.ipcmd.link_set_mtu(ifaceobj.name, lower_iface_mtu)
630
631 elif (not (ifaceobj.name == 'lo') and not ifaceobj.link_kind and
632 not (ifaceobj.link_privflags & ifaceLinkPrivFlags.BOND_SLAVE) and
633 self.default_mtu):
634 # logical devices like bridges and vlan devices rely on mtu
635 # from their lower devices. ie mtu travels from
636 # lower devices to upper devices. For bonds mtu travels from
637 # upper to lower devices. running mtu depends on upper and
638 # lower device mtu. With all this implicit mtu
639 # config by the kernel in play, we try to be cautious here
640 # on which devices we want to reset mtu to default.
641 # essentially only physical interfaces which are not bond slaves
642 running_mtu = self.ipcmd.link_get_mtu(ifaceobj.name)
643 if running_mtu != self.default_mtu:
644 self.ipcmd.link_set(ifaceobj.name, 'mtu', self.default_mtu)
645
646 def _set_bridge_forwarding(self, ifaceobj):
647 """ set ip forwarding to 0 if bridge interface does not have a
648 ip nor svi """
649 ifname = ifaceobj.name
650 if not ifaceobj.upperifaces and not ifaceobj.get_attr_value('address'):
651 if self.sysctl_get_forwarding_value_from_proc(ifname, "ipv4") == '1':
652 self.sysctl_write_forwarding_value_to_proc(ifname, "ipv4", 0)
653 if self.sysctl_get_forwarding_value_from_proc(ifname, "ipv6") == '1':
654 self.sysctl_write_forwarding_value_to_proc(ifname, "ipv6", 0)
655 else:
656 if self.sysctl_get_forwarding_value_from_proc(ifname, "ipv4") == '0':
657 self.sysctl_write_forwarding_value_to_proc(ifname, "ipv4", 1)
658 if self.sysctl_get_forwarding_value_from_proc(ifname, "ipv6") == '0':
659 self.sysctl_write_forwarding_value_to_proc(ifname, "ipv6", 1)
660
661 def sysctl_get_forwarding_value_from_proc(self, ifname, family):
662 return self.read_file_oneline("/proc/sys/net/%s/conf/%s/forwarding" % (family, ifname))
663
664 def sysctl_write_forwarding_value_to_proc(self, ifname, family, value):
665 self.write_file("/proc/sys/net/%s/conf/%s/forwarding" % (family, ifname), "%s\n" % value)
666
667 def _sysctl_config(self, ifaceobj):
668 setting_default_value = False
669 mpls_enable = ifaceobj.get_attr_value_first('mpls-enable');
670 if not mpls_enable:
671 setting_default_value = True
672 mpls_enable = self.get_mod_subattr('mpls-enable', 'default')
673 mpls_enable = utils.boolean_support_binary(mpls_enable)
674 # File read has been used for better performance
675 # instead of using sysctl command
676 if ifupdownflags.flags.PERFMODE:
677 running_mpls_enable = '0'
678 else:
679 running_mpls_enable = self.read_file_oneline(
680 '/proc/sys/net/mpls/conf/%s/input'
681 % ifaceobj.name
682 )
683
684 if mpls_enable != running_mpls_enable:
685 try:
686 self.sysctl_set('net.mpls.conf.%s.input'
687 %('/'.join(ifaceobj.name.split("."))),
688 mpls_enable)
689 except Exception as e:
690 if not setting_default_value:
691 ifaceobj.status = ifaceStatus.ERROR
692 self.logger.error('%s: %s' %(ifaceobj.name, str(e)))
693
694 if (ifaceobj.link_kind & ifaceLinkKind.BRIDGE):
695 self._set_bridge_forwarding(ifaceobj)
696 return
697 if not self.syntax_check_sysctls(ifaceobj):
698 return
699 ipforward = ifaceobj.get_attr_value_first('ip-forward')
700 ip6forward = ifaceobj.get_attr_value_first('ip6-forward')
701 if ifupdownflags.flags.PERFMODE:
702 if ipforward:
703 self.sysctl_set('net.ipv4.conf.%s.forwarding'
704 %('/'.join(ifaceobj.name.split("."))),
705 utils.boolean_support_binary(ipforward))
706 if ip6forward:
707 self.sysctl_set('net.ipv6.conf.%s.forwarding'
708 %('/'.join(ifaceobj.name.split("."))),
709 utils.boolean_support_binary(ip6forward))
710 return
711 bridge_port = ifaceobj.link_privflags & ifaceLinkPrivFlags.BRIDGE_PORT
712 if bridge_port:
713 if ipforward:
714 self.log_error('%s: \'ip-forward\' is not supported for '
715 'bridge port' %ifaceobj.name)
716 if ip6forward:
717 self.log_error('%s: \'ip6-forward\' is not supported for '
718 'bridge port' %ifaceobj.name)
719 return
720
721 setting_default_value = False
722 if not ipforward:
723 setting_default_value = True
724 ipforward = self.ipforward
725
726 if ipforward:
727 ipforward = utils.boolean_support_binary(ipforward)
728 # File read has been used for better performance
729 # instead of using sysctl command
730 running_ipforward = self.read_file_oneline(
731 '/proc/sys/net/ipv4/conf/%s/forwarding'
732 %ifaceobj.name)
733
734 if ipforward != running_ipforward:
735 try:
736
737 self.sysctl_set('net.ipv4.conf.%s.forwarding'
738 %('/'.join(ifaceobj.name.split("."))),
739 ipforward)
740 except Exception as e:
741 if not setting_default_value:
742 ifaceobj.status = ifaceStatus.ERROR
743 self.logger.error('%s: %s' %(ifaceobj.name, str(e)))
744
745
746 setting_default_value = False
747 if not ip6forward:
748 setting_default_value = True
749 ip6forward = self.ip6forward
750
751 if ip6forward:
752 ip6forward = utils.boolean_support_binary(ip6forward)
753 # File read has been used for better performance
754 # instead of using sysctl command
755 running_ip6forward = self.read_file_oneline(
756 '/proc/sys/net/ipv6/conf/%s/forwarding'
757 %ifaceobj.name)
758 if ip6forward != running_ip6forward:
759 try:
760 self.sysctl_set('net.ipv6.conf.%s.forwarding'
761 %('/'.join(ifaceobj.name.split("."))),
762 ip6forward)
763 except Exception as e:
764 # There is chance of ipv6 being removed because of,
765 # for example, setting mtu < 1280
766 # In such cases, log error only if user has configured
767 # ip6-forward
768 if not setting_default_value:
769 ifaceobj.status = ifaceStatus.ERROR
770 self.logger.error('%s: %s' %(ifaceobj.name, str(e)))
771
772 def process_mtu(self, ifaceobj, ifaceobj_getfunc):
773 mtu = ifaceobj.get_attr_value_first('mtu')
774
775 if not mtu:
776 default_iface_mtu = self.ifaces_defaults.get(ifaceobj.name, {}).get('mtu')
777
778 if default_iface_mtu:
779 try:
780 mtu = default_iface_mtu
781 int(default_iface_mtu)
782 except Exception as e:
783 self.logger.warning('%s: MTU value from policy file: %s' % (ifaceobj.name, str(e)))
784 return
785
786 self._process_mtu_config(ifaceobj, ifaceobj_getfunc, mtu)
787
788 def up_ipv6_addrgen(self, ifaceobj):
789 user_configured_ipv6_addrgen = ifaceobj.get_attr_value_first('ipv6-addrgen')
790
791 if not user_configured_ipv6_addrgen and ifupdownflags.flags.PERFMODE:
792 # no need to go further during perfmode (boot)
793 return
794
795 if not user_configured_ipv6_addrgen and ifaceobj.addr_method == 'dhcp':
796 return
797
798 if not user_configured_ipv6_addrgen:
799 # if user didn't configure ipv6-addrgen, should we reset to default?
800 user_configured_ipv6_addrgen = self.get_attr_default_value('ipv6-addrgen')
801
802 ipv6_addrgen_nl = {
803 'on': 0,
804 'yes': 0,
805 '0': 0,
806 'off': 1,
807 'no': 1,
808 '1': 1
809 }.get(user_configured_ipv6_addrgen.lower(), None)
810
811 if ipv6_addrgen_nl is not None:
812 self.ipcmd.ipv6_addrgen(ifaceobj.name, ipv6_addrgen_nl, link_created=True)
813 # link_create=False will flush the addr cache of that intf
814 else:
815 self.logger.warning('%s: invalid value "%s" for attribute ipv6-addrgen' % (ifaceobj.name, user_configured_ipv6_addrgen))
816
817 def _up(self, ifaceobj, ifaceobj_getfunc=None):
818 if not self.ipcmd.link_exists(ifaceobj.name):
819 return
820
821 if not self.syntax_check_enable_l3_iface_forwardings(ifaceobj, ifaceobj_getfunc):
822 return
823
824 alias = ifaceobj.get_attr_value_first('alias')
825 current_alias = self.ipcmd.link_get_alias(ifaceobj.name)
826 if alias and alias != current_alias:
827 self.ipcmd.link_set_alias(ifaceobj.name, alias)
828 elif not alias and current_alias:
829 self.ipcmd.link_set_alias(ifaceobj.name, '')
830
831 self._sysctl_config(ifaceobj)
832
833 addr_method = ifaceobj.addr_method
834 force_reapply = False
835 try:
836 # release any stale dhcp addresses if present
837 if (addr_method not in ["dhcp", "ppp"] and not ifupdownflags.flags.PERFMODE and
838 not (ifaceobj.flags & iface.HAS_SIBLINGS)):
839 # if not running in perf mode and ifaceobj does not have
840 # any sibling iface objects, kill any stale dhclient
841 # processes
842 dhclientcmd = dhclient()
843 if dhclientcmd.is_running(ifaceobj.name):
844 # release any dhcp leases
845 dhclientcmd.release(ifaceobj.name)
846 force_reapply = True
847 elif dhclientcmd.is_running6(ifaceobj.name):
848 dhclientcmd.release6(ifaceobj.name)
849 force_reapply = True
850 except:
851 pass
852
853 self.ipcmd.batch_start()
854 self.up_ipv6_addrgen(ifaceobj)
855
856 if addr_method not in ["dhcp", "ppp"]:
857 self._inet_address_config(ifaceobj, ifaceobj_getfunc,
858 force_reapply)
859
860 self.process_mtu(ifaceobj, ifaceobj_getfunc)
861
862 try:
863 self.ipcmd.batch_commit()
864 except Exception as e:
865 self.log_error('%s: %s' % (ifaceobj.name, str(e)), ifaceobj, raise_error=False)
866
867 try:
868 hwaddress = self._get_hwaddress(ifaceobj)
869 if hwaddress:
870 running_hwaddress = None
871 if not ifupdownflags.flags.PERFMODE: # system is clean
872 running_hwaddress = self.ipcmd.link_get_hwaddress(ifaceobj.name)
873 if hwaddress != running_hwaddress:
874 slave_down = False
875 netlink.link_set_updown(ifaceobj.name, "down")
876 if ifaceobj.link_kind & ifaceLinkKind.BOND:
877 # if bond, down all the slaves
878 if ifaceobj.lowerifaces:
879 for l in ifaceobj.lowerifaces:
880 netlink.link_set_updown(l, "down")
881 slave_down = True
882 try:
883 self.ipcmd.link_set(ifaceobj.name, 'address', hwaddress)
884 finally:
885 netlink.link_set_updown(ifaceobj.name, "up")
886 if slave_down:
887 for l in ifaceobj.lowerifaces:
888 netlink.link_set_updown(l, "up")
889
890 # Handle special things on a bridge
891 self._process_bridge(ifaceobj, True)
892 except Exception, e:
893 self.log_error('%s: %s' %(ifaceobj.name, str(e)), ifaceobj)
894
895 gateways = ifaceobj.get_attr_value('gateway')
896 if not gateways:
897 gateways = []
898 prev_gw = self._get_prev_gateway(ifaceobj, gateways)
899 self._add_delete_gateway(ifaceobj, gateways, prev_gw)
900
901 def _down(self, ifaceobj, ifaceobj_getfunc=None):
902 try:
903 if not self.ipcmd.link_exists(ifaceobj.name):
904 return
905 addr_method = ifaceobj.addr_method
906 if addr_method not in ["dhcp", "ppp"]:
907 if ifaceobj.get_attr_value_first('address-purge')=='no':
908 addrlist = ifaceobj.get_attr_value('address')
909 for addr in addrlist:
910 self.ipcmd.addr_del(ifaceobj.name, addr)
911 #self.ipcmd.addr_del(ifaceobj.name, ifaceobj.get_attr_value('address')[0])
912 elif not ifaceobj.link_kind:
913 # for logical interfaces we don't need to remove the ip addresses
914 # kernel will do it for us on 'ip link del'
915 self.ipcmd.del_addr_all(ifaceobj.name)
916 gateways = ifaceobj.get_attr_value('gateway')
917 if gateways:
918 self._delete_gateway(ifaceobj, gateways,
919 ifaceobj.get_attr_value_first('vrf'),
920 ifaceobj.get_attr_value_first('metric'))
921 mtu = ifaceobj.get_attr_value_first('mtu')
922 if (not ifaceobj.link_kind and mtu and
923 self.default_mtu and (mtu != self.default_mtu)):
924 self.ipcmd.link_set(ifaceobj.name, 'mtu', self.default_mtu)
925 alias = ifaceobj.get_attr_value_first('alias')
926 if alias:
927 self.write_file('/sys/class/net/%s/ifalias' % ifaceobj.name, '\n')
928 # XXX hwaddress reset cannot happen because we dont know last
929 # address.
930
931 # Handle special things on a bridge
932 self._process_bridge(ifaceobj, False)
933 except Exception, e:
934 self.logger.debug('%s : %s' %(ifaceobj.name, str(e)))
935 pass
936
937 def _get_iface_addresses(self, ifaceobj):
938 addrlist = ifaceobj.get_attr_value('address')
939 outaddrlist = []
940
941 if not addrlist: return None
942 for addrindex in range(0, len(addrlist)):
943 addr = addrlist[addrindex]
944 netmask = ifaceobj.get_attr_value_n('netmask', addrindex)
945 if netmask:
946 prefixlen = IPNetwork('%s' %addr +
947 '/%s' %netmask).prefixlen
948 addr = addr + '/%s' %prefixlen
949 outaddrlist.append(addr)
950 return outaddrlist
951
952 def _get_bridge_fdbs(self, bridgename, vlan):
953 fdbs = self._bridge_fdb_query_cache.get(bridgename)
954 if not fdbs:
955 fdbs = self.ipcmd.bridge_fdb_show_dev(bridgename)
956 if not fdbs:
957 return
958 self._bridge_fdb_query_cache[bridgename] = fdbs
959 return fdbs.get(vlan)
960
961 def _check_addresses_in_bridge(self, ifaceobj, hwaddress):
962 """ If the device is a bridge, make sure the addresses
963 are in the bridge """
964 if ifaceobj.link_kind & ifaceLinkKind.VLAN:
965 bridgename = ifaceobj.lowerifaces[0]
966 vlan = self._get_vlan_id(ifaceobj)
967 if self.ipcmd.bridge_is_vlan_aware(bridgename):
968 fdb_addrs = self._get_bridge_fdbs(bridgename, str(vlan))
969 if not fdb_addrs or hwaddress not in fdb_addrs:
970 return False
971 return True
972
973 def _query_sysctl(self, ifaceobj, ifaceobjcurr):
974 bridge_port = ifaceobj.link_privflags & ifaceLinkPrivFlags.BRIDGE_PORT
975 ipforward = ifaceobj.get_attr_value_first('ip-forward')
976 if ipforward:
977 if bridge_port:
978 ifaceobjcurr.status = ifaceStatus.ERROR
979 ifaceobjcurr.status_str = ('\'ip-forward\' not supported ' +
980 'for bridge port')
981 ifaceobjcurr.update_config_with_status('ip-forward', 1, None)
982 else:
983 running_ipforward = self.read_file_oneline(
984 '/proc/sys/net/ipv4/conf/%s/forwarding'
985 %ifaceobj.name)
986 running_ipforward = utils.get_boolean_from_string(running_ipforward)
987 config_ipforward = utils.get_boolean_from_string(ipforward)
988 ifaceobjcurr.update_config_with_status(
989 'ip-forward',
990 'on' if running_ipforward else 'off',
991 running_ipforward != config_ipforward
992 )
993
994 ip6forward = ifaceobj.get_attr_value_first('ip6-forward')
995 if ip6forward:
996 if bridge_port:
997 ifaceobjcurr.status = ifaceStatus.ERROR
998 ifaceobjcurr.status_str = ('\'ip6-forward\' not supported ' +
999 'for bridge port')
1000 ifaceobjcurr.update_config_with_status('ip6-forward', 1, None)
1001 else:
1002 running_ip6forward = self.read_file_oneline(
1003 '/proc/sys/net/ipv6/conf/%s/forwarding'
1004 %ifaceobj.name)
1005 running_ip6forward = utils.get_boolean_from_string(running_ip6forward)
1006 config_ip6forward = utils.get_boolean_from_string(ip6forward)
1007 ifaceobjcurr.update_config_with_status(
1008 'ip6-forward',
1009 'on' if running_ip6forward else 'off',
1010 running_ip6forward != config_ip6forward
1011 )
1012 mpls_enable = ifaceobj.get_attr_value_first('mpls-enable');
1013 if mpls_enable:
1014 running_mpls_enable = self.read_file_oneline(
1015 '/proc/sys/net/mpls/conf/%s/input'
1016 %ifaceobj.name)
1017 running_mpls_enable = utils.get_yesno_from_onezero(
1018 running_mpls_enable)
1019 ifaceobjcurr.update_config_with_status('mpls-enable',
1020 running_mpls_enable,
1021 mpls_enable != running_mpls_enable)
1022 return
1023
1024 def query_check_ipv6_addrgen(self, ifaceobj, ifaceobjcurr):
1025 ipv6_addrgen = ifaceobj.get_attr_value_first('ipv6-addrgen')
1026
1027 if not ipv6_addrgen:
1028 return
1029
1030 if ipv6_addrgen in utils._string_values:
1031 ifaceobjcurr.update_config_with_status(
1032 'ipv6-addrgen',
1033 ipv6_addrgen,
1034 utils.get_boolean_from_string(ipv6_addrgen) == self.ipcmd.get_ipv6_addrgen_mode(ifaceobj.name)
1035 )
1036 else:
1037 ifaceobjcurr.update_config_with_status('ipv6-addrgen', ipv6_addrgen, 1)
1038
1039 def _query_check(self, ifaceobj, ifaceobjcurr, ifaceobj_getfunc=None):
1040 runningaddrsdict = None
1041 if not self.ipcmd.link_exists(ifaceobj.name):
1042 self.logger.debug('iface %s not found' %ifaceobj.name)
1043 return
1044
1045 self.query_check_ipv6_addrgen(ifaceobj, ifaceobjcurr)
1046
1047 addr_method = ifaceobj.addr_method
1048 self.query_n_update_ifaceobjcurr_attr(ifaceobj, ifaceobjcurr,
1049 'mtu', self.ipcmd.link_get_mtu)
1050 hwaddress = self._get_hwaddress(ifaceobj)
1051 if hwaddress:
1052 rhwaddress = self.ipcmd.link_get_hwaddress(ifaceobj.name)
1053 if not rhwaddress or rhwaddress != hwaddress:
1054 ifaceobjcurr.update_config_with_status('hwaddress', rhwaddress,
1055 1)
1056 elif not self._check_addresses_in_bridge(ifaceobj, hwaddress):
1057 # XXX: hw address is not in bridge
1058 ifaceobjcurr.update_config_with_status('hwaddress', rhwaddress,
1059 1)
1060 ifaceobjcurr.status_str = 'bridge fdb error'
1061 else:
1062 ifaceobjcurr.update_config_with_status('hwaddress', rhwaddress,
1063 0)
1064 self.query_n_update_ifaceobjcurr_attr(ifaceobj, ifaceobjcurr,
1065 'alias', self.ipcmd.link_get_alias)
1066 self._query_sysctl(ifaceobj, ifaceobjcurr)
1067 # compare addresses
1068 if addr_method in ["dhcp", "ppp"]:
1069 return
1070 addrs = utils.get_normalized_ip_addr(ifaceobj.name,
1071 self._get_iface_addresses(ifaceobj))
1072 runningaddrsdict = self.ipcmd.get_running_addrs(ifaceobj)
1073 # if anycast address is configured on 'lo' and is in running config
1074 # add it to addrs so that query_check doesn't fail
1075 anycast_addr = utils.get_normalized_ip_addr(ifaceobj.name, ifaceobj.get_attr_value_first('clagd-vxlan-anycast-ip'))
1076 if anycast_addr:
1077 anycast_addr = anycast_addr+'/32'
1078 if runningaddrsdict and anycast_addr and runningaddrsdict.get(anycast_addr):
1079 addrs.append(anycast_addr)
1080
1081 # Set ifaceobjcurr method and family
1082 ifaceobjcurr.addr_method = ifaceobj.addr_method
1083 ifaceobjcurr.addr_family = ifaceobj.addr_family
1084 if not runningaddrsdict and not addrs:
1085 return
1086 runningaddrs = runningaddrsdict.keys() if runningaddrsdict else []
1087 # Add /32 netmask to configured address without netmask.
1088 # This may happen on interfaces where pointopoint is used.
1089 runningaddrs = [ addr if '/' in addr else addr + '/32' for addr in runningaddrs]
1090 if runningaddrs != addrs:
1091 runningaddrsset = set(runningaddrs) if runningaddrs else set([])
1092 addrsset = set(addrs) if addrs else set([])
1093 if (ifaceobj.flags & iface.HAS_SIBLINGS):
1094 if not addrsset:
1095 return
1096 # only check for addresses present in running config
1097 addrsdiff = addrsset.difference(runningaddrsset)
1098 for addr in addrs:
1099 if addr in addrsdiff:
1100 ifaceobjcurr.update_config_with_status('address',
1101 addr, 1)
1102 else:
1103 ifaceobjcurr.update_config_with_status('address',
1104 addr, 0)
1105 else:
1106 addrsdiff = addrsset.symmetric_difference(runningaddrsset)
1107 for addr in addrsset.union(runningaddrsset):
1108 if addr in addrsdiff:
1109 ifaceobjcurr.update_config_with_status('address',
1110 addr, 1)
1111 else:
1112 ifaceobjcurr.update_config_with_status('address',
1113 addr, 0)
1114 elif addrs:
1115 [ifaceobjcurr.update_config_with_status('address',
1116 addr, 0) for addr in addrs]
1117 #XXXX Check broadcast address, scope, etc
1118 return
1119
1120 def query_running_ipv6_addrgen(self, ifaceobjrunning):
1121 ipv6_addrgen = self.ipcmd.get_ipv6_addrgen_mode(ifaceobjrunning.name)
1122
1123 if ipv6_addrgen:
1124 ifaceobjrunning.update_config('ipv6-addrgen', 'off')
1125
1126 def _query_running(self, ifaceobjrunning, ifaceobj_getfunc=None):
1127 if not self.ipcmd.link_exists(ifaceobjrunning.name):
1128 self.logger.debug('iface %s not found' %ifaceobjrunning.name)
1129 return
1130
1131 self.query_running_ipv6_addrgen(ifaceobjrunning)
1132
1133 dhclientcmd = dhclient()
1134 if (dhclientcmd.is_running(ifaceobjrunning.name) or
1135 dhclientcmd.is_running6(ifaceobjrunning.name)):
1136 # If dhcp is configured on the interface, we skip it
1137 return
1138 isloopback = self.ipcmd.link_isloopback(ifaceobjrunning.name)
1139 if isloopback:
1140 default_addrs = ['127.0.0.1/8', '::1/128']
1141 ifaceobjrunning.addr_family.append('inet')
1142 ifaceobjrunning.addr_method = 'loopback'
1143 else:
1144 default_addrs = []
1145 runningaddrsdict = self.ipcmd.get_running_addrs(ifaceobjrunning)
1146 if runningaddrsdict:
1147 [ifaceobjrunning.update_config('address', addr)
1148 for addr, addrattrs in runningaddrsdict.items()
1149 if addr not in default_addrs]
1150 mtu = self.ipcmd.link_get_mtu(ifaceobjrunning.name)
1151 if (mtu and
1152 (ifaceobjrunning.name == 'lo' and mtu != '16436') or
1153 (ifaceobjrunning.name != 'lo' and
1154 mtu != self.get_mod_subattr('mtu', 'default'))):
1155 ifaceobjrunning.update_config('mtu', mtu)
1156 alias = self.ipcmd.link_get_alias(ifaceobjrunning.name)
1157 if alias:
1158 ifaceobjrunning.update_config('alias', alias)
1159
1160 ipforward = self.read_file_oneline(
1161 '/proc/sys/net/ipv4/conf/%s/forwarding'
1162 %ifaceobjrunning.name)
1163
1164
1165 _run_ops = {'up' : _up,
1166 'down' : _down,
1167 'query-checkcurr' : _query_check,
1168 'query-running' : _query_running }
1169
1170 def get_ops(self):
1171 """ returns list of ops supported by this module """
1172 return self._run_ops.keys()
1173
1174 def _init_command_handlers(self):
1175 if not self.ipcmd:
1176 self.ipcmd = LinkUtils()
1177
1178 def run(self, ifaceobj, operation, query_ifaceobj=None, ifaceobj_getfunc=None):
1179 """ run address configuration on the interface object passed as argument
1180
1181 Args:
1182 **ifaceobj** (object): iface object
1183
1184 **operation** (str): any of 'up', 'down', 'query-checkcurr',
1185 'query-running'
1186 Kwargs:
1187 query_ifaceobj (object): query check ifaceobject. This is only
1188 valid when op is 'query-checkcurr'. It is an object same as
1189 ifaceobj, but contains running attribute values and its config
1190 status. The modules can use it to return queried running state
1191 of interfaces. status is success if the running state is same
1192 as user required state in ifaceobj. error otherwise.
1193 """
1194 if ifaceobj.type == ifaceType.BRIDGE_VLAN:
1195 return
1196 op_handler = self._run_ops.get(operation)
1197 if not op_handler:
1198 return
1199 self._init_command_handlers()
1200 if operation == 'query-checkcurr':
1201 op_handler(self, ifaceobj, query_ifaceobj,
1202 ifaceobj_getfunc=ifaceobj_getfunc)
1203 else:
1204 op_handler(self, ifaceobj,
1205 ifaceobj_getfunc=ifaceobj_getfunc)