summaryrefslogtreecommitdiff
path: root/zebra/if_netlink.c
diff options
context:
space:
mode:
authorPhilippe Guibert <philippe.guibert@6wind.com>2021-03-11 15:33:41 +0100
committerPhilippe Guibert <philippe.guibert@6wind.com>2021-04-30 10:33:18 +0200
commit62b4b7e44ae72cbd611a78cd7abe8558366af21c (patch)
tree254284fcdf2a9c7d4fca1c19d8645fafe2222c03 /zebra/if_netlink.c
parent372b887859b7e5739137b02a1cecf2ea702ba586 (diff)
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>
Diffstat (limited to 'zebra/if_netlink.c')
-rw-r--r--zebra/if_netlink.c60
1 files changed, 59 insertions, 1 deletions
diff --git a/zebra/if_netlink.c b/zebra/if_netlink.c
index bc74babd19..44ee8d9469 100644
--- a/zebra/if_netlink.c
+++ b/zebra/if_netlink.c
@@ -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)
{