0
0
mirror of https://gitlab.nic.cz/labs/bird.git synced 2024-12-31 14:11:54 +00:00

Neighbor cache: fixed neighbor referencing

This commit is contained in:
Maria Matejka 2024-11-10 13:33:22 +01:00
parent 03f51079c1
commit eb6918e4db
8 changed files with 87 additions and 15 deletions

View File

@ -262,7 +262,7 @@ if_enqueue_notify_to(struct iface_notification x, struct iface_subscription *s)
break; break;
case IFNOT_NEIGHBOR: case IFNOT_NEIGHBOR:
if (!s->neigh_notify) return; if (!s->neigh_notify) return;
neigh_link(x.n); neigh_link_locked(x.n);
break; break;
default: default:
bug("Unknown interface notification type: %d", x.type); bug("Unknown interface notification type: %d", x.type);
@ -583,9 +583,7 @@ iface_notify_hook(void *_s)
break; break;
case IFNOT_NEIGHBOR: case IFNOT_NEIGHBOR:
s->neigh_notify(n->n); s->neigh_notify(n->n);
IFACE_LOCK;
neigh_unlink(n->n); neigh_unlink(n->n);
IFACE_UNLOCK;
break; break;
default: default:
bug("Bad interface notification type: %d", n->type); bug("Bad interface notification type: %d", n->type);
@ -658,8 +656,6 @@ iface_unsubscribe(struct iface_subscription *s)
IFACE_LOCK; IFACE_LOCK;
SKIP_BACK_DECLARE(struct proto, p, iface_sub, s); SKIP_BACK_DECLARE(struct proto, p, iface_sub, s);
WALK_TLIST_DELSAFE(proto_neigh, n, &p->neighbors)
neigh_unlink(n);
ifsub_rem_node(&iface_sub_list, s); ifsub_rem_node(&iface_sub_list, s);
ev_postpone(&s->event); ev_postpone(&s->event);
@ -676,7 +672,7 @@ iface_unsubscribe(struct iface_subscription *s)
if_unlink(n->i); if_unlink(n->i);
break; break;
case IFNOT_NEIGHBOR: case IFNOT_NEIGHBOR:
neigh_unlink(n->n); neigh_unlink_locked(n->n);
break; break;
default: default:
bug("Bad interface notification type: %d", n->type); bug("Bad interface notification type: %d", n->type);
@ -686,6 +682,12 @@ iface_unsubscribe(struct iface_subscription *s)
sl_free(n); sl_free(n);
} }
WALK_TLIST_DELSAFE(proto_neigh, n, &p->neighbors)
{
log(L_WARN "%s: Unlinking forgotten neighbor %I", p->name, n->addr);
neigh_unlink_locked(n);
}
ASSERT_DIE(EMPTY_TLIST(proto_neigh, &p->neighbors)); ASSERT_DIE(EMPTY_TLIST(proto_neigh, &p->neighbors));
IFACE_UNLOCK; IFACE_UNLOCK;

View File

@ -10,6 +10,7 @@
#define _BIRD_IFACE_H_ #define _BIRD_IFACE_H_
#include "lib/locking.h" #include "lib/locking.h"
#include "lib/defer.h"
#include "lib/event.h" #include "lib/event.h"
#include "lib/lists.h" #include "lib/lists.h"
#include "lib/tlists.h" #include "lib/tlists.h"
@ -178,6 +179,27 @@ void neigh_init(struct pool *);
void neigh_link(neighbor *); void neigh_link(neighbor *);
void neigh_unlink(neighbor *); void neigh_unlink(neighbor *);
struct neigh_unlink_deferred {
struct deferred_call dc;
neighbor *n;
};
void neigh_unlink_deferred(struct deferred_call *dc);
static inline void neigh_unlink_later(neighbor *n)
{
struct neigh_unlink_deferred nud = {
.dc.hook = neigh_unlink_deferred,
.n = n,
};
defer_call(&nud.dc, sizeof nud);
}
/* For internal use */
void neigh_link_locked(neighbor *);
void neigh_unlink_locked(neighbor *);
/* /*
* Notification mechanism * Notification mechanism
*/ */

View File

@ -283,7 +283,8 @@ neigh_find(struct proto *p, ip_addr a, struct iface *iface, uint flags)
n->flags = flags; n->flags = flags;
n->scope = scope; n->scope = scope;
neigh_link(n); neigh_link_locked(n);
neigh_unlink_later(n);
IFACE_UNLOCK; IFACE_UNLOCK;
return n; return n;
@ -378,14 +379,14 @@ neigh_down(neighbor *n)
} }
void void
neigh_link(neighbor *n) neigh_link_locked(neighbor *n)
{ {
IFACE_ASSERT_LOCKED; IFACE_ASSERT_LOCKED;
n->uc++; n->uc++;
} }
void void
neigh_unlink(neighbor *n) neigh_unlink_locked(neighbor *n)
{ {
IFACE_ASSERT_LOCKED; IFACE_ASSERT_LOCKED;
if (--n->uc) if (--n->uc)
@ -409,6 +410,27 @@ neigh_unlink(neighbor *n)
sl_free(n); sl_free(n);
} }
void
neigh_link(neighbor *n)
{
IFACE_LOCK;
neigh_link_locked(n);
IFACE_UNLOCK;
}
void
neigh_unlink(neighbor *n)
{
IFACE_LOCK;
neigh_unlink_locked(n);
IFACE_UNLOCK;
}
void neigh_unlink_deferred(struct deferred_call *dc)
{
neigh_unlink(SKIP_BACK(struct neigh_unlink_deferred, dc, dc)->n);
}
/** /**
* neigh_update: update neighbor entry w.r.t. change on specific iface * neigh_update: update neighbor entry w.r.t. change on specific iface
* @n: neighbor to update * @n: neighbor to update
@ -472,7 +494,7 @@ neigh_update(neighbor *n, struct iface *iface)
if ((n->scope < 0) && !(n->flags & NEF_STICKY)) if ((n->scope < 0) && !(n->flags & NEF_STICKY))
{ {
neigh_unlink(n); neigh_unlink_locked(n);
return; return;
} }

View File

@ -1291,13 +1291,17 @@ proto_event(void *ptr)
if (p->do_stop) if (p->do_stop)
{ {
iface_unsubscribe(&p->iface_sub);
p->do_stop = 0; p->do_stop = 0;
} }
if (proto_is_done(p) && p->pool_inloop) /* perusing pool_inloop to do this once only */ if (proto_is_done(p) && p->pool_inloop) /* perusing pool_inloop to do this once only */
{ {
/* Interface notification unsubscribe can't be done
* before the protocol is really done, as it also destroys
* the neighbors which may be needed (e.g. by BGP->MRT)
* during the STOP phase as well. */
iface_unsubscribe(&p->iface_sub);
rp_free(p->pool_inloop); rp_free(p->pool_inloop);
p->pool_inloop = NULL; p->pool_inloop = NULL;
if (p->loop != &main_birdloop) if (p->loop != &main_birdloop)

View File

@ -994,6 +994,8 @@ bfd_start_neighbor(struct bfd_proto *p, struct bfd_neighbor *n)
return; return;
} }
neigh_link(nb);
n->neigh = nb; n->neigh = nb;
nb->data = n; nb->data = n;
@ -1007,8 +1009,11 @@ static void
bfd_stop_neighbor(struct bfd_proto *p UNUSED, struct bfd_neighbor *n) bfd_stop_neighbor(struct bfd_proto *p UNUSED, struct bfd_neighbor *n)
{ {
if (n->neigh) if (n->neigh)
{
n->neigh->data = NULL; n->neigh->data = NULL;
n->neigh = NULL; neigh_unlink(n->neigh);
n->neigh = NULL;
}
rfree(n->req); rfree(n->req);
n->req = NULL; n->req = NULL;

View File

@ -588,7 +588,11 @@ bgp_down(struct bgp_proto *p)
bgp_close(p); bgp_close(p);
} }
p->neigh = NULL; if (p->neigh)
{
neigh_unlink(p->neigh);
p->neigh = NULL;
}
BGP_TRACE(D_EVENTS, "Down"); BGP_TRACE(D_EVENTS, "Down");
proto_notify_state(&p->p, PS_DOWN); proto_notify_state(&p->p, PS_DOWN);
@ -1749,6 +1753,7 @@ bgp_start_locked(void *_p)
} }
p->neigh = n; p->neigh = n;
neigh_link(n);
if (n->scope <= 0) if (n->scope <= 0)
BGP_TRACE(D_EVENTS, "Waiting for %I%J to become my neighbor", p->remote_ip, cf->iface); BGP_TRACE(D_EVENTS, "Waiting for %I%J to become my neighbor", p->remote_ip, cf->iface);

View File

@ -454,6 +454,8 @@ rip_get_neighbor(struct rip_proto *p, ip_addr *a, struct rip_iface *ifa)
struct rip_neighbor *n = mb_allocz(p->p.pool, sizeof(struct rip_neighbor)); struct rip_neighbor *n = mb_allocz(p->p.pool, sizeof(struct rip_neighbor));
n->ifa = ifa; n->ifa = ifa;
n->nbr = nbr; n->nbr = nbr;
neigh_link(nbr);
nbr->data = n; nbr->data = n;
n->csn = nbr->aux; n->csn = nbr->aux;
@ -475,6 +477,8 @@ rip_remove_neighbor(struct rip_proto *p, struct rip_neighbor *n)
nbr->data = NULL; nbr->data = NULL;
nbr->aux = n->csn; nbr->aux = n->csn;
neigh_unlink(nbr);
rfree(n->bfd_req); rfree(n->bfd_req);
n->bfd_req = NULL; n->bfd_req = NULL;
n->last_seen = 0; n->last_seen = 0;

View File

@ -302,6 +302,8 @@ static_add_rte(struct static_proto *p, struct static_route *r)
continue; continue;
} }
neigh_link(n);
r2->neigh = n; r2->neigh = n;
r2->chain = n->data; r2->chain = n->data;
n->data = r2; n->data = r2;
@ -321,7 +323,13 @@ static_reset_rte(struct static_proto *p UNUSED, struct static_route *r)
for (r2 = r; r2; r2 = r2->mp_next) for (r2 = r; r2; r2 = r2->mp_next)
{ {
r2->neigh = NULL; if (r2->neigh)
{
r2->neigh->data = NULL;
neigh_unlink(r2->neigh);
r2->neigh = NULL;
}
r2->chain = NULL; r2->chain = NULL;
r2->state = 0; r2->state = 0;