diff options
author | Roland Dreier <roland@purestorage.com> | 2012-02-07 09:51:21 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-02-08 18:26:54 -0500 |
commit | 936d7de3d736e0737542641269436f4b5968e9ef (patch) | |
tree | d83c1f3ce184202d31ade4fe46e78b6b7100e0ae | |
parent | a1728800bed3b93b231d99e97c756f622b9991c2 (diff) |
IPoIB: Stop lying about hard_header_len and use skb->cb to stash LL addresses
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>
-rw-r--r-- | drivers/infiniband/ulp/ipoib/ipoib.h | 6 | ||||
-rw-r--r-- | drivers/infiniband/ulp/ipoib/ipoib_main.c | 55 | ||||
-rw-r--r-- | drivers/infiniband/ulp/ipoib/ipoib_multicast.c | 10 |
3 files changed, 24 insertions, 47 deletions
diff --git a/drivers/infiniband/ulp/ipoib/ipoib.h b/drivers/infiniband/ulp/ipoib/ipoib.h index b3cc1e062b17..86df632ea612 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib.h +++ b/drivers/infiniband/ulp/ipoib/ipoib.h | |||
@@ -44,6 +44,7 @@ | |||
44 | #include <linux/mutex.h> | 44 | #include <linux/mutex.h> |
45 | 45 | ||
46 | #include <net/neighbour.h> | 46 | #include <net/neighbour.h> |
47 | #include <net/sch_generic.h> | ||
47 | 48 | ||
48 | #include <linux/atomic.h> | 49 | #include <linux/atomic.h> |
49 | 50 | ||
@@ -117,8 +118,9 @@ struct ipoib_header { | |||
117 | u16 reserved; | 118 | u16 reserved; |
118 | }; | 119 | }; |
119 | 120 | ||
120 | struct ipoib_pseudoheader { | 121 | struct ipoib_cb { |
121 | u8 hwaddr[INFINIBAND_ALEN]; | 122 | struct qdisc_skb_cb qdisc_cb; |
123 | u8 hwaddr[INFINIBAND_ALEN]; | ||
122 | }; | 124 | }; |
123 | 125 | ||
124 | /* Used for all multicast joins (broadcast, IPv4 mcast and IPv6 mcast) */ | 126 | /* Used for all multicast joins (broadcast, IPv4 mcast and IPv6 mcast) */ |
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c index 3514ca05deea..3974c290b667 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_main.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c | |||
@@ -653,7 +653,7 @@ static void ipoib_path_lookup(struct sk_buff *skb, struct neighbour *n, struct n | |||
653 | } | 653 | } |
654 | 654 | ||
655 | static void unicast_arp_send(struct sk_buff *skb, struct net_device *dev, | 655 | static void unicast_arp_send(struct sk_buff *skb, struct net_device *dev, |
656 | struct ipoib_pseudoheader *phdr) | 656 | struct ipoib_cb *cb) |
657 | { | 657 | { |
658 | struct ipoib_dev_priv *priv = netdev_priv(dev); | 658 | struct ipoib_dev_priv *priv = netdev_priv(dev); |
659 | struct ipoib_path *path; | 659 | struct ipoib_path *path; |
@@ -661,17 +661,15 @@ static void unicast_arp_send(struct sk_buff *skb, struct net_device *dev, | |||
661 | 661 | ||
662 | spin_lock_irqsave(&priv->lock, flags); | 662 | spin_lock_irqsave(&priv->lock, flags); |
663 | 663 | ||
664 | path = __path_find(dev, phdr->hwaddr + 4); | 664 | path = __path_find(dev, cb->hwaddr + 4); |
665 | if (!path || !path->valid) { | 665 | if (!path || !path->valid) { |
666 | int new_path = 0; | 666 | int new_path = 0; |
667 | 667 | ||
668 | if (!path) { | 668 | if (!path) { |
669 | path = path_rec_create(dev, phdr->hwaddr + 4); | 669 | path = path_rec_create(dev, cb->hwaddr + 4); |
670 | new_path = 1; | 670 | new_path = 1; |
671 | } | 671 | } |
672 | if (path) { | 672 | if (path) { |
673 | /* put pseudoheader back on for next time */ | ||
674 | skb_push(skb, sizeof *phdr); | ||
675 | __skb_queue_tail(&path->queue, skb); | 673 | __skb_queue_tail(&path->queue, skb); |
676 | 674 | ||
677 | if (!path->query && path_rec_start(dev, path)) { | 675 | if (!path->query && path_rec_start(dev, path)) { |
@@ -695,12 +693,10 @@ static void unicast_arp_send(struct sk_buff *skb, struct net_device *dev, | |||
695 | be16_to_cpu(path->pathrec.dlid)); | 693 | be16_to_cpu(path->pathrec.dlid)); |
696 | 694 | ||
697 | spin_unlock_irqrestore(&priv->lock, flags); | 695 | spin_unlock_irqrestore(&priv->lock, flags); |
698 | ipoib_send(dev, skb, path->ah, IPOIB_QPN(phdr->hwaddr)); | 696 | ipoib_send(dev, skb, path->ah, IPOIB_QPN(cb->hwaddr)); |
699 | return; | 697 | return; |
700 | } else if ((path->query || !path_rec_start(dev, path)) && | 698 | } else if ((path->query || !path_rec_start(dev, path)) && |
701 | skb_queue_len(&path->queue) < IPOIB_MAX_PATH_REC_QUEUE) { | 699 | skb_queue_len(&path->queue) < IPOIB_MAX_PATH_REC_QUEUE) { |
702 | /* put pseudoheader back on for next time */ | ||
703 | skb_push(skb, sizeof *phdr); | ||
704 | __skb_queue_tail(&path->queue, skb); | 700 | __skb_queue_tail(&path->queue, skb); |
705 | } else { | 701 | } else { |
706 | ++dev->stats.tx_dropped; | 702 | ++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_noref_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; |
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c index f7ff9dd66cda..20ebc6fd1bb9 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c | |||
@@ -262,21 +262,13 @@ static int ipoib_mcast_join_finish(struct ipoib_mcast *mcast, | |||
262 | netif_tx_lock_bh(dev); | 262 | netif_tx_lock_bh(dev); |
263 | while (!skb_queue_empty(&mcast->pkt_queue)) { | 263 | while (!skb_queue_empty(&mcast->pkt_queue)) { |
264 | struct sk_buff *skb = skb_dequeue(&mcast->pkt_queue); | 264 | struct sk_buff *skb = skb_dequeue(&mcast->pkt_queue); |
265 | struct dst_entry *dst = skb_dst(skb); | ||
266 | struct neighbour *n = NULL; | ||
267 | 265 | ||
268 | netif_tx_unlock_bh(dev); | 266 | netif_tx_unlock_bh(dev); |
269 | 267 | ||
270 | skb->dev = dev; | 268 | skb->dev = dev; |
271 | if (dst) | ||
272 | n = dst_get_neighbour_noref_raw(dst); | ||
273 | if (!dst || !n) { | ||
274 | /* put pseudoheader back on for next time */ | ||
275 | skb_push(skb, sizeof (struct ipoib_pseudoheader)); | ||
276 | } | ||
277 | |||
278 | if (dev_queue_xmit(skb)) | 269 | if (dev_queue_xmit(skb)) |
279 | ipoib_warn(priv, "dev_queue_xmit failed to requeue packet\n"); | 270 | ipoib_warn(priv, "dev_queue_xmit failed to requeue packet\n"); |
271 | |||
280 | netif_tx_lock_bh(dev); | 272 | netif_tx_lock_bh(dev); |
281 | } | 273 | } |
282 | netif_tx_unlock_bh(dev); | 274 | netif_tx_unlock_bh(dev); |