source: rtems/c/src/lib/libnetworking/rtems/rtems_glue.c @ f74abcf7

4.104.114.84.95
Last change on this file since f74abcf7 was f74abcf7, checked in by Joel Sherrill <joel.sherrill@…>, on 05/28/99 at 18:21:25

Changes from Eric Norum to add a loop and limit on the length of time
the stack will wait for mbufs.

  • Property mode set to 100644
File size: 21.0 KB
Line 
1/*
2 *  $Id$
3 */
4
5#include <string.h>
6#include <stdarg.h>
7#include <stdio.h>
8#include <errno.h>
9
10#include <rtems.h>
11#include <rtems/libio.h>
12#include <rtems/error.h>
13#include <rtems/rtems_bsdnet.h>
14#include <sys/types.h>
15#include <sys/param.h>
16#include <sys/domain.h>
17#include <sys/mbuf.h>
18#include <sys/socketvar.h>
19#include <sys/socket.h>
20#include <sys/sockio.h>
21#include <sys/callout.h>
22#include <sys/proc.h>
23#include <sys/ioctl.h>
24#include <net/if.h>
25#include <net/route.h>
26#include <netinet/in.h>
27#include <vm/vm.h>
28#include <arpa/inet.h>
29
30#include <net/netisr.h>
31#include <net/route.h>
32
33/*
34 * Memory allocation
35 */
36static int nmbuf        = (64 * 1024) / MSIZE;
37       int nmbclusters  = (128 * 1024) / MCLBYTES;
38
39/*
40 * Socket buffering parameters
41 */
42unsigned long sb_efficiency = 8;
43
44/*
45 * Network task synchronization
46 */
47static rtems_id networkSemaphore;
48static rtems_id networkDaemonTid;
49static rtems_unsigned32 networkDaemonPriority;
50static void networkDaemon (void *task_argument);
51
52/*
53 * Network timing
54 */
55int                     rtems_bsdnet_ticks_per_second;
56int                     rtems_bsdnet_microseconds_per_tick;
57
58/*
59 * Callout processing
60 */
61static rtems_interval   ticksWhenCalloutsLastChecked;
62static struct callout *callfree, calltodo;
63
64/*
65 * FreeBSD variables
66 */
67int nfs_diskless_valid;
68
69/*
70 * BOOTP values
71 */
72struct in_addr rtems_bsdnet_log_host_address;
73struct in_addr rtems_bsdnet_bootp_server_address;
74char *rtems_bsdnet_bootp_boot_file_name;
75char *rtems_bsdnet_bootp_server_name;
76char *rtems_bsdnet_domain_name;
77struct in_addr rtems_bsdnet_nameserver[sizeof rtems_bsdnet_config.name_server /
78                        sizeof rtems_bsdnet_config.name_server[0]];
79int rtems_bsdnet_nameserver_count;
80
81/*
82 * Perform FreeBSD memory allocation.
83 * FIXME: This should be modified to keep memory allocation statistics.
84 */
85#undef malloc
86#undef free
87extern void *malloc (size_t);
88extern void free (void *);
89void *
90rtems_bsdnet_malloc (unsigned long size, int type, int flags)
91{
92        void *p;
93        int try = 0;
94
95        for (;;) {
96                p = malloc (size);
97                if (p || (flags & M_NOWAIT))
98                        return p;
99                rtems_bsdnet_semaphore_release ();
100                if (++try >= 30) {
101                        printf ("rtems_bsdnet_malloc still waiting.\n");
102                        try = 0;
103                }
104                rtems_task_wake_after (rtems_bsdnet_ticks_per_second);
105                rtems_bsdnet_semaphore_obtain ();
106        }
107}
108
109/*
110 * Free FreeBSD memory
111 * FIXME: This should be modified to keep memory allocation statistics.
112 */
113void
114rtems_bsdnet_free (void *addr, int type)
115{
116        free (addr);
117}
118
119/*
120 * Do the initializations required by the BSD code
121 */
122static void
123bsd_init ()
124{
125        int i;
126        char *p;
127
128        /*
129         * Set up mbuf cluster data strutures
130         */
131        p = malloc ((nmbclusters*MCLBYTES)+MCLBYTES-1);
132        p = (char *)(((unsigned long)p + (MCLBYTES-1)) & ~(MCLBYTES-1));
133        if (p == NULL)
134                rtems_panic ("Can't get network cluster memory.");
135        mbutl = (struct mbuf *)p;
136        for (i = 0; i < nmbclusters; i++) {
137                ((union mcluster *)p)->mcl_next = mclfree;
138                mclfree = (union mcluster *)p;
139                p += MCLBYTES;
140                mbstat.m_clfree++;
141        }
142        mbstat.m_clusters = nmbclusters;
143        mclrefcnt = malloc (nmbclusters);
144        if (mclrefcnt == NULL)
145                rtems_panic ("Can't get mbuf cluster reference counts memory.");
146        memset (mclrefcnt, '\0', nmbclusters);
147
148        /*
149         * Set up mbuf data structures
150         */
151
152        p = malloc(nmbuf * MSIZE + MSIZE - 1);
153        p = (char *)(((unsigned int)p + MSIZE - 1) & ~(MSIZE - 1));
154        if (p == NULL)
155                rtems_panic ("Can't get network memory.");
156        for (i = 0; i < nmbuf; i++) {
157                ((struct mbuf *)p)->m_next = mmbfree;
158                mmbfree = (struct mbuf *)p;
159                p += MSIZE;
160        }
161        mbstat.m_mbufs = nmbuf;
162        mbstat.m_mtypes[MT_FREE] = nmbuf;
163
164        /*
165         * Set up domains
166         */
167        {
168        extern struct domain routedomain;
169        extern struct domain inetdomain;
170
171        routedomain.dom_next = domains;
172        domains = &routedomain;
173        inetdomain.dom_next = domains;
174        domains = &inetdomain;
175        domaininit (NULL);
176        }
177
178        /*
179         * Set up interfaces
180         */
181        ifinit (NULL);
182}
183
184/*
185 * Initialize and start network operations
186 */
187static void
188rtems_bsdnet_initialize (void)
189{
190        rtems_status_code sc;
191
192        /*
193         * Set the priority of all network tasks
194         */
195        if (rtems_bsdnet_config.network_task_priority == 0)
196                networkDaemonPriority = 100;
197        else
198                networkDaemonPriority = rtems_bsdnet_config.network_task_priority;
199
200        /*
201         * Set the memory allocation limits
202         */
203        if (rtems_bsdnet_config.mbuf_bytecount)
204                nmbuf = rtems_bsdnet_config.mbuf_bytecount / MSIZE;
205        if (rtems_bsdnet_config.mbuf_cluster_bytecount)
206                nmbclusters = rtems_bsdnet_config.mbuf_cluster_bytecount / MCLBYTES;
207
208        /*
209         * Create the task-synchronization semaphore
210         */
211        sc = rtems_semaphore_create (rtems_build_name('B', 'S', 'D', 'n'),
212                                        0,
213                                        RTEMS_FIFO |
214                                                RTEMS_BINARY_SEMAPHORE |
215                                                RTEMS_NO_INHERIT_PRIORITY |
216                                                RTEMS_NO_PRIORITY_CEILING |
217                                                RTEMS_LOCAL,
218                                        0,
219                                        &networkSemaphore);
220        if (sc != RTEMS_SUCCESSFUL)
221                rtems_panic ("Can't create network seamphore: `%s'\n", rtems_status_text (sc));
222
223        /*
224         * Compute clock tick conversion factors
225         */
226        rtems_clock_get (RTEMS_CLOCK_GET_TICKS_PER_SECOND, &rtems_bsdnet_ticks_per_second);
227        if (rtems_bsdnet_ticks_per_second <= 0)
228                rtems_bsdnet_ticks_per_second = 1;
229        rtems_bsdnet_microseconds_per_tick = 1000000 / rtems_bsdnet_ticks_per_second;
230
231        /*
232         * Ensure that `seconds' is greater than 0
233         */
234        rtems_task_wake_after (rtems_bsdnet_ticks_per_second);
235
236        /*
237         * Set up BSD-style sockets
238         */
239        bsd_init ();
240
241        /*
242         * Start network daemon
243         */
244        networkDaemonTid = rtems_bsdnet_newproc ("ntwk", 4096, networkDaemon, NULL);
245
246        /*
247         * Let other network tasks begin
248         */
249        rtems_bsdnet_semaphore_release ();
250}
251
252rtems_id TaskWithSemaphore;
253/*
254 * Obtain network mutex
255 */
256void
257rtems_bsdnet_semaphore_obtain (void)
258{
259        rtems_status_code sc;
260
261        sc = rtems_semaphore_obtain (networkSemaphore, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
262rtems_task_ident (RTEMS_SELF, 0, &TaskWithSemaphore);
263        if (sc != RTEMS_SUCCESSFUL)
264                rtems_panic ("Can't obtain network semaphore: `%s'\n", rtems_status_text (sc));
265}
266
267/*
268 * Release network mutex
269 */
270void
271rtems_bsdnet_semaphore_release (void)
272{
273        rtems_status_code sc;
274
275TaskWithSemaphore = 0;
276        sc = rtems_semaphore_release (networkSemaphore);
277        if (sc != RTEMS_SUCCESSFUL)
278                rtems_panic ("Can't release network semaphore: `%s'\n", rtems_status_text (sc));
279                                                                                }
280
281/*
282 * Wait for something to happen to a socket buffer
283 */
284int
285sbwait(sb)
286        struct sockbuf *sb;
287{
288        rtems_event_set events;
289        rtems_id tid;
290        rtems_status_code sc;
291
292        /*
293         * Soak up any pending events.
294         * The sleep/wakeup synchronization in the FreeBSD
295         * kernel has no memory.
296         */
297        rtems_event_receive (SBWAIT_EVENT, RTEMS_EVENT_ANY | RTEMS_NO_WAIT, RTEMS_NO_TIMEOUT, &events);
298
299        /*
300         * Set this task as the target of the wakeup operation.
301         */
302        rtems_task_ident (RTEMS_SELF, 0, &tid);
303        sb->sb_sel.si_pid = tid;
304
305        /*
306         * Show that socket is waiting
307         */
308        sb->sb_flags |= SB_WAIT;
309
310        /*
311         * Release the network semaphore.
312         */
313        rtems_bsdnet_semaphore_release ();
314
315        /*
316         * Wait for the wakeup event.
317         */
318        sc = rtems_event_receive (SBWAIT_EVENT, RTEMS_EVENT_ANY | RTEMS_WAIT, sb->sb_timeo, &events);
319
320        /*
321         * Reobtain the network semaphore.
322         */
323        rtems_bsdnet_semaphore_obtain ();
324
325        /*
326         * Return the status of the wait.
327         */
328        switch (sc) {
329        case RTEMS_SUCCESSFUL:  return 0;
330        case RTEMS_TIMEOUT:     return EWOULDBLOCK;
331        default:                return ENXIO;
332        }
333}
334
335
336/*
337 * Wake up the task waiting on a socket buffer.
338 */
339void
340sowakeup(so, sb)
341        register struct socket *so;
342        register struct sockbuf *sb;
343{
344        if (sb->sb_flags & SB_WAIT) {
345                sb->sb_flags &= ~SB_WAIT;
346                rtems_event_send (sb->sb_sel.si_pid, SBWAIT_EVENT);
347        }
348}
349
350/*
351 * For now, a socket can be used by only one task at a time.
352 */
353int
354sb_lock(sb)
355        register struct sockbuf *sb;
356{
357        rtems_panic ("Socket buffer is already in use.");
358        return 0;
359}
360void
361wakeup (void *p)
362{
363        rtems_panic ("Wakeup called");
364}
365
366/*
367 * Wait for a connection/disconnection event.
368 */
369int
370soconnsleep (struct socket *so)
371{
372        rtems_event_set events;
373        rtems_id tid;
374        rtems_status_code sc;
375
376        /*
377         * Soak up any pending events.
378         * The sleep/wakeup synchronization in the FreeBSD
379         * kernel has no memory.
380         */
381        rtems_event_receive (SOSLEEP_EVENT, RTEMS_EVENT_ANY | RTEMS_NO_WAIT, RTEMS_NO_TIMEOUT, &events);
382
383        /*
384         * Set this task as the target of the wakeup operation.
385         */
386        if (so->so_pgid)
387                rtems_panic ("Another task is already sleeping on that socket");
388        rtems_task_ident (RTEMS_SELF, 0, &tid);
389        so->so_pgid = tid;
390
391        /*
392         * Wait for the wakeup event.
393         */
394        sc = rtems_bsdnet_event_receive (SOSLEEP_EVENT, RTEMS_EVENT_ANY | RTEMS_WAIT, so->so_rcv.sb_timeo, &events);
395
396        /*
397         * Relinquish ownership of the socket.
398         */
399        so->so_pgid = 0;
400
401        switch (sc) {
402        case RTEMS_SUCCESSFUL:  return 0;
403        case RTEMS_TIMEOUT:     return EWOULDBLOCK;
404        default:                return ENXIO;
405        }
406}
407
408/*
409 * Wake up a task waiting for a connection/disconnection to complete.
410 */
411void
412soconnwakeup (struct socket *so)
413{
414        if (so->so_pgid)
415                rtems_event_send (so->so_pgid, SOSLEEP_EVENT);
416}
417
418/*
419 * Send an event to the network daemon.
420 * This corresponds to sending a software interrupt in the BSD kernel.
421 */
422void
423rtems_bsdnet_schednetisr (int n)
424{
425        rtems_event_send (networkDaemonTid, 1 << n);
426}
427
428/*
429 * The network daemon
430 * This provides a context to run BSD software interrupts
431 */
432static void
433networkDaemon (void *task_argument)
434{
435        rtems_event_set events;
436        rtems_interval now;
437        int ticksPassed;
438        unsigned32 timeout;
439        struct callout *c;
440
441        for (;;) {
442                c = calltodo.c_next;
443                if (c)
444                        timeout = c->c_time;
445                else
446                        timeout = RTEMS_NO_TIMEOUT;
447                rtems_bsdnet_event_receive (NETISR_EVENTS,
448                                                RTEMS_EVENT_ANY | RTEMS_WAIT,
449                                                timeout,
450                                                &events);
451                if (events & NETISR_IP_EVENT)
452                        ipintr ();
453                if (events & NETISR_ARP_EVENT)
454                        arpintr ();
455                rtems_clock_get (RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &now);
456                ticksPassed = now - ticksWhenCalloutsLastChecked;
457                if (ticksPassed != 0) {
458                        ticksWhenCalloutsLastChecked = now;
459                       
460                        c = calltodo.c_next;
461                        if (c) {
462                                c->c_time -= ticksPassed;
463                                while ((c = calltodo.c_next) != NULL && c->c_time <= 0) {
464                                        void *arg;
465                                        void (*func) (void *);
466
467                                        func = c->c_func;
468                                        arg = c->c_arg;
469                                        calltodo.c_next = c->c_next;
470                                        c->c_next = callfree;
471                                        callfree = c;
472                                        (*func)(arg);
473                                }
474                        }
475                }
476        }
477}
478
479/*
480 * Structure passed to task-start stub
481 */
482struct newtask {
483        void (*entry)(void *);
484        void *arg;
485};
486
487/*
488 * Task-start stub
489 */
490static void
491taskEntry (rtems_task_argument arg)
492{
493        struct newtask t;
494       
495        /*
496         * Pick up task information and free
497         * the memory allocated to pass the
498         * information to this task.
499         */
500        t = *(struct newtask *)arg;
501        free ((struct newtask *)arg);
502
503        /*
504         * Enter the competition for the network semaphore
505         */
506        rtems_bsdnet_semaphore_obtain ();
507
508        /*
509         * Enter the task
510         */
511        (*t.entry)(t.arg);
512        rtems_panic ("Network task returned!\n");
513}
514
515/*
516 * Start a network task
517 */
518rtems_id
519rtems_bsdnet_newproc (char *name, int stacksize, void(*entry)(void *), void *arg)
520{
521        struct newtask *t;
522        char nm[4];
523        rtems_id tid;
524        rtems_status_code sc;
525
526        strncpy (nm, name, 4);
527        sc = rtems_task_create (rtems_build_name(nm[0], nm[1], nm[2], nm[3]),
528                networkDaemonPriority,
529                stacksize,
530                RTEMS_PREEMPT|RTEMS_NO_TIMESLICE|RTEMS_NO_ASR|RTEMS_INTERRUPT_LEVEL(0),
531                RTEMS_NO_FLOATING_POINT|RTEMS_LOCAL,
532                &tid);
533        if (sc != RTEMS_SUCCESSFUL)
534                rtems_panic ("Can't create network daemon `%s': `%s'\n", name, rtems_status_text (sc));
535
536        /*
537         * Set up task arguments
538         */
539        t = malloc (sizeof *t);
540        t->entry = entry;
541        t->arg = arg;
542
543        /*
544         * Start the task
545         */
546        sc = rtems_task_start (tid, taskEntry, (rtems_task_argument)t);
547        if (sc != RTEMS_SUCCESSFUL)
548                rtems_panic ("Can't start network daemon `%s': `%s'\n", name, rtems_status_text (sc));
549
550        /*
551         * Let our caller know the i.d. of the new task
552         */
553        return tid;
554}
555
556rtems_status_code rtems_bsdnet_event_receive (
557  rtems_event_set  event_in,
558  rtems_option     option_set,
559  rtems_interval   ticks,
560  rtems_event_set *event_out)
561{
562        rtems_status_code sc;
563
564        rtems_bsdnet_semaphore_release ();
565        sc = rtems_event_receive (event_in, option_set, ticks, event_out);
566        rtems_bsdnet_semaphore_obtain ();
567        return sc;
568}
569
570/*
571 * Return time since startup
572 */
573void
574microtime (struct timeval *t)
575{
576        rtems_interval now;
577
578        rtems_clock_get (RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &now);
579        t->tv_sec = now / rtems_bsdnet_ticks_per_second;
580        t->tv_usec = (now % rtems_bsdnet_ticks_per_second) * rtems_bsdnet_microseconds_per_tick;
581}
582
583unsigned long
584rtems_bsdnet_seconds_since_boot (void)
585{
586        rtems_interval now;
587
588        rtems_clock_get (RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &now);
589        return now / rtems_bsdnet_ticks_per_second;
590}
591
592/*
593 * Fake random number generator
594 */
595unsigned long
596rtems_bsdnet_random (void)
597{
598        rtems_interval now;
599
600        rtems_clock_get (RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &now);
601        return (now * 99991);
602}
603
604/*
605 * Callout list processing
606 */
607void
608timeout(void (*ftn)(void *), void *arg, int ticks)
609{
610        register struct callout *new, *p, *t;
611
612        if (ticks <= 0)
613                ticks = 1;
614
615        /* Fill in the next free callout structure. */
616        if (callfree == NULL) {
617                callfree = malloc (sizeof *callfree);
618                if (callfree == NULL)
619                        rtems_panic ("No memory for timeout table entry");
620                callfree->c_next = NULL;
621        }
622
623        new = callfree;
624        callfree = new->c_next;
625        new->c_arg = arg;
626        new->c_func = ftn;
627
628        /*
629         * The time for each event is stored as a difference from the time
630         * of the previous event on the queue.  Walk the queue, correcting
631         * the ticks argument for queue entries passed.  Correct the ticks
632         * value for the queue entry immediately after the insertion point
633         * as well.  Watch out for negative c_time values; these represent
634         * overdue events.
635         */
636        for (p = &calltodo;
637            (t = p->c_next) != NULL && ticks > t->c_time; p = t)
638                if (t->c_time > 0)
639                        ticks -= t->c_time;
640        new->c_time = ticks;
641        if (t != NULL)
642                t->c_time -= ticks;
643
644        /* Insert the new entry into the queue. */
645        p->c_next = new;
646        new->c_next = t;
647}
648
649/*
650 * Ticks till specified time
651 * XXX: This version worries only about seconds, but that's good
652 * enough for the way the network code uses this routine.
653 */
654int
655hzto(struct timeval *tv)
656{
657        long diff = tv->tv_sec - rtems_bsdnet_seconds_since_boot();
658
659        if (diff <= 0)
660                return 1;
661        return diff * rtems_bsdnet_ticks_per_second;
662}
663
664/*
665 * Kernel debugging
666 */
667int rtems_bsdnet_log_priority;
668void
669rtems_bsdnet_log (int priority, const char *fmt, ...)
670{
671        va_list args;
672       
673        if (priority & rtems_bsdnet_log_priority) {
674                va_start (args, fmt);
675                vprintf (fmt, args);
676                va_end (args);
677        }
678}
679
680/*
681 * IP header checksum routine for processors which don't have an inline version
682 */
683u_int
684in_cksum_hdr (const void *ip)
685{
686        rtems_unsigned32 sum;
687        const rtems_unsigned16 *sp;
688        int i;
689
690        sum = 0;
691        sp = (rtems_unsigned16 *)ip;
692        for (i = 0 ; i < 10 ; i++)
693                sum += *sp++;
694        while (sum > 0xFFFF)
695                sum = (sum & 0xffff) + (sum >> 16);
696        return ~sum & 0xFFFF;
697}
698
699/*
700 * Manipulate routing tables
701 */
702int rtems_bsdnet_rtrequest (
703    int req,
704    struct sockaddr *dst,
705    struct sockaddr *gateway,
706    struct sockaddr *netmask,
707    int flags,
708    struct rtentry **net_nrt)
709{
710        int error;
711
712        rtems_bsdnet_semaphore_obtain ();
713        error = rtrequest (req, dst, gateway, netmask, flags, net_nrt);
714        rtems_bsdnet_semaphore_release ();
715        if (error) {
716                errno = error;
717                return -1;
718        }
719        return 0;
720}
721
722static void
723rtems_bsdnet_setup (void)
724{
725        struct rtems_bsdnet_ifconfig *ifp;
726        int s;
727        struct ifreq ifreq;
728        struct sockaddr_in address;
729        struct sockaddr_in netmask;
730        struct sockaddr_in broadcast;
731        struct sockaddr_in gateway;
732        int i;
733
734        /*
735         * Set local parameters
736         */
737        if (rtems_bsdnet_config.hostname)
738                sethostname (rtems_bsdnet_config.hostname,
739                                        strlen (rtems_bsdnet_config.hostname));
740        if (rtems_bsdnet_config.domainname)
741                rtems_bsdnet_domain_name =
742                                        strdup (rtems_bsdnet_config.domainname);
743        if (rtems_bsdnet_config.log_host)
744                rtems_bsdnet_log_host_address.s_addr =
745                                inet_addr (rtems_bsdnet_config.log_host);
746        for (i = 0 ; i < sizeof rtems_bsdnet_config.name_server /
747                        sizeof rtems_bsdnet_config.name_server[0] ; i++) {
748                if (!rtems_bsdnet_config.name_server[i])
749                        break;
750                rtems_bsdnet_nameserver[rtems_bsdnet_nameserver_count++].s_addr
751                        = inet_addr (rtems_bsdnet_config.name_server[i]);
752        }
753
754        /*
755         * Configure interfaces
756         */
757        s = socket (AF_INET, SOCK_DGRAM, 0);
758        if (s < 0)
759                rtems_panic ("Can't create initial socket: %s", strerror (errno));
760        for (ifp = rtems_bsdnet_config.ifconfig ; ifp ; ifp = ifp->next) {
761                if (ifp->ip_address == NULL)
762                        continue;
763
764                /*
765                 * Get the interface flags
766                 */
767                strcpy (ifreq.ifr_name, ifp->name);
768                if (ioctl (s, SIOCGIFFLAGS, &ifreq) < 0)
769                        rtems_panic ("Can't get %s flags: %s", ifp->name, strerror (errno));
770
771                /*
772                 * Bring interface up
773                 */
774                ifreq.ifr_flags |= IFF_UP;
775                if (ioctl (s, SIOCSIFFLAGS, &ifreq) < 0)
776                        rtems_panic ("Can't bring %s up: %s", ifp->name, strerror (errno));
777
778                /*
779                 * Set interface netmask
780                 */
781                memset (&netmask, '\0', sizeof netmask);
782                netmask.sin_len = sizeof netmask;
783                netmask.sin_family = AF_INET;
784                netmask.sin_addr.s_addr = inet_addr (ifp->ip_netmask);
785                memcpy (&ifreq.ifr_addr, &netmask, sizeof netmask);
786                if (ioctl (s, SIOCSIFNETMASK, &ifreq) < 0)
787                        rtems_panic ("Can't set %s netmask: %s", ifp->name, strerror (errno));
788
789                /*
790                 * Set interface address
791                 */
792                memset (&address, '\0', sizeof address);
793                address.sin_len = sizeof address;
794                address.sin_family = AF_INET;
795                address.sin_addr.s_addr = inet_addr (ifp->ip_address);
796                memcpy (&ifreq.ifr_addr, &address, sizeof address);
797                if (ioctl (s, SIOCSIFADDR, &ifreq) < 0)
798                        rtems_panic ("Can't set %s address: %s", ifp->name, strerror (errno));
799
800                /*
801                 * Set interface broadcast address
802                 */
803                memset (&broadcast, '\0', sizeof broadcast);
804                broadcast.sin_len = sizeof broadcast;
805                broadcast.sin_family = AF_INET;
806                broadcast.sin_addr.s_addr = address.sin_addr.s_addr | ~netmask.sin_addr.s_addr;
807                memcpy (&ifreq.ifr_broadaddr, &broadcast, sizeof broadcast);
808                if (ioctl (s, SIOCSIFBRDADDR, &ifreq) < 0)
809                        rtems_panic ("Can't set %s broadcast address: %s", ifp->name, strerror (errno));
810        }
811
812        /*
813         * We're done with the dummy socket
814         */
815        close (s);
816
817        /*
818         * Set default route
819         */
820        if (rtems_bsdnet_config.gateway) {
821                address.sin_addr.s_addr = INADDR_ANY;
822                netmask.sin_addr.s_addr = INADDR_ANY;
823                memset (&gateway, '\0', sizeof gateway);
824                gateway.sin_len = sizeof gateway;
825                gateway.sin_family = AF_INET;
826                gateway.sin_addr.s_addr = inet_addr (rtems_bsdnet_config.gateway);
827                if (rtems_bsdnet_rtrequest (
828                                RTM_ADD,
829                                (struct sockaddr *)&address,
830                                (struct sockaddr *)&gateway,
831                                (struct sockaddr *)&netmask,
832                                (RTF_UP | RTF_GATEWAY | RTF_STATIC), NULL) < 0)
833                        rtems_panic ("Can't set default route: %s", strerror (errno));
834        }
835}
836
837/*
838 * Initialize the network
839 */
840int
841rtems_bsdnet_initialize_network (void)
842{
843        struct rtems_bsdnet_ifconfig *ifp;
844
845        /*
846         * Start network tasks.
847         * Initialize BSD network data structures.
848         */
849        rtems_bsdnet_initialize ();
850
851        /*
852         * Attach interfaces
853         */
854        for (ifp = rtems_bsdnet_config.ifconfig ; ifp ; ifp = ifp->next) {
855                rtems_bsdnet_semaphore_obtain ();
856                (ifp->attach)(ifp);
857                rtems_bsdnet_semaphore_release ();
858        }
859
860        /*
861         * Bring up the network
862         */
863        rtems_bsdnet_setup ();
864        if (rtems_bsdnet_config.bootp)
865                (*rtems_bsdnet_config.bootp)();
866        return 0;
867}
868
869/*
870 * Parse a network driver name into a name and a unit number
871 */
872int
873rtems_bsdnet_parse_driver_name (const struct rtems_bsdnet_ifconfig *config, char **namep)
874{
875        const char *cp = config->name;
876        char c;
877        int unitNumber = 0;
878
879        if (cp == NULL) {
880                printf ("No network driver name");
881                return -1;
882        }
883        while ((c = *cp++) != '\0') {
884                if ((c >= '0') && (c <= '9')) {
885                        int len = cp - config->name;
886                        if ((len < 2) || (len > 50))
887                                break;
888                        for (;;) {
889                                unitNumber = (unitNumber * 10) + (c - '0');
890                                c = *cp++;
891                                if (c == '\0') {
892                                        char *unitName = malloc (len);
893                                        if (unitName == NULL) {
894                                                printf ("No memory");
895                                                return -1;
896                                        }
897                                        strncpy (unitName, config->name, len - 1);
898                                        unitName[len-1] = '\0';
899                                        *namep = unitName;
900                                        return unitNumber;
901                                }
902                                if ((c < '0') || (c > '9'))
903                                        break;
904                        }
905                        break;
906                }
907        }
908        printf ("Bad network driver name `%s'", config->name);
909        return -1;
910}
911
912/*
913 * Handle requests for more network memory
914 * XXX: Another possibility would be to use a semaphore here with
915 *      a release in the mbuf free macro.  I have chosen this `polling'
916 *      approach because:
917 *      1) It is simpler.
918 *      2) It adds no complexity to the free macro.
919 *      3) Running out of mbufs should be a rare
920 *         condition -- predeployment testing of
921 *         an application should indicate the
922 *         required mbuf pool size.
923 * XXX: Should there be a panic if a task is stuck in the loop for
924 *      more than a minute or so?
925 */
926int
927m_mballoc (int nmb, int nowait)
928{
929        if (nowait)
930                return 0;
931        m_reclaim ();
932        if (mmbfree == NULL) {
933                int try = 0;
934                int print_limit = 30 * rtems_bsdnet_ticks_per_second;
935
936                mbstat.m_wait++;
937                for (;;) {
938                        rtems_bsdnet_semaphore_release ();
939                        rtems_task_wake_after (1);
940                        rtems_bsdnet_semaphore_obtain ();
941                        if (mmbfree)
942                                break;
943                        if (++try >= print_limit) {
944                                printf ("Still waiting for mbuf.\n");
945                                try = 0;
946                        }
947                }
948        }
949        else {
950                mbstat.m_drops++;
951        }
952        return 1;
953}
954
955int
956m_clalloc(ncl, nowait)
957{
958        if (nowait)
959                return 0;
960        m_reclaim ();
961        if (mclfree == NULL) {
962                int try = 0;
963                int print_limit = 30 * rtems_bsdnet_ticks_per_second;
964
965                mbstat.m_wait++;
966                for (;;) {
967                        rtems_bsdnet_semaphore_release ();
968                        rtems_task_wake_after (1);
969                        rtems_bsdnet_semaphore_obtain ();
970                        if (mclfree)
971                                break;
972                        if (++try >= print_limit) {
973                                printf ("Still waiting for mbuf cluster.\n");
974                                try = 0;
975                        }
976                }
977        }
978        else {
979                mbstat.m_drops++;
980        }
981        return 1;
982}
Note: See TracBrowser for help on using the repository browser.