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 self
.ipcmd
.bridge_fdb_add(bridgename
, hwaddress
, vlan
)
305 self
.ipcmd
.bridge_fdb_del(bridgename
, hwaddress
, vlan
)
307 def _get_anycast_addr(self
, ifaceobjlist
):
308 for ifaceobj
in ifaceobjlist
:
309 anycast_addr
= ifaceobj
.get_attr_value_first('clagd-vxlan-anycast-ip')
311 anycast_addr
= anycast_addr
+'/32'
315 def _inet_address_convert_to_cidr(self
, ifaceobjlist
):
319 for ifaceobj
in ifaceobjlist
:
320 addrs
= ifaceobj
.get_attr_value('address')
324 if not self
.syntax_check_addr_allowed_on(ifaceobj
,
326 return (False, newaddrs
, newaddr_attrs
)
327 # If user address is not in CIDR notation, convert them to CIDR
328 for addr_index
in range(0, len(addrs
)):
329 addr
= addrs
[addr_index
]
332 newaddrs
.append(addr
)
334 netmask
= ifaceobj
.get_attr_value_n('netmask', addr_index
)
336 prefixlen
= IPNetwork('%s' %addr
+
337 '/%s' %netmask
).prefixlen
338 newaddr
= addr
+ '/%s' %prefixlen
340 # we are here because there is no slash (/xx) and no netmask
341 # just let IPNetwork handle the ipv4 or ipv6 address mask
342 prefixlen
= IPNetwork(addr
).prefixlen
343 newaddr
= addr
+ '/%s' %prefixlen
344 newaddrs
.append(newaddr
)
347 for a
in ['broadcast', 'pointopoint', 'scope',
348 'preferred-lifetime']:
349 aval
= ifaceobj
.get_attr_value_n(a
, addr_index
)
354 newaddr_attrs
[newaddr
]= attrs
355 return (True, newaddrs
, newaddr_attrs
)
357 def _inet_address_list_config(self
, ifaceobj
, newaddrs
, newaddr_attrs
):
358 for addr_index
in range(0, len(newaddrs
)):
361 self
.ipcmd
.addr_add(ifaceobj
.name
, newaddrs
[addr_index
],
362 newaddr_attrs
.get(newaddrs
[addr_index
],
363 {}).get('broadcast'),
364 newaddr_attrs
.get(newaddrs
[addr_index
],
365 {}).get('pointopoint'),
366 newaddr_attrs
.get(newaddrs
[addr_index
],
368 newaddr_attrs
.get(newaddrs
[addr_index
],
369 {}).get('preferred-lifetime'))
371 self
.ipcmd
.addr_add(ifaceobj
.name
, newaddrs
[addr_index
])
373 self
.log_error(str(e
), ifaceobj
)
375 def _inet_address_config(self
, ifaceobj
, ifaceobj_getfunc
=None,
376 force_reapply
=False):
377 squash_addr_config
= (True if \
378 ifupdownconfig
.config
.get('addr_config_squash', \
379 '0') == '1' else False)
381 if (squash_addr_config
and
382 not (ifaceobj
.flags
& ifaceobj
.YOUNGEST_SIBLING
)):
385 purge_addresses
= ifaceobj
.get_attr_value_first('address-purge')
386 if not purge_addresses
:
387 purge_addresses
= 'yes'
389 if squash_addr_config
and ifaceobj
.flags
& iface
.HAS_SIBLINGS
:
390 ifaceobjlist
= ifaceobj_getfunc(ifaceobj
.name
)
392 ifaceobjlist
= [ifaceobj
]
394 module_name
= self
.__class
__.__name
__
395 ifname
= ifaceobj
.name
397 (addr_supported
, newaddrs
, newaddr_attrs
) = self
._inet
_address
_convert
_to
_cidr
(ifaceobjlist
)
398 newaddrs
= utils
.get_ip_objs(module_name
, ifname
, newaddrs
)
400 if not addr_supported
:
402 if (not squash_addr_config
and (ifaceobj
.flags
& iface
.HAS_SIBLINGS
)):
403 # if youngest sibling and squash addr is not set
404 # print a warning that addresses will not be purged
405 if (ifaceobj
.flags
& iface
.YOUNGEST_SIBLING
):
406 self
.logger
.warn('%s: interface has multiple ' %ifaceobj
.name
+
407 'iface stanzas, skip purging existing addresses')
408 purge_addresses
= 'no'
410 if not ifupdownflags
.flags
.PERFMODE
and purge_addresses
== 'yes':
411 # if perfmode is not set and purge addresses is not set to 'no'
412 # lets purge addresses not in the config
413 runningaddrs
= self
.ipcmd
.get_running_addrs(ifaceobj
, details
=False)
415 # if anycast address is configured on 'lo' and is in running config
416 # add it to newaddrs so that ifreload doesn't wipe it out
417 anycast_addr
= utils
.get_normalized_ip_addr(ifaceobj
.name
, self
._get
_anycast
_addr
(ifaceobjlist
))
419 if runningaddrs
and anycast_addr
and anycast_addr
in runningaddrs
:
420 newaddrs
.append(anycast_addr
)
422 user_ip4
, user_ip6
, newaddrs
= self
.order_user_configured_addrs(newaddrs
)
424 if newaddrs
== runningaddrs
or self
.compare_running_ips_and_user_config(user_ip4
, user_ip6
, runningaddrs
):
426 self
._inet
_address
_list
_config
(ifaceobj
, newaddrs
, newaddr_attrs
)
429 # if primary address is not same, there is no need to keep any.
430 # reset all addresses
431 if newaddrs
and runningaddrs
and newaddrs
[0] != runningaddrs
[0]:
434 skip_addrs
= newaddrs
or []
435 for addr
in runningaddrs
or []:
436 if addr
in skip_addrs
:
438 self
.ipcmd
.addr_del(ifaceobj
.name
, addr
)
440 self
.log_warn(str(e
))
443 self
._inet
_address
_list
_config
(ifaceobj
, newaddrs
, newaddr_attrs
)
445 def compare_running_ips_and_user_config(self
, user_ip4
, user_ip6
, running_addrs
):
447 We need to compare the user config ips and the running ips.
448 ip4 ordering matters (primary etc) but ip6 order doesn't matter
450 this function replaces the strict comparison previously in place
451 if newaddrs == running_addrs ?
453 We will compare if the ip4 ordering is correct, then check if all
454 ip6 are present in the list (without checking the ordering)
456 if (user_ip4
or user_ip6
) and not running_addrs
:
458 elif running_addrs
and not user_ip4
and not user_ip6
:
460 elif not running_addrs
and not user_ip4
and not user_ip6
:
463 len_ip4
= len(user_ip4
)
464 len_running_addrs
= len(running_addrs
)
466 if len_ip4
> len_running_addrs
:
471 if user_ip4
[i
] != running_addrs
[i
]:
476 running_ip6
= running_addrs
[len_ip4
:]
478 running_ip6
= running_addrs
481 len_ip6
= len(user_ip6
)
483 for ip6
in running_ip6
:
484 if ip6
not in user_ip6
:
490 def order_user_configured_addrs(self
, user_config_addrs
):
494 for a
in user_config_addrs
:
495 if isinstance(a
, _BaseV6
):
500 return ip4
, ip6
, ip4
+ ip6
502 def _delete_gateway(self
, ifaceobj
, gateways
, vrf
, metric
):
503 for del_gw
in gateways
:
505 self
.ipcmd
.route_del_gateway(ifaceobj
.name
, del_gw
, vrf
, metric
)
506 except Exception as e
:
507 self
.logger
.debug('%s: %s' % (ifaceobj
.name
, str(e
)))
509 def _add_delete_gateway(self
, ifaceobj
, gateways
=[], prev_gw
=[]):
510 vrf
= ifaceobj
.get_attr_value_first('vrf')
511 metric
= ifaceobj
.get_attr_value_first('metric')
512 self
._delete
_gateway
(ifaceobj
, list(set(prev_gw
) - set(gateways
)),
514 for add_gw
in gateways
:
516 self
.ipcmd
.route_add_gateway(ifaceobj
.name
, add_gw
, vrf
, metric
, onlink
=self
.l3_intf_default_gateway_set_onlink
)
517 except Exception as e
:
518 self
.log_error('%s: %s' % (ifaceobj
.name
, str(e
)))
520 def _get_prev_gateway(self
, ifaceobj
, gateways
):
522 saved_ifaceobjs
= statemanager
.statemanager_api
.get_ifaceobjs(ifaceobj
.name
)
523 if not saved_ifaceobjs
:
525 prev_gateways
= saved_ifaceobjs
[0].get_attr_value('gateway')
526 if not prev_gateways
:
530 def _check_mtu_config(self
, ifaceobj
, mtu
, ifaceobj_getfunc
, syntaxcheck
=False):
532 if (ifaceobj
.link_kind
& ifaceLinkKind
.BRIDGE
):
534 self
.logger
.warn('%s: bridge inherits mtu from its ports. There is no need to assign mtu on a bridge' %ifaceobj
.name
)
537 self
.logger
.info('%s: bridge inherits mtu from its ports. There is no need to assign mtu on a bridge' %ifaceobj
.name
)
538 elif ifaceobj_getfunc
:
539 if ((ifaceobj
.link_privflags
& ifaceLinkPrivFlags
.BOND_SLAVE
) and
540 ifaceobj
.upperifaces
):
541 masterobj
= ifaceobj_getfunc(ifaceobj
.upperifaces
[0])
543 master_mtu
= masterobj
[0].get_attr_value_first('mtu')
544 if master_mtu
and master_mtu
!= mtu
:
546 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
))
549 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
))
550 elif ((ifaceobj
.link_kind
& ifaceLinkKind
.VLAN
) and
551 ifaceobj
.lowerifaces
):
552 lowerobj
= ifaceobj_getfunc(ifaceobj
.lowerifaces
[0])
555 lowerdev_mtu
= lowerobj
[0].get_attr_value_first('mtu')
557 lowerdev_mtu
= self
.ipcmd
.link_get_mtu_sysfs(lowerobj
[0].name
)
558 if lowerdev_mtu
and int(mtu
) > int(lowerdev_mtu
):
559 self
.logger
.warn('%s: vlan dev mtu %s is greater than lower realdev %s mtu %s'
560 %(ifaceobj
.name
, mtu
, lowerobj
[0].name
, lowerdev_mtu
))
562 elif (not lowerobj
[0].link_kind
and
563 not (lowerobj
[0].link_privflags
& ifaceLinkPrivFlags
.LOOPBACK
) and
564 not lowerdev_mtu
and self
.default_mtu
and
565 (int(mtu
) > int(self
.default_mtu
))):
566 # only check default mtu on lower device which is a physical interface
567 self
.logger
.warn('%s: vlan dev mtu %s is greater than lower realdev %s mtu %s'
568 %(ifaceobj
.name
, mtu
, lowerobj
[0].name
, self
.default_mtu
))
570 if self
.max_mtu
and mtu
> self
.max_mtu
:
571 self
.logger
.warn('%s: specified mtu %s is greater than max mtu %s'
572 %(ifaceobj
.name
, mtu
, self
.max_mtu
))
576 def _propagate_mtu_to_upper_devs(self
, ifaceobj
, mtu
, ifaceobj_getfunc
):
577 if (not ifaceobj
.upperifaces
or
578 (ifaceobj
.link_privflags
& ifaceLinkPrivFlags
.BOND_SLAVE
) or
579 (ifaceobj
.link_privflags
& ifaceLinkPrivFlags
.VRF_SLAVE
) or
580 (ifaceobj
.link_privflags
& ifaceLinkPrivFlags
.BRIDGE_PORT
)):
582 for u
in ifaceobj
.upperifaces
:
583 upperobjs
= ifaceobj_getfunc(u
)
585 not (upperobjs
[0].link_kind
& ifaceLinkKind
.VLAN
)):
587 # only adjust mtu for vlan devices on ifaceobj
588 umtu
= upperobjs
[0].get_attr_value_first('mtu')
590 running_mtu
= self
.ipcmd
.link_get_mtu(upperobjs
[0].name
)
591 if not running_mtu
or (running_mtu
!= mtu
):
592 self
.ipcmd
.link_set(u
, 'mtu', mtu
)
594 def _process_mtu_config(self
, ifaceobj
, ifaceobj_getfunc
, mtu
):
596 if not self
._check
_mtu
_config
(ifaceobj
, mtu
, ifaceobj_getfunc
):
598 cached_running_mtu
= self
.ipcmd
.link_get_mtu(ifaceobj
.name
)
599 running_mtu
= self
.ipcmd
.link_get_mtu_sysfs(ifaceobj
.name
)
600 if not running_mtu
or (running_mtu
and running_mtu
!= mtu
):
601 force
= cached_running_mtu
!= running_mtu
602 self
.ipcmd
.link_set(ifaceobj
.name
, 'mtu', mtu
, force
=force
)
603 if (not ifupdownflags
.flags
.ALL
and
604 not ifaceobj
.link_kind
and
605 ifupdownconfig
.config
.get('adjust_logical_dev_mtu', '1') != '0'):
606 # This is additional cost to us, so do it only when
607 # ifupdown2 is called on a particular interface and
608 # it is a physical interface
609 self
._propagate
_mtu
_to
_upper
_devs
(ifaceobj
, mtu
, ifaceobj_getfunc
)
612 if ifaceobj
.link_kind
:
613 # bonds, vxlan and custom devices (like dummy) need an explicit set of mtu.
614 # bridges don't need mtu set
615 if (ifaceobj
.link_kind
& ifaceLinkKind
.BOND
or
616 ifaceobj
.link_kind
& ifaceLinkKind
.VXLAN
or
617 ifaceobj
.link_kind
& ifaceLinkKind
.OTHER
619 running_mtu
= self
.ipcmd
.link_get_mtu(ifaceobj
.name
)
620 if (self
.default_mtu
and running_mtu
!= self
.default_mtu
):
621 self
.ipcmd
.link_set(ifaceobj
.name
, 'mtu', self
.default_mtu
)
623 if (ifupdownconfig
.config
.get('adjust_logical_dev_mtu', '1') != '0'
624 and ifaceobj
.lowerifaces
):
625 # set vlan interface mtu to lower device mtu
626 if (ifaceobj
.link_kind
& ifaceLinkKind
.VLAN
):
627 lower_iface
= ifaceobj
.lowerifaces
[0]
628 if lower_iface
not in self
.lower_iface_mtu_checked_list
:
629 lower_iface_mtu
= self
.ipcmd
.link_get_mtu_sysfs(lower_iface
)
630 self
.ipcmd
.cache_update([lower_iface
, 'mtu'], lower_iface_mtu
)
631 self
.lower_iface_mtu_checked_list
.append(lower_iface
)
633 lower_iface_mtu
= self
.ipcmd
.link_get_mtu(lower_iface
)
635 if lower_iface_mtu
!= self
.ipcmd
.link_get_mtu_sysfs(ifaceobj
.name
):
636 self
.ipcmd
.link_set_mtu(ifaceobj
.name
, lower_iface_mtu
)
638 elif (not (ifaceobj
.name
== 'lo') and not ifaceobj
.link_kind
and
639 not (ifaceobj
.link_privflags
& ifaceLinkPrivFlags
.BOND_SLAVE
) and
641 # logical devices like bridges and vlan devices rely on mtu
642 # from their lower devices. ie mtu travels from
643 # lower devices to upper devices. For bonds mtu travels from
644 # upper to lower devices. running mtu depends on upper and
645 # lower device mtu. With all this implicit mtu
646 # config by the kernel in play, we try to be cautious here
647 # on which devices we want to reset mtu to default.
648 # essentially only physical interfaces which are not bond slaves
649 running_mtu
= self
.ipcmd
.link_get_mtu(ifaceobj
.name
)
650 if running_mtu
!= self
.default_mtu
:
651 self
.ipcmd
.link_set(ifaceobj
.name
, 'mtu', self
.default_mtu
)
653 def _set_bridge_forwarding(self
, ifaceobj
):
654 """ set ip forwarding to 0 if bridge interface does not have a
656 ifname
= ifaceobj
.name
657 if not ifaceobj
.upperifaces
and not ifaceobj
.get_attr_value('address'):
658 if self
.sysctl_get_forwarding_value_from_proc(ifname
, "ipv4") == '1':
659 self
.sysctl_write_forwarding_value_to_proc(ifname
, "ipv4", 0)
660 if self
.sysctl_get_forwarding_value_from_proc(ifname
, "ipv6") == '1':
661 self
.sysctl_write_forwarding_value_to_proc(ifname
, "ipv6", 0)
663 if self
.sysctl_get_forwarding_value_from_proc(ifname
, "ipv4") == '0':
664 self
.sysctl_write_forwarding_value_to_proc(ifname
, "ipv4", 1)
665 if self
.sysctl_get_forwarding_value_from_proc(ifname
, "ipv6") == '0':
666 self
.sysctl_write_forwarding_value_to_proc(ifname
, "ipv6", 1)
668 def sysctl_get_forwarding_value_from_proc(self
, ifname
, family
):
669 return self
.read_file_oneline("/proc/sys/net/%s/conf/%s/forwarding" % (family
, ifname
))
671 def sysctl_write_forwarding_value_to_proc(self
, ifname
, family
, value
):
672 self
.write_file("/proc/sys/net/%s/conf/%s/forwarding" % (family
, ifname
), "%s\n" % value
)
674 def _sysctl_config(self
, ifaceobj
):
675 setting_default_value
= False
676 mpls_enable
= ifaceobj
.get_attr_value_first('mpls-enable');
678 setting_default_value
= True
679 mpls_enable
= self
.get_mod_subattr('mpls-enable', 'default')
680 mpls_enable
= utils
.boolean_support_binary(mpls_enable
)
681 # File read has been used for better performance
682 # instead of using sysctl command
683 if ifupdownflags
.flags
.PERFMODE
:
684 running_mpls_enable
= '0'
686 running_mpls_enable
= self
.read_file_oneline(
687 '/proc/sys/net/mpls/conf/%s/input'
691 if mpls_enable
!= running_mpls_enable
:
693 self
.sysctl_set('net.mpls.conf.%s.input'
694 %('/'.join(ifaceobj
.name
.split("."))),
696 except Exception as e
:
697 if not setting_default_value
:
698 ifaceobj
.status
= ifaceStatus
.ERROR
699 self
.logger
.error('%s: %s' %(ifaceobj
.name
, str(e
)))
701 if (ifaceobj
.link_kind
& ifaceLinkKind
.BRIDGE
):
702 self
._set
_bridge
_forwarding
(ifaceobj
)
704 if not self
.syntax_check_sysctls(ifaceobj
):
706 ipforward
= ifaceobj
.get_attr_value_first('ip-forward')
707 ip6forward
= ifaceobj
.get_attr_value_first('ip6-forward')
708 if ifupdownflags
.flags
.PERFMODE
:
710 self
.sysctl_set('net.ipv4.conf.%s.forwarding'
711 %('/'.join(ifaceobj
.name
.split("."))),
712 utils
.boolean_support_binary(ipforward
))
714 self
.sysctl_set('net.ipv6.conf.%s.forwarding'
715 %('/'.join(ifaceobj
.name
.split("."))),
716 utils
.boolean_support_binary(ip6forward
))
718 bridge_port
= ifaceobj
.link_privflags
& ifaceLinkPrivFlags
.BRIDGE_PORT
721 self
.log_error('%s: \'ip-forward\' is not supported for '
722 'bridge port' %ifaceobj
.name
)
724 self
.log_error('%s: \'ip6-forward\' is not supported for '
725 'bridge port' %ifaceobj
.name
)
728 setting_default_value
= False
730 setting_default_value
= True
731 ipforward
= self
.ipforward
734 ipforward
= utils
.boolean_support_binary(ipforward
)
735 # File read has been used for better performance
736 # instead of using sysctl command
737 running_ipforward
= self
.read_file_oneline(
738 '/proc/sys/net/ipv4/conf/%s/forwarding'
741 if ipforward
!= running_ipforward
:
744 self
.sysctl_set('net.ipv4.conf.%s.forwarding'
745 %('/'.join(ifaceobj
.name
.split("."))),
747 except Exception as e
:
748 if not setting_default_value
:
749 ifaceobj
.status
= ifaceStatus
.ERROR
750 self
.logger
.error('%s: %s' %(ifaceobj
.name
, str(e
)))
753 setting_default_value
= False
755 setting_default_value
= True
756 ip6forward
= self
.ip6forward
759 ip6forward
= utils
.boolean_support_binary(ip6forward
)
760 # File read has been used for better performance
761 # instead of using sysctl command
762 running_ip6forward
= self
.read_file_oneline(
763 '/proc/sys/net/ipv6/conf/%s/forwarding'
765 if ip6forward
!= running_ip6forward
:
767 self
.sysctl_set('net.ipv6.conf.%s.forwarding'
768 %('/'.join(ifaceobj
.name
.split("."))),
770 except Exception as e
:
771 # There is chance of ipv6 being removed because of,
772 # for example, setting mtu < 1280
773 # In such cases, log error only if user has configured
775 if not setting_default_value
:
776 ifaceobj
.status
= ifaceStatus
.ERROR
777 self
.logger
.error('%s: %s' %(ifaceobj
.name
, str(e
)))
779 def process_mtu(self
, ifaceobj
, ifaceobj_getfunc
):
780 mtu
= ifaceobj
.get_attr_value_first('mtu')
783 default_iface_mtu
= self
.ifaces_defaults
.get(ifaceobj
.name
, {}).get('mtu')
785 if default_iface_mtu
:
787 mtu
= default_iface_mtu
788 int(default_iface_mtu
)
789 except Exception as e
:
790 self
.logger
.warning('%s: MTU value from policy file: %s' % (ifaceobj
.name
, str(e
)))
793 self
._process
_mtu
_config
(ifaceobj
, ifaceobj_getfunc
, mtu
)
795 def up_ipv6_addrgen(self
, ifaceobj
):
796 user_configured_ipv6_addrgen
= ifaceobj
.get_attr_value_first('ipv6-addrgen')
798 if not user_configured_ipv6_addrgen
and ifupdownflags
.flags
.PERFMODE
:
799 # no need to go further during perfmode (boot)
802 if not user_configured_ipv6_addrgen
and ifaceobj
.addr_method
== 'dhcp':
805 if not user_configured_ipv6_addrgen
:
806 # if user didn't configure ipv6-addrgen, should we reset to default?
807 user_configured_ipv6_addrgen
= self
.get_attr_default_value('ipv6-addrgen')
816 }.get(user_configured_ipv6_addrgen
.lower(), None)
818 if ipv6_addrgen_nl
is not None:
819 self
.ipcmd
.ipv6_addrgen(ifaceobj
.name
, ipv6_addrgen_nl
, link_created
=True)
820 # link_create=False will flush the addr cache of that intf
822 self
.logger
.warning('%s: invalid value "%s" for attribute ipv6-addrgen' % (ifaceobj
.name
, user_configured_ipv6_addrgen
))
824 def _up(self
, ifaceobj
, ifaceobj_getfunc
=None):
825 if not self
.ipcmd
.link_exists(ifaceobj
.name
):
828 if not self
.syntax_check_enable_l3_iface_forwardings(ifaceobj
, ifaceobj_getfunc
):
831 alias
= ifaceobj
.get_attr_value_first('alias')
832 current_alias
= self
.ipcmd
.link_get_alias(ifaceobj
.name
)
833 if alias
and alias
!= current_alias
:
834 self
.ipcmd
.link_set_alias(ifaceobj
.name
, alias
)
835 elif not alias
and current_alias
:
836 self
.ipcmd
.link_set_alias(ifaceobj
.name
, '')
838 self
._sysctl
_config
(ifaceobj
)
840 addr_method
= ifaceobj
.addr_method
841 force_reapply
= False
843 # release any stale dhcp addresses if present
844 if (addr_method
not in ["dhcp", "ppp"] and not ifupdownflags
.flags
.PERFMODE
and
845 not (ifaceobj
.flags
& iface
.HAS_SIBLINGS
)):
846 # if not running in perf mode and ifaceobj does not have
847 # any sibling iface objects, kill any stale dhclient
849 dhclientcmd
= dhclient()
850 if dhclientcmd
.is_running(ifaceobj
.name
):
851 # release any dhcp leases
852 dhclientcmd
.release(ifaceobj
.name
)
854 elif dhclientcmd
.is_running6(ifaceobj
.name
):
855 dhclientcmd
.release6(ifaceobj
.name
)
860 self
.ipcmd
.batch_start()
861 self
.up_ipv6_addrgen(ifaceobj
)
863 if addr_method
not in ["dhcp", "ppp"]:
864 self
._inet
_address
_config
(ifaceobj
, ifaceobj_getfunc
,
867 self
.process_mtu(ifaceobj
, ifaceobj_getfunc
)
870 self
.ipcmd
.batch_commit()
871 except Exception as e
:
872 self
.log_error('%s: %s' % (ifaceobj
.name
, str(e
)), ifaceobj
, raise_error
=False)
874 self
.up_hwaddress(ifaceobj
)
876 gateways
= ifaceobj
.get_attr_value('gateway')
879 prev_gw
= self
._get
_prev
_gateway
(ifaceobj
, gateways
)
880 self
._add
_delete
_gateway
(ifaceobj
, gateways
, prev_gw
)
882 def up_hwaddress(self
, ifaceobj
):
884 hwaddress
= self
._get
_hwaddress
(ifaceobj
)
887 if not ifupdownflags
.flags
.PERFMODE
: # system is clean
888 running_hwaddress
= self
.ipcmd
.link_get_hwaddress(ifaceobj
.name
)
890 running_hwaddress
= None
892 if self
.ipcmd
.mac_str_to_int(running_hwaddress
) != self
.ipcmd
.mac_str_to_int(hwaddress
):
894 netlink
.link_set_updown(ifaceobj
.name
, "down")
895 if ifaceobj
.link_kind
& ifaceLinkKind
.BOND
:
896 # if bond, down all the slaves
897 if ifaceobj
.lowerifaces
:
898 for l
in ifaceobj
.lowerifaces
:
899 netlink
.link_set_updown(l
, "down")
902 self
.ipcmd
.link_set_hwaddress(ifaceobj
.name
, hwaddress
, force
=True)
904 netlink
.link_set_updown(ifaceobj
.name
, "up")
906 for l
in ifaceobj
.lowerifaces
:
907 netlink
.link_set_updown(l
, "up")
909 # Handle special things on a bridge
910 self
._process
_bridge
(ifaceobj
, True)
912 self
.log_error('%s: %s' % (ifaceobj
.name
, str(e
)), ifaceobj
)
914 def _down(self
, ifaceobj
, ifaceobj_getfunc
=None):
916 if not self
.ipcmd
.link_exists(ifaceobj
.name
):
918 addr_method
= ifaceobj
.addr_method
919 if addr_method
not in ["dhcp", "ppp"]:
920 if ifaceobj
.get_attr_value_first('address-purge')=='no':
921 addrlist
= ifaceobj
.get_attr_value('address')
922 for addr
in addrlist
:
923 self
.ipcmd
.addr_del(ifaceobj
.name
, addr
)
924 #self.ipcmd.addr_del(ifaceobj.name, ifaceobj.get_attr_value('address')[0])
925 elif not ifaceobj
.link_kind
:
926 # for logical interfaces we don't need to remove the ip addresses
927 # kernel will do it for us on 'ip link del'
928 self
.ipcmd
.del_addr_all(ifaceobj
.name
)
929 gateways
= ifaceobj
.get_attr_value('gateway')
931 self
._delete
_gateway
(ifaceobj
, gateways
,
932 ifaceobj
.get_attr_value_first('vrf'),
933 ifaceobj
.get_attr_value_first('metric'))
934 mtu
= ifaceobj
.get_attr_value_first('mtu')
935 if (not ifaceobj
.link_kind
and mtu
and
936 self
.default_mtu
and (mtu
!= self
.default_mtu
)):
937 self
.ipcmd
.link_set(ifaceobj
.name
, 'mtu', self
.default_mtu
)
938 alias
= ifaceobj
.get_attr_value_first('alias')
940 self
.write_file('/sys/class/net/%s/ifalias' % ifaceobj
.name
, '\n')
941 # XXX hwaddress reset cannot happen because we dont know last
944 # Handle special things on a bridge
945 self
._process
_bridge
(ifaceobj
, False)
947 self
.logger
.debug('%s : %s' %(ifaceobj
.name
, str(e
)))
950 def _get_iface_addresses(self
, ifaceobj
):
951 addrlist
= ifaceobj
.get_attr_value('address')
954 if not addrlist
: return None
955 for addrindex
in range(0, len(addrlist
)):
956 addr
= addrlist
[addrindex
]
957 netmask
= ifaceobj
.get_attr_value_n('netmask', addrindex
)
959 prefixlen
= IPNetwork('%s' %addr
+
960 '/%s' %netmask
).prefixlen
961 addr
= addr
+ '/%s' %prefixlen
962 outaddrlist
.append(addr
)
965 def _get_bridge_fdbs(self
, bridgename
, vlan
):
966 fdbs
= self
._bridge
_fdb
_query
_cache
.get(bridgename
)
968 fdbs
= self
.ipcmd
.bridge_fdb_show_dev(bridgename
)
971 self
._bridge
_fdb
_query
_cache
[bridgename
] = fdbs
972 return fdbs
.get(vlan
)
974 def _check_addresses_in_bridge(self
, ifaceobj
, hwaddress
):
975 """ If the device is a bridge, make sure the addresses
976 are in the bridge """
977 if ifaceobj
.link_kind
& ifaceLinkKind
.VLAN
:
978 bridgename
= ifaceobj
.lowerifaces
[0]
979 vlan
= self
._get
_vlan
_id
(ifaceobj
)
980 if self
.ipcmd
.bridge_is_vlan_aware(bridgename
):
981 fdb_addrs
= [self
.ipcmd
.mac_str_to_int(fdb_addr
) for fdb_addr
in self
._get
_bridge
_fdbs
(bridgename
, str(vlan
))]
984 hwaddress_int
= self
.ipcmd
.mac_str_to_int(hwaddress
)
985 if hwaddress_int
not in fdb_addrs
:
989 def _query_sysctl(self
, ifaceobj
, ifaceobjcurr
):
990 bridge_port
= ifaceobj
.link_privflags
& ifaceLinkPrivFlags
.BRIDGE_PORT
991 ipforward
= ifaceobj
.get_attr_value_first('ip-forward')
994 ifaceobjcurr
.status
= ifaceStatus
.ERROR
995 ifaceobjcurr
.status_str
= ('\'ip-forward\' not supported ' +
997 ifaceobjcurr
.update_config_with_status('ip-forward', 1, None)
999 running_ipforward
= self
.read_file_oneline(
1000 '/proc/sys/net/ipv4/conf/%s/forwarding'
1002 running_ipforward
= utils
.get_boolean_from_string(running_ipforward
)
1003 config_ipforward
= utils
.get_boolean_from_string(ipforward
)
1004 ifaceobjcurr
.update_config_with_status(
1006 'on' if running_ipforward
else 'off',
1007 running_ipforward
!= config_ipforward
1010 ip6forward
= ifaceobj
.get_attr_value_first('ip6-forward')
1013 ifaceobjcurr
.status
= ifaceStatus
.ERROR
1014 ifaceobjcurr
.status_str
= ('\'ip6-forward\' not supported ' +
1016 ifaceobjcurr
.update_config_with_status('ip6-forward', 1, None)
1018 running_ip6forward
= self
.read_file_oneline(
1019 '/proc/sys/net/ipv6/conf/%s/forwarding'
1021 running_ip6forward
= utils
.get_boolean_from_string(running_ip6forward
)
1022 config_ip6forward
= utils
.get_boolean_from_string(ip6forward
)
1023 ifaceobjcurr
.update_config_with_status(
1025 'on' if running_ip6forward
else 'off',
1026 running_ip6forward
!= config_ip6forward
1028 mpls_enable
= ifaceobj
.get_attr_value_first('mpls-enable');
1030 running_mpls_enable
= self
.read_file_oneline(
1031 '/proc/sys/net/mpls/conf/%s/input'
1033 running_mpls_enable
= utils
.get_yesno_from_onezero(
1034 running_mpls_enable
)
1035 ifaceobjcurr
.update_config_with_status('mpls-enable',
1036 running_mpls_enable
,
1037 mpls_enable
!= running_mpls_enable
)
1040 def query_check_ipv6_addrgen(self
, ifaceobj
, ifaceobjcurr
):
1041 ipv6_addrgen
= ifaceobj
.get_attr_value_first('ipv6-addrgen')
1043 if not ipv6_addrgen
:
1046 if ipv6_addrgen
in utils
._string
_values
:
1047 ifaceobjcurr
.update_config_with_status(
1050 utils
.get_boolean_from_string(ipv6_addrgen
) == self
.ipcmd
.get_ipv6_addrgen_mode(ifaceobj
.name
)
1053 ifaceobjcurr
.update_config_with_status('ipv6-addrgen', ipv6_addrgen
, 1)
1055 def _query_check(self
, ifaceobj
, ifaceobjcurr
, ifaceobj_getfunc
=None):
1056 runningaddrsdict
= None
1057 if not self
.ipcmd
.link_exists(ifaceobj
.name
):
1058 self
.logger
.debug('iface %s not found' %ifaceobj
.name
)
1061 self
.query_check_ipv6_addrgen(ifaceobj
, ifaceobjcurr
)
1063 addr_method
= ifaceobj
.addr_method
1064 self
.query_n_update_ifaceobjcurr_attr(ifaceobj
, ifaceobjcurr
,
1065 'mtu', self
.ipcmd
.link_get_mtu
)
1066 hwaddress
= self
._get
_hwaddress
(ifaceobj
)
1068 rhwaddress
= self
.ipcmd
.link_get_hwaddress(ifaceobj
.name
)
1069 if not rhwaddress
or self
.ipcmd
.mac_str_to_int(rhwaddress
) != self
.ipcmd
.mac_str_to_int(hwaddress
):
1070 ifaceobjcurr
.update_config_with_status('hwaddress', rhwaddress
,
1072 elif not self
._check
_addresses
_in
_bridge
(ifaceobj
, hwaddress
):
1073 # XXX: hw address is not in bridge
1074 ifaceobjcurr
.update_config_with_status('hwaddress', rhwaddress
,
1076 ifaceobjcurr
.status_str
= 'bridge fdb error'
1078 ifaceobjcurr
.update_config_with_status('hwaddress', rhwaddress
,
1080 self
.query_n_update_ifaceobjcurr_attr(ifaceobj
, ifaceobjcurr
,
1081 'alias', self
.ipcmd
.link_get_alias
)
1082 self
._query
_sysctl
(ifaceobj
, ifaceobjcurr
)
1084 if addr_method
in ["dhcp", "ppp"]:
1086 addrs
= utils
.get_normalized_ip_addr(ifaceobj
.name
,
1087 self
._get
_iface
_addresses
(ifaceobj
))
1088 runningaddrsdict
= self
.ipcmd
.get_running_addrs(ifaceobj
)
1089 # if anycast address is configured on 'lo' and is in running config
1090 # add it to addrs so that query_check doesn't fail
1091 anycast_addr
= utils
.get_normalized_ip_addr(ifaceobj
.name
, ifaceobj
.get_attr_value_first('clagd-vxlan-anycast-ip'))
1093 anycast_addr
= anycast_addr
+'/32'
1094 if runningaddrsdict
and anycast_addr
and runningaddrsdict
.get(anycast_addr
):
1095 addrs
.append(anycast_addr
)
1097 # Set ifaceobjcurr method and family
1098 ifaceobjcurr
.addr_method
= ifaceobj
.addr_method
1099 ifaceobjcurr
.addr_family
= ifaceobj
.addr_family
1100 if not runningaddrsdict
and not addrs
:
1102 runningaddrs
= runningaddrsdict
.keys() if runningaddrsdict
else []
1103 # Add /32 netmask to configured address without netmask.
1104 # This may happen on interfaces where pointopoint is used.
1105 runningaddrs
= [ addr
if '/' in addr
else addr
+ '/32' for addr
in runningaddrs
]
1106 if runningaddrs
!= addrs
:
1107 runningaddrsset
= set(runningaddrs
) if runningaddrs
else set([])
1108 addrsset
= set(addrs
) if addrs
else set([])
1109 if (ifaceobj
.flags
& iface
.HAS_SIBLINGS
):
1112 # only check for addresses present in running config
1113 addrsdiff
= addrsset
.difference(runningaddrsset
)
1115 if addr
in addrsdiff
:
1116 ifaceobjcurr
.update_config_with_status('address',
1119 ifaceobjcurr
.update_config_with_status('address',
1122 addrsdiff
= addrsset
.symmetric_difference(runningaddrsset
)
1123 for addr
in addrsset
.union(runningaddrsset
):
1124 if addr
in addrsdiff
:
1125 ifaceobjcurr
.update_config_with_status('address',
1128 ifaceobjcurr
.update_config_with_status('address',
1131 [ifaceobjcurr
.update_config_with_status('address',
1132 addr
, 0) for addr
in addrs
]
1133 #XXXX Check broadcast address, scope, etc
1136 def query_running_ipv6_addrgen(self
, ifaceobjrunning
):
1137 ipv6_addrgen
= self
.ipcmd
.get_ipv6_addrgen_mode(ifaceobjrunning
.name
)
1140 ifaceobjrunning
.update_config('ipv6-addrgen', 'off')
1142 def _query_running(self
, ifaceobjrunning
, ifaceobj_getfunc
=None):
1143 if not self
.ipcmd
.link_exists(ifaceobjrunning
.name
):
1144 self
.logger
.debug('iface %s not found' %ifaceobjrunning
.name
)
1147 self
.query_running_ipv6_addrgen(ifaceobjrunning
)
1149 dhclientcmd
= dhclient()
1150 if (dhclientcmd
.is_running(ifaceobjrunning
.name
) or
1151 dhclientcmd
.is_running6(ifaceobjrunning
.name
)):
1152 # If dhcp is configured on the interface, we skip it
1154 isloopback
= self
.ipcmd
.link_isloopback(ifaceobjrunning
.name
)
1156 default_addrs
= ['127.0.0.1/8', '::1/128']
1157 ifaceobjrunning
.addr_family
.append('inet')
1158 ifaceobjrunning
.addr_method
= 'loopback'
1161 runningaddrsdict
= self
.ipcmd
.get_running_addrs(ifaceobjrunning
)
1162 if runningaddrsdict
:
1163 [ifaceobjrunning
.update_config('address', addr
)
1164 for addr
, addrattrs
in runningaddrsdict
.items()
1165 if addr
not in default_addrs
]
1166 mtu
= self
.ipcmd
.link_get_mtu(ifaceobjrunning
.name
)
1168 (ifaceobjrunning
.name
== 'lo' and mtu
!= '16436') or
1169 (ifaceobjrunning
.name
!= 'lo' and
1170 mtu
!= self
.get_mod_subattr('mtu', 'default'))):
1171 ifaceobjrunning
.update_config('mtu', mtu
)
1172 alias
= self
.ipcmd
.link_get_alias(ifaceobjrunning
.name
)
1174 ifaceobjrunning
.update_config('alias', alias
)
1176 ipforward
= self
.read_file_oneline(
1177 '/proc/sys/net/ipv4/conf/%s/forwarding'
1178 %ifaceobjrunning
.name
)
1181 _run_ops
= {'up' : _up
,
1183 'query-checkcurr' : _query_check
,
1184 'query-running' : _query_running
}
1187 """ returns list of ops supported by this module """
1188 return self
._run
_ops
.keys()
1190 def _init_command_handlers(self
):
1192 self
.ipcmd
= LinkUtils()
1194 def run(self
, ifaceobj
, operation
, query_ifaceobj
=None, ifaceobj_getfunc
=None):
1195 """ run address configuration on the interface object passed as argument
1198 **ifaceobj** (object): iface object
1200 **operation** (str): any of 'up', 'down', 'query-checkcurr',
1203 query_ifaceobj (object): query check ifaceobject. This is only
1204 valid when op is 'query-checkcurr'. It is an object same as
1205 ifaceobj, but contains running attribute values and its config
1206 status. The modules can use it to return queried running state
1207 of interfaces. status is success if the running state is same
1208 as user required state in ifaceobj. error otherwise.
1210 if ifaceobj
.type == ifaceType
.BRIDGE_VLAN
:
1212 op_handler
= self
._run
_ops
.get(operation
)
1215 self
._init
_command
_handlers
()
1216 if operation
== 'query-checkcurr':
1217 op_handler(self
, ifaceobj
, query_ifaceobj
,
1218 ifaceobj_getfunc
=ifaceobj_getfunc
)
1220 op_handler(self
, ifaceobj
,
1221 ifaceobj_getfunc
=ifaceobj_getfunc
)