Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b13912bb authored by Roland Dreier's avatar Roland Dreier
Browse files

IPoIB: Call skb_dst_drop() once skb is enqueued for sending



Currently, IPoIB delays collecting send completions for TX packets in
order to batch work more efficiently.  It does skb_orphan() right after
queuing the packets so that destructors run early, to avoid problems
like holding socket send buffers for too long (since we might not
collect a send completion until a long time after the packet is
actually sent).

However, IPoIB clears IFF_XMIT_DST_RELEASE because it actually looks
at skb_dst() to update the PMTU when it gets a too-long packet.  This
means that the packets sitting in the TX ring with uncollected send
completions are holding a reference on the dst.  We've seen this lead
to pathological behavior with respect to route and neighbour GC.  The
easy fix for this is to call skb_dst_drop() when we call skb_orphan().

Also, give packets sent via connected mode (CM) the same skb_orphan()
/ skb_dst_drop() treatment that packets sent via datagram mode get.

Signed-off-by: default avatarRoland Dreier <roland@purestorage.com>
parent 5bd665f2
Loading
Loading
Loading
Loading
+3 −0
Original line number Original line Diff line number Diff line
@@ -752,6 +752,9 @@ void ipoib_cm_send(struct net_device *dev, struct sk_buff *skb, struct ipoib_cm_
		dev->trans_start = jiffies;
		dev->trans_start = jiffies;
		++tx->tx_head;
		++tx->tx_head;


		skb_orphan(skb);
		skb_dst_drop(skb);

		if (++priv->tx_outstanding == ipoib_sendq_size) {
		if (++priv->tx_outstanding == ipoib_sendq_size) {
			ipoib_dbg(priv, "TX ring 0x%x full, stopping kernel net queue\n",
			ipoib_dbg(priv, "TX ring 0x%x full, stopping kernel net queue\n",
				  tx->qp->qp_num);
				  tx->qp->qp_num);
+2 −1
Original line number Original line Diff line number Diff line
@@ -615,8 +615,9 @@ void ipoib_send(struct net_device *dev, struct sk_buff *skb,


		address->last_send = priv->tx_head;
		address->last_send = priv->tx_head;
		++priv->tx_head;
		++priv->tx_head;
		skb_orphan(skb);


		skb_orphan(skb);
		skb_dst_drop(skb);
	}
	}


	if (unlikely(priv->tx_outstanding > MAX_SEND_CQE))
	if (unlikely(priv->tx_outstanding > MAX_SEND_CQE))