} while (read_seqretry(&hh->hh_lock, seq));
skb_push(skb, hh_len);
- return hh->hh_output(skb);
+ return dev_queue_xmit(skb);
}
static inline int neigh_output(struct neighbour *n, struct sk_buff *skb)
{
struct hh_cache *hh = &n->hh;
- if (hh->hh_len)
+ if ((n->nud_state & NUD_CONNECTED) && hh->hh_len)
return neigh_hh_output(hh, skb);
else
return n->output(skb);
*/
static void neigh_suspect(struct neighbour *neigh)
{
- struct hh_cache *hh;
-
NEIGH_PRINTK2("neigh %p is suspected.\n", neigh);
neigh->output = neigh->ops->output;
-
- hh = &neigh->hh;
- if (hh->hh_len)
- hh->hh_output = neigh->ops->output;
}
/* Neighbour state is OK;
*/
static void neigh_connect(struct neighbour *neigh)
{
- struct hh_cache *hh;
-
NEIGH_PRINTK2("neigh %p is connected.\n", neigh);
neigh->output = neigh->ops->connected_output;
-
- hh = &neigh->hh;
- if (hh->hh_len)
- hh->hh_output = dev_queue_xmit;
}
static void neigh_periodic_work(struct work_struct *work)
/* Only one thread can come in here and initialize the
* hh_cache entry.
*/
- if (hh->hh_len)
- goto end;
-
- if (dev->header_ops->cache(n, hh, prot))
- goto end;
-
- if (n->nud_state & NUD_CONNECTED)
- hh->hh_output = dev_queue_xmit;
- else
- hh->hh_output = n->ops->output;
+ if (!hh->hh_len)
+ dev->header_ops->cache(n, hh, prot);
-end:
write_unlock_bh(&n->lock);
}
dst_metric(&r->dst, RTAX_RTTVAR)),
r->rt_key_tos,
-1,
- (r->dst.neighbour ?
- (r->dst.neighbour->hh.hh_output ==
- dev_queue_xmit) : 0),
+ (r->dst.neighbour &&
+ (r->dst.neighbour->nud_state & NUD_CONNECTED)) ?
+ 1 : 0,
r->rt_spec_dst, &len);
seq_printf(seq, "%*s\n", 127 - len, "");