]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Merge commit 'aa70e14c' into thread-next
authorMaria Matejka <mq@ucw.cz>
Tue, 24 Oct 2023 07:34:06 +0000 (09:34 +0200)
committerMaria Matejka <mq@ucw.cz>
Tue, 24 Oct 2023 07:34:06 +0000 (09:34 +0200)
1  2 
proto/bfd/bfd.c

diff --cc proto/bfd/bfd.c
index 5980148b4d3e9dc3e3f69c93133bfbd912b791c7,97eb2d9b44302a34ef1f340b71827cd0c06671d4..cb0f5ae899b99b370f536bfcecf0e1b65b4d6332
@@@ -645,20 -648,10 +645,20 @@@ bfd_request_notify(struct bfd_request *
    req->state = state;
    req->diag = diag;
    req->old_state = old_state;
-   req->down = (old_state == BFD_STATE_UP) && (state == BFD_STATE_DOWN);
+   req->down = (old_state == BFD_STATE_UP) && (state == BFD_STATE_DOWN) && (remote != BFD_STATE_ADMIN_DOWN);
  
    if (req->hook)
 +  {
 +    struct birdloop *target = !birdloop_inside(req->target) ? req->target : NULL;
 +
 +    if (target)
 +      birdloop_enter(target);
 +
      req->hook(req);
 +
 +    if (target)
 +      birdloop_leave(target);
 +  }
  }
  
  static int
@@@ -711,84 -691,20 +711,84 @@@ bfd_add_request(struct bfd_proto *p, st
  }
  
  static void
 -bfd_submit_request(struct bfd_request *req)
 +bfd_pickup_requests(void *_data UNUSED)
  {
 -  node *n;
 +  /* NOTE TO MY FUTURE SELF
 +   *
 +   * Functions bfd_take_requests() and bfd_drop_requests() need to have
 +   * consistent &bfd_global.wait_list and this is ensured only by having these
 +   * functions called from bfd_start() and bfd_shutdown() which are both called
 +   * in PROTO_LOCKED_FROM_MAIN context, i.e. always from &main_birdloop.
 +   *
 +   * This pickup event is also called in &main_birdloop, therefore we can
 +   * freely do BFD_LOCK/BFD_UNLOCK while processing all the requests. All BFD
 +   * protocols capable of bfd_add_request() are either started before this code
 +   * happens or after that.
 +   *
 +   * If BFD protocols could start in parallel with this routine, they might
 +   * miss some of the waiting requests, thus if anybody tries to start
 +   * protocols or run this pickup event outside &main_birdloop in future, they
 +   * shall ensure that this race condition is mitigated somehow.
 +   *
 +   * Thank you, my future self, for understanding. Have a nice day!
 +   */
 +
 +  DBG("BFD pickup loop starting");
 +
 +  BFD_LOCK;
 +  do {
 +    bfd_global.pickup_reload = 0;
 +    BFD_UNLOCK;
 +
 +    node *n;
 +    WALK_LIST(n, bfd_global.proto_list)
 +    {
 +      struct bfd_proto *p = SKIP_BACK(struct bfd_proto, bfd_node, n);
 +      birdloop_enter(p->p.loop);
 +      BFD_LOCK;
 +
 +      TRACE(D_EVENTS, "Picking up new requests (%d available)", list_length(&bfd_global.pickup_list));
 +
 +      node *rn, *rnxt;
 +      WALK_LIST_DELSAFE(rn, rnxt, bfd_global.pickup_list)
 +      bfd_add_request(p, SKIP_BACK(struct bfd_request, n, rn));
 +
 +      BFD_UNLOCK;
 +
 +      /* Remove sessions with no requests */
 +      HASH_WALK_DELSAFE(p->session_hash_id, next_id, s)
 +      {
 +      if (EMPTY_LIST(s->request_list))
 +        bfd_remove_session_locked(p, s);
 +      }
 +      HASH_WALK_END;
  
 -  WALK_LIST(n, bfd_proto_list)
 -    if (bfd_add_request(SKIP_BACK(struct bfd_proto, bfd_node, n), req))
 -      return;
 +      birdloop_leave(p->p.loop);
 +    }
  
 -  rem_node(&req->n);
 -  add_tail(&bfd_wait_list, &req->n);
 -  req->session = NULL;
 -  bfd_request_notify(req, BFD_STATE_ADMIN_DOWN, BFD_STATE_ADMIN_DOWN, 0);
 +    BFD_LOCK;
 +  } while (bfd_global.pickup_reload);
 +
 +  list tmp_list;
 +  init_list(&tmp_list);
 +  add_tail_list(&tmp_list, &bfd_global.pickup_list);
 +
 +  init_list(&bfd_global.pickup_list);
 +  BFD_UNLOCK;
 +
 +  log(L_TRACE "No protocol for %d BFD requests", list_length(&tmp_list));
 +
 +  node *n;
 +  WALK_LIST(n, tmp_list)
-     bfd_request_notify(SKIP_BACK(struct bfd_request, n, n), BFD_STATE_ADMIN_DOWN, 0);
++    bfd_request_notify(SKIP_BACK(struct bfd_request, n, n), BFD_STATE_ADMIN_DOWN, BFD_STATE_ADMIN_DOWN, 0);
 +
 +  BFD_LOCK;
 +  add_tail_list(&bfd_global.wait_list, &tmp_list);
 +  BFD_UNLOCK;
  }
  
 +static event bfd_pickup_event = { .hook = bfd_pickup_requests };
 +
  static void
  bfd_take_requests(struct bfd_proto *p)
  {
@@@ -1020,15 -917,21 +1020,15 @@@ bfd_reconfigure_neighbors(struct bfd_pr
  
  /* This core notify code should be replaced after main loop transition to birdloop */
  
 -int pipe(int pipefd[2]);
 -void pipe_drain(int fd);
 -void pipe_kick(int fd);
 -
 -static int
 -bfd_notify_hook(sock *sk, uint len UNUSED)
 +static void
 +bfd_notify_hook(void *data)
  {
 -  struct bfd_proto *p = sk->data;
 +  struct bfd_proto *p = data;
    struct bfd_session *s;
    list tmp_list;
-   u8 state, diag;
+   u8 loc_state, rem_state, diag;
    node *n, *nn;
  
 -  pipe_drain(sk->fd);
 -
    bfd_lock_sessions(p);
    init_list(&tmp_list);
    add_tail_list(&tmp_list, &p->notify_list);
      diag = s->loc_diag;
      bfd_unlock_sessions(p);
  
 -    s->notify_running = 1;
      WALK_LIST_DELSAFE(n, nn, s->request_list)
-       bfd_request_notify(SKIP_BACK(struct bfd_request, n, n), state, diag);
+       bfd_request_notify(SKIP_BACK(struct bfd_request, n, n), loc_state, rem_state, diag);
 -    s->notify_running = 0;
  
      /* Remove the session if all requests were removed in notify hooks */
      if (EMPTY_LIST(s->request_list))