LWIP协议:网络接口

网络数据包是通过实际的网络接口接收和发送的。

每一种网口都可以用一个netif网络接口结构体定义,一个硬件,可能有多个不同类型的网络接口,就需要定义多个netif变量,映射到硬件底层。

LWIP协议:网络接口_第1张图片

每一个网口都可以用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.当有数据到来时,以中断的方式去调用数据读取函数。

LWIP协议:网络接口_第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);发送数据。

以太网数据包结构:

LWIP协议:网络接口_第3张图片


附录1(函数指针)

定义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)

 

几个容易混淆的定义:

  • 10个指针数组,指向整型变量:int * p[10];有10个指针
  • 一个指针,指向10个整型变量的数组:int (*p)[10];
  • 一个函数指针,传入变量是整型,返回值为整型:int (*p)(int); 可以与上面一个相互记
  • 10个指针的数组,指向一个函数,传入变量是整型,返回值为整型:int (*p[10])(int)

附录2(netif_add函数)

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;
}

 

你可能感兴趣的:(FPGA接口与协议)