diff mbox

Add odp helper function for udp checksum

Message ID 1398071709-5807-3-git-send-email-weilong.chen@linaro.org
State Accepted
Commit d081f612b65a4d392aeb7e29469649852597a59f
Headers show

Commit Message

Weilong Chen April 21, 2014, 9:15 a.m. UTC
Signed-off-by: Weilong Chen <weilong.chen@linaro.org>
---
 include/helper/odp_udp.h |   49 ++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 49 insertions(+)

Comments

Ola Liljedahl April 22, 2014, 1:37 p.m. UTC | #1
Why is the checksum both set in the UDP header and returned?
Isn't it better just to compute and return the checksum, then the
caller can decide whether to set the checksum field in the header (and
the caller is responsible for clearing this field before computing the
checksum) or whether to just verify an existing checksum.



On 21 April 2014 11:15, Weilong Chen <weilong.chen@linaro.org> wrote:
>
> Signed-off-by: Weilong Chen <weilong.chen@linaro.org>
> ---
>  include/helper/odp_udp.h |   49 ++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 49 insertions(+)
>
> diff --git a/include/helper/odp_udp.h b/include/helper/odp_udp.h
> index 738470e..2070861 100644
> --- a/include/helper/odp_udp.h
> +++ b/include/helper/odp_udp.h
> @@ -33,6 +33,55 @@ typedef struct ODP_PACKED {
>         uint16be_t chksum;   /**< UDP header and data checksum (0 if not used)*/
>  } odp_udphdr_t;
>
> +static inline uint16be_t odp_ipv4_udp_chksum(odp_packet_t pkt)
> +{
> +       unsigned long sum = 0;
> +       odp_udphdr_t *udph;
> +       odp_ipv4hdr_t *iph;
> +       unsigned short *buf;
> +       unsigned short udplen;
> +
> +       if (!odp_packet_l3_offset(pkt))
> +               return 0;
> +
> +       if (!odp_packet_l4_offset(pkt))
> +               return 0;
> +
> +       iph = (odp_ipv4hdr_t *)odp_packet_l3(pkt);
> +       udph = (odp_udphdr_t *)odp_packet_l4(pkt);
> +       buf = (unsigned short *)udph;
> +       udplen = odp_be_to_cpu_16(udph->length);
> +
> +       /* the source ip */
> +       sum += (iph->src_addr >> 16) & 0xFFFF;
> +       sum += (iph->src_addr) & 0xFFFF;
> +       /* the dest ip */
> +       sum += (iph->dst_addr >> 16) & 0xFFFF;
> +       sum += (iph->dst_addr) & 0xFFFF;
> +       sum += odp_cpu_to_be_16(ODP_IPPROTO_UDP);
> +       /* the length */
> +       sum += udph->length;
> +
> +       /* initialize checksum to 0 */
> +       udph->chksum = 0;
> +       while (udplen > 1) {
> +               sum += *buf++;
> +               udplen -= 2;
> +       }
> +       /* if any bytes left, pad the bytes and add */
> +       if (udplen > 0)
> +               sum += ((*buf)&odp_cpu_to_be_16(0xFF00));
> +
> +       /* Fold sum to 16 bits: add carrier to result */
> +       while (sum >> 16)
> +               sum = (sum & 0xFFFF) + (sum >> 16);
> +       sum = ~sum;
> +       /* set computation result */
> +       udph->chksum = ((unsigned short)sum == 0x0) ? 0xFFFF
> +                         : (unsigned short)sum;
> +
> +       return udph->chksum;
> +}
>
>  /** @internal Compile time assert */
>  ODP_ASSERT(sizeof(odp_udphdr_t) == ODP_UDPHDR_LEN, ODP_UDPHDR_T__SIZE_ERROR);
> --
> 1.7.9.5
>
>
> _______________________________________________
> lng-odp mailing list
> lng-odp@lists.linaro.org
> http://lists.linaro.org/mailman/listinfo/lng-odp
Weilong Chen April 29, 2014, 8:48 a.m. UTC | #2
​OK,
Thanks!​


On 22 April 2014 21:37, Ola Liljedahl <ola.liljedahl@linaro.org> wrote:

> Why is the checksum both set in the UDP header and returned?
> Isn't it better just to compute and return the checksum, then the
> caller can decide whether to set the checksum field in the header (and
> the caller is responsible for clearing this field before computing the
> checksum) or whether to just verify an existing checksum.
>
>
>
> On 21 April 2014 11:15, Weilong Chen <weilong.chen@linaro.org> wrote:
> >
> > Signed-off-by: Weilong Chen <weilong.chen@linaro.org>
> > ---
> >  include/helper/odp_udp.h |   49
> ++++++++++++++++++++++++++++++++++++++++++++++
> >  1 file changed, 49 insertions(+)
> >
> > diff --git a/include/helper/odp_udp.h b/include/helper/odp_udp.h
> > index 738470e..2070861 100644
> > --- a/include/helper/odp_udp.h
> > +++ b/include/helper/odp_udp.h
> > @@ -33,6 +33,55 @@ typedef struct ODP_PACKED {
> >         uint16be_t chksum;   /**< UDP header and data checksum (0 if not
> used)*/
> >  } odp_udphdr_t;
> >
> > +static inline uint16be_t odp_ipv4_udp_chksum(odp_packet_t pkt)
> > +{
> > +       unsigned long sum = 0;
> > +       odp_udphdr_t *udph;
> > +       odp_ipv4hdr_t *iph;
> > +       unsigned short *buf;
> > +       unsigned short udplen;
> > +
> > +       if (!odp_packet_l3_offset(pkt))
> > +               return 0;
> > +
> > +       if (!odp_packet_l4_offset(pkt))
> > +               return 0;
> > +
> > +       iph = (odp_ipv4hdr_t *)odp_packet_l3(pkt);
> > +       udph = (odp_udphdr_t *)odp_packet_l4(pkt);
> > +       buf = (unsigned short *)udph;
> > +       udplen = odp_be_to_cpu_16(udph->length);
> > +
> > +       /* the source ip */
> > +       sum += (iph->src_addr >> 16) & 0xFFFF;
> > +       sum += (iph->src_addr) & 0xFFFF;
> > +       /* the dest ip */
> > +       sum += (iph->dst_addr >> 16) & 0xFFFF;
> > +       sum += (iph->dst_addr) & 0xFFFF;
> > +       sum += odp_cpu_to_be_16(ODP_IPPROTO_UDP);
> > +       /* the length */
> > +       sum += udph->length;
> > +
> > +       /* initialize checksum to 0 */
> > +       udph->chksum = 0;
> > +       while (udplen > 1) {
> > +               sum += *buf++;
> > +               udplen -= 2;
> > +       }
> > +       /* if any bytes left, pad the bytes and add */
> > +       if (udplen > 0)
> > +               sum += ((*buf)&odp_cpu_to_be_16(0xFF00));
> > +
> > +       /* Fold sum to 16 bits: add carrier to result */
> > +       while (sum >> 16)
> > +               sum = (sum & 0xFFFF) + (sum >> 16);
> > +       sum = ~sum;
> > +       /* set computation result */
> > +       udph->chksum = ((unsigned short)sum == 0x0) ? 0xFFFF
> > +                         : (unsigned short)sum;
> > +
> > +       return udph->chksum;
> > +}
> >
> >  /** @internal Compile time assert */
> >  ODP_ASSERT(sizeof(odp_udphdr_t) == ODP_UDPHDR_LEN,
> ODP_UDPHDR_T__SIZE_ERROR);
> > --
> > 1.7.9.5
> >
> >
> > _______________________________________________
> > lng-odp mailing list
> > lng-odp@lists.linaro.org
> > http://lists.linaro.org/mailman/listinfo/lng-odp
>
diff mbox

Patch

diff --git a/include/helper/odp_udp.h b/include/helper/odp_udp.h
index 738470e..2070861 100644
--- a/include/helper/odp_udp.h
+++ b/include/helper/odp_udp.h
@@ -33,6 +33,55 @@  typedef struct ODP_PACKED {
 	uint16be_t chksum;   /**< UDP header and data checksum (0 if not used)*/
 } odp_udphdr_t;
 
+static inline uint16be_t odp_ipv4_udp_chksum(odp_packet_t pkt)
+{
+	unsigned long sum = 0;
+	odp_udphdr_t *udph;
+	odp_ipv4hdr_t *iph;
+	unsigned short *buf;
+	unsigned short udplen;
+
+	if (!odp_packet_l3_offset(pkt))
+		return 0;
+
+	if (!odp_packet_l4_offset(pkt))
+		return 0;
+
+	iph = (odp_ipv4hdr_t *)odp_packet_l3(pkt);
+	udph = (odp_udphdr_t *)odp_packet_l4(pkt);
+	buf = (unsigned short *)udph;
+	udplen = odp_be_to_cpu_16(udph->length);
+
+	/* the source ip */
+	sum += (iph->src_addr >> 16) & 0xFFFF;
+	sum += (iph->src_addr) & 0xFFFF;
+	/* the dest ip */
+	sum += (iph->dst_addr >> 16) & 0xFFFF;
+	sum += (iph->dst_addr) & 0xFFFF;
+	sum += odp_cpu_to_be_16(ODP_IPPROTO_UDP);
+	/* the length */
+	sum += udph->length;
+
+	/* initialize checksum to 0 */
+	udph->chksum = 0;
+	while (udplen > 1) {
+		sum += *buf++;
+		udplen -= 2;
+	}
+	/* if any bytes left, pad the bytes and add */
+	if (udplen > 0)
+		sum += ((*buf)&odp_cpu_to_be_16(0xFF00));
+
+	/* Fold sum to 16 bits: add carrier to result */
+	while (sum >> 16)
+		sum = (sum & 0xFFFF) + (sum >> 16);
+	sum = ~sum;
+	/* set computation result */
+	udph->chksum = ((unsigned short)sum == 0x0) ? 0xFFFF
+			  : (unsigned short)sum;
+
+	return udph->chksum;
+}
 
 /** @internal Compile time assert */
 ODP_ASSERT(sizeof(odp_udphdr_t) == ODP_UDPHDR_LEN, ODP_UDPHDR_T__SIZE_ERROR);