]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - include/net/sock.h
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
[karo-tx-linux.git] / include / net / sock.h
index 94e65fd703548dd40e16c30207fd55c879ed0b60..9ccefa5c5487863e69831c3bf45e4f0edf78eb65 100644 (file)
@@ -240,6 +240,7 @@ struct sock_common {
   *    @sk_wq: sock wait queue and async head
   *    @sk_rx_dst: receive input route used by early demux
   *    @sk_dst_cache: destination cache
+  *    @sk_dst_pending_confirm: need to confirm neighbour
   *    @sk_policy: flow policy
   *    @sk_receive_queue: incoming packets
   *    @sk_wmem_alloc: transmit queue bytes committed
@@ -393,6 +394,8 @@ struct sock {
        struct sk_buff_head     sk_write_queue;
        __s32                   sk_peek_off;
        int                     sk_write_pending;
+       __u32                   sk_dst_pending_confirm;
+       /* Note: 32bit hole on 64bit arches */
        long                    sk_sndtimeo;
        struct timer_list       sk_timer;
        __u32                   sk_priority;
@@ -1764,6 +1767,7 @@ static inline void dst_negative_advice(struct sock *sk)
                if (ndst != dst) {
                        rcu_assign_pointer(sk->sk_dst_cache, ndst);
                        sk_tx_queue_clear(sk);
+                       sk->sk_dst_pending_confirm = 0;
                }
        }
 }
@@ -1774,6 +1778,7 @@ __sk_dst_set(struct sock *sk, struct dst_entry *dst)
        struct dst_entry *old_dst;
 
        sk_tx_queue_clear(sk);
+       sk->sk_dst_pending_confirm = 0;
        /*
         * This can be called while sk is owned by the caller only,
         * with no state that can be checked in a rcu_dereference_check() cond
@@ -1789,6 +1794,7 @@ sk_dst_set(struct sock *sk, struct dst_entry *dst)
        struct dst_entry *old_dst;
 
        sk_tx_queue_clear(sk);
+       sk->sk_dst_pending_confirm = 0;
        old_dst = xchg((__force struct dst_entry **)&sk->sk_dst_cache, dst);
        dst_release(old_dst);
 }
@@ -1809,6 +1815,26 @@ struct dst_entry *__sk_dst_check(struct sock *sk, u32 cookie);
 
 struct dst_entry *sk_dst_check(struct sock *sk, u32 cookie);
 
+static inline void sk_dst_confirm(struct sock *sk)
+{
+       if (!sk->sk_dst_pending_confirm)
+               sk->sk_dst_pending_confirm = 1;
+}
+
+static inline void sock_confirm_neigh(struct sk_buff *skb, struct neighbour *n)
+{
+       if (skb_get_dst_pending_confirm(skb)) {
+               struct sock *sk = skb->sk;
+               unsigned long now = jiffies;
+
+               /* avoid dirtying neighbour */
+               if (n->confirmed != now)
+                       n->confirmed = now;
+               if (sk && sk->sk_dst_pending_confirm)
+                       sk->sk_dst_pending_confirm = 0;
+       }
+}
+
 bool sk_mc_loop(struct sock *sk);
 
 static inline bool sk_can_gso(const struct sock *sk)
@@ -2009,7 +2035,9 @@ void sk_reset_timer(struct sock *sk, struct timer_list *timer,
 void sk_stop_timer(struct sock *sk, struct timer_list *timer);
 
 int __sk_queue_drop_skb(struct sock *sk, struct sk_buff *skb,
-                       unsigned int flags);
+                       unsigned int flags,
+                       void (*destructor)(struct sock *sk,
+                                          struct sk_buff *skb));
 int __sock_queue_rcv_skb(struct sock *sk, struct sk_buff *skb);
 int sock_queue_rcv_skb(struct sock *sk, struct sk_buff *skb);