diff --git a/test/validation/api/ipsec/ipsec.c b/test/validation/api/ipsec/ipsec.c
index 853bd88a9..5883f23e2 100644
--- a/test/validation/api/ipsec/ipsec.c
+++ b/test/validation/api/ipsec/ipsec.c
@@ -117,6 +117,35 @@ static void pktio_stop(odp_pktio_t pktio)
 	}
 }
 
+static odp_cos_t ipsec_cos_create(void)
+{
+	odp_cls_cos_param_t param;
+	odp_cos_t cos;
+
+	odp_cls_cos_param_init(&param);
+	param.pool = suite_context.pool;
+	param.num_queue = 1;
+	param.queue = odp_queue_create("ipsec-cos-queue", NULL);
+
+	if (ODP_QUEUE_INVALID == param.queue)
+		return ODP_COS_INVALID;
+
+	cos = odp_cls_cos_create("ipsec-cos", &param);
+	if (ODP_COS_INVALID != cos)
+		suite_context.cos_queue = odp_cos_queue(cos);
+
+	return cos;
+}
+
+static void ipsec_cos_destroy(void)
+{
+	odp_queue_t queue = odp_cos_queue(suite_context.cos);
+
+	suite_context.cos_queue = ODP_QUEUE_INVALID;
+	odp_cos_destroy(suite_context.cos);
+	odp_queue_destroy(queue);
+}
+
 #define MAX_ALG_CAPA 32
 
 int ipsec_check(odp_bool_t ah,
@@ -147,6 +176,11 @@ int ipsec_check(odp_bool_t ah,
 	     ODP_SUPPORT_NO == capa.op_mode_inline_out))
 		return ODP_TEST_INACTIVE;
 
+	if (ODP_COS_INVALID != suite_context.cos &&
+	    (capa.pipeline_cls == ODP_SUPPORT_NO ||
+	     capa.max_cls_cos < 1))
+		return ODP_TEST_INACTIVE;
+
 	if (ah && (ODP_SUPPORT_NO == capa.proto_ah))
 		return ODP_TEST_INACTIVE;
 
@@ -288,6 +322,11 @@ void ipsec_sa_param_fill(odp_ipsec_sa_param_t *param,
 	if (in)
 		param->inbound.lookup_mode = ODP_IPSEC_LOOKUP_SPI;
 
+	if (in && (ODP_COS_INVALID != suite_context.cos)) {
+		param->inbound.pipeline = ODP_IPSEC_PIPELINE_CLS;
+		param->inbound.dest_cos = suite_context.cos;
+	}
+
 	param->proto = ah ? ODP_IPSEC_AH :
 			    ODP_IPSEC_ESP;
 
@@ -438,23 +477,53 @@ static int ipsec_send_in_one(const ipsec_test_part *part,
 							    pkto, &num_out,
 							    &param));
 		CU_ASSERT_EQUAL(num_out, part->out_pkt);
-	} else if (ODP_IPSEC_OP_MODE_ASYNC == suite_context.inbound_op_mode) {
+	} else if (ODP_IPSEC_OP_MODE_ASYNC == suite_context.inbound_op_mode &&
+		   ODP_QUEUE_INVALID == suite_context.cos_queue) {
 		CU_ASSERT_EQUAL(1, odp_ipsec_in_enq(&pkt, 1, &param));
 
-		for (i = 0; i < num_out; i++) {
-			odp_event_t event;
+		for (i = 0; i < num_out;) {
+			odp_event_t ev;
 			odp_event_subtype_t subtype;
 
-			do {
-				event = odp_queue_deq(suite_context.queue);
-			} while (event == ODP_EVENT_INVALID);
+			ev = odp_queue_deq(suite_context.queue);
+			if (ODP_EVENT_INVALID != ev) {
+				CU_ASSERT_EQUAL(ODP_EVENT_PACKET,
+						odp_event_types(ev, &subtype));
+				CU_ASSERT_EQUAL(ODP_EVENT_PACKET_IPSEC,
+						subtype);
+				pkto[i++] = odp_ipsec_packet_from_event(ev);
+			}
+		}
+	} else if (ODP_IPSEC_OP_MODE_ASYNC == suite_context.inbound_op_mode &&
+		   ODP_QUEUE_INVALID != suite_context.cos_queue) {
+		CU_ASSERT_EQUAL(1, odp_ipsec_in_enq(&pkt, 1, &param));
 
-			CU_ASSERT_EQUAL(ODP_EVENT_PACKET,
-					odp_event_types(event, &subtype));
-			CU_ASSERT_EQUAL(ODP_EVENT_PACKET_IPSEC, subtype);
-			pkto[i] = odp_ipsec_packet_from_event(event);
+		for (i = 0; i < num_out;) {
+			odp_event_t ev;
+			odp_event_subtype_t subtype;
+
+			ev = odp_queue_deq(suite_context.queue);
+			if (ODP_EVENT_INVALID != ev) {
+				CU_ASSERT_EQUAL(ODP_EVENT_PACKET,
+						odp_event_types(ev, &subtype));
+				CU_ASSERT_EQUAL(ODP_EVENT_PACKET_IPSEC,
+						subtype);
+				CU_ASSERT(part->out[i].status.error.all);
+				pkto[i++] = odp_ipsec_packet_from_event(ev);
+			}
+
+			ev = odp_queue_deq(suite_context.cos_queue);
+			if (ODP_EVENT_INVALID != ev) {
+				CU_ASSERT_EQUAL(ODP_EVENT_PACKET,
+						odp_event_types(ev, &subtype));
+				CU_ASSERT_EQUAL(ODP_EVENT_PACKET_IPSEC,
+						subtype);
+				CU_ASSERT(!part->out[i].status.error.all);
+				pkto[i++] = odp_ipsec_packet_from_event(ev);
+			}
 		}
-	} else {
+	} else if (ODP_IPSEC_OP_MODE_INLINE == suite_context.inbound_op_mode &&
+		   ODP_QUEUE_INVALID == suite_context.cos_queue) {
 		odp_queue_t queue;
 		odp_pktout_queue_t pktout;
 
@@ -495,6 +564,63 @@ static int ipsec_send_in_one(const ipsec_test_part *part,
 				continue;
 			}
 		}
+	} else if (ODP_IPSEC_OP_MODE_INLINE == suite_context.inbound_op_mode &&
+		   ODP_QUEUE_INVALID != suite_context.cos_queue) {
+		odp_queue_t queue;
+		odp_pktout_queue_t pktout;
+
+		CU_ASSERT_EQUAL_FATAL(1, odp_pktout_queue(suite_context.pktio,
+							  &pktout, 1));
+
+		CU_ASSERT_EQUAL(1, odp_pktout_send(pktout, &pkt, 1));
+		CU_ASSERT_EQUAL_FATAL(1,
+				      odp_pktin_event_queue(suite_context.
+							    pktio,
+							    &queue, 1));
+
+		for (i = 0; i < num_out;) {
+			odp_event_t ev;
+			odp_event_subtype_t subtype;
+
+			ev = odp_queue_deq(suite_context.cos_queue);
+			if (ODP_EVENT_INVALID != ev) {
+				CU_ASSERT_EQUAL(ODP_EVENT_PACKET,
+						odp_event_types(ev, &subtype));
+				CU_ASSERT_EQUAL(ODP_EVENT_PACKET_IPSEC,
+						subtype);
+				CU_ASSERT(!part->out[i].status.error.all);
+
+				pkto[i++] = odp_ipsec_packet_from_event(ev);
+				continue;
+			}
+
+			ev = odp_queue_deq(queue);
+			if (ODP_EVENT_INVALID != ev) {
+				CU_ASSERT_EQUAL(ODP_EVENT_PACKET,
+						odp_event_types(ev, &subtype));
+				CU_ASSERT_EQUAL(ODP_EVENT_PACKET_BASIC,
+						subtype);
+				CU_ASSERT(part->out[i].status.error.sa_lookup);
+
+				pkto[i++] = odp_ipsec_packet_from_event(ev);
+				continue;
+			}
+
+			ev = odp_queue_deq(suite_context.queue);
+			if (ODP_EVENT_INVALID != ev) {
+				CU_ASSERT_EQUAL(ODP_EVENT_PACKET,
+						odp_event_types(ev, &subtype));
+				CU_ASSERT_EQUAL(ODP_EVENT_PACKET_IPSEC,
+						subtype);
+				CU_ASSERT(!part->out[i].status.error.sa_lookup);
+				CU_ASSERT(part->out[i].status.error.all);
+
+				pkto[i++] = odp_ipsec_packet_from_event(ev);
+				continue;
+			}
+		}
+	} else {
+		CU_FAIL("Unsupported configuration!\n");
 	}
 
 	return num_out;
@@ -724,14 +850,31 @@ int ipsec_suite_init(void)
 	if (rc == 0)
 		suite_context.pktio = ODP_PKTIO_INVALID;
 
+	suite_context.cos = ODP_COS_INVALID;
+
 	return rc < 0 ? -1 : 0;
 }
 
+int ipsec_suite_cos_init(void)
+{
+	int ret = ipsec_suite_init();
+
+	if (ret < 0)
+		return ret;
+
+	suite_context.cos = ipsec_cos_create();
+
+	return 0;
+}
+
 static int ipsec_suite_term(odp_testinfo_t *suite)
 {
 	int i;
 	int first = 1;
 
+	if (suite_context.cos != ODP_COS_INVALID)
+		ipsec_cos_destroy();
+
 	if (suite_context.pktio != ODP_PKTIO_INVALID)
 		pktio_stop(suite_context.pktio);
 
diff --git a/test/validation/api/ipsec/ipsec.h b/test/validation/api/ipsec/ipsec.h
index d1c6854b7..472179f91 100644
--- a/test/validation/api/ipsec/ipsec.h
+++ b/test/validation/api/ipsec/ipsec.h
@@ -21,6 +21,7 @@ int ipsec_in_inline_init(void);
 int ipsec_out_inline_init(void);
 
 int ipsec_suite_init(void);
+int ipsec_suite_cos_init(void);
 int ipsec_in_term(void);
 int ipsec_out_term(void);
 
@@ -30,6 +31,8 @@ struct suite_context_s {
 	odp_pool_t pool;
 	odp_queue_t queue;
 	odp_pktio_t pktio;
+	odp_cos_t cos;
+	odp_queue_t cos_queue;
 };
 
 extern struct suite_context_s suite_context;
diff --git a/test/validation/api/ipsec/ipsec_async.c b/test/validation/api/ipsec/ipsec_async.c
index 796879230..f5d384392 100644
--- a/test/validation/api/ipsec/ipsec_async.c
+++ b/test/validation/api/ipsec/ipsec_async.c
@@ -32,6 +32,7 @@ static int ipsec_async_init(odp_instance_t *inst)
 
 odp_suiteinfo_t ipsec_suites[] = {
 	{"IPsec-in", ipsec_suite_init, ipsec_in_term, ipsec_in_suite},
+	{"IPsec-cos-in", ipsec_suite_cos_init, ipsec_in_term, ipsec_in_suite},
 	{"IPsec-out", ipsec_suite_init, ipsec_out_term, ipsec_out_suite},
 	ODP_SUITE_INFO_NULL,
 };
diff --git a/test/validation/api/ipsec/ipsec_inline_in.c b/test/validation/api/ipsec/ipsec_inline_in.c
index 2a595353d..c2f6411f0 100644
--- a/test/validation/api/ipsec/ipsec_inline_in.c
+++ b/test/validation/api/ipsec/ipsec_inline_in.c
@@ -34,6 +34,7 @@ static int ipsec_sync_init(odp_instance_t *inst)
 
 odp_suiteinfo_t ipsec_suites[] = {
 	{"IPsec-in", ipsec_suite_init, ipsec_in_term, ipsec_in_suite},
+	{"IPsec-cos-in", ipsec_suite_cos_init, ipsec_in_term, ipsec_in_suite},
 	ODP_SUITE_INFO_NULL,
 };
 
