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 def syntax_check(self
, ifaceobj
, ifaceobj_getfunc
=None):
160 return (self
.syntax_check_multiple_gateway(ifaceobj
)
161 and self
.syntax_check_addr_allowed_on(ifaceobj
, True)
162 and self
.syntax_check_mtu(ifaceobj
, ifaceobj_getfunc
)
163 and self
.syntax_check_sysctls(ifaceobj
)
164 and self
.syntax_check_enable_l3_iface_forwardings(ifaceobj
, ifaceobj_getfunc
, syntax_check
=True))
166 def syntax_check_enable_l3_iface_forwardings(self
, ifaceobj
, ifaceobj_getfunc
, syntax_check
=False):
167 if (self
.enable_l3_iface_forwarding_checks
168 and (ifaceobj
.link_kind
& ifaceLinkKind
.VLAN
169 or ifaceobj
.link_kind
& ifaceLinkKind
.BRIDGE
)
170 and not ifaceobj
.link_privflags
& ifaceLinkPrivFlags
.BRIDGE_PORT
):
172 ifname
= ifaceobj
.name
174 vlan_ipforward_off
= None
176 for obj
in ifaceobj_getfunc(ifname
) or [ifaceobj
]:
178 vlan_addr
= obj
.get_attr_value('address')
180 if not vlan_ipforward_off
:
181 ip_forward_value
= obj
.get_attr_value_first('ip-forward')
183 if ip_forward_value
and not utils
.get_boolean_from_string(ip_forward_value
):
184 vlan_ipforward_off
= True
186 if vlan_addr
and vlan_ipforward_off
:
189 'configuring ip-forward off and ip address(es) (%s) is not compatible'
190 % (', '.join(vlan_addr
))
194 '%s: configuring ip-forward off and ip address(es) (%s) is not compatible'
195 % (ifname
, ', '.join(vlan_addr
))
200 def syntax_check_sysctls(self
, ifaceobj
):
202 bridge_port
= (ifaceobj
.link_privflags
& ifaceLinkPrivFlags
.BRIDGE_PORT
)
203 ipforward
= ifaceobj
.get_attr_value_first('ip-forward')
204 if bridge_port
and ipforward
:
206 self
.log_error('%s: \'ip-forward\' is not supported for '
207 'bridge port' %ifaceobj
.name
)
208 ip6forward
= ifaceobj
.get_attr_value_first('ip6-forward')
209 if bridge_port
and ip6forward
:
211 self
.log_error('%s: \'ip6-forward\' is not supported for '
212 'bridge port' %ifaceobj
.name
)
215 def syntax_check_mtu(self
, ifaceobj
, ifaceobj_getfunc
):
216 mtu
= ifaceobj
.get_attr_value_first('mtu')
218 return self
._check
_mtu
_config
(ifaceobj
, mtu
, ifaceobj_getfunc
,
222 def syntax_check_addr_allowed_on(self
, ifaceobj
, syntax_check
=False):
223 if ifaceobj
.get_attr_value('address'):
224 return utils
.is_addr_ip_allowed_on(ifaceobj
, syntax_check
=syntax_check
)
227 def _syntax_check_multiple_gateway(self
, family
, found
, addr
, type_obj
):
228 if type(IPNetwork(addr
)) == type_obj
:
230 raise Exception('%s: multiple gateways for %s family'
235 def syntax_check_multiple_gateway(self
, ifaceobj
):
239 gateways
= ifaceobj
.get_attr_value('gateway')
240 for addr
in gateways
if gateways
else []:
242 if self
._syntax
_check
_multiple
_gateway
('inet', inet
, addr
,
245 if self
._syntax
_check
_multiple
_gateway
('inet6', inet6
, addr
,
248 except Exception as e
:
249 self
.logger
.warning('%s: address: %s' % (ifaceobj
.name
, str(e
)))
253 def _address_valid(self
, addrs
):
256 if any(map(lambda a
: True if a
[:7] != '0.0.0.0'
261 def _get_hwaddress(self
, ifaceobj
):
262 return utils
.strip_hwaddress(ifaceobj
.get_attr_value_first('hwaddress'))
264 def _process_bridge(self
, ifaceobj
, up
):
265 hwaddress
= self
._get
_hwaddress
(ifaceobj
)
266 addrs
= ifaceobj
.get_attr_value_first('address')
267 is_vlan_dev_on_vlan_aware_bridge
= False
268 is_bridge
= self
.ipcmd
.is_bridge(ifaceobj
.name
)
270 if ifaceobj
.link_kind
& ifaceLinkKind
.VLAN
:
271 bridgename
= ifaceobj
.lowerifaces
[0]
272 vlan
= self
._get
_vlan
_id
(ifaceobj
)
273 is_vlan_dev_on_vlan_aware_bridge
= self
.ipcmd
.bridge_is_vlan_aware(bridgename
)
274 if ((is_bridge
and not self
.ipcmd
.bridge_is_vlan_aware(ifaceobj
.name
))
275 or is_vlan_dev_on_vlan_aware_bridge
):
276 if self
._address
_valid
(addrs
):
277 if self
.l3_intf_arp_accept
:
279 self
.write_file('/proc/sys/net/ipv4/conf/%s' % ifaceobj
.name
+
282 self
.write_file('/proc/sys/net/ipv4/conf/%s' % ifaceobj
.name
+
285 self
.write_file('/proc/sys/net/ipv4/conf/%s/arp_accept' % ifaceobj
.name
, '0')
286 if hwaddress
and is_vlan_dev_on_vlan_aware_bridge
:
288 self
.ipcmd
.bridge_fdb_add(bridgename
, hwaddress
, vlan
)
290 self
.ipcmd
.bridge_fdb_del(bridgename
, hwaddress
, vlan
)
292 def _get_anycast_addr(self
, ifaceobjlist
):
293 for ifaceobj
in ifaceobjlist
:
294 anycast_addr
= ifaceobj
.get_attr_value_first('clagd-vxlan-anycast-ip')
296 anycast_addr
= anycast_addr
+'/32'
300 def _inet_address_convert_to_cidr(self
, ifaceobjlist
):
304 for ifaceobj
in ifaceobjlist
:
305 addrs
= ifaceobj
.get_attr_value('address')
309 if not self
.syntax_check_addr_allowed_on(ifaceobj
,
311 return (False, newaddrs
, newaddr_attrs
)
312 # If user address is not in CIDR notation, convert them to CIDR
313 for addr_index
in range(0, len(addrs
)):
314 addr
= addrs
[addr_index
]
317 newaddrs
.append(addr
)
319 netmask
= ifaceobj
.get_attr_value_n('netmask', addr_index
)
321 prefixlen
= IPNetwork('%s' %addr
+
322 '/%s' %netmask
).prefixlen
323 newaddr
= addr
+ '/%s' %prefixlen
325 # we are here because there is no slash (/xx) and no netmask
326 # just let IPNetwork handle the ipv4 or ipv6 address mask
327 prefixlen
= IPNetwork(addr
).prefixlen
328 newaddr
= addr
+ '/%s' %prefixlen
329 newaddrs
.append(newaddr
)
332 for a
in ['broadcast', 'pointopoint', 'scope',
333 'preferred-lifetime']:
334 aval
= ifaceobj
.get_attr_value_n(a
, addr_index
)
339 newaddr_attrs
[newaddr
]= attrs
340 return (True, newaddrs
, newaddr_attrs
)
342 def _inet_address_list_config(self
, ifaceobj
, newaddrs
, newaddr_attrs
):
343 for addr_index
in range(0, len(newaddrs
)):
346 self
.ipcmd
.addr_add(ifaceobj
.name
, newaddrs
[addr_index
],
347 newaddr_attrs
.get(newaddrs
[addr_index
],
348 {}).get('broadcast'),
349 newaddr_attrs
.get(newaddrs
[addr_index
],
350 {}).get('pointopoint'),
351 newaddr_attrs
.get(newaddrs
[addr_index
],
353 newaddr_attrs
.get(newaddrs
[addr_index
],
354 {}).get('preferred-lifetime'))
356 self
.ipcmd
.addr_add(ifaceobj
.name
, newaddrs
[addr_index
])
358 self
.log_error(str(e
), ifaceobj
)
360 def _inet_address_config(self
, ifaceobj
, ifaceobj_getfunc
=None,
361 force_reapply
=False):
362 squash_addr_config
= (True if \
363 ifupdownconfig
.config
.get('addr_config_squash', \
364 '0') == '1' else False)
366 if (squash_addr_config
and
367 not (ifaceobj
.flags
& ifaceobj
.YOUNGEST_SIBLING
)):
370 purge_addresses
= ifaceobj
.get_attr_value_first('address-purge')
371 if not purge_addresses
:
372 purge_addresses
= 'yes'
374 if squash_addr_config
and ifaceobj
.flags
& iface
.HAS_SIBLINGS
:
375 ifaceobjlist
= ifaceobj_getfunc(ifaceobj
.name
)
377 ifaceobjlist
= [ifaceobj
]
379 module_name
= self
.__class
__.__name
__
380 ifname
= ifaceobj
.name
382 (addr_supported
, newaddrs
, newaddr_attrs
) = self
._inet
_address
_convert
_to
_cidr
(ifaceobjlist
)
383 newaddrs
= utils
.get_ip_objs(module_name
, ifname
, newaddrs
)
385 if not addr_supported
:
387 if (not squash_addr_config
and (ifaceobj
.flags
& iface
.HAS_SIBLINGS
)):
388 # if youngest sibling and squash addr is not set
389 # print a warning that addresses will not be purged
390 if (ifaceobj
.flags
& iface
.YOUNGEST_SIBLING
):
391 self
.logger
.warn('%s: interface has multiple ' %ifaceobj
.name
+
392 'iface stanzas, skip purging existing addresses')
393 purge_addresses
= 'no'
395 if not ifupdownflags
.flags
.PERFMODE
and purge_addresses
== 'yes':
396 # if perfmode is not set and purge addresses is not set to 'no'
397 # lets purge addresses not in the config
398 runningaddrs
= self
.ipcmd
.get_running_addrs(ifaceobj
, details
=False)
400 # if anycast address is configured on 'lo' and is in running config
401 # add it to newaddrs so that ifreload doesn't wipe it out
402 anycast_addr
= utils
.get_normalized_ip_addr(ifaceobj
.name
, self
._get
_anycast
_addr
(ifaceobjlist
))
404 if runningaddrs
and anycast_addr
and anycast_addr
in runningaddrs
:
405 newaddrs
.append(anycast_addr
)
407 user_ip4
, user_ip6
, newaddrs
= self
.order_user_configured_addrs(newaddrs
)
409 if newaddrs
== runningaddrs
or self
.compare_running_ips_and_user_config(user_ip4
, user_ip6
, runningaddrs
):
411 self
._inet
_address
_list
_config
(ifaceobj
, newaddrs
, newaddr_attrs
)
414 # if primary address is not same, there is no need to keep any.
415 # reset all addresses
416 if newaddrs
and runningaddrs
and newaddrs
[0] != runningaddrs
[0]:
419 skip_addrs
= newaddrs
or []
420 for addr
in runningaddrs
or []:
421 if addr
in skip_addrs
:
423 self
.ipcmd
.addr_del(ifaceobj
.name
, addr
)
425 self
.log_warn(str(e
))
428 self
._inet
_address
_list
_config
(ifaceobj
, newaddrs
, newaddr_attrs
)
430 def compare_running_ips_and_user_config(self
, user_ip4
, user_ip6
, running_addrs
):
432 We need to compare the user config ips and the running ips.
433 ip4 ordering matters (primary etc) but ip6 order doesn't matter
435 this function replaces the strict comparison previously in place
436 if newaddrs == running_addrs ?
438 We will compare if the ip4 ordering is correct, then check if all
439 ip6 are present in the list (without checking the ordering)
441 if (user_ip4
or user_ip6
) and not running_addrs
:
443 elif running_addrs
and not user_ip4
and not user_ip6
:
445 elif not running_addrs
and not user_ip4
and not user_ip6
:
448 len_ip4
= len(user_ip4
)
449 len_running_addrs
= len(running_addrs
)
451 if len_ip4
> len_running_addrs
:
456 if user_ip4
[i
] != running_addrs
[i
]:
461 running_ip6
= running_addrs
[len_ip4
:]
463 running_ip6
= running_addrs
466 len_ip6
= len(user_ip6
)
468 for ip6
in running_ip6
:
469 if ip6
not in user_ip6
:
475 def order_user_configured_addrs(self
, user_config_addrs
):
479 for a
in user_config_addrs
:
480 if isinstance(a
, _BaseV6
):
485 return ip4
, ip6
, ip4
+ ip6
487 def _delete_gateway(self
, ifaceobj
, gateways
, vrf
, metric
):
488 for del_gw
in gateways
:
490 self
.ipcmd
.route_del_gateway(ifaceobj
.name
, del_gw
, vrf
, metric
)
491 except Exception as e
:
492 self
.logger
.debug('%s: %s' % (ifaceobj
.name
, str(e
)))
494 def _add_delete_gateway(self
, ifaceobj
, gateways
=[], prev_gw
=[]):
495 vrf
= ifaceobj
.get_attr_value_first('vrf')
496 metric
= ifaceobj
.get_attr_value_first('metric')
497 self
._delete
_gateway
(ifaceobj
, list(set(prev_gw
) - set(gateways
)),
499 for add_gw
in gateways
:
501 self
.ipcmd
.route_add_gateway(ifaceobj
.name
, add_gw
, vrf
, metric
)
502 except Exception as e
:
503 self
.log_error('%s: %s' % (ifaceobj
.name
, str(e
)))
505 def _get_prev_gateway(self
, ifaceobj
, gateways
):
507 saved_ifaceobjs
= statemanager
.statemanager_api
.get_ifaceobjs(ifaceobj
.name
)
508 if not saved_ifaceobjs
:
510 prev_gateways
= saved_ifaceobjs
[0].get_attr_value('gateway')
511 if not prev_gateways
:
515 def _check_mtu_config(self
, ifaceobj
, mtu
, ifaceobj_getfunc
, syntaxcheck
=False):
517 if (ifaceobj
.link_kind
& ifaceLinkKind
.BRIDGE
):
519 self
.logger
.warn('%s: bridge inherits mtu from its ports. There is no need to assign mtu on a bridge' %ifaceobj
.name
)
522 self
.logger
.info('%s: bridge inherits mtu from its ports. There is no need to assign mtu on a bridge' %ifaceobj
.name
)
523 elif ifaceobj_getfunc
:
524 if ((ifaceobj
.link_privflags
& ifaceLinkPrivFlags
.BOND_SLAVE
) and
525 ifaceobj
.upperifaces
):
526 masterobj
= ifaceobj_getfunc(ifaceobj
.upperifaces
[0])
528 master_mtu
= masterobj
[0].get_attr_value_first('mtu')
529 if master_mtu
and master_mtu
!= mtu
:
531 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
))
534 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
))
535 elif ((ifaceobj
.link_kind
& ifaceLinkKind
.VLAN
) and
536 ifaceobj
.lowerifaces
):
537 lowerobj
= ifaceobj_getfunc(ifaceobj
.lowerifaces
[0])
540 lowerdev_mtu
= lowerobj
[0].get_attr_value_first('mtu')
542 lowerdev_mtu
= self
.ipcmd
.link_get_mtu_sysfs(lowerobj
[0].name
)
543 if lowerdev_mtu
and int(mtu
) > int(lowerdev_mtu
):
544 self
.logger
.warn('%s: vlan dev mtu %s is greater than lower realdev %s mtu %s'
545 %(ifaceobj
.name
, mtu
, lowerobj
[0].name
, lowerdev_mtu
))
547 elif (not lowerobj
[0].link_kind
and
548 not (lowerobj
[0].link_privflags
& ifaceLinkPrivFlags
.LOOPBACK
) and
549 not lowerdev_mtu
and self
.default_mtu
and
550 (int(mtu
) > int(self
.default_mtu
))):
551 # only check default mtu on lower device which is a physical interface
552 self
.logger
.warn('%s: vlan dev mtu %s is greater than lower realdev %s mtu %s'
553 %(ifaceobj
.name
, mtu
, lowerobj
[0].name
, self
.default_mtu
))
555 if self
.max_mtu
and mtu
> self
.max_mtu
:
556 self
.logger
.warn('%s: specified mtu %s is greater than max mtu %s'
557 %(ifaceobj
.name
, mtu
, self
.max_mtu
))
561 def _propagate_mtu_to_upper_devs(self
, ifaceobj
, mtu
, ifaceobj_getfunc
):
562 if (not ifaceobj
.upperifaces
or
563 (ifaceobj
.link_privflags
& ifaceLinkPrivFlags
.BOND_SLAVE
) or
564 (ifaceobj
.link_privflags
& ifaceLinkPrivFlags
.VRF_SLAVE
) or
565 (ifaceobj
.link_privflags
& ifaceLinkPrivFlags
.BRIDGE_PORT
)):
567 for u
in ifaceobj
.upperifaces
:
568 upperobjs
= ifaceobj_getfunc(u
)
570 not (upperobjs
[0].link_kind
& ifaceLinkKind
.VLAN
)):
572 # only adjust mtu for vlan devices on ifaceobj
573 umtu
= upperobjs
[0].get_attr_value_first('mtu')
575 running_mtu
= self
.ipcmd
.link_get_mtu(upperobjs
[0].name
)
576 if not running_mtu
or (running_mtu
!= mtu
):
577 self
.ipcmd
.link_set(u
, 'mtu', mtu
)
579 def _process_mtu_config(self
, ifaceobj
, ifaceobj_getfunc
, mtu
):
581 if not self
._check
_mtu
_config
(ifaceobj
, mtu
, ifaceobj_getfunc
):
583 cached_running_mtu
= self
.ipcmd
.link_get_mtu(ifaceobj
.name
)
584 running_mtu
= self
.ipcmd
.link_get_mtu_sysfs(ifaceobj
.name
)
585 if not running_mtu
or (running_mtu
and running_mtu
!= mtu
):
586 force
= cached_running_mtu
!= running_mtu
587 self
.ipcmd
.link_set(ifaceobj
.name
, 'mtu', mtu
, force
=force
)
588 if (not ifupdownflags
.flags
.ALL
and
589 not ifaceobj
.link_kind
and
590 ifupdownconfig
.config
.get('adjust_logical_dev_mtu', '1') != '0'):
591 # This is additional cost to us, so do it only when
592 # ifupdown2 is called on a particular interface and
593 # it is a physical interface
594 self
._propagate
_mtu
_to
_upper
_devs
(ifaceobj
, mtu
, ifaceobj_getfunc
)
597 if ifaceobj
.link_kind
:
598 # bonds and vxlan devices need an explicit set of mtu.
599 # bridges don't need mtu set
600 if (ifaceobj
.link_kind
& ifaceLinkKind
.BOND
or
601 ifaceobj
.link_kind
& ifaceLinkKind
.VXLAN
):
602 running_mtu
= self
.ipcmd
.link_get_mtu(ifaceobj
.name
)
603 if (self
.default_mtu
and running_mtu
!= self
.default_mtu
):
604 self
.ipcmd
.link_set(ifaceobj
.name
, 'mtu', self
.default_mtu
)
606 if (ifupdownconfig
.config
.get('adjust_logical_dev_mtu', '1') != '0'
607 and ifaceobj
.lowerifaces
):
608 # set vlan interface mtu to lower device mtu
609 if (ifaceobj
.link_kind
& ifaceLinkKind
.VLAN
):
610 lower_iface
= ifaceobj
.lowerifaces
[0]
611 if lower_iface
not in self
.lower_iface_mtu_checked_list
:
612 lower_iface_mtu
= self
.ipcmd
.link_get_mtu_sysfs(lower_iface
)
613 self
.ipcmd
.cache_update([lower_iface
, 'mtu'], lower_iface_mtu
)
614 self
.lower_iface_mtu_checked_list
.append(lower_iface
)
616 lower_iface_mtu
= self
.ipcmd
.link_get_mtu(lower_iface
)
618 if lower_iface_mtu
!= self
.ipcmd
.link_get_mtu_sysfs(ifaceobj
.name
):
619 self
.ipcmd
.link_set_mtu(ifaceobj
.name
, lower_iface_mtu
)
621 elif (not (ifaceobj
.name
== 'lo') and not ifaceobj
.link_kind
and
622 not (ifaceobj
.link_privflags
& ifaceLinkPrivFlags
.BOND_SLAVE
) and
624 # logical devices like bridges and vlan devices rely on mtu
625 # from their lower devices. ie mtu travels from
626 # lower devices to upper devices. For bonds mtu travels from
627 # upper to lower devices. running mtu depends on upper and
628 # lower device mtu. With all this implicit mtu
629 # config by the kernel in play, we try to be cautious here
630 # on which devices we want to reset mtu to default.
631 # essentially only physical interfaces which are not bond slaves
632 running_mtu
= self
.ipcmd
.link_get_mtu(ifaceobj
.name
)
633 if running_mtu
!= self
.default_mtu
:
634 self
.ipcmd
.link_set(ifaceobj
.name
, 'mtu', self
.default_mtu
)
636 def _set_bridge_forwarding(self
, ifaceobj
):
637 """ set ip forwarding to 0 if bridge interface does not have a
639 ifname
= ifaceobj
.name
640 if not ifaceobj
.upperifaces
and not ifaceobj
.get_attr_value('address'):
641 if self
.sysctl_get_forwarding_value_from_proc(ifname
, "ipv4") == '1':
642 self
.sysctl_write_forwarding_value_to_proc(ifname
, "ipv4", 0)
643 if self
.sysctl_get_forwarding_value_from_proc(ifname
, "ipv6") == '1':
644 self
.sysctl_write_forwarding_value_to_proc(ifname
, "ipv6", 0)
646 if self
.sysctl_get_forwarding_value_from_proc(ifname
, "ipv4") == '0':
647 self
.sysctl_write_forwarding_value_to_proc(ifname
, "ipv4", 1)
648 if self
.sysctl_get_forwarding_value_from_proc(ifname
, "ipv6") == '0':
649 self
.sysctl_write_forwarding_value_to_proc(ifname
, "ipv6", 1)
651 def sysctl_get_forwarding_value_from_proc(self
, ifname
, family
):
652 return self
.read_file_oneline("/proc/sys/net/%s/conf/%s/forwarding" % (family
, ifname
))
654 def sysctl_write_forwarding_value_to_proc(self
, ifname
, family
, value
):
655 self
.write_file("/proc/sys/net/%s/conf/%s/forwarding" % (family
, ifname
), "%s\n" % value
)
657 def _sysctl_config(self
, ifaceobj
):
658 setting_default_value
= False
659 mpls_enable
= ifaceobj
.get_attr_value_first('mpls-enable');
661 setting_default_value
= True
662 mpls_enable
= self
.get_mod_subattr('mpls-enable', 'default')
663 mpls_enable
= utils
.boolean_support_binary(mpls_enable
)
664 # File read has been used for better performance
665 # instead of using sysctl command
666 if ifupdownflags
.flags
.PERFMODE
:
667 running_mpls_enable
= '0'
669 running_mpls_enable
= self
.read_file_oneline(
670 '/proc/sys/net/mpls/conf/%s/input'
674 if mpls_enable
!= running_mpls_enable
:
676 self
.sysctl_set('net.mpls.conf.%s.input'
677 %('/'.join(ifaceobj
.name
.split("."))),
679 except Exception as e
:
680 if not setting_default_value
:
681 ifaceobj
.status
= ifaceStatus
.ERROR
682 self
.logger
.error('%s: %s' %(ifaceobj
.name
, str(e
)))
684 if (ifaceobj
.link_kind
& ifaceLinkKind
.BRIDGE
):
685 self
._set
_bridge
_forwarding
(ifaceobj
)
687 if not self
.syntax_check_sysctls(ifaceobj
):
689 ipforward
= ifaceobj
.get_attr_value_first('ip-forward')
690 ip6forward
= ifaceobj
.get_attr_value_first('ip6-forward')
691 if ifupdownflags
.flags
.PERFMODE
:
693 self
.sysctl_set('net.ipv4.conf.%s.forwarding'
694 %('/'.join(ifaceobj
.name
.split("."))),
695 utils
.boolean_support_binary(ipforward
))
697 self
.sysctl_set('net.ipv6.conf.%s.forwarding'
698 %('/'.join(ifaceobj
.name
.split("."))),
699 utils
.boolean_support_binary(ip6forward
))
701 bridge_port
= ifaceobj
.link_privflags
& ifaceLinkPrivFlags
.BRIDGE_PORT
704 self
.log_error('%s: \'ip-forward\' is not supported for '
705 'bridge port' %ifaceobj
.name
)
707 self
.log_error('%s: \'ip6-forward\' is not supported for '
708 'bridge port' %ifaceobj
.name
)
710 setting_default_value
= False
712 setting_default_value
= True
713 ipforward
= (self
.ipforward
or
714 self
.get_mod_subattr('ip-forward', 'default'))
715 ipforward
= utils
.boolean_support_binary(ipforward
)
716 # File read has been used for better performance
717 # instead of using sysctl command
718 running_ipforward
= self
.read_file_oneline(
719 '/proc/sys/net/ipv4/conf/%s/forwarding'
721 if ipforward
!= running_ipforward
:
723 self
.sysctl_set('net.ipv4.conf.%s.forwarding'
724 %('/'.join(ifaceobj
.name
.split("."))),
726 except Exception as e
:
727 if not setting_default_value
:
728 ifaceobj
.status
= ifaceStatus
.ERROR
729 self
.logger
.error('%s: %s' %(ifaceobj
.name
, str(e
)))
731 setting_default_value
= False
733 setting_default_value
= True
734 ip6forward
= (self
.ip6forward
or
735 self
.get_mod_subattr('ip6-forward', 'default'))
736 ip6forward
= utils
.boolean_support_binary(ip6forward
)
737 # File read has been used for better performance
738 # instead of using sysctl command
739 running_ip6forward
= self
.read_file_oneline(
740 '/proc/sys/net/ipv6/conf/%s/forwarding'
742 if ip6forward
!= running_ip6forward
:
744 self
.sysctl_set('net.ipv6.conf.%s.forwarding'
745 %('/'.join(ifaceobj
.name
.split("."))),
747 except Exception as e
:
748 # There is chance of ipv6 being removed because of,
749 # for example, setting mtu < 1280
750 # In such cases, log error only if user has configured
752 if not setting_default_value
:
753 ifaceobj
.status
= ifaceStatus
.ERROR
754 self
.logger
.error('%s: %s' %(ifaceobj
.name
, str(e
)))
756 def process_mtu(self
, ifaceobj
, ifaceobj_getfunc
):
757 mtu
= ifaceobj
.get_attr_value_first('mtu')
760 default_iface_mtu
= self
.ifaces_defaults
.get(ifaceobj
.name
, {}).get('mtu')
762 if default_iface_mtu
:
764 mtu
= default_iface_mtu
765 int(default_iface_mtu
)
766 except Exception as e
:
767 self
.logger
.warning('%s: MTU value from policy file: %s' % (ifaceobj
.name
, str(e
)))
770 self
._process
_mtu
_config
(ifaceobj
, ifaceobj_getfunc
, mtu
)
772 def up_ipv6_addrgen(self
, ifaceobj
):
773 user_configured_ipv6_addrgen
= ifaceobj
.get_attr_value_first('ipv6-addrgen')
775 if not user_configured_ipv6_addrgen
and ifupdownflags
.flags
.PERFMODE
:
776 # no need to go further during perfmode (boot)
779 if not user_configured_ipv6_addrgen
and ifaceobj
.addr_method
== 'dhcp':
782 if not user_configured_ipv6_addrgen
:
783 # if user didn't configure ipv6-addrgen, should we reset to default?
784 user_configured_ipv6_addrgen
= self
.get_attr_default_value('ipv6-addrgen')
793 }.get(user_configured_ipv6_addrgen
.lower(), None)
795 if ipv6_addrgen_nl
is not None:
796 self
.ipcmd
.ipv6_addrgen(ifaceobj
.name
, ipv6_addrgen_nl
, link_created
=True)
797 # link_create=False will flush the addr cache of that intf
799 self
.logger
.warning('%s: invalid value "%s" for attribute ipv6-addrgen' % (ifaceobj
.name
, user_configured_ipv6_addrgen
))
801 def _up(self
, ifaceobj
, ifaceobj_getfunc
=None):
802 if not self
.ipcmd
.link_exists(ifaceobj
.name
):
805 if not self
.syntax_check_enable_l3_iface_forwardings(ifaceobj
, ifaceobj_getfunc
):
808 alias
= ifaceobj
.get_attr_value_first('alias')
809 current_alias
= self
.ipcmd
.link_get_alias(ifaceobj
.name
)
810 if alias
and alias
!= current_alias
:
811 self
.ipcmd
.link_set_alias(ifaceobj
.name
, alias
)
812 elif not alias
and current_alias
:
813 self
.ipcmd
.link_set_alias(ifaceobj
.name
, '')
815 self
._sysctl
_config
(ifaceobj
)
817 addr_method
= ifaceobj
.addr_method
818 force_reapply
= False
820 # release any stale dhcp addresses if present
821 if (addr_method
not in ["dhcp", "ppp"] and not ifupdownflags
.flags
.PERFMODE
and
822 not (ifaceobj
.flags
& iface
.HAS_SIBLINGS
)):
823 # if not running in perf mode and ifaceobj does not have
824 # any sibling iface objects, kill any stale dhclient
826 dhclientcmd
= dhclient()
827 if dhclientcmd
.is_running(ifaceobj
.name
):
828 # release any dhcp leases
829 dhclientcmd
.release(ifaceobj
.name
)
831 elif dhclientcmd
.is_running6(ifaceobj
.name
):
832 dhclientcmd
.release6(ifaceobj
.name
)
837 self
.ipcmd
.batch_start()
838 self
.up_ipv6_addrgen(ifaceobj
)
840 if addr_method
not in ["dhcp", "ppp"]:
841 self
._inet
_address
_config
(ifaceobj
, ifaceobj_getfunc
,
844 self
.process_mtu(ifaceobj
, ifaceobj_getfunc
)
847 self
.ipcmd
.batch_commit()
848 except Exception as e
:
849 self
.log_error('%s: %s' % (ifaceobj
.name
, str(e
)), ifaceobj
, raise_error
=False)
852 hwaddress
= self
._get
_hwaddress
(ifaceobj
)
854 running_hwaddress
= None
855 if not ifupdownflags
.flags
.PERFMODE
: # system is clean
856 running_hwaddress
= self
.ipcmd
.link_get_hwaddress(ifaceobj
.name
)
857 if hwaddress
!= running_hwaddress
:
859 netlink
.link_set_updown(ifaceobj
.name
, "down")
860 if ifaceobj
.link_kind
& ifaceLinkKind
.BOND
:
861 # if bond, down all the slaves
862 if ifaceobj
.lowerifaces
:
863 for l
in ifaceobj
.lowerifaces
:
864 netlink
.link_set_updown(l
, "down")
867 self
.ipcmd
.link_set(ifaceobj
.name
, 'address', hwaddress
)
869 netlink
.link_set_updown(ifaceobj
.name
, "up")
871 for l
in ifaceobj
.lowerifaces
:
872 netlink
.link_set_updown(l
, "up")
874 # Handle special things on a bridge
875 self
._process
_bridge
(ifaceobj
, True)
877 self
.log_error('%s: %s' %(ifaceobj
.name
, str(e
)), ifaceobj
)
879 gateways
= ifaceobj
.get_attr_value('gateway')
882 prev_gw
= self
._get
_prev
_gateway
(ifaceobj
, gateways
)
883 self
._add
_delete
_gateway
(ifaceobj
, gateways
, prev_gw
)
885 def _down(self
, ifaceobj
, ifaceobj_getfunc
=None):
887 if not self
.ipcmd
.link_exists(ifaceobj
.name
):
889 addr_method
= ifaceobj
.addr_method
890 if addr_method
not in ["dhcp", "ppp"]:
891 if ifaceobj
.get_attr_value_first('address-purge')=='no':
892 addrlist
= ifaceobj
.get_attr_value('address')
893 for addr
in addrlist
:
894 self
.ipcmd
.addr_del(ifaceobj
.name
, addr
)
895 #self.ipcmd.addr_del(ifaceobj.name, ifaceobj.get_attr_value('address')[0])
896 elif not ifaceobj
.link_kind
:
897 # for logical interfaces we don't need to remove the ip addresses
898 # kernel will do it for us on 'ip link del'
899 self
.ipcmd
.del_addr_all(ifaceobj
.name
)
900 gateways
= ifaceobj
.get_attr_value('gateway')
902 self
._delete
_gateway
(ifaceobj
, gateways
,
903 ifaceobj
.get_attr_value_first('vrf'),
904 ifaceobj
.get_attr_value_first('metric'))
905 mtu
= ifaceobj
.get_attr_value_first('mtu')
906 if (not ifaceobj
.link_kind
and mtu
and
907 self
.default_mtu
and (mtu
!= self
.default_mtu
)):
908 self
.ipcmd
.link_set(ifaceobj
.name
, 'mtu', self
.default_mtu
)
909 alias
= ifaceobj
.get_attr_value_first('alias')
911 self
.write_file('/sys/class/net/%s/ifalias' % ifaceobj
.name
, '\n')
912 # XXX hwaddress reset cannot happen because we dont know last
915 # Handle special things on a bridge
916 self
._process
_bridge
(ifaceobj
, False)
918 self
.logger
.debug('%s : %s' %(ifaceobj
.name
, str(e
)))
921 def _get_iface_addresses(self
, ifaceobj
):
922 addrlist
= ifaceobj
.get_attr_value('address')
925 if not addrlist
: return None
926 for addrindex
in range(0, len(addrlist
)):
927 addr
= addrlist
[addrindex
]
928 netmask
= ifaceobj
.get_attr_value_n('netmask', addrindex
)
930 prefixlen
= IPNetwork('%s' %addr
+
931 '/%s' %netmask
).prefixlen
932 addr
= addr
+ '/%s' %prefixlen
933 outaddrlist
.append(addr
)
936 def _get_bridge_fdbs(self
, bridgename
, vlan
):
937 fdbs
= self
._bridge
_fdb
_query
_cache
.get(bridgename
)
939 fdbs
= self
.ipcmd
.bridge_fdb_show_dev(bridgename
)
942 self
._bridge
_fdb
_query
_cache
[bridgename
] = fdbs
943 return fdbs
.get(vlan
)
945 def _check_addresses_in_bridge(self
, ifaceobj
, hwaddress
):
946 """ If the device is a bridge, make sure the addresses
947 are in the bridge """
948 if ifaceobj
.link_kind
& ifaceLinkKind
.VLAN
:
949 bridgename
= ifaceobj
.lowerifaces
[0]
950 vlan
= self
._get
_vlan
_id
(ifaceobj
)
951 if self
.ipcmd
.bridge_is_vlan_aware(bridgename
):
952 fdb_addrs
= self
._get
_bridge
_fdbs
(bridgename
, str(vlan
))
953 if not fdb_addrs
or hwaddress
not in fdb_addrs
:
957 def _query_sysctl(self
, ifaceobj
, ifaceobjcurr
):
958 bridge_port
= ifaceobj
.link_privflags
& ifaceLinkPrivFlags
.BRIDGE_PORT
959 ipforward
= ifaceobj
.get_attr_value_first('ip-forward')
962 ifaceobjcurr
.status
= ifaceStatus
.ERROR
963 ifaceobjcurr
.status_str
= ('\'ip-forward\' not supported ' +
965 ifaceobjcurr
.update_config_with_status('ip-forward', 1, None)
967 running_ipforward
= self
.read_file_oneline(
968 '/proc/sys/net/ipv4/conf/%s/forwarding'
970 running_ipforward
= utils
.get_boolean_from_string(running_ipforward
)
971 config_ipforward
= utils
.get_boolean_from_string(ipforward
)
972 ifaceobjcurr
.update_config_with_status(
974 'on' if running_ipforward
else 'off',
975 running_ipforward
!= config_ipforward
978 ip6forward
= ifaceobj
.get_attr_value_first('ip6-forward')
981 ifaceobjcurr
.status
= ifaceStatus
.ERROR
982 ifaceobjcurr
.status_str
= ('\'ip6-forward\' not supported ' +
984 ifaceobjcurr
.update_config_with_status('ip6-forward', 1, None)
986 running_ip6forward
= self
.read_file_oneline(
987 '/proc/sys/net/ipv6/conf/%s/forwarding'
989 running_ip6forward
= utils
.get_boolean_from_string(running_ip6forward
)
990 config_ip6forward
= utils
.get_boolean_from_string(ip6forward
)
991 ifaceobjcurr
.update_config_with_status(
993 'on' if running_ip6forward
else 'off',
994 running_ip6forward
!= config_ip6forward
996 mpls_enable
= ifaceobj
.get_attr_value_first('mpls-enable');
998 running_mpls_enable
= self
.read_file_oneline(
999 '/proc/sys/net/mpls/conf/%s/input'
1001 running_mpls_enable
= utils
.get_yesno_from_onezero(
1002 running_mpls_enable
)
1003 ifaceobjcurr
.update_config_with_status('mpls-enable',
1004 running_mpls_enable
,
1005 mpls_enable
!= running_mpls_enable
)
1008 def query_check_ipv6_addrgen(self
, ifaceobj
, ifaceobjcurr
):
1009 ipv6_addrgen
= ifaceobj
.get_attr_value_first('ipv6-addrgen')
1011 if not ipv6_addrgen
:
1014 if ipv6_addrgen
in utils
._string
_values
:
1015 ifaceobjcurr
.update_config_with_status(
1018 utils
.get_boolean_from_string(ipv6_addrgen
) == self
.ipcmd
.get_ipv6_addrgen_mode(ifaceobj
.name
)
1021 ifaceobjcurr
.update_config_with_status('ipv6-addrgen', ipv6_addrgen
, 1)
1023 def _query_check(self
, ifaceobj
, ifaceobjcurr
, ifaceobj_getfunc
=None):
1024 runningaddrsdict
= None
1025 if not self
.ipcmd
.link_exists(ifaceobj
.name
):
1026 self
.logger
.debug('iface %s not found' %ifaceobj
.name
)
1029 self
.query_check_ipv6_addrgen(ifaceobj
, ifaceobjcurr
)
1031 addr_method
= ifaceobj
.addr_method
1032 self
.query_n_update_ifaceobjcurr_attr(ifaceobj
, ifaceobjcurr
,
1033 'mtu', self
.ipcmd
.link_get_mtu
)
1034 hwaddress
= self
._get
_hwaddress
(ifaceobj
)
1036 rhwaddress
= self
.ipcmd
.link_get_hwaddress(ifaceobj
.name
)
1037 if not rhwaddress
or rhwaddress
!= hwaddress
:
1038 ifaceobjcurr
.update_config_with_status('hwaddress', rhwaddress
,
1040 elif not self
._check
_addresses
_in
_bridge
(ifaceobj
, hwaddress
):
1041 # XXX: hw address is not in bridge
1042 ifaceobjcurr
.update_config_with_status('hwaddress', rhwaddress
,
1044 ifaceobjcurr
.status_str
= 'bridge fdb error'
1046 ifaceobjcurr
.update_config_with_status('hwaddress', rhwaddress
,
1048 self
.query_n_update_ifaceobjcurr_attr(ifaceobj
, ifaceobjcurr
,
1049 'alias', self
.ipcmd
.link_get_alias
)
1050 self
._query
_sysctl
(ifaceobj
, ifaceobjcurr
)
1052 if addr_method
in ["dhcp", "ppp"]:
1054 addrs
= utils
.get_normalized_ip_addr(ifaceobj
.name
,
1055 self
._get
_iface
_addresses
(ifaceobj
))
1056 runningaddrsdict
= self
.ipcmd
.get_running_addrs(ifaceobj
)
1057 # if anycast address is configured on 'lo' and is in running config
1058 # add it to addrs so that query_check doesn't fail
1059 anycast_addr
= utils
.get_normalized_ip_addr(ifaceobj
.name
, ifaceobj
.get_attr_value_first('clagd-vxlan-anycast-ip'))
1061 anycast_addr
= anycast_addr
+'/32'
1062 if runningaddrsdict
and anycast_addr
and runningaddrsdict
.get(anycast_addr
):
1063 addrs
.append(anycast_addr
)
1065 # Set ifaceobjcurr method and family
1066 ifaceobjcurr
.addr_method
= ifaceobj
.addr_method
1067 ifaceobjcurr
.addr_family
= ifaceobj
.addr_family
1068 if not runningaddrsdict
and not addrs
:
1070 runningaddrs
= runningaddrsdict
.keys() if runningaddrsdict
else []
1071 # Add /32 netmask to configured address without netmask.
1072 # This may happen on interfaces where pointopoint is used.
1073 runningaddrs
= [ addr
if '/' in addr
else addr
+ '/32' for addr
in runningaddrs
]
1074 if runningaddrs
!= addrs
:
1075 runningaddrsset
= set(runningaddrs
) if runningaddrs
else set([])
1076 addrsset
= set(addrs
) if addrs
else set([])
1077 if (ifaceobj
.flags
& iface
.HAS_SIBLINGS
):
1080 # only check for addresses present in running config
1081 addrsdiff
= addrsset
.difference(runningaddrsset
)
1083 if addr
in addrsdiff
:
1084 ifaceobjcurr
.update_config_with_status('address',
1087 ifaceobjcurr
.update_config_with_status('address',
1090 addrsdiff
= addrsset
.symmetric_difference(runningaddrsset
)
1091 for addr
in addrsset
.union(runningaddrsset
):
1092 if addr
in addrsdiff
:
1093 ifaceobjcurr
.update_config_with_status('address',
1096 ifaceobjcurr
.update_config_with_status('address',
1099 [ifaceobjcurr
.update_config_with_status('address',
1100 addr
, 0) for addr
in addrs
]
1101 #XXXX Check broadcast address, scope, etc
1104 def query_running_ipv6_addrgen(self
, ifaceobjrunning
):
1105 ipv6_addrgen
= self
.ipcmd
.get_ipv6_addrgen_mode(ifaceobjrunning
.name
)
1108 ifaceobjrunning
.update_config('ipv6-addrgen', 'off')
1110 def _query_running(self
, ifaceobjrunning
, ifaceobj_getfunc
=None):
1111 if not self
.ipcmd
.link_exists(ifaceobjrunning
.name
):
1112 self
.logger
.debug('iface %s not found' %ifaceobjrunning
.name
)
1115 self
.query_running_ipv6_addrgen(ifaceobjrunning
)
1117 dhclientcmd
= dhclient()
1118 if (dhclientcmd
.is_running(ifaceobjrunning
.name
) or
1119 dhclientcmd
.is_running6(ifaceobjrunning
.name
)):
1120 # If dhcp is configured on the interface, we skip it
1122 isloopback
= self
.ipcmd
.link_isloopback(ifaceobjrunning
.name
)
1124 default_addrs
= ['127.0.0.1/8', '::1/128']
1125 ifaceobjrunning
.addr_family
.append('inet')
1126 ifaceobjrunning
.addr_method
= 'loopback'
1129 runningaddrsdict
= self
.ipcmd
.get_running_addrs(ifaceobjrunning
)
1130 if runningaddrsdict
:
1131 [ifaceobjrunning
.update_config('address', addr
)
1132 for addr
, addrattrs
in runningaddrsdict
.items()
1133 if addr
not in default_addrs
]
1134 mtu
= self
.ipcmd
.link_get_mtu(ifaceobjrunning
.name
)
1136 (ifaceobjrunning
.name
== 'lo' and mtu
!= '16436') or
1137 (ifaceobjrunning
.name
!= 'lo' and
1138 mtu
!= self
.get_mod_subattr('mtu', 'default'))):
1139 ifaceobjrunning
.update_config('mtu', mtu
)
1140 alias
= self
.ipcmd
.link_get_alias(ifaceobjrunning
.name
)
1142 ifaceobjrunning
.update_config('alias', alias
)
1144 ipforward
= self
.read_file_oneline(
1145 '/proc/sys/net/ipv4/conf/%s/forwarding'
1146 %ifaceobjrunning
.name
)
1149 _run_ops
= {'up' : _up
,
1151 'query-checkcurr' : _query_check
,
1152 'query-running' : _query_running
}
1155 """ returns list of ops supported by this module """
1156 return self
._run
_ops
.keys()
1158 def _init_command_handlers(self
):
1160 self
.ipcmd
= LinkUtils()
1162 def run(self
, ifaceobj
, operation
, query_ifaceobj
=None, ifaceobj_getfunc
=None):
1163 """ run address configuration on the interface object passed as argument
1166 **ifaceobj** (object): iface object
1168 **operation** (str): any of 'up', 'down', 'query-checkcurr',
1171 query_ifaceobj (object): query check ifaceobject. This is only
1172 valid when op is 'query-checkcurr'. It is an object same as
1173 ifaceobj, but contains running attribute values and its config
1174 status. The modules can use it to return queried running state
1175 of interfaces. status is success if the running state is same
1176 as user required state in ifaceobj. error otherwise.
1178 if ifaceobj
.type == ifaceType
.BRIDGE_VLAN
:
1180 op_handler
= self
._run
_ops
.get(operation
)
1183 self
._init
_command
_handlers
()
1184 if operation
== 'query-checkcurr':
1185 op_handler(self
, ifaceobj
, query_ifaceobj
,
1186 ifaceobj_getfunc
=ifaceobj_getfunc
)
1188 op_handler(self
, ifaceobj
,
1189 ifaceobj_getfunc
=ifaceobj_getfunc
)