/* ****************************************************************************** * SOURCE FILE * * Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipnet_cmd_ctrl.c,v $ $Revision: 1.85.10.8 $ * $Source: /home/interpeak/CVSRoot/ipnet2/src/ipnet_cmd_ctrl.c,v $ * $Author: svc-cmnet $ * $State: Exp $ $Locker: $ * * INTERPEAK_COPYRIGHT_STRING * Design and implementation by Kenneth Jonsson ****************************************************************************** */ /* **************************************************************************** * 1 DESCRIPTION **************************************************************************** * Prints information about internal structures in IPNET. */ /* **************************************************************************** * 2 CONFIGURATION **************************************************************************** */ #ifdef IPCOM_KERNEL #undef IPCOM_KERNEL #endif #include "ipnet_config.h" /* **************************************************************************** * 3 INCLUDE FILES **************************************************************************** */ #define IPCOM_USE_CLIB_PROTO #include #include #include #include "ipnet.h" #include "ipnet_cmd.h" #include "ipnet_h.h" #include "ipnet_peer_info.h" #include "ipnet_timeout.h" #ifdef IPTCP #include #endif #ifdef IPNET_DEBUG /* **************************************************************************** * 4 DEFINES **************************************************************************** */ #define IPNET_CTRL_PRINT_BUF_SIZE 1024*1024 /* **************************************************************************** * 5 TYPES **************************************************************************** */ /* **************************************************************************** * 6 EXTERN PROTOTYPES **************************************************************************** */ /* **************************************************************************** * 7 LOCAL PROTOTYPES **************************************************************************** */ /* **************************************************************************** * 8 DATA **************************************************************************** */ #define IPCOM_PKT_ID_UNINITIALIZED 0xffff #ifdef IPNET_USE_PACKET_POOL IP_STATIC Ipcom_cmd_int_str_map ipnet_ctrl_id_map[] = { { IPCOM_PKT_ID_INIT, "Init" }, { IPCOM_PKT_ID_UNINITIALIZED, "Uninitialized" }, { IPCOM_PKT_ID_MALLOC, "Just allocated" }, { IPCOM_PKT_ID_RX, "Driver input irq" }, { IPCOM_PKT_ID_TX, "Driver output" }, { IPCOM_PKT_ID_FREEQ, "Free queue" }, { IPCOM_PKT_ID_DELREF, "Delete ref" }, { IPCOM_PKT_ID_ADDREF, "Add ref" }, { IPCOM_PKT_ID_INPUT, "Pkt input" }, { IPCOM_PKT_ID_INQ, "Input queue" }, { IPCOM_PKT_ID_OUTQ, "Output queue" }, { IPCOM_PKT_ID_NETIF_OUTQ, "Netif output queue" }, { IPCOM_PKT_ID_SOCKRECVQ, "Recv. queue" }, { IPCOM_PKT_ID_TCP, "TCP" }, { IPCOM_PKT_ID_TCP_INPUT, "TCP input" }, { IPCOM_PKT_ID_TCP_OUTPUT, "TCP output" }, { IPCOM_PKT_ID_TCP_SOCKOOORECVQ, "TCP out-of-order" }, { IPCOM_PKT_ID_TCP_RETRANSQ, "TCP retrans. queue" }, { IPCOM_PKT_ID_IP4_INPUT, "IPv4 input" }, { IPCOM_PKT_ID_IP4_OUTPUT, "IPv4 output" }, { IPCOM_PKT_ID_IP4_REASSEMBLY, "IPv4 reassembly" }, { IPCOM_PKT_ID_IP6_INPUT, "IPv6 input" }, { IPCOM_PKT_ID_IP6_OUTPUT, "IPv6 output" }, { IPCOM_PKT_ID_IP6_REASSEMBLY, "IPv6 reassembly" }, { IPCOM_PKT_ID_REMOVE, "Removed from queue" }, { IPCOM_PKT_ID_IPSEC_INPUT, "input ipsec" }, { IPCOM_PKT_ID_IPSEC_OUTPUT, "output ipsec(new)" }, { IPCOM_PKT_ID_IPSEC_OUTPUT_ORG, "output ipsec(org)" }, { IPCOM_PKT_ID_IPSEC_PF_KEY_IN, "PF_KEY input" }, { IPCOM_PKT_ID_PPP, "PPP" }, { IPCOM_PKT_ID_PPP_ORGOUT, "PPP orgout" }, { IPCOM_PKT_ID_PPP_INPUT, "PPP input" }, { IPCOM_PKT_ID_PPP_OUTPUT, "PPP output" }, { IPCOM_PKT_ID_RTSOCK, "Route sock" }, { IPCOM_PKT_ID_UDP_INPUT, "UDP input" }, { IPCOM_PKT_ID_NETIF_DEQUEUE, "Dequeued from netif" }, { IPCOM_PKT_ID_SOCKSENDQ, "Send queue" }, { IPCOM_PKT_ID_SENT_PIPE, "Send to pipe" }, { IPCOM_PKT_ID_RECV_PIPE, "Received from pipe" }, { IPCOM_PKT_ID_FRAG, "New fragment" }, { IPCOM_PKT_ID_PRE_SEND_SIG, "Before SEND signature" }, { IPCOM_PKT_ID_POST_SEND_SIG, "After SEND signature" }, { IPCOM_PKT_ID_CACHE, "Packet cache" }, { IPCOM_PKT_ID_SCTP_INPUT, "SCTP input" }, { IPCOM_PKT_ID_ETH_TX, "Ethernet TX" }, { IPCOM_PKT_ID_FWD_TX, "Forwarder TX" }, { IPCOM_PKT_ID_TUNNEL_RX, "Tunnel interface RX" }, { IPCOM_PKT_ID_TUNNEL_TX, "Tunnel interface TX" }, { -1, IP_NULL } }; #endif #define IPNET_CTRL_PKT_FOUND (-2) /* Must no be a valid socket or IP_SOCKERR */ #define IPNET_CTRL_CREATE_CPU_RETVAL(cpu) ((cpu) - 10000) /* **************************************************************************** * 9 LOCAL FUNCTIONS **************************************************************************** */ #ifdef IPNET_USE_PACKET_POOL /* *=========================================================================== * ipnet_ctrl_verify_inq *=========================================================================== * Description: Verifies that a packet can be found in the input queue. * Parameters: pkt - Packet to find. * Returns: IPNET_CTRL_INQ if the packet was found in the input queue, * IP_SOCKERR if it was not found. * */ IP_STATIC int ipnet_ctrl_verify_inq(Ipcom_pkt *pkt) { Ipcom_pkt *ipkt; for (ipkt = ipnet->task.inq.head; ipkt != IP_NULL; ipkt = ipkt->next) if (ipkt == pkt) return IPNET_CTRL_PKT_FOUND; return IP_SOCKERR; } /* *=========================================================================== * ipnet_ctrl_verify_pkt_cache *=========================================================================== * Description: Verify that this packet can be found in one of the pkt cache. * Parameters: pkt - packet to find * Returns: * */ IP_STATIC int ipnet_ctrl_verify_pkt_cache(Ipcom_pkt *pkt) { Ipnet_pkt_cache_entry *pce; int i; int ret = IP_SOCKERR; if (pkt->data_freefunc_cookie == (void *)ipnet->slabs.pkt_buf_1500) pce = &ipnet->pkt_cache.pkts; else pce = &ipnet->pkt_cache.hdrs; ipcom_spinlock_lock(&pce->lock); for (i = pce->top; i < IPNET_PKT_CACHE_MAX_COUNT; i++) if (pce->stack[i] == pkt) ret = IPNET_CTRL_PKT_FOUND; ipcom_spinlock_unlock(&pce->lock); return ret; } /* *=========================================================================== * ipnet_ctrl_verify_reassembly *=========================================================================== * Description: Verifies that a packet can be found in the input queue. * Parameters: pkt - Packet to find. * Returns: IPNET_CTRL_INQ if the packet was found in the reassembly queue, * IP_SOCKERR if it was not found. * */ IP_STATIC int ipnet_ctrl_verify_reassembly(Ipcom_pkt *pkt) { Ipnet_peer_info **ppeer_info; Ipcom_pkt *fragment_list; Ipcom_pkt *fragment; Ipcom_pkt *pkt_list_head = IP_NULL; ppeer_info = ipcom_pkt_get_info(pkt, IPNET_PKT_INFO_PEER_INFO_PTR); if (ppeer_info != IP_NULL) pkt_list_head = (*ppeer_info)->reassembly_list; for (fragment_list = pkt_list_head; fragment_list != IP_NULL; fragment_list = fragment_list->next) { for (fragment = fragment_list; fragment != IP_NULL; fragment = fragment->next_fragment) if (fragment == pkt) return IPNET_CTRL_PKT_FOUND; } return IP_SOCKERR; } /* *=========================================================================== * ipnet_ctrl_verify_socksendq *=========================================================================== * Description: Verify that the packet is located at one of the sockets * send queue. * Parameters: pkt - Packet to find. * Returns: The socket descriptor where the packet is in send queue. * */ IP_STATIC Ip_fd ipnet_ctrl_verify_socksendq(Ipcom_pkt *pkt) { int i; Iptcp_socket *sock; for (i = 0; i < ipnet_conf_max_sockets; i++) { sock = ipstack->sockets[i]; if (sock != IP_NULL && pkt == sock->snd_head) return sock->ipcom.fd; } return IP_SOCKERR; } /* *=========================================================================== * ipnet_ctrl_verify_location *=========================================================================== * Description: Verifies that the packet can be found in the location specified * by the 'id' field. * Parameters: pkt - Packet to find. * str - Buffer to print the status. * Returns: A description of the location status. * */ IP_STATIC IP_CONST char * ipnet_ctrl_verify_location(Ipcom_pkt *pkt, char *str) { Ip_fd fd; enum Ipcom_pkt_id id; id = IPCOM_GET_PKT_ID(pkt); switch (id) { #ifdef IPTCP case IPCOM_PKT_ID_TCP_RETRANSQ: fd = iptcp_ctrl_verify_retransq(pkt); break; case IPCOM_PKT_ID_SOCKRECVQ: fd = iptcp_ctrl_verify_sockrecvq(pkt); break; case IPCOM_PKT_ID_TCP_SOCKOOORECVQ: fd = iptcp_ctrl_verify_sockooorecvq(pkt); break; #endif /* IPTCP */ #ifdef IPCOM_USE_INET case IPCOM_PKT_ID_IP4_REASSEMBLY: #endif /* IPCOM_USE_INET */ #ifdef IPCOM_USE_INET6 case IPCOM_PKT_ID_IP6_REASSEMBLY: #endif /* IPCOM_USE_INET6 */ fd = ipnet_ctrl_verify_reassembly(pkt); break; case IPCOM_PKT_ID_SOCKSENDQ: fd = ipnet_ctrl_verify_socksendq(pkt); break; case IPCOM_PKT_ID_INIT: case IPCOM_PKT_ID_ADDREF: case IPCOM_PKT_ID_DELREF: case IPCOM_PKT_ID_RX: case IPCOM_PKT_ID_TX: case IPCOM_PKT_ID_INPUT: case IPCOM_PKT_ID_OUTQ: case IPCOM_PKT_ID_NETIF_OUTQ: case IPCOM_PKT_ID_TCP: case IPCOM_PKT_ID_TCP_INPUT: case IPCOM_PKT_ID_TCP_OUTPUT: case IPCOM_PKT_ID_IP4_INPUT: case IPCOM_PKT_ID_IP4_OUTPUT: case IPCOM_PKT_ID_IP6_INPUT: case IPCOM_PKT_ID_IP6_OUTPUT: case IPCOM_PKT_ID_REMOVE: case IPCOM_PKT_ID_IPSEC_INPUT: case IPCOM_PKT_ID_IPSEC_OUTPUT: case IPCOM_PKT_ID_IPSEC_OUTPUT_ORG: case IPCOM_PKT_ID_IPSEC_PF_KEY_IN: case IPCOM_PKT_ID_PPP: case IPCOM_PKT_ID_PPP_ORGOUT: case IPCOM_PKT_ID_PPP_INPUT: case IPCOM_PKT_ID_PPP_OUTPUT: case IPCOM_PKT_ID_RTSOCK: case IPCOM_PKT_ID_UDP_INPUT: case IPCOM_PKT_ID_NETIF_DEQUEUE: case IPCOM_PKT_ID_PRE_SEND_SIG: case IPCOM_PKT_ID_POST_SEND_SIG: case IPCOM_PKT_ID_SENT_PIPE: case IPCOM_PKT_ID_RECV_PIPE: /* Packet is not located in any list in this state */ return ipcom_strcpy(str, "Can't check"); case IPCOM_PKT_ID_INQ: fd = ipnet_ctrl_verify_inq(pkt); break; case IPCOM_PKT_ID_CACHE: fd = ipnet_ctrl_verify_pkt_cache(pkt); break; case IPCOM_PKT_ID_FREEQ: /* This can only be caused by a bug! */ return ipcom_strcpy(str, "BUG!"); default: if (id == IPCOM_PKT_ID_UNINITIALIZED) ipcom_strcpy(str, "Can't check"); else ipcom_sprintf(str, "Invalid id: %d", id); return str; } if (fd > 0) ipcom_sprintf(str, "Yes: sock=%d", fd); else if (fd == IP_SOCKERR) ipcom_strcpy(str, "No"); else if (fd == IPNET_CTRL_PKT_FOUND) ipcom_strcpy(str, "Yes"); else ipcom_strcpy(str, "BUG!"); return str; } /* *=========================================================================== * ipnet_ctrl_print_allocated_packets *=========================================================================== * Description: Prints information about allocated packets * Parameters: * Returns: * */ IP_STATIC int ipnet_ctrl_print_allocated_packets(char *output) { char str[20]; int pos; Ipcom_pkt *pkt; IP_CONST char *if_name; Ipnet_netif *netif; char *buffer; IPNET_DATA_LOCK(ipnet->pkt_pool_lock); pos = ipcom_snprintf(output, IPNET_CTRL_PRINT_BUF_SIZE, "%-6s%-6s%-6s%-6s%-20s%-16s%-6s%-10s%-10s\n", "Start", "End", "Max", "Used", "Location", "Loc-verified", "If", "Flags", "Ptr"); for (pkt = ipnet->allocated_pkt_list; pkt != IP_NULL; pkt = pkt->next_alloc) { netif = ipnet_if_indextonetif(IPCOM_VR_ANY, pkt->ifindex); if (netif == IP_NULL) if_name = "N/A"; else if_name = netif->ipcom.name; pos += ipcom_snprintf(output + pos, (Ip_size_t) (IPNET_CTRL_PRINT_BUF_SIZE - pos), "%-6d%-6d%-6d%-6u%-20s%-16s%-6s%#08x %p\n", pkt->start, pkt->end, pkt->maxlen, (unsigned int) pkt->num_allocated, ipcom_cmd_key_to_str(ipnet_ctrl_id_map, IPCOM_GET_PKT_ID(pkt), IP_NULL, 0), ipnet_ctrl_verify_location(pkt, str), if_name, (unsigned) pkt->flags, (void*) pkt); } IPNET_DATA_UNLOCK(ipnet->pkt_pool_lock); buffer = ipcom_malloc(1001); buffer[1000] = 0; pos = 0; do { strncpy( buffer, output+pos, 1000 ); pos += 1000; (void)ipcom_printf("%s", buffer); } while ( 1000 == strlen( buffer ) ); ipcom_free( buffer ); return 0; } /* *=========================================================================== * ipnet_ctrl_print_packets *=========================================================================== * Description: Prints information about allocated packets * Parameters: * Returns: * */ IP_STATIC int ipnet_ctrl_print_packets(char *output) { int pos = 0; Ipcom_pkt *pkt; IPNET_DATA_LOCK(ipnet->pkt_pool_lock); for (pkt = ipnet->allocated_pkt_list; pkt != IP_NULL; pkt = pkt->next_alloc) { if ( pkt->num_allocated || IPCOM_PKT_GET_REF_COUNT(pkt) ) { unsigned i; pos += ipcom_snprintf(output + pos, (Ip_size_t) (IPNET_CTRL_PRINT_BUF_SIZE - pos), "%-10p Allocated: %-6u Ref: %-3u\n", (void *) pkt, (unsigned int) pkt->num_allocated, IPCOM_PKT_GET_REF_COUNT(pkt)); for (i = (pkt->next_trace == 0 ? IPCOM_PKT_TRACE_BUFFER_LEN : pkt->next_trace) - 1; i != pkt->next_trace; i = (i == 0 ? IPCOM_PKT_TRACE_BUFFER_LEN : i) - 1) { Ipcom_pkt_trace_buffer *tb = &pkt->trace_buffer[i]; pos += ipcom_snprintf(output + pos, (Ip_size_t) (IPNET_CTRL_PRINT_BUF_SIZE - pos), "\tPID: %u, ID: %-20s %s:%d\n", (unsigned) tb->pid, ipcom_cmd_key_to_str(ipnet_ctrl_id_map, tb->id, IP_NULL, 0), tb->file, tb->line); } } } #ifdef FIX_ME_NEED_TO_GET_THE_FREE_PACKET_HEADERS_FROM_THE_SLAB_INSTEAD for (pkt = ipnet->pkt_hdr_list; pkt != IP_NULL; pkt = pkt->next) { if ( pkt->num_allocated || IPCOM_PKT_GET_REF_COUNT(pkt) ) { pos += ipcom_snprintf(output + pos, (Ip_size_t) (IPNET_CTRL_PRINT_BUF_SIZE - pos), "%-10p %-20s Allocated: %-6u Ref: %-3u\n\t%-40s %-6d\n\t%-40s %-6d\n", (void *) pkt, ipcom_cmd_key_to_str(ipnet_ctrl_id_map, pkt->id, IP_NULL, 0), (unsigned int) pkt->num_allocated, IPCOM_PKT_GET_REF_COUNT(pkt), pkt->alloc_file == IP_NULL ? "*" : pkt->alloc_file, pkt->alloc_line, pkt->free_file == IP_NULL ? "*" : pkt->free_file, pkt->free_line); } } #endif IPNET_DATA_UNLOCK(ipnet->pkt_pool_lock); /* * This below instead of a simple printf because printf can't * handle that many characters */ for (pos = 0; ipcom_strlen(output + pos) > 1000; pos += 1000) { char *end = output + pos + 1000; char tkn = *end; *end = '\0'; (void)ipcom_printf("%s", output + pos); *end = tkn; } (void)ipcom_printf("%s", output + pos); return 0; } #endif /* IPNET_USE_PACKET_POOL */ /* *=========================================================================== * ipnet_ctrl_print_timeouts *=========================================================================== * Description: Prints all running timeouts in IPNET. * Parameters: * Returns: * */ IP_STATIC int ipnet_ctrl_print_timeouts(char *output) { Ipnet_timeout **tmo_elems = IP_NULL; int i = 0; int j; int num_elem; int offset = 0; Ipnet_cmd_tmo_handler_to_str *map; void *suspend_handle; Ip_s64 msec; suspend_handle = ipnet_suspend_stack(); if (suspend_handle == IP_NULL) { ipcom_printf("Failed to suspend the stack"IP_LF); goto cleanup; } /* Refresh the stack view of the wall clock time. */ ipnet->msec_now = ipnet_msec_now(); tmo_elems = ipcom_malloc((10 + (Ip_size_t)ipcom_pqueue_size(ipnet->timeouts)) * sizeof(*tmo_elems)); if (tmo_elems == IP_NULL) { ipnet_resume_stack(suspend_handle); ipcom_printf("Timeout dump failed: out of memory" IP_LF); goto cleanup; } while (IP_NULL != (tmo_elems[i++] = ipcom_pqueue_remove_next(ipnet->timeouts))) /* Do nothing */; num_elem = i - 1; for (i = 0; i < num_elem; i++) { msec = ipnet_timeout_msec_until(tmo_elems[i]); if (msec / (1000 * 60 * 60 * 2)) /* More than 2 hours */ (void)ipcom_snprintf(ipnet->log_buf, sizeof(ipnet->log_buf), "%5u hours ", (unsigned) (msec / (1000 * 60 * 60))); else if (msec / (1000 * 60 * 2)) /* More than 2 minutes */ (void)ipcom_snprintf(ipnet->log_buf, sizeof(ipnet->log_buf), "%5u minutes ", (unsigned) (msec / (1000 * 60))); else if (msec / (1000 * 2)) /* More than 2 seconds */ (void)ipcom_snprintf(ipnet->log_buf, sizeof(ipnet->log_buf), "%5u seconds ", (unsigned) (msec / 1000)); else (void)ipcom_snprintf(ipnet->log_buf, sizeof(ipnet->log_buf), "%5u millisec", (unsigned) (msec)); offset += ipcom_snprintf(&output[offset], (Ip_size_t) (IPNET_CTRL_PRINT_BUF_SIZE - offset), "%s ", ipnet->log_buf); for (j = 0, map = IP_NULL; map == IP_NULL && j < ipnet->tmo_map_size; j++) if (ipnet->tmo_map[j].key == tmo_elems[i]->handler) map = &ipnet->tmo_map[j]; if (map != IP_NULL) offset += map->to_str_func(tmo_elems[i]->cookie, &output[offset], (Ip_size_t) (IPNET_CTRL_PRINT_BUF_SIZE - offset)); else offset += ipcom_snprintf(&output[offset], (Ip_size_t) (IPNET_CTRL_PRINT_BUF_SIZE - offset), "Handler is at %p", tmo_elems[i]->handler); offset += ipcom_snprintf(&output[offset], (Ip_size_t) (IPNET_CTRL_PRINT_BUF_SIZE - offset), IP_LF); } for (i = 0; i < num_elem; i++) (void)ipcom_pqueue_insert(ipnet->timeouts, tmo_elems[i]); ipnet_resume_stack(suspend_handle); for (i = 0; output[i] != '\0'; i++) (void)ipcom_printf("%c", output[i]); cleanup: ipcom_free(tmo_elems); return 0; } /* *=========================================================================== * ipnet_ctrl_print_route_entry *=========================================================================== * Description: Prints an internal or leaf node in the route table. * Parameters: * Returns: * */ IP_STATIC void ipnet_ctrl_print_route_entry(char *output, Ipcom_route *rtab, Ipcom_route_entry *rt) { int i; Ipcom_route_entry *h; for (h = rt; h->parent; h = h->parent) (void)ipcom_sprintf(output + ipcom_strlen(output), " "); if (rt->on) (void)ipcom_sprintf(output + ipcom_strlen(output), "bit:%d", rt->bit); else { if (IP_BIT_ISSET(rt->flags, IPCOM_ROUTE_FLAG_INIT)) (void)ipcom_sprintf(output + ipcom_strlen(output), "#key:"); else (void)ipcom_sprintf(output + ipcom_strlen(output), " key:"); for (i = 0; i < rtab->octet_count; i++) (void)ipcom_sprintf(output + ipcom_strlen(output), "%02x" , ((Ip_u8*)rt->key)[i]); } if (rt->mask) { (void)ipcom_sprintf(output + ipcom_strlen(output), " mask:"); for (i = 0; i < rtab->octet_count; i++) (void)ipcom_sprintf(output + ipcom_strlen(output), "%02x", ((Ip_u8*)rt->mask)[i]); } if (rt->on == IP_NULL && IP_BIT_ISFALSE(rt->flags, IPCOM_ROUTE_FLAG_INIT)) { Ipnet_route_entry *r = (Ipnet_route_entry *) rt; void *a = IP_NULL; int a_len; if (r->gateway != IP_NULL) { switch (r->gateway->sa_family) { case IP_AF_INET: a = &((struct Ip_sockaddr_in *)r->gateway)->sin_addr; a_len = 4; break; case IP_AF_INET6: a = &((struct Ip_sockaddr_in6 *)r->gateway)->sin6_addr; a_len = 16; break; case IP_AF_LINK: a = IP_SOCKADDR_DL_LLADDR(r->gateway); a_len = ((struct Ip_sockaddr_dl *)r->gateway)->sdl_alen; break; default: a_len = 0; break; } if (a_len) { (void)ipcom_sprintf(output + ipcom_strlen(output), " gw:"); for (i = 0; i < a_len; i++) (void)ipcom_sprintf(output + ipcom_strlen(output), "%02x", ((Ip_u8*)a)[i]); } } } ipcom_sprintf(output + ipcom_strlen(output), " flags:%08x", (unsigned) rt->flags); (void)ipcom_sprintf(output + ipcom_strlen(output), IP_LF); } /* *=========================================================================== * ipnet_ctrl_inorder_route_dump *=========================================================================== * Description: Walks through the entire route table and print every node. * Parameters: * Returns: * */ IP_STATIC void ipnet_ctrl_inorder_route_dump(char *output, Ipcom_route *rtab, Ipcom_route_entry *rt) { if (rt == IP_NULL) return; ipnet_ctrl_inorder_route_dump(output, rtab, rt->on); if (rt->on == IP_FALSE && IP_BIT_ISFALSE(rt->flags, IPCOM_ROUTE_FLAG_INIT)) ipnet_ctrl_inorder_route_dump(output, rtab, &((Ipnet_route_entry *) rt)->narrow->hdr); ipnet_ctrl_print_route_entry(output, rtab, rt); if (rt->on == IP_FALSE && IP_BIT_ISFALSE(rt->flags, IPCOM_ROUTE_FLAG_INIT)) ipnet_ctrl_inorder_route_dump(output, rtab, &((Ipnet_route_entry *) rt)->next->hdr); ipnet_ctrl_inorder_route_dump(output, rtab, rt->off); } /* *=========================================================================== * ipnet_ctrl_dump_route_table *=========================================================================== * Description: Prints all routes in a route table. * Parameters: * Returns: * */ #ifdef IPTESTENGINE IP_GLOBAL int ipnet_ctrl_dump_route_table(char *output, int domain, Ip_u16 vrtab, Ip_u32 table); IP_GLOBAL int #else IP_STATIC int #endif ipnet_ctrl_dump_route_table(char *output, int domain, Ip_u16 vrtab, Ip_u32 table) { Ipcom_route *rtab; if (ipnet_route_get_rtab(domain, vrtab, table, &rtab) < 0) { ipcom_printf("Failed to get route table for domain %d, virtual router %d and table ID %d"IP_LF, domain, vrtab, table); return -1; } output[0] = '\0'; ipnet_ctrl_inorder_route_dump(output, rtab, rtab->top); (void)ipcom_printf("%s", output); return 0; } /* *=========================================================================== * ipnet_ctrl_suspend_stack *=========================================================================== * Description: Suspends the stack for the specified number of seconds * Parameters: sec - number of seconds to suspend the stack. * Returns: * */ IP_STATIC void ipnet_ctrl_suspend_stack(unsigned int sec) { void *suspend_handle; suspend_handle = ipnet_suspend_stack(); if (suspend_handle == IP_NULL) ipcom_printf("Stack could not resume\n"); else { ipcom_sleep(sec); ipnet_resume_stack(suspend_handle); } } /* *=========================================================================== * ipnet_ctrl_print_usage *=========================================================================== * Description: Prints usage for the shell command. * Parameters: * Returns: * */ IP_STATIC void ipnet_ctrl_print_usage(void) { ipcom_printf("\n"); ipcom_printf("NAME\n"); ipcom_printf(" ipnet_ctrl - control functions for IPNET\n"); ipcom_printf(" WARNING: this command will access datastructures internal to IPNET\n"); ipcom_printf(" and does it in a way that might not work on all OS:es.\n"); ipcom_printf(" This command is only debug tool for the stack and is only guaranteed\n"); ipcom_printf(" to work on the user-mode Linux port\n"); ipcom_printf("\n"); ipcom_printf("SYNOPSIS\n"); ipcom_printf(" ipnet_ctrl -p\n"); ipcom_printf(" ipnet_ctrl -a\n"); ipcom_printf(" ipnet_ctrl -t\n"); ipcom_printf(" ipnet_ctrl -r :\n"); ipcom_printf("\n"); ipcom_printf("DESCRIPTION\n"); ipcom_printf(" ipnet_ctrl is used to check the internal state of the IPNET stack.\n"); ipcom_printf("\n"); ipcom_printf(" -p\n" " List all allocated packets in the system.\n" " -a\n" " List all packets in the system.\n" " -t\n" " List all timeouts.\n" " -r [:[:]]\n" " Dump the routing table.\n" " -s \n" " Suspend the stack for seconds\n" "\n"); } /* **************************************************************************** * 10 PUBLIC FUNCTIONS **************************************************************************** */ /* *=========================================================================== * ipnet_cmd_ctrl *=========================================================================== * Description: Shell command to view internal structures. * Parameters: * Returns: * */ IP_PUBLIC int ipnet_cmd_ctrl(int argc, char **argv) { Ipcom_getopt opt; int c; char *output; int ret = 0; int domain; Ip_u16 vrtab = 0; Ip_u32 table = IPCOM_ROUTE_TABLE_DEFAULT; char *s; char *p; Ip_bool print_usage = IP_TRUE; output = ipcom_malloc(IPNET_CTRL_PRINT_BUF_SIZE); if (output == IP_NULL) { ipcom_printf("Out of memory for display buffer\n"); return -1; } output[0] = '\0'; ipcom_getopt_clear_r(&opt); while ((c = ipcom_getopt_r(argc, argv, "patr:s:", &opt)) != -1) { print_usage = IP_FALSE; switch (c) { #ifdef IPNET_USE_PACKET_POOL case 'p': ret = ipnet_ctrl_print_allocated_packets(output); break; case 'a': ret = ipnet_ctrl_print_packets(output); break; #endif /* IPNET_USE_PACKET_POOL */ case 't': ret = ipnet_ctrl_print_timeouts(output); break; case 'r': print_usage = IP_TRUE; s = ipcom_strtok_r(opt.optarg, ":", &p); domain = ipcom_atoi(s); s = ipcom_strtok_r(IP_NULL, ":"IP_LF, &p); if (s != IP_NULL) { vrtab = (Ip_u16) ipcom_atoi(s); s = ipcom_strtok_r(IP_NULL, IP_LF, &p); if (s != IP_NULL) table = (Ip_u32) ipcom_atoi(s); } ret = ipnet_ctrl_dump_route_table(output, domain, vrtab, table); print_usage = IP_FALSE; break; case 's': ipnet_ctrl_suspend_stack((unsigned int)ipcom_strtoul(opt.optarg, (char **)IP_NULL, 10)); break; default: print_usage = IP_TRUE; break; } } ipcom_free(output); if (print_usage) ipnet_ctrl_print_usage(); return ret; } #endif /* IPNET_DEBUG */ /* **************************************************************************** * END OF FILE **************************************************************************** */