3 # Copyright 2014-2017 Cumulus Networks, Inc. All rights reserved.
4 # Author: Roopa Prabhu, roopa@cumulusnetworks.com
9 from ipaddr
import IPNetwork
, IPv4Network
, IPv6Network
, _BaseV6
12 from ifupdown2
.ifupdown
.iface
import *
13 from ifupdown2
.ifupdown
.utils
import utils
14 from ifupdown2
.ifupdown
.netlink
import netlink
16 from ifupdown2
.ifupdownaddons
.dhclient
import dhclient
17 from ifupdown2
.ifupdownaddons
.LinkUtils
import LinkUtils
18 from ifupdown2
.ifupdownaddons
.modulebase
import moduleBase
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
25 from ifupdown
.iface
import *
26 from ifupdown
.utils
import utils
27 from ifupdown
.netlink
import netlink
29 from ifupdownaddons
.dhclient
import dhclient
30 from ifupdownaddons
.LinkUtils
import LinkUtils
31 from ifupdownaddons
.modulebase
import moduleBase
33 import ifupdown
.statemanager
as statemanager
34 import ifupdown
.policymanager
as policymanager
35 import ifupdown
.ifupdownflags
as ifupdownflags
36 import ifupdown
.ifupdownconfig
as ifupdownconfig
39 class address(moduleBase
):
40 """ ifupdown2 addon module to configure address, mtu, hwaddress, alias
41 (description) on an interface """
43 _modinfo
= {'mhelp' : 'address configuration module for interfaces',
46 {'help' : 'ipv4 or ipv6 addresses',
47 'validvals' : ['<ipv4/prefixlen>', '<ipv6/prefixlen>'],
49 'example' : ['address 10.0.12.3/24',
50 'address 2000:1000:1000:1000:3::5/128']},
53 'example' : ['netmask 255.255.255.0'],
56 {'help': 'broadcast address',
57 'validvals' : ['<ipv4>', ],
58 'example' : ['broadcast 10.0.1.255']},
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']},
69 {'help': 'default gateway',
70 'validvals' : ['<ipv4>', '<ipv6>'],
72 'example' : ['gateway 255.255.255.0']},
74 { 'help': 'interface mtu',
75 'validrange' : ['552', '9216'],
76 'example' : ['mtu 1600'],
79 {'help' : 'hw address',
80 'validvals' : ['<mac>',],
81 'example': ['hwaddress 44:38:39:00:27:b8']},
83 { 'help': 'description/alias',
84 'example' : ['alias testnetwork']},
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'],
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']},
100 { 'help': 'ip forwarding flag',
101 'validvals': ['on', 'off', 'yes', 'no', '0', '1'],
103 'example' : ['ip-forward off']},
105 { 'help': 'ipv6 forwarding flag',
106 'validvals': ['on', 'off', 'yes', 'no', '0', '1'],
108 'example' : ['ip6-forward off']},
110 { 'help': 'mpls enable flag',
111 'validvals': ['yes', 'no'],
113 'example' : ['mpls-enable yes']},
115 'help': 'enable disable ipv6 link addrgenmode',
116 'validvals': ['on', 'off'],
125 def __init__(self
, *args
, **kargs
):
126 moduleBase
.__init
__(self
, *args
, **kargs
)
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'
141 if not self
.default_mtu
:
142 self
.default_mtu
= '1500'
144 self
.logger
.info('address: using default mtu %s' %self
.default_mtu
)
147 self
.logger
.info('address: using max mtu %s' %self
.max_mtu
)
149 self
.lower_iface_mtu_checked_list
= list()
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'
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'
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))
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
):
180 ifname
= ifaceobj
.name
182 vlan_ipforward_off
= None
184 for obj
in ifaceobj_getfunc(ifname
) or [ifaceobj
]:
186 vlan_addr
= obj
.get_attr_value('address')
188 if not vlan_ipforward_off
:
189 ip_forward_value
= obj
.get_attr_value_first('ip-forward')
191 if ip_forward_value
and not utils
.get_boolean_from_string(ip_forward_value
):
192 vlan_ipforward_off
= True
194 if vlan_addr
and vlan_ipforward_off
:
197 'configuring ip-forward off and ip address(es) (%s) is not compatible'
198 % (', '.join(vlan_addr
))
202 '%s: configuring ip-forward off and ip address(es) (%s) is not compatible'
203 % (ifname
, ', '.join(vlan_addr
))
208 def syntax_check_sysctls(self
, ifaceobj
):
210 bridge_port
= (ifaceobj
.link_privflags
& ifaceLinkPrivFlags
.BRIDGE_PORT
)
211 ipforward
= ifaceobj
.get_attr_value_first('ip-forward')
212 if bridge_port
and ipforward
:
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
:
219 self
.log_error('%s: \'ip6-forward\' is not supported for '
220 'bridge port' %ifaceobj
.name
)
223 def syntax_check_mtu(self
, ifaceobj
, ifaceobj_getfunc
):
224 mtu
= ifaceobj
.get_attr_value_first('mtu')
226 return self
._check
_mtu
_config
(ifaceobj
, mtu
, ifaceobj_getfunc
,
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
)
235 def _syntax_check_multiple_gateway(self
, family
, found
, addr
, type_obj
):
236 if type(IPNetwork(addr
)) == type_obj
:
238 raise Exception('%s: multiple gateways for %s family'
243 def syntax_check_multiple_gateway(self
, ifaceobj
):
247 gateways
= ifaceobj
.get_attr_value('gateway')
248 for addr
in gateways
if gateways
else []:
250 if self
._syntax
_check
_multiple
_gateway
('inet', inet
, addr
,
253 if self
._syntax
_check
_multiple
_gateway
('inet6', inet6
, addr
,
256 except Exception as e
:
257 self
.logger
.warning('%s: address: %s' % (ifaceobj
.name
, str(e
)))
261 def _address_valid(self
, addrs
):
264 if any(map(lambda a
: True if a
[:7] != '0.0.0.0'
269 def _get_hwaddress(self
, ifaceobj
):
270 return utils
.strip_hwaddress(ifaceobj
.get_attr_value_first('hwaddress'))
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
)
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
:
287 self
.write_file('/proc/sys/net/ipv4/conf/%s' % ifaceobj
.name
+
290 self
.write_file('/proc/sys/net/ipv4/conf/%s' % ifaceobj
.name
+
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
:
296 # check statemanager to delete the old entry if necessary
298 for old_obj
in statemanager
.statemanager_api
.get_ifaceobjs(ifaceobj
.name
) or []:
299 old_hwaddress
= old_obj
.get_attr_value_first("hwaddress")
300 if old_hwaddress
and self
.ipcmd
.mac_str_to_int(old_hwaddress
) != self
.ipcmd
.mac_str_to_int(hwaddress
):
301 self
.ipcmd
.bridge_fdb_del(bridgename
, old_hwaddress
, vlan
)
305 self
.ipcmd
.bridge_fdb_add(bridgename
, hwaddress
, vlan
)
307 self
.ipcmd
.bridge_fdb_del(bridgename
, hwaddress
, vlan
)
309 def _get_anycast_addr(self
, ifaceobjlist
):
310 for ifaceobj
in ifaceobjlist
:
311 anycast_addr
= ifaceobj
.get_attr_value_first('clagd-vxlan-anycast-ip')
313 anycast_addr
= anycast_addr
+'/32'
317 def _inet_address_convert_to_cidr(self
, ifaceobjlist
):
321 for ifaceobj
in ifaceobjlist
:
322 addrs
= ifaceobj
.get_attr_value('address')
326 if not self
.syntax_check_addr_allowed_on(ifaceobj
,
328 return (False, newaddrs
, newaddr_attrs
)
329 # If user address is not in CIDR notation, convert them to CIDR
330 for addr_index
in range(0, len(addrs
)):
331 addr
= addrs
[addr_index
]
334 newaddrs
.append(addr
)
336 netmask
= ifaceobj
.get_attr_value_n('netmask', addr_index
)
338 prefixlen
= IPNetwork('%s' %addr
+
339 '/%s' %netmask
).prefixlen
340 newaddr
= addr
+ '/%s' %prefixlen
342 # we are here because there is no slash (/xx) and no netmask
343 # just let IPNetwork handle the ipv4 or ipv6 address mask
344 prefixlen
= IPNetwork(addr
).prefixlen
345 newaddr
= addr
+ '/%s' %prefixlen
346 newaddrs
.append(newaddr
)
349 for a
in ['broadcast', 'pointopoint', 'scope',
350 'preferred-lifetime']:
351 aval
= ifaceobj
.get_attr_value_n(a
, addr_index
)
356 newaddr_attrs
[newaddr
]= attrs
357 return (True, newaddrs
, newaddr_attrs
)
359 def _inet_address_list_config(self
, ifaceobj
, newaddrs
, newaddr_attrs
):
360 for addr_index
in range(0, len(newaddrs
)):
363 self
.ipcmd
.addr_add(ifaceobj
.name
, newaddrs
[addr_index
],
364 newaddr_attrs
.get(newaddrs
[addr_index
],
365 {}).get('broadcast'),
366 newaddr_attrs
.get(newaddrs
[addr_index
],
367 {}).get('pointopoint'),
368 newaddr_attrs
.get(newaddrs
[addr_index
],
370 newaddr_attrs
.get(newaddrs
[addr_index
],
371 {}).get('preferred-lifetime'))
373 self
.ipcmd
.addr_add(ifaceobj
.name
, newaddrs
[addr_index
])
375 self
.log_error(str(e
), ifaceobj
)
377 def _inet_address_config(self
, ifaceobj
, ifaceobj_getfunc
=None,
378 force_reapply
=False):
379 squash_addr_config
= (True if \
380 ifupdownconfig
.config
.get('addr_config_squash', \
381 '0') == '1' else False)
383 if (squash_addr_config
and
384 not (ifaceobj
.flags
& ifaceobj
.YOUNGEST_SIBLING
)):
387 purge_addresses
= ifaceobj
.get_attr_value_first('address-purge')
388 if not purge_addresses
:
389 purge_addresses
= 'yes'
391 if squash_addr_config
and ifaceobj
.flags
& iface
.HAS_SIBLINGS
:
392 ifaceobjlist
= ifaceobj_getfunc(ifaceobj
.name
)
394 ifaceobjlist
= [ifaceobj
]
396 module_name
= self
.__class
__.__name
__
397 ifname
= ifaceobj
.name
399 (addr_supported
, newaddrs
, newaddr_attrs
) = self
._inet
_address
_convert
_to
_cidr
(ifaceobjlist
)
400 newaddrs
= utils
.get_ip_objs(module_name
, ifname
, newaddrs
)
402 if not addr_supported
:
404 if (not squash_addr_config
and (ifaceobj
.flags
& iface
.HAS_SIBLINGS
)):
405 # if youngest sibling and squash addr is not set
406 # print a warning that addresses will not be purged
407 if (ifaceobj
.flags
& iface
.YOUNGEST_SIBLING
):
408 self
.logger
.warn('%s: interface has multiple ' %ifaceobj
.name
+
409 'iface stanzas, skip purging existing addresses')
410 purge_addresses
= 'no'
412 if not ifupdownflags
.flags
.PERFMODE
and purge_addresses
== 'yes':
413 # if perfmode is not set and purge addresses is not set to 'no'
414 # lets purge addresses not in the config
415 runningaddrs
= self
.ipcmd
.get_running_addrs(ifaceobj
, details
=False)
417 # if anycast address is configured on 'lo' and is in running config
418 # add it to newaddrs so that ifreload doesn't wipe it out
419 anycast_addr
= utils
.get_normalized_ip_addr(ifaceobj
.name
, self
._get
_anycast
_addr
(ifaceobjlist
))
421 if runningaddrs
and anycast_addr
and anycast_addr
in runningaddrs
:
422 newaddrs
.append(anycast_addr
)
424 user_ip4
, user_ip6
, newaddrs
= self
.order_user_configured_addrs(newaddrs
)
426 if newaddrs
== runningaddrs
or self
.compare_running_ips_and_user_config(user_ip4
, user_ip6
, runningaddrs
):
428 self
._inet
_address
_list
_config
(ifaceobj
, newaddrs
, newaddr_attrs
)
431 # if primary address is not same, there is no need to keep any.
432 # reset all addresses
433 if newaddrs
and runningaddrs
and newaddrs
[0] != runningaddrs
[0]:
436 skip_addrs
= newaddrs
or []
437 for addr
in runningaddrs
or []:
438 if addr
in skip_addrs
:
440 self
.ipcmd
.addr_del(ifaceobj
.name
, addr
)
442 self
.log_warn(str(e
))
445 self
._inet
_address
_list
_config
(ifaceobj
, newaddrs
, newaddr_attrs
)
447 def compare_running_ips_and_user_config(self
, user_ip4
, user_ip6
, running_addrs
):
449 We need to compare the user config ips and the running ips.
450 ip4 ordering matters (primary etc) but ip6 order doesn't matter
452 this function replaces the strict comparison previously in place
453 if newaddrs == running_addrs ?
455 We will compare if the ip4 ordering is correct, then check if all
456 ip6 are present in the list (without checking the ordering)
458 if (user_ip4
or user_ip6
) and not running_addrs
:
460 elif running_addrs
and not user_ip4
and not user_ip6
:
462 elif not running_addrs
and not user_ip4
and not user_ip6
:
465 len_ip4
= len(user_ip4
)
466 len_running_addrs
= len(running_addrs
)
468 if len_ip4
> len_running_addrs
:
473 if user_ip4
[i
] != running_addrs
[i
]:
478 running_ip6
= running_addrs
[len_ip4
:]
480 running_ip6
= running_addrs
483 len_ip6
= len(user_ip6
)
485 for ip6
in running_ip6
:
486 if ip6
not in user_ip6
:
492 def order_user_configured_addrs(self
, user_config_addrs
):
496 for a
in user_config_addrs
:
497 if isinstance(a
, _BaseV6
):
502 return ip4
, ip6
, ip4
+ ip6
504 def _delete_gateway(self
, ifaceobj
, gateways
, vrf
, metric
):
505 for del_gw
in gateways
:
507 self
.ipcmd
.route_del_gateway(ifaceobj
.name
, del_gw
, vrf
, metric
)
508 except Exception as e
:
509 self
.logger
.debug('%s: %s' % (ifaceobj
.name
, str(e
)))
511 def _add_delete_gateway(self
, ifaceobj
, gateways
=[], prev_gw
=[]):
512 vrf
= ifaceobj
.get_attr_value_first('vrf')
513 metric
= ifaceobj
.get_attr_value_first('metric')
514 self
._delete
_gateway
(ifaceobj
, list(set(prev_gw
) - set(gateways
)),
516 for add_gw
in gateways
:
518 self
.ipcmd
.route_add_gateway(ifaceobj
.name
, add_gw
, vrf
, metric
, onlink
=self
.l3_intf_default_gateway_set_onlink
)
519 except Exception as e
:
520 self
.log_error('%s: %s' % (ifaceobj
.name
, str(e
)))
522 def _get_prev_gateway(self
, ifaceobj
, gateways
):
524 saved_ifaceobjs
= statemanager
.statemanager_api
.get_ifaceobjs(ifaceobj
.name
)
525 if not saved_ifaceobjs
:
527 prev_gateways
= saved_ifaceobjs
[0].get_attr_value('gateway')
528 if not prev_gateways
:
532 def _check_mtu_config(self
, ifaceobj
, mtu
, ifaceobj_getfunc
, syntaxcheck
=False):
534 if (ifaceobj
.link_kind
& ifaceLinkKind
.BRIDGE
):
536 self
.logger
.warn('%s: bridge inherits mtu from its ports. There is no need to assign mtu on a bridge' %ifaceobj
.name
)
539 self
.logger
.info('%s: bridge inherits mtu from its ports. There is no need to assign mtu on a bridge' %ifaceobj
.name
)
540 elif ifaceobj_getfunc
:
541 if ((ifaceobj
.link_privflags
& ifaceLinkPrivFlags
.BOND_SLAVE
) and
542 ifaceobj
.upperifaces
):
543 masterobj
= ifaceobj_getfunc(ifaceobj
.upperifaces
[0])
545 master_mtu
= masterobj
[0].get_attr_value_first('mtu')
546 if master_mtu
and master_mtu
!= mtu
:
548 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
))
551 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
))
552 elif ((ifaceobj
.link_kind
& ifaceLinkKind
.VLAN
) and
553 ifaceobj
.lowerifaces
):
554 lowerobj
= ifaceobj_getfunc(ifaceobj
.lowerifaces
[0])
557 lowerdev_mtu
= lowerobj
[0].get_attr_value_first('mtu')
559 lowerdev_mtu
= self
.ipcmd
.link_get_mtu_sysfs(lowerobj
[0].name
)
560 if lowerdev_mtu
and int(mtu
) > int(lowerdev_mtu
):
561 self
.logger
.warn('%s: vlan dev mtu %s is greater than lower realdev %s mtu %s'
562 %(ifaceobj
.name
, mtu
, lowerobj
[0].name
, lowerdev_mtu
))
564 elif (not lowerobj
[0].link_kind
and
565 not (lowerobj
[0].link_privflags
& ifaceLinkPrivFlags
.LOOPBACK
) and
566 not lowerdev_mtu
and self
.default_mtu
and
567 (int(mtu
) > int(self
.default_mtu
))):
568 # only check default mtu on lower device which is a physical interface
569 self
.logger
.warn('%s: vlan dev mtu %s is greater than lower realdev %s mtu %s'
570 %(ifaceobj
.name
, mtu
, lowerobj
[0].name
, self
.default_mtu
))
572 if self
.max_mtu
and mtu
> self
.max_mtu
:
573 self
.logger
.warn('%s: specified mtu %s is greater than max mtu %s'
574 %(ifaceobj
.name
, mtu
, self
.max_mtu
))
578 def _propagate_mtu_to_upper_devs(self
, ifaceobj
, mtu
, ifaceobj_getfunc
):
579 if (not ifaceobj
.upperifaces
or
580 (ifaceobj
.link_privflags
& ifaceLinkPrivFlags
.BOND_SLAVE
) or
581 (ifaceobj
.link_privflags
& ifaceLinkPrivFlags
.VRF_SLAVE
) or
582 (ifaceobj
.link_privflags
& ifaceLinkPrivFlags
.BRIDGE_PORT
)):
584 for u
in ifaceobj
.upperifaces
:
585 upperobjs
= ifaceobj_getfunc(u
)
587 not (upperobjs
[0].link_kind
& ifaceLinkKind
.VLAN
)):
589 # only adjust mtu for vlan devices on ifaceobj
590 umtu
= upperobjs
[0].get_attr_value_first('mtu')
592 running_mtu
= self
.ipcmd
.link_get_mtu(upperobjs
[0].name
)
593 if not running_mtu
or (running_mtu
!= mtu
):
594 self
.ipcmd
.link_set(u
, 'mtu', mtu
)
596 def _process_mtu_config(self
, ifaceobj
, ifaceobj_getfunc
, mtu
):
598 if not self
._check
_mtu
_config
(ifaceobj
, mtu
, ifaceobj_getfunc
):
600 cached_running_mtu
= self
.ipcmd
.link_get_mtu(ifaceobj
.name
)
601 running_mtu
= self
.ipcmd
.link_get_mtu_sysfs(ifaceobj
.name
)
602 if not running_mtu
or (running_mtu
and running_mtu
!= mtu
):
603 force
= cached_running_mtu
!= running_mtu
604 self
.ipcmd
.link_set(ifaceobj
.name
, 'mtu', mtu
, force
=force
)
605 if (not ifupdownflags
.flags
.ALL
and
606 not ifaceobj
.link_kind
and
607 ifupdownconfig
.config
.get('adjust_logical_dev_mtu', '1') != '0'):
608 # This is additional cost to us, so do it only when
609 # ifupdown2 is called on a particular interface and
610 # it is a physical interface
611 self
._propagate
_mtu
_to
_upper
_devs
(ifaceobj
, mtu
, ifaceobj_getfunc
)
614 if ifaceobj
.link_kind
:
615 # bonds, vxlan and custom devices (like dummy) need an explicit set of mtu.
616 # bridges don't need mtu set
617 if (ifaceobj
.link_kind
& ifaceLinkKind
.BOND
or
618 ifaceobj
.link_kind
& ifaceLinkKind
.VXLAN
or
619 ifaceobj
.link_kind
& ifaceLinkKind
.OTHER
621 running_mtu
= self
.ipcmd
.link_get_mtu(ifaceobj
.name
)
622 if (self
.default_mtu
and running_mtu
!= self
.default_mtu
):
623 self
.ipcmd
.link_set(ifaceobj
.name
, 'mtu', self
.default_mtu
)
625 if (ifupdownconfig
.config
.get('adjust_logical_dev_mtu', '1') != '0'
626 and ifaceobj
.lowerifaces
):
627 # set vlan interface mtu to lower device mtu
628 if (ifaceobj
.link_kind
& ifaceLinkKind
.VLAN
):
629 lower_iface
= ifaceobj
.lowerifaces
[0]
630 if lower_iface
not in self
.lower_iface_mtu_checked_list
:
631 lower_iface_mtu
= self
.ipcmd
.link_get_mtu_sysfs(lower_iface
)
632 self
.ipcmd
.cache_update([lower_iface
, 'mtu'], lower_iface_mtu
)
633 self
.lower_iface_mtu_checked_list
.append(lower_iface
)
635 lower_iface_mtu
= self
.ipcmd
.link_get_mtu(lower_iface
)
637 if lower_iface_mtu
!= self
.ipcmd
.link_get_mtu_sysfs(ifaceobj
.name
):
638 self
.ipcmd
.link_set_mtu(ifaceobj
.name
, lower_iface_mtu
)
640 elif (not (ifaceobj
.name
== 'lo') and not ifaceobj
.link_kind
and
641 not (ifaceobj
.link_privflags
& ifaceLinkPrivFlags
.BOND_SLAVE
) and
643 # logical devices like bridges and vlan devices rely on mtu
644 # from their lower devices. ie mtu travels from
645 # lower devices to upper devices. For bonds mtu travels from
646 # upper to lower devices. running mtu depends on upper and
647 # lower device mtu. With all this implicit mtu
648 # config by the kernel in play, we try to be cautious here
649 # on which devices we want to reset mtu to default.
650 # essentially only physical interfaces which are not bond slaves
651 running_mtu
= self
.ipcmd
.link_get_mtu(ifaceobj
.name
)
652 if running_mtu
!= self
.default_mtu
:
653 self
.ipcmd
.link_set(ifaceobj
.name
, 'mtu', self
.default_mtu
)
655 def _set_bridge_forwarding(self
, ifaceobj
):
656 """ set ip forwarding to 0 if bridge interface does not have a
658 ifname
= ifaceobj
.name
659 if not ifaceobj
.upperifaces
and not ifaceobj
.get_attr_value('address'):
660 if self
.sysctl_get_forwarding_value_from_proc(ifname
, "ipv4") == '1':
661 self
.sysctl_write_forwarding_value_to_proc(ifname
, "ipv4", 0)
662 if self
.sysctl_get_forwarding_value_from_proc(ifname
, "ipv6") == '1':
663 self
.sysctl_write_forwarding_value_to_proc(ifname
, "ipv6", 0)
665 if self
.sysctl_get_forwarding_value_from_proc(ifname
, "ipv4") == '0':
666 self
.sysctl_write_forwarding_value_to_proc(ifname
, "ipv4", 1)
667 if self
.sysctl_get_forwarding_value_from_proc(ifname
, "ipv6") == '0':
668 self
.sysctl_write_forwarding_value_to_proc(ifname
, "ipv6", 1)
670 def sysctl_get_forwarding_value_from_proc(self
, ifname
, family
):
671 return self
.read_file_oneline("/proc/sys/net/%s/conf/%s/forwarding" % (family
, ifname
))
673 def sysctl_write_forwarding_value_to_proc(self
, ifname
, family
, value
):
674 self
.write_file("/proc/sys/net/%s/conf/%s/forwarding" % (family
, ifname
), "%s\n" % value
)
676 def _sysctl_config(self
, ifaceobj
):
677 setting_default_value
= False
678 mpls_enable
= ifaceobj
.get_attr_value_first('mpls-enable');
680 setting_default_value
= True
681 mpls_enable
= self
.get_mod_subattr('mpls-enable', 'default')
682 mpls_enable
= utils
.boolean_support_binary(mpls_enable
)
683 # File read has been used for better performance
684 # instead of using sysctl command
685 if ifupdownflags
.flags
.PERFMODE
:
686 running_mpls_enable
= '0'
688 running_mpls_enable
= self
.read_file_oneline(
689 '/proc/sys/net/mpls/conf/%s/input'
693 if mpls_enable
!= running_mpls_enable
:
695 self
.sysctl_set('net.mpls.conf.%s.input'
696 %('/'.join(ifaceobj
.name
.split("."))),
698 except Exception as e
:
699 if not setting_default_value
:
700 ifaceobj
.status
= ifaceStatus
.ERROR
701 self
.logger
.error('%s: %s' %(ifaceobj
.name
, str(e
)))
703 if (ifaceobj
.link_kind
& ifaceLinkKind
.BRIDGE
):
704 self
._set
_bridge
_forwarding
(ifaceobj
)
706 if not self
.syntax_check_sysctls(ifaceobj
):
708 ipforward
= ifaceobj
.get_attr_value_first('ip-forward')
709 ip6forward
= ifaceobj
.get_attr_value_first('ip6-forward')
710 if ifupdownflags
.flags
.PERFMODE
:
712 self
.sysctl_set('net.ipv4.conf.%s.forwarding'
713 %('/'.join(ifaceobj
.name
.split("."))),
714 utils
.boolean_support_binary(ipforward
))
716 self
.sysctl_set('net.ipv6.conf.%s.forwarding'
717 %('/'.join(ifaceobj
.name
.split("."))),
718 utils
.boolean_support_binary(ip6forward
))
720 bridge_port
= ifaceobj
.link_privflags
& ifaceLinkPrivFlags
.BRIDGE_PORT
723 self
.log_error('%s: \'ip-forward\' is not supported for '
724 'bridge port' %ifaceobj
.name
)
726 self
.log_error('%s: \'ip6-forward\' is not supported for '
727 'bridge port' %ifaceobj
.name
)
730 setting_default_value
= False
732 setting_default_value
= True
733 ipforward
= self
.ipforward
736 ipforward
= utils
.boolean_support_binary(ipforward
)
737 # File read has been used for better performance
738 # instead of using sysctl command
739 running_ipforward
= self
.read_file_oneline(
740 '/proc/sys/net/ipv4/conf/%s/forwarding'
743 if ipforward
!= running_ipforward
:
746 self
.sysctl_set('net.ipv4.conf.%s.forwarding'
747 %('/'.join(ifaceobj
.name
.split("."))),
749 except Exception as e
:
750 if not setting_default_value
:
751 ifaceobj
.status
= ifaceStatus
.ERROR
752 self
.logger
.error('%s: %s' %(ifaceobj
.name
, str(e
)))
755 setting_default_value
= False
757 setting_default_value
= True
758 ip6forward
= self
.ip6forward
761 ip6forward
= utils
.boolean_support_binary(ip6forward
)
762 # File read has been used for better performance
763 # instead of using sysctl command
764 running_ip6forward
= self
.read_file_oneline(
765 '/proc/sys/net/ipv6/conf/%s/forwarding'
767 if ip6forward
!= running_ip6forward
:
769 self
.sysctl_set('net.ipv6.conf.%s.forwarding'
770 %('/'.join(ifaceobj
.name
.split("."))),
772 except Exception as e
:
773 # There is chance of ipv6 being removed because of,
774 # for example, setting mtu < 1280
775 # In such cases, log error only if user has configured
777 if not setting_default_value
:
778 ifaceobj
.status
= ifaceStatus
.ERROR
779 self
.logger
.error('%s: %s' %(ifaceobj
.name
, str(e
)))
781 def process_mtu(self
, ifaceobj
, ifaceobj_getfunc
):
782 mtu
= ifaceobj
.get_attr_value_first('mtu')
785 default_iface_mtu
= self
.ifaces_defaults
.get(ifaceobj
.name
, {}).get('mtu')
787 if default_iface_mtu
:
789 mtu
= default_iface_mtu
790 int(default_iface_mtu
)
791 except Exception as e
:
792 self
.logger
.warning('%s: MTU value from policy file: %s' % (ifaceobj
.name
, str(e
)))
795 self
._process
_mtu
_config
(ifaceobj
, ifaceobj_getfunc
, mtu
)
797 def up_ipv6_addrgen(self
, ifaceobj
):
798 user_configured_ipv6_addrgen
= ifaceobj
.get_attr_value_first('ipv6-addrgen')
800 if not user_configured_ipv6_addrgen
and ifupdownflags
.flags
.PERFMODE
:
801 # no need to go further during perfmode (boot)
804 if not user_configured_ipv6_addrgen
and ifaceobj
.addr_method
== 'dhcp':
807 if not user_configured_ipv6_addrgen
:
808 # if user didn't configure ipv6-addrgen, should we reset to default?
809 user_configured_ipv6_addrgen
= self
.get_attr_default_value('ipv6-addrgen')
818 }.get(user_configured_ipv6_addrgen
.lower(), None)
820 if ipv6_addrgen_nl
is not None:
821 self
.ipcmd
.ipv6_addrgen(ifaceobj
.name
, ipv6_addrgen_nl
, link_created
=True)
822 # link_create=False will flush the addr cache of that intf
824 self
.logger
.warning('%s: invalid value "%s" for attribute ipv6-addrgen' % (ifaceobj
.name
, user_configured_ipv6_addrgen
))
826 def _up(self
, ifaceobj
, ifaceobj_getfunc
=None):
827 if not self
.ipcmd
.link_exists(ifaceobj
.name
):
830 if not self
.syntax_check_enable_l3_iface_forwardings(ifaceobj
, ifaceobj_getfunc
):
833 alias
= ifaceobj
.get_attr_value_first('alias')
834 current_alias
= self
.ipcmd
.link_get_alias(ifaceobj
.name
)
835 if alias
and alias
!= current_alias
:
836 self
.ipcmd
.link_set_alias(ifaceobj
.name
, alias
)
837 elif not alias
and current_alias
:
838 self
.ipcmd
.link_set_alias(ifaceobj
.name
, '')
840 self
._sysctl
_config
(ifaceobj
)
842 addr_method
= ifaceobj
.addr_method
843 force_reapply
= False
845 # release any stale dhcp addresses if present
846 if (addr_method
not in ["dhcp", "ppp"] and not ifupdownflags
.flags
.PERFMODE
and
847 not (ifaceobj
.flags
& iface
.HAS_SIBLINGS
)):
848 # if not running in perf mode and ifaceobj does not have
849 # any sibling iface objects, kill any stale dhclient
851 dhclientcmd
= dhclient()
852 if dhclientcmd
.is_running(ifaceobj
.name
):
853 # release any dhcp leases
854 dhclientcmd
.release(ifaceobj
.name
)
856 elif dhclientcmd
.is_running6(ifaceobj
.name
):
857 dhclientcmd
.release6(ifaceobj
.name
)
862 self
.ipcmd
.batch_start()
863 self
.up_ipv6_addrgen(ifaceobj
)
865 if addr_method
not in ["dhcp", "ppp"]:
866 self
._inet
_address
_config
(ifaceobj
, ifaceobj_getfunc
,
869 # remove old addresses added by ifupdown2
870 # (if intf was moved from static config to dhcp)
871 for old_ifaceobj
in statemanager
.statemanager_api
.get_ifaceobjs(ifaceobj
.name
) or []:
872 for addr
in old_ifaceobj
.get_attr_value("address") or []:
873 self
.ipcmd
.addr_del(ifaceobj
.name
, addr
)
875 self
.process_mtu(ifaceobj
, ifaceobj_getfunc
)
878 self
.ipcmd
.batch_commit()
879 except Exception as e
:
880 self
.log_error('%s: %s' % (ifaceobj
.name
, str(e
)), ifaceobj
, raise_error
=False)
882 self
.up_hwaddress(ifaceobj
)
884 gateways
= ifaceobj
.get_attr_value('gateway')
887 prev_gw
= self
._get
_prev
_gateway
(ifaceobj
, gateways
)
888 self
._add
_delete
_gateway
(ifaceobj
, gateways
, prev_gw
)
890 def up_hwaddress(self
, ifaceobj
):
892 hwaddress
= self
._get
_hwaddress
(ifaceobj
)
895 if not ifupdownflags
.flags
.PERFMODE
: # system is clean
896 running_hwaddress
= self
.ipcmd
.link_get_hwaddress(ifaceobj
.name
)
898 running_hwaddress
= None
900 if self
.ipcmd
.mac_str_to_int(running_hwaddress
) != self
.ipcmd
.mac_str_to_int(hwaddress
):
902 netlink
.link_set_updown(ifaceobj
.name
, "down")
903 if ifaceobj
.link_kind
& ifaceLinkKind
.BOND
:
904 # if bond, down all the slaves
905 if ifaceobj
.lowerifaces
:
906 for l
in ifaceobj
.lowerifaces
:
907 netlink
.link_set_updown(l
, "down")
910 self
.ipcmd
.link_set_hwaddress(ifaceobj
.name
, hwaddress
, force
=True)
912 netlink
.link_set_updown(ifaceobj
.name
, "up")
914 for l
in ifaceobj
.lowerifaces
:
915 netlink
.link_set_updown(l
, "up")
917 # Handle special things on a bridge
918 self
._process
_bridge
(ifaceobj
, True)
920 self
.log_error('%s: %s' % (ifaceobj
.name
, str(e
)), ifaceobj
)
922 def _down(self
, ifaceobj
, ifaceobj_getfunc
=None):
924 if not self
.ipcmd
.link_exists(ifaceobj
.name
):
926 addr_method
= ifaceobj
.addr_method
927 if addr_method
not in ["dhcp", "ppp"]:
928 if ifaceobj
.get_attr_value_first('address-purge')=='no':
929 addrlist
= ifaceobj
.get_attr_value('address')
930 for addr
in addrlist
:
931 self
.ipcmd
.addr_del(ifaceobj
.name
, addr
)
932 #self.ipcmd.addr_del(ifaceobj.name, ifaceobj.get_attr_value('address')[0])
933 elif not ifaceobj
.link_kind
:
934 # for logical interfaces we don't need to remove the ip addresses
935 # kernel will do it for us on 'ip link del'
936 self
.ipcmd
.del_addr_all(ifaceobj
.name
)
937 gateways
= ifaceobj
.get_attr_value('gateway')
939 self
._delete
_gateway
(ifaceobj
, gateways
,
940 ifaceobj
.get_attr_value_first('vrf'),
941 ifaceobj
.get_attr_value_first('metric'))
942 mtu
= ifaceobj
.get_attr_value_first('mtu')
943 if (not ifaceobj
.link_kind
and mtu
and
944 self
.default_mtu
and (mtu
!= self
.default_mtu
)):
945 self
.ipcmd
.link_set(ifaceobj
.name
, 'mtu', self
.default_mtu
)
946 alias
= ifaceobj
.get_attr_value_first('alias')
948 self
.write_file('/sys/class/net/%s/ifalias' % ifaceobj
.name
, '\n')
949 # XXX hwaddress reset cannot happen because we dont know last
952 # Handle special things on a bridge
953 self
._process
_bridge
(ifaceobj
, False)
955 self
.logger
.debug('%s : %s' %(ifaceobj
.name
, str(e
)))
958 def _get_iface_addresses(self
, ifaceobj
):
959 addrlist
= ifaceobj
.get_attr_value('address')
962 if not addrlist
: return None
963 for addrindex
in range(0, len(addrlist
)):
964 addr
= addrlist
[addrindex
]
965 netmask
= ifaceobj
.get_attr_value_n('netmask', addrindex
)
967 prefixlen
= IPNetwork('%s' %addr
+
968 '/%s' %netmask
).prefixlen
969 addr
= addr
+ '/%s' %prefixlen
970 outaddrlist
.append(addr
)
973 def _get_bridge_fdbs(self
, bridgename
, vlan
):
974 fdbs
= self
._bridge
_fdb
_query
_cache
.get(bridgename
)
976 fdbs
= self
.ipcmd
.bridge_fdb_show_dev(bridgename
)
979 self
._bridge
_fdb
_query
_cache
[bridgename
] = fdbs
980 return fdbs
.get(vlan
)
982 def _check_addresses_in_bridge(self
, ifaceobj
, hwaddress
):
983 """ If the device is a bridge, make sure the addresses
984 are in the bridge """
985 if ifaceobj
.link_kind
& ifaceLinkKind
.VLAN
:
986 bridgename
= ifaceobj
.lowerifaces
[0]
987 vlan
= self
._get
_vlan
_id
(ifaceobj
)
988 if self
.ipcmd
.bridge_is_vlan_aware(bridgename
):
989 fdb_addrs
= [self
.ipcmd
.mac_str_to_int(fdb_addr
) for fdb_addr
in self
._get
_bridge
_fdbs
(bridgename
, str(vlan
))]
992 hwaddress_int
= self
.ipcmd
.mac_str_to_int(hwaddress
)
993 if hwaddress_int
not in fdb_addrs
:
997 def _query_sysctl(self
, ifaceobj
, ifaceobjcurr
):
998 bridge_port
= ifaceobj
.link_privflags
& ifaceLinkPrivFlags
.BRIDGE_PORT
999 ipforward
= ifaceobj
.get_attr_value_first('ip-forward')
1002 ifaceobjcurr
.status
= ifaceStatus
.ERROR
1003 ifaceobjcurr
.status_str
= ('\'ip-forward\' not supported ' +
1005 ifaceobjcurr
.update_config_with_status('ip-forward', 1, None)
1007 running_ipforward
= self
.read_file_oneline(
1008 '/proc/sys/net/ipv4/conf/%s/forwarding'
1010 running_ipforward
= utils
.get_boolean_from_string(running_ipforward
)
1011 config_ipforward
= utils
.get_boolean_from_string(ipforward
)
1012 ifaceobjcurr
.update_config_with_status(
1014 'on' if running_ipforward
else 'off',
1015 running_ipforward
!= config_ipforward
1018 ip6forward
= ifaceobj
.get_attr_value_first('ip6-forward')
1021 ifaceobjcurr
.status
= ifaceStatus
.ERROR
1022 ifaceobjcurr
.status_str
= ('\'ip6-forward\' not supported ' +
1024 ifaceobjcurr
.update_config_with_status('ip6-forward', 1, None)
1026 running_ip6forward
= self
.read_file_oneline(
1027 '/proc/sys/net/ipv6/conf/%s/forwarding'
1029 running_ip6forward
= utils
.get_boolean_from_string(running_ip6forward
)
1030 config_ip6forward
= utils
.get_boolean_from_string(ip6forward
)
1031 ifaceobjcurr
.update_config_with_status(
1033 'on' if running_ip6forward
else 'off',
1034 running_ip6forward
!= config_ip6forward
1036 mpls_enable
= ifaceobj
.get_attr_value_first('mpls-enable');
1038 running_mpls_enable
= self
.read_file_oneline(
1039 '/proc/sys/net/mpls/conf/%s/input'
1041 running_mpls_enable
= utils
.get_yesno_from_onezero(
1042 running_mpls_enable
)
1043 ifaceobjcurr
.update_config_with_status('mpls-enable',
1044 running_mpls_enable
,
1045 mpls_enable
!= running_mpls_enable
)
1048 def query_check_ipv6_addrgen(self
, ifaceobj
, ifaceobjcurr
):
1049 ipv6_addrgen
= ifaceobj
.get_attr_value_first('ipv6-addrgen')
1051 if not ipv6_addrgen
:
1054 if ipv6_addrgen
in utils
._string
_values
:
1055 ifaceobjcurr
.update_config_with_status(
1058 utils
.get_boolean_from_string(ipv6_addrgen
) == self
.ipcmd
.get_ipv6_addrgen_mode(ifaceobj
.name
)
1061 ifaceobjcurr
.update_config_with_status('ipv6-addrgen', ipv6_addrgen
, 1)
1063 def _query_check(self
, ifaceobj
, ifaceobjcurr
, ifaceobj_getfunc
=None):
1064 runningaddrsdict
= None
1065 if not self
.ipcmd
.link_exists(ifaceobj
.name
):
1066 self
.logger
.debug('iface %s not found' %ifaceobj
.name
)
1069 self
.query_check_ipv6_addrgen(ifaceobj
, ifaceobjcurr
)
1071 addr_method
= ifaceobj
.addr_method
1072 self
.query_n_update_ifaceobjcurr_attr(ifaceobj
, ifaceobjcurr
,
1073 'mtu', self
.ipcmd
.link_get_mtu
)
1074 hwaddress
= self
._get
_hwaddress
(ifaceobj
)
1076 rhwaddress
= self
.ipcmd
.link_get_hwaddress(ifaceobj
.name
)
1077 if not rhwaddress
or self
.ipcmd
.mac_str_to_int(rhwaddress
) != self
.ipcmd
.mac_str_to_int(hwaddress
):
1078 ifaceobjcurr
.update_config_with_status('hwaddress', rhwaddress
,
1080 elif not self
._check
_addresses
_in
_bridge
(ifaceobj
, hwaddress
):
1081 # XXX: hw address is not in bridge
1082 ifaceobjcurr
.update_config_with_status('hwaddress', rhwaddress
,
1084 ifaceobjcurr
.status_str
= 'bridge fdb error'
1086 ifaceobjcurr
.update_config_with_status('hwaddress', rhwaddress
,
1088 self
.query_n_update_ifaceobjcurr_attr(ifaceobj
, ifaceobjcurr
,
1089 'alias', self
.ipcmd
.link_get_alias
)
1090 self
._query
_sysctl
(ifaceobj
, ifaceobjcurr
)
1092 if addr_method
in ["dhcp", "ppp"]:
1094 addrs
= utils
.get_normalized_ip_addr(ifaceobj
.name
,
1095 self
._get
_iface
_addresses
(ifaceobj
))
1096 runningaddrsdict
= self
.ipcmd
.get_running_addrs(ifaceobj
)
1097 # if anycast address is configured on 'lo' and is in running config
1098 # add it to addrs so that query_check doesn't fail
1099 anycast_addr
= utils
.get_normalized_ip_addr(ifaceobj
.name
, ifaceobj
.get_attr_value_first('clagd-vxlan-anycast-ip'))
1101 anycast_addr
= anycast_addr
+'/32'
1102 if runningaddrsdict
and anycast_addr
and runningaddrsdict
.get(anycast_addr
):
1103 addrs
.append(anycast_addr
)
1105 # Set ifaceobjcurr method and family
1106 ifaceobjcurr
.addr_method
= ifaceobj
.addr_method
1107 ifaceobjcurr
.addr_family
= ifaceobj
.addr_family
1108 if not runningaddrsdict
and not addrs
:
1110 runningaddrs
= runningaddrsdict
.keys() if runningaddrsdict
else []
1111 # Add /32 netmask to configured address without netmask.
1112 # This may happen on interfaces where pointopoint is used.
1113 runningaddrs
= [ addr
if '/' in addr
else addr
+ '/32' for addr
in runningaddrs
]
1114 if runningaddrs
!= addrs
:
1115 runningaddrsset
= set(runningaddrs
) if runningaddrs
else set([])
1116 addrsset
= set(addrs
) if addrs
else set([])
1117 if (ifaceobj
.flags
& iface
.HAS_SIBLINGS
):
1120 # only check for addresses present in running config
1121 addrsdiff
= addrsset
.difference(runningaddrsset
)
1123 if addr
in addrsdiff
:
1124 ifaceobjcurr
.update_config_with_status('address',
1127 ifaceobjcurr
.update_config_with_status('address',
1130 addrsdiff
= addrsset
.symmetric_difference(runningaddrsset
)
1131 for addr
in addrsset
.union(runningaddrsset
):
1132 if addr
in addrsdiff
:
1133 ifaceobjcurr
.update_config_with_status('address',
1136 ifaceobjcurr
.update_config_with_status('address',
1139 [ifaceobjcurr
.update_config_with_status('address',
1140 addr
, 0) for addr
in addrs
]
1141 #XXXX Check broadcast address, scope, etc
1144 def query_running_ipv6_addrgen(self
, ifaceobjrunning
):
1145 ipv6_addrgen
= self
.ipcmd
.get_ipv6_addrgen_mode(ifaceobjrunning
.name
)
1148 ifaceobjrunning
.update_config('ipv6-addrgen', 'off')
1150 def _query_running(self
, ifaceobjrunning
, ifaceobj_getfunc
=None):
1151 if not self
.ipcmd
.link_exists(ifaceobjrunning
.name
):
1152 self
.logger
.debug('iface %s not found' %ifaceobjrunning
.name
)
1155 self
.query_running_ipv6_addrgen(ifaceobjrunning
)
1157 dhclientcmd
= dhclient()
1158 if (dhclientcmd
.is_running(ifaceobjrunning
.name
) or
1159 dhclientcmd
.is_running6(ifaceobjrunning
.name
)):
1160 # If dhcp is configured on the interface, we skip it
1162 isloopback
= self
.ipcmd
.link_isloopback(ifaceobjrunning
.name
)
1164 default_addrs
= ['127.0.0.1/8', '::1/128']
1165 ifaceobjrunning
.addr_family
.append('inet')
1166 ifaceobjrunning
.addr_method
= 'loopback'
1169 runningaddrsdict
= self
.ipcmd
.get_running_addrs(ifaceobjrunning
)
1170 if runningaddrsdict
:
1171 [ifaceobjrunning
.update_config('address', addr
)
1172 for addr
, addrattrs
in runningaddrsdict
.items()
1173 if addr
not in default_addrs
]
1174 mtu
= self
.ipcmd
.link_get_mtu(ifaceobjrunning
.name
)
1176 (ifaceobjrunning
.name
== 'lo' and mtu
!= '16436') or
1177 (ifaceobjrunning
.name
!= 'lo' and
1178 mtu
!= self
.get_mod_subattr('mtu', 'default'))):
1179 ifaceobjrunning
.update_config('mtu', mtu
)
1180 alias
= self
.ipcmd
.link_get_alias(ifaceobjrunning
.name
)
1182 ifaceobjrunning
.update_config('alias', alias
)
1184 ipforward
= self
.read_file_oneline(
1185 '/proc/sys/net/ipv4/conf/%s/forwarding'
1186 %ifaceobjrunning
.name
)
1189 _run_ops
= {'up' : _up
,
1191 'query-checkcurr' : _query_check
,
1192 'query-running' : _query_running
}
1195 """ returns list of ops supported by this module """
1196 return self
._run
_ops
.keys()
1198 def _init_command_handlers(self
):
1200 self
.ipcmd
= LinkUtils()
1202 def run(self
, ifaceobj
, operation
, query_ifaceobj
=None, ifaceobj_getfunc
=None):
1203 """ run address configuration on the interface object passed as argument
1206 **ifaceobj** (object): iface object
1208 **operation** (str): any of 'up', 'down', 'query-checkcurr',
1211 query_ifaceobj (object): query check ifaceobject. This is only
1212 valid when op is 'query-checkcurr'. It is an object same as
1213 ifaceobj, but contains running attribute values and its config
1214 status. The modules can use it to return queried running state
1215 of interfaces. status is success if the running state is same
1216 as user required state in ifaceobj. error otherwise.
1218 if ifaceobj
.type == ifaceType
.BRIDGE_VLAN
:
1220 op_handler
= self
._run
_ops
.get(operation
)
1223 self
._init
_command
_handlers
()
1224 if operation
== 'query-checkcurr':
1225 op_handler(self
, ifaceobj
, query_ifaceobj
,
1226 ifaceobj_getfunc
=ifaceobj_getfunc
)
1228 op_handler(self
, ifaceobj
,
1229 ifaceobj_getfunc
=ifaceobj_getfunc
)