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 。
经验总结扩展阅读
- 梅花北服务区在哪个省
- 西瓜汁弄到衣服上能洗掉吗
- 埃菲尔铁塔和胡夫金字塔谁高
- 白茶有哪些品种 中国白茶五大知名品种排行榜
- 硫磺皂可以洗头发吗
- 新鲜香菇怎样算变质
- 一个泡芙的热量等于几碗饭
- 晚立秋热死牛有科学依据吗
- 卧鸡蛋怎么才能不飞
- 金铲铲之战黯灵龙技能是什么