LwIP的netif和底层的一些初始化工作

时间:2021-05-18 03:55:45

在LwIP_init( )中调用了netif_add(&netif, &ipaddr, &netmask, &gw, NULL, &ethernetif_init, &ethernet_input);

1.netif结构体

/** Generic data structure used for all lwIP network interfaces.
* The following fields should be filled in by the initialization
* function for the device driver: hwaddr_len, hwaddr[], mtu, flags */

struct netif {

struct netif *next;

struct ip_addr ip_addr;
struct ip_addr netmask;
struct ip_addr gw;


err_t (* input)(struct pbuf *p, struct netif *inp);   由网络驱动程序调用,向TCP/IP层发送一个数据包
"input 字段指向一个函数,这个函数将网卡设备接收到的数据包提交给IP层,使用时将
nput指针指向该函数即可,后面将详细讨论这个问题。该函数的两个参数是pbuf类型和netif
类型的,返回参数是err_t类型。其中pbuf代表接收到的数据包。"
err_t (* output)(struct netif *netif, struct pbuf *p,    IP层调用这个函数向网卡发送一个数据包
struct ip_addr *ipaddr);

"output字段向一个函数,这个函数和具体网络接口设备驱动密切相关,它用于IP 层将
一个数据包发送到网络接口上。用户需要根据实际网卡编写该函数,并将output 字段指向
该函数。该函数的三个参数是pbuf类型、netif类型和ip_addr类型,返回参数是err_t类型。
其中pbuf代表要发送的数据包。ipaddr 代表网卡需要将该数据包发送到的地址,该地址应
该是接收实际的链路层帧的主机的  IP  地址,而不一定为数据包最终需要到达的IP 地址。"
err_t (* linkoutput)(struct netif *netif, struct pbuf *p);   ARP模块调用这个函数向网卡发送一个数据包
”linkoutput字段和上面的output基ᴀ上是起相同的作用,但是这个函数是在ARP模块中
被调用的,这里不赘述了。注意这个函数只有两个参数。实际上output 字段函数的实现最
终还是调用linkoutput字段函数将数据包发送出去的。 “

...........
char* hostname;   //
u8_t hwaddr_len;  //硬件地址长度,对于以太网就是MAC地址长度,为6各字节 
u8_t hwaddr[NETIF_MAX_HWADDR_LEN];   
u16_t mtu;
u8_t flags;       //网卡状态信息标志位 ,
char name[2];   //  网络接口使用的设备驱动类型的种类 
u8_t num;        //  用来标示使用同种驱动类型的不同网络接口
#if LWIP_SNMP
u8_t link_type;
u32_t link_speed;
u32_t ts;
...

...
}


2.struct netif *
   netif_add(struct netif *netif, struct ip_addr *ipaddr, struct ip_addr *netmask,struct ip_addr *gw,  void *state,
  err_t (* init)(struct netif *netif),                               //@param init callback function that initializes the interface
  err_t (* input)(struct pbuf *p, struct netif *netif))   //@param input callback function that is called to pass

init-->ethernetif_init(struct netif *netif)   //底层初始化函数,函数里实际调用low_level_init()对硬件进行设置

input-->ethernet_input(struct pbuf *p, struct netif *netif)  //处理从底层接收来的以太网帧,P指向接收到的数据包,p->payload指向以太网帧头


3.在netif_add中

  netif->input = input;    //即netif结构体中的input指向ethernet_input

    

  /* call user specified initialization function for netif */
  if (init(netif) != ERR_OK) {        //这里就是初始化,进入ethernet_init
    return NULL;
  }


4.ethernet_init( )中几个重要的点

netif->output = etharp_output;     //netif结构体中的output指向etharp_out(struct netif *netif, struct pbuf *q, struct ip_addr                                                      //*ipaddr),

netif->linkoutput = low_level_output; 

 low_level_init(netif);


5.Low_level_init( struct netif *netif),

   a.对netif结构体中的相关参数赋值,

   b.Initialize Tx and Rx Descriptors list: Chain Mode

   c.Enable Ethernet Rx interrrupt 

   d.Enable MAC and DMA transmission and reception-->ETH_Start();


6.etharp_output后面调用etharp_send_ip();这个函数有调用了return netif->linkoutput(netif, p);也就是这里的low_level_output().


7.low_level_output()

  a.ETH_GetCurrentTxBuffer( ) //return Buffer address

  b.memcpy((u8_t*)&buffer[l], q->payload, q->len);

  c.ETH_TxPkt_ChainMode(FrameLength);   //Transmits a packet, from application buffer, pointed by ppkt.FrameLength:                                                                   //Tx Packet size.传递从应用层数据包,长度为FrameLength 


8.最后ethernet_input( )

调用ip_input( )   //This function is called by the network interface device driver when
                         // an IP packet is received. Finally, the packet is sent to the upper layer protocol input function.


参考了 老衲五木 的《LwIP协议栈源码详解 》,最近看到他出了嵌入式网络那些事:LwIP协议深度剖析与实战演练》,膜拜。
        



相关文章