@@ -58,6 +58,7 @@
#include <rte_debug.h>
#include <rte_cycles.h>
#include <rte_memory.h>
+#include <rte_malloc.h>
#include <rte_memzone.h>
#include <rte_launch.h>
#include <rte_tailq.h>
@@ -685,6 +686,10 @@ static void cmd_help_long_parsed(void *parsed_result,
"flush_flow_diretor (port_id)\n"
" Flush all flow director entries of a device.\n\n"
+
+ "flow_director_flex_payload (port_id)"
+ " (l2|l3|l4) (config)\n"
+ " configure flexible payload selection.\n\n"
);
}
}
@@ -7903,6 +7908,144 @@ cmdline_parse_inst_t cmd_flush_flow_director = {
},
};
+/* *** deal with flow director flexible payload configuration *** */
+struct cmd_flow_director_flexpayload_result {
+ cmdline_fixed_string_t flow_director_flexpayload;
+ uint8_t port_id;
+ cmdline_fixed_string_t payload_layer;
+ cmdline_fixed_string_t payload_cfg;
+};
+
+static inline int
+parse_flex_payload_cfg(const char *q_arg,
+ struct rte_eth_flex_payload_cfg *cfg)
+{
+ char s[256];
+ const char *p, *p0 = q_arg;
+ char *end;
+ enum fieldnames {
+ FLD_OFFSET = 0,
+ FLD_SIZE,
+ _NUM_FLD
+ };
+ unsigned long int_fld[_NUM_FLD];
+ char *str_fld[_NUM_FLD];
+ int i;
+ unsigned size;
+
+ cfg->nb_field = 0;
+ p = strchr(p0, '(');
+ while (p != NULL) {
+ ++p;
+ p0 = strchr(p, ')');
+ if (p0 == NULL)
+ return -1;
+
+ size = p0 - p;
+ if (size >= sizeof(s))
+ return -1;
+
+ snprintf(s, sizeof(s), "%.*s", size, p);
+ if (rte_strsplit(s, sizeof(s), str_fld, _NUM_FLD, ',') != _NUM_FLD)
+ return -1;
+ for (i = 0; i < _NUM_FLD; i++) {
+ errno = 0;
+ int_fld[i] = strtoul(str_fld[i], &end, 0);
+ if (errno != 0 || end == str_fld[i] || int_fld[i] > 255)
+ return -1;
+ }
+ cfg->field[cfg->nb_field].offset = (uint8_t)int_fld[FLD_OFFSET];
+ cfg->field[cfg->nb_field].size = (uint8_t)int_fld[FLD_SIZE];
+ cfg->nb_field++;
+ if (cfg->nb_field > 3) {
+ printf("exceeded max number of fields\n");
+ return -1;
+ }
+ p = strchr(p0, '(');
+ }
+ return 0;
+}
+
+static void
+cmd_flow_director_flxpld_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_flow_director_flexpayload_result *res = parsed_result;
+ struct rte_eth_fdir_cfg fdir_cfg;
+ struct rte_eth_flex_payload_cfg *flxpld_cfg;
+ int ret = 0;
+ int cfg_size = 3 * sizeof(struct rte_eth_field_vector) +
+ offsetof(struct rte_eth_flex_payload_cfg, field);
+
+ ret = rte_eth_dev_filter_supported(res->port_id, RTE_ETH_FILTER_FDIR);
+ if (ret < 0) {
+ printf("flow director is not supported on port %u.\n",
+ res->port_id);
+ return;
+ }
+
+ memset(&fdir_cfg, 0, sizeof(struct rte_eth_fdir_cfg));
+
+ flxpld_cfg = (struct rte_eth_flex_payload_cfg *)rte_zmalloc_socket("CLI",
+ cfg_size, CACHE_LINE_SIZE, rte_socket_id());
+
+ if (flxpld_cfg == NULL) {
+ printf("fail to malloc memory to configure flexible payload\n");
+ return;
+ }
+
+ if (!strcmp(res->payload_layer, "l2"))
+ flxpld_cfg->type = RTE_ETH_L2_PAYLOAD;
+ else if (!strcmp(res->payload_layer, "l3"))
+ flxpld_cfg->type = RTE_ETH_L3_PAYLOAD;
+ else if (!strcmp(res->payload_layer, "l4"))
+ flxpld_cfg->type = RTE_ETH_L4_PAYLOAD;
+
+ ret = parse_flex_payload_cfg(res->payload_cfg, flxpld_cfg);
+ if (ret < 0) {
+ printf("fdir flexpayload parsing error: (%s)\n",
+ strerror(-ret));
+ rte_free(flxpld_cfg);
+ return;
+ }
+ fdir_cfg.cmd = RTE_ETH_FDIR_CFG_FLX;
+ fdir_cfg.cfg = flxpld_cfg;
+ ret = rte_eth_dev_filter_ctrl(res->port_id, RTE_ETH_FILTER_FDIR,
+ RTE_ETH_FILTER_OP_SET, &fdir_cfg);
+ if (ret < 0)
+ printf("fdir flexpayload setting error: (%s)\n",
+ strerror(-ret));
+ rte_free(flxpld_cfg);
+}
+
+cmdline_parse_token_string_t cmd_flow_director_flexpayload =
+ TOKEN_STRING_INITIALIZER(struct cmd_flow_director_flexpayload_result,
+ flow_director_flexpayload,
+ "flow_director_flex_payload");
+cmdline_parse_token_num_t cmd_flow_director_flexpayload_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_flow_director_flexpayload_result,
+ port_id, UINT8);
+cmdline_parse_token_string_t cmd_flow_director_flexpayload_payload_layer =
+ TOKEN_STRING_INITIALIZER(struct cmd_flow_director_flexpayload_result,
+ payload_layer, "l2#l3#l4");
+cmdline_parse_token_string_t cmd_flow_director_flexpayload_payload_cfg =
+ TOKEN_STRING_INITIALIZER(struct cmd_flow_director_flexpayload_result,
+ payload_cfg, NULL);
+
+cmdline_parse_inst_t cmd_set_flow_director_flex_payload = {
+ .f = cmd_flow_director_flxpld_parsed,
+ .data = NULL,
+ .help_str = "set flow director's flexible payload on NIC",
+ .tokens = {
+ (void *)&cmd_flow_director_flexpayload,
+ (void *)&cmd_flow_director_flexpayload_port_id,
+ (void *)&cmd_flow_director_flexpayload_payload_layer,
+ (void *)&cmd_flow_director_flexpayload_payload_cfg,
+ NULL,
+ },
+};
+
/* ******************************************************************************** */
/* list of instructions */
@@ -8033,6 +8176,7 @@ cmdline_parse_ctx_t main_ctx[] = {
(cmdline_parse_inst_t *)&cmd_add_del_udp_flow_director,
(cmdline_parse_inst_t *)&cmd_add_del_sctp_flow_director,
(cmdline_parse_inst_t *)&cmd_flush_flow_director,
+ (cmdline_parse_inst_t *)&cmd_set_flow_director_flex_payload,
NULL,
};