summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/zclient.c23
-rw-r--r--lib/zclient.h8
-rw-r--r--sharpd/sharp_nht.c12
-rw-r--r--sharpd/sharp_zebra.c19
-rw-r--r--sharpd/sharp_zebra.h3
-rw-r--r--zebra/zapi_msg.c152
-rw-r--r--zebra/zebra_nhg.c8
7 files changed, 162 insertions, 63 deletions
diff --git a/lib/zclient.c b/lib/zclient.c
index 13eba4c790..b7d240b4e8 100644
--- a/lib/zclient.c
+++ b/lib/zclient.c
@@ -1017,9 +1017,10 @@ done:
return ret;
}
-static int zapi_nhg_encode(struct stream *s, uint16_t proto, int cmd,
- struct zapi_nhg *api_nhg)
+int zapi_nhg_encode(struct stream *s, int cmd, struct zapi_nhg *api_nhg)
{
+ int i;
+
if (cmd != ZEBRA_NHG_DEL && cmd != ZEBRA_NHG_ADD) {
flog_err(EC_LIB_ZAPI_ENCODE,
"%s: Specified zapi NHG command (%d) doesn't exist\n",
@@ -1030,17 +1031,26 @@ static int zapi_nhg_encode(struct stream *s, uint16_t proto, int cmd,
stream_reset(s);
zclient_create_header(s, cmd, VRF_DEFAULT);
- stream_putw(s, proto);
+ stream_putw(s, api_nhg->proto);
stream_putl(s, api_nhg->id);
if (cmd == ZEBRA_NHG_ADD) {
+ /* Nexthops */
zapi_nexthop_group_sort(api_nhg->nexthops,
api_nhg->nexthop_num);
stream_putw(s, api_nhg->nexthop_num);
- for (int i = 0; i < api_nhg->nexthop_num; i++)
+ for (i = 0; i < api_nhg->nexthop_num; i++)
zapi_nexthop_encode(s, &api_nhg->nexthops[i], 0, 0);
+
+ /* Backup nexthops */
+
+ stream_putw(s, api_nhg->backup_nexthop_num);
+
+ for (i = 0; i < api_nhg->backup_nexthop_num; i++)
+ zapi_nexthop_encode(s, &api_nhg->backup_nexthops[i], 0,
+ 0);
}
stream_putw_at(s, 0, stream_get_endp(s));
@@ -1050,8 +1060,9 @@ static int zapi_nhg_encode(struct stream *s, uint16_t proto, int cmd,
int zclient_nhg_send(struct zclient *zclient, int cmd, struct zapi_nhg *api_nhg)
{
- if (zapi_nhg_encode(zclient->obuf, zclient->redist_default, cmd,
- api_nhg))
+ api_nhg->proto = zclient->redist_default;
+
+ if (zapi_nhg_encode(zclient->obuf, cmd, api_nhg))
return -1;
return zclient_send_message(zclient);
diff --git a/lib/zclient.h b/lib/zclient.h
index b41f291554..959a101395 100644
--- a/lib/zclient.h
+++ b/lib/zclient.h
@@ -442,9 +442,14 @@ struct zapi_nexthop {
* ZAPI Nexthop Group. For use with protocol creation of nexthop groups.
*/
struct zapi_nhg {
+ uint16_t proto;
uint32_t id;
+
uint16_t nexthop_num;
struct zapi_nexthop nexthops[MULTIPATH_NUM];
+
+ uint16_t backup_nexthop_num;
+ struct zapi_nexthop backup_nexthops[MULTIPATH_NUM];
};
/*
@@ -907,6 +912,9 @@ bool zapi_ipset_notify_decode(struct stream *s,
uint32_t *unique,
enum zapi_ipset_notify_owner *note);
+
+extern int zapi_nhg_encode(struct stream *s, int cmd, struct zapi_nhg *api_nhg);
+extern int zapi_nhg_decode(struct stream *s, int cmd, struct zapi_nhg *api_nhg);
extern int zclient_nhg_send(struct zclient *zclient, int cmd,
struct zapi_nhg *api_nhg);
diff --git a/sharpd/sharp_nht.c b/sharpd/sharp_nht.c
index 9f31552720..5b3fe2583e 100644
--- a/sharpd/sharp_nht.c
+++ b/sharpd/sharp_nht.c
@@ -133,11 +133,15 @@ static void sharp_nhgroup_add_nexthop_cb(const struct nexthop_group_cmd *nhgc,
{
struct sharp_nhg lookup;
struct sharp_nhg *snhg;
+ struct nexthop_group_cmd *bnhgc = NULL;
strlcpy(lookup.name, nhgc->name, sizeof(lookup.name));
snhg = sharp_nhg_rb_find(&nhg_head, &lookup);
- nhg_add(snhg->id, &nhgc->nhg);
+ if (nhgc->backup_list_name[0])
+ bnhgc = nhgc_find(nhgc->backup_list_name);
+
+ nhg_add(snhg->id, &nhgc->nhg, (bnhgc ? &bnhgc->nhg : NULL));
}
static void sharp_nhgroup_del_nexthop_cb(const struct nexthop_group_cmd *nhgc,
@@ -145,11 +149,15 @@ static void sharp_nhgroup_del_nexthop_cb(const struct nexthop_group_cmd *nhgc,
{
struct sharp_nhg lookup;
struct sharp_nhg *snhg;
+ struct nexthop_group_cmd *bnhgc = NULL;
strlcpy(lookup.name, nhgc->name, sizeof(lookup.name));
snhg = sharp_nhg_rb_find(&nhg_head, &lookup);
- nhg_add(snhg->id, &nhgc->nhg);
+ if (nhgc->backup_list_name[0])
+ bnhgc = nhgc_find(nhgc->backup_list_name);
+
+ nhg_add(snhg->id, &nhgc->nhg, (bnhgc ? &bnhgc->nhg : NULL));
}
static void sharp_nhgroup_delete_cb(const char *name)
diff --git a/sharpd/sharp_zebra.c b/sharpd/sharp_zebra.c
index 50129c2363..d167e8e277 100644
--- a/sharpd/sharp_zebra.c
+++ b/sharpd/sharp_zebra.c
@@ -357,7 +357,8 @@ void vrf_label_add(vrf_id_t vrf_id, afi_t afi, mpls_label_t label)
zclient_send_vrf_label(zclient, vrf_id, afi, label, ZEBRA_LSP_SHARP);
}
-void nhg_add(uint32_t id, const struct nexthop_group *nhg)
+void nhg_add(uint32_t id, const struct nexthop_group *nhg,
+ const struct nexthop_group *backup_nhg)
{
struct zapi_nhg api_nhg = {};
struct zapi_nexthop *api_nh;
@@ -378,6 +379,22 @@ void nhg_add(uint32_t id, const struct nexthop_group *nhg)
api_nhg.nexthop_num++;
}
+ if (backup_nhg) {
+ for (ALL_NEXTHOPS_PTR(backup_nhg, nh)) {
+ if (api_nhg.backup_nexthop_num >= MULTIPATH_NUM) {
+ zlog_warn(
+ "%s: number of backup nexthops greater than max multipath size, truncating",
+ __func__);
+ break;
+ }
+ api_nh = &api_nhg.backup_nexthops
+ [api_nhg.backup_nexthop_num];
+
+ zapi_backup_nexthop_from_nexthop(api_nh, nh);
+ api_nhg.backup_nexthop_num++;
+ }
+ }
+
zclient_nhg_send(zclient, ZEBRA_NHG_ADD, &api_nhg);
}
diff --git a/sharpd/sharp_zebra.h b/sharpd/sharp_zebra.h
index 69d7343cc4..4a767ababf 100644
--- a/sharpd/sharp_zebra.h
+++ b/sharpd/sharp_zebra.h
@@ -29,7 +29,8 @@ int sharp_zclient_create(uint32_t session_id);
int sharp_zclient_delete(uint32_t session_id);
extern void vrf_label_add(vrf_id_t vrf_id, afi_t afi, mpls_label_t label);
-extern void nhg_add(uint32_t id, const struct nexthop_group *nhg);
+extern void nhg_add(uint32_t id, const struct nexthop_group *nhg,
+ const struct nexthop_group *backup_nhg);
extern void nhg_del(uint32_t id);
extern void route_add(const struct prefix *p, vrf_id_t, uint8_t instance,
uint32_t nhgid, const struct nexthop_group *nhg,
diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c
index 7ed3a41ae1..1d8c5c7cc0 100644
--- a/zebra/zapi_msg.c
+++ b/zebra/zapi_msg.c
@@ -1732,84 +1732,134 @@ static bool zapi_read_nexthops(struct zserv *client, struct prefix *p,
return true;
}
+int zapi_nhg_decode(struct stream *s, int cmd, struct zapi_nhg *api_nhg)
+{
+ uint16_t i;
+ struct zapi_nexthop *znh;
+
+ STREAM_GETW(s, api_nhg->proto);
+ STREAM_GETL(s, api_nhg->id);
+
+ if (cmd == ZEBRA_NHG_DEL)
+ goto done;
+
+ /* Nexthops */
+ STREAM_GETW(s, api_nhg->nexthop_num);
+
+ if (zserv_nexthop_num_warn(__func__, NULL, api_nhg->nexthop_num))
+ return -1;
+
+ if (api_nhg->nexthop_num <= 0) {
+ flog_warn(EC_ZEBRA_NEXTHOP_CREATION_FAILED,
+ "%s: No nexthops sent", __func__);
+ return -1;
+ }
+
+ for (i = 0; i < api_nhg->nexthop_num; i++) {
+ znh = &((api_nhg->nexthops)[i]);
+
+ if (zapi_nexthop_decode(s, znh, 0, 0) != 0) {
+ flog_warn(EC_ZEBRA_NEXTHOP_CREATION_FAILED,
+ "%s: Nexthop creation failed", __func__);
+ return -1;
+ }
+ }
+
+ /* Backup Nexthops */
+ STREAM_GETW(s, api_nhg->backup_nexthop_num);
+
+ if (zserv_nexthop_num_warn(__func__, NULL, api_nhg->backup_nexthop_num))
+ return -1;
+
+ for (i = 0; i < api_nhg->backup_nexthop_num; i++) {
+ znh = &((api_nhg->backup_nexthops)[i]);
+
+ if (zapi_nexthop_decode(s, znh, 0, 0) != 0) {
+ flog_warn(EC_ZEBRA_NEXTHOP_CREATION_FAILED,
+ "%s: Backup Nexthop creation failed",
+ __func__);
+ return -1;
+ }
+ }
+
+done:
+ return 0;
+
+stream_failure:
+ flog_warn(
+ EC_ZEBRA_NEXTHOP_CREATION_FAILED,
+ "%s: Nexthop Group decode failed with some sort of stream read failure",
+ __func__);
+ return -1;
+}
+
static void zread_nhg_del(ZAPI_HANDLER_ARGS)
{
- struct stream *s = msg;
- uint32_t id;
- uint16_t proto;
+ struct stream *s;
+ struct zapi_nhg api_nhg = {};
struct nhg_hash_entry *nhe;
- STREAM_GETW(s, proto);
- STREAM_GETL(s, id);
+ s = msg;
+ if (zapi_nhg_decode(s, hdr->command, &api_nhg) < 0) {
+ if (IS_ZEBRA_DEBUG_RECV)
+ zlog_debug("%s: Unable to decode zapi_nhg sent",
+ __func__);
+ return;
+ }
/*
* Delete the received nhg id
*/
- nhe = zebra_nhg_proto_del(id, proto);
+ nhe = zebra_nhg_proto_del(api_nhg.id, api_nhg.proto);
if (nhe) {
zebra_nhg_decrement_ref(nhe);
- nhg_notify(proto, client->instance, id, ZAPI_NHG_REMOVED);
+ nhg_notify(api_nhg.proto, client->instance, api_nhg.id,
+ ZAPI_NHG_REMOVED);
} else
- nhg_notify(proto, client->instance, id, ZAPI_NHG_REMOVE_FAIL);
-
- return;
-
-stream_failure:
- flog_warn(EC_ZEBRA_NEXTHOP_CREATION_FAILED,
- "%s: Nexthop group deletion failed", __func__);
- return;
+ nhg_notify(api_nhg.proto, client->instance, api_nhg.id,
+ ZAPI_NHG_REMOVE_FAIL);
}
static void zread_nhg_add(ZAPI_HANDLER_ARGS)
{
struct stream *s;
- uint32_t id;
- size_t nhops, i;
- struct zapi_nexthop zapi_nexthops[MULTIPATH_NUM];
+ struct zapi_nhg api_nhg = {};
struct nexthop_group *nhg = NULL;
- uint16_t proto;
+ struct nhg_backup_info *bnhg = NULL;
struct nhg_hash_entry *nhe;
s = msg;
-
- STREAM_GETW(s, proto);
- STREAM_GETL(s, id);
- STREAM_GETW(s, nhops);
-
- if (zserv_nexthop_num_warn(__func__, NULL, nhops))
- return;
-
- if (nhops <= 0) {
- flog_warn(EC_ZEBRA_NEXTHOP_CREATION_FAILED,
- "%s: No nexthops sent", __func__);
+ if (zapi_nhg_decode(s, hdr->command, &api_nhg) < 0) {
+ if (IS_ZEBRA_DEBUG_RECV)
+ zlog_debug("%s: Unable to decode zapi_nhg sent",
+ __func__);
return;
}
- for (i = 0; i < nhops; i++) {
- struct zapi_nexthop *znh = &zapi_nexthops[i];
+ if ((!zapi_read_nexthops(client, NULL, api_nhg.nexthops, 0, 0,
+ api_nhg.nexthop_num,
+ api_nhg.backup_nexthop_num, &nhg, NULL))
+ || (!zapi_read_nexthops(client, NULL, api_nhg.backup_nexthops, 0, 0,
+ api_nhg.backup_nexthop_num,
+ api_nhg.backup_nexthop_num, NULL, &bnhg))) {
- if (zapi_nexthop_decode(s, znh, 0, 0) != 0) {
- flog_warn(EC_ZEBRA_NEXTHOP_CREATION_FAILED,
- "%s: Nexthop creation failed", __func__);
- return;
- }
- }
-
- if (!zapi_read_nexthops(client, NULL, zapi_nexthops, 0, 0, nhops, 0,
- &nhg, NULL)) {
flog_warn(EC_ZEBRA_NEXTHOP_CREATION_FAILED,
"%s: Nexthop Group Creation failed", __func__);
+
+ nexthop_group_delete(&nhg);
+ zebra_nhg_backup_free(&bnhg);
return;
}
/*
* Create the nhg
*/
- nhe = zebra_nhg_proto_add(id, proto, nhg, 0);
+ nhe = zebra_nhg_proto_add(api_nhg.id, api_nhg.proto, nhg, 0);
nexthop_group_delete(&nhg);
+ zebra_nhg_backup_free(&bnhg);
/*
* TODO:
@@ -1818,18 +1868,11 @@ static void zread_nhg_add(ZAPI_HANDLER_ARGS)
* Resolution is going to need some more work.
*/
if (nhe)
- nhg_notify(proto, client->instance, id, ZAPI_NHG_INSTALLED);
+ nhg_notify(api_nhg.proto, client->instance, api_nhg.id,
+ ZAPI_NHG_INSTALLED);
else
- nhg_notify(proto, client->instance, id, ZAPI_NHG_FAIL_INSTALL);
-
- return;
-
-stream_failure:
- flog_warn(
- EC_ZEBRA_NEXTHOP_CREATION_FAILED,
- "%s: Nexthop Group creation failed with some sort of stream read failure",
- __func__);
- return;
+ nhg_notify(api_nhg.proto, client->instance, api_nhg.id,
+ ZAPI_NHG_FAIL_INSTALL);
}
static void zread_route_add(ZAPI_HANDLER_ARGS)
@@ -1911,6 +1954,9 @@ static void zread_route_add(ZAPI_HANDLER_ARGS)
api.flags, api.message,
api.backup_nexthop_num,
api.backup_nexthop_num, NULL, &bnhg))) {
+
+ nexthop_group_delete(&ng);
+ zebra_nhg_backup_free(&bnhg);
XFREE(MTYPE_RE, re);
return;
}
diff --git a/zebra/zebra_nhg.c b/zebra/zebra_nhg.c
index 1ed7ff00e5..6aa9ba0ebc 100644
--- a/zebra/zebra_nhg.c
+++ b/zebra/zebra_nhg.c
@@ -2759,6 +2759,14 @@ struct nhg_hash_entry *zebra_nhg_proto_add(uint32_t id, int type,
* Once resolution is figured out, we won't need this!
*/
for (ALL_NEXTHOPS_PTR(nhg, newhop)) {
+ if (CHECK_FLAG(newhop->flags, NEXTHOP_FLAG_HAS_BACKUP)) {
+ if (IS_ZEBRA_DEBUG_NHG)
+ zlog_debug(
+ "%s: id %u, backup nexthops not supported",
+ __func__, id);
+ return NULL;
+ }
+
if (newhop->type == NEXTHOP_TYPE_BLACKHOLE) {
if (IS_ZEBRA_DEBUG_NHG)
zlog_debug(