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': 'Allow gratuitous arp to update arp table',
101 'validvals': ['on', 'off', 'yes', 'no', '0', '1'],
103 'example' : ['arp-accept on']},
105 { 'help': 'ip forwarding flag',
106 'validvals': ['on', 'off', 'yes', 'no', '0', '1'],
108 'example' : ['ip-forward off']},
110 { 'help': 'ipv6 forwarding flag',
111 'validvals': ['on', 'off', 'yes', 'no', '0', '1'],
113 'example' : ['ip6-forward off']},
115 { 'help': 'mpls enable flag',
116 'validvals': ['yes', 'no'],
118 'example' : ['mpls-enable yes']},
120 'help': 'enable disable ipv6 link addrgenmode',
121 'validvals': ['on', 'off'],
130 def __init__(self
, *args
, **kargs
):
131 moduleBase
.__init
__(self
, *args
, **kargs
)
133 self
._bridge
_fdb
_query
_cache
= {}
134 self
.default_mtu
= policymanager
.policymanager_api
.get_attr_default(module_name
=self
.__class
__.__name
__, attr
='mtu')
135 self
.max_mtu
= policymanager
.policymanager_api
.get_module_globals(module_name
=self
.__class
__.__name
__, attr
='max_mtu')
136 self
.ipforward
= policymanager
.policymanager_api
.get_attr_default(module_name
=self
.__class
__.__name
__, attr
='ip-forward')
137 self
.ip6forward
= policymanager
.policymanager_api
.get_attr_default(module_name
=self
.__class
__.__name
__, attr
='ip6-forward')
138 self
.ifaces_defaults
= policymanager
.policymanager_api
.get_iface_defaults(module_name
=self
.__class
__.__name
__)
139 self
.enable_l3_iface_forwarding_checks
= utils
.get_boolean_from_string(
140 policymanager
.policymanager_api
.get_module_globals(
141 self
.__class
__.__name
__,
142 'enable_l3_iface_forwarding_checks'
146 if not self
.default_mtu
:
147 self
.default_mtu
= '1500'
149 self
.logger
.info('address: using default mtu %s' %self
.default_mtu
)
152 self
.logger
.info('address: using max mtu %s' %self
.max_mtu
)
154 self
.lower_iface_mtu_checked_list
= list()
156 self
.l3_intf_arp_accept
= utils
.get_boolean_from_string(
157 policymanager
.policymanager_api
.get_module_globals(
158 module_name
=self
.__class
__.__name
__,
159 attr
='l3_intf_arp_accept'
164 self
.l3_intf_default_gateway_set_onlink
= utils
.get_boolean_from_string(
165 policymanager
.policymanager_api
.get_module_globals(
166 module_name
=self
.__class
__.__name
__,
167 attr
='l3_intf_default_gateway_set_onlink'
172 def syntax_check(self
, ifaceobj
, ifaceobj_getfunc
=None):
173 return (self
.syntax_check_multiple_gateway(ifaceobj
)
174 and self
.syntax_check_addr_allowed_on(ifaceobj
, True)
175 and self
.syntax_check_mtu(ifaceobj
, ifaceobj_getfunc
)
176 and self
.syntax_check_sysctls(ifaceobj
)
177 and self
.syntax_check_enable_l3_iface_forwardings(ifaceobj
, ifaceobj_getfunc
, syntax_check
=True))
179 def syntax_check_enable_l3_iface_forwardings(self
, ifaceobj
, ifaceobj_getfunc
, syntax_check
=False):
180 if (self
.enable_l3_iface_forwarding_checks
181 and (ifaceobj
.link_kind
& ifaceLinkKind
.VLAN
182 or ifaceobj
.link_kind
& ifaceLinkKind
.BRIDGE
)
183 and not ifaceobj
.link_privflags
& ifaceLinkPrivFlags
.BRIDGE_PORT
):
185 ifname
= ifaceobj
.name
187 vlan_ipforward_off
= None
189 for obj
in ifaceobj_getfunc(ifname
) or [ifaceobj
]:
191 vlan_addr
= obj
.get_attr_value('address')
193 if not vlan_ipforward_off
:
194 ip_forward_value
= obj
.get_attr_value_first('ip-forward')
196 if ip_forward_value
and not utils
.get_boolean_from_string(ip_forward_value
):
197 vlan_ipforward_off
= True
199 if vlan_addr
and vlan_ipforward_off
:
202 'configuring ip-forward off and ip address(es) (%s) is not compatible'
203 % (', '.join(vlan_addr
))
207 '%s: configuring ip-forward off and ip address(es) (%s) is not compatible'
208 % (ifname
, ', '.join(vlan_addr
))
213 def syntax_check_sysctls(self
, ifaceobj
):
215 bridge_port
= (ifaceobj
.link_privflags
& ifaceLinkPrivFlags
.BRIDGE_PORT
)
216 ipforward
= ifaceobj
.get_attr_value_first('ip-forward')
217 if bridge_port
and ipforward
:
219 self
.log_error('%s: \'ip-forward\' is not supported for '
220 'bridge port' %ifaceobj
.name
)
221 ip6forward
= ifaceobj
.get_attr_value_first('ip6-forward')
222 if bridge_port
and ip6forward
:
224 self
.log_error('%s: \'ip6-forward\' is not supported for '
225 'bridge port' %ifaceobj
.name
)
228 def syntax_check_mtu(self
, ifaceobj
, ifaceobj_getfunc
):
229 mtu
= ifaceobj
.get_attr_value_first('mtu')
231 return self
._check
_mtu
_config
(ifaceobj
, mtu
, ifaceobj_getfunc
,
235 def syntax_check_addr_allowed_on(self
, ifaceobj
, syntax_check
=False):
236 if ifaceobj
.get_attr_value('address'):
237 return utils
.is_addr_ip_allowed_on(ifaceobj
, syntax_check
=syntax_check
)
240 def _syntax_check_multiple_gateway(self
, family
, found
, addr
, type_obj
):
241 if type(IPNetwork(addr
)) == type_obj
:
243 raise Exception('%s: multiple gateways for %s family'
248 def syntax_check_multiple_gateway(self
, ifaceobj
):
252 gateways
= ifaceobj
.get_attr_value('gateway')
253 for addr
in gateways
if gateways
else []:
255 if self
._syntax
_check
_multiple
_gateway
('inet', inet
, addr
,
258 if self
._syntax
_check
_multiple
_gateway
('inet6', inet6
, addr
,
261 except Exception as e
:
262 self
.logger
.warning('%s: address: %s' % (ifaceobj
.name
, str(e
)))
266 def _address_valid(self
, addrs
):
269 if any(map(lambda a
: True if a
[:7] != '0.0.0.0'
274 def _get_hwaddress(self
, ifaceobj
):
275 return utils
.strip_hwaddress(ifaceobj
.get_attr_value_first('hwaddress'))
277 def _process_bridge(self
, ifaceobj
, up
):
278 hwaddress
= self
._get
_hwaddress
(ifaceobj
)
279 addrs
= ifaceobj
.get_attr_value_first('address')
280 arp_accept
= ifaceobj
.get_attr_value_first('arp-accept')
281 arp_accept
= utils
.boolean_support_binary(arp_accept
)
282 is_vlan_dev_on_vlan_aware_bridge
= False
283 is_bridge
= self
.ipcmd
.is_bridge(ifaceobj
.name
)
285 if ifaceobj
.link_kind
& ifaceLinkKind
.VLAN
:
286 bridgename
= ifaceobj
.lowerifaces
[0]
287 vlan
= self
._get
_vlan
_id
(ifaceobj
)
288 is_vlan_dev_on_vlan_aware_bridge
= self
.ipcmd
.bridge_is_vlan_aware(bridgename
)
289 if ((is_bridge
and not self
.ipcmd
.bridge_is_vlan_aware(ifaceobj
.name
))
290 or is_vlan_dev_on_vlan_aware_bridge
):
291 if self
._address
_valid
(addrs
):
292 if self
.l3_intf_arp_accept
:
294 self
.write_file('/proc/sys/net/ipv4/conf/%s' % ifaceobj
.name
+
297 self
.write_file('/proc/sys/net/ipv4/conf/%s' % ifaceobj
.name
+
300 self
.write_file('/proc/sys/net/ipv4/conf/%s/arp_accept' % ifaceobj
.name
, arp_accept
)
301 if hwaddress
and is_vlan_dev_on_vlan_aware_bridge
:
303 # check statemanager to delete the old entry if necessary
305 for old_obj
in statemanager
.statemanager_api
.get_ifaceobjs(ifaceobj
.name
) or []:
306 old_hwaddress
= old_obj
.get_attr_value_first("hwaddress")
307 if old_hwaddress
and self
.ipcmd
.mac_str_to_int(old_hwaddress
) != self
.ipcmd
.mac_str_to_int(hwaddress
):
308 self
.ipcmd
.bridge_fdb_del(bridgename
, old_hwaddress
, vlan
)
312 self
.ipcmd
.bridge_fdb_add(bridgename
, hwaddress
, vlan
)
314 self
.ipcmd
.bridge_fdb_del(bridgename
, hwaddress
, vlan
)
316 def _get_anycast_addr(self
, ifaceobjlist
):
317 for ifaceobj
in ifaceobjlist
:
318 anycast_addr
= ifaceobj
.get_attr_value_first('clagd-vxlan-anycast-ip')
320 anycast_addr
= anycast_addr
+'/32'
324 def _inet_address_convert_to_cidr(self
, ifaceobjlist
):
328 for ifaceobj
in ifaceobjlist
:
329 addrs
= ifaceobj
.get_attr_value('address')
333 if not self
.syntax_check_addr_allowed_on(ifaceobj
,
335 return (False, newaddrs
, newaddr_attrs
)
336 # If user address is not in CIDR notation, convert them to CIDR
337 for addr_index
in range(0, len(addrs
)):
338 addr
= addrs
[addr_index
]
341 newaddrs
.append(addr
)
343 netmask
= ifaceobj
.get_attr_value_n('netmask', addr_index
)
345 prefixlen
= IPNetwork('%s' %addr
+
346 '/%s' %netmask
).prefixlen
347 newaddr
= addr
+ '/%s' %prefixlen
349 # we are here because there is no slash (/xx) and no netmask
350 # just let IPNetwork handle the ipv4 or ipv6 address mask
351 prefixlen
= IPNetwork(addr
).prefixlen
352 newaddr
= addr
+ '/%s' %prefixlen
353 newaddrs
.append(newaddr
)
356 for a
in ['broadcast', 'pointopoint', 'scope',
357 'preferred-lifetime']:
358 aval
= ifaceobj
.get_attr_value_n(a
, addr_index
)
363 newaddr_attrs
[newaddr
]= attrs
364 return (True, newaddrs
, newaddr_attrs
)
366 def _inet_address_list_config(self
, ifaceobj
, newaddrs
, newaddr_attrs
):
367 for addr_index
in range(0, len(newaddrs
)):
370 self
.ipcmd
.addr_add(ifaceobj
.name
, newaddrs
[addr_index
],
371 newaddr_attrs
.get(newaddrs
[addr_index
],
372 {}).get('broadcast'),
373 newaddr_attrs
.get(newaddrs
[addr_index
],
374 {}).get('pointopoint'),
375 newaddr_attrs
.get(newaddrs
[addr_index
],
377 newaddr_attrs
.get(newaddrs
[addr_index
],
378 {}).get('preferred-lifetime'))
380 self
.ipcmd
.addr_add(ifaceobj
.name
, newaddrs
[addr_index
])
382 self
.log_error(str(e
), ifaceobj
)
384 def _inet_address_config(self
, ifaceobj
, ifaceobj_getfunc
=None,
385 force_reapply
=False):
386 squash_addr_config
= (True if \
387 ifupdownconfig
.config
.get('addr_config_squash', \
388 '0') == '1' else False)
390 if (squash_addr_config
and
391 not (ifaceobj
.flags
& ifaceobj
.YOUNGEST_SIBLING
)):
394 purge_addresses
= ifaceobj
.get_attr_value_first('address-purge')
395 if not purge_addresses
:
396 purge_addresses
= 'yes'
398 if squash_addr_config
and ifaceobj
.flags
& iface
.HAS_SIBLINGS
:
399 ifaceobjlist
= ifaceobj_getfunc(ifaceobj
.name
)
401 ifaceobjlist
= [ifaceobj
]
403 module_name
= self
.__class
__.__name
__
404 ifname
= ifaceobj
.name
406 (addr_supported
, newaddrs
, newaddr_attrs
) = self
._inet
_address
_convert
_to
_cidr
(ifaceobjlist
)
407 newaddrs
= utils
.get_ip_objs(module_name
, ifname
, newaddrs
)
409 if not addr_supported
:
411 if (not squash_addr_config
and (ifaceobj
.flags
& iface
.HAS_SIBLINGS
)):
412 # if youngest sibling and squash addr is not set
413 # print a warning that addresses will not be purged
414 if (ifaceobj
.flags
& iface
.YOUNGEST_SIBLING
):
415 self
.logger
.warn('%s: interface has multiple ' %ifaceobj
.name
+
416 'iface stanzas, skip purging existing addresses')
417 purge_addresses
= 'no'
419 if not ifupdownflags
.flags
.PERFMODE
and purge_addresses
== 'yes':
420 # if perfmode is not set and purge addresses is not set to 'no'
421 # lets purge addresses not in the config
422 runningaddrs
= self
.ipcmd
.get_running_addrs(ifaceobj
, details
=False)
424 # if anycast address is configured on 'lo' and is in running config
425 # add it to newaddrs so that ifreload doesn't wipe it out
426 anycast_addr
= utils
.get_normalized_ip_addr(ifaceobj
.name
, self
._get
_anycast
_addr
(ifaceobjlist
))
428 if runningaddrs
and anycast_addr
and anycast_addr
in runningaddrs
:
429 newaddrs
.append(anycast_addr
)
431 user_ip4
, user_ip6
, newaddrs
= self
.order_user_configured_addrs(newaddrs
)
433 if newaddrs
== runningaddrs
or self
.compare_running_ips_and_user_config(user_ip4
, user_ip6
, runningaddrs
):
435 self
._inet
_address
_list
_config
(ifaceobj
, newaddrs
, newaddr_attrs
)
438 # if primary address is not same, there is no need to keep any.
439 # reset all addresses
440 if newaddrs
and runningaddrs
and newaddrs
[0] != runningaddrs
[0]:
443 skip_addrs
= newaddrs
or []
444 for addr
in runningaddrs
or []:
445 if addr
in skip_addrs
:
447 self
.ipcmd
.addr_del(ifaceobj
.name
, addr
)
449 self
.log_warn(str(e
))
452 self
._inet
_address
_list
_config
(ifaceobj
, newaddrs
, newaddr_attrs
)
454 def compare_running_ips_and_user_config(self
, user_ip4
, user_ip6
, running_addrs
):
456 We need to compare the user config ips and the running ips.
457 ip4 ordering matters (primary etc) but ip6 order doesn't matter
459 this function replaces the strict comparison previously in place
460 if newaddrs == running_addrs ?
462 We will compare if the ip4 ordering is correct, then check if all
463 ip6 are present in the list (without checking the ordering)
465 if (user_ip4
or user_ip6
) and not running_addrs
:
467 elif running_addrs
and not user_ip4
and not user_ip6
:
469 elif not running_addrs
and not user_ip4
and not user_ip6
:
472 len_ip4
= len(user_ip4
)
473 len_running_addrs
= len(running_addrs
)
475 if len_ip4
> len_running_addrs
:
480 if user_ip4
[i
] != running_addrs
[i
]:
485 running_ip6
= running_addrs
[len_ip4
:]
487 running_ip6
= running_addrs
490 len_ip6
= len(user_ip6
)
492 for ip6
in running_ip6
:
493 if ip6
not in user_ip6
:
499 def order_user_configured_addrs(self
, user_config_addrs
):
503 for a
in user_config_addrs
:
504 if isinstance(a
, _BaseV6
):
509 return ip4
, ip6
, ip4
+ ip6
511 def _delete_gateway(self
, ifaceobj
, gateways
, vrf
, metric
):
512 for del_gw
in gateways
:
514 self
.ipcmd
.route_del_gateway(ifaceobj
.name
, del_gw
, vrf
, metric
)
515 except Exception as e
:
516 self
.logger
.debug('%s: %s' % (ifaceobj
.name
, str(e
)))
518 def _add_delete_gateway(self
, ifaceobj
, gateways
=[], prev_gw
=[]):
519 vrf
= ifaceobj
.get_attr_value_first('vrf')
520 metric
= ifaceobj
.get_attr_value_first('metric')
521 self
._delete
_gateway
(ifaceobj
, list(set(prev_gw
) - set(gateways
)),
523 for add_gw
in gateways
:
525 self
.ipcmd
.route_add_gateway(ifaceobj
.name
, add_gw
, vrf
, metric
, onlink
=self
.l3_intf_default_gateway_set_onlink
)
526 except Exception as e
:
527 self
.log_error('%s: %s' % (ifaceobj
.name
, str(e
)))
529 def _get_prev_gateway(self
, ifaceobj
, gateways
):
531 saved_ifaceobjs
= statemanager
.statemanager_api
.get_ifaceobjs(ifaceobj
.name
)
532 if not saved_ifaceobjs
:
534 prev_gateways
= saved_ifaceobjs
[0].get_attr_value('gateway')
535 if not prev_gateways
:
539 def _check_mtu_config(self
, ifaceobj
, mtu
, ifaceobj_getfunc
, syntaxcheck
=False):
541 if (ifaceobj
.link_kind
& ifaceLinkKind
.BRIDGE
):
543 self
.logger
.warn('%s: bridge inherits mtu from its ports. There is no need to assign mtu on a bridge' %ifaceobj
.name
)
546 self
.logger
.info('%s: bridge inherits mtu from its ports. There is no need to assign mtu on a bridge' %ifaceobj
.name
)
547 elif ifaceobj_getfunc
:
548 if ((ifaceobj
.link_privflags
& ifaceLinkPrivFlags
.BOND_SLAVE
) and
549 ifaceobj
.upperifaces
):
550 masterobj
= ifaceobj_getfunc(ifaceobj
.upperifaces
[0])
552 master_mtu
= masterobj
[0].get_attr_value_first('mtu')
553 if master_mtu
and master_mtu
!= mtu
:
555 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
))
558 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
))
559 elif ((ifaceobj
.link_kind
& ifaceLinkKind
.VLAN
) and
560 ifaceobj
.lowerifaces
):
561 lowerobj
= ifaceobj_getfunc(ifaceobj
.lowerifaces
[0])
564 lowerdev_mtu
= lowerobj
[0].get_attr_value_first('mtu')
566 lowerdev_mtu
= self
.ipcmd
.link_get_mtu_sysfs(lowerobj
[0].name
)
567 if lowerdev_mtu
and int(mtu
) > int(lowerdev_mtu
):
568 self
.logger
.warn('%s: vlan dev mtu %s is greater than lower realdev %s mtu %s'
569 %(ifaceobj
.name
, mtu
, lowerobj
[0].name
, lowerdev_mtu
))
571 elif (not lowerobj
[0].link_kind
and
572 not (lowerobj
[0].link_privflags
& ifaceLinkPrivFlags
.LOOPBACK
) and
573 not lowerdev_mtu
and self
.default_mtu
and
574 (int(mtu
) > int(self
.default_mtu
))):
575 # only check default mtu on lower device which is a physical interface
576 self
.logger
.warn('%s: vlan dev mtu %s is greater than lower realdev %s mtu %s'
577 %(ifaceobj
.name
, mtu
, lowerobj
[0].name
, self
.default_mtu
))
579 if self
.max_mtu
and mtu
> self
.max_mtu
:
580 self
.logger
.warn('%s: specified mtu %s is greater than max mtu %s'
581 %(ifaceobj
.name
, mtu
, self
.max_mtu
))
585 def _propagate_mtu_to_upper_devs(self
, ifaceobj
, mtu
, ifaceobj_getfunc
):
586 if (not ifaceobj
.upperifaces
or
587 (ifaceobj
.link_privflags
& ifaceLinkPrivFlags
.BOND_SLAVE
) or
588 (ifaceobj
.link_privflags
& ifaceLinkPrivFlags
.VRF_SLAVE
) or
589 (ifaceobj
.link_privflags
& ifaceLinkPrivFlags
.BRIDGE_PORT
)):
591 for u
in ifaceobj
.upperifaces
:
592 upperobjs
= ifaceobj_getfunc(u
)
594 not (upperobjs
[0].link_kind
& ifaceLinkKind
.VLAN
)):
596 # only adjust mtu for vlan devices on ifaceobj
597 umtu
= upperobjs
[0].get_attr_value_first('mtu')
599 running_mtu
= self
.ipcmd
.link_get_mtu(upperobjs
[0].name
)
600 if not running_mtu
or (running_mtu
!= mtu
):
601 self
.ipcmd
.link_set(u
, 'mtu', mtu
)
603 def _process_mtu_config(self
, ifaceobj
, ifaceobj_getfunc
, mtu
):
605 if not self
._check
_mtu
_config
(ifaceobj
, mtu
, ifaceobj_getfunc
):
607 cached_running_mtu
= self
.ipcmd
.link_get_mtu(ifaceobj
.name
)
608 running_mtu
= self
.ipcmd
.link_get_mtu_sysfs(ifaceobj
.name
)
609 if not running_mtu
or (running_mtu
and running_mtu
!= mtu
):
610 force
= cached_running_mtu
!= running_mtu
611 self
.ipcmd
.link_set(ifaceobj
.name
, 'mtu', mtu
, force
=force
)
612 if (not ifupdownflags
.flags
.ALL
and
613 not ifaceobj
.link_kind
and
614 ifupdownconfig
.config
.get('adjust_logical_dev_mtu', '1') != '0'):
615 # This is additional cost to us, so do it only when
616 # ifupdown2 is called on a particular interface and
617 # it is a physical interface
618 self
._propagate
_mtu
_to
_upper
_devs
(ifaceobj
, mtu
, ifaceobj_getfunc
)
621 if ifaceobj
.link_kind
:
622 # bonds, vxlan and custom devices (like dummy) need an explicit set of mtu.
623 # bridges don't need mtu set
624 if (ifaceobj
.link_kind
& ifaceLinkKind
.BOND
or
625 ifaceobj
.link_kind
& ifaceLinkKind
.VXLAN
or
626 ifaceobj
.link_kind
& ifaceLinkKind
.OTHER
628 running_mtu
= self
.ipcmd
.link_get_mtu(ifaceobj
.name
)
629 if (self
.default_mtu
and running_mtu
!= self
.default_mtu
):
630 self
.ipcmd
.link_set(ifaceobj
.name
, 'mtu', self
.default_mtu
)
632 if (ifupdownconfig
.config
.get('adjust_logical_dev_mtu', '1') != '0'
633 and ifaceobj
.lowerifaces
):
634 # set vlan interface mtu to lower device mtu
635 if (ifaceobj
.link_kind
& ifaceLinkKind
.VLAN
):
636 lower_iface
= ifaceobj
.lowerifaces
[0]
637 if lower_iface
not in self
.lower_iface_mtu_checked_list
:
638 lower_iface_mtu
= self
.ipcmd
.link_get_mtu_sysfs(lower_iface
)
639 self
.ipcmd
.cache_update([lower_iface
, 'mtu'], lower_iface_mtu
)
640 self
.lower_iface_mtu_checked_list
.append(lower_iface
)
642 lower_iface_mtu
= self
.ipcmd
.link_get_mtu(lower_iface
)
644 if lower_iface_mtu
!= self
.ipcmd
.link_get_mtu_sysfs(ifaceobj
.name
):
645 self
.ipcmd
.link_set_mtu(ifaceobj
.name
, lower_iface_mtu
)
647 elif (not (ifaceobj
.name
== 'lo') and not ifaceobj
.link_kind
and
648 not (ifaceobj
.link_privflags
& ifaceLinkPrivFlags
.BOND_SLAVE
) and
650 # logical devices like bridges and vlan devices rely on mtu
651 # from their lower devices. ie mtu travels from
652 # lower devices to upper devices. For bonds mtu travels from
653 # upper to lower devices. running mtu depends on upper and
654 # lower device mtu. With all this implicit mtu
655 # config by the kernel in play, we try to be cautious here
656 # on which devices we want to reset mtu to default.
657 # essentially only physical interfaces which are not bond slaves
658 running_mtu
= self
.ipcmd
.link_get_mtu(ifaceobj
.name
)
659 if running_mtu
!= self
.default_mtu
:
660 self
.ipcmd
.link_set(ifaceobj
.name
, 'mtu', self
.default_mtu
)
662 def _set_bridge_forwarding(self
, ifaceobj
):
663 """ set ip forwarding to 0 if bridge interface does not have a
665 ifname
= ifaceobj
.name
666 if not ifaceobj
.upperifaces
and not ifaceobj
.get_attr_value('address'):
667 if self
.sysctl_get_forwarding_value_from_proc(ifname
, "ipv4") == '1':
668 self
.sysctl_write_forwarding_value_to_proc(ifname
, "ipv4", 0)
669 if self
.sysctl_get_forwarding_value_from_proc(ifname
, "ipv6") == '1':
670 self
.sysctl_write_forwarding_value_to_proc(ifname
, "ipv6", 0)
672 if self
.sysctl_get_forwarding_value_from_proc(ifname
, "ipv4") == '0':
673 self
.sysctl_write_forwarding_value_to_proc(ifname
, "ipv4", 1)
674 if self
.sysctl_get_forwarding_value_from_proc(ifname
, "ipv6") == '0':
675 self
.sysctl_write_forwarding_value_to_proc(ifname
, "ipv6", 1)
677 def sysctl_get_forwarding_value_from_proc(self
, ifname
, family
):
678 return self
.read_file_oneline("/proc/sys/net/%s/conf/%s/forwarding" % (family
, ifname
))
680 def sysctl_write_forwarding_value_to_proc(self
, ifname
, family
, value
):
681 self
.write_file("/proc/sys/net/%s/conf/%s/forwarding" % (family
, ifname
), "%s\n" % value
)
683 def _sysctl_config(self
, ifaceobj
):
684 setting_default_value
= False
685 mpls_enable
= ifaceobj
.get_attr_value_first('mpls-enable');
687 setting_default_value
= True
688 mpls_enable
= self
.get_mod_subattr('mpls-enable', 'default')
689 mpls_enable
= utils
.boolean_support_binary(mpls_enable
)
690 # File read has been used for better performance
691 # instead of using sysctl command
692 if ifupdownflags
.flags
.PERFMODE
:
693 running_mpls_enable
= '0'
695 running_mpls_enable
= self
.read_file_oneline(
696 '/proc/sys/net/mpls/conf/%s/input'
700 if mpls_enable
!= running_mpls_enable
:
702 self
.sysctl_set('net.mpls.conf.%s.input'
703 %('/'.join(ifaceobj
.name
.split("."))),
705 except Exception as e
:
706 if not setting_default_value
:
707 ifaceobj
.status
= ifaceStatus
.ERROR
708 self
.logger
.error('%s: %s' %(ifaceobj
.name
, str(e
)))
710 if (ifaceobj
.link_kind
& ifaceLinkKind
.BRIDGE
):
711 self
._set
_bridge
_forwarding
(ifaceobj
)
713 if not self
.syntax_check_sysctls(ifaceobj
):
715 ipforward
= ifaceobj
.get_attr_value_first('ip-forward')
716 ip6forward
= ifaceobj
.get_attr_value_first('ip6-forward')
717 if ifupdownflags
.flags
.PERFMODE
:
719 self
.sysctl_set('net.ipv4.conf.%s.forwarding'
720 %('/'.join(ifaceobj
.name
.split("."))),
721 utils
.boolean_support_binary(ipforward
))
723 self
.sysctl_set('net.ipv6.conf.%s.forwarding'
724 %('/'.join(ifaceobj
.name
.split("."))),
725 utils
.boolean_support_binary(ip6forward
))
727 bridge_port
= ifaceobj
.link_privflags
& ifaceLinkPrivFlags
.BRIDGE_PORT
730 self
.log_error('%s: \'ip-forward\' is not supported for '
731 'bridge port' %ifaceobj
.name
)
733 self
.log_error('%s: \'ip6-forward\' is not supported for '
734 'bridge port' %ifaceobj
.name
)
737 setting_default_value
= False
739 setting_default_value
= True
740 ipforward
= self
.ipforward
743 ipforward
= utils
.boolean_support_binary(ipforward
)
744 # File read has been used for better performance
745 # instead of using sysctl command
746 running_ipforward
= self
.read_file_oneline(
747 '/proc/sys/net/ipv4/conf/%s/forwarding'
750 if ipforward
!= running_ipforward
:
753 self
.sysctl_set('net.ipv4.conf.%s.forwarding'
754 %('/'.join(ifaceobj
.name
.split("."))),
756 except Exception as e
:
757 if not setting_default_value
:
758 ifaceobj
.status
= ifaceStatus
.ERROR
759 self
.logger
.error('%s: %s' %(ifaceobj
.name
, str(e
)))
762 setting_default_value
= False
764 setting_default_value
= True
765 ip6forward
= self
.ip6forward
768 ip6forward
= utils
.boolean_support_binary(ip6forward
)
769 # File read has been used for better performance
770 # instead of using sysctl command
771 running_ip6forward
= self
.read_file_oneline(
772 '/proc/sys/net/ipv6/conf/%s/forwarding'
774 if ip6forward
!= running_ip6forward
:
776 self
.sysctl_set('net.ipv6.conf.%s.forwarding'
777 %('/'.join(ifaceobj
.name
.split("."))),
779 except Exception as e
:
780 # There is chance of ipv6 being removed because of,
781 # for example, setting mtu < 1280
782 # In such cases, log error only if user has configured
784 if not setting_default_value
:
785 ifaceobj
.status
= ifaceStatus
.ERROR
786 self
.logger
.error('%s: %s' %(ifaceobj
.name
, str(e
)))
788 def process_mtu(self
, ifaceobj
, ifaceobj_getfunc
):
789 mtu
= ifaceobj
.get_attr_value_first('mtu')
792 default_iface_mtu
= self
.ifaces_defaults
.get(ifaceobj
.name
, {}).get('mtu')
794 if default_iface_mtu
:
796 mtu
= default_iface_mtu
797 int(default_iface_mtu
)
798 except Exception as e
:
799 self
.logger
.warning('%s: MTU value from policy file: %s' % (ifaceobj
.name
, str(e
)))
802 self
._process
_mtu
_config
(ifaceobj
, ifaceobj_getfunc
, mtu
)
804 def up_ipv6_addrgen(self
, ifaceobj
):
805 user_configured_ipv6_addrgen
= ifaceobj
.get_attr_value_first('ipv6-addrgen')
807 if not user_configured_ipv6_addrgen
and ifupdownflags
.flags
.PERFMODE
:
808 # no need to go further during perfmode (boot)
811 if not user_configured_ipv6_addrgen
and ifaceobj
.addr_method
== 'dhcp':
814 if not user_configured_ipv6_addrgen
:
815 # if user didn't configure ipv6-addrgen, should we reset to default?
816 user_configured_ipv6_addrgen
= self
.get_attr_default_value('ipv6-addrgen')
825 }.get(user_configured_ipv6_addrgen
.lower(), None)
827 if ipv6_addrgen_nl
is not None:
828 self
.ipcmd
.ipv6_addrgen(ifaceobj
.name
, ipv6_addrgen_nl
, link_created
=True)
829 # link_create=False will flush the addr cache of that intf
831 self
.logger
.warning('%s: invalid value "%s" for attribute ipv6-addrgen' % (ifaceobj
.name
, user_configured_ipv6_addrgen
))
833 def _up(self
, ifaceobj
, ifaceobj_getfunc
=None):
834 if not self
.ipcmd
.link_exists(ifaceobj
.name
):
837 if not self
.syntax_check_enable_l3_iface_forwardings(ifaceobj
, ifaceobj_getfunc
):
840 alias
= ifaceobj
.get_attr_value_first('alias')
841 current_alias
= self
.ipcmd
.link_get_alias(ifaceobj
.name
)
842 if alias
and alias
!= current_alias
:
843 self
.ipcmd
.link_set_alias(ifaceobj
.name
, alias
)
844 elif not alias
and current_alias
:
845 self
.ipcmd
.link_set_alias(ifaceobj
.name
, '')
847 self
._sysctl
_config
(ifaceobj
)
849 addr_method
= ifaceobj
.addr_method
850 force_reapply
= False
852 # release any stale dhcp addresses if present
853 if (addr_method
not in ["dhcp", "ppp"] and not ifupdownflags
.flags
.PERFMODE
and
854 not (ifaceobj
.flags
& iface
.HAS_SIBLINGS
)):
855 # if not running in perf mode and ifaceobj does not have
856 # any sibling iface objects, kill any stale dhclient
858 dhclientcmd
= dhclient()
859 if dhclientcmd
.is_running(ifaceobj
.name
):
860 # release any dhcp leases
861 dhclientcmd
.release(ifaceobj
.name
)
863 elif dhclientcmd
.is_running6(ifaceobj
.name
):
864 dhclientcmd
.release6(ifaceobj
.name
)
869 self
.ipcmd
.batch_start()
870 self
.up_ipv6_addrgen(ifaceobj
)
872 if addr_method
not in ["dhcp", "ppp"]:
873 self
._inet
_address
_config
(ifaceobj
, ifaceobj_getfunc
,
876 # remove old addresses added by ifupdown2
877 # (if intf was moved from static config to dhcp)
878 for old_ifaceobj
in statemanager
.statemanager_api
.get_ifaceobjs(ifaceobj
.name
) or []:
879 for addr
in old_ifaceobj
.get_attr_value("address") or []:
880 self
.ipcmd
.addr_del(ifaceobj
.name
, addr
)
882 self
.process_mtu(ifaceobj
, ifaceobj_getfunc
)
885 self
.ipcmd
.batch_commit()
886 except Exception as e
:
887 self
.log_error('%s: %s' % (ifaceobj
.name
, str(e
)), ifaceobj
, raise_error
=False)
889 self
.up_hwaddress(ifaceobj
)
891 gateways
= ifaceobj
.get_attr_value('gateway')
894 prev_gw
= self
._get
_prev
_gateway
(ifaceobj
, gateways
)
895 self
._add
_delete
_gateway
(ifaceobj
, gateways
, prev_gw
)
897 def up_hwaddress(self
, ifaceobj
):
899 hwaddress
= self
._get
_hwaddress
(ifaceobj
)
902 if not ifupdownflags
.flags
.PERFMODE
: # system is clean
903 running_hwaddress
= self
.ipcmd
.link_get_hwaddress(ifaceobj
.name
)
905 running_hwaddress
= None
907 if self
.ipcmd
.mac_str_to_int(running_hwaddress
) != self
.ipcmd
.mac_str_to_int(hwaddress
):
909 netlink
.link_set_updown(ifaceobj
.name
, "down")
910 if ifaceobj
.link_kind
& ifaceLinkKind
.BOND
:
911 # if bond, down all the slaves
912 if ifaceobj
.lowerifaces
:
913 for l
in ifaceobj
.lowerifaces
:
914 netlink
.link_set_updown(l
, "down")
917 self
.ipcmd
.link_set_hwaddress(ifaceobj
.name
, hwaddress
, force
=True)
919 netlink
.link_set_updown(ifaceobj
.name
, "up")
921 for l
in ifaceobj
.lowerifaces
:
922 netlink
.link_set_updown(l
, "up")
924 # Handle special things on a bridge
925 self
._process
_bridge
(ifaceobj
, True)
927 self
.log_error('%s: %s' % (ifaceobj
.name
, str(e
)), ifaceobj
)
929 def _down(self
, ifaceobj
, ifaceobj_getfunc
=None):
931 if not self
.ipcmd
.link_exists(ifaceobj
.name
):
933 addr_method
= ifaceobj
.addr_method
934 if addr_method
not in ["dhcp", "ppp"]:
935 if ifaceobj
.get_attr_value_first('address-purge')=='no':
936 addrlist
= ifaceobj
.get_attr_value('address')
937 for addr
in addrlist
:
938 self
.ipcmd
.addr_del(ifaceobj
.name
, addr
)
939 #self.ipcmd.addr_del(ifaceobj.name, ifaceobj.get_attr_value('address')[0])
940 elif not ifaceobj
.link_kind
:
941 # for logical interfaces we don't need to remove the ip addresses
942 # kernel will do it for us on 'ip link del'
943 self
.ipcmd
.del_addr_all(ifaceobj
.name
)
944 gateways
= ifaceobj
.get_attr_value('gateway')
946 self
._delete
_gateway
(ifaceobj
, gateways
,
947 ifaceobj
.get_attr_value_first('vrf'),
948 ifaceobj
.get_attr_value_first('metric'))
949 mtu
= ifaceobj
.get_attr_value_first('mtu')
950 if (not ifaceobj
.link_kind
and mtu
and
951 self
.default_mtu
and (mtu
!= self
.default_mtu
)):
952 self
.ipcmd
.link_set(ifaceobj
.name
, 'mtu', self
.default_mtu
)
953 alias
= ifaceobj
.get_attr_value_first('alias')
955 self
.write_file('/sys/class/net/%s/ifalias' % ifaceobj
.name
, '\n')
956 # XXX hwaddress reset cannot happen because we dont know last
959 # Handle special things on a bridge
960 self
._process
_bridge
(ifaceobj
, False)
962 self
.logger
.debug('%s : %s' %(ifaceobj
.name
, str(e
)))
965 def _get_iface_addresses(self
, ifaceobj
):
966 addrlist
= ifaceobj
.get_attr_value('address')
969 if not addrlist
: return None
970 for addrindex
in range(0, len(addrlist
)):
971 addr
= addrlist
[addrindex
]
972 netmask
= ifaceobj
.get_attr_value_n('netmask', addrindex
)
974 prefixlen
= IPNetwork('%s' %addr
+
975 '/%s' %netmask
).prefixlen
976 addr
= addr
+ '/%s' %prefixlen
977 outaddrlist
.append(addr
)
980 def _get_bridge_fdbs(self
, bridgename
, vlan
):
981 fdbs
= self
._bridge
_fdb
_query
_cache
.get(bridgename
)
983 fdbs
= self
.ipcmd
.bridge_fdb_show_dev(bridgename
)
986 self
._bridge
_fdb
_query
_cache
[bridgename
] = fdbs
987 return fdbs
.get(vlan
)
989 def _check_addresses_in_bridge(self
, ifaceobj
, hwaddress
):
990 """ If the device is a bridge, make sure the addresses
991 are in the bridge """
992 if ifaceobj
.link_kind
& ifaceLinkKind
.VLAN
:
993 bridgename
= ifaceobj
.lowerifaces
[0]
994 vlan
= self
._get
_vlan
_id
(ifaceobj
)
995 if self
.ipcmd
.bridge_is_vlan_aware(bridgename
):
996 fdb_addrs
= [self
.ipcmd
.mac_str_to_int(fdb_addr
) for fdb_addr
in self
._get
_bridge
_fdbs
(bridgename
, str(vlan
))]
999 hwaddress_int
= self
.ipcmd
.mac_str_to_int(hwaddress
)
1000 if hwaddress_int
not in fdb_addrs
:
1004 def _query_sysctl(self
, ifaceobj
, ifaceobjcurr
):
1005 bridge_port
= ifaceobj
.link_privflags
& ifaceLinkPrivFlags
.BRIDGE_PORT
1006 ipforward
= ifaceobj
.get_attr_value_first('ip-forward')
1009 ifaceobjcurr
.status
= ifaceStatus
.ERROR
1010 ifaceobjcurr
.status_str
= ('\'ip-forward\' not supported ' +
1012 ifaceobjcurr
.update_config_with_status('ip-forward', 1, None)
1014 running_ipforward
= self
.read_file_oneline(
1015 '/proc/sys/net/ipv4/conf/%s/forwarding'
1017 running_ipforward
= utils
.get_boolean_from_string(running_ipforward
)
1018 config_ipforward
= utils
.get_boolean_from_string(ipforward
)
1019 ifaceobjcurr
.update_config_with_status(
1021 'on' if running_ipforward
else 'off',
1022 running_ipforward
!= config_ipforward
1025 ip6forward
= ifaceobj
.get_attr_value_first('ip6-forward')
1028 ifaceobjcurr
.status
= ifaceStatus
.ERROR
1029 ifaceobjcurr
.status_str
= ('\'ip6-forward\' not supported ' +
1031 ifaceobjcurr
.update_config_with_status('ip6-forward', 1, None)
1033 running_ip6forward
= self
.read_file_oneline(
1034 '/proc/sys/net/ipv6/conf/%s/forwarding'
1036 running_ip6forward
= utils
.get_boolean_from_string(running_ip6forward
)
1037 config_ip6forward
= utils
.get_boolean_from_string(ip6forward
)
1038 ifaceobjcurr
.update_config_with_status(
1040 'on' if running_ip6forward
else 'off',
1041 running_ip6forward
!= config_ip6forward
1043 mpls_enable
= ifaceobj
.get_attr_value_first('mpls-enable');
1045 running_mpls_enable
= self
.read_file_oneline(
1046 '/proc/sys/net/mpls/conf/%s/input'
1048 running_mpls_enable
= utils
.get_yesno_from_onezero(
1049 running_mpls_enable
)
1050 ifaceobjcurr
.update_config_with_status('mpls-enable',
1051 running_mpls_enable
,
1052 mpls_enable
!= running_mpls_enable
)
1055 def query_check_ipv6_addrgen(self
, ifaceobj
, ifaceobjcurr
):
1056 ipv6_addrgen
= ifaceobj
.get_attr_value_first('ipv6-addrgen')
1058 if not ipv6_addrgen
:
1061 if ipv6_addrgen
in utils
._string
_values
:
1062 ifaceobjcurr
.update_config_with_status(
1065 utils
.get_boolean_from_string(ipv6_addrgen
) == self
.ipcmd
.get_ipv6_addrgen_mode(ifaceobj
.name
)
1068 ifaceobjcurr
.update_config_with_status('ipv6-addrgen', ipv6_addrgen
, 1)
1070 def _query_check(self
, ifaceobj
, ifaceobjcurr
, ifaceobj_getfunc
=None):
1071 runningaddrsdict
= None
1072 if not self
.ipcmd
.link_exists(ifaceobj
.name
):
1073 self
.logger
.debug('iface %s not found' %ifaceobj
.name
)
1076 self
.query_check_ipv6_addrgen(ifaceobj
, ifaceobjcurr
)
1078 addr_method
= ifaceobj
.addr_method
1079 self
.query_n_update_ifaceobjcurr_attr(ifaceobj
, ifaceobjcurr
,
1080 'mtu', self
.ipcmd
.link_get_mtu
)
1081 hwaddress
= self
._get
_hwaddress
(ifaceobj
)
1083 rhwaddress
= self
.ipcmd
.link_get_hwaddress(ifaceobj
.name
)
1084 if not rhwaddress
or self
.ipcmd
.mac_str_to_int(rhwaddress
) != self
.ipcmd
.mac_str_to_int(hwaddress
):
1085 ifaceobjcurr
.update_config_with_status('hwaddress', rhwaddress
,
1087 elif not self
._check
_addresses
_in
_bridge
(ifaceobj
, hwaddress
):
1088 # XXX: hw address is not in bridge
1089 ifaceobjcurr
.update_config_with_status('hwaddress', rhwaddress
,
1091 ifaceobjcurr
.status_str
= 'bridge fdb error'
1093 ifaceobjcurr
.update_config_with_status('hwaddress', rhwaddress
,
1095 self
.query_n_update_ifaceobjcurr_attr(ifaceobj
, ifaceobjcurr
,
1096 'alias', self
.ipcmd
.link_get_alias
)
1097 self
._query
_sysctl
(ifaceobj
, ifaceobjcurr
)
1099 if addr_method
in ["dhcp", "ppp"]:
1101 addrs
= utils
.get_normalized_ip_addr(ifaceobj
.name
,
1102 self
._get
_iface
_addresses
(ifaceobj
))
1103 runningaddrsdict
= self
.ipcmd
.get_running_addrs(ifaceobj
)
1104 # if anycast address is configured on 'lo' and is in running config
1105 # add it to addrs so that query_check doesn't fail
1106 anycast_addr
= utils
.get_normalized_ip_addr(ifaceobj
.name
, ifaceobj
.get_attr_value_first('clagd-vxlan-anycast-ip'))
1108 anycast_addr
= anycast_addr
+'/32'
1109 if runningaddrsdict
and anycast_addr
and runningaddrsdict
.get(anycast_addr
):
1110 addrs
.append(anycast_addr
)
1112 # Set ifaceobjcurr method and family
1113 ifaceobjcurr
.addr_method
= ifaceobj
.addr_method
1114 ifaceobjcurr
.addr_family
= ifaceobj
.addr_family
1115 if not runningaddrsdict
and not addrs
:
1117 runningaddrs
= runningaddrsdict
.keys() if runningaddrsdict
else []
1118 # Add /32 netmask to configured address without netmask.
1119 # This may happen on interfaces where pointopoint is used.
1120 runningaddrs
= [ addr
if '/' in addr
else addr
+ '/32' for addr
in runningaddrs
]
1121 if runningaddrs
!= addrs
:
1122 runningaddrsset
= set(runningaddrs
) if runningaddrs
else set([])
1123 addrsset
= set(addrs
) if addrs
else set([])
1124 if (ifaceobj
.flags
& iface
.HAS_SIBLINGS
):
1127 # only check for addresses present in running config
1128 addrsdiff
= addrsset
.difference(runningaddrsset
)
1130 if addr
in addrsdiff
:
1131 ifaceobjcurr
.update_config_with_status('address',
1134 ifaceobjcurr
.update_config_with_status('address',
1137 addrsdiff
= addrsset
.symmetric_difference(runningaddrsset
)
1138 for addr
in addrsset
.union(runningaddrsset
):
1139 if addr
in addrsdiff
:
1140 ifaceobjcurr
.update_config_with_status('address',
1143 ifaceobjcurr
.update_config_with_status('address',
1146 [ifaceobjcurr
.update_config_with_status('address',
1147 addr
, 0) for addr
in addrs
]
1148 #XXXX Check broadcast address, scope, etc
1151 def query_running_ipv6_addrgen(self
, ifaceobjrunning
):
1152 ipv6_addrgen
= self
.ipcmd
.get_ipv6_addrgen_mode(ifaceobjrunning
.name
)
1155 ifaceobjrunning
.update_config('ipv6-addrgen', 'off')
1157 def _query_running(self
, ifaceobjrunning
, ifaceobj_getfunc
=None):
1158 if not self
.ipcmd
.link_exists(ifaceobjrunning
.name
):
1159 self
.logger
.debug('iface %s not found' %ifaceobjrunning
.name
)
1162 self
.query_running_ipv6_addrgen(ifaceobjrunning
)
1164 dhclientcmd
= dhclient()
1165 if (dhclientcmd
.is_running(ifaceobjrunning
.name
) or
1166 dhclientcmd
.is_running6(ifaceobjrunning
.name
)):
1167 # If dhcp is configured on the interface, we skip it
1169 isloopback
= self
.ipcmd
.link_isloopback(ifaceobjrunning
.name
)
1171 default_addrs
= ['127.0.0.1/8', '::1/128']
1172 ifaceobjrunning
.addr_family
.append('inet')
1173 ifaceobjrunning
.addr_method
= 'loopback'
1176 runningaddrsdict
= self
.ipcmd
.get_running_addrs(ifaceobjrunning
)
1177 if runningaddrsdict
:
1178 [ifaceobjrunning
.update_config('address', addr
)
1179 for addr
, addrattrs
in runningaddrsdict
.items()
1180 if addr
not in default_addrs
]
1181 mtu
= self
.ipcmd
.link_get_mtu(ifaceobjrunning
.name
)
1183 (ifaceobjrunning
.name
== 'lo' and mtu
!= '16436') or
1184 (ifaceobjrunning
.name
!= 'lo' and
1185 mtu
!= self
.get_mod_subattr('mtu', 'default'))):
1186 ifaceobjrunning
.update_config('mtu', mtu
)
1187 alias
= self
.ipcmd
.link_get_alias(ifaceobjrunning
.name
)
1189 ifaceobjrunning
.update_config('alias', alias
)
1191 ipforward
= self
.read_file_oneline(
1192 '/proc/sys/net/ipv4/conf/%s/forwarding'
1193 %ifaceobjrunning
.name
)
1196 _run_ops
= {'up' : _up
,
1198 'query-checkcurr' : _query_check
,
1199 'query-running' : _query_running
}
1202 """ returns list of ops supported by this module """
1203 return self
._run
_ops
.keys()
1205 def _init_command_handlers(self
):
1207 self
.ipcmd
= LinkUtils()
1209 def run(self
, ifaceobj
, operation
, query_ifaceobj
=None, ifaceobj_getfunc
=None):
1210 """ run address configuration on the interface object passed as argument
1213 **ifaceobj** (object): iface object
1215 **operation** (str): any of 'up', 'down', 'query-checkcurr',
1218 query_ifaceobj (object): query check ifaceobject. This is only
1219 valid when op is 'query-checkcurr'. It is an object same as
1220 ifaceobj, but contains running attribute values and its config
1221 status. The modules can use it to return queried running state
1222 of interfaces. status is success if the running state is same
1223 as user required state in ifaceobj. error otherwise.
1225 if ifaceobj
.type == ifaceType
.BRIDGE_VLAN
:
1227 op_handler
= self
._run
_ops
.get(operation
)
1230 self
._init
_command
_handlers
()
1231 if operation
== 'query-checkcurr':
1232 op_handler(self
, ifaceobj
, query_ifaceobj
,
1233 ifaceobj_getfunc
=ifaceobj_getfunc
)
1235 op_handler(self
, ifaceobj
,
1236 ifaceobj_getfunc
=ifaceobj_getfunc
)