协议栈内部使用netif的结构体来描述网络接口,先来看一下这个结构体。
/* netif结构体 */
struct netif {
struct netif *next; //用于将netif连接成链表
/* IP地址、子网掩码、网关地址 */
struct ip_addr ip_addr;
struct ip_addr netmask;
struct ip_addr gw;
/* 向IP层输入数据包 */
err_t (* input)(struct pbuf *p, struct netif *inp);
/* 发送IP层数据包(先通过ARP查找目的MAC,再调用linkoutput) */
err_t (* output)(struct netif *netif, struct pbuf *p, struct ip_addr *ipaddr);
/* 底层数据包发送 */
err_t (* linkoutput)(struct netif *netif, struct pbuf *p);
/* 用户字段 */
void *state;
/* 最大允许数据包长度 */
u16_t mtu;
/* 物理MAC地址 */
u8_t hwaddr_len;
u8_t hwaddr[NETIF_MAX_HWADDR_LEN];
u8_t flags; //标志位
char name[2]; //网络接口名字
u8_t num; //网路接口编号
};
关于标志位的定义如下
/* 网络接口标志位 */
#define NETIF_FLAG_UP 0x01U /* 网络接口是否已被上层使能 */
#define NETIF_FLAG_BROADCAST 0x02U /* 网络接口是否支持广播 */
#define NETIF_FLAG_POINTTOPOINT 0x04U /* 网络接口是否支持点到点连接 */
#define NETIF_FLAG_DHCP 0x08U /* 网络接口是否支持DHCP功能 */
#define NETIF_FLAG_LINK_UP 0x10U /* 网络接口链路层是否已经使能 */
#define NETIF_FLAG_ETHARP 0x20U /* 网络接口是否支持ARP功能 */
#define NETIF_FLAG_IGMP 0x40U /* 网络接口是否支持IGMP功能 */
LwIP最终会将所有网络接口组织成一个链表
/* 网络接口链表 */
struct netif *netif_list;
netif_add函数用于向协议栈添加一个网络接口
/* 添加一个网络接口到链表 */
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), err_t (* input)(struct pbuf *p, struct netif *netif))
{
static u8_t netifnum = 0;
/* 清空网路接口成员 */
netif->ip_addr.addr = 0;
netif->netmask.addr = 0;
netif->gw.addr = 0;
netif->flags = 0;
/* 设置用户数据 */
netif->state = state;
/* 设置网络接口编号 */
netif->num = netifnum++;
/* 设置接收回调函数 */
netif->input = input;
/* 设置IP地址、子网掩码、网关地址 */
netif_set_addr(netif, ipaddr, netmask, gw);
/* 调用参数提供的init函数,初始化网卡 */
if (init(netif) != ERR_OK) {
return NULL;
}
/* 将网络接口添加到链表 */
netif->next = netif_list;
netif_list = netif;
return netif;
}
netif_remove从协议栈中移除网络接口
/* 从链表中移除一个网络接口 */
void netif_remove(struct netif * netif)
{
if ( netif == NULL ) return;
/* 网络接口在链表头部 */
if (netif_list == netif) {
/* 删除头节点 */
netif_list = netif->next;
}
else {
struct netif * tmpNetif;
/* 遍历整个链表 */
for (tmpNetif = netif_list; tmpNetif != NULL; tmpNetif = tmpNetif->next) {
/* 删除该节点 */
if (tmpNetif->next == netif) {
tmpNetif->next = netif->next;
break;
}
}
/* 没找到该节点 */
if (tmpNetif == NULL)
return;
}
/* 该网络接口为默认网络接口,默认网络接口置为MULL */
if (netif_default == netif)
netif_set_default(NULL);
}
启用和禁止网络接口
/* 使能网络接口 */
void netif_set_up(struct netif *netif)
{
/* 设置网络接口使能标志位 */
if (!(netif->flags & NETIF_FLAG_UP )) {
netif->flags |= NETIF_FLAG_UP;
/* 广播无回报ARP */
if (netif->flags & NETIF_FLAG_ETHARP) {
etharp_gratuitous(netif);
}
}
}
/* 关闭网络接口 */
void netif_set_down(struct netif *netif)
{
/* 清空网络接口使能标志位 */
if (netif->flags & NETIF_FLAG_UP )
{
netif->flags &= ~NETIF_FLAG_UP;
}
}
/* 网络接口是否使能 */
u8_t netif_is_up(struct netif *netif)
{
return (netif->flags & NETIF_FLAG_UP) ? 1 : 0;
}
改变IP地址、子网掩码、网关地址函数
/* 网络接口改变IP地址 */
void netif_set_ipaddr(struct netif *netif, struct ip_addr *ipaddr)
{
struct tcp_pcb *pcb;
struct tcp_pcb_listen *lpcb;
/* IP发生变化 */
if ((ip_addr_cmp(ipaddr, &(netif->ip_addr))) == 0)
{
/* 遍历active状态TCP控制块链表 */
pcb = tcp_active_pcbs;
while (pcb != NULL) {
/* 查找和网络接口IP相同的TCP控制块 */
if (ip_addr_cmp(&(pcb->local_ip), &(netif->ip_addr))) {
struct tcp_pcb *next = pcb->next;
/* TCP连接复位(RST) */
tcp_abort(pcb);
pcb = next;
} else {
pcb = pcb->next;
}
}
/* 遍历listen状态TCP控制块链表 */
for (lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) {
/* 查找和网络接口IP相同的TCP控制块 */
if ((!(ip_addr_isany(&(lpcb->local_ip)))) && (ip_addr_cmp(&(lpcb->local_ip), &(netif->ip_addr)))) {
/* TCP控制块设置新的本地IP地址 */
ip_addr_set(&(lpcb->local_ip), ipaddr);
}
}
}
/* 网络接口设置新的IP地址 */
ip_addr_set(&(netif->ip_addr), ipaddr);
}
/* 设置IP地址 */
#define ip_addr_set(dest, src) (dest)->addr = \
((src) == NULL? 0:\
(src)->addr)
/* 网络接口改变子网掩码 */
void netif_set_netmask(struct netif *netif, struct ip_addr *netmask)
{
/* 网络接口设置新的子网掩码 */
ip_addr_set(&(netif->netmask), netmask);
}
/* 网络接口改变网关地址 */
void netif_set_gw(struct netif *netif, struct ip_addr *gw)
{
/* 网络接口设置新的网关地址 */
ip_addr_set(&(netif->gw), gw);
}
通过名字查找网络接口
/* 通过名字查找网络接口,name[0-1]为网络接口名字,name[2]为网络接口编号 */
struct netif *netif_find(char *name)
{
struct netif *netif;
u8_t num;
if (name == NULL) {
return NULL;
}
num = name[2] - '0';
/* 遍历网络接口链表 */
for(netif = netif_list; netif != NULL; netif = netif->next) {
/* 匹配网络接口名字 */
if (num == netif->num && name[0] == netif->name[0] && name[1] == netif->name[1]) {
return netif;
}
}
return NULL;
}
LwIP提供了一个默认网络接口
/* 默认网络接口 */
struct netif *netif_default;
/* 设置netif为默认网络接口 */
void netif_set_default(struct netif *netif)
{
netif_default = netif;
}