aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorErez Shitrit <erezsh@mellanox.com>2017-02-01 12:10:05 -0500
committerDoug Ledford <dledford@redhat.com>2017-02-15 09:51:28 -0500
commit2b0841766a898aba84630fb723989a77a9d3b4e6 (patch)
tree7e0d03f6b923886ebcee28915e9a65706fee32ec
parent592e8b3226a2b6d116589908d96c45fa13302ad7 (diff)
IB/IPoIB: Add destination address when re-queue packet
When sending packet to destination that was not resolved yet via path query, the driver keeps the skb and tries to re-send it again when the path is resolved. But when re-sending via dev_queue_xmit the kernel doesn't call to dev_hard_header, so IPoIB needs to keep 20 bytes in the skb and to put the destination address inside them. In that way the dev_start_xmit will have the correct destination, and the driver won't take the destination from the skb->data, while nothing exists there, which causes to packet be be dropped. The test flow is: 1. Run the SM on remote node, 2. Restart the driver. 4. Ping some destination, 3. Observe that first ICMP request will be dropped. Fixes: fc791b633515 ("IB/ipoib: move back IB LL address into the hard header") Cc: <stable@vger.kernel.org> # v4.8+ Signed-off-by: Erez Shitrit <erezsh@mellanox.com> Signed-off-by: Noa Osherovich <noaos@mellanox.com> Signed-off-by: Leon Romanovsky <leon@kernel.org> Tested-by: Yuval Shaia <yuval.shaia@oracle.com> Signed-off-by: Doug Ledford <dledford@redhat.com>
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_main.c30
1 files changed, 17 insertions, 13 deletions
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c
index e3bfa8a99ad2..259c59f67394 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -721,6 +721,14 @@ int ipoib_check_sm_sendonly_fullmember_support(struct ipoib_dev_priv *priv)
721 return ret; 721 return ret;
722} 722}
723 723
724static void push_pseudo_header(struct sk_buff *skb, const char *daddr)
725{
726 struct ipoib_pseudo_header *phdr;
727
728 phdr = (struct ipoib_pseudo_header *)skb_push(skb, sizeof(*phdr));
729 memcpy(phdr->hwaddr, daddr, INFINIBAND_ALEN);
730}
731
724void ipoib_flush_paths(struct net_device *dev) 732void ipoib_flush_paths(struct net_device *dev)
725{ 733{
726 struct ipoib_dev_priv *priv = netdev_priv(dev); 734 struct ipoib_dev_priv *priv = netdev_priv(dev);
@@ -947,8 +955,7 @@ static void neigh_add_path(struct sk_buff *skb, u8 *daddr,
947 } 955 }
948 if (skb_queue_len(&neigh->queue) < 956 if (skb_queue_len(&neigh->queue) <
949 IPOIB_MAX_PATH_REC_QUEUE) { 957 IPOIB_MAX_PATH_REC_QUEUE) {
950 /* put pseudoheader back on for next time */ 958 push_pseudo_header(skb, neigh->daddr);
951 skb_push(skb, IPOIB_PSEUDO_LEN);
952 __skb_queue_tail(&neigh->queue, skb); 959 __skb_queue_tail(&neigh->queue, skb);
953 } else { 960 } else {
954 ipoib_warn(priv, "queue length limit %d. Packet drop.\n", 961 ipoib_warn(priv, "queue length limit %d. Packet drop.\n",
@@ -966,10 +973,12 @@ static void neigh_add_path(struct sk_buff *skb, u8 *daddr,
966 973
967 if (!path->query && path_rec_start(dev, path)) 974 if (!path->query && path_rec_start(dev, path))
968 goto err_path; 975 goto err_path;
969 if (skb_queue_len(&neigh->queue) < IPOIB_MAX_PATH_REC_QUEUE) 976 if (skb_queue_len(&neigh->queue) < IPOIB_MAX_PATH_REC_QUEUE) {
977 push_pseudo_header(skb, neigh->daddr);
970 __skb_queue_tail(&neigh->queue, skb); 978 __skb_queue_tail(&neigh->queue, skb);
971 else 979 } else {
972 goto err_drop; 980 goto err_drop;
981 }
973 } 982 }
974 983
975 spin_unlock_irqrestore(&priv->lock, flags); 984 spin_unlock_irqrestore(&priv->lock, flags);
@@ -1005,8 +1014,7 @@ static void unicast_arp_send(struct sk_buff *skb, struct net_device *dev,
1005 } 1014 }
1006 if (path) { 1015 if (path) {
1007 if (skb_queue_len(&path->queue) < IPOIB_MAX_PATH_REC_QUEUE) { 1016 if (skb_queue_len(&path->queue) < IPOIB_MAX_PATH_REC_QUEUE) {
1008 /* put pseudoheader back on for next time */ 1017 push_pseudo_header(skb, phdr->hwaddr);
1009 skb_push(skb, IPOIB_PSEUDO_LEN);
1010 __skb_queue_tail(&path->queue, skb); 1018 __skb_queue_tail(&path->queue, skb);
1011 } else { 1019 } else {
1012 ++dev->stats.tx_dropped; 1020 ++dev->stats.tx_dropped;
@@ -1038,8 +1046,7 @@ static void unicast_arp_send(struct sk_buff *skb, struct net_device *dev,
1038 return; 1046 return;
1039 } else if ((path->query || !path_rec_start(dev, path)) && 1047 } else if ((path->query || !path_rec_start(dev, path)) &&
1040 skb_queue_len(&path->queue) < IPOIB_MAX_PATH_REC_QUEUE) { 1048 skb_queue_len(&path->queue) < IPOIB_MAX_PATH_REC_QUEUE) {
1041 /* put pseudoheader back on for next time */ 1049 push_pseudo_header(skb, phdr->hwaddr);
1042 skb_push(skb, IPOIB_PSEUDO_LEN);
1043 __skb_queue_tail(&path->queue, skb); 1050 __skb_queue_tail(&path->queue, skb);
1044 } else { 1051 } else {
1045 ++dev->stats.tx_dropped; 1052 ++dev->stats.tx_dropped;
@@ -1120,8 +1127,7 @@ send_using_neigh:
1120 } 1127 }
1121 1128
1122 if (skb_queue_len(&neigh->queue) < IPOIB_MAX_PATH_REC_QUEUE) { 1129 if (skb_queue_len(&neigh->queue) < IPOIB_MAX_PATH_REC_QUEUE) {
1123 /* put pseudoheader back on for next time */ 1130 push_pseudo_header(skb, phdr->hwaddr);
1124 skb_push(skb, sizeof(*phdr));
1125 spin_lock_irqsave(&priv->lock, flags); 1131 spin_lock_irqsave(&priv->lock, flags);
1126 __skb_queue_tail(&neigh->queue, skb); 1132 __skb_queue_tail(&neigh->queue, skb);
1127 spin_unlock_irqrestore(&priv->lock, flags); 1133 spin_unlock_irqrestore(&priv->lock, flags);
@@ -1153,7 +1159,6 @@ static int ipoib_hard_header(struct sk_buff *skb,
1153 unsigned short type, 1159 unsigned short type,
1154 const void *daddr, const void *saddr, unsigned len) 1160 const void *daddr, const void *saddr, unsigned len)
1155{ 1161{
1156 struct ipoib_pseudo_header *phdr;
1157 struct ipoib_header *header; 1162 struct ipoib_header *header;
1158 1163
1159 header = (struct ipoib_header *) skb_push(skb, sizeof *header); 1164 header = (struct ipoib_header *) skb_push(skb, sizeof *header);
@@ -1166,8 +1171,7 @@ static int ipoib_hard_header(struct sk_buff *skb,
1166 * destination address into skb hard header so we can figure out where 1171 * destination address into skb hard header so we can figure out where
1167 * to send the packet later. 1172 * to send the packet later.
1168 */ 1173 */
1169 phdr = (struct ipoib_pseudo_header *) skb_push(skb, sizeof(*phdr)); 1174 push_pseudo_header(skb, daddr);
1170 memcpy(phdr->hwaddr, daddr, INFINIBAND_ALEN);
1171 1175
1172 return IPOIB_HARD_LEN; 1176 return IPOIB_HARD_LEN;
1173} 1177}