您的位置:首页 > 其它

LWIP ethernetif.c分析

2013-11-16 21:44 399 查看
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字节

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: