A ring is identified by a unique name.
It is not possible to create two rings with the same name (rte_ring_create() returns NULL if this is attempted).
-Water Marking
-~~~~~~~~~~~~~
-
-The ring can have a high water mark (threshold).
-Once an enqueue operation reaches the high water mark, the producer is notified, if the water mark is configured.
-
-This mechanism can be used, for example, to exert a back pressure on I/O to inform the LAN to PAUSE.
-
Use Cases
---------
* removed the build-time setting ``CONFIG_RTE_RING_SPLIT_PROD_CONS``
* removed the build-time setting ``CONFIG_RTE_LIBRTE_RING_DEBUG``
* removed the build-time setting ``CONFIG_RTE_RING_PAUSE_REP_COUNT``
+ * removed the function ``rte_ring_set_water_mark`` as part of a general
+ removal of watermarks support in the library.
ABI Changes
-----------
DIRS-$(CONFIG_RTE_LIBRTE_IEEE1588) += ptpclient
DIRS-$(CONFIG_RTE_LIBRTE_METER) += qos_meter
DIRS-$(CONFIG_RTE_LIBRTE_SCHED) += qos_sched
-DIRS-y += quota_watermark
+#DIRS-y += quota_watermark
DIRS-$(CONFIG_RTE_ETHDEV_RXTX_CALLBACKS) += rxtx_callbacks
DIRS-y += skeleton
ifeq ($(CONFIG_RTE_LIBRTE_HASH),y)
if (ret < 0 || ret >= (int)sizeof(r->name))
return -ENAMETOOLONG;
r->flags = flags;
- r->watermark = count;
r->prod.single = !!(flags & RING_F_SP_ENQ);
r->cons.single = !!(flags & RING_F_SC_DEQ);
r->size = count;
rte_free(te);
}
-/*
- * change the high water mark. If *count* is 0, water marking is
- * disabled
- */
-int
-rte_ring_set_water_mark(struct rte_ring *r, unsigned count)
-{
- if (count >= r->size)
- return -EINVAL;
-
- /* if count is 0, disable the watermarking */
- if (count == 0)
- count = r->size;
-
- r->watermark = count;
- return 0;
-}
-
/* dump the status of the ring on the console */
void
rte_ring_dump(FILE *f, const struct rte_ring *r)
fprintf(f, " ph=%"PRIu32"\n", r->prod.head);
fprintf(f, " used=%u\n", rte_ring_count(r));
fprintf(f, " avail=%u\n", rte_ring_free_count(r));
- if (r->watermark == r->size)
- fprintf(f, " watermark=0\n");
- else
- fprintf(f, " watermark=%"PRIu32"\n", r->watermark);
}
/* dump the status of all rings on the console */
/**< Memzone, if any, containing the rte_ring */
uint32_t size; /**< Size of ring. */
uint32_t mask; /**< Mask (size-1) of ring. */
- uint32_t watermark; /**< Max items before EDQUOT in producer. */
/** Ring producer status. */
struct rte_ring_headtail prod __rte_aligned(PROD_ALIGN);
#define RING_F_SP_ENQ 0x0001 /**< The default enqueue is "single-producer". */
#define RING_F_SC_DEQ 0x0002 /**< The default dequeue is "single-consumer". */
-#define RTE_RING_QUOT_EXCEED (1 << 31) /**< Quota exceed for burst ops */
#define RTE_RING_SZ_MASK (unsigned)(0x0fffffff) /**< Ring size mask */
/**
*/
void rte_ring_free(struct rte_ring *r);
-/**
- * Change the high water mark.
- *
- * If *count* is 0, water marking is disabled. Otherwise, it is set to the
- * *count* value. The *count* value must be greater than 0 and less
- * than the ring size.
- *
- * This function can be called at any time (not necessarily at
- * initialization).
- *
- * @param r
- * A pointer to the ring structure.
- * @param count
- * The new water mark value.
- * @return
- * - 0: Success; water mark changed.
- * - -EINVAL: Invalid water mark value.
- */
-int rte_ring_set_water_mark(struct rte_ring *r, unsigned count);
-
/**
* Dump the status of the ring to a file.
*
* Depend on the behavior value
* if behavior = RTE_RING_QUEUE_FIXED
* - 0: Success; objects enqueue.
- * - -EDQUOT: Quota exceeded. The objects have been enqueued, but the
- * high water mark is exceeded.
* - -ENOBUFS: Not enough room in the ring to enqueue, no object is enqueued.
* if behavior = RTE_RING_QUEUE_VARIABLE
* - n: Actual number of objects enqueued.
int success;
unsigned int i;
uint32_t mask = r->mask;
- int ret;
/* Avoid the unnecessary cmpset operation below, which is also
* potentially harmful when n equals 0. */
ENQUEUE_PTRS();
rte_smp_wmb();
- /* if we exceed the watermark */
- if (unlikely(((mask + 1) - free_entries + n) > r->watermark))
- ret = (behavior == RTE_RING_QUEUE_FIXED) ? -EDQUOT :
- (int)(n | RTE_RING_QUOT_EXCEED);
- else
- ret = (behavior == RTE_RING_QUEUE_FIXED) ? 0 : n;
-
/*
* If there are other enqueues in progress that preceded us,
* we need to wait for them to complete
rte_pause();
r->prod.tail = prod_next;
- return ret;
+ return (behavior == RTE_RING_QUEUE_FIXED) ? 0 : n;
}
/**
* Depend on the behavior value
* if behavior = RTE_RING_QUEUE_FIXED
* - 0: Success; objects enqueue.
- * - -EDQUOT: Quota exceeded. The objects have been enqueued, but the
- * high water mark is exceeded.
* - -ENOBUFS: Not enough room in the ring to enqueue, no object is enqueued.
* if behavior = RTE_RING_QUEUE_VARIABLE
* - n: Actual number of objects enqueued.
uint32_t prod_next, free_entries;
unsigned int i;
uint32_t mask = r->mask;
- int ret;
prod_head = r->prod.head;
cons_tail = r->cons.tail;
ENQUEUE_PTRS();
rte_smp_wmb();
- /* if we exceed the watermark */
- if (unlikely(((mask + 1) - free_entries + n) > r->watermark))
- ret = (behavior == RTE_RING_QUEUE_FIXED) ? -EDQUOT :
- (int)(n | RTE_RING_QUOT_EXCEED);
- else
- ret = (behavior == RTE_RING_QUEUE_FIXED) ? 0 : n;
-
r->prod.tail = prod_next;
- return ret;
+ return (behavior == RTE_RING_QUEUE_FIXED) ? 0 : n;
}
/**
* The number of objects to add in the ring from the obj_table.
* @return
* - 0: Success; objects enqueue.
- * - -EDQUOT: Quota exceeded. The objects have been enqueued, but the
- * high water mark is exceeded.
* - -ENOBUFS: Not enough room in the ring to enqueue, no object is enqueued.
*/
static inline int __attribute__((always_inline))
* The number of objects to add in the ring from the obj_table.
* @return
* - 0: Success; objects enqueued.
- * - -EDQUOT: Quota exceeded. The objects have been enqueued, but the
- * high water mark is exceeded.
* - -ENOBUFS: Not enough room in the ring to enqueue; no object is enqueued.
*/
static inline int __attribute__((always_inline))
* The number of objects to add in the ring from the obj_table.
* @return
* - 0: Success; objects enqueued.
- * - -EDQUOT: Quota exceeded. The objects have been enqueued, but the
- * high water mark is exceeded.
* - -ENOBUFS: Not enough room in the ring to enqueue; no object is enqueued.
*/
static inline int __attribute__((always_inline))
* A pointer to the object to be added.
* @return
* - 0: Success; objects enqueued.
- * - -EDQUOT: Quota exceeded. The objects have been enqueued, but the
- * high water mark is exceeded.
* - -ENOBUFS: Not enough room in the ring to enqueue; no object is enqueued.
*/
static inline int __attribute__((always_inline))
* A pointer to the object to be added.
* @return
* - 0: Success; objects enqueued.
- * - -EDQUOT: Quota exceeded. The objects have been enqueued, but the
- * high water mark is exceeded.
* - -ENOBUFS: Not enough room in the ring to enqueue; no object is enqueued.
*/
static inline int __attribute__((always_inline))
* A pointer to the object to be added.
* @return
* - 0: Success; objects enqueued.
- * - -EDQUOT: Quota exceeded. The objects have been enqueued, but the
- * high water mark is exceeded.
* - -ENOBUFS: Not enough room in the ring to enqueue; no object is enqueued.
*/
static inline int __attribute__((always_inline))
elif index == 2:
return -1, "Fail [Timeout]"
- child.sendline("set_watermark test 100")
- child.sendline("dump_ring test")
- index = child.expect([" watermark=100",
- pexpect.TIMEOUT], timeout=1)
- if index != 0:
- return -1, "Fail [Bad watermark]"
-
return 0, "Success"
/****************/
-struct cmd_set_ring_result {
- cmdline_fixed_string_t set;
- cmdline_fixed_string_t name;
- uint32_t value;
-};
-
-static void cmd_set_ring_parsed(void *parsed_result, struct cmdline *cl,
- __attribute__((unused)) void *data)
-{
- struct cmd_set_ring_result *res = parsed_result;
- struct rte_ring *r;
- int ret;
-
- r = rte_ring_lookup(res->name);
- if (r == NULL) {
- cmdline_printf(cl, "Cannot find ring\n");
- return;
- }
-
- if (!strcmp(res->set, "set_watermark")) {
- ret = rte_ring_set_water_mark(r, res->value);
- if (ret != 0)
- cmdline_printf(cl, "Cannot set water mark\n");
- }
-}
-
-cmdline_parse_token_string_t cmd_set_ring_set =
- TOKEN_STRING_INITIALIZER(struct cmd_set_ring_result, set,
- "set_watermark");
-
-cmdline_parse_token_string_t cmd_set_ring_name =
- TOKEN_STRING_INITIALIZER(struct cmd_set_ring_result, name, NULL);
-
-cmdline_parse_token_num_t cmd_set_ring_value =
- TOKEN_NUM_INITIALIZER(struct cmd_set_ring_result, value, UINT32);
-
-cmdline_parse_inst_t cmd_set_ring = {
- .f = cmd_set_ring_parsed, /* function to call */
- .data = NULL, /* 2nd arg of func */
- .help_str = "set watermark: "
- "set_watermark <ring_name> <value>",
- .tokens = { /* token list, NULL terminated */
- (void *)&cmd_set_ring_set,
- (void *)&cmd_set_ring_name,
- (void *)&cmd_set_ring_value,
- NULL,
- },
-};
-
-/****************/
-
struct cmd_quit_result {
cmdline_fixed_string_t quit;
};
(cmdline_parse_inst_t *)&cmd_autotest,
(cmdline_parse_inst_t *)&cmd_dump,
(cmdline_parse_inst_t *)&cmd_dump_one,
- (cmdline_parse_inst_t *)&cmd_set_ring,
(cmdline_parse_inst_t *)&cmd_quit,
(cmdline_parse_inst_t *)&cmd_set_rxtx,
(cmdline_parse_inst_t *)&cmd_set_rxtx_anchor,
* - Dequeue one object, two objects, MAX_BULK objects
* - Check that dequeued pointers are correct
*
- * - Test watermark and default bulk enqueue/dequeue:
- *
- * - Set watermark
- * - Set default bulk value
- * - Enqueue objects, check that -EDQUOT is returned when
- * watermark is exceeded
- * - Check that dequeued pointers are correct
- *
- * #. Check live watermark change
- *
- * - Start a loop on another lcore that will enqueue and dequeue
- * objects in a ring. It will monitor the value of watermark.
- * - At the same time, change the watermark on the master lcore.
- * - The slave lcore will check that watermark changes from 16 to 32.
- *
* #. Performance tests.
*
* Tests done in test_ring_perf.c
#define TEST_RING_FULL_EMTPY_ITER 8
-static int
-check_live_watermark_change(__attribute__((unused)) void *dummy)
-{
- uint64_t hz = rte_get_timer_hz();
- void *obj_table[MAX_BULK];
- unsigned watermark, watermark_old = 16;
- uint64_t cur_time, end_time;
- int64_t diff = 0;
- int i, ret;
- unsigned count = 4;
-
- /* init the object table */
- memset(obj_table, 0, sizeof(obj_table));
- end_time = rte_get_timer_cycles() + (hz / 4);
-
- /* check that bulk and watermark are 4 and 32 (respectively) */
- while (diff >= 0) {
-
- /* add in ring until we reach watermark */
- ret = 0;
- for (i = 0; i < 16; i ++) {
- if (ret != 0)
- break;
- ret = rte_ring_enqueue_bulk(r, obj_table, count);
- }
-
- if (ret != -EDQUOT) {
- printf("Cannot enqueue objects, or watermark not "
- "reached (ret=%d)\n", ret);
- return -1;
- }
-
- /* read watermark, the only change allowed is from 16 to 32 */
- watermark = r->watermark;
- if (watermark != watermark_old &&
- (watermark_old != 16 || watermark != 32)) {
- printf("Bad watermark change %u -> %u\n", watermark_old,
- watermark);
- return -1;
- }
- watermark_old = watermark;
-
- /* dequeue objects from ring */
- while (i--) {
- ret = rte_ring_dequeue_bulk(r, obj_table, count);
- if (ret != 0) {
- printf("Cannot dequeue (ret=%d)\n", ret);
- return -1;
- }
- }
-
- cur_time = rte_get_timer_cycles();
- diff = end_time - cur_time;
- }
-
- if (watermark_old != 32 ) {
- printf(" watermark was not updated (wm=%u)\n",
- watermark_old);
- return -1;
- }
-
- return 0;
-}
-
-static int
-test_live_watermark_change(void)
-{
- unsigned lcore_id = rte_lcore_id();
- unsigned lcore_id2 = rte_get_next_lcore(lcore_id, 0, 1);
-
- printf("Test watermark live modification\n");
- rte_ring_set_water_mark(r, 16);
-
- /* launch a thread that will enqueue and dequeue, checking
- * watermark and quota */
- rte_eal_remote_launch(check_live_watermark_change, NULL, lcore_id2);
-
- rte_delay_ms(100);
- rte_ring_set_water_mark(r, 32);
- rte_delay_ms(100);
-
- if (rte_eal_wait_lcore(lcore_id2) < 0)
- return -1;
-
- return 0;
-}
-
-/* Test for catch on invalid watermark values */
-static int
-test_set_watermark( void ){
- unsigned count;
- int setwm;
-
- struct rte_ring *r = rte_ring_lookup("test_ring_basic_ex");
- if(r == NULL){
- printf( " ring lookup failed\n" );
- goto error;
- }
- count = r->size * 2;
- setwm = rte_ring_set_water_mark(r, count);
- if (setwm != -EINVAL){
- printf("Test failed to detect invalid watermark count value\n");
- goto error;
- }
-
- count = 0;
- rte_ring_set_water_mark(r, count);
- if (r->watermark != r->size) {
- printf("Test failed to detect invalid watermark count value\n");
- goto error;
- }
- return 0;
-
-error:
- return -1;
-}
-
/*
* helper routine for test_ring_basic
*/
cur_src = src;
cur_dst = dst;
- printf("test watermark and default bulk enqueue / dequeue\n");
- rte_ring_set_water_mark(r, 20);
+ printf("test default bulk enqueue / dequeue\n");
num_elems = 16;
cur_src = src;
}
ret = rte_ring_enqueue_bulk(r, cur_src, num_elems);
cur_src += num_elems;
- if (ret != -EDQUOT) {
- printf("Watermark not exceeded\n");
+ if (ret != 0) {
+ printf("Cannot enqueue\n");
goto fail;
}
ret = rte_ring_dequeue_bulk(r, cur_dst, num_elems);
return -1;
/* basic operations */
- if (test_live_watermark_change() < 0)
- return -1;
-
- if ( test_set_watermark() < 0){
- printf ("Test failed to detect invalid parameter\n");
- return -1;
- }
- else
- printf ( "Test detected forced bad watermark values\n");
-
if ( test_create_count_odd() < 0){
printf ("Test failed to detect odd count\n");
return -1;