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

📄 bonding.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 4 页
字号:
	if (!IS_UP(dev)) { /* bond down */		dev_kfree_skb(skb);		return 0;	}	read_lock_irqsave(&bond->lock, flags);	read_lock(&bond->ptrlock);	slave = start_at = bond->current_slave;	read_unlock(&bond->ptrlock);	if (slave == NULL) { /* we're at the root, get the first slave */		/* no suitable interface, frame not sent */		dev_kfree_skb(skb);		read_unlock_irqrestore(&bond->lock, flags);		return 0;	}	do {		if (IS_UP(slave->dev)		    && (slave->link == BOND_LINK_UP)		    && (slave->state == BOND_STATE_ACTIVE)) {			skb->dev = slave->dev;			skb->priority = 1;			dev_queue_xmit(skb);			write_lock(&bond->ptrlock);			bond->current_slave = slave->next;			write_unlock(&bond->ptrlock);			read_unlock_irqrestore(&bond->lock, flags);			return 0;		}	} while ((slave = slave->next) != start_at);	/* no suitable interface, frame not sent */	dev_kfree_skb(skb);	read_unlock_irqrestore(&bond->lock, flags);	return 0;}/*  * in XOR mode, we determine the output device by performing xor on * the source and destination hw adresses.  If this device is not  * enabled, find the next slave following this xor slave.  */static int bond_xmit_xor(struct sk_buff *skb, struct net_device *dev){	slave_t *slave, *start_at;	struct bonding *bond = (struct bonding *) dev->priv;	unsigned long flags;	struct ethhdr *data = (struct ethhdr *)skb->data;	int slave_no;	if (!IS_UP(dev)) { /* bond down */		dev_kfree_skb(skb);		return 0;	}	read_lock_irqsave(&bond->lock, flags);	slave = bond->prev;	/* we're at the root, get the first slave */	if ((slave == NULL) || (slave->dev == NULL)) { 		/* no suitable interface, frame not sent */		dev_kfree_skb(skb);		read_unlock_irqrestore(&bond->lock, flags);		return 0;	}	slave_no = (data->h_dest[5]^slave->dev->dev_addr[5]) % bond->slave_cnt;	while ( (slave_no > 0) && (slave != (slave_t *)bond) ) {		slave = slave->prev;		slave_no--;	} 	start_at = slave;	do {		if (IS_UP(slave->dev)		    && (slave->link == BOND_LINK_UP)		    && (slave->state == BOND_STATE_ACTIVE)) {			skb->dev = slave->dev;			skb->priority = 1;			dev_queue_xmit(skb);			read_unlock_irqrestore(&bond->lock, flags);			return 0;		}	} while ((slave = slave->next) != start_at);	/* no suitable interface, frame not sent */	dev_kfree_skb(skb);	read_unlock_irqrestore(&bond->lock, flags);	return 0;}/*  * in active-backup mode, we know that bond->current_slave is always valid if * the bond has a usable interface. */static int bond_xmit_activebackup(struct sk_buff *skb, struct net_device *dev){	struct bonding *bond = (struct bonding *) dev->priv;	unsigned long flags;	int ret;	if (!IS_UP(dev)) { /* bond down */		dev_kfree_skb(skb);		return 0;	}	/* if we are sending arp packets, try to at least 	   identify our own ip address */	if ( (arp_interval > 0) && (my_ip==0) &&		(skb->protocol == __constant_htons(ETH_P_ARP) ) ) {		char *the_ip = (((char *)skb->data)) 				+ sizeof(struct ethhdr)  				+ sizeof(struct arphdr) + 				ETH_ALEN;		memcpy(&my_ip, the_ip, 4);	}	/* if we are sending arp packets and don't know 	   the target hw address, save it so we don't need 	   to use a broadcast address */	if ( (arp_interval > 0) && (arp_target_hw_addr==NULL) &&	     (skb->protocol == __constant_htons(ETH_P_IP) ) ) {		struct ethhdr *eth_hdr = 			(struct ethhdr *) (((char *)skb->data));		arp_target_hw_addr = kmalloc(ETH_ALEN, GFP_KERNEL);		memcpy(arp_target_hw_addr, eth_hdr->h_dest, ETH_ALEN);	}	read_lock_irqsave(&bond->lock, flags);	read_lock(&bond->ptrlock);	if (bond->current_slave != NULL) { /* one usable interface */		skb->dev = bond->current_slave->dev;		read_unlock(&bond->ptrlock);		skb->priority = 1;		ret = dev_queue_xmit(skb);		read_unlock_irqrestore(&bond->lock, flags);		return 0;	}	else {		read_unlock(&bond->ptrlock);	}	/* no suitable interface, frame not sent */#ifdef BONDING_DEBUG	printk(KERN_INFO "There was no suitable interface, so we don't transmit\n");#endif	dev_kfree_skb(skb);	read_unlock_irqrestore(&bond->lock, flags);	return 0;}static struct net_device_stats *bond_get_stats(struct net_device *dev){	bonding_t *bond = dev->priv;	struct net_device_stats *stats = bond->stats, *sstats;	slave_t *slave;	unsigned long flags;	memset(bond->stats, 0, sizeof(struct net_device_stats));	read_lock_irqsave(&bond->lock, flags);	for (slave = bond->prev; slave!=(slave_t *)bond; slave = slave->prev) {		sstats = slave->dev->get_stats(slave->dev); 		stats->rx_packets += sstats->rx_packets;		stats->rx_bytes += sstats->rx_bytes;		stats->rx_errors += sstats->rx_errors;		stats->rx_dropped += sstats->rx_dropped;		stats->tx_packets += sstats->tx_packets;		stats->tx_bytes += sstats->tx_bytes;		stats->tx_errors += sstats->tx_errors;		stats->tx_dropped += sstats->tx_dropped;		stats->multicast += sstats->multicast;		stats->collisions += sstats->collisions;		stats->rx_length_errors += sstats->rx_length_errors;		stats->rx_over_errors += sstats->rx_over_errors;		stats->rx_crc_errors += sstats->rx_crc_errors;		stats->rx_frame_errors += sstats->rx_frame_errors;		stats->rx_fifo_errors += sstats->rx_fifo_errors;			stats->rx_missed_errors += sstats->rx_missed_errors;			stats->tx_aborted_errors += sstats->tx_aborted_errors;		stats->tx_carrier_errors += sstats->tx_carrier_errors;		stats->tx_fifo_errors += sstats->tx_fifo_errors;		stats->tx_heartbeat_errors += sstats->tx_heartbeat_errors;		stats->tx_window_errors += sstats->tx_window_errors;	}	read_unlock_irqrestore(&bond->lock, flags);	return stats;}static int bond_get_info(char *buf, char **start, off_t offset, int length){	bonding_t *bond = these_bonds;	int len = 0;	off_t begin = 0;	u16 link;	slave_t *slave = NULL;	unsigned long flags;	while (bond != NULL) {		/*		 * This function locks the mutex, so we can't lock it until 		 * afterwards		 */		link = bond_check_mii_link(bond);		len += sprintf(buf + len, "Bonding Mode: ");		len += sprintf(buf + len, "%s\n", mode ? "active-backup" : "load balancing");		if (mode == BOND_MODE_ACTIVEBACKUP) {			read_lock_irqsave(&bond->lock, flags);			read_lock(&bond->ptrlock);			if (bond->current_slave != NULL) {				len += sprintf(buf + len, 					"Currently Active Slave: %s\n", 					bond->current_slave->dev->name);			}			read_unlock(&bond->ptrlock);			read_unlock_irqrestore(&bond->lock, flags);		}		len += sprintf(buf + len, "MII Status: ");		len += sprintf(buf + len, 				link == MII_LINK_READY ? "up\n" : "down\n");		len += sprintf(buf + len, "MII Polling Interval (ms): %d\n", 				miimon);		len += sprintf(buf + len, "Up Delay (ms): %d\n", updelay);		len += sprintf(buf + len, "Down Delay (ms): %d\n", downdelay);		read_lock_irqsave(&bond->lock, flags);		for (slave = bond->prev; slave != (slave_t *)bond; 		     slave = slave->prev) {			len += sprintf(buf + len, "\nSlave Interface: %s\n", slave->dev->name);			len += sprintf(buf + len, "MII Status: ");			len += sprintf(buf + len, 				slave->link == BOND_LINK_UP ? 				"up\n" : "down\n");			len += sprintf(buf + len, "Link Failure Count: %d\n", 				slave->link_failure_count);		}		read_unlock_irqrestore(&bond->lock, flags);		/*		 * Figure out the calcs for the /proc/net interface		 */		*start = buf + (offset - begin);		len -= (offset - begin);		if (len > length) {			len = length;		}		if (len < 0) {			len = 0;		}		bond = bond->next_bond;	}	return len;}static int bond_event(struct notifier_block *this, unsigned long event, 			void *ptr){	struct bonding *this_bond=(struct bonding *)these_bonds;	struct bonding *last_bond;	struct net_device *event_dev = (struct net_device *)ptr;	/* while there are bonds configured */	while (this_bond != NULL) {		if (this_bond == event_dev->priv ) {			switch (event) {			case NETDEV_UNREGISTER:				/* 				 * remove this bond from a linked list of 				 * bonds 				 */				if (this_bond == these_bonds) {					these_bonds = this_bond->next_bond;				} else {					for (last_bond = these_bonds; 					     last_bond != NULL; 					     last_bond = last_bond->next_bond) {						if (last_bond->next_bond == 						    this_bond) {							last_bond->next_bond = 							this_bond->next_bond;						}					}				}				return NOTIFY_DONE;			default:				return NOTIFY_DONE;			}		} else if (this_bond->device == event_dev->master) {			switch (event) {			case NETDEV_UNREGISTER:				bond_release(this_bond->device, event_dev);				break;			}			return NOTIFY_DONE;		}		this_bond = this_bond->next_bond;	}	return NOTIFY_DONE;}static struct notifier_block bond_netdev_notifier={	bond_event,	NULL,	0};static int __init bond_init(struct net_device *dev){	bonding_t *bond, *this_bond, *last_bond;#ifdef BONDING_DEBUG	printk (KERN_INFO "Begin bond_init for %s\n", dev->name);#endif	bond = kmalloc(sizeof(struct bonding), GFP_KERNEL);	if (bond == NULL) {		return -ENOMEM;	}	memset(bond, 0, sizeof(struct bonding));	/* initialize rwlocks */	rwlock_init(&bond->lock);	rwlock_init(&bond->ptrlock);		bond->stats = kmalloc(sizeof(struct net_device_stats), GFP_KERNEL);	if (bond->stats == NULL) {		kfree(bond);		return -ENOMEM;	}	memset(bond->stats, 0, sizeof(struct net_device_stats));	bond->next = bond->prev = (slave_t *)bond;	bond->current_slave = NULL;	bond->device = dev;	dev->priv = bond;	/* Initialize the device structure. */	if (mode == BOND_MODE_ACTIVEBACKUP) {		dev->hard_start_xmit = bond_xmit_activebackup;	} else if (mode == BOND_MODE_ROUNDROBIN) {		dev->hard_start_xmit = bond_xmit_roundrobin;	} else if (mode == BOND_MODE_XOR) {		dev->hard_start_xmit = bond_xmit_xor;	} else {		printk(KERN_ERR "Unknown bonding mode %d\n", mode);		kfree(bond->stats);		kfree(bond);		return -EINVAL;	}	dev->get_stats = bond_get_stats;	dev->open = bond_open;	dev->stop = bond_close;	dev->set_multicast_list = set_multicast_list;	dev->do_ioctl = bond_ioctl;	/* 	 * Fill in the fields of the device structure with ethernet-generic 	 * values. 	 */	ether_setup(dev);	dev->tx_queue_len = 0;	dev->flags |= IFF_MASTER|IFF_MULTICAST;#ifdef CONFIG_NET_FASTROUTE	dev->accept_fastpath = bond_accept_fastpath;#endif	printk(KERN_INFO "%s registered with", dev->name);	if (miimon > 0) {		printk(" MII link monitoring set to %d ms", miimon);		updelay /= miimon;		downdelay /= miimon;	} else {		printk("out MII link monitoring");	}	printk(", in %s mode.\n",mode?"active-backup":"bonding");#ifdef CONFIG_PROC_FS	bond->bond_proc_dir = proc_mkdir(dev->name, proc_net);	if (bond->bond_proc_dir == NULL) {		printk(KERN_ERR "%s: Cannot init /proc/net/%s/\n", 			dev->name, dev->name);		kfree(bond->stats);		kfree(bond);		return -ENOMEM;	}	bond->bond_proc_info_file = 		create_proc_info_entry("info", 0, bond->bond_proc_dir, 					bond_get_info);	if (bond->bond_proc_info_file == NULL) {		printk(KERN_ERR "%s: Cannot init /proc/net/%s/info\n", 			dev->name, dev->name);		remove_proc_entry(dev->name, proc_net);		kfree(bond->stats);		kfree(bond);		return -ENOMEM;	}#endif /* CONFIG_PROC_FS */	if (first_pass == 1) {		these_bonds = bond;		register_netdevice_notifier(&bond_netdev_notifier);		first_pass = 0;	} else {		last_bond = these_bonds;		this_bond = these_bonds->next_bond;		while (this_bond != NULL) {			last_bond = this_bond;			this_bond = this_bond->next_bond;		}		last_bond->next_bond = bond;	} 	return 0;}/*static int __init bond_probe(struct net_device *dev){	bond_init(dev);	return 0;} */static int __init bonding_init(void){	int no;	int err;	/* Find a name for this unit */	static struct net_device *dev_bond = NULL;	dev_bond = dev_bonds = kmalloc(max_bonds*sizeof(struct net_device), 					GFP_KERNEL);	if (dev_bond == NULL) {		return -ENOMEM;	}	memset(dev_bonds, 0, max_bonds*sizeof(struct net_device));	if (arp_ip_target) {		if (my_inet_aton(arp_ip_target, &arp_target) == 0)  {			arp_interval = 0;		}	}	for (no = 0; no < max_bonds; no++) {		dev_bond->init = bond_init;			err = dev_alloc_name(dev_bond,"bond%d");		if (err < 0) {			kfree(dev_bonds);			return err;		}		SET_MODULE_OWNER(dev_bond);		if (register_netdev(dev_bond) != 0) {			kfree(dev_bonds);			return -EIO;		}			dev_bond++;	}	return 0;}static void __exit bonding_exit(void){	struct net_device *dev_bond = dev_bonds;	struct bonding *bond;	int no;	unregister_netdevice_notifier(&bond_netdev_notifier);		 	for (no = 0; no < max_bonds; no++) {#ifdef CONFIG_PROC_FS		bond = (struct bonding *) dev_bond->priv;		remove_proc_entry("info", bond->bond_proc_dir);		remove_proc_entry(dev_bond->name, proc_net);#endif		unregister_netdev(dev_bond);		kfree(bond->stats);		kfree(dev_bond->priv);				dev_bond->priv = NULL;		dev_bond++;	}	kfree(dev_bonds);}module_init(bonding_init);module_exit(bonding_exit);MODULE_LICENSE("GPL");/* * Local variables: *  c-indent-level: 8 *  c-basic-offset: 8 *  tab-width: 8 * End: */

⌨️ 快捷键说明

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