1 //==========================================================================
5 //==========================================================================
6 //####BSDCOPYRIGHTBEGIN####
8 // -------------------------------------------
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.
14 // Portions created by Red Hat are
15 // Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.
17 // Copyright (C) 2002, 2003 Gary Thomas
18 // Copyright (C) 2003 Andrew Lunn
19 // -------------------------------------------
21 //####BSDCOPYRIGHTEND####
22 //==========================================================================
24 //==========================================================================
28 // eCos wrapper and support functions
30 //==========================================================================
31 //####BSDCOPYRIGHTBEGIN####
33 // -------------------------------------------
35 // Portions of this software may have been derived from OpenBSD or other sources,
36 // and are covered by the appropriate copyright disclaimers included herein.
38 // -------------------------------------------
40 //####BSDCOPYRIGHTEND####
41 //==========================================================================
42 //#####DESCRIPTIONBEGIN####
44 // Author(s): gthomas, hmt
45 // Contributors: gthomas, hmt, andrew.lunn@ascom.ch
51 //####DESCRIPTIONEND####
53 //==========================================================================
56 // Support routines, etc., used by network code
58 #include <sys/param.h>
59 #include <sys/malloc.h>
61 #include <sys/domain.h>
62 #include <sys/protosw.h>
63 #include <sys/sockio.h>
64 #include <sys/socket.h>
65 #include <sys/socketvar.h>
67 #include <net/netisr.h>
69 #include <cyg/infra/diag.h>
70 #include <cyg/hal/hal_intr.h>
71 #include <cyg/kernel/kapi.h>
72 #include <cyg/hal/hal_if.h>
73 #include <cyg/infra/cyg_ass.h>
75 #ifdef CYGPKG_NET_INET6
76 #include <netinet/in.h>
77 #include <netinet6/in6_var.h>
80 #if !CYGPKG_NET_DRIVER_FRAMEWORK // Interface
81 #error At least one network driver framework must be defined!
83 #include <cyg/io/eth/netdev.h>
85 // Define table boundaries
86 CYG_HAL_TABLE_BEGIN( __NETDEVTAB__, netdev );
87 CYG_HAL_TABLE_END( __NETDEVTAB_END__, netdev );
88 CYG_HAL_TABLE_BEGIN( __NET_INIT_TAB__, _Net_inits );
89 CYG_HAL_TABLE_END( __NET_INIT_TAB_END__, _Net_inits );
90 extern struct init_tab_entry __NET_INIT_TAB__[], __NET_INIT_TAB_END__;
92 // Used for system-wide "ticks per second"
95 int tick = 10000; // usec per "tick"
96 volatile struct timeval ktime;
97 int proc = 0; // unused
98 struct proc * proc0 = 0; // unused
100 volatile struct timeval mono_time;
102 // Low-level network debugging & logging
103 #ifdef CYGPKG_NET_FREEBSD_LOGGING
104 int cyg_net_log_mask = CYGPKG_NET_FREEBSD_LOGGING;
107 #ifdef CYGPKG_NET_INET6
108 #define STACK_SIZE (CYGNUM_HAL_STACK_SIZE_TYPICAL+2048)
110 #define STACK_SIZE CYGNUM_HAL_STACK_SIZE_TYPICAL
112 static char netint_stack[STACK_SIZE];
113 static cyg_thread netint_thread_data;
114 static cyg_handle_t netint_thread_handle;
116 cyg_flag_t netint_flags;
117 #define NETISR_ANY 0xFFFFFFFF // Any possible bit...
119 extern void cyg_test_exit(void); // TEMP
121 cyg_panic(const char *msg, ...)
125 HAL_DISABLE_INTERRUPTS(old_ints);
126 diag_printf("PANIC: %s\n", msg);
127 cyg_test_exit(); // FIXME
130 #define NET_MEMPOOL_SIZE roundup(CYGPKG_NET_MEMPOOL_SIZE,MSIZE)
131 #define NET_MBUFS_SIZE roundup(CYGPKG_NET_MBUFS_SIZE,MSIZE)
132 #define NET_CLUSTERS_SIZE roundup(CYGPKG_NET_CLUSTERS_SIZE,MCLBYTES)
134 static unsigned char net_mempool_area[NET_MEMPOOL_SIZE];
135 static cyg_mempool_var net_mem_pool;
136 static cyg_handle_t net_mem;
137 static unsigned char net_mbufs_area[NET_MBUFS_SIZE];
138 static cyg_mempool_fix net_mbufs_pool;
139 static cyg_handle_t net_mbufs;
140 static unsigned char net_clusters_area[NET_CLUSTERS_SIZE];
141 static cyg_mempool_fix net_clusters_pool;
142 static cyg_handle_t net_clusters;
143 static char net_clusters_refcnt[(NET_CLUSTERS_SIZE/MCLBYTES)+1];
144 int nmbclusters = (NET_CLUSTERS_SIZE/MCLBYTES);
146 #ifdef CYGDBG_NET_TIMING_STATS
147 static struct net_stats stats_malloc, stats_free,
148 stats_memcpy, stats_memset,
149 stats_mbuf_alloc, stats_mbuf_free, stats_cluster_alloc;
151 // Display a number of ticks as microseconds
152 // Note: for improved calculation significance, values are kept in ticks*1000
153 static long rtc_resolution[] = CYGNUM_KERNEL_COUNTERS_RTC_RESOLUTION;
154 static long ns_per_system_clock;
157 show_ticks_in_us(cyg_uint32 ticks)
160 ns_per_system_clock = 1000000/rtc_resolution[1];
161 ns = (ns_per_system_clock * ((long long)ticks * 1000)) /
162 CYGNUM_KERNEL_COUNTERS_RTC_PERIOD;
163 ns += 5; // for rounding to .01us
164 diag_printf("%7d.%02d", (int)(ns/1000), (int)((ns%1000)/10));
168 show_net_stats(struct net_stats *stats, const char *title)
171 ave = stats->total_time / stats->count;
172 diag_printf("%s:\n", title);
173 diag_printf(" count: %6d", stats->count);
174 diag_printf(", min: ");
175 show_ticks_in_us(stats->min_time);
176 diag_printf(", max: ");
177 show_ticks_in_us(stats->max_time);
178 diag_printf(", total: ");
179 show_ticks_in_us(stats->total_time);
180 diag_printf(", ave: ");
181 show_ticks_in_us(ave);
184 memset(stats, 0, sizeof(*stats));
190 show_net_stats(&stats_malloc, "Net malloc");
191 show_net_stats(&stats_free, "Net free");
192 show_net_stats(&stats_mbuf_alloc, "Mbuf alloc");
193 show_net_stats(&stats_mbuf_free, "Mbuf free");
194 show_net_stats(&stats_cluster_alloc, "Cluster alloc");
195 show_net_stats(&stats_memcpy, "Net memcpy");
196 show_net_stats(&stats_memset, "Net memset");
198 #endif /* CYGDBG_NET_TIMING_STATS */
201 cyg_net_malloc(u_long size, int type, int flags)
206 log(LOG_MDEBUG, "Net malloc[%ld] = ", size);
207 if (flags & M_NOWAIT) {
208 res = cyg_mempool_var_try_alloc(net_mem, size);
210 res = cyg_mempool_var_alloc(net_mem, size);
212 if ((flags & M_ZERO) && res) {
215 FINISH_STATS(stats_malloc);
216 log(LOG_MDEBUG, "%p\n", res);
221 cyg_net_free(caddr_t addr, int type)
224 cyg_mempool_var_free(net_mem, addr);
225 FINISH_STATS(stats_free);
228 #ifdef CYGDBG_NET_SHOW_MBUFS
230 struct mbuf *mbinfo[300];
232 void cyg_net_show_mbufs(void)
235 diag_printf(" MBUF : TYPE FLGS DATA[LEN] NEXT NEXTPKT\n");
236 for( i = 0; i < 300; i++ )
238 struct mbuf *m = mbinfo[i];
240 if( m == 0 ) continue;
242 switch( m->m_hdr.mh_type )
244 case MT_FREE: type="FREE"; break;
245 case MT_DATA: type="DATA"; break;
246 case MT_HEADER: type="HEADER"; break;
247 case MT_SONAME: type="SONAME"; break;
248 case MT_FTABLE: type="FTABLE"; break;
249 case MT_CONTROL: type="CONTROL"; break;
250 case MT_OOBDATA: type="OOBDATA"; break;
251 default: type="UNKNOWN"; break;
254 diag_printf("%08x: %s %04x %08x[%03d] %08x %08x\n",
260 m->m_hdr.mh_nextpkt);
262 diag_printf(" MBUF : TYPE FLGS DATA[LEN] NEXT NEXTPKT\n");
268 cyg_net_mbuf_alloc(void)
273 log(LOG_MDEBUG, "Alloc mbuf = ");
274 res = cyg_mempool_fix_try_alloc(net_mbufs);
275 FINISH_STATS(stats_mbuf_alloc);
276 #ifdef CYGDBG_NET_SHOW_MBUFS
279 for( i = 0; i < (sizeof(mbinfo)/sizeof(mbinfo[0])); i++ )
282 mbinfo[i] = (struct mbuf *)res;
287 // Check that this nastiness works OK
288 CYG_ASSERT( dtom(res) == res, "dtom failed, base of mbuf" );
289 CYG_ASSERT( dtom((char *)res + MSIZE/2) == res, "dtom failed, mid mbuf" );
290 log(LOG_MDEBUG, "%p\n", res);
295 cyg_net_cluster_alloc(void)
300 log(LOG_MDEBUG, "Allocate cluster = ");
301 res = cyg_mempool_fix_try_alloc(net_clusters);
302 FINISH_STATS(stats_cluster_alloc);
303 log(LOG_MDEBUG, "%p\n", res);
307 static struct vm_zone *vm_zones = (struct vm_zone *)NULL;
310 zinit(char *name, int size, int nentries, int flags, int zalloc)
313 vm_zone_t zone = (vm_zone_t)0;
316 log(LOG_MDEBUG, "zinit '%s', size: %d, num: %d, flags: %d, alloc: %d\n",
317 name, size, nentries, flags, zalloc);
318 res = cyg_mempool_var_try_alloc(net_mem, sizeof(struct vm_zone));
320 zone = (vm_zone_t)res;
321 res = cyg_mempool_var_try_alloc(net_mem, size*nentries);
324 log(LOG_MDEBUG, "Can't allocate memory for %s\n", name);
325 panic("zinit: Out of memory\n");
328 zone->pool = (elem *)0;
329 zone->elem_size = size;
331 zone->free = zone->total = nentries;
332 zone->next = vm_zones;
333 zone->alloc_tries = zone->alloc_fails = zone->alloc_frees = 0;
335 while (nentries-- > 0) {
336 p->next = zone->pool;
338 p = (elem *)((char *)p + size);
343 log(LOG_MDEBUG, "p: %p, next: %p\n", p, p->next);
351 zalloci(vm_zone_t zone)
358 zone->pool = p->next;
363 log(LOG_MDEBUG, "zalloci from %s => %p\n", zone->name, p);
368 zfreei(vm_zone_t zone, void *item)
370 elem *p = (elem *)item;
372 log(LOG_MDEBUG, "zfreei to %s <= %p\n", zone->name, p);
373 p->next = zone->pool;
383 #ifdef CYGPKG_NET_DEBUG
384 diag_printf("Network stack using %d bytes for misc space\n", NET_MEMPOOL_SIZE);
385 diag_printf(" %d bytes for mbufs\n", NET_MBUFS_SIZE);
386 diag_printf(" %d bytes for mbuf clusters\n", NET_CLUSTERS_SIZE);
388 cyg_mempool_var_create(&net_mempool_area,
392 // Align the mbufs on MSIZE boudaries so that dtom() can work.
393 p = (unsigned char *)(((long)(&net_mbufs_area) + MSIZE - 1) & ~(MSIZE-1));
394 cyg_mempool_fix_create(p,
395 ((&(net_mbufs_area[NET_MBUFS_SIZE])) - p) & ~(MSIZE-1),
399 cyg_mempool_fix_create(&net_clusters_area,
404 mbutl = (struct mbuf *)&net_clusters_area;
405 mclrefcnt = net_clusters_refcnt;
408 void cyg_kmem_print_stats( void )
410 cyg_mempool_info info;
411 struct vm_zone *zone;
413 diag_printf( "Network stack mbuf stats:\n" );
414 diag_printf( " mbufs %ld, clusters %ld, free clusters %ld\n",
415 mbstat.m_mbufs, /* mbufs obtained from page pool */
416 mbstat.m_clusters, /* clusters obtained from page pool */
417 /* mbstat.m_spare, */ /* spare field */
418 mbstat.m_clfree /* free clusters */
420 diag_printf( " Failed to get %ld times\n"
421 " Waited to get %ld times\n"
422 " Drained queues to get %ld times\n",
423 mbstat.m_drops, /* times failed to find space */
424 mbstat.m_wait, /* times waited for space */
425 mbstat.m_drain /* times drained protocols for space */
426 /* mbstat.m_mtypes[256]; type specific mbuf allocations */
431 diag_printf("VM zone '%s':\n", zone->name);
432 diag_printf(" Total: %d, Free: %d, Allocs: %d, Frees: %d, Fails: %d\n",
433 zone->total, zone->free,
434 zone->alloc_tries, zone->alloc_frees, zone->alloc_fails);
438 cyg_mempool_var_get_info( net_mem, &info );
439 diag_printf( "Misc mpool: total %7d, free %7d, max free block %d\n",
445 cyg_mempool_fix_get_info( net_mbufs, &info );
446 diag_printf( "Mbufs pool: total %7d, free %7d, blocksize %4d\n",
453 cyg_mempool_fix_get_info( net_clusters, &info );
454 diag_printf( "Clust pool: total %7d, free %7d, blocksize %4d\n",
461 // This API is for our own automated network tests. It's not in any header
462 // files because it's not at all supported.
463 int cyg_net_get_mem_stats( int which, cyg_mempool_info *p )
465 CYG_CHECK_DATA_PTR( p, "Bad pointer to mempool_info" );
466 CYG_ASSERT( 0 <= which, "Mempool selector underflow" );
467 CYG_ASSERT( 2 >=which, "Mempool selector overflow" );
472 cyg_mempool_var_get_info( net_mem, p );
475 cyg_mempool_fix_get_info( net_mbufs, p );
478 cyg_mempool_fix_get_info( net_clusters, p );
490 res = (((u_long)(x) - (u_long)mbutl) >> MCLSHIFT);
498 res = (struct mbuf *)((caddr_t)((u_long)mbutl + ((u_long)(x) << MCLSHIFT)));
503 net_memcpy(void *d, void *s, int n)
507 FINISH_STATS(stats_memcpy);
511 net_memset(void *s, int v, int n)
515 FINISH_STATS(stats_memset);
518 // Rather than bring in the whole BSD 'random' code...
523 static unsigned long seed = 0xDEADB00B;
524 HAL_CLOCK_READ(&res); // Not so bad... (but often 0..N where N is small)
525 seed = ((seed & 0x007F00FF) << 7) ^
526 ((seed & 0x0F80FF00) >> 8) ^ // be sure to stir those low bits
527 (res << 13) ^ (res >> 9); // using the clock too!
532 get_random_bytes(void *buf, size_t len)
534 unsigned long ranbuf, *lp;
535 lp = (unsigned long *)buf;
537 ranbuf = arc4random();
539 len -= sizeof(ranbuf);
544 read_random_unlimited(void *buf, size_t len)
546 get_random_bytes(buf, len);
550 void read_random(void *buf, size_t len)
552 CYG_ASSERT(0 == (len & ~3), "Only multiple of words allowed");
554 get_random_bytes(buf, len);
558 microtime(struct timeval *tp)
561 log(LOG_DEBUG, "%s: = %ld.%ld\n", __FUNCTION__, tp->tv_sec, tp->tv_usec);
562 ktime.tv_usec++; // In case clock isn't running yet
566 getmicrotime(struct timeval *tp)
569 log(LOG_DEBUG, "%s: = %ld.%ld\n", __FUNCTION__, tp->tv_sec, tp->tv_usec);
570 ktime.tv_usec++; // In case clock isn't running yet
574 getmicrouptime(struct timeval *tp)
577 log(LOG_DEBUG, "%s: = %ld.%ld\n", __FUNCTION__, tp->tv_sec, tp->tv_usec);
578 ktime.tv_usec++; // In case clock isn't running yet
581 // Taken from kern/kern_clock.c
583 * Compute number of ticks in the specified amount of time.
586 #define LONG_MAX 0x7FFFFFFF
589 tvtohz(struct timeval *tv)
591 register unsigned long ticks;
592 register long sec, usec;
595 * If the number of usecs in the whole seconds part of the time
596 * difference fits in a long, then the total number of usecs will
597 * fit in an unsigned long. Compute the total and convert it to
598 * ticks, rounding up and adding 1 to allow for the current tick
599 * to expire. Rounding also depends on unsigned long arithmetic
602 * Otherwise, if the number of ticks in the whole seconds part of
603 * the time difference fits in a long, then convert the parts to
604 * ticks separately and add, using similar rounding methods and
605 * overflow avoidance. This method would work in the previous
606 * case but it is slightly slower and assumes that hz is integral.
608 * Otherwise, round the time difference down to the maximum
609 * representable value.
611 * If ints have 32 bits, then the maximum value for any timeout in
612 * 10ms ticks is 248 days.
626 printf("tvotohz: negative time difference %ld sec %ld usec\n",
630 } else if (sec <= LONG_MAX / 1000000)
631 ticks = (sec * 1000000 + (unsigned long)usec + (tick - 1))
633 else if (sec <= LONG_MAX / hz)
635 + ((unsigned long)usec + (tick - 1)) / tick + 1;
646 panic("get_mono_time");
650 csignal(pid_t pgid, int signum, uid_t uid, uid_t euid)
656 bcmp(const void *_p1, const void *_p2, size_t len)
659 unsigned char *p1 = (unsigned char *)_p1;
660 unsigned char *p2 = (unsigned char *)_p2;
669 copyout(const void *s, void *d, size_t len)
676 copyin(const void *s, void *d, size_t len)
683 ovbcopy(const void *s, void *d, size_t len)
689 // ------------------------------------------------------------------------
690 // THE NETWORK THREAD ITSELF
692 // Network software interrupt handler
693 // This function is run as a separate thread to allow
694 // processing of network events (mostly incoming packets)
695 // at "user level" instead of at interrupt time.
697 // The actual handlers are 'registered' at system startup
700 // The set of handlers
701 static netisr_t *_netisr_handlers[NETISR_MAX+1];
702 struct ifqueue ipintrq;
704 struct ifqueue ip6intrq;
706 char *hostname = "eCos_node";
708 // Register a 'netisr' handler for a given level
710 register_netisr(int level, netisr_t *fun)
712 CYG_ASSERT(level <= NETISR_MAX, "invalid netisr level");
713 CYG_ASSERT(_netisr_handlers[level] == 0, "re-registered netisr");
714 _netisr_handlers[level] = fun;
718 //int unregister_netisr __P((int));
721 cyg_netint(cyg_addrword_t param)
723 cyg_flag_value_t curisr;
727 curisr = cyg_flag_wait(&netint_flags, NETISR_ANY,
728 CYG_FLAG_WAITMODE_OR|CYG_FLAG_WAITMODE_CLR);
729 spl = splsoftnet(); // Prevent any overlapping "stack" processing
730 for (lvl = NETISR_MIN; lvl <= NETISR_MAX; lvl++) {
731 if (curisr & (1<<lvl)) {
732 CYG_ASSERT(_netisr_handlers[lvl] != 0, "unregistered netisr handler");
733 (*_netisr_handlers[lvl])();
741 // This just sets one of the pseudo-ISR bits used above.
745 // This is called if we are out of MBUFs - it doesn't do anything, and
746 // that situation is handled OK, so don't bother with the diagnostic:
748 // diag_printf("setsoftnet\n");
750 // No need to do this because it is ignored anyway:
751 // schednetisr(NETISR_SOFTNET);
755 /* Update the kernel globel ktime. */
757 cyg_ktime_func(cyg_handle_t alarm,cyg_addrword_t data)
759 cyg_tick_count_t now = cyg_current_time();
761 ktime.tv_usec = (now % hz) * tick;
762 ktime.tv_sec = 1 + now / hz;
768 cyg_handle_t ktime_alarm_handle;
769 static cyg_alarm ktime_alarm;
770 cyg_handle_t counter;
772 // Do not start at 0 - net stack thinks 0 an invalid time;
773 // Have a valid time available from right now:
777 cyg_clock_to_counter(cyg_real_time_clock(),&counter);
778 cyg_alarm_create(counter,
784 /* We want one alarm every 10ms. */
785 cyg_alarm_initialize(ktime_alarm_handle,cyg_current_time()+1,1);
786 cyg_alarm_enable(ktime_alarm_handle);
792 cyg_tick_count_t now = cyg_current_time();
797 // Network initialization
798 // This function is called during system initialization to setup the whole
799 // networking environment.
801 // Linker magic to execute this function as 'init'
802 extern void cyg_do_net_init(void);
804 extern void ifinit(void);
805 extern void loopattach(int);
806 extern void bridgeattach(int);
808 // Internal init functions:
809 extern void cyg_alarm_timeout_init(void);
810 extern void cyg_tsleep_init(void);
813 cyg_net_init_devs(void *ignored)
815 cyg_netdevtab_entry_t *t;
816 // Initialize all network devices
817 for (t = &__NETDEVTAB__[0]; t != &__NETDEVTAB_END__; t++) {
818 log(LOG_INIT, "Init device '%s'\n", t->name);
820 t->status = CYG_NETDEVTAB_STATUS_AVAIL;
822 // What to do if device init fails?
823 t->status = 0; // Device not [currently] available
826 #if 0 // Bridge code not available yet
832 SYSINIT(devs, SI_SUB_DEVICES, SI_ORDER_FIRST, cyg_net_init_devs, NULL)
837 static int _init = false;
838 struct init_tab_entry *init_entry;
839 #ifdef CYGPKG_NET_FORCE_SERIAL_CONSOLE
841 CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT);
846 #ifdef CYGPKG_NET_FORCE_SERIAL_CONSOLE
847 // Force default serial console during system initialization
848 // This avoids problems with debug messages occurring while the
849 // networking subsystem is being setup.
850 CYGACC_CALL_IF_SET_CONSOLE_COMM(0);
853 cyg_do_net_init(); // Just forces linking in the initializer/constructor
854 // Initialize interrupt "flags"
855 cyg_flag_init(&netint_flags);
856 // Initialize timeouts and net service thread (pseudo-DSRs)
857 cyg_alarm_timeout_init();
858 // Initialize tsleep/wakeup support
860 // Initialize network memory system
862 // Initialize network time
864 // Create network background thread
865 cyg_thread_create(CYGPKG_NET_THREAD_PRIORITY, // Priority
867 0, // entry parameter
868 "Network support", // Name
869 &netint_stack[0], // Stack
871 &netint_thread_handle, // Handle
872 &netint_thread_data // Thread data structure
874 cyg_thread_resume(netint_thread_handle); // Start it
876 // Run through dynamic initializers
877 for (init_entry = __NET_INIT_TAB__; init_entry != &__NET_INIT_TAB_END__; init_entry++) {
878 log(LOG_INIT, "[%s] Init: %s(%p)\n", __FUNCTION__, init_entry->name, init_entry->data);
879 (*init_entry->fun)(init_entry->data);
881 log(LOG_INIT, "[%s] Done\n", __FUNCTION__);
886 #ifdef CYGPKG_NET_FORCE_SERIAL_CONSOLE
887 // Revert to the original console, which might be a network connection
888 CYGACC_CALL_IF_SET_CONSOLE_COMM(orig_console);
894 #include <net/netdb.h>
895 #include <net/route.h>
896 externC void if_indextoname(int indx, char *buf, int len);
898 typedef void pr_fun(char *fmt, ...);
901 _mask(struct sockaddr *sa, char *buf, int _len)
903 unsigned char *cp = ((unsigned char *)sa) + 4;
904 int len = sa->sa_len - 4;
908 if (tot) *buf++ = '.';
909 buf += diag_sprintf(buf, "%u", *cp++);
914 if (tot) *buf++ = '.';
915 buf += diag_sprintf(buf, "%d", 0);
920 #ifdef CYGPKG_NET_INET6
922 _mask6(struct sockaddr *sa, char *buf, int _len)
924 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) sa;
929 while (addrword < 4) {
930 if (sin6->sin6_addr.s6_addr32[addrword] == 0) {
933 HAL_LSBIT_INDEX(index, sin6->sin6_addr.s6_addr32[addrword++]);
939 diag_sprintf(buf, "%d", bits);
943 _show_ifp(struct ifnet *ifp, pr_fun *pr)
946 char name[64], addr[64], netmask[64], broadcast[64];
948 if_indextoname(ifp->if_index, name, 64);
949 TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
950 if (ifa->ifa_addr->sa_family != AF_LINK) {
952 getnameinfo (ifa->ifa_addr, ifa->ifa_addr->sa_len, addr,
953 sizeof(addr), 0, 0, NI_NUMERICHOST);
954 if (ifa->ifa_addr->sa_family == AF_INET) {
955 getnameinfo (ifa->ifa_dstaddr, ifa->ifa_dstaddr->sa_len,
956 broadcast, sizeof(broadcast),
957 0, 0, NI_NUMERICHOST);
958 _mask(ifa->ifa_netmask, netmask, 64);
959 (*pr)("IP: %s, Broadcast: %s, Netmask: %s\n",
960 addr, broadcast, netmask);
962 #ifdef CYGPKG_NET_INET6
963 if (ifa->ifa_addr->sa_family == AF_INET6) {
964 struct in6_ifaddr * ifa6 = (struct in6_ifaddr *) ifa;
965 _mask6(ifa->ifa_netmask, netmask, 64);
966 (*pr)("IP: %s/%s ", addr,netmask);
967 if (ifa6->ia6_flags & IN6_IFF_ANYCAST) (*pr) ("Anycast ");
968 if (ifa6->ia6_flags & IN6_IFF_TENTATIVE) (*pr) ("Tentative ");
969 if (ifa6->ia6_flags & IN6_IFF_DUPLICATED) (*pr) ("Duplicate ");
970 if (ifa6->ia6_flags & IN6_IFF_DETACHED) (*pr) ("Detached ");
971 if (ifa6->ia6_flags & IN6_IFF_DEPRECATED) (*pr) ("Deprecated ");
972 if (ifa6->ia6_flags & IN6_IFF_NODAD) (*pr) ("NoDAD ");
973 if (ifa6->ia6_flags & IN6_IFF_AUTOCONF) (*pr) ("AutoConf ");
974 if (ifa6->ia6_flags & IN6_IFF_TEMPORARY) (*pr) ("Tempory ");
975 if (ifa6->ia6_flags & IN6_IFF_HOME) (*pr) ("Home ");
980 if ((ifp->if_flags & IFF_UP)) (*pr)("UP ");
981 if ((ifp->if_flags & IFF_BROADCAST)) (*pr)("BROADCAST ");
982 if ((ifp->if_flags & IFF_LOOPBACK)) (*pr)("LOOPBACK ");
983 if ((ifp->if_flags & IFF_RUNNING)) (*pr)("RUNNING ");
984 if ((ifp->if_flags & IFF_PROMISC)) (*pr)("PROMISC ");
985 if ((ifp->if_flags & IFF_MULTICAST)) (*pr)("MULTICAST ");
986 if ((ifp->if_flags & IFF_ALLMULTI)) (*pr)("ALLMULTI ");
987 (*pr)("MTU: %d, Metric: %d\n", ifp->if_mtu, ifp->if_metric);
988 (*pr)(" Rx - Packets: %d, Bytes: %d",
989 ifa->if_data.ifi_ipackets, ifa->if_data.ifi_ibytes);
990 (*pr)(", Tx - Packets: %d, Bytes: %d\n",
991 ifa->if_data.ifi_opackets, ifa->if_data.ifi_obytes);
997 _dumpentry(struct radix_node *rn, void *vw)
999 struct rtentry *rt = (struct rtentry *)rn;
1000 struct sockaddr *dst, *gate, *netmask, *genmask;
1002 pr_fun *pr = (pr_fun *)vw;
1005 gate = rt->rt_gateway;
1006 netmask = rt_mask(rt);
1007 genmask = rt->rt_genmask;
1008 if ((rt->rt_flags & (RTF_UP | RTF_WASCLONED)) == RTF_UP) {
1009 _inet_ntop(dst, addr, sizeof(addr));
1010 (*pr)("%-15s ", addr);
1012 _inet_ntop(gate, addr, sizeof(addr));
1013 (*pr)("%-15s ", addr);
1015 (*pr)("%-15s ", " ");
1017 if (netmask != NULL) {
1018 if (dst->sa_family == AF_INET) {
1019 _mask(netmask, addr, sizeof(addr));
1020 (*pr)("%-15s ", addr);
1022 #ifdef CYGPKG_NET_INET6
1023 if (dst->sa_family == AF_INET6) {
1024 _mask6(netmask, addr, sizeof(addr));
1025 (*pr)("/%-14s ", addr);
1029 (*pr)("%-15s ", " ");
1032 if ((rt->rt_flags & RTF_UP)) *cp++ = 'U';
1033 if ((rt->rt_flags & RTF_GATEWAY)) *cp++ = 'G';
1034 if ((rt->rt_flags & RTF_HOST)) *cp++ = 'H';
1035 if ((rt->rt_flags & RTF_REJECT)) *cp++ = '!';
1036 if ((rt->rt_flags & RTF_STATIC)) *cp++ = 'S';
1037 if ((rt->rt_flags & RTF_DYNAMIC)) *cp++ = 'D';
1038 if ((rt->rt_flags & RTF_MODIFIED)) *cp++ = 'M';
1040 (*pr)("%-8s ", addr); // Flags
1041 if_indextoname(rt->rt_ifp->if_index, addr, 64);
1042 (*pr)("%-8s ", addr);
1049 show_network_tables(pr_fun *pr)
1052 struct radix_node_head *rnh;
1055 cyg_scheduler_lock();
1056 (*pr)("Routing tables\n");
1057 (*pr)("Destination Gateway Mask Flags Interface\n");
1058 for (i = 1; i <= AF_MAX; i++) {
1059 if ((rnh = rt_tables[i]) != NULL) {
1060 error = rnh->rnh_walktree(rnh, _dumpentry, pr);
1064 (*pr)("Interface statistics\n");
1065 for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_link.tqe_next) {
1068 cyg_scheduler_unlock();
1071 #endif // CYGPKG_NET_DRIVER_FRAMEWORK