diff options
Diffstat (limited to 'include/net/dst.h')
| -rw-r--r-- | include/net/dst.h | 92 |
1 files changed, 69 insertions, 23 deletions
diff --git a/include/net/dst.h b/include/net/dst.h index 39c4a5963e12..02386505033d 100644 --- a/include/net/dst.h +++ b/include/net/dst.h | |||
| @@ -83,8 +83,6 @@ struct dst_entry { | |||
| 83 | * (L1_CACHE_SIZE would be too much) | 83 | * (L1_CACHE_SIZE would be too much) |
| 84 | */ | 84 | */ |
| 85 | #ifdef CONFIG_64BIT | 85 | #ifdef CONFIG_64BIT |
| 86 | long __pad_to_align_refcnt[2]; | ||
| 87 | #else | ||
| 88 | long __pad_to_align_refcnt[1]; | 86 | long __pad_to_align_refcnt[1]; |
| 89 | #endif | 87 | #endif |
| 90 | /* | 88 | /* |
| @@ -170,6 +168,12 @@ static inline void dst_use(struct dst_entry *dst, unsigned long time) | |||
| 170 | dst->lastuse = time; | 168 | dst->lastuse = time; |
| 171 | } | 169 | } |
| 172 | 170 | ||
| 171 | static inline void dst_use_noref(struct dst_entry *dst, unsigned long time) | ||
| 172 | { | ||
| 173 | dst->__use++; | ||
| 174 | dst->lastuse = time; | ||
| 175 | } | ||
| 176 | |||
| 173 | static inline | 177 | static inline |
| 174 | struct dst_entry * dst_clone(struct dst_entry * dst) | 178 | struct dst_entry * dst_clone(struct dst_entry * dst) |
| 175 | { | 179 | { |
| @@ -179,22 +183,79 @@ struct dst_entry * dst_clone(struct dst_entry * dst) | |||
| 179 | } | 183 | } |
| 180 | 184 | ||
| 181 | extern void dst_release(struct dst_entry *dst); | 185 | extern void dst_release(struct dst_entry *dst); |
| 186 | |||
| 187 | static inline void refdst_drop(unsigned long refdst) | ||
| 188 | { | ||
| 189 | if (!(refdst & SKB_DST_NOREF)) | ||
| 190 | dst_release((struct dst_entry *)(refdst & SKB_DST_PTRMASK)); | ||
| 191 | } | ||
| 192 | |||
| 193 | /** | ||
| 194 | * skb_dst_drop - drops skb dst | ||
| 195 | * @skb: buffer | ||
| 196 | * | ||
| 197 | * Drops dst reference count if a reference was taken. | ||
| 198 | */ | ||
| 182 | static inline void skb_dst_drop(struct sk_buff *skb) | 199 | static inline void skb_dst_drop(struct sk_buff *skb) |
| 183 | { | 200 | { |
| 184 | if (skb->_skb_dst) | 201 | if (skb->_skb_refdst) { |
| 185 | dst_release(skb_dst(skb)); | 202 | refdst_drop(skb->_skb_refdst); |
| 186 | skb->_skb_dst = 0UL; | 203 | skb->_skb_refdst = 0UL; |
| 204 | } | ||
| 205 | } | ||
| 206 | |||
| 207 | static inline void skb_dst_copy(struct sk_buff *nskb, const struct sk_buff *oskb) | ||
| 208 | { | ||
| 209 | nskb->_skb_refdst = oskb->_skb_refdst; | ||
| 210 | if (!(nskb->_skb_refdst & SKB_DST_NOREF)) | ||
| 211 | dst_clone(skb_dst(nskb)); | ||
| 212 | } | ||
| 213 | |||
| 214 | /** | ||
| 215 | * skb_dst_force - makes sure skb dst is refcounted | ||
| 216 | * @skb: buffer | ||
| 217 | * | ||
| 218 | * If dst is not yet refcounted, let's do it | ||
| 219 | */ | ||
| 220 | static inline void skb_dst_force(struct sk_buff *skb) | ||
| 221 | { | ||
| 222 | if (skb_dst_is_noref(skb)) { | ||
| 223 | WARN_ON(!rcu_read_lock_held()); | ||
| 224 | skb->_skb_refdst &= ~SKB_DST_NOREF; | ||
| 225 | dst_clone(skb_dst(skb)); | ||
| 226 | } | ||
| 227 | } | ||
| 228 | |||
| 229 | |||
| 230 | /** | ||
| 231 | * skb_tunnel_rx - prepare skb for rx reinsert | ||
| 232 | * @skb: buffer | ||
| 233 | * @dev: tunnel device | ||
| 234 | * | ||
| 235 | * After decapsulation, packet is going to re-enter (netif_rx()) our stack, | ||
| 236 | * so make some cleanups, and perform accounting. | ||
| 237 | */ | ||
| 238 | static inline void skb_tunnel_rx(struct sk_buff *skb, struct net_device *dev) | ||
| 239 | { | ||
| 240 | skb->dev = dev; | ||
| 241 | /* TODO : stats should be SMP safe */ | ||
| 242 | dev->stats.rx_packets++; | ||
| 243 | dev->stats.rx_bytes += skb->len; | ||
| 244 | skb->rxhash = 0; | ||
| 245 | skb_set_queue_mapping(skb, 0); | ||
| 246 | skb_dst_drop(skb); | ||
| 247 | nf_reset(skb); | ||
| 187 | } | 248 | } |
| 188 | 249 | ||
| 189 | /* Children define the path of the packet through the | 250 | /* Children define the path of the packet through the |
| 190 | * Linux networking. Thus, destinations are stackable. | 251 | * Linux networking. Thus, destinations are stackable. |
| 191 | */ | 252 | */ |
| 192 | 253 | ||
| 193 | static inline struct dst_entry *dst_pop(struct dst_entry *dst) | 254 | static inline struct dst_entry *skb_dst_pop(struct sk_buff *skb) |
| 194 | { | 255 | { |
| 195 | struct dst_entry *child = dst_clone(dst->child); | 256 | struct dst_entry *child = skb_dst(skb)->child; |
| 196 | 257 | ||
| 197 | dst_release(dst); | 258 | skb_dst_drop(skb); |
| 198 | return child; | 259 | return child; |
| 199 | } | 260 | } |
| 200 | 261 | ||
| @@ -227,21 +288,6 @@ static inline void dst_confirm(struct dst_entry *dst) | |||
| 227 | neigh_confirm(dst->neighbour); | 288 | neigh_confirm(dst->neighbour); |
| 228 | } | 289 | } |
| 229 | 290 | ||
| 230 | static inline void dst_negative_advice(struct dst_entry **dst_p, | ||
| 231 | struct sock *sk) | ||
| 232 | { | ||
| 233 | struct dst_entry * dst = *dst_p; | ||
| 234 | if (dst && dst->ops->negative_advice) { | ||
| 235 | *dst_p = dst->ops->negative_advice(dst); | ||
| 236 | |||
| 237 | if (dst != *dst_p) { | ||
| 238 | extern void sk_reset_txq(struct sock *sk); | ||
| 239 | |||
| 240 | sk_reset_txq(sk); | ||
| 241 | } | ||
| 242 | } | ||
| 243 | } | ||
| 244 | |||
| 245 | static inline void dst_link_failure(struct sk_buff *skb) | 291 | static inline void dst_link_failure(struct sk_buff *skb) |
| 246 | { | 292 | { |
| 247 | struct dst_entry *dst = skb_dst(skb); | 293 | struct dst_entry *dst = skb_dst(skb); |
