zebra: support route replace semantics in FPM

Set `NLM_F_REPLACE` instead of adding and removing the same route for an
update.

Signed-off-by: Rafael Zalamena <rzalamena@opensourcerouting.org>
This commit is contained in:
Rafael Zalamena 2023-07-26 17:30:07 -03:00
parent ff542b22d2
commit 6374aeab80
3 changed files with 53 additions and 12 deletions

View File

@ -65,6 +65,7 @@ struct fpm_nl_ctx {
bool disabled; bool disabled;
bool connecting; bool connecting;
bool use_nhg; bool use_nhg;
bool use_route_replace;
struct sockaddr_storage addr; struct sockaddr_storage addr;
/* data plane buffers. */ /* data plane buffers. */
@ -282,6 +283,25 @@ DEFUN(no_fpm_use_nhg, no_fpm_use_nhg_cmd,
return CMD_SUCCESS; return CMD_SUCCESS;
} }
DEFUN(fpm_use_route_replace, fpm_use_route_replace_cmd,
"fpm use-route-replace",
FPM_STR
"Use netlink route replace semantics\n")
{
gfnc->use_route_replace = true;
return CMD_SUCCESS;
}
DEFUN(no_fpm_use_route_replace, no_fpm_use_route_replace_cmd,
"no fpm use-route-replace",
NO_STR
FPM_STR
"Use netlink route replace semantics\n")
{
gfnc->use_route_replace = false;
return CMD_SUCCESS;
}
DEFUN(fpm_reset_counters, fpm_reset_counters_cmd, DEFUN(fpm_reset_counters, fpm_reset_counters_cmd,
"clear fpm counters", "clear fpm counters",
CLEAR_STR CLEAR_STR
@ -396,6 +416,11 @@ static int fpm_write_config(struct vty *vty)
written = 1; written = 1;
} }
if (!gfnc->use_route_replace) {
vty_out(vty, "no fpm use-route-replace\n");
written = 1;
}
return written; return written;
} }
@ -807,12 +832,20 @@ static int fpm_nl_enqueue(struct fpm_nl_ctx *fnc, struct zebra_dplane_ctx *ctx)
frr_mutex_lock_autounlock(&fnc->obuf_mutex); frr_mutex_lock_autounlock(&fnc->obuf_mutex);
/*
* If route replace is enabled then directly encode the install which
* is going to use `NLM_F_REPLACE` (instead of delete/add operations).
*/
if (fnc->use_route_replace && op == DPLANE_OP_ROUTE_UPDATE)
op = DPLANE_OP_ROUTE_INSTALL;
switch (op) { switch (op) {
case DPLANE_OP_ROUTE_UPDATE: case DPLANE_OP_ROUTE_UPDATE:
case DPLANE_OP_ROUTE_DELETE: case DPLANE_OP_ROUTE_DELETE:
rv = netlink_route_multipath_msg_encode(RTM_DELROUTE, ctx, rv = netlink_route_multipath_msg_encode(RTM_DELROUTE, ctx,
nl_buf, sizeof(nl_buf), nl_buf, sizeof(nl_buf),
true, fnc->use_nhg); true, fnc->use_nhg,
false);
if (rv <= 0) { if (rv <= 0) {
zlog_err( zlog_err(
"%s: netlink_route_multipath_msg_encode failed", "%s: netlink_route_multipath_msg_encode failed",
@ -828,9 +861,12 @@ static int fpm_nl_enqueue(struct fpm_nl_ctx *fnc, struct zebra_dplane_ctx *ctx)
/* FALL THROUGH */ /* FALL THROUGH */
case DPLANE_OP_ROUTE_INSTALL: case DPLANE_OP_ROUTE_INSTALL:
rv = netlink_route_multipath_msg_encode( rv = netlink_route_multipath_msg_encode(RTM_NEWROUTE, ctx,
RTM_NEWROUTE, ctx, &nl_buf[nl_buf_len], &nl_buf[nl_buf_len],
sizeof(nl_buf) - nl_buf_len, true, fnc->use_nhg); sizeof(nl_buf) -
nl_buf_len,
true, fnc->use_nhg,
fnc->use_route_replace);
if (rv <= 0) { if (rv <= 0) {
zlog_err( zlog_err(
"%s: netlink_route_multipath_msg_encode failed", "%s: netlink_route_multipath_msg_encode failed",
@ -1469,6 +1505,7 @@ static int fpm_nl_start(struct zebra_dplane_provider *prov)
/* Set default values. */ /* Set default values. */
fnc->use_nhg = true; fnc->use_nhg = true;
fnc->use_route_replace = true;
return 0; return 0;
} }
@ -1609,6 +1646,8 @@ static int fpm_nl_new(struct event_loop *tm)
install_element(CONFIG_NODE, &no_fpm_set_address_cmd); install_element(CONFIG_NODE, &no_fpm_set_address_cmd);
install_element(CONFIG_NODE, &fpm_use_nhg_cmd); install_element(CONFIG_NODE, &fpm_use_nhg_cmd);
install_element(CONFIG_NODE, &no_fpm_use_nhg_cmd); install_element(CONFIG_NODE, &no_fpm_use_nhg_cmd);
install_element(CONFIG_NODE, &fpm_use_route_replace_cmd);
install_element(CONFIG_NODE, &no_fpm_use_route_replace_cmd);
return 0; return 0;
} }

View File

@ -2060,10 +2060,10 @@ static int netlink_route_nexthop_encap(struct nlmsghdr *n, size_t nlen,
* Returns -1 on failure, 0 when the msg doesn't fit entirely in the buffer * Returns -1 on failure, 0 when the msg doesn't fit entirely in the buffer
* otherwise the number of bytes written to buf. * otherwise the number of bytes written to buf.
*/ */
ssize_t netlink_route_multipath_msg_encode(int cmd, ssize_t netlink_route_multipath_msg_encode(int cmd, struct zebra_dplane_ctx *ctx,
struct zebra_dplane_ctx *ctx,
uint8_t *data, size_t datalen, uint8_t *data, size_t datalen,
bool fpm, bool force_nhg) bool fpm, bool force_nhg,
bool force_rr)
{ {
int bytelen; int bytelen;
struct nexthop *nexthop = NULL; struct nexthop *nexthop = NULL;
@ -2097,8 +2097,9 @@ ssize_t netlink_route_multipath_msg_encode(int cmd,
req->n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); req->n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
req->n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST; req->n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST;
if ((cmd == RTM_NEWROUTE) && if (((cmd == RTM_NEWROUTE) &&
((p->family == AF_INET) || v6_rr_semantics)) ((p->family == AF_INET) || v6_rr_semantics)) ||
force_rr)
req->n.nlmsg_flags |= NLM_F_REPLACE; req->n.nlmsg_flags |= NLM_F_REPLACE;
req->n.nlmsg_type = cmd; req->n.nlmsg_type = cmd;
@ -2953,14 +2954,14 @@ static ssize_t netlink_newroute_msg_encoder(struct zebra_dplane_ctx *ctx,
void *buf, size_t buflen) void *buf, size_t buflen)
{ {
return netlink_route_multipath_msg_encode(RTM_NEWROUTE, ctx, buf, return netlink_route_multipath_msg_encode(RTM_NEWROUTE, ctx, buf,
buflen, false, false); buflen, false, false, false);
} }
static ssize_t netlink_delroute_msg_encoder(struct zebra_dplane_ctx *ctx, static ssize_t netlink_delroute_msg_encoder(struct zebra_dplane_ctx *ctx,
void *buf, size_t buflen) void *buf, size_t buflen)
{ {
return netlink_route_multipath_msg_encode(RTM_DELROUTE, ctx, buf, return netlink_route_multipath_msg_encode(RTM_DELROUTE, ctx, buf,
buflen, false, false); buflen, false, false, false);
} }
enum netlink_msg_status enum netlink_msg_status

View File

@ -56,7 +56,8 @@ extern ssize_t netlink_mpls_multipath_msg_encode(int cmd,
extern ssize_t netlink_route_multipath_msg_encode(int cmd, extern ssize_t netlink_route_multipath_msg_encode(int cmd,
struct zebra_dplane_ctx *ctx, struct zebra_dplane_ctx *ctx,
uint8_t *data, size_t datalen, uint8_t *data, size_t datalen,
bool fpm, bool force_nhg); bool fpm, bool force_nhg,
bool force_rr);
extern ssize_t netlink_macfdb_update_ctx(struct zebra_dplane_ctx *ctx, extern ssize_t netlink_macfdb_update_ctx(struct zebra_dplane_ctx *ctx,
void *data, size_t datalen); void *data, size_t datalen);