static int bond_fill_slave_info(struct sk_buff *skb, const struct net_device *bond_dev, const struct net_device *slave_dev) { struct slave *slave = bond_slave_get_rtnl(slave_dev); if (nla_put_u8(skb, IFLA_BOND_SLAVE_STATE, bond_slave_state(slave))) goto nla_put_failure; if (nla_put_u8(skb, IFLA_BOND_SLAVE_MII_STATUS, slave->link)) goto nla_put_failure; if (nla_put_u32(skb, IFLA_BOND_SLAVE_LINK_FAILURE_COUNT, slave->link_failure_count)) goto nla_put_failure; if (nla_put(skb, IFLA_BOND_SLAVE_PERM_HWADDR, slave_dev->addr_len, slave->perm_hwaddr)) goto nla_put_failure; if (nla_put_u16(skb, IFLA_BOND_SLAVE_QUEUE_ID, slave->queue_id)) goto nla_put_failure; if (BOND_MODE(slave->bond) == BOND_MODE_8023AD) { const struct aggregator *agg; const struct port *ad_port; ad_port = &SLAVE_AD_INFO(slave)->port; agg = SLAVE_AD_INFO(slave)->port.aggregator; if (agg) { if (nla_put_u16(skb, IFLA_BOND_SLAVE_AD_AGGREGATOR_ID, agg->aggregator_identifier)) goto nla_put_failure; if (nla_put_u8(skb, IFLA_BOND_SLAVE_AD_ACTOR_OPER_PORT_STATE, ad_port->actor_oper_port_state)) goto nla_put_failure; if (nla_put_u16(skb, IFLA_BOND_SLAVE_AD_PARTNER_OPER_PORT_STATE, ad_port->partner_oper.port_state)) goto nla_put_failure; } } return 0; nla_put_failure: return -EMSGSIZE; }
static int bond_option_active_slave_set(struct bonding *bond, const struct bond_opt_value *newval) { char ifname[IFNAMSIZ] = { 0, }; struct net_device *slave_dev; int ret = 0; sscanf(newval->string, "%15s", ifname); /* IFNAMSIZ */ if (!strlen(ifname) || newval->string[0] == '\n') { slave_dev = NULL; } else { slave_dev = __dev_get_by_name(dev_net(bond->dev), ifname); if (!slave_dev) return -ENODEV; } if (slave_dev) { if (!netif_is_bond_slave(slave_dev)) { netdev_err(bond->dev, "Device %s is not bonding slave\n", slave_dev->name); return -EINVAL; } if (bond->dev != netdev_master_upper_dev_get(slave_dev)) { netdev_err(bond->dev, "Device %s is not our slave\n", slave_dev->name); return -EINVAL; } } block_netpoll_tx(); /* check to see if we are clearing active */ if (!slave_dev) { netdev_dbg(bond->dev, "Clearing current active slave\n"); RCU_INIT_POINTER(bond->curr_active_slave, NULL); bond_select_active_slave(bond); } else { struct slave *old_active = rtnl_dereference(bond->curr_active_slave); struct slave *new_active = bond_slave_get_rtnl(slave_dev); BUG_ON(!new_active); if (new_active == old_active) { /* do nothing */ netdev_dbg(bond->dev, "%s is already the current active slave\n", new_active->dev->name); } else { if (old_active && (new_active->link == BOND_LINK_UP) && bond_slave_is_up(new_active)) { netdev_dbg(bond->dev, "Setting %s as active slave\n", new_active->dev->name); bond_change_active_slave(bond, new_active); } else { netdev_err(bond->dev, "Could not set %s as active slave; either %s is down or the link is down\n", new_active->dev->name, new_active->dev->name); ret = -EINVAL; } } } unblock_netpoll_tx(); return ret; }
int bond_option_active_slave_set(struct bonding *bond, struct bond_opt_value *newval) { char ifname[IFNAMSIZ] = { 0, }; struct net_device *slave_dev; int ret = 0; sscanf(newval->string, "%15s", ifname); /* IFNAMSIZ */ if (!strlen(ifname) || newval->string[0] == '\n') { slave_dev = NULL; } else { slave_dev = __dev_get_by_name(dev_net(bond->dev), ifname); if (!slave_dev) return -ENODEV; } if (slave_dev) { if (!netif_is_bond_slave(slave_dev)) { pr_err("Device %s is not bonding slave.\n", slave_dev->name); return -EINVAL; } if (bond->dev != netdev_master_upper_dev_get(slave_dev)) { pr_err("%s: Device %s is not our slave.\n", bond->dev->name, slave_dev->name); return -EINVAL; } } block_netpoll_tx(); write_lock_bh(&bond->curr_slave_lock); /* check to see if we are clearing active */ if (!slave_dev) { pr_info("%s: Clearing current active slave.\n", bond->dev->name); rcu_assign_pointer(bond->curr_active_slave, NULL); bond_select_active_slave(bond); } else { struct slave *old_active = bond->curr_active_slave; struct slave *new_active = bond_slave_get_rtnl(slave_dev); BUG_ON(!new_active); if (new_active == old_active) { /* do nothing */ pr_info("%s: %s is already the current active slave.\n", bond->dev->name, new_active->dev->name); } else { if (old_active && (new_active->link == BOND_LINK_UP) && IS_UP(new_active->dev)) { pr_info("%s: Setting %s as active slave.\n", bond->dev->name, new_active->dev->name); bond_change_active_slave(bond, new_active); } else { pr_err("%s: Could not set %s as active slave; either %s is down or the link is down.\n", bond->dev->name, new_active->dev->name, new_active->dev->name); ret = -EINVAL; } } } write_unlock_bh(&bond->curr_slave_lock); unblock_netpoll_tx(); return ret; }
int bond_option_active_slave_set(struct bonding *bond, struct net_device *slave_dev) { int ret = 0; if (slave_dev) { if (!netif_is_bond_slave(slave_dev)) { pr_err("Device %s is not bonding slave.\n", slave_dev->name); return -EINVAL; } if (bond->dev != netdev_master_upper_dev_get(slave_dev)) { pr_err("%s: Device %s is not our slave.\n", bond->dev->name, slave_dev->name); return -EINVAL; } } if (!USES_PRIMARY(bond->params.mode)) { pr_err("%s: Unable to change active slave; %s is in mode %d\n", bond->dev->name, bond->dev->name, bond->params.mode); return -EINVAL; } block_netpoll_tx(); read_lock(&bond->lock); write_lock_bh(&bond->curr_slave_lock); /* check to see if we are clearing active */ if (!slave_dev) { pr_info("%s: Clearing current active slave.\n", bond->dev->name); rcu_assign_pointer(bond->curr_active_slave, NULL); bond_select_active_slave(bond); } else { struct slave *old_active = bond->curr_active_slave; struct slave *new_active = bond_slave_get_rtnl(slave_dev); BUG_ON(!new_active); if (new_active == old_active) { /* do nothing */ pr_info("%s: %s is already the current active slave.\n", bond->dev->name, new_active->dev->name); } else { if (old_active && (new_active->link == BOND_LINK_UP) && IS_UP(new_active->dev)) { pr_info("%s: Setting %s as active slave.\n", bond->dev->name, new_active->dev->name); bond_change_active_slave(bond, new_active); } else { pr_err("%s: Could not set %s as active slave; either %s is down or the link is down.\n", bond->dev->name, new_active->dev->name, new_active->dev->name); ret = -EINVAL; } } } write_unlock_bh(&bond->curr_slave_lock); read_unlock(&bond->lock); unblock_netpoll_tx(); return ret; }