zoukankan      html  css  js  c++  java
  • 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 ")); 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; } }

  • 相关阅读:
    【springcloud alibaba】配置中心之nacos
    【springcloud alibaba】注册中心之nacos
    LeetCode计数质数Swift
    LeetCode移除链表元素Swift
    LeetCode删除重复的电子邮箱SQL
    LeetCode汉明距离Swift
    LeetCode两整数之和Swift
    LeetCode从不订购的客户SQL
    LeetCode超过经理收入的员工SQL
    LeetCode组合两个表SQL
  • 原文地址:https://www.cnblogs.com/llguanli/p/8670406.html
Copyright © 2011-2022 走看看