static int process_upcall(struct udpif *, struct upcall *,
struct ofpbuf *odp_actions, struct flow_wildcards *);
static void handle_upcalls(struct udpif *, struct upcall *, size_t n_upcalls);
-static void udpif_stop_threads(struct udpif *);
+static void udpif_stop_threads(struct udpif *, bool delete_flows);
static void udpif_start_threads(struct udpif *, size_t n_handlers,
size_t n_revalidators);
static void udpif_pause_revalidators(struct udpif *);
void
udpif_destroy(struct udpif *udpif)
{
- udpif_stop_threads(udpif);
+ udpif_stop_threads(udpif, false);
dpif_register_dp_purge_cb(udpif->dpif, NULL, udpif);
dpif_register_upcall_cb(udpif->dpif, NULL, udpif);
free(udpif);
}
-/* Stops the handler and revalidator threads. */
+/* Stops the handler and revalidator threads.
+ *
+ * If 'delete_flows' is true, we delete ukeys and delete all flows from the
+ * datapath. Otherwise, we end up double-counting stats for flows that remain
+ * in the datapath. If 'delete_flows' is false, we skip this step. This is
+ * appropriate if OVS is about to exit anyway and it is desirable to let
+ * existing network connections continue being forwarded afterward. */
static void
-udpif_stop_threads(struct udpif *udpif)
+udpif_stop_threads(struct udpif *udpif, bool delete_flows)
{
if (udpif && (udpif->n_handlers != 0 || udpif->n_revalidators != 0)) {
size_t i;
dpif_disable_upcall(udpif->dpif);
ovsrcu_quiesce_end();
- /* Delete ukeys, and delete all flows from the datapath to prevent
- * double-counting stats. */
- for (i = 0; i < udpif->n_revalidators; i++) {
- revalidator_purge(&udpif->revalidators[i]);
+ if (delete_flows) {
+ for (i = 0; i < udpif->n_revalidators; i++) {
+ revalidator_purge(&udpif->revalidators[i]);
+ }
}
latch_poll(&udpif->exit_latch);
if (udpif->n_handlers != n_handlers_
|| udpif->n_revalidators != n_revalidators_) {
- udpif_stop_threads(udpif);
+ udpif_stop_threads(udpif, true);
}
if (!udpif->handlers && !udpif->revalidators) {
size_t n_handlers_ = udpif->n_handlers;
size_t n_revalidators_ = udpif->n_revalidators;
- udpif_stop_threads(udpif);
+ udpif_stop_threads(udpif, true);
dpif_flow_flush(udpif->dpif);
udpif_start_threads(udpif, n_handlers_, n_revalidators_);
}
}
static void
-ofproto_flush__(struct ofproto *ofproto)
+ofproto_flush__(struct ofproto *ofproto, bool del)
OVS_EXCLUDED(ofproto_mutex)
{
struct oftable *table;
/* This will flush all datapath flows. */
- if (ofproto->ofproto_class->flush) {
+ if (del && ofproto->ofproto_class->flush) {
ofproto->ofproto_class->flush(ofproto);
}
return;
}
- ofproto_flush__(p);
+ ofproto_flush__(p, del);
HMAP_FOR_EACH_SAFE (ofport, next_ofport, hmap_node, &p->ports) {
ofport_destroy(ofport, del);
}
ofproto_flush_flows(struct ofproto *ofproto)
{
COVERAGE_INC(ofproto_flush);
- ofproto_flush__(ofproto);
+ ofproto_flush__(ofproto, false);
connmgr_flushed(ofproto->connmgr);
}
\f
.SS "GENERAL COMMANDS"
.IP "\fBexit\fR \fI--cleanup\fR"
Causes \fBovs\-vswitchd\fR to gracefully terminate. If \fI--cleanup\fR
-is specified, release datapath resources configured by \fBovs\-vswitchd\fR.
-Otherwise, datapath flows and other resources remains undeleted.
-Resources of datapaths that are integrated into \fBovs\-vswitchd\fR (e.g.
-the \fBnetdev\fR datapath type) are always released regardless of
-\fI--cleanup\fR except for ports with \fBinternal\fR type. Use \fI--cleanup\fR
-to release \fBinternal\fR ports too.
+is specified, deletes flows from datpaths and releases other datapath
+resources configured by \fBovs\-vswitchd\fR. Otherwise, datapath
+flows and other resources remains undeleted. Resources of datapaths
+that are integrated into \fBovs\-vswitchd\fR (e.g. the \fBnetdev\fR
+datapath type) are always released regardless of \fI--cleanup\fR
+except for ports with \fBinternal\fR type. Use \fI--cleanup\fR to
+release \fBinternal\fR ports too.
.
.IP "\fBqos/show-types\fR \fIinterface\fR"
Queries the interface for a list of Quality of Service types that are