




已阅读5页,还剩23页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
Linux vlan知识总结(beta 1) by moonflow qq:171932120 (总结自互联网) 目录前言3第一章 vlan的基本概念41.1 vlan的作用41.2 vlan的实现原理41.3 vlan的分类41.4 vlan帧结构4第二章 重要结构62.1 /include/linux/if_vlan.h6第三章 主要函数203.1 vlan_proto_init net8021qvlan.c203.2 register_pernet_subsys net8021qvlan.c213.3 register_netdevice_notifier /net/core/dev.c213.4 dev_add_pack /net/core/dev.c213.5 vlan_skb_recv /net/core/dev.c223.5 vlan_ioctl_set /net/socket.c25第四章 总结26参考资料27前言此文档是本人这段时间内学习Linux网络协议栈vlan功能相关知识,总结并且整理出来的文档。本文中的参考内核代码为2.6.24(相关的资料较多,便于开展),当然也是对互联网资源的整合。参考了锐捷的一份文档,并且参考了网上很多资源。可以说基本上总结自互联网。参考中附上我学习时参考的资料,很多,而且他们写的都非常好,导致我都不知道写啥了。不过仅仅只是为了借这次总结的机会,让个人对Linux vlan部分更加深入。因为本人初学Linux协议栈,对很多部分都还很迷茫,所以很多地方会出现失误或者不够清楚。我接触Linux时间很短,但是非常喜爱Linux,同时对网络部分非常喜爱,希望大家喜欢并且与我交流,共同进步。第一章 vlan的基本概念1.1 vlan的作用虚拟局域网VLAN是一组逻辑上的设备和用户,这些设备和用户并不受物理网段的限制,可以根据功能、部门及应用等因素将它们组织起来,相互之间的通信就好像它们在同一个网段中一样,由此得名虚拟局域网。VLAN是一种比较新的技术,工作在OSI参考模型的第2层和第3层,一个VLAN就是一个广播域,VLAN之间的通信是通过第3层的路由器来完成的。 1.2 vlan的实现原理当VLAN交换机从工作站接收到数据后,会对数据的部分内容进行检查,并与一个VLAN配置数据库(该数据库含有静态配置的或者动态学习而得到的MAC地址等信息)中的内容进行比较后,确定数据去向,如果数据要发往一个VLAN设备(VLAN-aware),一个标记(Tag)或者VLAN标识就被加到这个数据上,根据VLAN标识和目的地址,VLAN交换机就可以将该数据转发到同一VLAN上适当的目的地;如果数据发往非VLAN设备(VLAN-unaware),则VLAN交换机发送不带VLAN标识的数据。 1.3 vlan的分类a.基于端口的VLAN b.基于MAC地址的VLAN c.基于路由的VLAN d.基于策略的VLAN 1.4 vlan帧结构每一个支持802.1Q协议的主机,在发送数据包时,都在原来的以太网桢头中的源地址后增加了一个4字节的802.1Q桢头,之后接原来以太网的长度或类型域,关于以太网桢头的封装格式,参见以太网方面的培训教材。图1 带有802.1Q标签头的以太网桢 这4个字节的802.1Q标签头包含了2个字节的标签协议标(TPID-Tag Protocol Identifier,它的值是8100),和两个字节的标签控制信息(TCI-Tag Control Information),TPID是IEEE定义的新的类型,表明这是一个加了802.1Q标签的本文,图2显示了802.1Q标签头的详细内容。图2 802.1Q标签头 该标签头中的信息解释如下: LAN Identified( VLAN ID ): 这是一个12位的域,指明VLAN的ID,一共4096个,每个支持802.1Q协议的主机发送出来的数据包都会包含这个域,以指明自己属于哪一个VLAN,目前TNETX 3270只支持32个VLAN。Canonical Format Indicator( cfi ):这一位主要用于总线型的以太网与FDDI、令牌环网交换数据时的桢格式,TNETX 3270忽略此位。Priority:这3 位指明桢的优先级。一共有8种优先级,主要用于当交换机阻塞时,优先发送哪个数据包。TNETX 3270和TNETX 4090只支持一种优先级,所以这一位也没有用,第2章 重要结构2.1 /include/linux/if_vlan.h在/include/linux/if_vlan.h中定义vlan相关的基本数据结构/每一个支持802.1q协议的主机,在发送数据包时,都在原来的以太网帧头中的源地址后增加了一个4字节的802.1q帧头#define VLAN_HLEN 4 /* The additional bytes (on top of the Ethernet header) * that VLAN requires. */VLAN以太网头部的地址长度字节#define VLAN_ETH_ALEN 6 /* Octets in one ethernet addr */VLAN以太网头部的长度字节#define VLAN_ETH_HLEN 18 /* Total octets in header. */VLAN以太网不含CRC校验的数据最小长度#define VLAN_ETH_ZLEN 64 /* Min. octets in frame sans FCS */*备注以太网的情况#define ETH_ALEN 6 /*以太网地址,即MAC地址,6字节*/#define ETH_HLEN 14 /*以太网头部的总长度*/#define ETH_ZLEN 60 /*不含CRC校验的数据最小长度*/#define ETH_DATA_LEN 1500 /*帧内数据的最大长度*/#define ETH_FRAME_LEN 1514 /*不含CRC校验和的最大以太网数据长度*/*/* * According to 802.3ac, the packet can be 4 bytes longer. -Klika Jan */VLAN帧内数据的最大长度#define VLAN_ETH_DATA_LEN 1500 /* Max. octets in payload */VLAN中不含CRC校验和的最大以太网数据长度#define VLAN_ETH_FRAME_LEN 1518 /* Max. octets in frame sans FCS */* * struct vlan_hdr - vlan header * h_vlan_TCI: priority and VLAN ID *h_vlan_encapsulated_proto: packet type ID or len */struct vlan_hdr _be16 h_vlan_TCI; /TCI:802.1q标签头部分的priority and vlan id,标签控制信息 _be16 h_vlan_encapsulated_proto; /包类型ID或者长度;/* *struct vlan_ethhdr - vlan ethernet header (ethhdr + vlan_hdr) *h_dest: destination ethernet address *h_source: source ethernet address *h_vlan_proto: ethernet protocol (always 0x8100) *h_vlan_TCI: priority and VLAN ID *h_vlan_encapsulated_proto: packet type ID or len */struct vlan_ethhdr unsigned char h_destETH_ALEN; /目的地址 unsigned char h_sourceETH_ALEN; /源地址 _be16 h_vlan_proto; /以太网协议 _be16 h_vlan_TCI; /标签控制信息 _be16 h_vlan_encapsulated_proto;/包类型ID或者长度;#include static inline struct vlan_ethhdr *vlan_eth_hdr(const struct sk_buff *skb) return (struct vlan_ethhdr *)skb_mac_header(skb);#define VLAN_PRIO_MASK 0xe000 /* Priority Code Point */#define VLAN_PRIO_SHIFT 13#define VLAN_CFI_MASK 0x1000 /* Canonical Format Indicator */#define VLAN_TAG_PRESENT VLAN_CFI_MASK /这一位主要用于总线型的以太网与FDDI、令牌环网交换数据时的桢格式,TNETX 3270忽略此位#define VLAN_VID_MASK 0x0fff /* VLAN Identifier */ /VLAN标识符#define VLAN_N_VID 4096 /VLAN ID总共4096个/* found in socket.c */extern void vlan_ioctl_set(int (*hook)(struct net *, void _user *);/* if this changes, algorithm will have to be reworked because this * depends on completely exhausting the VLAN identifier space. Thus * it gives constant time look-up, but in many cases it wastes memory. */#define VLAN_GROUP_ARRAY_SPLIT_PARTS 8#define VLAN_GROUP_ARRAY_PART_LEN (VLAN_N_VID/VLAN_GROUP_ARRAY_SPLIT_PARTS)struct vlan_group struct net_device *real_dev; /* The ethernet(like) device * the vlan is attached to. */ unsigned int nr_vlans; int killall; struct hlist_node hlist; /* linked list */ struct net_device *vlan_devices_arraysVLAN_GROUP_ARRAY_SPLIT_PARTS; struct rcu_head rcu; /rcu锁;/获取vlan组里设备static inline struct net_device *vlan_group_get_device(struct vlan_group *vg, u16 vlan_id) struct net_device *array; array = vg-vlan_devices_arraysvlan_id / VLAN_GROUP_ARRAY_PART_LEN; return array ? arrayvlan_id % VLAN_GROUP_ARRAY_PART_LEN : NULL;/设置vlan组设备static inline void vlan_group_set_device(struct vlan_group *vg, u16 vlan_id, struct net_device *dev) struct net_device *array; if (!vg) return; array = vg-vlan_devices_arraysvlan_id / VLAN_GROUP_ARRAY_PART_LEN; arrayvlan_id % VLAN_GROUP_ARRAY_PART_LEN = dev;/vlan下硬件加速处理#define vlan_tx_tag_present(_skb) (_skb)-vlan_tci & VLAN_TAG_PRESENT)#define vlan_tx_tag_get(_skb) (_skb)-vlan_tci & VLAN_TAG_PRESENT)#if defined(CONFIG_VLAN_8021Q) | defined(CONFIG_VLAN_8021Q_MODULE)/* Must be invoked with rcu_read_lock or with RTNL. */static inline struct net_device *vlan_find_dev(struct net_device *real_dev, u16 vlan_id) struct vlan_group *grp = rcu_dereference_rtnl(real_dev-vlgrp); if (grp) return vlan_group_get_device(grp, vlan_id); return NULL;extern struct net_device *vlan_dev_real_dev(const struct net_device *dev);extern u16 vlan_dev_vlan_id(const struct net_device *dev);extern int _vlan_hwaccel_rx(struct sk_buff *skb, struct vlan_group *grp, u16 vlan_tci, int polling);extern bool vlan_hwaccel_do_receive(struct sk_buff *skb);extern gro_result_tvlan_gro_receive(struct napi_struct *napi, struct vlan_group *grp, unsigned int vlan_tci, struct sk_buff *skb);extern gro_result_tvlan_gro_frags(struct napi_struct *napi, struct vlan_group *grp, unsigned int vlan_tci);#elsestatic inline struct net_device *vlan_find_dev(struct net_device *real_dev, u16 vlan_id) return NULL;static inline struct net_device *vlan_dev_real_dev(const struct net_device *dev) BUG(); return NULL;static inline u16 vlan_dev_vlan_id(const struct net_device *dev) BUG(); return 0;static inline int _vlan_hwaccel_rx(struct sk_buff *skb, struct vlan_group *grp, u16 vlan_tci, int polling) BUG(); return NET_XMIT_SUCCESS;static inline bool vlan_hwaccel_do_receive(struct sk_buff *skb) if (*skb)-vlan_tci & VLAN_VID_MASK) (*skb)-pkt_type = PACKET_OTHERHOST; return false;static inline gro_result_tvlan_gro_receive(struct napi_struct *napi, struct vlan_group *grp, unsigned int vlan_tci, struct sk_buff *skb) return GRO_DROP;static inline gro_result_tvlan_gro_frags(struct napi_struct *napi, struct vlan_group *grp, unsigned int vlan_tci) return GRO_DROP;#endif/* * vlan_hwaccel_rx - netif_rx wrapper for VLAN RX acceleration * skb: buffer * grp: vlan group * vlan_tci: VLAN TCI as received from the card */static inline int vlan_hwaccel_rx(struct sk_buff *skb, struct vlan_group *grp, u16 vlan_tci) return _vlan_hwaccel_rx(skb, grp, vlan_tci, 0);/* * vlan_hwaccel_receive_skb - netif_receive_skb wrapper for VLAN RX acceleration * skb: buffer * grp: vlan group * vlan_tci: VLAN TCI as received from the card */static inline int vlan_hwaccel_receive_skb(struct sk_buff *skb, struct vlan_group *grp, u16 vlan_tci) return _vlan_hwaccel_rx(skb, grp, vlan_tci, 1);/* * _vlan_put_tag - regular VLAN tag inserting * skb: skbuff to tag * vlan_tci: VLAN TCI to insert * * Inserts the VLAN tag into skb as part of the payload * Returns a VLAN tagged skb. If a new skb is created, skb is freed. * * Following the skb_unshare() example, in case of error, the calling function * doesnt have to worry about freeing the original skb. */static inline struct sk_buff *_vlan_put_tag(struct sk_buff *skb, u16 vlan_tci) struct vlan_ethhdr *veth; if (skb_cow_head(skb, VLAN_HLEN) data, skb-data + VLAN_HLEN, 2 * VLAN_ETH_ALEN); skb-mac_header -= VLAN_HLEN; /* first, the ethernet type */ veth-h_vlan_proto = htons(ETH_P_8021Q); /* now, the TCI */ veth-h_vlan_TCI = htons(vlan_tci); skb-protocol = htons(ETH_P_8021Q); return skb;/* * _vlan_hwaccel_put_tag - hardware accelerated VLAN inserting * skb: skbuff to tag * vlan_tci: VLAN TCI to insert * * Puts the VLAN TCI in skb-vlan_tci and lets the device do the rest */static inline struct sk_buff *_vlan_hwaccel_put_tag(struct sk_buff *skb, u16 vlan_tci) skb-vlan_tci = VLAN_TAG_PRESENT | vlan_tci; return skb;#define HAVE_VLAN_PUT_TAG/* * vlan_put_tag - inserts VLAN tag according to device features * skb: skbuff to tag * vlan_tci: VLAN TCI to insert * * Assumes skb-dev is the target that will xmit this frame. * Returns a VLAN tagged skb. */static inline struct sk_buff *vlan_put_tag(struct sk_buff *skb, u16 vlan_tci) if (skb-dev-features & NETIF_F_HW_VLAN_TX) return _vlan_hwaccel_put_tag(skb, vlan_tci); else return _vlan_put_tag(skb, vlan_tci); /* * _vlan_get_tag - get the VLAN ID that is part of the payload * skb: skbuff to query * vlan_tci: buffer to store vlaue * * Returns error if the skb is not of VLAN type */static inline int _vlan_get_tag(const struct sk_buff *skb, u16 *vlan_tci) struct vlan_ethhdr *veth = (struct vlan_ethhdr *)skb-data; if (veth-h_vlan_proto != htons(ETH_P_8021Q) return -EINVAL; *vlan_tci = ntohs(veth-h_vlan_TCI); return 0;/* * _vlan_hwaccel_get_tag - get the VLAN ID that is in skb-cb * skb: skbuff to query * vlan_tci: buffer to store vlaue * * Returns error if skb-vlan_tci is not set correctly */static inline int _vlan_hwaccel_get_tag(const struct sk_buff *skb, u16 *vlan_tci) if (vlan_tx_tag_present(skb) *vlan_tci = vlan_tx_tag_get(skb); return 0; else *vlan_tci = 0; return -EINVAL; #define HAVE_VLAN_GET_TAG/* * vlan_get_tag - get the VLAN ID from the skb * skb: skbuff to query * vlan_tci: buffer to store vlaue * * Returns error if the skb is not VLAN tagged */static inline int vlan_get_tag(const struct sk_buff *skb, u16 *vlan_tci) if (skb-dev-features & NETIF_F_HW_VLAN_TX) return _vlan_hwaccel_get_tag(skb, vlan_tci); else return _vlan_get_tag(skb, vlan_tci); /* * vlan_get_protocol - get protocol EtherType. * skb: skbuff to query * * Returns the EtherType of the packet, regardless of whether it is * vlan encapsulated (normal or hardware accelerated) or not. */static inline _be16 vlan_get_protocol(const struct sk_buff *skb) _be16 protocol = 0; if (vlan_tx_tag_present(skb) | skb-protocol != cpu_to_be16(ETH_P_8021Q) protocol = skb-protocol; else _be16 proto, *protop; protop = skb_header_pointer(skb, offsetof(struct vlan_ethhdr, h_vlan_encapsulated_proto), sizeof(proto), &proto); if (likely(protop) protocol = *protop; return protocol;#endif /* _KERNEL_ */* VLAN IOCTLs are found in sockios.h */* Passed in vlan_ioctl_args structure to determine behaviour. */enum vlan_ioctl_cmds ADD_VLAN_CMD, DEL_VLAN_CMD, SET_VLAN_INGRESS_PRIORITY_CMD, SET_VLAN_EGRESS_PRIORITY_CMD, GET_VLAN_INGRESS_PRIORITY_CMD, GET_VLAN_EGRESS_PRIORITY_CMD, SET_VLAN_NAME_TYPE_CMD, SET_VLAN_FLAG_CMD, GET_VLAN_REALDEV_NAME_CMD, /* If this works, you know its a VLAN device, btw */ GET_VLAN_VID_CMD /* Get the VID of this VLAN (specified by name) */;enum vlan_flags VLAN_FLAG_REORDER_HDR = 0x1, VLAN_FLAG_GVRP = 0x2, VLAN_FLAG_LOOSE_BINDING = 0x4,;enum vlan_name_types VLAN_NAME_TYPE_PLUS_VID, /* Name will look like: vlan0005 */ VLAN_NAME_TYPE_RAW_PLUS_VID, /* name will look like: eth1.0005 */ VLAN_NAME_TYPE_PLUS_VID_NO_PAD, /* Name will look like: vlan5 */ VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD, /* Name will look like: eth0.5 */ VLAN_NAME_TYPE_HIGHEST;struct vlan_ioctl_args int cmd; /* Should be one of the vlan_ioctl_cmds enum above. */ char device124; union char device224; int VID; unsigned int skb_priority; unsigned int name_type; unsigned int bind_type; unsigned int flag; /* Matches vlan_dev_info flags */ u; short vlan_qos; ;#endif /* !(_LINUX_IF_VLAN_H_) */;第3章 主要函数vlan_proto_init-register_netdevice_notifier(&vlan_notifier_bock) 把vlan_device_event函数挂接到netdev_chain链表上 -dev_add_pack(&vlan_packet_type) -vlan_ioctl_set(vlan_ioctl_handler) 让vlan_ioctl_hook指向此函数 sock_ioctl-SIOCSIFVLAN/SIOCGIFVLAN-vlan_ioctl_hook(就是函数vlan_ioctl_handler)-DEL_VLAN_CMD-unregister_vlan_device -ADD_VLAN_CMD-register_vlan_device3.1 vlan_proto_init net8021qvlan.cvlan模块的初始化vlan_proto_init,注册vlan网络系统子空间。 static int _init vlan_proto_init(void) . err = register_pernet_subsys(&vlan_net_ops); /注册vlan网络系统子空间 . err = register_netdevice_notifier(&vlan_notifier_block); /注册vlan_notifier_block到netdev_chain中,然后通知事件NETDEV_REGISTER和NETDEV_UP事件到网络系统的中的每个设备: . err = vlan_gvrp_init(); /初始化gvrp协议 . err = vlan_netlink_init(); /初始化netlink . dev_add_pack(&vlan_packet_type); /添加协议模块vlan_packet_type到ptype_base中 vlan_ioctl_set(vlan_ioctl_handler); /添加ioctl供用户空间调用 .3.2 register_pernet_subsys net8021qvlan.cregister_pernet_subsys函数调用关系:register_pernet_subsys()-register_pernet_operations()-ida_get_new_above()而ida_get_new_above的作用如它注释所描述的。分配一个新的ID大于等于一个起始IDida_get_new_above():ida_get_new_above - allocate new ID above or equal to a start id。另外register_pernet_operations()中通过调用 _register_pernet_operations函数,再通过调用ops_init(ops, &init_net),调用会调用子空间的初始化函数vlan_init_net(),而vlan_init_net()的作用就是有关vlan的proc文件系统信息。即register_pernet_operations()的调用关系如下:register_pernet_operations()-_register_pernet_operations()-ops_init()-vlan_init_net()3.3 register_netdevice_notifier /net/core/dev.c当使用SIOCBRADDBR调用ioctl时,会通过br_add_bridge函数创建新的网桥。在这err = register_netdevice_notifier(&vlan_notifier_block); static struct notifier_block vlan_notifier_block _read_mostly = .notifier_call = vlan_device_event, ; 参考/qy532846454/article/details/6529166,分析的很详细3.4 dev_add_pack /net/core/dev.cvoid dev_add_pack(struct packet_type *pt) struct list_head *head = ptype_head(pt); spin_lock(&ptype_lock); list_add_rcu(&pt-list, head); spin_unlock(&ptype_lock);static struct packet_type vlan_packet_type _read_mostly = .type = cpu_to_be16(ETH_P_8021Q), .func = vlan_skb_recv, /* VLAN receive method */;参考/qy532846454/article/details/6529166,里面相关部分很详细3.5 vlan_skb_recv /net/core/dev.cint vlan_skb_recv(struct sk_buff *skb, struct net_device *dev, struct packet_type *ptype, struct net_device *orig_dev) struct vlan_hdr *vhdr; struct vlan_pcpu_stats *rx_stats; struct net_device *vlan_dev; u16 vlan_id; u16 vlan_tci; skb = skb_share_check(skb, GFP_ATOM
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 河北省秦皇岛市青龙满族自治县第一中学2025-2026学年高二上学期9月月考数学试题(原卷版)
- 黑龙江省哈尔滨第三中学2025-2026学年高二上学期9月月考化学试题
- 2026届湖南长沙市广益实验中学英语九年级第一学期期末教学质量检测试题含解析
- 2026届重庆市重点中学英语九上期末复习检测试题含解析
- 2026届贵州省黔东南州剑河县九年级化学第一学期期末联考模拟试题含解析
- 2026届孝感市重点中学化学九上期末质量跟踪监视试题含解析
- 2026届辽宁省营口中学化学九年级第一学期期末学业质量监测模拟试题含解析
- 2026届山西省运城市夏县英语九上期末统考模拟试题含解析
- 2026届广东省湛江市霞山职业高级中学九上化学期中学业水平测试模拟试题含解析
- 2026届哈尔滨香坊区四校联考九年级化学第一学期期中教学质量检测试题含解析
- 农业现代化种植技术培训课件
- 中城汽车(山东)有限公司审计报告
- 大学博士竞赛试题及答案
- 钢结构彩钢瓦施工工艺与技术交底
- 2025版煤矿安全规程宣贯培训课件
- 新课标(水平三)体育与健康《篮球》大单元教学计划及配套教案(18课时)
- 《幼儿园保育教育质量评估指南》知识专题培训
- DB32-T 3751-2020公共建筑能源审计标准-(高清现行)
- 建设工程施工合同最新版(示范文本)(GF—2021—0201)
- 苹果电脑的发展史ppt课件
- 北京中考英语词汇表1600词汇+词组
评论
0/150
提交评论