diff options
Diffstat (limited to 'include/net/dst_metadata.h')
-rw-r--r-- | include/net/dst_metadata.h | 56 |
1 files changed, 56 insertions, 0 deletions
diff --git a/include/net/dst_metadata.h b/include/net/dst_metadata.h new file mode 100644 index 000000000000..075f523ff23f --- /dev/null +++ b/include/net/dst_metadata.h @@ -0,0 +1,56 @@ +#ifndef __NET_DST_METADATA_H +#define __NET_DST_METADATA_H 1 + +#include <linux/skbuff.h> +#include <net/ip_tunnels.h> +#include <net/dst.h> + +struct metadata_dst { + struct dst_entry dst; + size_t opts_len; + union { + struct ip_tunnel_info tun_info; + } u; +}; + +static inline struct metadata_dst *skb_metadata_dst(struct sk_buff *skb) +{ + struct metadata_dst *md_dst = (struct metadata_dst *) skb_dst(skb); + + if (md_dst && md_dst->dst.flags & DST_METADATA) + return md_dst; + + return NULL; +} + +static inline struct ip_tunnel_info *skb_tunnel_info(struct sk_buff *skb, + int family) +{ + struct metadata_dst *md_dst = skb_metadata_dst(skb); + struct rtable *rt; + + if (md_dst) + return &md_dst->u.tun_info; + + switch (family) { + case AF_INET: + rt = (struct rtable *)skb_dst(skb); + if (rt && rt->rt_lwtstate) + return lwt_tun_info(rt->rt_lwtstate); + break; + } + + return NULL; +} + +static inline bool skb_valid_dst(const struct sk_buff *skb) +{ + struct dst_entry *dst = skb_dst(skb); + + return dst && !(dst->flags & DST_METADATA); +} + +struct metadata_dst *metadata_dst_alloc(u8 optslen, gfp_t flags); +struct metadata_dst __percpu *metadata_dst_alloc_percpu(u8 optslen, gfp_t flags); + +#endif /* __NET_DST_METADATA_H */ |