summaryrefslogtreecommitdiff
path: root/lib/zclient.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/zclient.c')
-rw-r--r--lib/zclient.c231
1 files changed, 230 insertions, 1 deletions
diff --git a/lib/zclient.c b/lib/zclient.c
index 3ea1789441..10dda5ba0e 100644
--- a/lib/zclient.c
+++ b/lib/zclient.c
@@ -41,6 +41,7 @@
#include "lib_errors.h"
#include "srte.h"
#include "printfrr.h"
+#include "srv6.h"
DEFINE_MTYPE_STATIC(LIB, ZCLIENT, "Zclient");
DEFINE_MTYPE_STATIC(LIB, REDIST_INST, "Redistribution instance IDs");
@@ -435,6 +436,42 @@ enum zclient_send_status zclient_send_vrf_label(struct zclient *zclient,
return zclient_send_message(zclient);
}
+enum zclient_send_status zclient_send_localsid(struct zclient *zclient,
+ const struct in6_addr *sid, ifindex_t oif,
+ enum seg6local_action_t action,
+ const struct seg6local_context *context)
+{
+ struct prefix_ipv6 p = {};
+ struct zapi_route api = {};
+ struct nexthop nh = {};
+
+ p.family = AF_INET6;
+ p.prefixlen = 128;
+ p.prefix = *sid;
+
+ api.vrf_id = VRF_DEFAULT;
+ api.type = ZEBRA_ROUTE_BGP;
+ api.instance = 0;
+ api.safi = SAFI_UNICAST;
+ memcpy(&api.prefix, &p, sizeof(p));
+
+ if (action == ZEBRA_SEG6_LOCAL_ACTION_UNSPEC)
+ return zclient_route_send(ZEBRA_ROUTE_DELETE, zclient, &api);
+
+ SET_FLAG(api.flags, ZEBRA_FLAG_ALLOW_RECURSION);
+ SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
+
+ nh.type = NEXTHOP_TYPE_IFINDEX;
+ nh.ifindex = oif;
+ SET_FLAG(nh.flags, ZAPI_NEXTHOP_FLAG_SEG6LOCAL);
+ nexthop_add_srv6_seg6local(&nh, action, context);
+
+ zapi_nexthop_from_nexthop(&api.nexthops[0], &nh);
+ api.nexthop_num = 1;
+
+ return zclient_route_send(ZEBRA_ROUTE_ADD, zclient, &api);
+}
+
/* Send register requests to zebra daemon for the information in a VRF. */
void zclient_send_reg_requests(struct zclient *zclient, vrf_id_t vrf_id)
{
@@ -796,6 +833,26 @@ static int zapi_nexthop_labels_cmp(const struct zapi_nexthop *next1,
return memcmp(next1->labels, next2->labels, next1->label_num);
}
+static int zapi_nexthop_srv6_cmp(const struct zapi_nexthop *next1,
+ const struct zapi_nexthop *next2)
+{
+ int ret = 0;
+
+ ret = memcmp(&next1->seg6_segs, &next2->seg6_segs,
+ sizeof(struct in6_addr));
+ if (ret != 0)
+ return ret;
+
+ if (next1->seg6local_action > next2->seg6local_action)
+ return 1;
+
+ if (next1->seg6local_action < next2->seg6local_action)
+ return -1;
+
+ return memcmp(&next1->seg6local_ctx, &next2->seg6local_ctx,
+ sizeof(struct seg6local_context));
+}
+
static int zapi_nexthop_cmp_no_labels(const struct zapi_nexthop *next1,
const struct zapi_nexthop *next2)
{
@@ -896,6 +953,10 @@ static int zapi_nexthop_cmp(const void *item1, const void *item2)
return ret;
ret = zapi_nexthop_labels_cmp(next1, next2);
+ if (ret != 0)
+ return ret;
+
+ ret = zapi_nexthop_srv6_cmp(next1, next2);
return ret;
}
@@ -992,10 +1053,58 @@ int zapi_nexthop_encode(struct stream *s, const struct zapi_nexthop *api_nh,
stream_putc(s, api_nh->backup_idx[i]);
}
+ if (CHECK_FLAG(nh_flags, ZAPI_NEXTHOP_FLAG_SEG6LOCAL)) {
+ stream_putl(s, api_nh->seg6local_action);
+ stream_write(s, &api_nh->seg6local_ctx,
+ sizeof(struct seg6local_context));
+ }
+
+ if (CHECK_FLAG(nh_flags, ZAPI_NEXTHOP_FLAG_SEG6))
+ stream_write(s, &api_nh->seg6_segs,
+ sizeof(struct in6_addr));
+
done:
return ret;
}
+int zapi_srv6_locator_chunk_encode(struct stream *s,
+ const struct srv6_locator_chunk *c)
+{
+ stream_putw(s, strlen(c->locator_name));
+ stream_put(s, c->locator_name, strlen(c->locator_name));
+ stream_putw(s, c->prefix.prefixlen);
+ stream_put(s, &c->prefix.prefix, sizeof(c->prefix.prefix));
+ stream_putc(s, c->block_bits_length);
+ stream_putc(s, c->node_bits_length);
+ stream_putc(s, c->function_bits_length);
+ stream_putc(s, c->argument_bits_length);
+ return 0;
+}
+
+int zapi_srv6_locator_chunk_decode(struct stream *s,
+ struct srv6_locator_chunk *c)
+{
+ uint16_t len = 0;
+
+ c->prefix.family = AF_INET6;
+
+ STREAM_GETW(s, len);
+ if (len > SRV6_LOCNAME_SIZE)
+ goto stream_failure;
+
+ STREAM_GET(c->locator_name, s, len);
+ STREAM_GETW(s, c->prefix.prefixlen);
+ STREAM_GET(&c->prefix.prefix, s, sizeof(c->prefix.prefix));
+ STREAM_GETC(s, c->block_bits_length);
+ STREAM_GETC(s, c->node_bits_length);
+ STREAM_GETC(s, c->function_bits_length);
+ STREAM_GETC(s, c->argument_bits_length);
+ return 0;
+
+stream_failure:
+ return -1;
+}
+
static int zapi_nhg_encode(struct stream *s, int cmd, struct zapi_nhg *api_nhg)
{
int i;
@@ -1273,6 +1382,16 @@ int zapi_nexthop_decode(struct stream *s, struct zapi_nexthop *api_nh,
STREAM_GETC(s, api_nh->backup_idx[i]);
}
+ if (CHECK_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_SEG6LOCAL)) {
+ STREAM_GETL(s, api_nh->seg6local_action);
+ STREAM_GET(&api_nh->seg6local_ctx, s,
+ sizeof(struct seg6local_context));
+ }
+
+ if (CHECK_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_SEG6))
+ STREAM_GET(&api_nh->seg6_segs, s,
+ sizeof(struct in6_addr));
+
/* Success */
ret = 0;
@@ -1637,6 +1756,13 @@ struct nexthop *nexthop_from_zapi_nexthop(const struct zapi_nexthop *znh)
memcpy(n->backup_idx, znh->backup_idx, n->backup_num);
}
+ if (znh->seg6local_action != ZEBRA_SEG6_LOCAL_ACTION_UNSPEC)
+ nexthop_add_srv6_seg6local(n, znh->seg6local_action,
+ &znh->seg6local_ctx);
+
+ if (!sid_zero(&znh->seg6_segs))
+ nexthop_add_srv6_seg6(n, &znh->seg6_segs);
+
return n;
}
@@ -1681,6 +1807,23 @@ int zapi_nexthop_from_nexthop(struct zapi_nexthop *znh,
memcpy(znh->backup_idx, nh->backup_idx, znh->backup_num);
}
+ if (nh->nh_srv6) {
+ if (nh->nh_srv6->seg6local_action !=
+ ZEBRA_SEG6_LOCAL_ACTION_UNSPEC) {
+ SET_FLAG(znh->flags, ZAPI_NEXTHOP_FLAG_SEG6LOCAL);
+ znh->seg6local_action = nh->nh_srv6->seg6local_action;
+ memcpy(&znh->seg6local_ctx,
+ &nh->nh_srv6->seg6local_ctx,
+ sizeof(struct seg6local_context));
+ }
+
+ if (!sid_zero(&nh->nh_srv6->seg6_segs)) {
+ SET_FLAG(znh->flags, ZAPI_NEXTHOP_FLAG_SEG6);
+ memcpy(&znh->seg6_segs, &nh->nh_srv6->seg6_segs,
+ sizeof(struct in6_addr));
+ }
+ }
+
return 0;
}
@@ -2598,6 +2741,76 @@ stream_failure:
return -1;
}
+/**
+ * Function to request a srv6-locator chunk in an Asyncronous way
+ *
+ * @param zclient Zclient used to connect to table manager (zebra)
+ * @param locator_name Name of SRv6-locator
+ * @result 0 on success, -1 otherwise
+ */
+int srv6_manager_get_locator_chunk(struct zclient *zclient,
+ const char *locator_name)
+{
+ struct stream *s;
+ const size_t len = strlen(locator_name);
+
+ if (zclient_debug)
+ zlog_debug("Getting SRv6-Locator Chunk %s", locator_name);
+
+ if (zclient->sock < 0)
+ return -1;
+
+ /* send request */
+ s = zclient->obuf;
+ stream_reset(s);
+ zclient_create_header(s, ZEBRA_SRV6_MANAGER_GET_LOCATOR_CHUNK,
+ VRF_DEFAULT);
+
+ /* locator_name */
+ stream_putw(s, len);
+ stream_put(s, locator_name, len);
+
+ /* Put length at the first point of the stream. */
+ stream_putw_at(s, 0, stream_get_endp(s));
+
+ return zclient_send_message(zclient);
+}
+
+/**
+ * Function to release a srv6-locator chunk
+ *
+ * @param zclient Zclient used to connect to table manager (zebra)
+ * @param locator_name Name of SRv6-locator
+ * @result 0 on success, -1 otherwise
+ */
+int srv6_manager_release_locator_chunk(struct zclient *zclient,
+ const char *locator_name)
+{
+ struct stream *s;
+ const size_t len = strlen(locator_name);
+
+ if (zclient_debug)
+ zlog_debug("Releasing SRv6-Locator Chunk %s", locator_name);
+
+ if (zclient->sock < 0)
+ return -1;
+
+ /* send request */
+ s = zclient->obuf;
+ stream_reset(s);
+ zclient_create_header(s, ZEBRA_SRV6_MANAGER_RELEASE_LOCATOR_CHUNK,
+ VRF_DEFAULT);
+
+ /* locator_name */
+ stream_putw(s, len);
+ stream_put(s, locator_name, len);
+
+ /* Put length at the first point of the stream. */
+ stream_putw_at(s, 0, stream_get_endp(s));
+
+ return zclient_send_message(zclient);
+}
+
/*
* Asynchronous label chunk request
*
@@ -3345,7 +3558,8 @@ enum zclient_send_status zclient_send_mlag_register(struct zclient *client,
enum zclient_send_status zclient_send_mlag_deregister(struct zclient *client)
{
- return zebra_message_send(client, ZEBRA_MLAG_CLIENT_UNREGISTER, VRF_DEFAULT);
+ return zebra_message_send(client, ZEBRA_MLAG_CLIENT_UNREGISTER,
+ VRF_DEFAULT);
}
enum zclient_send_status zclient_send_mlag_data(struct zclient *client,
@@ -3888,6 +4102,21 @@ static int zclient_read(struct thread *thread)
case ZEBRA_MLAG_FORWARD_MSG:
zclient_mlag_handle_msg(command, zclient, length, vrf_id);
break;
+ case ZEBRA_SRV6_LOCATOR_ADD:
+ if (zclient->srv6_locator_add)
+ (*zclient->srv6_locator_add)(command, zclient, length,
+ vrf_id);
+ break;
+ case ZEBRA_SRV6_LOCATOR_DELETE:
+ if (zclient->srv6_locator_delete)
+ (*zclient->srv6_locator_delete)(command, zclient,
+ length, vrf_id);
+ break;
+ case ZEBRA_SRV6_MANAGER_GET_LOCATOR_CHUNK:
+ if (zclient->process_srv6_locator_chunk)
+ (*zclient->process_srv6_locator_chunk)(command, zclient,
+ length, vrf_id);
+ break;
case ZEBRA_ERROR:
zclient_handle_error(command, zclient, length, vrf_id);
break;