]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - net/8021q/vlan.h
net: vlan: prepare for 802.1ad support
[karo-tx-linux.git] / net / 8021q / vlan.h
index 670f1e8cfc0fd1dec4e0415ef7ab37cf33db7c5f..245de9653db0b8752da5ed7c6861e74a2769e45a 100644 (file)
@@ -49,6 +49,7 @@ struct netpoll;
  *     @ingress_priority_map: ingress priority mappings
  *     @nr_egress_mappings: number of egress priority mappings
  *     @egress_priority_map: hash of egress priority mappings
+ *     @vlan_proto: VLAN encapsulation protocol
  *     @vlan_id: VLAN identifier
  *     @flags: device flags
  *     @real_dev: underlying netdevice
@@ -62,6 +63,7 @@ struct vlan_dev_priv {
        unsigned int                            nr_egress_mappings;
        struct vlan_priority_tci_mapping        *egress_priority_map[16];
 
+       __be16                                  vlan_proto;
        u16                                     vlan_id;
        u16                                     flags;
 
@@ -87,10 +89,16 @@ static inline struct vlan_dev_priv *vlan_dev_priv(const struct net_device *dev)
 #define VLAN_GROUP_ARRAY_SPLIT_PARTS  8
 #define VLAN_GROUP_ARRAY_PART_LEN     (VLAN_N_VID/VLAN_GROUP_ARRAY_SPLIT_PARTS)
 
+enum vlan_protos {
+       VLAN_PROTO_8021Q        = 0,
+       VLAN_PROTO_NUM,
+};
+
 struct vlan_group {
        unsigned int            nr_vlan_devs;
        struct hlist_node       hlist;  /* linked list */
-       struct net_device **vlan_devices_arrays[VLAN_GROUP_ARRAY_SPLIT_PARTS];
+       struct net_device **vlan_devices_arrays[VLAN_PROTO_NUM]
+                                              [VLAN_GROUP_ARRAY_SPLIT_PARTS];
 };
 
 struct vlan_info {
@@ -103,37 +111,64 @@ struct vlan_info {
        struct rcu_head         rcu;
 };
 
-static inline struct net_device *vlan_group_get_device(struct vlan_group *vg,
-                                                      u16 vlan_id)
+static inline unsigned int vlan_proto_idx(__be16 proto)
+{
+       switch (proto) {
+       case __constant_htons(ETH_P_8021Q):
+               return VLAN_PROTO_8021Q;
+       default:
+               BUG();
+       }
+}
+
+static inline struct net_device *__vlan_group_get_device(struct vlan_group *vg,
+                                                        unsigned int pidx,
+                                                        u16 vlan_id)
 {
        struct net_device **array;
-       array = vg->vlan_devices_arrays[vlan_id / VLAN_GROUP_ARRAY_PART_LEN];
+
+       array = vg->vlan_devices_arrays[pidx]
+                                      [vlan_id / VLAN_GROUP_ARRAY_PART_LEN];
        return array ? array[vlan_id % VLAN_GROUP_ARRAY_PART_LEN] : NULL;
 }
 
+static inline struct net_device *vlan_group_get_device(struct vlan_group *vg,
+                                                      __be16 vlan_proto,
+                                                      u16 vlan_id)
+{
+       return __vlan_group_get_device(vg, vlan_proto_idx(vlan_proto), vlan_id);
+}
+
 static inline void vlan_group_set_device(struct vlan_group *vg,
-                                        u16 vlan_id,
+                                        __be16 vlan_proto, 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 = vg->vlan_devices_arrays[vlan_proto_idx(vlan_proto)]
+                                      [vlan_id / VLAN_GROUP_ARRAY_PART_LEN];
        array[vlan_id % VLAN_GROUP_ARRAY_PART_LEN] = dev;
 }
 
 /* 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)
+                                              __be16 vlan_proto, u16 vlan_id)
 {
        struct vlan_info *vlan_info = rcu_dereference_rtnl(real_dev->vlan_info);
 
        if (vlan_info)
-               return vlan_group_get_device(&vlan_info->grp, vlan_id);
+               return vlan_group_get_device(&vlan_info->grp,
+                                            vlan_proto, vlan_id);
 
        return NULL;
 }
 
+#define vlan_group_for_each_dev(grp, i, dev) \
+       for ((i) = 0; i < VLAN_PROTO_NUM * VLAN_N_VID; i++) \
+               if (((dev) = __vlan_group_get_device((grp), (i) / VLAN_N_VID, \
+                                                           (i) % VLAN_N_VID)))
+
 /* found in vlan_dev.c */
 void vlan_dev_set_ingress_priority(const struct net_device *dev,
                                   u32 skb_prio, u16 vlan_prio);
@@ -142,7 +177,8 @@ int vlan_dev_set_egress_priority(const struct net_device *dev,
 int vlan_dev_change_flags(const struct net_device *dev, u32 flag, u32 mask);
 void vlan_dev_get_realdev_name(const struct net_device *dev, char *result);
 
-int vlan_check_real_dev(struct net_device *real_dev, u16 vlan_id);
+int vlan_check_real_dev(struct net_device *real_dev,
+                       __be16 protocol, u16 vlan_id);
 void vlan_setup(struct net_device *dev);
 int register_vlan_dev(struct net_device *dev);
 void unregister_vlan_dev(struct net_device *dev, struct list_head *head);