diff options
author | David Miller <davem@davemloft.net> | 2011-12-02 11:52:44 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-12-05 15:20:20 -0500 |
commit | 17e6abeec4cb8df1e33ea0e2b889586c731a68be (patch) | |
tree | 0e1dedd8afb3fffe9c67a5f61ce85f8da2bedd71 /drivers/infiniband/ulp/ipoib | |
parent | 51e059bdd62f8da90973edf8a6180bd2c080f866 (diff) |
infiniband: ipoib: Sanitize neighbour handling in ipoib_main.c
Reduce the number of dst_get_neighbour_noref() calls within a single
call chain. Primarily by passing the neighbour pointer down to the
helper functions.
Handle dst_get_neighbour_noref() returning NULL in ipoib_start_xmit()
by incrementing the dropped counter and freeing the packet. We don't
want it to fall through into the ARP/RARP/multicast handling, since
that should only happen when skb_dst() is NULL.
Signed-off-by: David S. Miller <davem@davemloft.net>
Acked-by: Roland Dreier <roland@purestorage.com>
Diffstat (limited to 'drivers/infiniband/ulp/ipoib')
-rw-r--r-- | drivers/infiniband/ulp/ipoib/ipoib_main.c | 24 |
1 files changed, 12 insertions, 12 deletions
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c index eef6786c8de6..3514ca05deea 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_main.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c | |||
@@ -556,15 +556,13 @@ static int path_rec_start(struct net_device *dev, | |||
556 | } | 556 | } |
557 | 557 | ||
558 | /* called with rcu_read_lock */ | 558 | /* called with rcu_read_lock */ |
559 | static void neigh_add_path(struct sk_buff *skb, struct net_device *dev) | 559 | static void neigh_add_path(struct sk_buff *skb, struct neighbour *n, struct net_device *dev) |
560 | { | 560 | { |
561 | struct ipoib_dev_priv *priv = netdev_priv(dev); | 561 | struct ipoib_dev_priv *priv = netdev_priv(dev); |
562 | struct ipoib_path *path; | 562 | struct ipoib_path *path; |
563 | struct ipoib_neigh *neigh; | 563 | struct ipoib_neigh *neigh; |
564 | struct neighbour *n; | ||
565 | unsigned long flags; | 564 | unsigned long flags; |
566 | 565 | ||
567 | n = dst_get_neighbour_noref(skb_dst(skb)); | ||
568 | neigh = ipoib_neigh_alloc(n, skb->dev); | 566 | neigh = ipoib_neigh_alloc(n, skb->dev); |
569 | if (!neigh) { | 567 | if (!neigh) { |
570 | ++dev->stats.tx_dropped; | 568 | ++dev->stats.tx_dropped; |
@@ -638,16 +636,13 @@ err_drop: | |||
638 | } | 636 | } |
639 | 637 | ||
640 | /* called with rcu_read_lock */ | 638 | /* called with rcu_read_lock */ |
641 | static void ipoib_path_lookup(struct sk_buff *skb, struct net_device *dev) | 639 | static void ipoib_path_lookup(struct sk_buff *skb, struct neighbour *n, struct net_device *dev) |
642 | { | 640 | { |
643 | struct ipoib_dev_priv *priv = netdev_priv(skb->dev); | 641 | struct ipoib_dev_priv *priv = netdev_priv(skb->dev); |
644 | struct dst_entry *dst = skb_dst(skb); | ||
645 | struct neighbour *n; | ||
646 | 642 | ||
647 | /* Look up path record for unicasts */ | 643 | /* Look up path record for unicasts */ |
648 | n = dst_get_neighbour_noref(dst); | ||
649 | if (n->ha[4] != 0xff) { | 644 | if (n->ha[4] != 0xff) { |
650 | neigh_add_path(skb, dev); | 645 | neigh_add_path(skb, n, dev); |
651 | return; | 646 | return; |
652 | } | 647 | } |
653 | 648 | ||
@@ -723,12 +718,17 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
723 | unsigned long flags; | 718 | unsigned long flags; |
724 | 719 | ||
725 | rcu_read_lock(); | 720 | rcu_read_lock(); |
726 | if (likely(skb_dst(skb))) | 721 | if (likely(skb_dst(skb))) { |
727 | n = dst_get_neighbour_noref(skb_dst(skb)); | 722 | n = dst_get_neighbour_noref(skb_dst(skb)); |
728 | 723 | if (!n) { | |
724 | ++dev->stats.tx_dropped; | ||
725 | dev_kfree_skb_any(skb); | ||
726 | goto unlock; | ||
727 | } | ||
728 | } | ||
729 | if (likely(n)) { | 729 | if (likely(n)) { |
730 | if (unlikely(!*to_ipoib_neigh(n))) { | 730 | if (unlikely(!*to_ipoib_neigh(n))) { |
731 | ipoib_path_lookup(skb, dev); | 731 | ipoib_path_lookup(skb, n, dev); |
732 | goto unlock; | 732 | goto unlock; |
733 | } | 733 | } |
734 | 734 | ||
@@ -751,7 +751,7 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
751 | list_del(&neigh->list); | 751 | list_del(&neigh->list); |
752 | ipoib_neigh_free(dev, neigh); | 752 | ipoib_neigh_free(dev, neigh); |
753 | spin_unlock_irqrestore(&priv->lock, flags); | 753 | spin_unlock_irqrestore(&priv->lock, flags); |
754 | ipoib_path_lookup(skb, dev); | 754 | ipoib_path_lookup(skb, n, dev); |
755 | goto unlock; | 755 | goto unlock; |
756 | } | 756 | } |
757 | 757 | ||