Kernel version: 2.6.34
802.1q
1. Register VLAN network system subspace,
Err = Register_pernet_subsys
(&vlan_net_ops);
static struct Pernet_operations Vlan_net_ops = {
. init = vlan_init_net,
. Exit = Vlan_exit_net,
. ID = & amp;vlan_net_id,
. size = sizeof (struct vlan_net),
};
Each subspace registration success is assigned an ID, which is obtained in Register_pernet_subsys ()-> register_pernet_operations ()-> ida_get_new_above () and Vlan_ This ID is recorded in the vlan_net_id in Net_ops. The end of the registration subspace invokes the initialization function vlan_init_net () of the subspace, which adds the Vlan_net (proc file system information about the VLAN) to the global Net->gen->ptr array, which is labeled as the previously assigned ID. In this way, through the vlan_net_id can be found at any time vlan_net information, mainly related to Proc.
2. Register Vlan_notifier_block
Err = Register_netdevice_notifier (&vlan_notifier_block);
static struct Notifier_block Vlan_notifier_block __read_mostly = {
. Notifier_call = Vlan_device_event,
};
The work on Register_netdevice_notifier () is not complicated and will first register Vlan_notifier_block to Netdev_chain:
Err = Raw_notifier_chain_register (&netdev_chain, NB);
Then notify the event Netdev_register and NETDEV_UP events to each device in the network system:
For_each_net (net) {
For_each_netdev (NET, dev) {
err = Nb->notifier_call (nb, netdev_register, dev);
Err = Notifier_to_errno (err);
if (err)
goto rollback;
if (!) ( Dev->flags & iff_up))
continue;
Nb->notifier_call (NB, netdev_up, dev);
}
NB is vlan_notifier_block at this time, calling the notification function vlan_device_event (). Assume that the host has the device lo[loopback interface], eth1[network card], eth1.1[virtual interface] to see the Vlan_device_event () function:
To determine if it is a VLAN virtual interface, execute __vlan_device_event (), which is the function of adding or removing the corresponding entries for the VLAN virtual device in the proc file system. Obviously, the qualifying is eth1.1, and event Netdev_register creates eth1.1 files in the/proc/net directory.
if (Is_vlan_dev (dev))
__vlan_device_event (Dev, event);
Then determine if Dev is in the Vlan_group_hash table [refer to the last "VLAN device organization"], which is dev->ifindex as a hash value, obviously, only eth1 has the right ifindex, Lo and eth1.1 will exit vlan_device_event because of a query failure.
GRP = __vlan_find_group (dev);
if (!GRP)
goto out;
The following event processing only eth1 will execute, take netdev_up as an example, through the Vlan_group_hash table can be traced to all the virtual network card interface created on it, if the NIC interface is not open, open it, here is the use of the Dev_change_ Flags (Vlandev, FLGS | IFF_UP). Tracking the function can be found that it is only modified flags, notify the Netdev_up event, waiting for the device to handle. The implication here is that if the ifconfig eth1 up, all the VLAN NIC interfaces created on ETH1 will be up.
Case NETDEV_UP:/* Put all VLANs to this dev in the
"up" state too. * for
(i = 0; i < Vlan_group_array_len i++) {
Vlandev = vlan_group_get_device (grp, i);
if (!vlandev)
continue;
Flgs = vlandev->flags;
if (Flgs & iff_up)
continue;
VLAN = Vlan_dev_info (Vlandev);
if (!) ( Vlan->flags & vlan_flag_loose_binding))
dev_change_flags (Vlandev, Flgs | IFF_UP);
Netif_stacked_transfer_operstate (Dev, vlandev);
}
Break
As you can see, Vlan_device_event is the last VLAN virtual interface operation, this is very important, do not exceed the authority to deal with other devices.
3. Add Protocol module Vlan_packet_type to Ptype_base
Dev_add_pack (&vlan_packet_type);
In the [net\8021q] directory, it's mainly about packet reception.
static struct Packet_type Vlan_packet_type __read_mostly = {
. Type = Cpu_to_be16 (eth_p_8021q),
. Func = vlan_skb_ recv, * VLAN Receive method *
/};
VLAN_SKB_RECV () [NET\8021Q\VLAN.C]