mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-04 06:55:18 +00:00
zebra: new dplane action to set gre link interface
This action is initiated by nhrp and has been stubbed when moving to zebra. Now, a netlink request is forged to set the link interface of a gre interface if that gre interface does not have already a link interface. Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
This commit is contained in:
parent
372b887859
commit
62b4b7e44a
@ -463,6 +463,46 @@ uint32_t kernel_get_speed(struct interface *ifp, int *error)
|
||||
return get_iflink_speed(ifp, error);
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
netlink_gre_set_msg_encoder(struct zebra_dplane_ctx *ctx, void *buf,
|
||||
size_t buflen)
|
||||
{
|
||||
struct {
|
||||
struct nlmsghdr n;
|
||||
struct ifinfomsg ifi;
|
||||
char buf[];
|
||||
} *req = buf;
|
||||
uint32_t link_idx;
|
||||
struct rtattr *rta_info, *rta_data;
|
||||
|
||||
if (buflen < sizeof(*req))
|
||||
return 0;
|
||||
memset(req, 0, sizeof(*req));
|
||||
|
||||
req->n.nlmsg_type = RTM_NEWLINK;
|
||||
req->n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
|
||||
req->n.nlmsg_flags = NLM_F_REQUEST;
|
||||
|
||||
req->ifi.ifi_index = dplane_ctx_get_ifindex(ctx);
|
||||
req->ifi.ifi_change = 0xFFFFFFFF;
|
||||
link_idx = dplane_ctx_gre_get_link_ifindex(ctx);
|
||||
|
||||
rta_info = nl_attr_nest(&req->n, buflen, IFLA_LINKINFO);
|
||||
if (!rta_info)
|
||||
return 0;
|
||||
if (!nl_attr_put(&req->n, buflen, IFLA_INFO_KIND, "gre", 3))
|
||||
return 0;
|
||||
rta_data = nl_attr_nest(&req->n, buflen, IFLA_INFO_DATA);
|
||||
if (!rta_info)
|
||||
return 0;
|
||||
if (!nl_attr_put32(&req->n, buflen, IFLA_GRE_LINK, link_idx))
|
||||
return 0;
|
||||
nl_attr_nest_end(&req->n, rta_data);
|
||||
nl_attr_nest_end(&req->n, rta_info);
|
||||
|
||||
return NLMSG_ALIGN(req->n.nlmsg_len);
|
||||
}
|
||||
|
||||
static int netlink_extract_bridge_info(struct rtattr *link_data,
|
||||
struct zebra_l2info_bridge *bridge_info)
|
||||
{
|
||||
@ -524,9 +564,13 @@ static int netlink_extract_gre_info(struct rtattr *link_data,
|
||||
if (!attr[IFLA_GRE_LINK]) {
|
||||
if (IS_ZEBRA_DEBUG_KERNEL)
|
||||
zlog_debug("IFLA_GRE_LINK missing from GRE IF message");
|
||||
} else
|
||||
} else {
|
||||
gre_info->ifindex_link =
|
||||
*(ifindex_t *)RTA_DATA(attr[IFLA_GRE_LINK]);
|
||||
if (IS_ZEBRA_DEBUG_KERNEL)
|
||||
zlog_debug("IFLA_GRE_LINK obtained is %u",
|
||||
gre_info->ifindex_link);
|
||||
}
|
||||
if (attr[IFLA_GRE_IKEY])
|
||||
gre_info->ikey = *(uint32_t *)RTA_DATA(attr[IFLA_GRE_IKEY]);
|
||||
if (attr[IFLA_GRE_OKEY])
|
||||
@ -986,6 +1030,20 @@ static int netlink_request_intf_addr(struct nlsock *netlink_cmd, int family,
|
||||
return netlink_request(netlink_cmd, &req);
|
||||
}
|
||||
|
||||
enum netlink_msg_status
|
||||
netlink_put_gre_set_msg(struct nl_batch *bth, struct zebra_dplane_ctx *ctx)
|
||||
{
|
||||
enum dplane_op_e op;
|
||||
enum netlink_msg_status ret;
|
||||
|
||||
op = dplane_ctx_get_op(ctx);
|
||||
assert(op == DPLANE_OP_GRE_SET);
|
||||
|
||||
ret = netlink_batch_add_msg(bth, ctx, netlink_gre_set_msg_encoder, false);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Interface lookup by netlink socket. */
|
||||
int interface_lookup_netlink(struct zebra_ns *zns)
|
||||
{
|
||||
|
@ -32,6 +32,9 @@ extern int netlink_interface_addr(struct nlmsghdr *h, ns_id_t ns_id,
|
||||
extern int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup);
|
||||
extern int interface_lookup_netlink(struct zebra_ns *zns);
|
||||
|
||||
extern enum netlink_msg_status
|
||||
netlink_put_gre_set_msg(struct nl_batch *bth, struct zebra_dplane_ctx *ctx);
|
||||
|
||||
extern enum netlink_msg_status
|
||||
netlink_put_address_update_msg(struct nl_batch *bth,
|
||||
struct zebra_dplane_ctx *ctx);
|
||||
|
@ -1360,6 +1360,9 @@ static enum netlink_msg_status nl_put_msg(struct nl_batch *bth,
|
||||
case DPLANE_OP_IPSET_ENTRY_DELETE:
|
||||
return FRR_NETLINK_ERROR;
|
||||
|
||||
case DPLANE_OP_GRE_SET:
|
||||
return netlink_put_gre_set_msg(bth, ctx);
|
||||
|
||||
case DPLANE_OP_NONE:
|
||||
return FRR_NETLINK_ERROR;
|
||||
}
|
||||
|
@ -81,9 +81,6 @@ extern int mpls_kernel_init(void);
|
||||
extern uint32_t kernel_get_speed(struct interface *ifp, int *error);
|
||||
extern int kernel_get_ipmr_sg_stats(struct zebra_vrf *zvrf, void *mroute);
|
||||
|
||||
extern int kernel_configure_if_link(struct interface *ifp,
|
||||
struct interface *link_ifp, ns_id_t ns_id);
|
||||
|
||||
/*
|
||||
* Southbound Initialization routines to get initial starting
|
||||
* state.
|
||||
|
@ -3890,14 +3890,6 @@ netlink_put_neigh_update_msg(struct nl_batch *bth, struct zebra_dplane_ctx *ctx)
|
||||
false);
|
||||
}
|
||||
|
||||
int kernel_configure_if_link(struct interface *ifp,
|
||||
struct interface *link_ifp,
|
||||
ns_id_t ns_id)
|
||||
{
|
||||
/* TODO */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* MPLS label forwarding table change via netlink interface, using dataplane
|
||||
* context information.
|
||||
|
@ -394,12 +394,6 @@ enum zebra_dplane_result kernel_mac_update_ctx(struct zebra_dplane_ctx *ctx)
|
||||
return ZEBRA_DPLANE_REQUEST_SUCCESS;
|
||||
}
|
||||
|
||||
int kernel_configure_if_link(struct interface *ifp, struct interface *link_ifp,
|
||||
ns_id_t ns_id)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern int kernel_interface_set_master(struct interface *master,
|
||||
struct interface *slave)
|
||||
{
|
||||
|
@ -3435,22 +3435,40 @@ static inline void zebra_gre_source_set(ZAPI_HANDLER_ARGS)
|
||||
vrf_id_t link_vrf_id;
|
||||
struct interface *ifp;
|
||||
struct interface *ifp_link;
|
||||
ns_id_t ns_id;
|
||||
vrf_id_t vrf_id = zvrf->vrf->vrf_id;
|
||||
struct zebra_if *zif, *gre_zif;
|
||||
struct zebra_l2info_gre *gre_info;
|
||||
|
||||
s = msg;
|
||||
STREAM_GETL(s, idx);
|
||||
ifp = if_lookup_by_index(idx, vrf_id);
|
||||
STREAM_GETL(s, link_idx);
|
||||
STREAM_GETL(s, link_vrf_id);
|
||||
|
||||
ifp_link = if_lookup_by_index(link_idx, link_vrf_id);
|
||||
if (!ifp_link || !ifp) {
|
||||
zlog_warn("GRE (index %u, VRF %u) or GRE link interface (index %u, VRF %u) not found, when setting GRE params",
|
||||
idx, vrf_id, link_idx, link_vrf_id);
|
||||
return;
|
||||
}
|
||||
ns_id = zvrf->zns->ns_id;
|
||||
kernel_configure_if_link(ifp, ifp_link, ns_id);
|
||||
|
||||
if (!IS_ZEBRA_IF_GRE(ifp))
|
||||
return;
|
||||
|
||||
gre_zif = (struct zebra_if *)ifp->info;
|
||||
zif = (struct zebra_if *)ifp_link->info;
|
||||
if (!zif || !gre_zif)
|
||||
return;
|
||||
|
||||
gre_info = &zif->l2info.gre;
|
||||
if (!gre_info)
|
||||
return;
|
||||
|
||||
/* if gre link already set */
|
||||
if (gre_zif->link && gre_zif->link == ifp_link)
|
||||
return;
|
||||
|
||||
dplane_gre_set(ifp, ifp_link);
|
||||
|
||||
stream_failure:
|
||||
return;
|
||||
|
@ -271,6 +271,9 @@ struct dplane_rule_info {
|
||||
struct dplane_ctx_rule old;
|
||||
};
|
||||
|
||||
struct dplane_gre_ctx {
|
||||
uint32_t link_ifindex;
|
||||
};
|
||||
/*
|
||||
* The context block used to exchange info about route updates across
|
||||
* the boundary between the zebra main context (and pthread) and the
|
||||
@ -327,6 +330,7 @@ struct zebra_dplane_ctx {
|
||||
struct zebra_pbr_ipset_info info;
|
||||
} ipset_entry;
|
||||
struct dplane_neigh_table neightable;
|
||||
struct dplane_gre_ctx gre;
|
||||
} u;
|
||||
|
||||
/* Namespace info, used especially for netlink kernel communication */
|
||||
@ -469,6 +473,9 @@ static struct zebra_dplane_globals {
|
||||
_Atomic uint32_t dg_neightable_in;
|
||||
_Atomic uint32_t dg_neightable_errors;
|
||||
|
||||
_Atomic uint32_t dg_gre_set_in;
|
||||
_Atomic uint32_t dg_gre_set_errors;
|
||||
|
||||
/* Dataplane pthread */
|
||||
struct frr_pthread *dg_pthread;
|
||||
|
||||
@ -713,6 +720,9 @@ static void dplane_ctx_free_internal(struct zebra_dplane_ctx *ctx)
|
||||
}
|
||||
list_delete(&ctx->u.iptable.interface_name_list);
|
||||
}
|
||||
break;
|
||||
case DPLANE_OP_GRE_SET:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -979,6 +989,10 @@ const char *dplane_op2str(enum dplane_op_e op)
|
||||
case DPLANE_OP_NEIGH_TABLE_UPDATE:
|
||||
ret = "NEIGH_TABLE_UPDATE";
|
||||
break;
|
||||
|
||||
case DPLANE_OP_GRE_SET:
|
||||
ret = "GRE_SET";
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
@ -1772,6 +1786,15 @@ uint32_t dplane_ctx_neigh_get_update_flags(const struct zebra_dplane_ctx *ctx)
|
||||
return ctx->u.neigh.update_flags;
|
||||
}
|
||||
|
||||
/* Accessor for GRE set */
|
||||
uint32_t
|
||||
dplane_ctx_gre_get_link_ifindex(const struct zebra_dplane_ctx *ctx)
|
||||
{
|
||||
DPLANE_CTX_VALID(ctx);
|
||||
|
||||
return ctx->u.gre.link_ifindex;
|
||||
}
|
||||
|
||||
/* Accessors for PBR rule information */
|
||||
int dplane_ctx_rule_get_sock(const struct zebra_dplane_ctx *ctx)
|
||||
{
|
||||
@ -4125,6 +4148,67 @@ dplane_pbr_ipset_entry_delete(struct zebra_pbr_ipset_entry *ipset)
|
||||
return ipset_entry_update_internal(DPLANE_OP_IPSET_ENTRY_DELETE, ipset);
|
||||
}
|
||||
|
||||
/*
|
||||
* Common helper api for GRE set
|
||||
*/
|
||||
enum zebra_dplane_result
|
||||
dplane_gre_set(struct interface *ifp, struct interface *ifp_link)
|
||||
{
|
||||
enum zebra_dplane_result result = ZEBRA_DPLANE_REQUEST_FAILURE;
|
||||
struct zebra_dplane_ctx *ctx;
|
||||
enum dplane_op_e op = DPLANE_OP_GRE_SET;
|
||||
int ret;
|
||||
struct zebra_ns *zns;
|
||||
|
||||
ctx = dplane_ctx_alloc();
|
||||
|
||||
if (!ifp)
|
||||
return result;
|
||||
|
||||
if (IS_ZEBRA_DEBUG_DPLANE_DETAIL) {
|
||||
zlog_debug("init dplane ctx %s: if %s link %s%s",
|
||||
dplane_op2str(op), ifp->name,
|
||||
ifp_link ? "set" : "unset", ifp_link ?
|
||||
ifp_link->name : "");
|
||||
}
|
||||
|
||||
ctx->zd_op = op;
|
||||
ctx->zd_status = ZEBRA_DPLANE_REQUEST_SUCCESS;
|
||||
zns = zebra_ns_lookup(ifp->vrf_id);
|
||||
if (!zns)
|
||||
return result;
|
||||
dplane_ctx_ns_init(ctx, zns, false);
|
||||
|
||||
dplane_ctx_set_ifname(ctx, ifp->name);
|
||||
ctx->zd_vrf_id = ifp->vrf_id;
|
||||
ctx->zd_ifindex = ifp->ifindex;
|
||||
if (ifp_link)
|
||||
ctx->u.gre.link_ifindex = ifp_link->ifindex;
|
||||
else
|
||||
ctx->u.gre.link_ifindex = 0;
|
||||
|
||||
ctx->zd_status = ZEBRA_DPLANE_REQUEST_SUCCESS;
|
||||
|
||||
/* Enqueue context for processing */
|
||||
ret = dplane_update_enqueue(ctx);
|
||||
|
||||
/* Update counter */
|
||||
atomic_fetch_add_explicit(&zdplane_info.dg_gre_set_in, 1,
|
||||
memory_order_relaxed);
|
||||
|
||||
if (ret == AOK)
|
||||
result = ZEBRA_DPLANE_REQUEST_QUEUED;
|
||||
else {
|
||||
atomic_fetch_add_explicit(
|
||||
&zdplane_info.dg_gre_set_errors, 1,
|
||||
memory_order_relaxed);
|
||||
if (ctx)
|
||||
dplane_ctx_free(&ctx);
|
||||
result = ZEBRA_DPLANE_REQUEST_FAILURE;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Handler for 'show dplane'
|
||||
*/
|
||||
@ -4234,6 +4318,13 @@ int dplane_show_helper(struct vty *vty, bool detailed)
|
||||
memory_order_relaxed);
|
||||
vty_out(vty, "Neighbor Table updates: %"PRIu64"\n", incoming);
|
||||
vty_out(vty, "Neighbor Table errors: %"PRIu64"\n", errs);
|
||||
|
||||
incoming = atomic_load_explicit(&zdplane_info.dg_gre_set_in,
|
||||
memory_order_relaxed);
|
||||
errs = atomic_load_explicit(&zdplane_info.dg_gre_set_errors,
|
||||
memory_order_relaxed);
|
||||
vty_out(vty, "GRE set updates: %"PRIu64"\n", incoming);
|
||||
vty_out(vty, "GRE set errors: %"PRIu64"\n", errs);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
@ -4680,6 +4771,12 @@ static void kernel_dplane_log_detail(struct zebra_dplane_ctx *ctx)
|
||||
dplane_ctx_get_ifname(ctx),
|
||||
family2str(dplane_ctx_neightable_get_family(ctx)));
|
||||
break;
|
||||
case DPLANE_OP_GRE_SET:
|
||||
zlog_debug("Dplane gre set op %s, ifp %s, link %u",
|
||||
dplane_op2str(dplane_ctx_get_op(ctx)),
|
||||
dplane_ctx_get_ifname(ctx),
|
||||
ctx->u.gre.link_ifindex);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -4808,6 +4905,12 @@ static void kernel_dplane_handle_result(struct zebra_dplane_ctx *ctx)
|
||||
memory_order_relaxed);
|
||||
break;
|
||||
|
||||
case DPLANE_OP_GRE_SET:
|
||||
if (res != ZEBRA_DPLANE_REQUEST_SUCCESS)
|
||||
atomic_fetch_add_explicit(
|
||||
&zdplane_info.dg_gre_set_errors, 1,
|
||||
memory_order_relaxed);
|
||||
break;
|
||||
/* Ignore 'notifications' - no-op */
|
||||
case DPLANE_OP_SYS_ROUTE_ADD:
|
||||
case DPLANE_OP_SYS_ROUTE_DELETE:
|
||||
|
@ -171,6 +171,7 @@ enum dplane_op_e {
|
||||
DPLANE_OP_NEIGH_IP_DELETE,
|
||||
|
||||
DPLANE_OP_NEIGH_TABLE_UPDATE,
|
||||
DPLANE_OP_GRE_SET,
|
||||
};
|
||||
|
||||
/*
|
||||
@ -527,6 +528,10 @@ dplane_ctx_neightable_get_mcast_probes(const struct zebra_dplane_ctx *ctx);
|
||||
uint32_t
|
||||
dplane_ctx_neightable_get_ucast_probes(const struct zebra_dplane_ctx *ctx);
|
||||
|
||||
/* Accessor for GRE set */
|
||||
uint32_t
|
||||
dplane_ctx_gre_get_link_ifindex(const struct zebra_dplane_ctx *ctx);
|
||||
|
||||
/* Namespace info - esp. for netlink communication */
|
||||
const struct zebra_dplane_info *dplane_ctx_get_ns(
|
||||
const struct zebra_dplane_ctx *ctx);
|
||||
@ -695,6 +700,12 @@ enum zebra_dplane_result dplane_neigh_table_update(const struct interface *ifp,
|
||||
const uint32_t ucast_probes,
|
||||
const uint32_t mcast_probes);
|
||||
|
||||
/*
|
||||
* Enqueue a GRE set
|
||||
*/
|
||||
enum zebra_dplane_result
|
||||
dplane_gre_set(struct interface *ifp, struct interface *ifp_link);
|
||||
|
||||
/* Forward ref of zebra_pbr_rule */
|
||||
struct zebra_pbr_rule;
|
||||
|
||||
|
@ -134,6 +134,7 @@ enum zebra_log_refs {
|
||||
EC_ZEBRA_DUPLICATE_NHG_MESSAGE,
|
||||
EC_ZEBRA_VRF_MISCONFIGURED,
|
||||
EC_ZEBRA_ES_CREATE,
|
||||
EC_ZEBRA_GRE_SET_UPDATE,
|
||||
};
|
||||
|
||||
void zebra_error_init(void);
|
||||
|
@ -2965,6 +2965,7 @@ void zebra_nhg_dplane_result(struct zebra_dplane_ctx *ctx)
|
||||
case DPLANE_OP_IPSET_ENTRY_ADD:
|
||||
case DPLANE_OP_IPSET_ENTRY_DELETE:
|
||||
case DPLANE_OP_NEIGH_TABLE_UPDATE:
|
||||
case DPLANE_OP_GRE_SET:
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -4062,6 +4062,7 @@ static int rib_process_dplane_results(struct thread *thread)
|
||||
case DPLANE_OP_NEIGH_DISCOVER:
|
||||
case DPLANE_OP_BR_PORT_UPDATE:
|
||||
case DPLANE_OP_NEIGH_TABLE_UPDATE:
|
||||
case DPLANE_OP_GRE_SET:
|
||||
case DPLANE_OP_NONE:
|
||||
/* Don't expect this: just return the struct? */
|
||||
dplane_ctx_fini(&ctx);
|
||||
|
Loading…
Reference in New Issue
Block a user