mirror of
				https://gitlab.labs.nic.cz/labs/bird.git
				synced 2024-05-11 16:54:54 +00:00 
			
		
		
		
	Merge branch 'master' into HEAD
This commit is contained in:
		
							
								
								
									
										44
									
								
								Makefile.in
									
									
									
									
									
								
							
							
						
						
									
										44
									
								
								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)
 | 
			
		||||
@@ -103,35 +104,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
 | 
			
		||||
 | 
			
		||||
$(objdir)/.dir-stamp:
 | 
			
		||||
# ## 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: Makefile
 | 
			
		||||
	$(E)echo MKDIR -p $(addprefix $(objdir)/,$(dirs) doc)
 | 
			
		||||
	$(Q)mkdir -p $(addprefix $(objdir)/,$(dirs) doc)
 | 
			
		||||
	$(Q)touch $@
 | 
			
		||||
@@ -150,7 +166,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)
 | 
			
		||||
 | 
			
		||||
@@ -165,16 +181,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]`
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -3,8 +3,6 @@ obj := $(src-o-files)
 | 
			
		||||
 | 
			
		||||
$(all-client)
 | 
			
		||||
 | 
			
		||||
$(o)commands.o: $(objdir)/conf/commands.h
 | 
			
		||||
 | 
			
		||||
$(exedir)/birdc: $(o)birdc.o
 | 
			
		||||
$(exedir)/birdc: LIBS += $(CLIENT_LIBS)
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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)
 | 
			
		||||
 
 | 
			
		||||
@@ -1045,7 +1045,7 @@ cmd:
 | 
			
		||||
   }
 | 
			
		||||
 | UNSET '(' rtadot dynamic_attr ')' ';' {
 | 
			
		||||
     $$ = f_new_inst_da(FI_EA_SET, $4);
 | 
			
		||||
     $$->aux = EAF_TYPE_UNDEF | EAF_TEMP;
 | 
			
		||||
     $$->aux = EAF_TYPE_UNDEF;
 | 
			
		||||
     $$->a1.p = NULL;
 | 
			
		||||
   }
 | 
			
		||||
 | break_command print_list ';' { $$ = f_new_inst(FI_PRINT_AND_DIE); $$->a1.p = $2; $$->a2.i = $1; }
 | 
			
		||||
 
 | 
			
		||||
@@ -196,8 +196,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,
 | 
			
		||||
@@ -213,8 +213,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);
 | 
			
		||||
@@ -299,18 +299,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;
 | 
			
		||||
 
 | 
			
		||||
@@ -315,6 +315,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);
 | 
			
		||||
@@ -492,6 +496,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)
 | 
			
		||||
@@ -520,7 +525,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 */
 | 
			
		||||
@@ -550,6 +554,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);
 | 
			
		||||
@@ -582,6 +587,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 *
 | 
			
		||||
 
 | 
			
		||||
@@ -571,8 +571,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)
 | 
			
		||||
@@ -596,10 +596,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;
 | 
			
		||||
 | 
			
		||||
@@ -979,8 +975,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");
 | 
			
		||||
 
 | 
			
		||||
@@ -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))
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										209
									
								
								nest/rt-table.c
									
									
									
									
									
								
							
							
						
						
									
										209
									
								
								nest/rt-table.c
									
									
									
									
									
								
							@@ -325,6 +325,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)
 | 
			
		||||
{
 | 
			
		||||
@@ -423,7 +593,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(&(c->out_filter), &rt, pool,
 | 
			
		||||
@@ -1415,26 +1585,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))
 | 
			
		||||
	  rta *old_attrs;
 | 
			
		||||
	  rte_make_tmp_attrs(&new, rte_update_pool, &old_attrs);
 | 
			
		||||
 | 
			
		||||
	  int fr = f_run(&(c->in_filter), &new, rte_update_pool, 0);
 | 
			
		||||
	  if (fr > F_ACCEPT)
 | 
			
		||||
	  {
 | 
			
		||||
	    stats->imp_updates_filtered++;
 | 
			
		||||
	    rte_trace_in(D_FILTERS, p, new, "filtered out");
 | 
			
		||||
 | 
			
		||||
	    if (! c->in_keep_filtered)
 | 
			
		||||
	    {
 | 
			
		||||
	      ea_list *oldea = new->attrs->eattrs;
 | 
			
		||||
	      int fr = f_run(&(c->in_filter), &new, rte_update_pool, 0);
 | 
			
		||||
	      if (fr > F_ACCEPT)
 | 
			
		||||
		{
 | 
			
		||||
		  stats->imp_updates_filtered++;
 | 
			
		||||
		  rte_trace_in(D_FILTERS, p, new, "filtered out");
 | 
			
		||||
 | 
			
		||||
		  if (! c->in_keep_filtered)
 | 
			
		||||
		    goto drop;
 | 
			
		||||
 | 
			
		||||
		  new->flags |= REF_FILTERED;
 | 
			
		||||
		}
 | 
			
		||||
	      if (new->attrs->eattrs != oldea && src->proto->store_tmp_attrs)
 | 
			
		||||
		src->proto->store_tmp_attrs(new);
 | 
			
		||||
	      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);
 | 
			
		||||
@@ -1531,7 +1702,7 @@ rt_examine(rtable *t, net_addr *a, struct proto *p, struct filter_slot *filter_s
 | 
			
		||||
  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_slot, &rt, rte_update_pool, FF_SILENT | FF_TEMP) <= F_ACCEPT);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 
 | 
			
		||||
@@ -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);
 | 
			
		||||
 | 
			
		||||
    struct filter_slot fs = { .filter = s->filter };
 | 
			
		||||
    if (f_run(&(fs), &rt, s->linpool, FF_TEMP) <= F_ACCEPT)
 | 
			
		||||
 
 | 
			
		||||
@@ -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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 
 | 
			
		||||
@@ -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);
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user