Blame view
net/802/tr.c
14.8 KB
1da177e4c Linux-2.6.12-rc2 |
1 2 |
/* * NET3: Token ring device handling subroutines |
9afa0949e [NET] 802: Fix wh... |
3 |
* |
1da177e4c Linux-2.6.12-rc2 |
4 5 6 7 8 9 10 11 12 13 14 |
* 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: 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. * 22 Jun 98 Paul Norton <p.norton@computer.org> Rearranged * tr_header and tr_type_trans to handle passing IPX SNAP and * 802.2 through the correct layers. Eliminated tr_reformat. |
9afa0949e [NET] 802: Fix wh... |
15 |
* |
1da177e4c Linux-2.6.12-rc2 |
16 17 18 19 |
*/ #include <asm/uaccess.h> #include <asm/system.h> |
1da177e4c Linux-2.6.12-rc2 |
20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
#include <linux/module.h> #include <linux/types.h> #include <linux/kernel.h> #include <linux/jiffies.h> #include <linux/string.h> #include <linux/mm.h> #include <linux/socket.h> #include <linux/in.h> #include <linux/inet.h> #include <linux/netdevice.h> #include <linux/trdevice.h> #include <linux/skbuff.h> #include <linux/errno.h> #include <linux/timer.h> #include <linux/net.h> #include <linux/proc_fs.h> #include <linux/seq_file.h> #include <linux/init.h> #include <net/arp.h> |
457c4cbc5 [NET]: Make /proc... |
39 |
#include <net/net_namespace.h> |
1da177e4c Linux-2.6.12-rc2 |
40 41 42 43 44 45 46 47 48 |
static void tr_add_rif_info(struct trh_hdr *trh, struct net_device *dev); static void rif_check_expire(unsigned long dummy); #define TR_SR_DEBUG 0 /* * Each RIF entry we learn is kept this way */ |
9afa0949e [NET] 802: Fix wh... |
49 |
|
c8b35d2a2 [TOKENRING]: net/... |
50 |
struct rif_cache { |
1da177e4c Linux-2.6.12-rc2 |
51 52 |
unsigned char addr[TR_ALEN]; int iface; |
c6b336539 [TOKENRING]: be'i... |
53 54 |
__be16 rcf; __be16 rseg[8]; |
c8b35d2a2 [TOKENRING]: net/... |
55 |
struct rif_cache *next; |
1da177e4c Linux-2.6.12-rc2 |
56 57 58 59 60 61 62 63 64 65 |
unsigned long last_used; unsigned char local_ring; }; #define RIF_TABLE_SIZE 32 /* * We hash the RIF cache 32 ways. We do after all have to look it * up a lot. */ |
9afa0949e [NET] 802: Fix wh... |
66 |
|
c8b35d2a2 [TOKENRING]: net/... |
67 |
static struct rif_cache *rif_table[RIF_TABLE_SIZE]; |
1da177e4c Linux-2.6.12-rc2 |
68 69 70 71 72 73 74 |
static DEFINE_SPINLOCK(rif_lock); /* * Garbage disposal timer. */ |
9afa0949e [NET] 802: Fix wh... |
75 |
|
1da177e4c Linux-2.6.12-rc2 |
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 |
static struct timer_list rif_timer; int sysctl_tr_rif_timeout = 60*10*HZ; static inline unsigned long rif_hash(const unsigned char *addr) { unsigned long x; x = addr[0]; x = (x << 2) ^ addr[1]; x = (x << 2) ^ addr[2]; x = (x << 2) ^ addr[3]; x = (x << 2) ^ addr[4]; x = (x << 2) ^ addr[5]; x ^= x >> 8; return x & (RIF_TABLE_SIZE - 1); } /* * Put the headers on a token ring packet. Token ring source routing * makes this a little more exciting than on ethernet. */ |
9afa0949e [NET] 802: Fix wh... |
100 |
|
1da177e4c Linux-2.6.12-rc2 |
101 102 |
static int tr_header(struct sk_buff *skb, struct net_device *dev, unsigned short type, |
3b04ddde0 [NET]: Move hardw... |
103 |
const void *daddr, const void *saddr, unsigned len) |
1da177e4c Linux-2.6.12-rc2 |
104 105 106 |
{ struct trh_hdr *trh; int hdr_len; |
9afa0949e [NET] 802: Fix wh... |
107 108 |
/* * Add the 802.2 SNAP header if IP as the IPv4/IPv6 code calls |
1da177e4c Linux-2.6.12-rc2 |
109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 |
* dev->hard_header directly. */ if (type == ETH_P_IP || type == ETH_P_IPV6 || type == ETH_P_ARP) { struct trllc *trllc; hdr_len = sizeof(struct trh_hdr) + sizeof(struct trllc); trh = (struct trh_hdr *)skb_push(skb, hdr_len); trllc = (struct trllc *)(trh+1); trllc->dsap = trllc->ssap = EXTENDED_SAP; trllc->llc = UI_CMD; trllc->protid[0] = trllc->protid[1] = trllc->protid[2] = 0x00; trllc->ethertype = htons(type); } else { hdr_len = sizeof(struct trh_hdr); |
9afa0949e [NET] 802: Fix wh... |
126 |
trh = (struct trh_hdr *)skb_push(skb, hdr_len); |
1da177e4c Linux-2.6.12-rc2 |
127 128 129 130 131 132 133 134 135 136 137 138 139 |
} trh->ac=AC; trh->fc=LLC_FRAME; if(saddr) memcpy(trh->saddr,saddr,dev->addr_len); else memcpy(trh->saddr,dev->dev_addr,dev->addr_len); /* * Build the destination and then source route the frame */ |
9afa0949e [NET] 802: Fix wh... |
140 141 |
if(daddr) |
1da177e4c Linux-2.6.12-rc2 |
142 143 |
{ memcpy(trh->daddr,daddr,dev->addr_len); |
3b04ddde0 [NET]: Move hardw... |
144 |
tr_source_route(skb, trh, dev); |
1da177e4c Linux-2.6.12-rc2 |
145 146 147 148 149 |
return(hdr_len); } return -hdr_len; } |
9afa0949e [NET] 802: Fix wh... |
150 |
|
1da177e4c Linux-2.6.12-rc2 |
151 152 153 154 |
/* * A neighbour discovery of some species (eg arp) has completed. We * can now send the packet. */ |
9afa0949e [NET] 802: Fix wh... |
155 156 |
static int tr_rebuild_header(struct sk_buff *skb) |
1da177e4c Linux-2.6.12-rc2 |
157 158 159 160 161 162 163 164 |
{ struct trh_hdr *trh=(struct trh_hdr *)skb->data; struct trllc *trllc=(struct trllc *)(skb->data+sizeof(struct trh_hdr)); struct net_device *dev = skb->dev; /* * FIXME: We don't yet support IPv6 over token rings */ |
9afa0949e [NET] 802: Fix wh... |
165 |
|
1da177e4c Linux-2.6.12-rc2 |
166 |
if(trllc->ethertype != htons(ETH_P_IP)) { |
0ac0760a5 [TR]: endiannness... |
167 168 |
printk("tr_rebuild_header: Don't know how to resolve type %04X addresses ? ", ntohs(trllc->ethertype)); |
1da177e4c Linux-2.6.12-rc2 |
169 170 171 172 173 174 175 |
return 0; } #ifdef CONFIG_INET if(arp_find(trh->daddr, skb)) { return 1; } |
9afa0949e [NET] 802: Fix wh... |
176 177 178 179 |
else #endif { tr_source_route(skb,trh,dev); |
1da177e4c Linux-2.6.12-rc2 |
180 181 182 |
return 0; } } |
9afa0949e [NET] 802: Fix wh... |
183 |
|
1da177e4c Linux-2.6.12-rc2 |
184 185 186 187 188 |
/* * 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. */ |
9afa0949e [NET] 802: Fix wh... |
189 |
|
0ac0760a5 [TR]: endiannness... |
190 |
__be16 tr_type_trans(struct sk_buff *skb, struct net_device *dev) |
1da177e4c Linux-2.6.12-rc2 |
191 |
{ |
c1a4b86e3 [TR]: Use tr_hdr(... |
192 |
struct trh_hdr *trh; |
1da177e4c Linux-2.6.12-rc2 |
193 194 |
struct trllc *trllc; unsigned riflen=0; |
9afa0949e [NET] 802: Fix wh... |
195 |
|
c8fb7948d [TR]: Make tr_typ... |
196 |
skb->dev = dev; |
459a98ed8 [SK_BUFF]: Introd... |
197 |
skb_reset_mac_header(skb); |
c1a4b86e3 [TR]: Use tr_hdr(... |
198 |
trh = tr_hdr(skb); |
9afa0949e [NET] 802: Fix wh... |
199 200 |
if(trh->saddr[0] & TR_RII) |
1da177e4c Linux-2.6.12-rc2 |
201 202 203 204 205 |
riflen = (ntohs(trh->rcf) & TR_RCF_LEN_MASK) >> 8; trllc = (struct trllc *)(skb->data+sizeof(struct trh_hdr)-TR_MAXRIFLEN+riflen); skb_pull(skb,sizeof(struct trh_hdr)-TR_MAXRIFLEN+riflen); |
9afa0949e [NET] 802: Fix wh... |
206 |
if(*trh->daddr & 0x80) |
1da177e4c Linux-2.6.12-rc2 |
207 |
{ |
9afa0949e [NET] 802: Fix wh... |
208 |
if(!memcmp(trh->daddr,dev->broadcast,TR_ALEN)) |
1da177e4c Linux-2.6.12-rc2 |
209 210 211 212 213 214 215 216 |
skb->pkt_type=PACKET_BROADCAST; else skb->pkt_type=PACKET_MULTICAST; } else if ( (trh->daddr[0] & 0x01) && (trh->daddr[1] & 0x00) && (trh->daddr[2] & 0x5E)) { skb->pkt_type=PACKET_MULTICAST; } |
9afa0949e [NET] 802: Fix wh... |
217 |
else if(dev->flags & IFF_PROMISC) |
1da177e4c Linux-2.6.12-rc2 |
218 219 220 221 222 223 224 |
{ if(memcmp(trh->daddr, dev->dev_addr, TR_ALEN)) skb->pkt_type=PACKET_OTHERHOST; } if ((skb->pkt_type != PACKET_BROADCAST) && (skb->pkt_type != PACKET_MULTICAST)) |
9afa0949e [NET] 802: Fix wh... |
225 |
tr_add_rif_info(trh,dev) ; |
1da177e4c Linux-2.6.12-rc2 |
226 227 |
/* |
9afa0949e [NET] 802: Fix wh... |
228 |
* Strip the SNAP header from ARP packets since we don't |
1da177e4c Linux-2.6.12-rc2 |
229 230 231 232 |
* pass them through to the 802.2/SNAP layers. */ if (trllc->dsap == EXTENDED_SAP && |
0ac0760a5 [TR]: endiannness... |
233 234 235 |
(trllc->ethertype == htons(ETH_P_IP) || trllc->ethertype == htons(ETH_P_IPV6) || trllc->ethertype == htons(ETH_P_ARP))) |
1da177e4c Linux-2.6.12-rc2 |
236 237 238 239 |
{ skb_pull(skb, sizeof(struct trllc)); return trllc->ethertype; } |
0ac0760a5 [TR]: endiannness... |
240 |
return htons(ETH_P_TR_802_2); |
1da177e4c Linux-2.6.12-rc2 |
241 242 243 |
} /* |
9afa0949e [NET] 802: Fix wh... |
244 |
* We try to do source routing... |
1da177e4c Linux-2.6.12-rc2 |
245 |
*/ |
3b04ddde0 [NET]: Move hardw... |
246 247 |
void tr_source_route(struct sk_buff *skb,struct trh_hdr *trh, struct net_device *dev) |
1da177e4c Linux-2.6.12-rc2 |
248 249 250 |
{ int slack; unsigned int hash; |
c8b35d2a2 [TOKENRING]: net/... |
251 |
struct rif_cache *entry; |
1da177e4c Linux-2.6.12-rc2 |
252 |
unsigned char *olddata; |
001dd250c [TOKENRING]: Use ... |
253 |
unsigned long flags; |
9afa0949e [NET] 802: Fix wh... |
254 |
static const unsigned char mcast_func_addr[] |
1da177e4c Linux-2.6.12-rc2 |
255 |
= {0xC0,0x00,0x00,0x04,0x00,0x00}; |
9afa0949e [NET] 802: Fix wh... |
256 |
|
001dd250c [TOKENRING]: Use ... |
257 |
spin_lock_irqsave(&rif_lock, flags); |
1da177e4c Linux-2.6.12-rc2 |
258 259 |
/* |
9afa0949e [NET] 802: Fix wh... |
260 |
* Broadcasts are single route as stated in RFC 1042 |
1da177e4c Linux-2.6.12-rc2 |
261 262 263 264 |
*/ if( (!memcmp(&(trh->daddr[0]),&(dev->broadcast[0]),TR_ALEN)) || (!memcmp(&(trh->daddr[0]),&(mcast_func_addr[0]), TR_ALEN)) ) { |
9afa0949e [NET] 802: Fix wh... |
265 |
trh->rcf=htons((((sizeof(trh->rcf)) << 8) & TR_RCF_LEN_MASK) |
1da177e4c Linux-2.6.12-rc2 |
266 267 268 |
| TR_RCF_FRAME2K | TR_RCF_LIMITED_BROADCAST); trh->saddr[0]|=TR_RII; } |
9afa0949e [NET] 802: Fix wh... |
269 |
else |
1da177e4c Linux-2.6.12-rc2 |
270 271 272 273 274 275 276 277 278 279 |
{ hash = rif_hash(trh->daddr); /* * 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 we found an entry we can route the frame. */ |
9afa0949e [NET] 802: Fix wh... |
280 |
if(entry) |
1da177e4c Linux-2.6.12-rc2 |
281 282 |
{ #if TR_SR_DEBUG |
0795af572 [NET]: Introduce ... |
283 284 285 286 287 |
{ DECLARE_MAC_BUF(mac); printk("source routing for %s ",print_mac(mac, trh->daddr)); } |
1da177e4c Linux-2.6.12-rc2 |
288 289 290 291 292 |
#endif 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)); |
9afa0949e [NET] 802: Fix wh... |
293 |
trh->rcf^=htons(TR_RCF_DIR_BIT); |
1da177e4c Linux-2.6.12-rc2 |
294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 |
trh->rcf&=htons(0x1fff); /* Issam Chehab <ichehab@madge1.demon.co.uk> */ trh->saddr[0]|=TR_RII; #if TR_SR_DEBUG printk("entry found with rcf %04x ", entry->rcf); } else { printk("entry found but without rcf length, local=%02x ", entry->local_ring); #endif } entry->last_used=jiffies; } |
9afa0949e [NET] 802: Fix wh... |
309 |
else |
1da177e4c Linux-2.6.12-rc2 |
310 311 312 313 314 315 |
{ /* * Without the information we simply have to shout * on the wire. The replies should rapidly clean this * situation up. */ |
9afa0949e [NET] 802: Fix wh... |
316 |
trh->rcf=htons((((sizeof(trh->rcf)) << 8) & TR_RCF_LEN_MASK) |
1da177e4c Linux-2.6.12-rc2 |
317 318 319 320 321 322 323 324 325 326 327 328 |
| TR_RCF_FRAME2K | TR_RCF_LIMITED_BROADCAST); trh->saddr[0]|=TR_RII; #if TR_SR_DEBUG printk("no entry in rif table found - broadcasting frame "); #endif } } /* Compress the RIF here so we don't have to do it in the driver(s) */ if (!(trh->saddr[0] & 0x80)) slack = 18; |
9afa0949e [NET] 802: Fix wh... |
329 |
else |
1da177e4c Linux-2.6.12-rc2 |
330 331 |
slack = 18 - ((ntohs(trh->rcf) & TR_RCF_LEN_MASK)>>8); olddata = skb->data; |
001dd250c [TOKENRING]: Use ... |
332 |
spin_unlock_irqrestore(&rif_lock, flags); |
1da177e4c Linux-2.6.12-rc2 |
333 334 335 336 337 338 339 340 341 |
skb_pull(skb, slack); memmove(skb->data, olddata, sizeof(struct trh_hdr) - slack); } /* * We have learned some new RIF information for our source * routing. */ |
9afa0949e [NET] 802: Fix wh... |
342 |
|
1da177e4c Linux-2.6.12-rc2 |
343 344 345 |
static void tr_add_rif_info(struct trh_hdr *trh, struct net_device *dev) { unsigned int hash, rii_p = 0; |
001dd250c [TOKENRING]: Use ... |
346 |
unsigned long flags; |
c8b35d2a2 [TOKENRING]: net/... |
347 |
struct rif_cache *entry; |
5ac660ee1 [TR]: Preserve RI... |
348 |
unsigned char saddr0; |
1da177e4c Linux-2.6.12-rc2 |
349 |
|
001dd250c [TOKENRING]: Use ... |
350 |
spin_lock_irqsave(&rif_lock, flags); |
5ac660ee1 [TR]: Preserve RI... |
351 |
saddr0 = trh->saddr[0]; |
9afa0949e [NET] 802: Fix wh... |
352 |
|
1da177e4c Linux-2.6.12-rc2 |
353 354 355 |
/* * Firstly see if the entry exists */ |
9afa0949e [NET] 802: Fix wh... |
356 |
if(trh->saddr[0] & TR_RII) |
1da177e4c Linux-2.6.12-rc2 |
357 358 359 360 361 |
{ trh->saddr[0]&=0x7f; if (((ntohs(trh->rcf) & TR_RCF_LEN_MASK) >> 8) > 2) { rii_p = 1; |
9afa0949e [NET] 802: Fix wh... |
362 |
} |
1da177e4c Linux-2.6.12-rc2 |
363 364 365 366 |
} hash = rif_hash(trh->saddr); for(entry=rif_table[hash];entry && memcmp(&(entry->addr[0]),&(trh->saddr[0]),TR_ALEN);entry=entry->next); |
9afa0949e [NET] 802: Fix wh... |
367 |
if(entry==NULL) |
1da177e4c Linux-2.6.12-rc2 |
368 369 |
{ #if TR_SR_DEBUG |
0795af572 [NET]: Introduce ... |
370 371 372 373 |
DECLARE_MAC_BUF(mac); printk("adding rif_entry: addr:%s rcf:%04X ", print_mac(mac, trh->saddr), ntohs(trh->rcf)); |
1da177e4c Linux-2.6.12-rc2 |
374 375 376 377 378 379 380 381 |
#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. */ |
c8b35d2a2 [TOKENRING]: net/... |
382 |
entry=kmalloc(sizeof(struct rif_cache),GFP_ATOMIC); |
1da177e4c Linux-2.6.12-rc2 |
383 |
|
9afa0949e [NET] 802: Fix wh... |
384 |
if(!entry) |
1da177e4c Linux-2.6.12-rc2 |
385 386 387 |
{ printk(KERN_DEBUG "tr.c: Couldn't malloc rif cache entry ! "); |
001dd250c [TOKENRING]: Use ... |
388 |
spin_unlock_irqrestore(&rif_lock, flags); |
1da177e4c Linux-2.6.12-rc2 |
389 390 391 392 393 394 395 396 397 398 399 400 401 402 |
return; } memcpy(&(entry->addr[0]),&(trh->saddr[0]),TR_ALEN); entry->iface = dev->ifindex; entry->next=rif_table[hash]; entry->last_used=jiffies; rif_table[hash]=entry; 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; |
1da177e4c Linux-2.6.12-rc2 |
403 404 405 406 407 |
} else { entry->local_ring = 1; } |
9afa0949e [NET] 802: Fix wh... |
408 |
} |
1da177e4c Linux-2.6.12-rc2 |
409 |
else /* Y. Tahara added */ |
9afa0949e [NET] 802: Fix wh... |
410 |
{ |
1da177e4c Linux-2.6.12-rc2 |
411 412 413 |
/* * Update existing entries */ |
9afa0949e [NET] 802: Fix wh... |
414 |
if (!entry->local_ring) |
1da177e4c Linux-2.6.12-rc2 |
415 416 417 418 |
if (entry->rcf != (trh->rcf & htons((unsigned short)~TR_RCF_BROADCAST_MASK)) && !(trh->rcf & htons(TR_RCF_BROADCAST_MASK))) { #if TR_SR_DEBUG |
0795af572 [NET]: Introduce ... |
419 420 421 422 423 424 |
{ DECLARE_MAC_BUF(mac); printk("updating rif_entry: addr:%s rcf:%04X ", print_mac(mac, trh->saddr), ntohs(trh->rcf)); } |
1da177e4c Linux-2.6.12-rc2 |
425 426 |
#endif entry->rcf = trh->rcf & htons((unsigned short)~TR_RCF_BROADCAST_MASK); |
9afa0949e [NET] 802: Fix wh... |
427 428 429 |
memcpy(&(entry->rseg[0]),&(trh->rseg[0]),8*sizeof(unsigned short)); } entry->last_used=jiffies; |
1da177e4c Linux-2.6.12-rc2 |
430 |
} |
5ac660ee1 [TR]: Preserve RI... |
431 |
trh->saddr[0]=saddr0; /* put the routing indicator back for tcpdump */ |
001dd250c [TOKENRING]: Use ... |
432 |
spin_unlock_irqrestore(&rif_lock, flags); |
1da177e4c Linux-2.6.12-rc2 |
433 434 435 436 437 |
} /* * Scan the cache with a timer and see what we need to throw out. */ |
9afa0949e [NET] 802: Fix wh... |
438 |
static void rif_check_expire(unsigned long dummy) |
1da177e4c Linux-2.6.12-rc2 |
439 440 |
{ int i; |
001dd250c [TOKENRING]: Use ... |
441 |
unsigned long flags, next_interval = jiffies + sysctl_tr_rif_timeout/2; |
1da177e4c Linux-2.6.12-rc2 |
442 |
|
001dd250c [TOKENRING]: Use ... |
443 |
spin_lock_irqsave(&rif_lock, flags); |
9afa0949e [NET] 802: Fix wh... |
444 |
|
1da177e4c Linux-2.6.12-rc2 |
445 |
for(i =0; i < RIF_TABLE_SIZE; i++) { |
c8b35d2a2 [TOKENRING]: net/... |
446 |
struct rif_cache *entry, **pentry; |
9afa0949e [NET] 802: Fix wh... |
447 |
|
1da177e4c Linux-2.6.12-rc2 |
448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 |
pentry = rif_table+i; while((entry=*pentry) != NULL) { unsigned long expires = entry->last_used + sysctl_tr_rif_timeout; if (time_before_eq(expires, jiffies)) { *pentry = entry->next; kfree(entry); } else { pentry = &entry->next; if (time_before(expires, next_interval)) next_interval = expires; } } } |
9afa0949e [NET] 802: Fix wh... |
464 |
|
001dd250c [TOKENRING]: Use ... |
465 |
spin_unlock_irqrestore(&rif_lock, flags); |
1da177e4c Linux-2.6.12-rc2 |
466 467 468 469 470 471 472 473 474 |
mod_timer(&rif_timer, next_interval); } /* * Generate the /proc/net information for the token ring RIF * routing. */ |
9afa0949e [NET] 802: Fix wh... |
475 |
|
1da177e4c Linux-2.6.12-rc2 |
476 |
#ifdef CONFIG_PROC_FS |
c8b35d2a2 [TOKENRING]: net/... |
477 |
static struct rif_cache *rif_get_idx(loff_t pos) |
1da177e4c Linux-2.6.12-rc2 |
478 479 |
{ int i; |
c8b35d2a2 [TOKENRING]: net/... |
480 |
struct rif_cache *entry; |
1da177e4c Linux-2.6.12-rc2 |
481 |
loff_t off = 0; |
9afa0949e [NET] 802: Fix wh... |
482 |
for(i = 0; i < RIF_TABLE_SIZE; i++) |
1da177e4c Linux-2.6.12-rc2 |
483 484 485 486 487 488 489 490 491 492 493 |
for(entry = rif_table[i]; entry; entry = entry->next) { if (off == pos) return entry; ++off; } return NULL; } static void *rif_seq_start(struct seq_file *seq, loff_t *pos) { |
001dd250c [TOKENRING]: Use ... |
494 |
spin_lock_irq(&rif_lock); |
1da177e4c Linux-2.6.12-rc2 |
495 496 497 498 499 500 501 |
return *pos ? rif_get_idx(*pos - 1) : SEQ_START_TOKEN; } static void *rif_seq_next(struct seq_file *seq, void *v, loff_t *pos) { int i; |
c8b35d2a2 [TOKENRING]: net/... |
502 |
struct rif_cache *ent = v; |
1da177e4c Linux-2.6.12-rc2 |
503 504 505 506 507 508 509 |
++*pos; if (v == SEQ_START_TOKEN) { i = -1; goto scan; } |
9afa0949e [NET] 802: Fix wh... |
510 |
if (ent->next) |
1da177e4c Linux-2.6.12-rc2 |
511 512 513 514 515 516 517 518 519 520 521 522 523 |
return ent->next; i = rif_hash(ent->addr); scan: while (++i < RIF_TABLE_SIZE) { if ((ent = rif_table[i]) != NULL) return ent; } return NULL; } static void rif_seq_stop(struct seq_file *seq, void *v) { |
001dd250c [TOKENRING]: Use ... |
524 |
spin_unlock_irq(&rif_lock); |
1da177e4c Linux-2.6.12-rc2 |
525 526 527 528 529 |
} static int rif_seq_show(struct seq_file *seq, void *v) { int j, rcf_len, segment, brdgnmb; |
c8b35d2a2 [TOKENRING]: net/... |
530 |
struct rif_cache *entry = v; |
0795af572 [NET]: Introduce ... |
531 |
DECLARE_MAC_BUF(mac); |
1da177e4c Linux-2.6.12-rc2 |
532 533 534 535 536 537 |
if (v == SEQ_START_TOKEN) seq_puts(seq, "if TR address TTL rcf routing segments "); else { |
881d966b4 [NET]: Make the d... |
538 |
struct net_device *dev = dev_get_by_index(&init_net, entry->iface); |
1da177e4c Linux-2.6.12-rc2 |
539 540 |
long ttl = (long) (entry->last_used + sysctl_tr_rif_timeout) - (long) jiffies; |
0795af572 [NET]: Introduce ... |
541 |
seq_printf(seq, "%s %s %7li ", |
1da177e4c Linux-2.6.12-rc2 |
542 |
dev?dev->name:"?", |
0795af572 [NET]: Introduce ... |
543 |
print_mac(mac, entry->addr), |
1da177e4c Linux-2.6.12-rc2 |
544 545 546 |
ttl/HZ); if (entry->local_ring) |
9afa0949e [NET] 802: Fix wh... |
547 548 |
seq_puts(seq, "local "); |
1da177e4c Linux-2.6.12-rc2 |
549 550 551 |
else { seq_printf(seq, "%04X", ntohs(entry->rcf)); |
9afa0949e [NET] 802: Fix wh... |
552 |
rcf_len = ((ntohs(entry->rcf) & TR_RCF_LEN_MASK)>>8)-2; |
1da177e4c Linux-2.6.12-rc2 |
553 |
if (rcf_len) |
9afa0949e [NET] 802: Fix wh... |
554 |
rcf_len >>= 1; |
1da177e4c Linux-2.6.12-rc2 |
555 556 557 558 |
for(j = 1; j < rcf_len; j++) { if(j==1) { segment=ntohs(entry->rseg[j-1])>>4; seq_printf(seq," %03X",segment); |
3ff50b799 [NET]: cleanup ex... |
559 |
} |
1da177e4c Linux-2.6.12-rc2 |
560 561 562 563 564 565 566 |
segment=ntohs(entry->rseg[j])>>4; brdgnmb=ntohs(entry->rseg[j-1])&0x00f; seq_printf(seq,"-%01X-%03X",brdgnmb,segment); } seq_putc(seq, ' '); } |
9afa0949e [NET] 802: Fix wh... |
567 |
} |
1da177e4c Linux-2.6.12-rc2 |
568 569 |
return 0; } |
56b3d975b [NET]: Make all i... |
570 |
static const struct seq_operations rif_seq_ops = { |
1da177e4c Linux-2.6.12-rc2 |
571 572 573 574 575 576 577 578 579 580 |
.start = rif_seq_start, .next = rif_seq_next, .stop = rif_seq_stop, .show = rif_seq_show, }; static int rif_seq_open(struct inode *inode, struct file *file) { return seq_open(file, &rif_seq_ops); } |
9a32144e9 [PATCH] mark stru... |
581 |
static const struct file_operations rif_seq_fops = { |
1da177e4c Linux-2.6.12-rc2 |
582 583 584 585 586 587 588 589 |
.owner = THIS_MODULE, .open = rif_seq_open, .read = seq_read, .llseek = seq_lseek, .release = seq_release, }; #endif |
3b04ddde0 [NET]: Move hardw... |
590 591 592 593 |
static const struct header_ops tr_header_ops = { .create = tr_header, .rebuild= tr_rebuild_header, }; |
1da177e4c Linux-2.6.12-rc2 |
594 595 596 597 598 |
static void tr_setup(struct net_device *dev) { /* * Configure and register */ |
9afa0949e [NET] 802: Fix wh... |
599 |
|
3b04ddde0 [NET]: Move hardw... |
600 |
dev->header_ops = &tr_header_ops; |
1da177e4c Linux-2.6.12-rc2 |
601 602 603 604 605 606 |
dev->type = ARPHRD_IEEE802_TR; dev->hard_header_len = TR_HLEN; dev->mtu = 2000; dev->addr_len = TR_ALEN; dev->tx_queue_len = 100; /* Long queues on tr */ |
9afa0949e [NET] 802: Fix wh... |
607 |
|
1da177e4c Linux-2.6.12-rc2 |
608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 |
memset(dev->broadcast,0xFF, TR_ALEN); /* New-style flags. */ dev->flags = IFF_BROADCAST | IFF_MULTICAST ; } /** * alloc_trdev - Register token ring device * @sizeof_priv: Size of additional driver-private structure to be allocated * for this token ring device * * Fill in the fields of the device structure with token ring-generic values. * * Constructs a new net device, complete with a private data area of * size @sizeof_priv. A 32-byte (not bit) alignment is enforced for * this private data area. */ struct net_device *alloc_trdev(int sizeof_priv) { return alloc_netdev(sizeof_priv, "tr%d", tr_setup); } /* * Called during bootup. We don't actually have to initialise * too much for this. */ static int __init rif_init(void) { init_timer(&rif_timer); rif_timer.expires = sysctl_tr_rif_timeout; rif_timer.data = 0L; rif_timer.function = rif_check_expire; add_timer(&rif_timer); |
457c4cbc5 [NET]: Make /proc... |
642 |
proc_net_fops_create(&init_net, "tr_rif", S_IRUGO, &rif_seq_fops); |
1da177e4c Linux-2.6.12-rc2 |
643 644 645 646 |
return 0; } module_init(rif_init); |
1da177e4c Linux-2.6.12-rc2 |
647 648 |
EXPORT_SYMBOL(tr_type_trans); EXPORT_SYMBOL(alloc_trdev); |