Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 341692
b: refs/heads/master
c: abe303d
h: refs/heads/master
v: v3
  • Loading branch information
David S. Miller committed Dec 1, 2012
1 parent b24e949 commit cbc9ac7
Show file tree
Hide file tree
Showing 78 changed files with 2,565 additions and 1,815 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: b9cc977d9d4d1866ee83df38815f4b3b34d99dd9
refs/heads/master: abe303dbc22bd16cde6f1a62fc25f63cc254caf7
3 changes: 1 addition & 2 deletions trunk/MAINTAINERS
Original file line number Diff line number Diff line change
Expand Up @@ -7454,8 +7454,7 @@ S: Maintained
F: drivers/net/ethernet/dec/tulip/

TUN/TAP driver
M: Maxim Krasnyansky <maxk@qualcomm.com>
L: vtun@office.satix.net
M: Maxim Krasnyansky <maxk@qti.qualcomm.com>
W: http://vtun.sourceforge.net/tun
S: Maintained
F: Documentation/networking/tuntap.txt
Expand Down
20 changes: 10 additions & 10 deletions trunk/drivers/isdn/mISDN/tei.c
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ tei_debug(struct FsmInst *fi, char *fmt, ...)
static int
get_free_id(struct manager *mgr)
{
u64 ids = 0;
DECLARE_BITMAP(ids, 64) = { [0 ... BITS_TO_LONGS(64) - 1] = 0 };
int i;
struct layer2 *l2;

Expand All @@ -261,11 +261,11 @@ get_free_id(struct manager *mgr)
__func__);
return -EBUSY;
}
test_and_set_bit(l2->ch.nr, (u_long *)&ids);
__set_bit(l2->ch.nr, ids);
}
for (i = 1; i < 64; i++)
if (!test_bit(i, (u_long *)&ids))
return i;
i = find_next_zero_bit(ids, 64, 1);
if (i < 64)
return i;
printk(KERN_WARNING "%s: more as 63 layer2 for one device\n",
__func__);
return -EBUSY;
Expand All @@ -274,7 +274,7 @@ get_free_id(struct manager *mgr)
static int
get_free_tei(struct manager *mgr)
{
u64 ids = 0;
DECLARE_BITMAP(ids, 64) = { [0 ... BITS_TO_LONGS(64) - 1] = 0 };
int i;
struct layer2 *l2;

Expand All @@ -288,11 +288,11 @@ get_free_tei(struct manager *mgr)
continue;
i -= 64;

test_and_set_bit(i, (u_long *)&ids);
__set_bit(i, ids);
}
for (i = 0; i < 64; i++)
if (!test_bit(i, (u_long *)&ids))
return i + 64;
i = find_first_zero_bit(ids, 64);
if (i < 64)
return i + 64;
printk(KERN_WARNING "%s: more as 63 dynamic tei for one device\n",
__func__);
return -1;
Expand Down
197 changes: 163 additions & 34 deletions trunk/drivers/net/bonding/bond_alb.c
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,10 @@ static inline struct arp_pkt *arp_pkt(const struct sk_buff *skb)

/* Forward declaration */
static void alb_send_learning_packets(struct slave *slave, u8 mac_addr[]);
static void rlb_purge_src_ip(struct bonding *bond, struct arp_pkt *arp);
static void rlb_src_unlink(struct bonding *bond, u32 index);
static void rlb_src_link(struct bonding *bond, u32 ip_src_hash,
u32 ip_dst_hash);

static inline u8 _simple_hash(const u8 *hash_start, int hash_size)
{
Expand Down Expand Up @@ -354,6 +358,18 @@ static int rlb_arp_recv(const struct sk_buff *skb, struct bonding *bond,
if (!arp)
goto out;

/* We received an ARP from arp->ip_src.
* We might have used this IP address previously (on the bonding host
* itself or on a system that is bridged together with the bond).
* However, if arp->mac_src is different than what is stored in
* rx_hashtbl, some other host is now using the IP and we must prevent
* sending out client updates with this IP address and the old MAC
* address.
* Clean up all hash table entries that have this address as ip_src but
* have a different mac_src.
*/
rlb_purge_src_ip(bond, arp);

if (arp->op_code == htons(ARPOP_REPLY)) {
/* update rx hash table for this ARP */
rlb_update_entry_from_arp(bond, arp);
Expand Down Expand Up @@ -432,9 +448,9 @@ static void rlb_clear_slave(struct bonding *bond, struct slave *slave)
_lock_rx_hashtbl_bh(bond);

rx_hash_table = bond_info->rx_hashtbl;
index = bond_info->rx_hashtbl_head;
index = bond_info->rx_hashtbl_used_head;
for (; index != RLB_NULL_INDEX; index = next_index) {
next_index = rx_hash_table[index].next;
next_index = rx_hash_table[index].used_next;
if (rx_hash_table[index].slave == slave) {
struct slave *assigned_slave = rlb_next_rx_slave(bond);

Expand Down Expand Up @@ -519,8 +535,9 @@ static void rlb_update_rx_clients(struct bonding *bond)

_lock_rx_hashtbl_bh(bond);

hash_index = bond_info->rx_hashtbl_head;
for (; hash_index != RLB_NULL_INDEX; hash_index = client_info->next) {
hash_index = bond_info->rx_hashtbl_used_head;
for (; hash_index != RLB_NULL_INDEX;
hash_index = client_info->used_next) {
client_info = &(bond_info->rx_hashtbl[hash_index]);
if (client_info->ntt) {
rlb_update_client(client_info);
Expand Down Expand Up @@ -548,8 +565,9 @@ static void rlb_req_update_slave_clients(struct bonding *bond, struct slave *sla

_lock_rx_hashtbl_bh(bond);

hash_index = bond_info->rx_hashtbl_head;
for (; hash_index != RLB_NULL_INDEX; hash_index = client_info->next) {
hash_index = bond_info->rx_hashtbl_used_head;
for (; hash_index != RLB_NULL_INDEX;
hash_index = client_info->used_next) {
client_info = &(bond_info->rx_hashtbl[hash_index]);

if ((client_info->slave == slave) &&
Expand Down Expand Up @@ -578,8 +596,9 @@ static void rlb_req_update_subnet_clients(struct bonding *bond, __be32 src_ip)

_lock_rx_hashtbl(bond);

hash_index = bond_info->rx_hashtbl_head;
for (; hash_index != RLB_NULL_INDEX; hash_index = client_info->next) {
hash_index = bond_info->rx_hashtbl_used_head;
for (; hash_index != RLB_NULL_INDEX;
hash_index = client_info->used_next) {
client_info = &(bond_info->rx_hashtbl[hash_index]);

if (!client_info->slave) {
Expand Down Expand Up @@ -625,6 +644,7 @@ static struct slave *rlb_choose_channel(struct sk_buff *skb, struct bonding *bon
/* update mac address from arp */
memcpy(client_info->mac_dst, arp->mac_dst, ETH_ALEN);
}
memcpy(client_info->mac_src, arp->mac_src, ETH_ALEN);

assigned_slave = client_info->slave;
if (assigned_slave) {
Expand All @@ -647,13 +667,25 @@ static struct slave *rlb_choose_channel(struct sk_buff *skb, struct bonding *bon
assigned_slave = rlb_next_rx_slave(bond);

if (assigned_slave) {
if (!(client_info->assigned &&
client_info->ip_src == arp->ip_src)) {
/* ip_src is going to be updated,
* fix the src hash list
*/
u32 hash_src = _simple_hash((u8 *)&arp->ip_src,
sizeof(arp->ip_src));
rlb_src_unlink(bond, hash_index);
rlb_src_link(bond, hash_src, hash_index);
}

client_info->ip_src = arp->ip_src;
client_info->ip_dst = arp->ip_dst;
/* arp->mac_dst is broadcast for arp reqeusts.
* will be updated with clients actual unicast mac address
* upon receiving an arp reply.
*/
memcpy(client_info->mac_dst, arp->mac_dst, ETH_ALEN);
memcpy(client_info->mac_src, arp->mac_src, ETH_ALEN);
client_info->slave = assigned_slave;

if (!ether_addr_equal_64bits(client_info->mac_dst, mac_bcast)) {
Expand All @@ -669,11 +701,11 @@ static struct slave *rlb_choose_channel(struct sk_buff *skb, struct bonding *bon
}

if (!client_info->assigned) {
u32 prev_tbl_head = bond_info->rx_hashtbl_head;
bond_info->rx_hashtbl_head = hash_index;
client_info->next = prev_tbl_head;
u32 prev_tbl_head = bond_info->rx_hashtbl_used_head;
bond_info->rx_hashtbl_used_head = hash_index;
client_info->used_next = prev_tbl_head;
if (prev_tbl_head != RLB_NULL_INDEX) {
bond_info->rx_hashtbl[prev_tbl_head].prev =
bond_info->rx_hashtbl[prev_tbl_head].used_prev =
hash_index;
}
client_info->assigned = 1;
Expand All @@ -694,6 +726,12 @@ static struct slave *rlb_arp_xmit(struct sk_buff *skb, struct bonding *bond)
struct arp_pkt *arp = arp_pkt(skb);
struct slave *tx_slave = NULL;

/* Don't modify or load balance ARPs that do not originate locally
* (e.g.,arrive via a bridge).
*/
if (!bond_slave_has_mac(bond, arp->mac_src))
return NULL;

if (arp->op_code == htons(ARPOP_REPLY)) {
/* the arp must be sent on the selected
* rx channel
Expand Down Expand Up @@ -740,8 +778,9 @@ static void rlb_rebalance(struct bonding *bond)
_lock_rx_hashtbl_bh(bond);

ntt = 0;
hash_index = bond_info->rx_hashtbl_head;
for (; hash_index != RLB_NULL_INDEX; hash_index = client_info->next) {
hash_index = bond_info->rx_hashtbl_used_head;
for (; hash_index != RLB_NULL_INDEX;
hash_index = client_info->used_next) {
client_info = &(bond_info->rx_hashtbl[hash_index]);
assigned_slave = rlb_next_rx_slave(bond);
if (assigned_slave && (client_info->slave != assigned_slave)) {
Expand All @@ -759,11 +798,113 @@ static void rlb_rebalance(struct bonding *bond)
}

/* Caller must hold rx_hashtbl lock */
static void rlb_init_table_entry_dst(struct rlb_client_info *entry)
{
entry->used_next = RLB_NULL_INDEX;
entry->used_prev = RLB_NULL_INDEX;
entry->assigned = 0;
entry->slave = NULL;
entry->tag = 0;
}
static void rlb_init_table_entry_src(struct rlb_client_info *entry)
{
entry->src_first = RLB_NULL_INDEX;
entry->src_prev = RLB_NULL_INDEX;
entry->src_next = RLB_NULL_INDEX;
}

static void rlb_init_table_entry(struct rlb_client_info *entry)
{
memset(entry, 0, sizeof(struct rlb_client_info));
entry->next = RLB_NULL_INDEX;
entry->prev = RLB_NULL_INDEX;
rlb_init_table_entry_dst(entry);
rlb_init_table_entry_src(entry);
}

static void rlb_delete_table_entry_dst(struct bonding *bond, u32 index)
{
struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
u32 next_index = bond_info->rx_hashtbl[index].used_next;
u32 prev_index = bond_info->rx_hashtbl[index].used_prev;

if (index == bond_info->rx_hashtbl_used_head)
bond_info->rx_hashtbl_used_head = next_index;
if (prev_index != RLB_NULL_INDEX)
bond_info->rx_hashtbl[prev_index].used_next = next_index;
if (next_index != RLB_NULL_INDEX)
bond_info->rx_hashtbl[next_index].used_prev = prev_index;
}

/* unlink a rlb hash table entry from the src list */
static void rlb_src_unlink(struct bonding *bond, u32 index)
{
struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
u32 next_index = bond_info->rx_hashtbl[index].src_next;
u32 prev_index = bond_info->rx_hashtbl[index].src_prev;

bond_info->rx_hashtbl[index].src_next = RLB_NULL_INDEX;
bond_info->rx_hashtbl[index].src_prev = RLB_NULL_INDEX;

if (next_index != RLB_NULL_INDEX)
bond_info->rx_hashtbl[next_index].src_prev = prev_index;

if (prev_index == RLB_NULL_INDEX)
return;

/* is prev_index pointing to the head of this list? */
if (bond_info->rx_hashtbl[prev_index].src_first == index)
bond_info->rx_hashtbl[prev_index].src_first = next_index;
else
bond_info->rx_hashtbl[prev_index].src_next = next_index;

}

static void rlb_delete_table_entry(struct bonding *bond, u32 index)
{
struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
struct rlb_client_info *entry = &(bond_info->rx_hashtbl[index]);

rlb_delete_table_entry_dst(bond, index);
rlb_init_table_entry_dst(entry);

rlb_src_unlink(bond, index);
}

/* add the rx_hashtbl[ip_dst_hash] entry to the list
* of entries with identical ip_src_hash
*/
static void rlb_src_link(struct bonding *bond, u32 ip_src_hash, u32 ip_dst_hash)
{
struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
u32 next;

bond_info->rx_hashtbl[ip_dst_hash].src_prev = ip_src_hash;
next = bond_info->rx_hashtbl[ip_src_hash].src_first;
bond_info->rx_hashtbl[ip_dst_hash].src_next = next;
if (next != RLB_NULL_INDEX)
bond_info->rx_hashtbl[next].src_prev = ip_dst_hash;
bond_info->rx_hashtbl[ip_src_hash].src_first = ip_dst_hash;
}

/* deletes all rx_hashtbl entries with arp->ip_src if their mac_src does
* not match arp->mac_src */
static void rlb_purge_src_ip(struct bonding *bond, struct arp_pkt *arp)
{
struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
u32 ip_src_hash = _simple_hash((u8*)&(arp->ip_src), sizeof(arp->ip_src));
u32 index;

_lock_rx_hashtbl_bh(bond);

index = bond_info->rx_hashtbl[ip_src_hash].src_first;
while (index != RLB_NULL_INDEX) {
struct rlb_client_info *entry = &(bond_info->rx_hashtbl[index]);
u32 next_index = entry->src_next;
if (entry->ip_src == arp->ip_src &&
!ether_addr_equal_64bits(arp->mac_src, entry->mac_src))
rlb_delete_table_entry(bond, index);
index = next_index;
}
_unlock_rx_hashtbl_bh(bond);
}

static int rlb_initialize(struct bonding *bond)
Expand All @@ -781,7 +922,7 @@ static int rlb_initialize(struct bonding *bond)

bond_info->rx_hashtbl = new_hashtbl;

bond_info->rx_hashtbl_head = RLB_NULL_INDEX;
bond_info->rx_hashtbl_used_head = RLB_NULL_INDEX;

for (i = 0; i < RLB_HASH_TABLE_SIZE; i++) {
rlb_init_table_entry(bond_info->rx_hashtbl + i);
Expand All @@ -803,7 +944,7 @@ static void rlb_deinitialize(struct bonding *bond)

kfree(bond_info->rx_hashtbl);
bond_info->rx_hashtbl = NULL;
bond_info->rx_hashtbl_head = RLB_NULL_INDEX;
bond_info->rx_hashtbl_used_head = RLB_NULL_INDEX;

_unlock_rx_hashtbl_bh(bond);
}
Expand All @@ -815,25 +956,13 @@ static void rlb_clear_vlan(struct bonding *bond, unsigned short vlan_id)

_lock_rx_hashtbl_bh(bond);

curr_index = bond_info->rx_hashtbl_head;
curr_index = bond_info->rx_hashtbl_used_head;
while (curr_index != RLB_NULL_INDEX) {
struct rlb_client_info *curr = &(bond_info->rx_hashtbl[curr_index]);
u32 next_index = bond_info->rx_hashtbl[curr_index].next;
u32 prev_index = bond_info->rx_hashtbl[curr_index].prev;

if (curr->tag && (curr->vlan_id == vlan_id)) {
if (curr_index == bond_info->rx_hashtbl_head) {
bond_info->rx_hashtbl_head = next_index;
}
if (prev_index != RLB_NULL_INDEX) {
bond_info->rx_hashtbl[prev_index].next = next_index;
}
if (next_index != RLB_NULL_INDEX) {
bond_info->rx_hashtbl[next_index].prev = prev_index;
}
u32 next_index = bond_info->rx_hashtbl[curr_index].used_next;

rlb_init_table_entry(curr);
}
if (curr->tag && (curr->vlan_id == vlan_id))
rlb_delete_table_entry(bond, curr_index);

curr_index = next_index;
}
Expand Down
Loading

0 comments on commit cbc9ac7

Please sign in to comment.