diff options
author | Claudio Jeker <claudio@cvs.openbsd.org> | 2006-08-23 08:13:05 +0000 |
---|---|---|
committer | Claudio Jeker <claudio@cvs.openbsd.org> | 2006-08-23 08:13:05 +0000 |
commit | ae64b77bf4c8892086dffe7f47515b2fd04d0f1d (patch) | |
tree | 9f37556320791fc746d0db017d23a0e8de183b74 | |
parent | ce7a8ba8c04f6be11323324c248d6e8299d590fc (diff) |
Extend show rib interface code so that it is possible to show the adj-rib-in
and adj-rib-out. Additionally it is now possible to limit the output to a
specified peer. OK henning@
-rw-r--r-- | usr.sbin/bgpd/bgpd.h | 6 | ||||
-rw-r--r-- | usr.sbin/bgpd/control.c | 43 | ||||
-rw-r--r-- | usr.sbin/bgpd/rde.c | 115 |
3 files changed, 129 insertions, 35 deletions
diff --git a/usr.sbin/bgpd/bgpd.h b/usr.sbin/bgpd/bgpd.h index f3d83ce7db7..38d719cf7d8 100644 --- a/usr.sbin/bgpd/bgpd.h +++ b/usr.sbin/bgpd/bgpd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: bgpd.h,v 1.205 2006/08/04 12:01:48 henning Exp $ */ +/* $OpenBSD: bgpd.h,v 1.206 2006/08/23 08:13:04 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -80,6 +80,8 @@ #define F_BLACKHOLE 0x0100 #define F_LONGER 0x0200 #define F_CTL_DETAIL 0x1000 /* only used by bgpctl */ +#define F_CTL_ADJ_IN 0x2000 +#define F_CTL_ADJ_OUT 0x4000 enum { PROC_MAIN, @@ -518,8 +520,10 @@ struct filter_as { }; struct ctl_show_rib_request { + struct ctl_neighbor neighbor; struct bgpd_addr prefix; struct filter_as as; + u_int32_t peerid; pid_t pid; u_int16_t flags; sa_family_t af; diff --git a/usr.sbin/bgpd/control.c b/usr.sbin/bgpd/control.c index d3a2ab64d0f..95d47958c7b 100644 --- a/usr.sbin/bgpd/control.c +++ b/usr.sbin/bgpd/control.c @@ -1,4 +1,4 @@ -/* $OpenBSD: control.c,v 1.52 2006/05/27 21:24:36 claudio Exp $ */ +/* $OpenBSD: control.c,v 1.53 2006/08/23 08:13:04 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -193,6 +193,7 @@ control_dispatch_msg(struct pollfd *pfd, u_int *ctl_cnt) int n; struct peer *p; struct ctl_neighbor *neighbor; + struct ctl_show_rib_request *ribreq; if ((c = control_connbyfd(pfd->fd)) == NULL) { log_warn("control_dispatch_msg: fd %d: not found", pfd->fd); @@ -331,6 +332,46 @@ control_dispatch_msg(struct pollfd *pfd, u_int *ctl_cnt) case IMSG_CTL_SHOW_RIB: case IMSG_CTL_SHOW_RIB_AS: case IMSG_CTL_SHOW_RIB_PREFIX: + if (imsg.hdr.len == IMSG_HEADER_SIZE + + sizeof(struct ctl_show_rib_request)) { + ribreq = imsg.data; + neighbor = &ribreq->neighbor; + neighbor->descr[PEER_DESCR_LEN - 1] = 0; + ribreq->peerid = 0; + p = NULL; + if (neighbor->addr.af) { + p = getpeerbyaddr(&neighbor->addr); + if (p == NULL) { + control_result(c, + CTL_RES_NOSUCHPEER); + break; + } + ribreq->peerid = p->conf.id; + } else if (neighbor->descr[0]) { + p = getpeerbydesc(neighbor->descr); + if (p == NULL) { + control_result(c, + CTL_RES_NOSUCHPEER); + break; + } + ribreq->peerid = p->conf.id; + } + if ((ribreq->flags & F_CTL_ADJ_IN) && p && + !p->conf.softreconfig_in) { + /* + * if no neighbor was specified we + * try our best. + */ + control_result(c, CTL_RES_NOCAP); + break; + } + c->ibuf.pid = imsg.hdr.pid; + imsg_compose_rde(imsg.hdr.type, imsg.hdr.pid, + imsg.data, imsg.hdr.len - IMSG_HEADER_SIZE); + } else + log_warnx("got IMSG_CTL_SHOW_RIB with " + "wrong length"); + break; case IMSG_CTL_SHOW_RIB_MEM: case IMSG_CTL_SHOW_NETWORK: c->ibuf.pid = imsg.hdr.pid; diff --git a/usr.sbin/bgpd/rde.c b/usr.sbin/bgpd/rde.c index 9e899a3f555..b51cc4c78ad 100644 --- a/usr.sbin/bgpd/rde.c +++ b/usr.sbin/bgpd/rde.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rde.c,v 1.210 2006/08/22 15:02:07 henning Exp $ */ +/* $OpenBSD: rde.c,v 1.211 2006/08/23 08:13:04 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -58,7 +58,12 @@ void rde_update_log(const char *, const struct rde_peer *, const struct bgpd_addr *, const struct bgpd_addr *, u_int8_t); int rde_reflector(struct rde_peer *, struct rde_aspath *); -void rde_dump_rib_as(struct prefix *, pid_t, int); +void rde_dump_rib_as(struct prefix *, struct rde_aspath *,pid_t, + int); +void rde_dump_filter(struct prefix *, + struct ctl_show_rib_request *); +void rde_dump_filterout(struct rde_peer *, struct prefix *, + struct ctl_show_rib_request *); void rde_dump_upcall(struct pt_entry *, void *); void rde_dump_as(struct ctl_show_rib_request *); void rde_dump_prefix_upcall(struct pt_entry *, void *); @@ -1510,7 +1515,7 @@ rde_reflector(struct rde_peer *peer, struct rde_aspath *asp) * control specific functions */ void -rde_dump_rib_as(struct prefix *p, pid_t pid, int flags) +rde_dump_rib_as(struct prefix *p, struct rde_aspath *asp, pid_t pid, int flags) { struct ctl_show_rib rib; struct buf *wbuf; @@ -1520,19 +1525,19 @@ rde_dump_rib_as(struct prefix *p, pid_t pid, int flags) bzero(&rib, sizeof(rib)); rib.lastchange = p->lastchange; - rib.local_pref = p->aspath->lpref; - rib.med = p->aspath->med; - rib.prefix_cnt = p->aspath->prefix_cnt; - rib.active_cnt = p->aspath->active_cnt; - rib.adjrib_cnt = p->aspath->adjrib_cnt; - strlcpy(rib.descr, p->aspath->peer->conf.descr, sizeof(rib.descr)); - memcpy(&rib.remote_addr, &p->aspath->peer->remote_addr, + rib.local_pref = asp->lpref; + rib.med = asp->med; + rib.prefix_cnt = asp->prefix_cnt; + rib.active_cnt = asp->active_cnt; + rib.adjrib_cnt = asp->adjrib_cnt; + strlcpy(rib.descr, asp->peer->conf.descr, sizeof(rib.descr)); + memcpy(&rib.remote_addr, &asp->peer->remote_addr, sizeof(rib.remote_addr)); - rib.remote_id = p->aspath->peer->remote_bgpid; - if (p->aspath->nexthop != NULL) { - memcpy(&rib.true_nexthop, &p->aspath->nexthop->true_nexthop, + rib.remote_id = asp->peer->remote_bgpid; + if (asp->nexthop != NULL) { + memcpy(&rib.true_nexthop, &asp->nexthop->true_nexthop, sizeof(rib.true_nexthop)); - memcpy(&rib.exit_nexthop, &p->aspath->nexthop->exit_nexthop, + memcpy(&rib.exit_nexthop, &asp->nexthop->exit_nexthop, sizeof(rib.exit_nexthop)); } else { /* announced network may have a NULL nexthop */ @@ -1543,32 +1548,31 @@ rde_dump_rib_as(struct prefix *p, pid_t pid, int flags) } pt_getaddr(p->prefix, &rib.prefix); rib.prefixlen = p->prefix->prefixlen; - rib.origin = p->aspath->origin; + rib.origin = asp->origin; rib.flags = 0; if (p->prefix->active == p) rib.flags |= F_RIB_ACTIVE; - if (p->aspath->peer->conf.ebgp == 0) + if (asp->peer->conf.ebgp == 0) rib.flags |= F_RIB_INTERNAL; - if (p->aspath->flags & F_PREFIX_ANNOUNCED) + if (asp->flags & F_PREFIX_ANNOUNCED) rib.flags |= F_RIB_ANNOUNCE; - if (p->aspath->nexthop == NULL || - p->aspath->nexthop->state == NEXTHOP_REACH) + if (asp->nexthop == NULL || asp->nexthop->state == NEXTHOP_REACH) rib.flags |= F_RIB_ELIGIBLE; - rib.aspath_len = aspath_length(p->aspath->aspath); + rib.aspath_len = aspath_length(asp->aspath); if ((wbuf = imsg_create(ibuf_se, IMSG_CTL_SHOW_RIB, 0, pid, sizeof(rib) + rib.aspath_len)) == NULL) return; if (imsg_add(wbuf, &rib, sizeof(rib)) == -1 || - imsg_add(wbuf, aspath_dump(p->aspath->aspath), + imsg_add(wbuf, aspath_dump(asp->aspath), rib.aspath_len) == -1) return; if (imsg_close(ibuf_se, wbuf) == -1) return; if (flags & F_CTL_DETAIL) - for (l = 0; l < p->aspath->others_len; l++) { - if ((a = p->aspath->others[l]) == NULL) + for (l = 0; l < asp->others_len; l++) { + if ((a = asp->others[l]) == NULL) break; if ((wbuf = imsg_create(ibuf_se, IMSG_CTL_SHOW_RIB_ATTR, 0, pid, attr_optlen(a))) == NULL) @@ -1588,15 +1592,65 @@ rde_dump_rib_as(struct prefix *p, pid_t pid, int flags) } void +rde_dump_filterout(struct rde_peer *peer, struct prefix *p, + struct ctl_show_rib_request *req) +{ + struct bgpd_addr addr; + struct rde_aspath *asp; + enum filter_actions a; + + if (up_test_update(peer, p) != 1) + return; + + pt_getaddr(p->prefix, &addr); + a = rde_filter(&asp, rules_l, peer, p->aspath, &addr, + p->prefix->prefixlen, p->aspath->peer, DIR_OUT); + if (asp) + asp->peer = p->aspath->peer; + else + asp = p->aspath; + + if (a == ACTION_ALLOW) + rde_dump_rib_as(p, asp, req->pid, req->flags); + + if (asp != p->aspath) + path_put(asp); +} + +void +rde_dump_filter(struct prefix *p, struct ctl_show_rib_request *req) +{ + struct rde_peer *peer; + + if ((req->flags & F_CTL_ADJ_IN && p->flags & F_ORIGINAL) || + (!(req->flags & (F_CTL_ADJ_IN|F_CTL_ADJ_OUT)) && + p->flags & F_LOCAL)) { + if (req->peerid && req->peerid != p->aspath->peer->conf.id) + return; + rde_dump_rib_as(p, p->aspath, req->pid, req->flags); + } else if (req->flags & F_CTL_ADJ_OUT && p->flags & F_LOCAL) { + if (p->prefix->active != p) + /* only consider active prefix */ + return; + + if (req->peerid) { + if ((peer = peer_get(req->peerid)) != NULL) + rde_dump_filterout(peer, p, req); + return; + } + LIST_FOREACH(peer, &peerlist, peer_l) + rde_dump_filterout(peer, p, req); + } +} + +void rde_dump_upcall(struct pt_entry *pt, void *ptr) { struct prefix *p; struct ctl_show_rib_request *req = ptr; LIST_FOREACH(p, &pt->prefix_h, prefix_l) - /* for now dump only stuff from the local-RIB */ - if (p->flags & F_LOCAL) - rde_dump_rib_as(p, req->pid, req->flags); + rde_dump_filter(p, req); } void @@ -1614,10 +1668,7 @@ rde_dump_as(struct ctl_show_rib_request *req) continue; /* match found */ LIST_FOREACH(p, &asp->prefix_h, path_l) - /* for now dump only stuff from the local-RIB */ - if (p->flags & F_LOCAL) - rde_dump_rib_as(p, req->pid, - req->flags); + rde_dump_filter(p, req); } } } @@ -1636,9 +1687,7 @@ rde_dump_prefix_upcall(struct pt_entry *pt, void *ptr) return; if (!prefix_compare(&req->prefix, &addr, req->prefixlen)) LIST_FOREACH(p, &pt->prefix_h, prefix_l) - /* for now dump only stuff from the local-RIB */ - if (p->flags & F_LOCAL) - rde_dump_rib_as(p, req->pid, req->flags); + rde_dump_filter(p, req); } void |