Tomáš Pecka | 6936b91 | 2023-06-12 11:30:36 +0200 | [diff] [blame] | 1 | From ed72d91efb80888846267f72e9214470eaca4ce6 Mon Sep 17 00:00:00 2001 |
Tomáš Pecka | ae30176 | 2021-10-13 10:50:37 +0200 | [diff] [blame] | 2 | From: Tomas Pecka <peckato1@users.noreply.github.com> |
| 3 | Date: Wed, 15 Sep 2021 14:42:34 +0200 |
Tomáš Pecka | 6936b91 | 2023-06-12 11:30:36 +0200 | [diff] [blame] | 4 | Subject: [PATCH 5/7] networkctl: lldp now uses varlink call |
Tomáš Pecka | ae30176 | 2021-10-13 10:50:37 +0200 | [diff] [blame] | 5 | |
| 6 | `networkctl lldp` now uses varlink call to the networkd to query LLDP |
| 7 | neighbor data. |
| 8 | --- |
Tomáš Pecka | 6936b91 | 2023-06-12 11:30:36 +0200 | [diff] [blame] | 9 | src/network/networkctl.c | 183 ++++++++++++++++++++++++++------------- |
| 10 | 1 file changed, 123 insertions(+), 60 deletions(-) |
Tomáš Pecka | ae30176 | 2021-10-13 10:50:37 +0200 | [diff] [blame] | 11 | |
| 12 | diff --git a/src/network/networkctl.c b/src/network/networkctl.c |
Tomáš Pecka | 6936b91 | 2023-06-12 11:30:36 +0200 | [diff] [blame] | 13 | index a2e216e779..bab6cf5433 100644 |
Tomáš Pecka | ae30176 | 2021-10-13 10:50:37 +0200 | [diff] [blame] | 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" |
Václav Kubernát | 8cd6156 | 2021-12-08 13:27:31 +0100 | [diff] [blame] | 24 | @@ -62,6 +63,7 @@ |
Tomáš Pecka | ae30176 | 2021-10-13 10:50:37 +0200 | [diff] [blame] | 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 | |
Tomáš Pecka | 6936b91 | 2023-06-12 11:30:36 +0200 | [diff] [blame] | 32 | @@ -2439,14 +2441,103 @@ static void lldp_capabilities_legend(uint16_t x) { |
Tomáš Pecka | ae30176 | 2021-10-13 10:50:37 +0200 | [diff] [blame] | 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 { |
Václav Kubernát | 8cd6156 | 2021-12-08 13:27:31 +0100 | [diff] [blame] | 55 | + int neighbors_count; |
| 56 | + uint16_t capabilities_all; |
| 57 | + |
| 58 | + Table *table; |
Tomáš Pecka | ae30176 | 2021-10-13 10:50:37 +0200 | [diff] [blame] | 59 | + |
| 60 | + char *link_name; |
Tomáš Pecka | ae30176 | 2021-10-13 10:50:37 +0200 | [diff] [blame] | 61 | +} LLDPUserdata; |
| 62 | + |
Václav Kubernát | 8cd6156 | 2021-12-08 13:27:31 +0100 | [diff] [blame] | 63 | +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áš Pecka | ae30176 | 2021-10-13 10:50:37 +0200 | [diff] [blame] | 68 | + 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át | 8cd6156 | 2021-12-08 13:27:31 +0100 | [diff] [blame] | 105 | + udata->neighbors_count += 1; |
| 106 | + udata->capabilities_all |= entry.capabilities; |
Tomáš Pecka | ae30176 | 2021-10-13 10:50:37 +0200 | [diff] [blame] | 107 | + |
| 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át | 8cd6156 | 2021-12-08 13:27:31 +0100 | [diff] [blame] | 119 | - _cleanup_(table_unrefp) Table *table = NULL; |
Tomáš Pecka | ae30176 | 2021-10-13 10:50:37 +0200 | [diff] [blame] | 120 | - int r, c, m = 0; |
| 121 | - uint16_t all = 0; |
Václav Kubernát | 8cd6156 | 2021-12-08 13:27:31 +0100 | [diff] [blame] | 122 | + _cleanup_(lldp_userdata_freep) LLDPUserdata udata = {}; |
Tomáš Pecka | ae30176 | 2021-10-13 10:50:37 +0200 | [diff] [blame] | 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 | + |
Václav Kubernát | 8cd6156 | 2021-12-08 13:27:31 +0100 | [diff] [blame] | 132 | + r = varlink_bind_reply(link, lldp_neighbors_varlink_reply); |
Tomáš Pecka | ae30176 | 2021-10-13 10:50:37 +0200 | [diff] [blame] | 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"); |
Tomáš Pecka | 6936b91 | 2023-06-12 11:30:36 +0200 | [diff] [blame] | 139 | @@ -2457,80 +2548,52 @@ static int link_lldp_status(int argc, char *argv[], void *userdata) { |
Václav Kubernát | 8cd6156 | 2021-12-08 13:27:31 +0100 | [diff] [blame] | 140 | |
| 141 | pager_open(arg_pager_flags); |
| 142 | |
| 143 | - table = table_new("link", |
Tomáš Pecka | 6936b91 | 2023-06-12 11:30:36 +0200 | [diff] [blame] | 144 | - "chassis-id", |
| 145 | - "system-name", |
Václav Kubernát | 8cd6156 | 2021-12-08 13:27:31 +0100 | [diff] [blame] | 146 | - "caps", |
Tomáš Pecka | 6936b91 | 2023-06-12 11:30:36 +0200 | [diff] [blame] | 147 | - "port-id", |
| 148 | - "port-description"); |
Václav Kubernát | 8cd6156 | 2021-12-08 13:27:31 +0100 | [diff] [blame] | 149 | - if (!table) |
| 150 | + udata.table = table_new("link", |
Tomáš Pecka | 6936b91 | 2023-06-12 11:30:36 +0200 | [diff] [blame] | 151 | + "chassis-id", |
| 152 | + "system-name", |
Václav Kubernát | 8cd6156 | 2021-12-08 13:27:31 +0100 | [diff] [blame] | 153 | + "caps", |
Tomáš Pecka | 6936b91 | 2023-06-12 11:30:36 +0200 | [diff] [blame] | 154 | + "port-id", |
| 155 | + "port-description"); |
Václav Kubernát | 8cd6156 | 2021-12-08 13:27:31 +0100 | [diff] [blame] | 156 | + if (!udata.table) |
Tomáš Pecka | ae30176 | 2021-10-13 10:50:37 +0200 | [diff] [blame] | 157 | return log_oom(); |
| 158 | |
Václav Kubernát | 8cd6156 | 2021-12-08 13:27:31 +0100 | [diff] [blame] | 159 | 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áš Pecka | 6936b91 | 2023-06-12 11:30:36 +0200 | [diff] [blame] | 164 | - |
Václav Kubernát | 8cd6156 | 2021-12-08 13:27:31 +0100 | [diff] [blame] | 165 | - assert_se(cell = table_get_cell(table, 0, 3)); |
| 166 | - table_set_minimum_width(table, cell, 11); |
Tomáš Pecka | 6936b91 | 2023-06-12 11:30:36 +0200 | [diff] [blame] | 167 | - table_set_ersatz_string(table, TABLE_ERSATZ_DASH); |
| 168 | + table_set_header(udata.table, arg_legend); |
Václav Kubernát | 8cd6156 | 2021-12-08 13:27:31 +0100 | [diff] [blame] | 169 | |
Tomáš Pecka | 5e07025 | 2022-05-20 20:41:21 +0200 | [diff] [blame] | 170 | - for (int i = 0; i < c; i++) { |
Tomáš Pecka | ae30176 | 2021-10-13 10:50:37 +0200 | [diff] [blame] | 171 | - _cleanup_fclose_ FILE *f = NULL; |
Tomáš Pecka | 6936b91 | 2023-06-12 11:30:36 +0200 | [diff] [blame] | 172 | - |
Tomáš Pecka | ae30176 | 2021-10-13 10:50:37 +0200 | [diff] [blame] | 173 | - 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áš Pecka | 6936b91 | 2023-06-12 11:30:36 +0200 | [diff] [blame] | 180 | + 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áš Pecka | ae30176 | 2021-10-13 10:50:37 +0200 | [diff] [blame] | 184 | - for (;;) { |
Tomáš Pecka | ae30176 | 2021-10-13 10:50:37 +0200 | [diff] [blame] | 185 | - 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áš Pecka | 6936b91 | 2023-06-12 11:30:36 +0200 | [diff] [blame] | 187 | - _cleanup_free_ char *capabilities = NULL; |
Tomáš Pecka | ae30176 | 2021-10-13 10:50:37 +0200 | [diff] [blame] | 188 | - uint16_t cc; |
Tomáš Pecka | 6936b91 | 2023-06-12 11:30:36 +0200 | [diff] [blame] | 189 | + varlink_set_userdata(link, &udata); |
| 190 | |
Tomáš Pecka | ae30176 | 2021-10-13 10:50:37 +0200 | [diff] [blame] | 191 | - 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áš Pecka | 5e07025 | 2022-05-20 20:41:21 +0200 | [diff] [blame] | 198 | + for (int i = 0; i < c; i++) { |
| 199 | + _cleanup_(json_variant_unrefp) JsonVariant *cparams = NULL; |
Tomáš Pecka | ae30176 | 2021-10-13 10:50:37 +0200 | [diff] [blame] | 200 | |
| 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áš Pecka | 5e07025 | 2022-05-20 20:41:21 +0200 | [diff] [blame] | 205 | + udata.link_name = links[i].name; |
| 206 | |
Tomáš Pecka | ae30176 | 2021-10-13 10:50:37 +0200 | [diff] [blame] | 207 | - if (sd_lldp_neighbor_get_enabled_capabilities(n, &cc) >= 0) { |
| 208 | - capabilities = lldp_capabilities_to_string(cc); |
| 209 | - all |= cc; |
| 210 | - } |
Tomáš Pecka | 5e07025 | 2022-05-20 20:41:21 +0200 | [diff] [blame] | 211 | + 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áš Pecka | ae30176 | 2021-10-13 10:50:37 +0200 | [diff] [blame] | 216 | - 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áš Pecka | 5e07025 | 2022-05-20 20:41:21 +0200 | [diff] [blame] | 225 | + r = varlink_observe(link, method, cparams); |
| 226 | + if (r < 0) |
| 227 | + return log_error_errno(r, "Failed to execute varlink call: %m"); |
| 228 | |
Tomáš Pecka | ae30176 | 2021-10-13 10:50:37 +0200 | [diff] [blame] | 229 | - m++; |
| 230 | - } |
| 231 | + r = varlink_observe_complete(link); |
| 232 | + if (r < 0) |
| 233 | + return r; |
| 234 | } |
| 235 | |
Václav Kubernát | 8cd6156 | 2021-12-08 13:27:31 +0100 | [diff] [blame] | 236 | - r = table_print(table, NULL); |
| 237 | + r = table_print(udata.table, NULL); |
| 238 | if (r < 0) |
Tomáš Pecka | ae30176 | 2021-10-13 10:50:37 +0200 | [diff] [blame] | 239 | 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át | 8cd6156 | 2021-12-08 13:27:31 +0100 | [diff] [blame] | 244 | + lldp_capabilities_legend(udata.capabilities_all); |
| 245 | + printf("\n%i neighbors listed.\n", udata.neighbors_count); |
Tomáš Pecka | ae30176 | 2021-10-13 10:50:37 +0200 | [diff] [blame] | 246 | } |
| 247 | |
| 248 | return 0; |
| 249 | -- |
Tomáš Pecka | 6936b91 | 2023-06-12 11:30:36 +0200 | [diff] [blame] | 250 | 2.41.0 |
Tomáš Pecka | ae30176 | 2021-10-13 10:50:37 +0200 | [diff] [blame] | 251 | |