This commit adds logic using ovs barrier to allow main thread pause
all revalidators.  This new feature will be used in a later patch.

Signed-off-by: Alex Wang <ee07b...@gmail.com>
---
V3:
- new patch.
---
 ofproto/ofproto-dpif-upcall.c | 46 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 46 insertions(+)

diff --git a/ofproto/ofproto-dpif-upcall.c b/ofproto/ofproto-dpif-upcall.c
index 419fd1a..109b99c 100644
--- a/ofproto/ofproto-dpif-upcall.c
+++ b/ofproto/ofproto-dpif-upcall.c
@@ -111,6 +111,9 @@ struct udpif {
     struct seq *reval_seq;             /* Incremented to force revalidation. */
     bool reval_exit;                   /* Set by leader on 'exit_latch. */
     struct ovs_barrier reval_barrier;  /* Barrier used by revalidators. */
+    struct latch pause_latch;          /* Set to force revalidators pause. */
+    struct ovs_barrier pause_barrier;  /* Barrier used to pause all */
+                                       /* revalidators by main thread. */
     struct dpif_flow_dump *dump;       /* DPIF flow dump state. */
     long long int dump_duration;       /* Duration of the last flow dump. */
     struct seq *dump_seq;              /* Increments each dump iteration. */
@@ -267,10 +270,13 @@ static void handle_upcalls(struct udpif *, struct upcall 
*, size_t n_upcalls);
 static void udpif_stop_threads(struct udpif *);
 static void udpif_start_threads(struct udpif *, size_t n_handlers,
                                 size_t n_revalidators);
+static void udpif_pause_revalidators(struct udpif *);
+static void udpif_resume_revalidators(struct udpif *);
 static void *udpif_upcall_handler(void *);
 static void *udpif_revalidator(void *);
 static unsigned long udpif_get_n_flows(struct udpif *);
 static void revalidate(struct revalidator *);
+static void revalidator_pause(struct revalidator *);
 static void revalidator_sweep(struct revalidator *);
 static void revalidator_purge(struct revalidator *);
 static void upcall_unixctl_show(struct unixctl_conn *conn, int argc,
@@ -356,6 +362,7 @@ udpif_create(struct dpif_backer *backer, struct dpif *dpif)
     udpif->reval_seq = seq_create();
     udpif->dump_seq = seq_create();
     latch_init(&udpif->exit_latch);
+    latch_init(&udpif->pause_latch);
     list_push_back(&all_udpifs, &udpif->list_node);
     atomic_init(&udpif->enable_ufid, false);
     atomic_init(&udpif->n_flows, 0);
@@ -401,6 +408,7 @@ udpif_destroy(struct udpif *udpif)
 
     list_remove(&udpif->list_node);
     latch_destroy(&udpif->exit_latch);
+    latch_destroy(&udpif->pause_latch);
     seq_destroy(udpif->reval_seq);
     seq_destroy(udpif->dump_seq);
     ovs_mutex_destroy(&udpif->n_flows_mutex);
@@ -440,6 +448,7 @@ udpif_stop_threads(struct udpif *udpif)
         latch_poll(&udpif->exit_latch);
 
         ovs_barrier_destroy(&udpif->reval_barrier);
+        ovs_barrier_destroy(&udpif->pause_barrier);
 
         free(udpif->revalidators);
         udpif->revalidators = NULL;
@@ -479,6 +488,7 @@ udpif_start_threads(struct udpif *udpif, size_t n_handlers,
         dpif_enable_upcall(udpif->dpif);
 
         ovs_barrier_init(&udpif->reval_barrier, udpif->n_revalidators);
+        ovs_barrier_init(&udpif->pause_barrier, udpif->n_revalidators + 1);
         udpif->reval_exit = false;
         udpif->revalidators = xzalloc(udpif->n_revalidators
                                       * sizeof *udpif->revalidators);
@@ -492,6 +502,25 @@ udpif_start_threads(struct udpif *udpif, size_t n_handlers,
     }
 }
 
+/* Pauses all revalidators.  Should only be called by the main thread.
+ * When function returns, all revalidators are paused and will proceed
+ * only after udpif_resume_revalidators() is called. */
+static void
+udpif_pause_revalidators(struct udpif *udpif)
+{
+    latch_set(&udpif->pause_latch);
+    ovs_barrier_block(&udpif->pause_barrier);
+}
+
+/* Resumes the pausing of revalidators.  Should only be called by the
+ * main thread. */
+static void
+udpif_resume_revalidators(struct udpif *udpif)
+{
+    latch_poll(&udpif->pause_latch);
+    ovs_barrier_block(&udpif->pause_barrier);
+}
+
 /* Tells 'udpif' how many threads it should use to handle upcalls.
  * 'n_handlers' and 'n_revalidators' can never be zero.  'udpif''s
  * datapath handle must have packet reception enabled before starting
@@ -762,6 +791,11 @@ udpif_revalidator(void *arg)
 
     revalidator->id = ovsthread_id_self();
     for (;;) {
+        /* Pauses all revalidators if wanted. */
+        if (latch_is_set(&udpif->pause_latch)) {
+            revalidator_pause(revalidator);
+        }
+
         if (leader) {
             uint64_t reval_seq;
 
@@ -832,6 +866,7 @@ udpif_revalidator(void *arg)
             poll_timer_wait_until(start_time + MIN(ofproto_max_idle, 500));
             seq_wait(udpif->reval_seq, last_reval_seq);
             latch_wait(&udpif->exit_latch);
+            latch_wait(&udpif->pause_latch);
             poll_block();
         }
     }
@@ -2108,6 +2143,17 @@ revalidate(struct revalidator *revalidator)
     ofpbuf_uninit(&odp_actions);
 }
 
+/* Pauses the 'revalidator', can only proceed after main thread
+ * calls udpif_resume_revalidators(). */
+static void
+revalidator_pause(struct revalidator *revalidator)
+{
+    /* The first block is for sync'ing the pause with main thread. */
+    ovs_barrier_block(&revalidator->udpif->pause_barrier);
+    /* The second block is for pausing until main thread resumes. */
+    ovs_barrier_block(&revalidator->udpif->pause_barrier);
+}
+
 static void
 revalidator_sweep__(struct revalidator *revalidator, bool purge)
 {
-- 
1.9.1

_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to