📄 bond_main.c
字号:
} }}/* * Add a Multicast address to slaves * according to mode */static void bond_mc_add(struct bonding *bond, void *addr, int alen){ if (USES_PRIMARY(bond->params.mode)) { /* write lock already acquired */ if (bond->curr_active_slave) { dev_mc_add(bond->curr_active_slave->dev, addr, alen, 0); } } else { struct slave *slave; int i; bond_for_each_slave(bond, slave, i) { dev_mc_add(slave->dev, addr, alen, 0); } }}/* * Remove a multicast address from slave * according to mode */static void bond_mc_delete(struct bonding *bond, void *addr, int alen){ if (USES_PRIMARY(bond->params.mode)) { /* write lock already acquired */ if (bond->curr_active_slave) { dev_mc_delete(bond->curr_active_slave->dev, addr, alen, 0); } } else { struct slave *slave; int i; bond_for_each_slave(bond, slave, i) { dev_mc_delete(slave->dev, addr, alen, 0); } }}/* * Totally destroys the mc_list in bond */static void bond_mc_list_destroy(struct bonding *bond){ struct dev_mc_list *dmi; dmi = bond->mc_list; while (dmi) { bond->mc_list = dmi->next; kfree(dmi); dmi = bond->mc_list; }}/* * Copy all the Multicast addresses from src to the bonding device dst */static int bond_mc_list_copy(struct dev_mc_list *mc_list, struct bonding *bond, int gpf_flag){ struct dev_mc_list *dmi, *new_dmi; for (dmi = mc_list; dmi; dmi = dmi->next) { new_dmi = kmalloc(sizeof(struct dev_mc_list), gpf_flag); if (!new_dmi) { /* FIXME: Potential memory leak !!! */ return -ENOMEM; } new_dmi->next = bond->mc_list; bond->mc_list = new_dmi; new_dmi->dmi_addrlen = dmi->dmi_addrlen; memcpy(new_dmi->dmi_addr, dmi->dmi_addr, dmi->dmi_addrlen); new_dmi->dmi_users = dmi->dmi_users; new_dmi->dmi_gusers = dmi->dmi_gusers; } return 0;}/* * flush all members of flush->mc_list from device dev->mc_list */static void bond_mc_list_flush(struct net_device *bond_dev, struct net_device *slave_dev){ struct bonding *bond = bond_dev->priv; struct dev_mc_list *dmi; for (dmi = bond_dev->mc_list; dmi; dmi = dmi->next) { dev_mc_delete(slave_dev, dmi->dmi_addr, dmi->dmi_addrlen, 0); } if (bond->params.mode == BOND_MODE_8023AD) { /* del lacpdu mc addr from mc list */ u8 lacpdu_multicast[ETH_ALEN] = MULTICAST_LACPDU_ADDR; dev_mc_delete(slave_dev, lacpdu_multicast, ETH_ALEN, 0); }}/*--------------------------- Active slave change ---------------------------*//* * Update the mc list and multicast-related flags for the new and * old active slaves (if any) according to the multicast mode, and * promiscuous flags unconditionally. */static void bond_mc_swap(struct bonding *bond, struct slave *new_active, struct slave *old_active){ struct dev_mc_list *dmi; if (!USES_PRIMARY(bond->params.mode)) { /* nothing to do - mc list is already up-to-date on * all slaves */ return; } if (old_active) { if (bond->dev->flags & IFF_PROMISC) { dev_set_promiscuity(old_active->dev, -1); } if (bond->dev->flags & IFF_ALLMULTI) { dev_set_allmulti(old_active->dev, -1); } for (dmi = bond->dev->mc_list; dmi; dmi = dmi->next) { dev_mc_delete(old_active->dev, dmi->dmi_addr, dmi->dmi_addrlen, 0); } } if (new_active) { if (bond->dev->flags & IFF_PROMISC) { dev_set_promiscuity(new_active->dev, 1); } if (bond->dev->flags & IFF_ALLMULTI) { dev_set_allmulti(new_active->dev, 1); } for (dmi = bond->dev->mc_list; dmi; dmi = dmi->next) { dev_mc_add(new_active->dev, dmi->dmi_addr, dmi->dmi_addrlen, 0); } }}/** * find_best_interface - select the best available slave to be the active one * @bond: our bonding struct * * Warning: Caller must hold curr_slave_lock for writing. */static struct slave *bond_find_best_slave(struct bonding *bond){ struct slave *new_active, *old_active; struct slave *bestslave = NULL; int mintime = bond->params.updelay; int i; new_active = old_active = bond->curr_active_slave; if (!new_active) { /* there were no active slaves left */ if (bond->slave_cnt > 0) { /* found one slave */ new_active = bond->first_slave; } else { return NULL; /* still no slave, return NULL */ } } /* first try the primary link; if arping, a link must tx/rx traffic * before it can be considered the curr_active_slave - also, we would skip * slaves between the curr_active_slave and primary_slave that may be up * and able to arp */ if ((bond->primary_slave) && (!bond->params.arp_interval) && (IS_UP(bond->primary_slave->dev))) { new_active = bond->primary_slave; } /* remember where to stop iterating over the slaves */ old_active = new_active; bond_for_each_slave_from(bond, new_active, i, old_active) { if (IS_UP(new_active->dev)) { if (new_active->link == BOND_LINK_UP) { return new_active; } else if (new_active->link == BOND_LINK_BACK) { /* link up, but waiting for stabilization */ if (new_active->delay < mintime) { mintime = new_active->delay; bestslave = new_active; } } } } return bestslave;}/** * change_active_interface - change the active slave into the specified one * @bond: our bonding struct * @new: the new slave to make the active one * * Set the new slave to the bond's settings and unset them on the old * curr_active_slave. * Setting include flags, mc-list, promiscuity, allmulti, etc. * * If @new's link state is %BOND_LINK_BACK we'll set it to %BOND_LINK_UP, * because it is apparently the best available slave we have, even though its * updelay hasn't timed out yet. * * Warning: Caller must hold curr_slave_lock for writing. */static void bond_change_active_slave(struct bonding *bond, struct slave *new_active){ struct slave *old_active = bond->curr_active_slave; if (old_active == new_active) { return; } if (new_active) { if (new_active->link == BOND_LINK_BACK) { if (USES_PRIMARY(bond->params.mode)) { printk(KERN_INFO DRV_NAME ": %s: making interface %s the new " "active one %d ms earlier.\n", bond->dev->name, new_active->dev->name, (bond->params.updelay - new_active->delay) * bond->params.miimon); } new_active->delay = 0; new_active->link = BOND_LINK_UP; new_active->jiffies = jiffies; if (bond->params.mode == BOND_MODE_8023AD) { bond_3ad_handle_link_change(new_active, BOND_LINK_UP); } if ((bond->params.mode == BOND_MODE_TLB) || (bond->params.mode == BOND_MODE_ALB)) { bond_alb_handle_link_change(bond, new_active, BOND_LINK_UP); } } else { if (USES_PRIMARY(bond->params.mode)) { printk(KERN_INFO DRV_NAME ": %s: making interface %s the new " "active one.\n", bond->dev->name, new_active->dev->name); } } } if (bond->params.mode == BOND_MODE_ACTIVEBACKUP) { if (old_active) { bond_set_slave_inactive_flags(old_active); } if (new_active) { bond_set_slave_active_flags(new_active); } } if (USES_PRIMARY(bond->params.mode)) { bond_mc_swap(bond, new_active, old_active); } if ((bond->params.mode == BOND_MODE_TLB) || (bond->params.mode == BOND_MODE_ALB)) { bond_alb_handle_active_change(bond, new_active); } else { bond->curr_active_slave = new_active; }}/** * bond_select_active_slave - select a new active slave, if needed * @bond: our bonding struct * * This functions shoud be called when one of the following occurs: * - The old curr_active_slave has been released or lost its link. * - The primary_slave has got its link back. * - A slave has got its link back and there's no old curr_active_slave. * * Warning: Caller must hold curr_slave_lock for writing. */static void bond_select_active_slave(struct bonding *bond){ struct slave *best_slave; best_slave = bond_find_best_slave(bond); if (best_slave != bond->curr_active_slave) { bond_change_active_slave(bond, best_slave); }}/*--------------------------- slave list handling ---------------------------*//* * This function attaches the slave to the end of list. * * bond->lock held for writing by caller. */static void bond_attach_slave(struct bonding *bond, struct slave *new_slave){ if (bond->first_slave == NULL) { /* attaching the first slave */ new_slave->next = new_slave; new_slave->prev = new_slave; bond->first_slave = new_slave; } else { new_slave->next = bond->first_slave; new_slave->prev = bond->first_slave->prev; new_slave->next->prev = new_slave; new_slave->prev->next = new_slave; } bond->slave_cnt++;}/* * This function detaches the slave from the list. * WARNING: no check is made to verify if the slave effectively * belongs to <bond>. * Nothing is freed on return, structures are just unchained. * If any slave pointer in bond was pointing to <slave>, * it should be changed by the calling function. * * bond->lock held for writing by caller. */static void bond_detach_slave(struct bonding *bond, struct slave *slave){ if (slave->next) { slave->next->prev = slave->prev; } if (slave->prev) { slave->prev->next = slave->next; } if (bond->first_slave == slave) { /* slave is the first slave */ if (bond->slave_cnt > 1) { /* there are more slave */ bond->first_slave = slave->next; } else { bond->first_slave = NULL; /* slave was the last one */ } } slave->next = NULL; slave->prev = NULL; bond->slave_cnt--;}/*---------------------------------- IOCTL ----------------------------------*/static int bond_sethwaddr(struct net_device *bond_dev, struct net_device *slave_dev){ dprintk("bond_dev=%p\n", bond_dev); dprintk("slave_dev=%p\n", slave_dev); dprintk("slave_dev->addr_len=%d\n", slave_dev->addr_len); memcpy(bond_dev->dev_addr, slave_dev->dev_addr, slave_dev->addr_len); return 0;}/* enslave device <slave> to bond device <master> */static int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev){ struct bonding *bond = bond_dev->priv; struct slave *new_slave = NULL; struct dev_mc_list *dmi; struct sockaddr addr; int link_reporting; int old_features = bond_dev->features; int res = 0; if (slave_dev->do_ioctl == NULL) { printk(KERN_WARNING DRV_NAME ": Warning : no link monitoring support for %s\n", slave_dev->name); } /* bond must be initialized by bond_open() before enslaving */ if (!(bond_dev->flags & IFF_UP)) { dprintk("Error, master_dev is not up\n"); return -EPERM; } /* already enslaved */ if (slave_dev->flags & IFF_SLAVE) { dprintk("Error, Device was already enslaved\n"); return -EBUSY; } /* vlan challenged mutual exclusion */ /* no need to lock since we're protected by rtnl_lock */ if (slave_dev->features & NETIF_F_VLAN_CHALLENGED) { dprintk("%s: NETIF_F_VLAN_CHALLENGED\n", slave_dev->name); if (!list_empty(&bond->vlan_list)) { printk(KERN_ERR DRV_NAME
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -