app/testpmd: add commands for conntrack

The command line for testing connection tracking is added. To create
a conntrack object, 3 parts are needed.
  set conntrack com peer ...
  set conntrack orig scale ...
  set conntrack rply scale ...
This will create a full conntrack action structure for the indirect
action. After the indirect action handle of "conntrack" created, it
could be used in the flow creation. Before updating, the same
structure is also needed together with the update command
"conntrack_update" to update the "dir" or "ctx".

After the flow with conntrack action created, the packet should jump
to the next flow for the result checking with conntrack item. The
state is defined with bits and a valid combination could be
supported.

Signed-off-by: Bing Zhao <bingz@nvidia.com>
Acked-by: Ori Kam <orika@nvidia.com>
This commit is contained in:
Bing Zhao 2021-04-20 01:51:31 +08:00 committed by Ferruh Yigit
parent 9847fd125d
commit 4d07cbefe3
6 changed files with 551 additions and 1 deletions

View File

@ -13621,6 +13621,359 @@ cmdline_parse_inst_t cmd_set_mplsoudp_decap_with_vlan = {
},
};
/** Set connection tracking object common details */
struct cmd_set_conntrack_common_result {
cmdline_fixed_string_t set;
cmdline_fixed_string_t conntrack;
cmdline_fixed_string_t common;
cmdline_fixed_string_t peer;
cmdline_fixed_string_t is_orig;
cmdline_fixed_string_t enable;
cmdline_fixed_string_t live;
cmdline_fixed_string_t sack;
cmdline_fixed_string_t cack;
cmdline_fixed_string_t last_dir;
cmdline_fixed_string_t liberal;
cmdline_fixed_string_t state;
cmdline_fixed_string_t max_ack_win;
cmdline_fixed_string_t retrans;
cmdline_fixed_string_t last_win;
cmdline_fixed_string_t last_seq;
cmdline_fixed_string_t last_ack;
cmdline_fixed_string_t last_end;
cmdline_fixed_string_t last_index;
uint8_t stat;
uint8_t factor;
uint16_t peer_port;
uint32_t is_original;
uint32_t en;
uint32_t is_live;
uint32_t s_ack;
uint32_t c_ack;
uint32_t ld;
uint32_t lb;
uint8_t re_num;
uint8_t li;
uint16_t lw;
uint32_t ls;
uint32_t la;
uint32_t le;
};
cmdline_parse_token_string_t cmd_set_conntrack_set =
TOKEN_STRING_INITIALIZER(struct cmd_set_conntrack_common_result,
set, "set");
cmdline_parse_token_string_t cmd_set_conntrack_conntrack =
TOKEN_STRING_INITIALIZER(struct cmd_set_conntrack_common_result,
conntrack, "conntrack");
cmdline_parse_token_string_t cmd_set_conntrack_common_com =
TOKEN_STRING_INITIALIZER(struct cmd_set_conntrack_common_result,
common, "com");
cmdline_parse_token_string_t cmd_set_conntrack_common_peer =
TOKEN_STRING_INITIALIZER(struct cmd_set_conntrack_common_result,
peer, "peer");
cmdline_parse_token_num_t cmd_set_conntrack_common_peer_value =
TOKEN_NUM_INITIALIZER(struct cmd_set_conntrack_common_result,
peer_port, RTE_UINT16);
cmdline_parse_token_string_t cmd_set_conntrack_common_is_orig =
TOKEN_STRING_INITIALIZER(struct cmd_set_conntrack_common_result,
is_orig, "is_orig");
cmdline_parse_token_num_t cmd_set_conntrack_common_is_orig_value =
TOKEN_NUM_INITIALIZER(struct cmd_set_conntrack_common_result,
is_original, RTE_UINT32);
cmdline_parse_token_string_t cmd_set_conntrack_common_enable =
TOKEN_STRING_INITIALIZER(struct cmd_set_conntrack_common_result,
enable, "enable");
cmdline_parse_token_num_t cmd_set_conntrack_common_enable_value =
TOKEN_NUM_INITIALIZER(struct cmd_set_conntrack_common_result,
en, RTE_UINT32);
cmdline_parse_token_string_t cmd_set_conntrack_common_live =
TOKEN_STRING_INITIALIZER(struct cmd_set_conntrack_common_result,
live, "live");
cmdline_parse_token_num_t cmd_set_conntrack_common_live_value =
TOKEN_NUM_INITIALIZER(struct cmd_set_conntrack_common_result,
is_live, RTE_UINT32);
cmdline_parse_token_string_t cmd_set_conntrack_common_sack =
TOKEN_STRING_INITIALIZER(struct cmd_set_conntrack_common_result,
sack, "sack");
cmdline_parse_token_num_t cmd_set_conntrack_common_sack_value =
TOKEN_NUM_INITIALIZER(struct cmd_set_conntrack_common_result,
s_ack, RTE_UINT32);
cmdline_parse_token_string_t cmd_set_conntrack_common_cack =
TOKEN_STRING_INITIALIZER(struct cmd_set_conntrack_common_result,
cack, "cack");
cmdline_parse_token_num_t cmd_set_conntrack_common_cack_value =
TOKEN_NUM_INITIALIZER(struct cmd_set_conntrack_common_result,
c_ack, RTE_UINT32);
cmdline_parse_token_string_t cmd_set_conntrack_common_last_dir =
TOKEN_STRING_INITIALIZER(struct cmd_set_conntrack_common_result,
last_dir, "last_dir");
cmdline_parse_token_num_t cmd_set_conntrack_common_last_dir_value =
TOKEN_NUM_INITIALIZER(struct cmd_set_conntrack_common_result,
ld, RTE_UINT32);
cmdline_parse_token_string_t cmd_set_conntrack_common_liberal =
TOKEN_STRING_INITIALIZER(struct cmd_set_conntrack_common_result,
liberal, "liberal");
cmdline_parse_token_num_t cmd_set_conntrack_common_liberal_value =
TOKEN_NUM_INITIALIZER(struct cmd_set_conntrack_common_result,
lb, RTE_UINT32);
cmdline_parse_token_string_t cmd_set_conntrack_common_state =
TOKEN_STRING_INITIALIZER(struct cmd_set_conntrack_common_result,
state, "state");
cmdline_parse_token_num_t cmd_set_conntrack_common_state_value =
TOKEN_NUM_INITIALIZER(struct cmd_set_conntrack_common_result,
stat, RTE_UINT8);
cmdline_parse_token_string_t cmd_set_conntrack_common_max_ackwin =
TOKEN_STRING_INITIALIZER(struct cmd_set_conntrack_common_result,
max_ack_win, "max_ack_win");
cmdline_parse_token_num_t cmd_set_conntrack_common_max_ackwin_value =
TOKEN_NUM_INITIALIZER(struct cmd_set_conntrack_common_result,
factor, RTE_UINT8);
cmdline_parse_token_string_t cmd_set_conntrack_common_retrans =
TOKEN_STRING_INITIALIZER(struct cmd_set_conntrack_common_result,
retrans, "r_lim");
cmdline_parse_token_num_t cmd_set_conntrack_common_retrans_value =
TOKEN_NUM_INITIALIZER(struct cmd_set_conntrack_common_result,
re_num, RTE_UINT8);
cmdline_parse_token_string_t cmd_set_conntrack_common_last_win =
TOKEN_STRING_INITIALIZER(struct cmd_set_conntrack_common_result,
last_win, "last_win");
cmdline_parse_token_num_t cmd_set_conntrack_common_last_win_value =
TOKEN_NUM_INITIALIZER(struct cmd_set_conntrack_common_result,
lw, RTE_UINT16);
cmdline_parse_token_string_t cmd_set_conntrack_common_last_seq =
TOKEN_STRING_INITIALIZER(struct cmd_set_conntrack_common_result,
last_seq, "last_seq");
cmdline_parse_token_num_t cmd_set_conntrack_common_last_seq_value =
TOKEN_NUM_INITIALIZER(struct cmd_set_conntrack_common_result,
ls, RTE_UINT32);
cmdline_parse_token_string_t cmd_set_conntrack_common_last_ack =
TOKEN_STRING_INITIALIZER(struct cmd_set_conntrack_common_result,
last_ack, "last_ack");
cmdline_parse_token_num_t cmd_set_conntrack_common_last_ack_value =
TOKEN_NUM_INITIALIZER(struct cmd_set_conntrack_common_result,
la, RTE_UINT32);
cmdline_parse_token_string_t cmd_set_conntrack_common_last_end =
TOKEN_STRING_INITIALIZER(struct cmd_set_conntrack_common_result,
last_end, "last_end");
cmdline_parse_token_num_t cmd_set_conntrack_common_last_end_value =
TOKEN_NUM_INITIALIZER(struct cmd_set_conntrack_common_result,
le, RTE_UINT32);
cmdline_parse_token_string_t cmd_set_conntrack_common_last_index =
TOKEN_STRING_INITIALIZER(struct cmd_set_conntrack_common_result,
last_index, "last_index");
cmdline_parse_token_num_t cmd_set_conntrack_common_last_index_value =
TOKEN_NUM_INITIALIZER(struct cmd_set_conntrack_common_result,
li, RTE_UINT8);
static void cmd_set_conntrack_common_parsed(void *parsed_result,
__rte_unused struct cmdline *cl,
__rte_unused void *data)
{
struct cmd_set_conntrack_common_result *res = parsed_result;
/* No need to swap to big endian. */
conntrack_context.peer_port = res->peer_port;
conntrack_context.is_original_dir = res->is_original;
conntrack_context.enable = res->en;
conntrack_context.live_connection = res->is_live;
conntrack_context.selective_ack = res->s_ack;
conntrack_context.challenge_ack_passed = res->c_ack;
conntrack_context.last_direction = res->ld;
conntrack_context.liberal_mode = res->lb;
conntrack_context.state = (enum rte_flow_conntrack_state)res->stat;
conntrack_context.max_ack_window = res->factor;
conntrack_context.retransmission_limit = res->re_num;
conntrack_context.last_window = res->lw;
conntrack_context.last_index =
(enum rte_flow_conntrack_tcp_last_index)res->li;
conntrack_context.last_seq = res->ls;
conntrack_context.last_ack = res->la;
conntrack_context.last_end = res->le;
}
cmdline_parse_inst_t cmd_set_conntrack_common = {
.f = cmd_set_conntrack_common_parsed,
.data = NULL,
.help_str = "set conntrack com peer <port_id> is_orig <dir> enable <en>"
" live <ack_seen> sack <en> cack <passed> last_dir <dir>"
" liberal <en> state <s> max_ack_win <factor> r_lim <num>"
" last_win <win> last_seq <seq> last_ack <ack> last_end <end>"
" last_index <flag>",
.tokens = {
(void *)&cmd_set_conntrack_set,
(void *)&cmd_set_conntrack_conntrack,
(void *)&cmd_set_conntrack_common_com,
(void *)&cmd_set_conntrack_common_peer,
(void *)&cmd_set_conntrack_common_peer_value,
(void *)&cmd_set_conntrack_common_is_orig,
(void *)&cmd_set_conntrack_common_is_orig_value,
(void *)&cmd_set_conntrack_common_enable,
(void *)&cmd_set_conntrack_common_enable_value,
(void *)&cmd_set_conntrack_common_live,
(void *)&cmd_set_conntrack_common_live_value,
(void *)&cmd_set_conntrack_common_sack,
(void *)&cmd_set_conntrack_common_sack_value,
(void *)&cmd_set_conntrack_common_cack,
(void *)&cmd_set_conntrack_common_cack_value,
(void *)&cmd_set_conntrack_common_last_dir,
(void *)&cmd_set_conntrack_common_last_dir_value,
(void *)&cmd_set_conntrack_common_liberal,
(void *)&cmd_set_conntrack_common_liberal_value,
(void *)&cmd_set_conntrack_common_state,
(void *)&cmd_set_conntrack_common_state_value,
(void *)&cmd_set_conntrack_common_max_ackwin,
(void *)&cmd_set_conntrack_common_max_ackwin_value,
(void *)&cmd_set_conntrack_common_retrans,
(void *)&cmd_set_conntrack_common_retrans_value,
(void *)&cmd_set_conntrack_common_last_win,
(void *)&cmd_set_conntrack_common_last_win_value,
(void *)&cmd_set_conntrack_common_last_seq,
(void *)&cmd_set_conntrack_common_last_seq_value,
(void *)&cmd_set_conntrack_common_last_ack,
(void *)&cmd_set_conntrack_common_last_ack_value,
(void *)&cmd_set_conntrack_common_last_end,
(void *)&cmd_set_conntrack_common_last_end_value,
(void *)&cmd_set_conntrack_common_last_index,
(void *)&cmd_set_conntrack_common_last_index_value,
NULL,
},
};
/** Set connection tracking object both directions' details */
struct cmd_set_conntrack_dir_result {
cmdline_fixed_string_t set;
cmdline_fixed_string_t conntrack;
cmdline_fixed_string_t dir;
cmdline_fixed_string_t scale;
cmdline_fixed_string_t fin;
cmdline_fixed_string_t ack_seen;
cmdline_fixed_string_t unack;
cmdline_fixed_string_t sent_end;
cmdline_fixed_string_t reply_end;
cmdline_fixed_string_t max_win;
cmdline_fixed_string_t max_ack;
uint32_t factor;
uint32_t f;
uint32_t as;
uint32_t un;
uint32_t se;
uint32_t re;
uint32_t mw;
uint32_t ma;
};
cmdline_parse_token_string_t cmd_set_conntrack_dir_set =
TOKEN_STRING_INITIALIZER(struct cmd_set_conntrack_dir_result,
set, "set");
cmdline_parse_token_string_t cmd_set_conntrack_dir_conntrack =
TOKEN_STRING_INITIALIZER(struct cmd_set_conntrack_dir_result,
conntrack, "conntrack");
cmdline_parse_token_string_t cmd_set_conntrack_dir_dir =
TOKEN_STRING_INITIALIZER(struct cmd_set_conntrack_dir_result,
dir, "orig#rply");
cmdline_parse_token_string_t cmd_set_conntrack_dir_scale =
TOKEN_STRING_INITIALIZER(struct cmd_set_conntrack_dir_result,
scale, "scale");
cmdline_parse_token_num_t cmd_set_conntrack_dir_scale_value =
TOKEN_NUM_INITIALIZER(struct cmd_set_conntrack_dir_result,
factor, RTE_UINT32);
cmdline_parse_token_string_t cmd_set_conntrack_dir_fin =
TOKEN_STRING_INITIALIZER(struct cmd_set_conntrack_dir_result,
fin, "fin");
cmdline_parse_token_num_t cmd_set_conntrack_dir_fin_value =
TOKEN_NUM_INITIALIZER(struct cmd_set_conntrack_dir_result,
f, RTE_UINT32);
cmdline_parse_token_string_t cmd_set_conntrack_dir_ack =
TOKEN_STRING_INITIALIZER(struct cmd_set_conntrack_dir_result,
ack_seen, "acked");
cmdline_parse_token_num_t cmd_set_conntrack_dir_ack_value =
TOKEN_NUM_INITIALIZER(struct cmd_set_conntrack_dir_result,
as, RTE_UINT32);
cmdline_parse_token_string_t cmd_set_conntrack_dir_unack_data =
TOKEN_STRING_INITIALIZER(struct cmd_set_conntrack_dir_result,
unack, "unack_data");
cmdline_parse_token_num_t cmd_set_conntrack_dir_unack_data_value =
TOKEN_NUM_INITIALIZER(struct cmd_set_conntrack_dir_result,
un, RTE_UINT32);
cmdline_parse_token_string_t cmd_set_conntrack_dir_sent_end =
TOKEN_STRING_INITIALIZER(struct cmd_set_conntrack_dir_result,
sent_end, "sent_end");
cmdline_parse_token_num_t cmd_set_conntrack_dir_sent_end_value =
TOKEN_NUM_INITIALIZER(struct cmd_set_conntrack_dir_result,
se, RTE_UINT32);
cmdline_parse_token_string_t cmd_set_conntrack_dir_reply_end =
TOKEN_STRING_INITIALIZER(struct cmd_set_conntrack_dir_result,
reply_end, "reply_end");
cmdline_parse_token_num_t cmd_set_conntrack_dir_reply_end_value =
TOKEN_NUM_INITIALIZER(struct cmd_set_conntrack_dir_result,
re, RTE_UINT32);
cmdline_parse_token_string_t cmd_set_conntrack_dir_max_win =
TOKEN_STRING_INITIALIZER(struct cmd_set_conntrack_dir_result,
max_win, "max_win");
cmdline_parse_token_num_t cmd_set_conntrack_dir_max_win_value =
TOKEN_NUM_INITIALIZER(struct cmd_set_conntrack_dir_result,
mw, RTE_UINT32);
cmdline_parse_token_string_t cmd_set_conntrack_dir_max_ack =
TOKEN_STRING_INITIALIZER(struct cmd_set_conntrack_dir_result,
max_ack, "max_ack");
cmdline_parse_token_num_t cmd_set_conntrack_dir_max_ack_value =
TOKEN_NUM_INITIALIZER(struct cmd_set_conntrack_dir_result,
ma, RTE_UINT32);
static void cmd_set_conntrack_dir_parsed(void *parsed_result,
__rte_unused struct cmdline *cl,
__rte_unused void *data)
{
struct cmd_set_conntrack_dir_result *res = parsed_result;
struct rte_flow_tcp_dir_param *dir = NULL;
if (strcmp(res->dir, "orig") == 0)
dir = &conntrack_context.original_dir;
else if (strcmp(res->dir, "rply") == 0)
dir = &conntrack_context.reply_dir;
else
return;
dir->scale = res->factor;
dir->close_initiated = res->f;
dir->last_ack_seen = res->as;
dir->data_unacked = res->un;
dir->sent_end = res->se;
dir->reply_end = res->re;
dir->max_ack = res->ma;
dir->max_win = res->mw;
}
cmdline_parse_inst_t cmd_set_conntrack_dir = {
.f = cmd_set_conntrack_dir_parsed,
.data = NULL,
.help_str = "set conntrack orig|rply scale <factor> fin <sent>"
" acked <seen> unack_data <unack> sent_end <sent>"
" reply_end <reply> max_win <win> max_ack <ack>",
.tokens = {
(void *)&cmd_set_conntrack_set,
(void *)&cmd_set_conntrack_conntrack,
(void *)&cmd_set_conntrack_dir_dir,
(void *)&cmd_set_conntrack_dir_scale,
(void *)&cmd_set_conntrack_dir_scale_value,
(void *)&cmd_set_conntrack_dir_fin,
(void *)&cmd_set_conntrack_dir_fin_value,
(void *)&cmd_set_conntrack_dir_ack,
(void *)&cmd_set_conntrack_dir_ack_value,
(void *)&cmd_set_conntrack_dir_unack_data,
(void *)&cmd_set_conntrack_dir_unack_data_value,
(void *)&cmd_set_conntrack_dir_sent_end,
(void *)&cmd_set_conntrack_dir_sent_end_value,
(void *)&cmd_set_conntrack_dir_reply_end,
(void *)&cmd_set_conntrack_dir_reply_end_value,
(void *)&cmd_set_conntrack_dir_max_win,
(void *)&cmd_set_conntrack_dir_max_win_value,
(void *)&cmd_set_conntrack_dir_max_ack,
(void *)&cmd_set_conntrack_dir_max_ack_value,
NULL,
},
};
/* Strict link priority scheduling mode setting */
static void
cmd_strict_link_prio_parsed(
@ -17120,6 +17473,8 @@ cmdline_parse_ctx_t main_ctx[] = {
(cmdline_parse_inst_t *)&cmd_set_mplsoudp_encap_with_vlan,
(cmdline_parse_inst_t *)&cmd_set_mplsoudp_decap,
(cmdline_parse_inst_t *)&cmd_set_mplsoudp_decap_with_vlan,
(cmdline_parse_inst_t *)&cmd_set_conntrack_common,
(cmdline_parse_inst_t *)&cmd_set_conntrack_dir,
(cmdline_parse_inst_t *)&cmd_ddp_add,
(cmdline_parse_inst_t *)&cmd_ddp_del,
(cmdline_parse_inst_t *)&cmd_ddp_get_list,

View File

@ -298,6 +298,7 @@ enum index {
ITEM_INTEGRITY,
ITEM_INTEGRITY_LEVEL,
ITEM_INTEGRITY_VALUE,
ITEM_CONNTRACK,
/* Validate/create actions. */
ACTIONS,
@ -436,6 +437,10 @@ enum index {
ACTION_MODIFY_FIELD_SRC_OFFSET,
ACTION_MODIFY_FIELD_SRC_VALUE,
ACTION_MODIFY_FIELD_WIDTH,
ACTION_CONNTRACK,
ACTION_CONNTRACK_UPDATE,
ACTION_CONNTRACK_UPDATE_DIR,
ACTION_CONNTRACK_UPDATE_CTX,
};
/** Maximum size for pattern in struct rte_flow_item_raw. */
@ -574,6 +579,8 @@ struct mplsoudp_encap_conf mplsoudp_encap_conf;
struct mplsoudp_decap_conf mplsoudp_decap_conf;
struct rte_flow_action_conntrack conntrack_context;
#define ACTION_SAMPLE_ACTIONS_NUM 10
#define RAW_SAMPLE_CONFS_MAX_NUM 8
/** Storage for struct rte_flow_action_sample including external data. */
@ -974,6 +981,7 @@ static const enum index next_item[] = {
ITEM_ECPRI,
ITEM_GENEVE_OPT,
ITEM_INTEGRITY,
ITEM_CONNTRACK,
END_SET,
ZERO,
};
@ -1403,6 +1411,8 @@ static const enum index next_action[] = {
ACTION_SAMPLE,
ACTION_INDIRECT,
ACTION_MODIFY_FIELD,
ACTION_CONNTRACK,
ACTION_CONNTRACK_UPDATE,
ZERO,
};
@ -1671,6 +1681,13 @@ static const enum index action_modify_field_src[] = {
ZERO,
};
static const enum index action_update_conntrack[] = {
ACTION_CONNTRACK_UPDATE_DIR,
ACTION_CONNTRACK_UPDATE_CTX,
ACTION_NEXT,
ZERO,
};
static int parse_set_raw_encap_decap(struct context *, const struct token *,
const char *, unsigned int,
void *, unsigned int);
@ -1761,6 +1778,10 @@ static int
parse_vc_modify_field_id(struct context *ctx, const struct token *token,
const char *str, unsigned int len, void *buf,
unsigned int size);
static int
parse_vc_action_conntrack_update(struct context *ctx, const struct token *token,
const char *str, unsigned int len, void *buf,
unsigned int size);
static int parse_destroy(struct context *, const struct token *,
const char *, unsigned int,
void *, unsigned int);
@ -3458,6 +3479,13 @@ static const struct token token_list[] = {
item_param),
.args = ARGS(ARGS_ENTRY(struct rte_flow_item_integrity, value)),
},
[ITEM_CONNTRACK] = {
.name = "conntrack",
.help = "conntrack state",
.next = NEXT(NEXT_ENTRY(ITEM_NEXT), NEXT_ENTRY(UNSIGNED),
item_param),
.args = ARGS(ARGS_ENTRY(struct rte_flow_item_conntrack, flags)),
},
/* Validate/create actions. */
[ACTIONS] = {
.name = "actions",
@ -4556,6 +4584,34 @@ static const struct token token_list[] = {
.call = parse_vc_action_sample_index,
.comp = comp_set_sample_index,
},
[ACTION_CONNTRACK] = {
.name = "conntrack",
.help = "create a conntrack object",
.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
.priv = PRIV_ACTION(CONNTRACK,
sizeof(struct rte_flow_action_conntrack)),
.call = parse_vc,
},
[ACTION_CONNTRACK_UPDATE] = {
.name = "conntrack_update",
.help = "update a conntrack object",
.next = NEXT(action_update_conntrack),
.priv = PRIV_ACTION(CONNTRACK,
sizeof(struct rte_flow_modify_conntrack)),
.call = parse_vc,
},
[ACTION_CONNTRACK_UPDATE_DIR] = {
.name = "dir",
.help = "update a conntrack object direction",
.next = NEXT(action_update_conntrack),
.call = parse_vc_action_conntrack_update,
},
[ACTION_CONNTRACK_UPDATE_CTX] = {
.name = "ctx",
.help = "update a conntrack object context",
.next = NEXT(action_update_conntrack),
.call = parse_vc_action_conntrack_update,
},
/* Indirect action destroy arguments. */
[INDIRECT_ACTION_DESTROY_ID] = {
.name = "action_id",
@ -6362,6 +6418,42 @@ parse_vc_modify_field_id(struct context *ctx, const struct token *token,
return len;
}
/** Parse the conntrack update, not a rte_flow_action. */
static int
parse_vc_action_conntrack_update(struct context *ctx, const struct token *token,
const char *str, unsigned int len, void *buf,
unsigned int size)
{
struct buffer *out = buf;
struct rte_flow_modify_conntrack *ct_modify = NULL;
(void)size;
if (ctx->curr != ACTION_CONNTRACK_UPDATE_CTX &&
ctx->curr != ACTION_CONNTRACK_UPDATE_DIR)
return -1;
/* Token name must match. */
if (parse_default(ctx, token, str, len, NULL, 0) < 0)
return -1;
ct_modify = (struct rte_flow_modify_conntrack *)out->args.vc.data;
/* Nothing else to do if there is no buffer. */
if (!out)
return len;
if (ctx->curr == ACTION_CONNTRACK_UPDATE_DIR) {
ct_modify->new_ct.is_original_dir =
conntrack_context.is_original_dir;
ct_modify->direction = 1;
} else {
uint32_t old_dir;
old_dir = ct_modify->new_ct.is_original_dir;
memcpy(&ct_modify->new_ct, &conntrack_context,
sizeof(conntrack_context));
ct_modify->new_ct.is_original_dir = old_dir;
ct_modify->state = 1;
}
return len;
}
/** Parse tokens for destroy command. */
static int
parse_destroy(struct context *ctx, const struct token *token,

View File

@ -1485,6 +1485,11 @@ port_action_handle_create(portid_t port_id, uint32_t id,
pia->age_type = ACTION_AGE_CONTEXT_TYPE_INDIRECT_ACTION;
age->context = &pia->age_type;
} else if (action->type == RTE_FLOW_ACTION_TYPE_CONNTRACK) {
struct rte_flow_action_conntrack *ct =
(struct rte_flow_action_conntrack *)(uintptr_t)(action->conf);
memcpy(ct, &conntrack_context, sizeof(*ct));
}
/* Poisoning to make sure PMDs update it in case of error. */
memset(&error, 0x22, sizeof(error));
@ -1566,11 +1571,24 @@ port_action_handle_update(portid_t port_id, uint32_t id,
{
struct rte_flow_error error;
struct rte_flow_action_handle *action_handle;
struct port_indirect_action *pia;
const void *update;
action_handle = port_action_handle_get_by_id(port_id, id);
if (!action_handle)
return -EINVAL;
if (rte_flow_action_handle_update(port_id, action_handle, action,
pia = action_get_by_id(port_id, id);
if (!pia)
return -EINVAL;
switch (pia->type) {
case RTE_FLOW_ACTION_TYPE_CONNTRACK:
update = action->conf;
break;
default:
update = action;
break;
}
if (rte_flow_action_handle_update(port_id, action_handle, update,
&error)) {
return port_flow_complain(&error);
}
@ -1623,6 +1641,51 @@ port_action_handle_query(portid_t port_id, uint32_t id)
}
data = NULL;
break;
case RTE_FLOW_ACTION_TYPE_CONNTRACK:
if (!ret) {
struct rte_flow_action_conntrack *ct = data;
printf("Conntrack Context:\n"
" Peer: %u, Flow dir: %s, Enable: %u\n"
" Live: %u, SACK: %u, CACK: %u\n"
" Packet dir: %s, Liberal: %u, State: %u\n"
" Factor: %u, Retrans: %u, TCP flags: %u\n"
" Last Seq: %u, Last ACK: %u\n"
" Last Win: %u, Last End: %u\n",
ct->peer_port,
ct->is_original_dir ? "Original" : "Reply",
ct->enable, ct->live_connection,
ct->selective_ack, ct->challenge_ack_passed,
ct->last_direction ? "Original" : "Reply",
ct->liberal_mode, ct->state,
ct->max_ack_window, ct->retransmission_limit,
ct->last_index, ct->last_seq, ct->last_ack,
ct->last_window, ct->last_end);
printf(" Original Dir:\n"
" scale: %u, fin: %u, ack seen: %u\n"
" unacked data: %u\n Sent end: %u,"
" Reply end: %u, Max win: %u, Max ACK: %u\n",
ct->original_dir.scale,
ct->original_dir.close_initiated,
ct->original_dir.last_ack_seen,
ct->original_dir.data_unacked,
ct->original_dir.sent_end,
ct->original_dir.reply_end,
ct->original_dir.max_win,
ct->original_dir.max_ack);
printf(" Reply Dir:\n"
" scale: %u, fin: %u, ack seen: %u\n"
" unacked data: %u\n Sent end: %u,"
" Reply end: %u, Max win: %u, Max ACK: %u\n",
ct->reply_dir.scale,
ct->reply_dir.close_initiated,
ct->reply_dir.last_ack_seen,
ct->reply_dir.data_unacked,
ct->reply_dir.sent_end, ct->reply_dir.reply_end,
ct->reply_dir.max_win, ct->reply_dir.max_ack);
}
data = NULL;
break;
default:
printf("Indirect action %u (type: %d) on port %u doesn't"
" support query\n", id, pia->type, port_id);

View File

@ -630,6 +630,8 @@ extern struct mplsoudp_decap_conf mplsoudp_decap_conf;
extern enum rte_eth_rx_mq_mode rx_mq_mode;
extern struct rte_flow_action_conntrack conntrack_context;
static inline unsigned int
lcore_num(void)
{

View File

@ -233,6 +233,9 @@ New Features
``show port (port_id) rxq (queue_id) desc used count``
* Added command to dump internal representation information of single flow.
``flow dump (port_id) rule (rule_id)``
* Added commands to construct conntrack context and relevant indirect
action handle creation, update for conntrack action as well as conntrack
item matching.
* **Added support for the FIB lookup method in the l3fwd example app.**

View File

@ -3796,6 +3796,8 @@ This section lists supported pattern items and their attributes, if any.
- ``value {unsigned}``: A bitmask that specify what packet elements
must be matched for integrity.
- ``conntrack``: match conntrack state.
Actions list
^^^^^^^^^^^^
@ -4955,6 +4957,39 @@ General packet integrity is matched with the ``packet_ok`` bit 0.
testpmd> flow create 0 ingress pattern integrity value mask 1 value spec 0 / end actions queue index 0 / end
Sample conntrack rules
~~~~~~~~~~~~~~~~~~~~~~
Conntrack rules can be set by the following commands
Need to construct the connection context with provided information.
In the first table, create a flow rule by using conntrack action and jump to
the next table. In the next table, create a rule to check the state.
::
testpmd> set conntrack com peer 1 is_orig 1 enable 1 live 1 sack 1 cack 0
last_dir 0 liberal 0 state 1 max_ack_win 7 r_lim 5 last_win 510
last_seq 2632987379 last_ack 2532480967 last_end 2632987379
last_index 0x8
testpmd> set conntrack orig scale 7 fin 0 acked 1 unack_data 0
sent_end 2632987379 reply_end 2633016339 max_win 28960
max_ack 2632987379
testpmd> set conntrack rply scale 7 fin 0 acked 1 unack_data 0
sent_end 2532480967 reply_end 2532546247 max_win 65280
max_ack 2532480967
testpmd> flow indirect_action 0 create ingress action conntrack / end
testpmd> flow create 0 group 3 ingress pattern eth / ipv4 / tcp / end actions indirect 0 / jump group 5 / end
testpmd> flow create 0 group 5 ingress pattern eth / ipv4 / tcp / conntrack is 1 / end actions queue index 5 / end
Construct the conntrack again with only "is_orig" set to 0 (other fields are
ignored), then use "update" interface to update the direction. Create flow
rules like above for the peer port.
::
testpmd> flow indirect_action 0 update 0 action conntrack_update dir / end
BPF Functions
--------------