source: rtems/cpukit/libnetworking/rtems/rtems_glue.c @ 4a9b897

4.104.114.84.95
Last change on this file since 4a9b897 was 4a9b897, checked in by Joel Sherrill <joel.sherrill@…>, on 01/21/00 at 15:11:40

Patch from Eric Norum <eric@…> at the request of Jake
Janovetz <janovetz@…> to return a status from
network initialization rather than panic'ing. It changes a bunch
of rtems_panics to printfs and returns a status from
rtems_bsdnet_initialize_network().

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