@@ -149,6 +149,7 @@ enum index {
QUEUE_INDIRECT_ACTION_UPDATE,
QUEUE_INDIRECT_ACTION_DESTROY,
QUEUE_INDIRECT_ACTION_QUERY,
+ QUEUE_INDIRECT_ACTION_QUERY_UPDATE,
/* Queue indirect action create arguments */
QUEUE_INDIRECT_ACTION_CREATE_ID,
@@ -168,6 +169,9 @@ enum index {
/* Queue indirect action query arguments */
QUEUE_INDIRECT_ACTION_QUERY_POSTPONE,
+ /* Queue indirect action query_update arguments */
+ QUEUE_INDIRECT_ACTION_QU_MODE,
+
/* Push arguments. */
PUSH_QUEUE,
@@ -227,6 +231,7 @@ enum index {
CONFIG_AGING_OBJECTS_NUMBER,
CONFIG_METERS_NUMBER,
CONFIG_CONN_TRACK_NUMBER,
+ CONFIG_QUOTAS_NUMBER,
CONFIG_FLAGS,
/* Indirect action arguments */
@@ -234,6 +239,7 @@ enum index {
INDIRECT_ACTION_UPDATE,
INDIRECT_ACTION_DESTROY,
INDIRECT_ACTION_QUERY,
+ INDIRECT_ACTION_QUERY_UPDATE,
/* Indirect action create arguments */
INDIRECT_ACTION_CREATE_ID,
@@ -245,6 +251,10 @@ enum index {
/* Indirect action destroy arguments */
INDIRECT_ACTION_DESTROY_ID,
+ /* Indirect action query-and-update arguments */
+ INDIRECT_ACTION_QU_MODE,
+ INDIRECT_ACTION_QU_MODE_NAME,
+
/* Validate/create pattern. */
ITEM_PATTERN,
ITEM_PARAM_IS,
@@ -465,6 +475,9 @@ enum index {
ITEM_METER,
ITEM_METER_COLOR,
ITEM_METER_COLOR_NAME,
+ ITEM_QUOTA,
+ ITEM_QUOTA_STATE,
+ ITEM_QUOTA_STATE_NAME,
/* Validate/create actions. */
ACTIONS,
@@ -621,6 +634,14 @@ enum index {
ACTION_REPRESENTED_PORT,
ACTION_REPRESENTED_PORT_ETHDEV_PORT_ID,
ACTION_SEND_TO_KERNEL,
+ ACTION_QUOTA_CREATE,
+ ACTION_QUOTA_CREATE_LIMIT,
+ ACTION_QUOTA_CREATE_MODE,
+ ACTION_QUOTA_CREATE_MODE_NAME,
+ ACTION_QUOTA_QU,
+ ACTION_QUOTA_QU_LIMIT,
+ ACTION_QUOTA_QU_UPDATE_OP,
+ ACTION_QUOTA_QU_UPDATE_OP_NAME,
};
/** Maximum size for pattern in struct rte_flow_item_raw. */
@@ -1011,6 +1032,7 @@ struct buffer {
} ia_destroy; /**< Indirect action destroy arguments. */
struct {
uint32_t action_id;
+ enum rte_flow_query_update_mode qu_mode;
} ia; /* Indirect action query arguments */
struct {
uint32_t table_id;
@@ -1097,6 +1119,7 @@ static const enum index next_config_attr[] = {
CONFIG_AGING_OBJECTS_NUMBER,
CONFIG_METERS_NUMBER,
CONFIG_CONN_TRACK_NUMBER,
+ CONFIG_QUOTAS_NUMBER,
CONFIG_FLAGS,
END,
ZERO,
@@ -1190,6 +1213,7 @@ static const enum index next_qia_subcmd[] = {
QUEUE_INDIRECT_ACTION_UPDATE,
QUEUE_INDIRECT_ACTION_DESTROY,
QUEUE_INDIRECT_ACTION_QUERY,
+ QUEUE_INDIRECT_ACTION_QUERY_UPDATE,
ZERO,
};
@@ -1231,6 +1255,25 @@ static const enum index next_ia_create_attr[] = {
ZERO,
};
+static const enum index next_ia[] = {
+ INDIRECT_ACTION_ID2PTR,
+ ACTION_NEXT,
+ ZERO
+};
+
+static const enum index next_qia_qu_attr[] = {
+ QUEUE_INDIRECT_ACTION_QU_MODE,
+ QUEUE_INDIRECT_ACTION_UPDATE_POSTPONE,
+ INDIRECT_ACTION_SPEC,
+ ZERO
+};
+
+static const enum index next_ia_qu_attr[] = {
+ INDIRECT_ACTION_QU_MODE,
+ INDIRECT_ACTION_SPEC,
+ ZERO
+};
+
static const enum index next_dump_subcmd[] = {
DUMP_ALL,
DUMP_ONE,
@@ -1242,6 +1285,7 @@ static const enum index next_ia_subcmd[] = {
INDIRECT_ACTION_UPDATE,
INDIRECT_ACTION_DESTROY,
INDIRECT_ACTION_QUERY,
+ INDIRECT_ACTION_QUERY_UPDATE,
ZERO,
};
@@ -1355,6 +1399,7 @@ static const enum index next_item[] = {
ITEM_L2TPV2,
ITEM_PPP,
ITEM_METER,
+ ITEM_QUOTA,
END_SET,
ZERO,
};
@@ -1821,6 +1866,12 @@ static const enum index item_meter[] = {
ZERO,
};
+static const enum index item_quota[] = {
+ ITEM_QUOTA_STATE,
+ ITEM_NEXT,
+ ZERO,
+};
+
static const enum index next_action[] = {
ACTION_END,
ACTION_VOID,
@@ -1886,9 +1937,25 @@ static const enum index next_action[] = {
ACTION_PORT_REPRESENTOR,
ACTION_REPRESENTED_PORT,
ACTION_SEND_TO_KERNEL,
+ ACTION_QUOTA_CREATE,
+ ACTION_QUOTA_QU,
ZERO,
};
+static const enum index action_quota_create[] = {
+ ACTION_QUOTA_CREATE_LIMIT,
+ ACTION_QUOTA_CREATE_MODE,
+ ACTION_NEXT,
+ ZERO
+};
+
+static const enum index action_quota_update[] = {
+ ACTION_QUOTA_QU_LIMIT,
+ ACTION_QUOTA_QU_UPDATE_OP,
+ ACTION_NEXT,
+ ZERO
+};
+
static const enum index action_mark[] = {
ACTION_MARK_ID,
ACTION_NEXT,
@@ -2399,6 +2466,22 @@ static int parse_meter_policy_id2ptr(struct context *ctx,
static int parse_meter_color(struct context *ctx, const struct token *token,
const char *str, unsigned int len, void *buf,
unsigned int size);
+static int
+parse_quota_state_name(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len, void *buf,
+ unsigned int size);
+static int
+parse_quota_mode_name(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len, void *buf,
+ unsigned int size);
+static int
+parse_quota_update_name(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len, void *buf,
+ unsigned int size);
+static int
+parse_qu_mode_name(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len, void *buf,
+ unsigned int size);
static int comp_none(struct context *, const struct token *,
unsigned int, char *, unsigned int);
static int comp_boolean(struct context *, const struct token *,
@@ -2431,6 +2514,18 @@ static int comp_queue_id(struct context *, const struct token *,
unsigned int, char *, unsigned int);
static int comp_meter_color(struct context *, const struct token *,
unsigned int, char *, unsigned int);
+static int
+comp_quota_state_name(struct context *ctx, const struct token *token,
+ unsigned int ent, char *buf, unsigned int size);
+static int
+comp_quota_mode_name(struct context *ctx, const struct token *token,
+ unsigned int ent, char *buf, unsigned int size);
+static int
+comp_quota_update_name(struct context *ctx, const struct token *token,
+ unsigned int ent, char *buf, unsigned int size);
+static int
+comp_qu_mode_name(struct context *ctx, const struct token *token,
+ unsigned int ent, char *buf, unsigned int size);
/** Token definitions. */
static const struct token token_list[] = {
@@ -2695,6 +2790,14 @@ static const struct token token_list[] = {
.args = ARGS(ARGS_ENTRY(struct buffer,
args.configure.port_attr.nb_aging_objects)),
},
+ [CONFIG_QUOTAS_NUMBER] = {
+ .name = "quotas_number",
+ .help = "number of quotas",
+ .next = NEXT(next_config_attr,
+ NEXT_ENTRY(COMMON_UNSIGNED)),
+ .args = ARGS(ARGS_ENTRY(struct buffer,
+ args.configure.port_attr.nb_quotas)),
+ },
[CONFIG_METERS_NUMBER] = {
.name = "meters_number",
.help = "number of meters",
@@ -3077,7 +3180,7 @@ static const struct token token_list[] = {
.help = "query indirect action",
.next = NEXT(next_qia_query_attr,
NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
- .args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)),
+ .args = ARGS(ARGS_ENTRY(struct buffer, args.ia.action_id)),
.call = parse_qia,
},
/* Indirect action destroy arguments. */
@@ -3097,6 +3200,21 @@ static const struct token token_list[] = {
args.ia_destroy.action_id)),
.call = parse_qia_destroy,
},
+ [QUEUE_INDIRECT_ACTION_QUERY_UPDATE] = {
+ .name = "query_update",
+ .help = "indirect query [and|or] update action",
+ .next = NEXT(next_qia_qu_attr, NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
+ .args = ARGS(ARGS_ENTRY(struct buffer, args.ia.action_id)),
+ .call = parse_qia
+ },
+ [QUEUE_INDIRECT_ACTION_QU_MODE] = {
+ .name = "mode",
+ .help = "indirect query [and|or] update action",
+ .next = NEXT(next_qia_qu_attr,
+ NEXT_ENTRY(INDIRECT_ACTION_QU_MODE_NAME)),
+ .args = ARGS(ARGS_ENTRY(struct buffer, args.ia.qu_mode)),
+ .call = parse_qia
+ },
/* Indirect action update arguments. */
[QUEUE_INDIRECT_ACTION_UPDATE_POSTPONE] = {
.name = "postpone",
@@ -3220,6 +3338,27 @@ static const struct token token_list[] = {
.args = ARGS(ARGS_ENTRY(struct buffer, args.ia.action_id)),
.call = parse_ia,
},
+ [INDIRECT_ACTION_QUERY_UPDATE] = {
+ .name = "query_update",
+ .help = "query [and|or] update",
+ .next = NEXT(next_ia_qu_attr, NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
+ .args = ARGS(ARGS_ENTRY(struct buffer, args.ia.action_id)),
+ .call = parse_ia
+ },
+ [INDIRECT_ACTION_QU_MODE] = {
+ .name = "mode",
+ .help = "query_update mode",
+ .next = NEXT(next_ia_qu_attr,
+ NEXT_ENTRY(INDIRECT_ACTION_QU_MODE_NAME)),
+ .args = ARGS(ARGS_ENTRY(struct buffer, args.ia.qu_mode)),
+ .call = parse_ia,
+ },
+ [INDIRECT_ACTION_QU_MODE_NAME] = {
+ .name = "mode_name",
+ .help = "query-update mode name",
+ .call = parse_qu_mode_name,
+ .comp = comp_qu_mode_name,
+ },
[VALIDATE] = {
.name = "validate",
.help = "check whether a flow rule can be created",
@@ -5127,6 +5266,26 @@ static const struct token token_list[] = {
.call = parse_meter_color,
.comp = comp_meter_color,
},
+ [ITEM_QUOTA] = {
+ .name = "quota",
+ .help = "match quota",
+ .priv = PRIV_ITEM(QUOTA, sizeof(struct rte_flow_item_quota)),
+ .next = NEXT(item_quota),
+ .call = parse_vc
+ },
+ [ITEM_QUOTA_STATE] = {
+ .name = "quota_state",
+ .help = "quota state",
+ .next = NEXT(item_quota, NEXT_ENTRY(ITEM_QUOTA_STATE_NAME),
+ NEXT_ENTRY(ITEM_PARAM_SPEC, ITEM_PARAM_MASK)),
+ .args = ARGS(ARGS_ENTRY(struct rte_flow_item_quota, state))
+ },
+ [ITEM_QUOTA_STATE_NAME] = {
+ .name = "state_name",
+ .help = "quota state name",
+ .call = parse_quota_state_name,
+ .comp = comp_quota_state_name
+ },
/* Validate/create actions. */
[ACTIONS] = {
.name = "actions",
@@ -6360,7 +6519,7 @@ static const struct token token_list[] = {
.name = "indirect",
.help = "apply indirect action by id",
.priv = PRIV_ACTION(INDIRECT, 0),
- .next = NEXT(NEXT_ENTRY(INDIRECT_ACTION_ID2PTR)),
+ .next = NEXT(next_ia),
.args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t))),
.call = parse_vc,
},
@@ -6411,6 +6570,64 @@ static const struct token token_list[] = {
.help = "submit a list of associated actions for red",
.next = NEXT(next_action),
},
+ [ACTION_QUOTA_CREATE] = {
+ .name = "quota_create",
+ .help = "create quota action",
+ .priv = PRIV_ACTION(QUOTA,
+ sizeof(struct rte_flow_action_quota)),
+ .next = NEXT(action_quota_create),
+ .call = parse_vc
+ },
+ [ACTION_QUOTA_CREATE_LIMIT] = {
+ .name = "limit",
+ .help = "quota limit",
+ .next = NEXT(action_quota_create, NEXT_ENTRY(COMMON_UNSIGNED)),
+ .args = ARGS(ARGS_ENTRY(struct rte_flow_action_quota, quota)),
+ .call = parse_vc_conf
+ },
+ [ACTION_QUOTA_CREATE_MODE] = {
+ .name = "mode",
+ .help = "quota mode",
+ .next = NEXT(action_quota_create,
+ NEXT_ENTRY(ACTION_QUOTA_CREATE_MODE_NAME)),
+ .args = ARGS(ARGS_ENTRY(struct rte_flow_action_quota, mode)),
+ .call = parse_vc_conf
+ },
+ [ACTION_QUOTA_CREATE_MODE_NAME] = {
+ .name = "mode_name",
+ .help = "quota mode name",
+ .call = parse_quota_mode_name,
+ .comp = comp_quota_mode_name
+ },
+ [ACTION_QUOTA_QU] = {
+ .name = "quota_update",
+ .help = "update quota action",
+ .priv = PRIV_ACTION(QUOTA,
+ sizeof(struct rte_flow_update_quota)),
+ .next = NEXT(action_quota_update),
+ .call = parse_vc
+ },
+ [ACTION_QUOTA_QU_LIMIT] = {
+ .name = "limit",
+ .help = "quota limit",
+ .next = NEXT(action_quota_update, NEXT_ENTRY(COMMON_UNSIGNED)),
+ .args = ARGS(ARGS_ENTRY(struct rte_flow_update_quota, quota)),
+ .call = parse_vc_conf
+ },
+ [ACTION_QUOTA_QU_UPDATE_OP] = {
+ .name = "update_op",
+ .help = "query update op SET|ADD",
+ .next = NEXT(action_quota_update,
+ NEXT_ENTRY(ACTION_QUOTA_QU_UPDATE_OP_NAME)),
+ .args = ARGS(ARGS_ENTRY(struct rte_flow_update_quota, op)),
+ .call = parse_vc_conf
+ },
+ [ACTION_QUOTA_QU_UPDATE_OP_NAME] = {
+ .name = "update_op_name",
+ .help = "quota update op name",
+ .call = parse_quota_update_name,
+ .comp = comp_quota_update_name
+ },
/* Top-level command. */
[ADD] = {
@@ -6656,6 +6873,7 @@ parse_ia(struct context *ctx, const struct token *token,
switch (ctx->curr) {
case INDIRECT_ACTION_CREATE:
case INDIRECT_ACTION_UPDATE:
+ case INDIRECT_ACTION_QUERY_UPDATE:
out->args.vc.actions =
(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
sizeof(double));
@@ -6676,6 +6894,8 @@ parse_ia(struct context *ctx, const struct token *token,
case INDIRECT_ACTION_TRANSFER:
out->args.vc.attr.transfer = 1;
return len;
+ case INDIRECT_ACTION_QU_MODE:
+ return len;
default:
return -1;
}
@@ -6748,6 +6968,7 @@ parse_qia(struct context *ctx, const struct token *token,
return len;
case QUEUE_INDIRECT_ACTION_CREATE:
case QUEUE_INDIRECT_ACTION_UPDATE:
+ case QUEUE_INDIRECT_ACTION_QUERY_UPDATE:
out->args.vc.actions =
(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
sizeof(double));
@@ -6770,6 +6991,8 @@ parse_qia(struct context *ctx, const struct token *token,
return len;
case QUEUE_INDIRECT_ACTION_CREATE_POSTPONE:
return len;
+ case QUEUE_INDIRECT_ACTION_QU_MODE:
+ return len;
default:
return -1;
}
@@ -10052,6 +10275,107 @@ parse_meter_color(struct context *ctx, const struct token *token,
return len;
}
+static int
+parse_name_to_index(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len, void *buf,
+ unsigned int size,
+ const char *const names[], size_t names_size, uint32_t *dst)
+{
+ int ret;
+ uint32_t i;
+
+ RTE_SET_USED(token);
+ RTE_SET_USED(buf);
+ RTE_SET_USED(size);
+ if (!ctx->object)
+ return len;
+ for (i = 0; i < names_size; i++) {
+ if (!names[i])
+ continue;
+ ret = strcmp_partial(names[i], str,
+ RTE_MIN(len, strlen(names[i])));
+ if (!ret) {
+ *dst = i;
+ return len;
+ }
+ }
+ return -1;
+}
+
+static const char *const quota_mode_names[] = {
+ NULL,
+ [RTE_FLOW_QUOTA_MODE_PACKET] = "packet",
+ [RTE_FLOW_QUOTA_MODE_L2] = "l2",
+ [RTE_FLOW_QUOTA_MODE_L3] = "l3"
+};
+
+static const char *const quota_state_names[] = {
+ [RTE_FLOW_QUOTA_STATE_PASS] = "pass",
+ [RTE_FLOW_QUOTA_STATE_BLOCK] = "block"
+};
+
+static const char *const quota_update_names[] = {
+ [RTE_FLOW_UPDATE_QUOTA_SET] = "set",
+ [RTE_FLOW_UPDATE_QUOTA_ADD] = "add"
+};
+
+static const char *const query_update_mode_names[] = {
+ [RTE_FLOW_QU_QUERY_FIRST] = "query_first",
+ [RTE_FLOW_QU_UPDATE_FIRST] = "update_first"
+};
+
+static int
+parse_quota_state_name(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len, void *buf,
+ unsigned int size)
+{
+ struct rte_flow_item_quota *quota = ctx->object;
+
+ return parse_name_to_index(ctx, token, str, len, buf, size,
+ quota_state_names,
+ RTE_DIM(quota_state_names),
+ (uint32_t *)"a->state);
+}
+
+static int
+parse_quota_mode_name(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len, void *buf,
+ unsigned int size)
+{
+ struct rte_flow_action_quota *quota = ctx->object;
+
+ return parse_name_to_index(ctx, token, str, len, buf, size,
+ quota_mode_names,
+ RTE_DIM(quota_mode_names),
+ (uint32_t *)"a->mode);
+}
+
+static int
+parse_quota_update_name(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len, void *buf,
+ unsigned int size)
+{
+ struct rte_flow_update_quota *update = ctx->object;
+
+ return parse_name_to_index(ctx, token, str, len, buf, size,
+ quota_update_names,
+ RTE_DIM(quota_update_names),
+ (uint32_t *)&update->op);
+}
+
+static int
+parse_qu_mode_name(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len, void *buf,
+ unsigned int size)
+{
+ struct buffer *out = ctx->object;
+
+ return parse_name_to_index(ctx, token, str, len, buf, size,
+ query_update_mode_names,
+ RTE_DIM(query_update_mode_names),
+ (uint32_t *)&out->args.ia.qu_mode);
+}
+
/** No completion. */
static int
comp_none(struct context *ctx, const struct token *token,
@@ -10343,6 +10667,21 @@ comp_queue_id(struct context *ctx, const struct token *token,
return i;
}
+static int
+comp_names_to_index(struct context *ctx, const struct token *token,
+ unsigned int ent, char *buf, unsigned int size,
+ const char *const names[], size_t names_size)
+{
+ RTE_SET_USED(ctx);
+ RTE_SET_USED(token);
+ if (!buf)
+ return names_size;
+ if (names[ent] && ent < names_size)
+ return rte_strscpy(buf, names[ent], size);
+ return -1;
+
+}
+
/** Complete available Meter colors. */
static int
comp_meter_color(struct context *ctx, const struct token *token,
@@ -10357,6 +10696,42 @@ comp_meter_color(struct context *ctx, const struct token *token,
return -1;
}
+static int
+comp_quota_state_name(struct context *ctx, const struct token *token,
+ unsigned int ent, char *buf, unsigned int size)
+{
+ return comp_names_to_index(ctx, token, ent, buf, size,
+ quota_state_names,
+ RTE_DIM(quota_state_names));
+}
+
+static int
+comp_quota_mode_name(struct context *ctx, const struct token *token,
+ unsigned int ent, char *buf, unsigned int size)
+{
+ return comp_names_to_index(ctx, token, ent, buf, size,
+ quota_mode_names,
+ RTE_DIM(quota_mode_names));
+}
+
+static int
+comp_quota_update_name(struct context *ctx, const struct token *token,
+ unsigned int ent, char *buf, unsigned int size)
+{
+ return comp_names_to_index(ctx, token, ent, buf, size,
+ quota_update_names,
+ RTE_DIM(quota_update_names));
+}
+
+static int
+comp_qu_mode_name(struct context *ctx, const struct token *token,
+ unsigned int ent, char *buf, unsigned int size)
+{
+ return comp_names_to_index(ctx, token, ent, buf, size,
+ query_update_mode_names,
+ RTE_DIM(query_update_mode_names));
+}
+
/** Internal context. */
static struct context cmd_flow_context;
@@ -10715,7 +11090,14 @@ cmd_flow_parsed(const struct buffer *in)
case QUEUE_INDIRECT_ACTION_QUERY:
port_queue_action_handle_query(in->port,
in->queue, in->postpone,
- in->args.vc.attr.group);
+ in->args.ia.action_id);
+ break;
+ case QUEUE_INDIRECT_ACTION_QUERY_UPDATE:
+ port_queue_action_handle_query_update(in->port, in->queue,
+ in->postpone,
+ in->args.ia.action_id,
+ in->args.ia.qu_mode,
+ in->args.vc.actions);
break;
case INDIRECT_ACTION_CREATE:
port_action_handle_create(
@@ -10739,6 +11121,12 @@ cmd_flow_parsed(const struct buffer *in)
case INDIRECT_ACTION_QUERY:
port_action_handle_query(in->port, in->args.ia.action_id);
break;
+ case INDIRECT_ACTION_QUERY_UPDATE:
+ port_action_handle_query_update(in->port,
+ in->args.ia.action_id,
+ in->args.ia.qu_mode,
+ in->args.vc.actions);
+ break;
case VALIDATE:
port_flow_validate(in->port, &in->args.vc.attr,
in->args.vc.pattern, in->args.vc.actions,
@@ -1901,9 +1901,13 @@ port_action_handle_update(portid_t port_id, uint32_t id,
}
static void
-port_action_handle_query_dump(uint32_t type, union port_action_query *query)
+port_action_handle_query_dump(portid_t port_id,
+ const struct port_indirect_action *pia,
+ union port_action_query *query)
{
- switch (type) {
+ if (!pia || !query)
+ return;
+ switch (pia->type) {
case RTE_FLOW_ACTION_TYPE_AGE:
printf("Indirect AGE action:\n"
" aged: %u\n"
@@ -1967,15 +1971,41 @@ port_action_handle_query_dump(uint32_t type, union port_action_query *query)
query->ct.reply_dir.max_win,
query->ct.reply_dir.max_ack);
break;
+ case RTE_FLOW_ACTION_TYPE_QUOTA:
+ printf("Indirect QUOTA action %u\n"
+ " unused quota: %" PRId64 "\n",
+ pia->id, query->quota.quota);
+ break;
default:
- fprintf(stderr,
- "Indirect action (type: %d) doesn't support query\n",
- type);
+ printf("port-%u: indirect action %u (type: %d) doesn't support query\n",
+ pia->type, pia->id, port_id);
break;
}
}
+void
+port_action_handle_query_update(portid_t port_id, uint32_t id,
+ enum rte_flow_query_update_mode qu_mode,
+ const struct rte_flow_action *action)
+{
+ int ret;
+ struct rte_flow_error error;
+ struct port_indirect_action *pia;
+ union port_action_query query;
+
+ pia = action_get_by_id(port_id, id);
+ if (!pia || !pia->handle)
+ return;
+ ret = rte_flow_action_handle_query_update(port_id, pia->handle, action,
+ &query, qu_mode, &error);
+ if (ret)
+ port_flow_complain(&error);
+ else
+ port_action_handle_query_dump(port_id, pia, &query);
+
+}
+
int
port_action_handle_query(portid_t port_id, uint32_t id)
{
@@ -1989,6 +2019,7 @@ port_action_handle_query(portid_t port_id, uint32_t id)
switch (pia->type) {
case RTE_FLOW_ACTION_TYPE_AGE:
case RTE_FLOW_ACTION_TYPE_COUNT:
+ case RTE_FLOW_ACTION_TYPE_QUOTA:
break;
default:
fprintf(stderr,
@@ -2001,7 +2032,7 @@ port_action_handle_query(portid_t port_id, uint32_t id)
memset(&query, 0, sizeof(query));
if (rte_flow_action_handle_query(port_id, pia->handle, &query, &error))
return port_flow_complain(&error);
- port_action_handle_query_dump(pia->type, &query);
+ port_action_handle_query_dump(port_id, pia, &query);
return 0;
}
@@ -2945,6 +2976,42 @@ port_queue_action_handle_update(portid_t port_id,
return 0;
}
+void
+port_queue_action_handle_query_update(portid_t port_id,
+ uint32_t queue_id, bool postpone,
+ uint32_t id,
+ enum rte_flow_query_update_mode qu_mode,
+ const struct rte_flow_action *action)
+{
+ int ret;
+ struct rte_flow_error error;
+ struct port_indirect_action *pia = action_get_by_id(port_id, id);
+ const struct rte_flow_op_attr attr = { .postpone = postpone};
+ struct queue_job *job;
+
+ if (!pia || !pia->handle)
+ return;
+ job = calloc(1, sizeof(*job));
+ if (!job)
+ return;
+ job->type = QUEUE_JOB_TYPE_ACTION_QUERY;
+ job->pia = pia;
+
+ ret = rte_flow_async_action_handle_query_update(port_id, queue_id,
+ &attr, pia->handle,
+ action,
+ &job->query,
+ qu_mode, job,
+ &error);
+ if (ret) {
+ port_flow_complain(&error);
+ free(job);
+ } else {
+ printf("port-%u: indirect action #%u update-and-query queued\n",
+ port_id, id);
+ }
+}
+
/** Enqueue indirect action query operation. */
int
port_queue_action_handle_query(portid_t port_id,
@@ -3215,7 +3282,8 @@ port_queue_flow_pull(portid_t port_id, queueid_t queue_id)
else if (job->type == QUEUE_JOB_TYPE_ACTION_DESTROY)
free(job->pia);
else if (job->type == QUEUE_JOB_TYPE_ACTION_QUERY)
- port_action_handle_query_dump(job->pia->type, &job->query);
+ port_action_handle_query_dump(port_id, job->pia,
+ &job->query);
free(job);
}
printf("Queue #%u pulled %u operations (%u failed, %u succeeded)\n",
@@ -236,6 +236,7 @@ union port_action_query {
struct rte_flow_query_count count;
struct rte_flow_query_age age;
struct rte_flow_action_conntrack ct;
+ struct rte_flow_query_quota quota;
};
/* Descriptor for queue job. */
@@ -904,6 +905,10 @@ struct rte_flow_action_handle *port_action_handle_get_by_id(portid_t port_id,
uint32_t id);
int port_action_handle_update(portid_t port_id, uint32_t id,
const struct rte_flow_action *action);
+void
+port_action_handle_query_update(portid_t port_id, uint32_t id,
+ enum rte_flow_query_update_mode qu_mode,
+ const struct rte_flow_action *action);
int port_flow_get_info(portid_t port_id);
int port_flow_configure(portid_t port_id,
const struct rte_flow_port_attr *port_attr,
@@ -948,6 +953,12 @@ int port_queue_action_handle_update(portid_t port_id, uint32_t queue_id,
const struct rte_flow_action *action);
int port_queue_action_handle_query(portid_t port_id, uint32_t queue_id,
bool postpone, uint32_t id);
+void
+port_queue_action_handle_query_update(portid_t port_id,
+ uint32_t queue_id, bool postpone,
+ uint32_t id,
+ enum rte_flow_query_update_mode qu_mode,
+ const struct rte_flow_action *action);
int port_queue_flow_push(portid_t port_id, queueid_t queue_id);
int port_queue_flow_pull(portid_t port_id, queueid_t queue_id);
void port_queue_flow_aged(portid_t port_id, uint32_t queue_id, uint8_t destroy);
@@ -132,6 +132,7 @@ ppp =
pppoed =
pppoes =
pppoe_proto_id =
+quota =
raw =
represented_port =
sctp =
@@ -178,6 +179,7 @@ pf =
port_id =
port_representor =
queue =
+quota =
raw_decap =
raw_encap =
represented_port =
@@ -1544,6 +1544,13 @@ Matches Color Marker set by a Meter.
- ``color``: Metering color marker.
+Item: ``QUOTA``
+^^^^^^^^^^^^^^^
+
+Matches flow quota state set by quota action.
+
+- ``state``: Flow quota state
+
Actions
~~~~~~~
@@ -3227,6 +3234,40 @@ and rte_mtr_policy_get() API respectively.
| ``policy`` | Meter policy object |
+------------------+----------------------+
+Action: ``QUOTA``
+^^^^^^^^^^^^^^^^^
+
+Update ``quota`` value and set packet quota state.
+If the ``quota`` value after update is non-negative packet quota state set to
+``RTE_FLOW_QUOTA_STATE_PASS``. Otherwise, packet quota state set to ``RTE_FLOW_QUOTA_STATE_BLOCK``.
+The ``quota`` value is reduced according to ``mode`` setting.
+
+.. _table_rte_flow_action_quota:
+
+.. table:: QUOTA
+
+ +------------------+------------------------+
+ | Field | Value |
+ +==================+========================+
+ | ``mode`` | Quota operational mode |
+ +------------------+------------------------+
+ | ``quota`` | Quota value |
+ +------------------+------------------------+
+
+.. _rte_flow_quota_mode:
+
+.. table:: Quota update modes
+
+ +---------------------------------+-------------------------------------+
+ | Value | Description |
+ +=================================+=====================================+
+ | ``RTE_FLOW_QUOTA_MODE_PACKET`` | Count packets |
+ +---------------------------------+-------------------------------------+
+ | ``RTE_FLOW_QUOTA_MODE_L2`` | Count packet bytes starting from L2 |
+ +------------------+----------------------------------------------------+
+ | ``RTE_FLOW_QUOTA_MODE_L3`` | Count packet bytes starting from L3 |
+ +------------------+----------------------------------------------------+
+
Negative types
~~~~~~~~~~~~~~
@@ -77,6 +77,33 @@ New Features
- ``rte_flow_action_handle_query_update``
- ``rte_flow_async_action_handle_query_update``
+* **Added quota flow action and quota flow item.**
+
+ Quota action limits traffic according to pre-defined configuration.
+ Quota reflects overall traffic usage regardless bandwidth.
+ Quota flow action initialized with signed tokens number value.
+ Quota flow action updates tokens number according to
+ these rules:
+ * If quota was configured to count packet length, for each packet
+ of size S, tokens number reduced by S.
+ * If quota was configured to count packets, each packet decrements
+ tokens number.
+ Quota action sets packet metadata according to a number of remaining
+ tokens number:
+ * ``PASS`` - remaining tokens number is non-negative.
+ * ``BLOCK`` - remaining tokens number is negative.
+
+ Quota flow item matches on that metadata.
+
+ - ``RTE_FLOW_ACTION_TYPE_QUOTA``
+ - ``RTE_FLOW_ITEM_TYPE_QUOTA``
+
+* **Updated testpmd to support quota flow action and item.**
+
+ Added tokens to ``token_list[]`` for flow quota action and item support.
+
+
+
Removed Items
-------------
@@ -157,6 +157,7 @@ static const struct rte_flow_desc_data rte_flow_desc_item[] = {
MK_FLOW_ITEM(L2TPV2, sizeof(struct rte_flow_item_l2tpv2)),
MK_FLOW_ITEM(PPP, sizeof(struct rte_flow_item_ppp)),
MK_FLOW_ITEM(METER_COLOR, sizeof(struct rte_flow_item_meter_color)),
+ MK_FLOW_ITEM(QUOTA, sizeof(struct rte_flow_item_quota)),
};
/** Generate flow_action[] entry. */
@@ -251,6 +252,7 @@ static const struct rte_flow_desc_data rte_flow_desc_action[] = {
MK_FLOW_ACTION(REPRESENTED_PORT, sizeof(struct rte_flow_action_ethdev)),
MK_FLOW_ACTION(METER_MARK, sizeof(struct rte_flow_action_meter_mark)),
MK_FLOW_ACTION(SEND_TO_KERNEL, 0),
+ MK_FLOW_ACTION(QUOTA, sizeof(struct rte_flow_action_quota)),
};
int
@@ -624,7 +624,45 @@ enum rte_flow_item_type {
* See struct rte_flow_item_meter_color.
*/
RTE_FLOW_ITEM_TYPE_METER_COLOR,
+
+ /**
+ * Match Quota state
+ *
+ * @see struct rte_flow_item_quota
+ */
+ RTE_FLOW_ITEM_TYPE_QUOTA,
+};
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * QUOTA state.
+ *
+ * @see struct rte_flow_item_quota
+ */
+enum rte_flow_quota_state {
+ RTE_FLOW_QUOTA_STATE_PASS, /** PASS quota state */
+ RTE_FLOW_QUOTA_STATE_BLOCK /** BLOCK quota state */
+};
+
+/**
+ * RTE_FLOW_ITEM_TYPE_QUOTA
+ *
+ * Matches QUOTA state
+ */
+struct rte_flow_item_quota {
+ enum rte_flow_quota_state state;
+};
+
+/**
+ * Default mask for RTE_FLOW_ITEM_TYPE_QUOTA
+ */
+#ifndef __cplusplus
+static const struct rte_flow_item_quota rte_flow_item_quota_mask = {
+ .state = (enum rte_flow_quota_state)0xff
};
+#endif
/**
*
@@ -2736,6 +2774,81 @@ enum rte_flow_action_type {
* No associated configuration structure.
*/
RTE_FLOW_ACTION_TYPE_SEND_TO_KERNEL,
+
+ /**
+ * Apply the quota verdict (PASS or BLOCK) to a flow.
+ *
+ * @see struct rte_flow_action_quota
+ * @see struct rte_flow_query_quota
+ * @see struct rte_flow_update_quota
+ */
+ RTE_FLOW_ACTION_TYPE_QUOTA,
+};
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * QUOTA operational mode.
+ *
+ * @see struct rte_flow_action_quota
+ */
+enum rte_flow_quota_mode {
+ RTE_FLOW_QUOTA_MODE_PACKET = 1, /** Count packets */
+ RTE_FLOW_QUOTA_MODE_L2 = 2, /** Count packet bytes starting from L2 */
+ RTE_FLOW_QUOTA_MODE_L3 = 3, /** Count packet bytes starting from L3 */
+};
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Create QUOTA action.
+ *
+ * @see RTE_FLOW_ACTION_TYPE_QUOTA
+ */
+struct rte_flow_action_quota {
+ enum rte_flow_quota_mode mode; /** quota operational mode */
+ int64_t quota; /** quota value */
+};
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Query indirect QUOTA action.
+ *
+ * @see RTE_FLOW_ACTION_TYPE_QUOTA
+ *
+ */
+struct rte_flow_query_quota {
+ int64_t quota; /** quota value */
+};
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Indirect QUOTA update operations.
+ *
+ * @see struct rte_flow_update_quota
+ */
+enum rte_flow_update_quota_op {
+ RTE_FLOW_UPDATE_QUOTA_SET, /** set new quota value */
+ RTE_FLOW_UPDATE_QUOTA_ADD, /** increase existing quota with new value */
+};
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * @see RTE_FLOW_ACTION_TYPE_QUOTA
+ *
+ * Update indirect QUOTA action.
+ */
+struct rte_flow_update_quota {
+ enum rte_flow_update_quota_op op; /** update operation */
+ int64_t quota; /** quota value */
};
/**
@@ -4854,6 +4967,11 @@ struct rte_flow_port_info {
* @see RTE_FLOW_ACTION_TYPE_CONNTRACK
*/
uint32_t max_nb_conn_tracks;
+ /**
+ * Maximum number of quota actions.
+ * @see RTE_FLOW_ACTION_TYPE_QUOTA
+ */
+ uint32_t max_nb_quotas;
/**
* Port supported flags (RTE_FLOW_PORT_FLAG_*).
*/
@@ -4932,6 +5050,11 @@ struct rte_flow_port_attr {
* @see RTE_FLOW_ACTION_TYPE_CONNTRACK
*/
uint32_t nb_conn_tracks;
+ /**
+ * Maximum number of quota actions.
+ * @see RTE_FLOW_ACTION_TYPE_QUOTA
+ */
+ uint32_t nb_quotas;
/**
* Port flags (RTE_FLOW_PORT_FLAG_*).
*/