bond_sysfs.c

来自「LINUX 2.6.17.4的源码」· C语言 代码 · 共 1,365 行 · 第 1/3 页

C
1,365
字号
			      bond->params.downdelay * bond->params.miimon);		if (bond->params.arp_interval) {			printk(KERN_INFO DRV_NAME			       ": %s: MII monitoring cannot be used with "			       "ARP monitoring. Disabling ARP monitoring...\n",			       bond->dev->name);			bond->params.arp_interval = 0;			/* Kill ARP timer, else it brings bond's link down */			if (bond->mii_timer.function) {				printk(KERN_INFO DRV_NAME				": %s: Kill ARP timer, else it brings bond's link down...\n",			       bond->dev->name);				del_timer_sync(&bond->arp_timer);			}		}		if (bond->dev->flags & IFF_UP) {			/* If the interface is up, we may need to fire off			 * the MII timer. If the interface is down, the			 * timer will get fired off when the open function			 * is called.			 */			if (bond->mii_timer.function) {				/* The timer's already set up, so fire it off */				mod_timer(&bond->mii_timer, jiffies + 1);			} else {				/* Set up the timer. */				init_timer(&bond->mii_timer);				bond->mii_timer.expires = jiffies + 1;				bond->mii_timer.data =					(unsigned long) bond->dev;				bond->mii_timer.function =					(void *) &bond_mii_monitor;				add_timer(&bond->mii_timer);			}		}	}out:	return ret;}static CLASS_DEVICE_ATTR(miimon, S_IRUGO | S_IWUSR, bonding_show_miimon, bonding_store_miimon);/* * Show and set the primary slave.  The store function is much * simpler than bonding_store_slaves function because it only needs to * handle one interface name. * The bond must be a mode that supports a primary for this be * set. */static ssize_t bonding_show_primary(struct class_device *cd, char *buf){	int count = 0;	struct bonding *bond = to_bond(cd);	if (bond->primary_slave)		count = sprintf(buf, "%s\n", bond->primary_slave->dev->name) + 1;	else		count = sprintf(buf, "\n") + 1;	return count;}static ssize_t bonding_store_primary(struct class_device *cd, const char *buf, size_t count){	int i;	struct slave *slave;	struct bonding *bond = to_bond(cd);	write_lock_bh(&bond->lock);	if (!USES_PRIMARY(bond->params.mode)) {		printk(KERN_INFO DRV_NAME		       ": %s: Unable to set primary slave; %s is in mode %d\n",		       bond->dev->name, bond->dev->name, bond->params.mode);	} else {		bond_for_each_slave(bond, slave, i) {			if (strnicmp			    (slave->dev->name, buf,			     strlen(slave->dev->name)) == 0) {				printk(KERN_INFO DRV_NAME				       ": %s: Setting %s as primary slave.\n",				       bond->dev->name, slave->dev->name);				bond->primary_slave = slave;				bond_select_active_slave(bond);				goto out;			}		}		/* if we got here, then we didn't match the name of any slave */		if (strlen(buf) == 0 || buf[0] == '\n') {			printk(KERN_INFO DRV_NAME			       ": %s: Setting primary slave to None.\n",			       bond->dev->name);			bond->primary_slave = NULL;				bond_select_active_slave(bond);		} else {			printk(KERN_INFO DRV_NAME			       ": %s: Unable to set %.*s as primary slave as it is not a slave.\n",			       bond->dev->name, (int)strlen(buf) - 1, buf);		}	}out:	write_unlock_bh(&bond->lock);	return count;}static CLASS_DEVICE_ATTR(primary, S_IRUGO | S_IWUSR, bonding_show_primary, bonding_store_primary);/* * Show and set the use_carrier flag. */static ssize_t bonding_show_carrier(struct class_device *cd, char *buf){	struct bonding *bond = to_bond(cd);	return sprintf(buf, "%d\n", bond->params.use_carrier) + 1;}static ssize_t bonding_store_carrier(struct class_device *cd, const char *buf, size_t count){	int new_value, ret = count;	struct bonding *bond = to_bond(cd);	if (sscanf(buf, "%d", &new_value) != 1) {		printk(KERN_ERR DRV_NAME		       ": %s: no use_carrier value specified.\n",		       bond->dev->name);		ret = -EINVAL;		goto out;	}	if ((new_value == 0) || (new_value == 1)) {		bond->params.use_carrier = new_value;		printk(KERN_INFO DRV_NAME ": %s: Setting use_carrier to %d.\n",		       bond->dev->name, new_value);	} else {		printk(KERN_INFO DRV_NAME		       ": %s: Ignoring invalid use_carrier value %d.\n",		       bond->dev->name, new_value);	}out:	return count;}static CLASS_DEVICE_ATTR(use_carrier, S_IRUGO | S_IWUSR, bonding_show_carrier, bonding_store_carrier);/* * Show and set currently active_slave. */static ssize_t bonding_show_active_slave(struct class_device *cd, char *buf){	struct slave *curr;	struct bonding *bond = to_bond(cd);	int count;	read_lock(&bond->curr_slave_lock);	curr = bond->curr_active_slave;	read_unlock(&bond->curr_slave_lock);	if (USES_PRIMARY(bond->params.mode) && curr)		count = sprintf(buf, "%s\n", curr->dev->name) + 1;	else		count = sprintf(buf, "\n") + 1;	return count;}static ssize_t bonding_store_active_slave(struct class_device *cd, const char *buf, size_t count){	int i;	struct slave *slave;        struct slave *old_active = NULL;        struct slave *new_active = NULL;	struct bonding *bond = to_bond(cd);	write_lock_bh(&bond->lock);	if (!USES_PRIMARY(bond->params.mode)) {		printk(KERN_INFO DRV_NAME		       ": %s: Unable to change active slave; %s is in mode %d\n",		       bond->dev->name, bond->dev->name, bond->params.mode);	} else {		bond_for_each_slave(bond, slave, i) {			if (strnicmp			    (slave->dev->name, buf,			     strlen(slave->dev->name)) == 0) {        			old_active = bond->curr_active_slave;        			new_active = slave;        			if (new_active && (new_active == old_active)) {					/* do nothing */					printk(KERN_INFO DRV_NAME				       	       ": %s: %s is already the current active slave.\n",				               bond->dev->name, slave->dev->name);					goto out;				}				else {        				if ((new_active) &&            				    (old_active) &&				            (new_active->link == BOND_LINK_UP) &&				            IS_UP(new_active->dev)) {						printk(KERN_INFO DRV_NAME				       	              ": %s: Setting %s as active slave.\n",				                      bond->dev->name, slave->dev->name);                				bond_change_active_slave(bond, new_active);        				}					else {						printk(KERN_INFO DRV_NAME				       	              ": %s: Could not set %s as active slave; "						      "either %s is down or the link is down.\n",				                      bond->dev->name, slave->dev->name,						      slave->dev->name);					}					goto out;				}			}		}		/* if we got here, then we didn't match the name of any slave */		if (strlen(buf) == 0 || buf[0] == '\n') {			printk(KERN_INFO DRV_NAME			       ": %s: Setting active slave to None.\n",			       bond->dev->name);			bond->primary_slave = NULL;				bond_select_active_slave(bond);		} else {			printk(KERN_INFO DRV_NAME			       ": %s: Unable to set %.*s as active slave as it is not a slave.\n",			       bond->dev->name, (int)strlen(buf) - 1, buf);		}	}out:	write_unlock_bh(&bond->lock);	return count;}static CLASS_DEVICE_ATTR(active_slave, S_IRUGO | S_IWUSR, bonding_show_active_slave, bonding_store_active_slave);/* * Show link status of the bond interface. */static ssize_t bonding_show_mii_status(struct class_device *cd, char *buf){	struct slave *curr;	struct bonding *bond = to_bond(cd);	read_lock(&bond->curr_slave_lock);	curr = bond->curr_active_slave;	read_unlock(&bond->curr_slave_lock);	return sprintf(buf, "%s\n", (curr) ? "up" : "down") + 1;}static CLASS_DEVICE_ATTR(mii_status, S_IRUGO, bonding_show_mii_status, NULL);/* * Show current 802.3ad aggregator ID. */static ssize_t bonding_show_ad_aggregator(struct class_device *cd, char *buf){	int count = 0;	struct bonding *bond = to_bond(cd);	if (bond->params.mode == BOND_MODE_8023AD) {		struct ad_info ad_info;		count = sprintf(buf, "%d\n", (bond_3ad_get_active_agg_info(bond, &ad_info)) ?  0 : ad_info.aggregator_id) + 1;	}	else		count = sprintf(buf, "\n") + 1;	return count;}static CLASS_DEVICE_ATTR(ad_aggregator, S_IRUGO, bonding_show_ad_aggregator, NULL);/* * Show number of active 802.3ad ports. */static ssize_t bonding_show_ad_num_ports(struct class_device *cd, char *buf){	int count = 0;	struct bonding *bond = to_bond(cd);	if (bond->params.mode == BOND_MODE_8023AD) {		struct ad_info ad_info;		count = sprintf(buf, "%d\n", (bond_3ad_get_active_agg_info(bond, &ad_info)) ?  0: ad_info.ports) + 1;	}	else		count = sprintf(buf, "\n") + 1;	return count;}static CLASS_DEVICE_ATTR(ad_num_ports, S_IRUGO, bonding_show_ad_num_ports, NULL);/* * Show current 802.3ad actor key. */static ssize_t bonding_show_ad_actor_key(struct class_device *cd, char *buf){	int count = 0;	struct bonding *bond = to_bond(cd);	if (bond->params.mode == BOND_MODE_8023AD) {		struct ad_info ad_info;		count = sprintf(buf, "%d\n", (bond_3ad_get_active_agg_info(bond, &ad_info)) ?  0 : ad_info.actor_key) + 1;	}	else		count = sprintf(buf, "\n") + 1;	return count;}static CLASS_DEVICE_ATTR(ad_actor_key, S_IRUGO, bonding_show_ad_actor_key, NULL);/* * Show current 802.3ad partner key. */static ssize_t bonding_show_ad_partner_key(struct class_device *cd, char *buf){	int count = 0;	struct bonding *bond = to_bond(cd);	if (bond->params.mode == BOND_MODE_8023AD) {		struct ad_info ad_info;		count = sprintf(buf, "%d\n", (bond_3ad_get_active_agg_info(bond, &ad_info)) ?  0 : ad_info.partner_key) + 1;	}	else		count = sprintf(buf, "\n") + 1;	return count;}static CLASS_DEVICE_ATTR(ad_partner_key, S_IRUGO, bonding_show_ad_partner_key, NULL);/* * Show current 802.3ad partner mac. */static ssize_t bonding_show_ad_partner_mac(struct class_device *cd, char *buf){	int count = 0;	struct bonding *bond = to_bond(cd);	if (bond->params.mode == BOND_MODE_8023AD) {		struct ad_info ad_info;		if (!bond_3ad_get_active_agg_info(bond, &ad_info)) {			count = sprintf(buf,"%02x:%02x:%02x:%02x:%02x:%02x\n",				       ad_info.partner_system[0],				       ad_info.partner_system[1],				       ad_info.partner_system[2],				       ad_info.partner_system[3],				       ad_info.partner_system[4],				       ad_info.partner_system[5]) + 1;		}	}	else		count = sprintf(buf, "\n") + 1;	return count;}static CLASS_DEVICE_ATTR(ad_partner_mac, S_IRUGO, bonding_show_ad_partner_mac, NULL);static struct attribute *per_bond_attrs[] = {	&class_device_attr_slaves.attr,	&class_device_attr_mode.attr,	&class_device_attr_arp_interval.attr,	&class_device_attr_arp_ip_target.attr,	&class_device_attr_downdelay.attr,	&class_device_attr_updelay.attr,	&class_device_attr_lacp_rate.attr,	&class_device_attr_xmit_hash_policy.attr,	&class_device_attr_miimon.attr,	&class_device_attr_primary.attr,	&class_device_attr_use_carrier.attr,	&class_device_attr_active_slave.attr,	&class_device_attr_mii_status.attr,	&class_device_attr_ad_aggregator.attr,	&class_device_attr_ad_num_ports.attr,	&class_device_attr_ad_actor_key.attr,	&class_device_attr_ad_partner_key.attr,	&class_device_attr_ad_partner_mac.attr,	NULL,};static struct attribute_group bonding_group = {	.name = "bonding",	.attrs = per_bond_attrs,};/* * Initialize sysfs.  This sets up the bonding_masters file in * /sys/class/net. */int bond_create_sysfs(void){	int ret = 0;	struct bonding *firstbond;	init_rwsem(&bonding_rwsem);	/* get the netdev class pointer */	firstbond = container_of(bond_dev_list.next, struct bonding, bond_list);	if (!firstbond)		return -ENODEV;	netdev_class = firstbond->dev->class_dev.class;	if (!netdev_class)		return -ENODEV;	ret = class_create_file(netdev_class, &class_attr_bonding_masters);	return ret;}/* * Remove /sys/class/net/bonding_masters. */void bond_destroy_sysfs(void){	if (netdev_class)		class_remove_file(netdev_class, &class_attr_bonding_masters);}/* * Initialize sysfs for each bond.  This sets up and registers * the 'bondctl' directory for each individual bond under /sys/class/net. */int bond_create_sysfs_entry(struct bonding *bond){	struct net_device *dev = bond->dev;	int err;	err = sysfs_create_group(&(dev->class_dev.kobj), &bonding_group);	if (err) {		printk(KERN_EMERG "eek! didn't create group!\n");	}	if (expected_refcount < 1)		expected_refcount = atomic_read(&bond->dev->class_dev.kobj.kref.refcount);	return err;}/* * Remove sysfs entries for each bond. */void bond_destroy_sysfs_entry(struct bonding *bond){	struct net_device *dev = bond->dev;	sysfs_remove_group(&(dev->class_dev.kobj), &bonding_group);}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?