Bonjour, voila la solution, sachent qu'il faut ajouter "#define BOND_MODE_NOUVEAU 7" dans le fichier if_bonding.h et le tableau "bond_parm_tbl bond_ethx_tbl[]" dans le fichier bond_sysfs.c et recompiler le tous.
Remarque: j'ai enlevé plusieurs parties, j'ai laissé que cellle modifiabes pour que ça rentre.
/*
* originally based on the dummy device.
*
* Copyright 1999, Thomas Davis,
tadavis@lbl.gov.
* Licensed under the GPL. Based on dummy.c, and eql.c devices.
*
* bonding.c: an Ethernet Bonding driver
*
* This is useful to talk to a Cisco EtherChannel compatible equipment:
* Cisco 5500
* Sun Trunking (Solaris)
* Alteon AceDirector Trunks
* Linux Bonding
* and probably many L2 switches ...
*
* How it works:
* ifconfig bond0 ipaddress netmask up
* will setup a network device, with an ip address. No mac address
* will be assigned at this time. The hw mac address will come from
* the first slave bonded to the channel. All slaves will then use
* this hw mac address.
*
* ifconfig bond0 down
* will release all slaves, marking them as down.
*
* ifenslave bond0 eth0
* will attach eth0 to bond0 as a slave. eth0 hw mac address will either
* a: be used as initial mac address
* b: if a hw mac address already is there, eth0's hw mac address
* will then be set from bond0.
*
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/fcntl.h>
#include <linux/interrupt.h>
#include <linux/ptrace.h>
#include <linux/ioport.h>
#include <linux/in.h>
#include <net/ip.h>
#include <linux/ip.h>
#include <linux/tcp.h>
#include <linux/udp.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/init.h>
#include <linux/timer.h>
#include <linux/socket.h>
#include <linux/ctype.h>
#include <linux/inet.h>
#include <linux/bitops.h>
#include <asm/system.h>
#include <asm/io.h>
#include <asm/dma.h>
#include <asm/uaccess.h>
#include <linux/errno.h>
#include <linux/netdevice.h>
#include <linux/inetdevice.h>
#include <linux/igmp.h>
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
#include <net/sock.h>
#include <linux/rtnetlink.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/smp.h>
#include <linux/if_ether.h>
#include <net/arp.h>
#include <linux/mii.h>
#include <linux/ethtool.h>
#include <linux/if_vlan.h>
#include <linux/if_bonding.h>
#include <linux/jiffies.h>
#include <net/route.h>
#include <net/net_namespace.h>
#include "bonding.h"
#include "bond_3ad.h"
#include "bond_alb.h"
/*---------------------------- Module parameters ----------------------------*/
/* monitor all links that often (in milliseconds). <=0 disables monitoring */
#define BOND_LINK_MON_INTERV 0
#define BOND_LINK_ARP_INTERV 0
static int max_bonds = BOND_DEFAULT_MAX_BONDS;
static int num_grat_arp = 1;
static int num_unsol_na = 1;
static int miimon = BOND_LINK_MON_INTERV;
static int updelay = 0;
static int downdelay = 0;
static int use_carrier = 1;
static char *mode = NULL;
static char *primary = NULL;
static char *lacp_rate = NULL;
static char *ad_select = NULL;
static char *xmit_hash_policy = NULL;
static int arp_interval = BOND_LINK_ARP_INTERV;
static char *arp_ip_target[BOND_MAX_ARP_TARGETS] = { NULL, };
static char *arp_validate = NULL;
static char *fail_over_mac = NULL;
struct bond_params bonding_defaults;
/**************modificationnnnnnnnnnnnn*******************/
static char *eth0 = NULL;
static char *eth1 = NULL;
static char *eth2 = NULL;
static char *eth3 = NULL;
static char *eth4 = NULL;
static char *eth5 = NULL;
static char *eth6 = NULL;
static char *eth7 = NULL;
static char *eth8 = NULL;
static char *eth9 = NULL;
static char *eth10 = NULL;
static char *eth11 = NULL;
static char *eth12 = NULL;
static char *eth13 = NULL;
static char *eth14 = NULL;
static char *eth15 = NULL;
/**************modificationnnnnnnnnnnnn*******************/
module_param(max_bonds, int, 0);
MODULE_PARM_DESC(max_bonds, "Max number of bonded devices");
module_param(num_grat_arp, int, 0644);
MODULE_PARM_DESC(num_grat_arp, "Number of gratuitous ARP packets to send on failover event");
module_param(num_unsol_na, int, 0644);
MODULE_PARM_DESC(num_unsol_na, "Number of unsolicited IPv6 Neighbor Advertisements packets to send on failover event");
module_param(miimon, int, 0);
MODULE_PARM_DESC(miimon, "Link check interval in milliseconds");
module_param(updelay, int, 0);
MODULE_PARM_DESC(updelay, "Delay before considering link up, in milliseconds");
module_param(downdelay, int, 0);
MODULE_PARM_DESC(downdelay, "Delay before considering link down, "
"in milliseconds");
module_param(use_carrier, int, 0);
MODULE_PARM_DESC(use_carrier, "Use netif_carrier_ok (vs MII ioctls) in miimon; "
"0 for off, 1 for on (default)");
module_param(mode, charp, 0);
MODULE_PARM_DESC(mode, "Mode of operation : 0 for balance-rr, "
"1 for active-backup, 2 for balance-xor, "
"3 for broadcast, 4 for 802.3ad, 5 for balance-tlb, "
"6 for balance-alb");
module_param(primary, charp, 0);
MODULE_PARM_DESC(primary, "Primary network device to use");
module_param(lacp_rate, charp, 0);
MODULE_PARM_DESC(lacp_rate, "LACPDU tx rate to request from 802.3ad partner "
"(slow/fast)");
module_param(ad_select, charp, 0);
MODULE_PARM_DESC(ad_select, "803.ad aggregation selection logic: stable (0, default), bandwidth (1), count (2)");
module_param(xmit_hash_policy, charp, 0);
MODULE_PARM_DESC(xmit_hash_policy, "XOR hashing method: 0 for layer 2 (default)"
", 1 for layer 3+4");
module_param(arp_interval, int, 0);
MODULE_PARM_DESC(arp_interval, "arp interval in milliseconds");
module_param_array(arp_ip_target, charp, NULL, 0);
MODULE_PARM_DESC(arp_ip_target, "arp targets in n.n.n.n form");
module_param(arp_validate, charp, 0);
MODULE_PARM_DESC(arp_validate, "validate src/dst of ARP probes: none (default), active, backup or all");
module_param(fail_over_mac, charp, 0);
MODULE_PARM_DESC(fail_over_mac, "For active-backup, do not set all slaves to the same MAC. none (default), active or follow");
/**************modificationnnnnnnnnnnnn*******************/
module_param(eth0, charp, 0);
MODULE_PARM_DESC(eth0, "l'interface eth0");
module_param(eth1, charp, 0);
MODULE_PARM_DESC(eth1, "l'interface eth1");
module_param(eth2, charp, 0);
MODULE_PARM_DESC(eth2, "l'interface eth2");
module_param(eth3, charp, 0);
MODULE_PARM_DESC(eth3, "l'interface eth3");
module_param(eth4, charp, 0);
MODULE_PARM_DESC(eth4, "l'interface eth4");
module_param(eth5, charp, 0);
MODULE_PARM_DESC(eth5, "l'interface eth5");
module_param(eth6, charp, 0);
MODULE_PARM_DESC(eth6, "l'interface eth6");
module_param(eth7, charp, 0);
MODULE_PARM_DESC(eth7, "l'interface eth7");
module_param(eth8, charp, 0);
MODULE_PARM_DESC(eth8, "l'interface eth8");
module_param(eth9, charp, 0);
MODULE_PARM_DESC(eth9, "l'interface eth9");
module_param(eth10, charp, 0);
MODULE_PARM_DESC(eth10, "l'interface eth10");
module_param(eth11, charp, 0);
MODULE_PARM_DESC(eth11, "l'interface eth11");
module_param(eth12, charp, 0);
MODULE_PARM_DESC(eth12, "l'interface eth12");
module_param(eth13, charp, 0);
MODULE_PARM_DESC(eth13, "l'interface eth13");
module_param(eth14, charp, 0);
MODULE_PARM_DESC(eth14, "l'interface eth14");
module_param(eth15, charp, 0);
MODULE_PARM_DESC(eth15, "l'interface eth15");
/*----------------------------- Global variables ----------------------------*/
static const char * const version =
DRV_DESCRIPTION ": v" DRV_VERSION " (" DRV_RELDATE ")\n";
LIST_HEAD(bond_dev_list);
#ifdef CONFIG_PROC_FS
static struct proc_dir_entry *bond_proc_dir = NULL;
#endif
static __be32 arp_target[BOND_MAX_ARP_TARGETS] = { 0, } ;
static int arp_ip_count = 0;
static int bond_mode = BOND_MODE_ROUNDROBIN;
static int xmit_hashtype= BOND_XMIT_POLICY_LAYER2;
static int lacp_fast = 0;
/*******************************modificationnnnnnnnnnn****************************/
u32 param_eth0 = 0;
u32 param_eth1 = 0;
u32 param_eth2 = 0;
u32 param_eth3 = 0;
u32 param_eth4 = 0;
u32 param_eth5 = 0;
u32 param_eth6 = 0;
u32 param_eth7 = 0;
u32 param_eth8 = 0;
u32 param_eth9 = 0;
u32 param_eth10 = 0;
u32 param_eth11 = 0;
u32 param_eth12 = 0;
u32 param_eth13 = 0;
u32 param_eth14 = 0;
u32 param_eth15 = 0;
int j = -1;
/*******************************modificationnnnnnnnnnn****************************/
const struct bond_parm_tbl bond_lacp_tbl[] = {
{ "slow", AD_LACP_SLOW},
{ "fast", AD_LACP_FAST},
{ NULL, -1},
};
const struct bond_parm_tbl bond_mode_tbl[] = {
{ "balance-rr", BOND_MODE_ROUNDROBIN},
{ "active-backup", BOND_MODE_ACTIVEBACKUP},
{ "balance-xor", BOND_MODE_XOR},
{ "broadcast", BOND_MODE_BROADCAST},
{ "802.3ad", BOND_MODE_8023AD},
{ "balance-tlb", BOND_MODE_TLB},
{ "balance-alb", BOND_MODE_ALB},
{ "nouveau-mode", BOND_MODE_NOUVEAU}, /**********************modification**************************/
{ NULL, -1},
};
const struct bond_parm_tbl xmit_hashtype_tbl[] = {
{ "layer2", BOND_XMIT_POLICY_LAYER2},
{ "layer3+4", BOND_XMIT_POLICY_LAYER34},
{ "layer2+3", BOND_XMIT_POLICY_LAYER23},
{ NULL, -1},
};
const struct bond_parm_tbl arp_validate_tbl[] = {
{ "none", BOND_ARP_VALIDATE_NONE},
{ "active", BOND_ARP_VALIDATE_ACTIVE},
{ "backup", BOND_ARP_VALIDATE_BACKUP},
{ "all", BOND_ARP_VALIDATE_ALL},
{ NULL, -1},
};
const struct bond_parm_tbl fail_over_mac_tbl[] = {
{ "none", BOND_FOM_NONE},
{ "active", BOND_FOM_ACTIVE},
{ "follow", BOND_FOM_FOLLOW},
{ NULL, -1},
};
struct bond_parm_tbl ad_select_tbl[] = {
{ "stable", BOND_AD_STABLE},
{ "bandwidth", BOND_AD_BANDWIDTH},
{ "count", BOND_AD_COUNT},
{ NULL, -1},
};
struct bond_parm_tbl bond_ethx_tbl[] = {
};
/*-------------------------- Forward declarations ---------------------------*/
static void bond_send_gratuitous_arp(struct bonding *bond);
static void bond_deinit(struct net_device *bond_dev);
/*---------------------------- General routines -----------------------------*/
static const char *bond_mode_name(int mode)
{
static const char *names[] = {
[BOND_MODE_ROUNDROBIN] = "load balancing (round-robin)",
[BOND_MODE_ACTIVEBACKUP] = "fault-tolerance (active-backup)",
[BOND_MODE_XOR] = "load balancing (xor)",
[BOND_MODE_BROADCAST] = "fault-tolerance (broadcast)",
[BOND_MODE_8023AD]= "IEEE 802.3ad Dynamic link aggregation",
[BOND_MODE_TLB] = "transmit load balancing",
[BOND_MODE_ALB] = "adaptive load balancing",
[BOND_MODE_NOUVEAU] = "nouveau-mode", /**************************modification*************************/
};
if (mode < 0 || mode > BOND_MODE_AL
return "unknown";
return names[mode];
}
static int bond_xmit_roundrobin(struct sk_buff *skb, struct net_device *bond_dev)
{
struct bonding *bond = netdev_priv(bond_dev);
struct slave *slave, *start_at;
int i, slave_no, res = 1;
read_lock(&bond->lock);
if (!BOND_IS_OK(bond)) {
goto out;
}
/*
* Concurrent TX may collide on rr_tx_counter; we accept that
* as being rare enough not to justify using an atomic op here
*/
slave_no = bond->rr_tx_counter++ % bond->slave_cnt;
bond_for_each_slave(bond, slave, i) {
slave_no--;
if (slave_no < 0) {
break;
}
}
start_at = slave;
bond_for_each_slave_from(bond, slave, i, start_at) {
if (IS_UP(slave->dev) &&
(slave->link == BOND_LINK_UP) &&
(slave->state == BOND_STATE_ACTIVE)) {
res = bond_dev_queue_xmit(bond, skb, slave->dev);
break;
}
}
out:
if (res) {
/* no suitable interface, frame not sent */
dev_kfree_skb(skb);
}
read_unlock(&bond->lock);
return 0;
}
/*
* in active-backup mode, we know that bond->curr_active_slave is always valid if
* the bond has a usable interface.
*/
/*****************************modificationnnnnnnnnnn*********************************/
static int bond_xmit_my_roundrobin(struct sk_buff *skb, struct net_device *bond_dev)
{
struct bonding *bond = netdev_priv(bond_dev);
struct slave *slave, *start_at;
int i, slave_no, res = 1, var, k;
read_lock(&bond->lock);
if (!BOND_IS_OK(bond)) {
goto out;
}
/*
* Concurrent TX may collide on rr_tx_counter; we accept that
* as being rare enough not to justify using an atomic op here
*/
slave_no = bond->rr_tx_counter++ % bond->slave_cnt;
bond_for_each_slave(bond, slave, i) {
slave_no--;
if (slave_no < 0) {
break;
}
}
start_at = slave;
bond_for_each_slave_from(bond, slave, i, start_at) {
printk("\n salam, l'interface présente dans la boucle bond_for_eache_slave est: %s \n", slave->dev->name);
var=0;
for(k=0; k<=j; k++){
if(strcmp(slave->dev->name, bond_ethx_tbl[k].modename) == 0 ){
printk("\n l'interface réserver est:%s, et son marquage est:%d \n", slave->dev->name, bond_ethx_tbl[k].mode);
var=1;
}
}
printk("\n la valeure de var est:%d\n", var);
if(var == 0) {
if (IS_UP(slave->dev) &&
(slave->link == BOND_LINK_UP) &&
(slave->state == BOND_STATE_ACTIVE)) {
res = bond_dev_queue_xmit(bond, skb, slave->dev);
break;
}
}
}
out:
if (res) {
/* no suitable interface, frame not sent */
dev_kfree_skb(skb);
}
read_unlock(&bond->lock);
return 0;
}
static int bond_xmit_nouveau(struct sk_buff *skb, struct net_device *bond_dev)
{
struct bonding *bond = netdev_priv(bond_dev);
struct slave *slave;
struct net_device *bond_dev1 = bond_dev;
int i,res;
read_lock(&bond->lock);
if (!BOND_IS_OK(bond)) {
goto out;
}
printk("\n salam, le marquage de nfmark est:%u\n", skb->mark);
if(eth0)
{
if( skb->mark == param_eth0 )
{
printk("\n salam, l'interface eth00000000000000000000");
bond_for_each_slave(bond, slave, i) {
if(strcmp(slave->dev->name, "eth0") == 0 ) {
res = bond_dev_queue_xmit(bond, skb, slave->dev);
goto out;
}
}
}
}
if(eth1)
{
if( skb->mark == param_eth1 )
{
printk("\n salam, l'intetrface eth11111111111111111");
bond_for_each_slave(bond, slave, i) {
if(strcmp(slave->dev->name, "eth1") == 0 ) {
res = bond_dev_queue_xmit(bond, skb, slave->dev);
goto out;
}
}
}
}
if(eth2)
{
if( skb->mark == param_eth2 )
{
printk("\n salam, l'intetrface eth2222222222222222");
bond_for_each_slave(bond, slave, i) {
if(strcmp(slave->dev->name, "eth2") == 0 ) {
res = bond_dev_queue_xmit(bond, skb, slave->dev);
goto out;
}
}
}
}
if(eth3)
{
if( skb->mark == param_eth3 )
{
printk("\n salam, l'intetrface eth333333333333333");
bond_for_each_slave(bond, slave, i) {
if(strcmp(slave->dev->name, "eth3") == 0 ) {
res = bond_dev_queue_xmit(bond, skb, slave->dev);
goto out;
}
}
}
}
if(eth4)
{
if( skb->mark == param_eth4 )
{
printk("\n salam, l'intetrface eth44444444444444");
bond_for_each_slave(bond, slave, i) {
if(strcmp(slave->dev->name, "eth4") == 0 ) {
res = bond_dev_queue_xmit(bond, skb, slave->dev);
goto out;
}
}
}
}
if(eth5)
{
if( skb->mark == param_eth5 )
{
printk("\n salam, l'intetrface eth55555555555555");
bond_for_each_slave(bond, slave, i) {
if(strcmp(slave->dev->name, "eth5") == 0 ) {
res = bond_dev_queue_xmit(bond, skb, slave->dev);
goto out;
}
}
}
}
if(eth6)
{
if( skb->mark == param_eth6 )
{
printk("\n salam, l'intetrface eth66666666666666");
bond_for_each_slave(bond, slave, i) {
if(strcmp(slave->dev->name, "eth6") == 0 ) {
res = bond_dev_queue_xmit(bond, skb, slave->dev);
goto out;
}
}
}
}
if(eth7)
{
if( skb->mark == param_eth7 )
{
printk("\n salam, l'intetrface eth7777777777777");
bond_for_each_slave(bond, slave, i) {
if(strcmp(slave->dev->name, "eth7") == 0 ) {
res = bond_dev_queue_xmit(bond, skb, slave->dev);
goto out;
}
}
}
}
if(eth8)
{
if( skb->mark == param_eth8 )
{
printk("\n salam, l'intetrface eth8888888888888");
bond_for_each_slave(bond, slave, i) {
if(strcmp(slave->dev->name, "eth8") == 0 ) {
res = bond_dev_queue_xmit(bond, skb, slave->dev);
goto out;
}
}
}
}
if(eth9)
{
if( skb->mark == param_eth9 )
{
printk("\n salam, l'intetrface eth9999999999999");
bond_for_each_slave(bond, slave, i) {
if(strcmp(slave->dev->name, "eth9") == 0 ) {
res = bond_dev_queue_xmit(bond, skb, slave->dev);
goto out;
}
}
}
}
if(eth10)
{
if( skb->mark == param_eth10 )
{
printk("\n salam, l'intetrface eth10 10 10 10 10 10 10");
bond_for_each_slave(bond, slave, i) {
if(strcmp(slave->dev->name, "eth10") == 0 ) {
res = bond_dev_queue_xmit(bond, skb, slave->dev);
goto out;
}
}
}
}
if(eth11)
{
if( skb->mark == param_eth11 )
{
printk("\n salam, l'intetrface eth11 11 11 11 11 11 11");
bond_for_each_slave(bond, slave, i) {
if(strcmp(slave->dev->name, "eth11") == 0 ) {
res = bond_dev_queue_xmit(bond, skb, slave->dev);
goto out;
}
}
}
}
if(eth12)
{
if( skb->mark == param_eth12 )
{
printk("\n salam, l'intetrface eth12 12 12 12 12 12 12");
bond_for_each_slave(bond, slave, i) {
if(strcmp(slave->dev->name, "eth12") == 0 ) {
res = bond_dev_queue_xmit(bond, skb, slave->dev);
goto out;
}
}
}
}
if(eth13)
{
if( skb->mark == param_eth13 )
{
printk("\n salam, l'intetrface eth13 13 13 13 13 13 13");
bond_for_each_slave(bond, slave, i) {
if(strcmp(slave->dev->name, "eth13") == 0 ) {
res = bond_dev_queue_xmit(bond, skb, slave->dev);
goto out;
}
}
}
}
if(eth14)
{
if( skb->mark == param_eth14 )
{
printk("\n salam, l'intetrface eth14 14 14 14 14 14 14");
bond_for_each_slave(bond, slave, i) {
if(strcmp(slave->dev->name, "eth14") == 0 ) {
res = bond_dev_queue_xmit(bond, skb, slave->dev);
goto out;
}
}
}
}
if(eth15)
{
if( skb->mark == param_eth15 )
{
printk("\n salam, l'intetrface eth15 15 15 15 15 15 15");
bond_for_each_slave(bond, slave, i) {
if(strcmp(slave->dev->name, "eth15") == 0 ) {
res = bond_dev_queue_xmit(bond, skb, slave->dev);
goto out;
}
}
}
}
res = bond_xmit_my_roundrobin(skb, bond_dev1);
out:
if(res) {
dev_kfree_skb(skb);
}
read_unlock(&bond->lock);
return 0;
}
/***************************mpodficationnnnnnnnnnnn**********************************/
static int bond_xmit_activebackup(struct sk_buff *skb, struct net_device *bond_dev)
{
struct bonding *bond = netdev_priv(bond_dev);
int res = 1;
read_lock(&bond->lock);
read_lock(&bond->curr_slave_lock);
if (!BOND_IS_OK(bond)) {
goto out;
}
if (!bond->curr_active_slave)
goto out;
res = bond_dev_queue_xmit(bond, skb, bond->curr_active_slave->dev);
out:
if (res) {
/* no suitable interface, frame not sent */
dev_kfree_skb(skb);
}
read_unlock(&bond->curr_slave_lock);
read_unlock(&bond->lock);
return 0;
}
/*
* In bond_xmit_xor() , we determine the output device by using a pre-
* determined xmit_hash_policy(), If the selected device is not enabled,
* find the next active slave.
*/
static int bond_xmit_xor(struct sk_buff *skb, struct net_device *bond_dev)
{
struct bonding *bond = netdev_priv(bond_dev);
struct slave *slave, *start_at;
int slave_no;
int i;
int res = 1;
read_lock(&bond->lock);
if (!BOND_IS_OK(bond)) {
goto out;
}
slave_no = bond->xmit_hash_policy(skb, bond_dev, bond->slave_cnt);
bond_for_each_slave(bond, slave, i) {
slave_no--;
if (slave_no < 0) {
break;
}
}
start_at = slave;
bond_for_each_slave_from(bond, slave, i, start_at) {
if (IS_UP(slave->dev) &&
(slave->link == BOND_LINK_UP) &&
(slave->state == BOND_STATE_ACTIVE)) {
res = bond_dev_queue_xmit(bond, skb, slave->dev);
break;
}
}
out:
if (res) {
/* no suitable interface, frame not sent */
dev_kfree_skb(skb);
}
read_unlock(&bond->lock);
return 0;
}
/*
* in broadcast mode, we send everything to all usable interfaces.
*/
static int bond_xmit_broadcast(struct sk_buff *skb, struct net_device *bond_dev)
{
struct bonding *bond = netdev_priv(bond_dev);
struct slave *slave, *start_at;
struct net_device *tx_dev = NULL;
int i;
int res = 1;
read_lock(&bond->lock);
if (!BOND_IS_OK(bond)) {
goto out;
}
read_lock(&bond->curr_slave_lock);
start_at = bond->curr_active_slave;
read_unlock(&bond->curr_slave_lock);
if (!start_at) {
goto out;
}
bond_for_each_slave_from(bond, slave, i, start_at) {
if (IS_UP(slave->dev) &&
(slave->link == BOND_LINK_UP) &&
(slave->state == BOND_STATE_ACTIVE)) {
if (tx_dev) {
struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC);
if (!skb2) {
printk(KERN_ERR DRV_NAME
": %s: Error: bond_xmit_broadcast(): "
"skb_clone() failed\n",
bond_dev->name);
continue;
}
res = bond_dev_queue_xmit(bond, skb2, tx_dev);
if (res) {
dev_kfree_skb(skb2);
continue;
}
}
tx_dev = slave->dev;
}
}
if (tx_dev) {
res = bond_dev_queue_xmit(bond, skb, tx_dev);
}
out:
if (res) {
/* no suitable interface, frame not sent */
dev_kfree_skb(skb);
}
/* frame sent to all suitable interfaces */
read_unlock(&bond->lock);
return 0;
}
/*------------------------- Device initialization ---------------------------*/
static void bond_set_xmit_hash_policy(struct bonding *bond)
{
switch (bond->params.xmit_policy) {
case BOND_XMIT_POLICY_LAYER23:
bond->xmit_hash_policy = bond_xmit_hash_policy_l23;
break;
case BOND_XMIT_POLICY_LAYER34:
bond->xmit_hash_policy = bond_xmit_hash_policy_l34;
break;
case BOND_XMIT_POLICY_LAYER2:
default:
bond->xmit_hash_policy = bond_xmit_hash_policy_l2;
break;
}
}
static int bond_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
const struct bonding *bond = netdev_priv(dev);
switch (bond->params.mode) {
case BOND_MODE_ROUNDROBIN:
return bond_xmit_roundrobin(skb, dev);
case BOND_MODE_ACTIVEBACKUP:
return bond_xmit_activebackup(skb, dev);
case BOND_MODE_XOR:
return bond_xmit_xor(skb, dev);
case BOND_MODE_BROADCAST:
return bond_xmit_broadcast(skb, dev);
case BOND_MODE_8023AD:
return bond_3ad_xmit_xor(skb, dev);
case BOND_MODE_ALB:
case BOND_MODE_TLB:
return bond_alb_xmit(skb, dev);
case BOND_MODE_NOUVEAU: /**************************modificationnnnnnnnnn*************************/
return bond_xmit_nouveau(skb, dev); /**************************moeificationnnnnnnnnn*************************/
default:
/* Should never happen, mode already checked */
printk(KERN_ERR DRV_NAME ": %s: Error: Unknown bonding mode %d\n",
dev->name, bond->params.mode);
WARN_ON_ONCE(1);
dev_kfree_skb(skb);
return NETDEV_TX_OK;
}
}
/*
* set bond mode specific net device operations
*/
void bond_set_mode_ops(struct bonding *bond, int mode)
{
struct net_device *bond_dev = bond->dev;
switch (mode) {
case BOND_MODE_ROUNDROBIN:
break;
case BOND_MODE_ACTIVEBACKUP:
break;
case BOND_MODE_XOR:
bond_set_xmit_hash_policy(bond);
break;
case BOND_MODE_BROADCAST:
break;
case BOND_MODE_8023AD:
bond_set_master_3ad_flags(bond);
bond_set_xmit_hash_policy(bond);
break;
case BOND_MODE_ALB:
bond_set_master_alb_flags(bond);
/* FALLTHRU */
case BOND_MODE_TLB:
break;
case BOND_MODE_NOUVEAU: /**************************modificationnnnnnnnnn********************************/
break; /**************************modificationnnnnnnnnn********************************/
default:
/* Should never happen, mode already checked */
printk(KERN_ERR DRV_NAME
": %s: Error: Unknown bonding mode %d\n",
bond_dev->name,
mode);
break;
}
}
static void bond_ethtool_get_drvinfo(struct net_device *bond_dev,
struct ethtool_drvinfo *drvinfo)
{
strncpy(drvinfo->driver, DRV_NAME, 32);
strncpy(drvinfo->version, DRV_VERSION, 32);
snprintf(drvinfo->fw_version, 32, "%d", BOND_ABI_VERSION);
}
static const struct ethtool_ops bond_ethtool_ops = {
.get_drvinfo = bond_ethtool_get_drvinfo,
.get_link = ethtool_op_get_link,
.get_tx_csum = ethtool_op_get_tx_csum,
.get_sg = ethtool_op_get_sg,
.get_tso = ethtool_op_get_tso,
.get_ufo = ethtool_op_get_ufo,
.get_flags = ethtool_op_get_flags,
};
static const struct net_device_ops bond_netdev_ops = {
.ndo_open = bond_open,
.ndo_stop = bond_close,
.ndo_start_xmit = bond_start_xmit,
.ndo_get_stats = bond_get_stats,
.ndo_do_ioctl = bond_do_ioctl,
.ndo_set_multicast_list = bond_set_multicast_list,
.ndo_change_mtu = bond_change_mtu,
.ndo_set_mac_address = bond_set_mac_address,
.ndo_neigh_setup = bond_neigh_setup,
.ndo_vlan_rx_register = bond_vlan_rx_register,
.ndo_vlan_rx_add_vid = bond_vlan_rx_add_vid,
.ndo_vlan_rx_kill_vid = bond_vlan_rx_kill_vid,
};
/*
* Does not allocate but creates a /proc entry.
* Allowed to fail.
*/
static int bond_init(struct net_device *bond_dev, struct bond_params *params)
{
struct bonding *bond = netdev_priv(bond_dev);
pr_debug("Begin bond_init for %s\n", bond_dev->name);
/* initialize rwlocks */
rwlock_init(&bond->lock);
rwlock_init(&bond->curr_slave_lock);
bond->params = *params; /* copy params struct */
bond->wq = create_singlethread_workqueue(bond_dev->name);
if (!bond->wq)
return -ENOMEM;
/* Initialize pointers */
bond->first_slave = NULL;
bond->curr_active_slave = NULL;
bond->current_arp_slave = NULL;
bond->primary_slave = NULL;
bond->dev = bond_dev;
bond->send_grat_arp = 0;
bond->send_unsol_na = 0;
bond->setup_by_slave = 0;
INIT_LIST_HEAD(&bond->vlan_list);
/* Initialize the device entry points */
bond_dev->netdev_ops = &bond_netdev_ops;
bond_dev->ethtool_ops = &bond_ethtool_ops;
bond_set_mode_ops(bond, bond->params.mode);
bond_dev->destructor = bond_destructor;
/* Initialize the device options */
bond_dev->tx_queue_len = 0;
bond_dev->flags |= IFF_MASTER|IFF_MULTICAST;
bond_dev->priv_flags |= IFF_BONDING;
if (bond->params.arp_interval)
bond_dev->priv_flags |= IFF_MASTER_ARPMON;
/* At first, we block adding VLANs. That's the only way to
* prevent problems that occur when adding VLANs over an
* empty bond. The block will be removed once non-challenged
* slaves are enslaved.
*/
bond_dev->features |= NETIF_F_VLAN_CHALLENGED;
/* don't acquire bond device's netif_tx_lock when
* transmitting */
bond_dev->features |= NETIF_F_LLTX;
/* By default, we declare the bond to be fully
* VLAN hardware accelerated capable. Special
* care is taken in the various xmit functions
* when there are slaves that are not hw accel
* capable
*/
bond_dev->features |= (NETIF_F_HW_VLAN_TX |
NETIF_F_HW_VLAN_RX |
NETIF_F_HW_VLAN_FILTER);
#ifdef CONFIG_PROC_FS
bond_create_proc_entry(bond);
#endif
list_add_tail(&bond->bond_list, &bond_dev_list);
return 0;
}
static void bond_work_cancel_all(struct bonding *bond)
{
write_lock_bh(&bond->lock);
bond->kill_timers = 1;
write_unlock_bh(&bond->lock);
if (bond->params.miimon && delayed_work_pending(&bond->mii_work))
cancel_delayed_work(&bond->mii_work);
if (bond->params.arp_interval && delayed_work_pending(&bond->arp_work))
cancel_delayed_work(&bond->arp_work);
if (bond->params.mode == BOND_MODE_ALB &&
delayed_work_pending(&bond->alb_work))
cancel_delayed_work(&bond->alb_work);
if (bond->params.mode == BOND_MODE_8023AD &&
delayed_work_pending(&bond->ad_work))
cancel_delayed_work(&bond->ad_work);
}
/* De-initialize device specific data.
* Caller must hold rtnl_lock.
*/
static void bond_deinit(struct net_device *bond_dev)
{
struct bonding *bond = netdev_priv(bond_dev);
list_del(&bond->bond_list);
bond_work_cancel_all(bond);
#ifdef CONFIG_PROC_FS
bond_remove_proc_entry(bond);
#endif
}
/* Unregister and free all bond devices.
* Caller must hold rtnl_lock.
*/
static void bond_free_all(void)
{
struct bonding *bond, *nxt;
list_for_each_entry_safe(bond, nxt, &bond_dev_list, bond_list) {
struct net_device *bond_dev = bond->dev;
bond_work_cancel_all(bond);
/* Release the bonded slaves */
bond_release_all(bond_dev);
bond_destroy(bond);
}
#ifdef CONFIG_PROC_FS
bond_destroy_proc_dir();
#endif
}
/*------------------------- Module initialization ---------------------------*/
/*
* Convert string input module parms. Accept either the
* number of the mode or its string name. A bit complicated because
* some mode names are substrings of other names, and calls from sysfs
* may have whitespace in the name (trailing newlines, for example).
*/
int bond_parse_parm(const char *buf, const struct bond_parm_tbl *tbl)
{
int mode = -1, i, rv;
char *p, modestr[BOND_MAX_MODENAME_LEN + 1] = { 0, };
for (p = (char *)buf; *p; p++)
if (!(isdigit(*p) || isspace(*p)))
break;
if (*p)
rv = sscanf(buf, "%20s", modestr);
else
rv = sscanf(buf, "%d", &mode);
if (!rv)
return -1;
for (i = 0; tbl
.modename; i++) {
if (mode == tbl.mode)
return tbl.mode;
if (strcmp(modestr, tbl.modename) == 0)
return tbl.mode;
}
return -1;
}
static int bond_check_params(struct bond_params *params)
{
int arp_validate_value, fail_over_mac_value;
/*
* Convert string parameters.
*/
if (mode) {
bond_mode = bond_parse_parm(mode, bond_mode_tbl);
if (bond_mode == -1) {
printk(KERN_ERR DRV_NAME
": Error: Invalid bonding mode \"%s\"\n",
mode == NULL ? "NULL" : mode);
return -EINVAL;
}
}
/**************modificatiionnnnnnnnnnnn************/
if(bond_mode == BOND_MODE_NOUVEAU) {
if((!eth0)&&(!eth1))
printk("\n erreur, il faut féfinire une interface, eth0 ou eth1\n");
}
if(eth0) {
if( bond_mode != BOND_MODE_NOUVEAU) {
printk(KERN_INFO DRV_NAME
": eth0 param is irrelevant in mode %s\n",
bond_mode_name(bond_mode));
}
j = j+1;
bond_ethx_tbl[j].mode = simple_strtol(eth0, NULL, 0);
bond_ethx_tbl[j].modename = "eth0";
param_eth0 = simple_strtol(eth0, NULL, 0);
}
if(eth1) {
if( bond_mode != BOND_MODE_NOUVEAU) {
printk(KERN_INFO DRV_NAME
": eth1 param is irrelevant in mode %s\n",
bond_mode_name(bond_mode));
}
j = j+1;
bond_ethx_tbl[j].mode = simple_strtol(eth1, NULL, 0);
bond_ethx_tbl[j].modename = "eth1";
param_eth1 = simple_strtol(eth1, NULL, 0);
}
if(eth2) {
if( bond_mode != BOND_MODE_NOUVEAU) {
printk(KERN_INFO DRV_NAME
": eth2 param is irrelevant in mode %s\n",
bond_mode_name(bond_mode));
}
j = j+1;
bond_ethx_tbl[j].mode = simple_strtol(eth2, NULL, 0);
bond_ethx_tbl[j].modename = "eth2";
param_eth2 = simple_strtol(eth2, NULL, 0);
}
if(eth3) {
if( bond_mode != BOND_MODE_NOUVEAU) {
printk(KERN_INFO DRV_NAME
": eth3 param is irrelevant in mode %s\n",
bond_mode_name(bond_mode));
}
j = j+1;
bond_ethx_tbl[j].mode = simple_strtol(eth3, NULL, 0);
bond_ethx_tbl[j].modename = "eth3";
param_eth3 = simple_strtol(eth3, NULL, 0);
}
if(eth4) {
if( bond_mode != BOND_MODE_NOUVEAU) {
printk(KERN_INFO DRV_NAME
": eth4 param is irrelevant in mode %s\n",
bond_mode_name(bond_mode));
}
j = j+1;
bond_ethx_tbl[j].mode = simple_strtol(eth4, NULL, 0);
bond_ethx_tbl[j].modename = "eth4";
param_eth4 = simple_strtol(eth4, NULL, 0);
}
if(eth5) {
if( bond_mode != BOND_MODE_NOUVEAU) {
printk(KERN_INFO DRV_NAME
": eth5 param is irrelevant in mode %s\n",
bond_mode_name(bond_mode));
}
j = j+1;
bond_ethx_tbl[j].mode = simple_strtol(eth5, NULL, 0);
bond_ethx_tbl[j].modename = "eth5";
param_eth5 = simple_strtol(eth5, NULL, 0);
}
if(eth6) {
if( bond_mode != BOND_MODE_NOUVEAU) {
printk(KERN_INFO DRV_NAME
": eth6 param is irrelevant in mode %s\n",
bond_mode_name(bond_mode));
}
j = j+1;
bond_ethx_tbl[j].mode = simple_strtol(eth6, NULL, 0);
bond_ethx_tbl[j].modename = "eth6";
param_eth6 = simple_strtol(eth6, NULL, 0);
}
if(eth7) {
if( bond_mode != BOND_MODE_NOUVEAU) {
printk(KERN_INFO DRV_NAME
": eth7 param is irrelevant in mode %s\n",
bond_mode_name(bond_mode));
}
j = j+1;
bond_ethx_tbl[j].mode = simple_strtol(eth7, NULL, 0);
bond_ethx_tbl[j].modename = "eth7";
param_eth7 = simple_strtol(eth7, NULL, 0);
}
if(eth8) {
if( bond_mode != BOND_MODE_NOUVEAU) {
printk(KERN_INFO DRV_NAME
": eth8 param is irrelevant in mode %s\n",
bond_mode_name(bond_mode));
}
j = j+1;
bond_ethx_tbl[j].mode = simple_strtol(eth8, NULL, 0);
bond_ethx_tbl[j].modename = "eth8";
param_eth8 = simple_strtol(eth8, NULL, 0);
}
if(eth9) {
if( bond_mode != BOND_MODE_NOUVEAU) {
printk(KERN_INFO DRV_NAME
": eth9 param is irrelevant in mode %s\n",
bond_mode_name(bond_mode));
}
j = j+1;
bond_ethx_tbl[j].mode = simple_strtol(eth9, NULL, 0);
bond_ethx_tbl[j].modename = "eth9";
param_eth9 = simple_strtol(eth9, NULL, 0);
}
if(eth10) {
if( bond_mode != BOND_MODE_NOUVEAU) {
printk(KERN_INFO DRV_NAME
": eth10 param is irrelevant in mode %s\n",
bond_mode_name(bond_mode));
}
j = j+1;
bond_ethx_tbl[j].mode = simple_strtol(eth10, NULL, 0);
bond_ethx_tbl[j].modename = "eth10";
param_eth10 = simple_strtol(eth10, NULL, 0);
}
if(eth11) {
if( bond_mode != BOND_MODE_NOUVEAU) {
printk(KERN_INFO DRV_NAME
": eth11 param is irrelevant in mode %s\n",
bond_mode_name(bond_mode));
}
j = j+1;
bond_ethx_tbl[j].mode = simple_strtol(eth11, NULL, 0);
bond_ethx_tbl[j].modename = "eth11";
param_eth11 = simple_strtol(eth11, NULL, 0);
}
if(eth12) {
if( bond_mode != BOND_MODE_NOUVEAU) {
printk(KERN_INFO DRV_NAME
": eth12 param is irrelevant in mode %s\n",
bond_mode_name(bond_mode));
}
j = j+1;
bond_ethx_tbl[j].mode = simple_strtol(eth12, NULL, 0);
bond_ethx_tbl[j].modename = "eth12";
param_eth12 = simple_strtol(eth12, NULL, 0);
}
if(eth13) {
if( bond_mode != BOND_MODE_NOUVEAU) {
printk(KERN_INFO DRV_NAME
": eth13 param is irrelevant in mode %s\n",
bond_mode_name(bond_mode));
}
j = j+1;
bond_ethx_tbl[j].mode = simple_strtol(eth13, NULL, 0);
bond_ethx_tbl[j].modename = "eth13";
param_eth13 = simple_strtol(eth13, NULL, 0);
}
if(eth14) {
if( bond_mode != BOND_MODE_NOUVEAU) {
printk(KERN_INFO DRV_NAME
": eth14 param is irrelevant in mode %s\n",
bond_mode_name(bond_mode));
}
j = j+1;
bond_ethx_tbl[j].mode = simple_strtol(eth14, NULL, 0);
bond_ethx_tbl[j].modename = "eth14";
param_eth14 = simple_strtol(eth14, NULL, 0);
}
if(eth15) {
if( bond_mode != BOND_MODE_NOUVEAU) {
printk(KERN_INFO DRV_NAME
": eth15 param is irrelevant in mode %s\n",
bond_mode_name(bond_mode));
}
j = j+1;
bond_ethx_tbl[j].mode = simple_strtol(eth15, NULL, 0);
bond_ethx_tbl[j].modename = "eth15";
param_eth15 = simple_strtol(eth15, NULL, 0);
}
/*************modificationnnnnnnnnnn***************/
if (xmit_hash_policy) {
if ((bond_mode != BOND_MODE_8023AD)) {
printk(KERN_INFO DRV_NAME
": xor_mode param is irrelevant in mode %s\n",
bond_mode_name(bond_mode));
} else {
xmit_hashtype = bond_parse_parm(xmit_hash_policy,
xmit_hashtype_tbl);
if (xmit_hashtype == -1) {
printk(KERN_ERR DRV_NAME
": Error: Invalid xmit_hash_policy \"%s\"\n",
xmit_hash_policy == NULL ? "NULL" :
xmit_hash_policy);
return -EINVAL;
}
}
}
if (lacp_rate) {
if (bond_mode != BOND_MODE_8023AD) {
printk(KERN_INFO DRV_NAME
": lacp_rate param is irrelevant in mode %s\n",
bond_mode_name(bond_mode));
} else {
lacp_fast = bond_parse_parm(lacp_rate, bond_lacp_tbl);
if (lacp_fast == -1) {
printk(KERN_ERR DRV_NAME
": Error: Invalid lacp rate \"%s\"\n",
lacp_rate == NULL ? "NULL" : lacp_rate);
return -EINVAL;
}
}
}
if (ad_select) {
params->ad_select = bond_parse_parm(ad_select, ad_select_tbl);
if (params->ad_select == -1) {
printk(KERN_ERR DRV_NAME
": Error: Invalid ad_select \"%s\"\n",
ad_select == NULL ? "NULL" : ad_select);
return -EINVAL;
}
if (bond_mode != BOND_MODE_8023AD) {
printk(KERN_WARNING DRV_NAME
": ad_select param only affects 802.3ad mode\n");
}
} else {
params->ad_select = BOND_AD_STABLE;
}
if (max_bonds < 0 || max_bonds > INT_MAX) {
printk(KERN_WARNING DRV_NAME
": Warning: max_bonds (%d) not in range %d-%d, so it "
"was reset to BOND_DEFAULT_MAX_BONDS (%d)\n",
max_bonds, 0, INT_MAX, BOND_DEFAULT_MAX_BONDS);
max_bonds = BOND_DEFAULT_MAX_BONDS;
}
if (miimon < 0) {
printk(KERN_WARNING DRV_NAME
": Warning: miimon module parameter (%d), "
"not in range 0-%d, so it was reset to %d\n",
miimon, INT_MAX, BOND_LINK_MON_INTERV);
miimon = BOND_LINK_MON_INTERV;
}
if (updelay < 0) {
printk(KERN_WARNING DRV_NAME
": Warning: updelay module parameter (%d), "
"not in range 0-%d, so it was reset to 0\n",
updelay, INT_MAX);
updelay = 0;
}
if (downdelay < 0) {
printk(KERN_WARNING DRV_NAME
": Warning: downdelay module parameter (%d), "
"not in range 0-%d, so it was reset to 0\n",
downdelay, INT_MAX);
downdelay = 0;
}
if ((use_carrier != 0) && (use_carrier != 1)) {
printk(KERN_WARNING DRV_NAME
": Warning: use_carrier module parameter (%d), "
"not of valid value (0/1), so it was set to 1\n",
use_carrier);
use_carrier = 1;
}
if (num_grat_arp < 0 || num_grat_arp > 255) {
printk(KERN_WARNING DRV_NAME
": Warning: num_grat_arp (%d) not in range 0-255 so it "
"was reset to 1 \n", num_grat_arp);
num_grat_arp = 1;
}
if (num_unsol_na < 0 || num_unsol_na > 255) {
printk(KERN_WARNING DRV_NAME
": Warning: num_unsol_na (%d) not in range 0-255 so it "
"was reset to 1 \n", num_unsol_na);
num_unsol_na = 1;
}
/* reset values for 802.3ad */
if (bond_mode == BOND_MODE_8023AD) {
if (!miimon) {
printk(KERN_WARNING DRV_NAME
": Warning: miimon must be specified, "
"otherwise bonding will not detect link "
"failure, speed and duplex which are "
"essential for 802.3ad operation\n");
printk(KERN_WARNING "Forcing miimon to 100msec\n");
miimon = 100;
}
}
/* reset values for TLB/ALB */
if ((bond_mode == BOND_MODE_TL
||
(bond_mode == BOND_MODE_AL
) {
if (!miimon) {
printk(KERN_WARNING DRV_NAME
": Warning: miimon must be specified, "
"otherwise bonding will not detect link "
"failure and link speed which are essential "
"for TLB/ALB load balancing\n");
printk(KERN_WARNING "Forcing miimon to 100msec\n");
miimon = 100;
}
}
if (bond_mode == BOND_MODE_AL
{
printk(KERN_NOTICE DRV_NAME
": In ALB mode you might experience client "
"disconnections upon reconnection of a link if the "
"bonding module updelay parameter (%d msec) is "
"incompatible with the forwarding delay time of the "
"switch\n",
updelay);
}
if (!miimon) {
if (updelay || downdelay) {
/* just warn the user the up/down delay will have
* no effect since miimon is zero...
*/
printk(KERN_WARNING DRV_NAME
": Warning: miimon module parameter not set "
"and updelay (%d) or downdelay (%d) module "
"parameter is set; updelay and downdelay have "
"no effect unless miimon is set\n",
updelay, downdelay);
}
} else {
/* don't allow arp monitoring */
if (arp_interval) {
printk(KERN_WARNING DRV_NAME
": Warning: miimon (%d) and arp_interval (%d) "
"can't be used simultaneously, disabling ARP "
"monitoring\n",
miimon, arp_interval);
arp_interval = 0;
}
if ((updelay % miimon) != 0) {
printk(KERN_WARNING DRV_NAME
": Warning: updelay (%d) is not a multiple "
"of miimon (%d), updelay rounded to %d ms\n",
updelay, miimon, (updelay / miimon) * miimon);
}
updelay /= miimon;
if ((downdelay % miimon) != 0) {
printk(KERN_WARNING DRV_NAME
": Warning: downdelay (%d) is not a multiple "
"of miimon (%d), downdelay rounded to %d ms\n",
downdelay, miimon,
(downdelay / miimon) * miimon);
}
downdelay /= miimon;
}
if (arp_interval < 0) {
printk(KERN_WARNING DRV_NAME
": Warning: arp_interval module parameter (%d) "
", not in range 0-%d, so it was reset to %d\n",
arp_interval, INT_MAX, BOND_LINK_ARP_INTERV);
arp_interval = BOND_LINK_ARP_INTERV;
}
for (arp_ip_count = 0;
(arp_ip_count < BOND_MAX_ARP_TARGETS) && arp_ip_target[arp_ip_count];
arp_ip_count++) {
/* not complete check, but should be good enough to
catch mistakes */
if (!isdigit(arp_ip_target[arp_ip_count][0])) {
printk(KERN_WARNING DRV_NAME
": Warning: bad arp_ip_target module parameter "
"(%s), ARP monitoring will not be performed\n",
arp_ip_target[arp_ip_count]);
arp_interval = 0;
} else {
__be32 ip = in_aton(arp_ip_target[arp_ip_count]);
arp_target[arp_ip_count] = ip;
}
}
if (arp_interval && !arp_ip_count) {
/* don't allow arping if no arp_ip_target given... */
printk(KERN_WARNING DRV_NAME
": Warning: arp_interval module parameter (%d) "
"specified without providing an arp_ip_target "
"parameter, arp_interval was reset to 0\n",
arp_interval);
arp_interval = 0;
}
if (arp_validate) {
if (bond_mode != BOND_MODE_ACTIVEBACKUP) {
printk(KERN_ERR DRV_NAME
": arp_validate only supported in active-backup mode\n");
return -EINVAL;
}
if (!arp_interval) {
printk(KERN_ERR DRV_NAME
": arp_validate requires arp_interval\n");
return -EINVAL;
}
arp_validate_value = bond_parse_parm(arp_validate,
arp_validate_tbl);
if (arp_validate_value == -1) {
printk(KERN_ERR DRV_NAME
": Error: invalid arp_validate \"%s\"\n",
arp_validate == NULL ? "NULL" : arp_validate);
return -EINVAL;
}
} else
arp_validate_value = 0;
if (miimon) {
printk(KERN_INFO DRV_NAME
": MII link monitoring set to %d ms\n",
miimon);
} else if (arp_interval) {
int i;
printk(KERN_INFO DRV_NAME
": ARP monitoring set to %d ms, validate %s, with %d target(s):",
arp_interval,
arp_validate_tbl[arp_validate_value].modename,
arp_ip_count);
for (i = 0; i < arp_ip_count; i++)
printk (" %s", arp_ip_target);
printk("\n");
} else if (max_bonds) {
/* miimon and arp_interval not set, we need one so things
* work as expected, see bonding.txt for details
*/
printk(KERN_WARNING DRV_NAME
": Warning: either miimon or arp_interval and "
"arp_ip_target module parameters must be specified, "
"otherwise bonding will not detect link failures! see "
"bonding.txt for details.\n");
}
if (primary && !USES_PRIMARY(bond_mode)) {
/* currently, using a primary only makes sense
* in active backup, TLB or ALB modes
*/
printk(KERN_WARNING DRV_NAME
": Warning: %s primary device specified but has no "
"effect in %s mode\n",
primary, bond_mode_name(bond_mode));
primary = NULL;
}
if (fail_over_mac) {
fail_over_mac_value = bond_parse_parm(fail_over_mac,
fail_over_mac_tbl);
if (fail_over_mac_value == -1) {
printk(KERN_ERR DRV_NAME
": Error: invalid fail_over_mac \"%s\"\n",
arp_validate == NULL ? "NULL" : arp_validate);
return -EINVAL;
}
if (bond_mode != BOND_MODE_ACTIVEBACKUP)
printk(KERN_WARNING DRV_NAME
": Warning: fail_over_mac only affects "
"active-backup mode.\n");
} else {
fail_over_mac_value = BOND_FOM_NONE;
}
/* fill params struct with the proper values */
params->mode = bond_mode;
params->xmit_policy = xmit_hashtype;
params->miimon = miimon;
params->num_grat_arp = num_grat_arp;
params->num_unsol_na = num_unsol_na;
params->arp_interval = arp_interval;
params->arp_validate = arp_validate_value;
params->updelay = updelay;
params->downdelay = downdelay;
params->use_carrier = use_carrier;
params->lacp_fast = lacp_fast;
params->primary[0] = 0;
params->fail_over_mac = fail_over_mac_value;
if (primary) {
strncpy(params->primary, primary, IFNAMSIZ);
params->primary[IFNAMSIZ - 1] = 0;
}
memcpy(params->arp_targets, arp_target, sizeof(arp_target));
return 0;
}
static struct lock_class_key bonding_netdev_xmit_lock_key;
static struct lock_class_key bonding_netdev_addr_lock_key;
static void bond_set_lockdep_class_one(struct net_device *dev,
struct netdev_queue *txq,
void *_unused)
{
lockdep_set_class(&txq->_xmit_lock,
&bonding_netdev_xmit_lock_key);
}
static void bond_set_lockdep_class(struct net_device *dev)
{
lockdep_set_class(&dev->addr_list_lock,
&bonding_netdev_addr_lock_key);
netdev_for_each_tx_queue(dev, bond_set_lockdep_class_one, NULL);
}
/* Create a new bond based on the specified name and bonding parameters.
* If name is NULL, obtain a suitable "bond%d" name for us.
* Caller must NOT hold rtnl_lock; we need to release it here before we
* set up our sysfs entries.
*/
int bond_create(char *name, struct bond_params *params)
{
struct net_device *bond_dev;
struct bonding *bond;
int res;
rtnl_lock();
down_write(&bonding_rwsem);
/* Check to see if the bond already exists. */
if (name) {
list_for_each_entry(bond, &bond_dev_list, bond_list)
if (strnicmp(bond->dev->name, name, IFNAMSIZ) == 0) {
printk(KERN_ERR DRV_NAME
": cannot add bond %s; it already exists\n",
name);
res = -EPERM;
goto out_rtnl;
}
}
bond_dev = alloc_netdev(sizeof(struct bonding), name ? name : "",
ether_setup);
if (!bond_dev) {
printk(KERN_ERR DRV_NAME
": %s: eek! can't alloc netdev!\n",
name);
res = -ENOMEM;
goto out_rtnl;
}
if (!name) {
res = dev_alloc_name(bond_dev, "bond%d");
if (res < 0)
goto out_netdev;
}
/* bond_init() must be called after dev_alloc_name() (for the
* /proc files), but before register_netdevice(), because we
* need to set function pointers.
*/
res = bond_init(bond_dev, params);
if (res < 0) {
goto out_netdev;
}
res = register_netdevice(bond_dev);
if (res < 0) {
goto out_bond;
}
bond_set_lockdep_class(bond_dev);
netif_carrier_off(bond_dev);
up_write(&bonding_rwsem);
rtnl_unlock(); /* allows sysfs registration of net device */
res = bond_create_sysfs_entry(netdev_priv(bond_dev));
if (res < 0) {
rtnl_lock();
down_write(&bonding_rwsem);
bond_deinit(bond_dev);
unregister_netdevice(bond_dev);
goto out_rtnl;
}
return 0;
out_bond:
bond_deinit(bond_dev);
out_netdev:
free_netdev(bond_dev);
out_rtnl:
up_write(&bonding_rwsem);
rtnl_unlock();
return res;
}
static int __init bonding_init(void)
{
int i;
int res;
struct bonding *bond;
printk(KERN_INFO "%s", version);
res = bond_check_params(&bonding_defaults);
if (res) {
goto out;
}
#ifdef CONFIG_PROC_FS
bond_create_proc_dir();
#endif
init_rwsem(&bonding_rwsem);
for (i = 0; i < max_bonds; i++) {
res = bond_create(NULL, &bonding_defaults);
if (res)
goto err;
}
res = bond_create_sysfs();
if (res)
goto err;
register_netdevice_notifier(&bond_netdev_notifier);
register_inetaddr_notifier(&bond_inetaddr_notifier);
bond_register_ipv6_notifier();
goto out;
err:
list_for_each_entry(bond, &bond_dev_list, bond_list) {
bond_work_cancel_all(bond);
destroy_workqueue(bond->wq);
}
bond_destroy_sysfs();
rtnl_lock();
bond_free_all();
rtnl_unlock();
out:
return res;
}
static void __exit bonding_exit(void)
{
unregister_netdevice_notifier(&bond_netdev_notifier);
unregister_inetaddr_notifier(&bond_inetaddr_notifier);
bond_unregister_ipv6_notifier();
bond_destroy_sysfs();
rtnl_lock();
bond_free_all();
rtnl_unlock();
}
module_init(bonding_init);
module_exit(bonding_exit);
MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_VERSION);
MODULE_DESCRIPTION(DRV_DESCRIPTION ", v" DRV_VERSION);
MODULE_AUTHOR("Thomas Davis, tadavis@lbl.gov and many others");
MODULE_SUPPORTED_DEVICE("most ethernet devices");
/*
* Local variables:
* c-indent-level: 8
* c-basic-offset: 8
* tab-width: 8
* End:
*/
J'espère que ça va aidé des personnes dans le future.