第二章 重要结构
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_dest[ETH_ALEN]; //目的地址 unsigned char h_source[ETH_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_arrays[VLAN_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_arrays[vlan_id / VLAN_GROUP_ARRAY_PART_LEN]; return array ? array[vlan_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_arrays[vlan_id / VLAN_GROUP_ARRAY_PART_LEN]; array[vlan_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_t
vlan_gro_receive(struct napi_struct *napi, struct vlan_group *grp, unsigned int vlan_tci, struct sk_buff *skb); extern gro_result_t
vlan_gro_frags(struct napi_struct *napi, struct vlan_group *grp, unsigned int vlan_tci); #else
static 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)