Ok. I didn't make 2.4.0 in 2000. Tough. I tried, but we had some
[davej-history.git] / net / decnet / dn_neigh.c
blob00c27cdeca9ece6ae817fde58bdf9d916066f4f8
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 int 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_htons(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);
488 return 0;
492 * Endnode hello message received
494 int dn_neigh_endnode_hello(struct sk_buff *skb)
496 struct endnode_hello_message *msg = (struct endnode_hello_message *)skb->data;
497 struct neighbour *neigh;
498 struct dn_neigh *dn;
499 dn_address src;
501 src = dn_htons(dn_eth2dn(msg->id));
503 neigh = __neigh_lookup(&dn_neigh_table, &src, skb->dev, 1);
505 dn = (struct dn_neigh *)neigh;
507 if (neigh) {
508 write_lock(&neigh->lock);
510 neigh->used = jiffies;
512 if (!(neigh->nud_state & NUD_PERMANENT)) {
513 neigh->updated = jiffies;
515 if (neigh->dev->type == ARPHRD_ETHER)
516 memcpy(neigh->ha, &skb->mac.ethernet->h_source, ETH_ALEN);
517 dn->flags &= ~(DN_NDFLAG_R1 | DN_NDFLAG_R2);
518 dn->blksize = dn_ntohs(msg->blksize);
519 dn->priority = 0;
522 write_unlock(&neigh->lock);
523 neigh_release(neigh);
526 kfree_skb(skb);
527 return 0;
531 #ifdef CONFIG_DECNET_ROUTER
532 static char *dn_find_slot(char *base, int max, int priority)
534 int i;
535 unsigned char *min = NULL;
537 base += 6; /* skip first id */
539 for(i = 0; i < max; i++) {
540 if (!min || (*base < *min))
541 min = base;
542 base += 7; /* find next priority */
545 if (!min)
546 return NULL;
548 return (*min < priority) ? (min - 6) : NULL;
551 int dn_neigh_elist(struct net_device *dev, unsigned char *ptr, int n)
553 int t = 0;
554 int i;
555 struct neighbour *neigh;
556 struct dn_neigh *dn;
557 struct neigh_table *tbl = &dn_neigh_table;
558 unsigned char *rs = ptr;
559 struct dn_dev *dn_db = (struct dn_dev *)dev->dn_ptr;
561 read_lock_bh(&tbl->lock);
563 for(i = 0; i < NEIGH_HASHMASK; i++) {
564 for(neigh = tbl->hash_buckets[i]; neigh != NULL; neigh = neigh->next) {
565 if (neigh->dev != dev)
566 continue;
567 dn = (struct dn_neigh *)neigh;
568 if (!(dn->flags & (DN_NDFLAG_R1|DN_NDFLAG_R2)))
569 continue;
570 if (dn_db->parms.forwarding == 1 && (dn->flags & DN_NDFLAG_R2))
571 continue;
572 if (t == n)
573 rs = dn_find_slot(ptr, n, dn->priority);
574 else
575 t++;
576 if (rs == NULL)
577 continue;
578 dn_dn2eth(rs, dn->addr);
579 rs += 6;
580 *rs = neigh->nud_state & NUD_CONNECTED ? 0x80 : 0x0;
581 *rs |= dn->priority;
582 rs++;
586 read_unlock_bh(&tbl->lock);
588 return t;
590 #endif /* CONFIG_DECNET_ROUTER */
594 #ifdef CONFIG_PROC_FS
595 static int dn_neigh_get_info(char *buffer, char **start, off_t offset, int length)
597 int len = 0;
598 off_t pos = 0;
599 off_t begin = 0;
600 struct neighbour *n;
601 int i;
602 char buf[DN_ASCBUF_LEN];
604 len += sprintf(buffer + len, "Addr Flags State Use Blksize Dev\n");
606 for(i=0;i <= NEIGH_HASHMASK; i++) {
607 read_lock_bh(&dn_neigh_table.lock);
608 n = dn_neigh_table.hash_buckets[i];
609 for(; n != NULL; n = n->next) {
610 struct dn_neigh *dn = (struct dn_neigh *)n;
612 read_lock(&n->lock);
613 len += sprintf(buffer+len, "%-7s %s%s%s %02x %02d %07ld %-8s\n",
614 dn_addr2asc(dn_ntohs(dn->addr), buf),
615 (dn->flags&DN_NDFLAG_R1) ? "1" : "-",
616 (dn->flags&DN_NDFLAG_R2) ? "2" : "-",
617 (dn->flags&DN_NDFLAG_P3) ? "3" : "-",
618 dn->n.nud_state,
619 atomic_read(&dn->n.refcnt),
620 dn->blksize,
621 (dn->n.dev) ? dn->n.dev->name : "?");
622 read_unlock(&n->lock);
624 pos = begin + len;
626 if (pos < offset) {
627 len = 0;
628 begin = pos;
631 if (pos > offset + length) {
632 read_unlock_bh(&dn_neigh_table.lock);
633 goto done;
636 read_unlock_bh(&dn_neigh_table.lock);
639 done:
641 *start = buffer + (offset - begin);
642 len -= offset - begin;
644 if (len > length) len = length;
646 return len;
649 #endif
651 void __init dn_neigh_init(void)
653 neigh_table_init(&dn_neigh_table);
655 #ifdef CONFIG_PROC_FS
656 proc_net_create("decnet_neigh",0,dn_neigh_get_info);
657 #endif /* CONFIG_PROC_FS */
660 void __exit dn_neigh_cleanup(void)
662 #ifdef CONFIG_PROC_FS
663 proc_net_remove("decnet_neigh");
664 #endif /* CONFIG_PROC_FS */
665 neigh_table_clear(&dn_neigh_table);