#include "isisd/isis_lsp.h"
#include "isisd/isis_route.h"
#include "isisd/isis_zebra.h"
+#include "isisd/isis_adjacency.h"
#include "isisd/isis_te.h"
#include "isisd/isis_sr.h"
zclient_route_send(ZEBRA_ROUTE_DELETE, zclient, &api);
}
-/* Install Prefix-SID in the forwarding plane. */
-void isis_zebra_install_prefix_sid(const struct sr_prefix *srp)
+/**
+ * Install Prefix-SID in the forwarding plane through Zebra.
+ *
+ * @param srp Segment Routing Prefix-SID
+ */
+static void isis_zebra_prefix_install_prefix_sid(const struct sr_prefix *srp)
{
struct zapi_labels zl;
struct zapi_nexthop *znh;
/* Prepare message. */
memset(&zl, 0, sizeof(zl));
zl.type = ZEBRA_LSP_ISIS_SR;
- zl.local_label = srp->local_label;
+ zl.local_label = srp->input_label;
switch (srp->type) {
case ISIS_SR_PREFIX_LOCAL:
(void)zebra_send_mpls_labels(zclient, ZEBRA_MPLS_LABELS_REPLACE, &zl);
}
-/* Uninstall Prefix-SID from the forwarding plane. */
-void isis_zebra_uninstall_prefix_sid(const struct sr_prefix *srp)
+/**
+ * Uninstall Prefix-SID from the forwarding plane through Zebra.
+ *
+ * @param srp Segment Routing Prefix-SID
+ */
+static void isis_zebra_uninstall_prefix_sid(const struct sr_prefix *srp)
{
struct zapi_labels zl;
/* Prepare message. */
memset(&zl, 0, sizeof(zl));
zl.type = ZEBRA_LSP_ISIS_SR;
- zl.local_label = srp->local_label;
+ zl.local_label = srp->input_label;
if (srp->type == ISIS_SR_PREFIX_REMOTE) {
/* Update route in the RIB too. */
(void)zebra_send_mpls_labels(zclient, ZEBRA_MPLS_LABELS_DELETE, &zl);
}
+/**
+ * Send Prefix-SID to ZEBRA for installation or deletion.
+ *
+ * @param cmd ZEBRA_MPLS_LABELS_REPLACE or ZEBRA_ROUTE_DELETE
+ * @param srp Segment Routing Prefix-SID
+ */
+void isis_zebra_send_prefix_sid(int cmd, const struct sr_prefix *srp)
+{
+
+ if (cmd != ZEBRA_MPLS_LABELS_REPLACE
+ && cmd != ZEBRA_MPLS_LABELS_DELETE) {
+ flog_warn(EC_LIB_DEVELOPMENT, "%s: wrong ZEBRA command",
+ __func__);
+ return;
+ }
+
+ sr_debug(" |- %s label %u for prefix %pFX",
+ cmd == ZEBRA_MPLS_LABELS_REPLACE ? "Update" : "Delete",
+ srp->input_label, &srp->prefix);
+
+ if (cmd == ZEBRA_MPLS_LABELS_REPLACE)
+ isis_zebra_prefix_install_prefix_sid(srp);
+ else
+ isis_zebra_uninstall_prefix_sid(srp);
+}
+
+/**
+ * Send (LAN)-Adjacency-SID to ZEBRA for installation or deletion.
+ *
+ * @param cmd ZEBRA_MPLS_LABELS_ADD or ZEBRA_ROUTE_DELETE
+ * @param sra Segment Routing Adjacency-SID
+ */
+void isis_zebra_send_adjacency_sid(int cmd, const struct sr_adjacency *sra)
+{
+ struct zapi_labels zl;
+ struct zapi_nexthop *znh;
+
+ if (cmd != ZEBRA_MPLS_LABELS_ADD && cmd != ZEBRA_MPLS_LABELS_DELETE) {
+ flog_warn(EC_LIB_DEVELOPMENT, "%s: wrong ZEBRA command",
+ __func__);
+ return;
+ }
+
+ sr_debug(" |- %s label %u for interface %s",
+ cmd == ZEBRA_MPLS_LABELS_ADD ? "Add" : "Delete",
+ sra->nexthop.label, sra->adj->circuit->interface->name);
+
+ memset(&zl, 0, sizeof(zl));
+ zl.type = ZEBRA_LSP_ISIS_SR;
+ zl.local_label = sra->nexthop.label;
+ zl.nexthop_num = 1;
+ znh = &zl.nexthops[0];
+ znh->gate = sra->nexthop.address;
+ znh->type = (sra->nexthop.family == AF_INET)
+ ? NEXTHOP_TYPE_IPV4_IFINDEX
+ : NEXTHOP_TYPE_IPV6_IFINDEX;
+ znh->ifindex = sra->adj->circuit->interface->ifindex;
+ znh->label_num = 1;
+ znh->labels[0] = MPLS_LABEL_IMPLICIT_NULL;
+
+ (void)zebra_send_mpls_labels(zclient, cmd, &zl);
+}
+
static int isis_zebra_read(ZAPI_CALLBACK_ARGS)
{
struct zapi_route api;
type, 0, VRF_DEFAULT);
}
-/* Label Manager Requests. */
+/* Label Manager Functions */
+
+/**
+ * Request Label Range to the Label Manager.
+ *
+ * @param base base label of the label range to request
+ * @param chunk_size size of the label range to request
+ *
+ * @return 0 on success, -1 on failure
+ */
int isis_zebra_request_label_range(uint32_t base, uint32_t chunk_size)
{
int ret;
return 0;
}
+/**
+ * Release Label Range to the Label Manager.
+ *
+ * @param start start of label range to release
+ * @param end end of label range to release
+ */
void isis_zebra_release_label_range(uint32_t start, uint32_t end)
{
int ret;
zlog_warn("%s: error releasing label range!", __func__);
}
+/**
+ * Get a new Label Chunk from the Label Manager. The new Label Chunk is
+ * added to the Label Chunk list.
+ *
+ * @return 0 on success, -1 on failure
+ */
static int isis_zebra_get_label_chunk(void)
{
int ret;
return 0;
}
+/**
+ * Request a label from the Label Chunk list.
+ *
+ * @return valid label on success or MPLS_INVALID_LABEL on failure
+ */
mpls_label_t isis_zebra_request_dynamic_label(void)
{
struct label_chunk *label_chunk;
return label;
}
+/**
+ * Delete a Label Chunk.
+ *
+ * @param val Pointer to the Label Chunk to free
+ */
static void isis_zebra_del_label_chunk(void *val)
{
free(val);
}
+/**
+ * Release a pre-allocated Label chunk to the Label Manager.
+ *
+ * @param start start of the label chunk to release
+ * @param end end of the label chunk to release
+ *
+ * @return 0 on success, -1 on failure
+ */
static int isis_zebra_release_label_chunk(uint32_t start, uint32_t end)
{
int ret;
return 0;
}
+/**
+ * Release a pre-attributes label to the Label Chunk list.
+ *
+ * @param label Label to be release
+ */
void isis_zebra_release_dynamic_label(mpls_label_t label)
{
struct listnode *node;
}
}
+/**
+ * Connect to the Label Manager.
+ */
static void isis_zebra_label_manager_connect(void)
{
/* Connect to label manager. */
while (zclient_socket_connect(zclient_sync) < 0) {
- zlog_warn("%s: error connecting synchronous zclient!",
+ zlog_warn("%s: re-attempt connecting synchronous zclient!",
__func__);
sleep(1);
}
+ /* make socket non-blocking */
set_nonblocking(zclient_sync->sock);
+
+ /* Send hello to notify zebra this is a synchronous client */
+ while (zclient_send_hello(zclient_sync) < 0) {
+ zlog_warn(
+ "%s: re-attempt sending hello for synchronous zclient!",
+ __func__);
+ sleep(1);
+ }
+
+ /* Connect to label manager */
while (lm_label_manager_connect(zclient_sync, 0) != 0) {
- zlog_warn("%s: error connecting to label manager!", __func__);
+ zlog_warn("%s: re-attempt connecting to label manager!", __func__);
sleep(1);
}
label_chunk_list = list_new();
label_chunk_list->del = isis_zebra_del_label_chunk;
while (isis_zebra_get_label_chunk() != 0) {
- zlog_warn("%s: error getting first label chunk!", __func__);
+ zlog_warn("%s: re-attempt getting first label chunk!", __func__);
sleep(1);
}
}
zclient->redistribute_route_del = isis_zebra_read;
/* Initialize special zclient for synchronous message exchanges. */
- zclient_sync = zclient_new(master, &zclient_options_default);
+ struct zclient_options options = zclient_options_default;
+ options.synchronous = true;
+ zclient_sync = zclient_new(master, &options);
zclient_sync->sock = -1;
zclient_sync->redist_default = ZEBRA_ROUTE_ISIS;
zclient_sync->instance = instance;
+ /*
+ * session_id must be different from default value (0) to distinguish
+ * the asynchronous socket from the synchronous one
+ */
+ zclient_sync->session_id = 1;
zclient_sync->privs = &isisd_privs;
}