xref: /linux-6.15/tools/net/ynl/samples/netdev.c (revision 3d8806f3)
1ee0202e2SJakub Kicinski // SPDX-License-Identifier: GPL-2.0
2ee0202e2SJakub Kicinski #include <stdio.h>
3ee0202e2SJakub Kicinski #include <string.h>
4ee0202e2SJakub Kicinski 
5ee0202e2SJakub Kicinski #include <ynl.h>
6ee0202e2SJakub Kicinski 
7ee0202e2SJakub Kicinski #include <net/if.h>
8ee0202e2SJakub Kicinski 
9ee0202e2SJakub Kicinski #include "netdev-user.h"
10ee0202e2SJakub Kicinski 
11ee0202e2SJakub Kicinski /* netdev genetlink family code sample
12ee0202e2SJakub Kicinski  * This sample shows off basics of the netdev family but also notification
13ee0202e2SJakub Kicinski  * handling, hence the somewhat odd UI. We subscribe to notifications first
14ee0202e2SJakub Kicinski  * then wait for ifc selection, so the socket may already accumulate
15ee0202e2SJakub Kicinski  * notifications as we wait. This allows us to test that YNL can handle
16ee0202e2SJakub Kicinski  * requests and notifications getting interleaved.
17ee0202e2SJakub Kicinski  */
18ee0202e2SJakub Kicinski 
netdev_print_device(struct netdev_dev_get_rsp * d,unsigned int op)19ee0202e2SJakub Kicinski static void netdev_print_device(struct netdev_dev_get_rsp *d, unsigned int op)
20ee0202e2SJakub Kicinski {
21ee0202e2SJakub Kicinski 	char ifname[IF_NAMESIZE];
22ee0202e2SJakub Kicinski 	const char *name;
23ee0202e2SJakub Kicinski 
24ee0202e2SJakub Kicinski 	if (!d->_present.ifindex)
25ee0202e2SJakub Kicinski 		return;
26ee0202e2SJakub Kicinski 
27ee0202e2SJakub Kicinski 	name = if_indextoname(d->ifindex, ifname);
28ee0202e2SJakub Kicinski 	if (name)
29ee0202e2SJakub Kicinski 		printf("%8s", name);
30ee0202e2SJakub Kicinski 	printf("[%d]\t", d->ifindex);
31ee0202e2SJakub Kicinski 
32ee0202e2SJakub Kicinski 	if (!d->_present.xdp_features)
33ee0202e2SJakub Kicinski 		return;
34ee0202e2SJakub Kicinski 
350c6c9b10SStanislav Fomichev 	printf("xdp-features (%llx):", d->xdp_features);
369276009dSStanislav Fomichev 	for (int i = 0; d->xdp_features >= 1U << i; i++) {
37ee0202e2SJakub Kicinski 		if (d->xdp_features & (1U << i))
38ee0202e2SJakub Kicinski 			printf(" %s", netdev_xdp_act_str(1 << i));
39ee0202e2SJakub Kicinski 	}
40ee0202e2SJakub Kicinski 
410c6c9b10SStanislav Fomichev 	printf(" xdp-rx-metadata-features (%llx):", d->xdp_rx_metadata_features);
429276009dSStanislav Fomichev 	for (int i = 0; d->xdp_rx_metadata_features >= 1U << i; i++) {
430c6c9b10SStanislav Fomichev 		if (d->xdp_rx_metadata_features & (1U << i))
440c6c9b10SStanislav Fomichev 			printf(" %s", netdev_xdp_rx_metadata_str(1 << i));
450c6c9b10SStanislav Fomichev 	}
460c6c9b10SStanislav Fomichev 
479276009dSStanislav Fomichev 	printf(" xsk-features (%llx):", d->xsk_features);
489276009dSStanislav Fomichev 	for (int i = 0; d->xsk_features >= 1U << i; i++) {
499276009dSStanislav Fomichev 		if (d->xsk_features & (1U << i))
509276009dSStanislav Fomichev 			printf(" %s", netdev_xsk_flags_str(1 << i));
519276009dSStanislav Fomichev 	}
529276009dSStanislav Fomichev 
5326fdb67eSStanislav Fomichev 	printf(" xdp-zc-max-segs=%u", d->xdp_zc_max_segs);
5426fdb67eSStanislav Fomichev 
55ee0202e2SJakub Kicinski 	name = netdev_op_str(op);
56ee0202e2SJakub Kicinski 	if (name)
57ee0202e2SJakub Kicinski 		printf(" (ntf: %s)", name);
58ee0202e2SJakub Kicinski 	printf("\n");
59ee0202e2SJakub Kicinski }
60ee0202e2SJakub Kicinski 
main(int argc,char ** argv)61ee0202e2SJakub Kicinski int main(int argc, char **argv)
62ee0202e2SJakub Kicinski {
63ee0202e2SJakub Kicinski 	struct netdev_dev_get_list *devs;
64ee0202e2SJakub Kicinski 	struct ynl_ntf_base_type *ntf;
65ee0202e2SJakub Kicinski 	struct ynl_error yerr;
66ee0202e2SJakub Kicinski 	struct ynl_sock *ys;
67ee0202e2SJakub Kicinski 	int ifindex = 0;
68ee0202e2SJakub Kicinski 
69ee0202e2SJakub Kicinski 	if (argc > 1)
70ee0202e2SJakub Kicinski 		ifindex = strtol(argv[1], NULL, 0);
71ee0202e2SJakub Kicinski 
72ee0202e2SJakub Kicinski 	ys = ynl_sock_create(&ynl_netdev_family, &yerr);
73ee0202e2SJakub Kicinski 	if (!ys) {
74ee0202e2SJakub Kicinski 		fprintf(stderr, "YNL: %s\n", yerr.msg);
75ee0202e2SJakub Kicinski 		return 1;
76ee0202e2SJakub Kicinski 	}
77ee0202e2SJakub Kicinski 
78ee0202e2SJakub Kicinski 	if (ynl_subscribe(ys, "mgmt"))
79ee0202e2SJakub Kicinski 		goto err_close;
80ee0202e2SJakub Kicinski 
81ee0202e2SJakub Kicinski 	printf("Select ifc ($ifindex; or 0 = dump; or -2 ntf check): ");
82*3d8806f3SJakub Kicinski 	if (scanf("%d", &ifindex) != 1) {
83*3d8806f3SJakub Kicinski 		fprintf(stderr, "Error: unable to parse input\n");
84*3d8806f3SJakub Kicinski 		goto err_destroy;
85*3d8806f3SJakub Kicinski 	}
86ee0202e2SJakub Kicinski 
87ee0202e2SJakub Kicinski 	if (ifindex > 0) {
88ee0202e2SJakub Kicinski 		struct netdev_dev_get_req *req;
89ee0202e2SJakub Kicinski 		struct netdev_dev_get_rsp *d;
90ee0202e2SJakub Kicinski 
91ee0202e2SJakub Kicinski 		req = netdev_dev_get_req_alloc();
92ee0202e2SJakub Kicinski 		netdev_dev_get_req_set_ifindex(req, ifindex);
93ee0202e2SJakub Kicinski 
94ee0202e2SJakub Kicinski 		d = netdev_dev_get(ys, req);
95ee0202e2SJakub Kicinski 		netdev_dev_get_req_free(req);
96ee0202e2SJakub Kicinski 		if (!d)
97ee0202e2SJakub Kicinski 			goto err_close;
98ee0202e2SJakub Kicinski 
99ee0202e2SJakub Kicinski 		netdev_print_device(d, 0);
100ee0202e2SJakub Kicinski 		netdev_dev_get_rsp_free(d);
101ee0202e2SJakub Kicinski 	} else if (!ifindex) {
102ee0202e2SJakub Kicinski 		devs = netdev_dev_get_dump(ys);
103ee0202e2SJakub Kicinski 		if (!devs)
104ee0202e2SJakub Kicinski 			goto err_close;
105ee0202e2SJakub Kicinski 
106d6d647d7SJakub Kicinski 		if (ynl_dump_empty(devs))
107d6d647d7SJakub Kicinski 			fprintf(stderr, "Error: no devices reported\n");
108ee0202e2SJakub Kicinski 		ynl_dump_foreach(devs, d)
109ee0202e2SJakub Kicinski 			netdev_print_device(d, 0);
110ee0202e2SJakub Kicinski 		netdev_dev_get_list_free(devs);
111ee0202e2SJakub Kicinski 	} else if (ifindex == -2) {
112ee0202e2SJakub Kicinski 		ynl_ntf_check(ys);
113ee0202e2SJakub Kicinski 	}
114ee0202e2SJakub Kicinski 	while ((ntf = ynl_ntf_dequeue(ys))) {
115ee0202e2SJakub Kicinski 		netdev_print_device((struct netdev_dev_get_rsp *)&ntf->data,
116ee0202e2SJakub Kicinski 				    ntf->cmd);
117ee0202e2SJakub Kicinski 		ynl_ntf_free(ntf);
118ee0202e2SJakub Kicinski 	}
119ee0202e2SJakub Kicinski 
120ee0202e2SJakub Kicinski 	ynl_sock_destroy(ys);
121ee0202e2SJakub Kicinski 	return 0;
122ee0202e2SJakub Kicinski 
123ee0202e2SJakub Kicinski err_close:
124ee0202e2SJakub Kicinski 	fprintf(stderr, "YNL: %s\n", ys->err.msg);
125*3d8806f3SJakub Kicinski err_destroy:
126ee0202e2SJakub Kicinski 	ynl_sock_destroy(ys);
127ee0202e2SJakub Kicinski 	return 2;
128ee0202e2SJakub Kicinski }
129