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 self
.ipcmd
.bridge_fdb_add(bridgename
, hwaddress
, vlan
)
298 self
.ipcmd
.bridge_fdb_del(bridgename
, hwaddress
, vlan
)
300 def _get_anycast_addr(self
, ifaceobjlist
):
301 for ifaceobj
in ifaceobjlist
:
302 anycast_addr
= ifaceobj
.get_attr_value_first('clagd-vxlan-anycast-ip')
304 anycast_addr
= anycast_addr
+'/32'
308 def _inet_address_convert_to_cidr(self
, ifaceobjlist
):
312 for ifaceobj
in ifaceobjlist
:
313 addrs
= ifaceobj
.get_attr_value('address')
317 if not self
.syntax_check_addr_allowed_on(ifaceobj
,
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
]
325 newaddrs
.append(addr
)
327 netmask
= ifaceobj
.get_attr_value_n('netmask', addr_index
)
329 prefixlen
= IPNetwork('%s' %addr
+
330 '/%s' %netmask
).prefixlen
331 newaddr
= addr
+ '/%s' %prefixlen
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
)
340 for a
in ['broadcast', 'pointopoint', 'scope',
341 'preferred-lifetime']:
342 aval
= ifaceobj
.get_attr_value_n(a
, addr_index
)
347 newaddr_attrs
[newaddr
]= attrs
348 return (True, newaddrs
, newaddr_attrs
)
350 def _inet_address_list_config(self
, ifaceobj
, newaddrs
, newaddr_attrs
):
351 for addr_index
in range(0, len(newaddrs
)):
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
],
361 newaddr_attrs
.get(newaddrs
[addr_index
],
362 {}).get('preferred-lifetime'))
364 self
.ipcmd
.addr_add(ifaceobj
.name
, newaddrs
[addr_index
])
366 self
.log_error(str(e
), ifaceobj
)
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)
374 if (squash_addr_config
and
375 not (ifaceobj
.flags
& ifaceobj
.YOUNGEST_SIBLING
)):
378 purge_addresses
= ifaceobj
.get_attr_value_first('address-purge')
379 if not purge_addresses
:
380 purge_addresses
= 'yes'
382 if squash_addr_config
and ifaceobj
.flags
& iface
.HAS_SIBLINGS
:
383 ifaceobjlist
= ifaceobj_getfunc(ifaceobj
.name
)
385 ifaceobjlist
= [ifaceobj
]
387 module_name
= self
.__class
__.__name
__
388 ifname
= ifaceobj
.name
390 (addr_supported
, newaddrs
, newaddr_attrs
) = self
._inet
_address
_convert
_to
_cidr
(ifaceobjlist
)
391 newaddrs
= utils
.get_ip_objs(module_name
, ifname
, newaddrs
)
393 if not addr_supported
:
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'
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)
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
))
412 if runningaddrs
and anycast_addr
and anycast_addr
in runningaddrs
:
413 newaddrs
.append(anycast_addr
)
415 user_ip4
, user_ip6
, newaddrs
= self
.order_user_configured_addrs(newaddrs
)
417 if newaddrs
== runningaddrs
or self
.compare_running_ips_and_user_config(user_ip4
, user_ip6
, runningaddrs
):
419 self
._inet
_address
_list
_config
(ifaceobj
, newaddrs
, newaddr_attrs
)
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]:
427 skip_addrs
= newaddrs
or []
428 for addr
in runningaddrs
or []:
429 if addr
in skip_addrs
:
431 self
.ipcmd
.addr_del(ifaceobj
.name
, addr
)
433 self
.log_warn(str(e
))
436 self
._inet
_address
_list
_config
(ifaceobj
, newaddrs
, newaddr_attrs
)
438 def compare_running_ips_and_user_config(self
, user_ip4
, user_ip6
, running_addrs
):
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
443 this function replaces the strict comparison previously in place
444 if newaddrs == running_addrs ?
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)
449 if (user_ip4
or user_ip6
) and not running_addrs
:
451 elif running_addrs
and not user_ip4
and not user_ip6
:
453 elif not running_addrs
and not user_ip4
and not user_ip6
:
456 len_ip4
= len(user_ip4
)
457 len_running_addrs
= len(running_addrs
)
459 if len_ip4
> len_running_addrs
:
464 if user_ip4
[i
] != running_addrs
[i
]:
469 running_ip6
= running_addrs
[len_ip4
:]
471 running_ip6
= running_addrs
474 len_ip6
= len(user_ip6
)
476 for ip6
in running_ip6
:
477 if ip6
not in user_ip6
:
483 def order_user_configured_addrs(self
, user_config_addrs
):
487 for a
in user_config_addrs
:
488 if isinstance(a
, _BaseV6
):
493 return ip4
, ip6
, ip4
+ ip6
495 def _delete_gateway(self
, ifaceobj
, gateways
, vrf
, metric
):
496 for del_gw
in gateways
:
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
)))
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
)),
507 for add_gw
in gateways
:
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
)))
513 def _get_prev_gateway(self
, ifaceobj
, gateways
):
515 saved_ifaceobjs
= statemanager
.statemanager_api
.get_ifaceobjs(ifaceobj
.name
)
516 if not saved_ifaceobjs
:
518 prev_gateways
= saved_ifaceobjs
[0].get_attr_value('gateway')
519 if not prev_gateways
:
523 def _check_mtu_config(self
, ifaceobj
, mtu
, ifaceobj_getfunc
, syntaxcheck
=False):
525 if (ifaceobj
.link_kind
& ifaceLinkKind
.BRIDGE
):
527 self
.logger
.warn('%s: bridge inherits mtu from its ports. There is no need to assign mtu on a bridge' %ifaceobj
.name
)
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])
536 master_mtu
= masterobj
[0].get_attr_value_first('mtu')
537 if master_mtu
and master_mtu
!= mtu
:
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
))
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])
548 lowerdev_mtu
= lowerobj
[0].get_attr_value_first('mtu')
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
))
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
))
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
))
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
)):
575 for u
in ifaceobj
.upperifaces
:
576 upperobjs
= ifaceobj_getfunc(u
)
578 not (upperobjs
[0].link_kind
& ifaceLinkKind
.VLAN
)):
580 # only adjust mtu for vlan devices on ifaceobj
581 umtu
= upperobjs
[0].get_attr_value_first('mtu')
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
)
587 def _process_mtu_config(self
, ifaceobj
, ifaceobj_getfunc
, mtu
):
589 if not self
._check
_mtu
_config
(ifaceobj
, mtu
, ifaceobj_getfunc
):
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
)
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
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
)
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
)
626 lower_iface_mtu
= self
.ipcmd
.link_get_mtu(lower_iface
)
628 if lower_iface_mtu
!= self
.ipcmd
.link_get_mtu_sysfs(ifaceobj
.name
):
629 self
.ipcmd
.link_set_mtu(ifaceobj
.name
, lower_iface_mtu
)
631 elif (not (ifaceobj
.name
== 'lo') and not ifaceobj
.link_kind
and
632 not (ifaceobj
.link_privflags
& ifaceLinkPrivFlags
.BOND_SLAVE
) and
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
)
646 def _set_bridge_forwarding(self
, ifaceobj
):
647 """ set ip forwarding to 0 if bridge interface does not have a
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)
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)
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
))
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
)
667 def _sysctl_config(self
, ifaceobj
):
668 setting_default_value
= False
669 mpls_enable
= ifaceobj
.get_attr_value_first('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'
679 running_mpls_enable
= self
.read_file_oneline(
680 '/proc/sys/net/mpls/conf/%s/input'
684 if mpls_enable
!= running_mpls_enable
:
686 self
.sysctl_set('net.mpls.conf.%s.input'
687 %('/'.join(ifaceobj
.name
.split("."))),
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
)))
694 if (ifaceobj
.link_kind
& ifaceLinkKind
.BRIDGE
):
695 self
._set
_bridge
_forwarding
(ifaceobj
)
697 if not self
.syntax_check_sysctls(ifaceobj
):
699 ipforward
= ifaceobj
.get_attr_value_first('ip-forward')
700 ip6forward
= ifaceobj
.get_attr_value_first('ip6-forward')
701 if ifupdownflags
.flags
.PERFMODE
:
703 self
.sysctl_set('net.ipv4.conf.%s.forwarding'
704 %('/'.join(ifaceobj
.name
.split("."))),
705 utils
.boolean_support_binary(ipforward
))
707 self
.sysctl_set('net.ipv6.conf.%s.forwarding'
708 %('/'.join(ifaceobj
.name
.split("."))),
709 utils
.boolean_support_binary(ip6forward
))
711 bridge_port
= ifaceobj
.link_privflags
& ifaceLinkPrivFlags
.BRIDGE_PORT
714 self
.log_error('%s: \'ip-forward\' is not supported for '
715 'bridge port' %ifaceobj
.name
)
717 self
.log_error('%s: \'ip6-forward\' is not supported for '
718 'bridge port' %ifaceobj
.name
)
721 setting_default_value
= False
723 setting_default_value
= True
724 ipforward
= self
.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'
734 if ipforward
!= running_ipforward
:
737 self
.sysctl_set('net.ipv4.conf.%s.forwarding'
738 %('/'.join(ifaceobj
.name
.split("."))),
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
)))
746 setting_default_value
= False
748 setting_default_value
= True
749 ip6forward
= self
.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'
758 if ip6forward
!= running_ip6forward
:
760 self
.sysctl_set('net.ipv6.conf.%s.forwarding'
761 %('/'.join(ifaceobj
.name
.split("."))),
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
768 if not setting_default_value
:
769 ifaceobj
.status
= ifaceStatus
.ERROR
770 self
.logger
.error('%s: %s' %(ifaceobj
.name
, str(e
)))
772 def process_mtu(self
, ifaceobj
, ifaceobj_getfunc
):
773 mtu
= ifaceobj
.get_attr_value_first('mtu')
776 default_iface_mtu
= self
.ifaces_defaults
.get(ifaceobj
.name
, {}).get('mtu')
778 if default_iface_mtu
:
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
)))
786 self
._process
_mtu
_config
(ifaceobj
, ifaceobj_getfunc
, mtu
)
788 def up_ipv6_addrgen(self
, ifaceobj
):
789 user_configured_ipv6_addrgen
= ifaceobj
.get_attr_value_first('ipv6-addrgen')
791 if not user_configured_ipv6_addrgen
and ifupdownflags
.flags
.PERFMODE
:
792 # no need to go further during perfmode (boot)
795 if not user_configured_ipv6_addrgen
and ifaceobj
.addr_method
== 'dhcp':
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')
809 }.get(user_configured_ipv6_addrgen
.lower(), None)
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
815 self
.logger
.warning('%s: invalid value "%s" for attribute ipv6-addrgen' % (ifaceobj
.name
, user_configured_ipv6_addrgen
))
817 def _up(self
, ifaceobj
, ifaceobj_getfunc
=None):
818 if not self
.ipcmd
.link_exists(ifaceobj
.name
):
821 if not self
.syntax_check_enable_l3_iface_forwardings(ifaceobj
, ifaceobj_getfunc
):
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
, '')
831 self
._sysctl
_config
(ifaceobj
)
833 addr_method
= ifaceobj
.addr_method
834 force_reapply
= False
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
842 dhclientcmd
= dhclient()
843 if dhclientcmd
.is_running(ifaceobj
.name
):
844 # release any dhcp leases
845 dhclientcmd
.release(ifaceobj
.name
)
847 elif dhclientcmd
.is_running6(ifaceobj
.name
):
848 dhclientcmd
.release6(ifaceobj
.name
)
853 self
.ipcmd
.batch_start()
854 self
.up_ipv6_addrgen(ifaceobj
)
856 if addr_method
not in ["dhcp", "ppp"]:
857 self
._inet
_address
_config
(ifaceobj
, ifaceobj_getfunc
,
860 # remove old addresses added by ifupdown2
861 # (if intf was moved from static config to dhcp)
862 for old_ifaceobj
in statemanager
.statemanager_api
.get_ifaceobjs(ifaceobj
.name
) or []:
863 for addr
in old_ifaceobj
.get_attr_value("address") or []:
864 self
.ipcmd
.addr_del(ifaceobj
.name
, addr
)
866 self
.process_mtu(ifaceobj
, ifaceobj_getfunc
)
869 self
.ipcmd
.batch_commit()
870 except Exception as e
:
871 self
.log_error('%s: %s' % (ifaceobj
.name
, str(e
)), ifaceobj
, raise_error
=False)
873 self
.up_hwaddress(ifaceobj
)
875 gateways
= ifaceobj
.get_attr_value('gateway')
878 prev_gw
= self
._get
_prev
_gateway
(ifaceobj
, gateways
)
879 self
._add
_delete
_gateway
(ifaceobj
, gateways
, prev_gw
)
881 def up_hwaddress(self
, ifaceobj
):
883 hwaddress
= self
._get
_hwaddress
(ifaceobj
)
886 if not ifupdownflags
.flags
.PERFMODE
: # system is clean
887 running_hwaddress
= self
.ipcmd
.link_get_hwaddress(ifaceobj
.name
)
889 running_hwaddress
= None
891 if self
.ipcmd
.mac_str_to_int(running_hwaddress
) != self
.ipcmd
.mac_str_to_int(hwaddress
):
893 netlink
.link_set_updown(ifaceobj
.name
, "down")
894 if ifaceobj
.link_kind
& ifaceLinkKind
.BOND
:
895 # if bond, down all the slaves
896 if ifaceobj
.lowerifaces
:
897 for l
in ifaceobj
.lowerifaces
:
898 netlink
.link_set_updown(l
, "down")
901 self
.ipcmd
.link_set_hwaddress(ifaceobj
.name
, hwaddress
, force
=True)
903 netlink
.link_set_updown(ifaceobj
.name
, "up")
905 for l
in ifaceobj
.lowerifaces
:
906 netlink
.link_set_updown(l
, "up")
908 # Handle special things on a bridge
909 self
._process
_bridge
(ifaceobj
, True)
911 self
.log_error('%s: %s' % (ifaceobj
.name
, str(e
)), ifaceobj
)
913 def _down(self
, ifaceobj
, ifaceobj_getfunc
=None):
915 if not self
.ipcmd
.link_exists(ifaceobj
.name
):
917 addr_method
= ifaceobj
.addr_method
918 if addr_method
not in ["dhcp", "ppp"]:
919 if ifaceobj
.get_attr_value_first('address-purge')=='no':
920 addrlist
= ifaceobj
.get_attr_value('address')
921 for addr
in addrlist
:
922 self
.ipcmd
.addr_del(ifaceobj
.name
, addr
)
923 #self.ipcmd.addr_del(ifaceobj.name, ifaceobj.get_attr_value('address')[0])
924 elif not ifaceobj
.link_kind
:
925 # for logical interfaces we don't need to remove the ip addresses
926 # kernel will do it for us on 'ip link del'
927 self
.ipcmd
.del_addr_all(ifaceobj
.name
)
928 gateways
= ifaceobj
.get_attr_value('gateway')
930 self
._delete
_gateway
(ifaceobj
, gateways
,
931 ifaceobj
.get_attr_value_first('vrf'),
932 ifaceobj
.get_attr_value_first('metric'))
933 mtu
= ifaceobj
.get_attr_value_first('mtu')
934 if (not ifaceobj
.link_kind
and mtu
and
935 self
.default_mtu
and (mtu
!= self
.default_mtu
)):
936 self
.ipcmd
.link_set(ifaceobj
.name
, 'mtu', self
.default_mtu
)
937 alias
= ifaceobj
.get_attr_value_first('alias')
939 self
.write_file('/sys/class/net/%s/ifalias' % ifaceobj
.name
, '\n')
940 # XXX hwaddress reset cannot happen because we dont know last
943 # Handle special things on a bridge
944 self
._process
_bridge
(ifaceobj
, False)
946 self
.logger
.debug('%s : %s' %(ifaceobj
.name
, str(e
)))
949 def _get_iface_addresses(self
, ifaceobj
):
950 addrlist
= ifaceobj
.get_attr_value('address')
953 if not addrlist
: return None
954 for addrindex
in range(0, len(addrlist
)):
955 addr
= addrlist
[addrindex
]
956 netmask
= ifaceobj
.get_attr_value_n('netmask', addrindex
)
958 prefixlen
= IPNetwork('%s' %addr
+
959 '/%s' %netmask
).prefixlen
960 addr
= addr
+ '/%s' %prefixlen
961 outaddrlist
.append(addr
)
964 def _get_bridge_fdbs(self
, bridgename
, vlan
):
965 fdbs
= self
._bridge
_fdb
_query
_cache
.get(bridgename
)
967 fdbs
= self
.ipcmd
.bridge_fdb_show_dev(bridgename
)
970 self
._bridge
_fdb
_query
_cache
[bridgename
] = fdbs
971 return fdbs
.get(vlan
)
973 def _check_addresses_in_bridge(self
, ifaceobj
, hwaddress
):
974 """ If the device is a bridge, make sure the addresses
975 are in the bridge """
976 if ifaceobj
.link_kind
& ifaceLinkKind
.VLAN
:
977 bridgename
= ifaceobj
.lowerifaces
[0]
978 vlan
= self
._get
_vlan
_id
(ifaceobj
)
979 if self
.ipcmd
.bridge_is_vlan_aware(bridgename
):
980 fdb_addrs
= [self
.ipcmd
.mac_str_to_int(fdb_addr
) for fdb_addr
in self
._get
_bridge
_fdbs
(bridgename
, str(vlan
))]
983 hwaddress_int
= self
.ipcmd
.mac_str_to_int(hwaddress
)
984 if hwaddress_int
not in fdb_addrs
:
988 def _query_sysctl(self
, ifaceobj
, ifaceobjcurr
):
989 bridge_port
= ifaceobj
.link_privflags
& ifaceLinkPrivFlags
.BRIDGE_PORT
990 ipforward
= ifaceobj
.get_attr_value_first('ip-forward')
993 ifaceobjcurr
.status
= ifaceStatus
.ERROR
994 ifaceobjcurr
.status_str
= ('\'ip-forward\' not supported ' +
996 ifaceobjcurr
.update_config_with_status('ip-forward', 1, None)
998 running_ipforward
= self
.read_file_oneline(
999 '/proc/sys/net/ipv4/conf/%s/forwarding'
1001 running_ipforward
= utils
.get_boolean_from_string(running_ipforward
)
1002 config_ipforward
= utils
.get_boolean_from_string(ipforward
)
1003 ifaceobjcurr
.update_config_with_status(
1005 'on' if running_ipforward
else 'off',
1006 running_ipforward
!= config_ipforward
1009 ip6forward
= ifaceobj
.get_attr_value_first('ip6-forward')
1012 ifaceobjcurr
.status
= ifaceStatus
.ERROR
1013 ifaceobjcurr
.status_str
= ('\'ip6-forward\' not supported ' +
1015 ifaceobjcurr
.update_config_with_status('ip6-forward', 1, None)
1017 running_ip6forward
= self
.read_file_oneline(
1018 '/proc/sys/net/ipv6/conf/%s/forwarding'
1020 running_ip6forward
= utils
.get_boolean_from_string(running_ip6forward
)
1021 config_ip6forward
= utils
.get_boolean_from_string(ip6forward
)
1022 ifaceobjcurr
.update_config_with_status(
1024 'on' if running_ip6forward
else 'off',
1025 running_ip6forward
!= config_ip6forward
1027 mpls_enable
= ifaceobj
.get_attr_value_first('mpls-enable');
1029 running_mpls_enable
= self
.read_file_oneline(
1030 '/proc/sys/net/mpls/conf/%s/input'
1032 running_mpls_enable
= utils
.get_yesno_from_onezero(
1033 running_mpls_enable
)
1034 ifaceobjcurr
.update_config_with_status('mpls-enable',
1035 running_mpls_enable
,
1036 mpls_enable
!= running_mpls_enable
)
1039 def query_check_ipv6_addrgen(self
, ifaceobj
, ifaceobjcurr
):
1040 ipv6_addrgen
= ifaceobj
.get_attr_value_first('ipv6-addrgen')
1042 if not ipv6_addrgen
:
1045 if ipv6_addrgen
in utils
._string
_values
:
1046 ifaceobjcurr
.update_config_with_status(
1049 utils
.get_boolean_from_string(ipv6_addrgen
) == self
.ipcmd
.get_ipv6_addrgen_mode(ifaceobj
.name
)
1052 ifaceobjcurr
.update_config_with_status('ipv6-addrgen', ipv6_addrgen
, 1)
1054 def _query_check(self
, ifaceobj
, ifaceobjcurr
, ifaceobj_getfunc
=None):
1055 runningaddrsdict
= None
1056 if not self
.ipcmd
.link_exists(ifaceobj
.name
):
1057 self
.logger
.debug('iface %s not found' %ifaceobj
.name
)
1060 self
.query_check_ipv6_addrgen(ifaceobj
, ifaceobjcurr
)
1062 addr_method
= ifaceobj
.addr_method
1063 self
.query_n_update_ifaceobjcurr_attr(ifaceobj
, ifaceobjcurr
,
1064 'mtu', self
.ipcmd
.link_get_mtu
)
1065 hwaddress
= self
._get
_hwaddress
(ifaceobj
)
1067 rhwaddress
= self
.ipcmd
.link_get_hwaddress(ifaceobj
.name
)
1068 if not rhwaddress
or self
.ipcmd
.mac_str_to_int(rhwaddress
) != self
.ipcmd
.mac_str_to_int(hwaddress
):
1069 ifaceobjcurr
.update_config_with_status('hwaddress', rhwaddress
,
1071 elif not self
._check
_addresses
_in
_bridge
(ifaceobj
, hwaddress
):
1072 # XXX: hw address is not in bridge
1073 ifaceobjcurr
.update_config_with_status('hwaddress', rhwaddress
,
1075 ifaceobjcurr
.status_str
= 'bridge fdb error'
1077 ifaceobjcurr
.update_config_with_status('hwaddress', rhwaddress
,
1079 self
.query_n_update_ifaceobjcurr_attr(ifaceobj
, ifaceobjcurr
,
1080 'alias', self
.ipcmd
.link_get_alias
)
1081 self
._query
_sysctl
(ifaceobj
, ifaceobjcurr
)
1083 if addr_method
in ["dhcp", "ppp"]:
1085 addrs
= utils
.get_normalized_ip_addr(ifaceobj
.name
,
1086 self
._get
_iface
_addresses
(ifaceobj
))
1087 runningaddrsdict
= self
.ipcmd
.get_running_addrs(ifaceobj
)
1088 # if anycast address is configured on 'lo' and is in running config
1089 # add it to addrs so that query_check doesn't fail
1090 anycast_addr
= utils
.get_normalized_ip_addr(ifaceobj
.name
, ifaceobj
.get_attr_value_first('clagd-vxlan-anycast-ip'))
1092 anycast_addr
= anycast_addr
+'/32'
1093 if runningaddrsdict
and anycast_addr
and runningaddrsdict
.get(anycast_addr
):
1094 addrs
.append(anycast_addr
)
1096 # Set ifaceobjcurr method and family
1097 ifaceobjcurr
.addr_method
= ifaceobj
.addr_method
1098 ifaceobjcurr
.addr_family
= ifaceobj
.addr_family
1099 if not runningaddrsdict
and not addrs
:
1101 runningaddrs
= runningaddrsdict
.keys() if runningaddrsdict
else []
1102 # Add /32 netmask to configured address without netmask.
1103 # This may happen on interfaces where pointopoint is used.
1104 runningaddrs
= [ addr
if '/' in addr
else addr
+ '/32' for addr
in runningaddrs
]
1105 if runningaddrs
!= addrs
:
1106 runningaddrsset
= set(runningaddrs
) if runningaddrs
else set([])
1107 addrsset
= set(addrs
) if addrs
else set([])
1108 if (ifaceobj
.flags
& iface
.HAS_SIBLINGS
):
1111 # only check for addresses present in running config
1112 addrsdiff
= addrsset
.difference(runningaddrsset
)
1114 if addr
in addrsdiff
:
1115 ifaceobjcurr
.update_config_with_status('address',
1118 ifaceobjcurr
.update_config_with_status('address',
1121 addrsdiff
= addrsset
.symmetric_difference(runningaddrsset
)
1122 for addr
in addrsset
.union(runningaddrsset
):
1123 if addr
in addrsdiff
:
1124 ifaceobjcurr
.update_config_with_status('address',
1127 ifaceobjcurr
.update_config_with_status('address',
1130 [ifaceobjcurr
.update_config_with_status('address',
1131 addr
, 0) for addr
in addrs
]
1132 #XXXX Check broadcast address, scope, etc
1135 def query_running_ipv6_addrgen(self
, ifaceobjrunning
):
1136 ipv6_addrgen
= self
.ipcmd
.get_ipv6_addrgen_mode(ifaceobjrunning
.name
)
1139 ifaceobjrunning
.update_config('ipv6-addrgen', 'off')
1141 def _query_running(self
, ifaceobjrunning
, ifaceobj_getfunc
=None):
1142 if not self
.ipcmd
.link_exists(ifaceobjrunning
.name
):
1143 self
.logger
.debug('iface %s not found' %ifaceobjrunning
.name
)
1146 self
.query_running_ipv6_addrgen(ifaceobjrunning
)
1148 dhclientcmd
= dhclient()
1149 if (dhclientcmd
.is_running(ifaceobjrunning
.name
) or
1150 dhclientcmd
.is_running6(ifaceobjrunning
.name
)):
1151 # If dhcp is configured on the interface, we skip it
1153 isloopback
= self
.ipcmd
.link_isloopback(ifaceobjrunning
.name
)
1155 default_addrs
= ['127.0.0.1/8', '::1/128']
1156 ifaceobjrunning
.addr_family
.append('inet')
1157 ifaceobjrunning
.addr_method
= 'loopback'
1160 runningaddrsdict
= self
.ipcmd
.get_running_addrs(ifaceobjrunning
)
1161 if runningaddrsdict
:
1162 [ifaceobjrunning
.update_config('address', addr
)
1163 for addr
, addrattrs
in runningaddrsdict
.items()
1164 if addr
not in default_addrs
]
1165 mtu
= self
.ipcmd
.link_get_mtu(ifaceobjrunning
.name
)
1167 (ifaceobjrunning
.name
== 'lo' and mtu
!= '16436') or
1168 (ifaceobjrunning
.name
!= 'lo' and
1169 mtu
!= self
.get_mod_subattr('mtu', 'default'))):
1170 ifaceobjrunning
.update_config('mtu', mtu
)
1171 alias
= self
.ipcmd
.link_get_alias(ifaceobjrunning
.name
)
1173 ifaceobjrunning
.update_config('alias', alias
)
1175 ipforward
= self
.read_file_oneline(
1176 '/proc/sys/net/ipv4/conf/%s/forwarding'
1177 %ifaceobjrunning
.name
)
1180 _run_ops
= {'up' : _up
,
1182 'query-checkcurr' : _query_check
,
1183 'query-running' : _query_running
}
1186 """ returns list of ops supported by this module """
1187 return self
._run
_ops
.keys()
1189 def _init_command_handlers(self
):
1191 self
.ipcmd
= LinkUtils()
1193 def run(self
, ifaceobj
, operation
, query_ifaceobj
=None, ifaceobj_getfunc
=None):
1194 """ run address configuration on the interface object passed as argument
1197 **ifaceobj** (object): iface object
1199 **operation** (str): any of 'up', 'down', 'query-checkcurr',
1202 query_ifaceobj (object): query check ifaceobject. This is only
1203 valid when op is 'query-checkcurr'. It is an object same as
1204 ifaceobj, but contains running attribute values and its config
1205 status. The modules can use it to return queried running state
1206 of interfaces. status is success if the running state is same
1207 as user required state in ifaceobj. error otherwise.
1209 if ifaceobj
.type == ifaceType
.BRIDGE_VLAN
:
1211 op_handler
= self
._run
_ops
.get(operation
)
1214 self
._init
_command
_handlers
()
1215 if operation
== 'query-checkcurr':
1216 op_handler(self
, ifaceobj
, query_ifaceobj
,
1217 ifaceobj_getfunc
=ifaceobj_getfunc
)
1219 op_handler(self
, ifaceobj
,
1220 ifaceobj_getfunc
=ifaceobj_getfunc
)