网卡接口

网络接口

网络接口(以太网)是硬件接口,LwIP是软件,并且网卡也是由很多种的

LwIP使用一个数据结构,nitif来描述网卡

用户提供最底层的接口函数,LwIP则提供统一的接口,这样用户根据网卡不同提供底层接口,上层则不需要改变

ethernetif.c文件提供了netif访问不同的网卡,每个网卡有不同的实现方式,用户仅仅修改ethernetif文件即可

单网卡中,netif结构体只有一个;多网卡设备中,LwIP将每个用netif描述的网卡连接成一个单项链表

网卡结构体

struct netif
{
#if !LWIP_SINGLE_NETIF
	struct netif *next;	//指向下一个节点,通过next指针遍历链表
#endif

#if LWIP_IPV4
	ip_addr_t ip_addr;	// ip地址,与网卡对应,多个网卡 即 多个ip地址
	ip_addr_t netmask;	// 子网掩码,判断IP与网卡是否在一个子网,IP发送数据包会选择与目标IP在一个子网的网卡
	ip_addr_t gw;		// 向不同子网的主机发送数据包,数据包先发送到网关,网关对数据包进行转发
#endif

	netif_input_fn input;	// 数据包递交到IP层 回调函数 ,对于物理层,一般赋值为 ethernet_input

#if LWIP_IPV4
	netif_output_fn output;	// IP层调用,发送数据包;先解析地址,再发送;物理层一般赋值为 etharp_output
#endif

	netif_linkoutput_fn linkoutput;	// 被函数 ethernet_output 调用,网卡发送数据包,底层硬件输出数据函数

#if LWIP_NETIF_STATUS_CALLBACK
	netif_status_callback_fn status_callback;	// netif状态为up/down时,调用这个函数
#endif

#if LWIP_NETIF_LINK_CALLBACK
	netif_status_callback_fn link_callback;		// netif链接为up/down时,调用这个函数
#endif

#if LWIP_NETIF_REMOVE_CALLBACK
	netif_status_callback_fn remove_callback;	// netif 被删除时,调用这个函数
#endif

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;			// netif 的主机名,NULL也是有效值
#endif

#if LWIP_CHECKSUM_CTRL_PER_NETIF
	u16_t chksum_flags;
#endif

	u16_t mtu;							// 最大传输字节,一般以太网设置为 1500
	u8_t hwaddr[NETIF_MAX_HWADDR_LEN];	// 网卡的链路层硬件地址,MAC地址
	u8_t hwaddr_len;					// MAC地址长度,一般是6个人字节
	u8_t flags;							// 网卡状态标志位,包括网卡功能,广播,ARP使能等控制位
	char name;							// 保存网卡的名字,表示网卡种类,蓝牙bt,WLAN wl,同名使用num区分
	u8_t num;							// 用来标示使用同种驱动类型的不同网卡

#if MIB2_STATS
	u8_t link_type;						// 连接类型
	u32_t link_speed;					// 连接速度
	u32_t ts;							// 最后一次更改的时间戳
	struct stats_mib2_netif_ctrs mib2_counters;
#endif

#if LWIP_IPV4 && LWIP_IGMP
	netif_igmp_mac_filter_fn igmp_mac_filter;	// 调用这个函数来添加或删除多播中的条目,以太网的MAC过滤表
#endif

#if LWIP_NETIF_USE_HINTS
struct netif_hint *hints;
#endif

#if ENABLE_LOOPBACK
	struct pbuf *loop_first;
	struct pbuf *loop_last;
	#if LWIP_LOOPBACK_MAX_PBUFS
		u16_t loop_cnt_current;
	#endif
#endif
};

使用

netif只定义了类型,使用时需要用户自行定义对应变量

在定义变量之后,将网卡挂载到链表中,通过 netif_add 函数

只要添加了新网卡,都需要通过函数 netif_add 将网卡挂载到网卡链表中

#define ip_addr_set_zero_ip4(ipaddr)	ip4_addr_set_zero(ipaddr)
#define ip4_addr_set_zero(ipaddr)		((ipaddr)->addr = 0)
struct netif * netif_add(	struct netif *netif,		// 网卡结构体
#if LWIP_IPV4
							const ip4_addr_t *ipaddr,	// ip地址
							const ip4_addr_t *netmask,	// 子网掩码
							const ip4_addr_t *gw,		// 网关地址
#endif
							void *state,				// 网卡状态
							netif_init_fn init,			// 网卡初始化函数
							netif_input_fn input)		// 
{
#if LWIP_IPV4
	if (ipaddr == NULL) 
	{
		ipaddr = ip_2_ip4(IP4_ADDR_ANY);	// ipaddr = (&((IP4_ADDR_ANY)->u_addr.ip4))
	}
	if (netmask == NULL) 
	{
		netmask = ip_2_ip4(IP4_ADDR_ANY);
	}
	if (gw == NULL) 
	{
		gw = ip_2_ip4(IP4_ADDR_ANY);
	}

	ip_addr_set_zero_ip4(&netif->ip_addr);		// ip地址置零
	ip_addr_set_zero_ip4(&netif->netmask);		// 子网掩码置零
	ip_addr_set_zero_ip4(&netif->gw);			// 网关置零
	netif->output = netif_null_output_ip4;		// 回调函数赋值
#endif 

#if LWIP_IPV6
	for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++)	// IPV6相关数据清零
	{
		ip_addr_set_zero_ip6(&netif->ip6_addr[i]);
		netif->ip6_addr_state[i] = IP6_ADDR_INVALID;
	#if LWIP_IPV6_ADDRESS_LIFETIMES
		netif->ip6_addr_valid_life[i] = IP6_ADDR_LIFE_STATIC;
		netif->ip6_addr_pref_life[i] = IP6_ADDR_LIFE_STATIC;
	#endif
	}
	netif->output_ip6 = netif_null_output_ip6;
#endif

	NETIF_SET_CHECKSUM_CTRL(netif, NETIF_CHECKSUM_ENABLE_ALL);	// (netif)->chksum_flags = NETIF_CHECKSUM_ENABLE_ALL
	netif->mtu = 0;												// 底层最大传输量清零,标志位清零
	netif->flags = 0;

#ifdef netif_get_client_data
	memset(netif->client_data, 0, sizeof(netif->client_data));	// 客户端数据清零
#endif

#if LWIP_IPV6
	#if LWIP_IPV6_AUTOCONFIG
		netif->ip6_autoconfig_enabled = 0;
	#endif
	nd6_restart_netif(netif);
#endif

#if LWIP_NETIF_STATUS_CALLBACK
	netif->status_callback = NULL;
#endif 

#if LWIP_NETIF_LINK_CALLBACK
	netif->link_callback = NULL;
#endif

#if LWIP_IGMP
	netif->igmp_mac_filter = NULL;
#endif

#if LWIP_IPV6 && LWIP_IPV6_MLD
	netif->mld_mac_filter = NULL;
#endif

#if ENABLE_LOOPBACK
	netif->loop_first = NULL;
	netif->loop_last = NULL;
#endif

	netif->state = state;						// 相关数据赋值,填写网卡state,input字段
	netif->num = netif_num;
	netif->input = input;						// 赋值为 tcpip_input
	NETIF_RESET_HINTS(netif);
#if ENABLE_LOOPBACK && LWIP_LOOPBACK_MAX_PBUFS
	netif->loop_cnt_current = 0;
#endif

#if LWIP_IPV4
	netif_set_addr(netif, ipaddr, netmask, gw);	// 设置ip信息,子网掩码,网关
#endif

	if (init(netif) != ERR_OK) 					// 通过回调函数对网卡进行初始化,一般由用户实现,ethernetif_init 函数
	{											// 或者调用函数
		return NULL;
	}

#if LWIP_IPV6 && LWIP_ND6_ALLOW_RA_UPDATES
	netif->mtu6 = netif->mtu;
#endif

#if !LWIP_SINGLE_NETIF							// 支持多网卡
	{
		struct netif *netif2;
		int num_netifs;
		do {
			if (netif->num == 255) 				// 遍历网卡链表
			{
				netif->num = 0;
			}
			num_netifs = 0;						// 网卡数量为0,从首字节开始遍历链表
			for (netif2 = netif_list; netif2 != NULL; netif2 = netif2->next) 
			{
				num_netifs++;					// 只要链表next指针不为空,一直移动next指针
				if (netif2->num == netif->num) 	// 
				{
					netif->num++;
					break;
				}
			}
		} while (netif2 != NULL);
	}
	if (netif->num == 254) 
	{
		netif_num = 0;
	} 
	else 
	{
		netif_num = (u8_t)(netif->num + 1);		// 计算携带有多少网卡
	}

	netif->next = netif_list;					// next 指针指向 netif_list
	netif_list = netif;
#endif
	mib2_netif_added(netif);					// 网卡挂载到链表中

#if LWIP_IGMP

	if (netif->flags & NETIF_FLAG_IGMP) 		// 网卡状态为 0x20
	{
		igmp_start(netif);
	}
#endif

#if LWIP_IPV4
	ip4_addr_debug_print(NETIF_DEBUG, ipaddr);
	ip4_addr_debug_print(NETIF_DEBUG, netmask);
	ip4_addr_debug_print(NETIF_DEBUG, gw);
#endif
	netif_invoke_ext_callback(netif, LWIP_NSC_NETIF_ADDED, NULL);

	return netif;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值