diff mbox series

net: ncsi: Adding padding bytes in the payload

Message ID 20211012062240.GA5761@gmail.com
State Not Applicable, archived
Headers show
Series net: ncsi: Adding padding bytes in the payload | expand

Commit Message

Kumar Thangavel Oct. 12, 2021, 6:22 a.m. UTC
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.

Signed-off-by: Kumar Thangavel <thangavel.k@hcl.com>

---
 net/ncsi/ncsi-cmd.c | 21 +++++++++++++++++----
 1 file changed, 17 insertions(+), 4 deletions(-)

Comments

Paul Menzel Oct. 12, 2021, 8:02 a.m. UTC | #1
Dear Kumar,


Thank you for your patch.

Nit: Could you please use the imperative mood in the commit message summary:

 > net: ncsi: Add padding bytes in the payload

Or more descriptive:

 > net: ncsi: Padd payload to be 32-bit aligned to fix dropped packets

Am 12.10.21 um 08:22 schrieb Kumar Thangavel:
> 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.

How can this be reproduced?

> Signed-off-by: Kumar Thangavel <thangavel.k@hcl.com>
> 
> ---
>   net/ncsi/ncsi-cmd.c | 21 +++++++++++++++++----
>   1 file changed, 17 insertions(+), 4 deletions(-)
> 
> diff --git a/net/ncsi/ncsi-cmd.c b/net/ncsi/ncsi-cmd.c
> index ba9ae482141b..4625fc935603 100644
> --- a/net/ncsi/ncsi-cmd.c
> +++ b/net/ncsi/ncsi-cmd.c
> @@ -214,11 +214,19 @@ static int ncsi_cmd_handler_oem(struct sk_buff *skb,
>   	struct ncsi_cmd_oem_pkt *cmd;
>   	unsigned int len;
>   
> +	/* NC-SI spec requires payload to be padded with 0

It’d be great, if you included the specification version, and section if 
the requirement.

> +	 * to 32-bit boundary before the checksum field.
> +	 * Ensure the padding bytes are accounted for in
> +	 * skb allocation
> +	 */
> +

Please remove the blank line.

> +	unsigned short payload = ALIGN(nca->payload, 4);
> +
>   	len = sizeof(struct ncsi_cmd_pkt_hdr) + 4;
> -	if (nca->payload < 26)
> +	if (payload < 26)
>   		len += 26;
>   	else
> -		len += nca->payload;
> +		len += payload;
>   
>   	cmd = skb_put_zero(skb, len);
>   	memcpy(&cmd->mfr_id, nca->data, nca->payload);
> @@ -272,6 +280,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 +290,18 @@ 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 follwoing payload is

following

> +	 * aligned to 32bit boundary.

32-bit

>   	 * 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)
> +
> +	payload = ALIGN(nca->payload, 4);
> +	if (payload < 26)
>   		len += 26;
>   	else
> -		len += nca->payload;
> +		len += payload;
>   
>   	/* Allocate skb */
>   	skb = alloc_skb(len, GFP_ATOMIC);
> 

Besides the nits, this looks fine to me.


Kind regards,

Paul
Joel Stanley Oct. 12, 2021, 10:44 p.m. UTC | #2
On Tue, 12 Oct 2021 at 06:23, Kumar Thangavel
<kumarthangavel.hcl@gmail.com> wrote:
>
> 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.

Can you help us review this by pointing out where this is described in
the NCSI spec?

We've been running this code for a number of years now and I wonder
why this hasn't been a problem so far.

Cheers,

Joel

>
> Signed-off-by: Kumar Thangavel <thangavel.k@hcl.com>
>
> ---
>  net/ncsi/ncsi-cmd.c | 21 +++++++++++++++++----
>  1 file changed, 17 insertions(+), 4 deletions(-)
>
> diff --git a/net/ncsi/ncsi-cmd.c b/net/ncsi/ncsi-cmd.c
> index ba9ae482141b..4625fc935603 100644
> --- a/net/ncsi/ncsi-cmd.c
> +++ b/net/ncsi/ncsi-cmd.c
> @@ -214,11 +214,19 @@ static int ncsi_cmd_handler_oem(struct sk_buff *skb,
>         struct ncsi_cmd_oem_pkt *cmd;
>         unsigned int len;
>
> +       /* NC-SI spec 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
> +        */
> +
> +       unsigned short payload = ALIGN(nca->payload, 4);
> +
>         len = sizeof(struct ncsi_cmd_pkt_hdr) + 4;
> -       if (nca->payload < 26)
> +       if (payload < 26)
>                 len += 26;
>         else
> -               len += nca->payload;
> +               len += payload;
>
>         cmd = skb_put_zero(skb, len);
>         memcpy(&cmd->mfr_id, nca->data, nca->payload);
> @@ -272,6 +280,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 +290,18 @@ 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 follwoing payload is
> +        * aligned to 32bit 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)
> +
> +       payload = ALIGN(nca->payload, 4);
> +       if (payload < 26)
>                 len += 26;
>         else
> -               len += nca->payload;
> +               len += payload;
>
>         /* Allocate skb */
>         skb = alloc_skb(len, GFP_ATOMIC);
> --
> 2.17.1
>
Sam Mendoza-Jonas Oct. 13, 2021, 2:46 a.m. UTC | #3
On Tue, 2021-10-12 at 22:44 +0000, Joel Stanley wrote:
> On Tue, 12 Oct 2021 at 06:23, Kumar Thangavel
> <kumarthangavel.hcl@gmail.com> wrote:
> > 
> > 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.
> 
> Can you help us review this by pointing out where this is described in
> the NCSI spec?
> 
> We've been running this code for a number of years now and I wonder
> why this hasn't been a problem so far.

I'm assuming this is referencing section 8.2.2.2:
If the payload is present and does not end on a 32-bit boundary, one to
three padding bytes equal to 0x00 shall be present to align the
checksum field to a 32-bit boundary.

But I'm also surprised this hasn't caused issues so far if we've been
getting it wrong. Is there an example that reproduces the issue?

Cheers,
Sam

> 
> Cheers,
> 
> Joel
> 
> > 
> > Signed-off-by: Kumar Thangavel <thangavel.k@hcl.com>
> > 
> > ---
> >  net/ncsi/ncsi-cmd.c | 21 +++++++++++++++++----
> >  1 file changed, 17 insertions(+), 4 deletions(-)
> > 
> > diff --git a/net/ncsi/ncsi-cmd.c b/net/ncsi/ncsi-cmd.c
> > index ba9ae482141b..4625fc935603 100644
> > --- a/net/ncsi/ncsi-cmd.c
> > +++ b/net/ncsi/ncsi-cmd.c
> > @@ -214,11 +214,19 @@ static int ncsi_cmd_handler_oem(struct sk_buff
> > *skb,
> >         struct ncsi_cmd_oem_pkt *cmd;
> >         unsigned int len;
> > 
> > +       /* NC-SI spec 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
> > +        */
> > +
> > +       unsigned short payload = ALIGN(nca->payload, 4);
> > +
> >         len = sizeof(struct ncsi_cmd_pkt_hdr) + 4;
> > -       if (nca->payload < 26)
> > +       if (payload < 26)
> >                 len += 26;
> >         else
> > -               len += nca->payload;
> > +               len += payload;
> > 
> >         cmd = skb_put_zero(skb, len);
> >         memcpy(&cmd->mfr_id, nca->data, nca->payload);
> > @@ -272,6 +280,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 +290,18 @@ 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 follwoing
> > payload is
> > +        * aligned to 32bit 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)
> > +
> > +       payload = ALIGN(nca->payload, 4);
> > +       if (payload < 26)
> >                 len += 26;
> >         else
> > -               len += nca->payload;
> > +               len += payload;
> > 
> >         /* Allocate skb */
> >         skb = alloc_skb(len, GFP_ATOMIC);
> > --
> > 2.17.1
> >
Kumar Thangavel Oct. 13, 2021, 1:05 p.m. UTC | #4
Thanks for your review. Please find my response below.

Fixed all the comments. I will update the next patchset.

Thanks,
Kumar.

On Wed, Oct 13, 2021 at 8:16 AM Samuel Mendoza-Jonas <sam@mendozajonas.com>
wrote:

> On Tue, 2021-10-12 at 22:44 +0000, Joel Stanley wrote:
> > On Tue, 12 Oct 2021 at 06:23, Kumar Thangavel
> > <kumarthangavel.hcl@gmail.com> wrote:
> > >
> > > 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.
> >
> > Can you help us review this by pointing out where this is described in
> > the NCSI spec?
> >
> > We've been running this code for a number of years now and I wonder
> > why this hasn't been a problem so far.
>
> I'm assuming this is referencing section 8.2.2.2:
> If the payload is present and does not end on a 32-bit boundary, one to
> three padding bytes equal to 0x00 shall be present to align the
> checksum field to a 32-bit boundary.
>

Kumar : Yes. In the NC-SI spec, section 8.2.2.2 represents a 32-bit
boundary.
              If it does not end on a 32-bit boundary, padding bytes can be
added.

>
> But I'm also surprised this hasn't caused issues so far if we've been
> getting it wrong. Is there an example that reproduces the issue?
>

Kumar :  We have a use case of NIC firmware update in our system which is
pldm based and the transport layer is NC-SI based on RBT.
               Sending some pldm based commands to NIC. In that, some of
the commands failed because of a payload size less than 32.
               So, Added padding bytes to align the 32-bit boundary and
issues got resolved.


>
> Cheers,
> Sam
>
> >
> > Cheers,
> >
> > Joel
> >
> > >
> > > Signed-off-by: Kumar Thangavel <thangavel.k@hcl.com>
> > >
> > > ---
> > >  net/ncsi/ncsi-cmd.c | 21 +++++++++++++++++----
> > >  1 file changed, 17 insertions(+), 4 deletions(-)
> > >
> > > diff --git a/net/ncsi/ncsi-cmd.c b/net/ncsi/ncsi-cmd.c
> > > index ba9ae482141b..4625fc935603 100644
> > > --- a/net/ncsi/ncsi-cmd.c
> > > +++ b/net/ncsi/ncsi-cmd.c
> > > @@ -214,11 +214,19 @@ static int ncsi_cmd_handler_oem(struct sk_buff
> > > *skb,
> > >         struct ncsi_cmd_oem_pkt *cmd;
> > >         unsigned int len;
> > >
> > > +       /* NC-SI spec 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
> > > +        */
> > > +
> > > +       unsigned short payload = ALIGN(nca->payload, 4);
> > > +
> > >         len = sizeof(struct ncsi_cmd_pkt_hdr) + 4;
> > > -       if (nca->payload < 26)
> > > +       if (payload < 26)
> > >                 len += 26;
> > >         else
> > > -               len += nca->payload;
> > > +               len += payload;
> > >
> > >         cmd = skb_put_zero(skb, len);
> > >         memcpy(&cmd->mfr_id, nca->data, nca->payload);
> > > @@ -272,6 +280,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 +290,18 @@ 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 follwoing
> > > payload is
> > > +        * aligned to 32bit 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)
> > > +
> > > +       payload = ALIGN(nca->payload, 4);
> > > +       if (payload < 26)
> > >                 len += 26;
> > >         else
> > > -               len += nca->payload;
> > > +               len += payload;
> > >
> > >         /* Allocate skb */
> > >         skb = alloc_skb(len, GFP_ATOMIC);
> > > --
> > > 2.17.1
> > >
>
>
>
diff mbox series

Patch

diff --git a/net/ncsi/ncsi-cmd.c b/net/ncsi/ncsi-cmd.c
index ba9ae482141b..4625fc935603 100644
--- a/net/ncsi/ncsi-cmd.c
+++ b/net/ncsi/ncsi-cmd.c
@@ -214,11 +214,19 @@  static int ncsi_cmd_handler_oem(struct sk_buff *skb,
 	struct ncsi_cmd_oem_pkt *cmd;
 	unsigned int len;
 
+	/* NC-SI spec 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
+	 */
+
+	unsigned short payload = ALIGN(nca->payload, 4);
+
 	len = sizeof(struct ncsi_cmd_pkt_hdr) + 4;
-	if (nca->payload < 26)
+	if (payload < 26)
 		len += 26;
 	else
-		len += nca->payload;
+		len += payload;
 
 	cmd = skb_put_zero(skb, len);
 	memcpy(&cmd->mfr_id, nca->data, nca->payload);
@@ -272,6 +280,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 +290,18 @@  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 follwoing payload is
+	 * aligned to 32bit 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)
+
+	payload = ALIGN(nca->payload, 4);
+	if (payload < 26)
 		len += 26;
 	else
-		len += nca->payload;
+		len += payload;
 
 	/* Allocate skb */
 	skb = alloc_skb(len, GFP_ATOMIC);