patch-2.1.26 linux/net/802/tr.c
Next file: linux/net/core/sock.c
Previous file: linux/net/802/sysctl_net_802.c
Back to the patch index
Back to the overall index
- Lines: 338
- Date:
Fri Feb 7 15:54:55 1997
- Orig file:
v2.1.25/linux/net/802/tr.c
- Orig date:
Thu Jan 2 15:55:26 1997
diff -u --recursive --new-file v2.1.25/linux/net/802/tr.c linux/net/802/tr.c
@@ -6,7 +6,10 @@
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*
- * Fixes:
+ * Fixes: 3 Feb 97 Paul Norton <pnorton@cts.com> Minor routing fixes.
+ * Added rif table to /proc/net/tr_rif and rif timeout to
+ * /proc/sys/net/token-ring/rif_timeout.
+ *
*/
#include <asm/uaccess.h>
@@ -26,31 +29,35 @@
#include <linux/string.h>
#include <linux/timer.h>
#include <linux/net.h>
+#include <linux/proc_fs.h>
#include <net/arp.h>
-static void tr_source_route(struct trh_hdr *trh,struct device *dev);
-static void tr_add_rif_info(struct trh_hdr *trh);
+static void tr_source_route(struct trh_hdr *trh, struct device *dev);
+static void tr_add_rif_info(struct trh_hdr *trh, struct device *dev);
static void rif_check_expire(unsigned long dummy);
+#define TR_SR_DEBUG 0
+
typedef struct rif_cache_s *rif_cache;
/*
* Each RIF entry we learn is kept this way
*/
-struct rif_cache_s
-{
- unsigned char addr[TR_ALEN];
- unsigned short rcf;
- unsigned short rseg[8];
- rif_cache next;
- unsigned long last_used;
+struct rif_cache_s {
+ unsigned char addr[TR_ALEN];
+ unsigned char iface[5];
+ __u16 rcf;
+ __u8 rseg[8];
+ rif_cache next;
+ unsigned long last_used;
+ unsigned char local_ring;
};
-#define RIF_TABLE_SIZE 16
+#define RIF_TABLE_SIZE 32
/*
- * We hash the RIF cache 16 ways. We do after all have to look it
+ * We hash the RIF cache 32 ways. We do after all have to look it
* up a lot.
*/
@@ -63,11 +70,9 @@
* Garbage disposal timer.
*/
-static struct timer_list rif_timer=
-{
- NULL,NULL,RIF_CHECK_INTERVAL,0L,rif_check_expire
-};
+static struct timer_list rif_timer;
+int sysctl_tr_rif_timeout = RIF_TIMEOUT;
/*
* Put the headers on a token ring packet. Token ring source routing
@@ -130,7 +135,7 @@
*/
if(trllc->ethertype != htons(ETH_P_IP)) {
- printk("tr_rebuild_header: Don't know how to resolve type %04X addresses ?\n",(unsigned int)htons( trllc->ethertype));
+ printk("tr_rebuild_header: Don't know how to resolve type %04X addresses ?\n",(unsigned int)htons(trllc->ethertype));
return 0;
}
@@ -160,8 +165,7 @@
skb_pull(skb,dev->hard_header_len);
- if(trh->saddr[0] & TR_RII)
- tr_add_rif_info(trh);
+ tr_add_rif_info(trh, dev);
if(*trh->daddr & 1)
{
@@ -214,11 +218,11 @@
*/
if(entry)
{
-#if 0
+#if TR_SR_DEBUG
printk("source routing for %02X %02X %02X %02X %02X %02X\n",trh->daddr[0],
trh->daddr[1],trh->daddr[2],trh->daddr[3],trh->daddr[4],trh->daddr[5]);
#endif
- if((ntohs(entry->rcf) & TR_RCF_LEN_MASK) >> 8)
+ if(!entry->local_ring && (ntohs(entry->rcf) & TR_RCF_LEN_MASK) >> 8)
{
trh->rcf=entry->rcf;
memcpy(&trh->rseg[0],&entry->rseg[0],8*sizeof(unsigned short));
@@ -226,8 +230,15 @@
trh->rcf&=htons(0x1fff); /* Issam Chehab <ichehab@madge1.demon.co.uk> */
trh->saddr[0]|=TR_RII;
- entry->last_used=jiffies;
+#if TR_SR_DEBUG
+ printk("entry found with rcf %04x\n", entry->rcf);
+ }
+ else
+ {
+ printk("entry found but without rcf length, local=%02x\n", entry->local_ring);
+#endif
}
+ entry->last_used=jiffies;
}
else
{
@@ -239,6 +250,7 @@
trh->rcf=htons((((sizeof(trh->rcf)) << 8) & TR_RCF_LEN_MASK)
| TR_RCF_FRAME2K | TR_RCF_LIMITED_BROADCAST);
trh->saddr[0]|=TR_RII;
+ printk("no entry in rif table found - broadcasting frame\n");
}
}
}
@@ -248,27 +260,36 @@
* routing.
*/
-static void tr_add_rif_info(struct trh_hdr *trh)
+static void tr_add_rif_info(struct trh_hdr *trh, struct device *dev)
{
int i;
- unsigned int hash;
+ unsigned int hash, rii_p = 0;
rif_cache entry;
/*
* Firstly see if the entry exists
*/
- trh->saddr[0]&=0x7f;
+
+ if(trh->saddr[0] & TR_RII)
+ {
+ trh->saddr[0]&=0x7f;
+ if (((ntohs(trh->rcf) & TR_RCF_LEN_MASK) >> 8) > 2)
+ {
+ rii_p = 1;
+ }
+ }
+
for(i=0,hash=0;i<TR_ALEN;hash+=trh->saddr[i++]);
hash&=RIF_TABLE_SIZE-1;
for(entry=rif_table[hash];entry && memcmp(&(entry->addr[0]),&(trh->saddr[0]),TR_ALEN);entry=entry->next);
if(entry==NULL)
{
-#if 0
+#if TR_SR_DEBUG
printk("adding rif_entry: addr:%02X:%02X:%02X:%02X:%02X:%02X rcf:%04X\n",
trh->saddr[0],trh->saddr[1],trh->saddr[2],
trh->saddr[3],trh->saddr[4],trh->saddr[5],
- trh->rcf);
+ ntohs(trh->rcf));
#endif
/*
* Allocate our new entry. A failure to allocate loses
@@ -278,14 +299,26 @@
* limiting and adjust the timers to suit.
*/
entry=kmalloc(sizeof(struct rif_cache_s),GFP_ATOMIC);
+
if(!entry)
{
printk(KERN_DEBUG "tr.c: Couldn't malloc rif cache entry !\n");
return;
}
- entry->rcf=trh->rcf;
- memcpy(&(entry->rseg[0]),&(trh->rseg[0]),8*sizeof(unsigned short));
+
+ if (rii_p)
+ {
+ entry->rcf = trh->rcf & htons((unsigned short)~TR_RCF_BROADCAST_MASK);
+ memcpy(&(entry->rseg[0]),&(trh->rseg[0]),8*sizeof(unsigned short));
+ entry->local_ring = 0;
+ }
+ else
+ {
+ entry->local_ring = 1;
+ }
+
memcpy(&(entry->addr[0]),&(trh->saddr[0]),TR_ALEN);
+ memcpy(&(entry->iface[0]),dev->name,5);
entry->next=rif_table[hash];
entry->last_used=jiffies;
rif_table[hash]=entry;
@@ -295,21 +328,20 @@
/*
* Update existing entries
*/
- if ( entry->rcf != trh->rcf )
- {
- if (!(trh->rcf & htons(TR_RCF_BROADCAST_MASK)))
- {
-#if 0
+ if (!entry->local_ring)
+ if (entry->rcf != (trh->rcf & htons((unsigned short)~TR_RCF_BROADCAST_MASK)) &&
+ !(trh->rcf & htons(TR_RCF_BROADCAST_MASK)))
+ {
+#if TR_SR_DEBUG
printk("updating rif_entry: addr:%02X:%02X:%02X:%02X:%02X:%02X rcf:%04X\n",
trh->saddr[0],trh->saddr[1],trh->saddr[2],
trh->saddr[3],trh->saddr[4],trh->saddr[5],
- trh->rcf);
+ ntohs(trh->rcf));
#endif
- entry->rcf = trh->rcf;
- memcpy(&(entry->rseg[0]),&(trh->rseg[0]),8*sizeof(unsigned short));
- entry->last_used=jiffies;
- }
- }
+ entry->rcf = trh->rcf & htons((unsigned short)~TR_RCF_BROADCAST_MASK);
+ memcpy(&(entry->rseg[0]),&(trh->rseg[0]),8*sizeof(unsigned short));
+ }
+ entry->last_used=jiffies;
}
}
@@ -333,7 +365,7 @@
/*
* Out it goes
*/
- if((now-entry->last_used) > RIF_TIMEOUT)
+ if((now-entry->last_used) > sysctl_tr_rif_timeout)
{
*pentry=entry->next;
kfree_s(entry,sizeof(struct rif_cache_s));
@@ -349,7 +381,7 @@
*/
del_timer(&rif_timer);
- rif_timer.expires=jiffies+RIF_CHECK_INTERVAL;
+ rif_timer.expires = jiffies + sysctl_tr_rif_timeout;
add_timer(&rif_timer);
}
@@ -359,27 +391,46 @@
* routing.
*/
-int rif_get_info(char *buffer,char **start, off_t offset, int length)
+#ifdef CONFIG_PROC_FS
+int rif_get_info(char *buffer,char **start, off_t offset, int length, int dummy)
{
int len=0;
off_t begin=0;
off_t pos=0;
- int size,i;
+ int size,i,j,rcf_len;
+ unsigned long now=jiffies;
rif_cache entry;
size=sprintf(buffer,
- " TR address rcf routing segments TTL\n\n");
+ "if TR address TTL rcf routing segments\n\n");
pos+=size;
len+=size;
for(i=0;i < RIF_TABLE_SIZE;i++)
{
for(entry=rif_table[i];entry;entry=entry->next) {
- size=sprintf(buffer+len,"%02X:%02X:%02X:%02X:%02X:%02X %04X %04X %04X %04X %04X %04X %04X %04X %04X %lu\n",
- entry->addr[0],entry->addr[1],entry->addr[2],entry->addr[3],entry->addr[4],entry->addr[5],
- entry->rcf,entry->rseg[0],entry->rseg[1],entry->rseg[2],entry->rseg[3],
- entry->rseg[4],entry->rseg[5],entry->rseg[6],entry->rseg[7],jiffies-entry->last_used);
+ size=sprintf(buffer+len,"%s %02X:%02X:%02X:%02X:%02X:%02X %7li ",
+ entry->iface,entry->addr[0],entry->addr[1],entry->addr[2],entry->addr[3],entry->addr[4],entry->addr[5],
+ sysctl_tr_rif_timeout-(now-entry->last_used));
+ len+=size;
+ pos=begin+len;
+ if (entry->local_ring)
+ size=sprintf(buffer+len,"local\n");
+ else {
+ size=sprintf(buffer+len,"%04X", ntohs(entry->rcf));
+ rcf_len = ((ntohs(entry->rcf) & TR_RCF_LEN_MASK)>>8)-2;
+ if (rcf_len)
+ rcf_len >>= 1;
+ for(j = 0; j < rcf_len; j++) {
+ len+=size;
+ pos=begin+len;
+ size=sprintf(buffer+len," %04X",ntohs(entry->rseg[j]));
+ }
+ len+=size;
+ pos=begin+len;
+ size=sprintf(buffer+len,"\n");
+ }
len+=size;
pos=begin+len;
@@ -401,15 +452,28 @@
len=length; /* Ending slop */
return len;
}
+#endif
/*
* Called during bootup. We don't actually have to initialise
- * too much for this. The timer structure is setup statically. Thats
- * probably NOT a good thing if we change the structure.
+ * too much for this.
*/
void rif_init(struct net_proto *unused)
{
+
+ rif_timer.expires = RIF_TIMEOUT;
+ rif_timer.data = 0L;
+ rif_timer.function = rif_check_expire;
+ init_timer(&rif_timer);
add_timer(&rif_timer);
-}
+#ifdef CONFIG_PROC_FS
+ proc_net_register(&(struct proc_dir_entry) {
+ PROC_NET_TR_RIF, 6, "tr_rif",
+ S_IFREG | S_IRUGO, 1, 0, 0,
+ 0, &proc_net_inode_operations,
+ rif_get_info
+ });
+#endif
+}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov