summaryrefslogtreecommitdiff
path: root/nest
diff options
context:
space:
mode:
authorOndrej Zajicek (work) <santiago@crfreenet.org>2017-12-07 18:35:46 +0100
committerOndrej Zajicek (work) <santiago@crfreenet.org>2017-12-07 18:35:46 +0100
commit46434a3cad99260b5a659e5df874eab4615bcb36 (patch)
treee5f4842fbdcc2ee0c66d6fdb437cb401a7234fb1 /nest
parent4ff15a75c56531fa2d3858d8250dcef1af4e75b6 (diff)
parent7b2c5f3d2826e3175bf31b1c36056c9efc587a2b (diff)
Merge commit '7b2c5f3d2826e3175bf31b1c36056c9efc587a2b' into int-new
Diffstat (limited to 'nest')
-rw-r--r--nest/config.Y3
-rw-r--r--nest/iface.c24
-rw-r--r--nest/iface.h2
-rw-r--r--nest/locks.c1
-rw-r--r--nest/locks.h1
-rw-r--r--nest/neighbor.c8
-rw-r--r--nest/proto.c7
-rw-r--r--nest/protocol.h2
-rw-r--r--nest/rt-fib.c18
9 files changed, 56 insertions, 10 deletions
diff --git a/nest/config.Y b/nest/config.Y
index ef29fb96..ad45a39d 100644
--- a/nest/config.Y
+++ b/nest/config.Y
@@ -65,7 +65,7 @@ proto_postconfig(void)
CF_DECLS
CF_KEYWORDS(ROUTER, ID, PROTOCOL, TEMPLATE, PREFERENCE, DISABLED, DEBUG, ALL, OFF, DIRECT)
-CF_KEYWORDS(INTERFACE, IMPORT, EXPORT, FILTER, NONE, TABLE, STATES, ROUTES, FILTERS)
+CF_KEYWORDS(INTERFACE, IMPORT, EXPORT, FILTER, NONE, VRF, TABLE, STATES, ROUTES, FILTERS)
CF_KEYWORDS(IPV4, IPV6, VPN4, VPN6, ROA4, ROA6)
CF_KEYWORDS(RECEIVE, LIMIT, ACTION, WARN, BLOCK, RESTART, DISABLE, KEEP, FILTERED)
CF_KEYWORDS(PASSWORD, FROM, PASSIVE, TO, ID, EVENTS, PACKETS, PROTOCOLS, INTERFACES)
@@ -225,6 +225,7 @@ proto_item:
| MRTDUMP mrtdump_mask { this_proto->mrtdump = $2; }
| ROUTER ID idval { this_proto->router_id = $3; }
| DESCRIPTION text { this_proto->dsc = $2; }
+ | VRF text { this_proto->vrf = if_get_by_name($2); }
;
diff --git a/nest/iface.c b/nest/iface.c
index dbc4debe..5e0a2450 100644
--- a/nest/iface.c
+++ b/nest/iface.c
@@ -120,7 +120,7 @@ if_what_changed(struct iface *i, struct iface *j)
unsigned c;
if (((i->flags ^ j->flags) & ~(IF_UP | IF_SHUTDOWN | IF_UPDATED | IF_ADMIN_UP | IF_LINK_UP | IF_TMP_DOWN | IF_JUST_CREATED))
- || i->index != j->index)
+ || (i->index != j->index) || (i->master != j->master))
return IF_CHANGE_TOO_MUCH;
c = 0;
if ((i->flags ^ j->flags) & IF_UP)
@@ -137,12 +137,16 @@ if_copy(struct iface *to, struct iface *from)
{
to->flags = from->flags | (to->flags & IF_TMP_DOWN);
to->mtu = from->mtu;
+ to->master_index = from->master_index;
+ to->master = from->master;
}
static inline void
ifa_send_notify(struct proto *p, unsigned c, struct ifa *a)
{
- if (p->ifa_notify && (p->proto_state != PS_DOWN))
+ if (p->ifa_notify &&
+ (p->proto_state != PS_DOWN) &&
+ (!p->vrf || p->vrf == a->iface->master))
{
if (p->debug & D_IFACES)
log(L_TRACE "%s < address %N on interface %s %s",
@@ -178,7 +182,9 @@ ifa_notify_change(unsigned c, struct ifa *a)
static inline void
if_send_notify(struct proto *p, unsigned c, struct iface *i)
{
- if (p->if_notify && (p->proto_state != PS_DOWN))
+ if (p->if_notify &&
+ (p->proto_state != PS_DOWN) &&
+ (!p->vrf || p->vrf == i->master))
{
if (p->debug & D_IFACES)
log(L_TRACE "%s < interface %s %s", p->name, i->name,
@@ -234,7 +240,9 @@ if_notify_change(unsigned c, struct iface *i)
static uint
if_recalc_flags(struct iface *i UNUSED, uint flags)
{
- if ((flags & IF_ADMIN_UP) && !(flags & (IF_SHUTDOWN | IF_TMP_DOWN)))
+ if ((flags & IF_ADMIN_UP) &&
+ !(flags & (IF_SHUTDOWN | IF_TMP_DOWN)) &&
+ !(i->master_index && !i->master))
flags |= IF_UP;
else
flags &= ~IF_UP;
@@ -835,7 +843,13 @@ if_show(void)
if (i->flags & IF_SHUTDOWN)
continue;
- cli_msg(-1001, "%s %s (index=%d)", i->name, (i->flags & IF_UP) ? "Up" : "Down", i->index);
+ char mbuf[16 + sizeof(i->name)] = {};
+ if (i->master)
+ bsprintf(mbuf, " master=%s", i->master->name);
+ else if (i->master_index)
+ bsprintf(mbuf, " master=#%u", i->master_index);
+
+ cli_msg(-1001, "%s %s (index=%d%s)", i->name, (i->flags & IF_UP) ? "Up" : "Down", i->index, mbuf);
if (!(i->flags & IF_MULTIACCESS))
type = "PtP";
else
diff --git a/nest/iface.h b/nest/iface.h
index 59b1253c..ab3f8f35 100644
--- a/nest/iface.h
+++ b/nest/iface.h
@@ -34,6 +34,8 @@ struct iface {
unsigned flags;
unsigned mtu;
unsigned index; /* OS-dependent interface index */
+ unsigned master_index; /* Interface index of master iface */
+ struct iface *master; /* Master iface (e.g. for VRF) */
list addrs; /* Addresses assigned to this interface */
struct ifa *addr4; /* Primary address for IPv4 */
struct ifa *addr6; /* Primary address for IPv6 */
diff --git a/nest/locks.c b/nest/locks.c
index 84b8b0ae..86c9ff14 100644
--- a/nest/locks.c
+++ b/nest/locks.c
@@ -45,6 +45,7 @@ olock_same(struct object_lock *x, struct object_lock *y)
return
x->type == y->type &&
x->iface == y->iface &&
+ x->vrf == y->vrf &&
x->port == y->port &&
x->inst == y->inst &&
ipa_equal(x->addr, y->addr);
diff --git a/nest/locks.h b/nest/locks.h
index 3d58c8ed..37026c68 100644
--- a/nest/locks.h
+++ b/nest/locks.h
@@ -30,6 +30,7 @@ struct object_lock {
uint port; /* ... port number */
uint inst; /* ... instance ID */
struct iface *iface; /* ... interface */
+ struct iface *vrf; /* ... or VRF (if iface is unknown) */
void (*hook)(struct object_lock *); /* Called when the lock succeeds */
void *data; /* User data */
/* ... internal to lock manager, don't touch ... */
diff --git a/nest/neighbor.c b/nest/neighbor.c
index 96475a50..fb05d96c 100644
--- a/nest/neighbor.c
+++ b/nest/neighbor.c
@@ -30,7 +30,8 @@
* when the protocol has explicitly requested it via the %NEF_STICKY
* flag because it wishes to be notified when the node will again become
* a neighbor. Such entries are enqueued in a special list which is walked
- * whenever an interface changes its state to up.
+ * whenever an interface changes its state to up. Neighbor entry VRF
+ * association is implied by respective protocol.
*
* When a neighbor event occurs (a neighbor gets disconnected or a sticky
* inactive neighbor becomes connected), the protocol hook neigh_notify()
@@ -153,8 +154,9 @@ neigh_find2(struct proto *p, ip_addr *a, struct iface *ifa, unsigned flags)
}
else
WALK_LIST(i, iface_list)
- if ((scope = if_connected(a, i, &addr)) >= 0)
- {
+ if ((!p->vrf || p->vrf == i->master) &&
+ ((scope = if_connected(a, i, &addr)) >= 0))
+ {
ifa = i;
break;
}
diff --git a/nest/proto.c b/nest/proto.c
index b28ac569..ecc3b0fe 100644
--- a/nest/proto.c
+++ b/nest/proto.c
@@ -13,6 +13,7 @@
#include "lib/resource.h"
#include "lib/lists.h"
#include "lib/event.h"
+#include "lib/timer.h"
#include "lib/string.h"
#include "conf/conf.h"
#include "nest/route.h"
@@ -673,6 +674,7 @@ proto_init(struct proto_config *c, node *n)
p->proto_state = PS_DOWN;
p->last_state_change = current_time();
+ p->vrf = c->vrf;
insert_node(&p->n, n);
p->event = ev_new(proto_pool);
@@ -819,7 +821,8 @@ proto_reconfigure(struct proto *p, struct proto_config *oc, struct proto_config
/* If there is a too big change in core attributes, ... */
if ((nc->protocol != oc->protocol) ||
(nc->net_type != oc->net_type) ||
- (nc->disabled != p->disabled))
+ (nc->disabled != p->disabled) ||
+ (nc->vrf != oc->vrf))
return 0;
p->name = nc->name;
@@ -1645,6 +1648,8 @@ proto_cmd_show(struct proto *p, uint verbose, int cnt)
cli_msg(-1006, " Description: %s", p->cf->dsc);
if (p->cf->router_id)
cli_msg(-1006, " Router ID: %R", p->cf->router_id);
+ if (p->vrf)
+ cli_msg(-1006, " VRF: %s", p->vrf->name);
if (p->proto->show_proto_info)
p->proto->show_proto_info(p);
diff --git a/nest/protocol.h b/nest/protocol.h
index e843b0b4..d7e84a44 100644
--- a/nest/protocol.h
+++ b/nest/protocol.h
@@ -100,6 +100,7 @@ struct proto_config {
u32 router_id; /* Protocol specific router ID */
list channels; /* List of channel configs (struct channel_config) */
+ struct iface *vrf; /* Related VRF instance, NULL if global */
/* Check proto_reconfigure() and proto_copy_config() after changing struct proto_config */
@@ -142,6 +143,7 @@ struct proto {
list channels; /* List of channels to rtables (struct channel) */
struct channel *main_channel; /* Primary channel */
struct rte_src *main_source; /* Primary route source */
+ struct iface *vrf; /* Related VRF instance, NULL if global */
char *name; /* Name of this instance (== cf->name) */
u32 debug; /* Debugging flags */
diff --git a/nest/rt-fib.c b/nest/rt-fib.c
index 11c31d0d..45f47261 100644
--- a/nest/rt-fib.c
+++ b/nest/rt-fib.c
@@ -32,6 +32,24 @@
* Basic FIB operations are performed by functions defined by this module,
* enumerating of FIB contents is accomplished by using the FIB_WALK() macro
* or FIB_ITERATE_START() if you want to do it asynchronously.
+ *
+ * For simple iteration just place the body of the loop between FIB_WALK() and
+ * FIB_WALK_END(). You can't modify the FIB during the iteration (you can modify
+ * data in the node, but not add or remove nodes).
+ *
+ * If you need more freedom, you can use the FIB_ITERATE_*() group of macros.
+ * First, you initialize an iterator with FIB_ITERATE_INIT(). Then you can put
+ * the loop body in between FIB_ITERATE_START() and FIB_ITERATE_END(). In
+ * addition, the iteration can be suspended by calling FIB_ITERATE_PUT().
+ * This'll link the iterator inside the FIB. While suspended, you may modify the
+ * FIB, exit the current function, etc. To resume the iteration, enter the loop
+ * again. You can use FIB_ITERATE_UNLINK() to unlink the iterator (while
+ * iteration is suspended) in cases like premature end of FIB iteration.
+ *
+ * Note that the iterator must not be destroyed when the iteration is suspended,
+ * the FIB would then contain a pointer to invalid memory. Therefore, after each
+ * FIB_ITERATE_INIT() or FIB_ITERATE_PUT() there must be either
+ * FIB_ITERATE_START() or FIB_ITERATE_UNLINK() before the iterator is destroyed.
*/
#undef LOCAL_DEBUG