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