diff mbox

[API-NEXT,v3,8/9] queue: handle return value of odp_queue_enq()

Message ID 1433526691-20058-9-git-send-email-zoltan.kiss@linaro.org
State New
Headers show

Commit Message

Zoltan Kiss June 5, 2015, 5:51 p.m. UTC
Unsent packet has to be released. If the event type is obvious from the
context, use directly the relevant release functions, otherwise
odp_event(free).
Wider error handling is attempted, but this patch can't fix all the flaws
in the many calling functions of odp_queue_enq()

Signed-off-by: Zoltan Kiss <zoltan.kiss@linaro.org>
---
 example/classifier/odp_classifier.c                       |  7 ++++++-
 example/generator/odp_generator.c                         |  1 +
 example/ipsec/odp_ipsec.c                                 | 11 ++++++++---
 example/ipsec/odp_ipsec_stream.c                          |  6 +++++-
 example/packet/odp_pktio.c                                |  6 +++++-
 platform/linux-generic/include/odp_schedule_internal.h    |  4 ++--
 platform/linux-generic/odp_crypto.c                       |  5 ++++-
 platform/linux-generic/odp_queue.c                        |  8 ++++----
 platform/linux-generic/odp_schedule.c                     | 14 ++++++++++----
 platform/linux-generic/odp_timer.c                        |  4 +++-
 test/performance/odp_l2fwd.c                              |  6 +++++-
 test/performance/odp_pktio_perf.c                         | 10 ++++++++--
 test/performance/odp_scheduling.c                         |  7 +++++++
 test/validation/classification/odp_classification_tests.c |  3 ++-
 test/validation/odp_pktio.c                               |  1 +
 test/validation/odp_queue.c                               |  9 ++++++---
 test/validation/odp_scheduler.c                           | 12 ++++++++----
 17 files changed, 85 insertions(+), 29 deletions(-)

Comments

Zoltan Kiss June 29, 2015, 6:16 p.m. UTC | #1
Hi,

So you say instead of returning I should use an ODP_ABORT()?

Zoli

On 09/06/15 14:46, Savolainen, Petri (Nokia - FI/Espoo) wrote:
>
> Although implementation (linux-generic) is using the API calls, it can do short cuts e.g. ensure that queue_enq will never fail (abort instead of fail) and then exploit that knowledge. The implementation gets more complex if any "API call" it uses can fail as specified by the API spec.
>
>
>> --- a/platform/linux-generic/odp_queue.c
>> +++ b/platform/linux-generic/odp_queue.c
>> @@ -355,8 +355,8 @@ int queue_enq(queue_entry_t *queue, odp_buffer_hdr_t
>> *buf_hdr)
>>   	UNLOCK(&queue->s.lock);
>>
>>   	/* Add queue to scheduling */
>> -	if (sched)
>> -		schedule_queue(queue);
>> +	if (sched && schedule_queue(queue))
>> +		return -1;
>
> For example here, the event has been already inserted to the queue (linked list) and this last bit activates scheduling if needed. A this point odp_queue_enq() cannot return "failure" without removing the event from list first. Otherwise both the user and the queue has ownership of the event. Next user would free it and the queue (linked list) is corrupted.
>
>
>>
>>   	return 0;
>>   }
>> @@ -395,8 +395,8 @@ int queue_enq_multi(queue_entry_t *queue,
>> odp_buffer_hdr_t *buf_hdr[], int num)
>>   	UNLOCK(&queue->s.lock);
>>
>>   	/* Add queue to scheduling */
>> -	if (sched)
>> -		schedule_queue(queue);
>> +	if (sched && schedule_queue(queue))
>> +		return -1;
>>
>
> Same here, too late to just return fail.
>
>
>>   	return num; /* All events enqueued */
>>   }
>> diff --git a/platform/linux-generic/odp_schedule.c b/platform/linux-
>> generic/odp_schedule.c
>> index 9206d5c..9e20fda 100644
>> --- a/platform/linux-generic/odp_schedule.c
>> +++ b/platform/linux-generic/odp_schedule.c
>> @@ -355,7 +355,10 @@ int schedule_pktio_start(odp_pktio_t pktio, int prio)
>>
>>   	pri_queue  = pri_set_pktio(pktio, prio);
>>
>> -	odp_queue_enq(pri_queue, odp_buffer_to_event(buf));
>> +	if (odp_queue_enq(pri_queue, odp_buffer_to_event(buf))) {
>> +		odp_buffer_free(buf);
>> +		return -1;
>> +	}
>>
>>   	return 0;
>>   }
>> @@ -365,7 +368,8 @@ void odp_schedule_release_atomic(void)
>>   	if (sched_local.pri_queue != ODP_QUEUE_INVALID &&
>>   	    sched_local.num       == 0) {
>>   		/* Release current atomic queue */
>> -		odp_queue_enq(sched_local.pri_queue, sched_local.cmd_ev);
>> +		if (odp_queue_enq(sched_local.pri_queue, sched_local.cmd_ev))
>> +			odp_event_free(sched_local.cmd_ev);
>
> If this happens the atomic queue is (silently) deadlocked. Schedule queues should never fail, just crash/abort.
>
>
>>   		sched_local.pri_queue = ODP_QUEUE_INVALID;
>>   	}
>>   }
>> @@ -456,7 +460,8 @@ static int schedule(odp_queue_t *out_queue,
>> odp_event_t out_ev[],
>>   					odp_buffer_free(buf);
>>   				} else {
>>   					/* Continue scheduling the pktio */
>> -					odp_queue_enq(pri_q, ev);
>> +					if (odp_queue_enq(pri_q, ev))
>> +						odp_event_free(ev);
>
> Pktio is deadlocked...
>
>>   				}
>>
>>   				continue;
>> @@ -487,7 +492,8 @@ static int schedule(odp_queue_t *out_queue,
>> odp_event_t out_ev[],
>>   				sched_local.cmd_ev    = ev;
>>   			} else {
>>   				/* Continue scheduling the queue */
>> -				odp_queue_enq(pri_q, ev);
>> +				if (odp_queue_enq(pri_q, ev))
>> +					odp_event_free(ev);
>
> Queue is never scheduled again...
>
>
> -Petri
>
>
>
>
Ola Liljedahl June 30, 2015, 10:18 a.m. UTC | #2
On 29 June 2015 at 20:16, Zoltan Kiss <zoltan.kiss@linaro.org> wrote:

> Hi,
>
> So you say instead of returning I should use an ODP_ABORT()?
>
If an ODP function cannot succeed or fail cleanly (e.g. internal side
effects unrolled, internal state consistent), it must not return at all.
Calling ODP_ABORT is one way of achieving this.


> Zoli
>
>
> On 09/06/15 14:46, Savolainen, Petri (Nokia - FI/Espoo) wrote:
>
>>
>> Although implementation (linux-generic) is using the API calls, it can do
>> short cuts e.g. ensure that queue_enq will never fail (abort instead of
>> fail) and then exploit that knowledge. The implementation gets more complex
>> if any "API call" it uses can fail as specified by the API spec.
>>
>>
>>  --- a/platform/linux-generic/odp_queue.c
>>> +++ b/platform/linux-generic/odp_queue.c
>>> @@ -355,8 +355,8 @@ int queue_enq(queue_entry_t *queue, odp_buffer_hdr_t
>>> *buf_hdr)
>>>         UNLOCK(&queue->s.lock);
>>>
>>>         /* Add queue to scheduling */
>>> -       if (sched)
>>> -               schedule_queue(queue);
>>> +       if (sched && schedule_queue(queue))
>>> +               return -1;
>>>
>>
>> For example here, the event has been already inserted to the queue
>> (linked list) and this last bit activates scheduling if needed. A this
>> point odp_queue_enq() cannot return "failure" without removing the event
>> from list first. Otherwise both the user and the queue has ownership of the
>> event. Next user would free it and the queue (linked list) is corrupted.
>>
>>
>>
>>>         return 0;
>>>   }
>>> @@ -395,8 +395,8 @@ int queue_enq_multi(queue_entry_t *queue,
>>> odp_buffer_hdr_t *buf_hdr[], int num)
>>>         UNLOCK(&queue->s.lock);
>>>
>>>         /* Add queue to scheduling */
>>> -       if (sched)
>>> -               schedule_queue(queue);
>>> +       if (sched && schedule_queue(queue))
>>> +               return -1;
>>>
>>>
>> Same here, too late to just return fail.
>>
>>
>>          return num; /* All events enqueued */
>>>   }
>>> diff --git a/platform/linux-generic/odp_schedule.c b/platform/linux-
>>> generic/odp_schedule.c
>>> index 9206d5c..9e20fda 100644
>>> --- a/platform/linux-generic/odp_schedule.c
>>> +++ b/platform/linux-generic/odp_schedule.c
>>> @@ -355,7 +355,10 @@ int schedule_pktio_start(odp_pktio_t pktio, int
>>> prio)
>>>
>>>         pri_queue  = pri_set_pktio(pktio, prio);
>>>
>>> -       odp_queue_enq(pri_queue, odp_buffer_to_event(buf));
>>> +       if (odp_queue_enq(pri_queue, odp_buffer_to_event(buf))) {
>>> +               odp_buffer_free(buf);
>>> +               return -1;
>>> +       }
>>>
>>>         return 0;
>>>   }
>>> @@ -365,7 +368,8 @@ void odp_schedule_release_atomic(void)
>>>         if (sched_local.pri_queue != ODP_QUEUE_INVALID &&
>>>             sched_local.num       == 0) {
>>>                 /* Release current atomic queue */
>>> -               odp_queue_enq(sched_local.pri_queue, sched_local.cmd_ev);
>>> +               if (odp_queue_enq(sched_local.pri_queue,
>>> sched_local.cmd_ev))
>>> +                       odp_event_free(sched_local.cmd_ev);
>>>
>>
>> If this happens the atomic queue is (silently) deadlocked. Schedule
>> queues should never fail, just crash/abort.
>>
>>
>>                  sched_local.pri_queue = ODP_QUEUE_INVALID;
>>>         }
>>>   }
>>> @@ -456,7 +460,8 @@ static int schedule(odp_queue_t *out_queue,
>>> odp_event_t out_ev[],
>>>                                         odp_buffer_free(buf);
>>>                                 } else {
>>>                                         /* Continue scheduling the pktio
>>> */
>>> -                                       odp_queue_enq(pri_q, ev);
>>> +                                       if (odp_queue_enq(pri_q, ev))
>>> +                                               odp_event_free(ev);
>>>
>>
>> Pktio is deadlocked...
>>
>>                                  }
>>>
>>>                                 continue;
>>> @@ -487,7 +492,8 @@ static int schedule(odp_queue_t *out_queue,
>>> odp_event_t out_ev[],
>>>                                 sched_local.cmd_ev    = ev;
>>>                         } else {
>>>                                 /* Continue scheduling the queue */
>>> -                               odp_queue_enq(pri_q, ev);
>>> +                               if (odp_queue_enq(pri_q, ev))
>>> +                                       odp_event_free(ev);
>>>
>>
>> Queue is never scheduled again...
>>
>>
>> -Petri
>>
>>
>>
>>
>>  _______________________________________________
> lng-odp mailing list
> lng-odp@lists.linaro.org
> https://lists.linaro.org/mailman/listinfo/lng-odp
>
diff mbox

Patch

diff --git a/example/classifier/odp_classifier.c b/example/classifier/odp_classifier.c
index 48fc1ab..129b042 100644
--- a/example/classifier/odp_classifier.c
+++ b/example/classifier/odp_classifier.c
@@ -292,7 +292,12 @@  static void *pktio_receive_thread(void *arg)
 		if (appl->appl_mode == APPL_MODE_DROP)
 			odp_packet_free(pkt);
 		else
-			odp_queue_enq(outq_def, ev);
+			if (odp_queue_enq(outq_def, ev)) {
+				EXAMPLE_ERR("  [%i] Queue enqueue failed.\n",
+					    thr);
+				odp_packet_free(pkt);
+				continue;
+			}
 	}
 
 	return NULL;
diff --git a/example/generator/odp_generator.c b/example/generator/odp_generator.c
index cbe93b5..c4ef361 100644
--- a/example/generator/odp_generator.c
+++ b/example/generator/odp_generator.c
@@ -410,6 +410,7 @@  static void *gen_send_thread(void *arg)
 		err = odp_queue_enq(outq_def, odp_packet_to_event(pkt));
 		if (err != 0) {
 			EXAMPLE_ERR("  [%02i] send pkt err!\n", thr);
+			odp_packet_free(pkt);
 			return NULL;
 		}
 
diff --git a/example/ipsec/odp_ipsec.c b/example/ipsec/odp_ipsec.c
index cb8f535..1d034dd 100644
--- a/example/ipsec/odp_ipsec.c
+++ b/example/ipsec/odp_ipsec.c
@@ -1078,7 +1078,8 @@  void *pktio_thread(void *arg EXAMPLE_UNUSED)
 					ctx->state = PKT_STATE_TRANSMIT;
 				} else {
 					ctx->state = PKT_STATE_IPSEC_OUT_SEQ;
-					odp_queue_enq(seqnumq, ev);
+					if (odp_queue_enq(seqnumq, ev))
+						rc = PKT_DROP;
 				}
 				break;
 
@@ -1096,8 +1097,12 @@  void *pktio_thread(void *arg EXAMPLE_UNUSED)
 
 			case PKT_STATE_TRANSMIT:
 
-				odp_queue_enq(ctx->outq, ev);
-				rc = PKT_DONE;
+				if (odp_queue_enq(ctx->outq, ev)) {
+					odp_event_free(ev);
+					rc = PKT_DROP;
+				} else {
+					rc = PKT_DONE;
+				}
 				break;
 
 			default:
diff --git a/example/ipsec/odp_ipsec_stream.c b/example/ipsec/odp_ipsec_stream.c
index 35042f5..af143ee 100644
--- a/example/ipsec/odp_ipsec_stream.c
+++ b/example/ipsec/odp_ipsec_stream.c
@@ -494,7 +494,11 @@  int create_stream_db_inputs(void)
 				break;
 			}
 			stream->created++;
-			odp_queue_enq(queue, odp_packet_to_event(pkt));
+			if (odp_queue_enq(queue, odp_packet_to_event(pkt))) {
+				odp_packet_free(pkt);
+				printf("Queue enqueue failed\n");
+				break;
+			}
 
 			/* Count this stream when we create first packet */
 			if (1 == stream->created)
diff --git a/example/packet/odp_pktio.c b/example/packet/odp_pktio.c
index 0b4a8f1..8004d69 100644
--- a/example/packet/odp_pktio.c
+++ b/example/packet/odp_pktio.c
@@ -233,7 +233,11 @@  static void *pktio_queue_thread(void *arg)
 		swap_pkt_addrs(&pkt, 1);
 
 		/* Enqueue the packet for output */
-		odp_queue_enq(outq_def, ev);
+		if (odp_queue_enq(outq_def, ev)) {
+			EXAMPLE_ERR("  [%i] Queue enqueue failed.\n", thr);
+			odp_packet_free(pkt);
+			continue;
+		}
 
 		/* Print packet counts every once in a while */
 		if (odp_unlikely(pkt_cnt++ % 100000 == 0)) {
diff --git a/platform/linux-generic/include/odp_schedule_internal.h b/platform/linux-generic/include/odp_schedule_internal.h
index 904bfbd..4c6577d 100644
--- a/platform/linux-generic/include/odp_schedule_internal.h
+++ b/platform/linux-generic/include/odp_schedule_internal.h
@@ -23,9 +23,9 @@  extern "C" {
 int schedule_queue_init(queue_entry_t *qe);
 void schedule_queue_destroy(queue_entry_t *qe);
 
-static inline void schedule_queue(const queue_entry_t *qe)
+static inline int schedule_queue(const queue_entry_t *qe)
 {
-	odp_queue_enq(qe->s.pri_queue, qe->s.cmd_ev);
+	return odp_queue_enq(qe->s.pri_queue, qe->s.cmd_ev);
 }
 
 
diff --git a/platform/linux-generic/odp_crypto.c b/platform/linux-generic/odp_crypto.c
index b16316c..e799047 100644
--- a/platform/linux-generic/odp_crypto.c
+++ b/platform/linux-generic/odp_crypto.c
@@ -431,7 +431,10 @@  odp_crypto_operation(odp_crypto_op_params_t *params,
 		op_result = get_op_result_from_event(completion_event);
 		op_result->magic = OP_RESULT_MAGIC;
 		op_result->result = local_result;
-		odp_queue_enq(session->compl_queue, completion_event);
+		if (odp_queue_enq(session->compl_queue, completion_event)) {
+			odp_event_free(completion_event);
+			return -1;
+		}
 
 		/* Indicate to caller operation was async */
 		*posted = 1;
diff --git a/platform/linux-generic/odp_queue.c b/platform/linux-generic/odp_queue.c
index 4a0465b..818e28e 100644
--- a/platform/linux-generic/odp_queue.c
+++ b/platform/linux-generic/odp_queue.c
@@ -355,8 +355,8 @@  int queue_enq(queue_entry_t *queue, odp_buffer_hdr_t *buf_hdr)
 	UNLOCK(&queue->s.lock);
 
 	/* Add queue to scheduling */
-	if (sched)
-		schedule_queue(queue);
+	if (sched && schedule_queue(queue))
+		return -1;
 
 	return 0;
 }
@@ -395,8 +395,8 @@  int queue_enq_multi(queue_entry_t *queue, odp_buffer_hdr_t *buf_hdr[], int num)
 	UNLOCK(&queue->s.lock);
 
 	/* Add queue to scheduling */
-	if (sched)
-		schedule_queue(queue);
+	if (sched && schedule_queue(queue))
+		return -1;
 
 	return num; /* All events enqueued */
 }
diff --git a/platform/linux-generic/odp_schedule.c b/platform/linux-generic/odp_schedule.c
index 9206d5c..9e20fda 100644
--- a/platform/linux-generic/odp_schedule.c
+++ b/platform/linux-generic/odp_schedule.c
@@ -355,7 +355,10 @@  int schedule_pktio_start(odp_pktio_t pktio, int prio)
 
 	pri_queue  = pri_set_pktio(pktio, prio);
 
-	odp_queue_enq(pri_queue, odp_buffer_to_event(buf));
+	if (odp_queue_enq(pri_queue, odp_buffer_to_event(buf))) {
+		odp_buffer_free(buf);
+		return -1;
+	}
 
 	return 0;
 }
@@ -365,7 +368,8 @@  void odp_schedule_release_atomic(void)
 	if (sched_local.pri_queue != ODP_QUEUE_INVALID &&
 	    sched_local.num       == 0) {
 		/* Release current atomic queue */
-		odp_queue_enq(sched_local.pri_queue, sched_local.cmd_ev);
+		if (odp_queue_enq(sched_local.pri_queue, sched_local.cmd_ev))
+			odp_event_free(sched_local.cmd_ev);
 		sched_local.pri_queue = ODP_QUEUE_INVALID;
 	}
 }
@@ -456,7 +460,8 @@  static int schedule(odp_queue_t *out_queue, odp_event_t out_ev[],
 					odp_buffer_free(buf);
 				} else {
 					/* Continue scheduling the pktio */
-					odp_queue_enq(pri_q, ev);
+					if (odp_queue_enq(pri_q, ev))
+						odp_event_free(ev);
 				}
 
 				continue;
@@ -487,7 +492,8 @@  static int schedule(odp_queue_t *out_queue, odp_event_t out_ev[],
 				sched_local.cmd_ev    = ev;
 			} else {
 				/* Continue scheduling the queue */
-				odp_queue_enq(pri_q, ev);
+				if (odp_queue_enq(pri_q, ev))
+					odp_event_free(ev);
 			}
 
 			/* Output the source queue handle */
diff --git a/platform/linux-generic/odp_timer.c b/platform/linux-generic/odp_timer.c
index f51d2de..4072db5 100644
--- a/platform/linux-generic/odp_timer.c
+++ b/platform/linux-generic/odp_timer.c
@@ -577,9 +577,11 @@  static unsigned timer_expire(odp_timer_pool *tp, uint32_t idx, uint64_t tick)
 		/* Post the timeout to the destination queue */
 		int rc = odp_queue_enq(tim->queue,
 				       odp_buffer_to_event(tmo_buf));
-		if (odp_unlikely(rc != 0))
+		if (odp_unlikely(rc != 0)) {
+			odp_buffer_free(tmo_buf);
 			ODP_ABORT("Failed to enqueue timeout buffer (%d)\n",
 				  rc);
+		}
 		return 1;
 	} else {
 		/* Else false positive, ignore */
diff --git a/test/performance/odp_l2fwd.c b/test/performance/odp_l2fwd.c
index dd0b4b1..9cc201f 100644
--- a/test/performance/odp_l2fwd.c
+++ b/test/performance/odp_l2fwd.c
@@ -152,7 +152,11 @@  static void *pktio_queue_thread(void *arg)
 		outq_def = lookup_dest_q(pkt);
 
 		/* Enqueue the packet for output */
-		odp_queue_enq(outq_def, ev);
+		if (odp_queue_enq(outq_def, ev)) {
+			printf("  [%i] Queue enqueue failed.\n", thr);
+			odp_packet_free(pkt);
+			continue;
+		}
 
 		stats->packets += 1;
 	}
diff --git a/test/performance/odp_pktio_perf.c b/test/performance/odp_pktio_perf.c
index b746eca..1ef07ae 100644
--- a/test/performance/odp_pktio_perf.c
+++ b/test/performance/odp_pktio_perf.c
@@ -272,8 +272,14 @@  static int send_packets(odp_queue_t outq,
 {
 	if (num_pkts == 0)
 		return 0;
-	else if (num_pkts == 1)
-		return odp_queue_enq(outq, event_tbl[0]) == 0 ? 1 : 0;
+	else if (num_pkts == 1) {
+		if (odp_queue_enq(outq, event_tbl[0])) {
+			odp_event_free(event_tbl[0]);
+			return 0;
+		} else {
+			return 1;
+		}
+	}
 
 	return odp_queue_enq_multi(outq, event_tbl, num_pkts);
 }
diff --git a/test/performance/odp_scheduling.c b/test/performance/odp_scheduling.c
index 558fec8..1283986 100644
--- a/test/performance/odp_scheduling.c
+++ b/test/performance/odp_scheduling.c
@@ -114,6 +114,7 @@  static int create_queue(int thr, odp_pool_t msg_pool, int prio)
 
 	if (odp_queue_enq(queue, odp_buffer_to_event(buf))) {
 		LOG_ERR("  [%i] Queue enqueue failed.\n", thr);
+		odp_buffer_free(buf);
 		return -1;
 	}
 
@@ -161,6 +162,7 @@  static int create_queues(int thr, odp_pool_t msg_pool, int prio)
 
 		if (odp_queue_enq(queue, odp_buffer_to_event(buf))) {
 			LOG_ERR("  [%i] Queue enqueue failed.\n", thr);
+			odp_buffer_free(buf);
 			return -1;
 		}
 	}
@@ -294,6 +296,7 @@  static int test_poll_queue(int thr, odp_pool_t msg_pool)
 
 		if (odp_queue_enq(queue, ev)) {
 			LOG_ERR("  [%i] Queue enqueue failed.\n", thr);
+			odp_buffer_free(buf);
 			return -1;
 		}
 
@@ -352,6 +355,7 @@  static int test_schedule_single(const char *str, int thr,
 
 		if (odp_queue_enq(queue, ev)) {
 			LOG_ERR("  [%i] Queue enqueue failed.\n", thr);
+			odp_event_free(ev);
 			return -1;
 		}
 	}
@@ -371,6 +375,7 @@  static int test_schedule_single(const char *str, int thr,
 
 		if (odp_queue_enq(queue, ev)) {
 			LOG_ERR("  [%i] Queue enqueue failed.\n", thr);
+			odp_event_free(ev);
 			return -1;
 		}
 	}
@@ -431,6 +436,7 @@  static int test_schedule_many(const char *str, int thr,
 
 		if (odp_queue_enq(queue, ev)) {
 			LOG_ERR("  [%i] Queue enqueue failed.\n", thr);
+			odp_event_free(ev);
 			return -1;
 		}
 	}
@@ -450,6 +456,7 @@  static int test_schedule_many(const char *str, int thr,
 
 		if (odp_queue_enq(queue, ev)) {
 			LOG_ERR("  [%i] Queue enqueue failed.\n", thr);
+			odp_event_free(ev);
 			return -1;
 		}
 	}
diff --git a/test/validation/classification/odp_classification_tests.c b/test/validation/classification/odp_classification_tests.c
index 441c194..ed4739d 100644
--- a/test/validation/classification/odp_classification_tests.c
+++ b/test/validation/classification/odp_classification_tests.c
@@ -109,7 +109,8 @@  void enqueue_loop_interface(odp_packet_t pkt)
 	odp_queue_t defqueue = odp_pktio_outq_getdef(pktio_loop);
 
 	ev = odp_packet_to_event(pkt);
-	CU_ASSERT(odp_queue_enq(defqueue, ev) == 0);
+	if (!(CU_ASSERT(odp_queue_enq(defqueue, ev) == 0)))
+		odp_packet_free(pkt);
 }
 
 static inline
diff --git a/test/validation/odp_pktio.c b/test/validation/odp_pktio.c
index 090057b..3027b25 100644
--- a/test/validation/odp_pktio.c
+++ b/test/validation/odp_pktio.c
@@ -380,6 +380,7 @@  static void pktio_txrx_multi(pktio_info_t *pktio_a, pktio_info_t *pktio_b,
 		ret = odp_queue_enq(pktio_a->outq, tx_ev[0]);
 		if (ret != 0) {
 			CU_FAIL("failed to enqueue test packet");
+			odp_packet_free(tx_pkt[0]);
 			return;
 		}
 	} else {
diff --git a/test/validation/odp_queue.c b/test/validation/odp_queue.c
index 01a704c..f8c64f7 100644
--- a/test/validation/odp_queue.c
+++ b/test/validation/odp_queue.c
@@ -71,9 +71,12 @@  static void test_odp_queue_sunnyday(void)
 	CU_ASSERT_FATAL(buf != ODP_BUFFER_INVALID);
 	ev  = odp_buffer_to_event(buf);
 
-	odp_queue_enq(queue_id, ev);
-	CU_ASSERT_EQUAL(ev, odp_queue_deq(queue_id));
-	odp_buffer_free(buf);
+	if (!(CU_ASSERT(odp_queue_enq(queue_id, ev) == 0))) {
+		odp_buffer_free(buf);
+	} else {
+		CU_ASSERT_EQUAL(ev, odp_queue_deq(queue_id));
+		odp_buffer_free(buf);
+	}
 
 	for (i = 0; i < MAX_BUFFER_QUEUE; i++) {
 		odp_buffer_t buf = odp_buffer_alloc(msg_pool);
diff --git a/test/validation/odp_scheduler.c b/test/validation/odp_scheduler.c
index e4df4f2..fa03f39 100644
--- a/test/validation/odp_scheduler.c
+++ b/test/validation/odp_scheduler.c
@@ -138,7 +138,8 @@  static void test_schedule_queue_destroy(void)
 		u32[0] = MAGIC;
 
 		ev = odp_buffer_to_event(buf);
-		CU_ASSERT(odp_queue_enq(queue, ev) == 0);
+		if (!(CU_ASSERT(odp_queue_enq(queue, ev) == 0)))
+			odp_buffer_free(buf);
 
 		ev = odp_schedule(&from, ODP_SCHED_WAIT);
 
@@ -288,8 +289,10 @@  static void fill_queues(thread_args_t *args)
 				buf = odp_buffer_alloc(pool);
 				CU_ASSERT_FATAL(buf != ODP_BUFFER_INVALID);
 				ev = odp_buffer_to_event(buf);
-				CU_ASSERT(odp_queue_enq(queue, ev) == 0);
-				buf_count++;
+				if (!(CU_ASSERT(odp_queue_enq(queue, ev) == 0)))
+					odp_buffer_free(buf);
+				else
+					buf_count++;
 			}
 		}
 	}
@@ -560,7 +563,8 @@  static void test_schedule_pause_resume(void)
 		buf = odp_buffer_alloc(pool);
 		CU_ASSERT_FATAL(buf != ODP_BUFFER_INVALID);
 		ev = odp_buffer_to_event(buf);
-		odp_queue_enq(queue, ev);
+		if (odp_queue_enq(queue, ev))
+			odp_buffer_free(buf);
 	}
 
 	for (i = 0; i < NUM_BUFS_BEFORE_PAUSE; i++) {