]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - include/net/dst_metadata.h
Merge branch 'uaccess-work.iov_iter' of git://git.kernel.org/pub/scm/linux/kernel...
[karo-tx-linux.git] / include / net / dst_metadata.h
index 701fc814d0af85cdc99c445eaa3da9a1ef5b5761..a803129a4849f23aeff75f75b1e8f8fd4fb5ec51 100644 (file)
@@ -5,10 +5,22 @@
 #include <net/ip_tunnels.h>
 #include <net/dst.h>
 
+enum metadata_type {
+       METADATA_IP_TUNNEL,
+       METADATA_HW_PORT_MUX,
+};
+
+struct hw_port_info {
+       struct net_device *lower_dev;
+       u32 port_id;
+};
+
 struct metadata_dst {
        struct dst_entry                dst;
+       enum metadata_type              type;
        union {
                struct ip_tunnel_info   tun_info;
+               struct hw_port_info     port_info;
        } u;
 };
 
@@ -27,7 +39,7 @@ static inline struct ip_tunnel_info *skb_tunnel_info(struct sk_buff *skb)
        struct metadata_dst *md_dst = skb_metadata_dst(skb);
        struct dst_entry *dst;
 
-       if (md_dst)
+       if (md_dst && md_dst->type == METADATA_IP_TUNNEL)
                return &md_dst->u.tun_info;
 
        dst = skb_dst(skb);
@@ -55,22 +67,33 @@ static inline int skb_metadata_dst_cmp(const struct sk_buff *skb_a,
        a = (const struct metadata_dst *) skb_dst(skb_a);
        b = (const struct metadata_dst *) skb_dst(skb_b);
 
-       if (!a != !b || a->u.tun_info.options_len != b->u.tun_info.options_len)
+       if (!a != !b || a->type != b->type)
                return 1;
 
-       return memcmp(&a->u.tun_info, &b->u.tun_info,
-                     sizeof(a->u.tun_info) + a->u.tun_info.options_len);
+       switch (a->type) {
+       case METADATA_HW_PORT_MUX:
+               return memcmp(&a->u.port_info, &b->u.port_info,
+                             sizeof(a->u.port_info));
+       case METADATA_IP_TUNNEL:
+               return memcmp(&a->u.tun_info, &b->u.tun_info,
+                             sizeof(a->u.tun_info) +
+                                        a->u.tun_info.options_len);
+       default:
+               return 1;
+       }
 }
 
 void metadata_dst_free(struct metadata_dst *);
-struct metadata_dst *metadata_dst_alloc(u8 optslen, gfp_t flags);
-struct metadata_dst __percpu *metadata_dst_alloc_percpu(u8 optslen, gfp_t flags);
+struct metadata_dst *metadata_dst_alloc(u8 optslen, enum metadata_type type,
+                                       gfp_t flags);
+struct metadata_dst __percpu *
+metadata_dst_alloc_percpu(u8 optslen, enum metadata_type type, gfp_t flags);
 
 static inline struct metadata_dst *tun_rx_dst(int md_size)
 {
        struct metadata_dst *tun_dst;
 
-       tun_dst = metadata_dst_alloc(md_size, GFP_ATOMIC);
+       tun_dst = metadata_dst_alloc(md_size, METADATA_IP_TUNNEL, GFP_ATOMIC);
        if (!tun_dst)
                return NULL;
 
@@ -85,11 +108,11 @@ static inline struct metadata_dst *tun_dst_unclone(struct sk_buff *skb)
        int md_size;
        struct metadata_dst *new_md;
 
-       if (!md_dst)
+       if (!md_dst || md_dst->type != METADATA_IP_TUNNEL)
                return ERR_PTR(-EINVAL);
 
        md_size = md_dst->u.tun_info.options_len;
-       new_md = metadata_dst_alloc(md_size, GFP_ATOMIC);
+       new_md = metadata_dst_alloc(md_size, METADATA_IP_TUNNEL, GFP_ATOMIC);
        if (!new_md)
                return ERR_PTR(-ENOMEM);