博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
LWIP ethernetif.c分析
阅读量:4110 次
发布时间:2019-05-25

本文共 3766 字,大约阅读时间需要 12 分钟。

1、ethernetif_init()初始化底层接口
err_t

ethernetif_init(struct netif *netif)

{

  struct ethernetif *ethernetif;
  ethernetif 是一个结构体,用来描述底层硬件设备,该结构体唯一不可或缺的是MAC地址,它是LWIP用于相应ARP查询的核心数据。其他如果没有特殊需要,可以不添加其他成员数据。

    

  ethernetif = mem_malloc(sizeof(struct ethernetif));

  if (ethernetif == NULL) {

    LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_init: out of memory\n"));

    return ERR_MEM;

  }
#if LWIP_NETIF_HOSTNAME

  /* Initialize interface hostname */

  netif->hostname = "lwip";

#endif /* LWIP_NETIF_HOSTNAME */
  /*

   * Initialize the snmp variables and counters inside the struct netif.

   * The last argument should be replaced with your link speed, in units

   * of bits per second.

   */

  NETIF_INIT_SNMP(netif, snmp_ifType_ethernet_csmacd, ???);
  netif->state = ethernetif;

  netif->name[0] = IFNAME0;

  netif->name[1] = IFNAME1;

  /* We directly use etharp_output() here to save a function call.

   * You can instead declare your own function an call etharp_output()

   * from it if you have to do some checks before sending (e.g. if link

   * is available...) */

  netif->output = ethernetif_output;
向LwIP注册发送函数。注意,这个函数并不是真正的发送函数,它是通过调用下一句完成信息包发送的。

  netif->linkoutput = low_level_output;

向LwIP注册链路层发送函数,该函数完成实际的信息包发送。这个函数需要结合实际的硬件情况亲自编写实现,LwIP仅提供了一个参考结构。

  ethernetif->ethaddr = (struct eth_addr *)&(netif->hwaddr[0]);

ethernetif->ethaddr指针指向netif中保存的网卡MAC地址 。

  /* initialize the hardware */

  low_level_init(netif);
网卡初始化,建立稳定的物理连接链路并建立接收线程(见图5.4.1中的第(3)、(4)步)。这个函数直接与底层硬件打交道,LwIP仅能为其提供一个参考结构,需要我们结合实际硬件情况重新设计实现。
  return ERR_OK;

}
 
2、low_level_output()――链路层发送函数
static err_t

low_level_output(struct netif *netif, struct pbuf *p)

{

  struct ethernetif *ethernetif = netif->state;

  struct pbuf *q;
  initiate transfer();

  

#if ETH_PAD_SIZE

  pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */

#endif
  for(q = p; q != NULL; q = q->next) {

    /* Send the data from the pbuf to the interface, one pbuf at a

       time. The size of the data in each pbuf is kept in the ->len

       variable. */

    send data from(q->payload, q->len);

  }
  signal that packet should be sent();
#if ETH_PAD_SIZE

  pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */

#endif

  发送数据包

  LINK_STATS_INC(link.xmit);
  return ERR_OK;

}
3、low_level_init()――网卡初始化函数
static void

low_level_init(struct netif *netif)

{

  struct ethernetif *ethernetif = netif->state;

  

  /* set MAC hardware address length */

  netif->hwaddr_len = ETHARP_HWADDR_LEN;
设置网卡MAC地址的长度。这个长度由LwIP定义的宏NETIF_MAX_HWADDR_LEN指定,长度值为6,单位为字节
  /* set MAC hardware address */

  netif->hwaddr[0] = ;

  ...

  netif->hwaddr[5] = ;
设定MAC地址
  /* maximum transfer unit */

  netif->mtu = 1500;

 设定mtu值 

  /* device capabilities */

  /* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */

  netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP;
允许处理网络广播通信,ARP。

 

  /* Do whatever else is needed to initialize interface. */  

}
4、ethernetif_input()――实现接收线程
static void

ethernetif_input(struct netif *netif)

{

  struct ethernetif *ethernetif;

  struct eth_hdr *ethhdr;

  struct pbuf *p;
  ethernetif = netif->state;
获取当前MAC地址
  /* move received packet into a new pbuf */

  p = low_level_input(netif);
读取EMAC的接收缓冲区

  /* 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;

  }
根据以太网帧头携带的上层协议类型值传递数据。以太网帧格式定义:
目的MAC地址 源MAC地址           类型/长度                  数据                     校验
   6字节                  6字节               2字节                   46-1500字节              4字节
                                                 ip:0x0800
                                                ARP:0x0806
最大帧长1518字节 最小字节64字节

}

转载地址:http://raosi.baihongyu.com/

你可能感兴趣的文章
Git:Git分支概念、Pycharm中使用使用分支
查看>>
Python:线程同步,Barrier屏障
查看>>
Python:信号量semaphore
查看>>
Python:多进程multiprocessing,多进程和多线程的应用
查看>>
Python:concurrent异步并行任务编程模块、 线程池、进程池、上下文管理
查看>>
JSONArray
查看>>
HTTP 请求中的Header 参数
查看>>
PostgreSQL远程连接,发生的SSL错误
查看>>
PostgreSQL 创建用户
查看>>
mysql 定时任务
查看>>
浅谈sql中的in与not in,exists与not exists的区别以及性能分析
查看>>
Tomcat注册为Windows服务
查看>>
pg_stat_statements windows 安装
查看>>
启用mqtt插件
查看>>
行转列
查看>>
erlang,rabbitMQ,mqtt安装配置 1
查看>>
rabbitmq 创建用户和权限
查看>>
数据库权限2
查看>>
linux 部署jar的常用命令
查看>>
安装数据源的驱动程序-postgresql
查看>>