summaryrefslogtreecommitdiff
path: root/nest
diff options
context:
space:
mode:
Diffstat (limited to 'nest')
-rw-r--r--nest/a-path.c6
-rw-r--r--nest/attrs.h5
-rw-r--r--nest/config.Y2
-rw-r--r--nest/neighbor.c2
-rw-r--r--nest/proto.c32
-rw-r--r--nest/route.h4
-rw-r--r--nest/rt-attr.c3
-rw-r--r--nest/rt-dev.c3
-rw-r--r--nest/rt-table.c6
9 files changed, 47 insertions, 16 deletions
diff --git a/nest/a-path.c b/nest/a-path.c
index b1812981..dc36e653 100644
--- a/nest/a-path.c
+++ b/nest/a-path.c
@@ -244,10 +244,11 @@ as_path_get_first(struct adata *path, u32 *last_as)
}
int
-as_path_is_member(struct adata *path, u32 as)
+as_path_contains(struct adata *path, u32 as, int min)
{
u8 *p = path->data;
u8 *q = p+path->length;
+ int num = 0;
int i, n;
while (p<q)
@@ -257,7 +258,8 @@ as_path_is_member(struct adata *path, u32 as)
for(i=0; i<n; i++)
{
if (get_as(p) == as)
- return 1;
+ if (++num == min)
+ return 1;
p += BS;
}
}
diff --git a/nest/attrs.h b/nest/attrs.h
index 44a23e18..b6e067cb 100644
--- a/nest/attrs.h
+++ b/nest/attrs.h
@@ -35,7 +35,7 @@ int as_path_getlen(struct adata *path);
int as_path_getlen_int(struct adata *path, int bs);
int as_path_get_first(struct adata *path, u32 *orig_as);
int as_path_get_last(struct adata *path, u32 *last_as);
-int as_path_is_member(struct adata *path, u32 as);
+int as_path_contains(struct adata *path, u32 as, int min);
int as_path_match_set(struct adata *path, struct f_tree *set);
struct adata *as_path_filter(struct linpool *pool, struct adata *path, struct f_tree *set, u32 key, int pos);
@@ -69,6 +69,9 @@ int as_path_match(struct adata *path, struct f_path_mask *mask);
static inline int int_set_get_size(struct adata *list)
{ return list->length / 4; }
+static inline int ec_set_get_size(struct adata *list)
+{ return list->length / 8; }
+
static inline u32 *int_set_get_data(struct adata *list)
{ return (u32 *) list->data; }
diff --git a/nest/config.Y b/nest/config.Y
index a6f13808..e9b8a21b 100644
--- a/nest/config.Y
+++ b/nest/config.Y
@@ -46,7 +46,7 @@ CF_KEYWORDS(ROUTER, ID, PROTOCOL, TEMPLATE, PREFERENCE, DISABLED, DEBUG, ALL, OF
CF_KEYWORDS(INTERFACE, IMPORT, EXPORT, FILTER, NONE, TABLE, STATES, ROUTES, FILTERS)
CF_KEYWORDS(RECEIVE, LIMIT, ACTION, WARN, BLOCK, RESTART, DISABLE, KEEP, FILTERED)
CF_KEYWORDS(PASSWORD, FROM, PASSIVE, TO, ID, EVENTS, PACKETS, PROTOCOLS, INTERFACES)
-CF_KEYWORDS(PRIMARY, STATS, COUNT, FOR, COMMANDS, PREEXPORT, GENERATE, ROA, MAX, FLUSH)
+CF_KEYWORDS(PRIMARY, STATS, COUNT, FOR, COMMANDS, PREEXPORT, GENERATE, ROA, MAX, FLUSH, AS)
CF_KEYWORDS(LISTEN, BGP, V6ONLY, DUAL, ADDRESS, PORT, PASSWORDS, DESCRIPTION, SORTED)
CF_KEYWORDS(RELOAD, IN, OUT, MRTDUMP, MESSAGES, RESTRICT, MEMORY, IGP_METRIC, CLASS, DSCP)
diff --git a/nest/neighbor.c b/nest/neighbor.c
index 9dce8119..11a980b2 100644
--- a/nest/neighbor.c
+++ b/nest/neighbor.c
@@ -231,7 +231,7 @@ neigh_up(neighbor *n, struct iface *i, int scope)
static void
neigh_down(neighbor *n)
{
- DBG("Flushing neighbor %I on %s\n", n->addr, i->name);
+ DBG("Flushing neighbor %I on %s\n", n->addr, n->iface->name);
rem_node(&n->if_n);
if (! (n->flags & NEF_BIND))
n->iface = NULL;
diff --git a/nest/proto.c b/nest/proto.c
index c15247be..75ba10dd 100644
--- a/nest/proto.c
+++ b/nest/proto.c
@@ -376,6 +376,7 @@ int proto_reconfig_type; /* Hack to propagate type info to pipe reconfigure hoo
static int
proto_reconfigure(struct proto *p, struct proto_config *oc, struct proto_config *nc, int type)
{
+ struct announce_hook *ah = p->main_ahook;
/* If the protocol is DOWN, we just restart it */
if (p->proto_state == PS_DOWN)
return 0;
@@ -407,14 +408,31 @@ proto_reconfigure(struct proto *p, struct proto_config *oc, struct proto_config
/* Update filters and limits in the main announce hook
Note that this also resets limit state */
- if (p->main_ahook)
+ if (ah)
{
- p->main_ahook->in_filter = nc->in_filter;
- p->main_ahook->out_filter = nc->out_filter;
- p->main_ahook->rx_limit = nc->rx_limit;
- p->main_ahook->in_limit = nc->in_limit;
- p->main_ahook->out_limit = nc->out_limit;
- p->main_ahook->in_keep_filtered = nc->in_keep_filtered;
+ ah->in_filter = nc->in_filter;
+ ah->out_filter = nc->out_filter;
+ ah->rx_limit = nc->rx_limit;
+ ah->in_limit = nc->in_limit;
+ ah->out_limit = nc->out_limit;
+ ah->in_keep_filtered = nc->in_keep_filtered;
+
+ if (p->proto_state == PS_UP) /* Recheck export/import/receive limit */
+ {
+ struct proto_stats *stats = ah->stats;
+ struct proto_limit *l = ah->in_limit;
+ u32 all_routes = stats->imp_routes + stats->filt_routes;
+
+ if (l && (stats->imp_routes >= l->limit)) proto_notify_limit(ah, l, PLD_IN, stats->imp_routes);
+
+ l = ah->rx_limit;
+
+ if (l && ( all_routes >= l->limit)) proto_notify_limit(ah, l, PLD_RX, all_routes );
+
+ l = ah->out_limit;
+
+ if (l && ( stats->exp_routes >= l->limit)) proto_notify_limit(ah, l, PLD_OUT, stats->exp_routes);
+ }
}
/* Update routes when filters changed. If the protocol in not UP,
diff --git a/nest/route.h b/nest/route.h
index 35b5fa19..e0b88551 100644
--- a/nest/route.h
+++ b/nest/route.h
@@ -405,6 +405,10 @@ struct adata {
byte data[0];
};
+static inline int adata_same(struct adata *a, struct adata *b)
+{ return (a->length == b->length && !memcmp(a->data, b->data, a->length)); }
+
+
typedef struct ea_list {
struct ea_list *next; /* In case we have an override list */
byte flags; /* Flags: EALF_... */
diff --git a/nest/rt-attr.c b/nest/rt-attr.c
index 6aed318b..3f79ee59 100644
--- a/nest/rt-attr.c
+++ b/nest/rt-attr.c
@@ -366,8 +366,7 @@ ea_same(ea_list *x, ea_list *y)
if (a->id != b->id ||
a->flags != b->flags ||
a->type != b->type ||
- ((a->type & EAF_EMBEDDED) ? a->u.data != b->u.data :
- (a->u.ptr->length != b->u.ptr->length || memcmp(a->u.ptr->data, b->u.ptr->data, a->u.ptr->length))))
+ ((a->type & EAF_EMBEDDED) ? a->u.data != b->u.data : !adata_same(a->u.ptr, b->u.ptr)))
return 0;
}
return 1;
diff --git a/nest/rt-dev.c b/nest/rt-dev.c
index 54cb14ba..4fb5bddb 100644
--- a/nest/rt-dev.c
+++ b/nest/rt-dev.c
@@ -34,6 +34,9 @@ dev_ifa_notify(struct proto *p, unsigned c, struct ifa *ad)
/* Empty list is automagically treated as "*" */
return;
+ if (ad->flags & IA_SECONDARY)
+ return;
+
if (ad->scope <= SCOPE_LINK)
return;
diff --git a/nest/rt-table.c b/nest/rt-table.c
index 16dd9bcd..fc554081 100644
--- a/nest/rt-table.c
+++ b/nest/rt-table.c
@@ -636,6 +636,7 @@ rte_recalculate(struct announce_hook *ah, net *net, rte *new, ea_list *tmpa, str
struct proto *p = ah->proto;
struct rtable *table = ah->table;
struct proto_stats *stats = ah->stats;
+ static struct rate_limit rl_pipe;
rte *before_old = NULL;
rte *old_best = net->routes;
rte *old = NULL;
@@ -659,7 +660,7 @@ rte_recalculate(struct announce_hook *ah, net *net, rte *new, ea_list *tmpa, str
{
if (new)
{
- log(L_ERR "Pipe collision detected when sending %I/%d to table %s",
+ log_rl(&rl_pipe, L_ERR "Pipe collision detected when sending %I/%d to table %s",
net->n.prefix, net->n.pxlen, table->name);
rte_free_quick(new);
}
@@ -1271,6 +1272,7 @@ rt_init(void)
static inline int
rt_prune_step(rtable *tab, int step, int *max_feed)
{
+ static struct rate_limit rl_flush;
struct fib_iterator *fit = &tab->prune_fit;
DBG("Pruning route table %s\n", tab->name);
@@ -1305,7 +1307,7 @@ again:
}
if (step)
- log(L_WARN "Route %I/%d from %s still in %s after flush",
+ log_rl(&rl_flush, L_WARN "Route %I/%d from %s still in %s after flush",
n->n.prefix, n->n.pxlen, e->attrs->proto->name, tab->name);
rte_discard(tab, e);