#ifdef HAVE_NETLINK
+/* The following definition is to workaround an issue in the Linux kernel
+ * header files with redefinition of 'struct in6_addr' in both
+ * netinet/in.h and linux/in6.h.
+ * Reference - https://sourceware.org/ml/libc-alpha/2013-01/msg00599.html
+ */
+#define _LINUX_IN6_H
+
#include <net/if_arp.h>
#include <linux/lwtunnel.h>
#include <linux/mpls_iptunnel.h>
+#include <linux/seg6_iptunnel.h>
+#include <linux/seg6_local.h>
#include <linux/neighbour.h>
#include <linux/rtnetlink.h>
#include <linux/nexthop.h>
#include "if.h"
#include "log.h"
#include "prefix.h"
+#include "plist.h"
+#include "plist_int.h"
#include "connected.h"
#include "table.h"
#include "memory.h"
sizeof(label_buf)))
return false;
+ if (nexthop->nh_seg6local_ctx) {
+ struct rtattr *nest;
+ const struct seg6local_context *ctx;
+
+ ctx = nexthop->nh_seg6local_ctx;
+ nl_attr_put16(nlmsg, req_size, RTA_ENCAP_TYPE,
+ LWTUNNEL_ENCAP_SEG6_LOCAL);
+
+ nest = nl_attr_nest(nlmsg, req_size, RTA_ENCAP);
+ switch (nexthop->nh_seg6local_action) {
+ case ZEBRA_SEG6_LOCAL_ACTION_END:
+ nl_attr_put32(nlmsg, req_size, SEG6_LOCAL_ACTION,
+ SEG6_LOCAL_ACTION_END);
+ break;
+ case ZEBRA_SEG6_LOCAL_ACTION_END_X:
+ nl_attr_put32(nlmsg, req_size, SEG6_LOCAL_ACTION,
+ SEG6_LOCAL_ACTION_END_X);
+ nl_attr_put(nlmsg, req_size, SEG6_LOCAL_NH6, &ctx->nh6,
+ sizeof(struct in6_addr));
+ break;
+ case ZEBRA_SEG6_LOCAL_ACTION_END_T:
+ nl_attr_put32(nlmsg, req_size, SEG6_LOCAL_ACTION,
+ SEG6_LOCAL_ACTION_END_T);
+ nl_attr_put32(nlmsg, req_size, SEG6_LOCAL_TABLE,
+ ctx->table);
+ break;
+ case ZEBRA_SEG6_LOCAL_ACTION_END_DX4:
+ nl_attr_put32(nlmsg, req_size, SEG6_LOCAL_ACTION,
+ SEG6_LOCAL_ACTION_END_DX4);
+ nl_attr_put(nlmsg, req_size, SEG6_LOCAL_NH4, &ctx->nh4,
+ sizeof(struct in_addr));
+ break;
+ case ZEBRA_SEG6_LOCAL_ACTION_END_DT6:
+ nl_attr_put32(nlmsg, req_size, SEG6_LOCAL_ACTION,
+ SEG6_LOCAL_ACTION_END_DT6);
+ nl_attr_put32(nlmsg, req_size, SEG6_LOCAL_TABLE,
+ ctx->table);
+ break;
+ default:
+ zlog_err("%s: unsupport seg6local behaviour action=%u",
+ __func__, nexthop->nh_seg6local_action);
+ break;
+ }
+ nl_attr_nest_end(nlmsg, nest);
+ }
+
if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK))
rtmsg->rtm_flags |= RTNH_F_ONLINK;
nl_attr_nest_end(&req->n, nest);
}
+ if (nh->nh_seg6local_ctx) {
+ uint32_t action;
+ uint16_t encap;
+ struct rtattr *nest;
+ const struct seg6local_context *ctx;
+
+ req->nhm.nh_family = AF_INET6;
+ action = nh->nh_seg6local_action;
+ ctx = nh->nh_seg6local_ctx;
+ encap = LWTUNNEL_ENCAP_SEG6_LOCAL;
+ nl_attr_put(&req->n, buflen, NHA_ENCAP_TYPE,
+ &encap, sizeof(uint16_t));
+
+ nest = nl_attr_nest(&req->n, buflen,
+ NHA_ENCAP | NLA_F_NESTED);
+ switch (action) {
+ case SEG6_LOCAL_ACTION_END:
+ nl_attr_put32(&req->n, buflen,
+ SEG6_LOCAL_ACTION,
+ SEG6_LOCAL_ACTION_END);
+ break;
+ case SEG6_LOCAL_ACTION_END_X:
+ nl_attr_put32(&req->n, buflen,
+ SEG6_LOCAL_ACTION,
+ SEG6_LOCAL_ACTION_END_X);
+ nl_attr_put(&req->n, buflen,
+ SEG6_LOCAL_NH6, &ctx->nh6,
+ sizeof(struct in6_addr));
+ break;
+ case SEG6_LOCAL_ACTION_END_T:
+ nl_attr_put32(&req->n, buflen,
+ SEG6_LOCAL_ACTION,
+ SEG6_LOCAL_ACTION_END_T);
+ nl_attr_put32(&req->n, buflen,
+ SEG6_LOCAL_TABLE,
+ ctx->table);
+ break;
+ case SEG6_LOCAL_ACTION_END_DX4:
+ nl_attr_put32(&req->n, buflen,
+ SEG6_LOCAL_ACTION,
+ SEG6_LOCAL_ACTION_END_DX4);
+ nl_attr_put(&req->n, buflen,
+ SEG6_LOCAL_NH4, &ctx->nh4,
+ sizeof(struct in_addr));
+ break;
+ case SEG6_LOCAL_ACTION_END_DT6:
+ nl_attr_put32(&req->n, buflen,
+ SEG6_LOCAL_ACTION,
+ SEG6_LOCAL_ACTION_END_DT6);
+ nl_attr_put32(&req->n, buflen,
+ SEG6_LOCAL_TABLE,
+ ctx->table);
+ break;
+ default:
+ zlog_err("%s: unsupport seg6local behaviour action=%u",
+ __func__, action);
+ break;
+ }
+ nl_attr_nest_end(&req->n, nest);
+ }
+
nexthop_done:
if (IS_ZEBRA_DEBUG_KERNEL)
sizeof(buf), 1));
}
+ if (nexthop->nh_seg6local_ctx) {
+ seg6local_context2str(buf, sizeof(buf),
+ nexthop->nh_seg6local_ctx,
+ nexthop->nh_seg6local_action);
+ vty_out(vty, ", seg6local %s %s",
+ seg6local_action2str(nexthop->nh_seg6local_action),
+ buf);
+ }
+
if (nexthop->weight)
vty_out(vty, ", weight %u", nexthop->weight);
char buf[SRCDEST2STR_BUFFER];
json_object *json_labels = NULL;
json_object *json_backups = NULL;
+ json_object *json_seg6local = NULL;
int i;
json_object_int_add(json_nexthop, "flags",
if (nexthop->srte_color)
json_object_int_add(json_nexthop, "srteColor",
nexthop->srte_color);
+
+ if (nexthop->nh_seg6local_ctx) {
+ json_seg6local = json_object_new_object();
+ json_object_string_add(
+ json_seg6local, "action",
+ seg6local_action2str(nexthop->nh_seg6local_action));
+ json_object_object_add(json_nexthop, "seg6local",
+ json_seg6local);
+ }
}
static void vty_show_ip_route(struct vty *vty, struct route_node *rn,