diff --git a/doc/bird.sgml b/doc/bird.sgml
index 666d9f62..8d8ec35e 100644
--- a/doc/bird.sgml
+++ b/doc/bird.sgml
@@ -1446,10 +1446,23 @@ and vice versa, depending on what's allowed by the filters. Export filters contr
of routes from the primary table to the secondary one, import filters control the opposite
direction.
+
The Pipe protocol may work in the opaque mode or in the transparent
+mode. In the opaque mode, thee Pipe protocol retransmits optimal route
+from one table to the other table in a similar way like other
+protocols send and receive routes. Retransmitted route will have the
+source set to the Pipe protocol, which may limit access to protocol
+specific route attributes. The opaque mode is a default mode.
+
+
In transparent mode, the Pipe protocol retransmits all routes from
+one table to the other table, retaining their original source and
+attributes. If import and export filters are set to accept, then both
+tables would have the same content. The mode can be set by
+The primary use of multiple routing tables and the Pipe protocol is for policy routing,
where handling of a single packet doesn't depend only on its destination address, but also
on its source address, source interface, protocol type and other similar parameters.
-In many systems (Linux 2.2 being a good example), the kernel allows to enforce routing policies
+In many systems (Linux being a good example), the kernel allows to enforce routing policies
by defining routing rules which choose one of several routing tables to be used for a packet
according to its parameters. Setting of these rules is outside the scope of BIRD's work
(on Linux, you can use the Configuration
- peer table Define secondary routing table to connect to. The
+ peer table Defines secondary routing table to connect to. The
primary one is selected by the mode opaque|transparent Specifies the mode for the pipe to work in. Default is opaque.
Attributes
diff --git a/nest/proto-hooks.c b/nest/proto-hooks.c
index 9af6ef5f..c30b1070 100644
--- a/nest/proto-hooks.c
+++ b/nest/proto-hooks.c
@@ -179,8 +179,8 @@ void ifa_notify(struct proto *p, unsigned flags, struct ifa *a)
* rt_notify - notify instance about routing table change
* @p: protocol instance
* @net: a network entry
- * @new: new optimal route for the network
- * @old: old optimal route for the network
+ * @new: new route for the network
+ * @old: old route for the network
* @attrs: extended attributes associated with the @new entry
*
* The rt_notify() hook is called to inform the protocol instance about
@@ -189,7 +189,16 @@ void ifa_notify(struct proto *p, unsigned flags, struct ifa *a)
* extended attributes @attrs. Either @new or @old or both can be %NULL
* if the corresponding route doesn't exist.
*
- * FIXME documentation
+ * If the type of route announcement is RA_OPTIMAL, it is an
+ * announcement of optimal route change, @new stores the new optimal
+ * route and @old stores the old optimal route.
+ *
+ * If the type of route announcement is RA_ANY, it is an announcement
+ * of any route change, @new stores the new route and @old stores the
+ * old route from the same protocol.
+ *
+ * @p->accept_ra_types specifies which kind of route announcements
+ * protocol wants to receive.
*/
void rt_notify(struct proto *p, net *net, rte *new, rte *old, ea_list *attrs)
{ DUMMY; }
diff --git a/nest/route.h b/nest/route.h
index e55ae1d1..1bd23a6b 100644
--- a/nest/route.h
+++ b/nest/route.h
@@ -195,8 +195,7 @@ static inline net *net_find(rtable *tab, ip_addr addr, unsigned len) { return (n
static inline net *net_get(rtable *tab, ip_addr addr, unsigned len) { return (net *) fib_get(&tab->fib, &addr, len); }
rte *rte_find(net *net, struct proto *p);
rte *rte_get_temp(struct rta *);
-void rte_update(rtable *tab, net *net, struct proto *p, rte *new);
-void rte_update2(rtable *tab, net *net, struct proto *p, struct proto *src, rte *new);
+void rte_update(rtable *tab, net *net, struct proto *p, struct proto *src, rte *new);
void rte_discard(rtable *tab, rte *old);
void rte_dump(rte *);
void rte_free(rte *);
diff --git a/nest/rt-dev.c b/nest/rt-dev.c
index 348bcc2e..b86015df 100644
--- a/nest/rt-dev.c
+++ b/nest/rt-dev.c
@@ -44,7 +44,7 @@ dev_ifa_notify(struct proto *p, unsigned c, struct ifa *ad)
DBG("dev_if_notify: device shutdown: prefix not found\n");
return;
}
- rte_update(p->table, n, p, NULL);
+ rte_update(p->table, n, p, p, NULL);
}
else if (c & IF_CHANGE_UP)
{
@@ -66,7 +66,7 @@ dev_ifa_notify(struct proto *p, unsigned c, struct ifa *ad)
e = rte_get_temp(a);
e->net = n;
e->pflags = 0;
- rte_update(p->table, n, p, e);
+ rte_update(p->table, n, p, p, e);
}
}
diff --git a/nest/rt-table.c b/nest/rt-table.c
index 176e2dee..235e534e 100644
--- a/nest/rt-table.c
+++ b/nest/rt-table.c
@@ -241,16 +241,24 @@ do_rte_announce(struct announce_hook *a, int type, net *net, rte *new, rte *old,
* @tmpa: a list of temporary attributes belonging to the new route
*
* This function gets a routing table update and announces it
- * to all protocols connected to the same table by their announcement hooks.
+ * to all protocols that acccepts given type of route announcement
+ * and are connected to the same table by their announcement hooks.
*
- * previous optimal route for the same network FIXME
+ * Route announcement of type RA_OPTIMAL si generated when optimal
+ * route (in routing table @tab) changes. In that case @old stores the
+ * old optimal route.
*
- * For each such protocol, we first call its import_control() hook which
- * performs basic checks on the route (each protocol has a right to veto
- * or force accept of the route before any filter is asked) and adds default
- * values of attributes specific to the new protocol (metrics, tags etc.).
- * Then it consults the protocol's export filter and if it accepts the
- * route, the rt_notify() hook of the protocol gets called.
+ * Route announcement of type RA_ANY si generated when any route (in
+ * routing table @tab) changes In that case @old stores the old route
+ * from the same protocol.
+ *
+ * For each appropriate protocol, we first call its import_control()
+ * hook which performs basic checks on the route (each protocol has a
+ * right to veto or force accept of the route before any filter is
+ * asked) and adds default values of attributes specific to the new
+ * protocol (metrics, tags etc.). Then it consults the protocol's
+ * export filter and if it accepts the route, the rt_notify() hook of
+ * the protocol gets called.
*/
static void
rte_announce(rtable *tab, int type, net *net, rte *new, rte *old, ea_list *tmpa)
@@ -455,6 +463,7 @@ rte_update_unlock(void)
* @table: table to be updated
* @net: network node
* @p: protocol submitting the update
+ * @src: protocol originating the update
* @new: a &rte representing the new route or %NULL for route removal.
*
* This function is called by the routing protocols whenever they discover
@@ -465,6 +474,12 @@ rte_update_unlock(void)
* rta_clone()), call rte_get_temp() to obtain a temporary &rte, fill in all
* the appropriate data and finally submit the new &rte by calling rte_update().
*
+ * @src specifies the protocol that originally created the route and the meaning
+ * of protocol-dependent data of @new. If @new is not %NULL, @src have to be the
+ * same value as @new->attrs->proto. @p specifies the protocol that called
+ * rte_update(). In most cases it is the same protocol as @src. rte_update()
+ * stores @p in @new->sender;
+ *
* When rte_update() gets any route, it automatically validates it (checks,
* whether the network and next hop address are valid IP addresses and also
* whether a normal routing protocol doesn't try to smuggle a host or link
@@ -474,7 +489,7 @@ rte_update_unlock(void)
* stores the temporary attributes back to the &rte.
*
* Now, having a "public" version of the route, we
- * automatically find any old route defined by the protocol @p
+ * automatically find any old route defined by the protocol @src
* for network @n, replace it by the new one (or removing it if @new is %NULL),
* recalculate the optimal route for this destination and finally broadcast
* the change (if any) to all routing protocols by calling rte_announce().
@@ -483,14 +498,9 @@ rte_update_unlock(void)
* from a special linear pool @rte_update_pool and freed when rte_update()
* finishes.
*/
-void
-rte_update(rtable *table, net *net, struct proto *p, rte *new)
-{
- rte_update2(table, net, p, p, new);
-}
void
-rte_update2(rtable *table, net *net, struct proto *p, struct proto *src, rte *new)
+rte_update(rtable *table, net *net, struct proto *p, struct proto *src, rte *new)
{
ea_list *tmpa = NULL;
diff --git a/proto/bgp/packets.c b/proto/bgp/packets.c
index 27adc166..d5397f5f 100644
--- a/proto/bgp/packets.c
+++ b/proto/bgp/packets.c
@@ -705,7 +705,7 @@ bgp_do_rx_update(struct bgp_conn *conn,
DECODE_PREFIX(withdrawn, withdrawn_len);
DBG("Withdraw %I/%d\n", prefix, pxlen);
if (n = net_find(p->p.table, prefix, pxlen))
- rte_update(p->p.table, n, &p->p, NULL);
+ rte_update(p->p.table, n, &p->p, &p->p, NULL);
}
if (!attr_len && !nlri_len) /* shortcut */
@@ -724,7 +724,7 @@ bgp_do_rx_update(struct bgp_conn *conn,
n = net_get(p->p.table, prefix, pxlen);
e->net = n;
e->pflags = 0;
- rte_update(p->p.table, n, &p->p, e);
+ rte_update(p->p.table, n, &p->p, &p->p, e);
}
}
bad:
@@ -783,7 +783,7 @@ bgp_do_rx_update(struct bgp_conn *conn,
DECODE_PREFIX(x, len);
DBG("Withdraw %I/%d\n", prefix, pxlen);
if (n = net_find(p->p.table, prefix, pxlen))
- rte_update(p->p.table, n, &p->p, NULL);
+ rte_update(p->p.table, n, &p->p, &p->p, NULL);
}
}
@@ -824,7 +824,7 @@ bgp_do_rx_update(struct bgp_conn *conn,
n = net_get(p->p.table, prefix, pxlen);
e->net = n;
e->pflags = 0;
- rte_update(p->p.table, n, &p->p, e);
+ rte_update(p->p.table, n, &p->p, &p->p, e);
}
rta_free(a);
}
diff --git a/proto/ospf/rt.c b/proto/ospf/rt.c
index f906de92..79b21e6a 100644
--- a/proto/ospf/rt.c
+++ b/proto/ospf/rt.c
@@ -1003,11 +1003,11 @@ again1:
e->pref = p->preference;
DBG("Mod rte type %d - %I/%d via %I on iface %s, met %d\n",
a0.source, nf->fn.prefix, nf->fn.pxlen, a0.gw, a0.iface ? a0.iface->name : "(none)", nf->n.metric1);
- rte_update(p->table, ne, p, e);
+ rte_update(p->table, ne, p, p, e);
}
else
{
- rte_update(p->table, ne, p, NULL);
+ rte_update(p->table, ne, p, p, NULL);
FIB_ITERATE_PUT(&fit, nftmp);
fib_delete(fib, nftmp);
goto again1;
diff --git a/proto/pipe/pipe.c b/proto/pipe/pipe.c
index 74e1bb3b..8ff430a9 100644
--- a/proto/pipe/pipe.c
+++ b/proto/pipe/pipe.c
@@ -78,7 +78,7 @@ pipe_send(struct pipe_proto *p, rtable *dest, net *n, rte *new, rte *old, ea_lis
}
dest->pipe_busy = 1;
- rte_update2(dest, nn, &p->p, (p->mode == PIPE_OPAQUE) ? &p->p : src, e);
+ rte_update(dest, nn, &p->p, (p->mode == PIPE_OPAQUE) ? &p->p : src, e);
dest->pipe_busy = 0;
}
diff --git a/proto/rip/rip.c b/proto/rip/rip.c
index ab417f01..c655cc36 100644
--- a/proto/rip/rip.c
+++ b/proto/rip/rip.c
@@ -268,7 +268,7 @@ rip_rte_update_if_better(rtable *tab, net *net, struct proto *p, rte *new)
if (!old || p->rte_better(new, old) ||
(ipa_equal(old->attrs->from, new->attrs->from) &&
(old->u.rip.metric != new->u.rip.metric)) )
- rte_update(tab, net, p, new);
+ rte_update(tab, net, p, p, new);
}
/*
diff --git a/proto/static/static.c b/proto/static/static.c
index c5324796..c71d1da9 100644
--- a/proto/static/static.c
+++ b/proto/static/static.c
@@ -60,7 +60,7 @@ static_install(struct proto *p, struct static_route *r, struct iface *ifa)
e = rte_get_temp(aa);
e->net = n;
e->pflags = 0;
- rte_update(p->table, n, p, e);
+ rte_update(p->table, n, p, p, e);
r->installed = 1;
}
@@ -75,7 +75,7 @@ static_remove(struct proto *p, struct static_route *r)
DBG("Removing static route %I/%d\n", r->net, r->masklen);
n = net_find(p->table, r->net, r->masklen);
if (n)
- rte_update(p->table, n, p, NULL);
+ rte_update(p->table, n, p, p, NULL);
r->installed = 0;
}
diff --git a/sysdep/unix/krt.c b/sysdep/unix/krt.c
index 0b55b40b..488447b7 100644
--- a/sysdep/unix/krt.c
+++ b/sysdep/unix/krt.c
@@ -280,7 +280,7 @@ krt_learn_announce_update(struct krt_proto *p, rte *e)
ee->pflags = 0;
ee->pref = p->p.preference;
ee->u.krt = e->u.krt;
- rte_update(p->p.table, nn, &p->p, ee);
+ rte_update(p->p.table, nn, &p->p, &p->p, ee);
}
static void
@@ -288,7 +288,7 @@ krt_learn_announce_delete(struct krt_proto *p, net *n)
{
n = net_find(p->p.table, n->n.prefix, n->n.pxlen);
if (n)
- rte_update(p->p.table, n, &p->p, NULL);
+ rte_update(p->p.table, n, &p->p, &p->p, NULL);
}
static void