Hi,

below patch adds "fib-priority" to ospfd.conf which allows to set a
custom priority to routes. 32 is still the default if not set. Changing
the priority with a reload is also supported.

A discussion about the feature can be found here:
https://marc.info/?l=openbsd-tech&m=138360663119816&w=2

My first idea was to add an additional parameter to the functions that
need it. But that that is not practical since then need the event that calls
kr_dispatch_msg() needs to be reset. Because of that I added fib_prio to 
struct kr_state.


OK?

Remi



cvs diff: Diffing .
Index: kroute.c
===================================================================
RCS file: /cvs/src/usr.sbin/ospfd/kroute.c,v
retrieving revision 1.111
diff -u -p -r1.111 kroute.c
--- kroute.c    10 Jul 2018 11:49:04 -0000      1.111
+++ kroute.c    9 Dec 2018 21:39:46 -0000
@@ -45,6 +45,7 @@ struct {
        pid_t                   pid;
        int                     fib_sync;
        int                     fib_serial;
+       u_int8_t                fib_prio;
        int                     fd;
        struct event            ev;
        struct event            reload;
@@ -127,14 +128,15 @@ kif_init(void)
 }
 
 int
-kr_init(int fs, u_int rdomain, int redis_label_or_prefix)
+kr_init(int fs, u_int rdomain, int redis_label_or_prefix, u_int8_t fib_prio)
 {
        int             opt = 0, rcvbuf, default_rcvbuf;
        socklen_t       optlen;
-       int             filter_prio = RTP_OSPF;
+       int             filter_prio = fib_prio;
 
        kr_state.fib_sync = fs;
        kr_state.rdomain = rdomain;
+       kr_state.fib_prio = fib_prio;
 
        if ((kr_state.fd = socket(AF_ROUTE,
            SOCK_RAW | SOCK_CLOEXEC | SOCK_NONBLOCK, AF_INET)) == -1) {
@@ -262,7 +264,7 @@ kr_change_fib(struct kroute_node *kr, st
                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 = kr_state.fib_prio;
                kn->r.ext_tag = kroute[i].ext_tag;
                rtlabel_unref(kn->r.rtlabel);   /* for RTM_CHANGE */
                kn->r.rtlabel = kroute[i].rtlabel;
@@ -286,7 +288,8 @@ kr_change(struct kroute *kroute, int krc
 
        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,
+           kr_state.fib_prio);
        if (kr != NULL && kr->next == NULL && krcount == 1)
                /* single path OSPF route */
                action = RTM_CHANGE;
@@ -297,7 +300,7 @@ kr_change(struct kroute *kroute, int krc
 int
 kr_delete_fib(struct kroute_node *kr)
 {
-       if (kr->r.priority != RTP_OSPF)
+       if (kr->r.priority != kr_state.fib_prio)
                log_warn("kr_delete_fib: %s/%d has wrong priority %d",
                    inet_ntoa(kr->r.prefix), kr->r.prefixlen, kr->r.priority);
 
@@ -316,7 +319,7 @@ kr_delete(struct kroute *kroute)
        struct kroute_node      *kr, *nkr;
 
        if ((kr = kroute_find(kroute->prefix.s_addr, kroute->prefixlen,
-           RTP_OSPF)) == NULL)
+           kr_state.fib_prio)) == NULL)
                return (0);
 
        while (kr != NULL) {
@@ -348,7 +351,7 @@ kr_fib_couple(void)
        kr_state.fib_sync = 1;
 
        RB_FOREACH(kr, kroute_tree, &krt)
-               if (kr->r.priority == RTP_OSPF)
+               if (kr->r.priority == kr_state.fib_prio)
                        for (kn = kr; kn != NULL; kn = kn->next)
                                send_rtmsg(kr_state.fd, RTM_ADD, &kn->r);
 
@@ -365,7 +368,7 @@ kr_fib_decouple(void)
                return;
 
        RB_FOREACH(kr, kroute_tree, &krt)
-               if (kr->r.priority == RTP_OSPF)
+               if (kr->r.priority == kr_state.fib_prio)
                        for (kn = kr; kn != NULL; kn = kn->next)
                                send_rtmsg(kr_state.fd, RTM_DELETE, &kn->r);
 
@@ -418,7 +421,7 @@ kr_fib_reload()
                        kn = kr->next;
 
                        if (kr->serial != kr_state.fib_serial) {
-                               if (kr->r.priority == RTP_OSPF) {
+                               if (kr->r.priority == kr_state.fib_prio) {
                                        kr->serial = kr_state.fib_serial;
                                        if (send_rtmsg(kr_state.fd,
                                            RTM_ADD, &kr->r) != 0)
@@ -431,6 +434,21 @@ kr_fib_reload()
        }
 }
 
+void
+kr_fib_update_prio(u_int8_t fib_prio)
+{
+       struct kroute_node      *kr;
+
+       RB_FOREACH(kr, kroute_tree, &krt)
+               if ((kr->r.flags & F_OSPFD_INSERTED))
+                       kr->r.priority = fib_prio;
+
+       log_info("fib priority changed from %hhu to %hhu",
+           kr_state.fib_prio, fib_prio);
+
+       kr_state.fib_prio = fib_prio;
+ }
+
 /* ARGSUSED */
 void
 kr_dispatch_msg(int fd, short event, void *bula)
@@ -618,7 +636,7 @@ kr_reload(int redis_label_or_prefix)
        struct kroute_node      *kr, *kn;
        u_int32_t                dummy;
        int                      r;
-       int                      filter_prio = RTP_OSPF;
+       int                      filter_prio = kr_state.fib_prio;
 
        /* update the priority filter */
        if (redis_label_or_prefix) {
@@ -1173,7 +1191,7 @@ send_rtmsg(int fd, int action, struct kr
        bzero(&hdr, sizeof(hdr));
        hdr.rtm_version = RTM_VERSION;
        hdr.rtm_type = action;
-       hdr.rtm_priority = RTP_OSPF;
+       hdr.rtm_priority = kr_state.fib_prio;
        hdr.rtm_tableid = kr_state.rdomain;     /* rtableid */
        if (action == RTM_CHANGE)
                hdr.rtm_fmask = RTF_REJECT|RTF_BLACKHOLE;
@@ -1414,7 +1432,7 @@ rtmsg_process(char *buf, size_t len)
                        if (rtm->rtm_flags & RTF_MPATH)
                                mpath = 1;
                        prio = rtm->rtm_priority;
-                       flags = (prio == RTP_OSPF) ?
+                       flags = (prio == kr_state.fib_prio) ?
                            F_OSPFD_INSERTED : F_KERNEL;
 
                        switch (sa->sa_family) {
@@ -1480,7 +1498,7 @@ rtmsg_process(char *buf, size_t len)
                            != NULL) {
                                /* get the correct route */
                                kr = okr;
-                               if ((mpath || prio == RTP_OSPF) &&
+                               if ((mpath || prio == kr_state.fib_prio) &&
                                    (kr = kroute_matchgw(okr, nexthop)) ==
                                    NULL) {
                                        log_warnx("dispatch_rtmsg "
@@ -1529,7 +1547,7 @@ add:
                                kr->r.ifindex = ifindex;
                                kr->r.priority = prio;
 
-                               if (rtm->rtm_priority == RTP_OSPF) {
+                               if (rtm->rtm_priority == kr_state.fib_prio) {
                                        log_warnx("alien OSPF route %s/%d",
                                            inet_ntoa(prefix), prefixlen);
                                        rv = send_rtmsg(kr_state.fd,
Index: ospfd.c
===================================================================
RCS file: /cvs/src/usr.sbin/ospfd/ospfd.c,v
retrieving revision 1.101
diff -u -p -r1.101 ospfd.c
--- ospfd.c     29 Oct 2018 22:13:33 -0000      1.101
+++ ospfd.c     9 Dec 2018 21:34:03 -0000
@@ -286,7 +286,8 @@ main(int argc, char *argv[])
                fatal("unveil");
 
        if (kr_init(!(ospfd_conf->flags & OSPFD_FLAG_NO_FIB_UPDATE),
-           ospfd_conf->rdomain, ospfd_conf->redist_label_or_prefix) == -1)
+           ospfd_conf->rdomain, ospfd_conf->redist_label_or_prefix,
+           ospfd_conf->fib_priority) == -1)
                fatalx("kr_init failed");
 
        /* remove unneeded stuff from config */
@@ -707,6 +708,15 @@ merge_config(struct ospfd_conf *conf, st
                        SIMPLEQ_REMOVE_HEAD(&xconf->redist_list, entry);
                        SIMPLEQ_INSERT_TAIL(&conf->redist_list, r, entry);
                }
+
+               /* adjust FIB priority if changed */
+               if (conf->fib_priority != xconf->fib_priority) {
+                       kr_fib_decouple();
+                       kr_fib_update_prio(xconf->fib_priority);
+                       conf->fib_priority = xconf->fib_priority;
+                       kr_fib_couple();
+               }
+
                goto done;
        }
 
Index: ospfd.conf.5
===================================================================
RCS file: /cvs/src/usr.sbin/ospfd/ospfd.conf.5,v
retrieving revision 1.54
diff -u -p -r1.54 ospfd.conf.5
--- ospfd.conf.5        27 Jul 2018 05:23:24 -0000      1.54
+++ ospfd.conf.5        11 Nov 2018 21:40:41 -0000
@@ -83,6 +83,11 @@ interface.
 The only settings that can be set globally and not overruled are listed below.
 .Pp
 .Bl -tag -width Ds -compact
+.It Ic fib-priority Ar prio
+Set the routing priority to
+.Ar prio .
+The default is 32.
+.Pp
 .It Xo
 .Ic fib-update
 .Pq Ic yes Ns | Ns Ic no
Index: ospfd.h
===================================================================
RCS file: /cvs/src/usr.sbin/ospfd/ospfd.h,v
retrieving revision 1.102
diff -u -p -r1.102 ospfd.h
--- ospfd.h     29 Aug 2018 08:43:17 -0000      1.102
+++ ospfd.h     9 Dec 2018 20:54:15 -0000
@@ -402,6 +402,7 @@ struct ospfd_conf {
        u_int8_t                rfc1583compat;
        u_int8_t                border;
        u_int8_t                redistribute;
+       u_int8_t                fib_priority;
        u_int                   rdomain;
        char                    *csock;
 };
@@ -572,13 +573,14 @@ u_int16_t  iso_cksum(void *, u_int16_t, 
 /* kroute.c */
 int             kif_init(void);
 void            kif_clear(void);
-int             kr_init(int, u_int, int);
+int             kr_init(int, u_int, int, u_int8_t);
 int             kr_change(struct kroute *, int);
 int             kr_delete(struct kroute *);
 void            kr_shutdown(void);
 void            kr_fib_couple(void);
 void            kr_fib_decouple(void);
 void            kr_fib_reload(void);
+void            kr_fib_update_prio(u_int8_t);
 void            kr_dispatch_msg(int, short, void *);
 void            kr_show_route(struct imsg *);
 void            kr_ifinfo(char *, pid_t);
Index: parse.y
===================================================================
RCS file: /cvs/src/usr.sbin/ospfd/parse.y,v
retrieving revision 1.93
diff -u -p -r1.93 parse.y
--- parse.y     1 Nov 2018 00:18:44 -0000       1.93
+++ parse.y     11 Nov 2018 22:35:00 -0000
@@ -25,6 +25,7 @@
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <sys/stat.h>
+#include <net/route.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
 #include <ctype.h>
@@ -125,8 +126,8 @@ typedef struct {
 
 %}
 
-%token AREA INTERFACE ROUTERID FIBUPDATE REDISTRIBUTE RTLABEL RDOMAIN
-%token RFC1583COMPAT STUB ROUTER SPFDELAY SPFHOLDTIME EXTTAG
+%token AREA INTERFACE ROUTERID FIBPRIORITY FIBUPDATE REDISTRIBUTE RTLABEL
+%token RDOMAIN RFC1583COMPAT STUB ROUTER SPFDELAY SPFHOLDTIME EXTTAG
 %token AUTHKEY AUTHTYPE AUTHMD AUTHMDKEYID
 %token METRIC PASSIVE
 %token HELLOINTERVAL FASTHELLOINTERVAL TRANSMITDELAY
@@ -229,6 +230,13 @@ conf_main  : ROUTERID STRING {
                        }
                        free($2);
                }
+               | FIBPRIORITY NUMBER {
+                       if ($2 <= RTP_NONE || $2 > RTP_MAX) {
+                               yyerror("invalid fib-priority");
+                               YYERROR;
+                       }
+                       conf->fib_priority = $2;
+               }
                | FIBUPDATE yesno {
                        if ($2 == 0)
                                conf->flags |= OSPFD_FLAG_NO_FIB_UPDATE;
@@ -804,6 +812,7 @@ lookup(char *s)
                {"depend",              DEPEND},
                {"external-tag",        EXTTAG},
                {"fast-hello-interval", FASTHELLOINTERVAL},
+               {"fib-priority",        FIBPRIORITY},
                {"fib-update",          FIBUPDATE},
                {"hello-interval",      HELLOINTERVAL},
                {"include",             INCLUDE},
@@ -1204,6 +1213,7 @@ parse_config(char *filename, int opts)
        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) {
Index: printconf.c
===================================================================
RCS file: /cvs/src/usr.sbin/ospfd/printconf.c,v
retrieving revision 1.19
diff -u -p -r1.19 printconf.c
--- printconf.c 11 Jul 2018 15:41:19 -0000      1.19
+++ printconf.c 11 Nov 2018 22:17:37 -0000
@@ -44,6 +44,8 @@ print_mainconf(struct ospfd_conf *conf)
        else
                printf("fib-update yes\n");
 
+       printf("fib-priority %hhu\n", conf->fib_priority);
+
        if (conf->rdomain)
                printf("rdomain %d\n", conf->rdomain);
 

Reply via email to