LwIP之网络接口管理

协议栈内部使用netif的结构体来描述网络接口,先来看一下这个结构体。(一定记住,看代码量庞大的工程时,要抓大放小)

/* 网络接口结构体 */
struct netif {
#if !LWIP_SINGLE_NETIF
  struct netif *next;					//下一个网络接口结构体指针
#endif

#if LWIP_IPV4
  ip_addr_t ip_addr;				//IP地址
  ip_addr_t netmask;				//子网掩码
  ip_addr_t gw;						//网关地址
#endif

#if LWIP_IPV6
  ip_addr_t ip6_addr[LWIP_IPV6_NUM_ADDRESSES];
  u8_t ip6_addr_state[LWIP_IPV6_NUM_ADDRESSES];
#if LWIP_IPV6_ADDRESS_LIFETIMES
  u32_t ip6_addr_valid_life[LWIP_IPV6_NUM_ADDRESSES];
  u32_t ip6_addr_pref_life[LWIP_IPV6_NUM_ADDRESSES];
#endif
#endif

  /* 向IP层输入pbuf数据 */
  netif_input_fn input;

#if LWIP_IPV4
  /* 发送IP数据包,通常指向etharp_output函数 */
  netif_output_fn output;
#endif

  /* 底层发送函数 */
  netif_linkoutput_fn linkoutput;

#if LWIP_IPV6
  netif_output_ip6_fn output_ip6;
#endif

#if LWIP_NETIF_STATUS_CALLBACK
  netif_status_callback_fn status_callback;
#endif

#if LWIP_NETIF_LINK_CALLBACK
  netif_status_callback_fn link_callback;
#endif 

#if LWIP_NETIF_REMOVE_CALLBACK
  netif_status_callback_fn remove_callback;
#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;
#endif 

#if LWIP_CHECKSUM_CTRL_PER_NETIF
  u16_t chksum_flags;
#endif

  u16_t mtu;			//最大数据包长度
 
#if LWIP_IPV6 && LWIP_ND6_ALLOW_RA_UPDATES
  u16_t mtu6;
#endif

  u8_t hwaddr[NETIF_MAX_HWADDR_LEN];	//物理地址
  u8_t hwaddr_len;										//物理地址长度

  u8_t flags;		//标志位
 
  char name[2];	//网络接口名字
  
  u8_t num;			//网络接口编号

#if LWIP_IPV6_AUTOCONFIG
  u8_t ip6_autoconfig_enabled;
#endif

#if LWIP_IPV6_SEND_ROUTER_SOLICIT
  u8_t rs_count;
#endif

#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;
#endif

#if LWIP_IPV6 && LWIP_IPV6_MLD
  netif_mld_mac_filter_fn mld_mac_filter;
#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_init,

主要内容是初始化回环接口。抓大放小,不分析回环接口,不要太纠结,主要关注网络接口初始化的过程。

/* 网络接口初始化 */
void netif_init(void)
{
#if LWIP_HAVE_LOOPIF

#if LWIP_IPV4
#define LOOPIF_ADDRINIT &loop_ipaddr, &loop_netmask, &loop_gw,
  ip4_addr_t loop_ipaddr, loop_netmask, loop_gw;
  IP4_ADDR(&loop_gw, 127, 0, 0, 1);
  IP4_ADDR(&loop_ipaddr, 127, 0, 0, 1);
  IP4_ADDR(&loop_netmask, 255, 0, 0, 0);
#else
#define LOOPIF_ADDRINIT
#endif

#if NO_SYS
  netif_add(&loop_netif, LOOPIF_ADDRINIT NULL, netif_loopif_init, ip_input);
#else
  netif_add(&loop_netif, LOOPIF_ADDRINIT NULL, netif_loopif_init, tcpip_input);
#endif

#if LWIP_IPV6
  IP_ADDR6_HOST(loop_netif.ip6_addr, 0, 0, 0, 0x00000001UL);
  loop_netif.ip6_addr_state[0] = IP6_ADDR_VALID;
#endif

  netif_set_link_up(&loop_netif);
  netif_set_up(&loop_netif);

#endif
}

可以分析出网络接口初始化的步骤,netif_add -> netif_set_link_up -> netif_set_up

 

netif_add函数用于向协议栈添加一个网络接口

/* 添加网络接口 */
struct netif *netif_add(struct netif *netif,
#if LWIP_IPV4
          const ip4_addr_t *ipaddr, const ip4_addr_t *netmask, const ip4_addr_t *gw,
#endif
          void *state, netif_init_fn init, netif_input_fn input)
{
#if LWIP_IPV6
  s8_t i;
#endif

  LWIP_ASSERT_CORE_LOCKED();

#if LWIP_SINGLE_NETIF
  if (netif_default != NULL) 
  {
    LWIP_ASSERT("single netif already set", 0);
    return NULL;
  }
#endif

  LWIP_ERROR("netif_add: invalid netif", netif != NULL, return NULL);
  LWIP_ERROR("netif_add: No init function given", init != NULL, return NULL);

#if LWIP_IPV4
  if (ipaddr == NULL) 
  {
    ipaddr = ip_2_ip4(IP4_ADDR_ANY);
  }
  if (netmask == NULL) {
    netmask = ip_2_ip4(IP4_ADDR_ANY);
  }
  if (gw == NULL) {
    gw = ip_2_ip4(IP4_ADDR_ANY);
  }

  /* 清空新网络接口的IP地址、子网掩码、网关地址 */
  ip_addr_set_zero_ip4(&netif->ip_addr);
  ip_addr_set_zero_ip4(&netif->netmask);
  ip_addr_set_zero_ip4(&netif->gw);

  /* 初始化IP数据包输出函数,空函数 */
  netif->output = netif_null_output_ip4;

#endif

#if LWIP_IPV6
  for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) 
  {
    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->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;
  /* 设置网络接口编号 */
  netif->num = netif_num;
  /* 设置IP层数据输入函数指针 */
  netif->input = input;

  NETIF_RESET_HINTS(netif);
#if ENABLE_LOOPBACK && LWIP_LOOPBACK_MAX_PBUFS
  netif->loop_cnt_current = 0;
#endif

#if LWIP_IPV4
  /* 设置IP地址、子网掩码、网关地址 */
  netif_set_addr(netif, ipaddr, netmask, gw);
#endif

  /* 初始化用户新加入的网络接口 */
  if (init(netif) != ERR_OK) 
  {
    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;

      /* 遍历网络接口链表 */
      for (netif2 = netif_list; netif2 != NULL; netif2 = netif2->next) 
      {
        LWIP_ASSERT("netif already added", netif2 != netif);

        /* 网络接口数量 */
        num_netifs++;
        
        LWIP_ASSERT("too many netifs, max. supported number is 255", num_netifs <= 255);

        /* 网络接口编号不能相同 */
        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;
  netif_list = netif;
#endif

  mib2_netif_added(netif);

#if LWIP_IGMP
  if (netif->flags & NETIF_FLAG_IGMP) 
  {
    igmp_start(netif);
  }
#endif

  LWIP_DEBUGF(NETIF_DEBUG, ("netif: added interface %c%c IP", netif->name[0], netif->name[1]));

#if LWIP_IPV4
  LWIP_DEBUGF(NETIF_DEBUG, (" addr "));
  ip4_addr_debug_print(NETIF_DEBUG, ipaddr);
  LWIP_DEBUGF(NETIF_DEBUG, (" netmask "));
  ip4_addr_debug_print(NETIF_DEBUG, netmask);
  LWIP_DEBUGF(NETIF_DEBUG, (" gw "));
  ip4_addr_debug_print(NETIF_DEBUG, gw);
#endif

  LWIP_DEBUGF(NETIF_DEBUG, ("\n"));

  netif_invoke_ext_callback(netif, LWIP_NSC_NETIF_ADDED, NULL);

  return netif;
}

netif_remove从协议栈中移除网络接口

/* 移除网络接口 */
void netif_remove(struct netif *netif)
{
#if LWIP_IPV6
  int i;
#endif

  LWIP_ASSERT_CORE_LOCKED();

  if (netif == NULL) 
  {
    return;
  }

  netif_invoke_ext_callback(netif, LWIP_NSC_NETIF_REMOVED, NULL);

#if LWIP_IPV4
  /* IP地址改变为空 */
  if (!ip4_addr_isany_val(*netif_ip4_addr(netif)))
  {
    netif_do_ip_addr_changed(netif_ip_addr4(netif), NULL);
  }

#if LWIP_IGMP
  if (netif->flags & NETIF_FLAG_IGMP) 
  {
    igmp_stop(netif);
  }
#endif

#endif

#if LWIP_IPV6
  for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) 
  {
    if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i))) 
    {
      netif_do_ip_addr_changed(netif_ip_addr6(netif, i), NULL);
    }
  }
#if LWIP_IPV6_MLD
  mld6_stop(netif);
#endif

#endif

  /* 网络接口已经使能 */
  if (netif_is_up(netif)) 
  {
    /* 关闭网络接口 */
    netif_set_down(netif);
  }

  mib2_remove_ip4(netif);

  /* 该网络接口是默认网络接口 */
  if (netif_default == netif) 
  {
    /* 默认网络接口设置为空 */
    netif_set_default(NULL);
  }

#if !LWIP_SINGLE_NETIF
  /* 将网络接口从链表中移除 */
  if (netif_list == netif) 
  {
    netif_list = netif->next;
  } 
  else 
  {
    struct netif *tmp_netif;
    NETIF_FOREACH(tmp_netif) 
    {
      if (tmp_netif->next == netif) 
      {
        tmp_netif->next = netif->next;
        break;
      }
    }
    if (tmp_netif == NULL) 
    {
      return;
    }
  }
#endif

  mib2_netif_removed(netif);
  
#if LWIP_NETIF_REMOVE_CALLBACK
  if (netif->remove_callback) 
  {
    netif->remove_callback(netif);
  }
#endif

  LWIP_DEBUGF( NETIF_DEBUG, ("netif_remove: removed netif\n") );
}

netif_add_noaddr函数。和netif_add功能类似,但是不设定IPV4地址。

/* 不设定地址添加网络接口 */
struct netif *netif_add_noaddr(struct netif *netif, void *state, netif_init_fn init, netif_input_fn input)
{
  return netif_add(netif,
#if LWIP_IPV4
                   NULL, NULL, NULL,
#endif
                   state, init, input);
}

 

下面看一些设置/获取网络接口IPV4地址的API

/* 设置网络接口IP地址、子网掩码、网关地址 */
void netif_set_addr(struct netif *netif, const ip4_addr_t *ipaddr, const ip4_addr_t *netmask, const ip4_addr_t *gw);
/* 设置网络接口IP地址 */
void netif_set_ipaddr(struct netif *netif, const ip4_addr_t *ipaddr);
/* 设置网络接口子网掩码 */
void netif_set_netmask(struct netif *netif, const ip4_addr_t *netmask);
/* 设置网络接口网关地址 */
void netif_set_gw(struct netif *netif, const ip4_addr_t *gw);
/* 获取网络接口IP地址 */
#define netif_ip4_addr(netif)    ((const ip4_addr_t*)ip_2_ip4(&((netif)->ip_addr)))
#define netif_ip_addr4(netif)    ((const ip_addr_t*)&((netif)->ip_addr))
/* 获取网络接口子网掩码 */
#define netif_ip4_netmask(netif) ((const ip4_addr_t*)ip_2_ip4(&((netif)->netmask)))
#define netif_ip_netmask4(netif) ((const ip_addr_t*)&((netif)->netmask))
/* 获取网络接口网关地址 */
#define netif_ip4_gw(netif)      ((const ip4_addr_t*)ip_2_ip4(&((netif)->gw)))
#define netif_ip_gw4(netif)      ((const ip_addr_t*)&((netif)->gw))

 

再看一下标志位相关的API

#define NETIF_FLAG_UP           0x01U        //网络接口启用
#define NETIF_FLAG_BROADCAST    0x02U        //网络接口支持广播
#define NETIF_FLAG_LINK_UP      0x04U        //网络接口底层链路启用
#define NETIF_FLAG_ETHARP       0x08U        //网络接口启用ARP
#define NETIF_FLAG_ETHERNET     0x10U        //网络接口是以太网设备
#define NETIF_FLAG_IGMP         0x20U        //网络接口启用IGMP
#define NETIF_FLAG_MLD6         0x40U        //网络接口MLD6(IPV6多播侦听)

/* 设置网络接口标志位 */
#define netif_set_flags(netif, set_flags)     do { (netif)->flags = (u8_t)((netif)->flags | (set_flags)); } while(0)
/* 清除网络接口标志位 */
#define netif_clear_flags(netif, clr_flags)   do { (netif)->flags = (u8_t)((netif)->flags & (u8_t)(~(clr_flags) & 0xff)); } while(0)
/* 判断网络接口标志位 */
#define netif_is_flag_set(nefif, flag)        (((netif)->flags & (flag)) != 0)
/* 判断网络接口是否使能 */
#define netif_is_up(netif) (((netif)->flags & NETIF_FLAG_UP) ? (u8_t)1 : (u8_t)0)

 

启用和禁止网络接口

/* 启用网络接口 */
void netif_set_up(struct netif *netif)
{
  LWIP_ASSERT_CORE_LOCKED();

  LWIP_ERROR("netif_set_up: invalid netif", netif != NULL, return);

  /* 还未启用网络接口 */
  if (!(netif->flags & NETIF_FLAG_UP)) 
  {
    /* 启用网络接口 */
    netif_set_flags(netif, NETIF_FLAG_UP);

    MIB2_COPY_SYSUPTIME_TO(&netif->ts);

    NETIF_STATUS_CALLBACK(netif);

#if LWIP_NETIF_EXT_STATUS_CALLBACK
    {
      netif_ext_callback_args_t args;
      args.status_changed.state = 1;
      netif_invoke_ext_callback(netif, LWIP_NSC_STATUS_CHANGED, &args);
    }
#endif

    /* 在启用网络接口、启用底层接口、改变IP地址时,向协议栈发送ARP/IGMP/MLD/RS事件 */
    netif_issue_reports(netif, NETIF_REPORT_TYPE_IPV4 | NETIF_REPORT_TYPE_IPV6);
#if LWIP_IPV6
    nd6_restart_netif(netif);
#endif
  }
}
/* 禁止网络接口 */
void netif_set_down(struct netif *netif)
{
  LWIP_ASSERT_CORE_LOCKED();

  LWIP_ERROR("netif_set_down: invalid netif", netif != NULL, return);

  /* 启用了网络接口 */
  if (netif->flags & NETIF_FLAG_UP) 
  {
#if LWIP_NETIF_EXT_STATUS_CALLBACK
    {
      netif_ext_callback_args_t args;
      args.status_changed.state = 0;
      netif_invoke_ext_callback(netif, LWIP_NSC_STATUS_CHANGED, &args);
    }
#endif

    /* 禁止网络接口 */
    netif_clear_flags(netif, NETIF_FLAG_UP);
    
    MIB2_COPY_SYSUPTIME_TO(&netif->ts);

#if LWIP_IPV4 && LWIP_ARP
    /* 已启用ARP */
    if (netif->flags & NETIF_FLAG_ETHARP) 
    {
      /* 清除网络接口ARP表 */
      etharp_cleanup_netif(netif);
    }
#endif

#if LWIP_IPV6
    nd6_cleanup_netif(netif);
#endif

    NETIF_STATUS_CALLBACK(netif);
  }
}
/* 启用网络接口底层链路 */
void netif_set_link_up(struct netif *netif)
{
  LWIP_ASSERT_CORE_LOCKED();

  LWIP_ERROR("netif_set_link_up: invalid netif", netif != NULL, return);

  /* 网络接口底层链路未启用 */
  if (!(netif->flags & NETIF_FLAG_LINK_UP)) 
  {
    /* 启用网络接口底层链路 */
    netif_set_flags(netif, NETIF_FLAG_LINK_UP);

#if LWIP_DHCP
    dhcp_network_changed(netif);
#endif

#if LWIP_AUTOIP
    autoip_network_changed(netif);
#endif

    /* 在启用网络接口、启用底层接口、改变IP地址时,向协议栈发送ARP/IGMP/MLD/RS事件 */
    netif_issue_reports(netif, NETIF_REPORT_TYPE_IPV4 | NETIF_REPORT_TYPE_IPV6);

#if LWIP_IPV6
    nd6_restart_netif(netif);
#endif

    NETIF_LINK_CALLBACK(netif);

#if LWIP_NETIF_EXT_STATUS_CALLBACK
    {
      netif_ext_callback_args_t args;
      args.link_changed.state = 1;
      netif_invoke_ext_callback(netif, LWIP_NSC_LINK_CHANGED, &args);
    }
#endif
  }
}
/* 禁用网络接口底层链路 */
void netif_set_link_down(struct netif *netif)
{
  LWIP_ASSERT_CORE_LOCKED();

  LWIP_ERROR("netif_set_link_down: invalid netif", netif != NULL, return);

  if (netif->flags & NETIF_FLAG_LINK_UP) 
  {
    netif_clear_flags(netif, NETIF_FLAG_LINK_UP);
    NETIF_LINK_CALLBACK(netif);
#if LWIP_NETIF_EXT_STATUS_CALLBACK
    {
      netif_ext_callback_args_t args;
      args.link_changed.state = 0;
      netif_invoke_ext_callback(netif, LWIP_NSC_LINK_CHANGED, &args);
    }
#endif
  }
}

 

网络接口输入函数

/* 网络接口输入函数 */
err_t netif_input(struct pbuf *p, struct netif *inp)
{
  LWIP_ASSERT_CORE_LOCKED();

  LWIP_ASSERT("netif_input: invalid pbuf", p != NULL);
  LWIP_ASSERT("netif_input: invalid netif", inp != NULL);

#if LWIP_ETHERNET
  if (inp->flags & (NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET)) 
  {
    return ethernet_input(p, inp);
  } 
  else
#endif
    return ip_input(p, inp);
}

 

你可能感兴趣的:(LwIP)