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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [net/] [decnet/] [dn_route.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
 
2
/*
3
 * DECnet       An implementation of the DECnet protocol suite for the LINUX
4
 *              operating system.  DECnet is implemented using the  BSD Socket
5
 *              interface as the means of communication with the user level.
6
 *
7
 *              DECnet Routing Functions (Endnode and Router)
8
 *
9
 * Authors:     Steve Whitehouse <SteveW@ACM.org>
10
 *              Eduardo Marcelo Serrat <emserrat@geocities.com>
11
 *
12
 * Changes:
13
 *              Steve Whitehouse : Fixes to allow "intra-ethernet" and
14
 *                                 "return-to-sender" bits on outgoing
15
 *                                 packets.
16
 *              Steve Whitehouse : Timeouts for cached routes.
17
 *              Steve Whitehouse : Use dst cache for input routes too.
18
 *              Steve Whitehouse : Fixed error values in dn_send_skb.
19
 *              Steve Whitehouse : Rework routing functions to better fit
20
 *                                 DECnet routing design
21
 *              Alexey Kuznetsov : New SMP locking
22
 *              Steve Whitehouse : More SMP locking changes & dn_cache_dump()
23
 *              Steve Whitehouse : Prerouting NF hook, now really is prerouting.
24
 *                                 Fixed possible skb leak in rtnetlink funcs.
25
 *              Steve Whitehouse : Dave Miller's dynamic hash table sizing and
26
 *                                 Alexey Kuznetsov's finer grained locking
27
 *                                 from ipv4/route.c.
28
 *              Steve Whitehouse : Routing is now starting to look like a
29
 *                                 sensible set of code now, mainly due to
30
 *                                 my copying the IPv4 routing code. The
31
 *                                 hooks here are modified and will continue
32
 *                                 to evolve for a while.
33
 *              Steve Whitehouse : Real SMP at last :-) Also new netfilter
34
 *                                 stuff. Look out raw sockets your days
35
 *                                 are numbered!
36
 *              Steve Whitehouse : Added return-to-sender functions. Added
37
 *                                 backlog congestion level return codes.
38
 *              Steve Whitehouse : Fixed bug where routes were set up with
39
 *                                 no ref count on net devices.
40
 *
41
 */
42
 
43
/******************************************************************************
44
    (c) 1995-1998 E.M. Serrat           emserrat@geocities.com
45
 
46
    This program is free software; you can redistribute it and/or modify
47
    it under the terms of the GNU General Public License as published by
48
    the Free Software Foundation; either version 2 of the License, or
49
    any later version.
50
 
51
    This program is distributed in the hope that it will be useful,
52
    but WITHOUT ANY WARRANTY; without even the implied warranty of
53
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
54
    GNU General Public License for more details.
55
*******************************************************************************/
56
 
57
#include <linux/config.h>
58
#include <linux/errno.h>
59
#include <linux/types.h>
60
#include <linux/socket.h>
61
#include <linux/in.h>
62
#include <linux/kernel.h>
63
#include <linux/sockios.h>
64
#include <linux/net.h>
65
#include <linux/netdevice.h>
66
#include <linux/inet.h>
67
#include <linux/route.h>
68
#include <net/sock.h>
69
#include <linux/fcntl.h>
70
#include <linux/mm.h>
71
#include <linux/proc_fs.h>
72
#include <linux/init.h>
73
#include <linux/rtnetlink.h>
74
#include <linux/string.h>
75
#include <linux/netfilter_decnet.h>
76
#include <asm/errno.h>
77
#include <net/neighbour.h>
78
#include <net/dst.h>
79
#include <net/dn.h>
80
#include <net/dn_dev.h>
81
#include <net/dn_nsp.h>
82
#include <net/dn_route.h>
83
#include <net/dn_neigh.h>
84
#include <net/dn_fib.h>
85
 
86
struct dn_rt_hash_bucket
87
{
88
        struct dn_route *chain;
89
        rwlock_t lock;
90
} __attribute__((__aligned__(8)));
91
 
92
extern struct neigh_table dn_neigh_table;
93
 
94
 
95
static unsigned char dn_hiord_addr[6] = {0xAA,0x00,0x04,0x00,0x00,0x00};
96
 
97
int dn_rt_min_delay = 2*HZ;
98
int dn_rt_max_delay = 10*HZ;
99
static unsigned long dn_rt_deadline = 0;
100
 
101
static int dn_dst_gc(void);
102
static struct dst_entry *dn_dst_check(struct dst_entry *, __u32);
103
static struct dst_entry *dn_dst_reroute(struct dst_entry *, struct sk_buff *skb);
104
static struct dst_entry *dn_dst_negative_advice(struct dst_entry *);
105
static void dn_dst_link_failure(struct sk_buff *);
106
static int dn_route_input(struct sk_buff *);
107
static void dn_run_flush(unsigned long dummy);
108
 
109
static struct dn_rt_hash_bucket *dn_rt_hash_table;
110
static unsigned dn_rt_hash_mask;
111
 
112
static struct timer_list dn_route_timer;
113
static struct timer_list dn_rt_flush_timer = { function: dn_run_flush };
114
int decnet_dst_gc_interval = 2;
115
 
116
static struct dst_ops dn_dst_ops = {
117
        family:                 PF_DECnet,
118
        protocol:               __constant_htons(ETH_P_DNA_RT),
119
        gc_thresh:              128,
120
        gc:                     dn_dst_gc,
121
        check:                  dn_dst_check,
122
        reroute:                dn_dst_reroute,
123
        negative_advice:        dn_dst_negative_advice,
124
        link_failure:           dn_dst_link_failure,
125
        entry_size:             sizeof(struct dn_route),
126
        entries:                ATOMIC_INIT(0),
127
};
128
 
129
static __inline__ unsigned dn_hash(unsigned short src, unsigned short dst)
130
{
131
        unsigned short tmp = src ^ dst;
132
        tmp ^= (tmp >> 3);
133
        tmp ^= (tmp >> 5);
134
        tmp ^= (tmp >> 10);
135
        return dn_rt_hash_mask & (unsigned)tmp;
136
}
137
 
138
static void SMP_TIMER_NAME(dn_dst_check_expire)(unsigned long dummy)
139
{
140
        int i;
141
        struct dn_route *rt, **rtp;
142
        unsigned long now = jiffies;
143
        unsigned long expire = 120 * HZ;
144
 
145
        for(i = 0; i <= dn_rt_hash_mask; i++) {
146
                rtp = &dn_rt_hash_table[i].chain;
147
 
148
                write_lock(&dn_rt_hash_table[i].lock);
149
                while((rt=*rtp) != NULL) {
150
                        if (atomic_read(&rt->u.dst.__refcnt) ||
151
                                        (now - rt->u.dst.lastuse) < expire) {
152
                                rtp = &rt->u.rt_next;
153
                                continue;
154
                        }
155
                        *rtp = rt->u.rt_next;
156
                        rt->u.rt_next = NULL;
157
                        dst_free(&rt->u.dst);
158
                }
159
                write_unlock(&dn_rt_hash_table[i].lock);
160
 
161
                if ((jiffies - now) > 0)
162
                        break;
163
        }
164
 
165
        mod_timer(&dn_route_timer, now + decnet_dst_gc_interval * HZ);
166
}
167
 
168
SMP_TIMER_DEFINE(dn_dst_check_expire, dn_dst_task);
169
 
170
static int dn_dst_gc(void)
171
{
172
        struct dn_route *rt, **rtp;
173
        int i;
174
        unsigned long now = jiffies;
175
        unsigned long expire = 10 * HZ;
176
 
177
        for(i = 0; i <= dn_rt_hash_mask; i++) {
178
 
179
                write_lock_bh(&dn_rt_hash_table[i].lock);
180
                rtp = &dn_rt_hash_table[i].chain;
181
 
182
                while((rt=*rtp) != NULL) {
183
                        if (atomic_read(&rt->u.dst.__refcnt) ||
184
                                        (now - rt->u.dst.lastuse) < expire) {
185
                                rtp = &rt->u.rt_next;
186
                                continue;
187
                        }
188
                        *rtp = rt->u.rt_next;
189
                        rt->u.rt_next = NULL;
190
                        dst_free(&rt->u.dst);
191
                        break;
192
                }
193
                write_unlock_bh(&dn_rt_hash_table[i].lock);
194
        }
195
 
196
        return 0;
197
}
198
 
199
static struct dst_entry *dn_dst_check(struct dst_entry *dst, __u32 cookie)
200
{
201
        dst_release(dst);
202
        return NULL;
203
}
204
 
205
static struct dst_entry *dn_dst_reroute(struct dst_entry *dst,
206
                                        struct sk_buff *skb)
207
{
208
        return NULL;
209
}
210
 
211
/*
212
 * This is called through sendmsg() when you specify MSG_TRYHARD
213
 * and there is already a route in cache.
214
 */
215
static struct dst_entry *dn_dst_negative_advice(struct dst_entry *dst)
216
{
217
        dst_release(dst);
218
        return NULL;
219
}
220
 
221
static void dn_dst_link_failure(struct sk_buff *skb)
222
{
223
        return;
224
}
225
 
226
static void dn_insert_route(struct dn_route *rt, unsigned hash)
227
{
228
        unsigned long now = jiffies;
229
 
230
        write_lock_bh(&dn_rt_hash_table[hash].lock);
231
        rt->u.rt_next = dn_rt_hash_table[hash].chain;
232
        dn_rt_hash_table[hash].chain = rt;
233
 
234
        dst_hold(&rt->u.dst);
235
        rt->u.dst.__use++;
236
        rt->u.dst.lastuse = now;
237
 
238
        write_unlock_bh(&dn_rt_hash_table[hash].lock);
239
}
240
 
241
void SMP_TIMER_NAME(dn_run_flush)(unsigned long dummy)
242
{
243
        int i;
244
        struct dn_route *rt, *next;
245
 
246
        for(i = 0; i < dn_rt_hash_mask; i++) {
247
                write_lock_bh(&dn_rt_hash_table[i].lock);
248
 
249
                if ((rt = xchg(&dn_rt_hash_table[i].chain, NULL)) == NULL)
250
                        goto nothing_to_declare;
251
 
252
                for(; rt; rt=next) {
253
                        next = rt->u.rt_next;
254
                        rt->u.rt_next = NULL;
255
                        dst_free((struct dst_entry *)rt);
256
                }
257
 
258
nothing_to_declare:
259
                write_unlock_bh(&dn_rt_hash_table[i].lock);
260
        }
261
}
262
 
263
SMP_TIMER_DEFINE(dn_run_flush, dn_flush_task);
264
 
265
static spinlock_t dn_rt_flush_lock = SPIN_LOCK_UNLOCKED;
266
 
267
void dn_rt_cache_flush(int delay)
268
{
269
        unsigned long now = jiffies;
270
        int user_mode = !in_interrupt();
271
 
272
        if (delay < 0)
273
                delay = dn_rt_min_delay;
274
 
275
        spin_lock_bh(&dn_rt_flush_lock);
276
 
277
        if (del_timer(&dn_rt_flush_timer) && delay > 0 && dn_rt_deadline) {
278
                long tmo = (long)(dn_rt_deadline - now);
279
 
280
                if (user_mode && tmo < dn_rt_max_delay - dn_rt_min_delay)
281
                        tmo = 0;
282
 
283
                if (delay > tmo)
284
                        delay = tmo;
285
        }
286
 
287
        if (delay <= 0) {
288
                spin_unlock_bh(&dn_rt_flush_lock);
289
                dn_run_flush(0);
290
                return;
291
        }
292
 
293
        if (dn_rt_deadline == 0)
294
                dn_rt_deadline = now + dn_rt_max_delay;
295
 
296
        dn_rt_flush_timer.expires = now + delay;
297
        add_timer(&dn_rt_flush_timer);
298
        spin_unlock_bh(&dn_rt_flush_lock);
299
}
300
 
301
/**
302
 * dn_return_short - Return a short packet to its sender
303
 * @skb: The packet to return
304
 *
305
 */
306
static int dn_return_short(struct sk_buff *skb)
307
{
308
        struct dn_skb_cb *cb;
309
        unsigned char *ptr;
310
        dn_address *src;
311
        dn_address *dst;
312
        dn_address tmp;
313
 
314
        /* Add back headers */
315
        skb_push(skb, skb->data - skb->nh.raw);
316
 
317
        if ((skb = skb_unshare(skb, GFP_ATOMIC)) == NULL)
318
                return NET_RX_DROP;
319
 
320
        cb = DN_SKB_CB(skb);
321
        /* Skip packet length and point to flags */
322
        ptr = skb->data + 2;
323
        *ptr++ = (cb->rt_flags & ~DN_RT_F_RQR) | DN_RT_F_RTS;
324
 
325
        dst = (dn_address *)ptr;
326
        ptr += 2;
327
        src = (dn_address *)ptr;
328
        ptr += 2;
329
        *ptr = 0; /* Zero hop count */
330
 
331
        /* Swap source and destination */
332
        tmp  = *src;
333
        *src = *dst;
334
        *dst = tmp;
335
 
336
        skb->pkt_type = PACKET_OUTGOING;
337
        dn_rt_finish_output(skb, NULL);
338
        return NET_RX_SUCCESS;
339
}
340
 
341
/**
342
 * dn_return_long - Return a long packet to its sender
343
 * @skb: The long format packet to return
344
 *
345
 */
346
static int dn_return_long(struct sk_buff *skb)
347
{
348
        struct dn_skb_cb *cb;
349
        unsigned char *ptr;
350
        unsigned char *src_addr, *dst_addr;
351
        unsigned char tmp[ETH_ALEN];
352
 
353
        /* Add back all headers */
354
        skb_push(skb, skb->data - skb->nh.raw);
355
 
356
        if ((skb = skb_unshare(skb, GFP_ATOMIC)) == NULL)
357
                return NET_RX_DROP;
358
 
359
        cb = DN_SKB_CB(skb);
360
        /* Ignore packet length and point to flags */
361
        ptr = skb->data + 2;
362
 
363
        /* Skip padding */
364
        if (*ptr & DN_RT_F_PF) {
365
                char padlen = (*ptr & ~DN_RT_F_PF);
366
                ptr += padlen;
367
        }
368
 
369
        *ptr++ = (cb->rt_flags & ~DN_RT_F_RQR) | DN_RT_F_RTS;
370
        ptr += 2;
371
        dst_addr = ptr;
372
        ptr += 8;
373
        src_addr = ptr;
374
        ptr += 6;
375
        *ptr = 0; /* Zero hop count */
376
 
377
        /* Swap source and destination */
378
        memcpy(tmp, src_addr, ETH_ALEN);
379
        memcpy(src_addr, dst_addr, ETH_ALEN);
380
        memcpy(dst_addr, tmp, ETH_ALEN);
381
 
382
        skb->pkt_type = PACKET_OUTGOING;
383
        dn_rt_finish_output(skb, tmp);
384
        return NET_RX_SUCCESS;
385
}
386
 
387
/**
388
 * dn_route_rx_packet - Try and find a route for an incoming packet
389
 * @skb: The packet to find a route for
390
 *
391
 * Returns: result of input function if route is found, error code otherwise
392
 */
393
static int dn_route_rx_packet(struct sk_buff *skb)
394
{
395
        struct dn_skb_cb *cb = DN_SKB_CB(skb);
396
        int err;
397
 
398
        if ((err = dn_route_input(skb)) == 0)
399
                return skb->dst->input(skb);
400
 
401
        if (decnet_debug_level & 4) {
402
                char *devname = skb->dev ? skb->dev->name : "???";
403
                struct dn_skb_cb *cb = DN_SKB_CB(skb);
404
                printk(KERN_DEBUG
405
                        "DECnet: dn_route_rx_packet: rt_flags=0x%02x dev=%s len=%d src=0x%04hx dst=0x%04hx err=%d type=%d\n",
406
                        (int)cb->rt_flags, devname, skb->len, cb->src, cb->dst,
407
                        err, skb->pkt_type);
408
        }
409
 
410
        if ((skb->pkt_type == PACKET_HOST) && (cb->rt_flags & DN_RT_F_RQR)) {
411
                switch(cb->rt_flags & DN_RT_PKT_MSK) {
412
                        case DN_RT_PKT_SHORT:
413
                                return dn_return_short(skb);
414
                        case DN_RT_PKT_LONG:
415
                                return dn_return_long(skb);
416
                }
417
        }
418
 
419
        kfree_skb(skb);
420
        return NET_RX_DROP;
421
}
422
 
423
static int dn_route_rx_long(struct sk_buff *skb)
424
{
425
        struct dn_skb_cb *cb = DN_SKB_CB(skb);
426
        unsigned char *ptr = skb->data;
427
 
428
        if (skb->len < 21) /* 20 for long header, 1 for shortest nsp */
429
                goto drop_it;
430
 
431
        skb_pull(skb, 20);
432
        skb->h.raw = skb->data;
433
 
434
        /* Destination info */
435
        ptr += 2;
436
        cb->dst = dn_htons(dn_eth2dn(ptr));
437
        if (memcmp(ptr, dn_hiord_addr, 4) != 0)
438
                goto drop_it;
439
        ptr += 6;
440
 
441
 
442
        /* Source info */
443
        ptr += 2;
444
        cb->src = dn_htons(dn_eth2dn(ptr));
445
        if (memcmp(ptr, dn_hiord_addr, 4) != 0)
446
                goto drop_it;
447
        ptr += 6;
448
        /* Other junk */
449
        ptr++;
450
        cb->hops = *ptr++; /* Visit Count */
451
 
452
        return NF_HOOK(PF_DECnet, NF_DN_PRE_ROUTING, skb, skb->dev, NULL, dn_route_rx_packet);
453
 
454
drop_it:
455
        kfree_skb(skb);
456
        return NET_RX_DROP;
457
}
458
 
459
 
460
 
461
static int dn_route_rx_short(struct sk_buff *skb)
462
{
463
        struct dn_skb_cb *cb = DN_SKB_CB(skb);
464
        unsigned char *ptr = skb->data;
465
 
466
        if (skb->len < 6) /* 5 for short header + 1 for shortest nsp */
467
                goto drop_it;
468
 
469
        skb_pull(skb, 5);
470
        skb->h.raw = skb->data;
471
 
472
        cb->dst = *(dn_address *)ptr;
473
        ptr += 2;
474
        cb->src = *(dn_address *)ptr;
475
        ptr += 2;
476
        cb->hops = *ptr & 0x3f;
477
 
478
        return NF_HOOK(PF_DECnet, NF_DN_PRE_ROUTING, skb, skb->dev, NULL, dn_route_rx_packet);
479
 
480
drop_it:
481
        kfree_skb(skb);
482
        return NET_RX_DROP;
483
}
484
 
485
static int dn_route_discard(struct sk_buff *skb)
486
{
487
        /*
488
         * I know we drop the packet here, but thats considered success in
489
         * this case
490
         */
491
        kfree_skb(skb);
492
        return NET_RX_SUCCESS;
493
}
494
 
495
static int dn_route_ptp_hello(struct sk_buff *skb)
496
{
497
        dn_dev_hello(skb);
498
        dn_neigh_pointopoint_hello(skb);
499
        return NET_RX_SUCCESS;
500
}
501
 
502
int dn_route_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt)
503
{
504
        struct dn_skb_cb *cb;
505
        unsigned char flags = 0;
506
        __u16 len = dn_ntohs(*(__u16 *)skb->data);
507
        struct dn_dev *dn = (struct dn_dev *)dev->dn_ptr;
508
        unsigned char padlen = 0;
509
 
510
        if (dn == NULL)
511
                goto dump_it;
512
 
513
        if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL)
514
                goto out;
515
 
516
        skb_pull(skb, 2);
517
 
518
        if (len > skb->len)
519
                goto dump_it;
520
 
521
        skb_trim(skb, len);
522
 
523
        flags = *skb->data;
524
 
525
        cb = DN_SKB_CB(skb);
526
        cb->stamp = jiffies;
527
        cb->iif = dev->ifindex;
528
 
529
        /*
530
         * If we have padding, remove it.
531
         */
532
        if (flags & DN_RT_F_PF) {
533
                padlen = flags & ~DN_RT_F_PF;
534
                skb_pull(skb, padlen);
535
                flags = *skb->data;
536
        }
537
 
538
        skb->nh.raw = skb->data;
539
 
540
        /*
541
         * Weed out future version DECnet
542
         */
543
        if (flags & DN_RT_F_VER)
544
                goto dump_it;
545
 
546
        cb->rt_flags = flags;
547
 
548
        if (decnet_debug_level & 1)
549
                printk(KERN_DEBUG
550
                        "dn_route_rcv: got 0x%02x from %s [%d %d %d]\n",
551
                        (int)flags, (dev) ? dev->name : "???", len, skb->len,
552
                        padlen);
553
 
554
        if (flags & DN_RT_PKT_CNTL) {
555
                switch(flags & DN_RT_CNTL_MSK) {
556
                        case DN_RT_PKT_INIT:
557
                                dn_dev_init_pkt(skb);
558
                                break;
559
                        case DN_RT_PKT_VERI:
560
                                dn_dev_veri_pkt(skb);
561
                                break;
562
                }
563
 
564
                if (dn->parms.state != DN_DEV_S_RU)
565
                        goto dump_it;
566
 
567
                switch(flags & DN_RT_CNTL_MSK) {
568
                        case DN_RT_PKT_HELO:
569
                                return NF_HOOK(PF_DECnet, NF_DN_HELLO, skb, skb->dev, NULL, dn_route_ptp_hello);
570
 
571
                        case DN_RT_PKT_L1RT:
572
                        case DN_RT_PKT_L2RT:
573
                                return NF_HOOK(PF_DECnet, NF_DN_ROUTE, skb, skb->dev, NULL, dn_route_discard);
574
                        case DN_RT_PKT_ERTH:
575
                                return NF_HOOK(PF_DECnet, NF_DN_HELLO, skb, skb->dev, NULL, dn_neigh_router_hello);
576
 
577
                        case DN_RT_PKT_EEDH:
578
                                return NF_HOOK(PF_DECnet, NF_DN_HELLO, skb, skb->dev, NULL, dn_neigh_endnode_hello);
579
                }
580
        } else {
581
                if (dn->parms.state != DN_DEV_S_RU)
582
                        goto dump_it;
583
 
584
                skb_pull(skb, 1); /* Pull flags */
585
 
586
                switch(flags & DN_RT_PKT_MSK) {
587
                        case DN_RT_PKT_LONG:
588
                                return dn_route_rx_long(skb);
589
                        case DN_RT_PKT_SHORT:
590
                                return dn_route_rx_short(skb);
591
                }
592
        }
593
 
594
dump_it:
595
        kfree_skb(skb);
596
out:
597
        return NET_RX_DROP;
598
}
599
 
600
static int dn_output(struct sk_buff *skb)
601
{
602
        struct dst_entry *dst = skb->dst;
603
        struct dn_route *rt = (struct dn_route *)dst;
604
        struct net_device *dev = dst->dev;
605
        struct dn_skb_cb *cb = DN_SKB_CB(skb);
606
        struct neighbour *neigh;
607
 
608
        int err = -EINVAL;
609
 
610
        if ((neigh = dst->neighbour) == NULL)
611
                goto error;
612
 
613
        skb->dev = dev;
614
 
615
        cb->src = rt->rt_saddr;
616
        cb->dst = rt->rt_daddr;
617
 
618
        /*
619
         * Always set the Intra-Ethernet bit on all outgoing packets
620
         * originated on this node. Only valid flag from upper layers
621
         * is return-to-sender-requested. Set hop count to 0 too.
622
         */
623
        cb->rt_flags &= ~DN_RT_F_RQR;
624
        cb->rt_flags |= DN_RT_F_IE;
625
        cb->hops = 0;
626
 
627
        return NF_HOOK(PF_DECnet, NF_DN_LOCAL_OUT, skb, NULL, dev, neigh->output);
628
 
629
error:
630
        if (net_ratelimit())
631
                printk(KERN_DEBUG "dn_output: This should not happen\n");
632
 
633
        kfree_skb(skb);
634
 
635
        return err;
636
}
637
 
638
#ifdef CONFIG_DECNET_ROUTER
639
static int dn_forward(struct sk_buff *skb)
640
{
641
        struct dn_skb_cb *cb = DN_SKB_CB(skb);
642
        struct dst_entry *dst = skb->dst;
643
        struct neighbour *neigh;
644
        struct net_device *dev = skb->dev;
645
        int err = -EINVAL;
646
 
647
        if ((neigh = dst->neighbour) == NULL)
648
                goto error;
649
 
650
        /*
651
         * Hop count exceeded.
652
         */
653
        err = NET_RX_DROP;
654
        if (++cb->hops > 30)
655
                goto drop;
656
 
657
        skb->dev = dst->dev;
658
 
659
        /*
660
         * If packet goes out same interface it came in on, then set
661
         * the Intra-Ethernet bit. This has no effect for short
662
         * packets, so we don't need to test for them here.
663
         */
664
        if (cb->iif == dst->dev->ifindex)
665
                cb->rt_flags |= DN_RT_F_IE;
666
        else
667
                cb->rt_flags &= ~DN_RT_F_IE;
668
 
669
        return NF_HOOK(PF_DECnet, NF_DN_FORWARD, skb, dev, skb->dev, neigh->output);
670
 
671
 
672
error:
673
        if (net_ratelimit())
674
                printk(KERN_DEBUG "dn_forward: This should not happen\n");
675
drop:
676
        kfree_skb(skb);
677
 
678
        return err;
679
}
680
#endif
681
 
682
/*
683
 * Drop packet. This is used for endnodes and for
684
 * when we should not be forwarding packets from
685
 * this dest.
686
 */
687
static int dn_blackhole(struct sk_buff *skb)
688
{
689
        kfree_skb(skb);
690
        return NET_RX_DROP;
691
}
692
 
693
/*
694
 * Used to catch bugs. This should never normally get
695
 * called.
696
 */
697
static int dn_rt_bug(struct sk_buff *skb)
698
{
699
        if (net_ratelimit()) {
700
                struct dn_skb_cb *cb = DN_SKB_CB(skb);
701
 
702
                printk(KERN_DEBUG "dn_rt_bug: skb from:%04x to:%04x\n",
703
                                cb->src, cb->dst);
704
        }
705
 
706
        kfree_skb(skb);
707
 
708
        return NET_RX_BAD;
709
}
710
 
711
static int dn_route_output_slow(struct dst_entry **pprt, dn_address dst, dn_address src, int flags)
712
{
713
        struct dn_route *rt = NULL;
714
        struct net_device *dev = decnet_default_device;
715
        struct neighbour *neigh = NULL;
716
        struct dn_dev *dn_db;
717
        unsigned hash;
718
#ifdef CONFIG_DECNET_ROUTER
719
        struct dn_fib_key key;
720
        struct dn_fib_res res;
721
        int err;
722
 
723
        key.src = src;
724
        key.dst = dst;
725
        key.iif = 0;
726
        key.oif = 0;
727
        key.fwmark = 0;
728
        key.scope = RT_SCOPE_UNIVERSE;
729
 
730
        if ((err = dn_fib_lookup(&key, &res)) == 0) {
731
                switch(res.type) {
732
                        case RTN_UNICAST:
733
                                /*
734
                                 * This method of handling multipath
735
                                 * routes is a hack and will change.
736
                                 * It works for now though.
737
                                 */
738
                                if (res.fi->fib_nhs)
739
                                        dn_fib_select_multipath(&key, &res);
740
                                neigh = __neigh_lookup(&dn_neigh_table, &DN_FIB_RES_GW(res), DN_FIB_RES_DEV(res), 1);
741
                                err = -ENOBUFS;
742
                                if (!neigh)
743
                                        break;
744
                                err = 0;
745
                                break;
746
                        case RTN_UNREACHABLE:
747
                                err = -EHOSTUNREACH;
748
                                break;
749
                        default:
750
                                err = -EINVAL;
751
                }
752
                dn_fib_res_put(&res);
753
                if (err < 0)
754
                        return err;
755
                goto got_route;
756
        }
757
 
758
        if (err != -ESRCH)
759
                return err;
760
#endif 
761
 
762
        /* Look in On-Ethernet cache first */
763
        if (!(flags & MSG_TRYHARD)) {
764
                if ((neigh = dn_neigh_lookup(&dn_neigh_table, &dst)) != NULL)
765
                        goto got_route;
766
        }
767
 
768
        if (dev == NULL)
769
                return -EINVAL;
770
 
771
        dn_db = dev->dn_ptr;
772
 
773
        if (dn_db == NULL)
774
                return -EINVAL;
775
 
776
        /* Try default router */
777
        if ((neigh = neigh_clone(dn_db->router)) != NULL)
778
                goto got_route;
779
 
780
        /* Send to default device (and hope for the best) if above fail */
781
        if ((neigh = __neigh_lookup(&dn_neigh_table, &dst, dev, 1)) != NULL)
782
                goto got_route;
783
 
784
 
785
        return -EINVAL;
786
 
787
got_route:
788
 
789
        if ((rt = dst_alloc(&dn_dst_ops)) == NULL) {
790
                neigh_release(neigh);
791
                return -EINVAL;
792
        }
793
 
794
        dn_db = (struct dn_dev *)neigh->dev->dn_ptr;
795
 
796
        rt->key.saddr  = src;
797
        rt->rt_saddr   = src;
798
        rt->key.daddr  = dst;
799
        rt->rt_daddr   = dst;
800
        rt->key.oif    = neigh ? neigh->dev->ifindex : -1;
801
        rt->key.iif    = 0;
802
        rt->key.fwmark = 0;
803
 
804
        rt->u.dst.neighbour = neigh;
805
        rt->u.dst.dev = neigh ? neigh->dev : NULL;
806
        if (rt->u.dst.dev)
807
                dev_hold(rt->u.dst.dev);
808
        rt->u.dst.lastuse = jiffies;
809
        rt->u.dst.output = dn_output;
810
        rt->u.dst.input  = dn_rt_bug;
811
 
812
        if (dn_dev_islocal(neigh->dev, rt->rt_daddr))
813
                rt->u.dst.input = dn_nsp_rx;
814
 
815
        hash = dn_hash(rt->key.saddr, rt->key.daddr);
816
        dn_insert_route(rt, hash);
817
        *pprt = &rt->u.dst;
818
 
819
        return 0;
820
}
821
 
822
int dn_route_output(struct dst_entry **pprt, dn_address dst, dn_address src, int flags)
823
{
824
        unsigned hash = dn_hash(src, dst);
825
        struct dn_route *rt = NULL;
826
 
827
        if (!(flags & MSG_TRYHARD)) {
828
                read_lock_bh(&dn_rt_hash_table[hash].lock);
829
                for(rt = dn_rt_hash_table[hash].chain; rt; rt = rt->u.rt_next) {
830
                        if ((dst == rt->key.daddr) &&
831
                                        (src == rt->key.saddr) &&
832
                                        (rt->key.iif == 0) &&
833
                                        (rt->key.oif != 0)) {
834
                                rt->u.dst.lastuse = jiffies;
835
                                dst_hold(&rt->u.dst);
836
                                rt->u.dst.__use++;
837
                                read_unlock_bh(&dn_rt_hash_table[hash].lock);
838
                                *pprt = &rt->u.dst;
839
                                return 0;
840
                        }
841
                }
842
                read_unlock_bh(&dn_rt_hash_table[hash].lock);
843
        }
844
 
845
        return dn_route_output_slow(pprt, dst, src, flags);
846
}
847
 
848
static int dn_route_input_slow(struct sk_buff *skb)
849
{
850
        struct dn_route *rt = NULL;
851
        struct dn_skb_cb *cb = DN_SKB_CB(skb);
852
        struct net_device *dev = skb->dev;
853
        struct dn_dev *dn_db;
854
        struct neighbour *neigh = NULL;
855
        int (*dnrt_input)(struct sk_buff *skb);
856
        int (*dnrt_output)(struct sk_buff *skb);
857
        u32 fwmark = 0;
858
        unsigned hash;
859
        dn_address saddr = cb->src;
860
        dn_address daddr = cb->dst;
861
#ifdef CONFIG_DECNET_ROUTER
862
        struct dn_fib_key key;
863
        struct dn_fib_res res;
864
        int err;
865
#endif
866
 
867
        if (dev == NULL)
868
                return -EINVAL;
869
 
870
        if ((dn_db = dev->dn_ptr) == NULL)
871
                return -EINVAL;
872
 
873
        /*
874
         * In this case we've just received a packet from a source
875
         * outside ourselves pretending to come from us. We don't
876
         * allow it any further to prevent routing loops, spoofing and
877
         * other nasties. Loopback packets already have the dst attached
878
         * so this only affects packets which have originated elsewhere.
879
         */
880
        if (dn_dev_islocal(dev, cb->src))
881
                return -ENOTUNIQ;
882
 
883
        /*
884
         * Default is to create a drop everything entry
885
         */
886
        dnrt_input  = dn_blackhole;
887
        dnrt_output = dn_rt_bug;
888
 
889
        /*
890
         * Is the destination us ?
891
         */
892
        if (!dn_dev_islocal(dev, cb->dst))
893
                goto non_local_input;
894
 
895
        /*
896
         * Local input... find source of skb
897
         */
898
        dnrt_input  = dn_nsp_rx;
899
        dnrt_output = dn_output;
900
        saddr = cb->dst;
901
        daddr = cb->src;
902
 
903
        if ((neigh = neigh_lookup(&dn_neigh_table, &cb->src, dev)) != NULL)
904
                goto add_entry;
905
 
906
        if (dn_db->router && ((neigh = neigh_clone(dn_db->router)) != NULL))
907
                goto add_entry;
908
 
909
        neigh = neigh_create(&dn_neigh_table, &cb->src, dev);
910
        if (!IS_ERR(neigh)) {
911
                if (dev->type == ARPHRD_ETHER)
912
                        memcpy(neigh->ha, skb->mac.ethernet->h_source, ETH_ALEN);
913
                goto add_entry;
914
        }
915
 
916
        return PTR_ERR(neigh);
917
 
918
non_local_input:
919
 
920
#ifdef CONFIG_DECNET_ROUTER
921
        /*
922
         * Destination is another node... find next hop in
923
         * routing table here.
924
         */
925
 
926
        key.src = cb->src;
927
        key.dst = cb->dst;
928
        key.iif = dev->ifindex;
929
        key.oif = 0;
930
        key.scope = RT_SCOPE_UNIVERSE;
931
 
932
#ifdef CONFIG_DECNET_ROUTE_FWMARK
933
        key.fwmark = skb->nfmark;
934
#else
935
        key.fwmark = 0;
936
#endif
937
 
938
        if ((err = dn_fib_lookup(&key, &res)) == 0) {
939
                switch(res.type) {
940
                        case RTN_UNICAST:
941
                                if (res.fi->fib_nhs)
942
                                        dn_fib_select_multipath(&key, &res);
943
                                neigh = __neigh_lookup(&dn_neigh_table, &DN_FIB_RES_GW(res), DN_FIB_RES_DEV(res), 1);
944
                                err = -ENOBUFS;
945
                                if (!neigh)
946
                                        break;
947
                                err = 0;
948
                                dnrt_input = dn_forward;
949
                                fwmark = key.fwmark;
950
                                break;
951
                        case RTN_UNREACHABLE:
952
                                dnrt_input = dn_blackhole;
953
                                fwmark = key.fwmark;
954
                                break;
955
                        default:
956
                                err = -EINVAL;
957
                }
958
                dn_fib_res_put(&res);
959
                if (err < 0)
960
                        return err;
961
                goto add_entry;
962
        }
963
 
964
        return err;
965
 
966
#endif /* CONFIG_DECNET_ROUTER */
967
 
968
add_entry:
969
 
970
        if ((rt = dst_alloc(&dn_dst_ops)) == NULL) {
971
                neigh_release(neigh);
972
                return -EINVAL;
973
        }
974
 
975
        rt->key.saddr  = cb->src;
976
        rt->rt_saddr   = saddr;
977
        rt->key.daddr  = cb->dst;
978
        rt->rt_daddr   = daddr;
979
        rt->key.oif    = 0;
980
        rt->key.iif    = dev->ifindex;
981
        rt->key.fwmark = fwmark;
982
 
983
        rt->u.dst.neighbour = neigh;
984
        rt->u.dst.dev = neigh ? neigh->dev : NULL;
985
        if (rt->u.dst.dev)
986
                dev_hold(rt->u.dst.dev);
987
        rt->u.dst.lastuse = jiffies;
988
        rt->u.dst.output = dnrt_output;
989
        rt->u.dst.input = dnrt_input;
990
 
991
        hash = dn_hash(rt->key.saddr, rt->key.daddr);
992
        dn_insert_route(rt, hash);
993
        skb->dst = (struct dst_entry *)rt;
994
 
995
        return 0;
996
}
997
 
998
int dn_route_input(struct sk_buff *skb)
999
{
1000
        struct dn_route *rt;
1001
        struct dn_skb_cb *cb = DN_SKB_CB(skb);
1002
        unsigned hash = dn_hash(cb->src, cb->dst);
1003
 
1004
        if (skb->dst)
1005
                return 0;
1006
 
1007
        read_lock(&dn_rt_hash_table[hash].lock);
1008
        for(rt = dn_rt_hash_table[hash].chain; rt != NULL; rt = rt->u.rt_next) {
1009
                if ((rt->key.saddr == cb->src) &&
1010
                                (rt->key.daddr == cb->dst) &&
1011
                                (rt->key.oif == 0) &&
1012
#ifdef CONFIG_DECNET_ROUTE_FWMARK
1013
                                (rt->key.fwmark == skb->nfmark) &&
1014
#endif
1015
                                (rt->key.iif == cb->iif)) {
1016
                        rt->u.dst.lastuse = jiffies;
1017
                        dst_hold(&rt->u.dst);
1018
                        rt->u.dst.__use++;
1019
                        read_unlock(&dn_rt_hash_table[hash].lock);
1020
                        skb->dst = (struct dst_entry *)rt;
1021
                        return 0;
1022
                }
1023
        }
1024
        read_unlock(&dn_rt_hash_table[hash].lock);
1025
 
1026
        return dn_route_input_slow(skb);
1027
}
1028
 
1029
static int dn_rt_fill_info(struct sk_buff *skb, u32 pid, u32 seq, int event, int nowait)
1030
{
1031
        struct dn_route *rt = (struct dn_route *)skb->dst;
1032
        struct rtmsg *r;
1033
        struct nlmsghdr *nlh;
1034
        unsigned char *b = skb->tail;
1035
 
1036
        nlh = NLMSG_PUT(skb, pid, seq, event, sizeof(*r));
1037
        r = NLMSG_DATA(nlh);
1038
        nlh->nlmsg_flags = nowait ? NLM_F_MULTI : 0;
1039
        r->rtm_family = AF_DECnet;
1040
        r->rtm_dst_len = 16;
1041
        r->rtm_src_len = 16;
1042
        r->rtm_tos = 0;
1043
        r->rtm_table = 0;
1044
        r->rtm_type = 0;
1045
        r->rtm_flags = 0;
1046
        r->rtm_scope = RT_SCOPE_UNIVERSE;
1047
        r->rtm_protocol = RTPROT_UNSPEC;
1048
        RTA_PUT(skb, RTA_DST, 2, &rt->rt_daddr);
1049
        RTA_PUT(skb, RTA_SRC, 2, &rt->rt_saddr);
1050
        if (rt->u.dst.dev)
1051
                RTA_PUT(skb, RTA_OIF, sizeof(int), &rt->u.dst.dev->ifindex);
1052
        if (rt->u.dst.window)
1053
                RTA_PUT(skb, RTAX_WINDOW, sizeof(unsigned), &rt->u.dst.window);
1054
        if (rt->u.dst.rtt)
1055
                RTA_PUT(skb, RTAX_RTT, sizeof(unsigned), &rt->u.dst.rtt);
1056
 
1057
        nlh->nlmsg_len = skb->tail - b;
1058
        return skb->len;
1059
 
1060
nlmsg_failure:
1061
rtattr_failure:
1062
        skb_trim(skb, b - skb->data);
1063
        return -1;
1064
}
1065
 
1066
/*
1067
 * This is called by both endnodes and routers now.
1068
 */
1069
int dn_cache_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh, void *arg)
1070
{
1071
        struct rtattr **rta = arg;
1072
        struct dn_route *rt = NULL;
1073
        struct dn_skb_cb *cb;
1074
        dn_address dst = 0;
1075
        dn_address src = 0;
1076
        int iif = 0;
1077
        int err;
1078
        struct sk_buff *skb;
1079
 
1080
        skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
1081
        if (skb == NULL)
1082
                return -ENOBUFS;
1083
        skb->mac.raw = skb->data;
1084
        cb = DN_SKB_CB(skb);
1085
 
1086
        if (rta[RTA_SRC-1])
1087
                memcpy(&src, RTA_DATA(rta[RTA_SRC-1]), 2);
1088
        if (rta[RTA_DST-1])
1089
                memcpy(&dst, RTA_DATA(rta[RTA_DST-1]), 2);
1090
        if (rta[RTA_IIF-1])
1091
                memcpy(&iif, RTA_DATA(rta[RTA_IIF-1]), sizeof(int));
1092
 
1093
        if (iif) {
1094
                struct net_device *dev;
1095
                if ((dev = dev_get_by_index(iif)) == NULL) {
1096
                        kfree_skb(skb);
1097
                        return -ENODEV;
1098
                }
1099
                if (!dev->dn_ptr) {
1100
                        dev_put(dev);
1101
                        kfree_skb(skb);
1102
                        return -ENODEV;
1103
                }
1104
                skb->protocol = __constant_htons(ETH_P_DNA_RT);
1105
                skb->dev = dev;
1106
                cb->src = src;
1107
                cb->dst = dst;
1108
                local_bh_disable();
1109
                err = dn_route_input(skb);
1110
                local_bh_enable();
1111
                memset(cb, 0, sizeof(struct dn_skb_cb));
1112
                rt = (struct dn_route *)skb->dst;
1113
        } else {
1114
                err = dn_route_output((struct dst_entry **)&rt, dst, src, 0);
1115
        }
1116
 
1117
        if (!err && rt->u.dst.error)
1118
                err = rt->u.dst.error;
1119
        if (skb->dev)
1120
                dev_put(skb->dev);
1121
        skb->dev = NULL;
1122
        if (err)
1123
                goto out_free;
1124
        skb->dst = &rt->u.dst;
1125
 
1126
        NETLINK_CB(skb).dst_pid = NETLINK_CB(in_skb).pid;
1127
 
1128
        err = dn_rt_fill_info(skb, NETLINK_CB(in_skb).pid, nlh->nlmsg_seq, RTM_NEWROUTE, 0);
1129
 
1130
        if (err == 0)
1131
                goto out_free;
1132
        if (err < 0) {
1133
                err = -EMSGSIZE;
1134
                goto out_free;
1135
        }
1136
 
1137
        err = netlink_unicast(rtnl, skb, NETLINK_CB(in_skb).pid, MSG_DONTWAIT);
1138
 
1139
        return err;
1140
 
1141
out_free:
1142
        kfree_skb(skb);
1143
        return err;
1144
}
1145
 
1146
/*
1147
 * For routers, this is called from dn_fib_dump, but for endnodes its
1148
 * called directly from the rtnetlink dispatch table.
1149
 */
1150
int dn_cache_dump(struct sk_buff *skb, struct netlink_callback *cb)
1151
{
1152
        struct dn_route *rt;
1153
        int h, s_h;
1154
        int idx, s_idx;
1155
 
1156
        if (NLMSG_PAYLOAD(cb->nlh, 0) < sizeof(struct rtmsg))
1157
                return -EINVAL;
1158
        if (!(((struct rtmsg *)NLMSG_DATA(cb->nlh))->rtm_flags&RTM_F_CLONED))
1159
                return 0;
1160
 
1161
        s_h = cb->args[0];
1162
        s_idx = idx = cb->args[1];
1163
        for(h = 0; h <= dn_rt_hash_mask; h++) {
1164
                if (h < s_h)
1165
                        continue;
1166
                if (h > s_h)
1167
                        s_idx = 0;
1168
                read_lock_bh(&dn_rt_hash_table[h].lock);
1169
                for(rt = dn_rt_hash_table[h].chain, idx = 0; rt; rt = rt->u.rt_next, idx++) {
1170
                        if (idx < s_idx)
1171
                                continue;
1172
                        skb->dst = dst_clone(&rt->u.dst);
1173
                        if (dn_rt_fill_info(skb, NETLINK_CB(cb->skb).pid,
1174
                                        cb->nlh->nlmsg_seq, RTM_NEWROUTE, 1) <= 0) {
1175
                                dst_release(xchg(&skb->dst, NULL));
1176
                                read_unlock_bh(&dn_rt_hash_table[h].lock);
1177
                                goto done;
1178
                        }
1179
                        dst_release(xchg(&skb->dst, NULL));
1180
                }
1181
                read_unlock_bh(&dn_rt_hash_table[h].lock);
1182
        }
1183
 
1184
done:
1185
        cb->args[0] = h;
1186
        cb->args[1] = idx;
1187
        return skb->len;
1188
}
1189
 
1190
#ifdef CONFIG_PROC_FS
1191
 
1192
static int decnet_cache_get_info(char *buffer, char **start, off_t offset, int length)
1193
{
1194
        int len = 0;
1195
        off_t pos = 0;
1196
        off_t begin = 0;
1197
        struct dn_route *rt;
1198
        int i;
1199
        char buf1[DN_ASCBUF_LEN], buf2[DN_ASCBUF_LEN];
1200
 
1201
        for(i = 0; i <= dn_rt_hash_mask; i++) {
1202
                read_lock_bh(&dn_rt_hash_table[i].lock);
1203
                rt = dn_rt_hash_table[i].chain;
1204
                for(; rt != NULL; rt = rt->u.rt_next) {
1205
                        len += sprintf(buffer + len, "%-8s %-7s %-7s %04d %04d %04d\n",
1206
                                        rt->u.dst.dev ? rt->u.dst.dev->name : "*",
1207
                                        dn_addr2asc(dn_ntohs(rt->rt_daddr), buf1),
1208
                                        dn_addr2asc(dn_ntohs(rt->rt_saddr), buf2),
1209
                                        atomic_read(&rt->u.dst.__refcnt),
1210
                                        rt->u.dst.__use,
1211
                                        (int)rt->u.dst.rtt
1212
                                        );
1213
 
1214
 
1215
 
1216
                        pos = begin + len;
1217
 
1218
                        if (pos < offset) {
1219
                                len   = 0;
1220
                                begin = pos;
1221
                        }
1222
                        if (pos > offset + length)
1223
                                break;
1224
                }
1225
                read_unlock_bh(&dn_rt_hash_table[i].lock);
1226
                if (pos > offset + length)
1227
                        break;
1228
        }
1229
 
1230
        *start = buffer + (offset - begin);
1231
        len   -= (offset - begin);
1232
 
1233
        if (len > length) len = length;
1234
 
1235
        return(len);
1236
}
1237
 
1238
#endif /* CONFIG_PROC_FS */
1239
 
1240
void __init dn_route_init(void)
1241
{
1242
        int i, goal, order;
1243
 
1244
        dn_dst_ops.kmem_cachep = kmem_cache_create("dn_dst_cache",
1245
                                                   sizeof(struct dn_route),
1246
                                                   0, SLAB_HWCACHE_ALIGN,
1247
                                                   NULL, NULL);
1248
 
1249
        if (!dn_dst_ops.kmem_cachep)
1250
                panic("DECnet: Failed to allocate dn_dst_cache\n");
1251
 
1252
        dn_route_timer.function = dn_dst_check_expire;
1253
        dn_route_timer.expires = jiffies + decnet_dst_gc_interval * HZ;
1254
        add_timer(&dn_route_timer);
1255
 
1256
        goal = num_physpages >> (26 - PAGE_SHIFT);
1257
 
1258
        for(order = 0; (1UL << order) < goal; order++)
1259
                /* NOTHING */;
1260
 
1261
        /*
1262
         * Only want 1024 entries max, since the table is very, very unlikely
1263
         * to be larger than that.
1264
         */
1265
        while(order && ((((1UL << order) * PAGE_SIZE) /
1266
                                sizeof(struct dn_rt_hash_bucket)) >= 2048))
1267
                order--;
1268
 
1269
        do {
1270
                dn_rt_hash_mask = (1UL << order) * PAGE_SIZE /
1271
                        sizeof(struct dn_rt_hash_bucket);
1272
                while(dn_rt_hash_mask & (dn_rt_hash_mask - 1))
1273
                        dn_rt_hash_mask--;
1274
                dn_rt_hash_table = (struct dn_rt_hash_bucket *)
1275
                        __get_free_pages(GFP_ATOMIC, order);
1276
        } while (dn_rt_hash_table == NULL && --order > 0);
1277
 
1278
        if (!dn_rt_hash_table)
1279
                panic("Failed to allocate DECnet route cache hash table\n");
1280
 
1281
        printk(KERN_INFO
1282
                "DECnet: Routing cache hash table of %u buckets, %ldKbytes\n",
1283
                dn_rt_hash_mask,
1284
                (long)(dn_rt_hash_mask*sizeof(struct dn_rt_hash_bucket))/1024);
1285
 
1286
        dn_rt_hash_mask--;
1287
        for(i = 0; i <= dn_rt_hash_mask; i++) {
1288
                dn_rt_hash_table[i].lock = RW_LOCK_UNLOCKED;
1289
                dn_rt_hash_table[i].chain = NULL;
1290
        }
1291
 
1292
        dn_dst_ops.gc_thresh = (dn_rt_hash_mask + 1);
1293
 
1294
#ifdef CONFIG_PROC_FS
1295
        proc_net_create("decnet_cache",0,decnet_cache_get_info);
1296
#endif /* CONFIG_PROC_FS */
1297
}
1298
 
1299
void __exit dn_route_cleanup(void)
1300
{
1301
        del_timer(&dn_route_timer);
1302
        dn_run_flush(0);
1303
 
1304
        proc_net_remove("decnet_cache");
1305
}
1306
 

powered by: WebSVN 2.1.0

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