网络数据包是通过实际的网络接口接收和发送的。
每一种网口都可以用一个netif网络接口结构体定义,一个硬件,可能有多个不同类型的网络接口,就需要定义多个netif变量,映射到硬件底层。
每一个网口都可以用netif结构体定义,各个元素:
1.next指针:指向下一个netif类型结构体,用于多网口设备。
2.ip_addr, netmask ,gw分别为本硬件设备网络接口IP地址,子网掩码和网关。
!!!!!!
回调函数input,传入数据p指针和netif结构体,当网络接口接到一个packet时,调用该函数去接收数据。
回调函数output,传入数据p指针,netif结构体和ip地址,网络接口要发送一个数据时,调用该函数。
回调函数linkoutput,同输出数据,用于ARP协议。何为ARP?
地址解析协议,即ARP(Address Resolution Protocol),是根据IP地址获取物理地址的一个TCP/IP协议。主机发送信息时将包含目标IP地址的ARP请求广播到网络上的所有主机,并接收返回消息,以此确定目标的物理地址;收到返回消息后将该IP地址和物理地址存入本机ARP缓存中并保留一定时间,下次请求时直接查询ARP缓存以节约资源。
3.state可以记录各种关心的网卡信息和状态(void*)
定义好网络接口,接着就是对网络接口初始化,尤其是上面的几个变量属性:
初始化:
初始化函数:struct netif *xemac_add函数根据mac地址类型的不同,对netif网络接口初始化不同的输出函数。
抽取其中一个case:
case xemac_type_xps_emaclite:
#ifdef XLWIP_CONFIG_INCLUDE_EMACLITE
return netif_add(netif, ipaddr, netmask, gw,
(void*)mac_baseaddr,
xemacliteif_init,
#if NO_SYS
ethernet_input
#else
tcpip_input
#endif
);
在netif函数里有:定义init==xemacliteif_init
/* call user specified initialization function for netif */
if (init(netif) != ERR_OK) {
return NULL;
}
设置netif——>input = tcpip_input;
output属性与linkoutput属性,初始化xemacliteif_init(netif)(附录2为netif_add函数)
设置netif——>output = ethernet_output
设置netif——>linkoutput = low_level_output
err_t
xemacliteif_init(struct netif *netif)
{
#if LWIP_SNMP
/* ifType ethernetCsmacd(6) @see RFC1213 */
netif->link_type = 6;
/* your link speed here */
netif->link_speed = ;
netif->ts = 0;
netif->ifinoctets = 0;
netif->ifinucastpkts = 0;
netif->ifinnucastpkts = 0;
netif->ifindiscards = 0;
netif->ifoutoctets = 0;
netif->ifoutucastpkts = 0;
netif->ifoutnucastpkts = 0;
netif->ifoutdiscards = 0;
#endif
netif->name[0] = IFNAME0;
netif->name[1] = IFNAME1;
netif->output = xemacliteif_output;
netif->linkoutput = low_level_output;
low_level_init(netif);
#if !NO_SYS
sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL);
#endif
return ERR_OK;
}
至此重要的信息都定义结束。
这里主要是物理层数据接收以及发送。
接收数据:
ethernetif_input(void * arg)//参数为netif * current_netif结构体,上面已初始化好。
这里读取网络芯片的数据可有两种方式:
1.while(1)循环读取,不断去读取数据,读到了则进行处理。
2.当有数据到来时,以中断的方式去调用数据读取函数。
对以太网数据包的处理:只对IP包和ARP包进行处理,对其他的包直接free(p)。
其中有个数据类型转换的define:htons
这个定义用于大小端转换
#define PP_HTONS(x) ((((x) & 0xff) << 8) | (((x) & 0xff00) >> 8))
即将数据低字节放到高位,数据高字节放到低位。网络字节是大端格式,ARM用的为小端格式。
发送数据:
当有数据发送时,直接调用ethernetif_output (pbuf* p, netif* inp, ip_addr* dest);发送数据。
以太网数据包结构:
定义input函数指针:
typedef err_t (*netif_input_fn)(struct pbuf *p, struct netif *inp);
netif_input_fn input;
则为定义函数指针:err_t (*input)(struct pbuf *p, struct netif *inp);
函数指针定义:返回值err_t类型,函数指针名为input,输入参数为p和inp,函数指针指向函数所在地址。
调用方式:
随便指向一个函数,input = strcmp;(函数名strcmp也是地址)
则strcmp(a,b)=============(*input)(a,b)
几个容易混淆的定义:
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)
{
LWIP_ASSERT("No init function given", init != NULL);
/* 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;
#if LWIP_DHCP
/* netif not under DHCP control by default */
netif->dhcp = NULL;
#endif /* LWIP_DHCP */
#if LWIP_AUTOIP
/* netif not under AutoIP control by default */
netif->autoip = NULL;
#endif /* LWIP_AUTOIP */
#if LWIP_NETIF_STATUS_CALLBACK
netif->status_callback = NULL;
#endif /* LWIP_NETIF_STATUS_CALLBACK */
#if LWIP_NETIF_LINK_CALLBACK
netif->link_callback = NULL;
#endif /* LWIP_NETIF_LINK_CALLBACK */
#if LWIP_IGMP
netif->igmp_mac_filter = NULL;
#endif /* LWIP_IGMP */
#if ENABLE_LOOPBACK
netif->loop_first = NULL;
netif->loop_last = NULL;
#endif /* ENABLE_LOOPBACK */
/* remember netif specific state information data */
netif->state = state;
netif->num = netif_num++;
netif->input = input;
NETIF_SET_HWADDRHINT(netif, NULL);
#if ENABLE_LOOPBACK && LWIP_LOOPBACK_MAX_PBUFS
netif->loop_cnt_current = 0;
#endif /* ENABLE_LOOPBACK && LWIP_LOOPBACK_MAX_PBUFS */
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();
#if LWIP_IGMP
/* start IGMP processing */
if (netif->flags & NETIF_FLAG_IGMP) {
igmp_start(netif);
}
#endif /* LWIP_IGMP */
LWIP_DEBUGF(NETIF_DEBUG, ("netif: added interface %c%c IP addr ",
netif->name[0], netif->name[1]));
ip_addr_debug_print(NETIF_DEBUG, ipaddr);
LWIP_DEBUGF(NETIF_DEBUG, (" netmask "));
ip_addr_debug_print(NETIF_DEBUG, netmask);
LWIP_DEBUGF(NETIF_DEBUG, (" gw "));
ip_addr_debug_print(NETIF_DEBUG, gw);
LWIP_DEBUGF(NETIF_DEBUG, ("\n"));
return netif;
}