]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Protocol shutdown/restart from limits is respecting the loops
authorMaria Matejka <mq@ucw.cz>
Mon, 6 Feb 2023 14:06:12 +0000 (15:06 +0100)
committerMaria Matejka <mq@ucw.cz>
Tue, 7 Feb 2023 13:28:25 +0000 (14:28 +0100)
lib/timer.h
nest/proto.c
nest/protocol.h

index 555fc96f7e767d9f67ac9bad418fd63142611a2c..4a3a210834f6729df527b2089749985677e46e19 100644 (file)
@@ -99,12 +99,14 @@ tm_set_max(timer *t, btime when)
 }
 
 static inline void
-tm_start_max(timer *t, btime after)
+tm_start_max_in(timer *t, btime after, struct birdloop *loop)
 {
   btime rem = tm_remains(t);
-  tm_start(t, MAX_(rem, after));
+  tm_start_in(t, MAX_(rem, after), loop);
 }
 
+#define tm_start_max(t, after) tm_start_max_in(t, after, &main_birdloop)
+
 /* In sysdep code */
 void times_update(void);
 
index 6e4b7d290fbffce4b1662e0c76ce5d82658794c2..94ca188d13d1b85fd98e345445096c939f172a7b 100644 (file)
@@ -30,7 +30,6 @@ static list STATIC_LIST_INIT(protocol_list);
 #define CD(c, msg, args...) ({ if (c->debug & D_STATES) log(L_TRACE "%s.%s: " msg, c->proto->name, c->name ?: "?", ## args); })
 #define PD(p, msg, args...) ({ if (p->debug & D_STATES) log(L_TRACE "%s: " msg, p->name, ## args); })
 
-static timer *proto_shutdown_timer;
 static timer *gr_wait_timer;
 
 #define GRS_NONE       0
@@ -47,7 +46,6 @@ static char *c_states[] = { "DOWN", "START", "UP", "STOP", "RESTART" };
 extern struct protocol proto_unix_iface;
 
 static void channel_request_reload(struct channel *c);
-static void proto_shutdown_loop(timer *);
 static void proto_rethink_goal(struct proto *p);
 static char *proto_state_name(struct proto *p);
 static void channel_init_limit(struct channel *c, struct limit *l, int dir, struct channel_limit *cf);
@@ -1866,8 +1864,6 @@ protos_build(void)
   protos_build_gen();
 
   proto_pool = rp_new(&root_pool, "Protocols");
-  proto_shutdown_timer = tm_new(proto_pool);
-  proto_shutdown_timer->hook = proto_shutdown_loop;
 }
 
 
@@ -1875,23 +1871,39 @@ protos_build(void)
 int proto_restart;
 
 static void
-proto_shutdown_loop(timer *t UNUSED)
+proto_restart_event_hook(void *_p)
 {
-  struct proto *p, *p_next;
+  struct proto *p = _p;
+  if (!p->down_sched)
+    return;
 
-  WALK_LIST_DELSAFE(p, p_next, proto_list)
-    if (p->down_sched)
-    {
-      proto_restart = (p->down_sched == PDS_RESTART);
+  proto_restart = (p->down_sched == PDS_RESTART);
+  p->disabled = 1;
+  proto_rethink_goal(p);
 
-      p->disabled = 1;
-      proto_rethink_goal(p);
-      if (proto_restart)
-      {
-       p->disabled = 0;
-       proto_rethink_goal(p);
-      }
-    }
+  p->restart_event = NULL;
+  p->restart_timer = NULL;
+
+  if (proto_restart)
+    /* No need to call proto_rethink_goal() here again as the proto_cleanup() routine will
+     * call it after the protocol stops ... and both these routines are fixed to main_birdloop.
+     */
+    p->disabled = 0;
+}
+
+static void
+proto_send_restart_event(struct proto *p)
+{
+  if (!p->restart_event)
+    p->restart_event = ev_new_init(p->pool, proto_restart_event_hook, p);
+
+  ev_send(&global_event_list, p->restart_event);
+}
+
+static void
+proto_send_restart_event_from_timer(struct timer *t)
+{
+  proto_send_restart_event((struct proto *) t->data);
 }
 
 static inline void
@@ -1906,7 +1918,21 @@ proto_schedule_down(struct proto *p, byte restart, byte code)
 
   p->down_sched = restart ? PDS_RESTART : PDS_DISABLE;
   p->down_code = code;
-  tm_start_max(proto_shutdown_timer, restart ? 250 MS : 0);
+
+  if (!restart)
+  {
+    if (p->restart_timer && tm_active(p->restart_timer))
+      tm_stop(p->restart_timer);
+
+    proto_send_restart_event(p);
+  }
+  else
+  {
+    if (!p->restart_timer)
+      p->restart_timer = tm_new_init(p->pool, proto_send_restart_event_from_timer, p, 0, 0);
+
+    tm_start_max_in(p->restart_timer, 250 MS, p->loop);
+  }
 }
 
 /**
index fdd0373a98e87c6659fd962a008b8e569bcaaeef..dfbfff4664cb2e738eb7ae8b6346db4de013b53f 100644 (file)
@@ -123,6 +123,8 @@ struct proto {
   struct proto_config *cf_new;         /* Configuration we want to switch to after shutdown (NULL=delete) */
   pool *pool;                          /* Pool containing local objects */
   event *event;                                /* Protocol event */
+  timer *restart_timer;                        /* Timer to restart the protocol from limits */
+  event *restart_event;                        /* Event to restart/shutdown the protocol from limits */
   struct birdloop *loop;               /* BIRDloop running this protocol */
 
   list channels;                       /* List of channels to rtables (struct channel) */