[ovs-dev] [PATCH v2 1/8] dpif-netdev: associate flow with a mark id
Yuanhan Liu
yliu at fridaylinux.org
Tue Sep 5 09:22:54 UTC 2017
This patch associate a flow with a mark id (a uint32_t number) by CMAP.
It re-uses the flow API (more precisely, the ->flow_put method) to setup
the hw flow. The flow_put implementation then is supposed to create a
flow with MARK action.
Co-authored-by: Finn Christensen <fc at napatech.com>
Signed-off-by: Yuanhan Liu <yliu at fridaylinux.org>
Signed-off-by: Finn Christensen <fc at napatech.com>
---
lib/dpif-netdev.c | 85 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
lib/netdev.h | 6 ++++
2 files changed, 91 insertions(+)
diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c
index 071ec14..f3b7f25 100644
--- a/lib/dpif-netdev.c
+++ b/lib/dpif-netdev.c
@@ -446,6 +446,12 @@ struct dp_netdev_flow {
const unsigned pmd_id; /* The 'core_id' of pmd thread owning this */
/* flow. */
+ const struct cmap_node mark_node; /* In owning dp_netdev_pmd_thread's */
+ /* 'mark_to_flow' */
+ bool has_mark; /* A flag to tell whether this flow has a
+ valid mark asscoiated with it. */
+ uint32_t mark; /* Unique flow mark assiged to a flow */
+
/* Number of references.
* The classifier owns one reference.
* Any thread trying to keep a rule from being freed should hold its own
@@ -569,6 +575,8 @@ struct dp_netdev_pmd_thread {
struct ovs_mutex flow_mutex;
struct cmap flow_table OVS_GUARDED; /* Flow table. */
+ struct cmap mark_to_flow;
+
/* One classifier per in_port polled by the pmd */
struct cmap classifiers;
/* Periodically sort subtable vectors according to hit frequencies */
@@ -1839,6 +1847,8 @@ dp_netdev_pmd_remove_flow(struct dp_netdev_pmd_thread *pmd,
OVS_REQUIRES(pmd->flow_mutex)
{
struct cmap_node *node = CONST_CAST(struct cmap_node *, &flow->node);
+ struct cmap_node *mark_node = CONST_CAST(struct cmap_node *,
+ &flow->mark_node);
struct dpcls *cls;
odp_port_t in_port = flow->flow.in_port.odp_port;
@@ -1846,6 +1856,10 @@ dp_netdev_pmd_remove_flow(struct dp_netdev_pmd_thread *pmd,
ovs_assert(cls != NULL);
dpcls_remove(cls, &flow->cr);
cmap_remove(&pmd->flow_table, node, dp_netdev_flow_hash(&flow->ufid));
+ if (flow->has_mark) {
+ cmap_remove(&pmd->mark_to_flow, mark_node, flow->mark);
+ flow->has_mark = false;
+ }
flow->dead = true;
dp_netdev_flow_unref(flow);
@@ -2235,6 +2249,38 @@ dp_netdev_pmd_find_flow(const struct dp_netdev_pmd_thread *pmd,
return NULL;
}
+static struct dp_netdev_flow *
+dp_netdev_pmd_find_flow_by_mark(const struct dp_netdev_pmd_thread *pmd,
+ const uint32_t mark)
+{
+ struct dp_netdev_flow *netdev_flow;
+
+ CMAP_FOR_EACH_WITH_HASH (netdev_flow, mark_node, mark,
+ &pmd->mark_to_flow) {
+ if (netdev_flow->has_mark && netdev_flow->mark == mark) {
+ return netdev_flow;
+ }
+ }
+
+ return NULL;
+}
+
+static bool
+dp_netdev_alloc_flow_mark(const struct dp_netdev_pmd_thread *pmd,
+ uint32_t *mark)
+{
+ uint32_t i;
+
+ for (i = 0; i < UINT32_MAX; i++) {
+ if (!dp_netdev_pmd_find_flow_by_mark(pmd, i)) {
+ *mark = i;
+ return true;
+ }
+ }
+
+ return false;
+}
+
static void
get_dpif_flow_stats(const struct dp_netdev_flow *netdev_flow_,
struct dpif_flow_stats *stats)
@@ -2434,6 +2480,7 @@ dp_netdev_flow_add(struct dp_netdev_pmd_thread *pmd,
struct dp_netdev_flow *flow;
struct netdev_flow_key mask;
struct dpcls *cls;
+ struct offload_info info;
/* Make sure in_port is exact matched before we read it. */
ovs_assert(match->wc.masks.in_port.odp_port == ODPP_NONE);
@@ -2460,6 +2507,7 @@ dp_netdev_flow_add(struct dp_netdev_pmd_thread *pmd,
memset(&flow->stats, 0, sizeof flow->stats);
flow->dead = false;
flow->batch = NULL;
+ flow->has_mark = false;
*CONST_CAST(unsigned *, &flow->pmd_id) = pmd->core_id;
*CONST_CAST(struct flow *, &flow->flow) = match->flow;
*CONST_CAST(ovs_u128 *, &flow->ufid) = *ufid;
@@ -2475,6 +2523,22 @@ dp_netdev_flow_add(struct dp_netdev_pmd_thread *pmd,
cmap_insert(&pmd->flow_table, CONST_CAST(struct cmap_node *, &flow->node),
dp_netdev_flow_hash(&flow->ufid));
+ if (netdev_is_flow_api_enabled() &&
+ dp_netdev_alloc_flow_mark(pmd, &info.flow_mark)) {
+ struct dp_netdev_port *port;
+ port = dp_netdev_lookup_port(pmd->dp, in_port);
+ if (netdev_flow_put(port->netdev, match,
+ CONST_CAST(struct nlattr *, actions),
+ actions_len, ufid, &info, NULL) == 0) {
+ flow->has_mark = true;
+ flow->mark = info.flow_mark;
+ cmap_insert(&pmd->mark_to_flow,
+ CONST_CAST(struct cmap_node *, &flow->mark_node),
+ info.flow_mark);
+ VLOG_INFO("installed flow %p with mark %u\n", flow, flow->mark);
+ }
+ }
+
if (OVS_UNLIKELY(!VLOG_DROP_DBG((&upcall_rl)))) {
struct ds ds = DS_EMPTY_INITIALIZER;
struct ofpbuf key_buf, mask_buf;
@@ -2562,6 +2626,25 @@ flow_put_on_pmd(struct dp_netdev_pmd_thread *pmd,
old_actions = dp_netdev_flow_get_actions(netdev_flow);
ovsrcu_set(&netdev_flow->actions, new_actions);
+ if (netdev_flow->has_mark) {
+ struct offload_info info;
+ struct dp_netdev_port *port;
+ odp_port_t in_port;
+ int ret;
+
+ in_port = netdev_flow->flow.in_port.odp_port;
+ port = dp_netdev_lookup_port(pmd->dp, in_port);
+ info.flow_mark = netdev_flow->mark;
+ ret = netdev_flow_put(port->netdev, match,
+ CONST_CAST(struct nlattr *,
+ put->actions),
+ put->actions_len, ufid, &info, stats);
+
+ VLOG_INFO("%s to modify flow %p associated with mark %u\n",
+ ret == 0 ? "succeed" : "failed",
+ netdev_flow, netdev_flow->mark);
+ }
+
if (stats) {
get_dpif_flow_stats(netdev_flow, stats);
}
@@ -4504,6 +4587,7 @@ dp_netdev_configure_pmd(struct dp_netdev_pmd_thread *pmd, struct dp_netdev *dp,
ovs_mutex_init(&pmd->flow_mutex);
ovs_mutex_init(&pmd->port_mutex);
cmap_init(&pmd->flow_table);
+ cmap_init(&pmd->mark_to_flow);
cmap_init(&pmd->classifiers);
pmd->next_optimization = time_msec() + DPCLS_OPTIMIZATION_INTERVAL;
pmd->rxq_interval = time_msec() + PMD_RXQ_INTERVAL_LEN;
@@ -4538,6 +4622,7 @@ dp_netdev_destroy_pmd(struct dp_netdev_pmd_thread *pmd)
}
cmap_destroy(&pmd->classifiers);
cmap_destroy(&pmd->flow_table);
+ cmap_destroy(&pmd->mark_to_flow);
ovs_mutex_destroy(&pmd->flow_mutex);
latch_destroy(&pmd->exit_latch);
seq_destroy(pmd->reload_seq);
diff --git a/lib/netdev.h b/lib/netdev.h
index f8482f7..2003165 100644
--- a/lib/netdev.h
+++ b/lib/netdev.h
@@ -188,6 +188,12 @@ void netdev_send_wait(struct netdev *, int qid);
struct offload_info {
const struct dpif_class *dpif_class;
ovs_be16 tp_dst_port; /* Destination port for tunnel in SET action */
+
+ /*
+ * The flow mark id assigened to the flow. If any pkts hit the flow,
+ * it will be in the pkt meta data.
+ */
+ uint32_t flow_mark;
};
struct dpif_class;
struct netdev_flow_dump;
--
2.7.4
More information about the dev
mailing list