2
0
mirror of https://github.com/openvswitch/ovs synced 2025-09-02 15:25:22 +00:00

netdev-offload-dpdk: Support offload of set MAC actions.

Signed-off-by: Eli Britstein <elibr@mellanox.com>
Reviewed-by: Oz Shlomo <ozsh@mellanox.com>
Signed-off-by: Ilya Maximets <i.maximets@ovn.org>
This commit is contained in:
Eli Britstein
2020-01-09 07:46:53 +00:00
committed by Ilya Maximets
parent abb288c00a
commit ae32e08d63
3 changed files with 102 additions and 1 deletions

View File

@@ -392,6 +392,7 @@ Supported actions for hardware offload are:
- Output. - Output.
- Drop. - Drop.
- Modification of Ethernet (mod_dl_src/mod_dl_dst).
Further Reading Further Reading
--------------- ---------------

3
NEWS
View File

@@ -34,7 +34,8 @@ Post-v2.12.0
interval is increased to 60 seconds for the connection to the interval is increased to 60 seconds for the connection to the
replication server. This value is configurable with the unixctl replication server. This value is configurable with the unixctl
command - ovsdb-server/set-active-ovsdb-server-probe-interval. command - ovsdb-server/set-active-ovsdb-server-probe-interval.
* Add hardware offload support for output and drop actions (experimental). * Add hardware offload support for output, drop and set MAC actions
(experimental).
- 'ovs-appctl dpctl/dump-flows' can now show offloaded=partial for - 'ovs-appctl dpctl/dump-flows' can now show offloaded=partial for
partially offloaded flows, dp:dpdk for fully offloaded by dpdk, and partially offloaded flows, dp:dpdk for fully offloaded by dpdk, and
type filter supports new filters: "dpdk" and "partially-offloaded". type filter supports new filters: "dpdk" and "partially-offloaded".

View File

@@ -369,6 +369,21 @@ dump_flow_action(struct ds *s, const struct rte_flow_action *actions)
} }
} else if (actions->type == RTE_FLOW_ACTION_TYPE_DROP) { } else if (actions->type == RTE_FLOW_ACTION_TYPE_DROP) {
ds_put_cstr(s, "rte flow drop action\n"); ds_put_cstr(s, "rte flow drop action\n");
} else if (actions->type == RTE_FLOW_ACTION_TYPE_SET_MAC_SRC ||
actions->type == RTE_FLOW_ACTION_TYPE_SET_MAC_DST) {
const struct rte_flow_action_set_mac *set_mac = actions->conf;
char *dirstr = actions->type == RTE_FLOW_ACTION_TYPE_SET_MAC_DST
? "dst" : "src";
ds_put_format(s, "rte flow set-mac-%s action:\n", dirstr);
if (set_mac) {
ds_put_format(s,
" Set-mac-%s: "ETH_ADDR_FMT"\n", dirstr,
ETH_ADDR_BYTES_ARGS(set_mac->mac_addr));
} else {
ds_put_format(s, " Set-mac-%s = null\n", dirstr);
}
} else { } else {
ds_put_format(s, "unknown rte flow action (%d)\n", actions->type); ds_put_format(s, "unknown rte flow action (%d)\n", actions->type);
} }
@@ -797,6 +812,80 @@ add_output_action(struct netdev *netdev,
return ret; return ret;
} }
static int
add_set_flow_action__(struct flow_actions *actions,
const void *value, void *mask,
const size_t size, const int attr)
{
void *spec;
if (mask) {
/* DPDK does not support partially masked set actions. In such
* case, fail the offload.
*/
if (is_all_zeros(mask, size)) {
return 0;
}
if (!is_all_ones(mask, size)) {
VLOG_DBG_RL(&rl, "Partial mask is not supported");
return -1;
}
}
spec = xzalloc(size);
memcpy(spec, value, size);
add_flow_action(actions, attr, spec);
/* Clear used mask for later checking. */
if (mask) {
memset(mask, 0, size);
}
return 0;
}
BUILD_ASSERT_DECL(sizeof(struct rte_flow_action_set_mac) ==
MEMBER_SIZEOF(struct ovs_key_ethernet, eth_src));
BUILD_ASSERT_DECL(sizeof(struct rte_flow_action_set_mac) ==
MEMBER_SIZEOF(struct ovs_key_ethernet, eth_dst));
static int
parse_set_actions(struct flow_actions *actions,
const struct nlattr *set_actions,
const size_t set_actions_len,
bool masked)
{
const struct nlattr *sa;
unsigned int sleft;
#define add_set_flow_action(field, type) \
if (add_set_flow_action__(actions, &key->field, \
mask ? CONST_CAST(void *, &mask->field) : NULL, \
sizeof key->field, type)) { \
return -1; \
}
NL_ATTR_FOR_EACH_UNSAFE (sa, sleft, set_actions, set_actions_len) {
if (nl_attr_type(sa) == OVS_KEY_ATTR_ETHERNET) {
const struct ovs_key_ethernet *key = nl_attr_get(sa);
const struct ovs_key_ethernet *mask = masked ? key + 1 : NULL;
add_set_flow_action(eth_src, RTE_FLOW_ACTION_TYPE_SET_MAC_SRC);
add_set_flow_action(eth_dst, RTE_FLOW_ACTION_TYPE_SET_MAC_DST);
if (mask && !is_all_zeros(mask, sizeof *mask)) {
VLOG_DBG_RL(&rl, "Unsupported ETHERNET set action");
return -1;
}
} else {
VLOG_DBG_RL(&rl,
"Unsupported set action type %d", nl_attr_type(sa));
return -1;
}
}
return 0;
}
static int static int
parse_flow_actions(struct netdev *netdev, parse_flow_actions(struct netdev *netdev,
struct flow_actions *actions, struct flow_actions *actions,
@@ -815,6 +904,16 @@ parse_flow_actions(struct netdev *netdev,
} }
} else if (nl_attr_type(nla) == OVS_ACTION_ATTR_DROP) { } else if (nl_attr_type(nla) == OVS_ACTION_ATTR_DROP) {
add_flow_action(actions, RTE_FLOW_ACTION_TYPE_DROP, NULL); add_flow_action(actions, RTE_FLOW_ACTION_TYPE_DROP, NULL);
} else if (nl_attr_type(nla) == OVS_ACTION_ATTR_SET ||
nl_attr_type(nla) == OVS_ACTION_ATTR_SET_MASKED) {
const struct nlattr *set_actions = nl_attr_get(nla);
const size_t set_actions_len = nl_attr_get_size(nla);
bool masked = nl_attr_type(nla) == OVS_ACTION_ATTR_SET_MASKED;
if (parse_set_actions(actions, set_actions, set_actions_len,
masked)) {
return -1;
}
} else { } else {
VLOG_DBG_RL(&rl, "Unsupported action type %d", nl_attr_type(nla)); VLOG_DBG_RL(&rl, "Unsupported action type %d", nl_attr_type(nla));
return -1; return -1;