diff options
author | Roland Dreier <roland@purestorage.com> | 2012-02-07 09:51:21 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-02-29 19:33:45 -0500 |
commit | aca5efd17c1a1ed6303537792517e7352cf74edd (patch) | |
tree | 7f05fdb94bc1c48bdaf578e31d94bce00144dbe1 /drivers/infiniband/ulp/ipoib/ipoib_main.c | |
parent | c3e8445f6ec4ad66c5143d6df8528f7440429b91 (diff) |
IPoIB: Stop lying about hard_header_len and use skb->cb to stash LL addresses
[ Upstream commit 936d7de3d736e0737542641269436f4b5968e9ef ]
Commit a0417fa3a18a ("net: Make qdisc_skb_cb upper size bound
explicit.") made it possible for a netdev driver to use skb->cb
between its header_ops.create method and its .ndo_start_xmit
method. Use this in ipoib_hard_header() to stash away the LL address
(GID + QPN), instead of the "ipoib_pseudoheader" hack. This allows
IPoIB to stop lying about its hard_header_len, which will let us fix
the L2 check for GRO.
Signed-off-by: Roland Dreier <roland@purestorage.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/infiniband/ulp/ipoib/ipoib_main.c')
-rw-r--r-- | drivers/infiniband/ulp/ipoib/ipoib_main.c | 55 |
1 files changed, 19 insertions, 36 deletions
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c index a98c414978e..b811444dcdd 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_main.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c | |||
@@ -658,7 +658,7 @@ static void ipoib_path_lookup(struct sk_buff *skb, struct net_device *dev) | |||
658 | } | 658 | } |
659 | 659 | ||
660 | static void unicast_arp_send(struct sk_buff *skb, struct net_device *dev, | 660 | static void unicast_arp_send(struct sk_buff *skb, struct net_device *dev, |
661 | struct ipoib_pseudoheader *phdr) | 661 | struct ipoib_cb *cb) |
662 | { | 662 | { |
663 | struct ipoib_dev_priv *priv = netdev_priv(dev); | 663 | struct ipoib_dev_priv *priv = netdev_priv(dev); |
664 | struct ipoib_path *path; | 664 | struct ipoib_path *path; |
@@ -666,17 +666,15 @@ static void unicast_arp_send(struct sk_buff *skb, struct net_device *dev, | |||
666 | 666 | ||
667 | spin_lock_irqsave(&priv->lock, flags); | 667 | spin_lock_irqsave(&priv->lock, flags); |
668 | 668 | ||
669 | path = __path_find(dev, phdr->hwaddr + 4); | 669 | path = __path_find(dev, cb->hwaddr + 4); |
670 | if (!path || !path->valid) { | 670 | if (!path || !path->valid) { |
671 | int new_path = 0; | 671 | int new_path = 0; |
672 | 672 | ||
673 | if (!path) { | 673 | if (!path) { |
674 | path = path_rec_create(dev, phdr->hwaddr + 4); | 674 | path = path_rec_create(dev, cb->hwaddr + 4); |
675 | new_path = 1; | 675 | new_path = 1; |
676 | } | 676 | } |
677 | if (path) { | 677 | if (path) { |
678 | /* put pseudoheader back on for next time */ | ||
679 | skb_push(skb, sizeof *phdr); | ||
680 | __skb_queue_tail(&path->queue, skb); | 678 | __skb_queue_tail(&path->queue, skb); |
681 | 679 | ||
682 | if (!path->query && path_rec_start(dev, path)) { | 680 | if (!path->query && path_rec_start(dev, path)) { |
@@ -700,12 +698,10 @@ static void unicast_arp_send(struct sk_buff *skb, struct net_device *dev, | |||
700 | be16_to_cpu(path->pathrec.dlid)); | 698 | be16_to_cpu(path->pathrec.dlid)); |
701 | 699 | ||
702 | spin_unlock_irqrestore(&priv->lock, flags); | 700 | spin_unlock_irqrestore(&priv->lock, flags); |
703 | ipoib_send(dev, skb, path->ah, IPOIB_QPN(phdr->hwaddr)); | 701 | ipoib_send(dev, skb, path->ah, IPOIB_QPN(cb->hwaddr)); |
704 | return; | 702 | return; |
705 | } else if ((path->query || !path_rec_start(dev, path)) && | 703 | } else if ((path->query || !path_rec_start(dev, path)) && |
706 | skb_queue_len(&path->queue) < IPOIB_MAX_PATH_REC_QUEUE) { | 704 | skb_queue_len(&path->queue) < IPOIB_MAX_PATH_REC_QUEUE) { |
707 | /* put pseudoheader back on for next time */ | ||
708 | skb_push(skb, sizeof *phdr); | ||
709 | __skb_queue_tail(&path->queue, skb); | 705 | __skb_queue_tail(&path->queue, skb); |
710 | } else { | 706 | } else { |
711 | ++dev->stats.tx_dropped; | 707 | ++dev->stats.tx_dropped; |
@@ -774,16 +770,14 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
774 | dev_kfree_skb_any(skb); | 770 | dev_kfree_skb_any(skb); |
775 | } | 771 | } |
776 | } else { | 772 | } else { |
777 | struct ipoib_pseudoheader *phdr = | 773 | struct ipoib_cb *cb = (struct ipoib_cb *) skb->cb; |
778 | (struct ipoib_pseudoheader *) skb->data; | ||
779 | skb_pull(skb, sizeof *phdr); | ||
780 | 774 | ||
781 | if (phdr->hwaddr[4] == 0xff) { | 775 | if (cb->hwaddr[4] == 0xff) { |
782 | /* Add in the P_Key for multicast*/ | 776 | /* Add in the P_Key for multicast*/ |
783 | phdr->hwaddr[8] = (priv->pkey >> 8) & 0xff; | 777 | cb->hwaddr[8] = (priv->pkey >> 8) & 0xff; |
784 | phdr->hwaddr[9] = priv->pkey & 0xff; | 778 | cb->hwaddr[9] = priv->pkey & 0xff; |
785 | 779 | ||
786 | ipoib_mcast_send(dev, phdr->hwaddr + 4, skb); | 780 | ipoib_mcast_send(dev, cb->hwaddr + 4, skb); |
787 | } else { | 781 | } else { |
788 | /* unicast GID -- should be ARP or RARP reply */ | 782 | /* unicast GID -- should be ARP or RARP reply */ |
789 | 783 | ||
@@ -792,14 +786,14 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
792 | ipoib_warn(priv, "Unicast, no %s: type %04x, QPN %06x %pI6\n", | 786 | ipoib_warn(priv, "Unicast, no %s: type %04x, QPN %06x %pI6\n", |
793 | skb_dst(skb) ? "neigh" : "dst", | 787 | skb_dst(skb) ? "neigh" : "dst", |
794 | be16_to_cpup((__be16 *) skb->data), | 788 | be16_to_cpup((__be16 *) skb->data), |
795 | IPOIB_QPN(phdr->hwaddr), | 789 | IPOIB_QPN(cb->hwaddr), |
796 | phdr->hwaddr + 4); | 790 | cb->hwaddr + 4); |
797 | dev_kfree_skb_any(skb); | 791 | dev_kfree_skb_any(skb); |
798 | ++dev->stats.tx_dropped; | 792 | ++dev->stats.tx_dropped; |
799 | goto unlock; | 793 | goto unlock; |
800 | } | 794 | } |
801 | 795 | ||
802 | unicast_arp_send(skb, dev, phdr); | 796 | unicast_arp_send(skb, dev, cb); |
803 | } | 797 | } |
804 | } | 798 | } |
805 | unlock: | 799 | unlock: |
@@ -825,8 +819,6 @@ static int ipoib_hard_header(struct sk_buff *skb, | |||
825 | const void *daddr, const void *saddr, unsigned len) | 819 | const void *daddr, const void *saddr, unsigned len) |
826 | { | 820 | { |
827 | struct ipoib_header *header; | 821 | struct ipoib_header *header; |
828 | struct dst_entry *dst; | ||
829 | struct neighbour *n; | ||
830 | 822 | ||
831 | header = (struct ipoib_header *) skb_push(skb, sizeof *header); | 823 | header = (struct ipoib_header *) skb_push(skb, sizeof *header); |
832 | 824 | ||
@@ -834,18 +826,13 @@ static int ipoib_hard_header(struct sk_buff *skb, | |||
834 | header->reserved = 0; | 826 | header->reserved = 0; |
835 | 827 | ||
836 | /* | 828 | /* |
837 | * If we don't have a neighbour structure, stuff the | 829 | * If we don't have a dst_entry structure, stuff the |
838 | * destination address onto the front of the skb so we can | 830 | * destination address into skb->cb so we can figure out where |
839 | * figure out where to send the packet later. | 831 | * to send the packet later. |
840 | */ | 832 | */ |
841 | dst = skb_dst(skb); | 833 | if (!skb_dst(skb)) { |
842 | n = NULL; | 834 | struct ipoib_cb *cb = (struct ipoib_cb *) skb->cb; |
843 | if (dst) | 835 | memcpy(cb->hwaddr, daddr, INFINIBAND_ALEN); |
844 | n = dst_get_neighbour_raw(dst); | ||
845 | if ((!dst || !n) && daddr) { | ||
846 | struct ipoib_pseudoheader *phdr = | ||
847 | (struct ipoib_pseudoheader *) skb_push(skb, sizeof *phdr); | ||
848 | memcpy(phdr->hwaddr, daddr, INFINIBAND_ALEN); | ||
849 | } | 836 | } |
850 | 837 | ||
851 | return 0; | 838 | return 0; |
@@ -1021,11 +1008,7 @@ static void ipoib_setup(struct net_device *dev) | |||
1021 | 1008 | ||
1022 | dev->flags |= IFF_BROADCAST | IFF_MULTICAST; | 1009 | dev->flags |= IFF_BROADCAST | IFF_MULTICAST; |
1023 | 1010 | ||
1024 | /* | 1011 | dev->hard_header_len = IPOIB_ENCAP_LEN; |
1025 | * We add in INFINIBAND_ALEN to allow for the destination | ||
1026 | * address "pseudoheader" for skbs without neighbour struct. | ||
1027 | */ | ||
1028 | dev->hard_header_len = IPOIB_ENCAP_LEN + INFINIBAND_ALEN; | ||
1029 | dev->addr_len = INFINIBAND_ALEN; | 1012 | dev->addr_len = INFINIBAND_ALEN; |
1030 | dev->type = ARPHRD_INFINIBAND; | 1013 | dev->type = ARPHRD_INFINIBAND; |
1031 | dev->tx_queue_len = ipoib_sendq_size * 2; | 1014 | dev->tx_queue_len = ipoib_sendq_size * 2; |