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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rc203soc/] [sw/] [uClinux/] [net/] [ipv4/] [ipmr.c] - Blame information for rev 1772

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1629 jcastillo
/*
2
 *      IP multicast routing support for mrouted 3.6/3.8
3
 *
4
 *              (c) 1995 Alan Cox, <alan@cymru.net>
5
 *        Linux Consultancy and Custom Driver Development
6
 *
7
 *      This program is free software; you can redistribute it and/or
8
 *      modify it under the terms of the GNU General Public License
9
 *      as published by the Free Software Foundation; either version
10
 *      2 of the License, or (at your option) any later version.
11
 *
12
 *
13
 *      Fixes:
14
 *      Michael Chastain        :       Incorrect size of copying.
15
 *      Alan Cox                :       Added the cache manager code.
16
 *      Alan Cox                :       Fixed the clone/copy bug and device race.
17
 *      Malcolm Beattie         :       Buffer handling fixes.
18
 *      Alexey Kuznetsov        :       Double buffer free and other fixes.
19
 *      SVR Anand               :       Fixed several multicast bugs and problems.
20
 *      Alexey Kuznetsov        :       Subset of bugfixes/changes pending for
21
 *                                      2.1. Doesn't include Alexey's PIM support.
22
 *
23
 *      Status:
24
 *              Cache manager under test. Forwarding in vague test mode
25
 *      Todo:
26
 *              Flow control
27
 *              Finish Tunnels
28
 *              Debug cache ttl handling properly
29
 *              Resolve IFF_ALLMULTI for rest of cards
30
 */
31
 
32
#include <linux/config.h>
33
#include <asm/system.h>
34
#include <asm/segment.h>
35
#include <linux/types.h>
36
#include <linux/sched.h>
37
#include <linux/errno.h>
38
#include <linux/timer.h>
39
#include <linux/mm.h>
40
#include <linux/kernel.h>
41
#include <linux/fcntl.h>
42
#include <linux/stat.h>
43
#include <linux/socket.h>
44
#include <linux/in.h>
45
#include <linux/inet.h>
46
#include <linux/netdevice.h>
47
#include <linux/proc_fs.h>
48
#include <linux/mroute.h>
49
#include <net/ip.h>
50
#include <net/protocol.h>
51
#include <linux/skbuff.h>
52
#include <net/sock.h>
53
#include <net/icmp.h>
54
#include <net/udp.h>
55
#include <linux/notifier.h>
56
#include <net/checksum.h>
57
 
58
/*
59
 *      Multicast router control variables
60
 */
61
 
62
static struct vif_device vif_table[MAXVIFS];            /* Devices              */
63
static unsigned long vifc_map;                          /* Active device map    */
64
int mroute_do_pim = 0;                                   /* Set in PIM assert    */
65
static struct mfc_cache *mfc_cache_array[MFC_LINES+1];  /* Forwarding cache     */
66
#define cache_resolve_queue (mfc_cache_array[MFC_LINES])/* Unresolved cache     */
67
int cache_resolve_queue_len = 0;                 /* Size of unresolved   */
68
 
69
/*
70
 *      Delete a VIF entry
71
 */
72
 
73
static void vif_delete(struct vif_device *v)
74
{
75
        if(!(v->flags&VIFF_TUNNEL))
76
        {
77
                v->dev->flags&=~IFF_ALLMULTI;
78
                dev_mc_upload(v->dev);
79
        }
80
        v->dev=NULL;
81
}
82
 
83
/*
84
 *      Delete a multicast route cache entry
85
 */
86
 
87
static void ipmr_cache_delete(struct mfc_cache *cache)
88
{
89
        struct sk_buff *skb;
90
        int line;
91
        struct mfc_cache **cp;
92
 
93
        /*
94
         *      Find the right cache line
95
         */
96
 
97
        if(cache->mfc_flags&MFC_QUEUED)
98
        {
99
                cp=&cache_resolve_queue;
100
                del_timer(&cache->mfc_timer);
101
        }
102
        else
103
        {
104
                line=MFC_HASH(cache->mfc_mcastgrp,cache->mfc_origin);
105
                cp=&(mfc_cache_array[line]);
106
        }
107
 
108
        /*
109
         *      Unlink the buffer
110
         */
111
 
112
        while(*cp!=NULL)
113
        {
114
                if(*cp==cache)
115
                {
116
                        *cp=cache->next;
117
                        break;
118
                }
119
                cp=&((*cp)->next);
120
        }
121
 
122
        /*
123
         *      Free the buffer. If it is a pending resolution
124
         *      clean up the other resources.
125
         */
126
 
127
        if(cache->mfc_flags&MFC_QUEUED)
128
        {
129
                cache_resolve_queue_len--;
130
                while((skb=skb_dequeue(&cache->mfc_unresolved)))
131
                        kfree_skb(skb, FREE_WRITE);
132
        }
133
        kfree_s(cache,sizeof(cache));
134
}
135
 
136
/*
137
 *      Cache expiry timer
138
 */
139
 
140
static void ipmr_cache_timer(unsigned long data)
141
{
142
        struct mfc_cache *cache=(struct mfc_cache *)data;
143
        ipmr_cache_delete(cache);
144
}
145
 
146
/*
147
 *      Insert a multicast cache entry
148
 */
149
 
150
static void ipmr_cache_insert(struct mfc_cache *c)
151
{
152
        int line=MFC_HASH(c->mfc_mcastgrp,c->mfc_origin);
153
        c->next=mfc_cache_array[line];
154
        mfc_cache_array[line]=c;
155
}
156
 
157
/*
158
 *      Find a multicast cache entry
159
 */
160
 
161
struct mfc_cache *ipmr_cache_find(__u32 origin, __u32 mcastgrp)
162
{
163
        int line=MFC_HASH(mcastgrp,origin);
164
        struct mfc_cache *cache;
165
        cache=mfc_cache_array[line];
166
        while(cache!=NULL)
167
        {
168
                if(cache->mfc_origin==origin && cache->mfc_mcastgrp==mcastgrp)
169
                        return cache;
170
                cache=cache->next;
171
        }
172
        cache=cache_resolve_queue;
173
        while(cache!=NULL)
174
        {
175
                if(cache->mfc_origin==origin && cache->mfc_mcastgrp==mcastgrp)
176
                        return cache;
177
                cache=cache->next;
178
        }
179
        return NULL;
180
}
181
 
182
/*
183
 *      Allocate a multicast cache entry
184
 */
185
 
186
static struct mfc_cache *ipmr_cache_alloc(int priority)
187
{
188
        struct mfc_cache *c=(struct mfc_cache *)kmalloc(sizeof(struct mfc_cache), priority);
189
        if(c==NULL)
190
                return NULL;
191
        c->mfc_queuelen=0;
192
        skb_queue_head_init(&c->mfc_unresolved);
193
        init_timer(&c->mfc_timer);
194
        c->mfc_timer.data=(long)c;
195
        c->mfc_timer.function=ipmr_cache_timer;
196
        c->mfc_packets=0;
197
        c->mfc_bytes=0;
198
        return c;
199
}
200
 
201
/*
202
 *      A cache entry has gone into a resolved state from queued
203
 */
204
 
205
static void ipmr_cache_resolve(struct mfc_cache *cache)
206
{
207
        struct mfc_cache **p;
208
        struct sk_buff *skb;
209
        /*
210
         *      Kill the queue entry timer.
211
         */
212
        del_timer(&cache->mfc_timer);
213
        cache->mfc_flags&=~MFC_QUEUED;
214
        /*
215
         *      Remove from the resolve queue
216
         */
217
        p=&cache_resolve_queue;
218
        while((*p)!=NULL)
219
        {
220
                if((*p)==cache)
221
                {
222
                        *p=cache->next;
223
                        break;
224
                }
225
                p=&((*p)->next);
226
        }
227
        cache_resolve_queue_len--;
228
        sti();
229
        /*
230
         *      Insert into the main cache
231
         */
232
        ipmr_cache_insert(cache);
233
        /*
234
         *      Play the pending entries through our router
235
         */
236
        while((skb=skb_dequeue(&cache->mfc_unresolved)))
237
                ipmr_forward(skb, skb->protocol);
238
}
239
 
240
/*
241
 *      Bounce a cache query up to mrouted. We could use netlink for this but mrouted
242
 *      expects the following bizarre scheme..
243
 */
244
 
245
static void ipmr_cache_report(struct sk_buff *pkt)
246
{
247
        struct sk_buff *skb=alloc_skb(128, GFP_ATOMIC);
248
        int ihl=pkt->ip_hdr->ihl<<2;
249
        struct igmphdr *igmp;
250
        if(!skb)
251
                return;
252
 
253
        skb->free=1;
254
 
255
        /*
256
         *      Copy the IP header
257
         */
258
 
259
        skb->ip_hdr=(struct iphdr *)skb_put(skb,ihl);
260
        skb->h.iph=skb->ip_hdr;
261
        memcpy(skb->data,pkt->data,ihl);
262
        skb->ip_hdr->protocol = 0;                       /* Flag to the kernel this is a route add */
263
 
264
        /*
265
         *      Add our header
266
         */
267
 
268
        igmp=(struct igmphdr *)skb_put(skb,sizeof(struct igmphdr));
269
        igmp->type      =       IGMPMSG_NOCACHE;                /* non IGMP dummy message */
270
        igmp->code      =       0;
271
        skb->ip_hdr->tot_len=htons(skb->len);                   /* Fix the length */
272
 
273
        /*
274
         *      Deliver to mrouted
275
         */
276
        if(sock_queue_rcv_skb(mroute_socket,skb)<0)
277
        {
278
                skb->sk=NULL;
279
                kfree_skb(skb, FREE_READ);
280
        }
281
}
282
 
283
 
284
/*
285
 *      Queue a packet for resolution
286
 */
287
 
288
static void ipmr_cache_unresolved(struct mfc_cache *cache, vifi_t vifi, struct sk_buff *skb, int is_frag)
289
{
290
        if(cache==NULL)
291
        {
292
                /*
293
                 *      Create a new entry if allowable
294
                 */
295
                if(cache_resolve_queue_len>=10 || (cache=ipmr_cache_alloc(GFP_ATOMIC))==NULL)
296
                {
297
                        kfree_skb(skb, FREE_WRITE);
298
                        return;
299
                }
300
                /*
301
                 *      Fill in the new cache entry
302
                 */
303
                cache->mfc_parent=vifi;
304
                cache->mfc_origin=skb->ip_hdr->saddr;
305
                cache->mfc_mcastgrp=skb->ip_hdr->daddr;
306
                cache->mfc_flags=MFC_QUEUED;
307
                /*
308
                 *      Link to the unresolved list
309
                 */
310
                cache->next=cache_resolve_queue;
311
                cache_resolve_queue=cache;
312
                cache_resolve_queue_len++;
313
                /*
314
                 *      Fire off the expiry timer
315
                 */
316
                cache->mfc_timer.expires=jiffies+10*HZ;
317
                add_timer(&cache->mfc_timer);
318
                /*
319
                 *      Reflect first query at mrouted.
320
                 */
321
                if(mroute_socket)
322
                        ipmr_cache_report(skb);
323
        }
324
        /*
325
         *      See if we can append the packet
326
         */
327
        if(cache->mfc_queuelen>3)
328
        {
329
                kfree_skb(skb, FREE_WRITE);
330
                return;
331
        }
332
        /*
333
         *      Add to our 'pending' list. Cache the is_frag data
334
         *      in skb->protocol now it is spare.
335
         */
336
        cache->mfc_queuelen++;
337
        skb->protocol=is_frag;
338
        skb_queue_tail(&cache->mfc_unresolved,skb);
339
}
340
 
341
/*
342
 *      MFC cache manipulation by user space mroute daemon
343
 */
344
 
345
int ipmr_mfc_modify(int action, struct mfcctl *mfc)
346
{
347
        struct mfc_cache *cache;
348
        if(!MULTICAST(mfc->mfcc_mcastgrp.s_addr))
349
                return -EINVAL;
350
        /*
351
         *      Find the cache line
352
         */
353
 
354
        cli();
355
 
356
        cache=ipmr_cache_find(mfc->mfcc_origin.s_addr,mfc->mfcc_mcastgrp.s_addr);
357
 
358
        /*
359
         *      Delete an entry
360
         */
361
        if(action==MRT_DEL_MFC)
362
        {
363
                if(cache)
364
                {
365
                        ipmr_cache_delete(cache);
366
                        sti();
367
                        return 0;
368
                }
369
                sti();
370
                return -ENOENT;
371
        }
372
        if(cache)
373
        {
374
                /*
375
                 *      Update the cache, see if it frees a pending queue
376
                 */
377
 
378
                cache->mfc_flags|=MFC_RESOLVED;
379
                cache->mfc_parent=mfc->mfcc_parent;
380
 
381
                memcpy(cache->mfc_ttls, mfc->mfcc_ttls,sizeof(cache->mfc_ttls));
382
 
383
                /*
384
                 *      Check to see if we resolved a queued list. If so we
385
                 *      need to send on the frames and tidy up.
386
                 */
387
 
388
                if(cache->mfc_flags&MFC_QUEUED)
389
                        ipmr_cache_resolve(cache);      /* Unhook & send the frames */
390
                sti();
391
                return 0;
392
        }
393
        /*
394
         *      Unsolicited update - that's ok, add anyway.
395
         */
396
 
397
 
398
        cache=ipmr_cache_alloc(GFP_ATOMIC);
399
        if(cache==NULL)
400
        {
401
                sti();
402
                return -ENOMEM;
403
        }
404
        cache->mfc_flags=MFC_RESOLVED;
405
        cache->mfc_origin=mfc->mfcc_origin.s_addr;
406
        cache->mfc_mcastgrp=mfc->mfcc_mcastgrp.s_addr;
407
        cache->mfc_parent=mfc->mfcc_parent;
408
        memcpy(cache->mfc_ttls, mfc->mfcc_ttls,sizeof(cache->mfc_ttls));
409
        ipmr_cache_insert(cache);
410
        sti();
411
        return 0;
412
}
413
 
414
/*
415
 *      Socket options and virtual interface manipulation. The whole
416
 *      virtual interface system is a complete heap, but unfortunately
417
 *      that's how BSD mrouted happens to think. Maybe one day with a proper
418
 *      MOSPF/PIM router set up we can clean this up.
419
 */
420
 
421
int ip_mroute_setsockopt(struct sock *sk,int optname,char *optval,int optlen)
422
{
423
        int err;
424
        struct vifctl vif;
425
        struct mfcctl mfc;
426
 
427
        if(optname!=MRT_INIT)
428
        {
429
                if(sk!=mroute_socket)
430
                        return -EACCES;
431
        }
432
 
433
        switch(optname)
434
        {
435
                case MRT_INIT:
436
                        if(sk->type!=SOCK_RAW || sk->num!=IPPROTO_IGMP)
437
                                return -EOPNOTSUPP;
438
                        if(optlen!=sizeof(int))
439
                                return -ENOPROTOOPT;
440
                        if((err=verify_area(VERIFY_READ,optval,sizeof(int)))<0)
441
                                return err;
442
                        if(get_user((int *)optval)!=1)
443
                                return -ENOPROTOOPT;
444
                        if(mroute_socket)
445
                                return -EADDRINUSE;
446
                        mroute_socket=sk;
447
                        /* Initialise state */
448
                        return 0;
449
                case MRT_DONE:
450
                        mroute_close(sk);
451
                        mroute_socket=NULL;
452
                        return 0;
453
                case MRT_ADD_VIF:
454
                case MRT_DEL_VIF:
455
                        if(optlen!=sizeof(vif))
456
                                return -EINVAL;
457
                        if((err=verify_area(VERIFY_READ, optval, sizeof(vif)))<0)
458
                                return err;
459
                        memcpy_fromfs(&vif,optval,sizeof(vif));
460
                        if(vif.vifc_vifi > MAXVIFS)
461
                                return -ENFILE;
462
                        if(optname==MRT_ADD_VIF)
463
                        {
464
                                struct vif_device *v=&vif_table[vif.vifc_vifi];
465
                                struct device *dev;
466
                                /* Empty vif ? */
467
                                if(vifc_map&(1<<vif.vifc_vifi))
468
                                        return -EADDRINUSE;
469
                                /* Find the interface */
470
                                dev=ip_dev_find(vif.vifc_lcl_addr.s_addr);
471
                                if(!dev)
472
                                        return -EADDRNOTAVAIL;
473
                                /* Must be tunnelled or multicastable */
474
                                if(vif.vifc_flags&VIFF_TUNNEL)
475
                                {
476
                                        if(vif.vifc_flags&VIFF_SRCRT)
477
                                                return -EOPNOTSUPP;
478
                                        /* IPIP will do all the work */
479
                                }
480
                                else
481
                                {
482
                                        if(dev->flags&IFF_MULTICAST)
483
                                        {
484
                                                /* Most ethernet cards don't know
485
                                                   how to do this yet.. */
486
                                                dev->flags|=IFF_ALLMULTI;
487
                                                dev_mc_upload(dev);
488
                                        }
489
                                        else
490
                                        {
491
                                                /* We are stuck.. */
492
                                                return -EOPNOTSUPP;
493
                                        }
494
                                }
495
                                /*
496
                                 *      Fill in the VIF structures
497
                                 */
498
                                cli();
499
                                v->rate_limit=vif.vifc_rate_limit;
500
                                v->local=vif.vifc_lcl_addr.s_addr;
501
                                v->remote=vif.vifc_rmt_addr.s_addr;
502
                                v->flags=vif.vifc_flags;
503
                                v->threshold=vif.vifc_threshold;
504
                                v->dev=dev;
505
                                v->bytes_in = 0;
506
                                v->bytes_out = 0;
507
                                v->pkt_in = 0;
508
                                v->pkt_out = 0;
509
                                vifc_map|=(1<<vif.vifc_vifi);
510
                                sti();
511
                                return 0;
512
                        }
513
                        else
514
                        /*
515
                         *      VIF deletion
516
                         */
517
                        {
518
                                struct vif_device *v=&vif_table[vif.vifc_vifi];
519
                                if(vifc_map&(1<<vif.vifc_vifi))
520
                                {
521
                                        vif_delete(v);
522
                                        vifc_map&=~(1<<vif.vifc_vifi);
523
                                        return 0;
524
                                }
525
                                else
526
                                        return -EADDRNOTAVAIL;
527
                        }
528
                /*
529
                 *      Manipulate the forwarding caches. These live
530
                 *      in a sort of kernel/user symbiosis.
531
                 */
532
                case MRT_ADD_MFC:
533
                case MRT_DEL_MFC:
534
                        err=verify_area(VERIFY_READ, optval, sizeof(mfc));
535
                        if(err)
536
                                return err;
537
                        memcpy_fromfs(&mfc,optval, sizeof(mfc));
538
                        return ipmr_mfc_modify(optname, &mfc);
539
                /*
540
                 *      Control PIM assert.
541
                 */
542
                case MRT_ASSERT:
543
                        if(optlen!=sizeof(int))
544
                                return -EINVAL;
545
                        if((err=verify_area(VERIFY_READ, optval,sizeof(int)))<0)
546
                                return err;
547
                        mroute_do_pim= get_user((int *)optval)?1:0;
548
                        return 0;
549
                /*
550
                 *      Spurious command, or MRT_VERSION which you cannot
551
                 *      set.
552
                 */
553
                default:
554
                        return -EOPNOTSUPP;
555
        }
556
}
557
 
558
/*
559
 *      Getsock opt support for the multicast routing system.
560
 */
561
 
562
int ip_mroute_getsockopt(struct sock *sk,int optname,char *optval,int *optlen)
563
{
564
        int olr;
565
        int err;
566
 
567
        if(sk!=mroute_socket)
568
                return -EACCES;
569
        if(optname!=MRT_VERSION && optname!=MRT_ASSERT)
570
                return -EOPNOTSUPP;
571
 
572
        olr=get_user(optlen);
573
        if(olr!=sizeof(int))
574
                return -EINVAL;
575
        err=verify_area(VERIFY_WRITE, optval,sizeof(int));
576
        if(err)
577
                return err;
578
        put_user(sizeof(int),optlen);
579
        if(optname==MRT_VERSION)
580
                put_user(0x0305,(int *)optval);
581
        else
582
                put_user(mroute_do_pim,(int *)optval);
583
        return 0;
584
}
585
 
586
/*
587
 *      The IP multicast ioctl support routines.
588
 */
589
 
590
int ipmr_ioctl(struct sock *sk, int cmd, unsigned long arg)
591
{
592
        int err;
593
        struct sioc_sg_req sr;
594
        struct sioc_vif_req vr;
595
        struct vif_device *vif;
596
        struct mfc_cache *cl;
597
 
598
        switch(cmd)
599
        {
600
                case SIOCGETVIFCNT:
601
                        err=verify_area(VERIFY_WRITE, (void *)arg, sizeof(vr));
602
                        if(err)
603
                                return err;
604
                        memcpy_fromfs(&vr,(void *)arg,sizeof(vr));
605
                        if(vr.vifi>=MAXVIFS)
606
                                return -EINVAL;
607
                        vif=&vif_table[vr.vifi];
608
                        if(vifc_map&(1<<vr.vifi))
609
                        {
610
                                vr.icount=vif->pkt_in;
611
                                vr.ocount=vif->pkt_out;
612
                                vr.ibytes=vif->bytes_in;
613
                                vr.obytes=vif->bytes_out;
614
                                memcpy_tofs((void *)arg,&vr,sizeof(vr));
615
                                return 0;
616
                        }
617
                        return -EADDRNOTAVAIL;
618
                case SIOCGETSGCNT:
619
                        err=verify_area(VERIFY_WRITE, (void *)arg, sizeof(sr));
620
                        if(err)
621
                                return err;
622
                        memcpy_fromfs(&sr,(void *)arg,sizeof(sr));
623
                        cl=ipmr_cache_find(sr.src.s_addr,sr.grp.s_addr);
624
                        if(cl==NULL)
625
                        {
626
                                sr.pktcnt=0;
627
                                sr.bytecnt=0;
628
                                sr.wrong_if=0;
629
                        }
630
                        else
631
                        {
632
                                sr.pktcnt=cl->mfc_packets;
633
                                sr.bytecnt=cl->mfc_bytes;
634
                                sr.wrong_if=0;
635
                        }
636
                        memcpy_tofs((void *)arg,&sr,sizeof(sr));
637
                        return 0;
638
                default:
639
                        return -EINVAL;
640
        }
641
}
642
 
643
/*
644
 *      Close the multicast socket, and clear the vif tables etc
645
 */
646
 
647
void mroute_close(struct sock *sk)
648
{
649
        int i;
650
        struct vif_device *v=&vif_table[0];
651
 
652
        /*
653
         *      Shut down all active vif entries
654
         */
655
 
656
        for(i=0;i<MAXVIFS;i++)
657
        {
658
                if(vifc_map&(1<<i))
659
                {
660
                        if(!(v->flags&VIFF_TUNNEL))
661
                        {
662
                                v->dev->flags&=~IFF_ALLMULTI;
663
                                dev_mc_upload(v->dev);
664
                        }
665
                }
666
                v++;
667
        }
668
        vifc_map=0;
669
        /*
670
         *      Wipe the cache
671
         */
672
        for(i=0;i<MFC_LINES;i++)
673
        {
674
                while(mfc_cache_array[i]!=NULL)
675
                        ipmr_cache_delete(mfc_cache_array[i]);
676
        }
677
        /* The timer will clear any 'pending' stuff */
678
}
679
 
680
static int ipmr_device_event(struct notifier_block *this, unsigned long event, void *ptr)
681
{
682
        struct vif_device *v;
683
        int ct;
684
        if(event!=NETDEV_DOWN)
685
                return NOTIFY_DONE;
686
        v=&vif_table[0];
687
        for(ct=0;ct<MAXVIFS;ct++)
688
        {
689
                if((vifc_map&(1<<ct)) && v->dev==ptr)
690
                {
691
                        vif_delete(v);
692
                        vifc_map&=~(1<<ct);
693
                }
694
                v++;
695
        }
696
        return NOTIFY_DONE;
697
}
698
 
699
 
700
static struct notifier_block ip_mr_notifier={
701
        ipmr_device_event,
702
        NULL,
703
 
704
};
705
 
706
/*
707
 *      Processing handlers for ipmr_forward
708
 */
709
 
710
static void ipmr_queue_xmit(struct sk_buff *skb, struct vif_device *vif, struct device *in_dev, int frag)
711
{
712
        int tunnel=0;
713
        __u32 raddr=skb->raddr;
714
        if(vif->flags&VIFF_TUNNEL)
715
        {
716
                tunnel=IPFWD_MULTITUNNEL;
717
                raddr=vif->remote;
718
        }
719
        vif->pkt_out++;
720
        vif->bytes_out+=skb->len;
721
        skb->dev=vif->dev;
722
        skb->raddr=skb->h.iph->daddr;
723
        /*
724
         *      If the vif went down as we were forwarding.. just throw the
725
         *      frame.
726
         */
727
        if(vif->dev==NULL || ip_forward(skb, in_dev, frag|IPFWD_MULTICASTING|tunnel, raddr)==-1)
728
                kfree_skb(skb, FREE_WRITE);
729
}
730
 
731
/*
732
 *      Multicast packets for forwarding arrive here
733
 */
734
 
735
void ipmr_forward(struct sk_buff *skb, int is_frag)
736
{
737
        struct mfc_cache *cache;
738
        struct sk_buff *skb2;
739
        int psend = -1;
740
        int vif,ct=0;
741
 
742
        /*
743
         *      Without the following addition, skb->h.iph points to something
744
         *      different that is not the ip header.
745
         */
746
 
747
        skb->h.iph = skb->ip_hdr;  /* Anand, ernet.  */
748
 
749
        cache=ipmr_cache_find(skb->ip_hdr->saddr,skb->ip_hdr->daddr);
750
 
751
        /*
752
         *      No usable cache entry
753
         */
754
 
755
        if(cache==NULL || (cache->mfc_flags&MFC_QUEUED))
756
        {
757
                ipmr_cache_unresolved(cache,ALL_VIFS,skb, is_frag);
758
                return;
759
        }
760
 
761
        vif=cache->mfc_parent;
762
 
763
        if(vif>=MAXVIFS || !(vifc_map&(1<<vif)) ||
764
                vif_table[vif].dev != skb->dev)
765
        {
766
                kfree_skb(skb, FREE_READ);
767
                return;
768
        }
769
 
770
        vif_table[vif].pkt_in++;
771
        vif_table[vif].bytes_in+=skb->len;
772
        cache->mfc_packets++;
773
        cache->mfc_bytes+=skb->len;
774
 
775
        /*
776
         *      Forward the frame
777
         */
778
 
779
         while(ct<MAXVIFS)
780
         {
781
                /*
782
                 *      0 means don't do it. Silly idea, 255 as don't do it would be cleaner!
783
                 */
784
                if(skb->ip_hdr->ttl > cache->mfc_ttls[ct] && cache->mfc_ttls[ct]>0)
785
                {
786
                        if(psend!=-1)
787
                        {
788
                                /*
789
                                 *      May get variant mac headers
790
                                 *      so must copy -- boo hoo.
791
                                 */
792
                                skb2=skb_copy(skb, GFP_ATOMIC);
793
                                if(skb2)
794
                                {
795
                                        skb2->free=1;
796
                                        ipmr_queue_xmit(skb2, &vif_table[psend], skb->dev, is_frag);
797
                                }
798
                        }
799
                        psend=ct;
800
                }
801
                ct++;
802
        }
803
        if(psend==-1)
804
                kfree_skb(skb, FREE_WRITE);
805
        else
806
                ipmr_queue_xmit(skb, &vif_table[psend], skb->dev, is_frag);
807
}
808
 
809
/*
810
 *      The /proc interfaces to multicast routing /proc/ip_mr_cache /proc/ip_mr_vif
811
 */
812
 
813
int ipmr_vif_info(char *buffer, char **start, off_t offset, int length, int dummy)
814
{
815
        struct vif_device *vif;
816
        int len=0;
817
        off_t pos=0;
818
        off_t begin=0;
819
        int size;
820
        int ct;
821
 
822
        len += sprintf(buffer,
823
                 "Interface  Bytes In  Pkts In  Bytes Out  Pkts Out  Flags Local    Remote\n");
824
        pos=len;
825
 
826
        for (ct=0;ct<MAXVIFS;ct++)
827
        {
828
                vif=&vif_table[ct];
829
                if(!(vifc_map&(1<<ct)))
830
                        continue;
831
                if(vif->dev==NULL)
832
                        continue;
833
                size = sprintf(buffer+len, "%-10s %8ld  %7ld  %8ld   %7ld   %05X %08lX %08lX\n",
834
                        vif->dev->name,vif->bytes_in, vif->pkt_in, vif->bytes_out,vif->pkt_out,
835
                        vif->flags, vif->local, vif->remote);
836
                len+=size;
837
                pos+=size;
838
                if(pos<offset)
839
                {
840
                        len=0;
841
                        begin=pos;
842
                }
843
                if(pos>offset+length)
844
                        break;
845
        }
846
 
847
        *start=buffer+(offset-begin);
848
        len-=(offset-begin);
849
        if(len>length)
850
                len=length;
851
        return len;
852
}
853
 
854
int ipmr_mfc_info(char *buffer, char **start, off_t offset, int length, int dummy)
855
{
856
        struct mfc_cache *mfc;
857
        int len=0;
858
        off_t pos=0;
859
        off_t begin=0;
860
        int size;
861
        int ct;
862
 
863
        len += sprintf(buffer,
864
                 "Group    Origin   SrcIface VifTtls\n");
865
        pos=len;
866
 
867
        for (ct=0;ct<MFC_LINES+1;ct++)
868
        {
869
                cli();
870
                mfc=mfc_cache_array[ct];
871
                while(mfc!=NULL)
872
                {
873
                        char *name="none";
874
                        int n;
875
                        /*
876
                         *      Device name
877
                         */
878
                        if(mfc->mfc_parent < MAXVIFS && vifc_map&(1<<mfc->mfc_parent))
879
                                name=vif_table[mfc->mfc_parent].dev->name;
880
 
881
                        size = sprintf(buffer+len, "%08lX %08lX %-8s",
882
                                (unsigned long)mfc->mfc_mcastgrp,
883
                                (unsigned long)mfc->mfc_origin,
884
                                name);
885
 
886
                        for(n=0;n<MAXVIFS;n++)
887
                        {
888
                                if(vifc_map&(1<<n))
889
                                        size+=sprintf(buffer+len+size,
890
                                                " %-3d", mfc->mfc_ttls[n]);
891
                                else
892
                                        size+=sprintf(buffer+len+size,
893
                                                " --- ");
894
                        }
895
                        size+=sprintf(buffer+len+size,"\n");
896
                        len+=size;
897
                        pos+=size;
898
                        if(pos<offset)
899
                        {
900
                                len=0;
901
                                begin=pos;
902
                        }
903
                        if(pos>offset+length)
904
                        {
905
                                sti();
906
                                goto done;
907
                        }
908
                        mfc=mfc->next;
909
                }
910
                sti();
911
        }
912
done:
913
        *start=buffer+(offset-begin);
914
        len-=(offset-begin);
915
        if(len>length)
916
                len=length;
917
        return len;
918
}
919
 
920
/*
921
 *      Setup for IP multicast routing
922
 */
923
 
924
#ifdef CONFIG_PROC_FS   
925
static struct proc_dir_entry pde1 = {
926
                PROC_NET_IPMR_VIF, 9 ,"ip_mr_vif",
927
                S_IFREG | S_IRUGO, 1, 0, 0,
928
                0, &proc_net_inode_operations,
929
                ipmr_vif_info
930
        };
931
static struct proc_net_register pde2 = {
932
                PROC_NET_IPMR_MFC, 11 ,"ip_mr_cache",
933
                S_IFREG | S_IRUGO, 1, 0, 0,
934
                0, &proc_net_inode_operations,
935
                ipmr_mfc_info
936
        };
937
#endif  
938
 
939
void ip_mr_init(void)
940
{
941
        printk(KERN_INFO "Linux IP multicast router 0.07.\n");
942
        register_netdevice_notifier(&ip_mr_notifier);
943
#ifdef CONFIG_PROC_FS   
944
        proc_net_register(&pde1);
945
        proc_net_register(&pde2);
946
#endif  
947
}

powered by: WebSVN 2.1.0

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