summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/printf.c16
-rw-r--r--lib/printf_test.c37
-rw-r--r--lib/string.h9
-rw-r--r--nest/bfd.h5
-rw-r--r--nest/config.Y5
-rw-r--r--nest/iface.c4
-rw-r--r--nest/neighbor.c11
-rw-r--r--nest/proto.c8
-rw-r--r--nest/protocol.h2
-rw-r--r--proto/bfd/bfd.c21
-rw-r--r--proto/bfd/config.Y4
-rw-r--r--proto/bfd/packets.c2
-rw-r--r--proto/bgp/bgp.c8
-rw-r--r--proto/ospf/neighbor.c7
-rw-r--r--proto/ospf/ospf.c2
-rw-r--r--proto/rip/rip.c3
-rw-r--r--proto/rpki/rpki.c6
-rw-r--r--proto/static/static.c3
-rw-r--r--sysdep/linux/netlink.c68
-rw-r--r--sysdep/unix/log.c3
20 files changed, 145 insertions, 79 deletions
diff --git a/lib/printf.c b/lib/printf.c
index c2065d9a..8f2cccb3 100644
--- a/lib/printf.c
+++ b/lib/printf.c
@@ -356,14 +356,14 @@ int bvsnprintf(char *buf, int size, const char *fmt, va_list args)
if (qualifier == 'l') {
X = va_arg(args, u64);
bsprintf(ipbuf, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
- ((X >> 56) & 0xff),
- ((X >> 48) & 0xff),
- ((X >> 40) & 0xff),
- ((X >> 32) & 0xff),
- ((X >> 24) & 0xff),
- ((X >> 16) & 0xff),
- ((X >> 8) & 0xff),
- (X & 0xff));
+ (uint) ((X >> 56) & 0xff),
+ (uint) ((X >> 48) & 0xff),
+ (uint) ((X >> 40) & 0xff),
+ (uint) ((X >> 32) & 0xff),
+ (uint) ((X >> 24) & 0xff),
+ (uint) ((X >> 16) & 0xff),
+ (uint) ((X >> 8) & 0xff),
+ (uint) (X & 0xff));
}
else
{
diff --git a/lib/printf_test.c b/lib/printf_test.c
index a2683d93..341fde9c 100644
--- a/lib/printf_test.c
+++ b/lib/printf_test.c
@@ -56,6 +56,27 @@ t_simple(void)
BSPRINTF(2, "-1", buf, "%d", -1);
BSPRINTF(11, "-2147483648", buf, "%d", -2147483648);
+ return 1;
+}
+
+static int
+t_router_id(void)
+{
+ char buf[256];
+
+ BSPRINTF(7, "1.2.3.4", buf, "%R", (u32) 0x01020304);
+ BSPRINTF(15, "240.224.208.192", buf, "%R", (u32) 0xF0E0D0C0);
+ BSPRINTF(23, "01:02:03:04:05:06:07:08", buf, "%lR", (u64) 0x0102030405060708);
+ BSPRINTF(23, "f0:e0:d0:c0:b0:a0:90:80", buf, "%lR", (u64) 0xF0E0D0C0B0A09080);
+
+ return 1;
+}
+
+static int
+t_time(void)
+{
+ char buf[256];
+
BSPRINTF(7, "123.456", buf, "%t", (btime) 123456789);
BSPRINTF(7, "123.456", buf, "%2t", (btime) 123456789);
BSPRINTF(8, " 123.456", buf, "%8t", (btime) 123456789);
@@ -68,12 +89,28 @@ t_simple(void)
return 1;
}
+static int
+t_bstrcmp(void)
+{
+ bt_assert(bstrcmp("aa", "aa") == 0);
+ bt_assert(bstrcmp("aa", "bb") == -1);
+ bt_assert(bstrcmp("bb", "aa") == 1);
+ bt_assert(bstrcmp(NULL, NULL) == 0);
+ bt_assert(bstrcmp(NULL, "bb") == -1);
+ bt_assert(bstrcmp("bb", NULL) == 1);
+
+ return 1;
+}
+
int
main(int argc, char *argv[])
{
bt_init(argc, argv);
bt_test_suite(t_simple, "printf without varargs");
+ bt_test_suite(t_router_id, "print router id");
+ bt_test_suite(t_time, "print time");
+ bt_test_suite(t_bstrcmp, "bstrcmp");
return bt_exit_value();
}
diff --git a/lib/string.h b/lib/string.h
index 6e549cb7..d6ae5ef7 100644
--- a/lib/string.h
+++ b/lib/string.h
@@ -63,6 +63,15 @@ memset32(void *D, u32 val, uint n)
dst[i] = val;
}
+static inline int
+bstrcmp(const char *s1, const char *s2)
+{
+ if (s1 && s2)
+ return strcmp(s1, s2);
+ else
+ return !s2 - !s1;
+}
+
#define ROUTER_ID_64_LENGTH 23
#endif
diff --git a/nest/bfd.h b/nest/bfd.h
index 04d6c001..36add991 100644
--- a/nest/bfd.h
+++ b/nest/bfd.h
@@ -19,6 +19,7 @@ struct bfd_request {
ip_addr addr;
ip_addr local;
struct iface *iface;
+ struct iface *vrf;
void (*hook)(struct bfd_request *);
void *data;
@@ -40,13 +41,13 @@ struct bfd_request {
#ifdef CONFIG_BFD
-struct bfd_request * bfd_request_session(pool *p, ip_addr addr, ip_addr local, struct iface *iface, void (*hook)(struct bfd_request *), void *data);
+struct bfd_request * bfd_request_session(pool *p, ip_addr addr, ip_addr local, struct iface *iface, struct iface *vrf, void (*hook)(struct bfd_request *), void *data);
static inline void cf_check_bfd(int use UNUSED) { }
#else
-static inline struct bfd_request * bfd_request_session(pool *p UNUSED, ip_addr addr UNUSED, ip_addr local UNUSED, struct iface *iface UNUSED, void (*hook)(struct bfd_request *) UNUSED, void *data UNUSED) { return NULL; }
+static inline struct bfd_request * bfd_request_session(pool *p UNUSED, ip_addr addr UNUSED, ip_addr local UNUSED, struct iface *iface UNUSED, struct iface *vrf UNUSED, void (*hook)(struct bfd_request *) UNUSED, void *data UNUSED) { return NULL; }
static inline void cf_check_bfd(int use) { if (use) cf_error("BFD not available"); }
diff --git a/nest/config.Y b/nest/config.Y
index e97b8fb3..4c4b6c33 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, VRF, TABLE, STATES, ROUTES, FILTERS)
+CF_KEYWORDS(INTERFACE, IMPORT, EXPORT, FILTER, NONE, VRF, DEFAULT, TABLE, STATES, ROUTES, FILTERS)
CF_KEYWORDS(IPV4, IPV6, VPN4, VPN6, ROA4, ROA6, FLOW4, FLOW6, SADR, MPLS)
CF_KEYWORDS(RECEIVE, LIMIT, ACTION, WARN, BLOCK, RESTART, DISABLE, KEEP, FILTERED)
CF_KEYWORDS(PASSWORD, FROM, PASSIVE, TO, ID, EVENTS, PACKETS, PROTOCOLS, INTERFACES)
@@ -211,7 +211,8 @@ 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); }
+ | VRF text { this_proto->vrf = if_get_by_name($2); this_proto->vrf_set = 1; }
+ | VRF DEFAULT { this_proto->vrf = NULL; this_proto->vrf_set = 1; }
;
diff --git a/nest/iface.c b/nest/iface.c
index c1966ac6..00dfc2ca 100644
--- a/nest/iface.c
+++ b/nest/iface.c
@@ -147,7 +147,7 @@ ifa_send_notify(struct proto *p, unsigned c, struct ifa *a)
{
if (p->ifa_notify &&
(p->proto_state != PS_DOWN) &&
- (!p->vrf || p->vrf == a->iface->master))
+ (!p->vrf_set || p->vrf == a->iface->master))
{
if (p->debug & D_IFACES)
log(L_TRACE "%s < address %N on interface %s %s",
@@ -185,7 +185,7 @@ if_send_notify(struct proto *p, unsigned c, struct iface *i)
{
if (p->if_notify &&
(p->proto_state != PS_DOWN) &&
- (!p->vrf || p->vrf == i->master))
+ (!p->vrf_set || p->vrf == i->master))
{
if (p->debug & D_IFACES)
log(L_TRACE "%s < interface %s %s", p->name, i->name,
diff --git a/nest/neighbor.c b/nest/neighbor.c
index 87253857..00a8e8a5 100644
--- a/nest/neighbor.c
+++ b/nest/neighbor.c
@@ -116,7 +116,7 @@ if_connected(ip_addr a, struct iface *i, struct ifa **ap, uint flags)
}
static inline int
-if_connected_any(ip_addr a, struct iface *vrf, struct iface **iface, struct ifa **addr, uint flags)
+if_connected_any(ip_addr a, struct iface *vrf, uint vrf_set, struct iface **iface, struct ifa **addr, uint flags)
{
struct iface *i;
struct ifa *b;
@@ -127,7 +127,7 @@ if_connected_any(ip_addr a, struct iface *vrf, struct iface **iface, struct ifa
/* Get first match, but prefer SCOPE_HOST to other matches */
WALK_LIST(i, iface_list)
- if ((!vrf || vrf == i->master) && ((s = if_connected(a, i, &b, flags)) >= 0))
+ if ((!vrf_set || vrf == i->master) && ((s = if_connected(a, i, &b, flags)) >= 0))
if ((scope < 0) || ((scope > SCOPE_HOST) && (s == SCOPE_HOST)))
{
*iface = i;
@@ -192,7 +192,7 @@ neigh_find(struct proto *p, ip_addr a, struct iface *iface, uint flags)
iface = (scope < 0) ? NULL : iface;
}
else
- scope = if_connected_any(a, p->vrf, &iface, &addr, flags);
+ scope = if_connected_any(a, p->vrf, p->vrf_set, &iface, &addr, flags);
/* scope < 0 means i don't know neighbor */
/* scope >= 0 <=> iface != NULL */
@@ -309,6 +309,7 @@ neigh_free(neighbor *n)
void
neigh_update(neighbor *n, struct iface *iface)
{
+ struct proto *p = n->proto;
struct ifa *ifa = NULL;
int scope = -1;
@@ -317,14 +318,14 @@ neigh_update(neighbor *n, struct iface *iface)
return;
/* VRF-bound neighbors ignore changes in other VRFs */
- if (n->proto->vrf && (n->proto->vrf != iface->master))
+ if (p->vrf_set && (p->vrf != iface->master))
return;
scope = if_connected(n->addr, iface, &ifa, n->flags);
/* When neighbor is going down, try to respawn it on other ifaces */
if ((scope < 0) && (n->scope >= 0) && !n->ifreq && (n->flags & NEF_STICKY))
- scope = if_connected_any(n->addr, n->proto->vrf, &iface, &ifa, n->flags);
+ scope = if_connected_any(n->addr, p->vrf, p->vrf_set, &iface, &ifa, n->flags);
/* No change or minor change - ignore or notify */
if ((scope == n->scope) && (iface == n->iface))
diff --git a/nest/proto.c b/nest/proto.c
index 9d0990de..2fb4e96f 100644
--- a/nest/proto.c
+++ b/nest/proto.c
@@ -765,6 +765,7 @@ proto_init(struct proto_config *c, node *n)
p->proto_state = PS_DOWN;
p->last_state_change = current_time();
p->vrf = c->vrf;
+ p->vrf_set = c->vrf_set;
insert_node(&p->n, n);
p->event = ev_new_init(proto_pool, proto_event, p);
@@ -932,7 +933,8 @@ proto_reconfigure(struct proto *p, struct proto_config *oc, struct proto_config
if ((nc->protocol != oc->protocol) ||
(nc->net_type != oc->net_type) ||
(nc->disabled != p->disabled) ||
- (nc->vrf != oc->vrf))
+ (nc->vrf != oc->vrf) ||
+ (nc->vrf_set != oc->vrf_set))
return 0;
p->name = nc->name;
@@ -1838,8 +1840,8 @@ proto_cmd_show(struct proto *p, uintptr_t verbose, int cnt)
cli_msg(-1006, " Message: %s", p->message);
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->vrf_set)
+ cli_msg(-1006, " VRF: %s", p->vrf ? p->vrf->name : "default");
if (p->proto->show_proto_info)
p->proto->show_proto_info(p);
diff --git a/nest/protocol.h b/nest/protocol.h
index b6f414f6..da12c771 100644
--- a/nest/protocol.h
+++ b/nest/protocol.h
@@ -120,6 +120,7 @@ struct proto_config {
int class; /* SYM_PROTO or SYM_TEMPLATE */
u8 net_type; /* Protocol network type (NET_*), 0 for undefined */
u8 disabled; /* Protocol enabled/disabled by default */
+ u8 vrf_set; /* Related VRF instance (below) is defined */
u32 debug, mrtdump; /* Debugging bitfields, both use D_* constants */
u32 router_id; /* Protocol specific router ID */
@@ -176,6 +177,7 @@ struct proto {
uint active_channels; /* Number of active channels */
byte net_type; /* Protocol network type (NET_*), 0 for undefined */
byte disabled; /* Manually disabled */
+ byte vrf_set; /* Related VRF instance (above) is defined */
byte proto_state; /* Protocol state machine (PS_*, see below) */
byte active; /* From PS_START to cleanup after PS_STOP */
byte do_start; /* Start actions are scheduled */
diff --git a/proto/bfd/bfd.c b/proto/bfd/bfd.c
index fdcd7225..93073070 100644
--- a/proto/bfd/bfd.c
+++ b/proto/bfd/bfd.c
@@ -624,6 +624,9 @@ bfd_request_notify(struct bfd_request *req, u8 state, u8 diag)
static int
bfd_add_request(struct bfd_proto *p, struct bfd_request *req)
{
+ if (p->p.vrf_set && (p->p.vrf != req->vrf))
+ return 0;
+
struct bfd_session *s = bfd_find_session_by_addr(p, req->addr);
u8 state, diag;
@@ -685,7 +688,8 @@ bfd_drop_requests(struct bfd_proto *p)
static struct resclass bfd_request_class;
struct bfd_request *
-bfd_request_session(pool *p, ip_addr addr, ip_addr local, struct iface *iface,
+bfd_request_session(pool *p, ip_addr addr, ip_addr local,
+ struct iface *iface, struct iface *vrf,
void (*hook)(struct bfd_request *), void *data)
{
struct bfd_request *req = ralloc(p, &bfd_request_class);
@@ -696,6 +700,7 @@ bfd_request_session(pool *p, ip_addr addr, ip_addr local, struct iface *iface,
req->addr = addr;
req->local = local;
req->iface = iface;
+ req->vrf = vrf;
bfd_submit_request(req);
@@ -754,7 +759,7 @@ bfd_neigh_notify(struct neighbor *nb)
if ((nb->scope > 0) && !n->req)
{
ip_addr local = ipa_nonzero(n->local) ? n->local : nb->ifa->ip;
- n->req = bfd_request_session(p->p.pool, n->addr, local, nb->iface, NULL, NULL);
+ n->req = bfd_request_session(p->p.pool, n->addr, local, nb->iface, p->p.vrf, NULL, NULL);
}
if ((nb->scope <= 0) && n->req)
@@ -771,7 +776,7 @@ bfd_start_neighbor(struct bfd_proto *p, struct bfd_neighbor *n)
if (n->multihop)
{
- n->req = bfd_request_session(p->p.pool, n->addr, n->local, NULL, NULL, NULL);
+ n->req = bfd_request_session(p->p.pool, n->addr, n->local, NULL, p->p.vrf, NULL, NULL);
return;
}
@@ -1051,15 +1056,6 @@ bfd_reconfigure(struct proto *P, struct proto_config *c)
return 1;
}
-/* Ensure one instance */
-struct bfd_config *bfd_cf;
-
-static void
-bfd_preconfig(struct protocol *P UNUSED, struct config *c UNUSED)
-{
- bfd_cf = NULL;
-}
-
static void
bfd_copy_config(struct proto_config *dest, struct proto_config *src UNUSED)
{
@@ -1123,6 +1119,5 @@ struct protocol proto_bfd = {
.start = bfd_start,
.shutdown = bfd_shutdown,
.reconfigure = bfd_reconfigure,
- .preconfig = bfd_preconfig,
.copy_config = bfd_copy_config,
};
diff --git a/proto/bfd/config.Y b/proto/bfd/config.Y
index 41228e51..ed416f25 100644
--- a/proto/bfd/config.Y
+++ b/proto/bfd/config.Y
@@ -38,10 +38,6 @@ bfd_proto_start: proto_start BFD
this_proto = proto_config_new(&proto_bfd, $1);
init_list(&BFD_CFG->patt_list);
init_list(&BFD_CFG->neigh_list);
-
- if (bfd_cf)
- cf_error("Only one BFD instance allowed");
- bfd_cf = BFD_CFG;
};
bfd_proto_item:
diff --git a/proto/bfd/packets.c b/proto/bfd/packets.c
index 6d5151ea..703c6e28 100644
--- a/proto/bfd/packets.c
+++ b/proto/bfd/packets.c
@@ -413,6 +413,7 @@ bfd_open_rx_sk(struct bfd_proto *p, int multihop, int af)
sk->type = SK_UDP;
sk->subtype = af;
sk->sport = !multihop ? BFD_CONTROL_PORT : BFD_MULTI_CTL_PORT;
+ sk->vrf = p->p.vrf;
sk->data = p;
sk->rbsize = BFD_MAX_LEN;
@@ -444,6 +445,7 @@ bfd_open_tx_sk(struct bfd_proto *p, ip_addr local, struct iface *ifa)
sk->saddr = local;
sk->dport = ifa ? BFD_CONTROL_PORT : BFD_MULTI_CTL_PORT;
sk->iface = ifa;
+ sk->vrf = p->p.vrf;
sk->data = p;
sk->tbsize = BFD_MAX_LEN;
diff --git a/proto/bgp/bgp.c b/proto/bgp/bgp.c
index b68575a5..5a403b40 100644
--- a/proto/bgp/bgp.c
+++ b/proto/bgp/bgp.c
@@ -1371,7 +1371,7 @@ bgp_update_bfd(struct bgp_proto *p, int use_bfd)
if (use_bfd && !p->bfd_req && !bgp_is_dynamic(p))
p->bfd_req = bfd_request_session(p->p.pool, p->remote_ip, p->local_ip,
p->cf->multihop ? NULL : p->neigh->iface,
- bgp_bfd_notify, p);
+ p->p.vrf, bgp_bfd_notify, p);
if (!use_bfd && p->bfd_req)
{
@@ -2011,12 +2011,10 @@ bgp_reconfigure(struct proto *P, struct proto_config *CF)
((byte *) new) + sizeof(struct proto_config),
// password item is last and must be checked separately
OFFSETOF(struct bgp_config, password) - sizeof(struct proto_config))
- && ((!old->password && !new->password)
- || (old->password && new->password && !strcmp(old->password, new->password)))
+ && !bstrcmp(old->password, new->password)
&& ((!old->remote_range && !new->remote_range)
|| (old->remote_range && new->remote_range && net_equal(old->remote_range, new->remote_range)))
- && ((!old->dynamic_name && !new->dynamic_name)
- || (old->dynamic_name && new->dynamic_name && !strcmp(old->dynamic_name, new->dynamic_name)))
+ && !bstrcmp(old->dynamic_name, new->dynamic_name)
&& (old->dynamic_name_digits == new->dynamic_name_digits);
/* FIXME: Move channel reconfiguration to generic protocol code ? */
diff --git a/proto/ospf/neighbor.c b/proto/ospf/neighbor.c
index 50ef6a49..30e80640 100644
--- a/proto/ospf/neighbor.c
+++ b/proto/ospf/neighbor.c
@@ -771,8 +771,11 @@ ospf_neigh_bfd_hook(struct bfd_request *req)
void
ospf_neigh_update_bfd(struct ospf_neighbor *n, int use_bfd)
{
+ struct ospf_proto *p = n->ifa->oa->po;
+
if (use_bfd && !n->bfd_req)
- n->bfd_req = bfd_request_session(n->pool, n->ip, n->ifa->addr->ip, n->ifa->iface,
+ n->bfd_req = bfd_request_session(n->pool, n->ip, n->ifa->addr->ip,
+ n->ifa->iface, p->p.vrf,
ospf_neigh_bfd_hook, n);
if (!use_bfd && n->bfd_req)
@@ -854,7 +857,7 @@ ospf_sh_neigh_info(struct ospf_neighbor *n)
pos = "Other";
}
- cli_msg(-1013, "%-1R\t%3u\t%s/%s\t%7t\t%-10s %-1I",
+ cli_msg(-1013, "%-12R\t%3u\t%s/%s\t%6t\t%-10s %I",
n->rid, n->priority, ospf_ns_names[n->state], pos,
tm_remains(n->inactim), ifa->ifname, n->ip);
}
diff --git a/proto/ospf/ospf.c b/proto/ospf/ospf.c
index ef627e20..63ff9e56 100644
--- a/proto/ospf/ospf.c
+++ b/proto/ospf/ospf.c
@@ -805,7 +805,7 @@ ospf_sh_neigh(struct proto *P, char *iff)
}
cli_msg(-1013, "%s:", p->p.name);
- cli_msg(-1013, "%-12s\t%3s\t%-15s\t%-5s\t%-10s %-12s", "Router ID", "Pri",
+ cli_msg(-1013, "%-12s\t%3s\t%-15s\t%-5s\t%-10s %s", "Router ID", "Pri",
" State", "DTime", "Interface", "Router IP");
WALK_LIST(ifa, p->iface_list)
if ((iff == NULL) || patmatch(iff, ifa->ifname))
diff --git a/proto/rip/rip.c b/proto/rip/rip.c
index 91c00588..4559310e 100644
--- a/proto/rip/rip.c
+++ b/proto/rip/rip.c
@@ -483,7 +483,8 @@ rip_update_bfd(struct rip_proto *p, struct rip_neighbor *n)
*/
ip_addr saddr = rip_is_v2(p) ? n->ifa->sk->saddr : n->nbr->ifa->ip;
n->bfd_req = bfd_request_session(p->p.pool, n->nbr->addr, saddr,
- n->nbr->iface, rip_bfd_notify, n);
+ n->nbr->iface, p->p.vrf,
+ rip_bfd_notify, n);
}
if (!use_bfd && n->bfd_req)
diff --git a/proto/rpki/rpki.c b/proto/rpki/rpki.c
index 36097dc5..70cd0cdd 100644
--- a/proto/rpki/rpki.c
+++ b/proto/rpki/rpki.c
@@ -687,9 +687,9 @@ rpki_reconfigure_cache(struct rpki_proto *p UNUSED, struct rpki_cache *cache, st
{
struct rpki_tr_ssh_config *ssh_old = (void *) old->tr_config.spec;
struct rpki_tr_ssh_config *ssh_new = (void *) new->tr_config.spec;
- if ((strcmp(ssh_old->bird_private_key, ssh_new->bird_private_key) != 0) ||
- (strcmp(ssh_old->cache_public_key, ssh_new->cache_public_key) != 0) ||
- (strcmp(ssh_old->user, ssh_new->user) != 0))
+ if (bstrcmp(ssh_old->bird_private_key, ssh_new->bird_private_key) ||
+ bstrcmp(ssh_old->cache_public_key, ssh_new->cache_public_key) ||
+ bstrcmp(ssh_old->user, ssh_new->user))
{
CACHE_TRACE(D_EVENTS, cache, "Settings of SSH transport configuration changed");
try_fast_reconnect = 1;
diff --git a/proto/static/static.c b/proto/static/static.c
index 2fa687eb..c899cc87 100644
--- a/proto/static/static.c
+++ b/proto/static/static.c
@@ -159,7 +159,8 @@ static_update_bfd(struct static_proto *p, struct static_route *r)
if (bfd_up && !r->bfd_req)
{
// ip_addr local = ipa_nonzero(r->local) ? r->local : nb->ifa->ip;
- r->bfd_req = bfd_request_session(p->p.pool, r->via, nb->ifa->ip, nb->iface,
+ r->bfd_req = bfd_request_session(p->p.pool, r->via, nb->ifa->ip,
+ nb->iface, p->p.vrf,
static_bfd_notify, r);
}
diff --git a/sysdep/linux/netlink.c b/sysdep/linux/netlink.c
index 95f0481e..10e9a18b 100644
--- a/sysdep/linux/netlink.c
+++ b/sysdep/linux/netlink.c
@@ -69,6 +69,7 @@
#define RTA_ENCAP 22
#endif
+#define krt_ipv4(p) ((p)->af == AF_INET)
#define krt_ecmp6(p) ((p)->af == AF_INET6)
const int rt_default_ecmp = 16;
@@ -466,10 +467,21 @@ static inline ip_addr rta_get_via(struct rtattr *a)
static u32 rta_mpls_stack[MPLS_MAX_LABEL_STACK];
static inline int rta_get_mpls(struct rtattr *a, u32 *stack)
{
+ if (!a)
+ return 0;
+
if (RTA_PAYLOAD(a) % 4)
log(L_WARN "KRT: Strange length of received MPLS stack: %u", RTA_PAYLOAD(a));
- return mpls_get(RTA_DATA(a), RTA_PAYLOAD(a) & ~0x3, stack);
+ int labels = mpls_get(RTA_DATA(a), RTA_PAYLOAD(a) & ~0x3, stack);
+
+ if (labels < 0)
+ {
+ log(L_WARN "KRT: Too long MPLS stack received, ignoring");
+ labels = 0;
+ }
+
+ return labels;
}
#endif
@@ -705,7 +717,7 @@ nl_parse_multipath(struct nl_parse_state *s, struct krt_proto *p, struct rtattr
rv->gw = IPA_NONE;
#ifdef HAVE_MPLS_KERNEL
- if (a[RTA_ENCAP_TYPE])
+ if (a[RTA_ENCAP] && a[RTA_ENCAP_TYPE])
{
if (rta_get_u16(a[RTA_ENCAP_TYPE]) != LWTUNNEL_ENCAP_MPLS) {
log(L_WARN "KRT: Unknown encapsulation method %d in multipath", rta_get_u16(a[RTA_ENCAP_TYPE]));
@@ -716,7 +728,6 @@ nl_parse_multipath(struct nl_parse_state *s, struct krt_proto *p, struct rtattr
nl_attr_len = RTA_PAYLOAD(a[RTA_ENCAP]);
nl_parse_attrs(RTA_DATA(a[RTA_ENCAP]), encap_mpls_want, enca, sizeof(enca));
rv->labels = rta_get_mpls(enca[RTA_DST], rv->label);
- break;
}
#endif
@@ -1368,27 +1379,43 @@ nl_delete_rte(struct krt_proto *p, rte *e)
return err;
}
+static inline int
+nl_replace_rte(struct krt_proto *p, rte *e)
+{
+ rta *a = e->attrs;
+ return nl_send_route(p, e, NL_OP_REPLACE, a->dest, &(a->nh));
+}
+
+
void
krt_replace_rte(struct krt_proto *p, net *n, rte *new, rte *old)
{
int err = 0;
/*
- * We could use NL_OP_REPLACE, but route replace on Linux has some problems:
+ * We use NL_OP_REPLACE for IPv4, it has an issue with not checking for
+ * matching rtm_protocol, but that is OK when dedicated priority is used.
*
- * 1) Does not check for matching rtm_protocol
- * 2) Has broken semantics for IPv6 ECMP
- * 3) Crashes some kernel version when used for IPv6 ECMP
+ * We do not use NL_OP_REPLACE for IPv6, as it has broken semantics for ECMP
+ * and with some kernel versions ECMP replace crashes kernel. Would need more
+ * testing and checks for kernel versions.
*
- * So we use NL_OP_DELETE and then NL_OP_ADD. We also do not trust the old
- * route value, so we do not try to optimize IPv6 ECMP reconfigurations.
+ * For IPv6, we use NL_OP_DELETE and then NL_OP_ADD. We also do not trust the
+ * old route value, so we do not try to optimize IPv6 ECMP reconfigurations.
*/
- if (old)
- nl_delete_rte(p, old);
+ if (krt_ipv4(p) && old && new)
+ {
+ err = nl_replace_rte(p, new);
+ }
+ else
+ {
+ if (old)
+ nl_delete_rte(p, old);
- if (new)
- err = nl_add_rte(p, new);
+ if (new)
+ err = nl_add_rte(p, new);
+ }
if (err < 0)
n->n.flags |= KRF_SYNC_ERROR;
@@ -1606,7 +1633,7 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h)
return;
}
- ra->nh = *nh;
+ nexthop_link(ra, nh);
break;
}
@@ -1666,9 +1693,8 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h)
}
#ifdef HAVE_MPLS_KERNEL
- int labels = 0;
if ((i->rtm_family == AF_MPLS) && a[RTA_NEWDST] && !ra->nh.next)
- labels = rta_get_mpls(a[RTA_NEWDST], ra->nh.label);
+ ra->nh.labels = rta_get_mpls(a[RTA_NEWDST], ra->nh.label);
if (a[RTA_ENCAP] && a[RTA_ENCAP_TYPE] && !ra->nh.next)
{
@@ -1679,7 +1705,7 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h)
struct rtattr *enca[BIRD_RTA_MAX];
nl_attr_len = RTA_PAYLOAD(a[RTA_ENCAP]);
nl_parse_attrs(RTA_DATA(a[RTA_ENCAP]), encap_mpls_want, enca, sizeof(enca));
- labels = rta_get_mpls(enca[RTA_DST], ra->nh.label);
+ ra->nh.labels = rta_get_mpls(enca[RTA_DST], ra->nh.label);
break;
}
default:
@@ -1687,14 +1713,6 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h)
break;
}
}
-
- if (labels < 0)
- {
- log(L_WARN "KRT: Too long MPLS stack received, ignoring.");
- ra->nh.labels = 0;
- }
- else
- ra->nh.labels = labels;
#endif
if (i->rtm_scope != def_scope)
diff --git a/sysdep/unix/log.c b/sysdep/unix/log.c
index 9d107709..45f442e7 100644
--- a/sysdep/unix/log.c
+++ b/sysdep/unix/log.c
@@ -387,8 +387,7 @@ log_switch(int initial, list *logs, char *new_syslog_name)
current_log_list = logs;
#ifdef HAVE_SYSLOG_H
- if (current_syslog_name && new_syslog_name &&
- !strcmp(current_syslog_name, new_syslog_name))
+ if (!bstrcmp(current_syslog_name, new_syslog_name))
return;
if (current_syslog_name)