blob: 3511700b04dc0f7f04c10cead2606c47a90f6928 [file] [log] [blame]
Tomáš Pecka6936b912023-06-12 11:30:36 +02001From ed72d91efb80888846267f72e9214470eaca4ce6 Mon Sep 17 00:00:00 2001
Tomáš Peckaae301762021-10-13 10:50:37 +02002From: Tomas Pecka <peckato1@users.noreply.github.com>
3Date: Wed, 15 Sep 2021 14:42:34 +0200
Tomáš Pecka6936b912023-06-12 11:30:36 +02004Subject: [PATCH 5/7] networkctl: lldp now uses varlink call
Tomáš Peckaae301762021-10-13 10:50:37 +02005
6`networkctl lldp` now uses varlink call to the networkd to query LLDP
7neighbor data.
8---
Tomáš Pecka6936b912023-06-12 11:30:36 +02009 src/network/networkctl.c | 183 ++++++++++++++++++++++++++-------------
10 1 file changed, 123 insertions(+), 60 deletions(-)
Tomáš Peckaae301762021-10-13 10:50:37 +020011
12diff --git a/src/network/networkctl.c b/src/network/networkctl.c
Tomáš Pecka6936b912023-06-12 11:30:36 +020013index a2e216e779..bab6cf5433 100644
Tomáš Peckaae301762021-10-13 10:50:37 +020014--- 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"
Václav Kubernát8cd61562021-12-08 13:27:31 +010024@@ -62,6 +63,7 @@
Tomáš Peckaae301762021-10-13 10:50:37 +020025 #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
Tomáš Pecka6936b912023-06-12 11:30:36 +020032@@ -2439,14 +2441,103 @@ static void lldp_capabilities_legend(uint16_t x) {
Tomáš Peckaae301762021-10-13 10:50:37 +020033 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 {
Václav Kubernát8cd61562021-12-08 13:27:31 +010055+ int neighbors_count;
56+ uint16_t capabilities_all;
57+
58+ Table *table;
Tomáš Peckaae301762021-10-13 10:50:37 +020059+
60+ char *link_name;
Tomáš Peckaae301762021-10-13 10:50:37 +020061+} LLDPUserdata;
62+
Václav Kubernát8cd61562021-12-08 13:27:31 +010063+static void lldp_userdata_freep(LLDPUserdata* p) {
64+ table_unref(p->table);
65+}
66+
67+static int lldp_neighbors_varlink_reply(Varlink *link, JsonVariant *parameters, const char *error_id, VarlinkReplyFlags flags, void *userdata) {
Tomáš Peckaae301762021-10-13 10:50:37 +020068+ int r;
69+ _cleanup_free_ char *capabilities = NULL;
70+ LLDPUserdata *udata;
71+ _cleanup_(lldp_neighbor_entry_free) LLDPNeighborEntry entry = {};
72+
73+ static const JsonDispatch dispatch_table[] = {
74+ { "chassisId", JSON_VARIANT_STRING, json_dispatch_string, offsetof(LLDPNeighborEntry, chassis_id), 0 },
75+ { "portId", JSON_VARIANT_STRING, json_dispatch_string, offsetof(LLDPNeighborEntry, port_id), 0 },
76+ { "systemName", JSON_VARIANT_STRING, json_dispatch_string, offsetof(LLDPNeighborEntry, system_name), 0 },
77+ { "enabledCapabilities", JSON_VARIANT_UNSIGNED, json_dispatch_uint32, offsetof(LLDPNeighborEntry, capabilities), 0 },
78+ { "portDescription", JSON_VARIANT_STRING, json_dispatch_string, offsetof(LLDPNeighborEntry, port_description), 0 },
79+ {}
80+ };
81+
82+ udata = userdata;
83+
84+ assert(udata);
85+ assert(udata->link_name);
86+
87+ r = json_dispatch(json_variant_by_key(parameters, "neighbor"), dispatch_table, NULL, 0, &entry);
88+ if (r < 0)
89+ return r;
90+
91+ if (udata->table) {
92+ capabilities = lldp_capabilities_to_string(entry.capabilities);
93+
94+ r = table_add_many(udata->table,
95+ TABLE_STRING, udata->link_name,
96+ TABLE_STRING, entry.chassis_id,
97+ TABLE_STRING, entry.system_name,
98+ TABLE_STRING, capabilities,
99+ TABLE_STRING, entry.port_id,
100+ TABLE_STRING, entry.port_description);
101+ if (r < 0)
102+ return table_log_add_error(r);
103+ }
104+
Václav Kubernát8cd61562021-12-08 13:27:31 +0100105+ udata->neighbors_count += 1;
106+ udata->capabilities_all |= entry.capabilities;
Tomáš Peckaae301762021-10-13 10:50:37 +0200107+
108+ return 0;
109+}
110+
111 static int link_lldp_status(int argc, char *argv[], void *userdata) {
112+ static const char *address = "/run/systemd/netif/io.systemd.Network";
113+ static const char *method = "io.systemd.Network.LLDPNeighbors";
114+
115+ int r, c;
116+ _cleanup_(varlink_flush_close_unrefp) Varlink *link = NULL;
117 _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
118 _cleanup_(link_info_array_freep) LinkInfo *links = NULL;
Václav Kubernát8cd61562021-12-08 13:27:31 +0100119- _cleanup_(table_unrefp) Table *table = NULL;
Tomáš Peckaae301762021-10-13 10:50:37 +0200120- int r, c, m = 0;
121- uint16_t all = 0;
Václav Kubernát8cd61562021-12-08 13:27:31 +0100122+ _cleanup_(lldp_userdata_freep) LLDPUserdata udata = {};
Tomáš Peckaae301762021-10-13 10:50:37 +0200123 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+
Václav Kubernát8cd61562021-12-08 13:27:31 +0100132+ r = varlink_bind_reply(link, lldp_neighbors_varlink_reply);
Tomáš Peckaae301762021-10-13 10:50:37 +0200133+ 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");
Tomáš Pecka6936b912023-06-12 11:30:36 +0200139@@ -2457,80 +2548,52 @@ static int link_lldp_status(int argc, char *argv[], void *userdata) {
Václav Kubernát8cd61562021-12-08 13:27:31 +0100140
141 pager_open(arg_pager_flags);
142
143- table = table_new("link",
Tomáš Pecka6936b912023-06-12 11:30:36 +0200144- "chassis-id",
145- "system-name",
Václav Kubernát8cd61562021-12-08 13:27:31 +0100146- "caps",
Tomáš Pecka6936b912023-06-12 11:30:36 +0200147- "port-id",
148- "port-description");
Václav Kubernát8cd61562021-12-08 13:27:31 +0100149- if (!table)
150+ udata.table = table_new("link",
Tomáš Pecka6936b912023-06-12 11:30:36 +0200151+ "chassis-id",
152+ "system-name",
Václav Kubernát8cd61562021-12-08 13:27:31 +0100153+ "caps",
Tomáš Pecka6936b912023-06-12 11:30:36 +0200154+ "port-id",
155+ "port-description");
Václav Kubernát8cd61562021-12-08 13:27:31 +0100156+ if (!udata.table)
Tomáš Peckaae301762021-10-13 10:50:37 +0200157 return log_oom();
158
Václav Kubernát8cd61562021-12-08 13:27:31 +0100159 if (arg_full)
160- table_set_width(table, 0);
161+ table_set_width(udata.table, 0);
162
163- table_set_header(table, arg_legend);
Tomáš Pecka6936b912023-06-12 11:30:36 +0200164-
Václav Kubernát8cd61562021-12-08 13:27:31 +0100165- assert_se(cell = table_get_cell(table, 0, 3));
166- table_set_minimum_width(table, cell, 11);
Tomáš Pecka6936b912023-06-12 11:30:36 +0200167- table_set_ersatz_string(table, TABLE_ERSATZ_DASH);
168+ table_set_header(udata.table, arg_legend);
Václav Kubernát8cd61562021-12-08 13:27:31 +0100169
Tomáš Pecka5e070252022-05-20 20:41:21 +0200170- for (int i = 0; i < c; i++) {
Tomáš Peckaae301762021-10-13 10:50:37 +0200171- _cleanup_fclose_ FILE *f = NULL;
Tomáš Pecka6936b912023-06-12 11:30:36 +0200172-
Tomáš Peckaae301762021-10-13 10:50:37 +0200173- r = open_lldp_neighbors(links[i].ifindex, &f);
174- if (r == -ENOENT)
175- continue;
176- if (r < 0) {
177- log_warning_errno(r, "Failed to open LLDP data for %i, ignoring: %m", links[i].ifindex);
178- continue;
179- }
Tomáš Pecka6936b912023-06-12 11:30:36 +0200180+ assert_se(cell = table_get_cell(udata.table, 0, 3));
181+ table_set_minimum_width(udata.table, cell, 11);
182+ table_set_ersatz_string(udata.table, TABLE_ERSATZ_DASH);
183
Tomáš Peckaae301762021-10-13 10:50:37 +0200184- for (;;) {
Tomáš Peckaae301762021-10-13 10:50:37 +0200185- const char *chassis_id = NULL, *port_id = NULL, *system_name = NULL, *port_description = NULL;
186- _cleanup_(sd_lldp_neighbor_unrefp) sd_lldp_neighbor *n = NULL;
Tomáš Pecka6936b912023-06-12 11:30:36 +0200187- _cleanup_free_ char *capabilities = NULL;
Tomáš Peckaae301762021-10-13 10:50:37 +0200188- uint16_t cc;
Tomáš Pecka6936b912023-06-12 11:30:36 +0200189+ varlink_set_userdata(link, &udata);
190
Tomáš Peckaae301762021-10-13 10:50:37 +0200191- r = next_lldp_neighbor(f, &n);
192- if (r < 0) {
193- log_warning_errno(r, "Failed to read neighbor data: %m");
194- break;
195- }
196- if (r == 0)
197- break;
Tomáš Pecka5e070252022-05-20 20:41:21 +0200198+ for (int i = 0; i < c; i++) {
199+ _cleanup_(json_variant_unrefp) JsonVariant *cparams = NULL;
Tomáš Peckaae301762021-10-13 10:50:37 +0200200
201- (void) sd_lldp_neighbor_get_chassis_id_as_string(n, &chassis_id);
202- (void) sd_lldp_neighbor_get_port_id_as_string(n, &port_id);
203- (void) sd_lldp_neighbor_get_system_name(n, &system_name);
204- (void) sd_lldp_neighbor_get_port_description(n, &port_description);
Tomáš Pecka5e070252022-05-20 20:41:21 +0200205+ udata.link_name = links[i].name;
206
Tomáš Peckaae301762021-10-13 10:50:37 +0200207- if (sd_lldp_neighbor_get_enabled_capabilities(n, &cc) >= 0) {
208- capabilities = lldp_capabilities_to_string(cc);
209- all |= cc;
210- }
Tomáš Pecka5e070252022-05-20 20:41:21 +0200211+ r = json_build(&cparams, JSON_BUILD_OBJECT(
212+ JSON_BUILD_PAIR("ifindex", JSON_BUILD_UNSIGNED(links[i].ifindex))));
213+ if (r < 0)
214+ return r;
215
Tomáš Peckaae301762021-10-13 10:50:37 +0200216- r = table_add_many(table,
217- TABLE_STRING, links[i].name,
218- TABLE_STRING, chassis_id,
219- TABLE_STRING, system_name,
220- TABLE_STRING, capabilities,
221- TABLE_STRING, port_id,
222- TABLE_STRING, port_description);
223- if (r < 0)
224- return table_log_add_error(r);
Tomáš Pecka5e070252022-05-20 20:41:21 +0200225+ r = varlink_observe(link, method, cparams);
226+ if (r < 0)
227+ return log_error_errno(r, "Failed to execute varlink call: %m");
228
Tomáš Peckaae301762021-10-13 10:50:37 +0200229- m++;
230- }
231+ r = varlink_observe_complete(link);
232+ if (r < 0)
233+ return r;
234 }
235
Václav Kubernát8cd61562021-12-08 13:27:31 +0100236- r = table_print(table, NULL);
237+ r = table_print(udata.table, NULL);
238 if (r < 0)
Tomáš Peckaae301762021-10-13 10:50:37 +0200239 return table_log_print_error(r);
240
241 if (arg_legend) {
242- lldp_capabilities_legend(all);
243- printf("\n%i neighbors listed.\n", m);
Václav Kubernát8cd61562021-12-08 13:27:31 +0100244+ lldp_capabilities_legend(udata.capabilities_all);
245+ printf("\n%i neighbors listed.\n", udata.neighbors_count);
Tomáš Peckaae301762021-10-13 10:50:37 +0200246 }
247
248 return 0;
249--
Tomáš Pecka6936b912023-06-12 11:30:36 +02002502.41.0
Tomáš Peckaae301762021-10-13 10:50:37 +0200251