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