当前位置:首页 >> 信息与通信 >>

LWIP之五IP层实现


LWIP 之 IP 层实现
2009-05-16 00:44:20 标签: 原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。否则将追究法律责任。 http://bluefish.blog.51cto.com/214870/158417

20092009-5-12 LWIP 之 IP 层实现

这一部分的实现都是在 ip.c 文件中【src\cor\ipv4】,可以看到在这个文件中主要实现了 3 个 函数,ip_input;ip_route;ip_output 以及 ip_output_if。下面分别来介绍它们。

这些函数可以分成两大类: 接收和发送。 下面就先从发送开始, 首先要说的就是 ip_output 函数, 这个也是发送过程中最重要的一个,它是被 tcp 层调用的,详细可参见以上章节。 * Simple interface to ip_output_if. It finds the outgoing network * interface and calls upon ip_output_if to do the actual work. err_t ip_output(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest, u8_t ttl, u8_t tos, u8_t proto) { struct netif *netif;

if ((netif = ip_route(dest)) == NULL) { return ERR_RTE; }

return ip_output_if(p, src, dest, ttl, tos, proto, netif); } 可以看到该函数的实现就像注释所说的一样,直接调用了 ip_route 和 ip_outputif 两个函数。根据 以往的经验,先看下 netif 这个结构的实现情况: * Generic data structure used for all lwIP network interfaces. * The following fields should be filled in by the initialization * function for the device driver: hwaddr_len, hwaddr[], mtu, flags//这几个是要用驱动层填 写的 struct netif { /** pointer to next in linked list */ struct netif *next;

/** IP address configuration in network byte order */ struct ip_addr ip_addr; struct ip_addr netmask; struct ip_addr gw;

/** This function is called by the network device driver * to pass a packet up the TCP/IP stack. */

err_t (* input)(struct pbuf *p, struct netif *inp);

/** This function is called by the IP module when it wants * * to send a packet on the interface. This function typically first resolves the hardware address, then sends the packet. */

err_t (* output)(struct netif *netif, struct pbuf *p, struct ip_addr *ipaddr);

/** This function is called by the ARP module when it wants * * to send a packet on the interface. This function outputs the pbuf as-is on the link medium. */

err_t (* linkoutput)(struct netif *netif, struct pbuf *p);

#if LWIP_NETIF_STATUS_CALLBACK /** This function is called when the netif state is set to up or down */ void (* status_callback)(struct netif *netif); #endif /* LWIP_NETIF_STATUS_CALLBACK */

#if LWIP_NETIF_LINK_CALLBACK /** This function is called when the netif link is set to up or down */ void (* link_callback)(struct netif *netif); #endif /* LWIP_NETIF_LINK_CALLBACK */

/** This field can be set by the device driver and could point * to state information for the device. */

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

/** number of bytes used in hwaddr */

u8_t hwaddr_len;

/** link level hardware address of this interface */ u8_t hwaddr[NETIF_MAX_HWADDR_LEN];

/** maximum transfer unit (in bytes) */ u16_t mtu; /** flags (see NETIF_FLAG_ above) */ u8_t flags;

/** descriptive abbreviation */ char name[2];

/** number of this interface */ u8_t num;

#if LWIP_SNMP /** link type (from "snmp_ifType" enum from snmp.h) */ u8_t link_type; /** (estimate) link speed */ u32_t link_speed; /** timestamp at last change made (up/down) */ u32_t ts; /** counters */ u32_t ifinoctets; u32_t ifinucastpkts; u32_t ifinnucastpkts; u32_t ifindiscards; u32_t ifoutoctets; u32_t ifoutucastpkts; u32_t ifoutnucastpkts; u32_t ifoutdiscards; #endif /* LWIP_SNMP */

#if LWIP_IGMP /* This function could be called to add or delete a entry in the multicast filter table of the ethernet MAC.*/ err_t (*igmp_mac_filter)( struct netif *netif, struct ip_addr *group, u8_t action); #endif /* LWIP_IGMP */

#if LWIP_NETIF_HWADDRHINT u8_t *addr_hint; #endif /* LWIP_NETIF_HWADDRHINT */ };

该结构体实现在 【src\include\lwip\netif.h】 注意到该结构体成员中有 3 个函数指针变量。 , 好了, 这个结构体先做一大体了解。用到的时候再详细讲。 接下来先看下 ip_route 函数的实现: * Finds the appropriate network interface for a given IP address. It * searches the list of network interfaces linearly. A match is found * if the masked IP address of the network interface equals the masked * IP address given to the function. struct netif * ip_route(struct ip_addr *dest) { struct netif *netif;

/* iterate through netifs */ for(netif = netif_list; netif != NULL; netif = netif->next) { /* network mask matches? */ if (netif_is_up(netif)) { if (ip_addr_netcmp(dest, &(netif->ip_addr), &(netif->netmask))) { /* return netif on which to forward IP packet */ return netif; } } } if ((netif_default == NULL) || (!netif_is_up(netif_default))) { snmp_inc_ipoutnoroutes(); return NULL; } /* no matching netif found, use default netif */ return netif_default; } 可以说这个函数的实现很简单,且作用也很容易看懂,就像其注释所说的一样。不过在这个函数中我 们还是发现了一些什么,对了,就是 struct netif *netif_list;【src\core\netif.c】的使用。既 然这里都使用了这个网络接口链表,那它是在哪里被初始化的呢? 好了,首先我们发现在 netif_add 函数中有对 netif_list 的调用,netif_add 是被 do_netifapi_netif_add 函数调用的,而 do_netifapi_netif_add 是在 netifapi_netif_add 中通过 netifapi_msg 被 TCPIP_NETIFAPI 调用的。问题似乎很清楚,只要找到 nnetifapi_netif_add 是被谁 调用的就好了, 然而, 搜遍整个工程也没有发现这个函数的影子, 除了一个声明一个实现外。 god, My 又进入死胡同了?好吧,这里先标识一下,待解【见下面的解释】

我们接着看 ip_output_if 这个函数,具体函数可参考【src\core\ipv4\ip.c】。它的函数定义 注释如下: * Sends an IP packet on a network interface. This function constructs * the IP header and calculates the IP header checksum. If the source * IP address is NULL, the IP address of the outgoing network * interface is filled in as source address.

* If the destination IP address is IP_HDRINCL, p is assumed to already * include an IP header and p->payload points to it instead of the data. 再看最后一句:return netif->output(netif, p, dest); 嗯,看来这个 netif 还是关键啊,如果估计不错的话,接收的时候也要用到这个结构的。那就看它在 什么地方被赋值的吧。又经过一番搜索,看来在目前的代码中是找不到的了。查看 lwip 协议栈的设 计与实现,特别是网络接口层的那一节,终于明白了,原来这些是要有设备驱动来参与的:【一下为 引用】 当收到一个信息包时,设备驱动程序调用 input 指针指向的函数。网络接口通过 output 指针连接到 设备驱动。这个指针指向设备驱动中一个向物理网络发送信息包的函数,当信息包包被发送时由 IP 层调用,这个字段由设备驱动的初始设置函数填充。 嗯,那就这样吧,到这里我们可以说 IP 层的发送流程已经走完了。

接下来就是 ip 层的接收过程了。 刚才上面也有提到驱动设备收到包, 丢给 netif 的 input 函数, 这个 input 函数也是设备驱动层来设置的。无非有两个可能,一个是 ip_input,另外一个就是 tcpip_input。因为 tcpip_input 函数的处理是最终调用到了 ip_input【在 tcpip_thread 中】。按 照正常情况下应该是 ip_input 函数的,我们先来看下这个函数。 * This function is called by the network interface device driver when * an IP packet is received. The function does the basic checks of the * IP header such as packet size being at least larger than the header * size etc. If the packet was not destined for us, the packet is * forwarded (using ip_forward). The IP checksum is always checked. 原型:err_t ip_input(struct pbuf *p, struct netif *inp) 该函数大致的处理过程是:处理 ip 包头;找到对应的 netif;检查如果是广播或多播包,则丢掉; 如果是 tcp 协议的话就直接调用了 tcp_input 函数处理数据。

到此,ip 层的东西大致就说完了。最后,由于 tcp 和 ip 层的东西都说完了,所以此时我们顺便 看下, tcpip 的整体实现, 这个主要是在 src\api\tcpip.c 文件中实现。 我们知道发送过程是由 socket 直接调用的,所以这个文件中不涉及,说白了,这个文件主要是涉及到整个接收过程。这里实现的函 数有 tcpip_input,和 tcpip_thread 以及 tcpip_init 函数。 Tcpip_init 函数很简单就是创建系统线程(sys_thread_new)tcpip_thread。 Tcpip_thread 函数的注释如下: * The main lwIP thread. This thread has exclusive access to lwIP core functions * (unless access to them is not locked). Other threads communicate with this * thread using message boxes. 它的整个过程就是一直从 mbox 中取出 msg,对各种 msg 的一个处理过程。 Tcpip_input 函数,是在 tcpip_thread 中被调用的处理设备驱动接收到的信息包,并调用 ip_input 来进一步处理。

整个启动过程: main---> vlwIPInit() void vlwIPInit( void ) { /* Initialize lwIP and its interface layer. */ sys_init();

mem_init(); memp_init(); pbuf_init(); netif_init(); ip_init(); sys_set_state(( signed portCHAR * ) "lwIP", lwipTCP_STACK_SIZE); tcpip_init( NULL, NULL ); sys_set_default_state(); }

从上面我们知道,tcpip_init 创建 tcpip_thread 在 tcpip_thread 的开始有如下代码: (void)arg; ip_init();

#if LWIP_UDP udp_init(); #endif

#if LWIP_TCP tcp_init(); #endif

#if IP_REASSEMBLY sys_timeout(1000, ip_timer, NULL); #endif

if (tcpip_init_done != NULL) { tcpip_init_done(tcpip_init_done_arg); }

下面是 tcp_init 的实现 Void tcp_init(void) { /* Clear globals. */ tcp_listen_pcbs.listen_pcbs = NULL; tcp_active_pcbs = NULL; tcp_tw_pcbs = NULL; tcp_tmp_pcb = NULL;

/* initialize timer */ tcp_ticks = 0; tcp_timer = 0;

}

本文出自 “bluefish” 博客,请务必保留此出处 http://bluefish.blog.51cto.com/214870/158417


相关文章:
uCOS平台下的LwIP移植(非常详细)
LwIP 以前的版本还要求 sys_arch 实现定时器调度,不过,从 LwIP0.5 开始,这...焦海波 2006-9-1 (8) (9) (10) (11)这几行代码完成数据向 IP 层传递...
LWIP目录结构以及在实验版web_server例子的实现原理
建立在用户提供的原始系统服务函数之上 Udp.c:一系统UDP层的函数,存在于TCPIP...LwIP协议详解 99页 5下载券 LwIP协议栈的设计与实现... 42页 5下载券 IP+...
LWIP的底层结构
5-11 LWIP 之 TCP 层发送相关 现在我们正式开始进入对 TCP 的研究, 它属于...到此也解开了 五.LWIP 之 IP 层实现 20092009-5-12 LWIP 之 IP 层实现 ...
LwIP协议栈开发嵌入式网络的三种方法分析
LwIP 含义是 light weight(轻型)IP 协议,在实现时...前者在内存池 中的默认个数是 5,后者是 8,其中 ...客户端连接,到达 TCP 层,在 tcp_listen_input ...
lwip中各种函数,标志位的总结
[5] = 'T'; netif->mtu = 1500//最大允许...LWIP实现了接收一个数 据包和发送一个数据包...IP 层的输入 8 位协议字段用来描述该 IP 数据包...
lwip之netif和pbuf分析
structip_addr *ipaddr) 它指向一个用于IP层输出的函数,初始化为etharp_output...LWIP之SOCKET的实现 40页 免费 lwip概述 35页 免费 LwIP协议详解 99页 5下载...
LWIP之SOCKET的实现
为了兼容性,lwip 的 socket 应该也是提供标准的 socket 接口函 数,恩,没错,...LWIP之五IP层实现 7页 1下载券 Lwip 协议栈的设计与实现... 37页 2下载券...
lwip协议的移植
LwIP 的特性如下: (1) 支持多网络接口下的 IP ...Dm_netif.c 网卡驱动与系统关联的抽象层 Dm9000a....在这个信号系统中本人还存在一个疑问,具体在 5”...
LWIP结构
IP 头的有效负荷; 收到数据包的网络接口; 操作系统模拟层: LWIP 为操作系统...LwIP协议栈的设计与实现... 42页 5下载券 LwIP协议详解 99页 5下载券 LWIP...
LwIP_TCPIP 常用函数
LwIP_TCPIP 常用函数_计算机软件及应用_IT/计算机_专业...设置某个协议控制块用于连接的本地 ip 地址和端口...实现 TCP 的状态机 5、static u8_t tcp_receive(...
更多相关标签:
ip层实现 | lwip 获取ip地址 | lwip dhcp获取不到ip | lwip 设置静态ip地址 | lwip ip地址 | lwip 设置ip | lwip 多ip | lwip怎么重新设置ip |