diff options
-rw-r--r-- | usr.sbin/bgpd/rde.c | 31 | ||||
-rw-r--r-- | usr.sbin/bgpd/rde.h | 16 | ||||
-rw-r--r-- | usr.sbin/bgpd/rde_decide.c | 13 | ||||
-rw-r--r-- | usr.sbin/bgpd/rde_rib.c | 59 |
4 files changed, 79 insertions, 40 deletions
diff --git a/usr.sbin/bgpd/rde.c b/usr.sbin/bgpd/rde.c index 3d42f8b1407..f876984be1f 100644 --- a/usr.sbin/bgpd/rde.c +++ b/usr.sbin/bgpd/rde.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rde.c,v 1.192 2006/01/13 13:04:33 claudio Exp $ */ +/* $OpenBSD: rde.c,v 1.193 2006/01/14 22:39:49 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -722,7 +722,8 @@ rde_update_dispatch(struct imsg *imsg) } rde_update_log("withdraw", peer, NULL, &prefix, prefixlen); - prefix_remove(peer, &prefix, prefixlen); + prefix_remove(peer, &prefix, prefixlen, F_LOCAL); + prefix_remove(peer, &prefix, prefixlen, F_ORIGINAL); } if (attrpath_len == 0) /* 0 = no NLRI information in this message */ @@ -774,7 +775,10 @@ rde_update_dispatch(struct imsg *imsg) rde_update_log("withdraw", peer, NULL, &prefix, prefixlen); - prefix_remove(peer, &prefix, prefixlen); + prefix_remove(peer, &prefix, prefixlen, + F_LOCAL); + prefix_remove(peer, &prefix, prefixlen, + F_ORIGINAL); } break; default: @@ -1473,7 +1477,9 @@ rde_dump_upcall(struct pt_entry *pt, void *ptr) memcpy(&pid, ptr, sizeof(pid)); LIST_FOREACH(p, &pt->prefix_h, prefix_l) - rde_dump_rib_as(p, pid); + /* for now dump only stuff from the local-RIB */ + if (p->flags & F_LOCAL) + rde_dump_rib_as(p, pid); } void @@ -1490,7 +1496,9 @@ rde_dump_as(struct filter_as *a, pid_t pid) continue; /* match found */ LIST_FOREACH(p, &asp->prefix_h, path_l) - rde_dump_rib_as(p, pid); + /* for now dump only stuff from the local-RIB */ + if (p->flags & F_LOCAL) + rde_dump_rib_as(p, pid); } } } @@ -1512,7 +1520,9 @@ rde_dump_prefix_upcall(struct pt_entry *pt, void *ptr) return; if (!prefix_compare(&ctl->pref->prefix, &addr, ctl->pref->prefixlen)) LIST_FOREACH(p, &pt->prefix_h, prefix_l) - rde_dump_rib_as(p, ctl->pid); + /* for now dump only stuff from the local-RIB */ + if (p->flags & F_LOCAL) + rde_dump_rib_as(p, ctl->pid); } void @@ -2173,10 +2183,15 @@ network_add(struct network_config *nc, int flagstatic) void network_delete(struct network_config *nc, int flagstatic) { + struct rde_peer *p; + if (flagstatic) - prefix_remove(&peerself, &nc->prefix, nc->prefixlen); + p = &peerself; else - prefix_remove(&peerdynamic, &nc->prefix, nc->prefixlen); + p = &peerdynamic; + + prefix_remove(p, &nc->prefix, nc->prefixlen, F_LOCAL); + prefix_remove(p, &nc->prefix, nc->prefixlen, F_ORIGINAL); } void diff --git a/usr.sbin/bgpd/rde.h b/usr.sbin/bgpd/rde.h index b40a897718a..fa9c50e81c5 100644 --- a/usr.sbin/bgpd/rde.h +++ b/usr.sbin/bgpd/rde.h @@ -1,4 +1,4 @@ -/* $OpenBSD: rde.h,v 1.82 2006/01/12 14:05:13 claudio Exp $ */ +/* $OpenBSD: rde.h,v 1.83 2006/01/14 22:39:49 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org> and @@ -148,6 +148,9 @@ LIST_HEAD(prefix_head, prefix); #define F_NEXTHOP_BLACKHOLE 0x0400 #define F_NEXTHOP_NOMODIFY 0x0800 #define F_ATTR_LINKED 0x1000 +#define F_LOCAL 0x2000 /* Local-RIB */ +#define F_ORIGINAL 0x4000 /* Adj-RIB-In */ + #define ORIGIN_IGP 0 #define ORIGIN_EGP 1 @@ -303,12 +306,15 @@ void path_put(struct rde_aspath *); #define PREFIX_SIZE(x) (((x) + 7) / 8 + 1) int prefix_compare(const struct bgpd_addr *, const struct bgpd_addr *, int); -struct prefix *prefix_get(struct rde_peer *, struct bgpd_addr *, int); -struct pt_entry *prefix_add(struct rde_aspath *, struct bgpd_addr *, int); +struct prefix *prefix_get(struct rde_peer *, struct bgpd_addr *, int, + u_int32_t); +struct pt_entry *prefix_add(struct rde_aspath *, struct bgpd_addr *, int, + u_int32_t); struct pt_entry *prefix_move(struct rde_aspath *, struct prefix *); -void prefix_remove(struct rde_peer *, struct bgpd_addr *, int); +void prefix_remove(struct rde_peer *, struct bgpd_addr *, int, + u_int32_t); int prefix_write(u_char *, int, struct bgpd_addr *, u_int8_t); -struct prefix *prefix_bypeer(struct pt_entry *, struct rde_peer *); +struct prefix *prefix_bypeer(struct pt_entry *, struct rde_peer *, u_int32_t); void prefix_updateall(struct rde_aspath *, enum nexthop_state); void prefix_destroy(struct prefix *); void prefix_network_clean(struct rde_peer *, time_t); diff --git a/usr.sbin/bgpd/rde_decide.c b/usr.sbin/bgpd/rde_decide.c index e4895538c07..8e2cbe06d97 100644 --- a/usr.sbin/bgpd/rde_decide.c +++ b/usr.sbin/bgpd/rde_decide.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rde_decide.c,v 1.45 2006/01/13 13:04:33 claudio Exp $ */ +/* $OpenBSD: rde_decide.c,v 1.46 2006/01/14 22:39:49 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org> @@ -115,6 +115,12 @@ prefix_cmp(struct prefix *p1, struct prefix *p2) if (p2 == NULL) return (1); + /* only prefix in the Local-RIB are eligible */ + if (!(p1->flags & F_LOCAL)) + return (-1); + if (!(p2->flags & F_LOCAL)) + return (1); + asp1 = p1->aspath; asp2 = p2->aspath; @@ -232,8 +238,9 @@ prefix_evaluate(struct prefix *p, struct pt_entry *pte) } xp = LIST_FIRST(&pte->prefix_h); - if (xp == NULL || (xp->aspath->nexthop != NULL && - xp->aspath->nexthop->state != NEXTHOP_REACH)) + if (xp == NULL || !(xp->flags & F_LOCAL) || + (xp->aspath->nexthop != NULL && xp->aspath->nexthop->state != + NEXTHOP_REACH)) /* xp is ineligible */ xp = NULL; diff --git a/usr.sbin/bgpd/rde_rib.c b/usr.sbin/bgpd/rde_rib.c index 41548ef65b4..b8bf8041028 100644 --- a/usr.sbin/bgpd/rde_rib.c +++ b/usr.sbin/bgpd/rde_rib.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rde_rib.c,v 1.77 2006/01/12 14:05:13 claudio Exp $ */ +/* $OpenBSD: rde_rib.c,v 1.78 2006/01/14 22:39:49 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org> @@ -84,7 +84,7 @@ path_update(struct rde_peer *peer, struct rde_aspath *nasp, rde_send_pftable(nasp->pftableid, prefix, prefixlen, 0); rde_send_pftable_commit(); - if ((p = prefix_get(peer, prefix, prefixlen)) != NULL) { + if ((p = prefix_get(peer, prefix, prefixlen, F_LOCAL)) != NULL) { if (path_compare(nasp, p->aspath) == 0) { /* update last change */ p->lastchange = time(NULL); @@ -107,7 +107,7 @@ path_update(struct rde_peer *peer, struct rde_aspath *nasp, if (p != NULL) prefix_move(asp, p); else - prefix_add(asp, prefix, prefixlen); + prefix_add(asp, prefix, prefixlen, F_LOCAL); } int @@ -313,7 +313,7 @@ path_put(struct rde_aspath *asp) static struct prefix *prefix_alloc(void); static void prefix_free(struct prefix *); static void prefix_link(struct prefix *, struct pt_entry *, - struct rde_aspath *); + struct rde_aspath *, u_int32_t); static void prefix_unlink(struct prefix *); int @@ -360,47 +360,44 @@ prefix_compare(const struct bgpd_addr *a, const struct bgpd_addr *b, * search for specified prefix of a peer. Returns NULL if not found. */ struct prefix * -prefix_get(struct rde_peer *peer, struct bgpd_addr *prefix, int prefixlen) +prefix_get(struct rde_peer *peer, struct bgpd_addr *prefix, int prefixlen, + u_int32_t flags) { struct pt_entry *pte; pte = pt_get(prefix, prefixlen); if (pte == NULL) return (NULL); - return (prefix_bypeer(pte, peer)); + return (prefix_bypeer(pte, peer, flags)); } /* * Adds or updates a prefix. */ struct pt_entry * -prefix_add(struct rde_aspath *asp, struct bgpd_addr *prefix, int prefixlen) +prefix_add(struct rde_aspath *asp, struct bgpd_addr *prefix, int prefixlen, + u_int32_t flags) { struct prefix *p; struct pt_entry *pte; - int needlink = 0; pte = pt_get(prefix, prefixlen); if (pte == NULL) pte = pt_add(prefix, prefixlen); - p = prefix_bypeer(pte, asp->peer); + p = prefix_bypeer(pte, asp->peer, flags); if (p == NULL) { - needlink = 1; p = prefix_alloc(); - } - - if (needlink == 1) - prefix_link(p, pte, asp); - else { + prefix_link(p, pte, asp, flags); + } else { if (p->aspath != asp) /* prefix belongs to a different aspath so move */ - return prefix_move(asp, p); + return (prefix_move(asp, p)); p->lastchange = time(NULL); } - return pte; + return (pte); } /* @@ -421,6 +418,7 @@ prefix_move(struct rde_aspath *asp, struct prefix *p) /* peer and prefix pointers are still equal */ np->prefix = p->prefix; np->lastchange = time(NULL); + np->flags = p->flags; /* add to new as path */ LIST_INSERT_HEAD(&asp->prefix_h, np, path_l); @@ -464,7 +462,8 @@ prefix_move(struct rde_aspath *asp, struct prefix *p) * pt_entry -- become empty remove them too. */ void -prefix_remove(struct rde_peer *peer, struct bgpd_addr *prefix, int prefixlen) +prefix_remove(struct rde_peer *peer, struct bgpd_addr *prefix, int prefixlen, + u_int32_t flags) { struct prefix *p; struct pt_entry *pte; @@ -474,14 +473,17 @@ prefix_remove(struct rde_peer *peer, struct bgpd_addr *prefix, int prefixlen) if (pte == NULL) /* Got a dummy withdrawn request */ return; - p = prefix_bypeer(pte, peer); + p = prefix_bypeer(pte, peer, flags); if (p == NULL) /* Got a dummy withdrawn request. */ return; asp = p->aspath; - rde_send_pftable(asp->pftableid, prefix, prefixlen, 1); - rde_send_pftable_commit(); + if (p->flags & F_LOCAL) { + /* only prefixes in the local RIB were pushed into pf */ + rde_send_pftable(asp->pftableid, prefix, prefixlen, 1); + rde_send_pftable_commit(); + } prefix_unlink(p); prefix_free(p); @@ -515,12 +517,12 @@ prefix_write(u_char *buf, int len, struct bgpd_addr *prefix, u_int8_t plen) * belonging to the peer peer. Returns NULL if no match found. */ struct prefix * -prefix_bypeer(struct pt_entry *pte, struct rde_peer *peer) +prefix_bypeer(struct pt_entry *pte, struct rde_peer *peer, u_int32_t flags) { struct prefix *p; LIST_FOREACH(p, &pte->prefix_h, prefix_l) { - if (p->aspath->peer == peer) + if (p->aspath->peer == peer && p->flags & flags) return (p); } return (NULL); @@ -536,6 +538,13 @@ prefix_updateall(struct rde_aspath *asp, enum nexthop_state state) return; LIST_FOREACH(p, &asp->prefix_h, path_l) { + /* + * skip non local-RIB nodes, only local-RIB prefixes are + * eligible. Both F_LOCAL and F_ORIGINAL may be set. + */ + if (!(p->flags & F_LOCAL)) + continue; + /* redo the route decision */ LIST_REMOVE(p, prefix_l); /* @@ -598,7 +607,8 @@ prefix_network_clean(struct rde_peer *peer, time_t reloadtime) * Link a prefix into the different parent objects. */ static void -prefix_link(struct prefix *pref, struct pt_entry *pte, struct rde_aspath *asp) +prefix_link(struct prefix *pref, struct pt_entry *pte, struct rde_aspath *asp, + u_int32_t flags) { LIST_INSERT_HEAD(&asp->prefix_h, pref, path_l); asp->prefix_cnt++; @@ -607,6 +617,7 @@ prefix_link(struct prefix *pref, struct pt_entry *pte, struct rde_aspath *asp) pref->aspath = asp; pref->prefix = pte; pref->lastchange = time(NULL); + pref->flags = flags; /* make route decision */ prefix_evaluate(pref, pte); |