LWIP code graphic analysis

        LwIP is a Light Weight (light) IP protocol, which can run with or without the support of the operating system. The focus of LwIP implementation is to reduce the RAM occupation on the basis of maintaining the main functions of the TCP protocol. It only needs more than a dozen KB of RAM and about 40K of ROM to run, which makes the LwIP protocol stack suitable for low-end embedded systems.

1 Protocol analysis (ICMP (ping) is used to return error messages or analyze routes, ARP Ethernet address analysis)

        The mechanism of the ICMP ping command is to echo the request and echo the response message. Specifically, it sends an ICMP message to another host on the network. If the specified host gets the message, it sends the message back to the sender intact.
        ARP Ethernet Address Resolution Protocol

2 lwip provides three APIs: 1) RAW API 2) lwip API 3) BSD API.

3 overall structure of the code

4 Code Analysis

MX_LWIP_Init() //创建3个线程(1 tcpip_thread 2ethernetif_set_link 3 ethernetif_input  )
{
    tcpip_init()
    {
        sys_mbox_new(&tcpip_mbox, TCPIP_MBOX_SIZE);
        sys_thread_new(TCPIP_THREAD_NAME, tcpip_thread, NULL, TCPIP_THREAD_STACKSIZE, TCPIP_THREAD_PRIO)
        {
            tcpip_thread(void *arg)
            {
                while (1)
                { /* MAIN Loop */
                    /* wait for a message, timeouts are processed while waiting */
                    TCPIP_MBOX_FETCH(&tcpip_mbox, (void **)&msg);
                    tcpip_thread_handle_msg(msg);
                }
            }
        }
    }
    /* add the network interface (IPv4/IPv6) with RTOS */
    netif_add(&gnetif, &ipaddr, &netmask, &gw, NULL, &ethernetif_init, &tcpip_input)
    {
        ethernetif_init()
        {
            low_level_init(netif)
            {
                osThreadNew(ethernetif_input, netif, &attributes)
                {
                    ethernetif_input()
                    {
                        for (;;)
                        {
                            osSemaphoreAcquire(s_xSemaphore, TIME_WAITING_FOR_INPUT);
                            netif->input(p, netif); //此函数为上面注册的tcpip_input
                        }
                    }
                }
            }
        }
        tcpip_input(struct pbuf * p, struct netif * inp)
        {
            tcpip_inpkt(p, inp, ip_input)
            {
                sys_mbox_trypost(&tcpip_mbox, msg); //收到数据发送信号量
            }
        }
    }
    /* Set the link callback function, this function is called on change of link status*/
    netif_set_link_callback(&gnetif, ethernetif_update_config);
    /* Create the Ethernet link handler thread */
    osThreadDef(LinkThr, ethernetif_set_link, osPriorityBelowNormal, 0, configMINIMAL_STACK_SIZE * 2)
    {
        ethernetif_set_link() //检查网线连接状态
        {
            for (;;)
            {
                /* Check whether the netif link down and the PHY link is up */
                if (!netif_is_link_up(link_arg->netif) && (regvalue))
                {
                    netif_set_link_up(link_arg->netif); /* network cable is connected */
                    {
                        netif->link_callback(n); //执行前面注册的回调函数
                    }
                }
                else if (netif_is_link_up(link_arg->netif) && (!regvalue))
                {
                    netif_set_link_down(link_arg->netif); /* network cable is dis-connected */
                    {
                        netif->link_callback(n); //执行前面注册的回调函数
                    }
                }
                osDelay(200);
            }
        }
    }
}

netconn_new(t)
{
    netconn_alloc(t, callback)
    {
        conn = (struct netconn *)memp_malloc(MEMP_NETCONN);
        sys_mbox_new(&conn->recvmbox, size); //创建信号量,当接收到数据时,注册的回调函数会发送此信号量
    }
    netconn_apimsg(lwip_netconn_do_newconn, &API_MSG_VAR_REF(msg))
    {
        lwip_netconn_do_newconn()
        {
            pcb_new(msg)
            {
                switch (NETCONNTYPE_GROUP(msg->conn->type))
                {
                case NETCONN_UDP: //设置接收到数据时执行的回调函数
                    udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);
                    {
                        recv_udp()
                        {
                            buf = (struct netbuf *)memp_malloc(MEMP_NETBUF);
                            sys_mbox_trypost(&conn->recvmbox, buf); //当收到数据时,发送信号量
                        }
                    }
                    break;
                case NETCONN_TCP:
                    setup_tcp(msg->conn) //设置回调函数
                    {
                        tcp_arg(pcb, conn);
                        tcp_recv(pcb, recv_tcp);
                        tcp_sent(pcb, sent_tcp);
                        tcp_poll(pcb, poll_tcp, NETCONN_TCP_POLL_INTERVAL);
                        tcp_err(pcb, err_tcp);
                    }
                    break;
                }
            }
        }
    }
}

netconn_recv()
{
    netconn_recv_data_tcp(conn, &p, 0);           // tcp
    netconn_recv_data(conn, (void **)new_buf, 0); // udp
    {
        sys_arch_mbox_fetch(&conn->recvmbox, &buf, 0); //等待信号量 非阻塞
    }
}

netconn_send(struct netconn *conn, struct netbuf *buf)
{
    netconn_apimsg(lwip_netconn_do_send, &API_MSG_VAR_REF(msg))
    {
        lwip_netconn_do_send(void *m)
        {
            udp_sendto(msg->conn->pcb.udp, msg->msg.b->p, &msg->msg.b->addr, msg->msg.b->port)
            {
                /* find the outgoing network interface for this packet */
                netif = ip_route(&pcb->local_ip, dst_ip);
                udp_sendto_if(pcb, p, dst_ip, dst_port, netif); //将package发送出去
            }
        }
    }
}

Guess you like

Origin blog.csdn.net/w356877795/article/details/126935966