int                     (*input)(struct sk_buff *);
        int                     (*output)(struct sk_buff *);
 
-       int                     flags;
+       unsigned short          flags;
 #define DST_HOST               0x0001
 #define DST_NOXFRM             0x0002
 #define DST_NOPOLICY           0x0004
 #define DST_FAKE_RTABLE                0x0080
 #define DST_XFRM_TUNNEL                0x0100
 
+       unsigned short          pending_confirm;
+
        short                   error;
        short                   obsolete;
        unsigned short          header_len;     /* more space at head required */
 
 extern int dst_discard(struct sk_buff *skb);
 extern void *dst_alloc(struct dst_ops *ops, struct net_device *dev,
-                      int initial_ref, int initial_obsolete, int flags);
+                      int initial_ref, int initial_obsolete,
+                      unsigned short flags);
 extern void __dst_free(struct dst_entry *dst);
 extern struct dst_entry *dst_destroy(struct dst_entry *dst);
 
 
 static inline void dst_confirm(struct dst_entry *dst)
 {
-       if (dst) {
-               struct neighbour *n;
+       dst->pending_confirm = 1;
+}
 
-               rcu_read_lock();
-               n = dst_get_neighbour_noref(dst);
-               neigh_confirm(n);
-               rcu_read_unlock();
+static inline int dst_neigh_output(struct dst_entry *dst, struct neighbour *n,
+                                  struct sk_buff *skb)
+{
+       struct hh_cache *hh;
+
+       if (unlikely(dst->pending_confirm)) {
+               n->confirmed = jiffies;
+               dst->pending_confirm = 0;
        }
+
+       hh = &n->hh;
+       if ((n->nud_state & NUD_CONNECTED) && hh->hh_len)
+               return neigh_hh_output(hh, skb);
+       else
+               return n->output(n, skb);
 }
 
 static inline struct neighbour *dst_neigh_lookup(const struct dst_entry *dst, const void *daddr)
 
 
 #define neigh_hold(n)  atomic_inc(&(n)->refcnt)
 
-static inline void neigh_confirm(struct neighbour *neigh)
-{
-       if (neigh)
-               neigh->confirmed = jiffies;
-}
-
 static inline int neigh_event_send(struct neighbour *neigh, struct sk_buff *skb)
 {
        unsigned long now = jiffies;
        return dev_queue_xmit(skb);
 }
 
-static inline int neigh_output(struct neighbour *n, struct sk_buff *skb)
-{
-       struct hh_cache *hh = &n->hh;
-       if ((n->nud_state & NUD_CONNECTED) && hh->hh_len)
-               return neigh_hh_output(hh, skb);
-       else
-               return n->output(n, skb);
-}
-
 static inline struct neighbour *
 __neigh_lookup(struct neigh_table *tbl, const void *pkey, struct net_device *dev, int creat)
 {
 
 const u32 dst_default_metrics[RTAX_MAX];
 
 void *dst_alloc(struct dst_ops *ops, struct net_device *dev,
-               int initial_ref, int initial_obsolete, int flags)
+               int initial_ref, int initial_obsolete, unsigned short flags)
 {
        struct dst_entry *dst;
 
        dst->__use = 0;
        dst->lastuse = jiffies;
        dst->flags = flags;
+       dst->pending_confirm = 0;
        dst->next = NULL;
        if (!(flags & DST_NOCOUNT))
                dst_entries_add(ops, 1);
 
        if (unlikely(!neigh))
                neigh = __neigh_create(&arp_tbl, &nexthop, dev, false);
        if (neigh) {
-               int res = neigh_output(neigh, skb);
+               int res = dst_neigh_output(dst, neigh, skb);
 
                rcu_read_unlock_bh();
                return res;
 
        if (sysctl_tcp_nometrics_save)
                return;
 
-       dst_confirm(dst);
-
        if (dst && (dst->flags & DST_HOST)) {
                const struct inet_connection_sock *icsk = inet_csk(sk);
                int m;
                unsigned long rtt;
 
+               dst_confirm(dst);
+
                if (icsk->icsk_backoff || !tp->srtt) {
                        /* This session failed to estimate rtt. Why?
                         * Probably, no packets returned in time.
                        tcp_cong_avoid(sk, ack, prior_in_flight);
        }
 
-       if ((flag & FLAG_FORWARD_PROGRESS) || !(flag & FLAG_NOT_DUP))
-               dst_confirm(__sk_dst_get(sk));
-
+       if ((flag & FLAG_FORWARD_PROGRESS) || !(flag & FLAG_NOT_DUP)) {
+               struct dst_entry *dst = __sk_dst_get(sk);
+               if (dst)
+                       dst_confirm(dst);
+       }
        return 1;
 
 no_queue:
 
                case TCP_FIN_WAIT1:
                        if (tp->snd_una == tp->write_seq) {
+                               struct dst_entry *dst;
+
                                tcp_set_state(sk, TCP_FIN_WAIT2);
                                sk->sk_shutdown |= SEND_SHUTDOWN;
-                               dst_confirm(__sk_dst_get(sk));
+
+                               dst = __sk_dst_get(sk);
+                               if (dst)
+                                       dst_confirm(dst);
 
                                if (!sock_flag(sk, SOCK_DEAD))
                                        /* Wake up lingering close() */
 
        rcu_read_lock();
        neigh = dst_get_neighbour_noref(dst);
        if (neigh) {
-               int res = neigh_output(neigh, skb);
+               int res = dst_neigh_output(dst, neigh, skb);
 
                rcu_read_unlock();
                return res;