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.
Signed-off-by: Yuanhan Liu <[email protected]> Signed-off-by: Finn Christensen <[email protected]> --- lib/dpif-netdev.c | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/netdev.h | 6 ++++ 2 files changed, 89 insertions(+) diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c index e2cd931..aaeb7c2 100644 --- a/lib/dpif-netdev.c +++ b/lib/dpif-netdev.c @@ -422,6 +422,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 @@ -545,6 +551,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 */ @@ -1765,6 +1773,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; @@ -1772,6 +1782,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); @@ -2161,6 +2175,37 @@ 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) @@ -2360,6 +2405,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); @@ -2386,6 +2432,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; @@ -2401,6 +2448,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; @@ -2488,6 +2551,24 @@ 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); } @@ -4307,6 +4388,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; hmap_init(&pmd->poll_list); @@ -4340,6 +4422,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 _______________________________________________ dev mailing list [email protected] https://mail.openvswitch.org/mailman/listinfo/ovs-dev
