-/* $OpenBSD: rde.c,v 1.592 2023/02/09 13:43:23 claudio Exp $ */
+/* $OpenBSD: rde.c,v 1.593 2023/02/13 18:07:53 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
static void
rde_softreconfig_out(struct rib_entry *re, void *arg)
{
- struct rib *rib = arg;
- struct prefix *p;
-
- if ((p = prefix_best(re)) == NULL)
+ if (prefix_best(re) == NULL)
/* no valid path for prefix */
return;
- rde_generate_updates(rib, p, NULL, NULL, NULL, EVAL_RECONF);
+ rde_generate_updates(re, NULL, NULL, EVAL_RECONF);
}
static void
-/* $OpenBSD: rde.h,v 1.282 2023/02/09 13:43:23 claudio Exp $ */
+/* $OpenBSD: rde.h,v 1.283 2023/02/13 18:07:53 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org> and
void rde_pftable_del(uint16_t, struct prefix *);
int rde_evaluate_all(void);
-void rde_generate_updates(struct rib *, struct prefix *,
- struct prefix *, struct prefix *, struct prefix *,
- enum eval_mode);
uint32_t rde_local_as(void);
int rde_decisionflags(void);
void rde_peer_send_rrefresh(struct rde_peer *, uint8_t, uint8_t);
struct rde_peer *peer_match(struct ctl_neighbor *, uint32_t);
struct rde_peer *peer_add(uint32_t, struct peer_config *);
+void rde_generate_updates(struct rib_entry *, struct prefix *,
+ struct prefix *, enum eval_mode);
+
void peer_up(struct rde_peer *, struct session_up *);
void peer_down(struct rde_peer *, void *);
void peer_flush(struct rde_peer *, uint8_t, time_t);
/* rde_update.c */
void up_init(struct rde_peer *);
void up_generate_updates(struct filter_head *, struct rde_peer *,
- struct prefix *, struct prefix *);
+ struct rib_entry *);
void up_generate_addpath(struct filter_head *, struct rde_peer *,
- struct prefix *, struct prefix *);
+ struct rib_entry *);
void up_generate_addpath_all(struct filter_head *,
- struct rde_peer *, struct prefix *, struct prefix *,
+ struct rde_peer *, struct rib_entry *, struct prefix *,
struct prefix *);
void up_generate_default(struct filter_head *, struct rde_peer *,
uint8_t);
-/* $OpenBSD: rde_decide.c,v 1.98 2022/09/23 15:49:20 claudio Exp $ */
+/* $OpenBSD: rde_decide.c,v 1.99 2023/02/13 18:07:53 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org>
* but remember that newbest may be NULL aka ineligible.
* Additional decision may be made by the called functions.
*/
- rde_generate_updates(rib, newbest, oldbest, new, old,
- EVAL_DEFAULT);
if ((rib->flags & F_RIB_NOFIB) == 0)
rde_send_kroute(rib, newbest, oldbest);
+ rde_generate_updates(re, new, old, EVAL_DEFAULT);
return;
}
*/
if (rde_evaluate_all())
if ((new != NULL && prefix_eligible(new)) || old != NULL)
- rde_generate_updates(rib, newbest, NULL, new, old,
- EVAL_ALL);
+ rde_generate_updates(re, new, old, EVAL_ALL);
}
void
* but remember that newbest may be NULL aka ineligible.
* Additional decision may be made by the called functions.
*/
- rde_generate_updates(rib, newbest, oldbest, p, p, EVAL_DEFAULT);
if ((rib->flags & F_RIB_NOFIB) == 0)
rde_send_kroute(rib, newbest, oldbest);
+ rde_generate_updates(re, p, p, EVAL_DEFAULT);
return;
}
* rde_generate_updates() will then take care of distribution.
*/
if (rde_evaluate_all())
- rde_generate_updates(rib, newbest, NULL, p, p, EVAL_ALL);
+ rde_generate_updates(re, p, p, EVAL_ALL);
}
-/* $OpenBSD: rde_peer.c,v 1.28 2023/02/09 13:43:23 claudio Exp $ */
+/* $OpenBSD: rde_peer.c,v 1.29 2023/02/13 18:07:53 claudio Exp $ */
/*
* Copyright (c) 2019 Claudio Jeker <claudio@openbsd.org>
RB_GENERATE(peer_tree, rde_peer, entry, peer_cmp);
static void
-peer_generate_update(struct rde_peer *peer, uint16_t rib_id,
- struct prefix *newbest, struct prefix *oldbest,
+peer_generate_update(struct rde_peer *peer, struct rib_entry *re,
struct prefix *newpath, struct prefix *oldpath,
enum eval_mode mode)
{
uint8_t aid;
- if (newbest != NULL)
- aid = newbest->pt->aid;
- else if (oldbest != NULL)
- aid = oldbest->pt->aid;
- else if (newpath != NULL)
- aid = newpath->pt->aid;
- else if (oldpath != NULL)
- aid = oldpath->pt->aid;
- else
- return;
+ aid = re->prefix->aid;
/* skip ourself */
if (peer == peerself)
if (peer->state != PEER_UP)
return;
/* skip peers using a different rib */
- if (peer->loc_rib_id != rib_id)
+ if (peer->loc_rib_id != re->rib_id)
return;
/* check if peer actually supports the address family */
if (peer->capa.mp[aid] == 0)
/* handle peers with add-path */
if (peer_has_add_path(peer, aid, CAPA_AP_SEND)) {
if (peer->eval.mode == ADDPATH_EVAL_ALL)
- up_generate_addpath_all(out_rules, peer, newbest,
+ up_generate_addpath_all(out_rules, peer, re,
newpath, oldpath);
else
- up_generate_addpath(out_rules, peer, newbest, oldbest);
+ up_generate_addpath(out_rules, peer, re);
return;
}
/* skip regular peers if the best path didn't change */
if (mode == EVAL_ALL && (peer->flags & PEERFLAG_EVALUATE_ALL) == 0)
return;
- up_generate_updates(out_rules, peer, newbest, oldbest);
+ up_generate_updates(out_rules, peer, re);
}
void
-rde_generate_updates(struct rib *rib, struct prefix *newbest,
- struct prefix *oldbest, struct prefix *newpath, struct prefix *oldpath,
- enum eval_mode mode)
+rde_generate_updates(struct rib_entry *re, struct prefix *newpath,
+ struct prefix *oldpath, enum eval_mode mode)
{
struct rde_peer *peer;
- /*
- * If oldbest is != NULL we know it was active and should be removed.
- * If newbest is != NULL we know it is reachable and then we should
- * generate an update.
- */
- if (oldbest == NULL && newbest == NULL)
- return;
-
RB_FOREACH(peer, peer_tree, &peertable)
- peer_generate_update(peer, rib->id, newbest, oldbest, newpath,
- oldpath, mode);
+ peer_generate_update(peer, re, newpath, oldpath, mode);
}
/*
if ((p = prefix_best(re)) == NULL)
/* no eligible prefix, not even for 'evaluate all' */
return;
- peer_generate_update(peer, re->rib_id, p, NULL, NULL, NULL, 0);
+ peer_generate_update(peer, re, NULL, NULL, 0);
}
static void
-/* $OpenBSD: rde_update.c,v 1.155 2023/02/11 08:50:43 claudio Exp $ */
+/* $OpenBSD: rde_update.c,v 1.156 2023/02/13 18:07:53 claudio Exp $ */
/*
* Copyright (c) 2004 Claudio Jeker <claudio@openbsd.org>
void
up_generate_updates(struct filter_head *rules, struct rde_peer *peer,
- struct prefix *new, struct prefix *old)
+ struct rib_entry *re)
{
struct bgpd_addr addr;
- struct prefix *p;
+ struct prefix *new, *p;
uint8_t prefixlen;
- if (new == NULL) {
- pt_getaddr(old->pt, &addr);
- prefixlen = old->pt->prefixlen;
- } else {
- pt_getaddr(new->pt, &addr);
- prefixlen = new->pt->prefixlen;
- }
+ pt_getaddr(re->prefix, &addr);
+ prefixlen = re->prefix->prefixlen;
p = prefix_adjout_lookup(peer, &addr, prefixlen);
+ new = prefix_best(re);
while (new != NULL) {
switch (up_process_prefix(rules, peer, new, p,
&addr, prefixlen)) {
*/
void
up_generate_addpath(struct filter_head *rules, struct rde_peer *peer,
- struct prefix *new, struct prefix *old)
+ struct rib_entry *re)
{
struct bgpd_addr addr;
- struct prefix *head, *p;
+ struct prefix *head, *new, *p;
uint8_t prefixlen;
int maxpaths = 0, extrapaths = 0, extra;
int checkmode = 1;
- if (new == NULL) {
- pt_getaddr(old->pt, &addr);
- prefixlen = old->pt->prefixlen;
- } else {
- pt_getaddr(new->pt, &addr);
- prefixlen = new->pt->prefixlen;
- }
+ pt_getaddr(re->prefix, &addr);
+ prefixlen = re->prefix->prefixlen;
head = prefix_adjout_lookup(peer, &addr, prefixlen);
p->flags |= PREFIX_FLAG_STALE;
/* update paths */
- for ( ; new != NULL; new = TAILQ_NEXT(new, entry.list.rib)) {
- /* since list is sorted, stop at first invalid prefix */
- if (!prefix_eligible(new))
- break;
-
+ new = prefix_best(re);
+ while (new != NULL) {
/* check limits and stop when a limit is reached */
if (peer->eval.maxpaths != 0 &&
maxpaths >= peer->eval.maxpaths)
/* just give up */
return;
}
+
+ /* only allow valid prefixes */
+ new = TAILQ_NEXT(new, entry.list.rib);
+ if (new == NULL || !prefix_eligible(new))
+ break;
}
/* withdraw stale paths */
*/
void
up_generate_addpath_all(struct filter_head *rules, struct rde_peer *peer,
- struct prefix *best, struct prefix *new, struct prefix *old)
+ struct rib_entry *re, struct prefix *new, struct prefix *old)
{
struct bgpd_addr addr;
- struct prefix *p, *next, *head = NULL;
+ struct prefix *p, *head = NULL;
uint8_t prefixlen;
int all = 0;
+ pt_getaddr(re->prefix, &addr);
+ prefixlen = re->prefix->prefixlen;
+
/*
* if old and new are NULL then insert all prefixes from best,
* clearing old routes in the process
*/
if (old == NULL && new == NULL) {
/* mark all paths as stale */
- pt_getaddr(best->pt, &addr);
- prefixlen = best->pt->prefixlen;
-
head = prefix_adjout_lookup(peer, &addr, prefixlen);
for (p = head; p != NULL; p = prefix_adjout_next(peer, p))
p->flags |= PREFIX_FLAG_STALE;
- new = best;
+ new = prefix_best(re);
all = 1;
}
if (old != NULL) {
/* withdraw stale paths */
- pt_getaddr(old->pt, &addr);
- p = prefix_adjout_get(peer, old->path_id_tx, &addr,
- old->pt->prefixlen);
+ p = prefix_adjout_get(peer, old->path_id_tx, &addr, prefixlen);
if (p != NULL)
prefix_adjout_withdraw(p);
}
- if (new != NULL) {
- pt_getaddr(new->pt, &addr);
- prefixlen = new->pt->prefixlen;
- }
-
/* add new path (or multiple if all is set) */
- for (; new != NULL; new = next) {
- if (all)
- next = TAILQ_NEXT(new, entry.list.rib);
- else
- next = NULL;
-
- /* only allow valid prefixes */
- if (!prefix_eligible(new))
- break;
-
+ while (new != NULL) {
switch (up_process_prefix(rules, peer, new, (void *)-1,
&addr, prefixlen)) {
case UP_OK:
/* just give up */
return;
}
+
+ if (!all)
+ break;
+
+ /* only allow valid prefixes */
+ new = TAILQ_NEXT(new, entry.list.rib);
+ if (new == NULL || !prefix_eligible(new))
+ break;
}
if (all) {