多应用+插件架构,代码干净,二开方便,首家独创一键云编译技术,文档视频完善,免费商用码云13.8K 广告
那么netif具体该如何使用呢?其实使用还是非常简单的。首先我们需要根据我们的网卡定义一个netif结构体变量struct netif gnetif,我们首先要把网卡挂载到netif\_list链表上才能使用,因为LwIP是通过链表来管理所有的网卡,所有第一步是通过netif\_add()函数将我们的网卡挂载到netif\_list链表上,netif\_add()函数具体见代码清单 4‑2。 ``` 1 struct netif * 2 netif_add(struct netif *netif,const ip4_addr_t *ipaddr, 3 const ip4_addr_t *netmask, const ip4_addr_t *gw, 4 void *state, netif_init_fn init, netif_input_fn input) 5 { 6 LWIP_ASSERT_CORE_LOCKED(); 7 8 if (ipaddr == NULL) 9 { 10 ipaddr = ip_2_ip4(IP4_ADDR_ANY); 11 } 12 if (netmask == NULL) 13 { 14 netmask = ip_2_ip4(IP4_ADDR_ANY); 15 } 16 if (gw == NULL) 17 { 18 gw = ip_2_ip4(IP4_ADDR_ANY); 19 } 20 21 /* reset new interface configuration state */ 22 ip_addr_set_zero_ip4(&netif->ip_addr); (1) 23 ip_addr_set_zero_ip4(&netif->netmask); 24 ip_addr_set_zero_ip4(&netif->gw); 25 netif->output = netif_null_output_ip4; 26 27 NETIF_SET_CHECKSUM_CTRL(netif, NETIF_CHECKSUM_ENABLE_ALL); 28 netif->mtu = 0; 29 netif->flags = 0; 30 31 memset(netif->client_data, 0, sizeof(netif->client_data)); 32 33 /* remember netif specific state information data */ 34 netif->state = state; 35 netif->num = netif_num; 36 netif->input = input; (2) 37 38 NETIF_RESET_HINTS(netif); 39 40 41 netif_set_addr(netif, ipaddr, netmask, gw); (3) 42 43 44 /* call user specified initialization function for netif */ 45 if (init(netif) != ERR_OK) (4) 46 { 47 return NULL; 48 } 49 50 { 51 struct netif *netif2; 52 int num_netifs; 53 do 54 { 55 if (netif->num == 255) 56 { 57 netif->num = 0; 58 } 59 num_netifs = 0; 60 for(netif2 = netif_list; netif2 != NULL; netif2 = netif2->next) 61 { 62 num_netifs++; 63 if (netif2->num == netif->num) 64 { 65 netif->num++; 66 break; 67 } 68 } 69 } 70 while (netif2 != NULL); 71 } 72 if (netif->num == 254) 73 { 74 netif_num = 0; 75 } 76 else 77 { 78 netif_num = (u8_t)(netif->num + 1); (5) 79 } 80 81 /* add this netif to the list */ 82 netif->next = netif_list; 83 netif_list = netif; (6) 84 85 mib2_netif_added(netif); 86 87 88 ip4_addr_debug_print(NETIF_DEBUG, ipaddr); 89 90 ip4_addr_debug_print(NETIF_DEBUG, netmask); 91 92 ip4_addr_debug_print(NETIF_DEBUG, gw); 93 94 95 netif_invoke_ext_callback(netif, LWIP_NSC_NETIF_ADDED, NULL); 96 97 return netif; 98 } ``` * (1):清空主机IP地址、子网掩码、网关等字段信息。 * (2):根据传递进来的参数填写网卡state、input等字段的相关信息。 * (3):调用网卡设置函数netif_set_addr()设置网卡IP地址、子网掩码、网关等信息。 * (4):通过传递进来的回调函数init()进行网卡真正的初始化操作,所以该函数是由用户实现的,对于不同网卡就使用不一样的初始化,而此处是以太网,则该回调函数一般为ethernetif_init(),该函数在后文想想讲解。 * (5):初始化网卡成功,则遍历当前设备拥有多少个网卡,并为当前网卡分配唯一标识num。 * (6):将当前网卡插入netif_list链表中。 在使用之前需要进行初始化主机IP地址、子网掩码、网关等,并且在调用netif_add()函数之后会触发netif_init_fn的回调函数。 总之一句话,在开始使用LwIP协议栈的时候,我们就需要将网卡底层移植完成,才能开始使用,而移植的第一步,就是将网络进行初始化,并且设置该网卡为默认网卡,让LwIP能通过网卡进行收发数据,具体见代码清单 4 3加粗部分 ``` 1 /*Static IP ADDRESS: IP_ADDR0.IP_ADDR1.IP_ADDR2.IP_ADDR3 */ 2 #define IP_ADDR0 192 3 #define IP_ADDR1 168 4 #define IP_ADDR2 1 5 #define IP_ADDR3 122 6 7 /*NETMASK*/ 8 #define NETMASK_ADDR0 255 9 #define NETMASK_ADDR1 255 10 #define NETMASK_ADDR2 255 11 #define NETMASK_ADDR3 0 12 13 /*Gateway Address*/ 14 #define GW_ADDR0 192 15 #define GW_ADDR1 168 16 #define GW_ADDR2 1 17 #define GW_ADDR3 1 18 19 struct netif gnetif; 20 ip4_addr_t ipaddr; 21 ip4_addr_t netmask; 22 ip4_addr_t gw; 23 uint8_t IP_ADDRESS[4]; 24 uint8_t NETMASK_ADDRESS[4]; 25 uint8_t GATEWAY_ADDRESS[4]; 26 27 void TCPIP_Init(void) 28 { 29 30 tcpip_init(NULL, NULL); 31 32 /* IP addresses initialization */ 33 /* USER CODE BEGIN 0 */ 34 #ifdef USE_DHCP 35 ip_addr_set_zero_ip4(&ipaddr); 36 ip_addr_set_zero_ip4(&netmask); 37 ip_addr_set_zero_ip4(&gw); 38 #else 39 IP4_ADDR(&ipaddr,IP_ADDR0,IP_ADDR1,IP_ADDR2,IP_ADDR3); 40 IP4_ADDR(&netmask,NETMASK_ADDR0,NETMASK_ADDR1,NETMASK_ADDR2,NETMASK_ADDR3); 41 IP4_ADDR(&gw,GW_ADDR0,GW_ADDR1,GW_ADDR2,GW_ADDR3); 42 #endif /* USE_DHCP */ 43 /* USER CODE END 0 */ 44 /* Initilialize the LwIP stack without RTOS */ 45 /* add the network interface (IPv4/IPv6) without RTOS */ 46 netif_add(&gnetif, &ipaddr, &netmask, &gw, NULL, &ethernetif_init, 47 &tcpip_input); 48 /* Registers the default network interface */ 49 netif_set_default(&gnetif); 50 51 if (netif_is_link_up(&gnetif)) 52 { 53 /* When the netif is fully configured this function must be called */ 54 netif_set_up(&gnetif); 55 } 56 else 57 { 58 /* When the netif link is down this function must be called */ 59 netif_set_down(&gnetif); 60 } 61 } ``` 挂载网卡的过程是非常简单的,如果一个设备当前是还没有网卡的,当调用netif\_add()函数挂载网卡后,其过程如图 4‑1所示,当设备需要挂载多个网卡的时候,就多次调用netif\_add()函数即可,新挂载的网卡会在链表的最前面,具体见图 4‑2。 ![](https://box.kancloud.cn/500561cd4262d0c74b51eff9d11b885a_432x325.png) ![](https://box.kancloud.cn/3defce5c264eb4e905f732cb5c85c7ee_802x393.png)