add idl4k kernel firmware version 1.13.0.105

This commit is contained in:
Jaroslav Kysela
2015-03-26 17:22:37 +01:00
parent 5194d2792e
commit e9070cdc77
31064 changed files with 12769984 additions and 0 deletions

View File

@@ -0,0 +1,11 @@
#
# Makefile for the Ethernet Bonding driver
#
obj-$(CONFIG_BONDING) += bonding.o
bonding-objs := bond_main.o bond_3ad.o bond_alb.o bond_sysfs.o
ipv6-$(subst m,y,$(CONFIG_IPV6)) += bond_ipv6.o
bonding-objs += $(ipv6-y)

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,285 @@
/*
* Copyright(c) 1999 - 2004 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 59
* Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* The full GNU General Public License is included in this distribution in the
* file called LICENSE.
*
*/
#ifndef __BOND_3AD_H__
#define __BOND_3AD_H__
#include <asm/byteorder.h>
#include <linux/skbuff.h>
#include <linux/netdevice.h>
#include <linux/if_ether.h>
// General definitions
#define PKT_TYPE_LACPDU cpu_to_be16(ETH_P_SLOW)
#define AD_TIMER_INTERVAL 100 /*msec*/
#define MULTICAST_LACPDU_ADDR {0x01, 0x80, 0xC2, 0x00, 0x00, 0x02}
#define AD_LACP_SLOW 0
#define AD_LACP_FAST 1
typedef struct mac_addr {
u8 mac_addr_value[ETH_ALEN];
} mac_addr_t;
enum {
BOND_AD_STABLE = 0,
BOND_AD_BANDWIDTH = 1,
BOND_AD_COUNT = 2,
};
// rx machine states(43.4.11 in the 802.3ad standard)
typedef enum {
AD_RX_DUMMY,
AD_RX_INITIALIZE, // rx Machine
AD_RX_PORT_DISABLED, // rx Machine
AD_RX_LACP_DISABLED, // rx Machine
AD_RX_EXPIRED, // rx Machine
AD_RX_DEFAULTED, // rx Machine
AD_RX_CURRENT // rx Machine
} rx_states_t;
// periodic machine states(43.4.12 in the 802.3ad standard)
typedef enum {
AD_PERIODIC_DUMMY,
AD_NO_PERIODIC, // periodic machine
AD_FAST_PERIODIC, // periodic machine
AD_SLOW_PERIODIC, // periodic machine
AD_PERIODIC_TX // periodic machine
} periodic_states_t;
// mux machine states(43.4.13 in the 802.3ad standard)
typedef enum {
AD_MUX_DUMMY,
AD_MUX_DETACHED, // mux machine
AD_MUX_WAITING, // mux machine
AD_MUX_ATTACHED, // mux machine
AD_MUX_COLLECTING_DISTRIBUTING // mux machine
} mux_states_t;
// tx machine states(43.4.15 in the 802.3ad standard)
typedef enum {
AD_TX_DUMMY,
AD_TRANSMIT // tx Machine
} tx_states_t;
// rx indication types
typedef enum {
AD_TYPE_LACPDU = 1, // type lacpdu
AD_TYPE_MARKER // type marker
} pdu_type_t;
// rx marker indication types
typedef enum {
AD_MARKER_INFORMATION_SUBTYPE = 1, // marker imformation subtype
AD_MARKER_RESPONSE_SUBTYPE // marker response subtype
} bond_marker_subtype_t;
// timers types(43.4.9 in the 802.3ad standard)
typedef enum {
AD_CURRENT_WHILE_TIMER,
AD_ACTOR_CHURN_TIMER,
AD_PERIODIC_TIMER,
AD_PARTNER_CHURN_TIMER,
AD_WAIT_WHILE_TIMER
} ad_timers_t;
#pragma pack(1)
// Link Aggregation Control Protocol(LACP) data unit structure(43.4.2.2 in the 802.3ad standard)
typedef struct lacpdu {
u8 subtype; // = LACP(= 0x01)
u8 version_number;
u8 tlv_type_actor_info; // = actor information(type/length/value)
u8 actor_information_length; // = 20
__be16 actor_system_priority;
struct mac_addr actor_system;
__be16 actor_key;
__be16 actor_port_priority;
__be16 actor_port;
u8 actor_state;
u8 reserved_3_1[3]; // = 0
u8 tlv_type_partner_info; // = partner information
u8 partner_information_length; // = 20
__be16 partner_system_priority;
struct mac_addr partner_system;
__be16 partner_key;
__be16 partner_port_priority;
__be16 partner_port;
u8 partner_state;
u8 reserved_3_2[3]; // = 0
u8 tlv_type_collector_info; // = collector information
u8 collector_information_length; // = 16
__be16 collector_max_delay;
u8 reserved_12[12];
u8 tlv_type_terminator; // = terminator
u8 terminator_length; // = 0
u8 reserved_50[50]; // = 0
} lacpdu_t;
typedef struct lacpdu_header {
struct ethhdr hdr;
struct lacpdu lacpdu;
} lacpdu_header_t;
// Marker Protocol Data Unit(PDU) structure(43.5.3.2 in the 802.3ad standard)
typedef struct bond_marker {
u8 subtype; // = 0x02 (marker PDU)
u8 version_number; // = 0x01
u8 tlv_type; // = 0x01 (marker information)
// = 0x02 (marker response information)
u8 marker_length; // = 0x16
u16 requester_port; // The number assigned to the port by the requester
struct mac_addr requester_system; // The requester's system id
u32 requester_transaction_id; // The transaction id allocated by the requester,
u16 pad; // = 0
u8 tlv_type_terminator; // = 0x00
u8 terminator_length; // = 0x00
u8 reserved_90[90]; // = 0
} bond_marker_t;
typedef struct bond_marker_header {
struct ethhdr hdr;
struct bond_marker marker;
} bond_marker_header_t;
#pragma pack()
struct slave;
struct bonding;
struct ad_info;
struct port;
#ifdef __ia64__
#pragma pack(8)
#endif
// aggregator structure(43.4.5 in the 802.3ad standard)
typedef struct aggregator {
struct mac_addr aggregator_mac_address;
u16 aggregator_identifier;
bool is_individual;
u16 actor_admin_aggregator_key;
u16 actor_oper_aggregator_key;
struct mac_addr partner_system;
u16 partner_system_priority;
u16 partner_oper_aggregator_key;
u16 receive_state; // BOOLEAN
u16 transmit_state; // BOOLEAN
struct port *lag_ports;
// ****** PRIVATE PARAMETERS ******
struct slave *slave; // pointer to the bond slave that this aggregator belongs to
u16 is_active; // BOOLEAN. Indicates if this aggregator is active
u16 num_of_ports;
} aggregator_t;
struct port_params {
struct mac_addr system;
u16 system_priority;
u16 key;
u16 port_number;
u16 port_priority;
u16 port_state;
};
// port structure(43.4.6 in the 802.3ad standard)
typedef struct port {
u16 actor_port_number;
u16 actor_port_priority;
struct mac_addr actor_system; // This parameter is added here although it is not specified in the standard, just for simplification
u16 actor_system_priority; // This parameter is added here although it is not specified in the standard, just for simplification
u16 actor_port_aggregator_identifier;
bool ntt;
u16 actor_admin_port_key;
u16 actor_oper_port_key;
u8 actor_admin_port_state;
u8 actor_oper_port_state;
struct port_params partner_admin;
struct port_params partner_oper;
bool is_enabled;
// ****** PRIVATE PARAMETERS ******
u16 sm_vars; // all state machines variables for this port
rx_states_t sm_rx_state; // state machine rx state
u16 sm_rx_timer_counter; // state machine rx timer counter
periodic_states_t sm_periodic_state;// state machine periodic state
u16 sm_periodic_timer_counter; // state machine periodic timer counter
mux_states_t sm_mux_state; // state machine mux state
u16 sm_mux_timer_counter; // state machine mux timer counter
tx_states_t sm_tx_state; // state machine tx state
u16 sm_tx_timer_counter; // state machine tx timer counter(allways on - enter to transmit state 3 time per second)
struct slave *slave; // pointer to the bond slave that this port belongs to
struct aggregator *aggregator; // pointer to an aggregator that this port related to
struct port *next_port_in_aggregator; // Next port on the linked list of the parent aggregator
u32 transaction_id; // continuous number for identification of Marker PDU's;
struct lacpdu lacpdu; // the lacpdu that will be sent for this port
} port_t;
// system structure
struct ad_system {
u16 sys_priority;
struct mac_addr sys_mac_addr;
};
#ifdef __ia64__
#pragma pack()
#endif
// ================= AD Exported structures to the main bonding code ==================
#define BOND_AD_INFO(bond) ((bond)->ad_info)
#define SLAVE_AD_INFO(slave) ((slave)->ad_info)
struct ad_bond_info {
struct ad_system system; /* 802.3ad system structure */
u32 agg_select_timer; // Timer to select aggregator after all adapter's hand shakes
u32 agg_select_mode; // Mode of selection of active aggregator(bandwidth/count)
int lacp_fast; /* whether fast periodic tx should be
* requested
*/
struct timer_list ad_timer;
struct packet_type ad_pkt_type;
};
struct ad_slave_info {
struct aggregator aggregator; // 802.3ad aggregator structure
struct port port; // 802.3ad port structure
spinlock_t rx_machine_lock; // To avoid race condition between callback and receive interrupt
u16 id;
};
// ================= AD Exported functions to the main bonding code ==================
void bond_3ad_initialize(struct bonding *bond, u16 tick_resolution, int lacp_fast);
int bond_3ad_bind_slave(struct slave *slave);
void bond_3ad_unbind_slave(struct slave *slave);
void bond_3ad_state_machine_handler(struct work_struct *);
void bond_3ad_initiate_agg_selection(struct bonding *bond, int timeout);
void bond_3ad_adapter_speed_changed(struct slave *slave);
void bond_3ad_adapter_duplex_changed(struct slave *slave);
void bond_3ad_handle_link_change(struct slave *slave, char link);
int bond_3ad_get_active_agg_info(struct bonding *bond, struct ad_info *ad_info);
int bond_3ad_xmit_xor(struct sk_buff *skb, struct net_device *dev);
int bond_3ad_lacpdu_recv(struct sk_buff *skb, struct net_device *dev, struct packet_type* ptype, struct net_device *orig_dev);
int bond_3ad_set_carrier(struct bonding *bond);
#endif //__BOND_3AD_H__

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,132 @@
/*
* Copyright(c) 1999 - 2004 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* The full GNU General Public License is included in this distribution in the
* file called LICENSE.
*
*/
#ifndef __BOND_ALB_H__
#define __BOND_ALB_H__
#include <linux/if_ether.h>
struct bonding;
struct slave;
#define BOND_ALB_INFO(bond) ((bond)->alb_info)
#define SLAVE_TLB_INFO(slave) ((slave)->tlb_info)
struct tlb_client_info {
struct slave *tx_slave; /* A pointer to slave used for transmiting
* packets to a Client that the Hash function
* gave this entry index.
*/
u32 tx_bytes; /* Each Client acumulates the BytesTx that
* were tranmitted to it, and after each
* CallBack the LoadHistory is devided
* by the balance interval
*/
u32 load_history; /* This field contains the amount of Bytes
* that were transmitted to this client by
* the server on the previous balance
* interval in Bps.
*/
u32 next; /* The next Hash table entry index, assigned
* to use the same adapter for transmit.
*/
u32 prev; /* The previous Hash table entry index,
* assigned to use the same
*/
};
/* -------------------------------------------------------------------------
* struct rlb_client_info contains all info related to a specific rx client
* connection. This is the Clients Hash Table entry struct
* -------------------------------------------------------------------------
*/
struct rlb_client_info {
__be32 ip_src; /* the server IP address */
__be32 ip_dst; /* the client IP address */
u8 mac_dst[ETH_ALEN]; /* the client MAC address */
u32 next; /* The next Hash table entry index */
u32 prev; /* The previous Hash table entry index */
u8 assigned; /* checking whether this entry is assigned */
u8 ntt; /* flag - need to transmit client info */
struct slave *slave; /* the slave assigned to this client */
u8 tag; /* flag - need to tag skb */
unsigned short vlan_id; /* VLAN tag associated with IP address */
};
struct tlb_slave_info {
u32 head; /* Index to the head of the bi-directional clients
* hash table entries list. The entries in the list
* are the entries that were assigned to use this
* slave for transmit.
*/
u32 load; /* Each slave sums the loadHistory of all clients
* assigned to it
*/
};
struct alb_bond_info {
struct timer_list alb_timer;
struct tlb_client_info *tx_hashtbl; /* Dynamically allocated */
spinlock_t tx_hashtbl_lock;
u32 unbalanced_load;
int tx_rebalance_counter;
int lp_counter;
/* -------- rlb parameters -------- */
int rlb_enabled;
struct packet_type rlb_pkt_type;
struct rlb_client_info *rx_hashtbl; /* Receive hash table */
spinlock_t rx_hashtbl_lock;
u32 rx_hashtbl_head;
u8 rx_ntt; /* flag - need to transmit
* to all rx clients
*/
struct slave *next_rx_slave;/* next slave to be assigned
* to a new rx client for
*/
u32 rlb_interval_counter;
u8 primary_is_promisc; /* boolean */
u32 rlb_promisc_timeout_counter;/* counts primary
* promiscuity time
*/
u32 rlb_update_delay_counter;
u32 rlb_update_retry_counter;/* counter of retries
* of client update
*/
u8 rlb_rebalance; /* flag - indicates that the
* rx traffic should be
* rebalanced
*/
struct vlan_entry *current_alb_vlan;
};
int bond_alb_initialize(struct bonding *bond, int rlb_enabled);
void bond_alb_deinitialize(struct bonding *bond);
int bond_alb_init_slave(struct bonding *bond, struct slave *slave);
void bond_alb_deinit_slave(struct bonding *bond, struct slave *slave);
void bond_alb_handle_link_change(struct bonding *bond, struct slave *slave, char link);
void bond_alb_handle_active_change(struct bonding *bond, struct slave *new_slave);
int bond_alb_xmit(struct sk_buff *skb, struct net_device *bond_dev);
void bond_alb_monitor(struct work_struct *);
int bond_alb_set_mac_address(struct net_device *bond_dev, void *addr);
void bond_alb_clear_vlan(struct bonding *bond, unsigned short vlan_id);
#endif /* __BOND_ALB_H__ */

View File

@@ -0,0 +1,223 @@
/*
* Copyright(c) 2008 Hewlett-Packard Development Company, L.P.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* The full GNU General Public License is included in this distribution in the
* file called LICENSE.
*
*/
#include <linux/types.h>
#include <linux/if_vlan.h>
#include <net/ipv6.h>
#include <net/ndisc.h>
#include <net/addrconf.h>
#include "bonding.h"
/*
* Assign bond->master_ipv6 to the next IPv6 address in the list, or
* zero it out if there are none.
*/
static void bond_glean_dev_ipv6(struct net_device *dev, struct in6_addr *addr)
{
struct inet6_dev *idev;
struct inet6_ifaddr *ifa;
if (!dev)
return;
idev = in6_dev_get(dev);
if (!idev)
return;
read_lock_bh(&idev->lock);
ifa = idev->addr_list;
if (ifa)
ipv6_addr_copy(addr, &ifa->addr);
else
ipv6_addr_set(addr, 0, 0, 0, 0);
read_unlock_bh(&idev->lock);
in6_dev_put(idev);
}
static void bond_na_send(struct net_device *slave_dev,
struct in6_addr *daddr,
int router,
unsigned short vlan_id)
{
struct in6_addr mcaddr;
struct icmp6hdr icmp6h = {
.icmp6_type = NDISC_NEIGHBOUR_ADVERTISEMENT,
};
struct sk_buff *skb;
/* The Ethernet header is built in ndisc_send_skb(), not
* ndisc_build_skb(), so we cannot insert a VLAN tag. Only an
* out-of-line tag inserted by the hardware will work.
*/
if (vlan_id && !(slave_dev->features & NETIF_F_HW_VLAN_TX))
return;
icmp6h.icmp6_router = router;
icmp6h.icmp6_solicited = 0;
icmp6h.icmp6_override = 1;
addrconf_addr_solict_mult(daddr, &mcaddr);
pr_debug("ipv6 na on slave %s: dest %pI6, src %pI6\n",
slave_dev->name, &mcaddr, daddr);
skb = ndisc_build_skb(slave_dev, &mcaddr, daddr, &icmp6h, daddr,
ND_OPT_TARGET_LL_ADDR);
if (!skb) {
pr_err(DRV_NAME ": NA packet allocation failed\n");
return;
}
if (vlan_id) {
skb = __vlan_hwaccel_put_tag(skb, vlan_id);
if (!skb) {
pr_err(DRV_NAME ": failed to insert VLAN tag\n");
return;
}
}
ndisc_send_skb(skb, slave_dev, NULL, &mcaddr, daddr, &icmp6h);
}
/*
* Kick out an unsolicited Neighbor Advertisement for an IPv6 address on
* the bonding master. This will help the switch learn our address
* if in active-backup mode.
*
* Caller must hold curr_slave_lock for read or better
*/
void bond_send_unsolicited_na(struct bonding *bond)
{
struct slave *slave = bond->curr_active_slave;
struct vlan_entry *vlan;
struct inet6_dev *idev;
int is_router;
pr_debug("bond_send_unsol_na: bond %s slave %s\n", bond->dev->name,
slave ? slave->dev->name : "NULL");
if (!slave || !bond->send_unsol_na ||
test_bit(__LINK_STATE_LINKWATCH_PENDING, &slave->dev->state))
return;
bond->send_unsol_na--;
idev = in6_dev_get(bond->dev);
if (!idev)
return;
is_router = !!idev->cnf.forwarding;
in6_dev_put(idev);
if (!ipv6_addr_any(&bond->master_ipv6))
bond_na_send(slave->dev, &bond->master_ipv6, is_router, 0);
list_for_each_entry(vlan, &bond->vlan_list, vlan_list) {
if (!ipv6_addr_any(&vlan->vlan_ipv6)) {
bond_na_send(slave->dev, &vlan->vlan_ipv6, is_router,
vlan->vlan_id);
}
}
}
/*
* bond_inet6addr_event: handle inet6addr notifier chain events.
*
* We keep track of device IPv6 addresses primarily to use as source
* addresses in NS probes.
*
* We track one IPv6 for the main device (if it has one).
*/
static int bond_inet6addr_event(struct notifier_block *this,
unsigned long event,
void *ptr)
{
struct inet6_ifaddr *ifa = ptr;
struct net_device *vlan_dev, *event_dev = ifa->idev->dev;
struct bonding *bond;
struct vlan_entry *vlan;
if (dev_net(event_dev) != &init_net)
return NOTIFY_DONE;
list_for_each_entry(bond, &bond_dev_list, bond_list) {
if (bond->dev == event_dev) {
switch (event) {
case NETDEV_UP:
if (ipv6_addr_any(&bond->master_ipv6))
ipv6_addr_copy(&bond->master_ipv6,
&ifa->addr);
return NOTIFY_OK;
case NETDEV_DOWN:
if (ipv6_addr_equal(&bond->master_ipv6,
&ifa->addr))
bond_glean_dev_ipv6(bond->dev,
&bond->master_ipv6);
return NOTIFY_OK;
default:
return NOTIFY_DONE;
}
}
list_for_each_entry(vlan, &bond->vlan_list, vlan_list) {
vlan_dev = vlan_group_get_device(bond->vlgrp,
vlan->vlan_id);
if (vlan_dev == event_dev) {
switch (event) {
case NETDEV_UP:
if (ipv6_addr_any(&vlan->vlan_ipv6))
ipv6_addr_copy(&vlan->vlan_ipv6,
&ifa->addr);
return NOTIFY_OK;
case NETDEV_DOWN:
if (ipv6_addr_equal(&vlan->vlan_ipv6,
&ifa->addr))
bond_glean_dev_ipv6(vlan_dev,
&vlan->vlan_ipv6);
return NOTIFY_OK;
default:
return NOTIFY_DONE;
}
}
}
}
return NOTIFY_DONE;
}
static struct notifier_block bond_inet6addr_notifier = {
.notifier_call = bond_inet6addr_event,
};
void bond_register_ipv6_notifier(void)
{
register_inet6addr_notifier(&bond_inet6addr_notifier);
}
void bond_unregister_ipv6_notifier(void)
{
unregister_inet6addr_notifier(&bond_inet6addr_notifier);
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,373 @@
/*
* Bond several ethernet interfaces into a Cisco, running 'Etherchannel'.
*
* Portions are (c) Copyright 1995 Simon "Guru Aleph-Null" Janes
* NCM: Network and Communications Management, Inc.
*
* BUT, I'm the one who modified it for ethernet, so:
* (c) Copyright 1999, Thomas Davis, tadavis@lbl.gov
*
* This software may be used and distributed according to the terms
* of the GNU Public License, incorporated herein by reference.
*
*/
#ifndef _LINUX_BONDING_H
#define _LINUX_BONDING_H
#include <linux/timer.h>
#include <linux/proc_fs.h>
#include <linux/if_bonding.h>
#include <linux/kobject.h>
#include <linux/in6.h>
#include "bond_3ad.h"
#include "bond_alb.h"
#define DRV_VERSION "3.5.0"
#define DRV_RELDATE "November 4, 2008"
#define DRV_NAME "bonding"
#define DRV_DESCRIPTION "Ethernet Channel Bonding Driver"
#define BOND_MAX_ARP_TARGETS 16
extern struct list_head bond_dev_list;
#define IS_UP(dev) \
((((dev)->flags & IFF_UP) == IFF_UP) && \
netif_running(dev) && \
netif_carrier_ok(dev))
/*
* Checks whether bond is ready for transmit.
*
* Caller must hold bond->lock
*/
#define BOND_IS_OK(bond) \
(((bond)->dev->flags & IFF_UP) && \
netif_running((bond)->dev) && \
((bond)->slave_cnt > 0))
/*
* Checks whether slave is ready for transmit.
*/
#define SLAVE_IS_OK(slave) \
(((slave)->dev->flags & IFF_UP) && \
netif_running((slave)->dev) && \
((slave)->link == BOND_LINK_UP) && \
((slave)->state == BOND_STATE_ACTIVE))
#define USES_PRIMARY(mode) \
(((mode) == BOND_MODE_ACTIVEBACKUP) || \
((mode) == BOND_MODE_TLB) || \
((mode) == BOND_MODE_ALB))
/*
* Less bad way to call ioctl from within the kernel; this needs to be
* done some other way to get the call out of interrupt context.
* Needs "ioctl" variable to be supplied by calling context.
*/
#define IOCTL(dev, arg, cmd) ({ \
int res = 0; \
mm_segment_t fs = get_fs(); \
set_fs(get_ds()); \
res = ioctl(dev, arg, cmd); \
set_fs(fs); \
res; })
/**
* bond_for_each_slave_from - iterate the slaves list from a starting point
* @bond: the bond holding this list.
* @pos: current slave.
* @cnt: counter for max number of moves
* @start: starting point.
*
* Caller must hold bond->lock
*/
#define bond_for_each_slave_from(bond, pos, cnt, start) \
for (cnt = 0, pos = start; \
cnt < (bond)->slave_cnt; \
cnt++, pos = (pos)->next)
/**
* bond_for_each_slave_from_to - iterate the slaves list from start point to stop point
* @bond: the bond holding this list.
* @pos: current slave.
* @cnt: counter for number max of moves
* @start: start point.
* @stop: stop point.
*
* Caller must hold bond->lock
*/
#define bond_for_each_slave_from_to(bond, pos, cnt, start, stop) \
for (cnt = 0, pos = start; \
((cnt < (bond)->slave_cnt) && (pos != (stop)->next)); \
cnt++, pos = (pos)->next)
/**
* bond_for_each_slave - iterate the slaves list from head
* @bond: the bond holding this list.
* @pos: current slave.
* @cnt: counter for max number of moves
*
* Caller must hold bond->lock
*/
#define bond_for_each_slave(bond, pos, cnt) \
bond_for_each_slave_from(bond, pos, cnt, (bond)->first_slave)
struct bond_params {
int mode;
int xmit_policy;
int miimon;
int num_grat_arp;
int num_unsol_na;
int arp_interval;
int arp_validate;
int use_carrier;
int fail_over_mac;
int updelay;
int downdelay;
int lacp_fast;
int ad_select;
char primary[IFNAMSIZ];
__be32 arp_targets[BOND_MAX_ARP_TARGETS];
};
struct bond_parm_tbl {
char *modename;
int mode;
};
#define BOND_MAX_MODENAME_LEN 20
struct vlan_entry {
struct list_head vlan_list;
__be32 vlan_ip;
unsigned short vlan_id;
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
struct in6_addr vlan_ipv6;
#endif
};
struct slave {
struct net_device *dev; /* first - useful for panic debug */
struct slave *next;
struct slave *prev;
int delay;
unsigned long jiffies;
unsigned long last_arp_rx;
s8 link; /* one of BOND_LINK_XXXX */
s8 new_link;
s8 state; /* one of BOND_STATE_XXXX */
u32 original_flags;
u32 original_mtu;
u32 link_failure_count;
u8 perm_hwaddr[ETH_ALEN];
u16 speed;
u8 duplex;
struct ad_slave_info ad_info; /* HUGE - better to dynamically alloc */
struct tlb_slave_info tlb_info;
};
/*
* Link pseudo-state only used internally by monitors
*/
#define BOND_LINK_NOCHANGE -1
/*
* Here are the locking policies for the two bonding locks:
*
* 1) Get bond->lock when reading/writing slave list.
* 2) Get bond->curr_slave_lock when reading/writing bond->curr_active_slave.
* (It is unnecessary when the write-lock is put with bond->lock.)
* 3) When we lock with bond->curr_slave_lock, we must lock with bond->lock
* beforehand.
*/
struct bonding {
struct net_device *dev; /* first - useful for panic debug */
struct slave *first_slave;
struct slave *curr_active_slave;
struct slave *current_arp_slave;
struct slave *primary_slave;
s32 slave_cnt; /* never change this value outside the attach/detach wrappers */
rwlock_t lock;
rwlock_t curr_slave_lock;
s8 kill_timers;
s8 send_grat_arp;
s8 send_unsol_na;
s8 setup_by_slave;
struct net_device_stats stats;
#ifdef CONFIG_PROC_FS
struct proc_dir_entry *proc_entry;
char proc_file_name[IFNAMSIZ];
#endif /* CONFIG_PROC_FS */
struct list_head bond_list;
struct dev_mc_list *mc_list;
int (*xmit_hash_policy)(struct sk_buff *, struct net_device *, int);
__be32 master_ip;
u16 flags;
u16 rr_tx_counter;
struct ad_bond_info ad_info;
struct alb_bond_info alb_info;
struct bond_params params;
struct list_head vlan_list;
struct vlan_group *vlgrp;
struct packet_type arp_mon_pt;
struct workqueue_struct *wq;
struct delayed_work mii_work;
struct delayed_work arp_work;
struct delayed_work alb_work;
struct delayed_work ad_work;
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
struct in6_addr master_ipv6;
#endif
};
/**
* Returns NULL if the net_device does not belong to any of the bond's slaves
*
* Caller must hold bond lock for read
*/
static inline struct slave *bond_get_slave_by_dev(struct bonding *bond, struct net_device *slave_dev)
{
struct slave *slave = NULL;
int i;
bond_for_each_slave(bond, slave, i) {
if (slave->dev == slave_dev) {
break;
}
}
return slave;
}
static inline struct bonding *bond_get_bond_by_slave(struct slave *slave)
{
if (!slave || !slave->dev->master) {
return NULL;
}
return (struct bonding *)netdev_priv(slave->dev->master);
}
static inline bool bond_is_lb(const struct bonding *bond)
{
return bond->params.mode == BOND_MODE_TLB
|| bond->params.mode == BOND_MODE_ALB;
}
#define BOND_FOM_NONE 0
#define BOND_FOM_ACTIVE 1
#define BOND_FOM_FOLLOW 2
#define BOND_ARP_VALIDATE_NONE 0
#define BOND_ARP_VALIDATE_ACTIVE (1 << BOND_STATE_ACTIVE)
#define BOND_ARP_VALIDATE_BACKUP (1 << BOND_STATE_BACKUP)
#define BOND_ARP_VALIDATE_ALL (BOND_ARP_VALIDATE_ACTIVE | \
BOND_ARP_VALIDATE_BACKUP)
static inline int slave_do_arp_validate(struct bonding *bond,
struct slave *slave)
{
return bond->params.arp_validate & (1 << slave->state);
}
static inline unsigned long slave_last_rx(struct bonding *bond,
struct slave *slave)
{
if (slave_do_arp_validate(bond, slave))
return slave->last_arp_rx;
return slave->dev->last_rx;
}
static inline void bond_set_slave_inactive_flags(struct slave *slave)
{
struct bonding *bond = netdev_priv(slave->dev->master);
if (!bond_is_lb(bond))
slave->state = BOND_STATE_BACKUP;
slave->dev->priv_flags |= IFF_SLAVE_INACTIVE;
if (slave_do_arp_validate(bond, slave))
slave->dev->priv_flags |= IFF_SLAVE_NEEDARP;
}
static inline void bond_set_slave_active_flags(struct slave *slave)
{
slave->state = BOND_STATE_ACTIVE;
slave->dev->priv_flags &= ~(IFF_SLAVE_INACTIVE | IFF_SLAVE_NEEDARP);
}
static inline void bond_set_master_3ad_flags(struct bonding *bond)
{
bond->dev->priv_flags |= IFF_MASTER_8023AD;
}
static inline void bond_unset_master_3ad_flags(struct bonding *bond)
{
bond->dev->priv_flags &= ~IFF_MASTER_8023AD;
}
static inline void bond_set_master_alb_flags(struct bonding *bond)
{
bond->dev->priv_flags |= IFF_MASTER_ALB;
}
static inline void bond_unset_master_alb_flags(struct bonding *bond)
{
bond->dev->priv_flags &= ~IFF_MASTER_ALB;
}
struct vlan_entry *bond_next_vlan(struct bonding *bond, struct vlan_entry *curr);
int bond_dev_queue_xmit(struct bonding *bond, struct sk_buff *skb, struct net_device *slave_dev);
int bond_create(const char *name);
int bond_release_and_destroy(struct net_device *bond_dev, struct net_device *slave_dev);
int bond_create_sysfs(void);
void bond_destroy_sysfs(void);
void bond_destroy_sysfs_entry(struct bonding *bond);
int bond_create_sysfs_entry(struct bonding *bond);
int bond_create_slave_symlinks(struct net_device *master, struct net_device *slave);
void bond_destroy_slave_symlinks(struct net_device *master, struct net_device *slave);
int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev);
int bond_release(struct net_device *bond_dev, struct net_device *slave_dev);
void bond_mii_monitor(struct work_struct *);
void bond_loadbalance_arp_mon(struct work_struct *);
void bond_activebackup_arp_mon(struct work_struct *);
void bond_set_mode_ops(struct bonding *bond, int mode);
int bond_parse_parm(const char *mode_arg, const struct bond_parm_tbl *tbl);
void bond_select_active_slave(struct bonding *bond);
void bond_change_active_slave(struct bonding *bond, struct slave *new_active);
void bond_register_arp(struct bonding *);
void bond_unregister_arp(struct bonding *);
/* exported from bond_main.c */
extern struct list_head bond_dev_list;
extern const struct bond_parm_tbl bond_lacp_tbl[];
extern const struct bond_parm_tbl bond_mode_tbl[];
extern const struct bond_parm_tbl xmit_hashtype_tbl[];
extern const struct bond_parm_tbl arp_validate_tbl[];
extern const struct bond_parm_tbl fail_over_mac_tbl[];
extern struct bond_parm_tbl ad_select_tbl[];
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
void bond_send_unsolicited_na(struct bonding *bond);
void bond_register_ipv6_notifier(void);
void bond_unregister_ipv6_notifier(void);
#else
static inline void bond_send_unsolicited_na(struct bonding *bond)
{
return;
}
static inline void bond_register_ipv6_notifier(void)
{
return;
}
static inline void bond_unregister_ipv6_notifier(void)
{
return;
}
#endif
#endif /* _LINUX_BONDING_H */