在LwIP中,物理网络硬件接口结构保存在一个全局链表中,它们通过结构体中的 next 指针连接。

struct netif {
/// pointer to next in linked list */
struct netif *next; /// IP address configuration in network byte order */
ip_addr_t ip_addr; //IP地址
ip_addr_t netmask; //子网掩码
ip_addr_t gw; //网关地址 netif_input_fn input; //设备驱动调用该函数传递一个包给TCP/IP协议栈 //IP模块调用该函数传递一个包给网卡,output 函数的第三个參数 ipaddr 是应该接收实际的链路层帧的主机的 IP 地址。
//它不必与 IP 信息包的目的地址同样。特别地,当要发送 IP 信息包到一个并不在本地网络里的主机上时,链路层帧会被发送到网络里的一个路由器上。
//在这样的情况下给output函数的IP地址将是这个路由器的地址。 netif_output_fn output; netif_linkoutput_fn linkoutput; //ARP模块调用该函数传递一个包给网卡 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 */ u16_t mtu; //一次传送的最大字节数,以太网一般为1500 u8_t hwaddr_len; //物理地址长度,通常是以太网MAC地址长度。6字节 u8_t hwaddr[NETIF_MAX_HWADDR_LEN]; //物理地址,通常是以太网MAC地址
/// flags (see NETIF_FLAG_ above) */
u8_t flags; //使能标志符。比方设置NETIF_FLAG_LINK_UP。接收到数据包才会向上传
/// descriptive abbreviation */
char name[2]; //设备驱动类型
/// number of this interface */
u8_t num; // List of packets to be queued for ourselves. */
struct pbuf *loop_first; //环回。指向发给自己数据包的第一个pbuf
struct pbuf *loop_last; //环回,指向发给自己数据包的最后一个pbuf
};
/*
* Add a network interface to the list of lwIP netifs.
*
* @param netif a pre-allocated netif structure
* @param ipaddr IP address for the new netif
* @param netmask network mask for the new netif
* @param gw default gateway IP address for the new netif
* @param state opaque data passed to the new netif
* @param init callback function that initializes the interface
* @param input callback function that is called to pass
* ingress packets up in the protocol layer stack.
*
* @return netif, or NULL if failed.
*/
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)
{
static u8_t netifnum = 0; // 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; // remember netif specific state information data */
netif->state = state;
netif->num = netifnum++;
netif->input = input; 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(); return netif;
} //用户自己定义初始化函数
err_t ethernetif_init(struct netif *netif)
{
netif->name[0] = IFNAME0; //比方蓝牙设备(bluetooth)的网络接口能够是bt,随便啦
netif->name[1] = IFNAME1;
netif->output = etharp_output; //IP模块发送数据包函数
netif->linkoutput = low_level_output; // //ARP模块发送数据包函数
low_level_init(netif); //底层硬件初始化函数
return ERR_OK;
} static void low_level_init(struct netif *netif)
{
netif->hwaddr_len = ETHARP_HWADDR_LEN; //设置MAC地址长度 netif->hwaddr[0] = 'F'; //设置网卡MAC地址
netif->hwaddr[1] = 'O';
netif->hwaddr[2] = 'R';
netif->hwaddr[3] = 'E';
netif->hwaddr[4] = 'S';
netif->hwaddr[5] = 'T'; netif->mtu = 1500; //最大同意传输单元 //同意该网卡的广播和ARP功能。而且该网卡同意有硬件链路连接
netif->flags = NETIF_FLAG_BROADCAST | \
NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP; E1280_init(netif->hwaddr); //详细网卡初始化函数
} /*
* Send an IP packet to be received on the same netif (loopif-like).
* The pbuf is simply copied and handed back to netif->input.
* In multithreaded mode, this is done directly since netif->input must put
* the packet on a queue.
* In callback mode, the packet is put on an internal queue and is fed to
* netif->input by netif_poll().
*
* @param netif the lwip network interface structure
* @param p the (IP) packet to 'send'
* @param ipaddr the ip address to send the packet to (not used)
* @return ERR_OK if the packet has been sent
* ERR_MEM if the pbuf used to copy the packet couldn't be allocated
*/
err_t
netif_loop_output(struct netif *netif, struct pbuf *p,
ip_addr_t *ipaddr)
{
struct pbuf *r;
err_t err;
struct pbuf *last; SYS_ARCH_DECL_PROTECT(lev);
LWIP_UNUSED_ARG(ipaddr); // Allocate a new pbuf */
r = pbuf_alloc(PBUF_LINK, p->tot_len, PBUF_RAM);
if (r == NULL) {
return ERR_MEM;
} // Copy the whole pbuf queue p into the single pbuf r */
if ((err = pbuf_copy(r, p)) != ERR_OK) { //拷贝要发送的数据到r中
pbuf_free(r);
return err;
} // Put the packet on a linked list which gets emptied through calling
netif_poll(). */
//能够调用netif_poll函数将当前loop链表上全部数据提交给IP层 // let last point to the last pbuf in chain r */
for (last = r; last->next != NULL; last = last->next); SYS_ARCH_PROTECT(lev);
if(netif->loop_first != NULL) { //原来的loop中还有数据
netif->loop_last->next = r; //接到原来数据的后面
netif->loop_last = last;
} else {
netif->loop_first = r;
netif->loop_last = last;
}
SYS_ARCH_UNPROTECT(lev); return ERR_OK;
} /*
* This function should be called when a packet is ready to be read
* from the interface. It uses the function low_level_input() that
* should handle the actual reception of bytes from the network
* interface. Then the type of the received packet is determined and
* the appropriate input function is called.
*
* @param netif the lwip network interface structure for this ethernetif
*/
static void
ethernetif_input(struct netif *netif)
{
struct ethernetif *ethernetif;
struct eth_hdr *ethhdr;
struct pbuf *p; ethernetif = netif->state; // move received packet into a new pbuf */
p = low_level_input(netif);
// 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;
}
} /*
* This function should be called when a packet is ready to be read
* from the interface. It uses the function low_level_input() that
* should handle the actual reception of bytes from the network
* interface. Then the type of the received packet is determined and
* the appropriate input function is called.
*
* @param netif the lwip network interface structure for this ethernetif
*/
static void
ethernetif_input(struct netif *netif)
{
struct ethernetif *ethernetif;
struct eth_hdr *ethhdr;
struct pbuf *p; ethernetif = netif->state; // move received packet into a new pbuf */
p = low_level_input(netif); //拷贝接收到的数据到一个新的pbuf
// 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:
// full packet send to tcpip_thread to process */
if (netif->input(p, netif)!=ERR_OK) //调用上层(IP/ARP)函数进行处理
{
pbuf_free(p);
p = NULL;
}
break; default:
pbuf_free(p);
p = NULL;
break;
}
}

LwIP协议栈(2):网络接口的更多相关文章

  1. lwip协议栈学习---udp

    书籍:<嵌入式网络那些事-lwip协议> udp协议的优点: 1)基于IP协议,无连接的用户数据报协议,适用于传送大批量数据, 2)实时性比较高,适用于嵌入式网络 发送函数:udp_sen ...

  2. LwIP协议栈规范翻译——摘要目录

    摘要 LwIP是一种TCP/IP协议栈的实现.LwIP协议栈专注于减少内存的使用和代码的大小,使LwIP适用于嵌入式系统中在有限的资源下能够使用小型的客户机.为了减少处理和内存的需求,LwIP使用裁剪 ...

  3. 1、 LwIP协议栈规范翻译——简介

    1.简介 在过去几年中,计算机和计算机支持设备接之间的互联到无线网络日趋增加.计算机已经越来越无缝的集成在了日常的设备且价格也在下降.同时,无线网络技术例如蓝牙[HNI+98]和IEEE802.11b ...

  4. LwIP协议栈开发嵌入式网络的三种方法分析

    LwIP协议栈开发嵌入式网络的三种方法分析   摘要  轻量级的TCP/IP协议栈LwIP,提供了三种应用程序设计方法,且很容易被移植到多任务的操作系统中.本文结合μC/OS-II这一实时操作系统,以 ...

  5. 基于Lwip协议栈中独立模式下回调函数的使用

    一.使用Lwip协议独立模式开发 最近在STM32F4上边移植了Lwip,Lwip是一个小型开源的TCP/IP协议栈,有无操作系统的支持都可以运行.我当前只测试了TCP Server功能,然后对TCP ...

  6. 一种基于uCos-II操作系统和lwIP协议栈的IEEE-1588主站以及基于该主站的报文处理方法

    主站以及应用于电力系统的支持IEEE‐1588协议的主时钟(IEEE‐1588主站)的实现方法.该方法是在一个低成本的硬件平台上,借助uCos‐II操作系统和TCP/IP的协议栈,对以太网数据进行了分 ...

  7. 7、LwIP协议规范翻译——网络接口

    7.网络接口 在lwIP中,物理网络硬件设备驱动是由类似于BSD网络接口结构表示.网络接口结构如图5所示.网络接口被保存在一个全局的链表中,通过结构体中的next指针来完成链表的链接. 每个网络接口都 ...

  8. 3、LwIP协议栈规范翻译——概述

    3.概述 像许多其他TCP/IP实现一样,分层协议设计已经成为设计lwIP实现的指南.每个协议实现为自己的模块,其中几个功能充当每个协议的入口点.尽管协议层是单独实现的,一些层却不全是,正如前面所叙述 ...

  9. 4、 LwIP协议栈规范翻译——流程模型

    4.流程模型 协议实现的流程模型描述了系统被划分为不同的流程的方式.用于实现通信协议的一个流程模型是让每个协议作为一个独立的进程运行.有了这个模型,严格的协议分层被强制执行,并且协议之间的通信点必须严 ...

随机推荐

  1. golang笔记:cookie

    在同一个问题上栽了两次,以后碰到cookie出问题多半都是因为这个. Request.Cookie(name)取Cookie的时候,返回值只有name和value cookie.go cookies ...

  2. NOI2013部分题解

    Day 1 T1:向量内积 直接暴力有60.发现将n个向量合成$n\times d$的矩阵$A$,然后求$A\times A^T$,得到的矩阵包含了所有的答案. 先考虑$k=2$,将答案矩阵和全1矩阵 ...

  3. [Luogu P4198]楼房重建(线段树)

    题目描述 小A的楼房外有一大片施工工地,工地上有N栋待建的楼房.每天,这片工地上的房子拆了又建.建了又拆.他经常无聊地看着窗外发呆,数自己能够看到多少栋房子. 为了简化问题,我们考虑这些事件发生在一个 ...

  4. CodeForces - 981D Bookshelves

    Discription Mr Keks is a typical white-collar in Byteland. He has a bookshelf in his office with som ...

  5. BZOJ 1852 [MexicoOI06]最长不下降序列(贪心+DP+线段树+离散化)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1852 [题目大意] 给你N对数A1,B1……An,Bn.要求你从中找出最多的对, 把它 ...

  6. [AGC012D]Colorful Balls

    题意:有$N$个球,有颜色$c_i$,重量$w_i$,若($c_a=c_b$且$w_a+w_b\leq X$)或($c_a\ne c_b$且$w_a+w_b\leq Y$),可以交换$a,b$,求总共 ...

  7. 【可持久化Trie】【set】bzoj3166 [Heoi2013]Alo

    枚举每个数,计算以其为次大数的最大区间,显然,只需要用这个区间的答案 对 答案进行更新即可. 找到每个数右侧.左侧第1.2个比它大的数,然后分类讨论一下即可. 找到的过程中把数sort以后,从大到小把 ...

  8. Scala实战高手****第9课:Scala类和对象彻底实战和Spark源码鉴赏

    scala类和对象 RDD中创建_sc和deps相比java更加的简洁. 在Spark的例如SparkContext.sqlSpark等全局成员在完成实例化. 在唯一实例的时候一般不会去使用伴生对象a ...

  9. JNI概述

    JNI是Java Native Interface的缩写,它提供了若干的API实现了Java和其他语言的通信(主要是C&C++). JNI 让你在利用强大 Java 平台的同时,使你仍然可以用 ...

  10. IIS 7 网站权限问题

    IIS7 应用程序池[标识]为[ApplicationPoolIdentity] 给程序目录赋权限: IUSER IIS AppPool\[应用程序池名]