[ATM]: [lec] convert lec_arp_table to hlist
Signed-off-by: Chas Williams <chas@cmf.nrl.navy.mil> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
1c9d3e72a7
commit
d0732f649f
442
net/atm/lec.c
442
net/atm/lec.c
|
@ -806,7 +806,7 @@ static void lec_push(struct atm_vcc *vcc, struct sk_buff *skb)
|
||||||
dev_kfree_skb(skb);
|
dev_kfree_skb(skb);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (priv->lec_arp_empty_ones) {
|
if (!hlist_empty(&priv->lec_arp_empty_ones)) {
|
||||||
lec_arp_check_empties(priv, vcc, skb);
|
lec_arp_check_empties(priv, vcc, skb);
|
||||||
}
|
}
|
||||||
skb->dev = dev;
|
skb->dev = dev;
|
||||||
|
@ -998,29 +998,32 @@ static void lec_info(struct seq_file *seq, struct lec_arp_table *entry)
|
||||||
struct lec_state {
|
struct lec_state {
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
struct lec_priv *locked;
|
struct lec_priv *locked;
|
||||||
struct lec_arp_table *entry;
|
struct hlist_node *node;
|
||||||
struct net_device *dev;
|
struct net_device *dev;
|
||||||
int itf;
|
int itf;
|
||||||
int arp_table;
|
int arp_table;
|
||||||
int misc_table;
|
int misc_table;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void *lec_tbl_walk(struct lec_state *state, struct lec_arp_table *tbl,
|
static void *lec_tbl_walk(struct lec_state *state, struct hlist_head *tbl,
|
||||||
loff_t *l)
|
loff_t *l)
|
||||||
{
|
{
|
||||||
struct lec_arp_table *e = state->entry;
|
struct hlist_node *e = state->node;
|
||||||
|
struct lec_arp_table *tmp;
|
||||||
|
|
||||||
if (!e)
|
if (!e)
|
||||||
e = tbl;
|
e = tbl->first;
|
||||||
if (e == (void *)1) {
|
if (e == (void *)1) {
|
||||||
e = tbl;
|
e = tbl->first;
|
||||||
--*l;
|
--*l;
|
||||||
}
|
}
|
||||||
for (; e; e = e->next) {
|
|
||||||
|
hlist_for_each_entry_from(tmp, e, next) {
|
||||||
if (--*l < 0)
|
if (--*l < 0)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
state->entry = e;
|
state->node = e;
|
||||||
|
|
||||||
return (*l < 0) ? state : NULL;
|
return (*l < 0) ? state : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1031,7 +1034,7 @@ static void *lec_arp_walk(struct lec_state *state, loff_t *l,
|
||||||
int p;
|
int p;
|
||||||
|
|
||||||
for (p = state->arp_table; p < LEC_ARP_TABLE_SIZE; p++) {
|
for (p = state->arp_table; p < LEC_ARP_TABLE_SIZE; p++) {
|
||||||
v = lec_tbl_walk(state, priv->lec_arp_tables[p], l);
|
v = lec_tbl_walk(state, &priv->lec_arp_tables[p], l);
|
||||||
if (v)
|
if (v)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1042,10 +1045,10 @@ static void *lec_arp_walk(struct lec_state *state, loff_t *l,
|
||||||
static void *lec_misc_walk(struct lec_state *state, loff_t *l,
|
static void *lec_misc_walk(struct lec_state *state, loff_t *l,
|
||||||
struct lec_priv *priv)
|
struct lec_priv *priv)
|
||||||
{
|
{
|
||||||
struct lec_arp_table *lec_misc_tables[] = {
|
struct hlist_head *lec_misc_tables[] = {
|
||||||
priv->lec_arp_empty_ones,
|
&priv->lec_arp_empty_ones,
|
||||||
priv->lec_no_forward,
|
&priv->lec_no_forward,
|
||||||
priv->mcast_fwds
|
&priv->mcast_fwds
|
||||||
};
|
};
|
||||||
void *v = NULL;
|
void *v = NULL;
|
||||||
int q;
|
int q;
|
||||||
|
@ -1112,7 +1115,7 @@ static void *lec_seq_start(struct seq_file *seq, loff_t *pos)
|
||||||
state->locked = NULL;
|
state->locked = NULL;
|
||||||
state->arp_table = 0;
|
state->arp_table = 0;
|
||||||
state->misc_table = 0;
|
state->misc_table = 0;
|
||||||
state->entry = (void *)1;
|
state->node = (void *)1;
|
||||||
|
|
||||||
return *pos ? lec_get_idx(state, *pos) : (void *)1;
|
return *pos ? lec_get_idx(state, *pos) : (void *)1;
|
||||||
}
|
}
|
||||||
|
@ -1148,9 +1151,10 @@ static int lec_seq_show(struct seq_file *seq, void *v)
|
||||||
else {
|
else {
|
||||||
struct lec_state *state = seq->private;
|
struct lec_state *state = seq->private;
|
||||||
struct net_device *dev = state->dev;
|
struct net_device *dev = state->dev;
|
||||||
|
struct lec_arp_table *entry = hlist_entry(state->node, struct lec_arp_table, next);
|
||||||
|
|
||||||
seq_printf(seq, "%s ", dev->name);
|
seq_printf(seq, "%s ", dev->name);
|
||||||
lec_info(seq, state->entry);
|
lec_info(seq, entry);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1455,8 +1459,11 @@ static void lec_arp_init(struct lec_priv *priv)
|
||||||
unsigned short i;
|
unsigned short i;
|
||||||
|
|
||||||
for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
|
for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
|
||||||
priv->lec_arp_tables[i] = NULL;
|
INIT_HLIST_HEAD(&priv->lec_arp_tables[i]);
|
||||||
}
|
}
|
||||||
|
INIT_HLIST_HEAD(&priv->lec_arp_empty_ones);
|
||||||
|
INIT_HLIST_HEAD(&priv->lec_no_forward);
|
||||||
|
INIT_HLIST_HEAD(&priv->mcast_fwds);
|
||||||
spin_lock_init(&priv->lec_arp_lock);
|
spin_lock_init(&priv->lec_arp_lock);
|
||||||
init_timer(&priv->lec_arp_timer);
|
init_timer(&priv->lec_arp_timer);
|
||||||
priv->lec_arp_timer.expires = jiffies + LEC_ARP_REFRESH_INTERVAL;
|
priv->lec_arp_timer.expires = jiffies + LEC_ARP_REFRESH_INTERVAL;
|
||||||
|
@ -1479,7 +1486,7 @@ static void lec_arp_clear_vccs(struct lec_arp_table *entry)
|
||||||
vcc->user_back = NULL;
|
vcc->user_back = NULL;
|
||||||
vcc->push = entry->old_push;
|
vcc->push = entry->old_push;
|
||||||
vcc_release_async(vcc, -EPIPE);
|
vcc_release_async(vcc, -EPIPE);
|
||||||
vcc = NULL;
|
entry->vcc = NULL;
|
||||||
}
|
}
|
||||||
if (entry->recv_vcc) {
|
if (entry->recv_vcc) {
|
||||||
entry->recv_vcc->push = entry->old_recv_push;
|
entry->recv_vcc->push = entry->old_recv_push;
|
||||||
|
@ -1493,27 +1500,17 @@ static void lec_arp_clear_vccs(struct lec_arp_table *entry)
|
||||||
* LANE2: Add to the end of the list to satisfy 8.1.13
|
* LANE2: Add to the end of the list to satisfy 8.1.13
|
||||||
*/
|
*/
|
||||||
static inline void
|
static inline void
|
||||||
lec_arp_add(struct lec_priv *priv, struct lec_arp_table *to_add)
|
lec_arp_add(struct lec_priv *priv, struct lec_arp_table *entry)
|
||||||
{
|
{
|
||||||
unsigned short place;
|
struct hlist_head *tmp;
|
||||||
struct lec_arp_table *tmp;
|
|
||||||
|
|
||||||
place = HASH(to_add->mac_addr[ETH_ALEN - 1]);
|
tmp = &priv->lec_arp_tables[HASH(entry->mac_addr[ETH_ALEN - 1])];
|
||||||
tmp = priv->lec_arp_tables[place];
|
hlist_add_head(&entry->next, tmp);
|
||||||
to_add->next = NULL;
|
|
||||||
if (tmp == NULL)
|
|
||||||
priv->lec_arp_tables[place] = to_add;
|
|
||||||
|
|
||||||
else { /* add to the end */
|
|
||||||
while (tmp->next)
|
|
||||||
tmp = tmp->next;
|
|
||||||
tmp->next = to_add;
|
|
||||||
}
|
|
||||||
|
|
||||||
DPRINTK("LEC_ARP: Added entry:%2.2x %2.2x %2.2x %2.2x %2.2x %2.2x\n",
|
DPRINTK("LEC_ARP: Added entry:%2.2x %2.2x %2.2x %2.2x %2.2x %2.2x\n",
|
||||||
0xff & to_add->mac_addr[0], 0xff & to_add->mac_addr[1],
|
0xff & entry->mac_addr[0], 0xff & entry->mac_addr[1],
|
||||||
0xff & to_add->mac_addr[2], 0xff & to_add->mac_addr[3],
|
0xff & entry->mac_addr[2], 0xff & entry->mac_addr[3],
|
||||||
0xff & to_add->mac_addr[4], 0xff & to_add->mac_addr[5]);
|
0xff & entry->mac_addr[4], 0xff & entry->mac_addr[5]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1522,40 +1519,26 @@ lec_arp_add(struct lec_priv *priv, struct lec_arp_table *to_add)
|
||||||
static int
|
static int
|
||||||
lec_arp_remove(struct lec_priv *priv, struct lec_arp_table *to_remove)
|
lec_arp_remove(struct lec_priv *priv, struct lec_arp_table *to_remove)
|
||||||
{
|
{
|
||||||
unsigned short place;
|
struct hlist_node *node;
|
||||||
struct lec_arp_table *tmp;
|
struct lec_arp_table *entry;
|
||||||
int remove_vcc = 1;
|
int i, remove_vcc = 1;
|
||||||
|
|
||||||
if (!to_remove) {
|
if (!to_remove) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
place = HASH(to_remove->mac_addr[ETH_ALEN - 1]);
|
|
||||||
tmp = priv->lec_arp_tables[place];
|
hlist_del(&to_remove->next);
|
||||||
if (tmp == to_remove) {
|
|
||||||
priv->lec_arp_tables[place] = tmp->next;
|
|
||||||
} else {
|
|
||||||
while (tmp && tmp->next != to_remove) {
|
|
||||||
tmp = tmp->next;
|
|
||||||
}
|
|
||||||
if (!tmp) { /* Entry was not found */
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
tmp->next = to_remove->next;
|
|
||||||
del_timer(&to_remove->timer);
|
del_timer(&to_remove->timer);
|
||||||
|
|
||||||
/* If this is the only MAC connected to this VCC, also tear down
|
/* If this is the only MAC connected to this VCC, also tear down the VCC */
|
||||||
the VCC */
|
|
||||||
if (to_remove->status >= ESI_FLUSH_PENDING) {
|
if (to_remove->status >= ESI_FLUSH_PENDING) {
|
||||||
/*
|
/*
|
||||||
* ESI_FLUSH_PENDING, ESI_FORWARD_DIRECT
|
* ESI_FLUSH_PENDING, ESI_FORWARD_DIRECT
|
||||||
*/
|
*/
|
||||||
for (place = 0; place < LEC_ARP_TABLE_SIZE; place++) {
|
for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
|
||||||
for (tmp = priv->lec_arp_tables[place]; tmp != NULL;
|
hlist_for_each_entry(entry, node, &priv->lec_arp_tables[i], next) {
|
||||||
tmp = tmp->next) {
|
if (memcmp(to_remove->atm_addr,
|
||||||
if (memcmp
|
entry->atm_addr, ATM_ESA_LEN) == 0) {
|
||||||
(tmp->atm_addr, to_remove->atm_addr,
|
|
||||||
ATM_ESA_LEN) == 0) {
|
|
||||||
remove_vcc = 0;
|
remove_vcc = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1591,28 +1574,19 @@ static char *get_status_string(unsigned char st)
|
||||||
return "<UNKNOWN>";
|
return "<UNKNOWN>";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
static void dump_arp_table(struct lec_priv *priv)
|
static void dump_arp_table(struct lec_priv *priv)
|
||||||
{
|
{
|
||||||
#if DEBUG_ARP_TABLE
|
struct hlist_node *node;
|
||||||
int i, j, offset;
|
|
||||||
struct lec_arp_table *rulla;
|
struct lec_arp_table *rulla;
|
||||||
char buf[1024];
|
char buf[256];
|
||||||
struct lec_arp_table **lec_arp_tables =
|
int i, j, offset;
|
||||||
(struct lec_arp_table **)priv->lec_arp_tables;
|
|
||||||
struct lec_arp_table *lec_arp_empty_ones =
|
|
||||||
(struct lec_arp_table *)priv->lec_arp_empty_ones;
|
|
||||||
struct lec_arp_table *lec_no_forward =
|
|
||||||
(struct lec_arp_table *)priv->lec_no_forward;
|
|
||||||
struct lec_arp_table *mcast_fwds = priv->mcast_fwds;
|
|
||||||
|
|
||||||
printk("Dump %p:\n", priv);
|
printk("Dump %p:\n", priv);
|
||||||
for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
|
for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
|
||||||
rulla = lec_arp_tables[i];
|
hlist_for_each_entry(rulla, node, &priv->lec_arp_tables[i], next) {
|
||||||
offset = 0;
|
offset = 0;
|
||||||
offset += sprintf(buf, "%d: %p\n", i, rulla);
|
offset += sprintf(buf, "%d: %p\n", i, rulla);
|
||||||
while (rulla) {
|
|
||||||
offset += sprintf(buf + offset, "Mac:");
|
offset += sprintf(buf + offset, "Mac:");
|
||||||
for (j = 0; j < ETH_ALEN; j++) {
|
for (j = 0; j < ETH_ALEN; j++) {
|
||||||
offset += sprintf(buf + offset,
|
offset += sprintf(buf + offset,
|
||||||
|
@ -1639,15 +1613,13 @@ static void dump_arp_table(struct lec_priv *priv)
|
||||||
"Flags:%x, Packets_flooded:%x, Status: %s ",
|
"Flags:%x, Packets_flooded:%x, Status: %s ",
|
||||||
rulla->flags, rulla->packets_flooded,
|
rulla->flags, rulla->packets_flooded,
|
||||||
get_status_string(rulla->status));
|
get_status_string(rulla->status));
|
||||||
offset += sprintf(buf + offset, "->%p\n", rulla->next);
|
printk("%s\n", buf);
|
||||||
rulla = rulla->next;
|
|
||||||
}
|
}
|
||||||
printk("%s", buf);
|
|
||||||
}
|
}
|
||||||
rulla = lec_no_forward;
|
|
||||||
if (rulla)
|
if (!hlist_empty(&priv->lec_no_forward))
|
||||||
printk("No forward\n");
|
printk("No forward\n");
|
||||||
while (rulla) {
|
hlist_for_each_entry(rulla, node, &priv->lec_no_forward, next) {
|
||||||
offset = 0;
|
offset = 0;
|
||||||
offset += sprintf(buf + offset, "Mac:");
|
offset += sprintf(buf + offset, "Mac:");
|
||||||
for (j = 0; j < ETH_ALEN; j++) {
|
for (j = 0; j < ETH_ALEN; j++) {
|
||||||
|
@ -1671,14 +1643,12 @@ static void dump_arp_table(struct lec_priv *priv)
|
||||||
"Flags:%x, Packets_flooded:%x, Status: %s ",
|
"Flags:%x, Packets_flooded:%x, Status: %s ",
|
||||||
rulla->flags, rulla->packets_flooded,
|
rulla->flags, rulla->packets_flooded,
|
||||||
get_status_string(rulla->status));
|
get_status_string(rulla->status));
|
||||||
offset += sprintf(buf + offset, "->%lx\n", (long)rulla->next);
|
printk("%s\n", buf);
|
||||||
rulla = rulla->next;
|
|
||||||
printk("%s", buf);
|
|
||||||
}
|
}
|
||||||
rulla = lec_arp_empty_ones;
|
|
||||||
if (rulla)
|
if (!hlist_empty(&priv->lec_arp_empty_ones))
|
||||||
printk("Empty ones\n");
|
printk("Empty ones\n");
|
||||||
while (rulla) {
|
hlist_for_each_entry(rulla, node, &priv->lec_arp_empty_ones, next) {
|
||||||
offset = 0;
|
offset = 0;
|
||||||
offset += sprintf(buf + offset, "Mac:");
|
offset += sprintf(buf + offset, "Mac:");
|
||||||
for (j = 0; j < ETH_ALEN; j++) {
|
for (j = 0; j < ETH_ALEN; j++) {
|
||||||
|
@ -1702,15 +1672,12 @@ static void dump_arp_table(struct lec_priv *priv)
|
||||||
"Flags:%x, Packets_flooded:%x, Status: %s ",
|
"Flags:%x, Packets_flooded:%x, Status: %s ",
|
||||||
rulla->flags, rulla->packets_flooded,
|
rulla->flags, rulla->packets_flooded,
|
||||||
get_status_string(rulla->status));
|
get_status_string(rulla->status));
|
||||||
offset += sprintf(buf + offset, "->%lx\n", (long)rulla->next);
|
|
||||||
rulla = rulla->next;
|
|
||||||
printk("%s", buf);
|
printk("%s", buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
rulla = mcast_fwds;
|
if (!hlist_empty(&priv->mcast_fwds))
|
||||||
if (rulla)
|
|
||||||
printk("Multicast Forward VCCs\n");
|
printk("Multicast Forward VCCs\n");
|
||||||
while (rulla) {
|
hlist_for_each_entry(rulla, node, &priv->mcast_fwds, next) {
|
||||||
offset = 0;
|
offset = 0;
|
||||||
offset += sprintf(buf + offset, "Mac:");
|
offset += sprintf(buf + offset, "Mac:");
|
||||||
for (j = 0; j < ETH_ALEN; j++) {
|
for (j = 0; j < ETH_ALEN; j++) {
|
||||||
|
@ -1734,13 +1701,13 @@ static void dump_arp_table(struct lec_priv *priv)
|
||||||
"Flags:%x, Packets_flooded:%x, Status: %s ",
|
"Flags:%x, Packets_flooded:%x, Status: %s ",
|
||||||
rulla->flags, rulla->packets_flooded,
|
rulla->flags, rulla->packets_flooded,
|
||||||
get_status_string(rulla->status));
|
get_status_string(rulla->status));
|
||||||
offset += sprintf(buf + offset, "->%lx\n", (long)rulla->next);
|
printk("%s\n", buf);
|
||||||
rulla = rulla->next;
|
|
||||||
printk("%s", buf);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
#define dump_arp_table(priv) do { } while (0)
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Destruction of arp-cache
|
* Destruction of arp-cache
|
||||||
|
@ -1748,7 +1715,8 @@ static void dump_arp_table(struct lec_priv *priv)
|
||||||
static void lec_arp_destroy(struct lec_priv *priv)
|
static void lec_arp_destroy(struct lec_priv *priv)
|
||||||
{
|
{
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
struct lec_arp_table *entry, *next;
|
struct hlist_node *node, *next;
|
||||||
|
struct lec_arp_table *entry;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
del_timer_sync(&priv->lec_arp_timer);
|
del_timer_sync(&priv->lec_arp_timer);
|
||||||
|
@ -1759,43 +1727,37 @@ static void lec_arp_destroy(struct lec_priv *priv)
|
||||||
|
|
||||||
spin_lock_irqsave(&priv->lec_arp_lock, flags);
|
spin_lock_irqsave(&priv->lec_arp_lock, flags);
|
||||||
for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
|
for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
|
||||||
for (entry = priv->lec_arp_tables[i]; entry != NULL;
|
hlist_for_each_entry_safe(entry, node, next, &priv->lec_arp_tables[i], next) {
|
||||||
entry = next) {
|
|
||||||
next = entry->next;
|
|
||||||
lec_arp_remove(priv, entry);
|
lec_arp_remove(priv, entry);
|
||||||
kfree(entry);
|
kfree(entry);
|
||||||
}
|
}
|
||||||
|
INIT_HLIST_HEAD(&priv->lec_arp_tables[i]);
|
||||||
}
|
}
|
||||||
entry = priv->lec_arp_empty_ones;
|
|
||||||
while (entry) {
|
hlist_for_each_entry_safe(entry, node, next, &priv->lec_arp_empty_ones, next) {
|
||||||
next = entry->next;
|
|
||||||
del_timer_sync(&entry->timer);
|
del_timer_sync(&entry->timer);
|
||||||
lec_arp_clear_vccs(entry);
|
lec_arp_clear_vccs(entry);
|
||||||
|
hlist_del(&entry->next);
|
||||||
kfree(entry);
|
kfree(entry);
|
||||||
entry = next;
|
|
||||||
}
|
}
|
||||||
priv->lec_arp_empty_ones = NULL;
|
INIT_HLIST_HEAD(&priv->lec_arp_empty_ones);
|
||||||
entry = priv->lec_no_forward;
|
|
||||||
while (entry) {
|
hlist_for_each_entry_safe(entry, node, next, &priv->lec_no_forward, next) {
|
||||||
next = entry->next;
|
|
||||||
del_timer_sync(&entry->timer);
|
del_timer_sync(&entry->timer);
|
||||||
lec_arp_clear_vccs(entry);
|
lec_arp_clear_vccs(entry);
|
||||||
|
hlist_del(&entry->next);
|
||||||
kfree(entry);
|
kfree(entry);
|
||||||
entry = next;
|
|
||||||
}
|
}
|
||||||
priv->lec_no_forward = NULL;
|
INIT_HLIST_HEAD(&priv->lec_no_forward);
|
||||||
entry = priv->mcast_fwds;
|
|
||||||
while (entry) {
|
hlist_for_each_entry_safe(entry, node, next, &priv->mcast_fwds, next) {
|
||||||
next = entry->next;
|
|
||||||
/* No timer, LANEv2 7.1.20 and 2.3.5.3 */
|
/* No timer, LANEv2 7.1.20 and 2.3.5.3 */
|
||||||
lec_arp_clear_vccs(entry);
|
lec_arp_clear_vccs(entry);
|
||||||
|
hlist_del(&entry->next);
|
||||||
kfree(entry);
|
kfree(entry);
|
||||||
entry = next;
|
|
||||||
}
|
}
|
||||||
priv->mcast_fwds = NULL;
|
INIT_HLIST_HEAD(&priv->mcast_fwds);
|
||||||
priv->mcast_vcc = NULL;
|
priv->mcast_vcc = NULL;
|
||||||
memset(priv->lec_arp_tables, 0,
|
|
||||||
sizeof(struct lec_arp_table *) * LEC_ARP_TABLE_SIZE);
|
|
||||||
spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
|
spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1805,20 +1767,19 @@ static void lec_arp_destroy(struct lec_priv *priv)
|
||||||
static struct lec_arp_table *lec_arp_find(struct lec_priv *priv,
|
static struct lec_arp_table *lec_arp_find(struct lec_priv *priv,
|
||||||
unsigned char *mac_addr)
|
unsigned char *mac_addr)
|
||||||
{
|
{
|
||||||
unsigned short place;
|
struct hlist_node *node;
|
||||||
struct lec_arp_table *to_return;
|
struct hlist_head *head;
|
||||||
|
struct lec_arp_table *entry;
|
||||||
|
|
||||||
DPRINTK("LEC_ARP: lec_arp_find :%2.2x %2.2x %2.2x %2.2x %2.2x %2.2x\n",
|
DPRINTK("LEC_ARP: lec_arp_find :%2.2x %2.2x %2.2x %2.2x %2.2x %2.2x\n",
|
||||||
mac_addr[0] & 0xff, mac_addr[1] & 0xff, mac_addr[2] & 0xff,
|
mac_addr[0] & 0xff, mac_addr[1] & 0xff, mac_addr[2] & 0xff,
|
||||||
mac_addr[3] & 0xff, mac_addr[4] & 0xff, mac_addr[5] & 0xff);
|
mac_addr[3] & 0xff, mac_addr[4] & 0xff, mac_addr[5] & 0xff);
|
||||||
place = HASH(mac_addr[ETH_ALEN - 1]);
|
|
||||||
|
|
||||||
to_return = priv->lec_arp_tables[place];
|
head = &priv->lec_arp_tables[HASH(mac_addr[ETH_ALEN - 1])];
|
||||||
while (to_return) {
|
hlist_for_each_entry(entry, node, head, next) {
|
||||||
if (!compare_ether_addr(mac_addr, to_return->mac_addr)) {
|
if (!compare_ether_addr(mac_addr, entry->mac_addr)) {
|
||||||
return to_return;
|
return entry;
|
||||||
}
|
}
|
||||||
to_return = to_return->next;
|
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -1834,6 +1795,7 @@ static struct lec_arp_table *make_entry(struct lec_priv *priv,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
memcpy(to_return->mac_addr, mac_addr, ETH_ALEN);
|
memcpy(to_return->mac_addr, mac_addr, ETH_ALEN);
|
||||||
|
INIT_HLIST_NODE(&to_return->next);
|
||||||
init_timer(&to_return->timer);
|
init_timer(&to_return->timer);
|
||||||
to_return->timer.function = lec_arp_expire_arp;
|
to_return->timer.function = lec_arp_expire_arp;
|
||||||
to_return->timer.data = (unsigned long)to_return;
|
to_return->timer.data = (unsigned long)to_return;
|
||||||
|
@ -1871,7 +1833,6 @@ static void lec_arp_expire_vcc(unsigned long data)
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
struct lec_arp_table *to_remove = (struct lec_arp_table *)data;
|
struct lec_arp_table *to_remove = (struct lec_arp_table *)data;
|
||||||
struct lec_priv *priv = (struct lec_priv *)to_remove->priv;
|
struct lec_priv *priv = (struct lec_priv *)to_remove->priv;
|
||||||
struct lec_arp_table *entry = NULL;
|
|
||||||
|
|
||||||
del_timer(&to_remove->timer);
|
del_timer(&to_remove->timer);
|
||||||
|
|
||||||
|
@ -1879,30 +1840,9 @@ static void lec_arp_expire_vcc(unsigned long data)
|
||||||
to_remove, priv,
|
to_remove, priv,
|
||||||
to_remove->vcc ? to_remove->recv_vcc->vpi : 0,
|
to_remove->vcc ? to_remove->recv_vcc->vpi : 0,
|
||||||
to_remove->vcc ? to_remove->recv_vcc->vci : 0);
|
to_remove->vcc ? to_remove->recv_vcc->vci : 0);
|
||||||
DPRINTK("eo:%p nf:%p\n", priv->lec_arp_empty_ones,
|
|
||||||
priv->lec_no_forward);
|
|
||||||
|
|
||||||
spin_lock_irqsave(&priv->lec_arp_lock, flags);
|
spin_lock_irqsave(&priv->lec_arp_lock, flags);
|
||||||
if (to_remove == priv->lec_arp_empty_ones)
|
hlist_del(&to_remove->next);
|
||||||
priv->lec_arp_empty_ones = to_remove->next;
|
|
||||||
else {
|
|
||||||
entry = priv->lec_arp_empty_ones;
|
|
||||||
while (entry && entry->next != to_remove)
|
|
||||||
entry = entry->next;
|
|
||||||
if (entry)
|
|
||||||
entry->next = to_remove->next;
|
|
||||||
}
|
|
||||||
if (!entry) {
|
|
||||||
if (to_remove == priv->lec_no_forward) {
|
|
||||||
priv->lec_no_forward = to_remove->next;
|
|
||||||
} else {
|
|
||||||
entry = priv->lec_no_forward;
|
|
||||||
while (entry && entry->next != to_remove)
|
|
||||||
entry = entry->next;
|
|
||||||
if (entry)
|
|
||||||
entry->next = to_remove->next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
|
spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
|
||||||
|
|
||||||
lec_arp_clear_vccs(to_remove);
|
lec_arp_clear_vccs(to_remove);
|
||||||
|
@ -1929,18 +1869,17 @@ static void lec_arp_check_expire(unsigned long data)
|
||||||
{
|
{
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
struct lec_priv *priv = (struct lec_priv *)data;
|
struct lec_priv *priv = (struct lec_priv *)data;
|
||||||
struct lec_arp_table *entry, *next;
|
struct hlist_node *node, *next;
|
||||||
|
struct lec_arp_table *entry;
|
||||||
unsigned long now;
|
unsigned long now;
|
||||||
unsigned long time_to_check;
|
unsigned long time_to_check;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
DPRINTK("lec_arp_check_expire %p\n", priv);
|
DPRINTK("lec_arp_check_expire %p\n", priv);
|
||||||
DPRINTK("expire: eo:%p nf:%p\n", priv->lec_arp_empty_ones,
|
|
||||||
priv->lec_no_forward);
|
|
||||||
now = jiffies;
|
now = jiffies;
|
||||||
spin_lock_irqsave(&priv->lec_arp_lock, flags);
|
spin_lock_irqsave(&priv->lec_arp_lock, flags);
|
||||||
for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
|
for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
|
||||||
for (entry = priv->lec_arp_tables[i]; entry != NULL;) {
|
hlist_for_each_entry_safe(entry, node, next, &priv->lec_arp_tables[i], next) {
|
||||||
if ((entry->flags) & LEC_REMOTE_FLAG &&
|
if ((entry->flags) & LEC_REMOTE_FLAG &&
|
||||||
priv->topology_change)
|
priv->topology_change)
|
||||||
time_to_check = priv->forward_delay_time;
|
time_to_check = priv->forward_delay_time;
|
||||||
|
@ -1954,10 +1893,8 @@ static void lec_arp_check_expire(unsigned long data)
|
||||||
&& !(entry->mac_addr[0] & 0x01)) { /* LANE2: 7.1.20 */
|
&& !(entry->mac_addr[0] & 0x01)) { /* LANE2: 7.1.20 */
|
||||||
/* Remove entry */
|
/* Remove entry */
|
||||||
DPRINTK("LEC:Entry timed out\n");
|
DPRINTK("LEC:Entry timed out\n");
|
||||||
next = entry->next;
|
|
||||||
lec_arp_remove(priv, entry);
|
lec_arp_remove(priv, entry);
|
||||||
kfree(entry);
|
kfree(entry);
|
||||||
entry = next;
|
|
||||||
} else {
|
} else {
|
||||||
/* Something else */
|
/* Something else */
|
||||||
if ((entry->status == ESI_VC_PENDING ||
|
if ((entry->status == ESI_VC_PENDING ||
|
||||||
|
@ -1988,7 +1925,6 @@ static void lec_arp_check_expire(unsigned long data)
|
||||||
entry->last_used = jiffies;
|
entry->last_used = jiffies;
|
||||||
entry->status = ESI_FORWARD_DIRECT;
|
entry->status = ESI_FORWARD_DIRECT;
|
||||||
}
|
}
|
||||||
entry = entry->next;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2100,15 +2036,14 @@ lec_addr_delete(struct lec_priv *priv, unsigned char *atm_addr,
|
||||||
unsigned long permanent)
|
unsigned long permanent)
|
||||||
{
|
{
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
struct lec_arp_table *entry, *next;
|
struct hlist_node *node, *next;
|
||||||
|
struct lec_arp_table *entry;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
DPRINTK("lec_addr_delete\n");
|
DPRINTK("lec_addr_delete\n");
|
||||||
spin_lock_irqsave(&priv->lec_arp_lock, flags);
|
spin_lock_irqsave(&priv->lec_arp_lock, flags);
|
||||||
for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
|
for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
|
||||||
for (entry = priv->lec_arp_tables[i]; entry != NULL;
|
hlist_for_each_entry_safe(entry, node, next, &priv->lec_arp_tables[i], next) {
|
||||||
entry = next) {
|
|
||||||
next = entry->next;
|
|
||||||
if (!memcmp(atm_addr, entry->atm_addr, ATM_ESA_LEN)
|
if (!memcmp(atm_addr, entry->atm_addr, ATM_ESA_LEN)
|
||||||
&& (permanent ||
|
&& (permanent ||
|
||||||
!(entry->flags & LEC_PERMANENT_FLAG))) {
|
!(entry->flags & LEC_PERMANENT_FLAG))) {
|
||||||
|
@ -2132,6 +2067,7 @@ lec_arp_update(struct lec_priv *priv, unsigned char *mac_addr,
|
||||||
unsigned int targetless_le_arp)
|
unsigned int targetless_le_arp)
|
||||||
{
|
{
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
struct hlist_node *node, *next;
|
||||||
struct lec_arp_table *entry, *tmp;
|
struct lec_arp_table *entry, *tmp;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
@ -2147,50 +2083,39 @@ lec_arp_update(struct lec_priv *priv, unsigned char *mac_addr,
|
||||||
* LANE2: ignore targetless LE_ARPs for which
|
* LANE2: ignore targetless LE_ARPs for which
|
||||||
* we have no entry in the cache. 7.1.30
|
* we have no entry in the cache. 7.1.30
|
||||||
*/
|
*/
|
||||||
if (priv->lec_arp_empty_ones) {
|
if (!hlist_empty(&priv->lec_arp_empty_ones)) {
|
||||||
entry = priv->lec_arp_empty_ones;
|
hlist_for_each_entry_safe(entry, node, next, &priv->lec_arp_empty_ones, next) {
|
||||||
if (!memcmp(entry->atm_addr, atm_addr, ATM_ESA_LEN)) {
|
if (memcmp(entry->atm_addr, atm_addr, ATM_ESA_LEN) == 0) {
|
||||||
priv->lec_arp_empty_ones = entry->next;
|
hlist_del(&entry->next);
|
||||||
} else {
|
|
||||||
while (entry->next && memcmp(entry->next->atm_addr,
|
|
||||||
atm_addr, ATM_ESA_LEN))
|
|
||||||
entry = entry->next;
|
|
||||||
if (entry->next) {
|
|
||||||
tmp = entry;
|
|
||||||
entry = entry->next;
|
|
||||||
tmp->next = entry->next;
|
|
||||||
} else
|
|
||||||
entry = NULL;
|
|
||||||
|
|
||||||
}
|
|
||||||
if (entry) {
|
|
||||||
del_timer(&entry->timer);
|
|
||||||
tmp = lec_arp_find(priv, mac_addr);
|
|
||||||
if (tmp) {
|
|
||||||
del_timer(&tmp->timer);
|
|
||||||
tmp->status = ESI_FORWARD_DIRECT;
|
|
||||||
memcpy(tmp->atm_addr, atm_addr, ATM_ESA_LEN);
|
|
||||||
tmp->vcc = entry->vcc;
|
|
||||||
tmp->old_push = entry->old_push;
|
|
||||||
tmp->last_used = jiffies;
|
|
||||||
del_timer(&entry->timer);
|
del_timer(&entry->timer);
|
||||||
kfree(entry);
|
tmp = lec_arp_find(priv, mac_addr);
|
||||||
entry = tmp;
|
if (tmp) {
|
||||||
} else {
|
del_timer(&tmp->timer);
|
||||||
entry->status = ESI_FORWARD_DIRECT;
|
tmp->status = ESI_FORWARD_DIRECT;
|
||||||
memcpy(entry->mac_addr, mac_addr, ETH_ALEN);
|
memcpy(tmp->atm_addr, atm_addr, ATM_ESA_LEN);
|
||||||
entry->last_used = jiffies;
|
tmp->vcc = entry->vcc;
|
||||||
lec_arp_add(priv, entry);
|
tmp->old_push = entry->old_push;
|
||||||
|
tmp->last_used = jiffies;
|
||||||
|
del_timer(&entry->timer);
|
||||||
|
kfree(entry);
|
||||||
|
entry = tmp;
|
||||||
|
} else {
|
||||||
|
entry->status = ESI_FORWARD_DIRECT;
|
||||||
|
memcpy(entry->mac_addr, mac_addr, ETH_ALEN);
|
||||||
|
entry->last_used = jiffies;
|
||||||
|
lec_arp_add(priv, entry);
|
||||||
|
}
|
||||||
|
if (remoteflag)
|
||||||
|
entry->flags |= LEC_REMOTE_FLAG;
|
||||||
|
else
|
||||||
|
entry->flags &= ~LEC_REMOTE_FLAG;
|
||||||
|
DPRINTK("After update\n");
|
||||||
|
dump_arp_table(priv);
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
if (remoteflag)
|
|
||||||
entry->flags |= LEC_REMOTE_FLAG;
|
|
||||||
else
|
|
||||||
entry->flags &= ~LEC_REMOTE_FLAG;
|
|
||||||
DPRINTK("After update\n");
|
|
||||||
dump_arp_table(priv);
|
|
||||||
goto out;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
entry = lec_arp_find(priv, mac_addr);
|
entry = lec_arp_find(priv, mac_addr);
|
||||||
if (!entry) {
|
if (!entry) {
|
||||||
entry = make_entry(priv, mac_addr);
|
entry = make_entry(priv, mac_addr);
|
||||||
|
@ -2203,7 +2128,7 @@ lec_arp_update(struct lec_priv *priv, unsigned char *mac_addr,
|
||||||
memcpy(entry->atm_addr, atm_addr, ATM_ESA_LEN);
|
memcpy(entry->atm_addr, atm_addr, ATM_ESA_LEN);
|
||||||
del_timer(&entry->timer);
|
del_timer(&entry->timer);
|
||||||
for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
|
for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
|
||||||
for (tmp = priv->lec_arp_tables[i]; tmp; tmp = tmp->next) {
|
hlist_for_each_entry(tmp, node, &priv->lec_arp_tables[i], next) {
|
||||||
if (entry != tmp &&
|
if (entry != tmp &&
|
||||||
!memcmp(tmp->atm_addr, atm_addr, ATM_ESA_LEN)) {
|
!memcmp(tmp->atm_addr, atm_addr, ATM_ESA_LEN)) {
|
||||||
/* Vcc to this host exists */
|
/* Vcc to this host exists */
|
||||||
|
@ -2226,8 +2151,7 @@ lec_arp_update(struct lec_priv *priv, unsigned char *mac_addr,
|
||||||
entry->flags &= ~LEC_REMOTE_FLAG;
|
entry->flags &= ~LEC_REMOTE_FLAG;
|
||||||
if (entry->status == ESI_ARP_PENDING || entry->status == ESI_UNKNOWN) {
|
if (entry->status == ESI_ARP_PENDING || entry->status == ESI_UNKNOWN) {
|
||||||
entry->status = ESI_VC_PENDING;
|
entry->status = ESI_VC_PENDING;
|
||||||
send_to_lecd(priv, l_svc_setup, entry->mac_addr, atm_addr,
|
send_to_lecd(priv, l_svc_setup, entry->mac_addr, atm_addr, NULL);
|
||||||
NULL);
|
|
||||||
}
|
}
|
||||||
DPRINTK("After update2\n");
|
DPRINTK("After update2\n");
|
||||||
dump_arp_table(priv);
|
dump_arp_table(priv);
|
||||||
|
@ -2244,6 +2168,7 @@ lec_vcc_added(struct lec_priv *priv, struct atmlec_ioc *ioc_data,
|
||||||
void (*old_push) (struct atm_vcc *vcc, struct sk_buff *skb))
|
void (*old_push) (struct atm_vcc *vcc, struct sk_buff *skb))
|
||||||
{
|
{
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
struct hlist_node *node;
|
||||||
struct lec_arp_table *entry;
|
struct lec_arp_table *entry;
|
||||||
int i, found_entry = 0;
|
int i, found_entry = 0;
|
||||||
|
|
||||||
|
@ -2269,8 +2194,7 @@ lec_vcc_added(struct lec_priv *priv, struct atmlec_ioc *ioc_data,
|
||||||
memcpy(entry->atm_addr, ioc_data->atm_addr, ATM_ESA_LEN);
|
memcpy(entry->atm_addr, ioc_data->atm_addr, ATM_ESA_LEN);
|
||||||
entry->recv_vcc = vcc;
|
entry->recv_vcc = vcc;
|
||||||
entry->old_recv_push = old_push;
|
entry->old_recv_push = old_push;
|
||||||
entry->next = priv->mcast_fwds;
|
hlist_add_head(&entry->next, &priv->mcast_fwds);
|
||||||
priv->mcast_fwds = entry;
|
|
||||||
goto out;
|
goto out;
|
||||||
} else if (ioc_data->receive == 1) {
|
} else if (ioc_data->receive == 1) {
|
||||||
/*
|
/*
|
||||||
|
@ -2300,9 +2224,8 @@ lec_vcc_added(struct lec_priv *priv, struct atmlec_ioc *ioc_data,
|
||||||
entry->status = ESI_UNKNOWN;
|
entry->status = ESI_UNKNOWN;
|
||||||
entry->timer.expires = jiffies + priv->vcc_timeout_period;
|
entry->timer.expires = jiffies + priv->vcc_timeout_period;
|
||||||
entry->timer.function = lec_arp_expire_vcc;
|
entry->timer.function = lec_arp_expire_vcc;
|
||||||
|
hlist_add_head(&entry->next, &priv->lec_no_forward);
|
||||||
add_timer(&entry->timer);
|
add_timer(&entry->timer);
|
||||||
entry->next = priv->lec_no_forward;
|
|
||||||
priv->lec_no_forward = entry;
|
|
||||||
dump_arp_table(priv);
|
dump_arp_table(priv);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
@ -2320,8 +2243,7 @@ lec_vcc_added(struct lec_priv *priv, struct atmlec_ioc *ioc_data,
|
||||||
ioc_data->atm_addr[16], ioc_data->atm_addr[17],
|
ioc_data->atm_addr[16], ioc_data->atm_addr[17],
|
||||||
ioc_data->atm_addr[18], ioc_data->atm_addr[19]);
|
ioc_data->atm_addr[18], ioc_data->atm_addr[19]);
|
||||||
for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
|
for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
|
||||||
for (entry = priv->lec_arp_tables[i]; entry;
|
hlist_for_each_entry(entry, node, &priv->lec_arp_tables[i], next) {
|
||||||
entry = entry->next) {
|
|
||||||
if (memcmp
|
if (memcmp
|
||||||
(ioc_data->atm_addr, entry->atm_addr,
|
(ioc_data->atm_addr, entry->atm_addr,
|
||||||
ATM_ESA_LEN) == 0) {
|
ATM_ESA_LEN) == 0) {
|
||||||
|
@ -2384,8 +2306,7 @@ lec_vcc_added(struct lec_priv *priv, struct atmlec_ioc *ioc_data,
|
||||||
memcpy(entry->atm_addr, ioc_data->atm_addr, ATM_ESA_LEN);
|
memcpy(entry->atm_addr, ioc_data->atm_addr, ATM_ESA_LEN);
|
||||||
memset(entry->mac_addr, 0, ETH_ALEN);
|
memset(entry->mac_addr, 0, ETH_ALEN);
|
||||||
entry->status = ESI_UNKNOWN;
|
entry->status = ESI_UNKNOWN;
|
||||||
entry->next = priv->lec_arp_empty_ones;
|
hlist_add_head(&entry->next, &priv->lec_arp_empty_ones);
|
||||||
priv->lec_arp_empty_ones = entry;
|
|
||||||
entry->timer.expires = jiffies + priv->vcc_timeout_period;
|
entry->timer.expires = jiffies + priv->vcc_timeout_period;
|
||||||
entry->timer.function = lec_arp_expire_vcc;
|
entry->timer.function = lec_arp_expire_vcc;
|
||||||
add_timer(&entry->timer);
|
add_timer(&entry->timer);
|
||||||
|
@ -2398,14 +2319,14 @@ out:
|
||||||
static void lec_flush_complete(struct lec_priv *priv, unsigned long tran_id)
|
static void lec_flush_complete(struct lec_priv *priv, unsigned long tran_id)
|
||||||
{
|
{
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
struct hlist_node *node;
|
||||||
struct lec_arp_table *entry;
|
struct lec_arp_table *entry;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
DPRINTK("LEC:lec_flush_complete %lx\n", tran_id);
|
DPRINTK("LEC:lec_flush_complete %lx\n", tran_id);
|
||||||
spin_lock_irqsave(&priv->lec_arp_lock, flags);
|
spin_lock_irqsave(&priv->lec_arp_lock, flags);
|
||||||
for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
|
for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
|
||||||
for (entry = priv->lec_arp_tables[i]; entry;
|
hlist_for_each_entry(entry, node, &priv->lec_arp_tables[i], next) {
|
||||||
entry = entry->next) {
|
|
||||||
if (entry->flush_tran_id == tran_id
|
if (entry->flush_tran_id == tran_id
|
||||||
&& entry->status == ESI_FLUSH_PENDING) {
|
&& entry->status == ESI_FLUSH_PENDING) {
|
||||||
struct sk_buff *skb;
|
struct sk_buff *skb;
|
||||||
|
@ -2427,19 +2348,19 @@ lec_set_flush_tran_id(struct lec_priv *priv,
|
||||||
unsigned char *atm_addr, unsigned long tran_id)
|
unsigned char *atm_addr, unsigned long tran_id)
|
||||||
{
|
{
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
struct hlist_node *node;
|
||||||
struct lec_arp_table *entry;
|
struct lec_arp_table *entry;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
spin_lock_irqsave(&priv->lec_arp_lock, flags);
|
spin_lock_irqsave(&priv->lec_arp_lock, flags);
|
||||||
for (i = 0; i < LEC_ARP_TABLE_SIZE; i++)
|
for (i = 0; i < LEC_ARP_TABLE_SIZE; i++)
|
||||||
for (entry = priv->lec_arp_tables[i]; entry;
|
hlist_for_each_entry(entry, node, &priv->lec_arp_tables[i], next) {
|
||||||
entry = entry->next)
|
|
||||||
if (!memcmp(atm_addr, entry->atm_addr, ATM_ESA_LEN)) {
|
if (!memcmp(atm_addr, entry->atm_addr, ATM_ESA_LEN)) {
|
||||||
entry->flush_tran_id = tran_id;
|
entry->flush_tran_id = tran_id;
|
||||||
DPRINTK
|
DPRINTK("Set flush transaction id to %lx for %p\n",
|
||||||
("Set flush transaction id to %lx for %p\n",
|
tran_id, entry);
|
||||||
tran_id, entry);
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
|
spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2483,15 +2404,17 @@ out:
|
||||||
static void lec_vcc_close(struct lec_priv *priv, struct atm_vcc *vcc)
|
static void lec_vcc_close(struct lec_priv *priv, struct atm_vcc *vcc)
|
||||||
{
|
{
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
struct lec_arp_table *entry, *next;
|
struct hlist_node *node, *next;
|
||||||
|
struct lec_arp_table *entry;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
DPRINTK("LEC_ARP: lec_vcc_close vpi:%d vci:%d\n", vcc->vpi, vcc->vci);
|
DPRINTK("LEC_ARP: lec_vcc_close vpi:%d vci:%d\n", vcc->vpi, vcc->vci);
|
||||||
dump_arp_table(priv);
|
dump_arp_table(priv);
|
||||||
|
|
||||||
spin_lock_irqsave(&priv->lec_arp_lock, flags);
|
spin_lock_irqsave(&priv->lec_arp_lock, flags);
|
||||||
|
|
||||||
for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
|
for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
|
||||||
for (entry = priv->lec_arp_tables[i]; entry; entry = next) {
|
hlist_for_each_entry_safe(entry, node, next, &priv->lec_arp_tables[i], next) {
|
||||||
next = entry->next;
|
|
||||||
if (vcc == entry->vcc) {
|
if (vcc == entry->vcc) {
|
||||||
lec_arp_remove(priv, entry);
|
lec_arp_remove(priv, entry);
|
||||||
kfree(entry);
|
kfree(entry);
|
||||||
|
@ -2502,49 +2425,31 @@ static void lec_vcc_close(struct lec_priv *priv, struct atm_vcc *vcc)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
entry = priv->lec_arp_empty_ones;
|
hlist_for_each_entry_safe(entry, node, next, &priv->lec_arp_empty_ones, next) {
|
||||||
priv->lec_arp_empty_ones = NULL;
|
if (entry->vcc == vcc) {
|
||||||
while (entry != NULL) {
|
|
||||||
next = entry->next;
|
|
||||||
if (entry->vcc == vcc) { /* leave it out from the list */
|
|
||||||
lec_arp_clear_vccs(entry);
|
lec_arp_clear_vccs(entry);
|
||||||
del_timer(&entry->timer);
|
del_timer(&entry->timer);
|
||||||
|
hlist_del(&entry->next);
|
||||||
kfree(entry);
|
kfree(entry);
|
||||||
} else { /* put it back to the list */
|
|
||||||
entry->next = priv->lec_arp_empty_ones;
|
|
||||||
priv->lec_arp_empty_ones = entry;
|
|
||||||
}
|
}
|
||||||
entry = next;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
entry = priv->lec_no_forward;
|
hlist_for_each_entry_safe(entry, node, next, &priv->lec_no_forward, next) {
|
||||||
priv->lec_no_forward = NULL;
|
|
||||||
while (entry != NULL) {
|
|
||||||
next = entry->next;
|
|
||||||
if (entry->recv_vcc == vcc) {
|
if (entry->recv_vcc == vcc) {
|
||||||
lec_arp_clear_vccs(entry);
|
lec_arp_clear_vccs(entry);
|
||||||
del_timer(&entry->timer);
|
del_timer(&entry->timer);
|
||||||
|
hlist_del(&entry->next);
|
||||||
kfree(entry);
|
kfree(entry);
|
||||||
} else {
|
|
||||||
entry->next = priv->lec_no_forward;
|
|
||||||
priv->lec_no_forward = entry;
|
|
||||||
}
|
}
|
||||||
entry = next;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
entry = priv->mcast_fwds;
|
hlist_for_each_entry_safe(entry, node, next, &priv->mcast_fwds, next) {
|
||||||
priv->mcast_fwds = NULL;
|
|
||||||
while (entry != NULL) {
|
|
||||||
next = entry->next;
|
|
||||||
if (entry->recv_vcc == vcc) {
|
if (entry->recv_vcc == vcc) {
|
||||||
lec_arp_clear_vccs(entry);
|
lec_arp_clear_vccs(entry);
|
||||||
/* No timer, LANEv2 7.1.20 and 2.3.5.3 */
|
/* No timer, LANEv2 7.1.20 and 2.3.5.3 */
|
||||||
|
hlist_del(&entry->next);
|
||||||
kfree(entry);
|
kfree(entry);
|
||||||
} else {
|
|
||||||
entry->next = priv->mcast_fwds;
|
|
||||||
priv->mcast_fwds = entry;
|
|
||||||
}
|
}
|
||||||
entry = next;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
|
spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
|
||||||
|
@ -2556,7 +2461,8 @@ lec_arp_check_empties(struct lec_priv *priv,
|
||||||
struct atm_vcc *vcc, struct sk_buff *skb)
|
struct atm_vcc *vcc, struct sk_buff *skb)
|
||||||
{
|
{
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
struct lec_arp_table *entry, *prev;
|
struct hlist_node *node, *next;
|
||||||
|
struct lec_arp_table *entry, *tmp;
|
||||||
struct lecdatahdr_8023 *hdr = (struct lecdatahdr_8023 *)skb->data;
|
struct lecdatahdr_8023 *hdr = (struct lecdatahdr_8023 *)skb->data;
|
||||||
unsigned char *src;
|
unsigned char *src;
|
||||||
#ifdef CONFIG_TR
|
#ifdef CONFIG_TR
|
||||||
|
@ -2569,41 +2475,23 @@ lec_arp_check_empties(struct lec_priv *priv,
|
||||||
src = hdr->h_source;
|
src = hdr->h_source;
|
||||||
|
|
||||||
spin_lock_irqsave(&priv->lec_arp_lock, flags);
|
spin_lock_irqsave(&priv->lec_arp_lock, flags);
|
||||||
entry = priv->lec_arp_empty_ones;
|
hlist_for_each_entry_safe(entry, node, next, &priv->lec_arp_empty_ones, next) {
|
||||||
if (vcc == entry->vcc) {
|
if (vcc == entry->vcc) {
|
||||||
del_timer(&entry->timer);
|
del_timer(&entry->timer);
|
||||||
memcpy(entry->mac_addr, src, ETH_ALEN);
|
memcpy(entry->mac_addr, src, ETH_ALEN);
|
||||||
entry->status = ESI_FORWARD_DIRECT;
|
entry->status = ESI_FORWARD_DIRECT;
|
||||||
entry->last_used = jiffies;
|
entry->last_used = jiffies;
|
||||||
priv->lec_arp_empty_ones = entry->next;
|
/* We might have got an entry */
|
||||||
/* We might have got an entry */
|
if ((tmp = lec_arp_find(priv, src))) {
|
||||||
if ((prev = lec_arp_find(priv, src))) {
|
lec_arp_remove(priv, tmp);
|
||||||
lec_arp_remove(priv, prev);
|
kfree(tmp);
|
||||||
kfree(prev);
|
}
|
||||||
|
hlist_del(&entry->next);
|
||||||
|
lec_arp_add(priv, entry);
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
lec_arp_add(priv, entry);
|
|
||||||
goto out;
|
|
||||||
}
|
}
|
||||||
prev = entry;
|
DPRINTK("LEC_ARP: Arp_check_empties: entry not found!\n");
|
||||||
entry = entry->next;
|
|
||||||
while (entry && entry->vcc != vcc) {
|
|
||||||
prev = entry;
|
|
||||||
entry = entry->next;
|
|
||||||
}
|
|
||||||
if (!entry) {
|
|
||||||
DPRINTK("LEC_ARP: Arp_check_empties: entry not found!\n");
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
del_timer(&entry->timer);
|
|
||||||
memcpy(entry->mac_addr, src, ETH_ALEN);
|
|
||||||
entry->status = ESI_FORWARD_DIRECT;
|
|
||||||
entry->last_used = jiffies;
|
|
||||||
prev->next = entry->next;
|
|
||||||
if ((prev = lec_arp_find(priv, src))) {
|
|
||||||
lec_arp_remove(priv, prev);
|
|
||||||
kfree(prev);
|
|
||||||
}
|
|
||||||
lec_arp_add(priv, entry);
|
|
||||||
out:
|
out:
|
||||||
spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
|
spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,18 +72,18 @@ struct lane2_ops {
|
||||||
struct lec_priv {
|
struct lec_priv {
|
||||||
struct net_device_stats stats;
|
struct net_device_stats stats;
|
||||||
unsigned short lecid; /* Lecid of this client */
|
unsigned short lecid; /* Lecid of this client */
|
||||||
struct lec_arp_table *lec_arp_empty_ones;
|
struct hlist_head lec_arp_empty_ones;
|
||||||
/* Used for storing VCC's that don't have a MAC address attached yet */
|
/* Used for storing VCC's that don't have a MAC address attached yet */
|
||||||
struct lec_arp_table *lec_arp_tables[LEC_ARP_TABLE_SIZE];
|
struct hlist_head lec_arp_tables[LEC_ARP_TABLE_SIZE];
|
||||||
/* Actual LE ARP table */
|
/* Actual LE ARP table */
|
||||||
struct lec_arp_table *lec_no_forward;
|
struct hlist_head lec_no_forward;
|
||||||
/*
|
/*
|
||||||
* Used for storing VCC's (and forward packets from) which are to
|
* Used for storing VCC's (and forward packets from) which are to
|
||||||
* age out by not using them to forward packets.
|
* age out by not using them to forward packets.
|
||||||
* This is because to some LE clients there will be 2 VCCs. Only
|
* This is because to some LE clients there will be 2 VCCs. Only
|
||||||
* one of them gets used.
|
* one of them gets used.
|
||||||
*/
|
*/
|
||||||
struct lec_arp_table *mcast_fwds;
|
struct hlist_head mcast_fwds;
|
||||||
/*
|
/*
|
||||||
* With LANEv2 it is possible that BUS (or a special multicast server)
|
* With LANEv2 it is possible that BUS (or a special multicast server)
|
||||||
* establishes multiple Multicast Forward VCCs to us. This list
|
* establishes multiple Multicast Forward VCCs to us. This list
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
#include <linux/atmlec.h>
|
#include <linux/atmlec.h>
|
||||||
|
|
||||||
struct lec_arp_table {
|
struct lec_arp_table {
|
||||||
struct lec_arp_table *next; /* Linked entry list */
|
struct hlist_node next; /* Linked entry list */
|
||||||
unsigned char atm_addr[ATM_ESA_LEN]; /* Atm address */
|
unsigned char atm_addr[ATM_ESA_LEN]; /* Atm address */
|
||||||
unsigned char mac_addr[ETH_ALEN]; /* Mac address */
|
unsigned char mac_addr[ETH_ALEN]; /* Mac address */
|
||||||
int is_rdesc; /* Mac address is a route descriptor */
|
int is_rdesc; /* Mac address is a route descriptor */
|
||||||
|
|
Loading…
Reference in New Issue