Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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

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: fb4ee67529ff ("net/ncsi: Add NCSI OEM command support")
Signed-off-by: Kumar Thangavel <thangavel.k@hcl.com>
Acked-by: Samuel Mendoza-Jonas <sam@mendozajonas.com>
Reviewed-by: Paul Menzel <pmenzel@molgen.mpg.de>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Kumar Thangavel and committed by
David S. Miller
ac132852 619ca0d0

+16 -8
+16 -8
net/ncsi/ncsi-cmd.c
··· 18 18 #include "internal.h" 19 19 #include "ncsi-pkt.h" 20 20 21 + static const int padding_bytes = 26; 22 + 21 23 u32 ncsi_calculate_checksum(unsigned char *data, int len) 22 24 { 23 25 u32 checksum = 0; ··· 215 213 { 216 214 struct ncsi_cmd_oem_pkt *cmd; 217 215 unsigned int len; 216 + int payload; 217 + /* NC-SI spec DSP_0222_1.2.0, section 8.2.2.2 218 + * requires payload to be padded with 0 to 219 + * 32-bit boundary before the checksum field. 220 + * Ensure the padding bytes are accounted for in 221 + * skb allocation 222 + */ 218 223 224 + payload = ALIGN(nca->payload, 4); 219 225 len = sizeof(struct ncsi_cmd_pkt_hdr) + 4; 220 - if (nca->payload < 26) 221 - len += 26; 222 - else 223 - len += nca->payload; 226 + len += max(payload, padding_bytes); 224 227 225 228 cmd = skb_put_zero(skb, len); 226 229 memcpy(&cmd->mfr_id, nca->data, nca->payload); ··· 279 272 struct net_device *dev = nd->dev; 280 273 int hlen = LL_RESERVED_SPACE(dev); 281 274 int tlen = dev->needed_tailroom; 275 + int payload; 282 276 int len = hlen + tlen; 283 277 struct sk_buff *skb; 284 278 struct ncsi_request *nr; ··· 289 281 return NULL; 290 282 291 283 /* NCSI command packet has 16-bytes header, payload, 4 bytes checksum. 284 + * Payload needs padding so that the checksum field following payload is 285 + * aligned to 32-bit boundary. 292 286 * The packet needs padding if its payload is less than 26 bytes to 293 287 * meet 64 bytes minimal ethernet frame length. 294 288 */ 295 289 len += sizeof(struct ncsi_cmd_pkt_hdr) + 4; 296 - if (nca->payload < 26) 297 - len += 26; 298 - else 299 - len += nca->payload; 290 + payload = ALIGN(nca->payload, 4); 291 + len += max(payload, padding_bytes); 300 292 301 293 /* Allocate skb */ 302 294 skb = alloc_skb(len, GFP_ATOMIC);