* __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 it's 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 device1[24];
union {
char device2[24]; 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_) */ };
第三章 主要函数
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_device
3.1 vlan_proto_init [net\\8021q\\vlan.c]
vlan模块的初始化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供用户空间调用 ............. }