Blame view
net/802/tr.c
15.1 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 |
#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> |
36f0bebd9 [TR]: Use ctl pat... |
38 |
#include <linux/sysctl.h> |
5a0e3ad6a include cleanup: ... |
39 |
#include <linux/slab.h> |
1da177e4c Linux-2.6.12-rc2 |
40 |
#include <net/arp.h> |
457c4cbc5 [NET]: Make /proc... |
41 |
#include <net/net_namespace.h> |
1da177e4c Linux-2.6.12-rc2 |
42 43 44 45 46 47 48 49 50 |
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... |
51 |
|
c8b35d2a2 [TOKENRING]: net/... |
52 |
struct rif_cache { |
1da177e4c Linux-2.6.12-rc2 |
53 54 |
unsigned char addr[TR_ALEN]; int iface; |
c6b336539 [TOKENRING]: be'i... |
55 56 |
__be16 rcf; __be16 rseg[8]; |
c8b35d2a2 [TOKENRING]: net/... |
57 |
struct rif_cache *next; |
1da177e4c Linux-2.6.12-rc2 |
58 59 60 61 62 63 64 65 66 67 |
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... |
68 |
|
c8b35d2a2 [TOKENRING]: net/... |
69 |
static struct rif_cache *rif_table[RIF_TABLE_SIZE]; |
1da177e4c Linux-2.6.12-rc2 |
70 71 72 73 74 75 76 |
static DEFINE_SPINLOCK(rif_lock); /* * Garbage disposal timer. */ |
9afa0949e [NET] 802: Fix wh... |
77 |
|
1da177e4c Linux-2.6.12-rc2 |
78 |
static struct timer_list rif_timer; |
81a21eb4e [TR] net/802/tr.c... |
79 |
static int sysctl_tr_rif_timeout = 60*10*HZ; |
1da177e4c Linux-2.6.12-rc2 |
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 |
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... |
101 |
|
1da177e4c Linux-2.6.12-rc2 |
102 103 |
static int tr_header(struct sk_buff *skb, struct net_device *dev, unsigned short type, |
3b04ddde0 [NET]: Move hardw... |
104 |
const void *daddr, const void *saddr, unsigned len) |
1da177e4c Linux-2.6.12-rc2 |
105 106 107 |
{ struct trh_hdr *trh; int hdr_len; |
9afa0949e [NET] 802: Fix wh... |
108 109 |
/* * Add the 802.2 SNAP header if IP as the IPv4/IPv6 code calls |
1da177e4c Linux-2.6.12-rc2 |
110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 |
* 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... |
127 |
trh = (struct trh_hdr *)skb_push(skb, hdr_len); |
1da177e4c Linux-2.6.12-rc2 |
128 129 130 131 132 133 134 135 136 137 138 139 140 |
} 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... |
141 142 |
if(daddr) |
1da177e4c Linux-2.6.12-rc2 |
143 144 |
{ memcpy(trh->daddr,daddr,dev->addr_len); |
3b04ddde0 [NET]: Move hardw... |
145 |
tr_source_route(skb, trh, dev); |
a02cec215 net: return opera... |
146 |
return hdr_len; |
1da177e4c Linux-2.6.12-rc2 |
147 148 149 150 |
} return -hdr_len; } |
9afa0949e [NET] 802: Fix wh... |
151 |
|
1da177e4c Linux-2.6.12-rc2 |
152 153 154 155 |
/* * A neighbour discovery of some species (eg arp) has completed. We * can now send the packet. */ |
9afa0949e [NET] 802: Fix wh... |
156 157 |
static int tr_rebuild_header(struct sk_buff *skb) |
1da177e4c Linux-2.6.12-rc2 |
158 159 160 161 162 163 164 165 |
{ 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... |
166 |
|
1da177e4c Linux-2.6.12-rc2 |
167 |
if(trllc->ethertype != htons(ETH_P_IP)) { |
0ac0760a5 [TR]: endiannness... |
168 169 |
printk("tr_rebuild_header: Don't know how to resolve type %04X addresses ? ", ntohs(trllc->ethertype)); |
1da177e4c Linux-2.6.12-rc2 |
170 171 172 173 174 175 176 |
return 0; } #ifdef CONFIG_INET if(arp_find(trh->daddr, skb)) { return 1; } |
9afa0949e [NET] 802: Fix wh... |
177 178 179 180 |
else #endif { tr_source_route(skb,trh,dev); |
1da177e4c Linux-2.6.12-rc2 |
181 182 183 |
return 0; } } |
9afa0949e [NET] 802: Fix wh... |
184 |
|
1da177e4c Linux-2.6.12-rc2 |
185 186 187 188 189 |
/* * 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... |
190 |
|
0ac0760a5 [TR]: endiannness... |
191 |
__be16 tr_type_trans(struct sk_buff *skb, struct net_device *dev) |
1da177e4c Linux-2.6.12-rc2 |
192 |
{ |
c1a4b86e3 [TR]: Use tr_hdr(... |
193 |
struct trh_hdr *trh; |
1da177e4c Linux-2.6.12-rc2 |
194 195 |
struct trllc *trllc; unsigned riflen=0; |
9afa0949e [NET] 802: Fix wh... |
196 |
|
c8fb7948d [TR]: Make tr_typ... |
197 |
skb->dev = dev; |
459a98ed8 [SK_BUFF]: Introd... |
198 |
skb_reset_mac_header(skb); |
c1a4b86e3 [TR]: Use tr_hdr(... |
199 |
trh = tr_hdr(skb); |
9afa0949e [NET] 802: Fix wh... |
200 201 |
if(trh->saddr[0] & TR_RII) |
1da177e4c Linux-2.6.12-rc2 |
202 203 204 205 206 |
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... |
207 |
if(*trh->daddr & 0x80) |
1da177e4c Linux-2.6.12-rc2 |
208 |
{ |
9afa0949e [NET] 802: Fix wh... |
209 |
if(!memcmp(trh->daddr,dev->broadcast,TR_ALEN)) |
1da177e4c Linux-2.6.12-rc2 |
210 211 212 213 214 215 216 217 |
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... |
218 |
else if(dev->flags & IFF_PROMISC) |
1da177e4c Linux-2.6.12-rc2 |
219 220 221 222 223 224 225 |
{ 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... |
226 |
tr_add_rif_info(trh,dev) ; |
1da177e4c Linux-2.6.12-rc2 |
227 228 |
/* |
9afa0949e [NET] 802: Fix wh... |
229 |
* Strip the SNAP header from ARP packets since we don't |
1da177e4c Linux-2.6.12-rc2 |
230 231 232 233 |
* pass them through to the 802.2/SNAP layers. */ if (trllc->dsap == EXTENDED_SAP && |
0ac0760a5 [TR]: endiannness... |
234 235 236 |
(trllc->ethertype == htons(ETH_P_IP) || trllc->ethertype == htons(ETH_P_IPV6) || trllc->ethertype == htons(ETH_P_ARP))) |
1da177e4c Linux-2.6.12-rc2 |
237 238 239 240 |
{ skb_pull(skb, sizeof(struct trllc)); return trllc->ethertype; } |
0ac0760a5 [TR]: endiannness... |
241 |
return htons(ETH_P_TR_802_2); |
1da177e4c Linux-2.6.12-rc2 |
242 243 244 |
} /* |
9afa0949e [NET] 802: Fix wh... |
245 |
* We try to do source routing... |
1da177e4c Linux-2.6.12-rc2 |
246 |
*/ |
3b04ddde0 [NET]: Move hardw... |
247 248 |
void tr_source_route(struct sk_buff *skb,struct trh_hdr *trh, struct net_device *dev) |
1da177e4c Linux-2.6.12-rc2 |
249 250 251 |
{ int slack; unsigned int hash; |
c8b35d2a2 [TOKENRING]: net/... |
252 |
struct rif_cache *entry; |
1da177e4c Linux-2.6.12-rc2 |
253 |
unsigned char *olddata; |
001dd250c [TOKENRING]: Use ... |
254 |
unsigned long flags; |
9afa0949e [NET] 802: Fix wh... |
255 |
static const unsigned char mcast_func_addr[] |
1da177e4c Linux-2.6.12-rc2 |
256 |
= {0xC0,0x00,0x00,0x04,0x00,0x00}; |
9afa0949e [NET] 802: Fix wh... |
257 |
|
001dd250c [TOKENRING]: Use ... |
258 |
spin_lock_irqsave(&rif_lock, flags); |
1da177e4c Linux-2.6.12-rc2 |
259 260 |
/* |
9afa0949e [NET] 802: Fix wh... |
261 |
* Broadcasts are single route as stated in RFC 1042 |
1da177e4c Linux-2.6.12-rc2 |
262 263 264 265 |
*/ 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... |
266 |
trh->rcf=htons((((sizeof(trh->rcf)) << 8) & TR_RCF_LEN_MASK) |
1da177e4c Linux-2.6.12-rc2 |
267 268 269 |
| TR_RCF_FRAME2K | TR_RCF_LIMITED_BROADCAST); trh->saddr[0]|=TR_RII; } |
9afa0949e [NET] 802: Fix wh... |
270 |
else |
1da177e4c Linux-2.6.12-rc2 |
271 272 273 274 275 276 277 278 279 280 |
{ 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... |
281 |
if(entry) |
1da177e4c Linux-2.6.12-rc2 |
282 283 |
{ #if TR_SR_DEBUG |
e174961ca net: convert prin... |
284 285 |
printk("source routing for %pM ", trh->daddr); |
1da177e4c Linux-2.6.12-rc2 |
286 287 288 289 290 |
#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... |
291 |
trh->rcf^=htons(TR_RCF_DIR_BIT); |
1da177e4c Linux-2.6.12-rc2 |
292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 |
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... |
307 |
else |
1da177e4c Linux-2.6.12-rc2 |
308 309 310 311 312 313 |
{ /* * Without the information we simply have to shout * on the wire. The replies should rapidly clean this * situation up. */ |
9afa0949e [NET] 802: Fix wh... |
314 |
trh->rcf=htons((((sizeof(trh->rcf)) << 8) & TR_RCF_LEN_MASK) |
1da177e4c Linux-2.6.12-rc2 |
315 316 317 318 319 320 321 322 323 324 325 326 |
| 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... |
327 |
else |
1da177e4c Linux-2.6.12-rc2 |
328 329 |
slack = 18 - ((ntohs(trh->rcf) & TR_RCF_LEN_MASK)>>8); olddata = skb->data; |
001dd250c [TOKENRING]: Use ... |
330 |
spin_unlock_irqrestore(&rif_lock, flags); |
1da177e4c Linux-2.6.12-rc2 |
331 332 333 334 335 336 337 338 339 |
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... |
340 |
|
1da177e4c Linux-2.6.12-rc2 |
341 342 343 |
static void tr_add_rif_info(struct trh_hdr *trh, struct net_device *dev) { unsigned int hash, rii_p = 0; |
001dd250c [TOKENRING]: Use ... |
344 |
unsigned long flags; |
c8b35d2a2 [TOKENRING]: net/... |
345 |
struct rif_cache *entry; |
5ac660ee1 [TR]: Preserve RI... |
346 |
unsigned char saddr0; |
1da177e4c Linux-2.6.12-rc2 |
347 |
|
001dd250c [TOKENRING]: Use ... |
348 |
spin_lock_irqsave(&rif_lock, flags); |
5ac660ee1 [TR]: Preserve RI... |
349 |
saddr0 = trh->saddr[0]; |
9afa0949e [NET] 802: Fix wh... |
350 |
|
1da177e4c Linux-2.6.12-rc2 |
351 352 353 |
/* * Firstly see if the entry exists */ |
9afa0949e [NET] 802: Fix wh... |
354 |
if(trh->saddr[0] & TR_RII) |
1da177e4c Linux-2.6.12-rc2 |
355 356 357 358 359 |
{ trh->saddr[0]&=0x7f; if (((ntohs(trh->rcf) & TR_RCF_LEN_MASK) >> 8) > 2) { rii_p = 1; |
9afa0949e [NET] 802: Fix wh... |
360 |
} |
1da177e4c Linux-2.6.12-rc2 |
361 362 363 364 |
} 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... |
365 |
if(entry==NULL) |
1da177e4c Linux-2.6.12-rc2 |
366 367 |
{ #if TR_SR_DEBUG |
e174961ca net: convert prin... |
368 369 370 |
printk("adding rif_entry: addr:%pM rcf:%04X ", trh->saddr, ntohs(trh->rcf)); |
1da177e4c Linux-2.6.12-rc2 |
371 372 373 374 375 376 377 378 |
#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/... |
379 |
entry=kmalloc(sizeof(struct rif_cache),GFP_ATOMIC); |
1da177e4c Linux-2.6.12-rc2 |
380 |
|
9afa0949e [NET] 802: Fix wh... |
381 |
if(!entry) |
1da177e4c Linux-2.6.12-rc2 |
382 383 384 |
{ printk(KERN_DEBUG "tr.c: Couldn't malloc rif cache entry ! "); |
001dd250c [TOKENRING]: Use ... |
385 |
spin_unlock_irqrestore(&rif_lock, flags); |
1da177e4c Linux-2.6.12-rc2 |
386 387 388 389 390 391 392 393 394 395 396 397 398 399 |
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 |
400 401 402 403 404 |
} else { entry->local_ring = 1; } |
9afa0949e [NET] 802: Fix wh... |
405 |
} |
1da177e4c Linux-2.6.12-rc2 |
406 |
else /* Y. Tahara added */ |
9afa0949e [NET] 802: Fix wh... |
407 |
{ |
1da177e4c Linux-2.6.12-rc2 |
408 409 410 |
/* * Update existing entries */ |
9afa0949e [NET] 802: Fix wh... |
411 |
if (!entry->local_ring) |
1da177e4c Linux-2.6.12-rc2 |
412 413 414 415 |
if (entry->rcf != (trh->rcf & htons((unsigned short)~TR_RCF_BROADCAST_MASK)) && !(trh->rcf & htons(TR_RCF_BROADCAST_MASK))) { #if TR_SR_DEBUG |
e174961ca net: convert prin... |
416 417 418 |
printk("updating rif_entry: addr:%pM rcf:%04X ", trh->saddr, ntohs(trh->rcf)); |
1da177e4c Linux-2.6.12-rc2 |
419 420 |
#endif entry->rcf = trh->rcf & htons((unsigned short)~TR_RCF_BROADCAST_MASK); |
9afa0949e [NET] 802: Fix wh... |
421 422 423 |
memcpy(&(entry->rseg[0]),&(trh->rseg[0]),8*sizeof(unsigned short)); } entry->last_used=jiffies; |
1da177e4c Linux-2.6.12-rc2 |
424 |
} |
5ac660ee1 [TR]: Preserve RI... |
425 |
trh->saddr[0]=saddr0; /* put the routing indicator back for tcpdump */ |
001dd250c [TOKENRING]: Use ... |
426 |
spin_unlock_irqrestore(&rif_lock, flags); |
1da177e4c Linux-2.6.12-rc2 |
427 428 429 430 431 |
} /* * Scan the cache with a timer and see what we need to throw out. */ |
9afa0949e [NET] 802: Fix wh... |
432 |
static void rif_check_expire(unsigned long dummy) |
1da177e4c Linux-2.6.12-rc2 |
433 434 |
{ int i; |
001dd250c [TOKENRING]: Use ... |
435 |
unsigned long flags, next_interval = jiffies + sysctl_tr_rif_timeout/2; |
1da177e4c Linux-2.6.12-rc2 |
436 |
|
001dd250c [TOKENRING]: Use ... |
437 |
spin_lock_irqsave(&rif_lock, flags); |
9afa0949e [NET] 802: Fix wh... |
438 |
|
1da177e4c Linux-2.6.12-rc2 |
439 |
for(i =0; i < RIF_TABLE_SIZE; i++) { |
c8b35d2a2 [TOKENRING]: net/... |
440 |
struct rif_cache *entry, **pentry; |
9afa0949e [NET] 802: Fix wh... |
441 |
|
1da177e4c Linux-2.6.12-rc2 |
442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 |
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... |
458 |
|
001dd250c [TOKENRING]: Use ... |
459 |
spin_unlock_irqrestore(&rif_lock, flags); |
1da177e4c Linux-2.6.12-rc2 |
460 461 462 463 464 465 466 467 468 |
mod_timer(&rif_timer, next_interval); } /* * Generate the /proc/net information for the token ring RIF * routing. */ |
9afa0949e [NET] 802: Fix wh... |
469 |
|
1da177e4c Linux-2.6.12-rc2 |
470 |
#ifdef CONFIG_PROC_FS |
c8b35d2a2 [TOKENRING]: net/... |
471 |
static struct rif_cache *rif_get_idx(loff_t pos) |
1da177e4c Linux-2.6.12-rc2 |
472 473 |
{ int i; |
c8b35d2a2 [TOKENRING]: net/... |
474 |
struct rif_cache *entry; |
1da177e4c Linux-2.6.12-rc2 |
475 |
loff_t off = 0; |
9afa0949e [NET] 802: Fix wh... |
476 |
for(i = 0; i < RIF_TABLE_SIZE; i++) |
1da177e4c Linux-2.6.12-rc2 |
477 478 479 480 481 482 483 484 485 486 |
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) |
81c553299 net/802: fix spar... |
487 |
__acquires(&rif_lock) |
1da177e4c Linux-2.6.12-rc2 |
488 |
{ |
001dd250c [TOKENRING]: Use ... |
489 |
spin_lock_irq(&rif_lock); |
1da177e4c Linux-2.6.12-rc2 |
490 491 492 493 494 495 496 |
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/... |
497 |
struct rif_cache *ent = v; |
1da177e4c Linux-2.6.12-rc2 |
498 499 500 501 502 503 504 |
++*pos; if (v == SEQ_START_TOKEN) { i = -1; goto scan; } |
9afa0949e [NET] 802: Fix wh... |
505 |
if (ent->next) |
1da177e4c Linux-2.6.12-rc2 |
506 507 508 509 510 511 512 513 514 515 516 517 |
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) |
81c553299 net/802: fix spar... |
518 |
__releases(&rif_lock) |
1da177e4c Linux-2.6.12-rc2 |
519 |
{ |
001dd250c [TOKENRING]: Use ... |
520 |
spin_unlock_irq(&rif_lock); |
1da177e4c Linux-2.6.12-rc2 |
521 522 523 524 525 |
} static int rif_seq_show(struct seq_file *seq, void *v) { int j, rcf_len, segment, brdgnmb; |
c8b35d2a2 [TOKENRING]: net/... |
526 |
struct rif_cache *entry = v; |
1da177e4c Linux-2.6.12-rc2 |
527 528 529 530 531 532 |
if (v == SEQ_START_TOKEN) seq_puts(seq, "if TR address TTL rcf routing segments "); else { |
881d966b4 [NET]: Make the d... |
533 |
struct net_device *dev = dev_get_by_index(&init_net, entry->iface); |
1da177e4c Linux-2.6.12-rc2 |
534 535 |
long ttl = (long) (entry->last_used + sysctl_tr_rif_timeout) - (long) jiffies; |
e174961ca net: convert prin... |
536 |
seq_printf(seq, "%s %pM %7li ", |
1da177e4c Linux-2.6.12-rc2 |
537 |
dev?dev->name:"?", |
e174961ca net: convert prin... |
538 |
entry->addr, |
1da177e4c Linux-2.6.12-rc2 |
539 540 541 |
ttl/HZ); if (entry->local_ring) |
9afa0949e [NET] 802: Fix wh... |
542 543 |
seq_puts(seq, "local "); |
1da177e4c Linux-2.6.12-rc2 |
544 545 546 |
else { seq_printf(seq, "%04X", ntohs(entry->rcf)); |
9afa0949e [NET] 802: Fix wh... |
547 |
rcf_len = ((ntohs(entry->rcf) & TR_RCF_LEN_MASK)>>8)-2; |
1da177e4c Linux-2.6.12-rc2 |
548 |
if (rcf_len) |
9afa0949e [NET] 802: Fix wh... |
549 |
rcf_len >>= 1; |
1da177e4c Linux-2.6.12-rc2 |
550 551 552 553 |
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... |
554 |
} |
1da177e4c Linux-2.6.12-rc2 |
555 556 557 558 559 560 561 |
segment=ntohs(entry->rseg[j])>>4; brdgnmb=ntohs(entry->rseg[j-1])&0x00f; seq_printf(seq,"-%01X-%03X",brdgnmb,segment); } seq_putc(seq, ' '); } |
3384901f1 tr: fix leakage o... |
562 563 564 |
if (dev) dev_put(dev); |
9afa0949e [NET] 802: Fix wh... |
565 |
} |
1da177e4c Linux-2.6.12-rc2 |
566 567 |
return 0; } |
56b3d975b [NET]: Make all i... |
568 |
static const struct seq_operations rif_seq_ops = { |
1da177e4c Linux-2.6.12-rc2 |
569 570 571 572 573 574 575 576 577 578 |
.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... |
579 |
static const struct file_operations rif_seq_fops = { |
1da177e4c Linux-2.6.12-rc2 |
580 581 582 583 584 585 586 587 |
.owner = THIS_MODULE, .open = rif_seq_open, .read = seq_read, .llseek = seq_lseek, .release = seq_release, }; #endif |
3b04ddde0 [NET]: Move hardw... |
588 589 590 591 |
static const struct header_ops tr_header_ops = { .create = tr_header, .rebuild= tr_rebuild_header, }; |
1da177e4c Linux-2.6.12-rc2 |
592 593 594 595 596 |
static void tr_setup(struct net_device *dev) { /* * Configure and register */ |
9afa0949e [NET] 802: Fix wh... |
597 |
|
3b04ddde0 [NET]: Move hardw... |
598 |
dev->header_ops = &tr_header_ops; |
1da177e4c Linux-2.6.12-rc2 |
599 600 601 602 603 604 |
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... |
605 |
|
1da177e4c Linux-2.6.12-rc2 |
606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 |
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); } |
36f0bebd9 [TR]: Use ctl pat... |
627 628 629 |
#ifdef CONFIG_SYSCTL static struct ctl_table tr_table[] = { { |
36f0bebd9 [TR]: Use ctl pat... |
630 631 632 633 |
.procname = "rif_timeout", .data = &sysctl_tr_rif_timeout, .maxlen = sizeof(int), .mode = 0644, |
6d9f239a1 net: '&' redux |
634 |
.proc_handler = proc_dointvec |
36f0bebd9 [TR]: Use ctl pat... |
635 |
}, |
f8572d8f2 sysctl net: Remov... |
636 |
{ }, |
36f0bebd9 [TR]: Use ctl pat... |
637 638 639 |
}; static __initdata struct ctl_path tr_path[] = { |
f8572d8f2 sysctl net: Remov... |
640 641 |
{ .procname = "net", }, { .procname = "token-ring", }, |
36f0bebd9 [TR]: Use ctl pat... |
642 643 644 |
{ } }; #endif |
1da177e4c Linux-2.6.12-rc2 |
645 646 647 648 649 650 651 |
/* * Called during bootup. We don't actually have to initialise * too much for this. */ static int __init rif_init(void) { |
1b310fca3 [TOKENRING]: rif_... |
652 |
rif_timer.expires = jiffies + sysctl_tr_rif_timeout; |
b24b8a247 [NET]: Convert in... |
653 |
setup_timer(&rif_timer, rif_check_expire, 0); |
1da177e4c Linux-2.6.12-rc2 |
654 |
add_timer(&rif_timer); |
36f0bebd9 [TR]: Use ctl pat... |
655 656 657 |
#ifdef CONFIG_SYSCTL register_sysctl_paths(tr_path, tr_table); #endif |
457c4cbc5 [NET]: Make /proc... |
658 |
proc_net_fops_create(&init_net, "tr_rif", S_IRUGO, &rif_seq_fops); |
1da177e4c Linux-2.6.12-rc2 |
659 660 661 662 |
return 0; } module_init(rif_init); |
1da177e4c Linux-2.6.12-rc2 |
663 664 |
EXPORT_SYMBOL(tr_type_trans); EXPORT_SYMBOL(alloc_trdev); |
422247451 net: fix tokenrin... |
665 666 |
MODULE_LICENSE("GPL"); |