patch-2.1.20 linux/net/802/tr.c

Next file: linux/net/Config.in
Previous file: linux/net/802/sysctl_net_802.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.1.19/linux/net/802/tr.c linux/net/802/tr.c
@@ -1,3 +1,14 @@
+/*
+ * NET3:	Token ring device handling subroutines
+ * 
+ *		This program is free software; you can redistribute it and/or
+ *		modify it under the terms of the GNU General Public License
+ *		as published by the Free Software Foundation; either version
+ *		2 of the License, or (at your option) any later version.
+ *
+ * Fixes:
+ */
+
 #include <asm/uaccess.h>
 #include <asm/system.h>
 #include <linux/types.h>
@@ -23,7 +34,12 @@
 
 typedef struct rif_cache_s *rif_cache;
 
-struct rif_cache_s {	
+/*
+ *	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];
@@ -32,12 +48,32 @@
 };
 
 #define RIF_TABLE_SIZE 16
+
+/*
+ *	We hash the RIF cache 16 ways. We do after all have to look it
+ *	up a lot.
+ */
+ 
 rif_cache rif_table[RIF_TABLE_SIZE]={ NULL, };
 
 #define RIF_TIMEOUT 60*10*HZ
 #define RIF_CHECK_INTERVAL 60*HZ
-static struct timer_list rif_timer={ NULL,NULL,RIF_CHECK_INTERVAL,0L,rif_check_expire };
 
+/*
+ *	Garbage disposal timer.
+ */
+ 
+static struct timer_list rif_timer=
+{
+	NULL,NULL,RIF_CHECK_INTERVAL,0L,rif_check_expire
+};
+
+
+/*
+ *	Put the headers on a token ring packet. Token ring source routing
+ *	makes this a little more exciting than on ethernet.
+ */
+ 
 int tr_header(struct sk_buff *skb, struct device *dev, unsigned short type,
               void *daddr, void *saddr, unsigned len) 
 {
@@ -53,13 +89,23 @@
 	else
 		memset(trh->saddr,0,dev->addr_len); /* Adapter fills in address */
 
+	/*
+	 *	This is the stuff needed for IP encoding - IP over 802.2
+	 *	with SNAP.
+	 */
+	 
 	trllc->dsap=trllc->ssap=EXTENDED_SAP;
 	trllc->llc=UI_CMD;
 	
 	trllc->protid[0]=trllc->protid[1]=trllc->protid[2]=0x00;
 	trllc->ethertype=htons(type);
 
-	if(daddr) {
+	/*
+	 *	Build the destination and then source route the frame
+	 */
+	 
+	if(daddr) 
+	{
 		memcpy(trh->daddr,daddr,dev->addr_len);
 		tr_source_route(trh,dev);
 		return(dev->hard_header_len);
@@ -68,12 +114,21 @@
 
 }
 	
-int tr_rebuild_header(struct sk_buff *skb) {
-
+/*
+ *	A neighbour discovery of some species (eg arp) has completed. We
+ *	can now send the packet.
+ */
+ 
+int tr_rebuild_header(struct sk_buff *skb) 
+{
 	struct trh_hdr *trh=(struct trh_hdr *)skb->data;
 	struct trllc *trllc=(struct trllc *)(skb->data+sizeof(struct trh_hdr));
 	struct device *dev = skb->dev;
 
+	/*
+	 *	FIXME: We don't yet support IPv6 over token rings
+	 */
+	 
 	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));
 		return 0;
@@ -82,13 +137,21 @@
 	if(arp_find(trh->daddr, skb)) {
 			return 1;
 	}
-	else {	
+	else 
+	{	
 		tr_source_route(trh,dev); 
 		return 0;
 	}
 }
 	
-unsigned short tr_type_trans(struct sk_buff *skb, struct device *dev) {
+/*
+ *	Some of this is a bit hackish. We intercept RIF information
+ *	used for source routing. We also grab IP directly and don't feed
+ *	it via SNAP.
+ */
+ 
+unsigned short tr_type_trans(struct sk_buff *skb, struct device *dev) 
+{
 
 	struct trh_hdr *trh=(struct trh_hdr *)skb->data;
 	struct trllc *trllc=(struct trllc *)(skb->data+sizeof(struct trh_hdr));
@@ -117,31 +180,46 @@
  	return trllc->ethertype;
 }
 
-/* We try to do source routing... */
+/*
+ *	We try to do source routing... 
+ */
 
-static void tr_source_route(struct trh_hdr *trh,struct device *dev) {
+static void tr_source_route(struct trh_hdr *trh,struct device *dev) 
+{
 
 	int i;
 	unsigned int hash;
 	rif_cache entry;
 
-	/* Broadcasts are single route as stated in RFC 1042 */
-	if(!memcmp(&(trh->daddr[0]),&(dev->broadcast[0]),TR_ALEN)) {
+	/*
+	 *	Broadcasts are single route as stated in RFC 1042 
+	 */
+	if(!memcmp(&(trh->daddr[0]),&(dev->broadcast[0]),TR_ALEN)) 
+	{
 		trh->rcf=htons((((sizeof(trh->rcf)) << 8) & TR_RCF_LEN_MASK)  
 			       | TR_RCF_FRAME2K | TR_RCF_LIMITED_BROADCAST);
 		trh->saddr[0]|=TR_RII;
 	}
-	else {
+	else 
+	{
 		for(i=0,hash=0;i<TR_ALEN;hash+=trh->daddr[i++]);
 		hash&=RIF_TABLE_SIZE-1;
+		/*
+		 *	Walk the hash table and look for an entry
+		 */
 		for(entry=rif_table[hash];entry && memcmp(&(entry->addr[0]),&(trh->daddr[0]),TR_ALEN);entry=entry->next);
 
-		if(entry) {
+		/*
+		 *	If we found an entry we can route the frame.
+		 */
+		if(entry) 
+		{
 #if 0
 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((ntohs(entry->rcf) & TR_RCF_LEN_MASK) >> 8) 
+			{
 				trh->rcf=entry->rcf;
 				memcpy(&trh->rseg[0],&entry->rseg[0],8*sizeof(unsigned short));
 				trh->rcf^=htons(TR_RCF_DIR_BIT);	
@@ -151,40 +229,58 @@
 				entry->last_used=jiffies;
 			}
 		}
-		else {
+		else 
+		{
+			/*
+			 *	Without the information we simply have to shout
+			 *	on the wire. The replies should rapidly clean this
+			 *	situation up.
+			 */
 			trh->rcf=htons((((sizeof(trh->rcf)) << 8) & TR_RCF_LEN_MASK)  
 				       | TR_RCF_FRAME2K | TR_RCF_LIMITED_BROADCAST);
 			trh->saddr[0]|=TR_RII;
 		}
 	}
-			
 }
 
-static void tr_add_rif_info(struct trh_hdr *trh) {
-
+/*
+ *	We have learned some new RIF information for our source
+ *	routing.
+ */
+ 
+static void tr_add_rif_info(struct trh_hdr *trh) 
+{
 	int i;
 	unsigned int hash;
 	rif_cache entry;
 
-
+	/*
+	 *	Firstly see if the entry exists
+	 */
 	trh->saddr[0]&=0x7f;
 	for(i=0,hash=0;i<TR_ALEN;hash+=trh->saddr[i++]);
 	hash&=RIF_TABLE_SIZE-1;
-#if 0
-	printk("hash: %d\n",hash);
-#endif
 	for(entry=rif_table[hash];entry && memcmp(&(entry->addr[0]),&(trh->saddr[0]),TR_ALEN);entry=entry->next);
 
-	if(entry==NULL) {
+	if(entry==NULL) 
+	{
 #if 0
 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);
 #endif
+		/*
+		 *	Allocate our new entry. A failure to allocate loses
+		 *	use the information. This is harmless.
+		 *
+		 *	FIXME: We ought to keep some kind of cache size
+		 *	limiting and adjust the timers to suit.
+		 */
 		entry=kmalloc(sizeof(struct rif_cache_s),GFP_ATOMIC);
-		if(!entry) {
-			printk("tr.c: Couldn't malloc rif cache entry !\n");
+		if(!entry) 
+		{
+			printk(KERN_DEBUG "tr.c: Couldn't malloc rif cache entry !\n");
 			return;
 		}
 		entry->rcf=trh->rcf;
@@ -193,69 +289,92 @@
 		entry->next=rif_table[hash];
 		entry->last_used=jiffies;
 		rif_table[hash]=entry;
-	}
-/* Y. Tahara added */
-   else {                                       
-		if ( entry->rcf != trh->rcf ) {               
-				if (!(trh->rcf & htons(TR_RCF_BROADCAST_MASK))) {
+	} 	
+	else	/* Y. Tahara added */
+	{ 
+		/*
+		 *	Update existing entries
+		 */
+		if ( entry->rcf != trh->rcf ) 
+		{ 
+			if (!(trh->rcf & htons(TR_RCF_BROADCAST_MASK))) 
+			{
 #if 0
 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);
 #endif
-     		       entry->rcf = trh->rcf;                  
-        		    memcpy(&(entry->rseg[0]),&(trh->rseg[0]),8*sizeof(unsigned short));
-           		 entry->last_used=jiffies;               
-				}                                          
+				entry->rcf = trh->rcf;                  
+				memcpy(&(entry->rseg[0]),&(trh->rseg[0]),8*sizeof(unsigned short));
+				entry->last_used=jiffies;               
+			}                                          
 		}                                             
 	}
-
 }
 
-static void rif_check_expire(unsigned long dummy) {
+/*
+ *	Scan the cache with a timer and see what we need to throw out.
+ */
 
+static void rif_check_expire(unsigned long dummy) 
+{
 	int i;
 	unsigned long now=jiffies,flags;
 
 	save_flags(flags);
 	cli();
 
-	for(i=0; i < RIF_TABLE_SIZE;i++) {
-
-	rif_cache entry, *pentry=rif_table+i;	
-
+	for(i=0; i < RIF_TABLE_SIZE;i++) 
+	{
+		rif_cache entry, *pentry=rif_table+i;	
 		while((entry=*pentry)) 
-			if((now-entry->last_used) > RIF_TIMEOUT) {
+		{
+			/*
+			 *	Out it goes
+			 */
+			if((now-entry->last_used) > RIF_TIMEOUT) 
+			{
 				*pentry=entry->next;
 				kfree_s(entry,sizeof(struct rif_cache_s));
 			}
 			else
-				pentry=&entry->next;	
+				pentry=&entry->next;
+		}
 	}
 	restore_flags(flags);
 
+	/*
+	 *	Reset the timer
+	 */
+	 
 	del_timer(&rif_timer);
 	rif_timer.expires=jiffies+RIF_CHECK_INTERVAL;
 	add_timer(&rif_timer);
 
 }
 
-int rif_get_info(char *buffer,char **start, off_t offset, int length) {
-
-   int len=0;
-   off_t begin=0;
-   off_t pos=0;
-   int size,i;
+/*
+ *	Generate the /proc/net information for the token ring RIF
+ *	routing.
+ */
+ 
+int rif_get_info(char *buffer,char **start, off_t offset, int length) 
+{
+	int len=0;
+	off_t begin=0;
+	off_t pos=0;
+	int size,i;
 
-   rif_cache entry;
+	rif_cache entry;
 
 	size=sprintf(buffer,
-"   TR address     rcf             routing segments             TTL\n\n");
-   pos+=size;
-   len+=size;
+		"   TR address     rcf             routing segments             TTL\n\n");
+	pos+=size;
+	len+=size;
 
-	for(i=0;i < RIF_TABLE_SIZE;i++) {
+	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],
@@ -264,27 +383,33 @@
 			len+=size;
 			pos=begin+len;
 
-			if(pos<offset) {
+			if(pos<offset) 
+			{
 				len=0;
 				begin=pos;
 			}
 			if(pos>offset+length)
 				break;
-   	}
+	   	}
 		if(pos>offset+length)
 			break;
 	}
 
-   *start=buffer+(offset-begin); /* Start of wanted data */
-   len-=(offset-begin);    /* Start slop */
-   if(len>length)
-      len=length;    /* Ending slop */
-   return len;
+	*start=buffer+(offset-begin); /* Start of wanted data */
+	len-=(offset-begin);    /* Start slop */
+	if(len>length)
+		len=length;    /* Ending slop */
+	return len;
 }
 
-void rif_init(struct net_proto *unused) {
-
+/*
+ *	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.
+ */
+ 
+void rif_init(struct net_proto *unused) 
+{
 	add_timer(&rif_timer);
-
 }
 

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov