aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/netdevice.h1
-rw-r--r--include/net/neighbour.h4
-rw-r--r--net/core/neighbour.c25
-rw-r--r--net/ipv4/route.c6
4 files changed, 7 insertions, 29 deletions
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index f84dfd25c431..52c4e3835aa6 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -254,7 +254,6 @@ struct netdev_hw_addr_list {
254struct hh_cache { 254struct hh_cache {
255 u16 hh_len; 255 u16 hh_len;
256 u16 __pad; 256 u16 __pad;
257 int (*hh_output)(struct sk_buff *skb);
258 seqlock_t hh_lock; 257 seqlock_t hh_lock;
259 258
260 /* cached hardware header; allow for machine alignment needs. */ 259 /* cached hardware header; allow for machine alignment needs. */
diff --git a/include/net/neighbour.h b/include/net/neighbour.h
index 97990ddca66c..60bac8112d86 100644
--- a/include/net/neighbour.h
+++ b/include/net/neighbour.h
@@ -340,13 +340,13 @@ static inline int neigh_hh_output(struct hh_cache *hh, struct sk_buff *skb)
340 } while (read_seqretry(&hh->hh_lock, seq)); 340 } while (read_seqretry(&hh->hh_lock, seq));
341 341
342 skb_push(skb, hh_len); 342 skb_push(skb, hh_len);
343 return hh->hh_output(skb); 343 return dev_queue_xmit(skb);
344} 344}
345 345
346static inline int neigh_output(struct neighbour *n, struct sk_buff *skb) 346static inline int neigh_output(struct neighbour *n, struct sk_buff *skb)
347{ 347{
348 struct hh_cache *hh = &n->hh; 348 struct hh_cache *hh = &n->hh;
349 if (hh->hh_len) 349 if ((n->nud_state & NUD_CONNECTED) && hh->hh_len)
350 return neigh_hh_output(hh, skb); 350 return neigh_hh_output(hh, skb);
351 else 351 else
352 return n->output(skb); 352 return n->output(skb);
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index c22def5ae486..2feda6e7a31d 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -720,15 +720,9 @@ EXPORT_SYMBOL(neigh_destroy);
720 */ 720 */
721static void neigh_suspect(struct neighbour *neigh) 721static void neigh_suspect(struct neighbour *neigh)
722{ 722{
723 struct hh_cache *hh;
724
725 NEIGH_PRINTK2("neigh %p is suspected.\n", neigh); 723 NEIGH_PRINTK2("neigh %p is suspected.\n", neigh);
726 724
727 neigh->output = neigh->ops->output; 725 neigh->output = neigh->ops->output;
728
729 hh = &neigh->hh;
730 if (hh->hh_len)
731 hh->hh_output = neigh->ops->output;
732} 726}
733 727
734/* Neighbour state is OK; 728/* Neighbour state is OK;
@@ -738,15 +732,9 @@ static void neigh_suspect(struct neighbour *neigh)
738 */ 732 */
739static void neigh_connect(struct neighbour *neigh) 733static void neigh_connect(struct neighbour *neigh)
740{ 734{
741 struct hh_cache *hh;
742
743 NEIGH_PRINTK2("neigh %p is connected.\n", neigh); 735 NEIGH_PRINTK2("neigh %p is connected.\n", neigh);
744 736
745 neigh->output = neigh->ops->connected_output; 737 neigh->output = neigh->ops->connected_output;
746
747 hh = &neigh->hh;
748 if (hh->hh_len)
749 hh->hh_output = dev_queue_xmit;
750} 738}
751 739
752static void neigh_periodic_work(struct work_struct *work) 740static void neigh_periodic_work(struct work_struct *work)
@@ -1215,18 +1203,9 @@ static void neigh_hh_init(struct neighbour *n, struct dst_entry *dst)
1215 /* Only one thread can come in here and initialize the 1203 /* Only one thread can come in here and initialize the
1216 * hh_cache entry. 1204 * hh_cache entry.
1217 */ 1205 */
1218 if (hh->hh_len) 1206 if (!hh->hh_len)
1219 goto end; 1207 dev->header_ops->cache(n, hh, prot);
1220
1221 if (dev->header_ops->cache(n, hh, prot))
1222 goto end;
1223
1224 if (n->nud_state & NUD_CONNECTED)
1225 hh->hh_output = dev_queue_xmit;
1226 else
1227 hh->hh_output = n->ops->output;
1228 1208
1229end:
1230 write_unlock_bh(&n->lock); 1209 write_unlock_bh(&n->lock);
1231} 1210}
1232 1211
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index a52bb74d2612..bcf9bb508200 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -427,9 +427,9 @@ static int rt_cache_seq_show(struct seq_file *seq, void *v)
427 dst_metric(&r->dst, RTAX_RTTVAR)), 427 dst_metric(&r->dst, RTAX_RTTVAR)),
428 r->rt_key_tos, 428 r->rt_key_tos,
429 -1, 429 -1,
430 (r->dst.neighbour ? 430 (r->dst.neighbour &&
431 (r->dst.neighbour->hh.hh_output == 431 (r->dst.neighbour->nud_state & NUD_CONNECTED)) ?
432 dev_queue_xmit) : 0), 432 1 : 0,
433 r->rt_spec_dst, &len); 433 r->rt_spec_dst, &len);
434 434
435 seq_printf(seq, "%*s\n", 127 - len, ""); 435 seq_printf(seq, "%*s\n", 127 - len, "");