netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Jakub Kicinski <kuba@kernel.org>
To: davem@davemloft.net
Cc: netdev@vger.kernel.org, edumazet@google.com, pabeni@redhat.com,
	andrew+netdev@lunn.ch, horms@kernel.org, donald.hunter@gmail.com,
	daniel@iogearbox.net, nicolas.dichtel@6wind.com,
	jacob.e.keller@intel.com, Jakub Kicinski <kuba@kernel.org>,
	bpf@vger.kernel.org
Subject: [PATCH net-next 9/9] tools: ynl: add a sample for rt-link
Date: Thu, 15 May 2025 16:16:50 -0700	[thread overview]
Message-ID: <20250515231650.1325372-10-kuba@kernel.org> (raw)
In-Reply-To: <20250515231650.1325372-1-kuba@kernel.org>

Add a fairly complete example of rt-link usage. If run without any
arguments it simply lists the interfaces and some of their attrs.
If run with an arg it tries to create and delete a netkit device.

 1 # ./tools/net/ynl/samples/rt-link 1
 2 Trying to create a Netkit interface
 3 Testing error message for policy being bad:
 4     Kernel error: 'Provided default xmit policy not supported' (bad attribute: .linkinfo.data(netkit).policy)
 5   1:               lo: mtu 65536
 6   2:           wlp0s1: mtu  1500
 7   3:          enp0s13: mtu  1500
 8   4:           dummy0: mtu  1500  kind dummy     altname one two
 9   5:              nk0: mtu  1500  kind netkit    primary 0  policy forward
10   6:              nk1: mtu  1500  kind netkit    primary 1  policy blackhole
11 Trying to delete a Netkit interface (ifindex 6)

Sample creates the device first, it sets an invalid value for a netkit
attribute to trigger reverse parsing. Line 4 shows the error with the
attribute path correctly generated by YNL.

Then sample fixes the bad attribute and re-issues the request, with
NLM_F_ECHO set. This flag causes the notification to be looped back
to the initiating socket (our socket). Sample parses this notification
to save the ifindex of the created netkit.

Sample then proceeds to list the devices. Line 8 above shows a dummy
device with two alt names. Lines 9 and 10 show the netkit devices
the sample itself created.

The "primary" and "policy" attrs are from inside the netkit submsg.
The string values are auto-generated for the enums by YNL.

To clean up sample deletes the interface it created (line 11).

Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
CC: bpf@vger.kernel.org
---
 tools/net/ynl/samples/rt-link.c  | 184 +++++++++++++++++++++++++++++++
 tools/net/ynl/samples/.gitignore |   1 +
 2 files changed, 185 insertions(+)
 create mode 100644 tools/net/ynl/samples/rt-link.c

diff --git a/tools/net/ynl/samples/rt-link.c b/tools/net/ynl/samples/rt-link.c
new file mode 100644
index 000000000000..acdd4b4a0f74
--- /dev/null
+++ b/tools/net/ynl/samples/rt-link.c
@@ -0,0 +1,184 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <stdio.h>
+#include <string.h>
+
+#include <ynl.h>
+
+#include <arpa/inet.h>
+#include <net/if.h>
+
+#include "rt-link-user.h"
+
+static void rt_link_print(struct rt_link_getlink_rsp *r)
+{
+	unsigned int i;
+
+	printf("%3d: ", r->_hdr.ifi_index);
+
+	if (r->_len.ifname)
+		printf("%16s: ", r->ifname);
+
+	if (r->_present.mtu)
+		printf("mtu %5d  ", r->mtu);
+
+	if (r->linkinfo._len.kind)
+		printf("kind %-8s  ", r->linkinfo.kind);
+	else
+		printf("     %8s  ", "");
+
+	if (r->prop_list._count.alt_ifname) {
+		printf("altname ");
+		for (i = 0; i < r->prop_list._count.alt_ifname; i++)
+			printf("%s ", r->prop_list.alt_ifname[i]->str);
+		printf(" ");
+	}
+
+	if (r->linkinfo._present.data && r->linkinfo.data._present.netkit) {
+		struct rt_link_linkinfo_netkit_attrs *netkit;
+		const char *name;
+
+		netkit = &r->linkinfo.data.netkit;
+		printf("primary %d  ", netkit->primary);
+
+		name = NULL;
+		if (netkit->_present.policy)
+			name = rt_link_netkit_policy_str(netkit->policy);
+		if (name)
+			printf("policy %s  ", name);
+	}
+
+	printf("\n");
+}
+
+static int rt_link_create_netkit(struct ynl_sock *ys)
+{
+	struct rt_link_getlink_ntf *ntf_gl;
+	struct rt_link_newlink_req *req;
+	struct ynl_ntf_base_type *ntf;
+	int ret;
+
+	req = rt_link_newlink_req_alloc();
+	if (!req) {
+		fprintf(stderr, "Can't alloc req\n");
+		return -1;
+	}
+
+	/* rtnetlink doesn't provide info about the created object.
+	 * It expects us to set the ECHO flag and the dig the info out
+	 * of the notifications...
+	 */
+	rt_link_newlink_req_set_nlflags(req, NLM_F_CREATE | NLM_F_ECHO);
+
+	rt_link_newlink_req_set_linkinfo_kind(req, "netkit");
+
+	/* Test error messages */
+	rt_link_newlink_req_set_linkinfo_data_netkit_policy(req, 10);
+	ret = rt_link_newlink(ys, req);
+	if (ret) {
+		printf("Testing error message for policy being bad:\n\t%s\n", ys->err.msg);
+	} else {
+		fprintf(stderr,	"Warning: unexpected success creating netkit with bad attrs\n");
+		goto created;
+	}
+
+	rt_link_newlink_req_set_linkinfo_data_netkit_policy(req, NETKIT_DROP);
+
+	ret = rt_link_newlink(ys, req);
+created:
+	rt_link_newlink_req_free(req);
+	if (ret) {
+		fprintf(stderr, "YNL: %s\n", ys->err.msg);
+		return -1;
+	}
+
+	if (!ynl_has_ntf(ys)) {
+		fprintf(stderr,
+			"Warning: interface created but received no notification, won't delete the interface\n");
+		return 0;
+	}
+
+	ntf = ynl_ntf_dequeue(ys);
+	if (ntf->cmd !=	RTM_NEWLINK) {
+		fprintf(stderr,
+			"Warning: unexpected notification type, won't delete the interface\n");
+		return 0;
+	}
+	ntf_gl = (void *)ntf;
+	ret = ntf_gl->obj._hdr.ifi_index;
+	ynl_ntf_free(ntf);
+
+	return ret;
+}
+
+static void rt_link_del(struct ynl_sock *ys, int ifindex)
+{
+	struct rt_link_dellink_req *req;
+
+	req = rt_link_dellink_req_alloc();
+	if (!req) {
+		fprintf(stderr, "Can't alloc req\n");
+		return;
+	}
+
+	req->_hdr.ifi_index = ifindex;
+	if (rt_link_dellink(ys, req))
+		fprintf(stderr, "YNL: %s\n", ys->err.msg);
+	else
+		fprintf(stderr,
+			"Trying to delete a Netkit interface (ifindex %d)\n",
+			ifindex);
+
+	rt_link_dellink_req_free(req);
+}
+
+int main(int argc, char **argv)
+{
+	struct rt_link_getlink_req_dump *req;
+	struct rt_link_getlink_list *rsp;
+	struct ynl_error yerr;
+	struct ynl_sock *ys;
+	int created = 0;
+
+	ys = ynl_sock_create(&ynl_rt_link_family, &yerr);
+	if (!ys) {
+		fprintf(stderr, "YNL: %s\n", yerr.msg);
+		return 1;
+	}
+
+	if (argc > 1) {
+		fprintf(stderr, "Trying to create a Netkit interface\n");
+		created = rt_link_create_netkit(ys);
+		if (created < 0)
+			goto err_destroy;
+	}
+
+	req = rt_link_getlink_req_dump_alloc();
+	if (!req)
+		goto err_del_ifc;
+
+	rsp = rt_link_getlink_dump(ys, req);
+	rt_link_getlink_req_dump_free(req);
+	if (!rsp)
+		goto err_close;
+
+	if (ynl_dump_empty(rsp))
+		fprintf(stderr, "Error: no links reported\n");
+	ynl_dump_foreach(rsp, link)
+		rt_link_print(link);
+	rt_link_getlink_list_free(rsp);
+
+	if (created)
+		rt_link_del(ys, created);
+
+	ynl_sock_destroy(ys);
+	return 0;
+
+err_close:
+	fprintf(stderr, "YNL: %s\n", ys->err.msg);
+err_del_ifc:
+	if (created)
+		rt_link_del(ys, created);
+err_destroy:
+	ynl_sock_destroy(ys);
+	return 2;
+}
diff --git a/tools/net/ynl/samples/.gitignore b/tools/net/ynl/samples/.gitignore
index 7f9781cf532f..b3ec3fb0929f 100644
--- a/tools/net/ynl/samples/.gitignore
+++ b/tools/net/ynl/samples/.gitignore
@@ -4,4 +4,5 @@ netdev
 ovs
 page-pool
 rt-addr
+rt-link
 rt-route
-- 
2.49.0


  parent reply	other threads:[~2025-05-15 23:17 UTC|newest]

Thread overview: 23+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-05-15 23:16 [PATCH net-next 0/9] tools: ynl-gen: support sub-messages and rt-link Jakub Kicinski
2025-05-15 23:16 ` [PATCH net-next 1/9] netlink: specs: rt-link: add C naming info for ovpn Jakub Kicinski
2025-05-16  9:08   ` Donald Hunter
2025-05-15 23:16 ` [PATCH net-next 2/9] tools: ynl-gen: factor out the annotation of pure nested struct Jakub Kicinski
2025-05-16  9:57   ` Donald Hunter
2025-05-15 23:16 ` [PATCH net-next 3/9] tools: ynl-gen: prepare for submsg structs Jakub Kicinski
2025-05-16 10:15   ` Donald Hunter
2025-05-15 23:16 ` [PATCH net-next 4/9] tools: ynl-gen: submsg: plumb thru an empty type Jakub Kicinski
2025-05-16 10:20   ` Donald Hunter
2025-05-15 23:16 ` [PATCH net-next 5/9] tools: ynl-gen: submsg: render the structs Jakub Kicinski
2025-05-16 10:31   ` Donald Hunter
2025-05-15 23:16 ` [PATCH net-next 6/9] tools: ynl-gen: submsg: support parsing and rendering sub-messages Jakub Kicinski
2025-05-16 10:43   ` Donald Hunter
2025-05-15 23:16 ` [PATCH net-next 7/9] tools: ynl: submsg: reverse parse / error reporting Jakub Kicinski
2025-05-16 10:58   ` Donald Hunter
2025-05-15 23:16 ` [PATCH net-next 8/9] tools: ynl: enable codegen for all rt- families Jakub Kicinski
2025-05-16 11:00   ` Donald Hunter
2025-05-19 14:49   ` Kory Maincent
2025-05-19 15:57     ` Jakub Kicinski
2025-05-20  8:28       ` Kory Maincent
2025-05-15 23:16 ` Jakub Kicinski [this message]
2025-05-16 11:40   ` [PATCH net-next 9/9] tools: ynl: add a sample for rt-link Donald Hunter
2025-05-16 23:40 ` [PATCH net-next 0/9] tools: ynl-gen: support sub-messages and rt-link patchwork-bot+netdevbpf

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20250515231650.1325372-10-kuba@kernel.org \
    --to=kuba@kernel.org \
    --cc=andrew+netdev@lunn.ch \
    --cc=bpf@vger.kernel.org \
    --cc=daniel@iogearbox.net \
    --cc=davem@davemloft.net \
    --cc=donald.hunter@gmail.com \
    --cc=edumazet@google.com \
    --cc=horms@kernel.org \
    --cc=jacob.e.keller@intel.com \
    --cc=netdev@vger.kernel.org \
    --cc=nicolas.dichtel@6wind.com \
    --cc=pabeni@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).