1 #ifndef __NET_DST_METADATA_H
2 #define __NET_DST_METADATA_H 1
4 #include <linux/skbuff.h>
5 #include <net/ip_tunnels.h>
11 struct ip_tunnel_info tun_info
;
15 static inline struct metadata_dst
*skb_metadata_dst(struct sk_buff
*skb
)
17 struct metadata_dst
*md_dst
= (struct metadata_dst
*) skb_dst(skb
);
19 if (md_dst
&& md_dst
->dst
.flags
& DST_METADATA
)
25 static inline struct ip_tunnel_info
*skb_tunnel_info(struct sk_buff
*skb
)
27 struct metadata_dst
*md_dst
= skb_metadata_dst(skb
);
28 struct dst_entry
*dst
;
31 return &md_dst
->u
.tun_info
;
34 if (dst
&& dst
->lwtstate
)
35 return lwt_tun_info(dst
->lwtstate
);
40 static inline bool skb_valid_dst(const struct sk_buff
*skb
)
42 struct dst_entry
*dst
= skb_dst(skb
);
44 return dst
&& !(dst
->flags
& DST_METADATA
);
47 static inline int skb_metadata_dst_cmp(const struct sk_buff
*skb_a
,
48 const struct sk_buff
*skb_b
)
50 const struct metadata_dst
*a
, *b
;
52 if (!(skb_a
->_skb_refdst
| skb_b
->_skb_refdst
))
55 a
= (const struct metadata_dst
*) skb_dst(skb_a
);
56 b
= (const struct metadata_dst
*) skb_dst(skb_b
);
58 if (!a
!= !b
|| a
->u
.tun_info
.options_len
!= b
->u
.tun_info
.options_len
)
61 return memcmp(&a
->u
.tun_info
, &b
->u
.tun_info
,
62 sizeof(a
->u
.tun_info
) + a
->u
.tun_info
.options_len
);
65 void metadata_dst_free(struct metadata_dst
*);
66 struct metadata_dst
*metadata_dst_alloc(u8 optslen
, gfp_t flags
);
67 struct metadata_dst __percpu
*metadata_dst_alloc_percpu(u8 optslen
, gfp_t flags
);
69 static inline struct metadata_dst
*tun_rx_dst(int md_size
)
71 struct metadata_dst
*tun_dst
;
73 tun_dst
= metadata_dst_alloc(md_size
, GFP_ATOMIC
);
77 tun_dst
->u
.tun_info
.options_len
= 0;
78 tun_dst
->u
.tun_info
.mode
= 0;
82 static inline struct metadata_dst
*tun_dst_unclone(struct sk_buff
*skb
)
84 struct metadata_dst
*md_dst
= skb_metadata_dst(skb
);
86 struct metadata_dst
*new_md
;
89 return ERR_PTR(-EINVAL
);
91 md_size
= md_dst
->u
.tun_info
.options_len
;
92 new_md
= metadata_dst_alloc(md_size
, GFP_ATOMIC
);
94 return ERR_PTR(-ENOMEM
);
96 memcpy(&new_md
->u
.tun_info
, &md_dst
->u
.tun_info
,
97 sizeof(struct ip_tunnel_info
) + md_size
);
99 dst_hold(&new_md
->dst
);
100 skb_dst_set(skb
, &new_md
->dst
);
104 static inline struct ip_tunnel_info
*skb_tunnel_info_unclone(struct sk_buff
*skb
)
106 struct metadata_dst
*dst
;
108 dst
= tun_dst_unclone(skb
);
112 return &dst
->u
.tun_info
;
115 static inline struct metadata_dst
*ip_tun_rx_dst(struct sk_buff
*skb
,
120 const struct iphdr
*iph
= ip_hdr(skb
);
121 struct metadata_dst
*tun_dst
;
123 tun_dst
= tun_rx_dst(md_size
);
127 ip_tunnel_key_init(&tun_dst
->u
.tun_info
.key
,
128 iph
->saddr
, iph
->daddr
, iph
->tos
, iph
->ttl
,
129 0, 0, 0, tunnel_id
, flags
);
133 static inline struct metadata_dst
*ipv6_tun_rx_dst(struct sk_buff
*skb
,
138 const struct ipv6hdr
*ip6h
= ipv6_hdr(skb
);
139 struct metadata_dst
*tun_dst
;
140 struct ip_tunnel_info
*info
;
142 tun_dst
= tun_rx_dst(md_size
);
146 info
= &tun_dst
->u
.tun_info
;
147 info
->mode
= IP_TUNNEL_INFO_IPV6
;
148 info
->key
.tun_flags
= flags
;
149 info
->key
.tun_id
= tunnel_id
;
150 info
->key
.tp_src
= 0;
151 info
->key
.tp_dst
= 0;
153 info
->key
.u
.ipv6
.src
= ip6h
->saddr
;
154 info
->key
.u
.ipv6
.dst
= ip6h
->daddr
;
156 info
->key
.tos
= ipv6_get_dsfield(ip6h
);
157 info
->key
.ttl
= ip6h
->hop_limit
;
158 info
->key
.label
= ip6_flowlabel(ip6h
);
163 #endif /* __NET_DST_METADATA_H */