LwIP之网络接口管理

协议栈内部使用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;
}
发布了208 篇原创文章 · 获赞 90 · 访问量 25万+

猜你喜欢

转载自blog.csdn.net/lushoumin/article/details/101158939