struct net_device *__vlan_find_dev_deep(struct net_device *real_dev, u16 vlan_id) { struct vlan_info *vlan_info = rcu_dereference_rtnl(real_dev->vlan_info); if (vlan_info) { return vlan_group_get_device(&vlan_info->grp, vlan_id); } else { /* */ if (netif_is_bond_slave(real_dev)) return __vlan_find_dev_deep(real_dev->master, vlan_id); } return NULL; }
/* Must be invoked with rcu_read_lock or with RTNL. */ struct net_device *__vlan_find_dev_deep(struct net_device *real_dev, u16 vlan_id) { struct vlan_info *vlan_info = rcu_dereference_rtnl(real_dev->vlan_info); if (vlan_info) { return vlan_group_get_device(&vlan_info->grp, vlan_id); } else { /* * Bonding slaves do not have grp assigned to themselves. * Grp is assigned to bonding master instead. */ if (netif_is_bond_slave(real_dev)) return __vlan_find_dev_deep(real_dev->master, vlan_id); } return NULL; }
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; }