|
@@ -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);
|
|
|
|