summaryrefslogtreecommitdiff
path: root/proto/pipe
diff options
context:
space:
mode:
Diffstat (limited to 'proto/pipe')
-rw-r--r--proto/pipe/Makefile2
-rw-r--r--proto/pipe/config.Y6
-rw-r--r--proto/pipe/pipe.c71
-rw-r--r--proto/pipe/pipe.h5
4 files changed, 57 insertions, 27 deletions
diff --git a/proto/pipe/Makefile b/proto/pipe/Makefile
index 5093da98..0d68db4c 100644
--- a/proto/pipe/Makefile
+++ b/proto/pipe/Makefile
@@ -3,4 +3,4 @@ obj := $(src-o-files)
$(all-daemon)
$(cf-local)
-tests_objs := $(tests_objs) $(src-o-files) \ No newline at end of file
+tests_objs := $(tests_objs) $(src-o-files)
diff --git a/proto/pipe/config.Y b/proto/pipe/config.Y
index fc08445f..444de127 100644
--- a/proto/pipe/config.Y
+++ b/proto/pipe/config.Y
@@ -42,6 +42,12 @@ pipe_proto:
pipe_proto_start '{'
| pipe_proto proto_item ';'
| pipe_proto channel_item_ ';'
+ | pipe_proto IMPORT IN net_any imexport ';' {
+ if (this_channel->net_type && ($4->type != this_channel->net_type))
+ cf_error("Incompatible export prefilter type");
+ PIPE_CFG->in_subprefix = $4;
+ this_channel->in_filter = $5;
+ }
| pipe_proto PEER TABLE rtable ';' { PIPE_CFG->peer = $4; }
| pipe_proto MAX GENERATION expr ';' {
if (($4 < 1) || ($4 > 254)) cf_error("Max generation must be in range 1..254, got %u", $4);
diff --git a/proto/pipe/pipe.c b/proto/pipe/pipe.c
index 270f7b92..b2083010 100644
--- a/proto/pipe/pipe.c
+++ b/proto/pipe/pipe.c
@@ -35,7 +35,7 @@
#include "nest/bird.h"
#include "nest/iface.h"
#include "nest/protocol.h"
-#include "nest/route.h"
+#include "nest/rt.h"
#include "nest/cli.h"
#include "conf/conf.h"
#include "filter/filter.h"
@@ -43,32 +43,29 @@
#include "pipe.h"
-#ifdef CONFIG_BGP
-#include "proto/bgp/bgp.h"
-#endif
-
static void
pipe_rt_notify(struct proto *P, struct channel *src_ch, const net_addr *n, rte *new, const rte *old)
{
struct pipe_proto *p = (void *) P;
struct channel *dst = (src_ch == p->pri) ? p->sec : p->pri;
+ uint *flags = (src_ch == p->pri) ? &p->sec_flags : &p->pri_flags;
if (!new && !old)
return;
+ /* Start the route refresh if requested to */
+ if (*flags & PIPE_FL_RR_BEGIN_PENDING)
+ {
+ *flags &= ~PIPE_FL_RR_BEGIN_PENDING;
+ rt_refresh_begin(&dst->in_req);
+ }
+
if (new)
{
- rta *a = alloca(rta_size(new->attrs));
- memcpy(a, new->attrs, rta_size(new->attrs));
+ rte e0 = rte_init_from(new);
- a->cached = 0;
- a->hostentry = NULL;
-
- rte e0 = {
- .attrs = a,
- .src = new->src,
- .generation = new->generation + 1,
- };
+ e0.generation = new->generation + 1;
+ ea_unset_attr(&e0.attrs, 0, &ea_gen_hostentry);
rte_update(dst, n, &e0, new->src);
}
@@ -77,12 +74,12 @@ pipe_rt_notify(struct proto *P, struct channel *src_ch, const net_addr *n, rte *
}
static int
-pipe_preexport(struct channel *c, rte *e)
+pipe_preexport(struct channel *C, rte *e)
{
- struct pipe_proto *p = (void *) c->proto;
+ struct pipe_proto *p = (void *) C->proto;
/* Avoid direct loopbacks */
- if (e->sender == c->in_req.hook)
+ if (e->sender == C->in_req.hook)
return -1;
/* Indirection check */
@@ -90,8 +87,8 @@ pipe_preexport(struct channel *c, rte *e)
if (e->generation >= max_generation)
{
log_rl(&p->rl_gen, L_ERR "Route overpiped (%u hops of %u configured in %s) in table %s: %N %s/%u:%u",
- e->generation, max_generation, c->proto->name,
- c->table->name, e->net, e->src->owner->name, e->src->private_id, e->src->global_id);
+ e->generation, max_generation, C->proto->name,
+ C->table->name, e->net, e->src->owner->name, e->src->private_id, e->src->global_id);
return -1;
}
@@ -109,12 +106,12 @@ pipe_reload_routes(struct channel *C)
}
static void
-pipe_feed_begin(struct channel *C, int refeeding UNUSED)
+pipe_feed_begin(struct channel *C, int initial UNUSED)
{
struct pipe_proto *p = (void *) C->proto;
- struct channel *dst = (C == p->pri) ? p->sec : p->pri;
+ uint *flags = (C == p->pri) ? &p->sec_flags : &p->pri_flags;
- channel_refresh_begin(dst);
+ *flags |= PIPE_FL_RR_BEGIN_PENDING;
}
static void
@@ -122,8 +119,17 @@ pipe_feed_end(struct channel *C)
{
struct pipe_proto *p = (void *) C->proto;
struct channel *dst = (C == p->pri) ? p->sec : p->pri;
+ uint *flags = (C == p->pri) ? &p->sec_flags : &p->pri_flags;
+
+ /* If not even started, start the RR now */
+ if (*flags & PIPE_FL_RR_BEGIN_PENDING)
+ {
+ *flags &= ~PIPE_FL_RR_BEGIN_PENDING;
+ rt_refresh_begin(&dst->in_req);
+ }
- channel_refresh_end(dst);
+ /* Finish RR always */
+ rt_refresh_end(&dst->in_req);
}
static void
@@ -144,10 +150,16 @@ pipe_postconfig(struct proto_config *CF)
if (cc->table->addr_type != cf->peer->addr_type)
cf_error("Primary table and peer table must have the same type");
+ if (cc->out_subprefix && (cc->table->addr_type != cc->out_subprefix->type))
+ cf_error("Export subprefix must match table type");
+
+ if (cf->in_subprefix && (cc->table->addr_type != cf->in_subprefix->type))
+ cf_error("Import subprefix must match table type");
+
if (cc->rx_limit.action)
cf_error("Pipe protocol does not support receive limits");
- if (cc->in_keep_filtered)
+ if (cc->in_keep)
cf_error("Pipe protocol prohibits keeping filtered routes");
cc->debug = cf->c.debug;
@@ -163,6 +175,7 @@ pipe_configure_channels(struct pipe_proto *p, struct pipe_config *cf)
.channel = cc->channel,
.table = cc->table,
.out_filter = cc->out_filter,
+ .out_subprefix = cc->out_subprefix,
.in_limit = cc->in_limit,
.ra_mode = RA_ANY,
.debug = cc->debug,
@@ -174,6 +187,7 @@ pipe_configure_channels(struct pipe_proto *p, struct pipe_config *cf)
.channel = cc->channel,
.table = cf->peer,
.out_filter = cc->in_filter,
+ .out_subprefix = cf->in_subprefix,
.in_limit = cc->out_limit,
.ra_mode = RA_ANY,
.debug = cc->debug,
@@ -318,7 +332,6 @@ pipe_update_debug(struct proto *P)
struct protocol proto_pipe = {
.name = "Pipe",
.template = "pipe%d",
- .class = PROTOCOL_PIPE,
.proto_size = sizeof(struct pipe_proto),
.config_size = sizeof(struct pipe_config),
.postconfig = pipe_postconfig,
@@ -328,3 +341,9 @@ struct protocol proto_pipe = {
.get_status = pipe_get_status,
.show_proto_info = pipe_show_proto_info
};
+
+void
+pipe_build(void)
+{
+ proto_build(&proto_pipe);
+}
diff --git a/proto/pipe/pipe.h b/proto/pipe/pipe.h
index 60c857eb..501b8565 100644
--- a/proto/pipe/pipe.h
+++ b/proto/pipe/pipe.h
@@ -12,6 +12,7 @@
struct pipe_config {
struct proto_config c;
struct rtable_config *peer; /* Table we're connected to */
+ const net_addr *in_subprefix;
u8 max_generation;
};
@@ -19,7 +20,11 @@ struct pipe_proto {
struct proto p;
struct channel *pri;
struct channel *sec;
+ uint pri_flags;
+ uint sec_flags;
struct tbf rl_gen;
};
+#define PIPE_FL_RR_BEGIN_PENDING 1 /* Route refresh should start with the first route notified */
+
#endif