@@ -705,6 +705,11 @@ static void cmd_help_long_parsed(void *parsed_result,
"flush_flow_director (port_id)\n"
" Flush all flow director entries of a device.\n\n"
+ "flow_director_flex_mask (port_id)"
+ " flow (ip4|tcp4|udp4|sctp4|ip6|tcp6|udp6|sctp6)"
+ " words_mask (words) (word_mask_list)\n"
+ " Configure mask of flex payload.\n\n"
+
"flow_director_flex_payload (port_id)"
" (l2|l3|l4) (config)\n"
" Configure flex payload selection.\n\n"
@@ -8130,6 +8135,173 @@ cmdline_parse_inst_t cmd_flush_flow_director = {
},
};
+/* *** deal with flow director mask on flexible payload *** */
+struct cmd_flow_director_flex_mask_result {
+ cmdline_fixed_string_t flow_director_flexmask;
+ uint8_t port_id;
+ cmdline_fixed_string_t flow;
+ cmdline_fixed_string_t flow_type;
+ cmdline_fixed_string_t words_mask;
+ uint8_t words;
+ cmdline_fixed_string_t word_mask_list;
+};
+
+static inline int
+parse_word_masks_cfg(const char *q_arg,
+ struct rte_eth_fdir_flex_masks *masks)
+{
+ char s[256];
+ const char *p, *p0 = q_arg;
+ char *end;
+ enum fieldnames {
+ FLD_OFFSET = 0,
+ FLD_MASK,
+ _NUM_FLD
+ };
+ unsigned long int_fld[_NUM_FLD];
+ char *str_fld[_NUM_FLD];
+ int i;
+ unsigned size;
+
+ masks->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] > UINT16_MAX)
+ return -1;
+ }
+ masks->field[masks->nb_field].offset =
+ (uint16_t)int_fld[FLD_OFFSET];
+ masks->field[masks->nb_field].bitmask =
+ ~(uint16_t)int_fld[FLD_MASK];
+ masks->nb_field++;
+ if (masks->nb_field > 2) {
+ printf("exceeded max number of fields: %hhu\n",
+ masks->nb_field);
+ return -1;
+ }
+ p = strchr(p0, '(');
+ }
+ return 0;
+}
+
+static void
+cmd_flow_director_flex_mask_parsed(void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct cmd_flow_director_flex_mask_result *res = parsed_result;
+ struct rte_eth_fdir_flex_masks *flex_masks;
+ struct rte_eth_fdir_cfg fdir_cfg;
+ int ret = 0;
+ int cfg_size = 2 * sizeof(struct rte_eth_flex_mask) +
+ offsetof(struct rte_eth_fdir_flex_masks, 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));
+
+ flex_masks = (struct rte_eth_fdir_flex_masks *)rte_zmalloc_socket("CLI",
+ cfg_size, CACHE_LINE_SIZE, rte_socket_id());
+
+ if (flex_masks == NULL) {
+ printf("fail to malloc memory to configure flex mask.\n");
+ return;
+ }
+
+ if (!strcmp(res->flow_type, "ip4"))
+ flex_masks->flow_type = RTE_ETH_FLOW_TYPE_IPV4_OTHER;
+ else if (!strcmp(res->flow_type, "udp4"))
+ flex_masks->flow_type = RTE_ETH_FLOW_TYPE_UDPV4;
+ else if (!strcmp(res->flow_type, "tcp4"))
+ flex_masks->flow_type = RTE_ETH_FLOW_TYPE_TCPV4;
+ else if (!strcmp(res->flow_type, "sctp4"))
+ flex_masks->flow_type = RTE_ETH_FLOW_TYPE_SCTPV4;
+ else if (!strcmp(res->flow_type, "ip6"))
+ flex_masks->flow_type = RTE_ETH_FLOW_TYPE_IPV6_OTHER;
+ else if (!strcmp(res->flow_type, "udp6"))
+ flex_masks->flow_type = RTE_ETH_FLOW_TYPE_UDPV6;
+ else if (!strcmp(res->flow_type, "tcp6"))
+ flex_masks->flow_type = RTE_ETH_FLOW_TYPE_TCPV6;
+ else if (!strcmp(res->flow_type, "sctp6"))
+ flex_masks->flow_type = RTE_ETH_FLOW_TYPE_SCTPV6;
+
+ flex_masks->words_mask = res->words;
+ ret = parse_word_masks_cfg(res->word_mask_list, flex_masks);
+ if (ret < 0) {
+ printf("error: Cannot parse words masks input.\n");
+ rte_free(flex_masks);
+ return;
+ }
+
+ fdir_cfg.cmd = RTE_ETH_FDIR_CFG_FLX_MASK;
+ fdir_cfg.cfg = flex_masks;
+ ret = rte_eth_dev_filter_ctrl(res->port_id, RTE_ETH_FILTER_FDIR,
+ RTE_ETH_FILTER_SET, &fdir_cfg);
+ if (ret < 0)
+ printf("fdir flex mask setting error: (%s)\n", strerror(-ret));
+ rte_free(flex_masks);
+}
+
+cmdline_parse_token_string_t cmd_flow_director_flexmask =
+ TOKEN_STRING_INITIALIZER(struct cmd_flow_director_flex_mask_result,
+ flow_director_flexmask,
+ "flow_director_flex_mask");
+cmdline_parse_token_num_t cmd_flow_director_flexmask_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_flow_director_flex_mask_result,
+ port_id, UINT8);
+cmdline_parse_token_string_t cmd_flow_director_flexmask_flow =
+ TOKEN_STRING_INITIALIZER(struct cmd_flow_director_flex_mask_result,
+ flow, "flow");
+cmdline_parse_token_string_t cmd_flow_director_flexmask_flow_type =
+ TOKEN_STRING_INITIALIZER(struct cmd_flow_director_flex_mask_result,
+ flow_type,
+ "ip4#tcp4#udp4#sctp4#ip6#tcp6#udp6#sctp6");
+cmdline_parse_token_string_t cmd_flow_director_flexmask_words_mask =
+ TOKEN_STRING_INITIALIZER(struct cmd_flow_director_flex_mask_result,
+ words_mask, "words_mask");
+cmdline_parse_token_num_t cmd_flow_director_flexmask_words =
+ TOKEN_NUM_INITIALIZER(struct cmd_flow_director_flex_mask_result,
+ words, UINT8);
+cmdline_parse_token_string_t cmd_flow_director_flexmask_word_mask_list =
+ TOKEN_STRING_INITIALIZER(struct cmd_flow_director_flex_mask_result,
+ word_mask_list, NULL);
+
+cmdline_parse_inst_t cmd_set_flow_director_flex_mask = {
+ .f = cmd_flow_director_flex_mask_parsed,
+ .data = NULL,
+ .help_str = "set flow director's flex mask on NIC",
+ .tokens = {
+ (void *)&cmd_flow_director_flexmask,
+ (void *)&cmd_flow_director_flexmask_port_id,
+ (void *)&cmd_flow_director_flexmask_flow,
+ (void *)&cmd_flow_director_flexmask_flow_type,
+ (void *)&cmd_flow_director_flexmask_words_mask,
+ (void *)&cmd_flow_director_flexmask_words,
+ (void *)&cmd_flow_director_flexmask_word_mask_list,
+ NULL,
+ },
+};
+
/* *** deal with flow director flexible payload configuration *** */
struct cmd_flow_director_flexpayload_result {
cmdline_fixed_string_t flow_director_flexpayload;
@@ -8400,6 +8572,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_mask,
(cmdline_parse_inst_t *)&cmd_set_flow_director_flex_payload,
NULL,
};