DEFINE_MTYPE_STATIC(LIB, NEXTHOP, "Nexthop");
DEFINE_MTYPE_STATIC(LIB, NH_LABEL, "Nexthop label");
+DEFINE_MTYPE_STATIC(LIB, NH_SEG6LOCAL, "Nexthop seg6local");
static int _nexthop_labels_cmp(const struct nexthop *nh1,
const struct nexthop *nh2)
(nhl1->num_labels * sizeof(mpls_label_t)));
}
+static int _nexthop_seg6local_cmp(const struct nexthop *nh1,
+ const struct nexthop *nh2)
+{
+ if (nh1->nh_seg6local_action > nh2->nh_seg6local_action)
+ return 1;
+
+ if (nh2->nh_seg6local_action < nh1->nh_seg6local_action)
+ return -1;
+
+ if (!nh1->nh_seg6local_ctx && !nh2->nh_seg6local_ctx)
+ return 0;
+
+ if (nh1->nh_seg6local_ctx && !nh2->nh_seg6local_ctx)
+ return 1;
+
+ if (!nh1->nh_seg6local_ctx && nh2->nh_seg6local_ctx)
+ return -1;
+
+ return memcmp(nh1->nh_seg6local_ctx, nh2->nh_seg6local_ctx,
+ sizeof(struct seg6local_context));
+}
+
int nexthop_g_addr_cmp(enum nexthop_types_t type, const union g_addr *addr1,
const union g_addr *addr2)
{
return ret;
ret = _nexthop_labels_cmp(next1, next2);
+ if (ret != 0)
+ return ret;
+
+ ret = _nexthop_seg6local_cmp(next1, next2);
return ret;
}
void nexthop_free(struct nexthop *nexthop)
{
nexthop_del_labels(nexthop);
+ nexthop_del_seg6local(nexthop);
if (nexthop->resolved)
nexthops_free(nexthop->resolved);
XFREE(MTYPE_NEXTHOP, nexthop);
nexthop->nh_label_type = ZEBRA_LSP_NONE;
}
+void nexthop_add_seg6local(struct nexthop *nexthop, uint32_t action,
+ const struct seg6local_context *ctx)
+{
+ struct seg6local_context *nh_ctx;
+
+ if (action == ZEBRA_SEG6_LOCAL_ACTION_UNSPEC)
+ return;
+
+ nh_ctx = XCALLOC(MTYPE_NH_SEG6LOCAL, sizeof(struct seg6local_context));
+ if (ctx)
+ *nh_ctx = *ctx;
+ nexthop->nh_seg6local_action = action;
+ nexthop->nh_seg6local_ctx = nh_ctx;
+}
+
+void nexthop_del_seg6local(struct nexthop *nexthop)
+{
+ XFREE(MTYPE_NH_SEG6LOCAL, nexthop->nh_seg6local_ctx);
+ nexthop->nh_seg6local_action = ZEBRA_SEG6_LOCAL_ACTION_UNSPEC;
+}
+
const char *nexthop2str(const struct nexthop *nexthop, char *str, int size)
{
switch (nexthop->type) {
key = jhash_1word(nexthop->backup_idx[i], key);
}
+ if (nexthop->nh_seg6local_ctx) {
+ key = jhash_1word(nexthop->nh_seg6local_action, key);
+ key = jhash(nexthop->nh_seg6local_ctx,
+ sizeof(nexthop->nh_seg6local_ctx), key);
+ }
+
return key;
}
nexthop_add_labels(copy, nexthop->nh_label_type,
nexthop->nh_label->num_labels,
&nexthop->nh_label->label[0]);
+
+ if (nexthop->nh_seg6local_ctx)
+ nexthop_add_seg6local(copy, nexthop->nh_seg6local_action,
+ nexthop->nh_seg6local_ctx);
}
void nexthop_copy(struct nexthop *copy, const struct nexthop *nexthop,
#include "prefix.h"
#include "mpls.h"
#include "vxlan.h"
+#include "srv6.h"
#ifdef __cplusplus
extern "C" {
/* SR-TE color used for matching SR-TE policies */
uint32_t srte_color;
+
+ /* SRv6 localsid info for Endpoint-behaviour */
+ enum seg6local_action_t nh_seg6local_action;
+ struct seg6local_context *nh_seg6local_ctx;
};
/* Utility to append one nexthop to another. */
void nexthop_add_labels(struct nexthop *nexthop, enum lsp_types_t ltype,
uint8_t num_labels, const mpls_label_t *labels);
void nexthop_del_labels(struct nexthop *);
+void nexthop_add_seg6local(struct nexthop *nexthop, uint32_t action,
+ const struct seg6local_context *ctx);
+void nexthop_del_seg6local(struct nexthop *nexthop);
/*
* Allocate a new nexthop object and initialize it from various args.
return memcmp(next1->labels, next2->labels, next1->label_num);
}
+static int zapi_nexthop_seg6local_cmp(const struct zapi_nexthop *next1,
+ const struct zapi_nexthop *next2)
+{
+ 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)
{
return ret;
ret = zapi_nexthop_labels_cmp(next1, next2);
+ if (ret != 0)
+ return ret;
+
+ ret = zapi_nexthop_seg6local_cmp(next1, next2);
return ret;
}
stream_putc(s, api_nh->backup_idx[i]);
}
+ if (CHECK_FLAG(api_flags, ZEBRA_FLAG_SEG6LOCAL_ROUTE)) {
+ stream_putl(s, api_nh->seg6local_action);
+ stream_write(s, &api_nh->seg6local_ctx,
+ sizeof(struct seg6local_context));
+ }
+
done:
return ret;
}
STREAM_GETC(s, api_nh->backup_idx[i]);
}
+ if (CHECK_FLAG(api_flags, ZEBRA_FLAG_SEG6LOCAL_ROUTE)) {
+ STREAM_GETL(s, api_nh->seg6local_action);
+ STREAM_GET(&api_nh->seg6local_ctx, s,
+ sizeof(struct seg6local_context));
+ }
+
/* Success */
ret = 0;
memcpy(n->backup_idx, znh->backup_idx, n->backup_num);
}
+ if (znh->seg6local_action != 0)
+ nexthop_add_seg6local(n, znh->seg6local_action,
+ &znh->seg6local_ctx);
+
return n;
}
memcpy(znh->backup_idx, nh->backup_idx, znh->backup_num);
}
+ if (nh->nh_seg6local_action != 0 && nh->nh_seg6local_ctx != NULL) {
+ znh->seg6local_action = nh->nh_seg6local_action;
+ memcpy(&znh->seg6local_ctx, nh->nh_seg6local_ctx,
+ sizeof(struct seg6local_context));
+ }
+
return 0;
}
/* SR-TE color. */
uint32_t srte_color;
+
+ /* SRv6 localsid info for Endpoint-behaviour */
+ uint32_t seg6local_action;
+ struct seg6local_context seg6local_ctx;
};
/*
* offload situation.
*/
#define ZEBRA_FLAG_OFFLOAD_FAILED 0x200
+/*
+ * This flag tells Zebra that the route is a seg6 route and should
+ * be treated specially.
+ */
+#define ZEBRA_FLAG_SEG6_ROUTE 0x400
+/*
+ * This flag tells Zebra that the route is a seg6local route and
+ * should be treated specially.
+ */
+#define ZEBRA_FLAG_SEG6LOCAL_ROUTE 0x800
/* The older XXX_MESSAGE flags live here */
uint32_t message;