]> rtime.felk.cvut.cz Git - rpp-test-sw.git/blobdiff - rpp-test-sw/commands/cmd_netstats.c
Merge branches 'master' and 'rm48/master'
[rpp-test-sw.git] / rpp-test-sw / commands / cmd_netstats.c
diff --git a/rpp-test-sw/commands/cmd_netstats.c b/rpp-test-sw/commands/cmd_netstats.c
new file mode 100644 (file)
index 0000000..924e546
--- /dev/null
@@ -0,0 +1,653 @@
+/*
+ * Copyright (C) 2012-2013 Czech Technical University in Prague
+ *
+ * Created on: Aug 23, 2013
+ *
+ * Authors:
+ *     - Jan Dolezal <pm.jenik@gmail.com>
+ *
+ * This document contains proprietary information belonging to Czech
+ * Technical University in Prague. Passing on and copying of this
+ * document, and communication of its contents is not permitted
+ * without prior written authorization.
+ *
+ * File : cmd_netstats.c
+ *
+ * Abstract:
+ *      This file contains commands for net statistics (ethernet interface and LwIP)
+ *
+ */
+
+#include "cmd_netstats.h"
+
+#ifndef DOCGEN
+
+#include <string.h>
+
+#include "rpp/rpp.h"
+#include "drv/emac.h"
+#include "lwip/opt.h"
+#include "lwip/stats.h"
+
+#define INTERFACE_INSTANCE_NUMBER 0
+
+int cmd_do_read_linkstat(cmd_io_t *cmd_io, const struct cmd_des *des, char *param[])
+{
+       if (!isPostInitialized()) {
+               rpp_sci_printf("Eth not initialized run 'ethinit' command first.\n");
+               return FAILURE;
+       }
+       struct netif *netif = rpp_eth_get_netif(INTERFACE_INSTANCE_NUMBER);
+       if (rpp_eth_phylinkstat(INTERFACE_INSTANCE_NUMBER))
+               rpp_sci_printf("%c%c%d : UP\r\n", netif->name[0], netif->name[1], netif->num);
+       else
+               rpp_sci_printf("%c%c%d : DOWN\r\n", netif->name[0], netif->name[1], netif->num);
+       return SUCCESS;
+}
+
+int cmd_do_read_mac(cmd_io_t *cmd_io, const struct cmd_des *des, char *param[])
+{
+       if (!isPostInitialized()) {
+               rpp_sci_printf("Eth not initialized run 'ethinit' command first.\n");
+               return FAILURE;
+       }
+       uint8_t macaddr[18];
+       rpp_eth_get_macAddrStr(INTERFACE_INSTANCE_NUMBER,macaddr);
+       rpp_sci_printf((const char *)"%s\n", macaddr);
+       return SUCCESS;
+}
+
+int cmd_do_read_ip(cmd_io_t *cmd_io, const struct cmd_des *des, char *param[])
+{
+       if (!isPostInitialized()) {
+               rpp_sci_printf("Eth not initialized run 'ethinit' command first.\n");
+               return FAILURE;
+       }
+       struct netif *netif = rpp_eth_get_netif(INTERFACE_INSTANCE_NUMBER);
+       uint8_t ipString[16];
+       rpp_eth_getIPDecimalStr(netif->ip_addr, ipString);
+       rpp_sci_printf("Address: %s\r\n", ipString);
+       rpp_eth_getIPDecimalStr(netif->netmask, ipString);
+       rpp_sci_printf("Netmask: %s\r\n", ipString);
+       rpp_eth_getIPDecimalStr(netif->gw, ipString);
+       rpp_sci_printf("Gateway: %s\r\n", ipString);
+       return SUCCESS;
+}
+
+
+
+
+/*      --- EMAC DESCRIPTOR FORMAT ---
+ *                                         bit fields
+ * WORD   |
+ * OFFSET | 31                               16 | 15                                 0
+ * ------------------------------------------------------------------------------------
+ *    0   |                         *Next Descriptor Pointer
+ *    1   |                           *Data Buffer Pointer
+ *    2   |            Buffer Offset            |            Buffer Length
+ *    3   |                Flags                |            Packet Length
+ *    4   |                                  *pbuf
+ */
+
+boolean_t bd_SOP(volatile struct emac_tx_bd *bufferDescriptor)
+{
+       return (bufferDescriptor->flags_pktlen & EMAC_DSC_FLAG_SOP);
+}
+
+boolean_t bd_EOP(volatile struct emac_tx_bd *bufferDescriptor)
+{
+       return (bufferDescriptor->flags_pktlen & EMAC_DSC_FLAG_EOP);
+}
+
+boolean_t bd_OWNER(volatile struct emac_tx_bd *bufferDescriptor)
+{
+       return (bufferDescriptor->flags_pktlen & EMAC_DSC_FLAG_OWNER);
+}
+
+boolean_t bd_EOQ(volatile struct emac_tx_bd *bufferDescriptor)
+{
+       return (bufferDescriptor->flags_pktlen & EMAC_DSC_FLAG_EOQ);
+}
+
+uint32_t bd_addr(uint16_t bd_num)
+{
+       return EMAC_CTRL_RAM_BASE_m(0) + bd_num*sizeof(struct emac_tx_bd);
+}
+
+volatile struct emac_tx_bd *findPreviousBD(volatile struct emac_tx_bd *bufferDescriptor)
+{
+       volatile struct emac_tx_bd *temporary = bufferDescriptor - 1;
+
+       /* first try space before given bd */
+       if ((uint32_t)temporary >= EMAC_CTRL_RAM_BASE_m(0) && temporary->next == bufferDescriptor)
+               return temporary;
+       temporary = bufferDescriptor->next;
+       while (temporary != bufferDescriptor && temporary != NULL) {
+               if (temporary->next == bufferDescriptor)
+                       return temporary;
+               temporary = (temporary + 1); /* going through memory, if you want to go through bd chains put here 'temporary = temporary->next;' */
+               if ( (uint32_t)(temporary+1) > EMAC_CTRL_RAM_BASE_m(0)+SIZE_EMAC_CTRL_RAM) /* when out of CPPI RAM */
+                       temporary = (struct emac_tx_bd *)EMAC_CTRL_RAM_BASE_m(0);  /* continue scanning from the beginning */
+       }
+       return (struct emac_tx_bd *)-1;  /* not found */
+}
+
+void print_bd_content(volatile struct emac_tx_bd *bufferDescriptor, boolean_t humanReadable)
+{
+       uint16_t data;
+
+       rpp_sci_printf("Buffer Descriptor at 0x%08x\n", bufferDescriptor);
+       rpp_sci_printf("Next BD:\t0x%08x\n", bufferDescriptor->next);
+       rpp_sci_printf("Data ptr:\t0x%08x\n", bufferDescriptor->bufptr);
+       rpp_sci_printf("Buf offset:\t%d\tBuf length:\t%d\n", (bufferDescriptor->bufoff_len >> 16), (bufferDescriptor->bufoff_len & 0xffff));
+       if (!humanReadable)
+               rpp_sci_printf("Flags:\t\t0x%04x\t", (bufferDescriptor->flags_pktlen >> 16));
+       else
+       {
+               data = bufferDescriptor->flags_pktlen;
+               rpp_sci_printf("Flags:\t%s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s\n", (data & EMAC_DSC_FLAG_SOP) ? "SOP" : "", (data & EMAC_DSC_FLAG_EOP) ? "EOP" : "", (data & EMAC_DSC_FLAG_OWNER) ? "OWNER" : "", (data & EMAC_DSC_FLAG_EOQ) ? "EOQ" : "", (data & EMAC_DSC_FLAG_TDOWNCMPLT) ? "TDWN" : "", (data & EMAC_DSC_FLAG_PASSCRC) ? "PSCRC" : "", (data & EMAC_DSC_FLAG_JABBER) ? "JBR" : "", (data & EMAC_DSC_FLAG_OVERSIZE) ? "OVSZ" : "", (data & EMAC_DSC_FLAG_FRAGMENT) ? "FRGM" : "", (data & EMAC_DSC_FLAG_UNDERSIZED) ? "UNSZ" : "", (data & EMAC_DSC_FLAG_CONTROL) ? "CTRL" : "", (data & EMAC_DSC_FLAG_OVERRUN) ? "OVRUN" : "", (data & EMAC_DSC_FLAG_CODEERROR) ? "CODEERR" : "", (data & EMAC_DSC_FLAG_ALIGNERROR) ? "ALGNERR" : "", (data & EMAC_DSC_FLAG_CRCERROR) ? "CRCERR" : "", (data & EMAC_DSC_FLAG_NOMATCH) ? "NOMATCH" : "");
+       }
+       rpp_sci_printf("Pkt length:\t%d\n", (bufferDescriptor->flags_pktlen & 0xffff));
+       rpp_sci_printf("Pbuf ptr:\t0x%08x\n", bufferDescriptor->pbuf);
+}
+
+/*
+ * mode: 0 flags -> param says which flag (0-15)
+ *       1 bd->next == NULL, no param
+ */
+void print_bds_state(uint8_t mode, uint8_t param)
+{
+       volatile struct emac_tx_bd *bufferDescriptor = (struct emac_tx_bd *)EMAC_CTRL_RAM_BASE_m(0);
+       uint16_t index = 0;
+
+       rpp_sci_printf("TX:");
+       while (index < 409) {
+               if (!(index%10)) {
+                       rpp_sci_printf(" ");
+                       if (!(index%50)) rpp_sci_printf("\n");
+               }
+               if (index == 204)
+                       rpp_sci_printf("\nRX: ");
+               if      (mode == 0) {
+                       if (bufferDescriptor->flags_pktlen & ((1 << 15) >> (param%16)))
+                               rpp_sci_printf("f");
+                       else
+                               rpp_sci_printf(".");
+               }
+               else if (mode == 1) {
+                       if (bufferDescriptor->next == NULL)
+                               rpp_sci_printf("0");
+                       else
+                               rpp_sci_printf(".");
+               }
+               else return;
+               bufferDescriptor++;
+               index++;
+       }
+       rpp_sci_printf("\n");
+}
+
+#define BUF_SIZE 15
+
+unsigned long readNum(uint8_t minamount, uint8_t maxamount, boolean_t hex)
+{
+       unsigned long out = 0;
+       uint8_t input_buffer[BUF_SIZE];
+       uint8_t buf_index = 0;
+       uint8_t input;
+
+       do {
+               input = rpp_sci_getc();
+               if (input == '\b' && buf_index > 0) {
+                       input_buffer[buf_index] = '\0';
+                       buf_index--;
+                       echo('\b');
+                       echo( ' ');
+                       echo('\b');
+               }
+               else if (buf_index >= maxamount)
+                       continue;
+               else if (input <= '9' && input >= '0') {
+                       input_buffer[buf_index] = input - '0';
+                       echo(input);
+                       buf_index++;
+               }
+               else if (hex && (input <= 'f' && input >= 'a')) {
+                       input_buffer[buf_index] = input - ('a' - 10);
+                       echo(input);
+                       buf_index++;
+               }
+               else if (hex && (input <= 'F' && input >= 'A')) {
+                       input_buffer[buf_index] = input - ('A' - 10);
+                       echo((input + ('a' - 'A')));
+                       buf_index++;
+               }
+       } while ( (input != '\r' && input != '\n' && buf_index < BUF_SIZE) || buf_index < minamount);
+       input = 0; /* use as index */
+       while (input < buf_index) {
+               if (hex)
+                       out = (out << 4) + input_buffer[input];
+               else
+                       out = (out*10) + input_buffer[input];
+               input++;
+       }
+       return out;
+}
+
+int cmd_do_bufferdescriptors(cmd_io_t *cmd_io, const struct cmd_des *des, char *param[])
+{
+       uint8_t pindex;
+       uint8_t input;
+       volatile struct emac_tx_bd *bufferDescriptor;
+       boolean_t run = TRUE, interactive = FALSE, overview = FALSE;
+
+#if RPP_ETH_STATS
+       boolean_t isrRun = FALSE, rb = FALSE, tb = FALSE;
+#endif
+
+       /* if eth not initialized return */
+       if (!isPostInitialized()) {
+               rpp_sci_printf("Eth not initialized run 'ethinit' command first.\n");
+               return FAILURE;
+       }
+
+       /* examine parameters */
+       for (pindex = 1; param[pindex] != 0; pindex++) {
+               if        (strncmp((char *)param[pindex], "-i", 3) == 0) {
+                       interactive = TRUE;
+                       break;
+               }
+               else if (strncmp((char *)param[pindex], "-o", 3) == 0) {
+                       overview = TRUE;
+                       break;
+               }
+#if RPP_ETH_STATS
+               else if (strncmp((char *)param[pindex], "-r", 3) == 0) {
+                       isrRun = TRUE;
+                       break;
+               }
+               else if (strncmp((char *)param[pindex], "-rb", 4) == 0) {
+                       rb = TRUE;
+                       break;
+               }
+               else if (strncmp((char *)param[pindex], "-tb", 4) == 0) {
+                       tb = TRUE;
+                       break;
+               }
+#endif
+       }
+       struct netif *netif = rpp_eth_get_netif(INTERFACE_INSTANCE_NUMBER);
+       if (netif == NULL) {
+               rpp_sci_printf("netif err\n");
+               return -1;
+       }
+
+       if (interactive)
+               while (run) {
+                       input = rpp_sci_getc();
+
+                       if (input == 'b') { /* print buffer descriptor at given address */
+                               rpp_sci_printf("-? 0x");
+                               bufferDescriptor = (struct emac_tx_bd *)readNum(8,8,TRUE);
+                               rpp_sci_printf("\n");
+                               /* check it fits EMAC CPPI RAM */
+                               /*if(bufferDescriptor >= EMAC_CTRL_RAM_BASE_m(INTERFACE_INSTANCE_NUMBER) && (bufferDescriptor + sizeof(struct emac_tx_bd)) <= EMAC_CTRL_RAM_BASE_m(INTERFACE_INSTANCE_NUMBER) + SIZE_EMAC_CTRL_RAM)
+                                  {*/
+                               print_bd_content(bufferDescriptor, FALSE);
+                               /*}
+                                  else
+                                  {
+                                   rpp_sci_printf("address not from BD CPPI RAM range\n");
+                                  }*/
+                               while (1) {
+                                       input = rpp_sci_getc();
+                                       if      (input == 'n') { /* next */
+                                               bufferDescriptor = bufferDescriptor->next;
+                                               if (bufferDescriptor != NULL)
+                                                       print_bd_content(bufferDescriptor, FALSE);
+                                               else {
+                                                       rpp_sci_printf("NULL\n");
+                                                       break;
+                                               }
+                                       }
+                                       else if (input == 'p') { /* previous */
+                                               bufferDescriptor = findPreviousBD(bufferDescriptor);
+                                               if ((int32_t)bufferDescriptor != -1) {
+                                                       if (bufferDescriptor == NULL) {
+                                                               rpp_sci_printf("NULL\n");
+                                                               break;
+                                                       }
+                                                       else
+                                                               print_bd_content(bufferDescriptor, FALSE);
+                                               }
+                                               else
+                                               {
+                                                       rpp_sci_printf("not found\n");
+                                                       break;
+                                               }
+                                       }
+                                       else if (input == 'r') { /* reprint */
+                                               if ((int32_t)bufferDescriptor == -1 || bufferDescriptor == NULL) break;
+                                               print_bd_content(bufferDescriptor, FALSE);
+                                       }
+                                       else break;
+                               }
+                       }
+
+                       if      (input == 'q') { /* quit */
+                               run = FALSE;
+                               continue;
+                       }
+#if RPP_ETH_STATS
+                       else if (input == 's') /* general statistics */
+                               printStatistics();
+                       else if (input == 't') { /* print tx channel */
+                               print_tx_channel_stat();
+                               continue;
+                       }
+                       else if (input == 'r') { /* print rx channel */
+                               print_rx_channel_stat();
+                               continue;
+                       }
+#endif
+                       else if (input == 'a') { /* autocheck consistency of buffer descriptors */
+
+                       }
+                       else if (input == 'o') { /* overview */
+                               uint8_t mode = rpp_sci_getc() - '0';
+                               uint8_t param = rpp_sci_getc() - '0';
+                               print_bds_state(mode, param);
+                       }
+                       else if (input == 'c')  /* convert */
+                               rpp_sci_printf("0x%08x", bd_addr((uint16_t)readNum(1, 3, FALSE)));
+               }
+       else
+       {
+               if (overview) {
+                       rpp_sci_printf(" --- OVERVIEWS ---\n");
+                       rpp_sci_printf("bd->next points to NULL\n");
+                       print_bds_state(1, 0);
+                       rpp_sci_printf("bds with EMAC_DSC_FLAG_SOP\n");
+                       print_bds_state(0, 0);
+                       rpp_sci_printf("bds with EMAC_DSC_FLAG_EOP\n");
+                       print_bds_state(0, 1);
+                       rpp_sci_printf("bds with EMAC_DSC_FLAG_OWNER\n");
+                       print_bds_state(0, 2);
+                       rpp_sci_printf("bds with EMAC_DSC_FLAG_EOQ\n");
+                       print_bds_state(0, 3);
+                       rpp_sci_printf("bds with EMAC_DSC_FLAG_TDOWNCMPLT\n");
+                       print_bds_state(0, 4);
+                       rpp_sci_printf("bds with EMAC_DSC_FLAG_PASSCRC\n");
+                       print_bds_state(0, 5);
+                       rpp_sci_printf("\nPress any key ...\r");
+                       rpp_sci_getc();
+                       /* These flags are not so much important */
+                       rpp_sci_printf("bds with EMAC_DSC_FLAG_JABBER\n");
+                       print_bds_state(0, 6);
+                       rpp_sci_printf("bds with EMAC_DSC_FLAG_OVERSIZE\n");
+                       print_bds_state(0, 7);
+                       rpp_sci_printf("bds with EMAC_DSC_FLAG_FRAGMENT\n");
+                       print_bds_state(0, 8);
+                       rpp_sci_printf("bds with EMAC_DSC_FLAG_UNDERSIZED\n");
+                       print_bds_state(0, 9);
+                       rpp_sci_printf("bds with EMAC_DSC_FLAG_CONTROL\n");
+                       print_bds_state(0, 10);
+                       rpp_sci_printf("bds with EMAC_DSC_FLAG_OVERRUN\n");
+                       print_bds_state(0, 11);
+                       rpp_sci_printf("bds with EMAC_DSC_FLAG_CODEERROR\n");
+                       print_bds_state(0, 12);
+                       rpp_sci_printf("bds with EMAC_DSC_FLAG_ALIGNERROR\n");
+                       print_bds_state(0, 13);
+                       rpp_sci_printf("bds with EMAC_DSC_FLAG_CRCERROR\n");
+                       print_bds_state(0, 14);
+                       rpp_sci_printf("bds with EMAC_DSC_FLAG_NOMATCH\n");
+                       print_bds_state(0, 15);
+               }
+#if RPP_ETH_STATS
+               if (isrRun) {
+                       rpp_sci_printf(" --- NUMBER OF ISR RUNS ---\n");
+                       rpp_sci_printf("TxIsr: %d", countEMACCore0TxIsr);
+                       rpp_sci_printf("RxIsr: %d", countEMACCore0RxIsr);
+               }
+#endif
+
+
+       }
+       return ERR_OK;
+}
+
+#if LWIP_DHCP
+int cmd_do_dhcp(cmd_io_t *cmd_io, const struct cmd_des *des, char *param[])
+{
+       if (!isPostInitialized()) {
+               rpp_sci_printf("Eth not initialized run 'ethinit' command first.\n");
+               return FAILURE;
+       }
+       rpp_sci_printf("not implemented yet.");
+       return ERR_OK;
+}
+#endif
+
+#if LWIP_STATS_DISPLAY
+int cmd_do_lwip(cmd_io_t *cmd_io, const struct cmd_des *des, char *param[])
+{
+       if (!isPostInitialized()) {
+               rpp_sci_printf("Eth not initialized run 'ethinit' command first.\n");
+               return FAILURE;
+       }
+       stats_display();
+       rpp_sci_printf("\n");
+       return ERR_OK;
+}
+#endif
+
+int cmd_do_ethinit(cmd_io_t *cmd_io, const struct cmd_des *des, char *param[])
+{
+       int8_t retVal = rpp_eth_init_postInit(0, NULL); /* post OS startup init of eth (LwIP) for application usage -- waits for a while, for auto-negotiation of ethernet speed and DHCP if used */
+
+       switch (retVal) {
+       case FAILURE:
+               rpp_sci_printf("already initialized\n");
+               break;
+       case NETIF_ADD_ERR:
+               rpp_sci_printf("initialization of physical part of ethernet failed\n");
+               break;
+       case DHCP_MEM_ERR:
+               rpp_sci_printf("DHCP couldn't be started due to insufficient memory\n");
+               break;
+       case PHY_LINK_DOWN:
+               rpp_sci_printf("cable is not connected\n");
+               break;
+       default:
+               rpp_sci_printf("ethinit DONE\n");
+       }
+       return retVal;
+}
+
+#endif  /* DOCGEN */
+
+cmd_des_t const cmd_des_linkstat = {
+       0,0,
+       "ethlinkstat","Print current status of ethernet interface",
+
+       "### Command syntax ###\n"
+       "\n"
+       "    ethlinkstat\n"
+       "\n"
+       "### Description ###\n"
+       "\n"
+       "This command reads PHY link status assigned to ethernet interface and\n"
+       "prints interface name and informs about PHY's status to the output.\n"
+       "\n"
+       "### Example ###\n"
+       "\n"
+       "    --> ethlinkstat\n"
+       "    et0 : UP\n"
+       "\n"
+       "    --> ethlinkstat\n"
+       "    et0 : DOWN\n",
+       CMD_HANDLER(cmd_do_read_linkstat), (void *)&cmd_list_netstats
+};
+
+cmd_des_t const cmd_des_mac = {
+       0,0,
+       "ethmac","Print current MAC address of ethernet interface",
+
+       "### Command syntax ###\n"
+       "\n"
+       "    ethmac\n"
+       "\n"
+       "### Description ###\n"
+       "\n"
+       "This command obtains MAC address from ethernet interface structure\n"
+       "and prints it to the output.\n"
+       "\n"
+       "### Example ###\n"
+       "\n"
+       "    --> ethmac\n"
+       "    12:34:56:78:9a:bc\n",
+       CMD_HANDLER(cmd_do_read_mac), (void *)&cmd_list_netstats
+};
+
+cmd_des_t const cmd_des_ip = {
+       0,0,
+       "ethip","Print current IP address of network interface",
+
+       "### Command syntax ###\n"
+       "\n"
+       "    ethip\n"
+       "\n"
+       "### Description ###\n"
+       "\n"
+       "This command reads current IP address, netmask and gateway of network\n"
+       "interface and prints these to the output.\n"
+       "\n"
+       "### Example ###\n"
+       "\n"
+       "    --> ethip\n"
+       "    Address: 192.168.247.1\n"
+       "    Netmask: 255.255.255.0\n"
+       "    Gateway: 192.168.247.255\n",
+       CMD_HANDLER(cmd_do_read_ip), (void *)&cmd_list_netstats
+};
+
+cmd_des_t const cmd_des_bufferdescriptors = {
+       0,CDESM_SPACE_SEP,
+       "ethbd","Examine emac buffer descriptors",
+
+       "### Command syntax ###\n"
+       "\n"
+       "    ethbd\n"
+       "\n"
+       "### Description ###\n"
+       "After startup you use keys to control what will be done.\n"
+       "\n"
+       "- q - quit\n"
+       "- s - general statistics\n"
+       "- t - transmit channel status\n"
+       "- r - receive channel status\n"
+       "- b - after giving address of bd it prints bd content\n"
+       "- a - checks consistency of buffer descriptors\n"
+       "\n"
+       "\n"
+       "### Example ###\n"
+       "\n"
+       "    --> ethbd\n",
+       CMD_HANDLER(cmd_do_bufferdescriptors), (void *)&cmd_list_netstats
+};
+
+#if LWIP_DHCP
+cmd_des_t const cmd_des_dhcp = {
+       0,0,
+       "dhcp","Prints and controls DHCP",
+
+       "### Command syntax ###\n"
+       "\n"
+       "    dhcp\n"
+       "\n"
+       "### Description ###\n"
+       "\n"
+       "\n"
+       ".\n"
+       "\n"
+       "### Example ###\n"
+       "\n"
+       "    --> dhcp\n"
+       "    \n",
+       CMD_HANDLER(cmd_do_dhcp), (void *)&cmd_list_netstats
+};
+#endif
+
+#if LWIP_STATS_DISPLAY
+cmd_des_t const cmd_des_lwip = {
+       0,0,
+       "lwip","Prints statistics for the LwIP stack",
+
+       "### Command syntax ###\n"
+       "\n"
+       "    lwip\n"
+       "\n"
+       "### Description ###\n"
+       "\n"
+       "Sections printed:\n"
+       "LINK\n"
+       "ETHARP\n"
+       "IP\n"
+       "ICMP\n"
+       "UDP\n"
+       "TCP\n"
+       "MEM HEAP\n"
+       "MEM RAW_PCB\n"
+       "MEM UDP_PCB\n"
+       "MEM TCP_PCB\n"
+       "MEM TCP_PCB_LISTEN\n"
+       "MEM TCP_SEB\n"
+       "MEM NETBUF\n"
+       "MEM NETCONN\n"
+       "MEM TCPIP_MSG_API\n"
+       "MEM TCPIP_MSG_INPKT\n"
+       "MEM SYS_TIMEOUT\n"
+       "MEM PBUF_REF/ROM\n"
+       "MEM PBUF_POOL\n"
+       "SYS\n"
+       ".\n"
+       "Shown sections depends on modules compiled in.\n"
+       "    \n",
+       CMD_HANDLER(cmd_do_lwip), (void *)&cmd_list_netstats
+};
+#endif /* if LWIP_STATS_DISPLAY */
+
+cmd_des_t const cmd_des_ethinit = {
+       0,0,
+       "ethinit","Post OS startup eth initialization",
+
+       "### Command syntax ###\n"
+       "\n"
+       "    ethinit\n"
+       "\n"
+       "### Description ###\n"
+       "This command finishes autonegotiation of PHY and initialize LwIP stack.\n"
+       "\n"
+       "\n"
+       "### Example ###\n"
+       "\n"
+       "    --> ethinit\n"
+       "    \n",
+       CMD_HANDLER(cmd_do_ethinit), (void *)&cmd_list_netstats
+};
+
+/** List of commands for lwip, defined as external */
+cmd_des_t const *cmd_list_netstats[] = {
+       &cmd_des_linkstat,
+       &cmd_des_mac,
+       &cmd_des_ip,
+       &cmd_des_bufferdescriptors,
+#if LWIP_DHCP
+       &cmd_des_dhcp,
+#endif
+#if LWIP_STATS_DISPLAY
+       &cmd_des_lwip,
+#endif
+       &cmd_des_ethinit,
+       NULL
+};