Re: ospf6d problem when a route already exists with a different nexthop
Sorry, here is the patch: diff -u ospf6d.uptodate/kroute.c ospf6d.patch1/kroute.c --- ospf6d.uptodate/kroute.cThu Sep 20 15:25:33 2012 +++ ospf6d.patch1/kroute.c Thu Sep 27 18:01:37 2012 @@ -59,6 +59,8 @@ intkr_redist_eval(struct kroute *, struct rroute *); void kr_redistribute(struct kroute_node *); intkroute_compare(struct kroute_node *, struct kroute_node *); +intkr_change_fib(struct kroute_node *, struct kroute *, int, int); +intkr_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 @@ * -
Re: ospf6d problem when a route already exists with a different nexthop
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 [demime 1.01d removed an attachment of type application/octet-stream which had a name of ospf6d-patch1]
Re: ospf6d problem when a route already exists with a different nexthop
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). Manuel On Sun, 9 Sep 2012 17:14:42 +0200 Manuel Guesdon ml+openbsd.m...@oxymium.net wrote: | Hi, | | When an ospf route already exists, ospf6d doesn't update the nexthop. | I have 6 routers (4 with openbsd 5.0, 2 with openbsd 4.9) running ospfd, | ospf6d and bgpd, routeur id is on lo1. | | For some reason (see at end for a way to reproduce it), one of the router | (openbsd 5.0 one) have multiple ospf ipv6 routes still in fib (even if no more | ospf6d or bgpd process is running). For exemple: | | root@core3: route -n get -inet6 :::a |route to: :::a | destination: :::a | gateway: fe80::5054:60ff:fe60:3a1%vlan216 | interface: vlan216 | if address: fe80::5054:60ff:fe60:348%vlan216 |priority: 32 (ospf) | flags: UP,GATEWAY,HOST,DONE | use mtuexpire | 4200 0 0 | | :::a is the loopback address of another router (the gateway is | obviously wrong as I've killed ospf6d and bgpd on the referenced host). | | when starting ospf6d, a new route for :::a is found but ospf6d | find the previous one and don't change the nexthop. And when killing | ospf6d it doesn't remove it. | | If I route delete -inet6 -host :::a | fe80::5054:60ff:fe60:3a1%vlan216, and restart ospf6d the problem disappear. | | I've took a look at ospf6d/kroute.c and found this route is processed like | that: | | kr_change(struct kroute *kroute) | { | struct kroute_node *kr; | int action = RTM_ADD; | | kroute-rtlabel = rtlabel_tag2id(kroute-ext_tag); | | if ((kr = kroute_find(kroute-prefix, kroute-prefixlen)) != | NULL) { | === goes here | | if (!(kr-r.flags F_KERNEL)) | action = RTM_CHANGE; | else { /* a non-ospf route already exists. not a problem */ | === goes here | if (!(kr-r.flags F_BGPD_INSERTED)) { | === goes here | do { | kr-r.flags |= F_OSPFD_INSERTED; | kr = kr-next; | } while (kr); | === exit (nexthop is unchanged) | return (0); | } | | | | This problem occurs when the prefix is announced by different | ospf peers with a different nexthop. Exemple: | | When starting ospf6d a first route is added learned from one ospf6d peer: | | root@core3: route -n get -inet6 :::8 |route to: :::8 | destination: :::8 | gateway: fe80::5054:60ff:fe60:365%vlan222 | interface: vlan222 | if address: fe80::5054:60ff:fe60:345%vlan222 |priority: 32 (ospf) | flags: UP,GATEWAY,HOST,DONE | use mtuexpire |0 0 0 | | Next a second route is learned (gateway on fe80::5054:60ff:fe60:321%vlan213 | which is the most direct route) but ospf6d doesn't update it. | | Here some traces I've added in ospf6d: | MG kr_change: prefix :::8/128 | MG send_rtmsg1: action 1, prefix :::8/128 | MG send_rtmsg2: action 1, nexthop: fe80::5054:60ff:fe60:365 | ... | MG kr_change: prefix :::8/128 | MG kr_change2: found prefix :::8/128 | MG kr_change: prefix :::8/128 !FKERNEL | MG send_rtmsg1: action 3, prefix :::8/128 | MG send_rtmsg2: action 3, nexthop: fe80::5054:60ff:fe60:321 | send_rtmsg: action 1, prefix :::8/128: File exists | | | After killing ospf6d, (first/bad) route is still here: | root@core3:usr.sbin$ route -n get -inet6 :::8 |route to: :::8 | destination: :::8 | gateway: fe80::5054:60ff:fe60:365%vlan222 | interface: vlan222 | if address: fe80::5054:60ff:fe60:345%vlan222 |priority: 32 (ospf) | flags: UP,GATEWAY,HOST,DONE | use mtuexpire | 28 0 0 | | I've retried multiple times and when the 1st learned route is the good one | (via vlan213) the route is well deleted when killing ospf6d. | | | I've tried to compare with ospfd and found that the following chnage seems to | handle nexthop change case: |
Re: ospf6d problem when a route already exists with a different nexthop
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. 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. -- :wq Claudio
ospf6d problem when a route already exists with a different nexthop
Hi, When an ospf route already exists, ospf6d doesn't update the nexthop. I have 6 routers (4 with openbsd 5.0, 2 with openbsd 4.9) running ospfd, ospf6d and bgpd, routeur id is on lo1. For some reason (see at end for a way to reproduce it), one of the router (openbsd 5.0 one) have multiple ospf ipv6 routes still in fib (even if no more ospf6d or bgpd process is running). For exemple: root@core3: route -n get -inet6 :::a route to: :::a destination: :::a gateway: fe80::5054:60ff:fe60:3a1%vlan216 interface: vlan216 if address: fe80::5054:60ff:fe60:348%vlan216 priority: 32 (ospf) flags: UP,GATEWAY,HOST,DONE use mtuexpire 4200 0 0 :::a is the loopback address of another router (the gateway is obviously wrong as I've killed ospf6d and bgpd on the referenced host). when starting ospf6d, a new route for :::a is found but ospf6d find the previous one and don't change the nexthop. And when killing ospf6d it doesn't remove it. If I route delete -inet6 -host :::a fe80::5054:60ff:fe60:3a1%vlan216, and restart ospf6d the problem disappear. I've took a look at ospf6d/kroute.c and found this route is processed like that: kr_change(struct kroute *kroute) { struct kroute_node *kr; int action = RTM_ADD; kroute-rtlabel = rtlabel_tag2id(kroute-ext_tag); if ((kr = kroute_find(kroute-prefix, kroute-prefixlen)) != NULL) { === goes here if (!(kr-r.flags F_KERNEL)) action = RTM_CHANGE; else { /* a non-ospf route already exists. not a problem */ === goes here if (!(kr-r.flags F_BGPD_INSERTED)) { === goes here do { kr-r.flags |= F_OSPFD_INSERTED; kr = kr-next; } while (kr); === exit (nexthop is unchanged) return (0); } This problem occurs when the prefix is announced by different ospf peers with a different nexthop. Exemple: When starting ospf6d a first route is added learned from one ospf6d peer: root@core3: route -n get -inet6 :::8 route to: :::8 destination: :::8 gateway: fe80::5054:60ff:fe60:365%vlan222 interface: vlan222 if address: fe80::5054:60ff:fe60:345%vlan222 priority: 32 (ospf) flags: UP,GATEWAY,HOST,DONE use mtuexpire 0 0 0 Next a second route is learned (gateway on fe80::5054:60ff:fe60:321%vlan213 which is the most direct route) but ospf6d doesn't update it. Here some traces I've added in ospf6d: MG kr_change: prefix :::8/128 MG send_rtmsg1: action 1, prefix :::8/128 MG send_rtmsg2: action 1, nexthop: fe80::5054:60ff:fe60:365 ... MG kr_change: prefix :::8/128 MG kr_change2: found prefix :::8/128 MG kr_change: prefix :::8/128 !FKERNEL MG send_rtmsg1: action 3, prefix :::8/128 MG send_rtmsg2: action 3, nexthop: fe80::5054:60ff:fe60:321 send_rtmsg: action 1, prefix :::8/128: File exists After killing ospf6d, (first/bad) route is still here: root@core3:usr.sbin$ route -n get -inet6 :::8 route to: :::8 destination: :::8 gateway: fe80::5054:60ff:fe60:365%vlan222 interface: vlan222 if address: fe80::5054:60ff:fe60:345%vlan222 priority: 32 (ospf) flags: UP,GATEWAY,HOST,DONE use mtuexpire 28 0 0 I've retried multiple times and when the 1st learned route is the good one (via vlan213) the route is well deleted when killing ospf6d. I've tried to compare with ospfd and found that the following chnage seems to handle nexthop change case: http://www.openbsd.org/cgi-bin/cvsweb/src/usr.sbin/ospfd/kroute.c.diff?r1=1.52;r2=1.53;f=h May be common changes in ospfd weren't ported to ospf6d ? Manuel