diff --git a/doc/guides/cryptodevs/aesni_mb.rst b/doc/guides/cryptodevs/aesni_mb.rst
index 1680c4a..236828c 100644
--- a/doc/guides/cryptodevs/aesni_mb.rst
+++ b/doc/guides/cryptodevs/aesni_mb.rst
@@ -38,6 +38,7 @@ Hash algorithms:
 * RTE_CRYPTO_HASH_SHA384_HMAC
 * RTE_CRYPTO_HASH_SHA512_HMAC
 * RTE_CRYPTO_HASH_AES_XCBC_HMAC
+* RTE_CRYPTO_HASH_AES_CMAC
 
 AEAD algorithms:
 
diff --git a/doc/guides/cryptodevs/features/aesni_mb.ini b/doc/guides/cryptodevs/features/aesni_mb.ini
index a5a45a6..15da95a 100644
--- a/doc/guides/cryptodevs/features/aesni_mb.ini
+++ b/doc/guides/cryptodevs/features/aesni_mb.ini
@@ -37,7 +37,7 @@ SHA256 HMAC  = Y
 SHA384 HMAC  = Y
 SHA512 HMAC  = Y
 AES XCBC MAC = Y
-
+AES CMAC (128)  = Y
 ;
 ; Supported AEAD algorithms of the 'aesni_mb' crypto driver.
 ;
diff --git a/doc/guides/cryptodevs/features/default.ini b/doc/guides/cryptodevs/features/default.ini
index 728ce3b..243ac76 100644
--- a/doc/guides/cryptodevs/features/default.ini
+++ b/doc/guides/cryptodevs/features/default.ini
@@ -62,6 +62,7 @@ AES GMAC     =
 SNOW3G UIA2  =
 KASUMI F9    =
 ZUC EIA3     =
+AES CMAC(128) =
 
 ;
 ; Supported AEAD algorithms of a default crypto driver.
diff --git a/doc/guides/rel_notes/release_18_05.rst b/doc/guides/rel_notes/release_18_05.rst
index 3923dc2..48d58b0 100644
--- a/doc/guides/rel_notes/release_18_05.rst
+++ b/doc/guides/rel_notes/release_18_05.rst
@@ -41,6 +41,12 @@ New Features
      Also, make sure to start the actual text at the margin.
      =========================================================
 
+    * **Updated the AESNI MB PMD.**
+
+      The AESNI MB PMD has been updated with additional support for:
+
+      * AES-CMAC (128-bit key).
+
 
 API Changes
 -----------
diff --git a/drivers/crypto/aesni_mb/aesni_mb_ops.h b/drivers/crypto/aesni_mb/aesni_mb_ops.h
index 56fd829..5a1cba6 100644
--- a/drivers/crypto/aesni_mb/aesni_mb_ops.h
+++ b/drivers/crypto/aesni_mb/aesni_mb_ops.h
@@ -33,9 +33,12 @@ typedef void (*aes_keyexp_192_t)
 		(const void *key, void *enc_exp_keys, void *dec_exp_keys);
 typedef void (*aes_keyexp_256_t)
 		(const void *key, void *enc_exp_keys, void *dec_exp_keys);
-
 typedef void (*aes_xcbc_expand_key_t)
 		(const void *key, void *exp_k1, void *k2, void *k3);
+typedef void (*aes_cmac_sub_key_gen_t)
+		(const void *exp_key, void *k2, void *k3);
+typedef void (*aes_cmac_keyexp_t)
+		(const void *key, void *keyexp);
 
 /** Multi-buffer library function pointer table */
 struct aesni_mb_op_fns {
@@ -77,9 +80,12 @@ struct aesni_mb_op_fns {
 			/**< AES192 key expansions */
 			aes_keyexp_256_t aes256;
 			/**< AES256 key expansions */
-
 			aes_xcbc_expand_key_t aes_xcbc;
-			/**< AES XCBC key expansions */
+			/**< AES XCBC key epansions */
+			aes_cmac_sub_key_gen_t aes_cmac_subkey;
+			/**< AES CMAC subkey expansions */
+			aes_cmac_keyexp_t aes_cmac_expkey;
+			/**< AES CMAC key expansions */
 		} keyexp;
 		/**< Key expansion functions */
 	} aux;
@@ -122,7 +128,9 @@ static const struct aesni_mb_op_fns job_ops[] = {
 					aes_keyexp_128_sse,
 					aes_keyexp_192_sse,
 					aes_keyexp_256_sse,
-					aes_xcbc_expand_key_sse
+					aes_xcbc_expand_key_sse,
+					aes_cmac_subkey_gen_sse,
+					aes_keyexp_128_enc_sse
 				}
 			}
 		},
@@ -147,7 +155,9 @@ static const struct aesni_mb_op_fns job_ops[] = {
 					aes_keyexp_128_avx,
 					aes_keyexp_192_avx,
 					aes_keyexp_256_avx,
-					aes_xcbc_expand_key_avx
+					aes_xcbc_expand_key_avx,
+					aes_cmac_subkey_gen_avx,
+					aes_keyexp_128_enc_avx
 				}
 			}
 		},
@@ -172,7 +182,9 @@ static const struct aesni_mb_op_fns job_ops[] = {
 					aes_keyexp_128_avx2,
 					aes_keyexp_192_avx2,
 					aes_keyexp_256_avx2,
-					aes_xcbc_expand_key_avx2
+					aes_xcbc_expand_key_avx2,
+					aes_cmac_subkey_gen_avx2,
+					aes_keyexp_128_enc_avx2
 				}
 			}
 		},
@@ -197,7 +209,9 @@ static const struct aesni_mb_op_fns job_ops[] = {
 					aes_keyexp_128_avx512,
 					aes_keyexp_192_avx512,
 					aes_keyexp_256_avx512,
-					aes_xcbc_expand_key_avx512
+					aes_xcbc_expand_key_avx512,
+					aes_cmac_subkey_gen_avx512,
+					aes_keyexp_128_enc_avx512
 				}
 			}
 		}
diff --git a/drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c b/drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c
index 6f06ec4..2e50078 100644
--- a/drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c
+++ b/drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c
@@ -124,6 +124,17 @@ aesni_mb_set_session_auth_parameters(const struct aesni_mb_op_fns *mb_ops,
 		return 0;
 	}
 
+	if (xform->auth.algo == RTE_CRYPTO_AUTH_AES_CMAC) {
+		sess->auth.algo = AES_CMAC;
+		(*mb_ops->aux.keyexp.aes_cmac_expkey)(xform->auth.key.data,
+				sess->auth.cmac.expkey);
+
+		(*mb_ops->aux.keyexp.aes_cmac_subkey)(sess->auth.cmac.expkey,
+				sess->auth.cmac.skey1, sess->auth.cmac.skey2);
+		return 0;
+	}
+
+
 	switch (xform->auth.algo) {
 	case RTE_CRYPTO_AUTH_MD5_HMAC:
 		sess->auth.algo = MD5;
@@ -338,16 +349,19 @@ aesni_mb_set_session_parameters(const struct aesni_mb_op_fns *mb_ops,
 		sess->chain_order = HASH_CIPHER;
 		auth_xform = xform;
 		cipher_xform = xform->next;
+		sess->auth.digest_len = xform->auth.digest_length;
 		break;
 	case AESNI_MB_OP_CIPHER_HASH:
 		sess->chain_order = CIPHER_HASH;
 		auth_xform = xform->next;
 		cipher_xform = xform;
+		sess->auth.digest_len = xform->auth.digest_length;
 		break;
 	case AESNI_MB_OP_HASH_ONLY:
 		sess->chain_order = HASH_CIPHER;
 		auth_xform = xform;
 		cipher_xform = NULL;
+		sess->auth.digest_len = xform->auth.digest_length;
 		break;
 	case AESNI_MB_OP_CIPHER_ONLY:
 		/*
@@ -366,13 +380,13 @@ aesni_mb_set_session_parameters(const struct aesni_mb_op_fns *mb_ops,
 	case AESNI_MB_OP_AEAD_CIPHER_HASH:
 		sess->chain_order = CIPHER_HASH;
 		sess->aead.aad_len = xform->aead.aad_length;
-		sess->aead.digest_len = xform->aead.digest_length;
+		sess->auth.digest_len = xform->aead.digest_length;
 		aead_xform = xform;
 		break;
 	case AESNI_MB_OP_AEAD_HASH_CIPHER:
 		sess->chain_order = HASH_CIPHER;
 		sess->aead.aad_len = xform->aead.aad_length;
-		sess->aead.digest_len = xform->aead.digest_length;
+		sess->auth.digest_len = xform->aead.digest_length;
 		aead_xform = xform;
 		break;
 	case AESNI_MB_OP_NOT_SUPPORTED:
@@ -523,6 +537,11 @@ set_mb_job_params(JOB_AES_HMAC *job, struct aesni_mb_qp *qp,
 	} else if (job->hash_alg == AES_CCM) {
 		job->u.CCM.aad = op->sym->aead.aad.data + 18;
 		job->u.CCM.aad_len_in_bytes = session->aead.aad_len;
+	} else if (job->hash_alg == AES_CMAC) {
+		job->u.CMAC._key_expanded = session->auth.cmac.expkey;
+		job->u.CMAC._skey1 = session->auth.cmac.skey1;
+		job->u.CMAC._skey2 = session->auth.cmac.skey2;
+
 	} else {
 		job->u.HMAC._hashed_auth_key_xor_ipad = session->auth.pads.inner;
 		job->u.HMAC._hashed_auth_key_xor_opad = session->auth.pads.outer;
@@ -568,11 +587,11 @@ set_mb_job_params(JOB_AES_HMAC *job, struct aesni_mb_qp *qp,
 	 * Multi-buffer library current only support returning a truncated
 	 * digest length as specified in the relevant IPsec RFCs
 	 */
-	if (job->hash_alg != AES_CCM)
+	if (job->hash_alg != AES_CCM && job->hash_alg != AES_CMAC)
 		job->auth_tag_output_len_in_bytes =
 				get_truncated_digest_byte_length(job->hash_alg);
 	else
-		job->auth_tag_output_len_in_bytes = session->aead.digest_len;
+		job->auth_tag_output_len_in_bytes = session->auth.digest_len;
 
 
 	/* Set IV parameters */
diff --git a/drivers/crypto/aesni_mb/rte_aesni_mb_pmd_private.h b/drivers/crypto/aesni_mb/rte_aesni_mb_pmd_private.h
index 948e091..61e8aa7 100644
--- a/drivers/crypto/aesni_mb/rte_aesni_mb_pmd_private.h
+++ b/drivers/crypto/aesni_mb/rte_aesni_mb_pmd_private.h
@@ -66,6 +66,7 @@ static const unsigned auth_truncated_digest_byte_lengths[] = {
 		[SHA_384]	= 24,
 		[SHA_512]	= 32,
 		[AES_XCBC]	= 12,
+		[AES_CMAC]	= 16,
 		[AES_CCM]	= 8,
 		[NULL_HASH]     = 0
 };
@@ -91,7 +92,8 @@ static const unsigned auth_digest_byte_lengths[] = {
 		[SHA_384]	= 48,
 		[SHA_512]	= 64,
 		[AES_XCBC]	= 16,
-		[NULL_HASH]     = 0
+		[AES_CMAC]	= 16,
+		[NULL_HASH]		= 0
 };
 
 /**
@@ -211,14 +213,24 @@ struct aesni_mb_session {
 			    uint8_t k3[16] __rte_aligned(16);
 			    /**< k3. */
 			} xcbc;
+
+			struct {
+				uint32_t expkey[60] __rte_aligned(16);
+						    /**< k1 (expanded key). */
+				uint32_t skey1[4] __rte_aligned(16);
+						    /**< k2. */
+				uint32_t skey2[4] __rte_aligned(16);
+						    /**< k3. */
+			} cmac;
 			/**< Expanded XCBC authentication keys */
 		};
+	/** digest size */
+	uint16_t digest_len;
+
 	} auth;
 	struct {
 		/** AAD data length */
 		uint16_t aad_len;
-		/** digest size */
-		uint16_t digest_len;
 	} aead;
 } __rte_cache_aligned;
 
diff --git a/test/test/test_cryptodev_hash_test_vectors.h b/test/test/test_cryptodev_hash_test_vectors.h
index df9202f..45e80dc 100644
--- a/test/test/test_cryptodev_hash_test_vectors.h
+++ b/test/test/test_cryptodev_hash_test_vectors.h
@@ -34,6 +34,7 @@ static const uint8_t plaintext_hash[] = {
 	"an old violinist or sculptor somewhere."
 };
 
+
 static const struct blockcipher_test_data
 md5_test_vector = {
 	.auth_algo = RTE_CRYPTO_AUTH_MD5,
@@ -319,6 +320,53 @@ hmac_sha512_test_vector = {
 	}
 };
 
+static const struct blockcipher_test_data
+cmac_test_vector = {
+	.auth_algo = RTE_CRYPTO_AUTH_AES_CMAC,
+	.ciphertext = {
+		.data = plaintext_hash,
+		.len = 512
+	},
+	.auth_key = {
+		.data = {
+			0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
+			0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c
+		},
+		.len = 16
+	},
+	.digest = {
+		.data = {
+			0x4c, 0x77, 0x87, 0xa0, 0x78, 0x8e, 0xea, 0x96,
+			0xc1, 0xeb, 0x1e, 0x4e, 0x95, 0x8f, 0xed, 0x27
+		},
+		.len = 16,
+		.truncated_len = 16
+	}
+};
+static const struct blockcipher_test_data
+cmac_test_vector_12 = {
+	.auth_algo = RTE_CRYPTO_AUTH_AES_CMAC,
+	.ciphertext = {
+		.data = plaintext_hash,
+		.len = 512
+	},
+	.auth_key = {
+		.data = {
+			0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
+			0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c
+		},
+		.len = 16
+	},
+	.digest = {
+		.data = {
+			0x4c, 0x77, 0x87, 0xa0, 0x78, 0x8e, 0xea, 0x96,
+			0xc1, 0xeb, 0x1e, 0x4e
+		},
+		.len = 12,
+		.truncated_len = 12
+	}
+};
+
 static const struct blockcipher_test_case hash_test_cases[] = {
 	{
 		.test_descr = "MD5 Digest",
@@ -562,6 +610,30 @@ static const struct blockcipher_test_case hash_test_cases[] = {
 			BLOCKCIPHER_TEST_TARGET_PMD_QAT |
 			BLOCKCIPHER_TEST_TARGET_PMD_MRVL
 	},
+	{
+		.test_descr = "CMAC Digest 12B",
+		.test_data = &cmac_test_vector_12,
+		.op_mask = BLOCKCIPHER_TEST_OP_AUTH_GEN,
+		.pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_MB
+	},
+	{
+		.test_descr = "CMAC Digest Verify 12B",
+		.test_data = &cmac_test_vector_12,
+		.op_mask = BLOCKCIPHER_TEST_OP_AUTH_VERIFY,
+		.pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_MB
+	},
+	{
+		.test_descr = "CMAC Digest 16B",
+		.test_data = &cmac_test_vector,
+		.op_mask = BLOCKCIPHER_TEST_OP_AUTH_GEN,
+		.pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_MB
+	},
+	{
+		.test_descr = "CMAC Digest Verify 16B",
+		.test_data = &cmac_test_vector,
+		.op_mask = BLOCKCIPHER_TEST_OP_AUTH_VERIFY,
+		.pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_MB
+	}
 };
 
 #endif /* TEST_CRYPTODEV_HASH_TEST_VECTORS_H_ */
