@@ -1579,7 +1579,7 @@ dpctl_del_flows(int argc, const char *argv[], struct dpctl_params *dpctl_p)
return error;
}
- error = dpif_flow_flush(dpif);
+ error = dpif_flow_and_ukey_flush(dpif);
if (error) {
dpctl_error(dpctl_p, error, "deleting all flows");
}
@@ -303,6 +303,10 @@ struct dp_netdev {
dp_purge_callback *dp_purge_cb;
void *dp_purge_aux;
+ /* Callback function for notifying clean ukey */
+ del_ukey_callback *del_ukey_cb;
+ void *del_ukey_aux;
+
/* Stores all 'struct dp_netdev_pmd_thread's. */
struct cmap poll_threads;
/* id pool for per thread static_tx_qid. */
@@ -1859,6 +1863,7 @@ create_dp_netdev(const char *name, const struct dpif_class *class,
dp_netdev_disable_upcall(dp);
dp->upcall_aux = NULL;
dp->upcall_cb = NULL;
+ dp->del_ukey_cb = NULL;
dp->conntrack = conntrack_init();
@@ -3052,6 +3057,62 @@ queue_netdev_flow_put(struct dp_netdev_pmd_thread *pmd,
dp_netdev_offload_flow_enqueue(item);
}
+static void
+dp_netdev_remove_ukey(struct dp_netdev_flow *flow,
+ struct dp_netdev_pmd_thread *pmd)
+{
+ struct dp_netdev *dp = pmd->dp;
+
+ if (dp->del_ukey_cb) {
+ dp->del_ukey_cb(dp->del_ukey_aux,flow->ufid,pmd->core_id);
+ }
+}
+
+static void
+dp_netdev_pmd_remove_flow_and_ukey(struct dp_netdev_pmd_thread *pmd,
+ struct dp_netdev_flow *flow)
+ OVS_REQUIRES(pmd->flow_mutex)
+{
+ struct cmap_node *node = CONST_CAST(struct cmap_node *, &flow->node);
+ struct dpcls *cls;
+ odp_port_t in_port = flow->flow.in_port.odp_port;
+
+ cls = dp_netdev_pmd_lookup_dpcls(pmd, in_port);
+ ovs_assert(cls != NULL);
+ dpcls_remove(cls, &flow->cr);
+ dp_netdev_simple_match_remove(pmd, flow);
+ cmap_remove(&pmd->flow_table, node, dp_netdev_flow_hash(&flow->ufid));
+ ccmap_dec(&pmd->n_flows, odp_to_u32(in_port));
+ queue_netdev_flow_del(pmd, flow);
+ flow->dead = true;
+ dp_netdev_remove_ukey(flow,pmd);
+ dp_netdev_flow_unref(flow);
+}
+
+static void
+dp_netdev_pmd_flow_and_ukey_flush(struct dp_netdev_pmd_thread *pmd)
+{
+ struct dp_netdev_flow *netdev_flow;
+
+ ovs_mutex_lock(&pmd->flow_mutex);
+ CMAP_FOR_EACH (netdev_flow, node, &pmd->flow_table) {
+ dp_netdev_pmd_remove_flow_and_ukey(pmd, netdev_flow);
+ }
+ ovs_mutex_unlock(&pmd->flow_mutex);
+}
+
+static int
+dpif_netdev_flow_and_ukey_flush(struct dpif *dpif)
+{
+ struct dp_netdev *dp = get_dp_netdev(dpif);
+ struct dp_netdev_pmd_thread *pmd;
+
+ CMAP_FOR_EACH (pmd, node, &dp->poll_threads) {
+ dp_netdev_pmd_flow_and_ukey_flush(pmd);
+ }
+ return 0;
+}
+
static void
dp_netdev_pmd_remove_flow(struct dp_netdev_pmd_thread *pmd,
struct dp_netdev_flow *flow)
@@ -8653,6 +8714,15 @@ dpif_netdev_register_upcall_cb(struct dpif *dpif, upcall_callback *cb,
dp->upcall_cb = cb;
}
+static void
+dpif_netdev_register_del_ukey_cb(struct dpif *dpif, del_ukey_callback *cb,
+ void *aux)
+{
+ struct dp_netdev *dp = get_dp_netdev(dpif);
+ dp->del_ukey_aux = aux;
+ dp->del_ukey_cb = cb;
+}
+
static void
dpif_netdev_xps_revalidate_pmd(const struct dp_netdev_pmd_thread *pmd,
bool purge)
@@ -9655,6 +9725,7 @@ const struct dpif_class dpif_netdev_class = {
NULL, /* recv_purge */
dpif_netdev_register_dp_purge_cb,
dpif_netdev_register_upcall_cb,
+ dpif_netdev_register_del_ukey_cb,
dpif_netdev_enable_upcall,
dpif_netdev_disable_upcall,
dpif_netdev_get_datapath_version,
@@ -9696,6 +9767,7 @@ const struct dpif_class dpif_netdev_class = {
NULL, /* cache_get_name */
NULL, /* cache_get_size */
NULL, /* cache_set_size */
+ dpif_netdev_flow_and_ukey_flush,
};
static void
@@ -4554,6 +4554,7 @@ const struct dpif_class dpif_netlink_class = {
dpif_netlink_recv_purge,
NULL, /* register_dp_purge_cb */
NULL, /* register_upcall_cb */
+ NULL, /* register_del_ukey_cb */
NULL, /* enable_upcall */
NULL, /* disable_upcall */
dpif_netlink_get_datapath_version, /* get_datapath_version */
@@ -4595,6 +4596,7 @@ const struct dpif_class dpif_netlink_class = {
dpif_netlink_cache_get_name,
dpif_netlink_cache_get_size,
dpif_netlink_cache_set_size,
+ NULL,
};
static int
@@ -431,6 +431,14 @@ struct dpif_class {
* callback on invocation. */
void (*register_upcall_cb)(struct dpif *, upcall_callback *, void *aux);
+ /* When 'dpif' is about to delete flow,the ukey associated with the flow
+ * is alse deleted.(e.g. Command line: ovs-appctl dpctl/del-flows)
+ *
+ * Registers an upcall callback function with 'dpif'. This is only used
+ * if 'dpif' needs to notify the deltete the flows. 'aux' is passed to
+ * the callback on invocation. */
+ void (*register_del_ukey_cb)(struct dpif *, del_ukey_callback *,void *aux);
+
/* Enables upcalls if 'dpif' directly executes upcall functions. */
void (*enable_upcall)(struct dpif *);
@@ -662,6 +670,9 @@ struct dpif_class {
/* Set cache size. */
int (*cache_set_size)(struct dpif *dpif, uint32_t level, uint32_t size);
+
+ /* delete ukey and flow */
+ int (*ukey_and_flow_flush)(struct dpif *dpif);
};
extern const struct dpif_class dpif_netlink_class;
@@ -934,6 +934,18 @@ dpif_flow_flush(struct dpif *dpif)
return error;
}
+/* deletes all flows and ukeys from 'dpif'. Return 0 if successful,
+* otherwise a positive errno value */
+int
+dpif_flow_and_ukey_flush(struct dpif *dpif)
+{
+ int error;
+
+ error = dpif->dpif_class->ukey_and_flow_flush(dpif);
+ log_operation(dpif, "ukey_and_flow_flush", error);
+ return error;
+
+}
/* Attempts to install 'key' into the datapath, fetches it, then deletes it.
* Returns true if the datapath supported installing 'flow', false otherwise.
*/
@@ -1526,6 +1538,14 @@ dpif_register_dp_purge_cb(struct dpif *dpif, dp_purge_callback *cb, void *aux)
}
}
+void
+dpif_register_del_ukey_cb(struct dpif *dpif, del_ukey_callback *cb, void *aux)
+{
+ if (dpif->dpif_class->register_del_ukey_cb) {
+ dpif->dpif_class->register_del_ukey_cb(dpif, cb, aux);
+ }
+}
+
void
dpif_register_upcall_cb(struct dpif *dpif, upcall_callback *cb, void *aux)
{
@@ -539,6 +539,7 @@ enum dpif_flow_put_flags {
bool dpif_probe_feature(struct dpif *, const char *name,
const struct ofpbuf *key, const struct ofpbuf *actions,
const ovs_u128 *ufid);
+int dpif_flow_and_ukey_flush(struct dpif *dpif);
int dpif_flow_flush(struct dpif *);
int dpif_flow_put(struct dpif *, enum dpif_flow_put_flags,
const struct nlattr *key, size_t key_len,
@@ -882,6 +883,9 @@ typedef int upcall_callback(const struct dp_packet *packet,
void dpif_register_upcall_cb(struct dpif *, upcall_callback *, void *aux);
+typedef int del_ukey_callback(void *aux, ovs_u128 ufid, unsigned pmd_id);
+void dpif_register_del_ukey_cb(struct dpif *, del_ukey_callback *, void *aux);
+
int dpif_recv_set(struct dpif *, bool enable);
int dpif_handlers_set(struct dpif *, uint32_t n_handlers);
bool dpif_number_handlers_required(struct dpif *, uint32_t *n_handlers);
@@ -415,6 +415,7 @@ static int udpif_flow_unprogram(struct udpif *udpif, struct udpif_key *ukey,
static upcall_callback upcall_cb;
static dp_purge_callback dp_purge_cb;
+static del_ukey_callback dp_del_ukey_cb;
static atomic_bool enable_megaflows = ATOMIC_VAR_INIT(true);
static atomic_bool enable_ufid = ATOMIC_VAR_INIT(true);
@@ -473,6 +474,7 @@ udpif_create(struct dpif_backer *backer, struct dpif *dpif)
dpif_register_upcall_cb(dpif, upcall_cb, udpif);
dpif_register_dp_purge_cb(dpif, dp_purge_cb, udpif);
+ dpif_register_del_ukey_cb(dpif, dp_del_ukey_cb, udpif);
return udpif;
}
@@ -2972,7 +2974,32 @@ dp_purge_cb(void *aux, unsigned pmd_id)
}
udpif_resume_revalidators(udpif);
}
-
+
+static int
+dp_del_ukey_cb(void *aux, ovs_u128 ufid, unsigned pmd_id)
+ OVS_NO_THREAD_SAFETY_ANALYSIS
+{
+ struct udpif *udpif = aux;
+ size_t i;
+
+ for (i = 0; i < N_UMAPS; i++) {
+ struct udpif_key *ukey;
+ struct umap *umap = &udpif->ukeys[i];
+
+ CMAP_FOR_EACH (ukey, cmap_node, &umap->cmap) {
+ if (ovs_u128_equals(ukey->ufid, ufid) &&
+ pmd_id == ukey->pmd_id) {
+ transition_ukey(ukey, UKEY_EVICTING);
+ ovs_mutex_lock(&umap->mutex);
+ ukey_delete(umap, ukey);
+ ovs_mutex_unlock(&umap->mutex);
+ }
+ }
+ ovsrcu_quiesce();
+ }
+ return 0;
+}
+
static void
upcall_unixctl_show(struct unixctl_conn *conn, int argc OVS_UNUSED,
const char *argv[] OVS_UNUSED, void *aux OVS_UNUSED)