summaryrefslogtreecommitdiff
path: root/nest
diff options
context:
space:
mode:
Diffstat (limited to 'nest')
-rw-r--r--nest/config.Y3
-rw-r--r--nest/iface.c19
-rw-r--r--nest/iface.h2
-rw-r--r--nest/proto.c6
-rw-r--r--nest/protocol.h2
5 files changed, 25 insertions, 7 deletions
diff --git a/nest/config.Y b/nest/config.Y
index 878224fe..025e8969 100644
--- a/nest/config.Y
+++ b/nest/config.Y
@@ -55,7 +55,7 @@ get_passwords(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(RECEIVE, LIMIT, ACTION, WARN, BLOCK, RESTART, DISABLE, KEEP, FILTERED)
CF_KEYWORDS(PASSWORD, FROM, PASSIVE, TO, ID, EVENTS, PACKETS, PROTOCOLS, INTERFACES)
CF_KEYWORDS(ALGORITHM, KEYED, HMAC, MD5, SHA1, SHA256, SHA384, SHA512)
@@ -227,6 +227,7 @@ proto_item:
| IMPORT LIMIT limit_spec { this_proto->in_limit = $3; }
| EXPORT LIMIT limit_spec { this_proto->out_limit = $3; }
| IMPORT KEEP FILTERED bool { this_proto->in_keep_filtered = $4; }
+ | VRF TEXT { this_proto->vrf = if_get_by_name($2); }
| TABLE rtable { this_proto->table = $2; }
| ROUTER ID idval { this_proto->router_id = $3; }
| DESCRIPTION text { this_proto->dsc = $2; }
diff --git a/nest/iface.c b/nest/iface.c
index ff362938..3dd45065 100644
--- a/nest/iface.c
+++ b/nest/iface.c
@@ -116,7 +116,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)
@@ -133,12 +133,14 @@ 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)
+ if (p->ifa_notify && (!p->vrf || p->vrf == a->iface->master))
{
if (p->debug & D_IFACES)
log(L_TRACE "%s <%s address %I/%d on interface %s %s",
@@ -175,7 +177,7 @@ 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)
+ if (p->if_notify && (!p->vrf || p->vrf == i->master))
{
if (p->debug & D_IFACES)
log(L_TRACE "%s < interface %s %s", p->name, i->name,
@@ -238,7 +240,8 @@ if_recalc_flags(struct iface *i, unsigned flags)
{
if ((flags & (IF_SHUTDOWN | IF_TMP_DOWN)) ||
!(flags & IF_ADMIN_UP) ||
- !i->addr)
+ !i->addr ||
+ (i->master_index && !i->master))
flags &= ~IF_UP;
else
flags |= IF_UP;
@@ -771,7 +774,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 56710e4a..b8e69838 100644
--- a/nest/iface.h
+++ b/nest/iface.h
@@ -34,8 +34,10 @@ struct iface {
unsigned flags;
unsigned mtu;
unsigned index; /* OS-dependent interface index */
+ unsigned master_index; /* Interface index of master iface */
list addrs; /* Addresses assigned to this interface */
struct ifa *addr; /* Primary address */
+ struct iface *master; /* Master iface (e.g. for VRF) */
list neighbors; /* All neighbors on this interface */
};
diff --git a/nest/proto.c b/nest/proto.c
index 1091b321..64422ee3 100644
--- a/nest/proto.c
+++ b/nest/proto.c
@@ -386,6 +386,7 @@ proto_init(struct proto_config *c)
q->core_state = FS_HUNGRY;
q->export_state = ES_DOWN;
q->last_state_change = now;
+ q->vrf = c->vrf;
add_tail(&initial_proto_list, &q->n);
@@ -409,6 +410,7 @@ 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->disabled != p->disabled) ||
+ (nc->vrf != oc->vrf) ||
(nc->table->table != oc->table->table))
return 0;
@@ -1474,7 +1476,9 @@ proto_show_limit(struct proto_limit *l, const char *dsc)
void
proto_show_basic_info(struct proto *p)
{
- // cli_msg(-1006, " Table: %s", p->table->name);
+ if (p->vrf)
+ cli_msg(-1006, " VRF: %s", p->vrf->name);
+
cli_msg(-1006, " Preference: %d", p->preference);
cli_msg(-1006, " Input filter: %s", filter_name(p->cf->in_filter));
cli_msg(-1006, " Output filter: %s", filter_name(p->cf->out_filter));
diff --git a/nest/protocol.h b/nest/protocol.h
index ec787355..3c30a581 100644
--- a/nest/protocol.h
+++ b/nest/protocol.h
@@ -94,6 +94,7 @@ struct proto_config {
unsigned preference, disabled; /* Generic parameters */
int in_keep_filtered; /* Routes rejected in import filter are kept */
u32 router_id; /* Protocol specific router ID */
+ struct iface *vrf; /* Related VRF instance, NULL if global */
struct rtable_config *table; /* Table we're attached to */
struct filter *in_filter, *out_filter; /* Attached filters */
struct proto_limit *rx_limit; /* Limit for receiving routes from protocol
@@ -213,6 +214,7 @@ struct proto {
void (*rte_insert)(struct network *, struct rte *);
void (*rte_remove)(struct network *, struct rte *);
+ struct iface *vrf; /* Related VRF instance, NULL if global */
struct rtable *table; /* Our primary routing table */
struct rte_src *main_source; /* Primary route source */
struct announce_hook *main_ahook; /* Primary announcement hook */