diff options
-rw-r--r-- | Makefile.in | 44 | ||||
-rw-r--r-- | NEWS | 8 | ||||
-rw-r--r-- | client/Makefile | 2 | ||||
-rw-r--r-- | conf/Makefile | 3 | ||||
-rw-r--r-- | filter/Makefile | 4 | ||||
-rw-r--r-- | filter/f-inst.c | 2 | ||||
-rw-r--r-- | misc/bird.spec | 2 | ||||
-rw-r--r-- | nest/protocol.h | 20 | ||||
-rw-r--r-- | nest/route.h | 9 | ||||
-rw-r--r-- | nest/rt-attr.c | 10 | ||||
-rw-r--r-- | nest/rt-show.c | 7 | ||||
-rw-r--r-- | nest/rt-table.c | 225 | ||||
-rw-r--r-- | proto/babel/babel.c | 45 | ||||
-rw-r--r-- | proto/mrt/mrt.c | 2 | ||||
-rw-r--r-- | proto/ospf/ospf.c | 53 | ||||
-rw-r--r-- | proto/ospf/rt.c | 17 | ||||
-rw-r--r-- | proto/rip/rip.c | 38 | ||||
-rw-r--r-- | sysdep/config.h | 2 | ||||
-rw-r--r-- | sysdep/unix/krt.c | 35 |
19 files changed, 319 insertions, 209 deletions
diff --git a/Makefile.in b/Makefile.in index 695fa744..e6dbd572 100644 --- a/Makefile.in +++ b/Makefile.in @@ -65,7 +65,8 @@ endif docgoals := docs userdocs progdocs testgoals := check test tests tests_run cleangoals := clean distclean testsclean -.PHONY: all daemon cli $(docgoals) $(testgoals) $(cleangoals) tags cscope +.PHONY: all daemon cli $(docgoals) $(testgoals) $(cleangoals) tags cscope prepare + all: daemon cli daemon: $(daemon) @@ -106,35 +107,50 @@ include $(addsuffix /Makefile,$(addprefix $(srcdir)/,$(dirs))) # Generic rules # Object file rules -$(objdir)/%.o: $(srcdir)/%.c $(objdir)/.dir-stamp $(objdir)/sysdep/paths.h +$(objdir)/%.o: $(srcdir)/%.c | prepare $(E)echo CC -o $@ -c $< $(Q)$(CC) $(CFLAGS) -MMD -MP -o $@ -c $< -$(objdir)/%.o: $(objdir)/%.c $(objdir)/.dir-stamp $(objdir)/sysdep/paths.h +$(objdir)/%.o: $(objdir)/%.c | prepare $(E)echo CC -o $@ -c $< $(Q)$(CC) $(CFLAGS) -MMD -MP -o $@ -c $< # Debug: Preprocessed source rules -$(objdir)/%.E: $(srcdir)/%.c $(objdir)/.dir-stamp $(objdir)/sysdep/paths.h +$(objdir)/%.E: $(srcdir)/%.c | prepare $(E)echo CC -o $@ -E $< $(Q)$(CC) $(CFLAGS) -MMD -MP -o $@ -E $< -$(objdir)/%.E: $(objdir)/%.c $(objdir)/.dir-stamp $(objdir)/sysdep/paths.h +$(objdir)/%.E: $(objdir)/%.c | prepare $(E)echo CC -o $@ -E $< $(Q)$(CC) $(CFLAGS) -MMD -MP -o $@ -E $< # Debug: Assembler object rules -$(objdir)/%.S: $(srcdir)/%.c $(objdir)/.dir-stamp $(objdir)/sysdep/paths.h +$(objdir)/%.S: $(srcdir)/%.c | prepare $(E)echo CC -o $@ -S $< $(Q)$(CC) $(CFLAGS) -MMD -MP -o $@ -S $< -$(objdir)/%.S: $(objdir)/%.c $(objdir)/.dir-stamp $(objdir)/sysdep/paths.h +$(objdir)/%.S: $(objdir)/%.c | prepare $(E)echo CC -o $@ -S $< $(Q)$(CC) $(CFLAGS) -MMD -MP -o $@ -S $< +# Finally include the computed dependencies: +DEPS = $(shell find $(objdir) -name '*.d') + +# ## if there is at least one non-clean goal +ifneq ($(filter-out $(cleangoals),$(MAKECMDGOALS)),) +-include $(DEPS) +endif + +# ## if the implicit goal is called +ifeq ($(MAKECMDGOALS),) +-include $(DEPS) +endif +# Rule for pre-generating all generated includables +# before compiling any C file +prepare: $(objdir)/sysdep/paths.h | $(objdir)/.dir-stamp -$(objdir)/.dir-stamp: +$(objdir)/.dir-stamp: Makefile $(E)echo MKDIR -p $(addprefix $(objdir)/,$(dirs) doc) $(Q)mkdir -p $(addprefix $(objdir)/,$(dirs) doc) $(Q)touch $@ @@ -153,7 +169,7 @@ $(objdir)/sysdep/paths.h: Makefile tests_targets_ok = $(addsuffix .ok,$(tests_targets)) -$(tests_targets): %: %.o $(tests_objs) +$(tests_targets): %: %.o $(tests_objs) | prepare $(E)echo LD $(LDFLAGS) -o $@ $< "..." $(LIBS) $(Q)$(CC) $(LDFLAGS) -o $@ $^ $(LIBS) @@ -168,16 +184,6 @@ check: tests tests_run tests: $(tests_targets) tests_run: $(tests_targets_ok) -# Finally include the computed dependencies - -ifneq ($(filter-out $(cleangoals),$(MAKECMDGOALS)),) --include $(shell find $(objdir) -name "*.d") -endif - -ifeq ($(MAKECMDGOALS),) --include $(shell find $(objdir) -name "*.d") -endif - tags: cd $(srcdir) ; etags -lc `find $(dirs) -name *.[chY]` @@ -1,3 +1,11 @@ +Version 2.0.4 (2019-02-27) + o OSPF: Opaque LSAs (RFC 5250) + o OSPF: DN-bit handling (RFC 4576) + o Preferred route counters are back + o Important BGP bugfix + o Several bugfixes related to route propagation + o some minor bugfixes + Version 2.0.3 (2019-01-05) o MRT table dumps (RFC 6396) o BGP Long-lived graceful restart diff --git a/client/Makefile b/client/Makefile index c91a30e0..4f972815 100644 --- a/client/Makefile +++ b/client/Makefile @@ -4,8 +4,6 @@ obj := $(src-o-files) $(all-client) $(conf-y-targets): $(s)cmds.Y -$(o)commands.o: $(objdir)/conf/commands.h - $(exedir)/birdc: $(o)birdc.o $(exedir)/birdc: LIBS += $(CLIENT_LIBS) diff --git a/conf/Makefile b/conf/Makefile index 3b65ad1e..19db9c2c 100644 --- a/conf/Makefile +++ b/conf/Makefile @@ -25,9 +25,10 @@ $(o)cf-parse.tab.c: $(o)cf-parse.y $(o)cf-lex.c: $(s)cf-lex.l $(FLEX) $(FLEX_DEBUG) -f -s -B -8 -Pcf_ -o$@ $< -$(o)cf-lex.o: $(o)cf-parse.tab.h $(o)keywords.h $(o)cf-lex.o: CFLAGS+=-Wno-sign-compare -Wno-unused-function +prepare: $(o)keywords.h $(o)commands.h $(o)cf-parse.tab.h + $(addprefix $(o), cf-parse.y keywords.h commands.h cf-parse.tab.h cf-parse.tab.c cf-lex.c): $(objdir)/.dir-stamp $(call clean,cf-parse.tab.h cf-parse.tab.c cf-parse.y keywords.h commands.h cf-lex.c cf-parse.output) diff --git a/filter/Makefile b/filter/Makefile index 9562a2ee..b2f8d96d 100644 --- a/filter/Makefile +++ b/filter/Makefile @@ -3,8 +3,6 @@ obj := $(src-o-files) $(all-daemon) $(cf-local) -$(conf-y-targets) $(conf-lex-targets) $(src-o-files): $(o)inst-gen.h - M4FLAGS_FILTERS=$(filter-out -s,$(M4FLAGS)) $(o)inst-gen.h: $(s)decl.m4 $(s)f-inst.c $(objdir)/.dir-stamp @@ -16,7 +14,7 @@ $(o)inst-gen.c: $(s)decl.m4 $(s)f-inst.c $(objdir)/.dir-stamp $(o)inst-interpret.c: $(s)decl.m4 $(s)f-inst.c $(objdir)/.dir-stamp $(M4) $(M4FLAGS_FILTERS) -DTARGET=I -P $^ >$@ -$(o)filter.o: $(o)inst-interpret.c $(o)inst-gen.h +prepare: $(o)inst-interpret.c $(o)inst-gen.h tests_src := tree_test.c filter_test.c trie_test.c tests_targets := $(tests_targets) $(tests-target-files) diff --git a/filter/f-inst.c b/filter/f-inst.c index 6f031782..3fea16c4 100644 --- a/filter/f-inst.c +++ b/filter/f-inst.c @@ -650,7 +650,7 @@ l->count = 1; l->attrs[0].id = da.ea_code; l->attrs[0].flags = 0; - l->attrs[0].type = EAF_TYPE_UNDEF | EAF_TEMP | EAF_ORIGINATED | EAF_FRESH; + l->attrs[0].type = EAF_TYPE_UNDEF | EAF_ORIGINATED | EAF_FRESH; l->attrs[0].u.data = 0; f_rta_cow(fs); diff --git a/misc/bird.spec b/misc/bird.spec index acd4fe2c..160b00c6 100644 --- a/misc/bird.spec +++ b/misc/bird.spec @@ -1,6 +1,6 @@ Summary: BIRD Internet Routing Daemon Name: bird -Version: 2.0.3 +Version: 2.0.4 Release: 1 Copyright: GPL Group: Networking/Daemons diff --git a/nest/protocol.h b/nest/protocol.h index 82b46261..1e7bfb59 100644 --- a/nest/protocol.h +++ b/nest/protocol.h @@ -194,8 +194,8 @@ struct proto { * ifa_notify Notify protocol about interface address changes. * rt_notify Notify protocol about routing table updates. * neigh_notify Notify protocol about neighbor cache events. - * make_tmp_attrs Construct ea_list from private attrs stored in rta. - * store_tmp_attrs Store private attrs back to rta. The route MUST NOT be cached. + * make_tmp_attrs Add attributes to rta from from private attrs stored in rte. The route and rta MUST NOT be cached. + * store_tmp_attrs Store private attrs back to rte and undef added attributes. The route and rta MUST NOT be cached. * preexport Called as the first step of the route exporting process. * It can construct a new rte, add private attributes and * decide whether the route shall be exported: 1=yes, -1=no, @@ -211,8 +211,8 @@ struct proto { void (*ifa_notify)(struct proto *, unsigned flags, struct ifa *a); void (*rt_notify)(struct proto *, struct channel *, struct network *net, struct rte *new, struct rte *old); void (*neigh_notify)(struct neighbor *neigh); - struct ea_list *(*make_tmp_attrs)(struct rte *rt, struct linpool *pool); - void (*store_tmp_attrs)(struct rte *rt); + void (*make_tmp_attrs)(struct rte *rt, struct linpool *pool); + void (*store_tmp_attrs)(struct rte *rt, struct linpool *pool); int (*preexport)(struct proto *, struct rte **rt, struct linpool *pool); void (*reload_routes)(struct channel *); void (*feed_begin)(struct channel *, int initial); @@ -297,18 +297,6 @@ proto_get_router_id(struct proto_config *pc) return pc->router_id ? pc->router_id : pc->global->router_id; } -static inline void -rte_make_tmp_attrs(struct rte **rt, struct linpool *pool) -{ - struct ea_list *(*mta)(struct rte *rt, struct linpool *pool); - mta = (*rt)->attrs->src->proto->make_tmp_attrs; - if (!mta) return; - *rt = rte_cow_rta(*rt, pool); - struct ea_list *ea = mta(*rt, pool); - ea->next = (*rt)->attrs->eattrs; - (*rt)->attrs->eattrs = ea; -} - extern pool *proto_pool; extern list proto_list; diff --git a/nest/route.h b/nest/route.h index 7c9f3005..9959ea69 100644 --- a/nest/route.h +++ b/nest/route.h @@ -308,6 +308,10 @@ void rte_free(rte *); rte *rte_do_cow(rte *); static inline rte * rte_cow(rte *r) { return (r->flags & REF_COW) ? rte_do_cow(r) : r; } rte *rte_cow_rta(rte *r, linpool *lp); +void rte_init_tmp_attrs(struct rte *r, linpool *lp, uint max); +void rte_make_tmp_attr(struct rte *r, uint id, uint type, uintptr_t val); +void rte_make_tmp_attrs(struct rte **r, struct linpool *pool, struct rta **old_attrs); +uintptr_t rte_store_tmp_attr(struct rte *r, uint id); void rt_dump(rtable *); void rt_dump_all(void); int rt_feed_channel(struct channel *c); @@ -481,6 +485,7 @@ typedef struct eattr { #define EA_CODE(proto,id) (((proto) << 8) | (id)) #define EA_ID(ea) ((ea) & 0xff) #define EA_PROTO(ea) ((ea) >> 8) +#define EA_ID_FLAG(ea) (1 << EA_ID(ea)) #define EA_CUSTOM(id) ((id) | EA_CUSTOM_BIT) #define EA_IS_CUSTOM(ea) ((ea) & EA_CUSTOM_BIT) #define EA_CUSTOM_ID(ea) ((ea) & ~EA_CUSTOM_BIT) @@ -510,7 +515,6 @@ const char *ea_custom_name(uint ea); #define EAF_VAR_LENGTH 0x02 /* Attribute length is variable (part of type spec) */ #define EAF_ORIGINATED 0x20 /* The attribute has originated locally */ #define EAF_FRESH 0x40 /* An uncached attribute (e.g. modified in export filter) */ -#define EAF_TEMP 0x80 /* A temporary attribute (the one stored in the tmp attr list) */ typedef struct adata { uint length; /* Length of data */ @@ -542,6 +546,7 @@ typedef struct ea_list { #define EALF_SORTED 1 /* Attributes are sorted by code */ #define EALF_BISECT 2 /* Use interval bisection for searching */ #define EALF_CACHED 4 /* Attributes belonging to cached rta */ +#define EALF_TEMP 8 /* Temporary ea_list added by make_tmp_attrs hooks */ struct rte_src *rt_find_source(struct proto *p, u32 id); struct rte_src *rt_get_source(struct proto *p, u32 id); @@ -574,6 +579,8 @@ void ea_format_bitfield(struct eattr *a, byte *buf, int bufsize, const char **na ea = t; \ } \ ea_sort(ea); \ + if (ea->count == 0) \ + ea = NULL; \ } while(0) \ static inline eattr * diff --git a/nest/rt-attr.c b/nest/rt-attr.c index 01e807fa..9c38e3ca 100644 --- a/nest/rt-attr.c +++ b/nest/rt-attr.c @@ -573,8 +573,8 @@ ea_do_sort(ea_list *e) } /** - * In place discard duplicates, undefs and temporary attributes in sorted - * ea_list. We use stable sort for this reason. + * In place discard duplicates and undefs in sorted ea_list. We use stable sort + * for this reason. **/ static inline void ea_do_prune(ea_list *e) @@ -598,10 +598,6 @@ ea_do_prune(ea_list *e) if ((s0->type & EAF_TYPE_MASK) == EAF_TYPE_UNDEF) continue; - /* Drop temporary attributes */ - if (s0->type & EAF_TEMP) - continue; - /* Copy the newest version to destination */ *d = *s0; @@ -981,8 +977,6 @@ ea_dump(ea_list *e) { eattr *a = &e->attrs[i]; debug(" %02x:%02x.%02x", EA_PROTO(a->id), EA_ID(a->id), a->flags); - if (a->type & EAF_TEMP) - debug("T"); debug("=%c", "?iO?I?P???S?????" [a->type & EAF_TYPE_MASK]); if (a->type & EAF_ORIGINATED) debug("o"); diff --git a/nest/rt-show.c b/nest/rt-show.c index c7bcdf2f..002a6039 100644 --- a/nest/rt-show.c +++ b/nest/rt-show.c @@ -45,10 +45,11 @@ rt_show_rte(struct cli *c, byte *ia, rte *e, struct rt_show_data *d) else from[0] = 0; - get_route_info = a->src->proto->proto->get_route_info; /* Need to normalize the extended attributes */ - if ((get_route_info || d->verbose) && !rta_is_cached(a)) + if (d->verbose && !rta_is_cached(a) && a->eattrs) ea_normalize(a->eattrs); + + get_route_info = a->src->proto->proto->get_route_info; if (get_route_info) get_route_info(e, info); else @@ -114,7 +115,7 @@ rt_show_net(struct cli *c, net *n, struct rt_show_data *d) continue; ee = e; - rte_make_tmp_attrs(&e, c->show_pool); + rte_make_tmp_attrs(&e, c->show_pool, NULL); /* Export channel is down, do not try to export routes to it */ if (ec && (ec->export_state == ES_DOWN)) diff --git a/nest/rt-table.c b/nest/rt-table.c index f05bd718..12966eca 100644 --- a/nest/rt-table.c +++ b/nest/rt-table.c @@ -326,6 +326,176 @@ rte_cow_rta(rte *r, linpool *lp) return r; } + +/** + * rte_init_tmp_attrs - initialize temporary ea_list for route + * @r: route entry to be modified + * @lp: linpool from which to allocate attributes + * @max: maximum number of added temporary attribus + * + * This function is supposed to be called from make_tmp_attrs() and + * store_tmp_attrs() hooks before rte_make_tmp_attr() / rte_store_tmp_attr() + * functions. It allocates &ea_list with length for @max items for temporary + * attributes and puts it on top of eattrs stack. + */ +void +rte_init_tmp_attrs(rte *r, linpool *lp, uint max) +{ + struct ea_list *e = lp_alloc(lp, sizeof(struct ea_list) + max * sizeof(eattr)); + + e->next = r->attrs->eattrs; + e->flags = EALF_SORTED | EALF_TEMP; + e->count = 0; + + r->attrs->eattrs = e; +} + +/** + * rte_make_tmp_attr - make temporary eattr from private route fields + * @r: route entry to be modified + * @id: attribute ID + * @type: attribute type + * @val: attribute value (u32 or adata ptr) + * + * This function is supposed to be called from make_tmp_attrs() hook for + * each temporary attribute, after temporary &ea_list was initialized by + * rte_init_tmp_attrs(). It checks whether temporary attribute is supposed to + * be defined (based on route pflags) and if so then it fills &eattr field in + * preallocated temporary &ea_list on top of route @r eattrs stack. + * + * Note that it may require free &eattr in temporary &ea_list, so it must not be + * called more times than @max argument of rte_init_tmp_attrs(). + */ +void +rte_make_tmp_attr(rte *r, uint id, uint type, uintptr_t val) +{ + if (r->pflags & EA_ID_FLAG(id)) + { + ea_list *e = r->attrs->eattrs; + eattr *a = &e->attrs[e->count++]; + a->id = id; + a->type = type; + a->flags = 0; + + if (type & EAF_EMBEDDED) + a->u.data = (u32) val; + else + a->u.ptr = (struct adata *) val; + } +} + +/** + * rte_store_tmp_attr - store temporary eattr to private route fields + * @r: route entry to be modified + * @id: attribute ID + * + * This function is supposed to be called from store_tmp_attrs() hook for + * each temporary attribute, after temporary &ea_list was initialized by + * rte_init_tmp_attrs(). It checks whether temporary attribute is defined in + * route @r eattrs stack, updates route pflags accordingly, undefines it by + * filling &eattr field in preallocated temporary &ea_list on top of the eattrs + * stack, and returns the value. Caller is supposed to store it in the + * appropriate private field. + * + * Note that it may require free &eattr in temporary &ea_list, so it must not be + * called more times than @max argument of rte_init_tmp_attrs() + */ +uintptr_t +rte_store_tmp_attr(rte *r, uint id) +{ + ea_list *e = r->attrs->eattrs; + eattr *a = ea_find(e->next, id); + + if (a) + { + e->attrs[e->count++] = (struct eattr) { .id = id, .type = EAF_TYPE_UNDEF }; + r->pflags |= EA_ID_FLAG(id); + return (a->type & EAF_EMBEDDED) ? a->u.data : (uintptr_t) a->u.ptr; + } + else + { + r->pflags &= ~EA_ID_FLAG(id); + return 0; + } +} + +/** + * rte_make_tmp_attrs - prepare route by adding all relevant temporary route attributes + * @r: route entry to be modified (may be replaced if COW) + * @lp: linpool from which to allocate attributes + * @old_attrs: temporary ref to old &rta (may be NULL) + * + * This function expands privately stored protocol-dependent route attributes + * to a uniform &eattr / &ea_list representation. It is essentially a wrapper + * around protocol make_tmp_attrs() hook, which does some additional work like + * ensuring that route @r is writable. + * + * The route @r may be read-only (with %REF_COW flag), in that case rw copy is + * obtained by rte_cow() and @r is replaced. If @rte is originally rw, it may be + * directly modified (and it is never copied). + * + * If the @old_attrs ptr is supplied, the function obtains another reference of + * old cached &rta, that is necessary in some cases (see rte_cow_rta() for + * details). It is freed by rte_store_tmp_attrs(), or manually by rta_free(). + * + * Generally, if caller ensures that @r is read-only (e.g. in route export) then + * it may ignore @old_attrs (and set it to NULL), but must handle replacement of + * @r. If caller ensures that @r is writable (e.g. in route import) then it may + * ignore replacement of @r, but it must handle @old_attrs. + */ +void +rte_make_tmp_attrs(rte **r, linpool *lp, rta **old_attrs) +{ + void (*make_tmp_attrs)(rte *r, linpool *lp); + make_tmp_attrs = (*r)->attrs->src->proto->make_tmp_attrs; + + if (!make_tmp_attrs) + return; + + /* We may need to keep ref to old attributes, will be freed in rte_store_tmp_attrs() */ + if (old_attrs) + *old_attrs = rta_is_cached((*r)->attrs) ? rta_clone((*r)->attrs) : NULL; + + *r = rte_cow_rta(*r, lp); + make_tmp_attrs(*r, lp); +} + +/** + * rte_store_tmp_attrs - store temporary route attributes back to private route fields + * @r: route entry to be modified + * @lp: linpool from which to allocate attributes + * @old_attrs: temporary ref to old &rta + * + * This function stores temporary route attributes that were expanded by + * rte_make_tmp_attrs() back to private route fields and also undefines them. + * It is essentially a wrapper around protocol store_tmp_attrs() hook, which + * does some additional work like shortcut if there is no change and cleanup + * of @old_attrs reference obtained by rte_make_tmp_attrs(). + */ +static void +rte_store_tmp_attrs(rte *r, linpool *lp, rta *old_attrs) +{ + void (*store_tmp_attrs)(rte *rt, linpool *lp); + store_tmp_attrs = r->attrs->src->proto->store_tmp_attrs; + + if (!store_tmp_attrs) + return; + + ASSERT(!rta_is_cached(r->attrs)); + + /* If there is no new ea_list, we just skip the temporary ea_list */ + ea_list *ea = r->attrs->eattrs; + if (ea && (ea->flags & EALF_TEMP)) + r->attrs->eattrs = ea->next; + else + store_tmp_attrs(r, lp); + + /* Free ref we got in rte_make_tmp_attrs(), have to do rta_lookup() first */ + r->attrs = rta_lookup(r->attrs); + rta_free(old_attrs); +} + + static int /* Actually better or at least as good as */ rte_better(rte *new, rte *old) { @@ -424,7 +594,7 @@ export_filter_(struct channel *c, rte *rt0, rte **rt_free, linpool *pool, int si goto accept; } - rte_make_tmp_attrs(&rt, pool); + rte_make_tmp_attrs(&rt, pool, NULL); v = filter && ((filter == FILTER_REJECT) || (f_run(filter, &rt, pool, @@ -1008,12 +1178,13 @@ rte_free_quick(rte *e) static int rte_same(rte *x, rte *y) { + /* rte.flags are not checked, as they are mostly internal to rtable */ return x->attrs == y->attrs && - x->flags == y->flags && x->pflags == y->pflags && x->pref == y->pref && - (!x->attrs->src->proto->rte_same || x->attrs->src->proto->rte_same(x, y)); + (!x->attrs->src->proto->rte_same || x->attrs->src->proto->rte_same(x, y)) && + rte_is_filtered(x) == rte_is_filtered(y); } static inline int rte_is_ok(rte *e) { return e && !rte_is_filtered(e); } @@ -1057,7 +1228,9 @@ rte_recalculate(struct channel *c, net *net, rte *new, struct rte_src *src) if (new && rte_same(old, new)) { - /* No changes, ignore the new route */ + /* No changes, ignore the new route and refresh the old one */ + + old->flags &= ~(REF_STALE | REF_DISCARD | REF_MODIFY); if (!rte_is_filtered(new)) { @@ -1401,26 +1574,27 @@ rte_update2(struct channel *c, const net_addr *n, rte *new, struct rte_src *src) /* new is a private copy, i could modify it */ new->flags |= REF_FILTERED; } - else + else if (filter) { - rte_make_tmp_attrs(&new, rte_update_pool); - if (filter && (filter != FILTER_REJECT)) - { - ea_list *oldea = new->attrs->eattrs; - int fr = f_run(filter, &new, rte_update_pool, 0); - if (fr > F_ACCEPT) - { - stats->imp_updates_filtered++; - rte_trace_in(D_FILTERS, p, new, "filtered out"); + rta *old_attrs; + rte_make_tmp_attrs(&new, rte_update_pool, &old_attrs); - if (! c->in_keep_filtered) - goto drop; + int fr = f_run(filter, &new, rte_update_pool, 0); + if (fr > F_ACCEPT) + { + stats->imp_updates_filtered++; + rte_trace_in(D_FILTERS, p, new, "filtered out"); - new->flags |= REF_FILTERED; - } - if (new->attrs->eattrs != oldea && src->proto->store_tmp_attrs) - src->proto->store_tmp_attrs(new); + if (! c->in_keep_filtered) + { + rta_free(old_attrs); + goto drop; } + + new->flags |= REF_FILTERED; + } + + rte_store_tmp_attrs(new, rte_update_pool, old_attrs); } if (!rta_is_cached(new->attrs)) /* Need to copy attributes */ new->attrs = rta_lookup(new->attrs); @@ -1517,7 +1691,7 @@ rt_examine(rtable *t, net_addr *a, struct proto *p, const struct filter *filter) int v = p->preexport ? p->preexport(p, &rt, rte_update_pool) : 0; if (v == RIC_PROCESS) { - rte_make_tmp_attrs(&rt, rte_update_pool); + rte_make_tmp_attrs(&rt, rte_update_pool, NULL); v = (f_run(filter, &rt, rte_update_pool, FF_SILENT) <= F_ACCEPT); } @@ -2363,7 +2537,16 @@ rte_update_in(struct channel *c, const net_addr *n, rte *new, struct rte_src *sr if (old->attrs->src == src) { if (new && rte_same(old, new)) + { + /* Refresh the old rte, continue with update to main rtable */ + if (old->flags & (REF_STALE | REF_DISCARD | REF_MODIFY)) + { + old->flags &= ~(REF_STALE | REF_DISCARD | REF_MODIFY); + return 1; + } + goto drop_update; + } /* Remove the old rte */ *pos = old->next; diff --git a/proto/babel/babel.c b/proto/babel/babel.c index d321f1d8..177ff3a3 100644 --- a/proto/babel/babel.c +++ b/proto/babel/babel.c @@ -645,7 +645,7 @@ babel_announce_rte(struct babel_proto *p, struct babel_entry *e) rte->u.babel.seqno = r->seqno; rte->u.babel.metric = r->metric; rte->u.babel.router_id = r->router_id; - rte->pflags = 0; + rte->pflags = EA_ID_FLAG(EA_BABEL_METRIC) | EA_ID_FLAG(EA_BABEL_ROUTER_ID); e->unreachable = 0; rte_update2(c, e->n.addr, rte, p->p.main_source); @@ -2077,32 +2077,6 @@ babel_kick_timer(struct babel_proto *p) } -static struct ea_list * -babel_prepare_attrs(struct linpool *pool, ea_list *next, uint metric, u64 router_id) -{ - struct ea_list *l = lp_alloc(pool, sizeof(struct ea_list) + 2*sizeof(eattr)); - struct adata *rid = lp_alloc(pool, sizeof(struct adata) + sizeof(u64)); - rid->length = sizeof(u64); - memcpy(&rid->data, &router_id, sizeof(u64)); - - l->next = next; - l->flags = EALF_SORTED; - l->count = 2; - - l->attrs[0].id = EA_BABEL_METRIC; - l->attrs[0].flags = 0; - l->attrs[0].type = EAF_TYPE_INT | EAF_TEMP; - l->attrs[0].u.data = metric; - - l->attrs[1].id = EA_BABEL_ROUTER_ID; - l->attrs[1].flags = 0; - l->attrs[1].type = EAF_TYPE_OPAQUE | EAF_TEMP; - l->attrs[1].u.ptr = rid; - - return l; -} - - static int babel_preexport(struct proto *P, struct rte **new, struct linpool *pool UNUSED) { @@ -2115,16 +2089,25 @@ babel_preexport(struct proto *P, struct rte **new, struct linpool *pool UNUSED) return 0; } -static struct ea_list * +static void babel_make_tmp_attrs(struct rte *rt, struct linpool *pool) { - return babel_prepare_attrs(pool, NULL, rt->u.babel.metric, rt->u.babel.router_id); + struct adata *id = lp_alloc_adata(pool, sizeof(u64)); + memcpy(id->data, &rt->u.babel.router_id, sizeof(u64)); + + rte_init_tmp_attrs(rt, pool, 2); + rte_make_tmp_attr(rt, EA_BABEL_METRIC, EAF_TYPE_INT, rt->u.babel.metric); + rte_make_tmp_attr(rt, EA_BABEL_ROUTER_ID, EAF_TYPE_OPAQUE, (uintptr_t) id); } static void -babel_store_tmp_attrs(struct rte *rt) +babel_store_tmp_attrs(struct rte *rt, struct linpool *pool) { - rt->u.babel.metric = ea_get_int(rt->attrs->eattrs, EA_BABEL_METRIC, 0); + rte_init_tmp_attrs(rt, pool, 2); + rt->u.babel.metric = rte_store_tmp_attr(rt, EA_BABEL_METRIC); + + /* EA_BABEL_ROUTER_ID is read-only, we do not really save the value */ + rte_store_tmp_attr(rt, EA_BABEL_ROUTER_ID); } /* diff --git a/proto/mrt/mrt.c b/proto/mrt/mrt.c index 95014958..e4f1acea 100644 --- a/proto/mrt/mrt.c +++ b/proto/mrt/mrt.c @@ -496,7 +496,7 @@ mrt_rib_table_dump(struct mrt_table_dump_state *s, net *n, int add_path) continue; } - rte_make_tmp_attrs(&rt, s->linpool); + rte_make_tmp_attrs(&rt, s->linpool, NULL); if (f_run(s->filter, &rt, s->linpool, 0) <= F_ACCEPT) mrt_rib_table_entry(s, rt); diff --git a/proto/ospf/ospf.c b/proto/ospf/ospf.c index 816f33aa..f26f0160 100644 --- a/proto/ospf/ospf.c +++ b/proto/ospf/ospf.c @@ -106,8 +106,8 @@ #include "ospf.h" static int ospf_preexport(struct proto *P, rte **new, struct linpool *pool); -static struct ea_list *ospf_make_tmp_attrs(struct rte *rt, struct linpool *pool); -static void ospf_store_tmp_attrs(struct rte *rt); +static void ospf_make_tmp_attrs(struct rte *rt, struct linpool *pool); +static void ospf_store_tmp_attrs(struct rte *rt, struct linpool *pool); static void ospf_reload_routes(struct channel *C); static int ospf_rte_better(struct rte *new, struct rte *old); static int ospf_rte_same(struct rte *new, struct rte *old); @@ -364,35 +364,6 @@ ospf_rte_same(struct rte *new, struct rte *old) new->u.ospf.router_id == old->u.ospf.router_id; } -static ea_list * -ospf_build_attrs(ea_list * next, struct linpool *pool, u32 m1, u32 m2, - u32 tag, u32 rid) -{ - struct ea_list *l = - lp_alloc(pool, sizeof(struct ea_list) + 4 * sizeof(eattr)); - - l->next = next; - l->flags = EALF_SORTED; - l->count = 4; - l->attrs[0].id = EA_OSPF_METRIC1; - l->attrs[0].flags = 0; - l->attrs[0].type = EAF_TYPE_INT | EAF_TEMP; - l->attrs[0].u.data = m1; - l->attrs[1].id = EA_OSPF_METRIC2; - l->attrs[1].flags = 0; - l->attrs[1].type = EAF_TYPE_INT | EAF_TEMP; - l->attrs[1].u.data = m2; - l->attrs[2].id = EA_OSPF_TAG; - l->attrs[2].flags = 0; - l->attrs[2].type = EAF_TYPE_INT | EAF_TEMP; - l->attrs[2].u.data = tag; - l->attrs[3].id = EA_OSPF_ROUTER_ID; - l->attrs[3].flags = 0; - l->attrs[3].type = EAF_TYPE_ROUTER_ID | EAF_TEMP; - l->attrs[3].u.data = rid; - return l; -} - void ospf_schedule_rtcalc(struct ospf_proto *p) @@ -467,20 +438,24 @@ ospf_preexport(struct proto *P, rte **new, struct linpool *pool UNUSED) return 0; } -static struct ea_list * +static void ospf_make_tmp_attrs(struct rte *rt, struct linpool *pool) { - return ospf_build_attrs(NULL, pool, rt->u.ospf.metric1, rt->u.ospf.metric2, - rt->u.ospf.tag, rt->u.ospf.router_id); + rte_init_tmp_attrs(rt, pool, 4); + rte_make_tmp_attr(rt, EA_OSPF_METRIC1, EAF_TYPE_INT, rt->u.ospf.metric1); + rte_make_tmp_attr(rt, EA_OSPF_METRIC2, EAF_TYPE_INT, rt->u.ospf.metric2); + rte_make_tmp_attr(rt, EA_OSPF_TAG, EAF_TYPE_INT, rt->u.ospf.tag); + rte_make_tmp_attr(rt, EA_OSPF_ROUTER_ID, EAF_TYPE_ROUTER_ID, rt->u.ospf.router_id); } static void -ospf_store_tmp_attrs(struct rte *rt) +ospf_store_tmp_attrs(struct rte *rt, struct linpool *pool) { - rt->u.ospf.metric1 = ea_get_int(rt->attrs->eattrs, EA_OSPF_METRIC1, LSINFINITY); - rt->u.ospf.metric2 = ea_get_int(rt->attrs->eattrs, EA_OSPF_METRIC2, 10000); - rt->u.ospf.tag = ea_get_int(rt->attrs->eattrs, EA_OSPF_TAG, 0); - rt->u.ospf.router_id = ea_get_int(rt->attrs->eattrs, EA_OSPF_ROUTER_ID, 0); + rte_init_tmp_attrs(rt, pool, 4); + rt->u.ospf.metric1 = rte_store_tmp_attr(rt, EA_OSPF_METRIC1); + rt->u.ospf.metric2 = rte_store_tmp_attr(rt, EA_OSPF_METRIC2); + rt->u.ospf.tag = rte_store_tmp_attr(rt, EA_OSPF_TAG); + rt->u.ospf.router_id = rte_store_tmp_attr(rt, EA_OSPF_ROUTER_ID); } /** diff --git a/proto/ospf/rt.c b/proto/ospf/rt.c index c580d06e..6ddd6c9f 100644 --- a/proto/ospf/rt.c +++ b/proto/ospf/rt.c @@ -402,8 +402,6 @@ add_network(struct ospf_area *oa, net_addr *net, int metric, struct top_hash_ent .type = RTS_OSPF, .options = 0, .metric1 = metric, - .metric2 = LSINFINITY, - .tag = 0, .rid = en->lsa.rt, .oa = oa, .nhs = en->nhs @@ -459,8 +457,6 @@ spfa_process_rt(struct ospf_proto *p, struct ospf_area *oa, struct top_hash_entr .type = RTS_OSPF, .options = rt->options, .metric1 = act->dist, - .metric2 = LSINFINITY, - .tag = 0, .rid = act->lsa.rt, .oa = oa, .nhs = act->nhs @@ -823,8 +819,6 @@ ospf_rt_sum(struct ospf_area *oa) .type = RTS_OSPF_IA, .options = options, .metric1 = abr->n.metric1 + metric, - .metric2 = LSINFINITY, - .tag = 0, .rid = en->lsa.rt, /* ABR ID */ .oa = oa, .nhs = abr->n.nhs @@ -1563,7 +1557,7 @@ ospf_ext_spf(struct ospf_proto *p) { nfa.type = RTS_OSPF_EXT1; nfa.metric1 = br_metric + rt.metric; - nfa.metric2 = LSINFINITY; + nfa.metric2 = 0; } /* Mark the LSA as reachable */ @@ -2033,7 +2027,14 @@ again1: e->u.ospf.metric2 = nf->old_metric2 = nf->n.metric2; e->u.ospf.tag = nf->old_tag = nf->n.tag; e->u.ospf.router_id = nf->old_rid = nf->n.rid; - e->pflags = 0; + e->pflags = EA_ID_FLAG(EA_OSPF_METRIC1) | EA_ID_FLAG(EA_OSPF_ROUTER_ID); + + if (nf->n.type == RTS_OSPF_EXT2) + e->pflags |= EA_ID_FLAG(EA_OSPF_METRIC2); + + /* Perhaps onfly if tag is non-zero? */ + if ((nf->n.type == RTS_OSPF_EXT1) || (nf->n.type == RTS_OSPF_EXT2)) + e->pflags |= EA_ID_FLAG(EA_OSPF_TAG); DBG("Mod rte type %d - %N via %I on iface %s, met %d\n", a0.source, nf->fn.addr, a0.gw, a0.iface ? a0.iface->name : "(none)", nf->n.metric1); diff --git a/proto/rip/rip.c b/proto/rip/rip.c index 612b6f92..91c00588 100644 --- a/proto/rip/rip.c +++ b/proto/rip/rip.c @@ -193,8 +193,7 @@ rip_announce_rte(struct rip_proto *p, struct rip_entry *en) e->u.rip.from = a0.nh.iface; e->u.rip.metric = rt_metric; e->u.rip.tag = rt_tag; - - e->pflags = 0; + e->pflags = EA_ID_FLAG(EA_RIP_METRIC) | EA_ID_FLAG(EA_RIP_TAG); rte_update(&p->p, en->n.addr, e); } @@ -997,28 +996,6 @@ rip_trigger_update(struct rip_proto *p) * RIP protocol glue */ -static struct ea_list * -rip_prepare_attrs(struct linpool *pool, ea_list *next, u8 metric, u16 tag) -{ - struct ea_list *l = lp_alloc(pool, sizeof(struct ea_list) + 2 * sizeof(eattr)); - - l->next = next; - l->flags = EALF_SORTED; - l->count = 2; - - l->attrs[0].id = EA_RIP_METRIC; - l->attrs[0].flags = 0; - l->attrs[0].type = EAF_TYPE_INT | EAF_TEMP; - l->attrs[0].u.data = metric; - - l->attrs[1].id = EA_RIP_TAG; - l->attrs[1].flags = 0; - l->attrs[1].type = EAF_TYPE_INT | EAF_TEMP; - l->attrs[1].u.data = tag; - - return l; -} - static void rip_reload_routes(struct channel *C) { @@ -1032,17 +1009,20 @@ rip_reload_routes(struct channel *C) rip_kick_timer(p); } -static struct ea_list * +static void rip_make_tmp_attrs(struct rte *rt, struct linpool *pool) { - return rip_prepare_attrs(pool, NULL, rt->u.rip.metric, rt->u.rip.tag); + rte_init_tmp_attrs(rt, pool, 2); + rte_make_tmp_attr(rt, EA_RIP_METRIC, EAF_TYPE_INT, rt->u.rip.metric); + rte_make_tmp_attr(rt, EA_RIP_TAG, EAF_TYPE_INT, rt->u.rip.tag); } static void -rip_store_tmp_attrs(struct rte *rt) +rip_store_tmp_attrs(struct rte *rt, struct linpool *pool) { - rt->u.rip.metric = ea_get_int(rt->attrs->eattrs, EA_RIP_METRIC, 1); - rt->u.rip.tag = ea_get_int(rt->attrs->eattrs, EA_RIP_TAG, 0); + rte_init_tmp_attrs(rt, pool, 2); + rt->u.rip.metric = rte_store_tmp_attr(rt, EA_RIP_METRIC); + rt->u.rip.tag = rte_store_tmp_attr(rt, EA_RIP_TAG); } static int diff --git a/sysdep/config.h b/sysdep/config.h index 96db1e7d..ab5f12a6 100644 --- a/sysdep/config.h +++ b/sysdep/config.h @@ -13,7 +13,7 @@ #ifdef GIT_LABEL #define BIRD_VERSION XSTR1(GIT_LABEL) #else -#define BIRD_VERSION "2.0.3" +#define BIRD_VERSION "2.0.4" #endif /* Include parameters determined by configure script */ diff --git a/sysdep/unix/krt.c b/sysdep/unix/krt.c index 24a4168d..2cec2cae 100644 --- a/sysdep/unix/krt.c +++ b/sysdep/unix/krt.c @@ -301,7 +301,7 @@ krt_learn_announce_update(struct krt_proto *p, rte *e) net *n = e->net; rta *aa = rta_clone(e->attrs); rte *ee = rte_get_temp(aa); - ee->pflags = 0; + ee->pflags = EA_ID_FLAG(EA_KRT_SOURCE) | EA_ID_FLAG(EA_KRT_METRIC); ee->u.krt = e->u.krt; rte_update(&p->p, n->n.addr, ee); } @@ -577,7 +577,7 @@ krt_export_net(struct krt_proto *p, net *net, rte **rt_free) if (filter == FILTER_REJECT) return NULL; - rte_make_tmp_attrs(&rt, krt_filter_lp); + rte_make_tmp_attrs(&rt, krt_filter_lp, NULL); /* We could run krt_preexport() here, but it is already handled by KRF_INSTALLED */ @@ -910,33 +910,20 @@ krt_scan_timer_kick(struct krt_proto *p) * Updates */ -static struct ea_list * -krt_make_tmp_attrs(rte *rt, struct linpool *pool) +static void +krt_make_tmp_attrs(struct rte *rt, struct linpool *pool) { - struct ea_list *l = lp_alloc(pool, sizeof(struct ea_list) + 2 * sizeof(eattr)); - - l->next = NULL; - l->flags = EALF_SORTED; - l->count = 2; - - l->attrs[0].id = EA_KRT_SOURCE; - l->attrs[0].flags = 0; - l->attrs[0].type = EAF_TYPE_INT | EAF_TEMP; - l->attrs[0].u.data = rt->u.krt.proto; - - l->attrs[1].id = EA_KRT_METRIC; - l->attrs[1].flags = 0; - l->attrs[1].type = EAF_TYPE_INT | EAF_TEMP; - l->attrs[1].u.data = rt->u.krt.metric; - - return l; + rte_init_tmp_attrs(rt, pool, 2); + rte_make_tmp_attr(rt, EA_KRT_SOURCE, EAF_TYPE_INT, rt->u.krt.proto); + rte_make_tmp_attr(rt, EA_KRT_METRIC, EAF_TYPE_INT, rt->u.krt.metric); } static void -krt_store_tmp_attrs(rte *rt) +krt_store_tmp_attrs(struct rte *rt, struct linpool *pool) { - /* EA_KRT_SOURCE is read-only */ - rt->u.krt.metric = ea_get_int(rt->attrs->eattrs, EA_KRT_METRIC, 0); + rte_init_tmp_attrs(rt, pool, 2); + rt->u.krt.proto = rte_store_tmp_attr(rt, EA_KRT_SOURCE); + rt->u.krt.metric = rte_store_tmp_attr(rt, EA_KRT_METRIC); } static int |