From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-bn3nam01on0094.outbound.protection.outlook.com ([104.47.33.94]:25184 "EHLO NAM01-BN3-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1031929AbeCAPYJ (ORCPT ); Thu, 1 Mar 2018 10:24:09 -0500 From: Sasha Levin To: "stable@vger.kernel.org" , "stable-commits@vger.kernel.org" CC: Julian Wiedmann , Ursula Braun , "David S . Miller" , Sasha Levin Subject: [added to the 4.1 stable tree] s390/qeth: no ETH header for outbound AF_IUCV Date: Thu, 1 Mar 2018 15:22:46 +0000 Message-ID: <20180301152116.1486-32-alexander.levin@microsoft.com> References: <20180301152116.1486-1-alexander.levin@microsoft.com> In-Reply-To: <20180301152116.1486-1-alexander.levin@microsoft.com> Content-Language: en-US Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Sender: stable-owner@vger.kernel.org List-ID: From: Julian Wiedmann This patch has been added to the 4.1 stable tree. If you have any objections, please let us know. =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D [ Upstream commit acd9776b5c45ef02d1a210969a6fcc058afb76e3 ] With AF_IUCV traffic, the skb passed to hard_start_xmit() has a 14 byte slot at skb->data, intended for an ETH header. qeth_l3_fill_af_iucv_hdr() fills this ETH header... and then immediately moves it to the skb's headroom, where it disappears and is never seen again. But it's still possible for us to return NETDEV_TX_BUSY after the skb has been modified. Since we didn't get a private copy of the skb, the next time the skb is delivered to hard_start_xmit() it no longer has the expected layout (we moved the ETH header to the headroom, so skb->data now starts at the IUCV_TRANS header). So when qeth_l3_fill_af_iucv_hdr() does another round of rebuilding, the resulting qeth header ends up all wrong. On transmission, the buffer is then rejected by the HiperSockets device with SBALF15 =3D x'04'. When this error is passed back to af_iucv as TX_NOTIFY_UNREACHABLE, it tears down the offending socket. As the ETH header for AF_IUCV serves no purpose, just align the code to what we do for IP traffic on L3 HiperSockets: keep the ETH header at skb->data, and pass down data_offset =3D ETH_HLEN to qeth_fill_buffer(). When mapping the payload into the SBAL elements, the ETH header is then stripped off. This avoids the skb manipulations in qeth_l3_fill_af_iucv_hdr(), and any buffer re-entering hard_start_xmit() after NETDEV_TX_BUSY is now processed properly. Signed-off-by: Julian Wiedmann Signed-off-by: Ursula Braun Signed-off-by: David S. Miller Signed-off-by: Sasha Levin --- drivers/s390/net/qeth_l3_main.c | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_mai= n.c index fefd3c512386..6dbf0d5a2a22 100644 --- a/drivers/s390/net/qeth_l3_main.c +++ b/drivers/s390/net/qeth_l3_main.c @@ -2790,17 +2790,13 @@ static void qeth_l3_fill_af_iucv_hdr(struct qeth_ca= rd *card, char daddr[16]; struct af_iucv_trans_hdr *iucv_hdr; =20 - skb_pull(skb, 14); - card->dev->header_ops->create(skb, card->dev, 0, - card->dev->dev_addr, card->dev->dev_addr, - card->dev->addr_len); - skb_pull(skb, 14); - iucv_hdr =3D (struct af_iucv_trans_hdr *)skb->data; memset(hdr, 0, sizeof(struct qeth_hdr)); hdr->hdr.l3.id =3D QETH_HEADER_TYPE_LAYER3; hdr->hdr.l3.ext_flags =3D 0; - hdr->hdr.l3.length =3D skb->len; + hdr->hdr.l3.length =3D skb->len - ETH_HLEN; hdr->hdr.l3.flags =3D QETH_HDR_IPV6 | QETH_CAST_UNICAST; + + iucv_hdr =3D (struct af_iucv_trans_hdr *) (skb->data + ETH_HLEN); memset(daddr, 0, sizeof(daddr)); daddr[0] =3D 0xfe; daddr[1] =3D 0x80; @@ -2983,10 +2979,7 @@ static int qeth_l3_hard_start_xmit(struct sk_buff *s= kb, struct net_device *dev) if ((card->info.type =3D=3D QETH_CARD_TYPE_IQD) && (!large_send) && (skb_shinfo(skb)->nr_frags =3D=3D 0)) { new_skb =3D skb; - if (new_skb->protocol =3D=3D ETH_P_AF_IUCV) - data_offset =3D 0; - else - data_offset =3D ETH_HLEN; + data_offset =3D ETH_HLEN; hdr =3D kmem_cache_alloc(qeth_core_header_cache, GFP_ATOMIC); if (!hdr) goto tx_drop; --=20 2.14.1