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

Commit 2654e6cf authored by Kumar Thangavel's avatar Kumar Thangavel Committed by Greg Kroah-Hartman
Browse files

net/ncsi : Add payload to be 32-bit aligned to fix dropped packets



[ Upstream commit ac132852147ad303a938dda318970dd1bbdfda4e ]

Update NC-SI command handler (both standard and OEM) to take into
account of payload paddings in allocating skb (in case of payload
size is not 32-bit aligned).

The checksum field follows payload field, without taking payload
padding into account can cause checksum being truncated, leading to
dropped packets.

Fixes: fb4ee675 ("net/ncsi: Add NCSI OEM command support")
Signed-off-by: default avatarKumar Thangavel <thangavel.k@hcl.com>
Acked-by: default avatarSamuel Mendoza-Jonas <sam@mendozajonas.com>
Reviewed-by: default avatarPaul Menzel <pmenzel@molgen.mpg.de>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
Signed-off-by: default avatarSasha Levin <sashal@kernel.org>
parent 080f6b69
Loading
Loading
Loading
Loading
+16 −8
Original line number Diff line number Diff line
@@ -18,6 +18,8 @@
#include "internal.h"
#include "ncsi-pkt.h"

static const int padding_bytes = 26;

u32 ncsi_calculate_checksum(unsigned char *data, int len)
{
	u32 checksum = 0;
@@ -213,12 +215,17 @@ static int ncsi_cmd_handler_oem(struct sk_buff *skb,
{
	struct ncsi_cmd_oem_pkt *cmd;
	unsigned int len;
	int payload;
	/* NC-SI spec DSP_0222_1.2.0, section 8.2.2.2
	 * requires payload to be padded with 0 to
	 * 32-bit boundary before the checksum field.
	 * Ensure the padding bytes are accounted for in
	 * skb allocation
	 */

	payload = ALIGN(nca->payload, 4);
	len = sizeof(struct ncsi_cmd_pkt_hdr) + 4;
	if (nca->payload < 26)
		len += 26;
	else
		len += nca->payload;
	len += max(payload, padding_bytes);

	cmd = skb_put_zero(skb, len);
	memcpy(&cmd->mfr_id, nca->data, nca->payload);
@@ -272,6 +279,7 @@ static struct ncsi_request *ncsi_alloc_command(struct ncsi_cmd_arg *nca)
	struct net_device *dev = nd->dev;
	int hlen = LL_RESERVED_SPACE(dev);
	int tlen = dev->needed_tailroom;
	int payload;
	int len = hlen + tlen;
	struct sk_buff *skb;
	struct ncsi_request *nr;
@@ -281,14 +289,14 @@ static struct ncsi_request *ncsi_alloc_command(struct ncsi_cmd_arg *nca)
		return NULL;

	/* NCSI command packet has 16-bytes header, payload, 4 bytes checksum.
	 * Payload needs padding so that the checksum field following payload is
	 * aligned to 32-bit boundary.
	 * The packet needs padding if its payload is less than 26 bytes to
	 * meet 64 bytes minimal ethernet frame length.
	 */
	len += sizeof(struct ncsi_cmd_pkt_hdr) + 4;
	if (nca->payload < 26)
		len += 26;
	else
		len += nca->payload;
	payload = ALIGN(nca->payload, 4);
	len += max(payload, padding_bytes);

	/* Allocate skb */
	skb = alloc_skb(len, GFP_ATOMIC);