OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [uclinux/] [uClinux-2.0.x/] [net/] [802/] [tr.c] - Blame information for rev 199

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 199 simons
#include <asm/segment.h>
2
#include <asm/system.h>
3
#include <linux/types.h>
4
#include <linux/kernel.h>
5
#include <linux/sched.h>
6
#include <linux/string.h>
7
#include <linux/mm.h>
8
#include <linux/socket.h>
9
#include <linux/in.h>
10
#include <linux/inet.h>
11
#include <linux/netdevice.h>
12
#include <linux/trdevice.h>
13
#include <linux/skbuff.h>
14
#include <linux/errno.h>
15
#include <linux/string.h>
16
#include <linux/timer.h>
17
#include <linux/net.h>
18
#include <net/arp.h>
19
 
20
static void tr_source_route(struct trh_hdr *trh,struct device *dev);
21
static void tr_add_rif_info(struct trh_hdr *trh);
22
static void rif_check_expire(unsigned long dummy);
23
 
24
typedef struct rif_cache_s *rif_cache;
25
 
26
struct rif_cache_s {
27
         unsigned char addr[TR_ALEN];
28
         unsigned short rcf;
29
         unsigned short rseg[8];
30
         rif_cache next;
31
         unsigned long last_used;
32
};
33
 
34
#define RIF_TABLE_SIZE 16
35
rif_cache rif_table[RIF_TABLE_SIZE]={ NULL, };
36
 
37
#define RIF_TIMEOUT 60*10*HZ
38
#define RIF_CHECK_INTERVAL 60*HZ
39
static struct timer_list rif_timer={ NULL,NULL,RIF_CHECK_INTERVAL,0L,rif_check_expire };
40
 
41
int tr_header(struct sk_buff *skb, struct device *dev, unsigned short type,
42
              void *daddr, void *saddr, unsigned len)
43
{
44
 
45
        struct trh_hdr *trh=(struct trh_hdr *)skb_push(skb,dev->hard_header_len);
46
        struct trllc *trllc=(struct trllc *)(trh+1);
47
 
48
        trh->ac=AC;
49
        trh->fc=LLC_FRAME;
50
 
51
        if(saddr)
52
                memcpy(trh->saddr,saddr,dev->addr_len);
53
        else
54
                memset(trh->saddr,0,dev->addr_len); /* Adapter fills in address */
55
 
56
        trllc->dsap=trllc->ssap=EXTENDED_SAP;
57
        trllc->llc=UI_CMD;
58
 
59
        trllc->protid[0]=trllc->protid[1]=trllc->protid[2]=0x00;
60
        trllc->ethertype=htons(type);
61
 
62
        if(daddr) {
63
                memcpy(trh->daddr,daddr,dev->addr_len);
64
                tr_source_route(trh,dev);
65
                return(dev->hard_header_len);
66
        }
67
        return -dev->hard_header_len;
68
 
69
}
70
 
71
int tr_rebuild_header(void *buff, struct device *dev, unsigned long dest,
72
                                                         struct sk_buff *skb) {
73
 
74
        struct trh_hdr *trh=(struct trh_hdr *)buff;
75
        struct trllc *trllc=(struct trllc *)(buff+sizeof(struct trh_hdr));
76
 
77
        if(trllc->ethertype != htons(ETH_P_IP)) {
78
                printk("tr_rebuild_header: Don't know how to resolve type %04X addresses ?\n",(unsigned int)htons(      trllc->ethertype));
79
                return 0;
80
        }
81
 
82
        if(arp_find(trh->daddr, dest, dev, dev->pa_addr, skb)) {
83
                        return 1;
84
        }
85
        else {
86
                tr_source_route(trh,dev);
87
                return 0;
88
        }
89
}
90
 
91
unsigned short tr_type_trans(struct sk_buff *skb, struct device *dev) {
92
 
93
        struct trh_hdr *trh=(struct trh_hdr *)skb->data;
94
        struct trllc *trllc=(struct trllc *)(skb->data+sizeof(struct trh_hdr));
95
 
96
        skb->mac.raw = skb->data;
97
 
98
        skb_pull(skb,dev->hard_header_len);
99
 
100
        if(trh->saddr[0] & TR_RII)
101
                tr_add_rif_info(trh);
102
 
103
        if(*trh->daddr & 1)
104
        {
105
                if(!memcmp(trh->daddr,dev->broadcast,TR_ALEN))
106
                        skb->pkt_type=PACKET_BROADCAST;
107
                else
108
                        skb->pkt_type=PACKET_MULTICAST;
109
        }
110
 
111
        else if(dev->flags & IFF_PROMISC)
112
        {
113
                if(memcmp(trh->daddr, dev->dev_addr, TR_ALEN))
114
                        skb->pkt_type=PACKET_OTHERHOST;
115
        }
116
 
117
        return trllc->ethertype;
118
}
119
 
120
/* We try to do source routing... */
121
 
122
static void tr_source_route(struct trh_hdr *trh,struct device *dev) {
123
 
124
        int i;
125
        unsigned int hash;
126
        rif_cache entry;
127
 
128
        /* Broadcasts are single route as stated in RFC 1042 */
129
        if(!memcmp(&(trh->daddr[0]),&(dev->broadcast[0]),TR_ALEN)) {
130
                trh->rcf=htons((((sizeof(trh->rcf)) << 8) & TR_RCF_LEN_MASK)
131
                               | TR_RCF_FRAME2K | TR_RCF_LIMITED_BROADCAST);
132
                trh->saddr[0]|=TR_RII;
133
        }
134
        else {
135
                for(i=0,hash=0;i<TR_ALEN;hash+=trh->daddr[i++]);
136
                hash&=RIF_TABLE_SIZE-1;
137
                for(entry=rif_table[hash];entry && memcmp(&(entry->addr[0]),&(trh->daddr[0]),TR_ALEN);entry=entry->next);
138
 
139
                if(entry) {
140
#if 0
141
printk("source routing for %02X %02X %02X %02X %02X %02X\n",trh->daddr[0],
142
                  trh->daddr[1],trh->daddr[2],trh->daddr[3],trh->daddr[4],trh->daddr[5]);
143
#endif
144
                        if((ntohs(entry->rcf) & TR_RCF_LEN_MASK) >> 8) {
145
                                trh->rcf=entry->rcf;
146
                                memcpy(&trh->rseg[0],&entry->rseg[0],8*sizeof(unsigned short));
147
                                trh->rcf^=htons(TR_RCF_DIR_BIT);
148
                                trh->rcf&=htons(0x1fff);        /* Issam Chehab <ichehab@madge1.demon.co.uk> */
149
 
150
                                trh->saddr[0]|=TR_RII;
151
                                entry->last_used=jiffies;
152
                        }
153
                }
154
                else {
155
                        trh->rcf=htons((((sizeof(trh->rcf)) << 8) & TR_RCF_LEN_MASK)
156
                                       | TR_RCF_FRAME2K | TR_RCF_LIMITED_BROADCAST);
157
                        trh->saddr[0]|=TR_RII;
158
                }
159
        }
160
 
161
}
162
 
163
static void tr_add_rif_info(struct trh_hdr *trh) {
164
 
165
        int i;
166
        unsigned int hash;
167
        rif_cache entry;
168
 
169
 
170
        trh->saddr[0]&=0x7f;
171
        for(i=0,hash=0;i<TR_ALEN;hash+=trh->saddr[i++]);
172
        hash&=RIF_TABLE_SIZE-1;
173
#if 0
174
        printk("hash: %d\n",hash);
175
#endif
176
        for(entry=rif_table[hash];entry && memcmp(&(entry->addr[0]),&(trh->saddr[0]),TR_ALEN);entry=entry->next);
177
 
178
        if(entry==NULL) {
179
#if 0
180
printk("adding rif_entry: addr:%02X:%02X:%02X:%02X:%02X:%02X rcf:%04X\n",
181
                trh->saddr[0],trh->saddr[1],trh->saddr[2],
182
                trh->saddr[3],trh->saddr[4],trh->saddr[5],
183
                trh->rcf);
184
#endif
185
                entry=kmalloc(sizeof(struct rif_cache_s),GFP_ATOMIC);
186
                if(!entry) {
187
                        printk("tr.c: Couldn't malloc rif cache entry !\n");
188
                        return;
189
                }
190
                entry->rcf=trh->rcf;
191
                memcpy(&(entry->rseg[0]),&(trh->rseg[0]),8*sizeof(unsigned short));
192
                memcpy(&(entry->addr[0]),&(trh->saddr[0]),TR_ALEN);
193
                entry->next=rif_table[hash];
194
                entry->last_used=jiffies;
195
                rif_table[hash]=entry;
196
        }
197
/* Y. Tahara added */
198
   else {
199
                if ( entry->rcf != trh->rcf ) {
200
                                if (!(trh->rcf & htons(TR_RCF_BROADCAST_MASK))) {
201
#if 0
202
printk("updating rif_entry: addr:%02X:%02X:%02X:%02X:%02X:%02X rcf:%04X\n",
203
                trh->saddr[0],trh->saddr[1],trh->saddr[2],
204
                trh->saddr[3],trh->saddr[4],trh->saddr[5],
205
                trh->rcf);
206
#endif
207
                       entry->rcf = trh->rcf;
208
                            memcpy(&(entry->rseg[0]),&(trh->rseg[0]),8*sizeof(unsigned short));
209
                         entry->last_used=jiffies;
210
                                }
211
                }
212
        }
213
 
214
}
215
 
216
static void rif_check_expire(unsigned long dummy) {
217
 
218
        int i;
219
        unsigned long now=jiffies,flags;
220
 
221
        save_flags(flags);
222
        cli();
223
 
224
        for(i=0; i < RIF_TABLE_SIZE;i++) {
225
 
226
        rif_cache entry, *pentry=rif_table+i;
227
 
228
                while((entry=*pentry))
229
                        if((now-entry->last_used) > RIF_TIMEOUT) {
230
                                *pentry=entry->next;
231
                                kfree_s(entry,sizeof(struct rif_cache_s));
232
                        }
233
                        else
234
                                pentry=&entry->next;
235
        }
236
        restore_flags(flags);
237
 
238
        del_timer(&rif_timer);
239
        rif_timer.expires=jiffies+RIF_CHECK_INTERVAL;
240
        add_timer(&rif_timer);
241
 
242
}
243
 
244
int rif_get_info(char *buffer,char **start, off_t offset, int length) {
245
 
246
   int len=0;
247
   off_t begin=0;
248
   off_t pos=0;
249
   int size,i;
250
 
251
   rif_cache entry;
252
 
253
        size=sprintf(buffer,
254
"   TR address     rcf             routing segments             TTL\n\n");
255
   pos+=size;
256
   len+=size;
257
 
258
        for(i=0;i < RIF_TABLE_SIZE;i++) {
259
                for(entry=rif_table[i];entry;entry=entry->next) {
260
                        size=sprintf(buffer+len,"%02X:%02X:%02X:%02X:%02X:%02X %04X %04X %04X %04X %04X %04X %04X %04X %04X %lu\n",
261
                                                                entry->addr[0],entry->addr[1],entry->addr[2],entry->addr[3],entry->addr[4],entry->addr[5],
262
                                                                entry->rcf,entry->rseg[0],entry->rseg[1],entry->rseg[2],entry->rseg[3],
263
                                                                entry->rseg[4],entry->rseg[5],entry->rseg[6],entry->rseg[7],jiffies-entry->last_used);
264
                        len+=size;
265
                        pos=begin+len;
266
 
267
                        if(pos<offset) {
268
                                len=0;
269
                                begin=pos;
270
                        }
271
                        if(pos>offset+length)
272
                                break;
273
        }
274
                if(pos>offset+length)
275
                        break;
276
        }
277
 
278
   *start=buffer+(offset-begin); /* Start of wanted data */
279
   len-=(offset-begin);    /* Start slop */
280
   if(len>length)
281
      len=length;    /* Ending slop */
282
   return len;
283
}
284
 
285
void rif_init(struct net_proto *unused) {
286
 
287
        add_timer(&rif_timer);
288
 
289
}
290
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.