1 #ifndef __NET_DST_METADATA_H 2 #define __NET_DST_METADATA_H 1 3 4 #include <linux/skbuff.h> 5 #include <net/ip_tunnels.h> 6 #include <net/dst.h> 7 8 struct metadata_dst { 9 struct dst_entry dst; 10 size_t opts_len; 11 union { 12 struct ip_tunnel_info tun_info; 13 } u; 14 }; 15 16 static inline struct metadata_dst *skb_metadata_dst(struct sk_buff *skb) 17 { 18 struct metadata_dst *md_dst = (struct metadata_dst *) skb_dst(skb); 19 20 if (md_dst && md_dst->dst.flags & DST_METADATA) 21 return md_dst; 22 23 return NULL; 24 } 25 26 static inline struct ip_tunnel_info *skb_tunnel_info(struct sk_buff *skb) 27 { 28 struct metadata_dst *md_dst = skb_metadata_dst(skb); 29 struct dst_entry *dst; 30 31 if (md_dst) 32 return &md_dst->u.tun_info; 33 34 dst = skb_dst(skb); 35 if (dst && dst->lwtstate) 36 return lwt_tun_info(dst->lwtstate); 37 38 return NULL; 39 } 40 41 static inline bool skb_valid_dst(const struct sk_buff *skb) 42 { 43 struct dst_entry *dst = skb_dst(skb); 44 45 return dst && !(dst->flags & DST_METADATA); 46 } 47 48 struct metadata_dst *metadata_dst_alloc(u8 optslen, gfp_t flags); 49 struct metadata_dst __percpu *metadata_dst_alloc_percpu(u8 optslen, gfp_t flags); 50 51 static inline struct metadata_dst *tun_rx_dst(__be16 flags, 52 __be64 tunnel_id, int md_size) 53 { 54 struct metadata_dst *tun_dst; 55 struct ip_tunnel_info *info; 56 57 tun_dst = metadata_dst_alloc(md_size, GFP_ATOMIC); 58 if (!tun_dst) 59 return NULL; 60 61 info = &tun_dst->u.tun_info; 62 info->key.tun_flags = flags; 63 info->key.tun_id = tunnel_id; 64 info->key.tp_src = 0; 65 info->key.tp_dst = 0; 66 return tun_dst; 67 } 68 69 static inline struct metadata_dst *ip_tun_rx_dst(struct sk_buff *skb, 70 __be16 flags, 71 __be64 tunnel_id, 72 int md_size) 73 { 74 const struct iphdr *iph = ip_hdr(skb); 75 struct metadata_dst *tun_dst; 76 struct ip_tunnel_info *info; 77 78 tun_dst = tun_rx_dst(flags, tunnel_id, md_size); 79 if (!tun_dst) 80 return NULL; 81 82 info = &tun_dst->u.tun_info; 83 info->key.u.ipv4.src = iph->saddr; 84 info->key.u.ipv4.dst = iph->daddr; 85 info->key.tos = iph->tos; 86 info->key.ttl = iph->ttl; 87 return tun_dst; 88 } 89 90 static inline struct metadata_dst *ipv6_tun_rx_dst(struct sk_buff *skb, 91 __be16 flags, 92 __be64 tunnel_id, 93 int md_size) 94 { 95 const struct ipv6hdr *ip6h = ipv6_hdr(skb); 96 struct metadata_dst *tun_dst; 97 struct ip_tunnel_info *info; 98 99 tun_dst = tun_rx_dst(flags, tunnel_id, md_size); 100 if (!tun_dst) 101 return NULL; 102 103 info = &tun_dst->u.tun_info; 104 info->key.u.ipv6.src = ip6h->saddr; 105 info->key.u.ipv6.dst = ip6h->daddr; 106 info->key.tos = ipv6_get_dsfield(ip6h); 107 info->key.ttl = ip6h->hop_limit; 108 info->mode = IP_TUNNEL_INFO_IPV6; 109 return tun_dst; 110 } 111 112 #endif /* __NET_DST_METADATA_H */ 113