diff --git a/addons/bond.py b/addons/bond.py index 9ac7671..b9921e3 100644 --- a/addons/bond.py +++ b/addons/bond.py @@ -151,6 +151,13 @@ class bond(moduleBase): else: return None + def _is_clag_bond(self, ifaceobj): + if ifaceobj.get_attr_value_first('bond-slaves'): + attrval = ifaceobj.get_attr_value_first('clag-id') + if attrval and attrval != '0': + return True + return False + def fetch_attr(self, ifaceobj, attrname): attrval = ifaceobj.get_attr_value_first(attrname) # grab the defaults from the policy file in case the @@ -239,6 +246,8 @@ class bond(moduleBase): if not self.PERFMODE: runningslaves = self.bondcmd.get_slaves(ifaceobj.name); + clag_bond = self._is_clag_bond(ifaceobj) + for slave in Set(slaves).difference(Set(runningslaves)): if not self.PERFMODE and not self.ipcmd.link_exists(slave): self.log_warn('%s: skipping slave %s, does not exist' @@ -248,6 +257,10 @@ class bond(moduleBase): if self.ipcmd.is_link_up(slave): rtnetlink_api.rtnl_api.link_set(slave, "down") link_up = True + # If clag bond place the slave in a protodown state; clagd + # will protoup it when it is ready + if clag_bond: + rtnetlink_api.rtnl_api.link_set_protodown(slave, "on") self.ipcmd.link_set(slave, 'master', ifaceobj.name) if link_up or ifaceobj.link_type != ifaceLinkType.LINK_NA: try: @@ -258,10 +271,12 @@ class bond(moduleBase): pass if runningslaves: - # Delete active slaves not in the new slave list - [ self.bondcmd.remove_slave(ifaceobj.name, s) - for s in runningslaves if s not in slaves ] - + for s in runningslaves: + if s not in slaves: + self.bondcmd.remove_slave(ifaceobj.name, s) + if clag_bond: + rtnetlink_api.rtnl_api.link_set_protodown(s, "off") + def _apply_slaves_lacp_bypass_prio(self, ifaceobj): slaves = self.bondcmd.get_slaves(ifaceobj.name) if not slaves: diff --git a/ifupdown/rtnetlink.py b/ifupdown/rtnetlink.py index db498f7..6d540e0 100644 --- a/ifupdown/rtnetlink.py +++ b/ifupdown/rtnetlink.py @@ -168,7 +168,7 @@ class Nlmsg(Structure): def rta_uint8(self, rta, value=None): data = RTA_DATA(rta) - if value: + if value is not None: c_uint8.from_address(data).value = value rta.rta_len = RTA_LENGTH(sizeof(c_uint8)) return rta.rta_len @@ -184,6 +184,15 @@ class Nlmsg(Structure): else: return c_uint16.from_address(data).value + def rta_sint32(self, rta, value=None): + data = RTA_DATA(rta) + if value is not None: + c_int32.from_address(data).value = value + rta.rta_len = RTA_LENGTH(sizeof(c_int32)) + return rta.rta_len + else: + return c_int32.from_address(data).value + def rta_uint32(self, rta, value=None): data = RTA_DATA(rta) if value: @@ -545,8 +554,17 @@ IFLA_AF_SPEC = 26 IFLA_GROUP = 27 # Group the device belongs to IFLA_NET_NS_FD = 28 IFLA_EXT_MASK = 29 # Extended info mask, VFs, etc -IFLA_MAX = 29 - +IFLA_PROMISCUITY = 30 +IFLA_NUM_TX_QUEUES = 31 +IFLA_NUM_RX_QUEUES = 32 +IFLA_CARRIER = 33 +IFLA_PHYS_PORT_ID = 34 +IFLA_CARRIER_CHANGES = 35 +IFLA_PHYS_SWITCH_ID = 36 +IFLA_LINK_NETNSID = 37 +IFLA_PHYS_PORT_NAME = 38 +IFLA_PROTO_DOWN = 39 +IFLA_MAX = 40 # IFLA_LINKINFO attributes IFLA_INFO_UNSPEC = 0 @@ -666,6 +684,16 @@ class Ifinfomsg(Nlmsg): IFLA_GROUP: self.rta_none, IFLA_NET_NS_FD: self.rta_none, IFLA_EXT_MASK: self.rta_none, + IFLA_PROMISCUITY: self.rta_uint32, + IFLA_NUM_TX_QUEUES: self.rta_uint32, + IFLA_NUM_RX_QUEUES: self.rta_uint32, + IFLA_CARRIER: self.rta_uint8, + IFLA_PHYS_PORT_ID: self.rta_uint8_array, + IFLA_CARRIER_CHANGES: self.rta_uint32, + IFLA_PHYS_SWITCH_ID: self.rta_uint8_array, + IFLA_LINK_NETNSID: self.rta_sint32, + IFLA_PHYS_PORT_NAME: self.rta_string, + IFLA_PROTO_DOWN: self.rta_uint8, } return fns; @@ -701,6 +729,16 @@ class Ifinfomsg(Nlmsg): IFLA_GROUP: self.rta_none, IFLA_NET_NS_FD: self.rta_none, IFLA_EXT_MASK: self.rta_none, + IFLA_PROMISCUITY: self.rta_uint32, + IFLA_NUM_TX_QUEUES: self.rta_uint32, + IFLA_NUM_RX_QUEUES: self.rta_uint32, + IFLA_CARRIER: self.rta_uint8, + IFLA_PHYS_PORT_ID: self.rta_uint8_array, + IFLA_CARRIER_CHANGES: self.rta_uint32, + IFLA_PHYS_SWITCH_ID: self.rta_uint8_array, + IFLA_LINK_NETNSID: self.rta_sint32, + IFLA_PHYS_PORT_NAME: self.rta_string, + IFLA_PROTO_DOWN: self.rta_uint8, } return fns.get(rta_type) diff --git a/ifupdown/rtnetlink_api.py b/ifupdown/rtnetlink_api.py index ce6c289..af89a29 100644 --- a/ifupdown/rtnetlink_api.py +++ b/ifupdown/rtnetlink_api.py @@ -105,6 +105,21 @@ class rtnetlinkApi(RtNetlink): token = self.request(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_ACK, ifm, rtas) self.process_wait([token]) + def link_set_protodown(self, ifname, state): + flags = 0 + self.logger.info('rtnetlink: setting link %s protodown %s' %(ifname, state)) + if ifupdownmain.ifupdownFlags.DRYRUN: + return + + protodown = 1 if state == "on" else 0 + + ifm = Ifinfomsg(AF_UNSPEC) + rtas = {IFLA_IFNAME : ifname, + IFLA_PROTO_DOWN : protodown} + + token = self.request(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_ACK, ifm, rtas) + self.process_wait([token]) + def link_set_hwaddress(self, ifname, hwaddress): flags = 0 self.logger.info('rtnetlink: setting link hwaddress %s %s' %(ifname, hwaddress))