Sorry, here is the patch:

diff -u ospf6d.uptodate/kroute.c ospf6d.patch1/kroute.c
--- ospf6d.uptodate/kroute.c    Thu Sep 20 15:25:33 2012
+++ ospf6d.patch1/kroute.c      Thu Sep 27 18:01:37 2012
@@ -59,6 +59,8 @@
 int    kr_redist_eval(struct kroute *, struct rroute *);
 void   kr_redistribute(struct kroute_node *);
 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_matchgw(struct kroute_node *,
@@ -140,18 +142,102 @@
 }
 
 int
-kr_change(struct kroute *kroute)
+kr_change_fib(struct kroute_node *kr, struct kroute *kroute, int krcount,
+    int action)
 {
+       int                      i;
+       struct kroute_node      *kn, *nkn;
+
+       if (action == RTM_ADD) {
+               /*
+                * First remove all stale multipath routes.
+                * This step must be skipped when the action is RTM_CHANGE
+                * because it is already a single path route that will be
+                * changed.
+                */
+               for (kn = kr; kn != NULL; kn = nkn) {
+                       for (i = 0; i < krcount; i++) {
+                               if 
(IN6_ARE_ADDR_EQUAL(&kn->r.nexthop,&kroute[i].nexthop))
+                                       break;
+                       }
+                       nkn = kn->next;
+                       if (i == krcount)
+                               /* stale route */
+                               if (kr_delete_fib(kn) == -1)
+                                       log_warnx("kr_delete_fib failed");
+                       log_debug("kr_update_fib: before: %s%s",
+                           log_in6addr(&kn->r.nexthop),
+                           i == krcount ? " (deleted)" : "");
+               }
+       }
+
+       /*
+        * now add or change the route
+        */
+       for (i = 0; i < krcount; i++) {
+               /* nexthop within 127/8 -> ignore silently */
+               if (kr && IN6_IS_ADDR_LOOPBACK(&kr->r.nexthop))
+                       continue;
+
+               if (action == RTM_ADD && kr) {
+                       for (kn = kr; kn != NULL; kn = kn->next) {
+                               if 
(IN6_ARE_ADDR_EQUAL(&kn->r.nexthop,&kroute[i].nexthop))
+                                       break;
+                       }
+
+                       log_debug("kr_update_fib: after : %s%s",
+                            log_in6addr(&kroute[i].nexthop),
+                            kn == NULL ? " (added)" : "");
+
+                       if (kn != NULL)
+                               /* nexthop already present, skip it */
+                               continue;
+               } else
+                       /* modify first entry */
+                       kn = kr;
+
+               /* send update */
+               if (send_rtmsg(kr_state.fd, action, &kroute[i]) == -1)
+                       return (-1);
+
+               /* create new entry unless we are changing the first entry */
+               if (action == RTM_ADD)
+                       if ((kn = calloc(1, sizeof(*kn))) == NULL)
+                               fatal(NULL);
+
+               kn->r.prefix = kroute[i].prefix;
+               kn->r.prefixlen = kroute[i].prefixlen;
+               kn->r.nexthop = kroute[i].nexthop;
+               kn->r.scope = kroute[i].scope;
+               kn->r.flags = kroute[i].flags | F_OSPFD_INSERTED;
+               kn->r.ext_tag = kroute[i].ext_tag;
+               rtlabel_unref(kn->r.rtlabel);   /* for RTM_CHANGE */
+               kn->r.rtlabel = kroute[i].rtlabel;
+               if (action == RTM_ADD) {
+                       if (kroute_insert(kn) == -1) {
+                               log_debug("kr_update_fib: cannot insert %s",
+                                   log_in6addr(&kn->r.nexthop));
+                               free(kn);
+                       }
+               }
+               action = RTM_ADD;
+       }
+       return  (0);
+}
+
+int
+kr_change(struct kroute *kroute, int krcount)
+{
        struct kroute_node      *kr;
        int                      action = RTM_ADD;
 
        kroute->rtlabel = rtlabel_tag2id(kroute->ext_tag);
 
-       if ((kr = kroute_find(&kroute->prefix, kroute->prefixlen)) !=
-           NULL) {
-               if (!(kr->r.flags & F_KERNEL))
-                       action = RTM_CHANGE;
-               else {  /* a non-ospf route already exists. not a problem */
+       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;
@@ -170,79 +256,43 @@
                         * - zero out ifindex (this is no longer relevant)
                         */
                        action = RTM_CHANGE;
-                       kr->r.flags = kroute->flags | F_OSPFD_INSERTED;
-                       kr->r.ifindex = 0;
-                       rtlabel_unref(kr->r.rtlabel);
-                       kr->r.ext_tag = kroute->ext_tag;
-                       kr->r.rtlabel = kroute->rtlabel;
-               }
+               } else if (kr->next == NULL)    /* single path OSPF route */
+                       action = RTM_CHANGE;
        }
 
-       /* nexthop within 127/8 -> ignore silently */
-       if (kr && IN6_IS_ADDR_LOOPBACK(&kr->r.nexthop))
-               return (0);
+       return (kr_change_fib(kr, kroute, krcount, action));
+}
 
-       /*
-        * Ingnore updates that did not change the route.
-        * Currently only the nexthop can change.
-        */
-       if (kr && kr->r.scope == kroute->scope &&
-           IN6_ARE_ADDR_EQUAL(&kr->r.nexthop, &kroute->nexthop))
+int
+kr_delete_fib(struct kroute_node *kr)
+{
+       if (!(kr->r.flags & F_OSPFD_INSERTED))
                return (0);
 
-       if (send_rtmsg(kr_state.fd, action, kroute) == -1)
+       if (send_rtmsg(kr_state.fd, RTM_DELETE, &kr->r) == -1)
                return (-1);
 
-       if (action == RTM_ADD) {
-               if ((kr = calloc(1, sizeof(struct kroute_node))) == NULL) {
-                       log_warn("kr_change");
-                       return (-1);
-               }
-               kr->r.prefix = kroute->prefix;
-               kr->r.prefixlen = kroute->prefixlen;
-               kr->r.nexthop = kroute->nexthop;
-               kr->r.scope = kroute->scope;
-               kr->r.flags = kroute->flags | F_OSPFD_INSERTED;
-               kr->r.ext_tag = kroute->ext_tag;
-               kr->r.rtlabel = kroute->rtlabel;
+       if (kroute_remove(kr) == -1)
+               return (-1);
 
-               if (kroute_insert(kr) == -1)
-                       free(kr);
-       } else if (kr) {
-               kr->r.nexthop = kroute->nexthop;
-               kr->r.scope = kroute->scope;
-       }
-
        return (0);
 }
 
 int
 kr_delete(struct kroute *kroute)
 {
-       struct kroute_node      *kr;
+       struct kroute_node      *kr, *nkr;
 
        if ((kr = kroute_find(&kroute->prefix, kroute->prefixlen)) ==
            NULL)
                return (0);
 
-       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 */
-               do {
-                       kr->r.flags &= ~F_OSPFD_INSERTED;
-                       kr = kr->next;
-               } while (kr);
-               return (0);
+       while (kr != NULL) {
+               nkr = kr->next;
+               if (kr_delete_fib(kr) == -1)
+                       return (-1);
+               kr = nkr;
        }
-
-       if (send_rtmsg(kr_state.fd, RTM_DELETE, kroute) == -1)
-               return (-1);
-
-       if (kroute_remove(kr) == -1)
-               return (-1);
-
        return (0);
 }
 
@@ -257,6 +307,7 @@
 kr_fib_couple(void)
 {
        struct kroute_node      *kr;
+       struct kroute_node      *kn;
 
        if (kr_state.fib_sync == 1)     /* already coupled */
                return;
@@ -265,7 +316,9 @@
 
        RB_FOREACH(kr, kroute_tree, &krt)
                if (!(kr->r.flags & F_KERNEL))
-                       send_rtmsg(kr_state.fd, RTM_ADD, &kr->r);
+                       for (kn = kr; kn != NULL; kn = kn->next) {
+                               send_rtmsg(kr_state.fd, RTM_ADD, &kn->r);
+                       }
 
        log_info("kernel routing table coupled");
 }
@@ -274,13 +327,16 @@
 kr_fib_decouple(void)
 {
        struct kroute_node      *kr;
+       struct kroute_node      *kn;
 
        if (kr_state.fib_sync == 0)     /* already decoupled */
                return;
 
        RB_FOREACH(kr, kroute_tree, &krt)
                if (!(kr->r.flags & F_KERNEL))
-                       send_rtmsg(kr_state.fd, RTM_DELETE, &kr->r);
+                       for (kn = kr; kn != NULL; kn = kn->next) {
+                               send_rtmsg(kr_state.fd, RTM_DELETE, &kn->r);
+                       }
 
        kr_state.fib_sync = 0;
 
@@ -1062,7 +1118,7 @@
        bzero(&hdr, sizeof(hdr));
        hdr.rtm_version = RTM_VERSION;
        hdr.rtm_type = action;
-       hdr.rtm_flags = RTF_UP;
+       hdr.rtm_flags = RTF_UP|RTF_MPATH;
        hdr.rtm_priority = RTP_OSPF;
        if (action == RTM_CHANGE)
                hdr.rtm_fmask = RTF_REJECT|RTF_BLACKHOLE;
diff -u ospf6d.uptodate/ospf6d.c ospf6d.patch1/ospf6d.c
--- ospf6d.uptodate/ospf6d.c    Thu Sep 20 15:25:33 2012
+++ ospf6d.patch1/ospf6d.c      Thu Sep 20 22:27:10 2012
@@ -422,7 +422,7 @@
        struct imsgbuf  *ibuf = &iev->ibuf;
        struct imsg      imsg;
        ssize_t          n;
-       int              shut = 0;
+       int              count, shut = 0;
 
        if (event & EV_READ) {
                if ((n = imsg_read(ibuf)) == -1)
@@ -444,7 +444,9 @@
 
                switch (imsg.hdr.type) {
                case IMSG_KROUTE_CHANGE:
-                       if (kr_change(imsg.data))
+                       count = (imsg.hdr.len - IMSG_HEADER_SIZE) /
+                               sizeof(struct kroute);
+                       if (kr_change(imsg.data,count))
                                log_warn("main_dispatch_rde: error changing "
                                    "route");
                        break;
diff -u ospf6d.uptodate/ospf6d.h ospf6d.patch1/ospf6d.h
--- ospf6d.uptodate/ospf6d.h    Thu Sep 20 15:25:33 2012
+++ ospf6d.patch1/ospf6d.h      Thu Sep 20 22:27:10 2012
@@ -526,7 +526,7 @@
 
 /* kroute.c */
 int             kr_init(int);
-int             kr_change(struct kroute *);
+int             kr_change(struct kroute *, int);
 int             kr_delete(struct kroute *);
 void            kr_shutdown(void);
 void            kr_fib_couple(void);
diff -u ospf6d.uptodate/rde.c ospf6d.patch1/rde.c
--- ospf6d.uptodate/rde.c       Thu Sep 20 15:25:33 2012
+++ ospf6d.patch1/rde.c Thu Sep 27 17:51:59 2012
@@ -869,28 +869,36 @@
 void
 rde_send_change_kroute(struct rt_node *r)
 {
+       int                      krcount = 0;
        struct kroute            kr;
        struct rt_nexthop       *rn;
+       struct ibuf             *wbuf;
 
-       TAILQ_FOREACH(rn, &r->nexthop, entry) {
-               if (!rn->invalid)
-                       break;
+       if ((wbuf = imsg_create(&iev_main->ibuf, IMSG_KROUTE_CHANGE, 0, 0,
+           sizeof(kr))) == NULL) {
+               return;
        }
-       if (!rn)
-               fatalx("rde_send_change_kroute: no valid nexthop found");
 
-       bzero(&kr, sizeof(kr));
-       kr.prefix = r->prefix;
-       kr.nexthop = rn->nexthop;
-       if (IN6_IS_ADDR_LINKLOCAL(&rn->nexthop) ||
-           IN6_IS_ADDR_MC_LINKLOCAL(&rn->nexthop))
-               kr.scope = rn->ifindex;
-       kr.ifindex = rn->ifindex;
-       kr.prefixlen = r->prefixlen;
-       kr.ext_tag = r->ext_tag;
+       TAILQ_FOREACH(rn, &r->nexthop, entry) {
+               if (rn->invalid)
+                       continue;
+               krcount++;
 
-       imsg_compose_event(iev_main, IMSG_KROUTE_CHANGE, 0, 0, -1,
-           &kr, sizeof(kr));
+               bzero(&kr, sizeof(kr));
+               kr.prefix = r->prefix;
+               kr.nexthop = rn->nexthop;
+               if (IN6_IS_ADDR_LINKLOCAL(&rn->nexthop) ||
+                   IN6_IS_ADDR_MC_LINKLOCAL(&rn->nexthop))
+                       kr.scope = rn->ifindex;
+               kr.ifindex = rn->ifindex;
+               kr.prefixlen = r->prefixlen;
+               kr.ext_tag = r->ext_tag;
+               imsg_add(wbuf, &kr, sizeof(kr));
+       }
+       if (krcount == 0)
+               fatalx("rde_send_change_kroute: no valid nexthop found");
+       imsg_close(&iev_main->ibuf, wbuf);
+       imsg_event_add(iev_main);
 }
 
 void


On Thu, 27 Sep 2012 19:09:58 +0200
Manuel Guesdon <ml+openbsd.m...@oxymium.net> wrote:

>| On Thu, 20 Sep 2012 18:00:26 +0200
>| Claudio Jeker <cje...@diehard.n-r-g.com> wrote:
>| 
>| >| On Thu, Sep 20, 2012 at 05:19:53PM +0200, Manuel Guesdon wrote:
>| >| > Hi,
>| >| > 
>| >| > After checking cvs tree, it seems that ospf6d isn't following changes 
>done in
>| >| > ospfd. 
>| >| > 
>| >| > Is someone working on updating ospf6d to add changes done in ospfd ? 
>(or may
>| >| > be it's not the best way to do ?).
>| >| > 
>| >| > If it's a good idea to do it, I can try. Do you have some advice ? 
>Should I
>| >| > try to apply a big diff between ospfd initial (i.e. 2007 version) and 
>current
>| >| > state ? Or is there a way to retrieve each patch made to ospfd between 
>2007
>| >| > and now ?
>| >| > 
>| >| > A last question: ospf6d initial version was created by copying and 
>modifying
>| >| > ospfd files; I presume it was done this way instead of having same code 
>with
>| >| > #ifdef mecanism for good reasons. After 5 years of evolution, does these
>| >| > reasons still appear beoing valid (I just ask, I haven't sufficient 
>knowledge
>| >| > to give an answer).
>| >| > 
>| >| 
>| >| OSPFv2 and OSPFv3 are similar but still to different to have a common
>| >| source. We try to sync parts between the two daemons from time to time but
>| >| in some parts the behaviour is to different so that syncing is almost
>| >| impossible.
>| 
>| OK.
>| 
>| >| I may sound like a broken record but we accept diffs. So if you think
>| >| there are commits in ospfd that need to be synced over we will have a look
>| >| at them.
>| 
>| Here is a patch adapted from ospfd patch of "Tue Sep 25 11:25:41 2007
>| UTC" (the one of version 1.52 of kroute.c):
>| <<
>| Last missing piece in the equal cost multipath support for ospfd.
>| Send all possible nexthops to the parent process and correctly sync
>| the RIB, FIB and kernel routing table. Based on initial work by pyr@.
>| OK pyr@ norby@
>| PS: don't forget that you need to enable multipath support via a sysctl
>| >>
>| 
>| It seems to solve my problem but not "perfectly". 
>| When starting ospf6d with the best link between 2 hosts down, fib contains
>| 2 other routes comme from 2 other hosts (these 2 routes have equal cost).
>| When the link came UP, these 2 routes are removed and replaced by the best
>| route; that's alright.
>| Next when the link goes down, the 2 alternative routes are well added in fib
>| but the precedent best route is still in the fib (I see it with  route -n -v
>| show |grep TargetIP). May be an important point: TargetIP is an IPv6 on lo1.
>| 
>| I can't find why; if you have any idea... I have a test network so I can make
>| test easily...
>| 
>| 
>| Manuel
>| 
>| 


-- 
Cordialement,

Manuel Guesdon

--
______________________________________________________________________
Manuel Guesdon - OXYMIUM

Reply via email to