[PATCH 1/9] Adding configuration option --enable-sadr.
From: dean <dluga93@gmail.com> It compiles with the macro SADR_OSPF defined. --- configure | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/configure b/configure index 09c6acf..ad92c7f 100755 --- a/configure +++ b/configure @@ -704,6 +704,7 @@ enable_debug enable_memcheck enable_client enable_ipv6 +enable_sadr enable_pthreads with_suffix with_sysconfig @@ -725,7 +726,6 @@ LIBS CPPFLAGS CPP' - # Initialize some variables set by options. ac_init_help= ac_init_version=false @@ -2317,6 +2317,13 @@ else enable_ipv6=no fi +# Check whether --enable-sadr was given. +if test "${enable_sadr+set}" = set; then : + : +else + enable_sadr=no +fi + # Check whether --enable-pthreads was given. if test "${enable_pthreads+set}" = set; then : enableval=$enable_pthreads; @@ -2401,6 +2408,10 @@ else SUFFIX="" fi +if test "$enable_sadr" = yes ; then + CPPFLAGS="$CPPFLAGS -D SADR_OSPF" +fi + if test "$given_suffix" = yes ; then SUFFIX="$with_suffix" fi -- 2.7.4
From: dean <dluga93@gmail.com> When SADR is enabled, fib_node contains source address prefix and prefix length. A data structure addr_data was added to be passed to fib_{get|find|route} and net_{get|find} functions and allow the same call syntax for the functions, independently of whether SADR is enabled. Two functions were also added that return an addr_data object initialized to zero or with the data from a fib_node object. The fib_* and net_* functions where duplicated to sfib_* snet_* (the 's' standing for sadr) and to fib_*2 net_*2. The sfib_* and snet_* versions exist if SADR is enabled and take both source and destination addresses as arguments. They do the lookup/routing considering both the source and destination. The fib_*2 and net_*2 versions call the correct fib_ or sfib_ function depending on whether SADR is enabled. They take an addr_data argument instead of addresses, so that the syntax of the function call is the same independently of whether SADR is enabled or not. Unchanged protocols will call the same fib_ and net_ functions even if SADR is enabled. In this case, the call is redirected to the sfib_ version using 0::/0 as source address. This is to avoid source specific routes being used by protocols that don't know about them. A part of the rte_validate function was duplicated to check the source prefix for correctness. --- nest/route.h | 46 +++++++++++++++ nest/rt-fib.c | 172 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ nest/rt-table.c | 11 ++++ 3 files changed, 229 insertions(+) diff --git a/nest/route.h b/nest/route.h index 2fcb189..d828ad8 100644 --- a/nest/route.h +++ b/nest/route.h @@ -40,8 +40,26 @@ struct fib_node { byte x0, x1; /* User-defined */ u32 uid; /* Unique ID based on hash */ ip_addr prefix; /* In host order */ + #ifdef SADR_OSPF + ip_addr src_prefix; + byte src_pxlen; + #endif }; +typedef struct addr_data { + ip_addr* prefix; + + #ifdef SADR_OSPF + ip_addr* src_prefix; + #endif + + byte pxlen; + + #ifdef SADR_OSPF + byte src_pxlen; + #endif +} addr_data; + struct fib_iterator { /* See lib/slists.h for an explanation */ struct fib_iterator *prev, *next; /* Must be synced with struct fib_node! */ byte efef; /* 0xff to distinguish between iterator and node */ @@ -68,6 +86,25 @@ void fib_init(struct fib *, pool *, unsigned node_size, unsigned hash_order, fib void *fib_find(struct fib *, ip_addr *, int); /* Find or return NULL if doesn't exist */ void *fib_get(struct fib *, ip_addr *, int); /* Find or create new if nonexistent */ void *fib_route(struct fib *, ip_addr, int); /* Longest-match routing lookup */ + +// same as above but take addr_data argument, and can handle both SADR and non-SADR +void *fib_find2(struct fib *, addr_data); +void *fib_get2(struct fib *, addr_data); +void *fib_route2(struct fib *, addr_data); + +static inline addr_data addr_data_init_empty(void) { + addr_data addr; + memset(&addr, 0, sizeof(addr)); + return addr; +} + +addr_data addr_data_fn_init(struct fib_node *fn); + +#ifdef SADR_OSPF +void *sfib_find(struct fib *, ip_addr *, int, ip_addr*, int); /* Find or return NULL if doesn't exist */ +void *sfib_get(struct fib *, ip_addr *, int, ip_addr*, int); /* Find or create new if nonexistent */ +void *sfib_route(struct fib *, ip_addr, int, ip_addr, int); /* Longest-match routing lookup */ +#endif void fib_delete(struct fib *, void *); /* Remove fib entry */ void fib_free(struct fib *); /* Destroy the fib */ void fib_check(struct fib *); /* Consistency check for debugging */ @@ -268,8 +305,17 @@ void rt_commit(struct config *new, struct config *old); void rt_lock_table(rtable *); void rt_unlock_table(rtable *); void rt_setup(pool *, rtable *, char *, struct rtable_config *); + static inline net *net_find(rtable *tab, ip_addr addr, unsigned len) { return (net *) fib_find(&tab->fib, &addr, len); } static inline net *net_get(rtable *tab, ip_addr addr, unsigned len) { return (net *) fib_get(&tab->fib, &addr, len); } + +static inline net *net_find2(rtable* tab, addr_data addr) { return (net *) fib_find2(&tab->fib, addr); } +static inline net *net_get2(rtable* tab, addr_data addr) { return (net *) fib_get2(&tab->fib, addr); } + +#ifdef SADR_OSPF +static inline net *snet_find(rtable *tab, ip_addr addr, unsigned len, ip_addr saddr, unsigned slen) { return (net *) sfib_find(&tab->fib, &addr, len, &saddr, slen); } +static inline net *snet_get(rtable *tab, ip_addr addr, unsigned len, ip_addr saddr, unsigned slen) { return (net *) sfib_get(&tab->fib, &addr, len, &saddr, slen); } +#endif rte *rte_find(net *net, struct rte_src *src); rte *rte_get_temp(struct rta *); void rte_update2(struct announce_hook *ah, net *net, rte *new, struct rte_src *src); diff --git a/nest/rt-fib.c b/nest/rt-fib.c index a73de1f..7b44e43 100644 --- a/nest/rt-fib.c +++ b/nest/rt-fib.c @@ -153,6 +153,15 @@ fib_rehash(struct fib *f, int step) fib_ht_free(m); } +void * +fib_find2(struct fib *f, addr_data addr) { + #ifdef SADR_OSPF + return sfib_find(f, addr.prefix, addr.pxlen, addr.src_prefix, addr.src_pxlen); + #else + return fib_find(f, addr.prefix, addr.pxlen); + #endif +} + /** * fib_find - search for FIB node by prefix * @f: FIB to search in @@ -165,6 +174,12 @@ fib_rehash(struct fib *f, int step) void * fib_find(struct fib *f, ip_addr *a, int len) { + #ifdef SADR_OSPF + // if SADR is enabled, protocols who don't use it should + // only search for entries with source address 0::/0 + return sfib_find(f, a, len, &IPA_NONE, 0); + #endif + struct fib_node *e = f->hash_table[fib_hash(f, a)]; while (e && (e->pxlen != len || !ipa_equal(*a, e->prefix))) @@ -172,6 +187,19 @@ fib_find(struct fib *f, ip_addr *a, int len) return e; } +#ifdef SADR_OSPF +void * +sfib_find(struct fib *f, ip_addr *a, int len, ip_addr *sa, int slen) +{ + struct fib_node *e = f->hash_table[fib_hash(f, a)]; + + while (e && (e->pxlen != len || !ipa_equal(*a, e->prefix) || + e->src_pxlen != slen || !ipa_equal(*sa, e->src_prefix))) + e = e->next; + return e; +} +#endif + /* int fib_histogram(struct fib *f) @@ -194,6 +222,15 @@ fib_histogram(struct fib *f) } */ +void * +fib_get2(struct fib* f, addr_data addr) { + #ifdef SADR_OSPF + return sfib_get(f, addr.prefix, addr.pxlen, addr.src_prefix, addr.src_pxlen); + #else + return fib_get(f, addr.prefix, addr.pxlen); + #endif +} + /** * fib_get - find or create a FIB node * @f: FIB to work with @@ -206,6 +243,10 @@ fib_histogram(struct fib *f) void * fib_get(struct fib *f, ip_addr *a, int len) { + #ifdef SADR_OSPF + return sfib_get(f, a, len, &IPA_NONE, 0); + #endif + uint h = ipa_hash(*a); struct fib_node **ee = f->hash_table + (h >> f->hash_shift); struct fib_node *g, *e = *ee; @@ -236,6 +277,73 @@ fib_get(struct fib *f, ip_addr *a, int len) e = sl_alloc(f->fib_slab); e->prefix = *a; e->pxlen = len; + + #ifdef SADR_OSPF + // if sadr is enabled, but we don't care about src info, we should + // still set the values to zero + e->src_prefix = IPA_NONE; + e->src_pxlen = 0; + #endif + + e->next = *ee; + e->uid = uid; + *ee = e; + e->readers = NULL; + f->init(e); + if (f->entries++ > f->entries_max) + fib_rehash(f, HASH_HI_STEP); + + return e; +} + +#ifdef SADR_OSPF +/** + * sfib_get - find or create a FIB node (taking into account src) + * @f: FIB to work with + * @a: pointer to IP address of the prefix + * @len: prefix length + * @sa: pointer to IP address of the source prefix + * @slen: source prefix length + * + * Search for a FIB node corresponding to the given prefix and + * return a pointer to it. If no such node exists, create it. + */ +void * +sfib_get(struct fib *f, ip_addr *a, int len, ip_addr* sa, int slen) +{ + uint h = ipa_hash(*a); + struct fib_node **ee = f->hash_table + (h >> f->hash_shift); + struct fib_node *g, *e = *ee; + u32 uid = h << 16; + + while (e && (e->pxlen != len || !ipa_equal(*a, e->prefix) + || e->src_pxlen != slen || !ipa_equal(*sa, e->src_prefix))) + e = e->next; + if (e) + return e; +#ifdef DEBUGGING + if (len < 0 || len > BITS_PER_IP_ADDRESS || !ip_is_prefix(*a,len)) + bug("fib_get() called for invalid address"); +#endif + + while ((g = *ee) && g->uid < uid) + ee = &g->next; + while ((g = *ee) && g->uid == uid) + { + ee = &g->next; + uid++; + } + + if ((uid >> 16) != h) + log(L_ERR "FIB hash table chains are too long"); + + // log (L_WARN "FIB_GET %I %x %x", *a, h, uid); + + e = sl_alloc(f->fib_slab); + e->prefix = *a; + e->pxlen = len; + e->src_prefix = *sa; + e->src_pxlen = slen; e->next = *ee; e->uid = uid; *ee = e; @@ -246,6 +354,17 @@ fib_get(struct fib *f, ip_addr *a, int len) return e; } +#endif + +void * +fib_route2(struct fib *f, addr_data addr) +{ + #ifdef SADR_OSPF + return sfib_route(f, *addr.prefix, addr.pxlen, *addr.src_prefix, addr.src_pxlen); + #else + return fib_route(f, *addr.prefix, addr.pxlen); + #endif +} /** * fib_route - CIDR routing lookup @@ -260,6 +379,10 @@ fib_get(struct fib *f, ip_addr *a, int len) void * fib_route(struct fib *f, ip_addr a, int len) { + #ifdef SADR_OSPF + sfib_route(f, a, len, IPA_NONE, 0); + #endif + ip_addr a0; void *t; @@ -274,6 +397,55 @@ fib_route(struct fib *f, ip_addr a, int len) return NULL; } +#ifdef SADR_OSPF +void * +sfib_route(struct fib *f, ip_addr a, int len, ip_addr sa, int slen) +{ + ip_addr a0, sa0; + void *t; + int slent; + + while (len >= 0) + { + a0 = ipa_and(a, ipa_mkmask(len)); + + // fib_find unconstrained by source address + struct fib_node *e = f->hash_table[fib_hash(f, &a)]; + while (e && (e->pxlen != len || !ipa_equal(a, e->prefix))) + e = e->next; + + t = e; + + if (t) { + slent = slen; + while (slent >= 0) { + sa0 = ipa_and(sa, ipa_mkmask(slent)); + t = sfib_find(f, &a0, len, &sa0, slent); + if (t) + return t; + slent--; + } + } + len--; + } + return NULL; +} +#endif + +addr_data addr_data_fn_init(struct fib_node *fn) { + addr_data addr = { + .prefix = &fn->prefix, + .pxlen = fn->pxlen + }; + + #ifdef SADR_OSPF + addr.src_prefix = &fn->src_prefix; + addr.src_pxlen = fn->src_pxlen; + #endif + + return addr; +} + static inline void fib_merge_readers(struct fib_iterator *i, struct fib_node *to) { diff --git a/nest/rt-table.c b/nest/rt-table.c index d3aba08..309c48c 100644 --- a/nest/rt-table.c +++ b/nest/rt-table.c @@ -817,6 +817,17 @@ rte_validate(rte *e) return 0; } + #ifdef SADR_OSPF + // validation for source address data + if ((n->n.src_pxlen > BITS_PER_IP_ADDRESS) || + !ip_is_prefix(n->n.src_prefix,n->n.src_pxlen)) + { + log(L_WARN "Ignoring bogus prefix %I/%d received via %s", + n->n.src_prefix, n->n.src_pxlen, e->sender->proto->name); + return 0; + } + #endif + return 1; } -- 2.7.4
On Tue, Mar 07, 2017 at 12:56:26AM +0100, Dean Luga wrote:
From: dean <dluga93@gmail.com>
When SADR is enabled, fib_node contains source address prefix and prefix length.
A data structure addr_data was added to be passed to fib_{get|find|route} and net_{get|find} functions and allow the same call syntax for the functions, independently of whether SADR is enabled. Two functions were also added that return an addr_data object initialized to zero or with the data from a fib_node object.
Hi It seems to me that many of these changes replicate the changes that we made in development of BIRD 2.x, perhaps your SADR support could be moved to that branch. It seems to me that a natural way how to represent SADR routes would be to have a new network type (e.g. NET_IP6_SADR) containing both src and dst IPv6 prefixes. That would allow to use generic code for handling networks and routes for handling SADR routes. -- 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 03/07/2017 12:05 PM, Ondrej Zajicek wrote:
On Tue, Mar 07, 2017 at 12:56:26AM +0100, Dean Luga wrote:
From: dean <dluga93@gmail.com>
When SADR is enabled, fib_node contains source address prefix and prefix length.
A data structure addr_data was added to be passed to fib_{get|find|route} and net_{get|find} functions and allow the same call syntax for the functions, independently of whether SADR is enabled. Two functions were also added that return an addr_data object initialized to zero or with the data from a fib_node object. Hi
It seems to me that many of these changes replicate the changes that we made in development of BIRD 2.x, perhaps your SADR support could be moved to that branch.
It seems to me that a natural way how to represent SADR routes would be to have a new network type (e.g. NET_IP6_SADR) containing both src and dst IPv6 prefixes. That would allow to use generic code for handling networks and routes for handling SADR routes.
Ok, where can I find BIRD 2.x? The archive in the website only contains documentation, and I don't see a gitlab branch for 2.x.
Dean <dluga93@gmail.com> writes:
On 03/07/2017 12:05 PM, Ondrej Zajicek wrote:
On Tue, Mar 07, 2017 at 12:56:26AM +0100, Dean Luga wrote:
From: dean <dluga93@gmail.com>
When SADR is enabled, fib_node contains source address prefix and prefix length.
A data structure addr_data was added to be passed to fib_{get|find|route} and net_{get|find} functions and allow the same call syntax for the functions, independently of whether SADR is enabled. Two functions were also added that return an addr_data object initialized to zero or with the data from a fib_node object. Hi
It seems to me that many of these changes replicate the changes that we made in development of BIRD 2.x, perhaps your SADR support could be moved to that branch.
It seems to me that a natural way how to represent SADR routes would be to have a new network type (e.g. NET_IP6_SADR) containing both src and dst IPv6 prefixes. That would allow to use generic code for handling networks and routes for handling SADR routes.
Ok, where can I find BIRD 2.x? The archive in the website only contains documentation, and I don't see a gitlab branch for 2.x.
It's the 'int-new' branch; took me a while to find it too :) -Toke
From: dean <dluga93@gmail.com> Two grammar rules were added that allow addition of source dependent routes in the configuration of the static protocol. route <dst_prefix> from <src_prefix> via <ip> route <dst_prefix> from <src_prefix> via "<interface>" Added a function that returns an addr_data object initialized from a static_route object. static_install and static_remove functions use net_*2 functions to install/remove SADR routes if SADR is enabled. --- proto/static/config.Y | 26 ++++++++++++++++++++++++++ proto/static/static.c | 21 +++++++++++++++++++-- proto/static/static.h | 6 ++++++ 3 files changed, 51 insertions(+), 2 deletions(-) diff --git a/proto/static/config.Y b/proto/static/config.Y index 182721b..1ab35a4 100644 --- a/proto/static/config.Y +++ b/proto/static/config.Y @@ -91,12 +91,38 @@ stat_route: this_srt->via = $3; this_srt->via_if = $4; } + | stat_route0 FROM prefix VIA ipa ipa_scope { + this_srt->dest = RTD_ROUTER; + this_srt->via = $5; + this_srt->via_if = $6; + + #ifdef SADR_OSPF + this_srt->from = $3.addr; + this_srt->slen = $3.len; + #else + cf_error("\"from\" keyword only works when SADR is enabled."); + #endif + } | stat_route0 VIA TEXT { this_srt->dest = RTD_DEVICE; this_srt->if_name = $3; rem_node(&this_srt->n); add_tail(&STATIC_CFG->iface_routes, &this_srt->n); } + | stat_route0 FROM prefix VIA TEXT { + this_srt->dest = RTD_DEVICE; + + #ifdef SADR_OSPF + this_srt->from = $3.addr; + this_srt->slen = $3.len; + #else + cf_error("\"from\" keyword only works when SADR is enabled."); + #endif + + this_srt->if_name = $5; + rem_node(&this_srt->n); + add_tail(&STATIC_CFG->iface_routes, &this_srt->n); + } | stat_route0 MULTIPATH stat_multipath { this_srt->dest = RTD_MULTIPATH; } diff --git a/proto/static/static.c b/proto/static/static.c index d54302a..acf6c30 100644 --- a/proto/static/static.c +++ b/proto/static/static.c @@ -57,6 +57,21 @@ p_igp_table(struct proto *p) return cf->igp_table ? cf->igp_table->table : p->table; } +static addr_data +addr_data_static_init(struct static_route *r) { + addr_data addr = { + .prefix = &r->net, + .pxlen = r->masklen + }; + + #ifdef SADR_OSPF + addr.src_prefix = &r->from; + addr.src_pxlen = r->slen; + #endif + + return addr; +} + static void static_install(struct proto *p, struct static_route *r, struct iface *ifa) { @@ -109,7 +124,8 @@ static_install(struct proto *p, struct static_route *r, struct iface *ifa) /* We skip rta_lookup() here */ - n = net_get(p->table, r->net, r->masklen); + addr_data addr = addr_data_static_init(r); + n = net_get2(p->table, addr); e = rte_get_temp(&a); e->net = n; e->pflags = 0; @@ -133,7 +149,8 @@ static_remove(struct proto *p, struct static_route *r) return; DBG("Removing static route %I/%d via %I\n", r->net, r->masklen, r->via); - n = net_find(p->table, r->net, r->masklen); + addr_data addr = addr_data_static_init(r); + n = net_find2(p->table, addr); rte_update(p, n, NULL); r->installed = 0; } diff --git a/proto/static/static.h b/proto/static/static.h index 6b04723..9bf481b 100644 --- a/proto/static/static.h +++ b/proto/static/static.h @@ -30,6 +30,12 @@ struct static_route { int masklen; /* Mask length */ int dest; /* Destination type (RTD_*) */ ip_addr via; /* Destination router */ + + #ifdef SADR_OSPF + ip_addr from; /* Source address */ + int slen; /* Source address mask length */ + #endif + struct iface *via_if; /* Destination iface, for link-local vias */ struct neighbor *neigh; byte *if_name; /* Name for RTD_DEVICE routes */ -- 2.7.4
From: dean <dluga93@gmail.com> If SADR is enabled, to specify a source constraint for a route, the RTA_SRC attribute, which contains the source address, is added to the netlink message, and the source prefix length is set. If SADR is enabled, the source attribute is also handled when parsing routes in nl_parse_route. --- sysdep/linux/netlink.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/sysdep/linux/netlink.c b/sysdep/linux/netlink.c index 79dd140..f4ec633 100644 --- a/sysdep/linux/netlink.c +++ b/sysdep/linux/netlink.c @@ -902,6 +902,11 @@ nl_send_route(struct krt_proto *p, rte *e, struct ea_list *eattrs, int op, int d r.r.rtm_scope = RT_SCOPE_NOWHERE; nl_add_attr_ipa(&r.h, sizeof(r), RTA_DST, net->n.prefix); + #ifdef SADR_OSPF + r.r.rtm_src_len = net->n.src_pxlen; + nl_add_attr_ipa(&r.h, sizeof(r), RTA_SRC, net->n.src_prefix); + #endif + /* * Strange behavior for RTM_DELROUTE: * 1) rtm_family is ignored in IPv6, works for IPv4 @@ -1138,6 +1143,7 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h) int new = h->nlmsg_type == RTM_NEWROUTE; ip_addr dst = IPA_NONE; + ip_addr srcaddr = IPA_NONE; u32 oif = ~0; u32 table; u32 priority = 0; @@ -1169,6 +1175,11 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h) memcpy(&dst, RTA_DATA(a[RTA_DST]), sizeof(dst)); ipa_ntoh(dst); } + if (a[RTA_SRC]) + { + memcpy(&srcaddr, RTA_DATA(a[RTA_SRC]), sizeof(srcaddr)); + ipa_ntoh(srcaddr); + } if (a[RTA_OIF]) oif = rta_get_u32(a[RTA_OIF]); @@ -1225,7 +1236,15 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h) src = KRT_SRC_ALIEN; } - net *net = net_get(p->p.table, dst, i->rtm_dst_len); + addr_data addr = addr_data_init_empty(); + addr.prefix = &dst; + addr.pxlen = i->rtm_dst_len; + + #ifdef SADR_OSPF + addr.src_prefix = &srcaddr; + addr.src_pxlen = i->rtm_src_len; + #endif + net *net = net_get2(p->p.table, addr); if (s->net && !nl_mergable_route(s, net, p, priority, i->rtm_type)) nl_announce_route(s); -- 2.7.4
From: dean <dluga93@gmail.com> Instead of prefix LSAs containing destination prefixes, they now contain pairs of (destination, source) prefixes. Meaning there will always be an even number of prefixes in the LSAs if SADR is enabled. Functions that process the prefix LSAs now also take into account that there are pairs of prefixes. So they read the prefixes two by two or skip the source prefixes (until a following patch allows them to process source prefixes as well). --- proto/ospf/ospf.c | 6 ++++++ proto/ospf/rt.c | 21 +++++++++++++++++++++ proto/ospf/topology.c | 36 +++++++++++++++++++++++++++++++++++- 3 files changed, 62 insertions(+), 1 deletion(-) diff --git a/proto/ospf/ospf.c b/proto/ospf/ospf.c index d5d5d35..92545e3 100644 --- a/proto/ospf/ospf.c +++ b/proto/ospf/ospf.c @@ -1148,6 +1148,12 @@ show_lsa_prefix(struct top_hash_entry *he, struct top_hash_entry *cnode) cli_msg(-1016, "\t\tstubnet %I/%d metric %u", pxa, pxlen, metric); else cli_msg(-1016, "\t\taddress %I/%d", pxa, pxlen); + + #ifdef SADR_OSPF + // skip source prefix + buf = lsa_get_ipv6_prefix(buf, &pxa, &pxlen, &pxopts, &metric); + i++; + #endif } } diff --git a/proto/ospf/rt.c b/proto/ospf/rt.c index cdf8012..fdcecae 100644 --- a/proto/ospf/rt.c +++ b/proto/ospf/rt.c @@ -587,10 +587,31 @@ spfa_process_prefixes(struct ospf_proto *p, struct ospf_area *oa) continue; buf = px->rest; + #ifdef SADR_OSPF + for (i = 0; i < px->pxcount; i+=2) + #else for (i = 0; i < px->pxcount; i++) + #endif { + addr_data addr = addr_data_init_empty(); + buf = lsa_get_ipv6_prefix(buf, &pxa, &pxlen, &pxopts, &metric); + addr.prefix = &pxa; + addr.pxlen = pxlen; + + #ifdef SADR_OSPF + // src prefix + ip_addr src_pxa; + int src_pxlen; + u8 src_pxopts; + u16 dummy_src_metric; + buf = lsa_get_ipv6_prefix(buf, &src_pxa, &src_pxlen, &src_pxopts, &dummy_src_metric); + + addr.src_prefix = &src_pxa; + addr.src_pxlen = src_pxlen; + #endif + if (pxopts & OPT_PX_NU) continue; diff --git a/proto/ospf/topology.c b/proto/ospf/topology.c index 7558d4a..e8a3772 100644 --- a/proto/ospf/topology.c +++ b/proto/ospf/topology.c @@ -1415,10 +1415,22 @@ prepare_prefix_rt_lsa_body(struct ospf_proto *p, struct ospf_area *oa) (ifa->type == OSPF_IT_PTMP)) { lsab_put_prefix(p, a->ip, MAX_PREFIX_LENGTH, 0); + #ifdef SADR_OSPF + // src prefix + lsab_put_prefix(p, IPA_NONE, 0, 0); + i++; + #endif host_addr = 1; } - else + else { + // put destination prefix lsab_put_prefix(p, a->prefix, a->pxlen, ifa->cost); + #ifdef SADR_OSPF + // put source prefix + lsab_put_prefix(p, IPA_NONE, 0, 0); + i++; + #endif + } i++; } @@ -1433,6 +1445,11 @@ prepare_prefix_rt_lsa_body(struct ospf_proto *p, struct ospf_area *oa) if (sn->px.len == MAX_PREFIX_LENGTH) host_addr = 1; i++; + + #ifdef SADR_OSPF + lsab_put_prefix(p, IPA_NONE, 0, 0); + i++; + #endif } /* If there are some configured vlinks, find some global address @@ -1453,6 +1470,12 @@ prepare_prefix_rt_lsa_body(struct ospf_proto *p, struct ospf_area *oa) /* Found some IP */ lsab_put_prefix(p, a->ip, MAX_PREFIX_LENGTH, 0); i++; + + #ifdef SADR_OSPF + lsab_put_prefix(p, IPA_NONE, 0, 0); + i++; + #endif + goto done; } } @@ -1538,6 +1561,17 @@ add_prefix(struct ospf_proto *p, u32 *px, int offset, int *pxc) pxl = lsab_alloc(p, pxspace); memcpy(pxl, px, pxspace); *pxl &= 0xFFFF0000; /* Set metric to zero */ + + #ifdef SADR_OSPF + // adding src_prefix + u32 spx = 0; + int spxspace = prefix_space(&spx); + u32* spxl = lsab_alloc(p, spxspace); + memcpy(spxl, &spx, spxspace); + + (*pxc)++; + #endif + (*pxc)++; } -- 2.7.4
From: dean <dluga93@gmail.com> Again with the same concept as for prefix LSAs, summary LSAs will include pairs of (destination, source) prefixes instead of just destination prefixes when SADR is enabled. To match this change, the functions that handle the summary LSA parsing and validation were also changed. Parsing summary LSAs is now done using the addr_data structure, instead of prefix address and prefix length, to avoid using a different call syntax based on whether SADR is enabled or not. The functions that call the summary LSA parsing function were also changed to use the addr_data objects. --- proto/ospf/lsalib.c | 27 ++++++++++++++++++++++----- proto/ospf/lsalib.h | 2 +- proto/ospf/ospf.c | 14 +++++++++++--- proto/ospf/rt.c | 35 ++++++++++++++++++++++++++--------- proto/ospf/topology.c | 15 +++++++++++++-- 5 files changed, 73 insertions(+), 20 deletions(-) diff --git a/proto/ospf/lsalib.c b/proto/ospf/lsalib.c index 1bbd137..eac9780 100644 --- a/proto/ospf/lsalib.c +++ b/proto/ospf/lsalib.c @@ -280,13 +280,15 @@ lsa_walk_rt(struct ospf_lsa_rt_walk *rt) void -lsa_parse_sum_net(struct top_hash_entry *en, int ospf2, ip_addr *ip, int *pxlen, u8 *pxopts, u32 *metric) +lsa_parse_sum_net(struct top_hash_entry *en, int ospf2, + addr_data *addr, + u8 *pxopts, u32 *metric) { if (ospf2) { struct ospf_lsa_sum2 *ls = en->lsa_body; - *ip = ipa_from_u32(en->lsa.id & ls->netmask); - *pxlen = u32_masklen(ls->netmask); + *addr->prefix = ipa_from_u32(en->lsa.id & ls->netmask); + addr->pxlen = u32_masklen(ls->netmask); *pxopts = 0; *metric = ls->metric & LSA_METRIC_MASK; } @@ -294,7 +296,12 @@ lsa_parse_sum_net(struct top_hash_entry *en, int ospf2, ip_addr *ip, int *pxlen, { struct ospf_lsa_sum3_net *ls = en->lsa_body; u16 rest; - lsa_get_ipv6_prefix(ls->prefix, ip, pxlen, pxopts, &rest); + u32* buf = lsa_get_ipv6_prefix(ls->prefix, addr->prefix, (int*)(&addr->pxlen), pxopts, &rest); + + #ifdef SADR_OSPF + lsa_get_ipv6_prefix(buf, addr->src_prefix, &addr->src_pxlen, pxopts, &rest); + #endif + *metric = ls->metric & LSA_METRIC_MASK; } } @@ -452,12 +459,22 @@ lsa_validate_sum3_net(struct ospf_lsa_header *lsa, struct ospf_lsa_sum3_net *bod return 0; u8 pxl = pxlen(body->prefix); + + #ifdef SADR_OSPF + u8 spxl = pxlen(body->prefix + IPV6_PREFIX_SPACE(pxl)/4); + #endif + if (pxl > MAX_PREFIX_LENGTH) return 0; if (lsa->length != (HDRLEN + sizeof(struct ospf_lsa_sum3_net) + - IPV6_PREFIX_SPACE(pxl))) + IPV6_PREFIX_SPACE(pxl) + #ifdef SADR_OSPF + + IPV6_PREFIX_SPACE(spxl) + #endif + )) { return 0; + } return 1; } diff --git a/proto/ospf/lsalib.h b/proto/ospf/lsalib.h index ae6af04..f306188 100644 --- a/proto/ospf/lsalib.h +++ b/proto/ospf/lsalib.h @@ -55,7 +55,7 @@ u16 lsa_verify_checksum(const void *lsa_n, int lsa_len); int lsa_comp(struct ospf_lsa_header *l1, struct ospf_lsa_header *l2); void lsa_walk_rt_init(struct ospf_proto *po, struct top_hash_entry *act, struct ospf_lsa_rt_walk *rt); int lsa_walk_rt(struct ospf_lsa_rt_walk *rt); -void lsa_parse_sum_net(struct top_hash_entry *en, int ospf2, ip_addr *ip, int *pxlen, u8 *pxopts, u32 *metric); +void lsa_parse_sum_net(struct top_hash_entry *en, int ospf2, addr_data *addr, u8 *pxopts, u32 *metric); void lsa_parse_sum_rt(struct top_hash_entry *en, int ospf2, u32 *drid, u32 *metric, u32 *options); void lsa_parse_ext(struct top_hash_entry *en, int ospf2, struct ospf_lsa_ext_local *rt); int lsa_validate(struct ospf_lsa_header *lsa, u32 lsa_type, int ospf2, void *body); diff --git a/proto/ospf/ospf.c b/proto/ospf/ospf.c index 92545e3..1fefb8d 100644 --- a/proto/ospf/ospf.c +++ b/proto/ospf/ospf.c @@ -1074,13 +1074,21 @@ show_lsa_network(struct top_hash_entry *he, int ospf2) static inline void show_lsa_sum_net(struct top_hash_entry *he, int ospf2) { + addr_data addr = addr_data_init_empty(); + ip_addr ip; - int pxlen; + addr.prefix = &ip; + + #ifdef SADR_OSPF + ip_addr src_ip; + addr.src_prefix = &src_ip; + #endif + u8 pxopts; u32 metric; - lsa_parse_sum_net(he, ospf2, &ip, &pxlen, &pxopts, &metric); - cli_msg(-1016, "\t\txnetwork %I/%d metric %u", ip, pxlen, metric); + lsa_parse_sum_net(he, ospf2, &addr, &pxopts, &metric); + cli_msg(-1016, "\t\txnetwork %I/%d metric %u", ip, addr.pxlen, metric); } static inline void diff --git a/proto/ospf/rt.c b/proto/ospf/rt.c index fdcecae..67ea04e 100644 --- a/proto/ospf/rt.c +++ b/proto/ospf/rt.c @@ -763,11 +763,20 @@ ospf_rt_sum(struct ospf_area *oa) { struct ospf_proto *p = oa->po; struct top_hash_entry *en; - ip_addr ip, abrip; + ip_addr abrip; u32 dst_rid, metric, options; ort *abr; - int pxlen = -1, type = -1; + int type = -1; u8 pxopts; + addr_data addr = addr_data_init_empty(); // replaces ip, pxlen (and also src_ip,src_pxlen if sadr is enabled) + + ip_addr a; + addr.prefix = &a; + + #ifdef SADR_OSPF + ip_addr sa; + addr.src_prefix = &sa; + #endif OSPF_TRACE(D_EVENTS, "Starting routing table calculation for inter-area (area %R)", oa->areaid); @@ -792,12 +801,13 @@ ospf_rt_sum(struct ospf_area *oa) if (en->lsa_type == LSA_T_SUM_NET) { - lsa_parse_sum_net(en, ospf_is_v2(p), &ip, &pxlen, &pxopts, &metric); + lsa_parse_sum_net(en, ospf_is_v2(p), &addr, + &pxopts, &metric); if (pxopts & OPT_PX_NU) continue; - if (pxlen < 0 || pxlen > MAX_PREFIX_LENGTH) + if (addr.pxlen < 0 || addr.pxlen > MAX_PREFIX_LENGTH) { log(L_WARN "%s: Invalid prefix in LSA (Type: %04x, Id: %R, Rt: %R)", p->p.name, en->lsa_type, en->lsa.id, en->lsa.rt); @@ -849,7 +859,7 @@ ospf_rt_sum(struct ospf_area *oa) }; if (type == ORT_NET) - ri_install_net(p, ip, pxlen, &nf); + ri_install_net(p, *addr.prefix, addr.pxlen, &nf); else ri_install_rt(oa, dst_rid, &nf); } @@ -865,9 +875,15 @@ ospf_rt_sum_tr(struct ospf_area *oa) ort *re, *abr; ip_addr ip, abrip; u32 dst_rid, metric, options; - int pxlen; u8 pxopts; + addr_data addr = addr_data_init_empty(); + addr.prefix = &ip; + + #ifdef SADR_OSPF + ip_addr src_prefix; + addr.src_prefix = &src_prefix; + #endif if (!bb) return; @@ -890,19 +906,20 @@ ospf_rt_sum_tr(struct ospf_area *oa) if (en->lsa_type == LSA_T_SUM_NET) { - lsa_parse_sum_net(en, ospf_is_v2(p), &ip, &pxlen, &pxopts, &metric); + lsa_parse_sum_net(en, ospf_is_v2(p), &addr, + &pxopts, &metric); if (pxopts & OPT_PX_NU) continue; - if (pxlen < 0 || pxlen > MAX_PREFIX_LENGTH) + if (addr.pxlen < 0 || addr.pxlen > MAX_PREFIX_LENGTH) { log(L_WARN "%s: Invalid prefix in LSA (Type: %04x, Id: %R, Rt: %R)", p->p.name, en->lsa_type, en->lsa.id, en->lsa.rt); continue; } - re = fib_find(&p->rtf, &ip, pxlen); + re = fib_find2(&p->rtf, addr); } else // en->lsa_type == LSA_T_SUM_RT { diff --git a/proto/ospf/topology.c b/proto/ospf/topology.c index e8a3772..b1bfc48 100644 --- a/proto/ospf/topology.c +++ b/proto/ospf/topology.c @@ -999,9 +999,20 @@ prepare_sum3_net_lsa_body(struct ospf_proto *p, ort *nf, u32 metric) { struct ospf_lsa_sum3_net *sum; - sum = lsab_allocz(p, sizeof(struct ospf_lsa_sum3_net) + IPV6_PREFIX_SPACE(nf->fn.pxlen)); + sum = lsab_allocz(p, sizeof(struct ospf_lsa_sum3_net) + + IPV6_PREFIX_SPACE(nf->fn.pxlen) + #ifdef SADR_OSPF + + IPV6_PREFIX_SPACE(nf->fn.src_pxlen) + #endif + ); sum->metric = metric; - put_ipv6_prefix(sum->prefix, nf->fn.prefix, nf->fn.pxlen, 0, 0); + // put dst prefix + u32* buf = put_ipv6_prefix(sum->prefix, nf->fn.prefix, nf->fn.pxlen, 0, 0); + + #ifdef SADR_OSPF + // put src prefix + put_ipv6_prefix(buf, nf->fn.src_prefix, nf->fn.src_pxlen, 0, 0); + #endif } static inline void -- 2.7.4
From: dean <dluga93@gmail.com> The add_network and ri_install_net functions that install networks in the OSPF routing tables when processing intra-area and inter-area routes were changed to use addr_data objects and support SADR entries. The respective calls to these functions also use addr_data objects. --- proto/ospf/rt.c | 41 ++++++++++++++++++++++++++++++----------- 1 file changed, 30 insertions(+), 11 deletions(-) diff --git a/proto/ospf/rt.c b/proto/ospf/rt.c index 67ea04e..c8eaa0f 100644 --- a/proto/ospf/rt.c +++ b/proto/ospf/rt.c @@ -334,9 +334,9 @@ ort_merge_ext(struct ospf_proto *p, ort *o, const orta *new) static inline void -ri_install_net(struct ospf_proto *p, ip_addr prefix, int pxlen, const orta *new) +ri_install_net(struct ospf_proto *p, addr_data addr, const orta *new) { - ort *old = (ort *) fib_get(&p->rtf, &prefix, pxlen); + ort *old = (ort *) fib_get2(&p->rtf, addr); int cmp = orta_compare(p, new, &old->n); if (cmp > 0) @@ -404,7 +404,8 @@ px_pos_to_ifa(struct ospf_area *oa, int pos) static void -add_network(struct ospf_area *oa, ip_addr px, int pxlen, int metric, struct top_hash_entry *en, int pos) +add_network(struct ospf_area *oa, addr_data addr, int metric, + struct top_hash_entry *en, int pos) { struct ospf_proto *p = oa->po; @@ -419,13 +420,22 @@ add_network(struct ospf_area *oa, ip_addr px, int pxlen, int metric, struct top_ .nhs = en->nhs }; - if (pxlen < 0 || pxlen > MAX_PREFIX_LENGTH) + if (addr.pxlen < 0 || addr.pxlen > MAX_PREFIX_LENGTH) { log(L_WARN "%s: Invalid prefix in LSA (Type: %04x, Id: %R, Rt: %R)", p->p.name, en->lsa_type, en->lsa.id, en->lsa.rt); return; } + #ifdef SADR_OSPF + if (addr.src_pxlen < 0 || addr.src_pxlen > MAX_PREFIX_LENGTH) + { + log(L_WARN "%s: Invalid src prefix in LSA (Type: %04x, Id: %R, Rt: %R)", + p->p.name, en->lsa_type, en->lsa.id, en->lsa.rt); + return; + } + #endif + if (en == oa->rt) { /* @@ -441,7 +451,7 @@ add_network(struct ospf_area *oa, ip_addr px, int pxlen, int metric, struct top_ nf.nhs = ifa ? new_nexthop(p, IPA_NONE, ifa->iface, ifa->ecmp_weight) : NULL; } - ri_install_net(p, px, pxlen, &nf); + ri_install_net(p, addr, &nf); } @@ -505,7 +515,12 @@ spfa_process_rt(struct ospf_proto *p, struct ospf_area *oa, struct top_hash_entr */ prefix = ipa_from_u32(rtl.id & rtl.data); pxlen = u32_masklen(rtl.data); - add_network(oa, prefix, pxlen, act->dist + rtl.metric, act, i); + + addr_data addr = addr_data_init_empty(); + addr.prefix = &prefix; + addr.pxlen = pxlen; + + add_network(oa, addr, act->dist + rtl.metric, act, i); break; case LSART_NET: @@ -528,13 +543,17 @@ spfa_process_net(struct ospf_proto *p, struct ospf_area *oa, struct top_hash_ent struct ospf_lsa_net *ln = act->lsa_body; struct top_hash_entry *tmp; ip_addr prefix; - int pxlen, i, cnt; + int i, cnt; if (ospf_is_v2(p)) { prefix = ipa_from_u32(act->lsa.id & ln->optx); - pxlen = u32_masklen(ln->optx); - add_network(oa, prefix, pxlen, act->dist, act, -1); + + addr_data addr = addr_data_init_empty(); + addr.prefix = &prefix; + addr.pxlen = u32_masklen(ln->optx); + + add_network(oa, addr, act->dist, act, -1); } cnt = lsa_net_count(&act->lsa); @@ -619,7 +638,7 @@ spfa_process_prefixes(struct ospf_proto *p, struct ospf_area *oa) if ((pxopts & OPT_PX_LA) && ipa_zero(src->lb)) src->lb = pxa; - add_network(oa, pxa, pxlen, src->dist + metric, src, i); + add_network(oa, addr, src->dist + metric, src, i); } } } @@ -859,7 +878,7 @@ ospf_rt_sum(struct ospf_area *oa) }; if (type == ORT_NET) - ri_install_net(p, *addr.prefix, addr.pxlen, &nf); + ri_install_net(p, addr, &nf); else ri_install_rt(oa, dst_rid, &nf); } -- 2.7.4
From: dean <dluga93@gmail.com> As with the previous LSAs, there won't be just simple destination prefixes in the LSA, but pairs of (destination, source) prefixes instead. The parsing and validation functions of external LSAs will handle these changes. The installation of the external routes in the OSPF routing table now uses the addr_data structure to support SADR without needing to change call syntax based on whether SADR is enabled. To facilitate these calls, a new function was added that creates an addr_data object based on an external LSA. --- proto/ospf/lsalib.c | 21 ++++++++++++++++++++- proto/ospf/ospf.c | 15 +++++++++++++++ proto/ospf/ospf.h | 8 ++++++++ proto/ospf/rt.c | 7 ++++--- proto/ospf/topology.c | 7 +++++++ 5 files changed, 54 insertions(+), 4 deletions(-) diff --git a/proto/ospf/lsalib.c b/proto/ospf/lsalib.c index eac9780..ac125a2 100644 --- a/proto/ospf/lsalib.c +++ b/proto/ospf/lsalib.c @@ -347,7 +347,17 @@ lsa_parse_ext(struct top_hash_entry *en, int ospf2, struct ospf_lsa_ext_local *r { struct ospf_lsa_ext3 *ext = en->lsa_body; u16 rest; - u32 *buf = lsa_get_ipv6_prefix(ext->rest, &rt->ip, &rt->pxlen, &rt->pxopts, &rest); + u32 *buf = + lsa_get_ipv6_prefix(ext->rest, &rt->ip, &rt->pxlen, &rt->pxopts, &rest); + + #ifdef SADR_OSPF + // get src + u8 dummy_opts; + u16 dummy_rest; + buf = lsa_get_ipv6_prefix(buf, &rt->src_ip, &rt->src_pxlen, + &dummy_opts, &dummy_rest); + #endif + rt->metric = ext->metric & LSA_METRIC_MASK; rt->ebit = ext->metric & LSA_EXT3_EBIT; @@ -512,6 +522,15 @@ lsa_validate_ext3(struct ospf_lsa_header *lsa, struct ospf_lsa_ext3 *body) return 0; int len = IPV6_PREFIX_SPACE(pxl); + + #ifdef SADR_OSPF + u32* src_start = body->rest + (len/4); + int src_pxlen = pxlen(src_start); + + int slen = IPV6_PREFIX_SPACE(src_pxlen); + len += slen; + #endif + if (body->metric & LSA_EXT3_FBIT) // forwardinf address len += 16; if (body->metric & LSA_EXT3_TBIT) // route tag diff --git a/proto/ospf/ospf.c b/proto/ospf/ospf.c index 1fefb8d..2a630e2 100644 --- a/proto/ospf/ospf.c +++ b/proto/ospf/ospf.c @@ -107,6 +107,21 @@ static int ospf_rte_better(struct rte *new, struct rte *old); static int ospf_rte_same(struct rte *new, struct rte *old); static void ospf_disp(timer *timer); +addr_data addr_data_extlsa_init(struct ospf_lsa_ext_local * lsa) { + addr_data addr = { + .prefix = &lsa->ip, + .pxlen = lsa->pxlen + + #ifdef SADR_OSPF + , + .src_prefix = &lsa->src_ip, + .src_pxlen = lsa->src_pxlen + #endif + }; + + return addr; +} + static void ospf_area_initfib(struct fib_node *fn) { diff --git a/proto/ospf/ospf.h b/proto/ospf/ospf.h index a4e525e..c8a5a51 100644 --- a/proto/ospf/ospf.h +++ b/proto/ospf/ospf.h @@ -683,10 +683,18 @@ struct ospf_lsa_ext_local { ip_addr ip, fwaddr; int pxlen; + + #ifdef SADR_OSPF + ip_addr src_ip; + int src_pxlen; + #endif + u32 metric, ebit, fbit, tag, propagate; u8 pxopts; }; +addr_data addr_data_extlsa_init(struct ospf_lsa_ext_local * lsa); + struct ospf_lsa_link { u32 options; diff --git a/proto/ospf/rt.c b/proto/ospf/rt.c index c8eaa0f..ac21f6e 100644 --- a/proto/ospf/rt.c +++ b/proto/ospf/rt.c @@ -367,9 +367,9 @@ ri_install_asbr(struct ospf_proto *p, ip_addr *addr, const orta *new) } static inline void -ri_install_ext(struct ospf_proto *p, ip_addr prefix, int pxlen, const orta *new) +ri_install_ext(struct ospf_proto *p, addr_data addr, const orta *new) { - ort *old = (ort *) fib_get(&p->rtf, &prefix, pxlen); + ort *old = (ort *) fib_get2(&p->rtf, addr); int cmp = orta_compare_ext(p, new, &old->n); if (cmp > 0) @@ -1599,7 +1599,8 @@ ospf_ext_spf(struct ospf_proto *p) nfa.oa = atmp; /* undefined in RFC 2328 */ nfa.en = en; /* store LSA for later (NSSA processing) */ - ri_install_ext(p, rt.ip, rt.pxlen, &nfa); + addr_data addr = addr_data_extlsa_init(&rt); + ri_install_ext(p, addr, &nfa); } } diff --git a/proto/ospf/topology.c b/proto/ospf/topology.c index b1bfc48..55910bc 100644 --- a/proto/ospf/topology.c +++ b/proto/ospf/topology.c @@ -1094,6 +1094,9 @@ prepare_ext3_lsa_body(struct ospf_proto *p, ort *nf, struct ospf_lsa_ext3 *ext; int bsize = sizeof(struct ospf_lsa_ext3) + IPV6_PREFIX_SPACE(nf->fn.pxlen) + #ifdef SADR_OSPF + + IPV6_PREFIX_SPACE(nf->fn.src_pxlen) + #endif + (ipa_nonzero(fwaddr) ? 16 : 0) + (tag ? 4 : 0); @@ -1103,6 +1106,10 @@ prepare_ext3_lsa_body(struct ospf_proto *p, ort *nf, buf = put_ipv6_prefix(buf, nf->fn.prefix, nf->fn.pxlen, pbit ? OPT_PX_P : 0, 0); + #ifdef SADR_OSPF + buf = put_ipv6_prefix(buf, nf->fn.src_prefix, nf->fn.src_pxlen, pbit ? OPT_PX_P : 0, 0); + #endif + if (ebit) ext->metric |= LSA_EXT3_EBIT; -- 2.7.4
From: dean <dluga93@gmail.com> This last patch updates the function in OSPF that handles routing table update notifications to use source information. Similar changes are applied to the function that synchronizes OSPF routing tables with nest's routing tables. Finally, some work of area border routers (like deciding whether to flush or originate summary LSAs) is also changed to support SADR entries if SADR is enabled. --- proto/ospf/rt.c | 30 ++++++++++++++++++++---------- proto/ospf/topology.c | 6 ++++-- 2 files changed, 24 insertions(+), 12 deletions(-) diff --git a/proto/ospf/rt.c b/proto/ospf/rt.c index ac21f6e..39de770 100644 --- a/proto/ospf/rt.c +++ b/proto/ospf/rt.c @@ -1054,8 +1054,9 @@ decide_sum_lsa(struct ospf_area *oa, ort *nf, int dest) if ((nf->n.oa == oa->po->backbone) && oa->trcap) return 1; + addr_data addr = addr_data_fn_init(&nf->fn); struct area_net *anet = (struct area_net *) - fib_route(&nf->n.oa->net_fib, nf->fn.prefix, nf->fn.pxlen); + fib_route2(&nf->n.oa->net_fib, addr); /* Condensed area network found */ if (anet) @@ -1080,7 +1081,8 @@ check_sum_net_lsa(struct ospf_proto *p, ort *nf) /* Find that area network */ WALK_LIST(anet_oa, p->area_list) { - anet = (struct area_net *) fib_find(&anet_oa->net_fib, &nf->fn.prefix, nf->fn.pxlen); + addr_data addr = addr_data_fn_init(&nf->fn); + anet = (struct area_net *) fib_find2(&anet_oa->net_fib, addr); if (anet) break; } @@ -1115,7 +1117,8 @@ decide_nssa_lsa(struct ospf_proto *p, ort *nf, struct ospf_lsa_ext_local *rt) return 0; /* Condensed area network found */ - if (fib_route(&oa->enet_fib, nf->fn.prefix, nf->fn.pxlen)) + addr_data addr = addr_data_fn_init(&nf->fn); + if (fib_route2(&oa->enet_fib, addr)) return 0; if (!en || (en->lsa_type != LSA_T_NSSA)) @@ -1150,7 +1153,8 @@ check_nssa_lsa(struct ospf_proto *p, ort *nf) /* Find that area network */ WALK_LIST(oa, p->area_list) { - anet = (struct area_net *) fib_find(&oa->enet_fib, &nf->fn.prefix, nf->fn.pxlen); + addr_data addr = addr_data_fn_init(&nf->fn); + anet = (struct area_net *) fib_find2(&oa->enet_fib, addr); if (anet) break; } @@ -1246,7 +1250,8 @@ ospf_rt_abr1(struct ospf_proto *p) /* Compute condensed area networks */ if (nf->n.type == RTS_OSPF) { - anet = (struct area_net *) fib_route(&nf->n.oa->net_fib, nf->fn.prefix, nf->fn.pxlen); + addr_data addr = addr_data_fn_init(&nf->fn); + anet = (struct area_net *) fib_route2(&nf->n.oa->net_fib, addr); if (anet) { if (!anet->active) @@ -1254,7 +1259,8 @@ ospf_rt_abr1(struct ospf_proto *p) anet->active = 1; /* Get a RT entry and mark it to know that it is an area network */ - ort *nfi = (ort *) fib_get(&p->rtf, &anet->fn.prefix, anet->fn.pxlen); + addr_data addr2 = addr_data_fn_init(&anet->fn); + ort *nfi = (ort *) fib_get2(&p->rtf, addr2); nfi->area_net = 1; /* 16.2. (3) */ @@ -1402,8 +1408,9 @@ ospf_rt_abr2(struct ospf_proto *p) nf = (ort *) nftmp; if (rt_is_nssa(nf) && (nf->n.options & ORTA_PROP)) { + addr_data addr = addr_data_fn_init(&nf->fn); struct area_net *anet = (struct area_net *) - fib_route(&nf->n.oa->enet_fib, nf->fn.prefix, nf->fn.pxlen); + fib_route2(&nf->n.oa->enet_fib, addr); if (anet) { @@ -1412,7 +1419,8 @@ ospf_rt_abr2(struct ospf_proto *p) anet->active = 1; /* Get a RT entry and mark it to know that it is an area network */ - nf2 = (ort *) fib_get(&p->rtf, &anet->fn.prefix, anet->fn.pxlen); + addr_data addr2 = addr_data_fn_init(&anet->fn); + nf2 = (ort *) fib_get2(&p->rtf, addr2); nf2->area_net = 1; } @@ -2019,7 +2027,8 @@ again1: if (reload || ort_changed(nf, &a0)) { - net *ne = net_get(p->p.table, nf->fn.prefix, nf->fn.pxlen); + addr_data addr = addr_data_fn_init(&nf->fn); + net *ne = net_get2(p->p.table, addr); rta *a = rta_lookup(&a0); rte *e = rte_get_temp(a); @@ -2044,7 +2053,8 @@ again1: rta_free(nf->old_rta); nf->old_rta = NULL; - net *ne = net_get(p->p.table, nf->fn.prefix, nf->fn.pxlen); + addr_data addr = addr_data_fn_init(&nf->fn); + net *ne = net_get2(p->p.table, addr); rte_update(&p->p, ne, NULL); } diff --git a/proto/ospf/topology.c b/proto/ospf/topology.c index 55910bc..4bcf3ce 100644 --- a/proto/ospf/topology.c +++ b/proto/ospf/topology.c @@ -1271,7 +1271,8 @@ ospf_rt_notify(struct proto *P, rtable *tbl UNUSED, net *n, rte *new, rte *old U if (!new) { - nf = (ort *) fib_find(&p->rtf, &n->n.prefix, n->n.pxlen); + addr_data addr = addr_data_fn_init(&n->n); + nf = (ort *) fib_find2(&p->rtf, addr); if (!nf || !nf->external_rte) return; @@ -1314,7 +1315,8 @@ ospf_rt_notify(struct proto *P, rtable *tbl UNUSED, net *n, rte *new, rte *old U } } - nf = (ort *) fib_get(&p->rtf, &n->n.prefix, n->n.pxlen); + addr_data addr = addr_data_fn_init(&n->n); + nf = (ort *) fib_get2(&p->rtf, addr); ospf_originate_ext_lsa(p, oa, nf, LSA_M_EXPORT, metric, ebit, fwd, tag, 1); nf->external_rte = 1; } -- 2.7.4
Dean Luga <dluga93@gmail.com> writes:
From: dean <dluga93@gmail.com>
It compiles with the macro SADR_OSPF defined.
Quick comment (I'll look over the rest in more detail later): Why is source address routing guarded by a configure switch? Shouldn't Bird be able to understand source-specific routing always, and have the use of them be configurable at runtime?
+if test "$enable_sadr" = yes ; then + CPPFLAGS="$CPPFLAGS -D SADR_OSPF" +fi +
See above; but if you *are* going to have a config flag, should it maybe be something that doesn't have the name of a protocol in it (since there will be other protocols supporting SADR routing)? :) -Toke
I used the configure switch since SADR makes changes to the LSAs and it will slightly impact network traffic even with source 0::/0. If someone doesn't want that, they can disable it. About the name, you are right, it should be changed. On 7 Mar 2017 10:32, "Toke Høiland-Jørgensen" <toke@toke.dk> wrote: Dean Luga <dluga93@gmail.com> writes:
From: dean <dluga93@gmail.com>
It compiles with the macro SADR_OSPF defined.
Quick comment (I'll look over the rest in more detail later): Why is source address routing guarded by a configure switch? Shouldn't Bird be able to understand source-specific routing always, and have the use of them be configurable at runtime?
+if test "$enable_sadr" = yes ; then + CPPFLAGS="$CPPFLAGS -D SADR_OSPF" +fi +
See above; but if you *are* going to have a config flag, should it maybe be something that doesn't have the name of a protocol in it (since there will be other protocols supporting SADR routing)? :) -Toke
Dean Luga <dluga93@gmail.com> writes:
I used the configure switch since SADR makes changes to the LSAs and it will slightly impact network traffic even with source 0::/0. If someone doesn't want that, they can disable it.
As in, when you enable SADR all routes announced now carry a SADR? Does that mean bird with SADR enabled will no longer compatible with an OSPF implementation that does not understand? And if so, is this inherent in the OSPF SADR extension, or is this a design choice of your implementation? -Toke
That is correct, it will not be compatible with other OSPF implementations.
From what I've searched, there is no standard for supporting SADR in OSPF, only some IETF drafts (some of which expired) that describe the desired behavior.
One or two of these drafts plan to use OSPF extended LSAs to support SADR, but the extended LSAs are also still drafts, and I am not sure they would cooperate with the current ospf standard. So yes, the design details are mine, but they are based on the OSPF behavior specified in these documents. On 7 Mar 2017 11:41, "Toke Høiland-Jørgensen" <toke@toke.dk> wrote:
Dean Luga <dluga93@gmail.com> writes:
I used the configure switch since SADR makes changes to the LSAs and it will slightly impact network traffic even with source 0::/0. If someone doesn't want that, they can disable it.
As in, when you enable SADR all routes announced now carry a SADR? Does that mean bird with SADR enabled will no longer compatible with an OSPF implementation that does not understand? And if so, is this inherent in the OSPF SADR extension, or is this a design choice of your implementation?
-Toke
Dean Luga <dluga93@gmail.com> writes:
That is correct, it will not be compatible with other OSPF implementations.
From what I've searched, there is no standard for supporting SADR in OSPF, only some IETF drafts (some of which expired) that describe the desired behavior.
One or two of these drafts plan to use OSPF extended LSAs to support SADR, but the extended LSAs are also still drafts, and I am not sure they would cooperate with the current ospf standard.
So yes, the design details are mine, but they are based on the OSPF behavior specified in these documents.
Ah, I see. Well, for compatibility with the Babel SADR extension, it would be good if at least the nest support could be done via separate data structures (Ondrej's suggestion of a separate address family is not a bad one). The Babel protocol specifies an extension TLV for SADR routes that can co-exist with non-SADR routes in the same network. Would need to support that in Bird as well, so please take that into account when you modify the Bird core :) -Toke
On 03/07/2017 01:17 PM, Toke Høiland-Jørgensen wrote:
Dean Luga <dluga93@gmail.com> writes:
That is correct, it will not be compatible with other OSPF implementations.
From what I've searched, there is no standard for supporting SADR in OSPF, only some IETF drafts (some of which expired) that describe the desired behavior.
One or two of these drafts plan to use OSPF extended LSAs to support SADR, but the extended LSAs are also still drafts, and I am not sure they would cooperate with the current ospf standard.
So yes, the design details are mine, but they are based on the OSPF behavior specified in these documents. Ah, I see. Well, for compatibility with the Babel SADR extension, it would be good if at least the nest support could be done via separate data structures (Ondrej's suggestion of a separate address family is not a bad one). The Babel protocol specifies an extension TLV for SADR routes that can co-exist with non-SADR routes in the same network. Would need to support that in Bird as well, so please take that into account when you modify the Bird core :)
-Toke
Hi, I don't know much about Babel, could you go into more detail about this? Is the problem with the code in nest, or with the fact that my OSPF implementation can't be used with other nodes that use the standard OSPF? I tried to make it so that SADR in OSPF wouldn't affect functionality of other protocols. Not counting the addition of the new data structure, the only changes of existing code in nest should be: 1. the fib_node structure having a couple more data fields. If a protocol doesn't use them, this data won't hurt it, right? 2. fib_get, fib_find, fib_route, net_get, and net_find functions might do some more processing, but they should ultimately have the same behavior. Thanks.
Dean <dluga93@gmail.com> writes:
On 03/07/2017 01:17 PM, Toke Høiland-Jørgensen wrote:
Dean Luga <dluga93@gmail.com> writes:
That is correct, it will not be compatible with other OSPF implementations.
From what I've searched, there is no standard for supporting SADR in OSPF, only some IETF drafts (some of which expired) that describe the desired behavior.
One or two of these drafts plan to use OSPF extended LSAs to support SADR, but the extended LSAs are also still drafts, and I am not sure they would cooperate with the current ospf standard.
So yes, the design details are mine, but they are based on the OSPF behavior specified in these documents. Ah, I see. Well, for compatibility with the Babel SADR extension, it would be good if at least the nest support could be done via separate data structures (Ondrej's suggestion of a separate address family is not a bad one). The Babel protocol specifies an extension TLV for SADR routes that can co-exist with non-SADR routes in the same network. Would need to support that in Bird as well, so please take that into account when you modify the Bird core :)
-Toke
Hi,
I don't know much about Babel, could you go into more detail about this? Is the problem with the code in nest, or with the fact that my OSPF implementation can't be used with other nodes that use the standard OSPF?
I tried to make it so that SADR in OSPF wouldn't affect functionality of other protocols. Not counting the addition of the new data structure, the only changes of existing code in nest should be:
Basically, I want to do the opposite: We are going to have several (well, at least two) protocols that understand source-specific routing, so the nest data structures should work with both. And since Babel at least is perfectly happy to mix source-specific and regular routes (and will interoperate with an implementation that only supports the latter), the nest data structures and lookup functions shouldn't be hidden behind a configure switch (but the OSPF support might be I guess, unless you can make it run-time configurable without too much hassle).
1. the fib_node structure having a couple more data fields. If a protocol doesn't use them, this data won't hurt it, right?
Some data structure overhead is probably fine.
2. fib_get, fib_find, fib_route, net_get, and net_find functions might do some more processing, but they should ultimately have the same behavior.
Yeah, the behaviour for non-source-specific routes should be unchanged, and it should do something sensible when both types of routes exist. Haven't gotten around to thinking seriously about how I'd implement source-specific routing for Babel in Bird yet, so you're kinda breaking new ground here; but happy to be a voice in the background at least ;) -Toke
On Tue, Mar 07, 2017 at 12:56:25AM +0100, Dean Luga wrote:
From: dean <dluga93@gmail.com>
It compiles with the macro SADR_OSPF defined. --- configure | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-)
diff --git a/configure b/configure
Hi The script 'configure' is autogenerated, any changes should be done to the source file 'configure.in'. -- 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."
I see, I'll look into it. On 7 Mar 2017 11:49, "Ondrej Zajicek" <santiago@crfreenet.org> wrote:
On Tue, Mar 07, 2017 at 12:56:25AM +0100, Dean Luga wrote:
From: dean <dluga93@gmail.com>
It compiles with the macro SADR_OSPF defined. --- configure | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-)
diff --git a/configure b/configure
Hi
The script 'configure' is autogenerated, any changes should be done to the source file 'configure.in'.
-- 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 (4)
-
Dean -
Dean Luga -
Ondrej Zajicek -
Toke Høiland-Jørgensen