📄 lec.c
字号:
get_status_string(rulla->status)); offset+=sprintf(buf+offset,"->%p\n",rulla->next); rulla = rulla->next; } printk("%s",buf); } rulla = lec_no_forward; if (rulla) printk("No forward\n"); while(rulla) { offset=0; offset += sprintf(buf+offset,"Mac:"); for(j=0;j<ETH_ALEN;j++) { offset+=sprintf(buf+offset,"%2.2x ", rulla->mac_addr[j]&0xff); } offset +=sprintf(buf+offset,"Atm:"); for(j=0;j<ATM_ESA_LEN;j++) { offset+=sprintf(buf+offset,"%2.2x ", rulla->atm_addr[j]&0xff); } offset+=sprintf(buf+offset, "Vcc vpi:%d vci:%d, Recv_vcc vpi:%d vci:%d Last_used:%lx, Timestamp:%lx, No_tries:%d ", rulla->vcc?rulla->vcc->vpi:0, rulla->vcc?rulla->vcc->vci:0, rulla->recv_vcc?rulla->recv_vcc->vpi:0, rulla->recv_vcc?rulla->recv_vcc->vci:0, rulla->last_used, rulla->timestamp, rulla->no_tries); offset+=sprintf(buf+offset, "Flags:%x, Packets_flooded:%x, Status: %s ", rulla->flags, rulla->packets_flooded, get_status_string(rulla->status)); offset+=sprintf(buf+offset,"->%lx\n",(long)rulla->next); rulla = rulla->next; printk("%s",buf); } rulla = lec_arp_empty_ones; if (rulla) printk("Empty ones\n"); while(rulla) { offset=0; offset += sprintf(buf+offset,"Mac:"); for(j=0;j<ETH_ALEN;j++) { offset+=sprintf(buf+offset,"%2.2x ", rulla->mac_addr[j]&0xff); } offset +=sprintf(buf+offset,"Atm:"); for(j=0;j<ATM_ESA_LEN;j++) { offset+=sprintf(buf+offset,"%2.2x ", rulla->atm_addr[j]&0xff); } offset+=sprintf(buf+offset, "Vcc vpi:%d vci:%d, Recv_vcc vpi:%d vci:%d Last_used:%lx, Timestamp:%lx, No_tries:%d ", rulla->vcc?rulla->vcc->vpi:0, rulla->vcc?rulla->vcc->vci:0, rulla->recv_vcc?rulla->recv_vcc->vpi:0, rulla->recv_vcc?rulla->recv_vcc->vci:0, rulla->last_used, rulla->timestamp, rulla->no_tries); offset+=sprintf(buf+offset, "Flags:%x, Packets_flooded:%x, Status: %s ", rulla->flags, rulla->packets_flooded, get_status_string(rulla->status)); offset+=sprintf(buf+offset,"->%lx\n",(long)rulla->next); rulla = rulla->next; printk("%s",buf); } rulla = mcast_fwds; if (rulla) printk("Multicast Forward VCCs\n"); while(rulla) { offset=0; offset += sprintf(buf+offset,"Mac:"); for(j=0;j<ETH_ALEN;j++) { offset+=sprintf(buf+offset,"%2.2x ", rulla->mac_addr[j]&0xff); } offset +=sprintf(buf+offset,"Atm:"); for(j=0;j<ATM_ESA_LEN;j++) { offset+=sprintf(buf+offset,"%2.2x ", rulla->atm_addr[j]&0xff); } offset+=sprintf(buf+offset, "Vcc vpi:%d vci:%d, Recv_vcc vpi:%d vci:%d Last_used:%lx, Timestamp:%lx, No_tries:%d ", rulla->vcc?rulla->vcc->vpi:0, rulla->vcc?rulla->vcc->vci:0, rulla->recv_vcc?rulla->recv_vcc->vpi:0, rulla->recv_vcc?rulla->recv_vcc->vci:0, rulla->last_used, rulla->timestamp, rulla->no_tries); offset+=sprintf(buf+offset, "Flags:%x, Packets_flooded:%x, Status: %s ", rulla->flags, rulla->packets_flooded, get_status_string(rulla->status)); offset+=sprintf(buf+offset,"->%lx\n",(long)rulla->next); rulla = rulla->next; printk("%s",buf); }#endif}/* * Destruction of arp-cache */voidlec_arp_destroy(struct lec_priv *priv){ struct lec_arp_table *entry, *next; int i; del_timer_sync(&priv->lec_arp_timer); /* * Remove all entries */ for (i=0;i<LEC_ARP_TABLE_SIZE;i++) { for(entry =priv->lec_arp_tables[i];entry != NULL; entry=next) { next = entry->next; lec_arp_remove(priv, entry); kfree(entry); } } entry = priv->lec_arp_empty_ones; while(entry) { next = entry->next; del_timer_sync(&entry->timer); lec_arp_clear_vccs(entry); kfree(entry); entry = next; } priv->lec_arp_empty_ones = NULL; entry = priv->lec_no_forward; while(entry) { next = entry->next; del_timer_sync(&entry->timer); lec_arp_clear_vccs(entry); kfree(entry); entry = next; } priv->lec_no_forward = NULL; entry = priv->mcast_fwds; while(entry) { next = entry->next; /* No timer, LANEv2 7.1.20 and 2.3.5.3 */ lec_arp_clear_vccs(entry); kfree(entry); entry = next; } priv->mcast_fwds = NULL; priv->mcast_vcc = NULL; memset(priv->lec_arp_tables, 0, sizeof(struct lec_arp_table*)*LEC_ARP_TABLE_SIZE);}/* * Find entry by mac_address */static struct lec_arp_table*lec_arp_find(struct lec_priv *priv, unsigned char *mac_addr){ unsigned short place; struct lec_arp_table *to_return; 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[3]&0xff, mac_addr[4]&0xff, mac_addr[5]&0xff); lec_arp_get(priv); place = HASH(mac_addr[ETH_ALEN-1]); to_return = priv->lec_arp_tables[place]; while(to_return) { if (memcmp(mac_addr, to_return->mac_addr, ETH_ALEN) == 0) { lec_arp_put(priv); return to_return; } to_return = to_return->next; } lec_arp_put(priv); return NULL;}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; 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++; } mod_timer(&entry->timer, jiffies + (1*HZ)); }}/* * * 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 *entry, *next; unsigned long now; unsigned long time_to_check; int i; DPRINTK("lec_arp_check_expire %p,%d\n",priv, atomic_read(&priv->lec_arp_users)); DPRINTK("expire: eo:%p nf:%p\n",priv->lec_arp_empty_ones, priv->lec_no_forward); if (!atomic_read(&priv->lec_arp_users)) { lec_arp_get(priv); now = jiffies; for(i=0;i<LEC_ARP_TABLE_SIZE;i++) { for(entry = priv->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(priv, 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)) { struct sk_buff *skb; while ((skb = skb_dequeue(&entry->tx_wait)) != NULL) lec_send(entry->vcc, skb, entry->priv); entry->last_used = jiffies; entry->status = ESI_FORWARD_DIRECT; } entry = entry->next; } } } lec_arp_put(priv); } mod_timer(&priv->lec_arp_timer, jiffies + LEC_ARP_REFRESH_INTERVAL);}/* * 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. I
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -