7.8 虚拟局域网VLAN源码分析7.8.1 以太网标准帧和VLAN帧的区别以太网标准数据帧报文及带VLAN标签的以太网标准数据帧报文的差异:
文章插图
VLAN字段是插入在以太网首部字段中 。再看代码实现,就明白了 。
7.8.2 以太网发送带VLAN数据帧VLAN字段数据结构:
- TPID和TCI字段倒置 。就是为了代码简易 。
/** VLAN header inserted between ethernet header and payload * if 'type' in ethernet header is ETHTYPE_VLAN. * See IEEE802.Q */struct eth_vlan_hdr {PACK_STRUCT_FIELD(u16_t prio_vid);PACK_STRUCT_FIELD(u16_t tpid);} PACK_STRUCT_STRUCT;
组建带VLAN标签的以太网帧代码段:- 因为只能偏移整个以太网帧首部,多偏移了类型字段的两个字节 。
- 所以按上述VLAN数据结构来看,
ACK_STRUCT_FIELD(u16_t tpid);
实际指向的是以太网类型字段 。 - 而为了兼容后面代码一致性 ,
eth_type_be = PP_HTONS(ETHTYPE_VLAN);
才是真正的VLAN的TPID字段 。
vlanhdr = (struct eth_vlan_hdr *)(((u8_t *)p->payload) + SIZEOF_ETH_HDR); /* 这里注意偏移 。了解带VLAN标签的以太网帧报文就知道下面的操作 */vlanhdr->tpid= eth_type_be; /* 以太网的类型字段 */vlanhdr->prio_vid = lwip_htons((u16_t)vlan_prio_vid); /* VLAN标签的TCI字段 */eth_type_be = PP_HTONS(ETHTYPE_VLAN); /* 这里才是VLAN的TPID字段(代码实现的手法) */
7.8.3 以太网接收带VLAN数据帧ethernet_input()
接收到数据帧时VLAN部分代码处理:如果对VLAN不感兴趣 , 上面代码可以直接忽略VLAN部分,这样会更加便于分析 。
其中检查过滤VLAN , 有三种方式(仅能选其一),优先级又高到低,描述如下:
LWIP_HOOK_VLAN_CHECK
:VLAN钩子函数,检查当前数据帧是否是需要的VLAN 。被ethernet_input()
函数调用 。ETHARP_VLAN_CHECK_FN
:也是检查当前数据帧是否是需要的VLAN 。返回1表示接受该数据帧 。ETHARP_VLAN_CHECK
:指定一个VLAN ID,整个协议栈只接收该VLAN的流量 。
/** * ETHARP_SUPPORT_VLAN==1: support receiving and sending ethernet packets with * VLAN header. See the description of LWIP_HOOK_VLAN_CHECK and * LWIP_HOOK_VLAN_SET hooks to check/set VLAN headers. * Additionally, you can define ETHARP_VLAN_CHECK to an u16_t VLAN ID to check. * If ETHARP_VLAN_CHECK is defined, only VLAN-traffic for this VLAN is accepted. * If ETHARP_VLAN_CHECK is not defined, all traffic is accepted. * Alternatively, define a function/define ETHARP_VLAN_CHECK_FN(eth_hdr, vlan) * that returns 1 to accept a packet or 0 to drop a packet. */#if !defined ETHARP_SUPPORT_VLAN || defined __DOXYGEN__#define ETHARP_SUPPORT_VLAN1#endif
LWIP_HOOK_VLAN_CHECK
钩子格式说明:/** * LWIP_HOOK_VLAN_CHECK(netif, eth_hdr, vlan_hdr): * Called from ethernet_input() if VLAN support is enabled * Signature:\code{.c} *int my_hook(struct netif *netif, struct eth_hdr *eth_hdr, struct eth_vlan_hdr *vlan_hdr); * \endcode * Arguments: * - netif: struct netif on which the packet has been received * - eth_hdr: struct eth_hdr of the packet * - vlan_hdr: struct eth_vlan_hdr of the packet * Return values: * - 0: Packet must be dropped. * - != 0: Packet must be accepted. */#ifdef __DOXYGEN__#define LWIP_HOOK_VLAN_CHECK(netif, eth_hdr, vlan_hdr)#endif
7.9 一个硬件映射到多个IP一个硬件映射到多个IP的实现需要开启LWIP_ARP_FILTER_NETIF
宏并定义LWIP_ARP_FILTER_NETIF_FN()
函数 。LWIP_ARP_FILTER_NETIF_FN()
函数会在ethernet_input()
以太网接收到数据帧处理时被调用,会根据数据帧的内容更新出的netif 。该函数代码实现思路说明:
- 根据以太网数据帧协议类型区别出IP、ARP或者其它协议 。
- 再根据协议分析出目标协议地址IP 。
- 再遍历netif链表,匹配IP 。
/** Define this to 1 and define LWIP_ARP_FILTER_NETIF_FN(pbuf, netif, type) * to a filter function that returns the correct netif when using multiple * netifs on one hardware interface where the netif's low-level receive * routine cannot decide for the correct netif (e.g. when mapping multiple * IP addresses to one hardware interface). */#ifndef LWIP_ARP_FILTER_NETIF#define LWIP_ARP_FILTER_NETIF 1#endif
推荐阅读
- switch上古卷轴5mod怎么用(switch上古卷轴5mod视频)
- 上古卷轴5mod如何用(上古卷轴5可以推倒npc吗)
- 穿越火线怎么调烟雾头(最新穿越火线烟雾怎么调)
- 四 【单片机入门】应用层软件开发的单片机学习之路-----ESP32开发板PWM控制电机以及中断的使用
- 二 【性能测试】Loadrunner12.55-飞机订票系统-脚本录制
- 含源码 【YOLOv5】手把手教你使用LabVIEW ONNX Runtime部署 TensorRT加速,实现YOLOv5实时物体识别
- 小米平板5正式官宣_小米平板5上市时间确定
- 【FAQ】关于华为地图服务定位存在偏差的原因及解决办法
- C# 8.0 添加和增强的功能【基础篇】
- 我的世界怎么开二级隐身(我的世界怎么搞隐身)