bgpd: fib-priority

classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

bgpd: fib-priority

Florian Obser-2
First stab, only lightly tested, reload is *not* working. I need to
think a bit more how to handle reloads exactly.

Note that if you try to shoot yourself in the foot by specifing
another already used priority (e.g. 32), it will not only take of your
foot but take the thigh right with it... (at least that's what I
think, haven't tried it)

diff --git bgpd.c bgpd.c
index 9c48bb3..6cd4eab 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;
@@ -161,6 +161,8 @@ main(int argc, char *argv[])
  if (argc > 0)
  usage();
 
+ conf.fib_priority = RTP_BGP; /* XXX how to handle default? */
+
  if (conf.opts & BGPD_OPT_NOACTION) {
  struct network_head net_l;
  struct rdomain_head rdom_l;
@@ -276,12 +278,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 +363,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 +472,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 +509,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 +555,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 +584,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 +594,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 +658,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 +712,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..29681d8 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,15 @@ 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_decouple(u_int, 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 kroute.c kroute.c
index d2426cc..6f2074d 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 *);
@@ -162,10 +162,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 +239,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 +286,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 +298,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 +306,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 +320,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 +349,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 +363,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 +383,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 +412,7 @@ ktable_preload(void)
 }
 
 void
-ktable_postload(void)
+ktable_postload(u_int8_t bgp_prio)
 {
  struct ktable *kt;
  u_int i;
@@ -417,7 +421,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 +456,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 +465,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 +506,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 +527,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 +565,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 +587,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 +602,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 +636,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 +659,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 +676,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 +710,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 +733,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 +756,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 +782,18 @@ 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_decouple(u_int rtableid, u_int8_t bgp_prio)
 {
  struct ktable *kt;
  struct kroute_node *kr;
@@ -802,10 +807,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;
 
@@ -2473,7 +2480,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 +2504,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 +2616,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 +2636,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 +2724,7 @@ retry:
 }
 
 int
-fetchtable(struct ktable *kt)
+fetchtable(struct ktable *kt, u_int8_t bgp_prio)
 {
  size_t len;
  int mib[7];
@@ -2863,15 +2872,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..c0623a6 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 < 0 || $2 > 255) {
+ 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},
@@ -2568,6 +2576,7 @@ parse_config(char *filename, struct bgpd_config *xconf,
 
  if ((conf = calloc(1, sizeof(struct bgpd_config))) == NULL)
  fatal(NULL);
+ conf->fib_priority = RTP_BGP; /* XXX how to handle default? */
  conf->opts = xconf->opts;
  conf->csock = strdup(SOCKET_NAME);
 
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.

Reply | Threaded
Open this post in threaded view
|

ospfd: fib-priority

Loïc Blot-2
Hi all,
sorry for to be late, but here is my ospfd patch for setting custom
routing priorities on ospfd (based on 5.4 sources)

My parse.y is more precise than Florian's, it allows priorities greater
than static routes (RTP_STATIC) and lower than RTP_MAX (63).

Also, when /etc/rc.d/ospfd reload is launched, fib is decouples,
priority changed and fib recoupled. It works nearly perfect.
The only missing point is that "ospfctl sh fib" shows both fib with old
and new prio (but real routing table only has new fib priority).

--- ../OpenBSD54/usr.sbin/ospfd/kroute.c 2013-07-07 18:26:04.000000000
+0200
+++ ospfd/kroute.c 2013-11-07 17:26:58.395763302 +0100
@@ -254,7 +254,7 @@
  kn->r.prefixlen = kroute[i].prefixlen;
  kn->r.nexthop.s_addr = kroute[i].nexthop.s_addr;
  kn->r.flags = kroute[i].flags | F_OSPFD_INSERTED;
- kn->r.priority = RTP_OSPF;
+ kn->r.priority = get_conf()->fib_priority;
  kn->r.ext_tag = kroute[i].ext_tag;
  rtlabel_unref(kn->r.rtlabel); /* for RTM_CHANGE */
  kn->r.rtlabel = kroute[i].rtlabel;
@@ -278,7 +278,7 @@
 
  kroute->rtlabel = rtlabel_tag2id(kroute->ext_tag);
 
- kr = kroute_find(kroute->prefix.s_addr, kroute->prefixlen, RTP_OSPF);
+ kr = kroute_find(kroute->prefix.s_addr, kroute->prefixlen,
get_conf()->fib_priority);
  if (kr != NULL && kr->next == NULL && krcount == 1)
  /* single path OSPF route */
  action = RTM_CHANGE;
@@ -289,7 +289,7 @@
 int
 kr_delete_fib(struct kroute_node *kr)
 {
- if (kr->r.priority != RTP_OSPF)
+ if (kr->r.priority != get_conf()->fib_priority)
  log_warn("kr_delete_fib: %s/%d has wrong priority %d",
     inet_ntoa(kr->r.prefix), kr->r.prefixlen, kr->r.priority);
 
@@ -308,7 +308,7 @@
  struct kroute_node *kr, *nkr;
 
  if ((kr = kroute_find(kroute->prefix.s_addr, kroute->prefixlen,
-    RTP_OSPF)) == NULL)
+    get_conf()->fib_priority)) == NULL)
  return (0);
 
  while (kr != NULL) {
@@ -340,7 +340,7 @@
  kr_state.fib_sync = 1;
 
  RB_FOREACH(kr, kroute_tree, &krt)
- if (kr->r.priority == RTP_OSPF)
+ if (kr->r.priority == get_conf()->fib_priority)
  for (kn = kr; kn != NULL; kn = kn->next)
  send_rtmsg(kr_state.fd, RTM_ADD, &kn->r);
 
@@ -357,7 +357,7 @@
  return;
 
  RB_FOREACH(kr, kroute_tree, &krt)
- if (kr->r.priority == RTP_OSPF)
+ if (kr->r.priority == get_conf()->fib_priority)
  for (kn = kr; kn != NULL; kn = kn->next)
  send_rtmsg(kr_state.fd, RTM_DELETE, &kn->r);
 
@@ -410,7 +410,7 @@
  kn = kr->next;
 
  if (kr->serial != kr_state.fib_serial) {
- if (kr->r.priority == RTP_OSPF) {
+ if (kr->r.priority == get_conf()->fib_priority) {
  kr->serial = kr_state.fib_serial;
  if (send_rtmsg(kr_state.fd,
     RTM_ADD, &kr->r) != 0)
@@ -1142,7 +1142,7 @@
  bzero(&hdr, sizeof(hdr));
  hdr.rtm_version = RTM_VERSION;
  hdr.rtm_type = action;
- hdr.rtm_priority = RTP_OSPF;
+ hdr.rtm_priority = get_conf()->fib_priority;
  hdr.rtm_tableid = kr_state.rdomain; /* rtableid */
  if (action == RTM_CHANGE)
  hdr.rtm_fmask = RTF_REJECT|RTF_BLACKHOLE;
@@ -1373,7 +1373,7 @@
  if (rtm->rtm_flags & RTF_MPATH)
  mpath = 1;
  prio = rtm->rtm_priority;
- flags = (prio == RTP_OSPF) ?
+ flags = (prio == get_conf()->fib_priority) ?
     F_OSPFD_INSERTED : F_KERNEL;
 
  switch (sa->sa_family) {
@@ -1432,7 +1432,7 @@
     != NULL) {
  /* get the correct route */
  kr = okr;
- if ((mpath || prio == RTP_OSPF) &&
+ if ((mpath || prio == get_conf()->fib_priority) &&
     (kr = kroute_matchgw(okr, nexthop)) ==
     NULL) {
  log_warnx("dispatch_rtmsg "
@@ -1481,7 +1481,7 @@
  kr->r.ifindex = ifindex;
  kr->r.priority = prio;
 
- if (rtm->rtm_priority == RTP_OSPF) {
+ if (rtm->rtm_priority == get_conf()->fib_priority) {
  log_warnx("alien OSPF route %s/%d",
     inet_ntoa(prefix), prefixlen);
  rv = send_rtmsg(kr_state.fd,
diff: ../OpenBSD54/usr.sbin/ospfd/obj: Aucun fichier ou dossier de ce
type
diff: ospfd/obj: Aucun fichier ou dossier de ce type
diff -u ../OpenBSD54/usr.sbin/ospfd/ospfd.c ospfd/ospfd.c
--- ../OpenBSD54/usr.sbin/ospfd/ospfd.c 2013-07-07 18:26:04.000000000
+0200
+++ ospfd/ospfd.c 2013-11-07 17:56:27.595760396 +0100
@@ -681,6 +681,7 @@
  struct iface *iface;
  struct redistribute *r;
  int rchange = 0;
+ uint8_t pchange = 0;
 
  /* change of rtr_id needs a restart */
  conf->flags = xconf->flags;
@@ -690,6 +691,17 @@
     SIMPLEQ_EMPTY(&xconf->redist_list))
  rchange = 1;
  conf->rfc1583compat = xconf->rfc1583compat;
+
+ /* flag for fib reloading, only when routing priority changes */
+ if (conf->fib_priority != xconf->fib_priority) {
+ kr_fib_decouple();
+ pchange = 1;
+ }
+
+ conf->fib_priority = xconf->fib_priority;
+
+ if (pchange == 1)
+ kr_fib_couple();
 
  if (ospfd_process == PROC_MAIN) {
  /* main process does neither use areas nor interfaces */
@@ -891,3 +903,7 @@
  return (i);
  return (NULL);
 }
+
+struct ospfd_conf* get_conf() {
+ return (ospfd_conf);
+}
diff -u ../OpenBSD54/usr.sbin/ospfd/ospfd.conf.5 ospfd/ospfd.conf.5
--- ../OpenBSD54/usr.sbin/ospfd/ospfd.conf.5 2012-10-09
00:48:09.000000000 +0200
+++ ospfd/ospfd.conf.5 2013-11-07 17:57:35.222426952 +0100
@@ -101,6 +101,11 @@
 .Ic stub Ic router
 option to ensure that no traffic tries to transit via this router.
 .Pp
+.It Ic fib-priority Ar prio
+Set the routing priority to
+.Ar prio .
+The default is 32.
+.Pp
 .It Ic rdomain Ar tableid
 Specifies the routing table
 .Xr ospfd 8
diff -u ../OpenBSD54/usr.sbin/ospfd/ospfd.h ospfd/ospfd.h
--- ../OpenBSD54/usr.sbin/ospfd/ospfd.h 2013-02-16 04:03:42.000000000
+0100
+++ ospfd/ospfd.h 2013-11-07 14:16:07.395782105 +0100
@@ -386,6 +386,7 @@
  u_int8_t rfc1583compat;
  u_int8_t border;
  u_int8_t redistribute;
+ u_int8_t fib_priority;
  u_int rdomain;
  char *csock;
 };
@@ -592,6 +593,7 @@
 void imsg_event_add(struct imsgev *);
 int imsg_compose_event(struct imsgev *, u_int16_t, u_int32_t,
     pid_t, int, void *, u_int16_t);
+struct ospfd_conf* get_conf(void);
 
 /* printconf.c */
 void print_config(struct ospfd_conf *);
diff -u ../OpenBSD54/usr.sbin/ospfd/parse.y ospfd/parse.y
--- ../OpenBSD54/usr.sbin/ospfd/parse.y 2013-07-07 18:26:04.000000000
+0200
+++ ospfd/parse.y 2013-11-07 17:29:40.195763036 +0100
@@ -37,6 +37,7 @@
 #include <stdio.h>
 #include <string.h>
 #include <syslog.h>
+#include <net/route.h>
 
 #include "ospf.h"
 #include "ospfd.h"
@@ -96,6 +97,7 @@
  enum auth_type auth_type;
  u_int8_t auth_keyid;
  u_int8_t priority;
+ u_int8_t fib_priority;
 };
 
 struct config_defaults globaldefs;
@@ -120,7 +122,7 @@
 %token AREA INTERFACE ROUTERID FIBUPDATE REDISTRIBUTE RTLABEL RDOMAIN
 %token RFC1583COMPAT STUB ROUTER SPFDELAY SPFHOLDTIME EXTTAG
 %token AUTHKEY AUTHTYPE AUTHMD AUTHMDKEYID
-%token METRIC PASSIVE
+%token METRIC PASSIVE FIBPRIORITY
 %token HELLOINTERVAL FASTHELLOINTERVAL TRANSMITDELAY
 %token RETRANSMITINTERVAL ROUTERDEADTIME ROUTERPRIORITY
 %token SET TYPE
@@ -209,6 +211,13 @@
  }
  free($2);
  }
+ | FIBPRIORITY NUMBER {
+ if ($2 <= RTP_STATIC || $2 > RTP_MAX) {
+ yyerror("invalid fib-priority");
+ YYERROR;
+ }
+ conf->fib_priority = $2;
+ }
  | FIBUPDATE yesno {
  if ($2 == 0)
  conf->flags |= OSPFD_FLAG_NO_FIB_UPDATE;
@@ -725,6 +734,7 @@
  {"demote", DEMOTE},
  {"external-tag", EXTTAG},
  {"fast-hello-interval", FASTHELLOINTERVAL},
+ {"fib-priority", FIBPRIORITY},
  {"fib-update", FIBUPDATE},
  {"hello-interval", HELLOINTERVAL},
  {"include", INCLUDE},
@@ -1094,6 +1104,7 @@
  conf->spf_delay = DEFAULT_SPF_DELAY;
  conf->spf_hold_time = DEFAULT_SPF_HOLDTIME;
  conf->spf_state = SPF_IDLE;
+ conf->fib_priority = RTP_OSPF;
 
  if ((file = pushfile(filename, !(conf->opts & OSPFD_OPT_NOACTION))) ==
NULL) {
  free(conf);


Reply | Threaded
Open this post in threaded view
|

Re: bgpd: fib-priority

Florian Obser-2
In reply to this post by Florian Obser-2
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.

Reply | Threaded
Open this post in threaded view
|

Re: bgpd: fib-priority

Loïc Blot-2
Hi Florian,
good job.
I think it's better to set minimum to RTP_CONNECTED+1 instead of
RTP_NONE+1

--
Best regards,
Loïc BLOT,
UNIX systems, security and network engineer
http://www.unix-experience.fr



Le samedi 09 novembre 2013 à 21:04 +0000, Florian Obser a écrit :

> 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
>
>

signature.asc (237 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: bgpd: fib-priority

Adam Thompson
In reply to this post by Florian Obser-2
> now with reload working; check RTP_NONE < fib-priority <= RTP_MAX

For some reason, I can't reply to Loic's followup email...

I disagree with his comment; while it's usually silly to have a BGP route
preferred over a connected route, I can think of at least one case
(tunnels) where it might make sense to have BGP take priority.

However, a warning message would be entirely appropriate when doing so,
because it's a very unusual/strange case.

-Adam Thompson
 [hidden email]