+ struct ds s_tnl;
};
struct flow_actions {
@@ -154,16 +160,20 @@ struct flow_actions {
static void
dump_flow_attr(struct ds *s, struct ds *s_extra,
const struct rte_flow_attr *attr,
+ struct flow_patterns *flow_patterns,
struct flow_actions *flow_actions)
{
if (flow_actions->num_of_tnl_actions) {
ds_clone(s_extra, &flow_actions->s_tnl);
+ } else if (flow_patterns->num_of_tnl_items) {
+ ds_clone(s_extra, &flow_patterns->s_tnl);
}
- ds_put_format(s, "%s%spriority %"PRIu32" group %"PRIu32" %s%s",
+ ds_put_format(s, "%s%spriority %"PRIu32" group %"PRIu32" %s%s%s",
attr->ingress ? "ingress " : "",
attr->egress ? "egress " : "", attr->priority,
attr->group,
attr->transfer ? "transfer " : "",
- flow_actions->num_of_tnl_actions ? "tunnel_set 1 " : "");
+ flow_actions->num_of_tnl_actions ? "tunnel_set 1 " : "",
+ flow_patterns->num_of_tnl_items ? "tunnel_match 1 " : "");
}
/* Adds one pattern item 'field' with the 'mask' to dynamic string 's' using
@@ -177,9 +187,18 @@ dump_flow_attr(struct ds *s, struct ds *s_extra,
}
static void
-dump_flow_pattern(struct ds *s, const struct rte_flow_item *item)
+dump_flow_pattern(struct ds *s,
+ struct flow_patterns *flow_patterns,
+ int pattern_index)
{
- if (item->type == RTE_FLOW_ITEM_TYPE_ETH) {
+ const struct rte_flow_item *item = &flow_patterns->items[pattern_index];
+
+ if (item->type == RTE_FLOW_ITEM_TYPE_END) {
+ ds_put_cstr(s, "end ");
+ } else if (flow_patterns->num_of_tnl_items &&
+ pattern_index < flow_patterns->num_of_tnl_items) {
+ return;
+ } else if (item->type == RTE_FLOW_ITEM_TYPE_ETH) {
const struct rte_flow_item_eth *eth_spec = item->spec;
const struct rte_flow_item_eth *eth_mask = item->mask;
@@ -569,19 +588,19 @@ dump_flow_action(struct ds *s, struct ds *s_extra,
static struct ds *
dump_flow(struct ds *s, struct ds *s_extra,
const struct rte_flow_attr *attr,
- const struct rte_flow_item *items,
+ struct flow_patterns *flow_patterns,
struct flow_actions *flow_actions)
{
int i;
if (attr) {
- dump_flow_attr(s, s_extra, attr, flow_actions);
+ dump_flow_attr(s, s_extra, attr, flow_patterns, flow_actions);
}
ds_put_cstr(s, "pattern ");
- while (items && items->type != RTE_FLOW_ITEM_TYPE_END) {
- dump_flow_pattern(s, items++);
+ for (i = 0; i < flow_patterns->cnt; i++) {
+ dump_flow_pattern(s, flow_patterns, i);
}
- ds_put_cstr(s, "end actions ");
+ ds_put_cstr(s, "actions ");
for (i = 0; i < flow_actions->cnt; i++) {
dump_flow_action(s, s_extra, flow_actions, i);
}
@@ -591,11 +610,12 @@ dump_flow(struct ds *s, struct ds *s_extra,
static struct rte_flow *
netdev_offload_dpdk_flow_create(struct netdev *netdev,
const struct rte_flow_attr *attr,
- const struct rte_flow_item *items,
+ struct flow_patterns *flow_patterns,
struct flow_actions *flow_actions,
struct rte_flow_error *error)
{
const struct rte_flow_action *actions = flow_actions->actions;
+ const struct rte_flow_item *items = flow_patterns->items;
struct ds s_extra = DS_EMPTY_INITIALIZER;
struct ds s = DS_EMPTY_INITIALIZER;
struct rte_flow *flow;
@@ -604,7 +624,7 @@ netdev_offload_dpdk_flow_create(struct netdev *netdev,
flow = netdev_dpdk_rte_flow_create(netdev, attr, items, actions, error);
if (flow) {
if (!VLOG_DROP_DBG(&rl)) {
- dump_flow(&s, &s_extra, attr, items, flow_actions);
+ dump_flow(&s, &s_extra, attr, flow_patterns, flow_actions);
extra_str = ds_cstr(&s_extra);
VLOG_DBG_RL(&rl, "%s: rte_flow 0x%"PRIxPTR" %s flow create %d
%s",
netdev_get_name(netdev), (intptr_t) flow, extra_str,
@@ -619,7 +639,7 @@ netdev_offload_dpdk_flow_create(struct netdev *netdev,
VLOG_RL(&rl, level, "%s: rte_flow creation failed: %d (%s).",
netdev_get_name(netdev), error->type, error->message);
if (!vlog_should_drop(&this_module, level, &rl)) {
- dump_flow(&s, &s_extra, attr, items, flow_actions);
+ dump_flow(&s, &s_extra, attr, flow_patterns, flow_actions);
extra_str = ds_cstr(&s_extra);
VLOG_RL(&rl, level, "%s: Failed flow: %s flow create %d %s",
netdev_get_name(netdev), extra_str,
@@ -654,6 +674,28 @@ add_flow_pattern(struct flow_patterns *patterns, enum
rte_flow_item_type type,
patterns->cnt++;
}
+static void
+add_flow_tnl_patterns(struct flow_patterns *all_patterns,
+ struct rte_flow_item *tnl_items,
--> pmd_tnl_items
+ uint32_t num_of_tnl_items,
--> num_pmd_tnl_items
+ struct flow_patterns *flow_patterns)
+{
+ int i;
+
+ all_patterns->num_of_tnl_items = num_of_tnl_items;
+
+ for (i = 0; i < num_of_tnl_items; i++) {
+ add_flow_pattern(all_patterns, tnl_items[i].type, tnl_items[i].spec,
+ tnl_items[i].mask);
+ }
+
+ for (i = 0; i < flow_patterns->cnt; i++) {
+ add_flow_pattern(all_patterns, flow_patterns->items[i].type,
+ flow_patterns->items[i].spec,
+ flow_patterns->items[i].mask);
+ }
+}
+
static void
add_flow_action(struct flow_actions *actions, enum rte_flow_action_type
type,
const void *conf)
@@ -1487,6 +1529,7 @@ parse_flow_actions(struct netdev *netdev,
static struct ufid_to_rte_flow_data *
create_netdev_offload(struct netdev *netdev,
+ struct netdev *vport,
const ovs_u128 *ufid,
struct flow_patterns *flow_patterns,
struct flow_actions *flow_actions,
@@ -1495,32 +1538,34 @@ create_netdev_offload(struct netdev *netdev,
{
struct rte_flow_attr flow_attr = { .ingress = 1, .transfer = 1, };
struct flow_actions rss_actions = { .actions = NULL, .cnt = 0 };
- struct rte_flow_item *items = flow_patterns->items;
struct ufid_to_rte_flow_data *flow_data = NULL;
bool actions_offloaded = true;
struct rte_flow *flow = NULL;
struct rte_flow_error error;
if (enable_full) {
- flow = netdev_offload_dpdk_flow_create(netdev, &flow_attr, items,
- flow_actions, &error);
+ flow = netdev_offload_dpdk_flow_create(netdev, &flow_attr,
+ flow_patterns, flow_actions,
+ &error);
}
- if (!flow) {
+ if (!vport && !flow) {
/* If we failed to offload the rule actions fallback to MARK+RSS
* actions.
*/
actions_offloaded = false;
flow_attr.transfer = 0;
add_flow_mark_rss_actions(&rss_actions, flow_mark, netdev);
- flow = netdev_offload_dpdk_flow_create(netdev, &flow_attr, items,
- &rss_actions, &error);
+ flow = netdev_offload_dpdk_flow_create(netdev, &flow_attr,
+ flow_patterns, &rss_actions,
+ &error);
}
if (flow) {
- flow_data = ufid_to_rte_flow_associate(ufid, netdev, flow,
+ flow_data = ufid_to_rte_flow_associate(ufid, netdev, vport, flow,
actions_offloaded);
- VLOG_DBG("%s: installed flow %p by ufid "UUID_FMT,
+ VLOG_DBG("%s/%s: installed flow %p by ufid "UUID_FMT,
+ vport ? netdev_get_name(vport) : netdev_get_name(netdev),
netdev_get_name(netdev), flow,
UUID_ARGS((struct uuid *) ufid));
}
@@ -1529,6 +1574,55 @@ create_netdev_offload(struct netdev *netdev,
return flow_data;
}
+static struct ufid_to_rte_flow_data *
+create_vport_offload(struct netdev *vport,
+ odp_port_t orig_in_port,
+ const ovs_u128 *ufid,
+ struct flow_patterns *flow_patterns,
+ struct flow_actions *flow_actions)
+{
+ struct flow_patterns all_patterns = { .items = NULL, .cnt = 0 };
+ struct ufid_to_rte_flow_data *flows_data = NULL;
+ struct rte_flow_item *tnl_items;
+ struct rte_flow_tunnel tunnel;
+ struct rte_flow_error error;
+ uint32_t num_of_tnl_items;
+ struct netdev *physdev;
+
+ physdev = netdev_ports_get(orig_in_port, vport->dpif_type);
+ if (physdev == NULL) {
+ return NULL;
+ }
+
+ if (vport_to_rte_tunnel(vport, &tunnel, physdev,
+ &all_patterns.s_tnl)) {
+ goto out;
+ }
+ if (netdev_dpdk_rte_flow_tunnel_match(physdev, &tunnel, &tnl_items,
+ &num_of_tnl_items, &error)) {
+ VLOG_DBG_RL(&rl, "%s: netdev_dpdk_rte_flow_tunnel_match failed: "
+ "%d (%s).", netdev_get_name(physdev), error.type,
+ error.message);
+ goto out;
+ }
+ add_flow_tnl_patterns(&all_patterns, tnl_items, num_of_tnl_items,
+ flow_patterns);
+ flows_data = create_netdev_offload(physdev, vport, ufid, &all_patterns,
+ flow_actions, true, 0);
+ if (netdev_dpdk_rte_flow_tunnel_item_release(physdev, tnl_items,
+ num_of_tnl_items,
+ &error)) {
+ VLOG_DBG_RL(&rl, "%s: netdev_dpdk_rte_flow_tunnel_item_release "
+ "failed: %d (%s).", netdev_get_name(physdev),
+ error.type, error.message);
+ }
+out:
+ all_patterns.cnt = 0;
+ free_flow_patterns(&all_patterns);
+ netdev_close(physdev);
+ return flows_data;
+}
+
static struct ufid_to_rte_flow_data *
netdev_offload_dpdk_add_flow(struct netdev *netdev,
struct match *match,
@@ -1550,8 +1644,14 @@ netdev_offload_dpdk_add_flow(struct netdev *netdev,
err = parse_flow_actions(netdev, &actions, nl_actions, actions_len);
For the vport offload (flow-F2), we should add a VXLAN_DECAP action to
the action list. Otherwise, there is no action in either F1 or F2 that
tells the PMD to pop the tunnel header.