LwIP of RT thread cutting series (I)

Time:2022-1-5

This article was originally published by RT thread forum users @ out ah:https://club.rt-thread.org/as…

preface

I began to sort out the following list of optimization items a long time ago, but I didn’t study many problems deeply and didn’t dare to launch them at once.
Not long ago, someone asked a question on the forum. At that time, I gave fewer answers than now, but these listed now can not be guaranteed to be all. Let’s add them later.

LwIP protocol stack and sal socket abstraction layer use many global array variables as thread stack, which can be modified to dynamically apply memory from memory heap.
Some functions and features are not used in embedded devices and can be removed first.
There are also optional features. If you want to use them, there is also optimization space, which can be realized by yourself.

The following description is not limited to LwIP, but also involved in sal.

Cutting details

Sal tailorable optimization

  1. SAL_INTERNET_CHECK: network detection, workqueue used. The detection principle is to try to connect “link. RT-Thread. Org:: 8101″ and send detection data.
    You can either remove the detection or replace it with your own server.
  2. #define SAL_SOCKETS_NUM 4: this may be the maximum number of sockets that can be created.
  3. RT_USING_NETDEV: network interface equipment can be optimized without terminal operation. Among them,NETDEV_USING_IFCONFIG NETDEV_USING_PING NETDEV_USING_NETSTAT NETDEV_USING_AUTO_DEFAULTThey can be added or deleted separately.
  4. NETDEV_IPV6: if the support is not popular at present, you can turn it off and turn it on if necessary.

LwIP tailorable optimization

  1. RT_LWIP_IGMPIf multicast is needed, it may be removed without multicast
  2. RT_LWIP_ICMPThe ping command uses a protocol that is not required without Ping.
  3. RT_LWIP_DNSThe LAN does not need this, or in other words, it can connect directly using IP address instead of URL link address, and DNS can not be used.
  4. RT_LWIP_TCP_WNDTCP receive window, which should be the requested memory size. Can be appropriately reduced. No, it’s 1460 x 2 bytes
  5. RT_LWIP_TCP_SND_BUFTCP send cache, the same as above, is not defined as 1460 x 2 bytes
  6. LWIP_NO_TX_THREADandLWIP_NO_RX_THREADEth thread, send one and receive one. The following are several related macro definitions. If the stack size is not defined, 1024 is used by default

    #define RT_LWIP_ETHTHREAD_PRIORITY 12
    #define RT_LWIP_ETHTHREAD_STACKSIZE 1024
    #define RT_LWIP_ETHTHREAD_MBOX_SIZE 8
    #define LWIP_NO_TX_THREAD
    #define LWIP_NO_RX_THREAD

    In the source code, there is still a lot of room for optimization in this part. See the details below.

  7. LWIP_NETIF_STATUS_CALLBACKAnd sal in front_ INTERNET_ For check, the network connection callback is set here. You can notify the application layer to connect to the Internet.
  8. LWIP_NETIF_LINK_CALLBACKThe network card connection status only indicates the physical connection to the network. It may be directly connected to the computer, or switches, routers, etc.
  9. SO_REUSEPort multiplexing, which is useful only in multicast and UDP protocol. Defined as 0 without
  10. LWIP_SO_SNDTIMEO LWIP_SO_RCVTIMEO LWIP_SO_RCVBUFThese three, if rtconf There is no definition in H, lwipopts H will be defined, so it does not need to be defined as 0.
    Including LwIP_ SO_ Rcvbuf receive buffer, involving the upper limit of receive buffer. In most cases, there will be no impact. This cache limit can be reached only when there is a lot of network data.
  11. RT_LWIP_USING_PINGThis is the same as the netdev in front_ USING_ PING RT_ LWIP_ ICMP related.
  12. RT_LWIP_STATSThis is the main switch of a group of stats. For details, see lwipopts H definitions in the document. Or cancel RT_ LWIP_ Define stats, close all stat items, or modify lwipopts separately Some stat definitions in the H file.
  13. Modify eth_ rx_ Thread and eth_ tx_ Thread, enable RT_ USING_ After heap, add a dynamically created thread. These two threads are initialized in init_ PREV_ Export phase. Both on-chip memory heap and off chip inner heap are initialized and registered in init_ BOARD_ In the export phase, you can apply for dynamic memory.

Erx ETX two threads

Take ETX as an example.ethernetif_linkoutputThe main operations of the function are as follows:

    if (rt_mb_send(ð_tx_thread_mb, (rt_uint32_t) &msg) == RT_EOK)
    {
        /* waiting for ack */
        rt_sem_take(&(enetif->tx_ack), RT_WAITING_FOREVER);
    }

Sent a mailbox and waited for a semaphore. Where does this semaphore come from? Look at the ETX thread entry function below.

static void eth_tx_thread_entry(void* parameter)
{
    struct eth_tx_msg* msg;

    while (1)
    {
        if (rt_mb_recv(ð_tx_thread_mb, (rt_ubase_t *)&msg, RT_WAITING_FOREVER) == RT_EOK)
        {
            struct eth_device* enetif;

            RT_ASSERT(msg->netif != RT_NULL);
            RT_ASSERT(msg->buf   != RT_NULL);

            enetif = (struct eth_device*)msg->netif->state;
            if (enetif != RT_NULL)
            {
                /* call driver's interface */
                if (enetif->eth_tx(&(enetif->parent), msg->buf) != RT_EOK)
                {
                    /* transmit eth packet failed */
                }
            }

            /* send ACK */
            rt_sem_release(&(enetif->tx_ack));
        }
    }
}

ETX waitethernetif_linkoutputMail message, then call the ETH driver interface function, and then release the semaphore.ethernetif_linkoutputA reply.

From here, you need to add two additional IPC messages with this thread.
After removing ETX?ethernetif_linkoutputBecome the following.

static err_t ethernetif_linkoutput(struct netif *netif, struct pbuf *p)
{
    struct eth_device* enetif;

    RT_ASSERT(netif != RT_NULL);
    enetif = (struct eth_device*)netif->state;

    if (enetif->eth_tx(&(enetif->parent), p) != RT_EOK)
    {
        return ERR_IF;
    }
    return ERR_OK;
}

The only difference from using ETX thread is that when using thread, the ETH driver sends data in ETX thread; If removed, multiple application threads may send data at the same time, and multiple threads compete for eth driven resources. However, this can be circumvented by optimizing the application layer business logic.

For more modifications to not using ETX and Erx threads, please move to my gitee repository.

All code changes mentioned in this series have been submitted to gitee. You are welcome to test
https://gitee.com/thewon/rt_t…