[dpdk-dev,v2,1/2] librte_net: add crc init and compute APIs

Message ID 1488283701-186162-2-git-send-email-jasvinder.singh@intel.com (mailing list archive)
State Superseded, archived
Delegated to: Thomas Monjalon
Headers

Checks

Context Check Description
ci/checkpatch success coding style OK
ci/Intel-compilation fail Compilation issues

Commit Message

Jasvinder Singh Feb. 28, 2017, 12:08 p.m. UTC
  APIs for initialising and computing the crc (16-bit and 32-bit CRCs)
are added. For CRCs calculation, scalar as well as x86 intrinsic(sse4.2)
versions are implemented.

The scalar version is based on generic Look-Up Table(LUT) algorithm,
while x86 intrinsic version uses carry-less multiplication for
fast CRC computation.

Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com>
---
 lib/librte_net/Makefile            |   2 +
 lib/librte_net/rte_net_crc.c       | 664 +++++++++++++++++++++++++++++++++++++
 lib/librte_net/rte_net_crc.h       | 101 ++++++
 lib/librte_net/rte_net_version.map |   8 +
 4 files changed, 775 insertions(+)
 create mode 100644 lib/librte_net/rte_net_crc.c
 create mode 100644 lib/librte_net/rte_net_crc.h
  

Comments

Jerin Jacob Feb. 28, 2017, 12:15 p.m. UTC | #1
On Tue, Feb 28, 2017 at 12:08:20PM +0000, Jasvinder Singh wrote:
> APIs for initialising and computing the crc (16-bit and 32-bit CRCs)
> are added. For CRCs calculation, scalar as well as x86 intrinsic(sse4.2)
> versions are implemented.
> 
> The scalar version is based on generic Look-Up Table(LUT) algorithm,
> while x86 intrinsic version uses carry-less multiplication for
> fast CRC computation.
> 
> Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com>
> ---
>  lib/librte_net/Makefile            |   2 +
>  lib/librte_net/rte_net_crc.c       | 664 +++++++++++++++++++++++++++++++++++++
>  lib/librte_net/rte_net_crc.h       | 101 ++++++
>  lib/librte_net/rte_net_version.map |   8 +
>  4 files changed, 775 insertions(+)
>  create mode 100644 lib/librte_net/rte_net_crc.c
>  create mode 100644 lib/librte_net/rte_net_crc.h
> 
> diff --git a/lib/librte_net/Makefile b/lib/librte_net/Makefile
> index 20cf664..41be751 100644
> --- a/lib/librte_net/Makefile
> +++ b/lib/librte_net/Makefile
> @@ -39,11 +39,13 @@ EXPORT_MAP := rte_net_version.map
>  LIBABIVER := 1
>  
>  SRCS-$(CONFIG_RTE_LIBRTE_NET) := rte_net.c
> +SRCS-$(CONFIG_RTE_LIBRTE_NET) += rte_net_crc.c
>  
>  # install includes
>  SYMLINK-$(CONFIG_RTE_LIBRTE_NET)-include := rte_ip.h rte_tcp.h rte_udp.h
>  SYMLINK-$(CONFIG_RTE_LIBRTE_NET)-include += rte_sctp.h rte_icmp.h rte_arp.h
>  SYMLINK-$(CONFIG_RTE_LIBRTE_NET)-include += rte_ether.h rte_gre.h rte_net.h
> +SYMLINK-$(CONFIG_RTE_LIBRTE_NET)-include += rte_net_crc.h
>  
>  DEPDIRS-$(CONFIG_RTE_LIBRTE_NET) += lib/librte_eal lib/librte_mbuf
>  
> diff --git a/lib/librte_net/rte_net_crc.c b/lib/librte_net/rte_net_crc.c
> new file mode 100644
> index 0000000..78a49dd
> --- /dev/null
> +++ b/lib/librte_net/rte_net_crc.c
> @@ -0,0 +1,664 @@
> +/*-
> + *   BSD LICENSE
> + *
> + *   Copyright(c) 2017 Intel Corporation.
> + *   All rights reserved.
> + *
> + *   Redistribution and use in source and binary forms, with or without
> + *   modification, are permitted provided that the following conditions
> + *   are met:
> + *
> + *     * Redistributions of source code must retain the above copyright
> + *       notice, this list of conditions and the following disclaimer.
> + *     * Redistributions in binary form must reproduce the above copyright
> + *       notice, this list of conditions and the following disclaimer in
> + *       the documentation and/or other materials provided with the
> + *       distribution.
> + *     * Neither the name of Intel Corporation nor the names of its
> + *       contributors may be used to endorse or promote products derived
> + *       from this software without specific prior written permission.
> + *
> + *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
> + *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
> + *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
> + *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
> + *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
> + *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
> + *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
> + *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
> + *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
> + *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
> + *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> + */
> +
> +#include <rte_net_crc.h>
> +#include <stddef.h>
> +
> +/* Macros for printing using RTE_LOG */
> +#define RTE_LOGTYPE_CRC RTE_LOGTYPE_USER1
> +
> +/** CRC polynomials */
> +#define CRC32_ETH_POLYNOMIAL 0x04c11db7UL
> +#define CRC16_CCITT_POLYNOMIAL 0x1021U
> +
> +typedef int (*rte_net_crc_handler)(struct rte_net_crc_params *);
> +
> +static int rte_crc16_ccitt_handler(struct rte_net_crc_params *p);
> +static int rte_crc32_eth_handler(struct rte_net_crc_params *p);
> +static int rte_crc_invalid_handler(struct rte_net_crc_params *p);
> +
> +static rte_net_crc_handler *handlers;
> +
> +static rte_net_crc_handler handlers_scalar[] = {
> +	[RTE_NET_CRC16_CCITT] = rte_crc16_ccitt_handler,
> +	[RTE_NET_CRC32_ETH] = rte_crc32_eth_handler,
> +	[RTE_NET_CRC_REQS] = rte_crc_invalid_handler,
> +};
> +
> +int
> +rte_crc_invalid_handler(__rte_unused struct rte_net_crc_params *p)
> +{
> +	RTE_LOG(ERR, CRC, "CRC type not supported!\n");
> +	return -1;	/* Error */
> +}
> +
> +#if defined RTE_ARCH_X86_64 && defined RTE_MACHINE_CPUFLAG_SSE4_2

Could you please abstract the vector function and move the SSE implementation to
separate file for future clean neon and altivec integration.

Reference: lib/librte_lpm/rte_lpm_sse.h
  
Thomas Monjalon March 1, 2017, 6:46 p.m. UTC | #2
2017-02-28 12:08, Jasvinder Singh:
>  lib/librte_net/rte_net_crc.c       | 664 +++++++++++++++++++++++++++++++++++++
>  lib/librte_net/rte_net_crc.h       | 101 ++++++

I think it should be in librte_hash.

Please check lib/librte_hash/rte_hash_crc.h
  
Jasvinder Singh March 2, 2017, 1:03 p.m. UTC | #3
Hi Thomas,

> -----Original Message-----
> From: Thomas Monjalon [mailto:thomas.monjalon@6wind.com]
> Sent: Wednesday, March 1, 2017 6:46 PM
> To: Singh, Jasvinder <jasvinder.singh@intel.com>
> Cc: dev@dpdk.org; Doherty, Declan <declan.doherty@intel.com>
> Subject: Re: [dpdk-dev] [PATCH v2 1/2] librte_net: add crc init and compute
> APIs
> 
> 2017-02-28 12:08, Jasvinder Singh:
> >  lib/librte_net/rte_net_crc.c       | 664
> +++++++++++++++++++++++++++++++++++++
> >  lib/librte_net/rte_net_crc.h       | 101 ++++++
> 
> I think it should be in librte_hash.
> 
> Please check lib/librte_hash/rte_hash_crc.h

Is it good to include payload crc calculation in hash library as I see all hash related functionality there?
  
Thomas Monjalon March 6, 2017, 3:27 p.m. UTC | #4
2017-03-02 13:03, Singh, Jasvinder:
> Hi Thomas,
> 
> > -----Original Message-----
> > From: Thomas Monjalon [mailto:thomas.monjalon@6wind.com]
> > Sent: Wednesday, March 1, 2017 6:46 PM
> > To: Singh, Jasvinder <jasvinder.singh@intel.com>
> > Cc: dev@dpdk.org; Doherty, Declan <declan.doherty@intel.com>
> > Subject: Re: [dpdk-dev] [PATCH v2 1/2] librte_net: add crc init and compute
> > APIs
> > 
> > 2017-02-28 12:08, Jasvinder Singh:
> > >  lib/librte_net/rte_net_crc.c       | 664
> > +++++++++++++++++++++++++++++++++++++
> > >  lib/librte_net/rte_net_crc.h       | 101 ++++++
> > 
> > I think it should be in librte_hash.
> > 
> > Please check lib/librte_hash/rte_hash_crc.h
> 
> Is it good to include payload crc calculation in hash library as I see all hash related functionality there?

I think yes. Pablo?
  
De Lara Guarch, Pablo March 8, 2017, 11:08 a.m. UTC | #5
> -----Original Message-----
> From: Thomas Monjalon [mailto:thomas.monjalon@6wind.com]
> Sent: Monday, March 06, 2017 3:28 PM
> To: Singh, Jasvinder
> Cc: dev@dpdk.org; Doherty, Declan; De Lara Guarch, Pablo
> Subject: Re: [dpdk-dev] [PATCH v2 1/2] librte_net: add crc init and compute
> APIs
> 
> 2017-03-02 13:03, Singh, Jasvinder:
> > Hi Thomas,
> >
> > > -----Original Message-----
> > > From: Thomas Monjalon [mailto:thomas.monjalon@6wind.com]
> > > Sent: Wednesday, March 1, 2017 6:46 PM
> > > To: Singh, Jasvinder <jasvinder.singh@intel.com>
> > > Cc: dev@dpdk.org; Doherty, Declan <declan.doherty@intel.com>
> > > Subject: Re: [dpdk-dev] [PATCH v2 1/2] librte_net: add crc init and
> compute
> > > APIs
> > >
> > > 2017-02-28 12:08, Jasvinder Singh:
> > > >  lib/librte_net/rte_net_crc.c       | 664
> > > +++++++++++++++++++++++++++++++++++++
> > > >  lib/librte_net/rte_net_crc.h       | 101 ++++++
> > >
> > > I think it should be in librte_hash.
> > >
> > > Please check lib/librte_hash/rte_hash_crc.h
> >
> > Is it good to include payload crc calculation in hash library as I see all hash
> related functionality there?
> 
> I think yes. Pablo?

I think this doesn't belong in the hash library. These new functions calculate CRC, but not as a hash function.
Yes, CRC can be used as hash function (in fact, it is used as such in the hash library,
the CRC32C version, and I assume that's why it is in there), but its use is much broader
(its main purpose is not to be a hash function, but for data error detection, for any data).

Therefore, I would suggest either creating a separate library for this, if we want to use this as a broader use,
or leave it in net library, if we want to focus on calculating CRC for Ethernet frames.

Regarding to the CRC that we have in the hash library, if we go for a separate library,
we could move that function there, but then it would have to follow the function prototype of a hash function,
defined in the hash library. 

Thanks,
Pablo
  
Thomas Monjalon March 15, 2017, 5:35 p.m. UTC | #6
2017-03-08 11:08, De Lara Guarch, Pablo:
> From: Thomas Monjalon [mailto:thomas.monjalon@6wind.com]
> > 2017-03-02 13:03, Singh, Jasvinder:
> > > From: Thomas Monjalon [mailto:thomas.monjalon@6wind.com]
> > > > 2017-02-28 12:08, Jasvinder Singh:
> > > > >  lib/librte_net/rte_net_crc.c       | 664 +++++++++++++++++++++++++++++++++++++
> > > > >  lib/librte_net/rte_net_crc.h       | 101 ++++++
> > > >
> > > > I think it should be in librte_hash.
> > > >
> > > > Please check lib/librte_hash/rte_hash_crc.h
> > >
> > > Is it good to include payload crc calculation in hash library as I see all hash
> > related functionality there?
> > 
> > I think yes. Pablo?
> 
> I think this doesn't belong in the hash library. These new functions calculate CRC, but not as a hash function.

Can't we say that a CRC is a hash? What is a hash?
A function generating the same output bytes from given input bytes.

I think you must separate hash functions and hash table management.

> Yes, CRC can be used as hash function (in fact, it is used as such in the hash library,
> the CRC32C version, and I assume that's why it is in there), but its use is much broader
> (its main purpose is not to be a hash function, but for data error detection, for any data).

The librte_hash has several hash functions, including CRC32C and Toeplitz.

> Therefore, I would suggest either creating a separate library for this, if we want to use this as a broader use,
> or leave it in net library, if we want to focus on calculating CRC for Ethernet frames.

I don't think Toeplitz should go in librte_net.
That's why I suggest to keep every kind of hash functions in librte_hash.

> Regarding to the CRC that we have in the hash library, if we go for a separate library,
> we could move that function there, but then it would have to follow the function prototype of a hash function,
> defined in the hash library.
  
Cristian Dumitrescu March 15, 2017, 7:03 p.m. UTC | #7
... <snip>

> > > > > I think it should be in librte_hash.
> > > > >
> > > > > Please check lib/librte_hash/rte_hash_crc.h
> > > >
> > > > Is it good to include payload crc calculation in hash library as I see all
> hash
> > > related functionality there?
> > >
> > > I think yes. Pablo?
> >
> > I think this doesn't belong in the hash library. These new functions calculate
> CRC, but not as a hash function.
> 
> Can't we say that a CRC is a hash? What is a hash?
> A function generating the same output bytes from given input bytes.
> 
> I think you must separate hash functions and hash table management.
> 

The fact that CRC32 instruction is opportunistically used to compute a hash digest/signature for load balancing (affinity-based) or hash tables (flow tables, ARP cache, etc) does not mean that all the code that uses CRC32 instruction should be placed in librte_hash.

The purpose of the hash functions in librte_hash is to compute a digest/signature for a given array of bytes (the key) as fast as possible. Any hash function that produces a hash signature with good uniform distribution in a small amount of cycles belongs here, including those opportunistically using specialized CPU instructions such as CRC32 (or XOR, AESNI, etc).

The code proposed in this patch is used to compute packet fields for various protocols that have a CRC field, such as FCS of Ethernet frames, etc. according to the relevant standard (IEEE 802, others). It is an utility to be used for implementing protocol-level functionality for various protocols from the network stack, similar to e.g. IP or UDP checksum. If we were to add an IP or UDCP checksum calculator, would you put it in librte_hash?

The code from this patch is never going to be used to compute a fast signature/digest. Typically this CRC is computed over the entire frame/packet rather than just selected fields from the packet representing the application-specific flow key. Also note that the signature produced by CRC32 hash function from librte_hash is actually not the correct Cyclic Redundancy Check of that array of bytes (or, for math guys, of the associated polynomial), it is just a partial/intermediate value.

Therefore, I suggest placing this code into: librte_ether (given that it can be used to compute Ethernet FCS), or librte_net, or librte_crc. Definitely not in librte_hash.

Regards,
Cristian
  
Cristian Dumitrescu March 15, 2017, 7:09 p.m. UTC | #8
> -----Original Message-----
> From: Dumitrescu, Cristian
> Sent: Wednesday, March 15, 2017 7:04 PM
> To: 'Thomas Monjalon' <thomas.monjalon@6wind.com>; De Lara Guarch,
> Pablo <pablo.de.lara.guarch@intel.com>
> Cc: Singh, Jasvinder <jasvinder.singh@intel.com>; dev@dpdk.org; Doherty,
> Declan <declan.doherty@intel.com>
> Subject: RE: [dpdk-dev] [PATCH v2 1/2] librte_net: add crc init and compute
> APIs
> 
> ... <snip>
> 
> > > > > > I think it should be in librte_hash.
> > > > > >
> > > > > > Please check lib/librte_hash/rte_hash_crc.h
> > > > >
> > > > > Is it good to include payload crc calculation in hash library as I see all
> > hash
> > > > related functionality there?
> > > >
> > > > I think yes. Pablo?
> > >
> > > I think this doesn't belong in the hash library. These new functions
> calculate
> > CRC, but not as a hash function.
> >
> > Can't we say that a CRC is a hash? What is a hash?
> > A function generating the same output bytes from given input bytes.
> >
> > I think you must separate hash functions and hash table management.
> >
> 
> The fact that CRC32 instruction is opportunistically used to compute a hash
> digest/signature for load balancing (affinity-based) or hash tables (flow
> tables, ARP cache, etc) does not mean that all the code that uses CRC32
> instruction should be placed in librte_hash.
> 
> The purpose of the hash functions in librte_hash is to compute a
> digest/signature for a given array of bytes (the key) as fast as possible. Any
> hash function that produces a hash signature with good uniform distribution
> in a small amount of cycles belongs here, including those opportunistically
> using specialized CPU instructions such as CRC32 (or XOR, AESNI, etc).
> 
> The code proposed in this patch is used to compute packet fields for various
> protocols that have a CRC field, such as FCS of Ethernet frames, etc.
> according to the relevant standard (IEEE 802, others). It is an utility to be used
> for implementing protocol-level functionality for various protocols from the
> network stack, similar to e.g. IP or UDP checksum. If we were to add an IP or
> UDCP checksum calculator, would you put it in librte_hash?
> 
> The code from this patch is never going to be used to compute a fast
> signature/digest. Typically this CRC is computed over the entire frame/packet
> rather than just selected fields from the packet representing the application-
> specific flow key. Also note that the signature produced by CRC32 hash
> function from librte_hash is actually not the correct Cyclic Redundancy Check
> of that array of bytes (or, for math guys, of the associated polynomial), it is
> just a partial/intermediate value.
> 
> Therefore, I suggest placing this code into: librte_ether (given that it can be
> used to compute Ethernet FCS), or librte_net, or librte_crc. Definitely not in
> librte_hash.
> 

Sorry, my bad on librte_ether: the rte_ether.h where Ethernet frame is defined is located in librte_net, not librte_ether, so librte_ether should not be on the above list. Therefore, my suggestion is: librte_net or a new library librte_crc.

> Regards,
> Cristian
  
Thomas Monjalon March 15, 2017, 8:15 p.m. UTC | #9
2017-03-15 19:03, Dumitrescu, Cristian:
> ... <snip>
> 
> > > > > > I think it should be in librte_hash.
> > > > > >
> > > > > > Please check lib/librte_hash/rte_hash_crc.h
> > > > >
> > > > > Is it good to include payload crc calculation in hash library as I see all
> > hash
> > > > related functionality there?
> > > >
> > > > I think yes. Pablo?
> > >
> > > I think this doesn't belong in the hash library. These new functions calculate
> > CRC, but not as a hash function.
> > 
> > Can't we say that a CRC is a hash? What is a hash?
> > A function generating the same output bytes from given input bytes.
> > 
> > I think you must separate hash functions and hash table management.
> > 
> 
> The fact that CRC32 instruction is opportunistically used to compute a hash digest/signature for load balancing (affinity-based) or hash tables (flow tables, ARP cache, etc) does not mean that all the code that uses CRC32 instruction should be placed in librte_hash.
> 
> The purpose of the hash functions in librte_hash is to compute a digest/signature for a given array of bytes (the key) as fast as possible. Any hash function that produces a hash signature with good uniform distribution in a small amount of cycles belongs here, including those opportunistically using specialized CPU instructions such as CRC32 (or XOR, AESNI, etc).
> 
> The code proposed in this patch is used to compute packet fields for various protocols that have a CRC field, such as FCS of Ethernet frames, etc. according to the relevant standard (IEEE 802, others). It is an utility to be used for implementing protocol-level functionality for various protocols from the network stack, similar to e.g. IP or UDP checksum. If we were to add an IP or UDCP checksum calculator, would you put it in librte_hash?
> 
> The code from this patch is never going to be used to compute a fast signature/digest. Typically this CRC is computed over the entire frame/packet rather than just selected fields from the packet representing the application-specific flow key. Also note that the signature produced by CRC32 hash function from librte_hash is actually not the correct Cyclic Redundancy Check of that array of bytes (or, for math guys, of the associated polynomial), it is just a partial/intermediate value.
> 
> Therefore, I suggest placing this code into: librte_ether (given that it can be used to compute Ethernet FCS), or librte_net, or librte_crc. Definitely not in librte_hash.

I agree with you Cristian that the protocol layer must be in librte_net.
But I think most of this patch is not protocol level.
I think you agree with me that the code computing a
"digest/signature for a given array of bytes" must go to librte_hash?
  
Cristian Dumitrescu March 15, 2017, 9:11 p.m. UTC | #10
> -----Original Message-----
> From: Thomas Monjalon [mailto:thomas.monjalon@6wind.com]
> Sent: Wednesday, March 15, 2017 8:16 PM
> To: Dumitrescu, Cristian <cristian.dumitrescu@intel.com>
> Cc: De Lara Guarch, Pablo <pablo.de.lara.guarch@intel.com>; Singh,
> Jasvinder <jasvinder.singh@intel.com>; dev@dpdk.org; Doherty, Declan
> <declan.doherty@intel.com>
> Subject: Re: [dpdk-dev] [PATCH v2 1/2] librte_net: add crc init and compute
> APIs
> 
> 2017-03-15 19:03, Dumitrescu, Cristian:
> > ... <snip>
> >
> > > > > > > I think it should be in librte_hash.
> > > > > > >
> > > > > > > Please check lib/librte_hash/rte_hash_crc.h
> > > > > >
> > > > > > Is it good to include payload crc calculation in hash library as I see all
> > > hash
> > > > > related functionality there?
> > > > >
> > > > > I think yes. Pablo?
> > > >
> > > > I think this doesn't belong in the hash library. These new functions
> calculate
> > > CRC, but not as a hash function.
> > >
> > > Can't we say that a CRC is a hash? What is a hash?
> > > A function generating the same output bytes from given input bytes.
> > >
> > > I think you must separate hash functions and hash table management.
> > >
> >
> > The fact that CRC32 instruction is opportunistically used to compute a hash
> digest/signature for load balancing (affinity-based) or hash tables (flow
> tables, ARP cache, etc) does not mean that all the code that uses CRC32
> instruction should be placed in librte_hash.
> >
> > The purpose of the hash functions in librte_hash is to compute a
> digest/signature for a given array of bytes (the key) as fast as possible. Any
> hash function that produces a hash signature with good uniform distribution
> in a small amount of cycles belongs here, including those opportunistically
> using specialized CPU instructions such as CRC32 (or XOR, AESNI, etc).
> >
> > The code proposed in this patch is used to compute packet fields for
> various protocols that have a CRC field, such as FCS of Ethernet frames, etc.
> according to the relevant standard (IEEE 802, others). It is an utility to be used
> for implementing protocol-level functionality for various protocols from the
> network stack, similar to e.g. IP or UDP checksum. If we were to add an IP or
> UDCP checksum calculator, would you put it in librte_hash?
> >
> > The code from this patch is never going to be used to compute a fast
> signature/digest. Typically this CRC is computed over the entire frame/packet
> rather than just selected fields from the packet representing the application-
> specific flow key. Also note that the signature produced by CRC32 hash
> function from librte_hash is actually not the correct Cyclic Redundancy Check
> of that array of bytes (or, for math guys, of the associated polynomial), it is
> just a partial/intermediate value.
> >
> > Therefore, I suggest placing this code into: librte_ether (given that it can be
> used to compute Ethernet FCS), or librte_net, or librte_crc. Definitely not in
> librte_hash.
> 
> I agree with you Cristian that the protocol layer must be in librte_net.
> But I think most of this patch is not protocol level.

Nope, this is the true CRC computed over entire protocol header and/or payload. Similar to to IPv4/UDP/TCP checksum. The only reason for computing it is because the protocol specs require it for data integrity checks, nothing to do with our signature for load balancing/hash tables.

More details on covered protocols from a reliable source :) [1]:
	CRC-32 (polynomial = 0x04C11DB7): used for HDLC, ANSI X3.66, ITU-T V.42, Ethernet, Serial ATA, MPEG-2, PKZIP, Gzip, Bzip2, PNG, many others
	CRC-16-CCITT (polynomial = 0x1021): used for X.25, V.41, HDLC FCS, XMODEM, Bluetooth, PACTOR, SD, DigRF, many others

[1] Wikipedia: https://en.wikipedia.org/wiki/Cyclic_redundancy_check#Standards_and_common_use

> I think you agree with me that the code computing a
> "digest/signature for a given array of bytes" must go to librte_hash?

Yes, but this is the true protocol-level CRC, not a digest/signature.

Non-cryptographic hash digest/signature:
-computed over selected packet fields (flow key) for load balancing (affinity scheme) or hash table; key size typical range: 8 .. 192 bytes
-required by application requirements (such as flow packet ordering preservation), not by protocol standards
-has uniform distribution
-requires small amount of cycles to compute
-used as meta-data, not written in the packet
-can be opportunistically generated using specialized CPU instructions, such as CRC32 (or XEOR, or AESNI); in this case, it is a partial/intermediate value, not the correct CRC of the array of bytes

Protocol CRC:
-computed over entire packet header and/or payload
-protocol overhead (required by standards)
-computational cost is typically big and proportional with the packet length; packet length typical range: 64 .. 1514 .. 9K
-written in the packet (by the application SW or by the HW)
  

Patch

diff --git a/lib/librte_net/Makefile b/lib/librte_net/Makefile
index 20cf664..41be751 100644
--- a/lib/librte_net/Makefile
+++ b/lib/librte_net/Makefile
@@ -39,11 +39,13 @@  EXPORT_MAP := rte_net_version.map
 LIBABIVER := 1
 
 SRCS-$(CONFIG_RTE_LIBRTE_NET) := rte_net.c
+SRCS-$(CONFIG_RTE_LIBRTE_NET) += rte_net_crc.c
 
 # install includes
 SYMLINK-$(CONFIG_RTE_LIBRTE_NET)-include := rte_ip.h rte_tcp.h rte_udp.h
 SYMLINK-$(CONFIG_RTE_LIBRTE_NET)-include += rte_sctp.h rte_icmp.h rte_arp.h
 SYMLINK-$(CONFIG_RTE_LIBRTE_NET)-include += rte_ether.h rte_gre.h rte_net.h
+SYMLINK-$(CONFIG_RTE_LIBRTE_NET)-include += rte_net_crc.h
 
 DEPDIRS-$(CONFIG_RTE_LIBRTE_NET) += lib/librte_eal lib/librte_mbuf
 
diff --git a/lib/librte_net/rte_net_crc.c b/lib/librte_net/rte_net_crc.c
new file mode 100644
index 0000000..78a49dd
--- /dev/null
+++ b/lib/librte_net/rte_net_crc.c
@@ -0,0 +1,664 @@ 
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2017 Intel Corporation.
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of Intel Corporation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <rte_net_crc.h>
+#include <stddef.h>
+
+/* Macros for printing using RTE_LOG */
+#define RTE_LOGTYPE_CRC RTE_LOGTYPE_USER1
+
+/** CRC polynomials */
+#define CRC32_ETH_POLYNOMIAL 0x04c11db7UL
+#define CRC16_CCITT_POLYNOMIAL 0x1021U
+
+typedef int (*rte_net_crc_handler)(struct rte_net_crc_params *);
+
+static int rte_crc16_ccitt_handler(struct rte_net_crc_params *p);
+static int rte_crc32_eth_handler(struct rte_net_crc_params *p);
+static int rte_crc_invalid_handler(struct rte_net_crc_params *p);
+
+static rte_net_crc_handler *handlers;
+
+static rte_net_crc_handler handlers_scalar[] = {
+	[RTE_NET_CRC16_CCITT] = rte_crc16_ccitt_handler,
+	[RTE_NET_CRC32_ETH] = rte_crc32_eth_handler,
+	[RTE_NET_CRC_REQS] = rte_crc_invalid_handler,
+};
+
+int
+rte_crc_invalid_handler(__rte_unused struct rte_net_crc_params *p)
+{
+	RTE_LOG(ERR, CRC, "CRC type not supported!\n");
+	return -1;	/* Error */
+}
+
+#if defined RTE_ARCH_X86_64 && defined RTE_MACHINE_CPUFLAG_SSE4_2
+
+#include <cpuid.h>
+
+/** PCLMULQDQ CRC computation context structure */
+struct crc_pclmulqdq_ctx {
+	__m128i rk1_rk2;
+	__m128i rk5_rk6;
+	__m128i rk7_rk8;
+};
+
+struct crc_pclmulqdq_ctx crc32_eth_pclmulqdq __rte_aligned(16);
+struct crc_pclmulqdq_ctx crc16_ccitt_pclmulqdq __rte_aligned(16);
+/**
+ * @brief Performs one folding round
+ *
+ * Logically function operates as follows:
+ *     DATA = READ_NEXT_16BYTES();
+ *     F1 = LSB8(FOLD)
+ *     F2 = MSB8(FOLD)
+ *     T1 = CLMUL(F1, RK1)
+ *     T2 = CLMUL(F2, RK2)
+ *     FOLD = XOR(T1, T2, DATA)
+ *
+ * @param data_block 16 byte data block
+ * @param precomp precomputed rk1 constanst
+ * @param fold running 16 byte folded data
+ *
+ * @return New 16 byte folded data
+ */
+static inline __attribute__((always_inline)) __m128i
+crcr32_folding_round(const __m128i data_block,
+		const __m128i precomp,
+		const __m128i fold)
+{
+	__m128i tmp0 = _mm_clmulepi64_si128(fold, precomp, 0x01);
+	__m128i tmp1 = _mm_clmulepi64_si128(fold, precomp, 0x10);
+
+	return _mm_xor_si128(tmp1, _mm_xor_si128(data_block, tmp0));
+}
+
+/**
+ * Performs reduction from 128 bits to 64 bits
+ *
+ * @param data128 128 bits data to be reduced
+ * @param precomp rk5 and rk6 precomputed constants
+ *
+ * @return data reduced to 64 bits
+ */
+
+static inline __attribute__((always_inline)) __m128i
+crcr32_reduce_128_to_64(__m128i data128,
+	const __m128i precomp)
+{
+	__m128i tmp0, tmp1, tmp2;
+
+	/* 64b fold */
+	tmp0 = _mm_clmulepi64_si128(data128, precomp, 0x00);
+	tmp1 = _mm_srli_si128(data128, 8);
+	tmp0 = _mm_xor_si128(tmp0, tmp1);
+
+	/* 32b fold */
+	tmp2 = _mm_slli_si128(tmp0, 4);
+	tmp1 = _mm_clmulepi64_si128(tmp2, precomp, 0x10);
+
+	return _mm_xor_si128(tmp1, tmp0);
+}
+
+/**
+ * Performs Barret's reduction from 64 bits to 32 bits
+ *
+ * @param data64 64 bits data to be reduced
+ * @param precomp rk7 precomputed constant
+ *
+ * @return data reduced to 32 bits
+ */
+
+static inline __attribute__((always_inline)) uint32_t
+crcr32_reduce_64_to_32(__m128i data64,
+	const __m128i precomp)
+{
+	static const uint32_t mask1[4] __rte_aligned(16) = {
+		0xffffffff, 0xffffffff, 0x00000000, 0x00000000
+	};
+
+	static const uint32_t mask2[4] __rte_aligned(16) = {
+		0x00000000, 0xffffffff, 0xffffffff, 0xffffffff
+	};
+	__m128i tmp0, tmp1, tmp2;
+
+	tmp0 = _mm_and_si128(data64, _mm_load_si128((const __m128i *)mask2));
+
+	tmp1 = _mm_clmulepi64_si128(tmp0, precomp, 0x00);
+	tmp1 = _mm_xor_si128(tmp1, tmp0);
+	tmp1 = _mm_and_si128(tmp1, _mm_load_si128((const __m128i *)mask1));
+
+	tmp2 = _mm_clmulepi64_si128(tmp1, precomp, 0x10);
+	tmp2 = _mm_xor_si128(tmp2, tmp1);
+	tmp2 = _mm_xor_si128(tmp2, tmp0);
+
+	return _mm_extract_epi32(tmp2, 2);
+}
+
+/**
+ * Computes constant for CLMUL algorithm
+ *
+ * Result is: X^exp mod poly
+ *
+ * @param poly polynomial
+ * @param exp exponent
+ *
+ * @return constant value
+ */
+
+static inline uint32_t
+get_poly_constant(const uint32_t poly, const uint32_t exp)
+{
+	uint32_t i, res = poly;
+
+	for (i = 32; i < exp; i++)
+		if (res & 0x80000000)
+			res = (res << 1) ^ poly;
+		else
+			res = (res << 1);
+
+	return res;
+}
+
+/**
+ * Calculates quotient and reminder of X^64 / P(X)
+ *
+ * @param poly P(X)
+ * @param q_ptr place to store quotient
+ * @param r_ptr place to store reminder
+ */
+static inline void
+div_poly(const uint64_t poly,
+	uint64_t *q_ptr,
+	uint64_t *r_ptr)
+{
+	uint64_t p = 0, q = 0, r = 0;
+	int i;
+
+	p = poly | 0x100000000ULL;
+
+	r = p;
+	r = r << 32;
+
+	i = 32;
+	do {
+		uint64_t one_shl_n = 0;
+
+		q = q << 1;
+		if ((i + 32) < 64)
+			one_shl_n = 1ULL << (32 + i);
+
+		if (r & one_shl_n) {
+			r ^= (p << i);
+			q |= 1;
+		}
+		i--;
+	} while (i >= 0);
+
+	if (q_ptr != NULL)
+		*q_ptr = q;
+
+	if (r_ptr != NULL)
+		*r_ptr = r;
+}
+
+/**
+ * Reflects selected group of bits in \a v
+ *
+ * @param v value to be reflected
+ * @param n size of the bit field to be reflected
+ *
+ * @return bit reflected value
+ */
+static uint64_t
+reflect(uint64_t v, const uint32_t n)
+{
+	uint32_t i;
+	uint64_t r = 0;
+
+	for (i = 0; i < n; i++) {
+		if (i != 0) {
+			r <<= 1;
+			v >>= 1;
+		}
+		r |= (v & 1);
+	}
+
+	return r;
+}
+
+const uint8_t crc_xmm_shift_tab[48] __rte_aligned(16) = {
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+	0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
+};
+
+/**
+ * Shifts left 128 bit register by specified number of bytes
+ *
+ * @param reg 128 bit value
+ * @param num number of bytes to shift left reg by (0-16)
+ *
+ * @return reg << (num * 8)
+ */
+
+static inline __attribute__((always_inline)) __m128i
+xmm_shift_left(__m128i reg, const unsigned int num)
+{
+	const __m128i *p = (const __m128i *)(crc_xmm_shift_tab + 16 - num);
+
+	return _mm_shuffle_epi8(reg, _mm_loadu_si128(p));
+}
+
+/**
+ * Initializes CRC computation context structure for given polynomial
+ *
+ * @param pctx plcmulqdq CRC computation context structure to be initialized
+ * @param poly CRC polynomial
+ *
+ * return 0 on success, -1 otherwise
+ */
+static inline __attribute__((always_inline)) int
+crc32_eth_init_pclmulqdq(
+	struct crc_pclmulqdq_ctx *pctx,
+	const uint64_t poly)
+{
+	uint64_t k1, k2, k5, k6;
+	uint64_t p = 0, q = 0;
+
+	if (pctx == NULL)
+		return -1;
+
+	k1 = get_poly_constant(poly, 128 - 32);
+	k2 = get_poly_constant(poly, 128 + 32);
+	k5 = get_poly_constant(poly, 96);
+	k6 = get_poly_constant(poly, 64);
+
+	div_poly(poly, &q, NULL);
+	q = q & 0xffffffff;			/** quotient X^64 / P(X) */
+	p = poly | 0x100000000ULL;	/** P(X) */
+
+	k1 = reflect(k1 << 32, 64) << 1;
+	k2 = reflect(k2 << 32, 64) << 1;
+	k5 = reflect(k5 << 32, 64) << 1;
+	k6 = reflect(k6 << 32, 64) << 1;
+	q = reflect(q, 33);
+	p = reflect(p, 33);
+
+	/** Save the params in context structure */
+	pctx->rk1_rk2 = _mm_setr_epi64(_m_from_int64(k1), _m_from_int64(k2));
+	pctx->rk5_rk6 = _mm_setr_epi64(_m_from_int64(k5), _m_from_int64(k6));
+	pctx->rk7_rk8 = _mm_setr_epi64(_m_from_int64(q), _m_from_int64(p));
+
+	return 0;
+}
+
+static inline __attribute__((always_inline)) uint32_t
+crc32_eth_calc_pclmulqdq(
+	const uint8_t *data,
+	uint32_t data_len,
+	uint32_t crc,
+	const struct crc_pclmulqdq_ctx *params)
+{
+	__m128i temp, fold, k;
+	uint32_t n;
+
+	if (unlikely(data == NULL))
+		return crc;
+
+	if (unlikely(data_len == 0))
+		return crc;
+
+	if (unlikely(params == NULL))
+		return crc;
+
+	/* Get CRC init value */
+	temp = _mm_insert_epi32(_mm_setzero_si128(), crc, 0);
+
+	/**
+	 * Folding all data into single 16 byte data block
+	 * Assumes: fold holds first 16 bytes of data
+	 */
+
+	if (unlikely(data_len < 32)) {
+		if (unlikely(data_len == 16)) {
+			/* 16 bytes */
+			fold = _mm_loadu_si128((const __m128i *)data);
+			fold = _mm_xor_si128(fold, temp);
+			goto reduction_128_64;
+		}
+
+		if (unlikely(data_len < 16)) {
+			/* 0 to 15 bytes */
+			uint8_t buffer[16] __rte_aligned(16);
+
+			memset(buffer, 0, sizeof(buffer));
+			memcpy(buffer, data, data_len);
+
+			fold = _mm_load_si128((const __m128i *)buffer);
+			fold = _mm_xor_si128(fold, temp);
+			if (unlikely(data_len < 4)) {
+				fold = xmm_shift_left(fold, 8 - data_len);
+				goto barret_reduction;
+			}
+			fold = xmm_shift_left(fold, 16 - data_len);
+			goto reduction_128_64;
+		}
+		/* 17 to 31 bytes */
+		fold = _mm_loadu_si128((const __m128i *)data);
+		fold = _mm_xor_si128(fold, temp);
+		n = 16;
+		k = params->rk1_rk2;
+		goto partial_bytes;
+	}
+
+	/** At least 32 bytes in the buffer */
+	/** Apply CRC initial value */
+	fold = _mm_loadu_si128((const __m128i *)data);
+	fold = _mm_xor_si128(fold, temp);
+
+	/** Main folding loop - the last 16 bytes is processed separately */
+	k = params->rk1_rk2;
+	for (n = 16; (n + 16) <= data_len; n += 16) {
+		temp = _mm_loadu_si128((const __m128i *)&data[n]);
+		fold = crcr32_folding_round(temp, k, fold);
+	}
+
+partial_bytes:
+	if (likely(n < data_len)) {
+
+		const uint32_t mask3[4] __rte_aligned(16) = {
+			0x80808080, 0x80808080, 0x80808080, 0x80808080
+		};
+
+		const uint8_t shf_table[32] __rte_aligned(16) = {
+			0x00, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+			0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
+			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+			0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
+		};
+
+		__m128i last16, a, b;
+
+		last16 = _mm_loadu_si128((const __m128i *)&data[data_len - 16]);
+
+		temp = _mm_loadu_si128((const __m128i *)
+			&shf_table[data_len & 15]);
+		a = _mm_shuffle_epi8(fold, temp);
+
+		temp = _mm_xor_si128(temp,
+			_mm_load_si128((const __m128i *)mask3));
+		b = _mm_shuffle_epi8(fold, temp);
+		b = _mm_blendv_epi8(b, last16, temp);
+
+		/* k = rk1 & rk2 */
+		temp = _mm_clmulepi64_si128(a, k, 0x01);
+		fold = _mm_clmulepi64_si128(a, k, 0x10);
+
+		fold = _mm_xor_si128(fold, temp);
+		fold = _mm_xor_si128(fold, b);
+	}
+
+	/** Reduction 128 -> 32 Assumes: fold holds 128bit folded data */
+reduction_128_64:
+	k = params->rk5_rk6;
+	fold = crcr32_reduce_128_to_64(fold, k);
+
+barret_reduction:
+	k = params->rk7_rk8;
+	n = crcr32_reduce_64_to_32(fold, k);
+
+	return n;
+}
+
+
+static int
+rte_net_crc_sse42_init(void)
+{
+	int status = 0;
+
+	/** Initialize CRC functions */
+	status = crc32_eth_init_pclmulqdq(&crc16_ccitt_pclmulqdq,
+		CRC16_CCITT_POLYNOMIAL << 16);
+	if (status == -1)
+		return -1;
+
+	status = crc32_eth_init_pclmulqdq(&crc32_eth_pclmulqdq,
+		CRC32_ETH_POLYNOMIAL);
+	if (status == -1)
+		return -1;
+
+	_mm_empty();
+
+	return 0;
+}
+
+static inline int
+rte_crc16_ccitt_sse42_handler(struct rte_net_crc_params *p)
+{
+	uint16_t ret;
+	const uint8_t *data =
+		rte_pktmbuf_mtod_offset(p->mbuf, uint8_t *, p->data_offset);
+
+	ret = (uint16_t)~crc32_eth_calc_pclmulqdq(data,
+		p->data_len,
+		0xffff,
+		&crc16_ccitt_pclmulqdq);
+
+	return ret;
+}
+
+static inline int
+rte_crc32_eth_sse42_handler(struct rte_net_crc_params *p)
+{
+	uint32_t ret;
+	const uint8_t *data =
+		rte_pktmbuf_mtod_offset(p->mbuf, uint8_t *, p->data_offset);
+
+	ret = ~crc32_eth_calc_pclmulqdq(data,
+		p->data_len,
+		0xffffffffUL,
+		&crc32_eth_pclmulqdq);
+
+	return ret;
+}
+
+static rte_net_crc_handler handlers_sse42[] = {
+	[RTE_NET_CRC16_CCITT] = rte_crc16_ccitt_sse42_handler,
+	[RTE_NET_CRC32_ETH] = rte_crc32_eth_sse42_handler,
+	[RTE_NET_CRC_REQS] = rte_crc_invalid_handler,
+};
+
+#endif
+
+/** Local data */
+static uint32_t crc32_eth_lut[256];
+static uint32_t crc16_ccitt_lut[256];
+
+/**
+ * @brief Reflect the bits about the middle
+ *
+ * @param x value to be reflected
+ *
+ * @return reflected value
+ */
+static uint32_t
+reflect_32bits(const uint32_t val)
+{
+	uint32_t i, res = 0;
+
+	for (i = 0; i < 32; i++)
+		if ((val & (1 << i)) != 0)
+			res |= (uint32_t)(1 << (31 - i));
+
+	return res;
+}
+
+static int
+crc32_eth_init_lut(const uint32_t poly,
+	uint32_t *lut)
+{
+	uint_fast32_t i, j;
+
+	if (lut == NULL)
+		return -1;
+
+	for (i = 0; i < 256; i++) {
+		uint_fast32_t crc = reflect_32bits(i);
+
+		for (j = 0; j < 8; j++) {
+			if (crc & 0x80000000L)
+				crc = (crc << 1) ^ poly;
+			else
+				crc <<= 1;
+		}
+	lut[i] = reflect_32bits(crc);
+	}
+
+	return 0;
+}
+
+static inline __attribute__((always_inline)) uint32_t
+crc32_eth_calc_lut(const uint8_t *data,
+	uint32_t data_len,
+	uint32_t crc,
+	const uint32_t *lut)
+{
+	if (unlikely(data == NULL || lut == NULL))
+		return crc;
+
+	while (data_len--)
+		crc = lut[(crc ^ *data++) & 0xffL] ^ (crc >> 8);
+
+	return crc;
+}
+
+static int
+rte_net_crc_scalar_init(void)
+{
+	int status = 0;
+
+	/** 32-bit crc init */
+	status = crc32_eth_init_lut(CRC32_ETH_POLYNOMIAL,
+		crc32_eth_lut);
+	if (status == -1)
+		return -1;
+
+	/** 16-bit CRC init */
+	status = crc32_eth_init_lut(CRC16_CCITT_POLYNOMIAL << 16,
+		crc16_ccitt_lut);
+	if (status == -1)
+		return -1;
+
+	return 0;
+}
+
+static inline int
+rte_crc16_ccitt_handler(struct rte_net_crc_params *p)
+{
+	uint16_t ret;
+	const uint8_t *data =
+		rte_pktmbuf_mtod_offset(p->mbuf, uint8_t *, p->data_offset);
+
+	ret = (uint16_t)~crc32_eth_calc_lut(data,
+		p->data_len,
+		0xffff,
+		crc16_ccitt_lut);
+
+	return ret;
+}
+
+static inline int
+rte_crc32_eth_handler(struct rte_net_crc_params *p)
+{
+	uint32_t ret;
+	const uint8_t *data =
+		rte_pktmbuf_mtod_offset(p->mbuf, uint8_t *, p->data_offset);
+
+	ret = ~crc32_eth_calc_lut(data,
+		p->data_len,
+		0xffffffffUL,
+		crc32_eth_lut);
+
+	return ret;
+}
+
+int
+rte_net_crc_init(enum rte_net_crc_mode m)
+{
+	int status;
+
+	switch (m) {
+
+	case RTE_NET_CRC_SSE42:
+#ifdef RTE_ARCH_X86_64
+		if (rte_cpu_get_flag_enabled(RTE_CPUFLAG_SSE4_2)) {
+			status = rte_net_crc_sse42_init();
+			handlers = handlers_sse42;
+		} else {
+			status = -1;
+			RTE_LOG(ERR, CRC,
+			"bad configuration(SSE4.2 not supported!)\n %s",
+			__func__);
+		}
+
+		return status;
+#else
+		RTE_LOG(ERR, CRC,
+			"bad configuration(x86_64 architecure not supported!)\n %s",
+			__func__);
+		return -1;
+#endif
+	case RTE_NET_CRC_SCALAR:
+	default:
+		status = rte_net_crc_scalar_init();
+		handlers = handlers_scalar;
+
+		return status;
+	}
+}
+
+int
+rte_net_crc_calc(struct rte_net_crc_params *p)
+{
+	int ret;
+	rte_net_crc_handler f_handle;
+
+	f_handle = handlers[p->type];
+	ret = f_handle(p);
+
+	return ret;
+}
diff --git a/lib/librte_net/rte_net_crc.h b/lib/librte_net/rte_net_crc.h
new file mode 100644
index 0000000..accbeea
--- /dev/null
+++ b/lib/librte_net/rte_net_crc.h
@@ -0,0 +1,101 @@ 
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2017 Intel Corporation.
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of Intel Corporation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _RTE_NET_CRC_H_
+#define _RTE_NET_CRC_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+
+#include <rte_mbuf.h>
+
+/** CRC types */
+enum rte_net_crc_type {
+	RTE_NET_CRC16_CCITT = 0,
+	RTE_NET_CRC32_ETH,
+	RTE_NET_CRC_REQS
+};
+
+/** CRC compute mode */
+enum rte_net_crc_mode {
+	RTE_NET_CRC_SCALAR = 0,
+	RTE_NET_CRC_SSE42,
+	RTE_NET_CRC_DEFAULT
+};
+
+/** CRC calc APIs params */
+struct rte_net_crc_params {
+	struct rte_mbuf *mbuf;		/**< packet mbuf */
+	uint32_t data_offset;		/**< offset to the data */
+	uint32_t data_len;			/**< length of the data */
+	enum rte_net_crc_type type;	/**< crc type */
+};
+
+/**
+ * CRC Initialisation API
+ *
+ *  This API should be called only once to initialise the internal crc
+ *  data structue before using CRC compute API.
+ *
+ * @param crc_mode
+ *   crc compute mode
+ *
+ * @return
+ *   0 on success, -1 otherwise
+ */
+
+int
+rte_net_crc_init(enum rte_net_crc_mode m);
+
+/**
+ * CRC compute API
+ *
+ * @param
+ *  structure rte_net_crc_params
+ *
+ * @return
+ *   crc value
+ */
+
+int
+rte_net_crc_calc(struct rte_net_crc_params *p);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* _RTE_NET_CRC_H_ */
diff --git a/lib/librte_net/rte_net_version.map b/lib/librte_net/rte_net_version.map
index 3b15e65..d391834 100644
--- a/lib/librte_net/rte_net_version.map
+++ b/lib/librte_net/rte_net_version.map
@@ -4,3 +4,11 @@  DPDK_16.11 {
 
 	local: *;
 };
+
+DPDK_17.05 {
+	global:
+
+	rte_net_crc_init;
+	rte_net_crc_calc;
+
+} DPDK_16.11;