blob: fc8b007a65eedeb52ddefe54db914b30c1519ba8 [file] [log] [blame]
Tomáš Peckaae301762021-10-13 10:50:37 +02001From e5b7f28a216ee1986c417f83132e3daf39ef5fd2 Mon Sep 17 00:00:00 2001
2From: Tomas Pecka <peckato1@users.noreply.github.com>
3Date: Wed, 15 Sep 2021 14:42:34 +0200
4Subject: [PATCH 7/9] networkctl: lldp now uses varlink call
5
6`networkctl lldp` now uses varlink call to the networkd to query LLDP
7neighbor data.
8---
9 src/network/networkctl.c | 157 ++++++++++++++++++++++++++++-----------
10 1 file changed, 113 insertions(+), 44 deletions(-)
11
12diff --git a/src/network/networkctl.c b/src/network/networkctl.c
13index a1d42cbe92..f98779da7e 100644
14--- a/src/network/networkctl.c
15+++ b/src/network/networkctl.c
16@@ -36,6 +36,7 @@
17 #include "glob-util.h"
18 #include "hwdb-util.h"
19 #include "ipvlan-util.h"
20+#include "json.h"
21 #include "local-addresses.h"
22 #include "locale-util.h"
23 #include "logs-show.h"
24@@ -61,6 +62,7 @@
25 #include "strxcpyx.h"
26 #include "terminal-util.h"
27 #include "unit-def.h"
28+#include "varlink.h"
29 #include "verbs.h"
30 #include "wifi-util.h"
31
32@@ -2481,14 +2483,104 @@ static void lldp_capabilities_legend(uint16_t x) {
33 puts("");
34 }
35
36+typedef struct LLDPNeighborEntry {
37+ uint32_t capabilities;
38+ char *chassis_id;
39+ char *port_id;
40+ char *system_name;
41+ char *port_description;
42+} LLDPNeighborEntry;
43+
44+static void lldp_neighbor_entry_free(LLDPNeighborEntry *e) {
45+ if (!e)
46+ return;
47+
48+ free(e->chassis_id);
49+ free(e->port_id);
50+ free(e->system_name);
51+ free(e->port_description);
52+}
53+
54+typedef struct LLDPUserdata {
55+ int *neighbors_count;
56+ uint16_t *capabilities_all;
57+
58+ char *link_name;
59+ Table *table;
60+} LLDPUserdata;
61+
62+static int lldp_neighbours_varlink_reply(Varlink *link, JsonVariant *parameters, const char *error_id, VarlinkReplyFlags flags, void *userdata) {
63+ int r;
64+ _cleanup_free_ char *capabilities = NULL;
65+ LLDPUserdata *udata;
66+ _cleanup_(lldp_neighbor_entry_free) LLDPNeighborEntry entry = {};
67+
68+ static const JsonDispatch dispatch_table[] = {
69+ { "chassisId", JSON_VARIANT_STRING, json_dispatch_string, offsetof(LLDPNeighborEntry, chassis_id), 0 },
70+ { "portId", JSON_VARIANT_STRING, json_dispatch_string, offsetof(LLDPNeighborEntry, port_id), 0 },
71+ { "systemName", JSON_VARIANT_STRING, json_dispatch_string, offsetof(LLDPNeighborEntry, system_name), 0 },
72+ { "enabledCapabilities", JSON_VARIANT_UNSIGNED, json_dispatch_uint32, offsetof(LLDPNeighborEntry, capabilities), 0 },
73+ { "portDescription", JSON_VARIANT_STRING, json_dispatch_string, offsetof(LLDPNeighborEntry, port_description), 0 },
74+ {}
75+ };
76+
77+ udata = userdata;
78+
79+ assert(udata);
80+ assert(udata->link_name);
81+
82+ r = json_dispatch(json_variant_by_key(parameters, "neighbor"), dispatch_table, NULL, 0, &entry);
83+ if (r < 0)
84+ return r;
85+
86+ if (udata->table) {
87+ capabilities = lldp_capabilities_to_string(entry.capabilities);
88+
89+ r = table_add_many(udata->table,
90+ TABLE_STRING, udata->link_name,
91+ TABLE_STRING, entry.chassis_id,
92+ TABLE_STRING, entry.system_name,
93+ TABLE_STRING, capabilities,
94+ TABLE_STRING, entry.port_id,
95+ TABLE_STRING, entry.port_description);
96+ if (r < 0)
97+ return table_log_add_error(r);
98+ }
99+
100+ if (udata->neighbors_count)
101+ *(udata->neighbors_count) += 1;
102+
103+ if (udata->capabilities_all)
104+ *(udata->capabilities_all) |= entry.capabilities;
105+
106+ return 0;
107+}
108+
109 static int link_lldp_status(int argc, char *argv[], void *userdata) {
110+ static const char *address = "/run/systemd/netif/io.systemd.Network";
111+ static const char *method = "io.systemd.Network.LLDPNeighbors";
112+
113+ int r, c;
114+ _cleanup_(varlink_flush_close_unrefp) Varlink *link = NULL;
115 _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
116 _cleanup_(link_info_array_freep) LinkInfo *links = NULL;
117 _cleanup_(table_unrefp) Table *table = NULL;
118- int r, c, m = 0;
119- uint16_t all = 0;
120+ int neighbors_count = 0;
121+ uint16_t capabilities_all = 0;
122+ LLDPUserdata udata = {};
123 TableCell *cell;
124
125+ r = varlink_connect_address(&link, address);
126+ if (r < 0)
127+ return log_error_errno(r, "Failed to connect to %s: %m", address);
128+
129+ (void) varlink_set_description(link, "network");
130+ (void) varlink_set_relative_timeout(link, USEC_INFINITY);
131+
132+ r = varlink_bind_reply(link, lldp_neighbours_varlink_reply);
133+ if (r < 0)
134+ return log_error_errno(r, "Failed to bind reply callback: %m");
135+
136 r = sd_netlink_open(&rtnl);
137 if (r < 0)
138 return log_error_errno(r, "Failed to connect to netlink: %m");
139@@ -2540,53 +2632,30 @@ static int link_lldp_status(int argc, char *argv[], void *userdata) {
140 if (table_set_empty_string(table, "n/a") < 0)
141 return log_oom();
142
143- for (int i = 0; i < c; i++) {
144- _cleanup_fclose_ FILE *f = NULL;
145+ udata.table = table;
146
147- r = open_lldp_neighbors(links[i].ifindex, &f);
148- if (r == -ENOENT)
149- continue;
150- if (r < 0) {
151- log_warning_errno(r, "Failed to open LLDP data for %i, ignoring: %m", links[i].ifindex);
152- continue;
153- }
154+ udata.neighbors_count = &neighbors_count;
155+ udata.capabilities_all = &capabilities_all;
156
157- for (;;) {
158- _cleanup_free_ char *capabilities = NULL;
159- const char *chassis_id = NULL, *port_id = NULL, *system_name = NULL, *port_description = NULL;
160- _cleanup_(sd_lldp_neighbor_unrefp) sd_lldp_neighbor *n = NULL;
161- uint16_t cc;
162+ varlink_set_userdata(link, &udata);
163
164- r = next_lldp_neighbor(f, &n);
165- if (r < 0) {
166- log_warning_errno(r, "Failed to read neighbor data: %m");
167- break;
168- }
169- if (r == 0)
170- break;
171+ for (int i = 0; i < c; i++) {
172+ _cleanup_(json_variant_unrefp) JsonVariant *cparams = NULL;
173
174- (void) sd_lldp_neighbor_get_chassis_id_as_string(n, &chassis_id);
175- (void) sd_lldp_neighbor_get_port_id_as_string(n, &port_id);
176- (void) sd_lldp_neighbor_get_system_name(n, &system_name);
177- (void) sd_lldp_neighbor_get_port_description(n, &port_description);
178+ udata.link_name = links[i].name;
179
180- if (sd_lldp_neighbor_get_enabled_capabilities(n, &cc) >= 0) {
181- capabilities = lldp_capabilities_to_string(cc);
182- all |= cc;
183- }
184+ r = json_build(&cparams, JSON_BUILD_OBJECT(
185+ JSON_BUILD_PAIR("ifindex", JSON_BUILD_UNSIGNED(links[i].ifindex))));
186+ if (r < 0)
187+ return r;
188
189- r = table_add_many(table,
190- TABLE_STRING, links[i].name,
191- TABLE_STRING, chassis_id,
192- TABLE_STRING, system_name,
193- TABLE_STRING, capabilities,
194- TABLE_STRING, port_id,
195- TABLE_STRING, port_description);
196- if (r < 0)
197- return table_log_add_error(r);
198+ r = varlink_observe(link, method, cparams);
199+ if (r < 0)
200+ return log_error_errno(r, "Failed to execute varlink call: %m");
201
202- m++;
203- }
204+ r = varlink_observe_complete(link);
205+ if (r < 0)
206+ return r;
207 }
208
209 r = table_print(table, NULL);
210@@ -2594,8 +2663,8 @@ static int link_lldp_status(int argc, char *argv[], void *userdata) {
211 return table_log_print_error(r);
212
213 if (arg_legend) {
214- lldp_capabilities_legend(all);
215- printf("\n%i neighbors listed.\n", m);
216+ lldp_capabilities_legend(capabilities_all);
217+ printf("\n%i neighbors listed.\n", neighbors_count);
218 }
219
220 return 0;
221--
2222.33.0
223