now with reload working; check RTP_NONE < fib-priority <= RTP_MAX test reports / comments / OKs?
diff --git bgpd.c bgpd.c index 9c48bb3..8ad95fe 100644 --- bgpd.c +++ bgpd.c @@ -43,7 +43,7 @@ int check_child(pid_t, const char *); int send_filterset(struct imsgbuf *, struct filter_set_head *); int reconfigure(char *, struct bgpd_config *, struct mrt_head *, struct peer **); -int dispatch_imsg(struct imsgbuf *, int); +int dispatch_imsg(struct imsgbuf *, int, struct bgpd_config *); int control_setup(struct bgpd_config *); int rfd = -1; @@ -276,12 +276,14 @@ main(int argc, char *argv[]) } if (nfds > 0 && pfd[PFD_PIPE_SESSION].revents & POLLIN) { - if (dispatch_imsg(ibuf_se, PFD_PIPE_SESSION) == -1) + if (dispatch_imsg(ibuf_se, PFD_PIPE_SESSION, &conf) == + -1) quit = 1; } if (nfds > 0 && pfd[PFD_PIPE_ROUTE].revents & POLLIN) { - if (dispatch_imsg(ibuf_rde, PFD_PIPE_ROUTE) == -1) + if (dispatch_imsg(ibuf_rde, PFD_PIPE_ROUTE, &conf) == + -1) quit = 1; } @@ -359,7 +361,7 @@ main(int argc, char *argv[]) control_cleanup(conf.csock); control_cleanup(conf.rcsock); carp_demote_shutdown(); - kr_shutdown(); + kr_shutdown(conf.fib_priority); pftable_clear_all(); free(conf.listen_addrs); @@ -468,7 +470,7 @@ reconfigure(char *conffile, struct bgpd_config *conf, struct mrt_head *mrt_l, while ((rr = SIMPLEQ_FIRST(&ribnames))) { SIMPLEQ_REMOVE_HEAD(&ribnames, entry); if (ktable_update(rr->rtableid, rr->name, NULL, - rr->flags) == -1) { + rr->flags, conf->fib_priority) == -1) { log_warnx("failed to load rdomain %d", rr->rtableid); return (-1); @@ -505,7 +507,7 @@ reconfigure(char *conffile, struct bgpd_config *conf, struct mrt_head *mrt_l, while ((rd = SIMPLEQ_FIRST(&rdom_l)) != NULL) { SIMPLEQ_REMOVE_HEAD(&rdom_l, entry); if (ktable_update(rd->rtableid, rd->descr, rd->ifmpe, - rd->flags) == -1) { + rd->flags, conf->fib_priority) == -1) { log_warnx("failed to load rdomain %d", rd->rtableid); return (-1); @@ -551,7 +553,7 @@ reconfigure(char *conffile, struct bgpd_config *conf, struct mrt_head *mrt_l, } int -dispatch_imsg(struct imsgbuf *ibuf, int idx) +dispatch_imsg(struct imsgbuf *ibuf, int idx, struct bgpd_config *conf) { struct imsg imsg; ssize_t n; @@ -580,7 +582,8 @@ dispatch_imsg(struct imsgbuf *ibuf, int idx) else if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(struct kroute_full)) log_warnx("wrong imsg len"); - else if (kr_change(imsg.hdr.peerid, imsg.data)) + else if (kr_change(imsg.hdr.peerid, imsg.data, + conf->fib_priority)) rv = -1; break; case IMSG_KROUTE_DELETE: @@ -589,7 +592,8 @@ dispatch_imsg(struct imsgbuf *ibuf, int idx) else if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(struct kroute_full)) log_warnx("wrong imsg len"); - else if (kr_delete(imsg.hdr.peerid, imsg.data)) + else if (kr_delete(imsg.hdr.peerid, imsg.data, + conf->fib_priority)) rv = -1; break; case IMSG_NEXTHOP_ADD: @@ -652,13 +656,15 @@ dispatch_imsg(struct imsgbuf *ibuf, int idx) if (idx != PFD_PIPE_SESSION) log_warnx("couple request not from SE"); else - kr_fib_couple(imsg.hdr.peerid); + kr_fib_couple(imsg.hdr.peerid, + conf->fib_priority); break; case IMSG_CTL_FIB_DECOUPLE: if (idx != PFD_PIPE_SESSION) log_warnx("decouple request not from SE"); else - kr_fib_decouple(imsg.hdr.peerid); + kr_fib_decouple(imsg.hdr.peerid, + conf->fib_priority); break; case IMSG_CTL_KROUTE: case IMSG_CTL_KROUTE_ADDR: @@ -704,7 +710,7 @@ dispatch_imsg(struct imsgbuf *ibuf, int idx) 0, -1, NULL, 0); /* finally fix kroute information */ - ktable_postload(); + ktable_postload(conf->fib_priority); /* redistribute list needs to be reloaded too */ kr_reload(); diff --git bgpd.conf.5 bgpd.conf.5 index d352015..c7a0b8a 100644 --- bgpd.conf.5 +++ bgpd.conf.5 @@ -206,6 +206,11 @@ dump all out "/tmp/all-out-%H%M" 300 dump updates out "/tmp/updates-out-%H%M" 300 .Ed .Pp +.It Ic fib-priority Ar prio +Set the routing priority to +.Ar prio . +The default is 48. +.Pp .It Xo .Ic fib-update .Pq Ic yes Ns | Ns Ic no diff --git bgpd.h bgpd.h index 67f79fc..fc0ed0f 100644 --- bgpd.h +++ bgpd.h @@ -209,6 +209,7 @@ struct bgpd_config { u_int16_t holdtime; u_int16_t min_holdtime; u_int16_t connectretry; + u_int8_t fib_priority; }; enum announce_type { @@ -932,15 +933,18 @@ int host(const char *, struct bgpd_addr *, u_int8_t *); /* kroute.c */ int kr_init(void); -int ktable_update(u_int, char *, char *, int); +int ktable_update(u_int, char *, char *, int, u_int8_t); void ktable_preload(void); -void ktable_postload(void); +void ktable_postload(u_int8_t); int ktable_exists(u_int, u_int *); -int kr_change(u_int, struct kroute_full *); -int kr_delete(u_int, struct kroute_full *); -void kr_shutdown(void); -void kr_fib_couple(u_int); -void kr_fib_decouple(u_int); +int kr_change(u_int, struct kroute_full *, u_int8_t); +int kr_delete(u_int, struct kroute_full *, u_int8_t); +void kr_shutdown(u_int8_t); +void kr_fib_couple(u_int, u_int8_t); +void kr_fib_couple_all(u_int8_t); +void kr_fib_decouple(u_int, u_int8_t); +void kr_fib_decouple_all(u_int8_t); +void kr_fib_update_prio_all(u_int8_t); int kr_dispatch_msg(void); int kr_nexthop_add(u_int32_t, struct bgpd_addr *); void kr_nexthop_delete(u_int32_t, struct bgpd_addr *); diff --git config.c config.c index 9e9abae..b10c139 100644 --- config.c +++ config.c @@ -65,6 +65,9 @@ merge_config(struct bgpd_config *xconf, struct bgpd_config *conf, if ((conf->flags & BGPD_FLAG_REFLECTOR) && conf->clusterid == 0) conf->clusterid = conf->bgpid; + if (!conf->fib_priority) + conf->fib_priority = RTP_BGP; + free(xconf->csock); free(xconf->rcsock); diff --git kroute.c kroute.c index d2426cc..e460bbf 100644 --- kroute.c +++ kroute.c @@ -84,17 +84,17 @@ struct kif_node { struct kif_kr6_head kroute6_l; }; -int ktable_new(u_int, u_int, char *, char *, int); -void ktable_free(u_int); -void ktable_destroy(struct ktable *); +int ktable_new(u_int, u_int, char *, char *, int, u_int8_t); +void ktable_free(u_int, u_int8_t); +void ktable_destroy(struct ktable *, u_int8_t); struct ktable *ktable_get(u_int); -int kr4_change(struct ktable *, struct kroute_full *); -int kr6_change(struct ktable *, struct kroute_full *); -int krVPN4_change(struct ktable *, struct kroute_full *); -int kr4_delete(struct ktable *, struct kroute_full *); -int kr6_delete(struct ktable *, struct kroute_full *); -int krVPN4_delete(struct ktable *, struct kroute_full *); +int kr4_change(struct ktable *, struct kroute_full *, u_int8_t); +int kr6_change(struct ktable *, struct kroute_full *, u_int8_t); +int krVPN4_change(struct ktable *, struct kroute_full *, u_int8_t); +int kr4_delete(struct ktable *, struct kroute_full *, u_int8_t); +int kr6_delete(struct ktable *, struct kroute_full *, u_int8_t); +int krVPN4_delete(struct ktable *, struct kroute_full *, u_int8_t); void kr_net_delete(struct network *); struct network *kr_net_match(struct ktable *, struct kroute *); struct network *kr_net_match6(struct ktable *, struct kroute6 *); @@ -107,6 +107,7 @@ int kroute_compare(struct kroute_node *, struct kroute_node *); int kroute6_compare(struct kroute6_node *, struct kroute6_node *); int knexthop_compare(struct knexthop_node *, struct knexthop_node *); int kif_compare(struct kif_node *, struct kif_node *); +void kr_fib_update_prio(u_int, u_int8_t); struct kroute_node *kroute_find(struct ktable *, in_addr_t, u_int8_t, u_int8_t); @@ -162,10 +163,12 @@ void get_rtaddrs(int, struct sockaddr *, struct sockaddr **); void if_change(u_short, int, struct if_data *); void if_announce(void *); -int send_rtmsg(int, int, struct ktable *, struct kroute *); -int send_rt6msg(int, int, struct ktable *, struct kroute6 *); +int send_rtmsg(int, int, struct ktable *, struct kroute *, + u_int8_t); +int send_rt6msg(int, int, struct ktable *, struct kroute6 *, + u_int8_t); int dispatch_rtmsg(void); -int fetchtable(struct ktable *); +int fetchtable(struct ktable *, u_int8_t); int fetchifs(int); int dispatch_rtmsg_addr(struct rt_msghdr *, struct sockaddr *[RTAX_MAX], struct ktable *); @@ -237,7 +240,8 @@ kr_init(void) } int -ktable_new(u_int rtableid, u_int rdomid, char *name, char *ifname, int fs) +ktable_new(u_int rtableid, u_int rdomid, char *name, char *ifname, int fs, + u_int8_t bgp_prio) { struct ktable **xkrt; struct ktable *kt; @@ -283,7 +287,7 @@ ktable_new(u_int rtableid, u_int rdomid, char *name, char *ifname, int fs) } /* ... and load it */ - if (fetchtable(kt) == -1) + if (fetchtable(kt, bgp_prio) == -1) return (-1); if (protect_lo(kt) == -1) return (-1); @@ -295,7 +299,7 @@ ktable_new(u_int rtableid, u_int rdomid, char *name, char *ifname, int fs) } void -ktable_free(u_int rtableid) +ktable_free(u_int rtableid, u_int8_t bgp_prio) { struct ktable *kt, *nkt; @@ -303,7 +307,7 @@ ktable_free(u_int rtableid) return; /* decouple from kernel, no new routes will be entered from here */ - kr_fib_decouple(kt->rtableid); + kr_fib_decouple(kt->rtableid, bgp_prio); /* first unhook from the nexthop table */ nkt = ktable_get(kt->nhtableid); @@ -317,16 +321,16 @@ ktable_free(u_int rtableid) * free so check that kt != nkt). */ if (kt != nkt && nkt->nhrefcnt <= 0) - ktable_destroy(nkt); + ktable_destroy(nkt, bgp_prio); if (kt->nhrefcnt <= 0) - ktable_destroy(kt); + ktable_destroy(kt, bgp_prio); } void -ktable_destroy(struct ktable *kt) +ktable_destroy(struct ktable *kt, u_int8_t bgp_prio) { /* decouple just to be sure, does not hurt */ - kr_fib_decouple(kt->rtableid); + kr_fib_decouple(kt->rtableid, bgp_prio); log_debug("freeing ktable %s rtableid %u", kt->descr, kt->rtableid); knexthop_clear(kt); @@ -346,7 +350,8 @@ ktable_get(u_int rtableid) } int -ktable_update(u_int rtableid, char *name, char *ifname, int flags) +ktable_update(u_int rtableid, char *name, char *ifname, int flags, u_int8_t + bgp_prio) { struct ktable *kt, *rkt; u_int rdomid; @@ -359,7 +364,7 @@ ktable_update(u_int rtableid, char *name, char *ifname, int flags) if (rkt == NULL) { char buf[32]; snprintf(buf, sizeof(buf), "rdomain_%d", rdomid); - if (ktable_new(rdomid, rdomid, buf, NULL, 0)) + if (ktable_new(rdomid, rdomid, buf, NULL, 0, bgp_prio)) return (-1); } else { /* there is no need for full fib synchronisation if @@ -379,7 +384,7 @@ ktable_update(u_int rtableid, char *name, char *ifname, int flags) kt = ktable_get(rtableid); if (kt == NULL) { if (ktable_new(rtableid, rdomid, name, ifname, - !(flags & F_RIB_NOFIBSYNC))) + !(flags & F_RIB_NOFIBSYNC), bgp_prio)) return (-1); } else { /* fib sync has higher preference then no sync */ @@ -408,7 +413,7 @@ ktable_preload(void) } void -ktable_postload(void) +ktable_postload(u_int8_t bgp_prio) { struct ktable *kt; u_int i; @@ -417,7 +422,7 @@ ktable_postload(void) if ((kt = ktable_get(i - 1)) == NULL) continue; if (kt->state == RECONF_DELETE) - ktable_free(i - 1); + ktable_free(i - 1, bgp_prio); else if (kt->state == RECONF_REINIT) kt->fib_sync = kt->fib_conf; } @@ -452,7 +457,7 @@ ktable_exists(u_int rtableid, u_int *rdomid) } int -kr_change(u_int rtableid, struct kroute_full *kl) +kr_change(u_int rtableid, struct kroute_full *kl, u_int8_t bgp_prio) { struct ktable *kt; @@ -461,25 +466,25 @@ kr_change(u_int rtableid, struct kroute_full *kl) return (0); switch (kl->prefix.aid) { case AID_INET: - return (kr4_change(kt, kl)); + return (kr4_change(kt, kl, bgp_prio)); case AID_INET6: - return (kr6_change(kt, kl)); + return (kr6_change(kt, kl, bgp_prio)); case AID_VPN_IPv4: - return (krVPN4_change(kt, kl)); + return (krVPN4_change(kt, kl, bgp_prio)); } log_warnx("kr_change: not handled AID"); return (-1); } int -kr4_change(struct ktable *kt, struct kroute_full *kl) +kr4_change(struct ktable *kt, struct kroute_full *kl, u_int8_t bgp_prio) { struct kroute_node *kr; int action = RTM_ADD; u_int16_t labelid; if ((kr = kroute_find(kt, kl->prefix.v4.s_addr, kl->prefixlen, - RTP_BGP)) != NULL) + bgp_prio)) != NULL) action = RTM_CHANGE; /* nexthop within 127/8 -> ignore silently */ @@ -502,7 +507,7 @@ kr4_change(struct ktable *kt, struct kroute_full *kl) kr->r.prefixlen = kl->prefixlen; kr->r.nexthop.s_addr = kl->nexthop.v4.s_addr; kr->r.flags = kl->flags | F_BGPD_INSERTED; - kr->r.priority = RTP_BGP; + kr->r.priority = bgp_prio; kr->r.labelid = labelid; if (kroute_insert(kt, kr) == -1) { @@ -523,21 +528,21 @@ kr4_change(struct ktable *kt, struct kroute_full *kl) kr->r.flags &= ~F_REJECT; } - if (send_rtmsg(kr_state.fd, action, kt, &kr->r) == -1) + if (send_rtmsg(kr_state.fd, action, kt, &kr->r, bgp_prio) == -1) return (-1); return (0); } int -kr6_change(struct ktable *kt, struct kroute_full *kl) +kr6_change(struct ktable *kt, struct kroute_full *kl, u_int8_t bgp_prio) { struct kroute6_node *kr6; struct in6_addr lo6 = IN6ADDR_LOOPBACK_INIT; int action = RTM_ADD; u_int16_t labelid; - if ((kr6 = kroute6_find(kt, &kl->prefix.v6, kl->prefixlen, RTP_BGP)) != + if ((kr6 = kroute6_find(kt, &kl->prefix.v6, kl->prefixlen, bgp_prio)) != NULL) action = RTM_CHANGE; @@ -561,7 +566,7 @@ kr6_change(struct ktable *kt, struct kroute_full *kl) memcpy(&kr6->r.nexthop, &kl->nexthop.v6, sizeof(struct in6_addr)); kr6->r.flags = kl->flags | F_BGPD_INSERTED; - kr6->r.priority = RTP_BGP; + kr6->r.priority = bgp_prio; kr6->r.labelid = labelid; if (kroute6_insert(kt, kr6) == -1) { @@ -583,14 +588,14 @@ kr6_change(struct ktable *kt, struct kroute_full *kl) kr6->r.flags &= ~F_REJECT; } - if (send_rt6msg(kr_state.fd, action, kt, &kr6->r) == -1) + if (send_rt6msg(kr_state.fd, action, kt, &kr6->r, bgp_prio) == -1) return (-1); return (0); } int -krVPN4_change(struct ktable *kt, struct kroute_full *kl) +krVPN4_change(struct ktable *kt, struct kroute_full *kl, u_int8_t bgp_prio) { struct kroute_node *kr; int action = RTM_ADD; @@ -598,7 +603,7 @@ krVPN4_change(struct ktable *kt, struct kroute_full *kl) u_int16_t labelid; if ((kr = kroute_find(kt, kl->prefix.vpn4.addr.s_addr, kl->prefixlen, - RTP_BGP)) != NULL) + bgp_prio)) != NULL) action = RTM_CHANGE; /* nexthop within 127/8 -> ignore silently */ @@ -632,7 +637,7 @@ krVPN4_change(struct ktable *kt, struct kroute_full *kl) kr->r.prefixlen = kl->prefixlen; kr->r.nexthop.s_addr = kl->nexthop.v4.s_addr; kr->r.flags = kl->flags | F_BGPD_INSERTED | F_MPLS; - kr->r.priority = RTP_BGP; + kr->r.priority = bgp_prio; kr->r.labelid = labelid; kr->r.mplslabel = mplslabel; @@ -655,14 +660,14 @@ krVPN4_change(struct ktable *kt, struct kroute_full *kl) kr->r.flags &= ~F_REJECT; } - if (send_rtmsg(kr_state.fd, action, kt, &kr->r) == -1) + if (send_rtmsg(kr_state.fd, action, kt, &kr->r, bgp_prio) == -1) return (-1); return (0); } int -kr_delete(u_int rtableid, struct kroute_full *kl) +kr_delete(u_int rtableid, struct kroute_full *kl, u_int8_t bgp_prio) { struct ktable *kt; @@ -672,29 +677,29 @@ kr_delete(u_int rtableid, struct kroute_full *kl) switch (kl->prefix.aid) { case AID_INET: - return (kr4_delete(kt, kl)); + return (kr4_delete(kt, kl, bgp_prio)); case AID_INET6: - return (kr6_delete(kt, kl)); + return (kr6_delete(kt, kl, bgp_prio)); case AID_VPN_IPv4: - return (krVPN4_delete(kt, kl)); + return (krVPN4_delete(kt, kl, bgp_prio)); } log_warnx("kr_change: not handled AID"); return (-1); } int -kr4_delete(struct ktable *kt, struct kroute_full *kl) +kr4_delete(struct ktable *kt, struct kroute_full *kl, u_int8_t bgp_prio) { struct kroute_node *kr; if ((kr = kroute_find(kt, kl->prefix.v4.s_addr, kl->prefixlen, - RTP_BGP)) == NULL) + bgp_prio)) == NULL) return (0); if (!(kr->r.flags & F_BGPD_INSERTED)) return (0); - if (send_rtmsg(kr_state.fd, RTM_DELETE, kt, &kr->r) == -1) + if (send_rtmsg(kr_state.fd, RTM_DELETE, kt, &kr->r, bgp_prio) == -1) return (-1); rtlabel_unref(kr->r.labelid); @@ -706,18 +711,18 @@ kr4_delete(struct ktable *kt, struct kroute_full *kl) } int -kr6_delete(struct ktable *kt, struct kroute_full *kl) +kr6_delete(struct ktable *kt, struct kroute_full *kl, u_int8_t bgp_prio) { struct kroute6_node *kr6; - if ((kr6 = kroute6_find(kt, &kl->prefix.v6, kl->prefixlen, RTP_BGP)) == + if ((kr6 = kroute6_find(kt, &kl->prefix.v6, kl->prefixlen, bgp_prio)) == NULL) return (0); if (!(kr6->r.flags & F_BGPD_INSERTED)) return (0); - if (send_rt6msg(kr_state.fd, RTM_DELETE, kt, &kr6->r) == -1) + if (send_rt6msg(kr_state.fd, RTM_DELETE, kt, &kr6->r, bgp_prio) == -1) return (-1); rtlabel_unref(kr6->r.labelid); @@ -729,18 +734,18 @@ kr6_delete(struct ktable *kt, struct kroute_full *kl) } int -krVPN4_delete(struct ktable *kt, struct kroute_full *kl) +krVPN4_delete(struct ktable *kt, struct kroute_full *kl, u_int8_t bgp_prio) { struct kroute_node *kr; if ((kr = kroute_find(kt, kl->prefix.vpn4.addr.s_addr, kl->prefixlen, - RTP_BGP)) == NULL) + bgp_prio)) == NULL) return (0); if (!(kr->r.flags & F_BGPD_INSERTED)) return (0); - if (send_rtmsg(kr_state.fd, RTM_DELETE, kt, &kr->r) == -1) + if (send_rtmsg(kr_state.fd, RTM_DELETE, kt, &kr->r, bgp_prio) == -1) return (-1); rtlabel_unref(kr->r.labelid); @@ -752,17 +757,17 @@ krVPN4_delete(struct ktable *kt, struct kroute_full *kl) } void -kr_shutdown(void) +kr_shutdown(u_int8_t bgp_prio) { u_int i; for (i = krt_size; i > 0; i--) - ktable_free(i - 1); + ktable_free(i - 1, bgp_prio); kif_clear(); } void -kr_fib_couple(u_int rtableid) +kr_fib_couple(u_int rtableid, u_int8_t bgp_prio) { struct ktable *kt; struct kroute_node *kr; @@ -778,17 +783,27 @@ kr_fib_couple(u_int rtableid) RB_FOREACH(kr, kroute_tree, &kt->krt) if ((kr->r.flags & F_BGPD_INSERTED)) - send_rtmsg(kr_state.fd, RTM_ADD, kt, &kr->r); + send_rtmsg(kr_state.fd, RTM_ADD, kt, &kr->r, bgp_prio); RB_FOREACH(kr6, kroute6_tree, &kt->krt6) if ((kr6->r.flags & F_BGPD_INSERTED)) - send_rt6msg(kr_state.fd, RTM_ADD, kt, &kr6->r); + send_rt6msg(kr_state.fd, RTM_ADD, kt, &kr6->r, + bgp_prio); log_info("kernel routing table %u (%s) coupled", kt->rtableid, kt->descr); } void -kr_fib_decouple(u_int rtableid) +kr_fib_couple_all(u_int8_t bgp_prio) +{ + u_int i; + + for (i = krt_size; i > 0; i--) + kr_fib_couple(i - 1, bgp_prio); +} + +void +kr_fib_decouple(u_int rtableid, u_int8_t bgp_prio) { struct ktable *kt; struct kroute_node *kr; @@ -802,10 +817,12 @@ kr_fib_decouple(u_int rtableid) RB_FOREACH(kr, kroute_tree, &kt->krt) if ((kr->r.flags & F_BGPD_INSERTED)) - send_rtmsg(kr_state.fd, RTM_DELETE, kt, &kr->r); + send_rtmsg(kr_state.fd, RTM_DELETE, kt, &kr->r, + bgp_prio); RB_FOREACH(kr6, kroute6_tree, &kt->krt6) if ((kr6->r.flags & F_BGPD_INSERTED)) - send_rt6msg(kr_state.fd, RTM_DELETE, kt, &kr6->r); + send_rt6msg(kr_state.fd, RTM_DELETE, kt, &kr6->r, + bgp_prio); kt->fib_sync = 0; @@ -813,6 +830,43 @@ kr_fib_decouple(u_int rtableid) kt->descr); } +void +kr_fib_decouple_all(u_int8_t bgp_prio) +{ + u_int i; + + for (i = krt_size; i > 0; i--) + kr_fib_decouple(i - 1, bgp_prio); +} + +void +kr_fib_update_prio(u_int rtableid, u_int8_t bgp_prio) +{ + struct ktable *kt; + struct kroute_node *kr; + struct kroute6_node *kr6; + + if ((kt = ktable_get(rtableid)) == NULL) /* table does not exist */ + return; + + RB_FOREACH(kr, kroute_tree, &kt->krt) + if ((kr->r.flags & F_BGPD_INSERTED)) + kr->r.priority = bgp_prio; + + RB_FOREACH(kr6, kroute6_tree, &kt->krt6) + if ((kr6->r.flags & F_BGPD_INSERTED)) + kr6->r.priority = bgp_prio; +} + +void +kr_fib_update_prio_all(u_int8_t bgp_prio) +{ + u_int i; + + for (i = krt_size; i > 0; i--) + kr_fib_update_prio(i - 1, bgp_prio); +} + int kr_dispatch_msg(void) { @@ -2473,7 +2527,8 @@ if_announce(void *msg) */ int -send_rtmsg(int fd, int action, struct ktable *kt, struct kroute *kroute) +send_rtmsg(int fd, int action, struct ktable *kt, struct kroute *kroute, + u_int8_t bgp_prio) { struct iovec iov[7]; struct rt_msghdr hdr; @@ -2496,7 +2551,7 @@ send_rtmsg(int fd, int action, struct ktable *kt, struct kroute *kroute) hdr.rtm_version = RTM_VERSION; hdr.rtm_type = action; hdr.rtm_tableid = kt->rtableid; - hdr.rtm_priority = RTP_BGP; + hdr.rtm_priority = bgp_prio; if (kroute->flags & F_BLACKHOLE) hdr.rtm_flags |= RTF_BLACKHOLE; if (kroute->flags & F_REJECT) @@ -2608,7 +2663,8 @@ retry: } int -send_rt6msg(int fd, int action, struct ktable *kt, struct kroute6 *kroute) +send_rt6msg(int fd, int action, struct ktable *kt, struct kroute6 *kroute, + u_int8_t bgp_prio) { struct iovec iov[5]; struct rt_msghdr hdr; @@ -2627,7 +2683,7 @@ send_rt6msg(int fd, int action, struct ktable *kt, struct kroute6 *kroute) hdr.rtm_version = RTM_VERSION; hdr.rtm_type = action; hdr.rtm_tableid = kt->rtableid; - hdr.rtm_priority = RTP_BGP; + hdr.rtm_priority = bgp_prio; if (kroute->flags & F_BLACKHOLE) hdr.rtm_flags |= RTF_BLACKHOLE; if (kroute->flags & F_REJECT) @@ -2715,7 +2771,7 @@ retry: } int -fetchtable(struct ktable *kt) +fetchtable(struct ktable *kt, u_int8_t bgp_prio) { size_t len; int mib[7]; @@ -2863,15 +2919,16 @@ fetchtable(struct ktable *kt) } if (sa->sa_family == AF_INET) { - if (rtm->rtm_priority == RTP_BGP) { - send_rtmsg(kr_state.fd, RTM_DELETE, kt, &kr->r); + if (rtm->rtm_priority == bgp_prio) { + send_rtmsg(kr_state.fd, RTM_DELETE, kt, &kr->r, + bgp_prio); free(kr); } else kroute_insert(kt, kr); } else if (sa->sa_family == AF_INET6) { - if (rtm->rtm_priority == RTP_BGP) { + if (rtm->rtm_priority == bgp_prio) { send_rt6msg(kr_state.fd, RTM_DELETE, kt, - &kr6->r); + &kr6->r, bgp_prio); free(kr6); } else kroute6_insert(kt, kr6); diff --git parse.y parse.y index 1492a08..92b4d70 100644 --- parse.y +++ parse.y @@ -170,7 +170,7 @@ typedef struct { %} -%token AS ROUTERID HOLDTIME YMIN LISTEN ON FIBUPDATE RTABLE +%token AS ROUTERID HOLDTIME YMIN LISTEN ON FIBUPDATE FIBPRIORITY RTABLE %token RDOMAIN RD EXPORTTRGT IMPORTTRGT %token RDE RIB EVALUATE IGNORE COMPARE %token GROUP NEIGHBOR NETWORK @@ -373,6 +373,13 @@ conf_main : AS as4number { memcpy(&la->sa, addr2sa(&$3, BGP_PORT), sizeof(la->sa)); TAILQ_INSERT_TAIL(listen_addrs, la, entry); } + | FIBPRIORITY NUMBER { + if ($2 <= RTP_NONE || $2 > RTP_MAX) { + yyerror("invalid fib-priority"); + YYERROR; + } + conf->fib_priority = $2; + } | FIBUPDATE yesno { struct rde_rib *rr; rr = find_rib("Loc-RIB"); @@ -2139,6 +2146,7 @@ lookup(char *s) { "evaluate", EVALUATE}, { "export-target", EXPORTTRGT}, { "ext-community", EXTCOMMUNITY}, + { "fib-priority", FIBPRIORITY}, { "fib-update", FIBUPDATE}, { "from", FROM}, { "group", GROUP}, @@ -2565,9 +2573,13 @@ parse_config(char *filename, struct bgpd_config *xconf, struct rde_rib *rr; struct rdomain *rd; int errors = 0; + u_int8_t old_prio; + + old_prio = xconf->fib_priority; if ((conf = calloc(1, sizeof(struct bgpd_config))) == NULL) fatal(NULL); + conf->opts = xconf->opts; conf->csock = strdup(SOCKET_NAME); @@ -2719,6 +2731,13 @@ parse_config(char *filename, struct bgpd_config *xconf, free(peerfilter_l); free(groupfilter_l); + if (!errors && old_prio != RTP_NONE && old_prio != + xconf->fib_priority) { + kr_fib_decouple_all(old_prio); + kr_fib_update_prio_all(xconf->fib_priority); + kr_fib_couple_all(xconf->fib_priority); + } + return (errors ? -1 : 0); } diff --git printconf.c printconf.c index 484bdf2..2482556 100644 --- printconf.c +++ printconf.c @@ -270,6 +270,7 @@ print_mainconf(struct bgpd_config *conf) printf("nexthop qualify via bgp\n"); if (conf->flags & BGPD_FLAG_NEXTHOP_DEFAULT) printf("nexthop qualify via default\n"); + printf("fib-priority %hhu", conf->fib_priority); } void -- I'm not entirely sure you are real.