mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-14 00:56:19 +00:00
zebra: Add code to set SRv6 encap source addr in dplane
Add a bunch of set functions and associated data structure in zebra_dplane to allow the configuration of the source address for SRv6 encap in the data plane. Signed-off-by: Carmine Scarpitta <carmine.scarpitta@uniroma2.it>
This commit is contained in:
parent
959267f7c2
commit
8d0b4745a1
@ -972,6 +972,7 @@ static int fpm_nl_enqueue(struct fpm_nl_ctx *fnc, struct zebra_dplane_ctx *ctx)
|
||||
case DPLANE_OP_TC_FILTER_ADD:
|
||||
case DPLANE_OP_TC_FILTER_DELETE:
|
||||
case DPLANE_OP_TC_FILTER_UPDATE:
|
||||
case DPLANE_OP_SRV6_ENCAP_SRCADDR_SET:
|
||||
case DPLANE_OP_NONE:
|
||||
case DPLANE_OP_STARTUP_STAGE:
|
||||
break;
|
||||
|
@ -111,6 +111,106 @@ int genl_resolve_family(const char *family)
|
||||
return ge_netlink_talk(genl_parse_getfamily, &req.n, zns, false);
|
||||
}
|
||||
|
||||
/*
|
||||
* sr tunsrc change via netlink interface, using a dataplane context object
|
||||
*
|
||||
* Returns -1 on failure, 0 when the msg doesn't fit entirely in the buffer
|
||||
* otherwise the number of bytes written to buf.
|
||||
*/
|
||||
ssize_t netlink_sr_tunsrc_set_msg_encode(int cmd, struct zebra_dplane_ctx *ctx,
|
||||
void *buf, size_t buflen)
|
||||
{
|
||||
struct nlsock *nl;
|
||||
const struct in6_addr *tunsrc_addr;
|
||||
struct genl_request *req = buf;
|
||||
|
||||
if (seg6_genl_family < 0) {
|
||||
zlog_err(
|
||||
"Failed to set SRv6 source address: kernel does not support 'SEG6' Generic Netlink family.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
tunsrc_addr = dplane_ctx_get_srv6_encap_srcaddr(ctx);
|
||||
if (!tunsrc_addr)
|
||||
return -1;
|
||||
|
||||
if (buflen < sizeof(*req))
|
||||
return 0;
|
||||
|
||||
nl = kernel_netlink_nlsock_lookup(dplane_ctx_get_ns_sock(ctx));
|
||||
|
||||
memset(req, 0, sizeof(*req));
|
||||
|
||||
req->n.nlmsg_len = NLMSG_LENGTH(GENL_HDRLEN);
|
||||
req->n.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
|
||||
|
||||
/* Prepare Netlink request to set tunsrc addr */
|
||||
req->n.nlmsg_type = seg6_genl_family;
|
||||
req->n.nlmsg_pid = nl->snl.nl_pid;
|
||||
|
||||
req->g.cmd = cmd;
|
||||
req->g.version = SEG6_GENL_VERSION;
|
||||
|
||||
switch (cmd) {
|
||||
case SEG6_CMD_SET_TUNSRC:
|
||||
if (!nl_attr_put(&req->n, buflen, SEG6_ATTR_DST, tunsrc_addr,
|
||||
sizeof(struct in6_addr)))
|
||||
return 0;
|
||||
break;
|
||||
default:
|
||||
zlog_err("Unsupported command (%u)", cmd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return NLMSG_ALIGN(req->n.nlmsg_len);
|
||||
}
|
||||
|
||||
ssize_t netlink_sr_tunsrc_set_msg_encoder(struct zebra_dplane_ctx *ctx,
|
||||
void *buf, size_t buflen)
|
||||
{
|
||||
enum dplane_op_e op;
|
||||
int cmd = 0;
|
||||
|
||||
op = dplane_ctx_get_op(ctx);
|
||||
|
||||
/* Call to netlink layer based on type of operation */
|
||||
if (op == DPLANE_OP_SRV6_ENCAP_SRCADDR_SET) {
|
||||
/* Validate */
|
||||
if (dplane_ctx_get_srv6_encap_srcaddr(ctx) == NULL) {
|
||||
if (IS_ZEBRA_DEBUG_KERNEL)
|
||||
zlog_debug(
|
||||
"sr tunsrc set failed: SRv6 encap source address not set");
|
||||
return -1;
|
||||
}
|
||||
|
||||
cmd = SEG6_CMD_SET_TUNSRC;
|
||||
} else {
|
||||
/* Invalid op */
|
||||
zlog_err("Context received for kernel sr tunsrc update with incorrect OP code (%u)",
|
||||
op);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return netlink_sr_tunsrc_set_msg_encode(cmd, ctx, buf, buflen);
|
||||
}
|
||||
|
||||
enum netlink_msg_status
|
||||
netlink_put_sr_tunsrc_set_msg(struct nl_batch *bth, struct zebra_dplane_ctx *ctx)
|
||||
{
|
||||
enum dplane_op_e op;
|
||||
struct zebra_ns *zns;
|
||||
struct genl_request req;
|
||||
|
||||
op = dplane_ctx_get_op(ctx);
|
||||
assert(op == DPLANE_OP_SRV6_ENCAP_SRCADDR_SET);
|
||||
|
||||
netlink_sr_tunsrc_set_msg_encoder(ctx, &req, sizeof(req));
|
||||
|
||||
zns = zebra_ns_lookup(dplane_ctx_get_ns_sock(ctx));
|
||||
|
||||
return ge_netlink_talk(netlink_talk_filter, &req.n, zns, false);
|
||||
}
|
||||
|
||||
void ge_netlink_init(struct zebra_ns *zns)
|
||||
{
|
||||
if (zns->ge_netlink_cmd.sock < 0)
|
||||
|
@ -25,6 +25,15 @@ struct genl_request {
|
||||
};
|
||||
|
||||
extern int genl_resolve_family(const char *family);
|
||||
extern ssize_t netlink_sr_tunsrc_set_msg_encode(int cmd,
|
||||
struct zebra_dplane_ctx *ctx,
|
||||
void *buf, size_t buflen);
|
||||
extern ssize_t netlink_sr_tunsrc_set_msg_encoder(struct zebra_dplane_ctx *ctx,
|
||||
void *buf, size_t buflen);
|
||||
struct nl_batch;
|
||||
extern enum netlink_msg_status
|
||||
netlink_put_sr_tunsrc_set_msg(struct nl_batch *bth,
|
||||
struct zebra_dplane_ctx *ctx);
|
||||
extern void ge_netlink_init(struct zebra_ns *zns);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -1648,6 +1648,9 @@ static enum netlink_msg_status nl_put_msg(struct nl_batch *bth,
|
||||
case DPLANE_OP_TC_FILTER_DELETE:
|
||||
case DPLANE_OP_TC_FILTER_UPDATE:
|
||||
return netlink_put_tc_filter_update_msg(bth, ctx);
|
||||
|
||||
case DPLANE_OP_SRV6_ENCAP_SRCADDR_SET:
|
||||
return netlink_put_sr_tunsrc_set_msg(bth, ctx);
|
||||
}
|
||||
|
||||
return FRR_NETLINK_ERROR;
|
||||
|
@ -1622,6 +1622,7 @@ void kernel_update_multi(struct dplane_ctx_list_head *ctx_list)
|
||||
case DPLANE_OP_INTF_ADDR_ADD:
|
||||
case DPLANE_OP_INTF_ADDR_DEL:
|
||||
case DPLANE_OP_STARTUP_STAGE:
|
||||
case DPLANE_OP_SRV6_ENCAP_SRCADDR_SET:
|
||||
zlog_err("Unhandled dplane data for %s",
|
||||
dplane_op2str(dplane_ctx_get_op(ctx)));
|
||||
res = ZEBRA_DPLANE_REQUEST_FAILURE;
|
||||
|
@ -356,6 +356,13 @@ struct dplane_tc_filter_info {
|
||||
uint32_t classid;
|
||||
};
|
||||
|
||||
/*
|
||||
* SRv6 encapsulation params context for the dataplane
|
||||
*/
|
||||
struct dplane_srv6_encap_ctx {
|
||||
struct in6_addr srcaddr;
|
||||
};
|
||||
|
||||
/*
|
||||
* The context block used to exchange info about route updates across
|
||||
* the boundary between the zebra main context (and pthread) and the
|
||||
@ -418,6 +425,7 @@ struct zebra_dplane_ctx {
|
||||
struct dplane_gre_ctx gre;
|
||||
struct dplane_netconf_info netconf;
|
||||
enum zebra_dplane_startup_notifications spot;
|
||||
struct dplane_srv6_encap_ctx srv6_encap;
|
||||
} u;
|
||||
|
||||
/* Namespace info, used especially for netlink kernel communication */
|
||||
@ -599,6 +607,9 @@ static struct zebra_dplane_globals {
|
||||
_Atomic uint32_t dg_tcs_in;
|
||||
_Atomic uint32_t dg_tcs_errors;
|
||||
|
||||
_Atomic uint32_t dg_srv6_encap_srcaddr_set_in;
|
||||
_Atomic uint32_t dg_srv6_encap_srcaddr_set_errors;
|
||||
|
||||
/* Dataplane pthread */
|
||||
struct frr_pthread *dg_pthread;
|
||||
|
||||
@ -861,6 +872,7 @@ static void dplane_ctx_free_internal(struct zebra_dplane_ctx *ctx)
|
||||
case DPLANE_OP_GRE_SET:
|
||||
case DPLANE_OP_INTF_NETCONFIG:
|
||||
case DPLANE_OP_STARTUP_STAGE:
|
||||
case DPLANE_OP_SRV6_ENCAP_SRCADDR_SET:
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1186,6 +1198,11 @@ const char *dplane_op2str(enum dplane_op_e op)
|
||||
break;
|
||||
case DPLANE_OP_STARTUP_STAGE:
|
||||
ret = "STARTUP_STAGE";
|
||||
break;
|
||||
|
||||
case DPLANE_OP_SRV6_ENCAP_SRCADDR_SET:
|
||||
ret = "SRV6_ENCAP_SRCADDR_SET";
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
@ -2599,6 +2616,16 @@ const struct prefix *dplane_ctx_get_intf_addr(
|
||||
return &(ctx->u.intf.prefix);
|
||||
}
|
||||
|
||||
|
||||
/* Accessors for SRv6 encapsulation source address information */
|
||||
const struct in6_addr *
|
||||
dplane_ctx_get_srv6_encap_srcaddr(const struct zebra_dplane_ctx *ctx)
|
||||
{
|
||||
DPLANE_CTX_VALID(ctx);
|
||||
|
||||
return &(ctx->u.srv6_encap.srcaddr);
|
||||
}
|
||||
|
||||
void dplane_ctx_set_intf_addr(struct zebra_dplane_ctx *ctx,
|
||||
const struct prefix *p)
|
||||
{
|
||||
@ -5872,6 +5899,60 @@ done:
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Common helper api for SRv6 encapsulation source address set
|
||||
*/
|
||||
enum zebra_dplane_result
|
||||
dplane_srv6_encap_srcaddr_set(const struct in6_addr *addr, ns_id_t ns_id)
|
||||
{
|
||||
enum zebra_dplane_result result = ZEBRA_DPLANE_REQUEST_FAILURE;
|
||||
struct zebra_dplane_ctx *ctx = NULL;
|
||||
enum dplane_op_e op = DPLANE_OP_SRV6_ENCAP_SRCADDR_SET;
|
||||
int ret;
|
||||
struct zebra_ns *zns;
|
||||
|
||||
if (!addr)
|
||||
return result;
|
||||
|
||||
if (IS_ZEBRA_DEBUG_DPLANE_DETAIL) {
|
||||
zlog_debug("init dplane ctx %s: addr %pI6", dplane_op2str(op),
|
||||
addr);
|
||||
}
|
||||
|
||||
zns = zebra_ns_lookup(ns_id);
|
||||
if (!zns)
|
||||
return result;
|
||||
|
||||
ctx = dplane_ctx_alloc();
|
||||
|
||||
ctx->zd_op = op;
|
||||
ctx->zd_status = ZEBRA_DPLANE_REQUEST_SUCCESS;
|
||||
|
||||
dplane_ctx_ns_init(ctx, zns, false);
|
||||
|
||||
/* Init the SRv6 encap source address specific data area */
|
||||
memcpy(&ctx->u.srv6_encap.srcaddr, addr,
|
||||
sizeof(ctx->u.srv6_encap.srcaddr));
|
||||
|
||||
/* Update counter */
|
||||
atomic_fetch_add_explicit(&zdplane_info.dg_srv6_encap_srcaddr_set_in, 1,
|
||||
memory_order_relaxed);
|
||||
|
||||
/* Enqueue context for processing */
|
||||
ret = dplane_update_enqueue(ctx);
|
||||
|
||||
if (ret == AOK)
|
||||
result = ZEBRA_DPLANE_REQUEST_QUEUED;
|
||||
else {
|
||||
atomic_fetch_add_explicit(&zdplane_info
|
||||
.dg_srv6_encap_srcaddr_set_errors,
|
||||
1, memory_order_relaxed);
|
||||
if (ctx)
|
||||
dplane_ctx_free(&ctx);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Handler for 'show dplane'
|
||||
*/
|
||||
@ -6597,6 +6678,12 @@ static void kernel_dplane_log_detail(struct zebra_dplane_ctx *ctx)
|
||||
case DPLANE_OP_TC_FILTER_UPDATE:
|
||||
case DPLANE_OP_STARTUP_STAGE:
|
||||
break;
|
||||
|
||||
case DPLANE_OP_SRV6_ENCAP_SRCADDR_SET:
|
||||
zlog_debug("Dplane SRv6 encap source address set op %s, addr %pI6",
|
||||
dplane_op2str(dplane_ctx_get_op(ctx)),
|
||||
&ctx->u.srv6_encap.srcaddr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -6767,6 +6854,13 @@ static void kernel_dplane_handle_result(struct zebra_dplane_ctx *ctx)
|
||||
case DPLANE_OP_INTF_NETCONFIG:
|
||||
break;
|
||||
|
||||
case DPLANE_OP_SRV6_ENCAP_SRCADDR_SET:
|
||||
if (res != ZEBRA_DPLANE_REQUEST_SUCCESS)
|
||||
atomic_fetch_add_explicit(&zdplane_info
|
||||
.dg_srv6_encap_srcaddr_set_errors,
|
||||
1, memory_order_relaxed);
|
||||
break;
|
||||
|
||||
case DPLANE_OP_NONE:
|
||||
case DPLANE_OP_STARTUP_STAGE:
|
||||
if (res != ZEBRA_DPLANE_REQUEST_SUCCESS)
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "zebra/zserv.h"
|
||||
#include "zebra/zebra_mpls.h"
|
||||
#include "zebra/zebra_nhg.h"
|
||||
#include "zebra/ge_netlink.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@ -198,6 +199,9 @@ enum dplane_op_e {
|
||||
|
||||
/* Startup Control */
|
||||
DPLANE_OP_STARTUP_STAGE,
|
||||
|
||||
/* Source address for SRv6 encapsulation */
|
||||
DPLANE_OP_SRV6_ENCAP_SRCADDR_SET,
|
||||
};
|
||||
|
||||
/*
|
||||
@ -664,6 +668,8 @@ bool dplane_ctx_intf_is_broadcast(const struct zebra_dplane_ctx *ctx);
|
||||
void dplane_ctx_intf_set_broadcast(struct zebra_dplane_ctx *ctx);
|
||||
const struct prefix *dplane_ctx_get_intf_addr(
|
||||
const struct zebra_dplane_ctx *ctx);
|
||||
const struct in6_addr *
|
||||
dplane_ctx_get_srv6_encap_srcaddr(const struct zebra_dplane_ctx *ctx);
|
||||
void dplane_ctx_set_intf_addr(struct zebra_dplane_ctx *ctx,
|
||||
const struct prefix *p);
|
||||
bool dplane_ctx_intf_has_dest(const struct zebra_dplane_ctx *ctx);
|
||||
@ -992,6 +998,13 @@ enum zebra_dplane_result
|
||||
dplane_gre_set(struct interface *ifp, struct interface *ifp_link,
|
||||
unsigned int mtu, const struct zebra_l2info_gre *gre_info);
|
||||
|
||||
/*
|
||||
* Enqueue an SRv6 encap source address set
|
||||
*/
|
||||
enum zebra_dplane_result
|
||||
dplane_srv6_encap_srcaddr_set(const struct in6_addr *addr, ns_id_t ns_id);
|
||||
|
||||
|
||||
/* Forward ref of zebra_pbr_rule */
|
||||
struct zebra_pbr_rule;
|
||||
|
||||
|
@ -4961,6 +4961,7 @@ static void rib_process_dplane_results(struct event *thread)
|
||||
case DPLANE_OP_BR_PORT_UPDATE:
|
||||
case DPLANE_OP_NEIGH_TABLE_UPDATE:
|
||||
case DPLANE_OP_GRE_SET:
|
||||
case DPLANE_OP_SRV6_ENCAP_SRCADDR_SET:
|
||||
case DPLANE_OP_NONE:
|
||||
break;
|
||||
case DPLANE_OP_STARTUP_STAGE:
|
||||
|
@ -415,6 +415,7 @@ void lua_pushzebra_dplane_ctx(lua_State *L, const struct zebra_dplane_ctx *ctx)
|
||||
case DPLANE_OP_TC_FILTER_UPDATE:
|
||||
/* Not currently handled */
|
||||
case DPLANE_OP_INTF_NETCONFIG: /*NYI*/
|
||||
case DPLANE_OP_SRV6_ENCAP_SRCADDR_SET:
|
||||
case DPLANE_OP_NONE:
|
||||
case DPLANE_OP_STARTUP_STAGE:
|
||||
break;
|
||||
|
Loading…
Reference in New Issue
Block a user