summaryrefslogtreecommitdiff
path: root/proto/pipe
diff options
context:
space:
mode:
Diffstat (limited to 'proto/pipe')
-rw-r--r--proto/pipe/config.Y11
-rw-r--r--proto/pipe/pipe.c40
-rw-r--r--proto/pipe/pipe.h5
3 files changed, 46 insertions, 10 deletions
diff --git a/proto/pipe/config.Y b/proto/pipe/config.Y
index 52f70dce..4e6c80cd 100644
--- a/proto/pipe/config.Y
+++ b/proto/pipe/config.Y
@@ -10,9 +10,13 @@ CF_HDR
#include "proto/pipe/pipe.h"
+CF_DEFINES
+
+#define PIPE_CFG ((struct pipe_config *) this_proto)
+
CF_DECLS
-CF_KEYWORDS(PIPE, PEER, TABLE)
+CF_KEYWORDS(PIPE, PEER, TABLE, MODE, OPAQUE, TRANSPARENT)
CF_GRAMMAR
@@ -21,6 +25,7 @@ CF_ADDTO(proto, pipe_proto '}')
pipe_proto_start: proto_start PIPE {
this_proto = proto_config_new(&proto_pipe, sizeof(struct pipe_config));
this_proto->preference = DEF_PREF_PIPE;
+ PIPE_CFG->mode = PIPE_OPAQUE;
}
;
@@ -30,8 +35,10 @@ pipe_proto:
| pipe_proto PEER TABLE SYM ';' {
if ($4->class != SYM_TABLE)
cf_error("Routing table name expected");
- ((struct pipe_config *) this_proto)->peer = $4->def;
+ PIPE_CFG->peer = $4->def;
}
+ | pipe_proto MODE OPAQUE ';' { PIPE_CFG->mode = PIPE_OPAQUE; }
+ | pipe_proto MODE TRANSPARENT ';' { PIPE_CFG->mode = PIPE_TRANSPARENT; }
;
CF_CODE
diff --git a/proto/pipe/pipe.c b/proto/pipe/pipe.c
index d1d6bba9..8ff430a9 100644
--- a/proto/pipe/pipe.c
+++ b/proto/pipe/pipe.c
@@ -31,12 +31,16 @@
#include "pipe.h"
static void
-pipe_send(struct pipe_proto *p, rtable *dest, net *n, rte *new, rte *old UNUSED, ea_list *attrs)
+pipe_send(struct pipe_proto *p, rtable *dest, net *n, rte *new, rte *old, ea_list *attrs)
{
+ struct proto *src;
net *nn;
rte *e;
rta a;
+ if (!new && !old)
+ return;
+
if (dest->pipe_busy)
{
log(L_ERR "Pipe loop detected when sending %I/%d to table %s",
@@ -47,17 +51,34 @@ pipe_send(struct pipe_proto *p, rtable *dest, net *n, rte *new, rte *old UNUSED,
if (new)
{
memcpy(&a, new->attrs, sizeof(rta));
- a.proto = &p->p;
- a.source = RTS_PIPE;
+
+ if (p->mode == PIPE_OPAQUE)
+ {
+ a.proto = &p->p;
+ a.source = RTS_PIPE;
+ }
+
a.aflags = 0;
a.eattrs = attrs;
e = rte_get_temp(&a);
e->net = nn;
+
+ if (p->mode == PIPE_TRANSPARENT)
+ {
+ /* Copy protocol specific embedded attributes. */
+ memcpy(&(e->u), &(new->u), sizeof(e->u));
+ }
+
+ src = new->attrs->proto;
}
else
- e = NULL;
+ {
+ e = NULL;
+ src = old->attrs->proto;
+ }
+
dest->pipe_busy = 1;
- rte_update(dest, nn, &p->p, e);
+ rte_update(dest, nn, &p->p, (p->mode == PIPE_OPAQUE) ? &p->p : src, e);
dest->pipe_busy = 0;
}
@@ -82,7 +103,7 @@ pipe_rt_notify_sec(struct proto *P, net *net, rte *new, rte *old, ea_list *attrs
static int
pipe_import_control(struct proto *P, rte **ee, ea_list **ea UNUSED, struct linpool *p UNUSED)
{
- struct proto *pp = (*ee)->attrs->proto;
+ struct proto *pp = (*ee)->sender;
if (pp == P || pp == &((struct pipe_proto *) P)->phantom->p)
return -1; /* Avoid local loops automatically */
@@ -106,6 +127,7 @@ pipe_start(struct proto *P)
memcpy(ph, p, sizeof(struct pipe_proto));
p->phantom = ph;
ph->phantom = p;
+ ph->p.accept_ra_types = (p->mode == PIPE_OPAQUE) ? RA_OPTIMAL : RA_ANY;
ph->p.rt_notify = pipe_rt_notify_sec;
ph->p.proto_state = PS_UP;
ph->p.core_state = ph->p.core_goal = FS_HAPPY;
@@ -141,6 +163,8 @@ pipe_init(struct proto_config *C)
struct pipe_proto *p = (struct pipe_proto *) P;
p->peer = c->peer->table;
+ p->mode = c->mode;
+ P->accept_ra_types = (p->mode == PIPE_OPAQUE) ? RA_OPTIMAL : RA_ANY;
P->rt_notify = pipe_rt_notify_pri;
P->import_control = pipe_import_control;
return P;
@@ -162,7 +186,7 @@ pipe_get_status(struct proto *P, byte *buf)
{
struct pipe_proto *p = (struct pipe_proto *) P;
- bsprintf(buf, "-> %s", p->peer->name);
+ bsprintf(buf, "%c> %s", (p->mode == PIPE_OPAQUE) ? '-' : '=', p->peer->name);
}
static int
@@ -171,7 +195,7 @@ pipe_reconfigure(struct proto *p, struct proto_config *new)
struct pipe_config *o = (struct pipe_config *) p->cf;
struct pipe_config *n = (struct pipe_config *) new;
- return o->peer == n->peer;
+ return (o->peer == n->peer) && (o->mode == n->mode);
}
struct protocol proto_pipe = {
diff --git a/proto/pipe/pipe.h b/proto/pipe/pipe.h
index 7e9cf8ae..368ba41b 100644
--- a/proto/pipe/pipe.h
+++ b/proto/pipe/pipe.h
@@ -9,14 +9,19 @@
#ifndef _BIRD_PIPE_H_
#define _BIRD_PIPE_H_
+#define PIPE_OPAQUE 0
+#define PIPE_TRANSPARENT 1
+
struct pipe_config {
struct proto_config c;
struct rtable_config *peer; /* Table we're connected to */
+ int mode; /* PIPE_OPAQUE or PIPE_TRANSPARENT */
};
struct pipe_proto {
struct proto p;
struct rtable *peer;
+ int mode; /* PIPE_OPAQUE or PIPE_TRANSPARENT */
struct pipe_proto *phantom;
};