Commit 127862f6 authored by Maria Matejka's avatar Maria Matejka
Browse files

Asynchronous neighbor notifications fixes

parent 0f6ea957
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -153,6 +153,7 @@ typedef struct neighbor {
#define NEF_STICKY	1
#define NEF_ONLINK	2
#define NEF_IFACE	4		/* Entry for whole iface */
#define NEF_NOTIFY_MAIN	0x100		/* Notify from main_birdloop context */


neighbor *neigh_find(struct proto *p, ip_addr a, struct iface *ifa, uint flags);
+36 −5
Original line number Diff line number Diff line
@@ -60,6 +60,7 @@
static slab *neigh_slab;
static list neigh_hash_table[NEIGH_HASH_SIZE], sticky_neigh_list;
static void neigh_do_notify(void *);
static void neigh_do_notify_main(void *);

static inline uint
neigh_hash(struct proto *p, ip_addr a, struct iface *i)
@@ -270,15 +271,29 @@ neigh_find(struct proto *p, ip_addr a, struct iface *iface, uint flags)
  n->proto = p;
  n->flags = flags;
  n->scope = scope;
  n->event = (event) { .hook = neigh_do_notify, .data = n };

  ASSERT_DIE(birdloop_inside(p->loop));

  if (p->loop == &main_birdloop)
    n->event.list = &global_event_list;
  if (flags & NEF_NOTIFY_MAIN)
    n->event = (event) {
      .hook = neigh_do_notify_main,
      .data = n,
      .list = &global_event_list,
    };
  else if (p->loop == &main_birdloop)
    n->event = (event) {
      .hook = neigh_do_notify,
      .data = n,
      .list = &global_event_list,
    };
  else
  {
    birdloop_link(p->loop);
    n->event.list = birdloop_event_list(p->loop);
    n->event = (event) {
      .hook = neigh_do_notify,
      .data = n,
      .list = birdloop_event_list(p->loop),
    };
  }

  IFACE_UNLOCK;
@@ -340,6 +355,14 @@ neigh_notify(neighbor *n)
  ev_send(n->event.list, &n->event);
}

static void
neigh_do_notify_main(void *data)
{
  neighbor *n = data;
  PROTO_LOCKED_FROM_MAIN(n->proto)
    neigh_do_notify(data);
}

static void
neigh_do_notify(void *data)
{
@@ -382,10 +405,18 @@ neigh_down(neighbor *n)
static inline void
neigh_free(neighbor *n)
{
  ASSERT_DIE(birdloop_inside(n->proto->loop));

  if (n->flags & NEF_NOTIFY_MAIN)
    ASSERT_DIE(birdloop_inside(&main_birdloop));

  rem_node(&n->n);
  rem_node(&n->if_n);
  ev_postpone(&n->event);

  if (n->event.list != &global_event_list)
    birdloop_unlink(n->proto->loop);

  ev_postpone(&n->event);
  sl_free(neigh_slab, n);
}

+1 −1
Original line number Diff line number Diff line
@@ -1541,7 +1541,7 @@ bgp_start_locked(struct object_lock *lock)
    return;
  }

  neighbor *n = neigh_find(&p->p, p->remote_ip, cf->iface, NEF_STICKY);
  neighbor *n = neigh_find(&p->p, p->remote_ip, cf->iface, NEF_STICKY | NEF_NOTIFY_MAIN);
  if (!n)
  {
    log(L_ERR "%s: Invalid remote address %I%J", p->p.name, p->remote_ip, cf->iface);
+4 −2
Original line number Diff line number Diff line
@@ -498,7 +498,9 @@ void
birdloop_unlink(struct birdloop *loop)
{
  ASSERT_DIE(birdloop_inside(loop));
  loop->links--;
  ASSERT_DIE(loop->links);
  if (!--loop->links)
    birdloop_ping(loop);
}

static void
@@ -541,7 +543,7 @@ birdloop_main(void *arg)

    birdloop_enter(loop);

    if (loop->stopped)
    if (loop->stopped && !loop->links)
      break;

    loop_begin = current_time();