[PATCH] More multipath support for OSPF
Hi, I noticed that the multipath support in OSPF seems to be fairly limited. Essentially I was only able to make it do multipath if I had two interfaces connecting to the same router. At my company, we need true multipath between multiple routers using a single interface. (If I needed the other, I could use LACP) I am aware of the implications the default multipath implementation in Linux which operates on a per-packet basis, which is why we've patched our kernels to do it per-flow instead. Anyway, I seemed to have managed to make multipath work as expected - at least in our setup. (Patch attached) Essentially, I've hooked my multipath code into ri_install_ext() and ri_install_net(), where I add the equal routes if the routes share the same type, metrics and OSPF area. I realize that my add_nexthops() is /very/ similar to merge_nexthops() in functionality, but it seemed that the top_hash_entry() could be null, so I wrote a new method which did not rely on that - at the cost of more calls to copy_nexthop(), I guess. Any thoughts? Best regard Peter Christensen
On Thu, Feb 06, 2014 at 02:17:12PM +0100, Peter Christensen wrote:
Hi,
Hello
I noticed that the multipath support in OSPF seems to be fairly limited. Essentially I was only able to make it do multipath if I had two interfaces connecting to the same router. At my company, we need true multipath between multiple routers using a single interface. (If I needed the other, I could use LACP)
Not if such multipath spans multiple routers (e.g. a network consists of several routers connected by ptp links to a circle. Also note that even if you have just one interface, you still get ECMP if there are several paths (through different neighbor routers) to one router few hops away.
I am aware of the implications the default multipath implementation in Linux which operates on a per-packet basis, which is why we've patched our kernels to do it per-flow instead.
Really? AFAIK default Linux implementation is per-flow, not per-packet, unless this was changed recently.
Anyway, I seemed to have managed to make multipath work as expected - at least in our setup. (Patch attached)
Well, what is expected is the question. BIRD currently do multipath on idea that multiple paths through OSPF network topology to one destination in one area are merged, but two same routes originated by two different routers are considered different destinations (which makes perfect sense for propagated default gateways or anycast destinations). You patch merges such routes from different routers, but still keeps routes from different area. Few months ago, Volodymyr Samodid commented that ECMP in OSPF should merge paths from multiple areas. So it seems that this should be at least configurable (like 'ecmp merge internal <bool>', 'ecmp merge external <bool>', 'ecmp merge areas <bool>'). The question is how much detailed such configuration shouldbe. For example, it may be useful to merge external routes with the same route tag, but not merge external routes with different ones. And what about merging internal and external routes together, is this useful? Any thoughts on this issue?
Essentially, I've hooked my multipath code into ri_install_ext() and ri_install_net(), where I add the equal routes if the routes share the same type, metrics and OSPF area. I realize that my add_nexthops() is /very/ similar to merge_nexthops() in functionality, but it seemed that the top_hash_entry() could be null, so I wrote a new method which did not rely on that - at the cost of more calls to copy_nexthop(), I guess.
Any thoughts?
The implementation looks clear and simple, i will look at it thoroughly in a few days. On the first look i see that the patch forgot to zero orta->rid and perhaps orta->tag if merged routes have it different. -- Elen sila lumenn' omentielvo Ondrej 'SanTiago' Zajicek (email: santiago@crfreenet.org) OpenPGP encrypted e-mails preferred (KeyID 0x11DEADC3, wwwkeys.pgp.net) "To err is human -- to blame it on a computer is even more so."
On 02/06/2014 04:14 PM, Ondrej Zajicek wrote:
On Thu, Feb 06, 2014 at 02:17:12PM +0100, Peter Christensen wrote:
Hi, Hello
I noticed that the multipath support in OSPF seems to be fairly limited. Essentially I was only able to make it do multipath if I had two interfaces connecting to the same router. At my company, we need true multipath between multiple routers using a single interface. (If I needed the other, I could use LACP) Not if such multipath spans multiple routers (e.g. a network consists of several routers connected by ptp links to a circle. True. I was just considering the simple case with two routers with two interfaces each connecting to a switch in between. Here, LACP would work just fine.
Also note that even if you have just one interface, you still get ECMP if there are several paths (through different neighbor routers) to one router few hops away. Apparently I didn't. I essentially tries to make my routers balance traffic across multiple load-balancers running OSPF with BIRD. Their setup looks something like this (simplified):
protocol ospf { import none; export none; area 1 { interface "eth0"; interface "lo"; }; } The loopback interface contains a number of anycast addresses which appears as stubnets in OSPF. The routers see the stubnet on both load-balancer, but only pick one (seemingly) random load-balancer when inserting into the routing table. If both the router and one of the load-balancers participated in the area on two interfaces, I got a multipath route entry. I traced the flow and found that stubnets never visited the current multipath code.
I am aware of the implications the default multipath implementation in Linux which operates on a per-packet basis, which is why we've patched our kernels to do it per-flow instead. Really? AFAIK default Linux implementation is per-flow, not per-packet, unless this was changed recently.
The IPv4 multipath code in the kernel actually picks a pseudo-random route in a round-robin fashion. The route cache would however ensure that the flow stayed on a particular path for a while if the route was used continuously. In Linux 3.6 the route cache was removed from the kernel (apparently the route cache behaved badly under heavy load), effectively turning the multipath code from per-flow to per-packet. The IPv6 multipath code has always used a hash-based modulo-N algorithm which ensured consistent flow-based multipath. So we basically added an option in the kernel allowing for hash-based modulo-N based multipath in IPv4 (as an added bonus, the round-robin code required a spinlock, while the hash-based code is lock-free). Unfortunately our implementation disregard multipath weights, so I haven't bothered sending it to any kernel mailing list. By recommendation of RFC 2992 (Analysis of an Equal-Cost Multi-Path Algorithm) I'll probably change our hash modulo-N algorithm to a hash-threshold algorithm, which have better behavior in case of gateways being added or removed to the multipath.
Anyway, I seemed to have managed to make multipath work as expected - at least in our setup. (Patch attached) Well, what is expected is the question. BIRD currently do multipath on idea that multiple paths through OSPF network topology to one destination in one area are merged, but two same routes originated by two different routers are considered different destinations (which makes perfect sense for propagated default gateways or anycast destinations).
The way I interpret the OSPFv2 spec, a destination is simply an IP address prefix. There may be several routes to a particular destination through a lot of routers, but if multiple routes to that destination exist whcih seems identical in quality (cost etc.), those routes are eligible for multipath - even though those destinations are default gateways or anycast destinations (anycast destination are after all indistinguishable from ordinary destinations). So at least what I expect is that /any/ seemingly equal route to a given network should be merged into a multipath route if ecmp is enabled. RFC 4786 (Operation of Anycast Services) talks about using ECMP with anycast services, obviously mentioning that per-packet load-balancing can be problematic with anycast, and that hash-based ECMP is preferred. In other words, combining hash-based multipath with anycast may often be preferable, and the OSPF algorithm ought to ensure that all active routes to the anycast destination are of equal best cost.
You patch merges such routes from different routers, but still keeps routes from different area. Few months ago, Volodymyr Samodid commented that ECMP in OSPF should merge paths from multiple areas.
Really? From RFC 2328 (OSPF Version 2) section 16.8 (page 178): "Each one of the multiple routes will be of the same type (intra-area, inter-area, type 1 external or type 2 external), cost, and will have the same associated area. However, each route may specify a separate next hop and Advertising router." Arent't they saying that each route in the multipath entry must share the same associated area?
So it seems that this should be at least configurable (like 'ecmp merge internal <bool>', 'ecmp merge external <bool>', 'ecmp merge areas <bool>'). The question is how much detailed such configuration shouldbe. For example, it may be useful to merge external routes with the same route tag, but not merge external routes with different ones. And what about merging internal and external routes together, is this useful?
Any thoughts on this issue?
At least from the RFC 2328 point of view, it apparently doesn't make sense to merge the routes across different types of routes. But I guess that boils down to the fact that they usually have different costs.
Essentially, I've hooked my multipath code into ri_install_ext() and ri_install_net(), where I add the equal routes if the routes share the same type, metrics and OSPF area. I realize that my add_nexthops() is /very/ similar to merge_nexthops() in functionality, but it seemed that the top_hash_entry() could be null, so I wrote a new method which did not rely on that - at the cost of more calls to copy_nexthop(), I guess.
Any thoughts? The implementation looks clear and simple, i will look at it thoroughly in a few days. On the first look i see that the patch forgot to zero orta->rid and perhaps orta->tag if merged routes have it different.
Yeah, I guess clearing rid makes sense since the route is really from different routers. As for the tag, I'm not sure what the expected behavior is, since it is out of the scope of the OSPFv2 spec. Maybe that is cause enough to make it tunable whether routes with different tags can be merged. Another thing I've personally noticed, is that I should probably also check ORTA_NSSA, ORTA_PROP and ORTA_PREF when verifying equal cost routes in ri_install_ext. ri_better_ext is after all taking them into consideration.
On Thu, Feb 06, 2014 at 09:47:03PM +0100, Peter Christensen wrote:
Anyway, I seemed to have managed to make multipath work as expected - at least in our setup. (Patch attached) Well, what is expected is the question. BIRD currently do multipath on idea that multiple paths through OSPF network topology to one destination in one area are merged, but two same routes originated by two different routers are considered different destinations (which makes perfect sense for propagated default gateways or anycast destinations). The way I interpret the OSPFv2 spec, a destination is simply an IP address prefix. There may be several routes to a particular destination through a lot of routers, but if multiple routes to that destination exist whcih seems identical in quality (cost etc.), those routes are eligible for multipath - even though those destinations are default gateways or anycast destinations (anycast destination are after all indistinguishable from ordinary destinations). So at least what I expect is that /any/ seemingly equal route to a given network should be merged into a multipath route if ecmp is enabled.
I checked the OSPFv2 spec and you are right, your interpretation seems to be more in line with the meaning of the OSPFv2 spec.
You patch merges such routes from different routers, but still keeps routes from different area. Few months ago, Volodymyr Samodid commented that ECMP in OSPF should merge paths from multiple areas. Really? From RFC 2328 (OSPF Version 2) section 16.8 (page 178): ... Arent't they saying that each route in the multipath entry must share the same associated area?
Sorry, i misremembered that comment, it was related to merging of external paths, not merging paths from different areas.
So it seems that this should be at least configurable (like 'ecmp merge internal <bool>', 'ecmp merge external <bool>', 'ecmp merge areas <bool>'). The question is how much detailed such configuration shouldbe. For example, it may be useful to merge external routes with the same route tag, but not merge external routes with different ones. And what about merging internal and external routes together, is this useful?
Any thoughts on this issue? At least from the RFC 2328 point of view, it apparently doesn't make sense to merge the routes across different types of routes. But I guess that boils down to the fact that they usually have different costs.
You are right, merging routes from different areas or of different types does not really make sense.
Essentially, I've hooked my multipath code into ri_install_ext() and ri_install_net(), where I add the equal routes if the routes share the same type, metrics and OSPF area. I realize that my add_nexthops() is /very/ similar to merge_nexthops() in functionality, but it seemed that the top_hash_entry() could be null, so I wrote a new method which did not rely on that - at the cost of more calls to copy_nexthop(), I guess.
Any thoughts? The implementation looks clear and simple, i will look at it thoroughly in a few days. On the first look i see that the patch forgot to zero orta->rid and perhaps orta->tag if merged routes have it different.
Yeah, I guess clearing rid makes sense since the route is really from different routers. As for the tag, I'm not sure what the expected behavior is, since it is out of the scope of the OSPFv2 spec. Maybe that is cause enough to make it tunable whether routes with different tags can be merged.
Another thing I've personally noticed, is that I should probably also check ORTA_NSSA, ORTA_PROP and ORTA_PREF when verifying equal cost routes in ri_install_ext. ri_better_ext is after all taking them into consideration.
Note that the last comparison in ri_better_ext() is based on rid, which means that you would have to merge ext routes even in some cases when ri_better() returns true. Or perhaps change ri_better_ext() to ri_compare_ext() returning -1, 0, 1 to avoid complicated ri_equal_cost(). Also i am not sure if we would not have to merge next hops in ri_install_rt() for the purpose of summary-rt LSA processing, i would have to look deeper at this. -- Elen sila lumenn' omentielvo Ondrej 'SanTiago' Zajicek (email: santiago@crfreenet.org) OpenPGP encrypted e-mails preferred (KeyID 0x11DEADC3, wwwkeys.pgp.net) "To err is human -- to blame it on a computer is even more so."
Hi, I've revised the old patch and now propose this new version (attached). First of all, I fixed a bug in add_nexthops() which could cause it to forget the existing nexthops if they appeared later in sorting order than then newly added nexthops. Secondly, if the resulting list of nexthops contains more than one nexthop, it now handles the router ID and tag. The only place router ID is used is apparently in NSSA handling which prefers larger router IDs. So to ensure that a multipath route doesn't get confused with another route with a lower router ID, we keep the highest router ID when adding multipaths. As for tags, it's difficult to tell what should be done, but in this case I've decided to clear the tag if the two tag differs, ensuring that we don't lie about the routes (except for cases where admins uses tag=0 to indicate something weird). ri_better(), ri_better_ext(), ri_better_asbr(), and my old ri_equal_cost() have been replaced with ri_compare(), ri_compare_ext(), and ri_compare_asbr() which returns <0, 1, or >0 depending on relative priority. The comparison code is structured syntactically different, but the end result is less code (and on x86 and amd64, less machine code). I just had to handle unsigned 32 bit values differently (rid and areaid). Paths are _ONLY_ considered equal if the area ids are also equal. In other cases, the highest area id is used. ri_compare_asbr() already needed that priority, and for the other scenarios, the RFC does not mandate priority. According to the IETF OSPF mailing list, different implementations prioritize area ids differently. I decided to do potential multipath in /all/ ri_install functions based on the RFC 2328 which states that all routes can be multipath. Besides, multiple threads in the IETF OSPF mailinglist seems to confirm that any route can be multipath as long as prefix, path type, cost, and area is the same. RFC 3101 (NSSA) doesn't mention multipath at all, which initially put me in a dilemma, since it uses router id to break ties. So my solution was to only do that comparison if both routes have the ORTA_NSSA option. I also took the liberty to add const to arguments where it made sense. Best regards Peter Christensen On 02/10/2014 01:00 PM, Ondrej Zajicek wrote:
On Thu, Feb 06, 2014 at 09:47:03PM +0100, Peter Christensen wrote:
Anyway, I seemed to have managed to make multipath work as expected - at least in our setup. (Patch attached) Well, what is expected is the question. BIRD currently do multipath on idea that multiple paths through OSPF network topology to one destination in one area are merged, but two same routes originated by two different routers are considered different destinations (which makes perfect sense for propagated default gateways or anycast destinations). The way I interpret the OSPFv2 spec, a destination is simply an IP address prefix. There may be several routes to a particular destination through a lot of routers, but if multiple routes to that destination exist whcih seems identical in quality (cost etc.), those routes are eligible for multipath - even though those destinations are default gateways or anycast destinations (anycast destination are after all indistinguishable from ordinary destinations). So at least what I expect is that /any/ seemingly equal route to a given network should be merged into a multipath route if ecmp is enabled. I checked the OSPFv2 spec and you are right, your interpretation seems to be more in line with the meaning of the OSPFv2 spec.
You patch merges such routes from different routers, but still keeps routes from different area. Few months ago, Volodymyr Samodid commented that ECMP in OSPF should merge paths from multiple areas. Really? From RFC 2328 (OSPF Version 2) section 16.8 (page 178): ... Arent't they saying that each route in the multipath entry must share the same associated area? Sorry, i misremembered that comment, it was related to merging of external paths, not merging paths from different areas.
So it seems that this should be at least configurable (like 'ecmp merge internal <bool>', 'ecmp merge external <bool>', 'ecmp merge areas <bool>'). The question is how much detailed such configuration shouldbe. For example, it may be useful to merge external routes with the same route tag, but not merge external routes with different ones. And what about merging internal and external routes together, is this useful?
Any thoughts on this issue? At least from the RFC 2328 point of view, it apparently doesn't make sense to merge the routes across different types of routes. But I guess that boils down to the fact that they usually have different costs. You are right, merging routes from different areas or of different types does not really make sense.
Essentially, I've hooked my multipath code into ri_install_ext() and ri_install_net(), where I add the equal routes if the routes share the same type, metrics and OSPF area. I realize that my add_nexthops() is /very/ similar to merge_nexthops() in functionality, but it seemed that the top_hash_entry() could be null, so I wrote a new method which did not rely on that - at the cost of more calls to copy_nexthop(), I guess.
Any thoughts? The implementation looks clear and simple, i will look at it thoroughly in a few days. On the first look i see that the patch forgot to zero orta->rid and perhaps orta->tag if merged routes have it different.
Yeah, I guess clearing rid makes sense since the route is really from different routers. As for the tag, I'm not sure what the expected behavior is, since it is out of the scope of the OSPFv2 spec. Maybe that is cause enough to make it tunable whether routes with different tags can be merged.
Another thing I've personally noticed, is that I should probably also check ORTA_NSSA, ORTA_PROP and ORTA_PREF when verifying equal cost routes in ri_install_ext. ri_better_ext is after all taking them into consideration. Note that the last comparison in ri_better_ext() is based on rid, which means that you would have to merge ext routes even in some cases when ri_better() returns true. Or perhaps change ri_better_ext() to ri_compare_ext() returning -1, 0, 1 to avoid complicated ri_equal_cost().
Also i am not sure if we would not have to merge next hops in ri_install_rt() for the purpose of summary-rt LSA processing, i would have to look deeper at this.
On Fri, Feb 28, 2014 at 10:16:48AM +0100, Peter Christensen wrote:
Hi,
I've revised the old patch and now propose this new version (attached).
Hi Sorry for late answer, i finally find some time to process, review, partially rewrite and merge the patch. I made these changes: 1) Unified add_nexthops() and merge_nexthops() as the algorithm is essentially the same. 2) Fixed several issues in compare functions (see below). 3) Fixed issue with missing special handling of device nexthops and vlink nexthops (and perhaps configured stub networks). 4) Fixed issue in the BIRD code which required special handling of device nexthops during ECMP merging so it is no longer needed (see fix_device_nexthops()). 5) Added config option 'merge external' to make merging of external routes from different LSAs/ASBRs optional (and to keep compatibility with the old behavior). 6) Special handling of orta.en when external routes are merged (see ort_merge_ext()) 7) Fixed some related issues in the BIRD code (like missing incomplete resolution of virtual next hops for routers in ospf_rt_abr1()); 8) Some style changes and some ri_* -> ort[a]_* function renaming. My comments to your patch are below and the final merged patch is attached. Feel free to comment it.
First of all, I fixed a bug in add_nexthops() which could cause it to forget the existing nexthops if they appeared later in sorting order than then newly added nexthops. Secondly, if the resulting list of nexthops contains more than one nexthop, it now handles the router ID and tag. The only place router ID is used is apparently in NSSA handling which prefers larger router IDs. So to ensure that a multipath route doesn't get confused with another route with a lower router ID, we keep the highest router ID when adding multipaths. As for tags, it's difficult to tell what should be done, but in this case I've decided to clear the tag if the two tag differs, ensuring that we don't lie about the routes (except for cases where admins uses tag=0 to indicate something weird).
OK, that is a good idea to clean up tag and keeping higher router ID.
ri_better(), ri_better_ext(), ri_better_asbr(), and my old ri_equal_cost() have been replaced with ri_compare(), ri_compare_ext(), and ri_compare_asbr() which returns <0, 1, or >0 depending on relative priority. The comparison code is structured syntactically different, but the end result is less code (and on x86 and amd64, less machine code).
+ /* Prefer lowest type 1 metric */ + ret = old->metric1 - new->metric1; + if (ret != 0) + return ret;
- if (new->metric1 < old->metric1) - return 1; - - if (new->metric1 > old->metric1) - return 0;
OK, but typecast to int would be a good idea for unsigned variables. Without that it will break if compiled in IPL64 mode (unlikely) or if someone later changes type of some of these variables to a smaller type (sometimes more likely).
just had to handle unsigned 32 bit values differently (rid and areaid). Paths are _ONLY_ considered equal if the area ids are also equal. In other cases, the highest area id is used. ri_compare_asbr() already needed that priority, and for the other scenarios, the RFC does not mandate priority. According to the IETF OSPF mailing list, different implementations prioritize area ids differently.
I decided to do potential multipath in /all/ ri_install functions based on the RFC 2328 which states that all routes can be multipath. Besides, multiple threads in the IETF OSPF mailinglist seems to confirm that any route can be multipath as long as prefix, path type, cost, and area is the same.
That makes sense for all the functions with the exception of ri_compare_asbr() / ri_install_asbr(), where RFC 2328 explicitly specifies that highest area should be used and there is just one possible ASBR with given router ID per area, so merging cannot happen.
I also took the liberty to add const to arguments where it made sense.
OK
diff --git a/proto/ospf/rt.c b/proto/ospf/rt.c index 1b39bda..a39ff2c 100644 --- a/proto/ospf/rt.c +++ b/proto/ospf/rt.c @@ -12,6 +12,8 @@ static void add_cand(list * l, struct top_hash_entry *en, struct top_hash_entry *par, u32 dist, struct ospf_area *oa, int i); static void rt_sync(struct proto_ospf *po); +static int +cmp_nhs(struct mpnh *s1, struct mpnh *s2);
/* In ospf_area->rtr we store paths to routers, but we use RID (and not IP address) as index, so we need to encapsulate RID to IP address */ @@ -54,7 +56,7 @@ new_nexthop(struct proto_ospf *po, ip_addr gw, struct iface *iface, unsigned cha }
static inline struct mpnh * -copy_nexthop(struct proto_ospf *po, struct mpnh *src) +copy_nexthop(struct proto_ospf *po, const struct mpnh *src) { struct mpnh *nh = lp_alloc(po->nhpool, sizeof(struct mpnh)); nh->gw = src->gw; @@ -64,74 +66,153 @@ copy_nexthop(struct proto_ospf *po, struct mpnh *src) return nh; }
+static void +add_nexthops(struct proto_ospf *po, struct orta *old, const struct orta *new) +{ + struct mpnh **pnh = &old->nhs; + struct mpnh *newnh = new->nhs; + + int count = po->ecmp; + + /* Iterate through new next hops */ + while (newnh != NULL && count) + { + struct mpnh *nh = *pnh; + if (nh == NULL) + { + /* Add next hop to end of list */ + *pnh = nh = copy_nexthop(po, newnh); + + pnh = &nh->next; + newnh = newnh->next; + } + else + { + int cmp = cmp_nhs(nh, newnh); + if (cmp < 0) + { + /* Continue to next nexthop */ + pnh = &nh->next; + } + else if (cmp > 0) + { + /* Add nexthop before current nexthop */ + struct mpnh *next; + + *pnh = next = copy_nexthop(po, newnh); + + next->next = nh;
I think this code is wrong, because orta.nhs values are shared between different orta nodes created from one top_hash_entry (like one router-LSA with several stub networks), therefore old->nhs cannot be modified in place. Proper solution would be use the similar approach like in merge_nexthops() - check if orta.nhs is private or shared and merge accordingly. I modified the code of merge_nexthops() so it could be used for both top_hash_entry.nhs and orta.nhs merging, as it is essentially the same process.
/* Whether the ASBR or the forward address destination is preferred in AS external route selection according to 16.4.1. */ static inline int -epath_preferred(orta *ep) +epath_preferred(const orta *ep) { return (ep->type == RTS_OSPF) && (ep->oa->areaid != 0); }
-/* 16.4. (3), return 1 if new is better */
- /* 16.4. (6c) */ + /* 16.4. (6c) - If not RFC1583, select preferred paths */ if (!po->rfc1583) { - u32 new_pref = new->options & ORTA_PREF; - u32 old_pref = old->options & ORTA_PREF; - - if (new_pref > old_pref) - return 1; - - if (new_pref < old_pref) - return 0; + ret = (new->options & ORTA_PREF) - (old->options & ORTA_PREF); + if (ret != 0) + return ret;
I think here is a bug, because ORTA_PREF is 0x80000000, which means that if new has the flag while old does not, ret would be negative (because 0x80000000 typecasted to int is -2^31).
- /* 16.4. (6d) */ - if (new->metric1 < old->metric1) - return 1; - - if (new->metric1 > old->metric1) - return 0; - - /* RFC 3103, 2.5. (6e) */ - int new_prio = orta_prio(new); - int old_prio = orta_prio(old); + /* 16.4. (6d) - Prefer the route with lowest type 1 metric */ + ret = old->metric1 - new->metric1; + if (ret != 0) + return ret;
+ /* RFC 3101, 2.5. (6e) - Prioritize Type-7 LSA with P-bit, then Type-5 LSA, then LSA with higher router ID */ + ret = orta_prio(new) - orta_prio(old); + if (ret != 0) + return ret;
- /* make it more deterministic */ - if (new->rid > old->rid) - return 1; + /* RFC 3101, 2.4 (2) - If the P-bit settings are the same, the LSA with higher router ID is preferred */ + if (new->options & ORTA_NSSA) + { + ret = (new->rid > old->rid) - (new->rid < old->rid); + if (ret != 0) + return ret; + }
- return 0; + /* Prefer largest area id */ + ret = (new->oa->areaid > old->oa->areaid) - (new->oa->areaid < old->oa->areaid); + return ret; }
These two comparisons (RFC 3101 2.5 (6e) preferences and largest area ID) do not make sense for external routes. The first one (together with higher router ID preference) is intended primarily for functionally equivalent LSAs (i.e. same non-zero forwarding address and other fields). There is no reason to not merge them (but we have to keep best LSA according to this criteria in orta.en for proper NSSA translation mechanism). There is no reason to compare area IDs for external routes (and such comparison is not mentioned in RFC 2328). Altough BIRD keeps orta.oa for external rtes, areas are explicitly undefined for external routing table entries in the standard (see RFC 2328 11. 'Area') and therefore the general rule that a routing table entry keeps nexthops from the same area is irrelevant, external routes based on LSAs from ASBRs from different areas could merge. -- Elen sila lumenn' omentielvo Ondrej 'SanTiago' Zajicek (email: santiago@crfreenet.org) OpenPGP encrypted e-mails preferred (KeyID 0x11DEADC3, wwwkeys.pgp.net) "To err is human -- to blame it on a computer is even more so."
participants (2)
-
Ondrej Zajicek -
Peter Christensen