diff options
author | Ondrej Filip <feela@network.cz> | 2018-02-27 06:08:03 +0100 |
---|---|---|
committer | Ondrej Filip <feela@network.cz> | 2018-02-27 06:08:03 +0100 |
commit | 44062812600bd29f8edf30ebc871ff218069c5a2 (patch) | |
tree | 656c5cfcfe340cc8a12e7a88d930cfe839f7b97e /nest | |
parent | 6f46465af1b3d21ca67e3b4379640c008fc9d1a1 (diff) | |
parent | 1561ee799cfe79d208ce9588e487da4b62a88dad (diff) |
Merge branch 'int-new' of ssh://gitlab.labs.nic.cz/labs/bird into int-new
Diffstat (limited to 'nest')
-rw-r--r-- | nest/a-path.c | 2 | ||||
-rw-r--r-- | nest/a-path_test.c | 6 | ||||
-rw-r--r-- | nest/cli.c | 4 | ||||
-rw-r--r-- | nest/config.Y | 21 | ||||
-rw-r--r-- | nest/iface.c | 2 | ||||
-rw-r--r-- | nest/mrtdump.h | 1 | ||||
-rw-r--r-- | nest/neighbor.c | 2 | ||||
-rw-r--r-- | nest/proto-hooks.c | 2 | ||||
-rw-r--r-- | nest/protocol.h | 2 | ||||
-rw-r--r-- | nest/route.h | 8 | ||||
-rw-r--r-- | nest/rt-attr.c | 2 | ||||
-rw-r--r-- | nest/rt-dev.c | 10 | ||||
-rw-r--r-- | nest/rt-fib.c | 26 | ||||
-rw-r--r-- | nest/rt-show.c | 8 | ||||
-rw-r--r-- | nest/rt-table.c | 89 |
15 files changed, 110 insertions, 75 deletions
diff --git a/nest/a-path.c b/nest/a-path.c index 32ffc72c..c0d16c30 100644 --- a/nest/a-path.c +++ b/nest/a-path.c @@ -810,7 +810,7 @@ as_path_match(const struct adata *path, struct f_path_mask *mask) case PM_ASN_RANGE: val = mask->val; val2 = mask->val2; - goto step; + goto step; case PM_QUESTION: step: nh = nl = -1; diff --git a/nest/a-path_test.c b/nest/a-path_test.c index 5e122396..a71b48ba 100644 --- a/nest/a-path_test.c +++ b/nest/a-path_test.c @@ -43,14 +43,14 @@ t_as_path_match(void) bt_debug("Prepending ASN: %10u \n", val); if (i == 0) - first_prepended = val; + first_prepended = val; if (i == AS_PATH_LENGTH-1) - last_prepended = val; + last_prepended = val; mask[i].kind = PM_ASN; mask[i].val = val; if (i) - mask[i].next = &mask[i-1]; + mask[i].next = &mask[i-1]; } bt_assert_msg(as_path_match(as_path, &mask[AS_PATH_LENGTH-1]), "Mask should match with AS path"); @@ -60,7 +60,7 @@ * the new one. When the consumer processes everything in the buffer * queue, it calls cli_written(), tha frees all buffers (except the * first one) and schedules cli.event . - * + * */ #include "nest/bird.h" @@ -136,7 +136,7 @@ cli_printf(cli *c, int code, char *msg, ...) } else if (cd == CLI_ASYNC_CODE) { - size = 1; buf[0] = '+'; + size = 1; buf[0] = '+'; errcode = cd; } else diff --git a/nest/config.Y b/nest/config.Y index 044aba2b..ab09a10c 100644 --- a/nest/config.Y +++ b/nest/config.Y @@ -66,7 +66,7 @@ CF_DECLS CF_KEYWORDS(ROUTER, ID, PROTOCOL, TEMPLATE, PREFERENCE, DISABLED, DEBUG, ALL, OFF, DIRECT) CF_KEYWORDS(INTERFACE, IMPORT, EXPORT, FILTER, NONE, VRF, TABLE, STATES, ROUTES, FILTERS) -CF_KEYWORDS(IPV4, IPV6, VPN4, VPN6, ROA4, ROA6) +CF_KEYWORDS(IPV4, IPV6, VPN4, VPN6, ROA4, ROA6, FLOW4, FLOW6, SADR, MPLS) CF_KEYWORDS(RECEIVE, LIMIT, ACTION, WARN, BLOCK, RESTART, DISABLE, KEEP, FILTERED) CF_KEYWORDS(PASSWORD, FROM, PASSIVE, TO, ID, EVENTS, PACKETS, PROTOCOLS, INTERFACES) CF_KEYWORDS(ALGORITHM, KEYED, HMAC, MD5, SHA1, SHA256, SHA384, SHA512) @@ -77,7 +77,7 @@ CF_KEYWORDS(TIMEFORMAT, ISO, SHORT, LONG, ROUTE, PROTOCOL, BASE, LOG, S, MS, US) CF_KEYWORDS(GRACEFUL, RESTART, WAIT, MAX, FLUSH, AS) /* For r_args_channel */ -CF_KEYWORDS(IPV4, IPV4_MC, IPV4_MPLS, IPV6, IPV6_MC, IPV6_MPLS, VPN4, VPN4_MC, VPN4_MPLS, VPN6, VPN6_MC, VPN6_MPLS, ROA4, ROA6, FLOW4, FLOW6, MPLS, PRI, SEC) +CF_KEYWORDS(IPV4, IPV4_MC, IPV4_MPLS, IPV6, IPV6_MC, IPV6_MPLS, IPV6_SADR, VPN4, VPN4_MC, VPN4_MPLS, VPN6, VPN6_MC, VPN6_MPLS, ROA4, ROA6, FLOW4, FLOW6, MPLS, PRI, SEC) CF_ENUM(T_ENUM_RTS, RTS_, DUMMY, STATIC, INHERIT, DEVICE, STATIC_DEVICE, REDIRECT, RIP, OSPF, OSPF_IA, OSPF_EXT1, OSPF_EXT2, BGP, PIPE, BABEL) @@ -134,6 +134,7 @@ gr_opts: GRACEFUL RESTART WAIT expr ';' { new_config->gr_wait = $4; } ; net_type: IPV4 { $$ = NET_IP4; } | IPV6 { $$ = NET_IP6; } + | IPV6 SADR { $$ = NET_IP6_SADR; } | VPN4 { $$ = NET_VPN4; } | VPN6 { $$ = NET_VPN6; } | ROA4 { $$ = NET_ROA4; } @@ -143,7 +144,7 @@ net_type: | MPLS { $$ = NET_MPLS; } ; -CF_ENUM(T_ENUM_NETTYPE, NET_, IP4, IP6, VPN4, VPN6, ROA4, ROA6, FLOW4, FLOW6) +CF_ENUM(T_ENUM_NETTYPE, NET_, IP4, IP6, VPN4, VPN6, ROA4, ROA6, FLOW4, FLOW6, IP6_SADR) /* Creation of routing tables */ @@ -151,7 +152,7 @@ CF_ENUM(T_ENUM_NETTYPE, NET_, IP4, IP6, VPN4, VPN6, ROA4, ROA6, FLOW4, FLOW6) CF_ADDTO(conf, table) table_sorted: - { $$ = 0; } + { $$ = 0; } | SORTED { $$ = 1; } ; @@ -454,9 +455,9 @@ password_item: password_item_begin: PASSWORD text { if (!this_p_list) { - this_p_list = cfg_alloc(sizeof(list)); - init_list(this_p_list); - password_id = 1; + this_p_list = cfg_alloc(sizeof(list)); + init_list(this_p_list); + password_id = 1; } this_p_item = cfg_alloc(sizeof (struct password_item)); this_p_item->password = $2; @@ -625,6 +626,7 @@ r_args_for: } | net_vpn4_ | net_vpn6_ + | net_ip6_sadr_ | VPN_RD IP4 { $$ = cfg_alloc(sizeof(net_addr_vpn4)); net_fill_vpn4($$, $2, IP4_MAX_PREFIX_LENGTH, $1); @@ -633,6 +635,10 @@ r_args_for: $$ = cfg_alloc(sizeof(net_addr_vpn6)); net_fill_vpn6($$, $2, IP6_MAX_PREFIX_LENGTH, $1); } + | IP6 FROM IP6 { + $$ = cfg_alloc(sizeof(net_addr_ip6_sadr)); + net_fill_ip6_sadr($$, $1, IP6_MAX_PREFIX_LENGTH, $3, IP6_MAX_PREFIX_LENGTH); + } | SYM { if ($1->class == (SYM_CONSTANT | T_IP)) { @@ -666,6 +672,7 @@ r_args_channel: | IPV6 { $$ = "ipv6"; } | IPV6_MC { $$ = "ipv6-mc"; } | IPV6_MPLS { $$ = "ipv6-mpls"; } + | IPV6_SADR { $$ = "ipv6-sadr"; } | VPN4 { $$ = "vpn4"; } | VPN4_MC { $$ = "vpn4-mc"; } | VPN4_MPLS { $$ = "vpn4-mpls"; } diff --git a/nest/iface.c b/nest/iface.c index 54c16c58..a633f748 100644 --- a/nest/iface.c +++ b/nest/iface.c @@ -317,7 +317,7 @@ if_update(struct iface *new) new->sysdep = i->sysdep; memcpy(&new->addrs, &i->addrs, sizeof(i->addrs)); memcpy(i, new, sizeof(*i)); - i->flags &= ~IF_UP; /* IF_TMP_DOWN will be added later */ + i->flags &= ~IF_UP; /* IF_TMP_DOWN will be added later */ goto newif; } diff --git a/nest/mrtdump.h b/nest/mrtdump.h index 73932553..28b3bdfd 100644 --- a/nest/mrtdump.h +++ b/nest/mrtdump.h @@ -28,4 +28,3 @@ void mrt_dump_message(struct proto *p, u16 type, u16 subtype, byte *buf, u32 len); #endif - diff --git a/nest/neighbor.c b/nest/neighbor.c index fb05d96c..4f93e29e 100644 --- a/nest/neighbor.c +++ b/nest/neighbor.c @@ -156,7 +156,7 @@ neigh_find2(struct proto *p, ip_addr *a, struct iface *ifa, unsigned flags) WALK_LIST(i, iface_list) if ((!p->vrf || p->vrf == i->master) && ((scope = if_connected(a, i, &addr)) >= 0)) - { + { ifa = i; break; } diff --git a/nest/proto-hooks.c b/nest/proto-hooks.c index 92863f8e..71cddd64 100644 --- a/nest/proto-hooks.c +++ b/nest/proto-hooks.c @@ -281,7 +281,7 @@ int import_control(struct proto *p, rte **e, ea_list **attrs, struct linpool *po /** * rte_recalculate - prepare routes for comparison - * @table: a routing table + * @table: a routing table * @net: a network entry * @new: new route for the network * @old: old route for the network diff --git a/nest/protocol.h b/nest/protocol.h index 9afd3a0a..8a22d76b 100644 --- a/nest/protocol.h +++ b/nest/protocol.h @@ -337,7 +337,7 @@ void proto_notify_state(struct proto *p, unsigned state); * * HUNGRY ----> FEEDING * ^ | - * | V + * | V * FLUSHING <---- HAPPY * * States: HUNGRY Protocol either administratively down (i.e., diff --git a/nest/route.h b/nest/route.h index 43d7d696..79127519 100644 --- a/nest/route.h +++ b/nest/route.h @@ -74,7 +74,7 @@ static inline struct fib_node * fib_user_to_node(struct fib *f, void *e) void fib_init(struct fib *f, pool *p, uint addr_type, uint node_size, uint node_offset, uint hash_order, fib_init_fn init); void *fib_find(struct fib *, const net_addr *); /* Find or return NULL if doesn't exist */ void *fib_get_chain(struct fib *f, const net_addr *a); /* Find first node in linked list from hash table */ -void *fib_get(struct fib *, const net_addr *); /* Find or create new if nonexistent */ +void *fib_get(struct fib *, const net_addr *); /* Find or create new if nonexistent */ void *fib_route(struct fib *, const net_addr *); /* Longest-match routing lookup */ void fib_delete(struct fib *, void *); /* Remove fib entry */ void fib_free(struct fib *); /* Destroy the fib */ @@ -104,7 +104,7 @@ void fit_put_next(struct fib *f, struct fib_iterator *i, struct fib_node *n, uin type *z; \ for(;;) { \ if (!fn_) \ - { \ + { \ if (++hpos_ >= count_) \ break; \ fn_ = (fib)->hash_table[hpos_]; \ @@ -282,7 +282,7 @@ void rt_preconfig(struct config *); 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 *); +void rt_setup(pool *, rtable *, struct rtable_config *); static inline net *net_find(rtable *tab, const net_addr *addr) { return (net *) fib_find(&tab->fib, addr); } static inline net *net_find_valid(rtable *tab, const net_addr *addr) { net *n = net_find(tab, addr); return (n && rte_is_valid(n->routes)) ? n : NULL; } @@ -663,7 +663,7 @@ extern struct protocol *attr_class_to_protocol[EAP_MAX]; * Default protocol preferences */ -#define DEF_PREF_DIRECT 240 /* Directly connected */ +#define DEF_PREF_DIRECT 240 /* Directly connected */ #define DEF_PREF_STATIC 200 /* Static route */ #define DEF_PREF_OSPF 150 /* OSPF intra-area, inter-area and type 1 external routes */ #define DEF_PREF_BABEL 130 /* Babel */ diff --git a/nest/rt-attr.c b/nest/rt-attr.c index 761ba9fe..881687de 100644 --- a/nest/rt-attr.c +++ b/nest/rt-attr.c @@ -1204,7 +1204,7 @@ rta_dump(rta *a) static char *rts[] = { "RTS_DUMMY", "RTS_STATIC", "RTS_INHERIT", "RTS_DEVICE", "RTS_STAT_DEV", "RTS_REDIR", "RTS_RIP", "RTS_OSPF", "RTS_OSPF_IA", "RTS_OSPF_EXT1", - "RTS_OSPF_EXT2", "RTS_BGP", "RTS_PIPE", "RTS_BABEL" }; + "RTS_OSPF_EXT2", "RTS_BGP", "RTS_PIPE", "RTS_BABEL" }; static char *rtd[] = { "", " DEV", " HOLE", " UNREACH", " PROHIBIT" }; debug("p=%s uc=%d %s %s%s h=%04x", diff --git a/nest/rt-dev.c b/nest/rt-dev.c index b3d5bf97..718c4578 100644 --- a/nest/rt-dev.c +++ b/nest/rt-dev.c @@ -159,13 +159,13 @@ dev_copy_config(struct proto_config *dest, struct proto_config *src) } struct protocol proto_device = { - .name = "Direct", - .template = "direct%d", + .name = "Direct", + .template = "direct%d", .preference = DEF_PREF_DIRECT, .channel_mask = NB_IP, .proto_size = sizeof(struct rt_dev_proto), .config_size = sizeof(struct rt_dev_config), - .init = dev_init, - .reconfigure = dev_reconfigure, - .copy_config = dev_copy_config + .init = dev_init, + .reconfigure = dev_reconfigure, + .copy_config = dev_copy_config }; diff --git a/nest/rt-fib.c b/nest/rt-fib.c index 24a7facc..18ccbfc3 100644 --- a/nest/rt-fib.c +++ b/nest/rt-fib.c @@ -92,8 +92,7 @@ fib_ht_free(struct fib_node **h) } -static u32 -fib_hash(struct fib *f, const net_addr *a); +static inline u32 fib_hash(struct fib *f, const net_addr *a); /** * fib_init - initialize a new FIB @@ -198,24 +197,11 @@ fib_rehash(struct fib *f, int step) }) -static u32 +static inline u32 fib_hash(struct fib *f, const net_addr *a) { - ASSERT(f->addr_type == a->type); - - switch (f->addr_type) - { - case NET_IP4: return FIB_HASH(f, a, ip4); - case NET_IP6: return FIB_HASH(f, a, ip6); - case NET_VPN4: return FIB_HASH(f, a, vpn4); - case NET_VPN6: return FIB_HASH(f, a, vpn6); - case NET_ROA4: return FIB_HASH(f, a, roa4); - case NET_ROA6: return FIB_HASH(f, a, roa6); - case NET_FLOW4: return FIB_HASH(f, a, flow4); - case NET_FLOW6: return FIB_HASH(f, a, flow6); - case NET_MPLS: return FIB_HASH(f, a, mpls); - default: bug("invalid type"); - } + /* Same as FIB_HASH() */ + return net_hash(a) >> f->hash_shift; } void * @@ -250,6 +236,7 @@ fib_find(struct fib *f, const net_addr *a) case NET_ROA6: return FIB_FIND(f, a, roa6); case NET_FLOW4: return FIB_FIND(f, a, flow4); case NET_FLOW6: return FIB_FIND(f, a, flow6); + case NET_IP6_SADR: return FIB_FIND(f, a, ip6_sadr); case NET_MPLS: return FIB_FIND(f, a, mpls); default: bug("invalid type"); } @@ -270,6 +257,7 @@ fib_insert(struct fib *f, const net_addr *a, struct fib_node *e) case NET_ROA6: FIB_INSERT(f, a, e, roa6); return; case NET_FLOW4: FIB_INSERT(f, a, e, flow4); return; case NET_FLOW6: FIB_INSERT(f, a, e, flow6); return; + case NET_IP6_SADR: FIB_INSERT(f, a, e, ip6_sadr); return; case NET_MPLS: FIB_INSERT(f, a, e, mpls); return; default: bug("invalid type"); } @@ -617,7 +605,7 @@ fib_histogram(struct fib *f) for (e = f->hash_table[i]; e != NULL; e = e->next) j++; if (j > 0) - log(L_WARN "Histogram line %d: %d", i, j); + log(L_WARN "Histogram line %d: %d", i, j); } log(L_WARN "Histogram dump end"); diff --git a/nest/rt-show.c b/nest/rt-show.c index 41a141a2..1f1b73d2 100644 --- a/nest/rt-show.c +++ b/nest/rt-show.c @@ -74,7 +74,7 @@ rt_show_rte(struct cli *c, byte *ia, rte *e, struct rt_show_data *d, ea_list *tm char weight[16] = ""; if (nh->labels) - { + { lsp += bsprintf(lsp, " mpls %d", nh->label[0]); for (int i=1;i<nh->labels; i++) lsp += bsprintf(lsp, "/%d", nh->label[i]); @@ -129,7 +129,7 @@ rt_show_net(struct cli *c, net *n, struct rt_show_data *d) /* Special case for merged export */ if ((d->export_mode == RSEM_EXPORT) && (ec->ra_mode == RA_MERGED)) - { + { rte *rt_free; e = rt_export_merged(ec, n, &rt_free, &tmpa, c->show_pool, 1); pass = 1; @@ -156,7 +156,8 @@ rt_show_net(struct cli *c, net *n, struct rt_show_data *d) * command may change the export filter and do not update routes. */ int do_export = (ic > 0) || - (f_run(ec->out_filter, &e, &tmpa, c->show_pool, FF_FORCE_TMPATTR) <= F_ACCEPT); + (f_run(ec->out_filter, &e, &tmpa, c->show_pool, + FF_FORCE_TMPATTR | FF_SILENT) <= F_ACCEPT); if (do_export != (d->export_mode == RSEM_EXPORT)) goto skip; @@ -418,4 +419,3 @@ rt_show(struct rt_show_data *d) cli_msg(8001, "Network not found"); } } - diff --git a/nest/rt-table.c b/nest/rt-table.c index b0dd6d3f..686d0e84 100644 --- a/nest/rt-table.c +++ b/nest/rt-table.c @@ -85,6 +85,45 @@ net_route_ip6(rtable *t, net_addr_ip6 *n) return r; } +static inline void * +net_route_ip6_sadr(rtable *t, net_addr_ip6_sadr *n) +{ + struct fib_node *fn; + + while (1) + { + net *best = NULL; + int best_pxlen = 0; + + /* We need to do dst first matching. Since sadr addresses are hashed on dst + prefix only, find the hash table chain and go through it to find the + match with the smallest matching src prefix. */ + for (fn = fib_get_chain(&t->fib, (net_addr *) n); fn; fn = fn->next) + { + net_addr_ip6_sadr *a = (void *) fn->addr; + + if (net_equal_dst_ip6_sadr(n, a) && + net_in_net_src_ip6_sadr(n, a) && + (a->src_pxlen >= best_pxlen)) + { + best = fib_node_to_user(&t->fib, fn); + best_pxlen = a->src_pxlen; + } + } + + if (best) + return best; + + if (!n->dst_pxlen) + break; + + n->dst_pxlen--; + ip6_clrbit(&n->dst_prefix, n->dst_pxlen); + } + + return NULL; +} + void * net_route(rtable *tab, const net_addr *n) { @@ -105,6 +144,9 @@ net_route(rtable *tab, const net_addr *n) case NET_ROA6: return net_route_ip6(tab, (net_addr_ip6 *) n0); + case NET_IP6_SADR: + return net_route_ip6_sadr(tab, (net_addr_ip6_sadr *) n0); + default: return NULL; } @@ -387,7 +429,8 @@ export_filter_(struct channel *c, rte *rt0, rte **rt_free, ea_list **tmpa, linpo } v = filter && ((filter == FILTER_REJECT) || - (f_run(filter, &rt, tmpa, pool, FF_FORCE_TMPATTR) > F_ACCEPT)); + (f_run(filter, &rt, tmpa, pool, + FF_FORCE_TMPATTR | (silent ? FF_SILENT : 0)) > F_ACCEPT)); if (v) { if (silent) @@ -613,9 +656,9 @@ rt_notify_accepted(struct channel *c, net *net, rte *new_changed, rte *old_chang old_meet = 1; } - /* + /* * Second, handle the feed case. That means we do not care for - * old_best. It is NULL for feed, and the new_best for refeed. + * old_best. It is NULL for feed, and the new_best for refeed. * For refeed, there is a hack similar to one in rt_notify_basic() * to ensure withdraws in case of changed filters */ @@ -824,7 +867,7 @@ rt_notify_merged(struct channel *c, net *net, rte *new_changed, rte *old_changed * @new_best: the new best route for the same network * @old_best: the previous best route for the same network * @before_old: The previous route before @old for the same network. - * If @before_old is NULL @old was the first. + * If @before_old is NULL @old was the first. * * This function gets a routing table update and announces it * to all protocols that acccepts given type of route announcement @@ -1386,7 +1429,7 @@ rte_update2(struct channel *c, const net_addr *n, rte *new, struct rte_src *src) /* Independent call to rte_announce(), used from next hop recalculation, outside of rte_update(). new must be non-NULL */ -static inline void +static inline void rte_announce_i(rtable *tab, unsigned type, net *net, rte *new, rte *old, rte *new_best, rte *old_best) { @@ -1419,7 +1462,8 @@ rt_examine(rtable *t, net_addr *a, struct proto *p, struct filter *filter) ea_list *tmpa = rte_make_tmp_attrs(rt, rte_update_pool); int v = p->import_control ? p->import_control(p, &rt, &tmpa, rte_update_pool) : 0; if (v == RIC_PROCESS) - v = (f_run(filter, &rt, &tmpa, rte_update_pool, FF_FORCE_TMPATTR) <= F_ACCEPT); + v = (f_run(filter, &rt, &tmpa, rte_update_pool, + FF_FORCE_TMPATTR | FF_SILENT) <= F_ACCEPT); /* Discard temporary rte */ if (rt != n->routes) @@ -1597,22 +1641,19 @@ rt_event(void *ptr) } void -rt_setup(pool *p, rtable *t, char *name, struct rtable_config *cf) +rt_setup(pool *p, rtable *t, struct rtable_config *cf) { bzero(t, sizeof(*t)); - t->name = name; + t->name = cf->name; t->config = cf; - t->addr_type = cf ? cf->addr_type : NET_IP4; + t->addr_type = cf->addr_type; fib_init(&t->fib, p, t->addr_type, sizeof(net), OFFSETOF(net, n), 0, NULL); init_list(&t->channels); - if (cf) - { - t->rt_event = ev_new(p); - t->rt_event->hook = rt_event; - t->rt_event->data = t; - t->gc_time = current_time(); - } + t->rt_event = ev_new(p); + t->rt_event->hook = rt_event; + t->rt_event->data = t; + t->gc_time = current_time(); } /** @@ -2088,7 +2129,7 @@ rt_commit(struct config *new, struct config *old) { rtable *t = mb_alloc(rt_table_pool, sizeof(struct rtable)); DBG("\t%s: created\n", r->name); - rt_setup(rt_table_pool, t, r->name, r); + rt_setup(rt_table_pool, t, r); add_tail(&routing_tables, &t->n); r->table = t; } @@ -2358,7 +2399,7 @@ if_local_addr(ip_addr a, struct iface *i) return 0; } -static u32 +static u32 rt_get_igp_metric(rte *rt) { eattr *ea = ea_find(rt->attrs->eattrs, EA_GEN_IGP_METRIC); @@ -2390,12 +2431,13 @@ static int rt_update_hostentry(rtable *tab, struct hostentry *he) { rta *old_src = he->src; + int direct = 0; int pxlen = 0; /* Reset the hostentry */ he->src = NULL; - he->nexthop_linkable = 0; he->dest = RTD_UNREACHABLE; + he->nexthop_linkable = 0; he->igp_metric = 0; net_addr he_addr; @@ -2415,9 +2457,7 @@ rt_update_hostentry(rtable *tab, struct hostentry *he) goto done; } - he->dest = a->dest; - he->nexthop_linkable = 1; - if (he->dest == RTD_UNICAST) + if (a->dest == RTD_UNICAST) { for (struct nexthop *nh = &(a->nh); nh; nh = nh->next) if (ipa_zero(nh->gw)) @@ -2430,12 +2470,13 @@ rt_update_hostentry(rtable *tab, struct hostentry *he) goto done; } - he->nexthop_linkable = 0; - break; + direct++; } } he->src = rta_clone(a); + he->dest = a->dest; + he->nexthop_linkable = !direct; he->igp_metric = rt_get_igp_metric(e); } |