📄 lec.c
字号:
static struct lec_arp_table*make_entry(struct lec_priv *priv, unsigned char *mac_addr){ struct lec_arp_table *to_return; to_return=(struct lec_arp_table *)kmalloc(sizeof(struct lec_arp_table), GFP_ATOMIC); if (!to_return) { printk("LEC: Arp entry kmalloc failed\n"); return NULL; } memset(to_return,0,sizeof(struct lec_arp_table)); memcpy(to_return->mac_addr, mac_addr, ETH_ALEN); init_timer(&to_return->timer); to_return->timer.function = lec_arp_expire_arp; to_return->timer.data = (unsigned long)to_return; to_return->last_used = jiffies; to_return->priv = priv; skb_queue_head_init(&to_return->tx_wait); return to_return;}/* * * Arp sent timer expired * */static voidlec_arp_expire_arp(unsigned long data){ struct lec_arp_table *entry; entry = (struct lec_arp_table *)data; del_timer(&entry->timer); DPRINTK("lec_arp_expire_arp\n"); if (entry->status == ESI_ARP_PENDING) { if (entry->no_tries <= entry->priv->max_retry_count) { if (entry->is_rdesc) send_to_lecd(entry->priv, l_rdesc_arp_xmt, entry->mac_addr, NULL, NULL); else send_to_lecd(entry->priv, l_arp_xmt, entry->mac_addr, NULL, NULL); entry->no_tries++; } entry->timer.expires = jiffies + (1*HZ); add_timer(&entry->timer); }}/* * * Unknown/unused vcc expire, remove associated entry * */static voidlec_arp_expire_vcc(unsigned long data){ struct lec_arp_table *to_remove = (struct lec_arp_table*)data; struct lec_priv *priv = (struct lec_priv *)to_remove->priv; struct lec_arp_table *entry = NULL; del_timer(&to_remove->timer); DPRINTK("LEC_ARP %p %p: lec_arp_expire_vcc vpi:%d vci:%d\n", to_remove, priv, to_remove->vcc?to_remove->recv_vcc->vpi: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); if (to_remove == priv->lec_arp_empty_ones) 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; } } lec_arp_clear_vccs(to_remove); kfree(to_remove);}/* * Expire entries. * 1. Re-set timer * 2. For each entry, delete entries that have aged past the age limit. * 3. For each entry, depending on the status of the entry, perform * the following maintenance. * a. If status is ESI_VC_PENDING or ESI_ARP_PENDING then if the * tick_count is above the max_unknown_frame_time, clear * the tick_count to zero and clear the packets_flooded counter * to zero. This supports the packet rate limit per address * while flooding unknowns. * b. If the status is ESI_FLUSH_PENDING and the tick_count is greater * than or equal to the path_switching_delay, change the status * to ESI_FORWARD_DIRECT. This causes the flush period to end * regardless of the progress of the flush protocol. */static voidlec_arp_check_expire(unsigned long data){ struct lec_priv *priv = (struct lec_priv *)data; struct lec_arp_table **lec_arp_tables = (struct lec_arp_table **)priv->lec_arp_tables; struct lec_arp_table *entry, *next; unsigned long now; unsigned long time_to_check; int i; del_timer(&priv->lec_arp_timer); DPRINTK("lec_arp_check_expire %p,%d\n",priv, priv->lec_arp_lock_var.counter); DPRINTK("expire: eo:%p nf:%p\n",priv->lec_arp_empty_ones, priv->lec_no_forward); if (!priv->lec_arp_lock_var.counter) { lec_arp_lock(priv); now = jiffies; for(i=0;i<LEC_ARP_TABLE_SIZE;i++) { for(entry = lec_arp_tables[i];entry != NULL;) { if ((entry->flags) & LEC_REMOTE_FLAG && priv->topology_change) time_to_check=priv->forward_delay_time; else time_to_check = priv->aging_time; DPRINTK("About to expire: %lx - %lx > %lx\n", now,entry->last_used, time_to_check); if( time_after(now, entry->last_used+ time_to_check) && !(entry->flags & LEC_PERMANENT_FLAG) && !(entry->mac_addr[0] & 0x01) ) { /* LANE2: 7.1.20 */ /* Remove entry */ DPRINTK("LEC:Entry timed out\n"); next = entry->next; lec_arp_remove(lec_arp_tables, entry); kfree(entry); entry = next; } else { /* Something else */ if ((entry->status == ESI_VC_PENDING || entry->status == ESI_ARP_PENDING) && time_after_eq(now, entry->timestamp + priv->max_unknown_frame_time)) { entry->timestamp = jiffies; entry->packets_flooded = 0; if (entry->status == ESI_VC_PENDING) send_to_lecd(priv, l_svc_setup, entry->mac_addr, entry->atm_addr, NULL); } if (entry->status == ESI_FLUSH_PENDING && time_after_eq(now, entry->timestamp+ priv->path_switching_delay)) { entry->last_used = jiffies; entry->status = ESI_FORWARD_DIRECT; } entry = entry->next; } } } lec_arp_unlock(priv); } priv->lec_arp_timer.expires = jiffies + LEC_ARP_REFRESH_INTERVAL; add_timer(&priv->lec_arp_timer);}/* * Try to find vcc where mac_address is attached. * */struct atm_vcc*lec_arp_resolve(struct lec_priv *priv, unsigned char *mac_to_find, int is_rdesc, struct lec_arp_table **ret_entry){ struct lec_arp_table *entry; if (mac_to_find[0]&0x01) { switch (priv->lane_version) { case 1: return priv->mcast_vcc; break; case 2: /* LANE2 wants arp for multicast addresses */ if ( memcmp(mac_to_find, bus_mac, ETH_ALEN) == 0) return priv->mcast_vcc; break; default: break; } } entry = lec_arp_find(priv, mac_to_find); if (entry) { if (entry->status == ESI_FORWARD_DIRECT) { /* Connection Ok */ entry->last_used = jiffies; *ret_entry = entry; return entry->vcc; } /* Data direct VC not yet set up, check to see if the unknown frame count is greater than the limit. If the limit has not been reached, allow the caller to send packet to BUS. */ if (entry->status != ESI_FLUSH_PENDING && entry->packets_flooded<priv->maximum_unknown_frame_count) { entry->packets_flooded++; DPRINTK("LEC_ARP: Flooding..\n"); return priv->mcast_vcc; } /* We got here because entry->status == ESI_FLUSH_PENDING * or BUS flood limit was reached for an entry which is * in ESI_ARP_PENDING or ESI_VC_PENDING state. */ *ret_entry = entry; DPRINTK("lec: entry->status %d entry->vcc %p\n", entry->status, entry->vcc); return NULL; } else { /* No matching entry was found */ entry = make_entry(priv, mac_to_find); DPRINTK("LEC_ARP: Making entry\n"); if (!entry) { return priv->mcast_vcc; } lec_arp_put(priv->lec_arp_tables, entry); /* We want arp-request(s) to be sent */ entry->packets_flooded =1; entry->status = ESI_ARP_PENDING; entry->no_tries = 1; entry->last_used = entry->timestamp = jiffies; entry->is_rdesc = is_rdesc; if (entry->is_rdesc) send_to_lecd(priv, l_rdesc_arp_xmt, mac_to_find, NULL, NULL); else send_to_lecd(priv, l_arp_xmt, mac_to_find, NULL, NULL); entry->timer.expires = jiffies + (1*HZ); entry->timer.function = lec_arp_expire_arp; add_timer(&entry->timer); return priv->mcast_vcc; }}intlec_addr_delete(struct lec_priv *priv, unsigned char *atm_addr, unsigned long permanent){ struct lec_arp_table *entry, *next; int i; lec_arp_lock(priv); DPRINTK("lec_addr_delete\n"); for(i=0;i<LEC_ARP_TABLE_SIZE;i++) { for(entry=priv->lec_arp_tables[i];entry != NULL; entry=next) { next = entry->next; if (!memcmp(atm_addr, entry->atm_addr, ATM_ESA_LEN) && (permanent || !(entry->flags & LEC_PERMANENT_FLAG))) { lec_arp_remove(priv->lec_arp_tables, entry); kfree(entry); } lec_arp_unlock(priv); return 0; } } lec_arp_unlock(priv); return -1;}/* * Notifies: Response to arp_request (atm_addr != NULL) */voidlec_arp_update(struct lec_priv *priv, unsigned char *mac_addr, unsigned char *atm_addr, unsigned long remoteflag, unsigned int targetless_le_arp){ struct lec_arp_table *entry, *tmp; int i; DPRINTK("lec:%s", (targetless_le_arp) ? "targetless ": " "); DPRINTK("lec_arp_update mac:%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x\n", mac_addr[0],mac_addr[1],mac_addr[2],mac_addr[3], mac_addr[4],mac_addr[5]); entry = lec_arp_find(priv, mac_addr); if (entry == NULL && targetless_le_arp) return; /* LANE2: ignore targetless LE_ARPs for which * we have no entry in the cache. 7.1.30 */ lec_arp_lock(priv); if (priv->lec_arp_empty_ones) { entry = priv->lec_arp_empty_ones; if (!memcmp(entry->atm_addr, atm_addr, ATM_ESA_LEN)) { priv->lec_arp_empty_ones = 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); kfree(entry); entry=tmp; } else { entry->status = ESI_FORWARD_DIRECT; memcpy(entry->mac_addr, mac_addr, ETH_ALEN); entry->last_used = jiffies; lec_arp_put(priv->lec_arp_tables, entry); } if (remoteflag) entry->flags|=LEC_REMOTE_FLAG; else entry->flags&=~LEC_REMOTE_FLAG; lec_arp_unlock(priv); DPRINTK("After update\n"); dump_arp_table(priv); return; } } entry = lec_arp_find(priv, mac_addr); if (!entry) { entry = make_entry(priv, mac_addr); if (!entry) { lec_arp_unlock(priv); return; } entry->status = ESI_UNKNOWN; lec_arp_put(priv->lec_arp_tables, entry); /* Temporary, changes before end of function */ } memcpy(entry->atm_addr, atm_addr, ATM_ESA_LEN);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -