struct netif结构体是lwip协议中非常重要的一个数据结构,每一个网卡都对应一个唯一的netif结构体,当软件中启动dhcp成功获取到ip地址之后,网卡的ip地址、子网掩码、网关地址等信息就会存储到这个netif结构体中,我们可以通过访问这个结构体来获取我们需要得到的信息。
lwip允许设允许存在多个网卡,所以netif通常会存储在一个链表中,以支持多个网卡的设备。
lwip不仅支持ipv4,而且支持ipv6,这里我们仅讨论ipv4.
netif结构体的原型如下(基于lwip2.1.2):
struct netif { #if !LWIP_SINGLE_NETIF /** pointer to next in linked list */ struct netif *next; #endif #if LWIP_IPV4 /** IP address configuration in network byte order */ ip_addr_t ip_addr;//ip地址 ip_addr_t netmask;//子网掩码 ip_addr_t gw;//网关地址 #endif /* LWIP_IPV4 */ #if LWIP_IPV6 /** IPV6的地址 */ ip_addr_t ip6_addr[LWIP_IPV6_NUM_ADDRESSES]; /** IPV6地址的状态*/ u8_t ip6_addr_state[LWIP_IPV6_NUM_ADDRESSES]; #if LWIP_IPV6_ADDRESS_LIFETIMES /** IPV6的生命周期,如果是特殊值 IP6_ADDR_LIFE_STATIC (0) 表示IPV6没有生命周期 */ u32_t ip6_addr_valid_life[LWIP_IPV6_NUM_ADDRESSES]; u32_t ip6_addr_pref_life[LWIP_IPV6_NUM_ADDRESSES]; #endif /* LWIP_IPV6_ADDRESS_LIFETIMES */ #endif /* LWIP_IPV6 */ /** 这个函数由网络设备驱动调用,用于将数据包传递给TCP/IP协议栈 */ netif_input_fn input; #if LWIP_IPV4 /** 这个函数由IP层调用,用于发送数据给接口. 它首先解析硬件地址,然后发送数据包. * For ethernet physical layer, this is usually etharp_output() */ netif_output_fn output; #endif /* LWIP_IPV4 */ /** This function is called by ethernet_output() when it wants * to send a packet on the interface. This function outputs * the pbuf as-is on the link medium. */ netif_linkoutput_fn linkoutput; #if LWIP_IPV6 /** This function is called by the IPv6 module when it wants * to send a packet on the interface. This function typically * first resolves the hardware address, then sends the packet. * For ethernet physical layer, this is usually ethip6_output() */ netif_output_ip6_fn output_ip6; #endif /* LWIP_IPV6 */ #if LWIP_NETIF_STATUS_CALLBACK /** IPV6当设备获取到ip或者失去ip时会调用这个回调函数 */ netif_status_callback_fn status_callback; #endif /* LWIP_NETIF_STATUS_CALLBACK */ #if LWIP_NETIF_LINK_CALLBACK /** IPV4当设备获取到ip或者失去ip时会调用这个回调函数 */ netif_status_callback_fn link_callback; #endif /* LWIP_NETIF_LINK_CALLBACK */ #if LWIP_NETIF_REMOVE_CALLBACK /** This function is called when the netif has been removed */ netif_status_callback_fn remove_callback; #endif /* LWIP_NETIF_REMOVE_CALLBACK */ /** This field can be set by the device driver and could point * to state information for the device. */ void *state; #ifdef netif_get_client_data void* client_data[LWIP_NETIF_CLIENT_DATA_INDEX_MAX + LWIP_NUM_NETIF_CLIENT_DATA]; #endif #if LWIP_NETIF_HOSTNAME /* 网卡的主机名称*/ const char* hostname; #endif /* LWIP_NETIF_HOSTNAME */ #if LWIP_CHECKSUM_CTRL_PER_NETIF u16_t chksum_flags; #endif /* LWIP_CHECKSUM_CTRL_PER_NETIF*/ /** 最大传输单元 (in bytes) */ u16_t mtu; #if LWIP_IPV6 && LWIP_ND6_ALLOW_RA_UPDATES /** maximum transfer unit (in bytes), updated by RA */ u16_t mtu6; #endif /* LWIP_IPV6 && LWIP_ND6_ALLOW_RA_UPDATES */ /** 设备的mac地址 */ u8_t hwaddr[NETIF_MAX_HWADDR_LEN]; /** number of bytes used in hwaddr */ u8_t hwaddr_len; /** flags (@see @ref netif_flags) */ u8_t flags; /** descriptive abbreviation */ char name[2]; /** number of this interface. Used for @ref if_api and @ref netifapi_netif, * as well as for IPv6 zones */ u8_t num; #if LWIP_IPV6_AUTOCONFIG /** is this netif enabled for IPv6 autoconfiguration */ u8_t ip6_autoconfig_enabled; #endif /* LWIP_IPV6_AUTOCONFIG */ #if LWIP_IPV6_SEND_ROUTER_SOLICIT /** Number of Router Solicitation messages that remain to be sent. */ u8_t rs_count; #endif /* LWIP_IPV6_SEND_ROUTER_SOLICIT */ #if MIB2_STATS /** link type (from "snmp_ifType" enum from snmp_mib2.h) */ u8_t link_type; /** (estimate) link speed */ u32_t link_speed; /** timestamp at last change made (up/down) */ u32_t ts; /** counters */ struct stats_mib2_netif_ctrs mib2_counters; #endif /* MIB2_STATS */ #if LWIP_IPV4 && LWIP_IGMP /** This function could be called to add or delete an entry in the multicast filter table of the ethernet MAC.*/ netif_igmp_mac_filter_fn igmp_mac_filter; #endif /* LWIP_IPV4 && LWIP_IGMP */ #if LWIP_IPV6 && LWIP_IPV6_MLD /** This function could be called to add or delete an entry in the IPv6 multicast filter table of the ethernet MAC. */ netif_mld_mac_filter_fn mld_mac_filter; #endif /* LWIP_IPV6 && LWIP_IPV6_MLD */ #if LWIP_NETIF_USE_HINTS struct netif_hint *hints; #endif /* LWIP_NETIF_USE_HINTS */ #if ENABLE_LOOPBACK /* List of packets to be queued for ourselves. */ struct pbuf *loop_first; struct pbuf *loop_last; #if LWIP_LOOPBACK_MAX_PBUFS u16_t loop_cnt_current; #endif /* LWIP_LOOPBACK_MAX_PBUFS */ #endif /* ENABLE_LOOPBACK */ };当设备成功获取到ip,或者因为某些原因失去原有的ip(如路由器断电、被路由器踢掉)时,系统会调用这个函数通知应用层进行相应的处理。我们可以自己定义这个回调函数来获取ip改变的信息。
MTU指的是在数据传输过程中允许报文的最大长度,在以太网中,这个值最大一般是1500。当传输的报文长度大于MTU时,会分片发送。
设备的mac地址
这个名称会显示在路由器中,当我们的手机连接上路由器时,会显示我们的手机名称,如“华为mate30”,这个字段就是在路由器中显示的设备名称。