DEFINE_MTYPE_STATIC(LIB, NEXTHOP, "Nexthop");
DEFINE_MTYPE_STATIC(LIB, NH_LABEL, "Nexthop label");
DEFINE_MTYPE_STATIC(LIB, NH_SEG6LOCAL, "Nexthop seg6local");
+DEFINE_MTYPE_STATIC(LIB, NH_SEG6, "Nexthop seg6");
static int _nexthop_labels_cmp(const struct nexthop *nh1,
const struct nexthop *nh2)
sizeof(struct seg6local_context));
}
+static int _nexthop_seg6_cmp(const struct nexthop *nh1,
+ const struct nexthop *nh2)
+{
+ if (!nh1->nh_seg6_segs && !nh2->nh_seg6_segs)
+ return 0;
+
+ if (nh1->nh_seg6_segs && !nh2->nh_seg6_segs)
+ return 1;
+
+ if (!nh1->nh_seg6_segs && nh2->nh_seg6_segs)
+ return -1;
+
+ return memcmp(nh1->nh_seg6_segs, nh2->nh_seg6_segs,
+ sizeof(struct in6_addr));
+}
+
int nexthop_g_addr_cmp(enum nexthop_types_t type, const union g_addr *addr1,
const union g_addr *addr2)
{
return ret;
ret = _nexthop_seg6local_cmp(next1, next2);
+ if (ret != 0)
+ return ret;
+
+ ret = _nexthop_seg6_cmp(next1, next2);
return ret;
}
{
nexthop_del_labels(nexthop);
nexthop_del_seg6local(nexthop);
+ nexthop_del_seg6(nexthop);
if (nexthop->resolved)
nexthops_free(nexthop->resolved);
XFREE(MTYPE_NEXTHOP, nexthop);
nexthop->nh_seg6local_action = ZEBRA_SEG6_LOCAL_ACTION_UNSPEC;
}
+void nexthop_add_seg6(struct nexthop *nexthop, const struct in6_addr *segs)
+{
+ struct in6_addr *nh_segs;
+
+ nh_segs = XCALLOC(MTYPE_NH_SEG6, sizeof(struct in6_addr));
+ if (segs)
+ *nh_segs = *segs;
+ nexthop->nh_seg6_segs = nh_segs;
+}
+
+void nexthop_del_seg6(struct nexthop *nexthop)
+{
+ XFREE(MTYPE_NH_SEG6, nexthop->nh_seg6_segs);
+}
+
const char *nexthop2str(const struct nexthop *nexthop, char *str, int size)
{
switch (nexthop->type) {
sizeof(nexthop->nh_seg6local_ctx), key);
}
+ if (nexthop->nh_seg6_segs)
+ key = jhash(nexthop->nh_seg6_segs,
+ sizeof(nexthop->nh_seg6_segs), key);
+
return key;
}
if (nexthop->nh_seg6local_ctx)
nexthop_add_seg6local(copy, nexthop->nh_seg6local_action,
nexthop->nh_seg6local_ctx);
+
+ if (nexthop->nh_seg6_segs)
+ nexthop_add_seg6(copy, nexthop->nh_seg6_segs);
}
void nexthop_copy(struct nexthop *copy, const struct nexthop *nexthop,
/* SRv6 localsid info for Endpoint-behaviour */
enum seg6local_action_t nh_seg6local_action;
struct seg6local_context *nh_seg6local_ctx;
+
+ /* SRv6 Headend-behaviour */
+ struct in6_addr *nh_seg6_segs;
};
/* Utility to append one nexthop to another. */
void nexthop_add_seg6local(struct nexthop *nexthop, uint32_t action,
const struct seg6local_context *ctx);
void nexthop_del_seg6local(struct nexthop *nexthop);
+void nexthop_add_seg6(struct nexthop *nexthop, const struct in6_addr* segs);
+void nexthop_del_seg6(struct nexthop *nexthop);
/*
* Allocate a new nexthop object and initialize it from various args.
sizeof(struct seg6local_context));
}
+static int zapi_nexthop_seg6_cmp(const struct zapi_nexthop *next1,
+ const struct zapi_nexthop *next2)
+{
+ return memcmp(&next1->seg6_segs, &next2->seg6_segs,
+ sizeof(struct in6_addr));
+}
+
static int zapi_nexthop_cmp_no_labels(const struct zapi_nexthop *next1,
const struct zapi_nexthop *next2)
{
return ret;
ret = zapi_nexthop_seg6local_cmp(next1, next2);
+ if (ret != 0)
+ return ret;
+
+ ret = zapi_nexthop_seg6_cmp(next1, next2);
return ret;
}
sizeof(struct seg6local_context));
}
+ if (CHECK_FLAG(api_flags, ZEBRA_FLAG_SEG6_ROUTE))
+ stream_write(s, &api_nh->seg6_segs,
+ sizeof(struct in6_addr));
+
done:
return ret;
}
sizeof(struct seg6local_context));
}
+ if (CHECK_FLAG(api_flags, ZEBRA_FLAG_SEG6_ROUTE))
+ STREAM_GET(&api_nh->seg6_segs, s,
+ sizeof(struct in6_addr));
+
/* Success */
ret = 0;
struct nexthop *nexthop_from_zapi_nexthop(const struct zapi_nexthop *znh)
{
+ uint8_t zero[16] = {0};
struct nexthop *n = nexthop_new();
n->type = znh->type;
nexthop_add_seg6local(n, znh->seg6local_action,
&znh->seg6local_ctx);
+ if (memcmp(&znh->seg6_segs, zero, sizeof(struct in6_addr)) != 0)
+ nexthop_add_seg6(n, &znh->seg6_segs);
+
return n;
}
sizeof(struct seg6local_context));
}
+ if (nh->nh_seg6_segs != NULL)
+ memcpy(&znh->seg6_segs, nh->nh_seg6_segs,
+ sizeof(struct in6_addr));
+
return 0;
}