2014-10-09 16:02:46 -07:00
#!/usr/bin/python
#
2018-12-13 11:43:32 -08:00
# Copyright 2014-2017 Cumulus Networks, Inc. All rights reserved.
2014-10-09 16:02:46 -07:00
# Author: Roopa Prabhu, roopa@cumulusnetworks.com
#
2018-07-10 00:18:39 +02:00
import socket
2018-12-13 11:43:32 -08:00
from ipaddr import IPNetwork , IPv4Network , IPv6Network , _BaseV6
2016-03-10 01:40:15 +01:00
2014-10-09 16:02:46 -07:00
try :
2018-12-13 11:43:32 -08:00
from ifupdown2 . ifupdown . iface import *
from ifupdown2 . ifupdown . utils import utils
from ifupdown2 . ifupdown . netlink import netlink
from ifupdown2 . ifupdownaddons . dhclient import dhclient
from ifupdown2 . ifupdownaddons . LinkUtils import LinkUtils
from ifupdown2 . ifupdownaddons . modulebase import moduleBase
import ifupdown2 . ifupdown . statemanager as statemanager
import ifupdown2 . ifupdown . policymanager as policymanager
import ifupdown2 . ifupdown . ifupdownflags as ifupdownflags
import ifupdown2 . ifupdown . ifupdownconfig as ifupdownconfig
except ImportError :
2014-10-09 16:02:46 -07:00
from ifupdown . iface import *
2016-09-14 16:00:25 -07:00
from ifupdown . utils import utils
2018-12-13 11:43:32 -08:00
from ifupdown . netlink import netlink
2014-10-09 16:02:46 -07:00
from ifupdownaddons . dhclient import dhclient
2018-12-13 11:43:32 -08:00
from ifupdownaddons . LinkUtils import LinkUtils
from ifupdownaddons . modulebase import moduleBase
import ifupdown . statemanager as statemanager
2016-04-15 10:16:53 +02:00
import ifupdown . policymanager as policymanager
2016-04-14 14:45:47 -07:00
import ifupdown . ifupdownflags as ifupdownflags
2018-12-13 11:43:32 -08:00
import ifupdown . ifupdownconfig as ifupdownconfig
2014-10-09 16:02:46 -07:00
class address ( moduleBase ) :
""" ifupdown2 addon module to configure address, mtu, hwaddress, alias
( description ) on an interface """
_modinfo = { ' mhelp ' : ' address configuration module for interfaces ' ,
' attrs ' : {
' address ' :
{ ' help ' : ' ipv4 or ipv6 addresses ' ,
2016-08-01 09:19:31 +02:00
' validvals ' : [ ' <ipv4/prefixlen> ' , ' <ipv6/prefixlen> ' ] ,
2016-05-31 13:12:21 -07:00
' multiline ' : True ,
2014-10-09 16:02:46 -07:00
' example ' : [ ' address 10.0.12.3/24 ' ,
' address 2000:1000:1000:1000:3::5/128 ' ] } ,
' netmask ' :
{ ' help ' : ' netmask ' ,
' example ' : [ ' netmask 255.255.255.0 ' ] ,
' compat ' : True } ,
' broadcast ' :
{ ' help ' : ' broadcast address ' ,
2016-08-01 09:19:31 +02:00
' validvals ' : [ ' <ipv4> ' , ] ,
2014-10-09 16:02:46 -07:00
' example ' : [ ' broadcast 10.0.1.255 ' ] } ,
' scope ' :
{ ' help ' : ' scope ' ,
2016-05-31 13:12:21 -07:00
' validvals ' : [ ' universe ' , ' site ' , ' link ' , ' host ' , ' nowhere ' ] ,
2014-10-09 16:02:46 -07:00
' example ' : [ ' scope host ' ] } ,
' preferred-lifetime ' :
{ ' help ' : ' preferred lifetime ' ,
2016-05-31 13:12:21 -07:00
' validrange ' : [ ' 0 ' , ' 65535 ' ] ,
2014-10-09 16:02:46 -07:00
' example ' : [ ' preferred-lifetime forever ' ,
' preferred-lifetime 10 ' ] } ,
' gateway ' :
{ ' help ' : ' default gateway ' ,
2016-08-01 09:19:31 +02:00
' validvals ' : [ ' <ipv4> ' , ' <ipv6> ' ] ,
2016-09-07 16:57:55 +00:00
' multiline ' : True ,
2014-10-09 16:02:46 -07:00
' example ' : [ ' gateway 255.255.255.0 ' ] } ,
' mtu ' :
{ ' help ' : ' interface mtu ' ,
2016-05-31 13:12:21 -07:00
' validrange ' : [ ' 552 ' , ' 9216 ' ] ,
2014-10-09 16:02:46 -07:00
' example ' : [ ' mtu 1600 ' ] ,
' default ' : ' 1500 ' } ,
' hwaddress ' :
{ ' help ' : ' hw address ' ,
2016-05-31 13:12:21 -07:00
' validvals ' : [ ' <mac> ' , ] ,
2014-10-09 16:02:46 -07:00
' example ' : [ ' hwaddress 44:38:39:00:27:b8 ' ] } ,
' alias ' :
{ ' help ' : ' description/alias ' ,
2014-11-11 21:08:38 -08:00
' example ' : [ ' alias testnetwork ' ] } ,
' address-purge ' :
{ ' help ' : ' purge existing addresses. By default ' +
' any existing ip addresses on an interface are ' +
' purged to match persistant addresses in the ' +
' interfaces file. Set this attribute to \' no \' ' +
' if you want to preserve existing addresses ' ,
2016-05-31 13:12:21 -07:00
' validvals ' : [ ' yes ' , ' no ' ] ,
2014-11-11 21:08:38 -08:00
' default ' : ' yes ' ,
2015-09-04 00:32:15 -07:00
' example ' : [ ' address-purge yes/no ' ] } ,
' clagd-vxlan-anycast-ip ' :
{ ' help ' : ' Anycast local IP address for ' +
' dual connected VxLANs ' ,
2016-08-01 09:19:31 +02:00
' validvals ' : [ ' <ipv4> ' , ] ,
2018-12-13 11:43:32 -08:00
' example ' : [ ' clagd-vxlan-anycast-ip 36.0.0.11 ' ] } ,
' ip-forward ' :
{ ' help ' : ' ip forwarding flag ' ,
2018-07-14 21:54:48 -07:00
' validvals ' : [ ' on ' , ' off ' , ' yes ' , ' no ' , ' 0 ' , ' 1 ' ] ,
2018-12-13 11:43:32 -08:00
' default ' : ' off ' ,
' example ' : [ ' ip-forward off ' ] } ,
' ip6-forward ' :
{ ' help ' : ' ipv6 forwarding flag ' ,
2018-07-14 21:54:48 -07:00
' validvals ' : [ ' on ' , ' off ' , ' yes ' , ' no ' , ' 0 ' , ' 1 ' ] ,
2018-12-13 11:43:32 -08:00
' default ' : ' off ' ,
' example ' : [ ' ip6-forward off ' ] } ,
' mpls-enable ' :
{ ' help ' : ' mpls enable flag ' ,
' validvals ' : [ ' yes ' , ' no ' ] ,
' default ' : ' no ' ,
' example ' : [ ' mpls-enable yes ' ] } ,
2018-06-18 18:57:20 +02:00
' ipv6-addrgen ' : {
' help ' : ' enable disable ipv6 link addrgenmode ' ,
' validvals ' : [ ' on ' , ' off ' ] ,
' default ' : ' on ' ,
' example ' : [
' ipv6-addrgen on ' ,
' ipv6-addrgen off '
]
}
2018-12-13 11:43:32 -08:00
} }
2014-10-09 16:02:46 -07:00
def __init__ ( self , * args , * * kargs ) :
moduleBase . __init__ ( self , * args , * * kargs )
self . ipcmd = None
2014-11-03 17:55:51 -08:00
self . _bridge_fdb_query_cache = { }
2016-04-15 10:16:53 +02:00
self . default_mtu = policymanager . policymanager_api . get_attr_default ( module_name = self . __class__ . __name__ , attr = ' mtu ' )
2016-11-07 10:48:24 -08:00
self . max_mtu = policymanager . policymanager_api . get_module_globals ( module_name = self . __class__ . __name__ , attr = ' max_mtu ' )
2018-12-13 11:43:32 -08:00
self . ipforward = policymanager . policymanager_api . get_attr_default ( module_name = self . __class__ . __name__ , attr = ' ip-forward ' )
self . ip6forward = policymanager . policymanager_api . get_attr_default ( module_name = self . __class__ . __name__ , attr = ' ip6-forward ' )
self . ifaces_defaults = policymanager . policymanager_api . get_iface_defaults ( module_name = self . __class__ . __name__ )
self . enable_l3_iface_forwarding_checks = utils . get_boolean_from_string (
policymanager . policymanager_api . get_module_globals (
self . __class__ . __name__ ,
' enable_l3_iface_forwarding_checks '
)
)
2016-11-07 10:48:24 -08:00
if not self . default_mtu :
self . default_mtu = ' 1500 '
self . logger . info ( ' address: using default mtu %s ' % self . default_mtu )
if self . max_mtu :
self . logger . info ( ' address: using max mtu %s ' % self . max_mtu )
2014-10-09 16:02:46 -07:00
2018-12-13 11:43:32 -08:00
self . lower_iface_mtu_checked_list = list ( )
2018-10-19 17:42:24 +02:00
self . l3_intf_arp_accept = utils . get_boolean_from_string (
policymanager . policymanager_api . get_module_globals (
module_name = self . __class__ . __name__ ,
attr = ' l3_intf_arp_accept '
) ,
default = False
)
2018-10-30 11:31:11 +01:00
self . l3_intf_default_gateway_set_onlink = utils . get_boolean_from_string (
policymanager . policymanager_api . get_module_globals (
module_name = self . __class__ . __name__ ,
attr = ' l3_intf_default_gateway_set_onlink '
) ,
default = True
)
2016-12-01 11:48:16 -08:00
def syntax_check ( self , ifaceobj , ifaceobj_getfunc = None ) :
2016-11-22 17:06:16 +01:00
return ( self . syntax_check_multiple_gateway ( ifaceobj )
2016-12-01 11:48:16 -08:00
and self . syntax_check_addr_allowed_on ( ifaceobj , True )
2018-12-13 11:43:32 -08:00
and self . syntax_check_mtu ( ifaceobj , ifaceobj_getfunc )
and self . syntax_check_sysctls ( ifaceobj )
and self . syntax_check_enable_l3_iface_forwardings ( ifaceobj , ifaceobj_getfunc , syntax_check = True ) )
def syntax_check_enable_l3_iface_forwardings ( self , ifaceobj , ifaceobj_getfunc , syntax_check = False ) :
if ( self . enable_l3_iface_forwarding_checks
and ( ifaceobj . link_kind & ifaceLinkKind . VLAN
or ifaceobj . link_kind & ifaceLinkKind . BRIDGE )
and not ifaceobj . link_privflags & ifaceLinkPrivFlags . BRIDGE_PORT ) :
ifname = ifaceobj . name
vlan_addr = None
vlan_ipforward_off = None
for obj in ifaceobj_getfunc ( ifname ) or [ ifaceobj ] :
if not vlan_addr :
vlan_addr = obj . get_attr_value ( ' address ' )
if not vlan_ipforward_off :
ip_forward_value = obj . get_attr_value_first ( ' ip-forward ' )
if ip_forward_value and not utils . get_boolean_from_string ( ip_forward_value ) :
vlan_ipforward_off = True
if vlan_addr and vlan_ipforward_off :
if syntax_check :
raise Exception (
' configuring ip-forward off and ip address(es) ( %s ) is not compatible '
% ( ' , ' . join ( vlan_addr ) )
)
else :
raise Exception (
' %s : configuring ip-forward off and ip address(es) ( %s ) is not compatible '
% ( ifname , ' , ' . join ( vlan_addr ) )
)
return True
def syntax_check_sysctls ( self , ifaceobj ) :
result = True
bridge_port = ( ifaceobj . link_privflags & ifaceLinkPrivFlags . BRIDGE_PORT )
ipforward = ifaceobj . get_attr_value_first ( ' ip-forward ' )
if bridge_port and ipforward :
result = False
self . log_error ( ' %s : \' ip-forward \' is not supported for '
' bridge port ' % ifaceobj . name )
ip6forward = ifaceobj . get_attr_value_first ( ' ip6-forward ' )
if bridge_port and ip6forward :
result = False
self . log_error ( ' %s : \' ip6-forward \' is not supported for '
' bridge port ' % ifaceobj . name )
return result
2016-12-01 11:48:16 -08:00
def syntax_check_mtu ( self , ifaceobj , ifaceobj_getfunc ) :
mtu = ifaceobj . get_attr_value_first ( ' mtu ' )
if mtu :
return self . _check_mtu_config ( ifaceobj , mtu , ifaceobj_getfunc ,
syntaxcheck = True )
return True
2016-11-22 17:06:16 +01:00
def syntax_check_addr_allowed_on ( self , ifaceobj , syntax_check = False ) :
if ifaceobj . get_attr_value ( ' address ' ) :
return utils . is_addr_ip_allowed_on ( ifaceobj , syntax_check = syntax_check )
return True
2016-11-21 16:43:57 +01:00
def _syntax_check_multiple_gateway ( self , family , found , addr , type_obj ) :
if type ( IPNetwork ( addr ) ) == type_obj :
if found :
raise Exception ( ' %s : multiple gateways for %s family '
% ( addr , family ) )
return True
return False
2016-11-22 17:06:16 +01:00
def syntax_check_multiple_gateway ( self , ifaceobj ) :
2016-11-21 16:43:57 +01:00
result = True
inet = False
inet6 = False
gateways = ifaceobj . get_attr_value ( ' gateway ' )
for addr in gateways if gateways else [ ] :
try :
if self . _syntax_check_multiple_gateway ( ' inet ' , inet , addr ,
IPv4Network ) :
inet = True
if self . _syntax_check_multiple_gateway ( ' inet6 ' , inet6 , addr ,
IPv6Network ) :
inet6 = True
except Exception as e :
self . logger . warning ( ' %s : address: %s ' % ( ifaceobj . name , str ( e ) ) )
result = False
return result
2014-11-17 16:23:42 -08:00
def _address_valid ( self , addrs ) :
if not addrs :
return False
if any ( map ( lambda a : True if a [ : 7 ] != ' 0.0.0.0 '
else False , addrs ) ) :
return True
return False
2016-03-15 15:41:04 +01:00
def _get_hwaddress ( self , ifaceobj ) :
2018-12-13 11:43:32 -08:00
return utils . strip_hwaddress ( ifaceobj . get_attr_value_first ( ' hwaddress ' ) )
2016-03-15 15:41:04 +01:00
def _process_bridge ( self , ifaceobj , up ) :
hwaddress = self . _get_hwaddress ( ifaceobj )
2014-11-17 16:23:42 -08:00
addrs = ifaceobj . get_attr_value_first ( ' address ' )
is_vlan_dev_on_vlan_aware_bridge = False
is_bridge = self . ipcmd . is_bridge ( ifaceobj . name )
if not is_bridge :
2018-12-13 11:43:32 -08:00
if ifaceobj . link_kind & ifaceLinkKind . VLAN :
bridgename = ifaceobj . lowerifaces [ 0 ]
vlan = self . _get_vlan_id ( ifaceobj )
2014-11-17 16:23:42 -08:00
is_vlan_dev_on_vlan_aware_bridge = self . ipcmd . bridge_is_vlan_aware ( bridgename )
2014-12-17 15:09:52 -08:00
if ( ( is_bridge and not self . ipcmd . bridge_is_vlan_aware ( ifaceobj . name ) )
or is_vlan_dev_on_vlan_aware_bridge ) :
2018-10-19 17:42:24 +02:00
if self . _address_valid ( addrs ) :
if self . l3_intf_arp_accept :
if up :
self . write_file ( ' /proc/sys/net/ipv4/conf/ %s ' % ifaceobj . name +
' /arp_accept ' , ' 1 ' )
else :
self . write_file ( ' /proc/sys/net/ipv4/conf/ %s ' % ifaceobj . name +
' /arp_accept ' , ' 0 ' )
else :
self . write_file ( ' /proc/sys/net/ipv4/conf/ %s /arp_accept ' % ifaceobj . name , ' 0 ' )
2014-11-17 16:23:42 -08:00
if hwaddress and is_vlan_dev_on_vlan_aware_bridge :
if up :
self . ipcmd . bridge_fdb_add ( bridgename , hwaddress , vlan )
else :
self . ipcmd . bridge_fdb_del ( bridgename , hwaddress , vlan )
2014-10-28 23:04:40 -07:00
2015-11-16 21:00:40 -08:00
def _get_anycast_addr ( self , ifaceobjlist ) :
for ifaceobj in ifaceobjlist :
anycast_addr = ifaceobj . get_attr_value_first ( ' clagd-vxlan-anycast-ip ' )
if anycast_addr :
anycast_addr = anycast_addr + ' /32 '
return anycast_addr
return None
def _inet_address_convert_to_cidr ( self , ifaceobjlist ) :
2014-10-09 16:02:46 -07:00
newaddrs = [ ]
2015-11-16 21:00:40 -08:00
newaddr_attrs = { }
for ifaceobj in ifaceobjlist :
addrs = ifaceobj . get_attr_value ( ' address ' )
if not addrs :
continue
2016-11-22 17:06:16 +01:00
if not self . syntax_check_addr_allowed_on ( ifaceobj ,
syntax_check = False ) :
2015-11-16 21:00:40 -08:00
return ( False , newaddrs , newaddr_attrs )
2014-10-09 16:02:46 -07:00
# If user address is not in CIDR notation, convert them to CIDR
for addr_index in range ( 0 , len ( addrs ) ) :
addr = addrs [ addr_index ]
2017-08-23 23:11:57 +02:00
newaddr = addr
2014-10-09 16:02:46 -07:00
if ' / ' in addr :
newaddrs . append ( addr )
2016-05-19 08:14:13 -07:00
else :
2017-08-23 23:11:57 +02:00
netmask = ifaceobj . get_attr_value_n ( ' netmask ' , addr_index )
if netmask :
prefixlen = IPNetwork ( ' %s ' % addr +
' / %s ' % netmask ) . prefixlen
newaddr = addr + ' / %s ' % prefixlen
else :
# we are here because there is no slash (/xx) and no netmask
# just let IPNetwork handle the ipv4 or ipv6 address mask
prefixlen = IPNetwork ( addr ) . prefixlen
newaddr = addr + ' / %s ' % prefixlen
newaddrs . append ( newaddr )
2014-10-09 16:02:46 -07:00
2015-11-16 21:00:40 -08:00
attrs = { }
for a in [ ' broadcast ' , ' pointopoint ' , ' scope ' ,
' preferred-lifetime ' ] :
aval = ifaceobj . get_attr_value_n ( a , addr_index )
if aval :
2016-02-08 13:05:33 -08:00
attrs [ a ] = aval
2015-11-16 21:00:40 -08:00
if attrs :
newaddr_attrs [ newaddr ] = attrs
return ( True , newaddrs , newaddr_attrs )
2016-05-09 18:48:52 -07:00
def _inet_address_list_config ( self , ifaceobj , newaddrs , newaddr_attrs ) :
for addr_index in range ( 0 , len ( newaddrs ) ) :
try :
if newaddr_attrs :
self . ipcmd . addr_add ( ifaceobj . name , newaddrs [ addr_index ] ,
newaddr_attrs . get ( newaddrs [ addr_index ] ,
{ } ) . get ( ' broadcast ' ) ,
newaddr_attrs . get ( newaddrs [ addr_index ] ,
{ } ) . get ( ' pointopoint ' ) ,
newaddr_attrs . get ( newaddrs [ addr_index ] ,
{ } ) . get ( ' scope ' ) ,
newaddr_attrs . get ( newaddrs [ addr_index ] ,
{ } ) . get ( ' preferred-lifetime ' ) )
else :
self . ipcmd . addr_add ( ifaceobj . name , newaddrs [ addr_index ] )
except Exception , e :
2016-05-15 13:28:10 -07:00
self . log_error ( str ( e ) , ifaceobj )
2016-05-09 18:48:52 -07:00
def _inet_address_config ( self , ifaceobj , ifaceobj_getfunc = None ,
force_reapply = False ) :
2015-11-16 21:00:40 -08:00
squash_addr_config = ( True if \
2018-12-13 11:43:32 -08:00
ifupdownconfig . config . get ( ' addr_config_squash ' , \
' 0 ' ) == ' 1 ' else False )
2015-11-16 21:00:40 -08:00
if ( squash_addr_config and
not ( ifaceobj . flags & ifaceobj . YOUNGEST_SIBLING ) ) :
return
purge_addresses = ifaceobj . get_attr_value_first ( ' address-purge ' )
if not purge_addresses :
purge_addresses = ' yes '
if squash_addr_config and ifaceobj . flags & iface . HAS_SIBLINGS :
ifaceobjlist = ifaceobj_getfunc ( ifaceobj . name )
else :
ifaceobjlist = [ ifaceobj ]
2018-12-13 11:43:32 -08:00
module_name = self . __class__ . __name__
ifname = ifaceobj . name
2015-11-16 21:00:40 -08:00
( addr_supported , newaddrs , newaddr_attrs ) = self . _inet_address_convert_to_cidr ( ifaceobjlist )
2018-12-13 11:43:32 -08:00
newaddrs = utils . get_ip_objs ( module_name , ifname , newaddrs )
2015-11-16 21:00:40 -08:00
if not addr_supported :
return
if ( not squash_addr_config and ( ifaceobj . flags & iface . HAS_SIBLINGS ) ) :
# if youngest sibling and squash addr is not set
# print a warning that addresses will not be purged
if ( ifaceobj . flags & iface . YOUNGEST_SIBLING ) :
self . logger . warn ( ' %s : interface has multiple ' % ifaceobj . name +
' iface stanzas, skip purging existing addresses ' )
purge_addresses = ' no '
2016-04-14 14:45:47 -07:00
if not ifupdownflags . flags . PERFMODE and purge_addresses == ' yes ' :
2015-11-16 21:00:40 -08:00
# if perfmode is not set and purge addresses is not set to 'no'
# lets purge addresses not in the config
2018-12-13 11:43:32 -08:00
runningaddrs = self . ipcmd . get_running_addrs ( ifaceobj , details = False )
2015-11-16 21:00:40 -08:00
2015-09-04 00:32:15 -07:00
# if anycast address is configured on 'lo' and is in running config
# add it to newaddrs so that ifreload doesn't wipe it out
2016-09-14 16:00:25 -07:00
anycast_addr = utils . get_normalized_ip_addr ( ifaceobj . name , self . _get_anycast_addr ( ifaceobjlist ) )
2015-11-16 21:00:40 -08:00
2015-09-04 00:32:15 -07:00
if runningaddrs and anycast_addr and anycast_addr in runningaddrs :
newaddrs . append ( anycast_addr )
2018-12-13 11:43:32 -08:00
user_ip4 , user_ip6 , newaddrs = self . order_user_configured_addrs ( newaddrs )
if newaddrs == runningaddrs or self . compare_running_ips_and_user_config ( user_ip4 , user_ip6 , runningaddrs ) :
2016-05-09 18:48:52 -07:00
if force_reapply :
self . _inet_address_list_config ( ifaceobj , newaddrs , newaddr_attrs )
2014-10-09 16:02:46 -07:00
return
try :
# if primary address is not same, there is no need to keep any.
# reset all addresses
2018-12-13 11:43:32 -08:00
if newaddrs and runningaddrs and newaddrs [ 0 ] != runningaddrs [ 0 ] :
skip_addrs = [ ]
2014-10-09 16:02:46 -07:00
else :
2018-12-13 11:43:32 -08:00
skip_addrs = newaddrs or [ ]
for addr in runningaddrs or [ ] :
if addr in skip_addrs :
continue
self . ipcmd . addr_del ( ifaceobj . name , addr )
2014-10-09 16:02:46 -07:00
except Exception , e :
self . log_warn ( str ( e ) )
if not newaddrs :
return
2016-05-09 18:48:52 -07:00
self . _inet_address_list_config ( ifaceobj , newaddrs , newaddr_attrs )
2014-10-09 16:02:46 -07:00
2018-12-13 11:43:32 -08:00
def compare_running_ips_and_user_config ( self , user_ip4 , user_ip6 , running_addrs ) :
"""
We need to compare the user config ips and the running ips .
ip4 ordering matters ( primary etc ) but ip6 order doesn ' t matter
this function replaces the strict comparison previously in place
if newaddrs == running_addrs ?
We will compare if the ip4 ordering is correct , then check if all
ip6 are present in the list ( without checking the ordering )
"""
if ( user_ip4 or user_ip6 ) and not running_addrs :
return False
elif running_addrs and not user_ip4 and not user_ip6 :
return False
elif not running_addrs and not user_ip4 and not user_ip6 :
return True
len_ip4 = len ( user_ip4 )
len_running_addrs = len ( running_addrs )
if len_ip4 > len_running_addrs :
return False
i = 0
while i < len_ip4 :
if user_ip4 [ i ] != running_addrs [ i ] :
return False
i + = 1
if len_ip4 > 0 :
running_ip6 = running_addrs [ len_ip4 : ]
else :
running_ip6 = running_addrs
i = 0
len_ip6 = len ( user_ip6 )
for ip6 in running_ip6 :
if ip6 not in user_ip6 :
return False
i + = 1
return i == len_ip6
def order_user_configured_addrs ( self , user_config_addrs ) :
ip4 = [ ]
ip6 = [ ]
for a in user_config_addrs :
if isinstance ( a , _BaseV6 ) :
ip6 . append ( str ( a ) )
else :
ip4 . append ( str ( a ) )
return ip4 , ip6 , ip4 + ip6
def _delete_gateway ( self , ifaceobj , gateways , vrf , metric ) :
for del_gw in gateways :
2016-07-20 15:23:13 -07:00
try :
self . ipcmd . route_del_gateway ( ifaceobj . name , del_gw , vrf , metric )
2017-01-13 06:51:28 +03:00
except Exception as e :
self . logger . debug ( ' %s : %s ' % ( ifaceobj . name , str ( e ) ) )
2018-12-13 11:43:32 -08:00
def _add_delete_gateway ( self , ifaceobj , gateways = [ ] , prev_gw = [ ] ) :
vrf = ifaceobj . get_attr_value_first ( ' vrf ' )
metric = ifaceobj . get_attr_value_first ( ' metric ' )
self . _delete_gateway ( ifaceobj , list ( set ( prev_gw ) - set ( gateways ) ) ,
vrf , metric )
2017-01-17 17:55:35 -08:00
for add_gw in gateways :
2016-07-20 15:23:13 -07:00
try :
2018-10-30 11:31:11 +01:00
self . ipcmd . route_add_gateway ( ifaceobj . name , add_gw , vrf , metric , onlink = self . l3_intf_default_gateway_set_onlink )
2017-01-13 06:51:28 +03:00
except Exception as e :
self . log_error ( ' %s : %s ' % ( ifaceobj . name , str ( e ) ) )
2016-07-20 15:23:13 -07:00
def _get_prev_gateway ( self , ifaceobj , gateways ) :
ipv = [ ]
saved_ifaceobjs = statemanager . statemanager_api . get_ifaceobjs ( ifaceobj . name )
if not saved_ifaceobjs :
return ipv
prev_gateways = saved_ifaceobjs [ 0 ] . get_attr_value ( ' gateway ' )
if not prev_gateways :
return ipv
return prev_gateways
addons: address: propagate physical mtu to upper vlan devices
Ticket: CM-13221
Reviewed By: julien, nikhil
Testing Done: tested mtu propagation for vlan devices
This is a followup to commit
29de36f36053 ("addons: address: various fixes for mtu handling").
This fixes a pending issue with mtu readjustments on vlan
interfaces on top of physical interfaces.
eg: with the below config:
$ifquery -a
auto swp1.100
iface swp1.100
auto swp1
iface swp1
mtu 9000
/* at boot-up swp1 and swp1.100 mtu is set to 9000 */
$ifdown swp1 /* resets swp1 mtu to 1500. swp1.100 mtu is reset to 1500
implicitly by the kernel */
$ifup swp1 /* swp1 mtu is set to 1500. But swp1.100 mtu stays at 1500
*/
This problem is unique to physical interfaces and vlan devices on
physical interfaces. This is because, when logical interface is ifdown,
kernel deletes all its sub-interfaces. And on the way up (ifup),
ifupdown2 re-creates all these sub-interfaces for you....that
sequence re-adjusts the mtu. For physical
interfaces, since the sub-interfaces are not deleted,
ifupdown2 does not do anything...and mtu of the subinterface is left to
what it was. And this ends up being what was there initially when the
lower interface went down. And ifdown of the lower physical interface,
resets the physical mtu to default which is 1500. The sub-interface mtu
returns to 1500 while the lower physical interface remains down.
(another detail here: kernel vlan driver re-adjusts mtu of the vlan
sub-interface on its own when the lower device mtu becomes lower. But
does not re-adjust its mtu when the lower device mtu increases. This is
expected and correct behavior). We will have to work around it in
ifupdown2 to suit our needs.
two solutions:
a) when physical interface is brought up, ifupdown2 can go and
pro-actively adjust the upper sub-interface mtu
OR
b) when physical interface is brought down, do not reset the mtu on the
device to default
(b) is the easiest and costs less if we dont expect the mtu of a
physical device to go to default on ifdown.
(a) is doable too, but is additional cost to go over all upper
interfaces.
This patch fixes this problem with solution (a). But, makes sure
this does not add additional cost to the default ifreload -a path.
Signed-off-by: Roopa Prabhu <roopa@cumulusnetworks.com>
2016-11-28 13:24:31 -08:00
def _check_mtu_config ( self , ifaceobj , mtu , ifaceobj_getfunc , syntaxcheck = False ) :
retval = True
if ( ifaceobj . link_kind & ifaceLinkKind . BRIDGE ) :
if syntaxcheck :
self . logger . warn ( ' %s : bridge inherits mtu from its ports. There is no need to assign mtu on a bridge ' % ifaceobj . name )
retval = False
else :
2016-11-07 10:48:24 -08:00
self . logger . info ( ' %s : bridge inherits mtu from its ports. There is no need to assign mtu on a bridge ' % ifaceobj . name )
addons: address: propagate physical mtu to upper vlan devices
Ticket: CM-13221
Reviewed By: julien, nikhil
Testing Done: tested mtu propagation for vlan devices
This is a followup to commit
29de36f36053 ("addons: address: various fixes for mtu handling").
This fixes a pending issue with mtu readjustments on vlan
interfaces on top of physical interfaces.
eg: with the below config:
$ifquery -a
auto swp1.100
iface swp1.100
auto swp1
iface swp1
mtu 9000
/* at boot-up swp1 and swp1.100 mtu is set to 9000 */
$ifdown swp1 /* resets swp1 mtu to 1500. swp1.100 mtu is reset to 1500
implicitly by the kernel */
$ifup swp1 /* swp1 mtu is set to 1500. But swp1.100 mtu stays at 1500
*/
This problem is unique to physical interfaces and vlan devices on
physical interfaces. This is because, when logical interface is ifdown,
kernel deletes all its sub-interfaces. And on the way up (ifup),
ifupdown2 re-creates all these sub-interfaces for you....that
sequence re-adjusts the mtu. For physical
interfaces, since the sub-interfaces are not deleted,
ifupdown2 does not do anything...and mtu of the subinterface is left to
what it was. And this ends up being what was there initially when the
lower interface went down. And ifdown of the lower physical interface,
resets the physical mtu to default which is 1500. The sub-interface mtu
returns to 1500 while the lower physical interface remains down.
(another detail here: kernel vlan driver re-adjusts mtu of the vlan
sub-interface on its own when the lower device mtu becomes lower. But
does not re-adjust its mtu when the lower device mtu increases. This is
expected and correct behavior). We will have to work around it in
ifupdown2 to suit our needs.
two solutions:
a) when physical interface is brought up, ifupdown2 can go and
pro-actively adjust the upper sub-interface mtu
OR
b) when physical interface is brought down, do not reset the mtu on the
device to default
(b) is the easiest and costs less if we dont expect the mtu of a
physical device to go to default on ifdown.
(a) is doable too, but is additional cost to go over all upper
interfaces.
This patch fixes this problem with solution (a). But, makes sure
this does not add additional cost to the default ifreload -a path.
Signed-off-by: Roopa Prabhu <roopa@cumulusnetworks.com>
2016-11-28 13:24:31 -08:00
elif ifaceobj_getfunc :
if ( ( ifaceobj . link_privflags & ifaceLinkPrivFlags . BOND_SLAVE ) and
ifaceobj . upperifaces ) :
2016-11-07 10:48:24 -08:00
masterobj = ifaceobj_getfunc ( ifaceobj . upperifaces [ 0 ] )
if masterobj :
master_mtu = masterobj [ 0 ] . get_attr_value_first ( ' mtu ' )
if master_mtu and master_mtu != mtu :
addons: address: propagate physical mtu to upper vlan devices
Ticket: CM-13221
Reviewed By: julien, nikhil
Testing Done: tested mtu propagation for vlan devices
This is a followup to commit
29de36f36053 ("addons: address: various fixes for mtu handling").
This fixes a pending issue with mtu readjustments on vlan
interfaces on top of physical interfaces.
eg: with the below config:
$ifquery -a
auto swp1.100
iface swp1.100
auto swp1
iface swp1
mtu 9000
/* at boot-up swp1 and swp1.100 mtu is set to 9000 */
$ifdown swp1 /* resets swp1 mtu to 1500. swp1.100 mtu is reset to 1500
implicitly by the kernel */
$ifup swp1 /* swp1 mtu is set to 1500. But swp1.100 mtu stays at 1500
*/
This problem is unique to physical interfaces and vlan devices on
physical interfaces. This is because, when logical interface is ifdown,
kernel deletes all its sub-interfaces. And on the way up (ifup),
ifupdown2 re-creates all these sub-interfaces for you....that
sequence re-adjusts the mtu. For physical
interfaces, since the sub-interfaces are not deleted,
ifupdown2 does not do anything...and mtu of the subinterface is left to
what it was. And this ends up being what was there initially when the
lower interface went down. And ifdown of the lower physical interface,
resets the physical mtu to default which is 1500. The sub-interface mtu
returns to 1500 while the lower physical interface remains down.
(another detail here: kernel vlan driver re-adjusts mtu of the vlan
sub-interface on its own when the lower device mtu becomes lower. But
does not re-adjust its mtu when the lower device mtu increases. This is
expected and correct behavior). We will have to work around it in
ifupdown2 to suit our needs.
two solutions:
a) when physical interface is brought up, ifupdown2 can go and
pro-actively adjust the upper sub-interface mtu
OR
b) when physical interface is brought down, do not reset the mtu on the
device to default
(b) is the easiest and costs less if we dont expect the mtu of a
physical device to go to default on ifdown.
(a) is doable too, but is additional cost to go over all upper
interfaces.
This patch fixes this problem with solution (a). But, makes sure
this does not add additional cost to the default ifreload -a path.
Signed-off-by: Roopa Prabhu <roopa@cumulusnetworks.com>
2016-11-28 13:24:31 -08:00
if syntaxcheck :
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 ) )
retval = False
else :
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 ) )
elif ( ( ifaceobj . link_kind & ifaceLinkKind . VLAN ) and
ifaceobj . lowerifaces ) :
lowerobj = ifaceobj_getfunc ( ifaceobj . lowerifaces [ 0 ] )
if lowerobj :
if syntaxcheck :
lowerdev_mtu = lowerobj [ 0 ] . get_attr_value_first ( ' mtu ' )
else :
2018-12-13 11:43:32 -08:00
lowerdev_mtu = self . ipcmd . link_get_mtu_sysfs ( lowerobj [ 0 ] . name )
addons: address: propagate physical mtu to upper vlan devices
Ticket: CM-13221
Reviewed By: julien, nikhil
Testing Done: tested mtu propagation for vlan devices
This is a followup to commit
29de36f36053 ("addons: address: various fixes for mtu handling").
This fixes a pending issue with mtu readjustments on vlan
interfaces on top of physical interfaces.
eg: with the below config:
$ifquery -a
auto swp1.100
iface swp1.100
auto swp1
iface swp1
mtu 9000
/* at boot-up swp1 and swp1.100 mtu is set to 9000 */
$ifdown swp1 /* resets swp1 mtu to 1500. swp1.100 mtu is reset to 1500
implicitly by the kernel */
$ifup swp1 /* swp1 mtu is set to 1500. But swp1.100 mtu stays at 1500
*/
This problem is unique to physical interfaces and vlan devices on
physical interfaces. This is because, when logical interface is ifdown,
kernel deletes all its sub-interfaces. And on the way up (ifup),
ifupdown2 re-creates all these sub-interfaces for you....that
sequence re-adjusts the mtu. For physical
interfaces, since the sub-interfaces are not deleted,
ifupdown2 does not do anything...and mtu of the subinterface is left to
what it was. And this ends up being what was there initially when the
lower interface went down. And ifdown of the lower physical interface,
resets the physical mtu to default which is 1500. The sub-interface mtu
returns to 1500 while the lower physical interface remains down.
(another detail here: kernel vlan driver re-adjusts mtu of the vlan
sub-interface on its own when the lower device mtu becomes lower. But
does not re-adjust its mtu when the lower device mtu increases. This is
expected and correct behavior). We will have to work around it in
ifupdown2 to suit our needs.
two solutions:
a) when physical interface is brought up, ifupdown2 can go and
pro-actively adjust the upper sub-interface mtu
OR
b) when physical interface is brought down, do not reset the mtu on the
device to default
(b) is the easiest and costs less if we dont expect the mtu of a
physical device to go to default on ifdown.
(a) is doable too, but is additional cost to go over all upper
interfaces.
This patch fixes this problem with solution (a). But, makes sure
this does not add additional cost to the default ifreload -a path.
Signed-off-by: Roopa Prabhu <roopa@cumulusnetworks.com>
2016-11-28 13:24:31 -08:00
if lowerdev_mtu and int ( mtu ) > int ( lowerdev_mtu ) :
self . logger . warn ( ' %s : vlan dev mtu %s is greater than lower realdev %s mtu %s '
% ( ifaceobj . name , mtu , lowerobj [ 0 ] . name , lowerdev_mtu ) )
retval = False
elif ( not lowerobj [ 0 ] . link_kind and
not ( lowerobj [ 0 ] . link_privflags & ifaceLinkPrivFlags . LOOPBACK ) and
2018-12-13 11:43:32 -08:00
not lowerdev_mtu and self . default_mtu and
( int ( mtu ) > int ( self . default_mtu ) ) ) :
addons: address: propagate physical mtu to upper vlan devices
Ticket: CM-13221
Reviewed By: julien, nikhil
Testing Done: tested mtu propagation for vlan devices
This is a followup to commit
29de36f36053 ("addons: address: various fixes for mtu handling").
This fixes a pending issue with mtu readjustments on vlan
interfaces on top of physical interfaces.
eg: with the below config:
$ifquery -a
auto swp1.100
iface swp1.100
auto swp1
iface swp1
mtu 9000
/* at boot-up swp1 and swp1.100 mtu is set to 9000 */
$ifdown swp1 /* resets swp1 mtu to 1500. swp1.100 mtu is reset to 1500
implicitly by the kernel */
$ifup swp1 /* swp1 mtu is set to 1500. But swp1.100 mtu stays at 1500
*/
This problem is unique to physical interfaces and vlan devices on
physical interfaces. This is because, when logical interface is ifdown,
kernel deletes all its sub-interfaces. And on the way up (ifup),
ifupdown2 re-creates all these sub-interfaces for you....that
sequence re-adjusts the mtu. For physical
interfaces, since the sub-interfaces are not deleted,
ifupdown2 does not do anything...and mtu of the subinterface is left to
what it was. And this ends up being what was there initially when the
lower interface went down. And ifdown of the lower physical interface,
resets the physical mtu to default which is 1500. The sub-interface mtu
returns to 1500 while the lower physical interface remains down.
(another detail here: kernel vlan driver re-adjusts mtu of the vlan
sub-interface on its own when the lower device mtu becomes lower. But
does not re-adjust its mtu when the lower device mtu increases. This is
expected and correct behavior). We will have to work around it in
ifupdown2 to suit our needs.
two solutions:
a) when physical interface is brought up, ifupdown2 can go and
pro-actively adjust the upper sub-interface mtu
OR
b) when physical interface is brought down, do not reset the mtu on the
device to default
(b) is the easiest and costs less if we dont expect the mtu of a
physical device to go to default on ifdown.
(a) is doable too, but is additional cost to go over all upper
interfaces.
This patch fixes this problem with solution (a). But, makes sure
this does not add additional cost to the default ifreload -a path.
Signed-off-by: Roopa Prabhu <roopa@cumulusnetworks.com>
2016-11-28 13:24:31 -08:00
# only check default mtu on lower device which is a physical interface
self . logger . warn ( ' %s : vlan dev mtu %s is greater than lower realdev %s mtu %s '
% ( ifaceobj . name , mtu , lowerobj [ 0 ] . name , self . default_mtu ) )
retval = False
2016-11-07 10:48:24 -08:00
if self . max_mtu and mtu > self . max_mtu :
self . logger . warn ( ' %s : specified mtu %s is greater than max mtu %s '
% ( ifaceobj . name , mtu , self . max_mtu ) )
addons: address: propagate physical mtu to upper vlan devices
Ticket: CM-13221
Reviewed By: julien, nikhil
Testing Done: tested mtu propagation for vlan devices
This is a followup to commit
29de36f36053 ("addons: address: various fixes for mtu handling").
This fixes a pending issue with mtu readjustments on vlan
interfaces on top of physical interfaces.
eg: with the below config:
$ifquery -a
auto swp1.100
iface swp1.100
auto swp1
iface swp1
mtu 9000
/* at boot-up swp1 and swp1.100 mtu is set to 9000 */
$ifdown swp1 /* resets swp1 mtu to 1500. swp1.100 mtu is reset to 1500
implicitly by the kernel */
$ifup swp1 /* swp1 mtu is set to 1500. But swp1.100 mtu stays at 1500
*/
This problem is unique to physical interfaces and vlan devices on
physical interfaces. This is because, when logical interface is ifdown,
kernel deletes all its sub-interfaces. And on the way up (ifup),
ifupdown2 re-creates all these sub-interfaces for you....that
sequence re-adjusts the mtu. For physical
interfaces, since the sub-interfaces are not deleted,
ifupdown2 does not do anything...and mtu of the subinterface is left to
what it was. And this ends up being what was there initially when the
lower interface went down. And ifdown of the lower physical interface,
resets the physical mtu to default which is 1500. The sub-interface mtu
returns to 1500 while the lower physical interface remains down.
(another detail here: kernel vlan driver re-adjusts mtu of the vlan
sub-interface on its own when the lower device mtu becomes lower. But
does not re-adjust its mtu when the lower device mtu increases. This is
expected and correct behavior). We will have to work around it in
ifupdown2 to suit our needs.
two solutions:
a) when physical interface is brought up, ifupdown2 can go and
pro-actively adjust the upper sub-interface mtu
OR
b) when physical interface is brought down, do not reset the mtu on the
device to default
(b) is the easiest and costs less if we dont expect the mtu of a
physical device to go to default on ifdown.
(a) is doable too, but is additional cost to go over all upper
interfaces.
This patch fixes this problem with solution (a). But, makes sure
this does not add additional cost to the default ifreload -a path.
Signed-off-by: Roopa Prabhu <roopa@cumulusnetworks.com>
2016-11-28 13:24:31 -08:00
retval = False
return retval
def _propagate_mtu_to_upper_devs ( self , ifaceobj , mtu , ifaceobj_getfunc ) :
if ( not ifaceobj . upperifaces or
( ifaceobj . link_privflags & ifaceLinkPrivFlags . BOND_SLAVE ) or
( ifaceobj . link_privflags & ifaceLinkPrivFlags . VRF_SLAVE ) or
( ifaceobj . link_privflags & ifaceLinkPrivFlags . BRIDGE_PORT ) ) :
return
for u in ifaceobj . upperifaces :
upperobjs = ifaceobj_getfunc ( u )
if ( not upperobjs or
not ( upperobjs [ 0 ] . link_kind & ifaceLinkKind . VLAN ) ) :
continue
# only adjust mtu for vlan devices on ifaceobj
umtu = upperobjs [ 0 ] . get_attr_value_first ( ' mtu ' )
if not umtu :
running_mtu = self . ipcmd . link_get_mtu ( upperobjs [ 0 ] . name )
if not running_mtu or ( running_mtu != mtu ) :
self . ipcmd . link_set ( u , ' mtu ' , mtu )
2018-12-13 11:43:32 -08:00
def _process_mtu_config ( self , ifaceobj , ifaceobj_getfunc , mtu ) :
addons: address: propagate physical mtu to upper vlan devices
Ticket: CM-13221
Reviewed By: julien, nikhil
Testing Done: tested mtu propagation for vlan devices
This is a followup to commit
29de36f36053 ("addons: address: various fixes for mtu handling").
This fixes a pending issue with mtu readjustments on vlan
interfaces on top of physical interfaces.
eg: with the below config:
$ifquery -a
auto swp1.100
iface swp1.100
auto swp1
iface swp1
mtu 9000
/* at boot-up swp1 and swp1.100 mtu is set to 9000 */
$ifdown swp1 /* resets swp1 mtu to 1500. swp1.100 mtu is reset to 1500
implicitly by the kernel */
$ifup swp1 /* swp1 mtu is set to 1500. But swp1.100 mtu stays at 1500
*/
This problem is unique to physical interfaces and vlan devices on
physical interfaces. This is because, when logical interface is ifdown,
kernel deletes all its sub-interfaces. And on the way up (ifup),
ifupdown2 re-creates all these sub-interfaces for you....that
sequence re-adjusts the mtu. For physical
interfaces, since the sub-interfaces are not deleted,
ifupdown2 does not do anything...and mtu of the subinterface is left to
what it was. And this ends up being what was there initially when the
lower interface went down. And ifdown of the lower physical interface,
resets the physical mtu to default which is 1500. The sub-interface mtu
returns to 1500 while the lower physical interface remains down.
(another detail here: kernel vlan driver re-adjusts mtu of the vlan
sub-interface on its own when the lower device mtu becomes lower. But
does not re-adjust its mtu when the lower device mtu increases. This is
expected and correct behavior). We will have to work around it in
ifupdown2 to suit our needs.
two solutions:
a) when physical interface is brought up, ifupdown2 can go and
pro-actively adjust the upper sub-interface mtu
OR
b) when physical interface is brought down, do not reset the mtu on the
device to default
(b) is the easiest and costs less if we dont expect the mtu of a
physical device to go to default on ifdown.
(a) is doable too, but is additional cost to go over all upper
interfaces.
This patch fixes this problem with solution (a). But, makes sure
this does not add additional cost to the default ifreload -a path.
Signed-off-by: Roopa Prabhu <roopa@cumulusnetworks.com>
2016-11-28 13:24:31 -08:00
if mtu :
if not self . _check_mtu_config ( ifaceobj , mtu , ifaceobj_getfunc ) :
return
2018-12-13 11:43:32 -08:00
cached_running_mtu = self . ipcmd . link_get_mtu ( ifaceobj . name )
running_mtu = self . ipcmd . link_get_mtu_sysfs ( ifaceobj . name )
addons: address: propagate physical mtu to upper vlan devices
Ticket: CM-13221
Reviewed By: julien, nikhil
Testing Done: tested mtu propagation for vlan devices
This is a followup to commit
29de36f36053 ("addons: address: various fixes for mtu handling").
This fixes a pending issue with mtu readjustments on vlan
interfaces on top of physical interfaces.
eg: with the below config:
$ifquery -a
auto swp1.100
iface swp1.100
auto swp1
iface swp1
mtu 9000
/* at boot-up swp1 and swp1.100 mtu is set to 9000 */
$ifdown swp1 /* resets swp1 mtu to 1500. swp1.100 mtu is reset to 1500
implicitly by the kernel */
$ifup swp1 /* swp1 mtu is set to 1500. But swp1.100 mtu stays at 1500
*/
This problem is unique to physical interfaces and vlan devices on
physical interfaces. This is because, when logical interface is ifdown,
kernel deletes all its sub-interfaces. And on the way up (ifup),
ifupdown2 re-creates all these sub-interfaces for you....that
sequence re-adjusts the mtu. For physical
interfaces, since the sub-interfaces are not deleted,
ifupdown2 does not do anything...and mtu of the subinterface is left to
what it was. And this ends up being what was there initially when the
lower interface went down. And ifdown of the lower physical interface,
resets the physical mtu to default which is 1500. The sub-interface mtu
returns to 1500 while the lower physical interface remains down.
(another detail here: kernel vlan driver re-adjusts mtu of the vlan
sub-interface on its own when the lower device mtu becomes lower. But
does not re-adjust its mtu when the lower device mtu increases. This is
expected and correct behavior). We will have to work around it in
ifupdown2 to suit our needs.
two solutions:
a) when physical interface is brought up, ifupdown2 can go and
pro-actively adjust the upper sub-interface mtu
OR
b) when physical interface is brought down, do not reset the mtu on the
device to default
(b) is the easiest and costs less if we dont expect the mtu of a
physical device to go to default on ifdown.
(a) is doable too, but is additional cost to go over all upper
interfaces.
This patch fixes this problem with solution (a). But, makes sure
this does not add additional cost to the default ifreload -a path.
Signed-off-by: Roopa Prabhu <roopa@cumulusnetworks.com>
2016-11-28 13:24:31 -08:00
if not running_mtu or ( running_mtu and running_mtu != mtu ) :
2018-12-13 11:43:32 -08:00
force = cached_running_mtu != running_mtu
self . ipcmd . link_set ( ifaceobj . name , ' mtu ' , mtu , force = force )
addons: address: propagate physical mtu to upper vlan devices
Ticket: CM-13221
Reviewed By: julien, nikhil
Testing Done: tested mtu propagation for vlan devices
This is a followup to commit
29de36f36053 ("addons: address: various fixes for mtu handling").
This fixes a pending issue with mtu readjustments on vlan
interfaces on top of physical interfaces.
eg: with the below config:
$ifquery -a
auto swp1.100
iface swp1.100
auto swp1
iface swp1
mtu 9000
/* at boot-up swp1 and swp1.100 mtu is set to 9000 */
$ifdown swp1 /* resets swp1 mtu to 1500. swp1.100 mtu is reset to 1500
implicitly by the kernel */
$ifup swp1 /* swp1 mtu is set to 1500. But swp1.100 mtu stays at 1500
*/
This problem is unique to physical interfaces and vlan devices on
physical interfaces. This is because, when logical interface is ifdown,
kernel deletes all its sub-interfaces. And on the way up (ifup),
ifupdown2 re-creates all these sub-interfaces for you....that
sequence re-adjusts the mtu. For physical
interfaces, since the sub-interfaces are not deleted,
ifupdown2 does not do anything...and mtu of the subinterface is left to
what it was. And this ends up being what was there initially when the
lower interface went down. And ifdown of the lower physical interface,
resets the physical mtu to default which is 1500. The sub-interface mtu
returns to 1500 while the lower physical interface remains down.
(another detail here: kernel vlan driver re-adjusts mtu of the vlan
sub-interface on its own when the lower device mtu becomes lower. But
does not re-adjust its mtu when the lower device mtu increases. This is
expected and correct behavior). We will have to work around it in
ifupdown2 to suit our needs.
two solutions:
a) when physical interface is brought up, ifupdown2 can go and
pro-actively adjust the upper sub-interface mtu
OR
b) when physical interface is brought down, do not reset the mtu on the
device to default
(b) is the easiest and costs less if we dont expect the mtu of a
physical device to go to default on ifdown.
(a) is doable too, but is additional cost to go over all upper
interfaces.
This patch fixes this problem with solution (a). But, makes sure
this does not add additional cost to the default ifreload -a path.
Signed-off-by: Roopa Prabhu <roopa@cumulusnetworks.com>
2016-11-28 13:24:31 -08:00
if ( not ifupdownflags . flags . ALL and
not ifaceobj . link_kind and
2018-12-13 11:43:32 -08:00
ifupdownconfig . config . get ( ' adjust_logical_dev_mtu ' , ' 1 ' ) != ' 0 ' ) :
addons: address: propagate physical mtu to upper vlan devices
Ticket: CM-13221
Reviewed By: julien, nikhil
Testing Done: tested mtu propagation for vlan devices
This is a followup to commit
29de36f36053 ("addons: address: various fixes for mtu handling").
This fixes a pending issue with mtu readjustments on vlan
interfaces on top of physical interfaces.
eg: with the below config:
$ifquery -a
auto swp1.100
iface swp1.100
auto swp1
iface swp1
mtu 9000
/* at boot-up swp1 and swp1.100 mtu is set to 9000 */
$ifdown swp1 /* resets swp1 mtu to 1500. swp1.100 mtu is reset to 1500
implicitly by the kernel */
$ifup swp1 /* swp1 mtu is set to 1500. But swp1.100 mtu stays at 1500
*/
This problem is unique to physical interfaces and vlan devices on
physical interfaces. This is because, when logical interface is ifdown,
kernel deletes all its sub-interfaces. And on the way up (ifup),
ifupdown2 re-creates all these sub-interfaces for you....that
sequence re-adjusts the mtu. For physical
interfaces, since the sub-interfaces are not deleted,
ifupdown2 does not do anything...and mtu of the subinterface is left to
what it was. And this ends up being what was there initially when the
lower interface went down. And ifdown of the lower physical interface,
resets the physical mtu to default which is 1500. The sub-interface mtu
returns to 1500 while the lower physical interface remains down.
(another detail here: kernel vlan driver re-adjusts mtu of the vlan
sub-interface on its own when the lower device mtu becomes lower. But
does not re-adjust its mtu when the lower device mtu increases. This is
expected and correct behavior). We will have to work around it in
ifupdown2 to suit our needs.
two solutions:
a) when physical interface is brought up, ifupdown2 can go and
pro-actively adjust the upper sub-interface mtu
OR
b) when physical interface is brought down, do not reset the mtu on the
device to default
(b) is the easiest and costs less if we dont expect the mtu of a
physical device to go to default on ifdown.
(a) is doable too, but is additional cost to go over all upper
interfaces.
This patch fixes this problem with solution (a). But, makes sure
this does not add additional cost to the default ifreload -a path.
Signed-off-by: Roopa Prabhu <roopa@cumulusnetworks.com>
2016-11-28 13:24:31 -08:00
# This is additional cost to us, so do it only when
# ifupdown2 is called on a particular interface and
# it is a physical interface
self . _propagate_mtu_to_upper_devs ( ifaceobj , mtu , ifaceobj_getfunc )
2016-11-07 10:48:24 -08:00
return
if ifaceobj . link_kind :
# bonds and vxlan devices need an explicit set of mtu.
# bridges don't need mtu set
if ( ifaceobj . link_kind & ifaceLinkKind . BOND or
ifaceobj . link_kind & ifaceLinkKind . VXLAN ) :
running_mtu = self . ipcmd . link_get_mtu ( ifaceobj . name )
if ( self . default_mtu and running_mtu != self . default_mtu ) :
self . ipcmd . link_set ( ifaceobj . name , ' mtu ' , self . default_mtu )
return
2018-12-13 11:43:32 -08:00
if ( ifupdownconfig . config . get ( ' adjust_logical_dev_mtu ' , ' 1 ' ) != ' 0 '
2016-11-07 10:48:24 -08:00
and ifaceobj . lowerifaces ) :
# set vlan interface mtu to lower device mtu
if ( ifaceobj . link_kind & ifaceLinkKind . VLAN ) :
2018-12-13 11:43:32 -08:00
lower_iface = ifaceobj . lowerifaces [ 0 ]
if lower_iface not in self . lower_iface_mtu_checked_list :
lower_iface_mtu = self . ipcmd . link_get_mtu_sysfs ( lower_iface )
self . ipcmd . cache_update ( [ lower_iface , ' mtu ' ] , lower_iface_mtu )
self . lower_iface_mtu_checked_list . append ( lower_iface )
else :
lower_iface_mtu = self . ipcmd . link_get_mtu ( lower_iface )
if lower_iface_mtu != self . ipcmd . link_get_mtu_sysfs ( ifaceobj . name ) :
2016-11-07 10:48:24 -08:00
self . ipcmd . link_set_mtu ( ifaceobj . name , lower_iface_mtu )
elif ( not ( ifaceobj . name == ' lo ' ) and not ifaceobj . link_kind and
not ( ifaceobj . link_privflags & ifaceLinkPrivFlags . BOND_SLAVE ) and
self . default_mtu ) :
# logical devices like bridges and vlan devices rely on mtu
# from their lower devices. ie mtu travels from
# lower devices to upper devices. For bonds mtu travels from
# upper to lower devices. running mtu depends on upper and
# lower device mtu. With all this implicit mtu
# config by the kernel in play, we try to be cautious here
# on which devices we want to reset mtu to default.
# essentially only physical interfaces which are not bond slaves
running_mtu = self . ipcmd . link_get_mtu ( ifaceobj . name )
if running_mtu != self . default_mtu :
self . ipcmd . link_set ( ifaceobj . name , ' mtu ' , self . default_mtu )
2018-12-13 11:43:32 -08:00
def _set_bridge_forwarding ( self , ifaceobj ) :
""" set ip forwarding to 0 if bridge interface does not have a
ip nor svi """
2018-10-29 14:20:19 +01:00
ifname = ifaceobj . name
2018-12-13 11:43:32 -08:00
if not ifaceobj . upperifaces and not ifaceobj . get_attr_value ( ' address ' ) :
2018-10-29 14:20:19 +01:00
if self . sysctl_get_forwarding_value_from_proc ( ifname , " ipv4 " ) == ' 1 ' :
self . sysctl_write_forwarding_value_to_proc ( ifname , " ipv4 " , 0 )
if self . sysctl_get_forwarding_value_from_proc ( ifname , " ipv6 " ) == ' 1 ' :
self . sysctl_write_forwarding_value_to_proc ( ifname , " ipv6 " , 0 )
2018-12-13 11:43:32 -08:00
else :
2018-10-29 14:20:19 +01:00
if self . sysctl_get_forwarding_value_from_proc ( ifname , " ipv4 " ) == ' 0 ' :
self . sysctl_write_forwarding_value_to_proc ( ifname , " ipv4 " , 1 )
if self . sysctl_get_forwarding_value_from_proc ( ifname , " ipv6 " ) == ' 0 ' :
self . sysctl_write_forwarding_value_to_proc ( ifname , " ipv6 " , 1 )
def sysctl_get_forwarding_value_from_proc ( self , ifname , family ) :
return self . read_file_oneline ( " /proc/sys/net/ %s /conf/ %s /forwarding " % ( family , ifname ) )
def sysctl_write_forwarding_value_to_proc ( self , ifname , family , value ) :
self . write_file ( " /proc/sys/net/ %s /conf/ %s /forwarding " % ( family , ifname ) , " %s \n " % value )
2018-12-13 11:43:32 -08:00
def _sysctl_config ( self , ifaceobj ) :
setting_default_value = False
mpls_enable = ifaceobj . get_attr_value_first ( ' mpls-enable ' ) ;
if not mpls_enable :
setting_default_value = True
mpls_enable = self . get_mod_subattr ( ' mpls-enable ' , ' default ' )
mpls_enable = utils . boolean_support_binary ( mpls_enable )
# File read has been used for better performance
# instead of using sysctl command
if ifupdownflags . flags . PERFMODE :
running_mpls_enable = ' 0 '
else :
running_mpls_enable = self . read_file_oneline (
' /proc/sys/net/mpls/conf/ %s /input '
% ifaceobj . name
)
if mpls_enable != running_mpls_enable :
try :
self . sysctl_set ( ' net.mpls.conf. %s .input '
% ( ' / ' . join ( ifaceobj . name . split ( " . " ) ) ) ,
mpls_enable )
except Exception as e :
if not setting_default_value :
ifaceobj . status = ifaceStatus . ERROR
self . logger . error ( ' %s : %s ' % ( ifaceobj . name , str ( e ) ) )
if ( ifaceobj . link_kind & ifaceLinkKind . BRIDGE ) :
self . _set_bridge_forwarding ( ifaceobj )
return
if not self . syntax_check_sysctls ( ifaceobj ) :
return
ipforward = ifaceobj . get_attr_value_first ( ' ip-forward ' )
ip6forward = ifaceobj . get_attr_value_first ( ' ip6-forward ' )
if ifupdownflags . flags . PERFMODE :
if ipforward :
self . sysctl_set ( ' net.ipv4.conf. %s .forwarding '
% ( ' / ' . join ( ifaceobj . name . split ( " . " ) ) ) ,
utils . boolean_support_binary ( ipforward ) )
if ip6forward :
self . sysctl_set ( ' net.ipv6.conf. %s .forwarding '
% ( ' / ' . join ( ifaceobj . name . split ( " . " ) ) ) ,
utils . boolean_support_binary ( ip6forward ) )
return
bridge_port = ifaceobj . link_privflags & ifaceLinkPrivFlags . BRIDGE_PORT
if bridge_port :
if ipforward :
self . log_error ( ' %s : \' ip-forward \' is not supported for '
' bridge port ' % ifaceobj . name )
if ip6forward :
self . log_error ( ' %s : \' ip6-forward \' is not supported for '
' bridge port ' % ifaceobj . name )
return
setting_default_value = False
if not ipforward :
setting_default_value = True
ipforward = ( self . ipforward or
self . get_mod_subattr ( ' ip-forward ' , ' default ' ) )
ipforward = utils . boolean_support_binary ( ipforward )
# File read has been used for better performance
# instead of using sysctl command
running_ipforward = self . read_file_oneline (
' /proc/sys/net/ipv4/conf/ %s /forwarding '
% ifaceobj . name )
if ipforward != running_ipforward :
try :
self . sysctl_set ( ' net.ipv4.conf. %s .forwarding '
% ( ' / ' . join ( ifaceobj . name . split ( " . " ) ) ) ,
ipforward )
except Exception as e :
if not setting_default_value :
ifaceobj . status = ifaceStatus . ERROR
self . logger . error ( ' %s : %s ' % ( ifaceobj . name , str ( e ) ) )
setting_default_value = False
if not ip6forward :
setting_default_value = True
ip6forward = ( self . ip6forward or
self . get_mod_subattr ( ' ip6-forward ' , ' default ' ) )
ip6forward = utils . boolean_support_binary ( ip6forward )
# File read has been used for better performance
# instead of using sysctl command
running_ip6forward = self . read_file_oneline (
' /proc/sys/net/ipv6/conf/ %s /forwarding '
% ifaceobj . name )
if ip6forward != running_ip6forward :
try :
self . sysctl_set ( ' net.ipv6.conf. %s .forwarding '
% ( ' / ' . join ( ifaceobj . name . split ( " . " ) ) ) ,
ip6forward )
except Exception as e :
# There is chance of ipv6 being removed because of,
# for example, setting mtu < 1280
# In such cases, log error only if user has configured
# ip6-forward
if not setting_default_value :
ifaceobj . status = ifaceStatus . ERROR
self . logger . error ( ' %s : %s ' % ( ifaceobj . name , str ( e ) ) )
def process_mtu ( self , ifaceobj , ifaceobj_getfunc ) :
mtu = ifaceobj . get_attr_value_first ( ' mtu ' )
if not mtu :
default_iface_mtu = self . ifaces_defaults . get ( ifaceobj . name , { } ) . get ( ' mtu ' )
if default_iface_mtu :
try :
mtu = default_iface_mtu
int ( default_iface_mtu )
except Exception as e :
self . logger . warning ( ' %s : MTU value from policy file: %s ' % ( ifaceobj . name , str ( e ) ) )
return
self . _process_mtu_config ( ifaceobj , ifaceobj_getfunc , mtu )
2018-06-18 18:57:20 +02:00
def up_ipv6_addrgen ( self , ifaceobj ) :
2018-07-10 00:18:39 +02:00
user_configured_ipv6_addrgen = ifaceobj . get_attr_value_first ( ' ipv6-addrgen ' )
2018-10-11 03:12:43 +02:00
if not user_configured_ipv6_addrgen and ifupdownflags . flags . PERFMODE :
# no need to go further during perfmode (boot)
return
2018-10-23 12:15:17 +02:00
if not user_configured_ipv6_addrgen and ifaceobj . addr_method == ' dhcp ' :
return
2018-07-10 00:18:39 +02:00
if not user_configured_ipv6_addrgen :
2018-07-23 10:38:29 +02:00
# if user didn't configure ipv6-addrgen, should we reset to default?
user_configured_ipv6_addrgen = self . get_attr_default_value ( ' ipv6-addrgen ' )
2018-07-10 00:18:39 +02:00
ipv6_addrgen_nl = {
' on ' : 0 ,
' yes ' : 0 ,
' 0 ' : 0 ,
' off ' : 1 ,
' no ' : 1 ,
' 1 ' : 1
} . get ( user_configured_ipv6_addrgen . lower ( ) , None )
if ipv6_addrgen_nl is not None :
self . ipcmd . ipv6_addrgen ( ifaceobj . name , ipv6_addrgen_nl , link_created = True )
# link_create=False will flush the addr cache of that intf
else :
self . logger . warning ( ' %s : invalid value " %s " for attribute ipv6-addrgen ' % ( ifaceobj . name , user_configured_ipv6_addrgen ) )
2018-06-18 18:57:20 +02:00
2015-11-16 21:00:40 -08:00
def _up ( self , ifaceobj , ifaceobj_getfunc = None ) :
2014-10-09 16:02:46 -07:00
if not self . ipcmd . link_exists ( ifaceobj . name ) :
return
addons: address: purge ifalias when no alias keyword is provided
Ticket: CM-13044
Reviewed By: Roopa, Nikhil G, Daniel W,
Testing Done:
For some reason we can't simply write into a file when we want to purge the
ifalias, we have to exec a command. I wasn't able to make it work in any
other way.
add an alias to an interface, ifreload, ip link show interface
modify it, ifreload, ip link show interface
remove it, ifreload, ip link show interface
Signed-off-by: Julien Fortin <julien@cumulusnetworks.com>
2016-12-27 17:03:19 +01:00
2018-12-13 11:43:32 -08:00
if not self . syntax_check_enable_l3_iface_forwardings ( ifaceobj , ifaceobj_getfunc ) :
return
addons: address: purge ifalias when no alias keyword is provided
Ticket: CM-13044
Reviewed By: Roopa, Nikhil G, Daniel W,
Testing Done:
For some reason we can't simply write into a file when we want to purge the
ifalias, we have to exec a command. I wasn't able to make it work in any
other way.
add an alias to an interface, ifreload, ip link show interface
modify it, ifreload, ip link show interface
remove it, ifreload, ip link show interface
Signed-off-by: Julien Fortin <julien@cumulusnetworks.com>
2016-12-27 17:03:19 +01:00
alias = ifaceobj . get_attr_value_first ( ' alias ' )
current_alias = self . ipcmd . link_get_alias ( ifaceobj . name )
if alias and alias != current_alias :
self . ipcmd . link_set_alias ( ifaceobj . name , alias )
elif not alias and current_alias :
self . ipcmd . link_set_alias ( ifaceobj . name , ' ' )
2018-12-13 11:43:32 -08:00
self . _sysctl_config ( ifaceobj )
2014-11-18 16:52:00 -08:00
addr_method = ifaceobj . addr_method
2016-05-09 18:48:52 -07:00
force_reapply = False
2014-10-09 16:02:46 -07:00
try :
# release any stale dhcp addresses if present
2018-06-25 16:22:22 +02:00
if ( addr_method not in [ " dhcp " , " ppp " ] and not ifupdownflags . flags . PERFMODE and
2014-10-09 16:02:46 -07:00
not ( ifaceobj . flags & iface . HAS_SIBLINGS ) ) :
# if not running in perf mode and ifaceobj does not have
# any sibling iface objects, kill any stale dhclient
# processes
2014-11-17 16:23:42 -08:00
dhclientcmd = dhclient ( )
2016-05-09 13:50:56 -07:00
if dhclientcmd . is_running ( ifaceobj . name ) :
2014-10-09 16:02:46 -07:00
# release any dhcp leases
dhclientcmd . release ( ifaceobj . name )
2016-05-09 18:48:52 -07:00
force_reapply = True
2016-05-09 13:50:56 -07:00
elif dhclientcmd . is_running6 ( ifaceobj . name ) :
2014-10-09 16:02:46 -07:00
dhclientcmd . release6 ( ifaceobj . name )
2016-05-09 18:48:52 -07:00
force_reapply = True
2014-10-09 16:02:46 -07:00
except :
pass
2014-11-03 17:55:51 -08:00
2014-10-09 16:02:46 -07:00
self . ipcmd . batch_start ( )
2018-06-18 18:57:20 +02:00
self . up_ipv6_addrgen ( ifaceobj )
2018-06-25 16:22:22 +02:00
if addr_method not in [ " dhcp " , " ppp " ] :
2016-05-09 18:48:52 -07:00
self . _inet_address_config ( ifaceobj , ifaceobj_getfunc ,
force_reapply )
2018-12-13 11:43:32 -08:00
self . process_mtu ( ifaceobj , ifaceobj_getfunc )
2016-04-15 15:56:24 -07:00
2016-08-10 15:08:38 +02:00
try :
self . ipcmd . batch_commit ( )
except Exception as e :
2016-09-13 17:03:24 -07:00
self . log_error ( ' %s : %s ' % ( ifaceobj . name , str ( e ) ) , ifaceobj , raise_error = False )
2015-09-17 11:26:56 -07:00
2014-11-18 16:52:00 -08:00
try :
2016-08-24 14:20:45 -07:00
hwaddress = self . _get_hwaddress ( ifaceobj )
if hwaddress :
running_hwaddress = None
if not ifupdownflags . flags . PERFMODE : # system is clean
running_hwaddress = self . ipcmd . link_get_hwaddress ( ifaceobj . name )
if hwaddress != running_hwaddress :
slave_down = False
netlink . link_set_updown ( ifaceobj . name , " down " )
if ifaceobj . link_kind & ifaceLinkKind . BOND :
# if bond, down all the slaves
if ifaceobj . lowerifaces :
for l in ifaceobj . lowerifaces :
netlink . link_set_updown ( l , " down " )
slave_down = True
try :
self . ipcmd . link_set ( ifaceobj . name , ' address ' , hwaddress )
finally :
netlink . link_set_updown ( ifaceobj . name , " up " )
if slave_down :
for l in ifaceobj . lowerifaces :
netlink . link_set_updown ( l , " up " )
2014-11-18 16:52:00 -08:00
# Handle special things on a bridge
self . _process_bridge ( ifaceobj , True )
except Exception , e :
2016-05-15 13:28:10 -07:00
self . log_error ( ' %s : %s ' % ( ifaceobj . name , str ( e ) ) , ifaceobj )
2014-10-28 23:04:40 -07:00
2018-12-13 11:43:32 -08:00
gateways = ifaceobj . get_attr_value ( ' gateway ' )
if not gateways :
gateways = [ ]
prev_gw = self . _get_prev_gateway ( ifaceobj , gateways )
self . _add_delete_gateway ( ifaceobj , gateways , prev_gw )
2014-10-09 16:02:46 -07:00
2015-11-16 21:00:40 -08:00
def _down ( self , ifaceobj , ifaceobj_getfunc = None ) :
2014-10-09 16:02:46 -07:00
try :
if not self . ipcmd . link_exists ( ifaceobj . name ) :
return
2014-11-18 16:52:00 -08:00
addr_method = ifaceobj . addr_method
2018-06-25 16:22:22 +02:00
if addr_method not in [ " dhcp " , " ppp " ] :
2016-03-03 12:13:23 -08:00
if ifaceobj . get_attr_value_first ( ' address-purge ' ) == ' no ' :
addrlist = ifaceobj . get_attr_value ( ' address ' )
for addr in addrlist :
self . ipcmd . addr_del ( ifaceobj . name , addr )
#self.ipcmd.addr_del(ifaceobj.name, ifaceobj.get_attr_value('address')[0])
2018-12-13 11:43:32 -08:00
elif not ifaceobj . link_kind :
# for logical interfaces we don't need to remove the ip addresses
# kernel will do it for us on 'ip link del'
2016-03-03 12:13:23 -08:00
self . ipcmd . del_addr_all ( ifaceobj . name )
2018-12-13 11:43:32 -08:00
gateways = ifaceobj . get_attr_value ( ' gateway ' )
if gateways :
self . _delete_gateway ( ifaceobj , gateways ,
ifaceobj . get_attr_value_first ( ' vrf ' ) ,
ifaceobj . get_attr_value_first ( ' metric ' ) )
2016-04-15 10:16:53 +02:00
mtu = ifaceobj . get_attr_value_first ( ' mtu ' )
2016-05-05 15:49:41 -07:00
if ( not ifaceobj . link_kind and mtu and
self . default_mtu and ( mtu != self . default_mtu ) ) :
2016-04-15 10:16:53 +02:00
self . ipcmd . link_set ( ifaceobj . name , ' mtu ' , self . default_mtu )
2014-10-09 16:02:46 -07:00
alias = ifaceobj . get_attr_value_first ( ' alias ' )
if alias :
2018-12-13 11:43:32 -08:00
self . write_file ( ' /sys/class/net/ %s /ifalias ' % ifaceobj . name , ' \n ' )
2014-11-17 16:23:42 -08:00
# XXX hwaddress reset cannot happen because we dont know last
# address.
# Handle special things on a bridge
self . _process_bridge ( ifaceobj , False )
2014-10-09 16:02:46 -07:00
except Exception , e :
2014-11-15 23:31:42 -08:00
self . logger . debug ( ' %s : %s ' % ( ifaceobj . name , str ( e ) ) )
pass
2014-10-09 16:02:46 -07:00
def _get_iface_addresses ( self , ifaceobj ) :
addrlist = ifaceobj . get_attr_value ( ' address ' )
outaddrlist = [ ]
if not addrlist : return None
for addrindex in range ( 0 , len ( addrlist ) ) :
addr = addrlist [ addrindex ]
netmask = ifaceobj . get_attr_value_n ( ' netmask ' , addrindex )
if netmask :
prefixlen = IPNetwork ( ' %s ' % addr +
' / %s ' % netmask ) . prefixlen
addr = addr + ' / %s ' % prefixlen
outaddrlist . append ( addr )
return outaddrlist
2014-11-03 17:55:51 -08:00
def _get_bridge_fdbs ( self , bridgename , vlan ) :
fdbs = self . _bridge_fdb_query_cache . get ( bridgename )
if not fdbs :
fdbs = self . ipcmd . bridge_fdb_show_dev ( bridgename )
if not fdbs :
return
self . _bridge_fdb_query_cache [ bridgename ] = fdbs
return fdbs . get ( vlan )
def _check_addresses_in_bridge ( self , ifaceobj , hwaddress ) :
""" If the device is a bridge, make sure the addresses
are in the bridge """
2018-12-13 11:43:32 -08:00
if ifaceobj . link_kind & ifaceLinkKind . VLAN :
bridgename = ifaceobj . lowerifaces [ 0 ]
vlan = self . _get_vlan_id ( ifaceobj )
2014-11-03 17:55:51 -08:00
if self . ipcmd . bridge_is_vlan_aware ( bridgename ) :
2018-12-13 11:43:32 -08:00
fdb_addrs = self . _get_bridge_fdbs ( bridgename , str ( vlan ) )
2014-11-03 17:55:51 -08:00
if not fdb_addrs or hwaddress not in fdb_addrs :
return False
return True
2018-12-13 11:43:32 -08:00
def _query_sysctl ( self , ifaceobj , ifaceobjcurr ) :
bridge_port = ifaceobj . link_privflags & ifaceLinkPrivFlags . BRIDGE_PORT
ipforward = ifaceobj . get_attr_value_first ( ' ip-forward ' )
if ipforward :
if bridge_port :
ifaceobjcurr . status = ifaceStatus . ERROR
ifaceobjcurr . status_str = ( ' \' ip-forward \' not supported ' +
' for bridge port ' )
ifaceobjcurr . update_config_with_status ( ' ip-forward ' , 1 , None )
else :
running_ipforward = self . read_file_oneline (
' /proc/sys/net/ipv4/conf/ %s /forwarding '
% ifaceobj . name )
2018-07-16 13:03:47 +02:00
running_ipforward = utils . get_boolean_from_string ( running_ipforward )
config_ipforward = utils . get_boolean_from_string ( ipforward )
ifaceobjcurr . update_config_with_status (
' ip-forward ' ,
' on ' if running_ipforward else ' off ' ,
running_ipforward != config_ipforward
)
2018-12-13 11:43:32 -08:00
ip6forward = ifaceobj . get_attr_value_first ( ' ip6-forward ' )
if ip6forward :
if bridge_port :
ifaceobjcurr . status = ifaceStatus . ERROR
ifaceobjcurr . status_str = ( ' \' ip6-forward \' not supported ' +
' for bridge port ' )
ifaceobjcurr . update_config_with_status ( ' ip6-forward ' , 1 , None )
else :
running_ip6forward = self . read_file_oneline (
' /proc/sys/net/ipv6/conf/ %s /forwarding '
% ifaceobj . name )
2018-07-16 13:03:47 +02:00
running_ip6forward = utils . get_boolean_from_string ( running_ip6forward )
config_ip6forward = utils . get_boolean_from_string ( ip6forward )
ifaceobjcurr . update_config_with_status (
' ip6-forward ' ,
' on ' if running_ip6forward else ' off ' ,
running_ip6forward != config_ip6forward
)
2018-12-13 11:43:32 -08:00
mpls_enable = ifaceobj . get_attr_value_first ( ' mpls-enable ' ) ;
if mpls_enable :
running_mpls_enable = self . read_file_oneline (
' /proc/sys/net/mpls/conf/ %s /input '
% ifaceobj . name )
running_mpls_enable = utils . get_yesno_from_onezero (
running_mpls_enable )
ifaceobjcurr . update_config_with_status ( ' mpls-enable ' ,
running_mpls_enable ,
mpls_enable != running_mpls_enable )
return
2018-07-10 00:18:39 +02:00
def query_check_ipv6_addrgen ( self , ifaceobj , ifaceobjcurr ) :
ipv6_addrgen = ifaceobj . get_attr_value_first ( ' ipv6-addrgen ' )
if not ipv6_addrgen :
return
if ipv6_addrgen in utils . _string_values :
ifaceobjcurr . update_config_with_status (
' ipv6-addrgen ' ,
ipv6_addrgen ,
utils . get_boolean_from_string ( ipv6_addrgen ) == self . ipcmd . get_ipv6_addrgen_mode ( ifaceobj . name )
)
else :
ifaceobjcurr . update_config_with_status ( ' ipv6-addrgen ' , ipv6_addrgen , 1 )
2015-11-16 21:00:40 -08:00
def _query_check ( self , ifaceobj , ifaceobjcurr , ifaceobj_getfunc = None ) :
2014-10-09 16:02:46 -07:00
runningaddrsdict = None
if not self . ipcmd . link_exists ( ifaceobj . name ) :
self . logger . debug ( ' iface %s not found ' % ifaceobj . name )
return
2018-07-10 00:18:39 +02:00
self . query_check_ipv6_addrgen ( ifaceobj , ifaceobjcurr )
2014-11-19 17:25:26 -08:00
addr_method = ifaceobj . addr_method
2014-10-09 16:02:46 -07:00
self . query_n_update_ifaceobjcurr_attr ( ifaceobj , ifaceobjcurr ,
' mtu ' , self . ipcmd . link_get_mtu )
2016-03-15 15:41:04 +01:00
hwaddress = self . _get_hwaddress ( ifaceobj )
2014-11-03 17:55:51 -08:00
if hwaddress :
2016-03-11 15:56:34 -08:00
rhwaddress = self . ipcmd . link_get_hwaddress ( ifaceobj . name )
2014-11-03 17:55:51 -08:00
if not rhwaddress or rhwaddress != hwaddress :
ifaceobjcurr . update_config_with_status ( ' hwaddress ' , rhwaddress ,
1 )
elif not self . _check_addresses_in_bridge ( ifaceobj , hwaddress ) :
# XXX: hw address is not in bridge
ifaceobjcurr . update_config_with_status ( ' hwaddress ' , rhwaddress ,
1 )
ifaceobjcurr . status_str = ' bridge fdb error '
else :
ifaceobjcurr . update_config_with_status ( ' hwaddress ' , rhwaddress ,
0 )
2014-10-09 16:02:46 -07:00
self . query_n_update_ifaceobjcurr_attr ( ifaceobj , ifaceobjcurr ,
' alias ' , self . ipcmd . link_get_alias )
2018-12-13 11:43:32 -08:00
self . _query_sysctl ( ifaceobj , ifaceobjcurr )
2014-10-09 16:02:46 -07:00
# compare addresses
2018-06-25 16:22:22 +02:00
if addr_method in [ " dhcp " , " ppp " ] :
2014-11-19 17:25:26 -08:00
return
2016-09-14 16:00:25 -07:00
addrs = utils . get_normalized_ip_addr ( ifaceobj . name ,
self . _get_iface_addresses ( ifaceobj ) )
2018-12-13 11:43:32 -08:00
runningaddrsdict = self . ipcmd . get_running_addrs ( ifaceobj )
2015-09-04 00:32:15 -07:00
# if anycast address is configured on 'lo' and is in running config
# add it to addrs so that query_check doesn't fail
2016-09-14 16:00:25 -07:00
anycast_addr = utils . get_normalized_ip_addr ( ifaceobj . name , ifaceobj . get_attr_value_first ( ' clagd-vxlan-anycast-ip ' ) )
2015-09-04 00:32:15 -07:00
if anycast_addr :
anycast_addr = anycast_addr + ' /32 '
if runningaddrsdict and anycast_addr and runningaddrsdict . get ( anycast_addr ) :
addrs . append ( anycast_addr )
2014-10-09 16:02:46 -07:00
# Set ifaceobjcurr method and family
ifaceobjcurr . addr_method = ifaceobj . addr_method
ifaceobjcurr . addr_family = ifaceobj . addr_family
if not runningaddrsdict and not addrs :
return
runningaddrs = runningaddrsdict . keys ( ) if runningaddrsdict else [ ]
2017-08-23 23:11:57 +02:00
# Add /32 netmask to configured address without netmask.
# This may happen on interfaces where pointopoint is used.
runningaddrs = [ addr if ' / ' in addr else addr + ' /32 ' for addr in runningaddrs ]
2014-10-09 16:02:46 -07:00
if runningaddrs != addrs :
runningaddrsset = set ( runningaddrs ) if runningaddrs else set ( [ ] )
addrsset = set ( addrs ) if addrs else set ( [ ] )
if ( ifaceobj . flags & iface . HAS_SIBLINGS ) :
if not addrsset :
return
# only check for addresses present in running config
addrsdiff = addrsset . difference ( runningaddrsset )
for addr in addrs :
if addr in addrsdiff :
ifaceobjcurr . update_config_with_status ( ' address ' ,
addr , 1 )
else :
ifaceobjcurr . update_config_with_status ( ' address ' ,
addr , 0 )
else :
addrsdiff = addrsset . symmetric_difference ( runningaddrsset )
for addr in addrsset . union ( runningaddrsset ) :
if addr in addrsdiff :
ifaceobjcurr . update_config_with_status ( ' address ' ,
addr , 1 )
else :
ifaceobjcurr . update_config_with_status ( ' address ' ,
addr , 0 )
elif addrs :
[ ifaceobjcurr . update_config_with_status ( ' address ' ,
addr , 0 ) for addr in addrs ]
#XXXX Check broadcast address, scope, etc
return
2018-07-10 00:18:39 +02:00
def query_running_ipv6_addrgen ( self , ifaceobjrunning ) :
ipv6_addrgen = self . ipcmd . get_ipv6_addrgen_mode ( ifaceobjrunning . name )
if ipv6_addrgen :
ifaceobjrunning . update_config ( ' ipv6-addrgen ' , ' off ' )
2015-11-16 21:00:40 -08:00
def _query_running ( self , ifaceobjrunning , ifaceobj_getfunc = None ) :
2014-10-09 16:02:46 -07:00
if not self . ipcmd . link_exists ( ifaceobjrunning . name ) :
self . logger . debug ( ' iface %s not found ' % ifaceobjrunning . name )
return
2018-07-10 00:18:39 +02:00
self . query_running_ipv6_addrgen ( ifaceobjrunning )
2014-10-09 16:02:46 -07:00
dhclientcmd = dhclient ( )
if ( dhclientcmd . is_running ( ifaceobjrunning . name ) or
dhclientcmd . is_running6 ( ifaceobjrunning . name ) ) :
# If dhcp is configured on the interface, we skip it
2016-04-15 10:16:53 +02:00
return
2014-10-09 16:02:46 -07:00
isloopback = self . ipcmd . link_isloopback ( ifaceobjrunning . name )
if isloopback :
default_addrs = [ ' 127.0.0.1/8 ' , ' ::1/128 ' ]
2016-11-15 18:33:07 +01:00
ifaceobjrunning . addr_family . append ( ' inet ' )
2014-10-09 16:02:46 -07:00
ifaceobjrunning . addr_method = ' loopback '
else :
default_addrs = [ ]
2018-12-13 11:43:32 -08:00
runningaddrsdict = self . ipcmd . get_running_addrs ( ifaceobjrunning )
2014-10-09 16:02:46 -07:00
if runningaddrsdict :
[ ifaceobjrunning . update_config ( ' address ' , addr )
for addr , addrattrs in runningaddrsdict . items ( )
if addr not in default_addrs ]
mtu = self . ipcmd . link_get_mtu ( ifaceobjrunning . name )
if ( mtu and
( ifaceobjrunning . name == ' lo ' and mtu != ' 16436 ' ) or
( ifaceobjrunning . name != ' lo ' and
mtu != self . get_mod_subattr ( ' mtu ' , ' default ' ) ) ) :
ifaceobjrunning . update_config ( ' mtu ' , mtu )
alias = self . ipcmd . link_get_alias ( ifaceobjrunning . name )
2016-04-15 10:16:53 +02:00
if alias :
2014-10-09 16:02:46 -07:00
ifaceobjrunning . update_config ( ' alias ' , alias )
2018-12-13 11:43:32 -08:00
ipforward = self . read_file_oneline (
' /proc/sys/net/ipv4/conf/ %s /forwarding '
% ifaceobjrunning . name )
addons: address: propagate physical mtu to upper vlan devices
Ticket: CM-13221
Reviewed By: julien, nikhil
Testing Done: tested mtu propagation for vlan devices
This is a followup to commit
29de36f36053 ("addons: address: various fixes for mtu handling").
This fixes a pending issue with mtu readjustments on vlan
interfaces on top of physical interfaces.
eg: with the below config:
$ifquery -a
auto swp1.100
iface swp1.100
auto swp1
iface swp1
mtu 9000
/* at boot-up swp1 and swp1.100 mtu is set to 9000 */
$ifdown swp1 /* resets swp1 mtu to 1500. swp1.100 mtu is reset to 1500
implicitly by the kernel */
$ifup swp1 /* swp1 mtu is set to 1500. But swp1.100 mtu stays at 1500
*/
This problem is unique to physical interfaces and vlan devices on
physical interfaces. This is because, when logical interface is ifdown,
kernel deletes all its sub-interfaces. And on the way up (ifup),
ifupdown2 re-creates all these sub-interfaces for you....that
sequence re-adjusts the mtu. For physical
interfaces, since the sub-interfaces are not deleted,
ifupdown2 does not do anything...and mtu of the subinterface is left to
what it was. And this ends up being what was there initially when the
lower interface went down. And ifdown of the lower physical interface,
resets the physical mtu to default which is 1500. The sub-interface mtu
returns to 1500 while the lower physical interface remains down.
(another detail here: kernel vlan driver re-adjusts mtu of the vlan
sub-interface on its own when the lower device mtu becomes lower. But
does not re-adjust its mtu when the lower device mtu increases. This is
expected and correct behavior). We will have to work around it in
ifupdown2 to suit our needs.
two solutions:
a) when physical interface is brought up, ifupdown2 can go and
pro-actively adjust the upper sub-interface mtu
OR
b) when physical interface is brought down, do not reset the mtu on the
device to default
(b) is the easiest and costs less if we dont expect the mtu of a
physical device to go to default on ifdown.
(a) is doable too, but is additional cost to go over all upper
interfaces.
This patch fixes this problem with solution (a). But, makes sure
this does not add additional cost to the default ifreload -a path.
Signed-off-by: Roopa Prabhu <roopa@cumulusnetworks.com>
2016-11-28 13:24:31 -08:00
2014-10-09 16:02:46 -07:00
_run_ops = { ' up ' : _up ,
' down ' : _down ,
' query-checkcurr ' : _query_check ,
' query-running ' : _query_running }
def get_ops ( self ) :
""" returns list of ops supported by this module """
return self . _run_ops . keys ( )
def _init_command_handlers ( self ) :
if not self . ipcmd :
2018-12-13 11:43:32 -08:00
self . ipcmd = LinkUtils ( )
2014-10-09 16:02:46 -07:00
2016-04-20 03:02:26 -07:00
def run ( self , ifaceobj , operation , query_ifaceobj = None , ifaceobj_getfunc = None ) :
2014-10-09 16:02:46 -07:00
""" run address configuration on the interface object passed as argument
Args :
* * ifaceobj * * ( object ) : iface object
* * operation * * ( str ) : any of ' up ' , ' down ' , ' query-checkcurr ' ,
' query-running '
Kwargs :
query_ifaceobj ( object ) : query check ifaceobject . This is only
valid when op is ' query-checkcurr ' . It is an object same as
ifaceobj , but contains running attribute values and its config
status . The modules can use it to return queried running state
of interfaces . status is success if the running state is same
as user required state in ifaceobj . error otherwise .
"""
2014-11-03 17:55:51 -08:00
if ifaceobj . type == ifaceType . BRIDGE_VLAN :
return
2014-10-09 16:02:46 -07:00
op_handler = self . _run_ops . get ( operation )
if not op_handler :
return
self . _init_command_handlers ( )
if operation == ' query-checkcurr ' :
2015-11-16 21:00:40 -08:00
op_handler ( self , ifaceobj , query_ifaceobj ,
ifaceobj_getfunc = ifaceobj_getfunc )
2014-10-09 16:02:46 -07:00
else :
2015-11-16 21:00:40 -08:00
op_handler ( self , ifaceobj ,
ifaceobj_getfunc = ifaceobj_getfunc )