Skip to content

Commit

Permalink
zebra: Extend FPM to send missing seg6local info
Browse files Browse the repository at this point in the history
Zebra’s `dplane_fpm_nl` module allows an external component to learn the
forwarding information computed by the FRR routing suite. Currently, the
SRv6 Local SIDs exported by the `dplane_fpm_nl` module do not include
some information such the SID format (i.e., locator block length,
locator node length, function length, and argument length).

This commit adds the missing information to the SRv6 Local SIDs exported
by the `dplane_fpm_nl`.

Signed-off-by: Carmine Scarpitta <[email protected]>
  • Loading branch information
cscarpitta committed Jun 8, 2023
1 parent 2fbdf88 commit b1dea24
Show file tree
Hide file tree
Showing 2 changed files with 282 additions and 0 deletions.
49 changes: 49 additions & 0 deletions lib/nexthop.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ enum blackhole_type {
enum nh_encap_type {
NET_VXLAN = 100, /* value copied from FPM_NH_ENCAP_VXLAN. */
FPM_NH_ENCAP_SRV6_ROUTE = 101,
FPM_NH_ENCAP_SRV6_LOCAL_SID = 102,
};

enum {
Expand All @@ -52,6 +53,54 @@ enum {
SRV6_ROUTE_ENCAP_SRC_ADDR = 2,
};

enum srv6_localsid_action {
FPM_SRV6_LOCALSID_ACTION_UNSPEC = 0,
FPM_SRV6_LOCALSID_ACTION_END = 1,
FPM_SRV6_LOCALSID_ACTION_END_X = 2,
FPM_SRV6_LOCALSID_ACTION_END_T = 3,
FPM_SRV6_LOCALSID_ACTION_END_DX2 = 4,
FPM_SRV6_LOCALSID_ACTION_END_DX6 = 5,
FPM_SRV6_LOCALSID_ACTION_END_DX4 = 6,
FPM_SRV6_LOCALSID_ACTION_END_DT6 = 7,
FPM_SRV6_LOCALSID_ACTION_END_DT4 = 8,
FPM_SRV6_LOCALSID_ACTION_END_B6 = 9,
FPM_SRV6_LOCALSID_ACTION_END_B6_ENCAP = 10,
FPM_SRV6_LOCALSID_ACTION_END_BM = 11,
FPM_SRV6_LOCALSID_ACTION_END_S = 12,
FPM_SRV6_LOCALSID_ACTION_END_AS = 13,
FPM_SRV6_LOCALSID_ACTION_END_AM = 14,
FPM_SRV6_LOCALSID_ACTION_END_BPF = 15,
FPM_SRV6_LOCALSID_ACTION_END_DT46 = 16,
FPM_SRV6_LOCALSID_ACTION_UDT4 = 100,
FPM_SRV6_LOCALSID_ACTION_UDT6 = 101,
FPM_SRV6_LOCALSID_ACTION_UDT46 = 102,
FPM_SRV6_LOCALSID_ACTION_MAX,
};

enum {
FPM_SRV6_LOCALSID_UNSPEC = 0,
FPM_SRV6_LOCALSID_ACTION = 1,
FPM_SRV6_LOCALSID_SRH = 2,
FPM_SRV6_LOCALSID_TABLE = 3,
FPM_SRV6_LOCALSID_NH4 = 4,
FPM_SRV6_LOCALSID_NH6 = 5,
FPM_SRV6_LOCALSID_IIF = 6,
FPM_SRV6_LOCALSID_OIF = 7,
FPM_SRV6_LOCALSID_BPF = 8,
FPM_SRV6_LOCALSID_VRFTABLE = 9,
FPM_SRV6_LOCALSID_COUNTERS = 10,
FPM_SRV6_LOCALSID_VRFNAME = 100,
FPM_SRV6_LOCALSID_FORMAT = 101,
};

enum {
FPM_SRV6_LOCALSID_FORMAT_UNSPEC = 0,
FPM_SRV6_LOCALSID_FORMAT_BLOCK_LEN = 1,
FPM_SRV6_LOCALSID_FORMAT_NODE_LEN = 2,
FPM_SRV6_LOCALSID_FORMAT_FUNC_LEN = 3,
FPM_SRV6_LOCALSID_FORMAT_ARG_LEN = 4,
};

/* Fixed limit on the number of backup nexthops per primary nexthop */
#define NEXTHOP_MAX_BACKUPS 8

Expand Down
233 changes: 233 additions & 0 deletions zebra/rt_netlink.c
Original file line number Diff line number Diff line change
Expand Up @@ -407,6 +407,29 @@ vrf_id_t vrf_lookup_by_table(uint32_t table_id, ns_id_t ns_id)
return VRF_DEFAULT;
}

static struct zebra_vrf *vrf_lookup_by_table_id(uint32_t table_id)
{
struct vrf *vrf;
struct zebra_vrf *zvrf;

RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) {
zvrf = vrf->info;
if (zvrf == NULL)
continue;
/* case vrf with netns : match the netnsid */
if (vrf_is_backend_netns()) {
return NULL;
} else {
/* VRF is VRF_BACKEND_VRF_LITE */
if (zvrf->table_id != table_id)
continue;
return zvrf;
}
}

return NULL;
}

/**
* @parse_encap_mpls() - Parses encapsulated mpls attributes
* @tb: Pointer to rtattr to look for nested items in.
Expand Down Expand Up @@ -1675,6 +1698,216 @@ static bool _netlink_route_build_singlepath(const struct prefix *p,
}

if (fpm && nexthop->nh_srv6) {
if (nexthop->nh_srv6->seg6local_action !=
ZEBRA_SEG6_LOCAL_ACTION_UNSPEC) {
struct zebra_srv6 *srv6 = zebra_srv6_get_default();
struct zebra_vrf *zvrf;
bool locator_found = false;
struct srv6_locator *locator;
struct listnode *node;
struct rtattr *nest, *inner_nest;
const struct seg6local_context *ctx;

ctx = &nexthop->nh_srv6->seg6local_ctx;

if (!nl_attr_put16(nlmsg, req_size, RTA_ENCAP_TYPE,
FPM_NH_ENCAP_SRV6_LOCAL_SID))
return false;

for (ALL_LIST_ELEMENTS_RO(srv6->locators, node,
locator)) {
if (prefix_match(&locator->prefix, p)) {
locator_found = true;
break;
}
}

nest = nl_attr_nest(nlmsg, req_size, RTA_ENCAP);

/* Process Local SID format */
if (locator_found) {
inner_nest =
nl_attr_nest(nlmsg, req_size,
FPM_SRV6_LOCALSID_FORMAT);

if (locator->block_bits_length)
if (!nl_attr_put8(
nlmsg, req_size,
FPM_SRV6_LOCALSID_FORMAT_BLOCK_LEN,
locator->block_bits_length))
return false;

if (locator->node_bits_length)
if (!nl_attr_put8(
nlmsg, req_size,
FPM_SRV6_LOCALSID_FORMAT_NODE_LEN,
locator->node_bits_length))
return false;

if (locator->function_bits_length)
if (!nl_attr_put8(
nlmsg, req_size,
FPM_SRV6_LOCALSID_FORMAT_FUNC_LEN,
locator->function_bits_length))
return false;

if (locator->argument_bits_length)
if (!nl_attr_put8(
nlmsg, req_size,
FPM_SRV6_LOCALSID_FORMAT_ARG_LEN,
locator->argument_bits_length))
return false;

nl_attr_nest_end(nlmsg, inner_nest);
}

switch (nexthop->nh_srv6->seg6local_action) {
case ZEBRA_SEG6_LOCAL_ACTION_END:
if (!nl_attr_put32(
nlmsg, req_size,
FPM_SRV6_LOCALSID_ACTION,
FPM_SRV6_LOCALSID_ACTION_END))
return false;

break;
case ZEBRA_SEG6_LOCAL_ACTION_END_X:
if (!nl_attr_put32(
nlmsg, req_size,
FPM_SRV6_LOCALSID_ACTION,
FPM_SRV6_LOCALSID_ACTION_END_X))
return false;

if (!nl_attr_put(nlmsg, req_size,
FPM_SRV6_LOCALSID_NH6,
&ctx->nh6,
sizeof(struct in6_addr)))
return false;
break;
case ZEBRA_SEG6_LOCAL_ACTION_END_T:
zvrf = vrf_lookup_by_table_id(ctx->table);
if (!zvrf)
return false;

if (!nl_attr_put32(
nlmsg, req_size,
FPM_SRV6_LOCALSID_ACTION,
FPM_SRV6_LOCALSID_ACTION_END_T))
return false;

if (!nl_attr_put(nlmsg, req_size,
FPM_SRV6_LOCALSID_VRFNAME,
zvrf->vrf->name,
strlen(zvrf->vrf->name) + 1))
return false;

break;
case ZEBRA_SEG6_LOCAL_ACTION_END_DX4:
if (!nl_attr_put32(
nlmsg, req_size,
FPM_SRV6_LOCALSID_ACTION,
FPM_SRV6_LOCALSID_ACTION_END_DX4))
return false;

if (!nl_attr_put(nlmsg, req_size,
FPM_SRV6_LOCALSID_NH4,
&ctx->nh4,
sizeof(struct in_addr)))
return false;

break;
case ZEBRA_SEG6_LOCAL_ACTION_END_DT6:
zvrf = vrf_lookup_by_table_id(ctx->table);
if (!zvrf)
return false;

if (locator_found &&
CHECK_FLAG(locator->flags,
SRV6_LOCATOR_USID)) {
if (!nl_attr_put32(
nlmsg, req_size,
FPM_SRV6_LOCALSID_ACTION,
FPM_SRV6_LOCALSID_ACTION_UDT6))
return false;
} else {
if (!nl_attr_put32(
nlmsg, req_size,
FPM_SRV6_LOCALSID_ACTION,
FPM_SRV6_LOCALSID_ACTION_END_DT6))
return false;
}

if (!nl_attr_put(nlmsg, req_size,
FPM_SRV6_LOCALSID_VRFNAME,
zvrf->vrf->name,
strlen(zvrf->vrf->name) + 1))
return false;

break;
case ZEBRA_SEG6_LOCAL_ACTION_END_DT4:
zvrf = vrf_lookup_by_table_id(ctx->table);
if (!zvrf)
return false;

if (locator_found &&
CHECK_FLAG(locator->flags,
SRV6_LOCATOR_USID)) {
if (!nl_attr_put32(
nlmsg, req_size,
FPM_SRV6_LOCALSID_ACTION,
FPM_SRV6_LOCALSID_ACTION_UDT4))
return false;
} else {
if (!nl_attr_put32(
nlmsg, req_size,
FPM_SRV6_LOCALSID_ACTION,
FPM_SRV6_LOCALSID_ACTION_END_DT4))
return false;
}

if (!nl_attr_put(nlmsg, req_size,
FPM_SRV6_LOCALSID_VRFNAME,
zvrf->vrf->name,
strlen(zvrf->vrf->name) + 1))
return false;

break;
case ZEBRA_SEG6_LOCAL_ACTION_END_DT46:
zvrf = vrf_lookup_by_table_id(ctx->table);
if (!zvrf)
return false;

if (locator_found &&
CHECK_FLAG(locator->flags,
SRV6_LOCATOR_USID)) {
if (!nl_attr_put32(
nlmsg, req_size,
FPM_SRV6_LOCALSID_ACTION,
FPM_SRV6_LOCALSID_ACTION_UDT46))
return false;
} else {
if (!nl_attr_put32(
nlmsg, req_size,
FPM_SRV6_LOCALSID_ACTION,
FPM_SRV6_LOCALSID_ACTION_END_DT46))
return false;
}

if (!nl_attr_put(nlmsg, req_size,
FPM_SRV6_LOCALSID_VRFNAME,
zvrf->vrf->name,
strlen(zvrf->vrf->name) + 1))
return false;

break;
default:
zlog_err(
"Unsupported seg6local behaviour action=%u",
nexthop->nh_srv6->seg6local_action);
return false;
}
nl_attr_nest_end(nlmsg, nest);
}

if (!sid_zero(&nexthop->nh_srv6->seg6_segs)) {
struct zebra_srv6 *srv6 = zebra_srv6_get_default();
struct rtattr *nest;
Expand Down

0 comments on commit b1dea24

Please sign in to comment.