Make sure packet order is maintained if enqueueing packets from an ordered
queue.

Fixes https://bugs.linaro.org/show_bug.cgi?id=3002

Signed-off-by: Matias Elo <[email protected]>
Reviewed-and-tested-by: Yi He <[email protected]>
---
V2:
- Fix pktout_enqueue() return value (Janne)


 platform/linux-generic/odp_packet_io.c       | 8 ++++++++
 platform/linux-generic/odp_queue.c           | 1 +
 platform/linux-generic/odp_schedule.c        | 5 ++++-
 platform/linux-generic/odp_schedule_iquery.c | 5 ++++-
 4 files changed, 17 insertions(+), 2 deletions(-)

diff --git a/platform/linux-generic/odp_packet_io.c 
b/platform/linux-generic/odp_packet_io.c
index 98460a5..50a000e 100644
--- a/platform/linux-generic/odp_packet_io.c
+++ b/platform/linux-generic/odp_packet_io.c
@@ -586,6 +586,10 @@ int pktout_enqueue(queue_entry_t *qentry, odp_buffer_hdr_t 
*buf_hdr)
        int len = 1;
        int nbr;
 
+       if (sched_fn->ord_enq_multi(qentry->s.index, (void **)buf_hdr, len,
+                                   &nbr))
+               return (nbr == len ? 0 : -1);
+
        nbr = odp_pktout_send(qentry->s.pktout, &pkt, len);
        return (nbr == len ? 0 : -1);
 }
@@ -603,6 +607,10 @@ int pktout_enq_multi(queue_entry_t *qentry, 
odp_buffer_hdr_t *buf_hdr[],
        int nbr;
        int i;
 
+       if (sched_fn->ord_enq_multi(qentry->s.index, (void **)buf_hdr, num,
+                                   &nbr))
+               return nbr;
+
        for (i = 0; i < num; ++i)
                pkt_tbl[i] = _odp_packet_from_buffer(buf_hdr[i]->handle.handle);
 
diff --git a/platform/linux-generic/odp_queue.c 
b/platform/linux-generic/odp_queue.c
index fcf4bf5..a96f922 100644
--- a/platform/linux-generic/odp_queue.c
+++ b/platform/linux-generic/odp_queue.c
@@ -95,6 +95,7 @@ static int queue_init(queue_entry_t *queue, const char *name,
        queue->s.dequeue_multi = queue_deq_multi;
 
        queue->s.pktin = PKTIN_INVALID;
+       queue->s.pktout = PKTOUT_INVALID;
 
        queue->s.head = NULL;
        queue->s.tail = NULL;
diff --git a/platform/linux-generic/odp_schedule.c 
b/platform/linux-generic/odp_schedule.c
index f680ac4..c4567d8 100644
--- a/platform/linux-generic/odp_schedule.c
+++ b/platform/linux-generic/odp_schedule.c
@@ -20,6 +20,7 @@
 #include <odp_config_internal.h>
 #include <odp_align_internal.h>
 #include <odp/api/sync.h>
+#include <odp/api/packet_io.h>
 #include <odp_ring_internal.h>
 #include <odp_queue_internal.h>
 
@@ -729,7 +730,9 @@ static int schedule_ord_enq_multi(uint32_t queue_index, 
void *buf_hdr[],
                return 0;
        }
 
-       if (odp_unlikely(stash_num >=  MAX_ORDERED_STASH)) {
+       /* Pktout may drop packets, so the operation cannot be stashed. */
+       if (dst_queue->s.pktout.pktio != ODP_PKTIO_INVALID ||
+           odp_unlikely(stash_num >=  MAX_ORDERED_STASH)) {
                /* If the local stash is full, wait until it is our turn and
                 * then release the stash and do enqueue directly. */
                wait_for_order(src_queue);
diff --git a/platform/linux-generic/odp_schedule_iquery.c 
b/platform/linux-generic/odp_schedule_iquery.c
index b8a4001..75470af 100644
--- a/platform/linux-generic/odp_schedule_iquery.c
+++ b/platform/linux-generic/odp_schedule_iquery.c
@@ -21,6 +21,7 @@
 #include <odp/api/hints.h>
 #include <odp/api/cpu.h>
 #include <odp/api/thrmask.h>
+#include <odp/api/packet_io.h>
 #include <odp_config_internal.h>
 
 /* Number of priority levels */
@@ -1176,7 +1177,9 @@ static int schedule_ord_enq_multi(uint32_t queue_index, 
void *buf_hdr[],
                return 0;
        }
 
-       if (odp_unlikely(stash_num >=  MAX_ORDERED_STASH)) {
+       /* Pktout may drop packets, so the operation cannot be stashed. */
+       if (dst_queue->s.pktout.pktio != ODP_PKTIO_INVALID ||
+           odp_unlikely(stash_num >=  MAX_ORDERED_STASH)) {
                /* If the local stash is full, wait until it is our turn and
                 * then release the stash and do enqueue directly. */
                wait_for_order(src_queue);
-- 
2.7.4

Reply via email to