Import 2.3.18pre1
[davej-history.git] / net / decnet / dn_neigh.c
blob996beaa0c589e2027000519f99ad05da47c4cfa4
1 /*
2 * DECnet An implementation of the DECnet protocol suite for the LINUX
3 * operating system. DECnet is implemented using the BSD Socket
4 * interface as the means of communication with the user level.
6 * DECnet Neighbour Functions (Adjacency Database and
7 * On-Ethernet Cache)
9 * Author: Steve Whitehouse <SteveW@ACM.org>
12 * Changes:
13 * Steve Whitehouse : Fixed router listing routine
14 * Steve Whitehouse : Added error_report functions
15 * Steve Whitehouse : Added default router detection
16 * Steve Whitehouse : Hop counts in outgoing messages
17 * Steve Whitehouse : Fixed src/dst in outgoing messages so
18 * forwarding now stands a good chance of
19 * working.
20 * Steve Whitehouse : Fixed neighbour states (for now anyway).
24 #include <linux/config.h>
25 #include <linux/net.h>
26 #include <linux/socket.h>
27 #include <linux/if_arp.h>
28 #include <linux/if_ether.h>
29 #include <linux/init.h>
30 #include <linux/proc_fs.h>
31 #include <linux/string.h>
32 #include <linux/netfilter_decnet.h>
33 #include <linux/spinlock.h>
34 #include <asm/atomic.h>
35 #include <net/neighbour.h>
36 #include <net/dst.h>
37 #include <net/dn.h>
38 #include <net/dn_dev.h>
39 #include <net/dn_neigh.h>
40 #include <net/dn_route.h>
42 static u32 dn_neigh_hash(const void *pkey, const struct net_device *dev);
43 static int dn_neigh_construct(struct neighbour *);
44 static void dn_long_error_report(struct neighbour *, struct sk_buff *);
45 static void dn_short_error_report(struct neighbour *, struct sk_buff *);
46 static int dn_long_output(struct sk_buff *);
47 static int dn_short_output(struct sk_buff *);
48 static int dn_phase3_output(struct sk_buff *);
52 * For talking to broadcast devices: Ethernet & PPP
54 static struct neigh_ops dn_long_ops = {
55 AF_DECnet,
56 NULL,
57 NULL,
58 dn_long_error_report,
59 dn_long_output,
60 dn_long_output,
61 dev_queue_xmit,
62 dev_queue_xmit
66 * For talking to pointopoint and multidrop devices: DDCMP and X.25
68 static struct neigh_ops dn_short_ops = {
69 AF_DECnet,
70 NULL,
71 NULL,
72 dn_short_error_report,
73 dn_short_output,
74 dn_short_output,
75 dev_queue_xmit,
76 dev_queue_xmit
80 * For talking to DECnet phase III nodes
82 static struct neigh_ops dn_phase3_ops = {
83 AF_DECnet,
84 NULL,
85 NULL,
86 dn_short_error_report, /* Can use short version here */
87 dn_phase3_output,
88 dn_phase3_output,
89 dev_queue_xmit,
90 dev_queue_xmit
93 struct neigh_table dn_neigh_table = {
94 NULL,
95 PF_DECnet,
96 sizeof(struct dn_neigh),
97 sizeof(dn_address),
98 dn_neigh_hash,
99 dn_neigh_construct,
100 NULL, /* pconstructor */
101 NULL, /* pdestructor */
102 NULL, /* proxyredo */
103 "dn_neigh_cache",
105 NULL,
106 NULL,
107 &dn_neigh_table,
109 NULL,
110 NULL,
111 30 * HZ, /* base_reachable_time */
112 1 * HZ, /* retrans_time */
113 60 * HZ, /* gc_staletime */
114 30 * HZ, /* reachable_time */
115 5 * HZ, /* delay_probe_time */
116 3, /* queue_len */
117 0, /* ucast_probes */
118 0, /* app_probes */
119 0, /* mcast_probes */
120 0, /* anycast_delay */
121 0, /* proxy_delay */
122 0, /* proxy_qlen */
123 1 * HZ, /* locktime */
125 30 * HZ, /* gc_interval */
126 128, /* gc_thresh1 */
127 512, /* gc_thresh2 */
128 1024, /* gc_thresh3 */
132 static u32 dn_neigh_hash(const void *pkey, const struct net_device *dev)
134 u32 hash_val;
136 hash_val = *(dn_address *)pkey;
137 hash_val ^= (hash_val >> 10);
138 hash_val ^= (hash_val >> 3);
140 return hash_val & NEIGH_HASHMASK;
143 static int dn_neigh_construct(struct neighbour *neigh)
145 struct net_device *dev = neigh->dev;
146 struct dn_neigh *dn = (struct dn_neigh *)neigh;
147 struct dn_dev *dn_db = (struct dn_dev *)dev->dn_ptr;
149 if (dn_db == NULL)
150 return -EINVAL;
152 if (dn_db->neigh_parms)
153 neigh->parms = dn_db->neigh_parms;
155 if (dn_db->use_long)
156 neigh->ops = &dn_long_ops;
157 else
158 neigh->ops = &dn_short_ops;
160 if (dn->flags & DN_NDFLAG_P3)
161 neigh->ops = &dn_phase3_ops;
163 neigh->nud_state = NUD_NOARP;
164 neigh->output = neigh->ops->connected_output;
166 if ((dev->type == ARPHRD_IPGRE) || (dev->flags & IFF_POINTOPOINT))
167 memcpy(neigh->ha, dev->broadcast, dev->addr_len);
168 else if ((dev->type == ARPHRD_ETHER) || (dev->type == ARPHRD_LOOPBACK))
169 dn_dn2eth(neigh->ha, dn->addr);
170 else {
171 if (net_ratelimit())
172 printk(KERN_DEBUG "Trying to create neigh for hw %d\n", dev->type);
173 return -EINVAL;
176 dn->blksize = 230;
178 return 0;
181 static void dn_long_error_report(struct neighbour *neigh, struct sk_buff *skb)
183 struct dn_skb_cb *cb = (struct dn_skb_cb *)skb->cb;
184 unsigned char *ptr;
186 printk(KERN_DEBUG "dn_long_error_report: called\n");
188 if (!(cb->rt_flags & DN_RT_F_RQR)) {
189 kfree_skb(skb);
190 return;
193 skb_push(skb, skb->data - skb->nh.raw);
194 ptr = skb->data;
196 *(unsigned short *)ptr = dn_htons(skb->len - 2);
197 ptr += 2;
199 if (*ptr & DN_RT_F_PF) {
200 char padlen = (*ptr & ~DN_RT_F_PF);
201 ptr += padlen;
204 *ptr++ |= (cb->rt_flags & ~DN_RT_F_RQR) | DN_RT_F_RTS;
206 ptr += 2;
207 dn_dn2eth(ptr, dn_ntohs(cb->src));
208 ptr += 8;
209 dn_dn2eth(ptr, dn_ntohs(cb->dst));
210 ptr += 6;
211 *ptr = 0;
213 skb->dst->neighbour->ops->queue_xmit(skb);
217 static void dn_short_error_report(struct neighbour *neigh, struct sk_buff *skb)
219 struct dn_skb_cb *cb = (struct dn_skb_cb *)skb->cb;
220 unsigned char *ptr;
222 printk(KERN_DEBUG "dn_short_error_report: called\n");
224 if (!(cb->rt_flags & DN_RT_F_RQR)) {
225 kfree_skb(skb);
226 return;
229 skb_push(skb, skb->data - skb->nh.raw);
230 ptr = skb->data;
232 *(unsigned short *)ptr = dn_htons(skb->len - 2);
233 ptr += 2;
234 *ptr++ = (cb->rt_flags & ~DN_RT_F_RQR) | DN_RT_F_RTS;
236 *(dn_address *)ptr = cb->src;
237 ptr += 2;
238 *(dn_address *)ptr = cb->dst;
239 ptr += 2;
240 *ptr = 0;
242 skb->dst->neighbour->ops->queue_xmit(skb);
245 static int dn_neigh_output_packet(struct sk_buff *skb)
247 struct dst_entry *dst = skb->dst;
248 struct neighbour *neigh = dst->neighbour;
249 struct net_device *dev = neigh->dev;
251 if (!dev->hard_header || dev->hard_header(skb, dev, ntohs(skb->protocol), neigh->ha, NULL, skb->len) >= 0)
252 return neigh->ops->queue_xmit(skb);
254 if (net_ratelimit())
255 printk(KERN_DEBUG "dn_neigh_output_packet: oops, can't send packet\n");
257 kfree_skb(skb);
258 return -EINVAL;
261 static int dn_long_output(struct sk_buff *skb)
263 struct dst_entry *dst = skb->dst;
264 struct neighbour *neigh = dst->neighbour;
265 struct net_device *dev = neigh->dev;
266 int headroom = dev->hard_header_len + sizeof(struct dn_long_packet) + 3;
267 unsigned char *data;
268 struct dn_long_packet *lp;
269 struct dn_skb_cb *cb = (struct dn_skb_cb *)skb->cb;
272 if (skb_headroom(skb) < headroom) {
273 struct sk_buff *skb2 = skb_realloc_headroom(skb, headroom);
274 if (skb2 == NULL) {
275 if (net_ratelimit())
276 printk(KERN_CRIT "dn_long_output: no memory\n");
277 kfree_skb(skb);
278 return -ENOBUFS;
280 kfree_skb(skb);
281 skb = skb2;
282 if (net_ratelimit())
283 printk(KERN_INFO "dn_long_output: Increasing headroom\n");
286 data = skb_push(skb, sizeof(struct dn_long_packet) + 3);
287 lp = (struct dn_long_packet *)(data+3);
289 *((unsigned short *)data) = dn_htons(skb->len - 2);
290 *(data + 2) = 1 | DN_RT_F_PF; /* Padding */
292 lp->msgflg = DN_RT_PKT_LONG|(cb->rt_flags&(DN_RT_F_IE|DN_RT_F_RQR|DN_RT_F_RTS));
293 lp->d_area = lp->d_subarea = 0;
294 dn_dn2eth(lp->d_id, dn_ntohs(cb->dst));
295 lp->s_area = lp->s_subarea = 0;
296 dn_dn2eth(lp->s_id, dn_ntohs(cb->src));
297 lp->nl2 = 0;
298 lp->visit_ct = cb->hops & 0x3f;
299 lp->s_class = 0;
300 lp->pt = 0;
302 skb->nh.raw = skb->data;
304 return NF_HOOK(PF_DECnet, NF_DN_POST_ROUTING, skb, NULL, neigh->dev, dn_neigh_output_packet);
307 static int dn_short_output(struct sk_buff *skb)
309 struct dst_entry *dst = skb->dst;
310 struct neighbour *neigh = dst->neighbour;
311 struct net_device *dev = neigh->dev;
312 int headroom = dev->hard_header_len + sizeof(struct dn_short_packet) + 2;
313 struct dn_short_packet *sp;
314 unsigned char *data;
315 struct dn_skb_cb *cb = (struct dn_skb_cb *)skb->cb;
318 if (skb_headroom(skb) < headroom) {
319 struct sk_buff *skb2 = skb_realloc_headroom(skb, headroom);
320 if (skb2 == NULL) {
321 if (net_ratelimit())
322 printk(KERN_CRIT "dn_short_output: no memory\n");
323 kfree_skb(skb);
324 return -ENOBUFS;
326 kfree_skb(skb);
327 skb = skb2;
328 if (net_ratelimit())
329 printk(KERN_INFO "dn_short_output: Increasing headroom\n");
332 data = skb_push(skb, sizeof(struct dn_short_packet) + 2);
333 *((unsigned short *)data) = dn_htons(skb->len - 2);
334 sp = (struct dn_short_packet *)(data+2);
336 sp->msgflg = DN_RT_PKT_SHORT|(cb->rt_flags&(DN_RT_F_RQR|DN_RT_F_RTS));
337 sp->dstnode = cb->dst;
338 sp->srcnode = cb->src;
339 sp->forward = cb->hops & 0x3f;
341 skb->nh.raw = skb->data;
343 return NF_HOOK(PF_DECnet, NF_DN_POST_ROUTING, skb, NULL, neigh->dev, dn_neigh_output_packet);
347 * Phase 3 output is the same is short output, execpt that
348 * it clears the area bits before transmission.
350 static int dn_phase3_output(struct sk_buff *skb)
352 struct dst_entry *dst = skb->dst;
353 struct neighbour *neigh = dst->neighbour;
354 struct net_device *dev = neigh->dev;
355 int headroom = dev->hard_header_len + sizeof(struct dn_short_packet) + 2;
356 struct dn_short_packet *sp;
357 unsigned char *data;
358 struct dn_skb_cb *cb = (struct dn_skb_cb *)skb->cb;
360 if (skb_headroom(skb) < headroom) {
361 struct sk_buff *skb2 = skb_realloc_headroom(skb, headroom);
362 if (skb2 == NULL) {
363 if (net_ratelimit())
364 printk(KERN_CRIT "dn_phase3_output: no memory\n");
365 kfree_skb(skb);
366 return -ENOBUFS;
368 kfree_skb(skb);
369 skb = skb2;
370 if (net_ratelimit())
371 printk(KERN_INFO "dn_phase3_output: Increasing headroom\n");
374 data = skb_push(skb, sizeof(struct dn_short_packet) + 2);
375 ((unsigned short *)data) = dn_htons(skb->len - 2);
376 sp = (struct dn_short_packet *)(data + 2);
378 sp->msgflg = DN_RT_PKT_SHORT|(cb->rt_flags&(DN_RT_F_RQR|DN_RT_F_RTS));
379 sp->dstnode = cb->dst & dn_htons(0x03ff);
380 sp->srcnode = cb->src & dn_htons(0x03ff);
381 sp->forward = cb->hops & 0x3f;
383 skb->nh.raw = skb->data;
385 return NF_HOOK(PF_DECnet, NF_DN_POST_ROUTING, skb, NULL, neigh->dev, dn_neigh_output_packet);
389 * Unfortunately, the neighbour code uses the device in its hash
390 * function, so we don't get any advantage from it. This function
391 * basically does a neigh_lookup(), but without comparing the device
392 * field. This is required for the On-Ethernet cache
394 struct neighbour *dn_neigh_lookup(struct neigh_table *tbl, void *ptr)
396 struct neighbour *neigh;
397 u32 hash_val;
399 hash_val = tbl->hash(ptr, NULL);
401 read_lock_bh(&tbl->lock);
402 for(neigh = tbl->hash_buckets[hash_val]; neigh != NULL; neigh = neigh->next) {
403 if (memcmp(neigh->primary_key, ptr, tbl->key_len) == 0) {
404 atomic_inc(&neigh->refcnt);
405 read_unlock_bh(&tbl->lock);
406 return neigh;
409 read_unlock_bh(&tbl->lock);
411 return NULL;
416 * Any traffic on a pointopoint link causes the timer to be reset
417 * for the entry in the neighbour table.
419 void dn_neigh_pointopoint_notify(struct sk_buff *skb)
421 return;
425 * Pointopoint link receives a hello message
427 void dn_neigh_pointopoint_hello(struct sk_buff *skb)
429 kfree_skb(skb);
433 * Ethernet router hello message received
435 void dn_neigh_router_hello(struct sk_buff *skb)
437 struct rtnode_hello_message *msg = (struct rtnode_hello_message *)skb->data;
439 struct neighbour *neigh;
440 struct dn_neigh *dn;
441 struct dn_dev *dn_db;
442 dn_address src;
444 src = dn_eth2dn(msg->id);
446 neigh = __neigh_lookup(&dn_neigh_table, &src, skb->dev, 1);
448 dn = (struct dn_neigh *)neigh;
450 if (neigh) {
451 write_lock(&neigh->lock);
453 neigh->used = jiffies;
454 dn_db = (struct dn_dev *)neigh->dev->dn_ptr;
456 if (!(neigh->nud_state & NUD_PERMANENT)) {
457 neigh->updated = jiffies;
459 if (neigh->dev->type == ARPHRD_ETHER)
460 memcpy(neigh->ha, &skb->mac.ethernet->h_source, ETH_ALEN);
462 dn->blksize = dn_ntohs(msg->blksize);
463 dn->priority = msg->priority;
465 dn->flags &= ~DN_NDFLAG_P3;
467 switch(msg->iinfo & DN_RT_INFO_TYPE) {
468 case DN_RT_INFO_L1RT:
469 dn->flags &=~DN_NDFLAG_R2;
470 dn->flags |= DN_NDFLAG_R1;
471 break;
472 case DN_RT_INFO_L2RT:
473 dn->flags |= DN_NDFLAG_R2;
477 if (!dn_db->router) {
478 dn_db->router = neigh_clone(neigh);
479 } else {
480 if (msg->priority > ((struct dn_neigh *)dn_db->router)->priority)
481 neigh_release(xchg(&dn_db->router, neigh_clone(neigh)));
483 write_unlock(&neigh->lock);
484 neigh_release(neigh);
487 kfree_skb(skb);
491 * Endnode hello message received
493 void dn_neigh_endnode_hello(struct sk_buff *skb)
495 struct endnode_hello_message *msg = (struct endnode_hello_message *)skb->data;
496 struct neighbour *neigh;
497 struct dn_neigh *dn;
498 dn_address src;
500 src = dn_eth2dn(msg->id);
502 neigh = __neigh_lookup(&dn_neigh_table, &src, skb->dev, 1);
504 dn = (struct dn_neigh *)neigh;
506 if (neigh) {
507 write_lock(&neigh->lock);
509 neigh->used = jiffies;
511 if (!(neigh->nud_state & NUD_PERMANENT)) {
512 neigh->updated = jiffies;
514 if (neigh->dev->type == ARPHRD_ETHER)
515 memcpy(neigh->ha, &skb->mac.ethernet->h_source, ETH_ALEN);
516 dn->flags &= ~(DN_NDFLAG_R1 | DN_NDFLAG_R2);
517 dn->blksize = dn_ntohs(msg->blksize);
518 dn->priority = 0;
521 write_unlock(&neigh->lock);
522 neigh_release(neigh);
525 kfree_skb(skb);
529 #ifdef CONFIG_DECNET_ROUTER
530 static char *dn_find_slot(char *base, int max, int priority)
532 int i;
533 unsigned char *min = NULL;
535 base += 6; /* skip first id */
537 for(i = 0; i < max; i++) {
538 if (!min || (*base < *min))
539 min = base;
540 base += 7; /* find next priority */
543 if (!min)
544 return NULL;
546 return (*min < priority) ? (min - 6) : NULL;
549 int dn_neigh_elist(struct net_device *dev, unsigned char *ptr, int n)
551 int t = 0;
552 int i;
553 struct neighbour *neigh;
554 struct dn_neigh *dn;
555 struct neigh_table *tbl = &dn_neigh_table;
556 unsigned char *rs = ptr;
558 read_lock_bh(&tbl->lock);
560 for(i = 0; i < NEIGH_HASHMASK; i++) {
561 for(neigh = tbl->hash_buckets[i]; neigh != NULL; neigh = neigh->next) {
562 if (neigh->dev != dev)
563 continue;
564 dn = (struct dn_neigh *)neigh;
565 if (!(dn->flags & (DN_NDFLAG_R1|DN_NDFLAG_R2)))
566 continue;
567 if (decnet_node_type == DN_RT_INFO_L1RT && (dn->flags & DN_NDFLAG_R2))
568 continue;
569 if (t == n)
570 rs = dn_find_slot(ptr, n, dn->priority);
571 else
572 t++;
573 if (rs == NULL)
574 continue;
575 dn_dn2eth(rs, dn->addr);
576 rs += 6;
577 *rs = neigh->nud_state & NUD_CONNECTED ? 0x80 : 0x0;
578 *rs |= dn->priority;
579 rs++;
583 read_unlock_bh(&tbl->lock);
585 return t;
587 #endif /* CONFIG_DECNET_ROUTER */
591 #ifdef CONFIG_PROC_FS
592 int dn_neigh_get_info(char *buffer, char **start, off_t offset, int length, int dummy)
594 int len = 0;
595 off_t pos = 0;
596 off_t begin = 0;
597 struct neighbour *n;
598 int i;
599 char buf[DN_ASCBUF_LEN];
601 len += sprintf(buffer + len, "Addr Flags State Use Blksize Dev\n");
603 for(i=0;i <= NEIGH_HASHMASK; i++) {
604 read_lock_bh(&dn_neigh_table.lock);
605 n = dn_neigh_table.hash_buckets[i];
606 for(; n != NULL; n = n->next) {
607 struct dn_neigh *dn = (struct dn_neigh *)n;
609 read_lock(&n->lock);
610 len += sprintf(buffer+len, "%-7s %s%s%s %02x %02d %07ld %-8s\n",
611 dn_addr2asc(dn_ntohs(dn->addr), buf),
612 (dn->flags&DN_NDFLAG_R1) ? "1" : "-",
613 (dn->flags&DN_NDFLAG_R2) ? "2" : "-",
614 (dn->flags&DN_NDFLAG_P3) ? "3" : "-",
615 dn->n.nud_state,
616 atomic_read(&dn->n.refcnt),
617 dn->blksize,
618 (dn->n.dev) ? dn->n.dev->name : "?");
619 read_unlock(&n->lock);
621 pos = begin + len;
623 if (pos < offset) {
624 len = 0;
625 begin = pos;
628 if (pos > offset + length) {
629 read_unlock_bh(&dn_neigh_table.lock);
630 goto done;
633 read_unlock_bh(&dn_neigh_table.lock);
636 done:
638 *start = buffer + (offset - begin);
639 len -= offset - begin;
641 if (len > length) len = length;
643 return len;
646 static struct proc_dir_entry proc_net_dn_neigh = {
647 PROC_NET_DN_ADJ, 12, "decnet_neigh",
648 S_IFREG | S_IRUGO, 1, 0, 0,
649 0, &proc_net_inode_operations,
650 dn_neigh_get_info
653 #endif
655 void __init dn_neigh_init(void)
657 neigh_table_init(&dn_neigh_table);
659 #ifdef CONFIG_PROC_FS
660 proc_net_register(&proc_net_dn_neigh);
661 #endif /* CONFIG_PROC_FS */
664 #ifdef CONFIG_DECNET_MODULE
665 void dn_neigh_cleanup(void)
667 #ifdef CONFIG_PROC_FS
668 proc_net_unregister(PROC_NET_DN_ADJ);
669 #endif /* CONFIG_PROC_FS */
670 neigh_table_clear(&dn_neigh_table);
672 #endif /* CONFIG_DECNET_MODULE */