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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [packages/] [net/] [bsd_tcpip/] [v2_0/] [src/] [sys/] [net/] [if_loop.c] - Blame information for rev 174

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 27 unneback
//==========================================================================
2
//
3
//      src/sys/net/if_loop.c
4
//
5
//==========================================================================
6
//####BSDCOPYRIGHTBEGIN####
7
//
8
// -------------------------------------------
9
//
10
// Portions of this software may have been derived from OpenBSD, 
11
// FreeBSD or other sources, and are covered by the appropriate
12
// copyright disclaimers included herein.
13
//
14
// Portions created by Red Hat are
15
// Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.
16
//
17
// -------------------------------------------
18
//
19
//####BSDCOPYRIGHTEND####
20
//==========================================================================
21
 
22
/*
23
 * Copyright (c) 1982, 1986, 1993
24
 *      The Regents of the University of California.  All rights reserved.
25
 *
26
 * Redistribution and use in source and binary forms, with or without
27
 * modification, are permitted provided that the following conditions
28
 * are met:
29
 * 1. Redistributions of source code must retain the above copyright
30
 *    notice, this list of conditions and the following disclaimer.
31
 * 2. Redistributions in binary form must reproduce the above copyright
32
 *    notice, this list of conditions and the following disclaimer in the
33
 *    documentation and/or other materials provided with the distribution.
34
 * 3. All advertising materials mentioning features or use of this software
35
 *    must display the following acknowledgement:
36
 *      This product includes software developed by the University of
37
 *      California, Berkeley and its contributors.
38
 * 4. Neither the name of the University nor the names of its contributors
39
 *    may be used to endorse or promote products derived from this software
40
 *    without specific prior written permission.
41
 *
42
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
43
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
44
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
45
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
46
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
47
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
48
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
49
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
50
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
51
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
52
 * SUCH DAMAGE.
53
 *
54
 *      @(#)if_loop.c   8.1 (Berkeley) 6/10/93
55
 * $FreeBSD: src/sys/net/if_loop.c,v 1.47.2.5 2001/07/03 11:01:41 ume Exp $
56
 */
57
 
58
/*
59
 * Loopback interface driver for protocol testing and timing.
60
 */
61
#include <sys/param.h>
62
#include <sys/mbuf.h>
63
#include <sys/socket.h>
64
#include <sys/sockio.h>
65
 
66
#include <net/if.h>
67
#include <net/if_types.h>
68
#include <net/netisr.h>
69
#include <net/route.h>
70
 
71
#ifdef  INET
72
#include <netinet/in.h>
73
#include <netinet/in_var.h>
74
#endif
75
 
76
#ifdef IPX
77
#include <netipx/ipx.h>
78
#include <netipx/ipx_if.h>
79
#endif
80
 
81
#ifdef INET6
82
#ifndef INET
83
#include <netinet/in.h>
84
#endif
85
#include <netinet6/in6_var.h>
86
#include <netinet/ip6.h>
87
#endif
88
 
89
#ifdef NS
90
#include <netns/ns.h>
91
#include <netns/ns_if.h>
92
#endif
93
 
94
#ifdef NETATALK
95
#include <netatalk/at.h>
96
#include <netatalk/at_var.h>
97
#endif /* NETATALK */
98
 
99
int loioctl __P((struct ifnet *, u_long, caddr_t));
100
static void lortrequest __P((int, struct rtentry *, struct sockaddr *));
101
 
102
static void loopattach __P((void *));
103
#ifdef ALTQ
104
static void lo_altqstart __P((struct ifnet *));
105
#endif
106
PSEUDO_SET(loopattach, if_loop);
107
 
108
int looutput __P((struct ifnet *ifp,
109
                struct mbuf *m, struct sockaddr *dst, struct rtentry *rt));
110
 
111
#ifdef TINY_LOMTU
112
#define LOMTU   (1024+512)
113
#elif defined(LARGE_LOMTU)
114
#define LOMTU   131072
115
#else
116
#define LOMTU   16384
117
#endif
118
 
119
struct  ifnet loif[NLOOP];
120
 
121
/* ARGSUSED */
122
static void
123
loopattach(dummy)
124
        void *dummy;
125
{
126
        register struct ifnet *ifp;
127
        register int i = 0;
128
 
129
        for (ifp = loif; i < NLOOP; ifp++) {
130
            ifp->if_name = "lo";
131
            ifp->if_unit = i++;
132
            ifp->if_mtu = LOMTU;
133
            ifp->if_flags = IFF_LOOPBACK | IFF_MULTICAST;
134
            ifp->if_ioctl = loioctl;
135
            ifp->if_output = looutput;
136
            ifp->if_type = IFT_LOOP;
137
            IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
138
            IFQ_SET_READY(&ifp->if_snd);
139
            if_attach(ifp);
140
#ifdef BPF
141
            bpfattach(ifp, DLT_NULL, sizeof(u_int));
142
#endif
143
        }
144
}
145
 
146
int
147
looutput(ifp, m, dst, rt)
148
        struct ifnet *ifp;
149
        register struct mbuf *m;
150
        struct sockaddr *dst;
151
        register struct rtentry *rt;
152
{
153
        if ((m->m_flags & M_PKTHDR) == 0)
154
                panic("looutput no HDR");
155
 
156
        if (rt && rt->rt_flags & (RTF_REJECT|RTF_BLACKHOLE)) {
157
                m_freem(m);
158
                return (rt->rt_flags & RTF_BLACKHOLE ? 0 :
159
                        rt->rt_flags & RTF_HOST ? EHOSTUNREACH : ENETUNREACH);
160
        }
161
        /*
162
         * KAME requires that the packet to be contiguous on the
163
         * mbuf.  We need to make that sure.
164
         * this kind of code should be avoided.
165
         * XXX: fails to join if interface MTU > MCLBYTES.  jumbogram?
166
         */
167
        if (m && m->m_next != NULL && m->m_pkthdr.len < MCLBYTES) {
168
                struct mbuf *n;
169
 
170
                MGETHDR(n, M_DONTWAIT, MT_HEADER);
171
                if (!n)
172
                        goto contiguousfail;
173
                MCLGET(n, M_DONTWAIT);
174
                if (! (n->m_flags & M_EXT)) {
175
                        m_freem(n);
176
                        goto contiguousfail;
177
                }
178
 
179
                m_copydata(m, 0, m->m_pkthdr.len, mtod(n, caddr_t));
180
                n->m_pkthdr = m->m_pkthdr;
181
                n->m_len = m->m_pkthdr.len;
182
                n->m_pkthdr.aux = m->m_pkthdr.aux;
183
                m->m_pkthdr.aux = (struct mbuf *)NULL;
184
                m_freem(m);
185
                m = n;
186
        }
187
        if (0) {
188
contiguousfail:
189
                printf("looutput: mbuf allocation failed\n");
190
        }
191
 
192
        ifp->if_opackets++;
193
        ifp->if_obytes += m->m_pkthdr.len;
194
#if 1   /* XXX */
195
        switch (dst->sa_family) {
196
        case AF_INET:
197
        case AF_INET6:
198
        case AF_IPX:
199
        case AF_NS:
200
        case AF_APPLETALK:
201
                break;
202
        default:
203
                printf("looutput: af=%d unexpected\n", dst->sa_family);
204
                m_freem(m);
205
                return (EAFNOSUPPORT);
206
        }
207
#endif
208
        return(if_simloop(ifp, m, dst->sa_family, 0));
209
}
210
 
211
/*
212
 * if_simloop()
213
 *
214
 * This function is to support software emulation of hardware loopback,
215
 * i.e., for interfaces with the IFF_SIMPLEX attribute. Since they can't
216
 * hear their own broadcasts, we create a copy of the packet that we
217
 * would normally receive via a hardware loopback.
218
 *
219
 * This function expects the packet to include the media header of length hlen.
220
 */
221
 
222
int
223
if_simloop(ifp, m, af, hlen)
224
        struct ifnet *ifp;
225
        struct mbuf *m;
226
        int af;
227
        int hlen;
228
{
229
        int s, isr;
230
        register struct ifqueue *ifq = 0;
231
 
232
        m->m_pkthdr.rcvif = ifp;
233
 
234
        /* BPF write needs to be handled specially */
235
        if (af == AF_UNSPEC) {
236
                af = *(mtod(m, int *));
237
                m->m_len -= sizeof(int);
238
                m->m_pkthdr.len -= sizeof(int);
239
                m->m_data += sizeof(int);
240
        }
241
 
242
#ifdef BPF
243
        /* Let BPF see incoming packet */
244
        if (ifp->if_bpf) {
245
                struct mbuf m0, *n = m;
246
 
247
                if (ifp->if_bpf->bif_dlt == DLT_NULL) {
248
                        /*
249
                         * We need to prepend the address family as
250
                         * a four byte field.  Cons up a dummy header
251
                         * to pacify bpf.  This is safe because bpf
252
                         * will only read from the mbuf (i.e., it won't
253
                         * try to free it or keep a pointer a to it).
254
                         */
255
                        m0.m_next = m;
256
                        m0.m_len = 4;
257
                        m0.m_data = (char *)&af;
258
                        n = &m0;
259
                }
260
                bpf_mtap(ifp, n);
261
        }
262
#endif
263
 
264
        /* Strip away media header */
265
        if (hlen > 0) {
266
                m_adj(m, hlen);
267
#ifdef __alpha__
268
                /* The alpha doesn't like unaligned data.
269
                 * We move data down in the first mbuf */
270
                if (mtod(m, vm_offset_t) & 3) {
271
//                      KASSERT(hlen >= 3, ("if_simloop: hlen too small"));
272
                        bcopy(m->m_data,
273
                            (char *)(mtod(m, vm_offset_t)
274
                                - (mtod(m, vm_offset_t) & 3)),
275
                            m->m_len);
276
                        mtod(m,vm_offset_t) -= (mtod(m, vm_offset_t) & 3);
277
                }
278
#endif
279
        }
280
 
281
        /* Deliver to upper layer protocol */
282
        switch (af) {
283
#ifdef INET
284
        case AF_INET:
285
                ifq = &ipintrq;
286
                isr = NETISR_IP;
287
                break;
288
#endif
289
#ifdef INET6
290
        case AF_INET6:
291
                m->m_flags |= M_LOOP;
292
                ifq = &ip6intrq;
293
                isr = NETISR_IPV6;
294
                break;
295
#endif
296
#ifdef IPX
297
        case AF_IPX:
298
                ifq = &ipxintrq;
299
                isr = NETISR_IPX;
300
                break;
301
#endif
302
#ifdef NS
303
        case AF_NS:
304
                ifq = &nsintrq;
305
                isr = NETISR_NS;
306
                break;
307
#endif
308
#ifdef NETATALK
309
        case AF_APPLETALK:
310
                ifq = &atintrq2;
311
                isr = NETISR_ATALK;
312
                break;
313
#endif /* NETATALK */
314
        default:
315
                printf("if_simloop: can't handle af=%d\n", af);
316
                m_freem(m);
317
                return (EAFNOSUPPORT);
318
        }
319
        s = splimp();
320
        if (IF_QFULL(ifq)) {
321
                IF_DROP(ifq);
322
                m_freem(m);
323
                splx(s);
324
                return (ENOBUFS);
325
        }
326
        IF_ENQUEUE(ifq, m);
327
        schednetisr(isr);
328
        ifp->if_ipackets++;
329
        ifp->if_ibytes += m->m_pkthdr.len;
330
        splx(s);
331
        return (0);
332
}
333
 
334
#ifdef ALTQ
335
static void
336
lo_altqstart(ifp)
337
        struct ifnet *ifp;
338
{
339
        struct ifqueue *ifq;
340
        struct mbuf *m;
341
        int32_t af, *afp;
342
        int s, isr;
343
 
344
        while (1) {
345
                s = splimp();
346
                IFQ_DEQUEUE(&ifp->if_snd, m);
347
                splx(s);
348
                if (m == NULL)
349
                        return;
350
 
351
                afp = mtod(m, int32_t *);
352
                af = *afp;
353
                m_adj(m, sizeof(int32_t));
354
 
355
                switch (af) {
356
#ifdef INET
357
                case AF_INET:
358
                        ifq = &ipintrq;
359
                        isr = NETISR_IP;
360
                        break;
361
#endif
362
#ifdef INET6
363
                case AF_INET6:
364
                        m->m_flags |= M_LOOP;
365
                        ifq = &ip6intrq;
366
                        isr = NETISR_IPV6;
367
                        break;
368
#endif
369
#ifdef IPX
370
                case AF_IPX:
371
                        ifq = &ipxintrq;
372
                        isr = NETISR_IPX;
373
                        break;
374
#endif
375
#ifdef NS
376
                case AF_NS:
377
                        ifq = &nsintrq;
378
                        isr = NETISR_NS;
379
                        break;
380
#endif
381
#ifdef ISO
382
                case AF_ISO:
383
                        ifq = &clnlintrq;
384
                        isr = NETISR_ISO;
385
                        break;
386
#endif
387
#ifdef NETATALK
388
                case AF_APPLETALK:
389
                        ifq = &atintrq2;
390
                        isr = NETISR_ATALK;
391
                        break;
392
#endif NETATALK
393
                default:
394
                        printf("lo_altqstart: can't handle af%d\n", af);
395
                        m_freem(m);
396
                        return;
397
                }
398
 
399
                s = splimp();
400
                if (IF_QFULL(ifq)) {
401
                        IF_DROP(ifq);
402
                        m_freem(m);
403
                        splx(s);
404
                        return;
405
                }
406
                IF_ENQUEUE(ifq, m);
407
                schednetisr(isr);
408
                ifp->if_ipackets++;
409
                ifp->if_ibytes += m->m_pkthdr.len;
410
                splx(s);
411
        }
412
}
413
#endif /* ALTQ */
414
 
415
/* ARGSUSED */
416
static void
417
lortrequest(cmd, rt, sa)
418
        int cmd;
419
        struct rtentry *rt;
420
        struct sockaddr *sa;
421
{
422
        if (rt) {
423
                rt->rt_rmx.rmx_mtu = rt->rt_ifp->if_mtu; /* for ISO */
424
                /*
425
                 * For optimal performance, the send and receive buffers
426
                 * should be at least twice the MTU plus a little more for
427
                 * overhead.
428
                 */
429
                rt->rt_rmx.rmx_recvpipe =
430
                        rt->rt_rmx.rmx_sendpipe = 3 * LOMTU;
431
        }
432
}
433
 
434
/*
435
 * Process an ioctl request.
436
 */
437
/* ARGSUSED */
438
int
439
loioctl(ifp, cmd, data)
440
        register struct ifnet *ifp;
441
        u_long cmd;
442
        caddr_t data;
443
{
444
        register struct ifaddr *ifa;
445
        register struct ifreq *ifr = (struct ifreq *)data;
446
        register int error = 0;
447
 
448
        switch (cmd) {
449
 
450
        case SIOCSIFADDR:
451
                ifp->if_flags |= IFF_UP | IFF_RUNNING | IFF_LOOPBACK;
452
                ifa = (struct ifaddr *)data;
453
                ifa->ifa_rtrequest = lortrequest;
454
                /*
455
                 * Everything else is done at a higher level.
456
                 */
457
                break;
458
 
459
        case SIOCADDMULTI:
460
        case SIOCDELMULTI:
461
                if (ifr == 0) {
462
                        error = EAFNOSUPPORT;           /* XXX */
463
                        break;
464
                }
465
                switch (ifr->ifr_addr.sa_family) {
466
 
467
#ifdef INET
468
                case AF_INET:
469
                        break;
470
#endif
471
#ifdef INET6
472
                case AF_INET6:
473
                        break;
474
#endif
475
 
476
                default:
477
                        error = EAFNOSUPPORT;
478
                        break;
479
                }
480
                break;
481
 
482
        case SIOCSIFMTU:
483
                ifp->if_mtu = ifr->ifr_mtu;
484
                break;
485
 
486
        case SIOCSIFFLAGS:
487
                break;
488
 
489
        default:
490
                error = EINVAL;
491
        }
492
        return (error);
493
}

powered by: WebSVN 2.1.0

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