LwIP协议栈(2):网络接口

  在LwIP中,物理网络硬件接口结构保存在一个全局链表中,它们通过结构体中的 next 指针连接。

struct netif {
  /// pointer to next in linked list */
  struct netif *next;

  /// IP address configuration in network byte order */
  ip_addr_t ip_addr; //IP地址
  ip_addr_t netmask; //子网掩码
  ip_addr_t gw;      //网关地址


  netif_input_fn input; //设备驱动调用该函数传递一个包给TCP/IP协议栈

  //IP模块调用该函数传递一个包给网卡,output 函数的第三个参数 ipaddr 是应该接收实际的链路层帧的主机的 IP 地址。
  //它不必与 IP 信息包的目的地址相同。特别地,当要发送 IP 信息包到一个并不在本地网络里的主机上时,链路层帧会被发送到网络里的一个路由器上。
  //在这种情况下给output函数的IP地址将是这个路由器的地址。
  netif_output_fn output; 

  netif_linkoutput_fn linkoutput; //ARP模块调用该函数传递一个包给网卡

  void *state; //由设备驱动设置,指向设备状态信息
#if LWIP_DHCP
  /// the DHCP client state information for this netif */
  struct dhcp *dhcp;
#endif // LWIP_DHCP */
#if LWIP_AUTOIP
  /// the AutoIP client state information for this netif */
  struct autoip *autoip;
#endif
#if LWIP_NETIF_HOSTNAME
  // the hostname for this netif, NULL is a valid value */
  char*  hostname;
#endif // LWIP_NETIF_HOSTNAME */

  u16_t mtu; //一次传送的最大字节数,以太网一般为1500

  u8_t hwaddr_len; //物理地址长度,一般是以太网MAC地址长度,6字节

  u8_t hwaddr[NETIF_MAX_HWADDR_LEN]; //物理地址,一般是以太网MAC地址
  /// flags (see NETIF_FLAG_ above) */
  u8_t flags; //使能标志符,比如设置NETIF_FLAG_LINK_UP,接收到数据包才会向上传
  /// descriptive abbreviation */
  char name[2]; //设备驱动类型
  /// number of this interface */
  u8_t num;

    // List of packets to be queued for ourselves. */
  struct pbuf *loop_first; //环回,指向发给自己数据包的第一个pbuf
  struct pbuf *loop_last;  //环回,指向发给自己数据包的最后一个pbuf
};
/*
 * Add a network interface to the list of lwIP netifs.
 *
 * @param netif a pre-allocated netif structure
 * @param ipaddr IP address for the new netif
 * @param netmask network mask for the new netif
 * @param gw default gateway IP address for the new netif
 * @param state opaque data passed to the new netif
 * @param init callback function that initializes the interface
 * @param input callback function that is called to pass
 * ingress packets up in the protocol layer stack.
 *
 * @return netif, or NULL if failed.
 */
struct netif *
netif_add(struct netif *netif, ip_addr_t *ipaddr, ip_addr_t *netmask,
  ip_addr_t *gw, void *state, netif_init_fn init, netif_input_fn input)
{
  static u8_t netifnum = 0;

  // reset new interface configuration state */
  ip_addr_set_zero(&netif->ip_addr);
  ip_addr_set_zero(&netif->netmask);
  ip_addr_set_zero(&netif->gw);
  netif->flags = 0;

  // remember netif specific state information data */
  netif->state = state;
  netif->num = netifnum++;
  netif->input = input;

  netif_set_addr(netif, ipaddr, netmask, gw);

  // call user specified initialization function for netif */
  if (init(netif) != ERR_OK) { //用户自定义初始化函数
    return NULL;
  }

  // add this netif to the list */
  netif->next = netif_list;
  netif_list = netif;
  snmp_inc_iflist();

  return netif;
}

//用户自定义初始化函数
err_t ethernetif_init(struct netif *netif) 
{
  netif->name[0] = IFNAME0;   //比如蓝牙设备(bluetooth)的网络接口可以是bt,随便啦
  netif->name[1] = IFNAME1; 
  netif->output = etharp_output;  //IP模块发送数据包函数
  netif->linkoutput = low_level_output; // //ARP模块发送数据包函数
  low_level_init(netif); //底层硬件初始化函数
  return ERR_OK;
}

static void low_level_init(struct netif *netif)
{
  netif->hwaddr_len = ETHARP_HWADDR_LEN; //设置MAC地址长度

  netif->hwaddr[0] = 'F'; //设置网卡MAC地址
  netif->hwaddr[1] = 'O'; 
  netif->hwaddr[2] = 'R'; 
  netif->hwaddr[3] = 'E';
  netif->hwaddr[4] = 'S';
  netif->hwaddr[5] = 'T';

  netif->mtu = 1500; //最大允许传输单元

  //允许该网卡的广播和ARP功能,并且该网卡允许有硬件链路连接
  netif->flags = NETIF_FLAG_BROADCAST | \
  NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP;

  E1280_init(netif->hwaddr); //具体网卡初始化函数
}

/*
 * Send an IP packet to be received on the same netif (loopif-like).
 * The pbuf is simply copied and handed back to netif->input.
 * In multithreaded mode, this is done directly since netif->input must put
 * the packet on a queue.
 * In callback mode, the packet is put on an internal queue and is fed to
 * netif->input by netif_poll().
 *
 * @param netif the lwip network interface structure
 * @param p the (IP) packet to 'send'
 * @param ipaddr the ip address to send the packet to (not used)
 * @return ERR_OK if the packet has been sent
 *         ERR_MEM if the pbuf used to copy the packet couldn't be allocated
 */
err_t
netif_loop_output(struct netif *netif, struct pbuf *p,
       ip_addr_t *ipaddr)
{
  struct pbuf *r;
  err_t err;
  struct pbuf *last;


  SYS_ARCH_DECL_PROTECT(lev);
  LWIP_UNUSED_ARG(ipaddr);

  // Allocate a new pbuf */
  r = pbuf_alloc(PBUF_LINK, p->tot_len, PBUF_RAM);
  if (r == NULL) {
    return ERR_MEM;
  }

  // Copy the whole pbuf queue p into the single pbuf r */
  if ((err = pbuf_copy(r, p)) != ERR_OK) { //拷贝要发送的数据到r中
    pbuf_free(r);
    return err;
  }

  // Put the packet on a linked list which gets emptied through calling
     netif_poll(). */ 
  //可以调用netif_poll函数将当前loop链表上所有数据提交给IP层

  // let last point to the last pbuf in chain r */
  for (last = r; last->next != NULL; last = last->next); 

  SYS_ARCH_PROTECT(lev);
  if(netif->loop_first != NULL) { //原来的loop中还有数据
    netif->loop_last->next = r;   //接到原来数据的后面
    netif->loop_last = last;
  } else {
    netif->loop_first = r;
    netif->loop_last = last;
  }
  SYS_ARCH_UNPROTECT(lev);


  return ERR_OK;
}

/*
 * This function should be called when a packet is ready to be read
 * from the interface. It uses the function low_level_input() that
 * should handle the actual reception of bytes from the network
 * interface. Then the type of the received packet is determined and
 * the appropriate input function is called.
 *
 * @param netif the lwip network interface structure for this ethernetif
 */
static void
ethernetif_input(struct netif *netif)
{
  struct ethernetif *ethernetif;
  struct eth_hdr *ethhdr;
  struct pbuf *p;

  ethernetif = netif->state;

  // move received packet into a new pbuf */
  p = low_level_input(netif);
  // no packet could be read, silently ignore this */
  if (p == NULL) return;
  // points to packet payload, which starts with an Ethernet header */
  ethhdr = p->payload;

  switch (htons(ethhdr->type)) {
  // IP or ARP packet? */
  case ETHTYPE_IP:
  case ETHTYPE_ARP:
#if PPPOE_SUPPORT
  // PPPoE packet? */
  case ETHTYPE_PPPOEDISC:
  case ETHTYPE_PPPOE:
#endif // PPPOE_SUPPORT */
    // full packet send to tcpip_thread to process */
    if (netif->input(p, netif)!=ERR_OK)
     { LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n"));
       pbuf_free(p);
       p = NULL;
     }
    break;

  default:
    pbuf_free(p);
    p = NULL;
    break;
  }
}

/*
 * This function should be called when a packet is ready to be read
 * from the interface. It uses the function low_level_input() that
 * should handle the actual reception of bytes from the network
 * interface. Then the type of the received packet is determined and
 * the appropriate input function is called.
 *
 * @param netif the lwip network interface structure for this ethernetif
 */
static void
ethernetif_input(struct netif *netif)
{
  struct ethernetif *ethernetif;
  struct eth_hdr *ethhdr;
  struct pbuf *p;

  ethernetif = netif->state;

  // move received packet into a new pbuf */
  p = low_level_input(netif); //拷贝接收到的数据到一个新的pbuf
  // no packet could be read, silently ignore this */
  if (p == NULL) return;
  // points to packet payload, which starts with an Ethernet header */
  ethhdr = p->payload;

  switch (htons(ethhdr->type)) {
  // IP or ARP packet? */
  case ETHTYPE_IP:
  case ETHTYPE_ARP:
    // full packet send to tcpip_thread to process */
    if (netif->input(p, netif)!=ERR_OK) //调用上层(IP/ARP)函数进行处理
     { 
       pbuf_free(p);
       p = NULL;
     }
    break;

  default:
    pbuf_free(p);
    p = NULL;
    break;
  }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
INTRODUCTION lwIP is a small independent implementation of the TCP/IP protocol suite. The focus of the lwIP TCP/IP implementation is to reduce the RAM usage while still having a full scale TCP. This making lwIP suitable for use in embedded systems with tens of kilobytes of free RAM and room for around 40 kilobytes of code ROM. lwIP was originally developed by Adam Dunkels at the Computer and Networks Architectures (CNA) lab at the Swedish Institute of Computer Science (SICS) and is now developed and maintained by a worldwide network of developers. FEATURES * IP (Internet Protocol, IPv4 and IPv6) including packet forwarding over multiple network interfaces * ICMP (Internet Control Message Protocol) for network maintenance and debugging * IGMP (Internet Group Management Protocol) for multicast traffic management * MLD (Multicast listener discovery for IPv6). Aims to be compliant with RFC 2710. No support for MLDv2 * ND (Neighbor discovery and stateless address autoconfiguration for IPv6). Aims to be compliant with RFC 4861 (Neighbor discovery) and RFC 4862 (Address autoconfiguration) * DHCP, AutoIP/APIPA (Zeroconf), ACD (Address Conflict Detection) and (stateless) DHCPv6 * UDP (User Datagram Protocol) including experimental UDP-lite extensions * TCP (Transmission Control Protocol) with congestion control, RTT estimation fast recovery/fast retransmit and sending SACKs * raw/native API for enhanced performance * Optional Berkeley-like socket API * TLS: optional layered TCP ("altcp") for nearly transparent TLS for any TCP-based protocol (ported to mbedTLS) (see changelog for more info) * PPPoS and PPPoE (Point-to-point protocol over Serial/Ethernet) * DNS (Domain name resolver incl. mDNS) * 6LoWPAN (via IEEE 802.15.4, BLE or ZEP) APPLICATIONS * HTTP server with SSI and CGI (HTTPS via altcp) * SNMPv2c agent with MIB compiler (Simple Network Management Protocol), v3 via altcp * SNTP (Simple network time protocol) * NetBIOS name service responder * MDNS (Multicast DNS) responder * iPerf server implementation * MQTT client (TLS support via altcp) LICENSE lwIP is freely available under a BSD license. DEVELOPMENT lwIP has grown into an excellent TCP/IP stack for embedded devices, and developers using the stack often submit bug fixes, improvements, and additions to the stack to further increase its usefulness. Development of lwIP is hosted on Savannah, a central point for software development, maintenance and distribution. Everyone can help improve lwIP by use of Savannah's interface, Git and the mailing list. A core team of developers will commit changes to the Git source tree. The lwIP TCP/IP stack is maintained in the 'lwip' Git module and contributions (such as platform ports) are in the 'contrib' Git module. See doc/savannah.txt for details on Git server access for users and developers. The current Git trees are web-browsable: http://git.savannah.gnu.org/cgit/lwip.git http://git.savannah.gnu.org/cgit/lwip/lwip-contrib.git Submit patches and bugs via the lwIP project page: http://savannah.nongnu.org/projects/lwip/ Continuous integration builds (GCC, clang): https://travis-ci.org/lwip-tcpip/lwip DOCUMENTATION Self documentation of the source code is regularly extracted from the current Git sources and is available from this web page: http://www.nongnu.org/lwip/ Also, there are mailing lists you can subscribe at http://savannah.nongnu.org/mail/?group=lwip plus searchable archives: http://lists.nongnu.org/archive/html/lwip-users/ http://lists.nongnu.org/archive/html/lwip-devel/ There is a wiki about lwIP at http://lwip.wikia.com/wiki/LwIP_Wiki You might get questions answered there, but unfortunately, it is not as well maintained as it should be. lwIP was originally written by Adam Dunkels: http://dunkels.com/adam/ Reading Adam's papers, the files in docs/, browsing the source code documentation and browsing the mailing list archives is a good way to become familiar with the design of lwIP. Adam Dunkels Leon Woestenberg

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

One2zeror

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值