⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bond_main.c

📁 h内核
💻 C
📖 第 1 页 / 共 5 页
字号:
		}	}}/* * 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 + -