会比较杂乱吧,随心所欲的写。
lwip-contrib/ports/unix/proj/minimal的echo srv。
采用tap0接口,在README中有说明。
运行echop, ip.srv == 102 / ip.cli == 108
在程序中修改*.18---->*.108了。
low_level_init()
{
snprintf(buf, sizeof(buf), "/sbin/ifconfig " IFCONFIG_ARGS,
ip4_addr1(&(netif->gw)),
ip4_addr2(&(netif->gw)),
ip4_addr3(&(netif->gw)),
ip4_addr4(&(netif->gw))+107); /*zlz add +107*/
}
分析,主要关注netif(本例为tap)的适配。
int main(int argc, char **argv)
{
/* startup defaults (may be overridden by one or more opts) */
IP4_ADDR(&gw, 192,168,0,1);
IP4_ADDR(&ipaddr, 192,168,0,102);
IP4_ADDR(&netmask, 255,255,255,0);
netif_add(&netif, &ipaddr, &netmask, &gw, NULL, mintapif_init, ethernet_input);
}
struct netif
{
netif_input_fn input; //netif fetch a pack
netif_output_fn output; //ip put a pack pack 2 netif,call linkoutput
netif_linkoutput_fn linkoutput; //called by output
}
//netif_add执行了netif_init_fn()--->mintapif_init()
netif_add(&netif, &ipaddr, &netmask, &gw, NULL, mintapif_init, ethernet_input);
{
netif->input = input;
if (init(netif) != ERR_OK) {
return NULL;
}
}
//tap0 init
mintapif_init(struct netif *netif)
{
netif->hwaddr_len = 6;
netif->name[0] = IFNAME0;
netif->name[1] = IFNAME1;
netif->output = etharp_output;
netif->linkoutput = low_level_output;
netif->mtu = 1500;
mintapif->ethaddr = (struct eth_addr *)&(netif->hwaddr[0]);
low_level_init(netif);
return ERR_OK;
}
low_level_init(struct netif *netif) //可以看作是具体网卡的init,init后就可以供其他cb使用了。
{
mintapif = (struct mintapif *)netif->state;
mintapif->fd = open(DEVTAP, O_RDWR);
}
low_level_output(struct netif *netif, struct pbuf *p) //wr--->send
{
mintapif = (struct mintapif *)netif->state;
/* signal that packet should be sent(); */
written = write(mintapif->fd, buf, p->tot_len);
}
low_level_input(struct netif *netif) //rd--->recv
{
mintapif = (struct mintapif *)netif->state;
/* Obtain the size of the packet and put it into the "len" variable. */
len = read(mintapif->fd, buf, sizeof(buf));
}
low_level_input/low_level_output就是具体的netif的recv/send。
现在来总结下,哪些是需要根据具体netif来重写的(红色),哪些是lwip的框架。
netif_add(&netif, &ipaddr, &netmask, &gw, NULL, mintapif_init, ethernet_input);
Ø 需要重写
mintapif_init()
low_level_output netif_linkoutput_fn linkoutput
low_level_input 见下面mintapif_input
Ø lwip框架
ethernet_input()
ethernet_input(struct pbuf *p, struct netif *netif) 是在netif init后才调用的,需要netif具体化。
etharp_output ,不要被“arp”误导。output最终call了linkoutput,这2个output可以看做是一个。
etharp_output(struct netif *netif, struct pbuf *q, const ip4_addr_t *ipaddr)
{
return etharp_send_ip(netif, q, (struct eth_addr*)(netif->hwaddr), dest);
}
etharp_send_ip(struct netif *netif, struct pbuf *p, struct eth_addr *src, const struct eth_addr *dst)
{
/* send the packet */
return netif->linkoutput(netif, p);
}
Ø Input flow
int
main(int argc, char **argv)
{
}
Ø Output flow
echo_send
{
wr_err = tcp_write(tpcb, ptr->payload, ptr->len, 1);
}
在1.4.x版本中,tcp_write只是准备好segment。tcpip_tcp_timer周期性(TCP_TMR_INTERVAL)调用tcp_tmr(){-->tcp_output},最终调用netif->output(本例为low_level_output)。
若无必要,不用tcp_write后就紧接着tcp_output,有可能打乱tcp的节奏。建议交给lwip自行处理(仅tcp_write就好了,参考echo.c)。
下图是从”LwIP协议深度剖析与实战演练”(朱升林著,应该和老衲五木是同一个人)中截取的。
自己的图
原文:http://www.cnblogs.com/freezlz/p/5483067.html