"1", "layer3+4",
"2", "layer2+3",
"3", "encap2+3",
- "4", "encap3+4"
+ "4", "encap3+4",
+ "5", "vlan+srcmac"
],
"default": "layer2",
"example": ["bond-xmit-hash-policy layer2"]
"example": [
"bond-slaves swp1 swp2",
"bond-slaves glob swp1-2",
- "bond-slaves regex (swp[1|2)"
+ "bond-slaves regex (swp[1|2])"
],
"aliases": ["bond-ports"]
},
"help": "Control which slave interface is "
"preferred active member",
"example": ["bond-primary swp1"]
+ },
+ "bond-primary-reselect": {
+ "help": "bond primary reselect",
+ "validvals": [
+ "0", "always",
+ "1", "better",
+ "2", "failure",
+ ],
+ "example": ["bond-primary-reselect failure"]
+ },
+ "es-sys-mac": {
+ "help": "evpn-mh: system mac address",
+ "validvals": ["<mac>", ],
+ "example": ["es-sys-mac 00:00:00:00:00:42"],
}
}
}
'bond-min-links': Link.IFLA_BOND_MIN_LINKS,
'bond-num-grat-arp': Link.IFLA_BOND_NUM_PEER_NOTIF,
'bond-num-unsol-na': Link.IFLA_BOND_NUM_PEER_NOTIF,
+ 'es-sys-mac': Link.IFLA_BOND_AD_ACTOR_SYSTEM,
'bond-ad-sys-mac-addr': Link.IFLA_BOND_AD_ACTOR_SYSTEM,
'bond-ad-actor-system': Link.IFLA_BOND_AD_ACTOR_SYSTEM,
'bond-ad-sys-priority': Link.IFLA_BOND_AD_ACTOR_SYS_PRIO,
'bond-lacp-bypass-allow': Link.IFLA_BOND_AD_LACP_BYPASS,
'bond-updelay': Link.IFLA_BOND_UPDELAY,
'bond-downdelay': Link.IFLA_BOND_DOWNDELAY,
- 'bond-primary': Link.IFLA_BOND_PRIMARY
+ 'bond-primary': Link.IFLA_BOND_PRIMARY,
+ 'bond-primary-reselect': Link.IFLA_BOND_PRIMARY_RESELECT
+
}
# ifquery-check attr dictionary with callable object to translate user data to netlink format
Link.IFLA_BOND_AD_LACP_BYPASS: lambda x: int(utils.get_boolean_from_string(x)),
Link.IFLA_BOND_UPDELAY: int,
Link.IFLA_BOND_DOWNDELAY: int,
+ Link.IFLA_BOND_PRIMARY_RESELECT: lambda x: Link.ifla_bond_primary_reselect_tbl[x],
# Link.IFLA_BOND_PRIMARY: self.netlink.get_ifname is added in __init__()
}
('bond-use-carrier', Link.IFLA_BOND_USE_CARRIER, lambda x: int(utils.get_boolean_from_string(x))),
('bond-lacp-rate', Link.IFLA_BOND_AD_LACP_RATE, lambda x: int(utils.get_boolean_from_string(x))),
('bond-lacp-bypass-allow', Link.IFLA_BOND_AD_LACP_BYPASS, lambda x: int(utils.get_boolean_from_string(x))),
+ ('es-sys-mac', Link.IFLA_BOND_AD_ACTOR_SYSTEM, str),
('bond-ad-sys-mac-addr', Link.IFLA_BOND_AD_ACTOR_SYSTEM, str),
- ('bond-ad-actor-system', Link.IFLA_BOND_AD_ACTOR_SYSTEM, str)
+ ('bond-ad-actor-system', Link.IFLA_BOND_AD_ACTOR_SYSTEM, str),
+ ('bond-primary-reselect', Link.IFLA_BOND_PRIMARY_RESELECT, lambda x: Link.ifla_bond_primary_reselect_tbl[x])
# ('bond-primary', Link.IFLA_BOND_PRIMARY, self.cache.get_ifindex) added in __init__()
)
self._bond_attr_ifquery_check_translate_func[Link.IFLA_BOND_PRIMARY] = self.cache.get_ifindex
self._bond_attr_set_list = self._bond_attr_set_list + (('bond-primary', Link.IFLA_BOND_PRIMARY, self.cache.get_ifindex),)
- @staticmethod
- def get_bond_slaves(ifaceobj):
- slaves = ifaceobj.get_attr_value_first('bond-slaves')
- if not slaves:
- slaves = ifaceobj.get_attr_value_first('bond-ports')
- return slaves
+ self.bond_mac_mgmt = utils.get_boolean_from_string(
+ policymanager.policymanager_api.get_module_globals(
+ module_name=self.__class__.__name__,
+ attr="bond_mac_mgmt"),
+ True
+ )
+
+ def get_bond_slaves(self, ifaceobj):
+ # bond-ports aliases should be translated to bond-slaves
+ return ifaceobj.get_attr_value_first('bond-slaves')
def _is_bond(self, ifaceobj):
# at first link_kind is not set but once ifupdownmain
# calls get_dependent_ifacenames link_kind is set to BOND
return ifaceobj.link_kind & ifaceLinkKind.BOND or self.get_bond_slaves(ifaceobj)
- def get_dependent_ifacenames(self, ifaceobj, ifacenames_all=None):
+ def get_dependent_ifacenames(self, ifaceobj, ifacenames_all=None, old_ifaceobjs=False):
""" Returns list of interfaces dependent on ifaceobj """
if not self._is_bond(ifaceobj):
ifaceobj.link_kind |= ifaceLinkKind.BOND
ifaceobj.role |= ifaceRole.MASTER
+ if ifaceobj.get_attr_value("es-sys-mac"):
+ ifaceobj.link_privflags |= ifaceLinkPrivFlags.ES_BOND
+
return slave_list
def syntax_check(self, ifaceobj, ifaceobj_getfunc):
clag_bond = self._is_clag_bond(ifaceobj)
- for slave in set(slaves).difference(set(runningslaves)):
+ # remove duplicates and devices that are already enslaved
+ devices_to_enslave = []
+ for s in slaves:
+ if s not in runningslaves and s not in devices_to_enslave:
+ devices_to_enslave.append(s)
+
+ for slave in devices_to_enslave:
if (not ifupdownflags.flags.PERFMODE and
not self.cache.link_exists(slave)):
self.log_error('%s: skipping slave %s, does not exist'
if self.cache.link_is_up(slave):
self.netlink.link_down_force(slave)
link_up = True
- # If clag bond place the slave in a protodown state; clagd
- # will protoup it when it is ready
- if clag_bond:
+
+ # if clag or ES bond: place the slave in a protodown state;
+ # (clagd will proto-up it when it is ready)
+ if clag_bond or ifaceobj.link_privflags & ifaceLinkPrivFlags.ES_BOND:
try:
self.netlink.link_set_protodown_on(slave)
except Exception as e:
self.enable_ipv6_if_prev_brport(slave)
self.netlink.link_set_master(slave, ifaceobj.name)
+ runningslaves.append(slave)
# TODO: if this fail we should switch to iproute2
# start a batch: down - set master - up
if link_up or ifaceobj.link_type != ifaceLinkType.LINK_NA:
ifaceLinkPrivFlags.KEEP_LINK_DOWN):
self.netlink.link_down_force(slave)
else:
- self.netlink.link_up(slave)
+ self.netlink.link_up_force(slave)
except Exception as e:
self.logger.debug('%s: %s' % (ifaceobj.name, str(e)))
pass
if runningslaves:
+ removed_slave = []
+
for s in runningslaves:
+ # make sure that slaves are not in protodown since we are not in the clag-bond or es-bond case
+ if not clag_bond and not ifaceobj.link_privflags & ifaceLinkPrivFlags.ES_BOND and self.cache.get_link_protodown(s):
+ self.netlink.link_set_protodown_off(s)
+
if s not in slaves:
self.sysfs.bond_remove_slave(ifaceobj.name, s)
+ removed_slave.append(s)
if clag_bond:
try:
self.netlink.link_set_protodown_off(s)
except Exception as e:
self.logger.error('%s: %s' % (ifaceobj.name, str(e)))
+
+ # ip link set $slave nomaster will set the slave admin down
+ # if the slave has an auto stanza, we should keep it admin up
+ # unless link-down yes is set
+ slave_class_auto = False
+ slave_link_down = False
+ for obj in ifaceobj_getfunc(s) or []:
+ if obj.auto:
+ slave_class_auto = True
+ if obj.link_privflags & ifaceLinkPrivFlags.KEEP_LINK_DOWN:
+ slave_link_down = True
+ if slave_class_auto and not slave_link_down:
+ self.netlink.link_up_force(s)
else:
# apply link-down config changes on running slaves
try:
except Exception as e:
self.logger.warning('%s: %s' % (ifaceobj.name, str(e)))
+ for s in removed_slave:
+ try:
+ runningslaves.remove(s)
+ except:
+ pass
+
+ return runningslaves
+
def _check_updown_delay_log(self, ifaceobj, attr_name, value):
ifaceobj.status = ifaceStatus.ERROR
self.logger.error('%s: unable to set %s %s as MII link monitoring is '
try:
miimon = int(ifaceobj.get_attr_value_first('bond-miimon'))
- except:
+ except Exception:
try:
miimon = int(policymanager.policymanager_api.get_iface_default(
module_name=self.__class__.__name__,
ifname=ifaceobj.name,
attr='bond-miimon'))
- except:
+ except Exception:
miimon = 0
if not miimon:
for lower_dev in ifaceobj.lowerifaces:
self.netlink.link_set_nomaster(lower_dev)
+
+ # when unslaving a device from an ES bond we need to set
+ # protodown off
+ if ifaceobj.link_privflags & ifaceLinkPrivFlags.ES_BOND:
+ self.netlink.link_set_protodown_off(lower_dev)
+
try:
bond_slaves.remove(lower_dev)
- except:
+ except Exception:
pass
else:
if link_exists and ifla_info_data and not is_link_up:
self.netlink.link_up_force(ifname)
- return bond_slaves
+ return link_exists, bond_slaves
def create_or_set_bond_config_sysfs(self, ifaceobj, ifla_info_data):
+ if len(ifaceobj.name) > 15:
+ self.log_error("%s: cannot create bond: interface name exceeds max length of 15" % ifaceobj.name, ifaceobj)
+ return
+
if not self.cache.link_exists(ifaceobj.name):
self.sysfs.bond_create(ifaceobj.name)
self.sysfs.bond_set_attrs_nl(ifaceobj.name, ifla_info_data)
def _up(self, ifaceobj, ifaceobj_getfunc=None):
try:
- bond_slaves = self.create_or_set_bond_config(ifaceobj)
- self._add_slaves(
+ link_exists, bond_slaves = self.create_or_set_bond_config(ifaceobj)
+ bond_slaves = self._add_slaves(
ifaceobj,
bond_slaves,
ifaceobj_getfunc,
)
+
+ if not self.bond_mac_mgmt or not link_exists or ifaceobj.get_attr_value_first("hwaddress"):
+ return
+
+ # check if the bond mac address is correctly inherited from it's
+ # first slave. There's a case where that might not be happening:
+ # $ ip link show swp1 | grep ether
+ # link/ether 08:00:27:04:d8:01 brd ff:ff:ff:ff:ff:ff
+ # $ ip link show swp2 | grep ether
+ # link/ether 08:00:27:04:d8:02 brd ff:ff:ff:ff:ff:ff
+ # $ ip link add dev bond0 type bond
+ # $ ip link set dev swp1 master bond0
+ # $ ip link set dev swp2 master bond0
+ # $ ip link show bond0 | grep ether
+ # link/ether 08:00:27:04:d8:01 brd ff:ff:ff:ff:ff:ff
+ # $ ip link add dev bond1 type bond
+ # $ ip link set dev swp1 master bond1
+ # $ ip link show swp1 | grep ether
+ # link/ether 08:00:27:04:d8:01 brd ff:ff:ff:ff:ff:ff
+ # $ ip link show swp2 | grep ether
+ # link/ether 08:00:27:04:d8:01 brd ff:ff:ff:ff:ff:ff
+ # $ ip link show bond0 | grep ether
+ # link/ether 08:00:27:04:d8:01 brd ff:ff:ff:ff:ff:ff
+ # $ ip link show bond1 | grep ether
+ # link/ether 08:00:27:04:d8:01 brd ff:ff:ff:ff:ff:ff
+ # $
+ # ifupdown2 will automatically correct and fix this unexpected behavior
+ bond_mac = self.cache.get_link_address(ifaceobj.name)
+
+ if bond_slaves:
+ first_slave_ifname = bond_slaves[0]
+ first_slave_mac = self.cache.get_link_info_slave_data_attribute(
+ first_slave_ifname,
+ Link.IFLA_BOND_SLAVE_PERM_HWADDR
+ )
+
+ if first_slave_mac and bond_mac != first_slave_mac:
+ self.logger.info(
+ "%s: invalid bond mac detected - resetting to %s's mac (%s)"
+ % (ifaceobj.name, first_slave_ifname, first_slave_mac)
+ )
+ self.netlink.link_set_address(ifaceobj.name, first_slave_mac, utils.mac_str_to_int(first_slave_mac))
except Exception as e:
self.log_error(str(e), ifaceobj)
running_bond_slaves = self.cache.get_slaves(ifaceobj.name)
self._query_check_bond_slaves(ifaceobjcurr, 'bond-slaves', user_bond_slaves, running_bond_slaves)
- except:
+ except Exception:
pass
try:
del iface_attrs[iface_attrs.index('bond-ports')]
running_bond_slaves = self.cache.get_slaves(ifaceobj.name)
self._query_check_bond_slaves(ifaceobjcurr, 'bond-ports', user_bond_slaves, running_bond_slaves)
- except:
+ except Exception:
pass
for attr in iface_attrs:
'bond-lacp-rate': self.translate_nl_value_slowfast(cached_vxlan_ifla_info_data.get(Link.IFLA_BOND_AD_LACP_RATE)),
'bond-min-links': cached_vxlan_ifla_info_data.get(Link.IFLA_BOND_MIN_LINKS),
'bond-ad-actor-system': cached_vxlan_ifla_info_data.get(Link.IFLA_BOND_AD_ACTOR_SYSTEM),
+ 'es-sys-mac': cached_vxlan_ifla_info_data.get(Link.IFLA_BOND_AD_ACTOR_SYSTEM),
'bond-ad-actor-sys-prio': cached_vxlan_ifla_info_data.get(Link.IFLA_BOND_AD_ACTOR_SYS_PRIO),
'bond-xmit-hash-policy': Link.ifla_bond_xmit_hash_policy_pretty_tbl.get(cached_vxlan_ifla_info_data.get(Link.IFLA_BOND_XMIT_HASH_POLICY)),
'bond-lacp-bypass-allow': self.translate_nl_value_yesno(cached_vxlan_ifla_info_data.get(Link.IFLA_BOND_AD_LACP_BYPASS)),