@@ -18,6 +18,7 @@
#include <rte_flow.h>
#include "dpif-netdev.h"
+#include "netdev-offload-provider.h"
#include "netdev-offload-dpdk-private.h"
#include "openvswitch/match.h"
#include "openvswitch/vlog.h"
@@ -25,6 +26,8 @@
VLOG_DEFINE_THIS_MODULE(netdev_offload_dpdk_flow);
+static struct vlog_rate_limit error_rl = VLOG_RATE_LIMIT_INIT(100, 5);
+
void
netdev_dpdk_flow_patterns_free(struct flow_patterns *patterns)
{
@@ -528,3 +531,28 @@ netdev_dpdk_flow_patterns_add(struct flow_patterns *patterns,
return 0;
}
+int
+netdev_dpdk_flow_actions_add(struct flow_actions *actions,
+ struct nlattr *nl_actions,
+ size_t nl_actions_len,
+ struct offload_info *info OVS_UNUSED)
+{
+ struct nlattr *nla;
+ size_t left;
+
+ NL_ATTR_FOR_EACH_UNSAFE (nla, left, nl_actions, nl_actions_len) {
+ VLOG_DBG_RL(&error_rl,
+ "Unsupported action type %d", nl_attr_type(nla));
+ return -1;
+ }
+
+ if (nl_actions_len == 0) {
+ VLOG_DBG_RL(&error_rl,
+ "Unsupported action type drop");
+ return -1;
+ }
+
+ add_flow_action(actions, RTE_FLOW_ACTION_TYPE_END, NULL);
+ return 0;
+}
+
@@ -51,6 +51,11 @@ void
netdev_dpdk_flow_actions_add_mark_rss(struct flow_actions *actions,
struct netdev *netdev,
uint32_t mark_id);
+int
+netdev_dpdk_flow_actions_add(struct flow_actions *actions,
+ struct nlattr *nl_actions,
+ size_t nl_actions_len,
+ struct offload_info *info);
struct ds *
netdev_dpdk_flow_ds_put_flow(struct ds *s,
const struct rte_flow_attr *attr,
@@ -115,13 +115,9 @@ ufid_to_rte_flow_disassociate(const ovs_u128 *ufid)
UUID_ARGS((struct uuid *) ufid));
}
-static int
-netdev_offload_dpdk_add_flow(struct netdev *netdev,
- const struct match *match,
- struct nlattr *nl_actions OVS_UNUSED,
- size_t actions_len OVS_UNUSED,
- const ovs_u128 *ufid,
- struct offload_info *info)
+static struct rte_flow *
+netdev_offload_dpdk_mark_rss(struct flow_patterns *patterns,
+ struct netdev *netdev, uint32_t flow_mark)
{
const struct rte_flow_attr flow_attr = {
.group = 0,
@@ -129,10 +125,63 @@ netdev_offload_dpdk_add_flow(struct netdev *netdev,
.ingress = 1,
.egress = 0
};
- struct flow_patterns patterns = { .items = NULL, .cnt = 0 };
struct flow_actions actions = { .actions = NULL, .cnt = 0 };
struct rte_flow_error error;
struct rte_flow *flow;
+
+ netdev_dpdk_flow_actions_add_mark_rss(&actions, netdev, flow_mark);
+ flow = netdev_dpdk_rte_flow_create(netdev, &flow_attr,
+ patterns->items,
+ actions.actions, &error);
+ if (!flow) {
+ VLOG_ERR("%s: rte flow create error: %u : message : %s\n",
+ netdev_get_name(netdev), error.type, error.message);
+ }
+ netdev_dpdk_flow_actions_free(&actions);
+ return flow;
+}
+
+static struct rte_flow *
+netdev_offload_dpdk_actions(struct netdev *netdev,
+ struct flow_patterns *patterns,
+ struct nlattr *nl_actions,
+ size_t actions_len,
+ struct offload_info *info)
+{
+ const struct rte_flow_attr flow_attr = { .ingress = 1, .transfer = 1 };
+ struct flow_actions actions = { .actions = NULL, .cnt = 0 };
+ struct rte_flow *flow = NULL;
+ struct rte_flow_error error;
+ int ret;
+
+ ret = netdev_dpdk_flow_actions_add(&actions, nl_actions, actions_len, info);
+ if (ret) {
+ goto out;
+ }
+ flow = netdev_dpdk_rte_flow_create(netdev, &flow_attr, patterns->items,
+ actions.actions, &error);
+ if (!flow) {
+ VLOG_ERR("%s: rte flow create error: %u : message : %s\n",
+ netdev_get_name(netdev), error.type, error.message);
+ }
+ if (flow && info->actions_offloaded) {
+ *info->actions_offloaded = true;
+ }
+out:
+ netdev_dpdk_flow_actions_free(&actions);
+ return flow;
+}
+
+static int
+netdev_offload_dpdk_add_flow(struct netdev *netdev,
+ const struct match *match,
+ struct nlattr *nl_actions,
+ size_t actions_len,
+ const ovs_u128 *ufid,
+ struct offload_info *info)
+{
+ struct flow_patterns patterns = { .items = NULL, .cnt = 0 };
+ struct rte_flow *flow;
int ret = 0;
ret = netdev_dpdk_flow_patterns_add(&patterns, match);
@@ -142,16 +191,15 @@ netdev_offload_dpdk_add_flow(struct netdev *netdev,
goto out;
}
- netdev_dpdk_flow_actions_add_mark_rss(&actions, netdev,
- info->flow_mark);
-
- flow = netdev_dpdk_rte_flow_create(netdev, &flow_attr,
- patterns.items,
- actions.actions, &error);
-
+ flow = netdev_offload_dpdk_actions(netdev, &patterns, nl_actions,
+ actions_len, info);
+ if (!flow) {
+ /* if we failed to offload the rule actions fallback to mark rss
+ * actions.
+ */
+ flow = netdev_offload_dpdk_mark_rss(&patterns, netdev, info->flow_mark);
+ }
if (!flow) {
- VLOG_ERR("%s: rte flow create error: %u : message : %s\n",
- netdev_get_name(netdev), error.type, error.message);
ret = -1;
goto out;
}
@@ -161,7 +209,6 @@ netdev_offload_dpdk_add_flow(struct netdev *netdev,
out:
netdev_dpdk_flow_patterns_free(&patterns);
- netdev_dpdk_flow_actions_free(&actions);
return ret;
}
@@ -71,6 +71,7 @@ struct offload_info {
* it will be in the pkt meta data.
*/
uint32_t flow_mark;
+ bool *actions_offloaded; /* true if flow is fully actions_offloaded */
};
int netdev_flow_flush(struct netdev *);