@@ -20,6 +20,8 @@
#include "openvswitch/vlog.h"
+#define SUBTABLE_STRING_OFFSET 18
+
VLOG_DEFINE_THIS_MODULE(dpif_netdev_lookup);
/* Actual list of implementations goes here */
@@ -93,11 +95,11 @@ dpcls_subtable_set_prio(const char *name, uint8_t priority)
}
dpcls_subtable_lookup_func
-dpcls_subtable_get_best_impl(uint32_t u0_bit_count, uint32_t u1_bit_count)
+dpcls_subtable_get_best_impl(uint32_t u0_bit_count, uint32_t u1_bit_count,
+ const char **name)
{
/* Iter over each subtable impl, and get highest priority one. */
int32_t prio = -1;
- const char *name = NULL;
dpcls_subtable_lookup_func best_func = NULL;
for (int i = 0; i < ARRAY_SIZE(subtable_lookups); i++) {
@@ -109,16 +111,45 @@ dpcls_subtable_get_best_impl(uint32_t u0_bit_count, uint32_t u1_bit_count)
if (probed_func) {
best_func = probed_func;
prio = probed_prio;
- name = subtable_lookups[i].name;
+ if (name) {
+ *name = subtable_lookups[i].name;
+ }
}
}
}
VLOG_DBG("Subtable lookup function '%s' with units (%d,%d), priority %d\n",
- name, u0_bit_count, u1_bit_count, prio);
+ *name, u0_bit_count, u1_bit_count, prio);
/* Programming error - we must always return a valid func ptr. */
ovs_assert(best_func != NULL);
return best_func;
}
+
+void
+dpcls_update_flow_dump(struct cmap flow_table,
+ struct dpcls_subtable_lookup_info_t *lookup_funcs,
+ int impls_count)
+{
+ struct dp_netdev_flow *flow;
+ const char *name = NULL;
+ int32_t prio = -1;
+
+ for (int i = 0; i < impls_count; i++) {
+ int32_t probed_prio = lookup_funcs[i].prio;
+ if (probed_prio > prio) {
+ name = lookup_funcs[i].name;
+ prio = probed_prio;
+ }
+ }
+ CMAP_FOR_EACH (flow, node, &flow_table) {
+ struct ds info = DS_EMPTY_INITIALIZER;
+ char *extra_info = ovsrcu_get(char *, &flow->dp_extra_info);
+ ds_put_cstr(&info, extra_info);
+ ds_truncate(&info, SUBTABLE_STRING_OFFSET);
+ ds_put_format(&info,",lookup(%s)", name);
+ ovsrcu_set(&flow->dp_extra_info, ds_steal_cstr(&info));
+ ds_destroy(&info);
+ }
+}
@@ -20,6 +20,7 @@
#include <config.h>
#include "dpif-netdev.h"
#include "dpif-netdev-private-dpcls.h"
+#include "dpif-netdev-private-flow.h"
/* Function to perform a probe for the subtable bit fingerprint.
* Returns NULL if not valid, or a valid function pointer to call for this
@@ -66,8 +67,14 @@ struct dpcls_subtable_lookup_info_t {
int32_t dpcls_subtable_set_prio(const char *name, uint8_t priority);
+/* Retrieve the best implementation for dpcls subtable.
+ * Name parameter is used to fetch the name of dpcls subtable
+ * selected by the function.
+ * The function can also be called with name as NULL.
+ */
dpcls_subtable_lookup_func
-dpcls_subtable_get_best_impl(uint32_t u0_bit_count, uint32_t u1_bit_count);
+dpcls_subtable_get_best_impl(uint32_t u0_bit_count, uint32_t u1_bit_count,
+ const char **name);
/* Retrieve the array of lookup implementations for iteration.
* On error, returns a negative number.
@@ -76,4 +83,9 @@ dpcls_subtable_get_best_impl(uint32_t u0_bit_count, uint32_t u1_bit_count);
int32_t
dpcls_subtable_lookup_info_get(struct dpcls_subtable_lookup_info_t **out_ptr);
+void
+dpcls_update_flow_dump(struct cmap flow_table,
+ struct dpcls_subtable_lookup_info_t *lookup_funcs,
+ int impls_count);
+
#endif /* dpif-netdev-lookup.h */
@@ -88,6 +88,9 @@ struct dpcls_subtable {
* here to prevent garbage from being read. */
ATOMIC(dpcls_subtable_lookup_func) lookup_func;
+ /* Holds the name of the DPCLS implementation slected. */
+ const char *subtable_lookup_name;
+
/* Caches the masks to match a packet to, reducing runtime calculations. */
uint64_t *mf_masks;
@@ -123,8 +123,10 @@ struct dp_netdev_flow {
* packet_batch_per_flow_init() and packet_batch_per_flow_execute()). */
struct packet_batch_per_flow *batch;
- /* Packet classification. */
- char *dp_extra_info; /* String to return in a flow dump/get. */
+ /* Packet classification.
+ * String to return in a flow dump/get.
+ */
+ OVSRCU_TYPE(char *) dp_extra_info;
struct dpcls_rule cr; /* In owning dp_netdev's 'cls'. */
/* 'cr' must be the last member. */
};
@@ -623,6 +623,8 @@ static int dpif_netdev_xps_get_tx_qid(const struct dp_netdev_pmd_thread *pmd,
inline struct dpcls *
dp_netdev_pmd_lookup_dpcls(struct dp_netdev_pmd_thread *pmd,
odp_port_t in_port);
+static inline struct dpcls_subtable *
+dpcls_find_subtable(struct dpcls *cls, const struct netdev_flow_key *mask);
static void dp_netdev_request_reconfigure(struct dp_netdev *dp);
static inline bool
@@ -1034,6 +1036,7 @@ dpif_netdev_subtable_lookup_set(struct unixctl_conn *conn, int argc OVS_UNUSED,
uint32_t new_prio = strtoul(argv[2], &err_char, 10);
uint32_t lookup_dpcls_changed = 0;
uint32_t lookup_subtable_changed = 0;
+ struct dpcls_subtable_lookup_info_t *lookup_funcs = NULL;
struct shash_node *node;
if (errno != 0 || new_prio > UINT8_MAX) {
unixctl_command_reply_error(conn,
@@ -1075,6 +1078,11 @@ dpif_netdev_subtable_lookup_set(struct unixctl_conn *conn, int argc OVS_UNUSED,
}
ovs_mutex_lock(&pmd->flow_mutex);
uint32_t subtbl_changes = dpcls_subtable_lookup_reprobe(cls);
+ if (subtbl_changes) {
+ int count = dpcls_subtable_lookup_info_get(&lookup_funcs);
+ dpcls_update_flow_dump(pmd->flow_table, lookup_funcs,
+ count);
+ }
ovs_mutex_unlock(&pmd->flow_mutex);
if (subtbl_changes) {
lookup_dpcls_changed++;
@@ -2380,7 +2388,8 @@ static void
dp_netdev_flow_free(struct dp_netdev_flow *flow)
{
dp_netdev_actions_free(dp_netdev_flow_get_actions(flow));
- free(flow->dp_extra_info);
+ ovsrcu_postpone(free,
+ ovsrcu_get_protected(char *, &flow->dp_extra_info));
free(flow);
}
@@ -3746,7 +3755,8 @@ dp_netdev_flow_to_dpif_flow(const struct dp_netdev *dp,
flow->pmd_id = netdev_flow->pmd_id;
get_dpif_flow_status(dp, netdev_flow, &flow->stats, &flow->attrs);
- flow->attrs.dp_extra_info = netdev_flow->dp_extra_info;
+ flow->attrs.dp_extra_info = ovsrcu_get(char *,
+ &netdev_flow->dp_extra_info);
}
static int
@@ -4116,7 +4126,11 @@ dp_netdev_flow_add(struct dp_netdev_pmd_thread *pmd,
count_1bits(flow->cr.mask->mf.map.bits[unit]));
}
ds_put_char(&extra_info, ')');
- flow->dp_extra_info = ds_steal_cstr(&extra_info);
+ struct dpcls_subtable *subtable = dpcls_find_subtable(cls, &mask);
+ ds_put_format(&extra_info, ",lookup(%s)", subtable->subtable_lookup_name);
+
+ ovsrcu_set(&flow->dp_extra_info, ds_steal_cstr(&extra_info));
+
ds_destroy(&extra_info);
cmap_insert(&pmd->flow_table, CONST_CAST(struct cmap_node *, &flow->node),
@@ -9753,7 +9767,8 @@ dpcls_create_subtable(struct dpcls *cls, const struct netdev_flow_key *mask)
* by the PMD thread.
*/
atomic_init(&subtable->lookup_func,
- dpcls_subtable_get_best_impl(unit0, unit1));
+ dpcls_subtable_get_best_impl(unit0, unit1,
+ &subtable->subtable_lookup_name));
cmap_insert(&cls->subtables_map, &subtable->cmap_node, mask->hash);
/* Add the new subtable at the end of the pvector (with no hits yet) */
@@ -9802,7 +9817,8 @@ dpcls_subtable_lookup_reprobe(struct dpcls *cls)
/* Set the subtable lookup function atomically to avoid garbage data
* being read by the PMD thread. */
atomic_store_relaxed(&subtable->lookup_func,
- dpcls_subtable_get_best_impl(u0_bits, u1_bits));
+ dpcls_subtable_get_best_impl(u0_bits, u1_bits,
+ &subtable->subtable_lookup_name));
subtables_changed += (old_func != subtable->lookup_func);
}
The patch adds the subtable lookup name to the existing dp-extra-info mentioned below: dp-extra-info:miniflow_bits(18,4), lookup(generic) dp-extra-info:miniflow_bits(9,4), lookup(avx512_gather) Suggested-by: Ilya Maximets <i.maximets@ovn.org> Signed-off-by: Kumar Amber <kumar.amber@intel.com> --- v2: - Add RCU protection for ds_extra_info. - Add string regeneration for dpcls reprobe. --- --- lib/dpif-netdev-lookup.c | 39 +++++++++++++++++++++++++++++---- lib/dpif-netdev-lookup.h | 14 +++++++++++- lib/dpif-netdev-private-dpcls.h | 3 +++ lib/dpif-netdev-private-flow.h | 6 +++-- lib/dpif-netdev.c | 26 +++++++++++++++++----- 5 files changed, 76 insertions(+), 12 deletions(-)