Import route priority support from ospfd to ospf6d.
authorfriehm <friehm@openbsd.org>
Mon, 19 Jun 2017 19:55:57 +0000 (19:55 +0000)
committerfriehm <friehm@openbsd.org>
Mon, 19 Jun 2017 19:55:57 +0000 (19:55 +0000)
Also remove the RTF_UP flag from hdr.rtm_flags in send_rtmsg() since
ospfd and bgpd don't set the flag.

OK bluhm@ claudio@

usr.sbin/ospf6ctl/ospf6ctl.c
usr.sbin/ospf6d/kroute.c
usr.sbin/ospf6d/ospf6d.h
usr.sbin/ospf6d/rde.c

index 3b384e1..fc0c433 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ospf6ctl.c,v 1.44 2016/12/22 23:03:55 jca Exp $ */
+/*     $OpenBSD: ospf6ctl.c,v 1.45 2017/06/19 19:55:57 friehm Exp $ */
 
 /*
  * Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org>
@@ -1256,7 +1256,8 @@ void
 show_fib_head(void)
 {
        printf("flags: * = valid, O = OSPF, C = Connected, S = Static\n");
-       printf("%-6s %-20s %-17s\n", "Flags", "Destination", "Nexthop");
+       printf("%-6s %-4s %-20s %-17s\n",
+           "Flags", "Prio", "Destination", "Nexthop");
 }
 
 int
@@ -1286,6 +1287,7 @@ show_fib_msg(struct imsg *imsg)
                        printf(" ");
 
                printf("     ");
+               printf("%4d ", k->priority);
                if (asprintf(&p, "%s/%u", log_in6addr(&k->prefix),
                    k->prefixlen) == -1)
                        err(1, NULL);
index 0031984..11fb77f 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: kroute.c,v 1.51 2017/05/30 12:42:31 friehm Exp $ */
+/*     $OpenBSD: kroute.c,v 1.52 2017/06/19 19:55:57 friehm Exp $ */
 
 /*
  * Copyright (c) 2004 Esben Norby <norby@openbsd.org>
@@ -62,7 +62,8 @@ int   kroute_compare(struct kroute_node *, struct kroute_node *);
 int    kr_change_fib(struct kroute_node *, struct kroute *, int, int);
 int    kr_delete_fib(struct kroute_node *);
 
-struct kroute_node     *kroute_find(const struct in6_addr *, u_int8_t);
+struct kroute_node     *kroute_find(const struct in6_addr *, u_int8_t,
+                           u_int8_t);
 struct kroute_node     *kroute_matchgw(struct kroute_node *,
                            struct in6_addr *, unsigned int);
 int                     kroute_insert(struct kroute_node *);
@@ -215,6 +216,7 @@ kr_change_fib(struct kroute_node *kr, struct kroute *kroute, int krcount,
                kn->r.nexthop = kroute[i].nexthop;
                kn->r.scope = kroute[i].scope;
                kn->r.flags = kroute[i].flags | F_OSPFD_INSERTED;
+               kn->r.priority = RTP_OSPF;
                kn->r.ext_tag = kroute[i].ext_tag;
                rtlabel_unref(kn->r.rtlabel);   /* for RTM_CHANGE */
                kn->r.rtlabel = kroute[i].rtlabel;
@@ -238,31 +240,10 @@ kr_change(struct kroute *kroute, int krcount)
 
        kroute->rtlabel = rtlabel_tag2id(kroute->ext_tag);
 
-       kr = kroute_find(&kroute->prefix, kroute->prefixlen);
-       if (kr != NULL) {
-               if (kr->r.flags & F_KERNEL) {
-                       /* a non-ospf route already exists. not a problem */
-                       if (!(kr->r.flags & F_BGPD_INSERTED)) {
-                               do {
-                                       kr->r.flags |= F_OSPFD_INSERTED;
-                                       kr = kr->next;
-                               } while (kr);
-                               return (0);
-                       }
-                       /*
-                        * XXX as long as there is no multipath support in
-                        * bgpd this is safe else we end up in a bad situation.
-                        */
-                       /*
-                        * ospf route has higher pref
-                        * - reset flags to the ospf ones
-                        * - use RTM_CHANGE
-                        * - zero out ifindex (this is no longer relevant)
-                        */
-                       action = RTM_CHANGE;
-               } else if (kr->next == NULL)    /* single path OSPF route */
-                       action = RTM_CHANGE;
-       }
+       kr = kroute_find(&kroute->prefix, kroute->prefixlen, RTP_OSPF);
+       if (kr != NULL && kr->next == NULL && krcount == 1)
+               /* single path OSPF route */
+               action = RTM_CHANGE;
 
        return (kr_change_fib(kr, kroute, krcount, action));
 }
@@ -270,14 +251,10 @@ kr_change(struct kroute *kroute, int krcount)
 int
 kr_delete_fib(struct kroute_node *kr)
 {
-       if (!(kr->r.flags & F_OSPFD_INSERTED))
-               return 0;
-
-       if (kr->r.flags & F_KERNEL) {
-               /* remove F_OSPFD_INSERTED flag, route still exists in kernel */
-               kr->r.flags &= ~F_OSPFD_INSERTED;
-               return (0);
-       }
+       if (kr->r.priority != RTP_OSPF)
+               log_warn("kr_delete_fib: %s/%d has wrong priority %d",
+                   log_in6addr(&kr->r.prefix), kr->r.prefixlen,
+                   kr->r.priority);
 
        if (send_rtmsg(kr_state.fd, RTM_DELETE, &kr->r) == -1)
                return (-1);
@@ -293,8 +270,8 @@ kr_delete(struct kroute *kroute)
 {
        struct kroute_node      *kr, *nkr;
 
-       if ((kr = kroute_find(&kroute->prefix, kroute->prefixlen)) ==
-           NULL)
+       if ((kr = kroute_find(&kroute->prefix, kroute->prefixlen,
+           RTP_OSPF)) == NULL)
                return (0);
 
        while (kr != NULL) {
@@ -326,10 +303,9 @@ kr_fib_couple(void)
        kr_state.fib_sync = 1;
 
        RB_FOREACH(kr, kroute_tree, &krt)
-               if (!(kr->r.flags & F_KERNEL))
-                       for (kn = kr; kn != NULL; kn = kn->next) {
+               if (kr->r.priority == RTP_OSPF)
+                       for (kn = kr; kn != NULL; kn = kn->next)
                                send_rtmsg(kr_state.fd, RTM_ADD, &kn->r);
-                       }
 
        log_info("kernel routing table coupled");
 }
@@ -343,12 +319,10 @@ kr_fib_decouple(void)
        if (kr_state.fib_sync == 0)     /* already decoupled */
                return;
 
-       RB_FOREACH(kr, kroute_tree, &krt) {
-               if (!(kr->r.flags & F_KERNEL))
-                       for (kn = kr; kn != NULL; kn = kn->next) {
+       RB_FOREACH(kr, kroute_tree, &krt)
+               if (kr->r.priority == RTP_OSPF)
+                       for (kn = kr; kn != NULL; kn = kn->next)
                                send_rtmsg(kr_state.fd, RTM_DELETE, &kn->r);
-                       }
-       }
 
        kr_state.fib_sync = 0;
 
@@ -359,6 +333,7 @@ kr_fib_decouple(void)
 void
 kr_dispatch_msg(int fd, short event, void *bula)
 {
+       /* XXX this is stupid */
        dispatch_rtmsg();
 }
 
@@ -500,6 +475,10 @@ kr_redistribute(struct kroute_node *kh)
        struct kroute            kr;
        int                      redistribute = 0;
 
+       /* only the highest prio route can be redistributed */
+       if (kroute_find(&kh->r.prefix, kh->r.prefixlen, RTP_ANY) != kh)
+               return;
+
        bzero(&kr, sizeof(kr));
        kr.metric = UINT_MAX;
        for (kn = kh; kn; kn = kn->next)
@@ -560,19 +539,40 @@ kroute_compare(struct kroute_node *a, struct kroute_node *b)
                return (-1);
        if (a->r.prefixlen > b->r.prefixlen)
                return (1);
+
+       /* if the priority is RTP_ANY finish on the first address hit */
+       if (a->r.priority == RTP_ANY || b->r.priority == RTP_ANY)
+               return (0);
+       if (a->r.priority < b->r.priority)
+               return (-1);
+       if (a->r.priority > b->r.priority)
+               return (1);
        return (0);
 }
 
 /* tree management */
 struct kroute_node *
-kroute_find(const struct in6_addr *prefix, u_int8_t prefixlen)
+kroute_find(const struct in6_addr *prefix, u_int8_t prefixlen, u_int8_t prio)
 {
        struct kroute_node      s;
+       struct kroute_node      *kn, *tmp;
 
        s.r.prefix = *prefix;
        s.r.prefixlen = prefixlen;
-
-       return (RB_FIND(kroute_tree, &krt, &s));
+       s.r.priority = prio;
+
+       kn = RB_FIND(kroute_tree, &krt, &s);
+       if (kn && prio == RTP_ANY) {
+               tmp = RB_PREV(kroute_tree, &krt, kn);
+               while (tmp) {
+                       if (kroute_compare(&s, tmp) == 0)
+                               kn = tmp;
+                       else
+                               break;
+                       tmp = RB_PREV(kroute_tree, &krt, kn);
+               }
+       }
+       return (kn);
 }
 
 struct kroute_node *
@@ -595,11 +595,9 @@ kroute_insert(struct kroute_node *kr)
 
        if ((krh = RB_INSERT(kroute_tree, &krt, kr)) != NULL) {
                /*
-                * Multipath route, add at end of list and clone the
-                * ospfd inserted flag.
+                * Multipath route, add at end of list.
                 */
                krm = krh;
-               kr->r.flags |= krm->r.flags & F_OSPFD_INSERTED;
                while (krm->next != NULL)
                        krm = krm->next;
                krm->next = kr;
@@ -730,12 +728,12 @@ kroute_match(struct in6_addr *key)
        /* we will never match the default route */
        for (i = 128; i > 0; i--) {
                inet6applymask(&ina, key, i);
-               if ((kr = kroute_find(&ina, i)) != NULL)
+               if ((kr = kroute_find(&ina, i, RTP_ANY)) != NULL)
                        return (kr);
        }
 
        /* if we don't have a match yet, try to find a default route */
-       if ((kr = kroute_find(&in6addr_any, 0)) != NULL)
+       if ((kr = kroute_find(&in6addr_any, 0, RTP_ANY)) != NULL)
                        return (kr);
 
        return (NULL);
@@ -999,10 +997,11 @@ send_rtmsg(int fd, int action, struct kroute *kroute)
        bzero(&hdr, sizeof(hdr));
        hdr.rtm_version = RTM_VERSION;
        hdr.rtm_type = action;
-       hdr.rtm_flags = RTF_UP|RTF_MPATH;
        hdr.rtm_priority = RTP_OSPF;
        if (action == RTM_CHANGE)
                hdr.rtm_fmask = RTF_REJECT|RTF_BLACKHOLE;
+       else
+               hdr.rtm_flags = RTF_MPATH;
        hdr.rtm_seq = kr_state.rtseq++; /* overflow doesn't matter */
        hdr.rtm_hdrlen = sizeof(hdr);
        hdr.rtm_msglen = sizeof(hdr);
@@ -1168,6 +1167,7 @@ fetchtable(void)
                }
 
                kr->r.flags = F_KERNEL;
+               kr->r.priority = rtm->rtm_priority;
 
                switch (sa->sa_family) {
                case AF_INET6:
@@ -1182,8 +1182,6 @@ fetchtable(void)
                                kr->r.flags |= F_REJECT;
                        if (rtm->rtm_flags & RTF_DYNAMIC)
                                kr->r.flags |= F_DYNAMIC;
-                       if (rtm->rtm_flags & RTF_PROTO1)
-                               kr->r.flags |= F_BGPD_INSERTED;
                        if (sa_in6 != NULL) {
                                if (sa_in6->sin6_len == 0)
                                        break;
@@ -1226,7 +1224,7 @@ fetchtable(void)
                                break;
                        }
 
-               if (rtm->rtm_flags & RTF_PROTO2)  {
+               if (rtm->rtm_priority == RTP_OSPF)  {
                        send_rtmsg(kr_state.fd, RTM_DELETE, &kr->r);
                        free(kr);
                } else {
@@ -1326,7 +1324,7 @@ dispatch_rtmsg(void)
        struct sockaddr_rtlabel *label;
        struct kroute_node      *kr, *okr;
        struct in6_addr          prefix, nexthop;
-       u_int8_t                 prefixlen;
+       u_int8_t                 prefixlen, prio;
        int                      flags, mpath;
        unsigned int             scope;
        u_short                  ifindex = 0;
@@ -1358,6 +1356,7 @@ dispatch_rtmsg(void)
                prefixlen = 0;
                flags = F_KERNEL;
                mpath = 0;
+               prio = 0;
 
                if (rtm->rtm_type == RTM_ADD || rtm->rtm_type == RTM_CHANGE ||
                    rtm->rtm_type == RTM_DELETE) {
@@ -1377,10 +1376,10 @@ dispatch_rtmsg(void)
                        if (rtm->rtm_flags & (RTF_LLINFO|RTF_BROADCAST))
                                continue;
 
-#ifdef RTF_MPATH
                        if (rtm->rtm_flags & RTF_MPATH)
                                mpath = 1;
-#endif
+                       prio = rtm->rtm_priority;
+
                        switch (sa->sa_family) {
                        case AF_INET6:
                                prefix =
@@ -1403,8 +1402,6 @@ dispatch_rtmsg(void)
                                        flags |= F_REJECT;
                                if (rtm->rtm_flags & RTF_DYNAMIC)
                                        flags |= F_DYNAMIC;
-                               if (rtm->rtm_flags & RTF_PROTO1)
-                                       flags |= F_BGPD_INSERTED;
                                break;
                        default:
                                continue;
@@ -1441,8 +1438,8 @@ dispatch_rtmsg(void)
                                continue;
                        }
 
-                       if ((okr = kroute_find(&prefix, prefixlen)) !=
-                           NULL) {
+                       if ((okr = kroute_find(&prefix, prefixlen, prio))
+                           != NULL) {
                                /* just add new multipath routes */
                                if (mpath && rtm->rtm_type == RTM_ADD)
                                        goto add;
@@ -1456,13 +1453,6 @@ dispatch_rtmsg(void)
                                        goto add;
                                }
 
-                               /*
-                                * ospf route overridden by kernel. Preference
-                                * of the route is not checked because this is
-                                * forced -- most probably by a user.
-                                */
-                               if (kr->r.flags & F_OSPFD_INSERTED)
-                                       flags |= F_OSPFD_INSERTED;
                                if (kr->r.flags & F_REDISTRIBUTED)
                                        flags |= F_REDISTRIBUTED;
                                kr->r.nexthop = nexthop;
@@ -1501,6 +1491,7 @@ add:
                                kr->r.scope = scope;
                                kr->r.flags = flags;
                                kr->r.ifindex = ifindex;
+                               kr->r.priority = prio;
 
                                if ((label = (struct sockaddr_rtlabel *)
                                    rti_info[RTAX_LABEL]) != NULL) {
@@ -1514,7 +1505,7 @@ add:
                        }
                        break;
                case RTM_DELETE:
-                       if ((kr = kroute_find(&prefix, prefixlen)) ==
+                       if ((kr = kroute_find(&prefix, prefixlen, prio)) ==
                            NULL)
                                continue;
                        if (!(kr->r.flags & F_KERNEL))
@@ -1527,14 +1518,6 @@ add:
                                    " not found");
                                return (-1);
                        }
-                       /*
-                        * last route is getting removed request the
-                        * ospf route from the RDE to insert instead
-                        */
-                       if (okr == kr && kr->next == NULL &&
-                           kr->r.flags & F_OSPFD_INSERTED)
-                               main_imsg_compose_rde(IMSG_KROUTE_GET, 0,
-                                   &kr->r, sizeof(struct kroute));
                        if (kroute_remove(kr) == -1)
                                return (-1);
                        break;
index bd07669..abed9c9 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ospf6d.h,v 1.32 2017/05/30 12:42:31 friehm Exp $ */
+/*     $OpenBSD: ospf6d.h,v 1.33 2017/06/19 19:55:57 friehm Exp $ */
 
 /*
  * Copyright (c) 2004, 2007 Esben Norby <norby@openbsd.org>
@@ -51,7 +51,6 @@
 
 #define        F_OSPFD_INSERTED        0x0001
 #define        F_KERNEL                0x0002
-#define        F_BGPD_INSERTED         0x0004
 #define        F_CONNECTED             0x0008
 #define        F_DOWN                  0x0010
 #define        F_STATIC                0x0020
@@ -101,7 +100,6 @@ enum imsg_type {
        IMSG_CTL_LOG_VERBOSE,
        IMSG_KROUTE_CHANGE,
        IMSG_KROUTE_DELETE,
-       IMSG_KROUTE_GET,
        IMSG_IFINFO,
        IMSG_IFADD,
        IMSG_IFDELETE,
@@ -396,6 +394,7 @@ struct kroute {
        u_int16_t       rtlabel;
        u_short         ifindex;
        u_int8_t        prefixlen;
+       u_int8_t        priority;
 };
 
 /* name2id */
index 45c3598..62de3c3 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: rde.c,v 1.70 2017/05/30 12:42:31 friehm Exp $ */
+/*     $OpenBSD: rde.c,v 1.71 2017/06/19 19:55:57 friehm Exp $ */
 
 /*
  * Copyright (c) 2004, 2005 Claudio Jeker <claudio@openbsd.org>
@@ -633,7 +633,6 @@ rde_dispatch_parent(int fd, short event, void *bula)
        struct imsgbuf          *ibuf = &iev->ibuf;
        struct lsa              *lsa;
        struct vertex           *v;
-       struct rt_node          *rn;
        ssize_t                  n;
        int                      shut = 0, wasvalid;
        unsigned int             ifindex;
@@ -695,22 +694,6 @@ rde_dispatch_parent(int fd, short event, void *bula)
                                        free(lsa);
                        }
                        break;
-               case IMSG_KROUTE_GET:
-                       if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(kr)) {
-                               log_warnx("rde_dispatch_parent: "
-                                   "wrong imsg len");
-                               break;
-                       }
-                       memcpy(&kr, imsg.data, sizeof(kr));
-
-                       if ((rn = rt_find(&kr.prefix, kr.prefixlen,
-                           DT_NET)) != NULL)
-                               rde_send_change_kroute(rn);
-                       else
-                               /* should not happen */
-                               imsg_compose_event(iev_main, IMSG_KROUTE_DELETE,
-                                   0, 0, -1, &kr, sizeof(kr));
-                       break;
                case IMSG_IFINFO:
                        if (imsg.hdr.len != IMSG_HEADER_SIZE +
                            sizeof(struct iface))