]> git.ipfire.org Git - thirdparty/lldpd.git/blob - src/client/display.c
lldp: add option/command to override hostname
[thirdparty/lldpd.git] / src / client / display.c
1 /* -*- mode: c; c-file-style: "openbsd" -*- */
2 /*
3 * Copyright (c) 2008 Vincent Bernat <bernat@luffy.cx>
4 *
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <unistd.h>
21 #include <ctype.h>
22 #include <time.h>
23 #include <errno.h>
24 #include <sys/types.h>
25 #include <sys/socket.h>
26 #include <sys/un.h>
27 #include <arpa/inet.h>
28 #include <string.h>
29
30 #include "../log.h"
31 #include "client.h"
32
33 static void
34 display_cap(struct writer * w, lldpctl_atom_t *chassis, u_int8_t bit, char *symbol)
35 {
36 if (lldpctl_atom_get_int(chassis, lldpctl_k_chassis_cap_available) & bit) {
37 tag_start(w, "capability", "Capability");
38 tag_attr (w, "type", "", symbol );
39 tag_attr (w, "enabled", "",
40 (lldpctl_atom_get_int(chassis, lldpctl_k_chassis_cap_enabled) & bit)?
41 "on":"off");
42 tag_end (w);
43 }
44 }
45
46 static void
47 display_med_capability(struct writer *w, long int available, int cap,
48 const char *symbol)
49 {
50 if (available & cap) {
51 tag_start(w, "capability", "Capability");
52 tag_attr(w, "type", "", symbol);
53 tag_end(w);
54 }
55 }
56
57 static void
58 display_med(struct writer *w, lldpctl_atom_t *port)
59 {
60 lldpctl_atom_t *medpolicies, *medpolicy;
61 lldpctl_atom_t *medlocations, *medlocation;
62 lldpctl_atom_t *caelements, *caelement;
63 long int cap = lldpctl_atom_get_int(port, lldpctl_k_chassis_med_cap);
64 const char *type;
65
66 if (lldpctl_atom_get_int(port, lldpctl_k_chassis_med_type) <= 0)
67 return;
68
69 tag_start(w, "lldp-med", "LLDP-MED");
70
71 tag_datatag(w, "device-type", "Device Type",
72 lldpctl_atom_get_str(port, lldpctl_k_chassis_med_type));
73
74 display_med_capability(w, cap, LLDP_MED_CAP_CAP, "Capabilities");
75 display_med_capability(w, cap, LLDP_MED_CAP_POLICY, "Policy");
76 display_med_capability(w, cap, LLDP_MED_CAP_LOCATION, "Location");
77 display_med_capability(w, cap, LLDP_MED_CAP_MDI_PSE, "MDI/PSE");
78 display_med_capability(w, cap, LLDP_MED_CAP_MDI_PD, "MDI/PD");
79 display_med_capability(w, cap, LLDP_MED_CAP_IV, "Inventory");
80
81 /* LLDP MED policies */
82 medpolicies = lldpctl_atom_get(port, lldpctl_k_port_med_policies);
83 lldpctl_atom_foreach(medpolicies, medpolicy) {
84 if (lldpctl_atom_get_int(medpolicy,
85 lldpctl_k_med_policy_type) <= 0) continue;
86
87 tag_start(w, "policy", "LLDP-MED Network Policy for");
88 tag_attr(w, "apptype", "", lldpctl_atom_get_str(medpolicy, lldpctl_k_med_policy_type));
89 tag_attr(w, "defined", "Defined",
90 (lldpctl_atom_get_int(medpolicy,
91 lldpctl_k_med_policy_unknown) > 0)?"no":"yes");
92
93 if (lldpctl_atom_get_int(medpolicy,
94 lldpctl_k_med_policy_tagged) > 0) {
95 int vid = lldpctl_atom_get_int(medpolicy,
96 lldpctl_k_med_policy_vid);
97 tag_start(w, "vlan", "VLAN");
98 if (vid == 0) {
99 tag_attr(w, "vid", "", "priority");
100 } else if (vid == 4095) {
101 tag_attr(w, "vid", "", "reserved");
102 } else {
103 tag_attr(w, "vid", "",
104 lldpctl_atom_get_str(medpolicy,
105 lldpctl_k_med_policy_vid));
106 }
107 tag_end(w);
108 }
109
110 tag_datatag(w, "priority", "Priority",
111 lldpctl_atom_get_str(medpolicy,
112 lldpctl_k_med_policy_priority));
113 tag_datatag(w, "dscp", "DSCP Value",
114 lldpctl_atom_get_str(medpolicy,
115 lldpctl_k_med_policy_dscp));
116
117 tag_end(w);
118 }
119 lldpctl_atom_dec_ref(medpolicies);
120
121 /* LLDP MED locations */
122 medlocations = lldpctl_atom_get(port, lldpctl_k_port_med_locations);
123 lldpctl_atom_foreach(medlocations, medlocation) {
124 int format = lldpctl_atom_get_int(medlocation,
125 lldpctl_k_med_location_format);
126 if (format <= 0) continue;
127 tag_start(w, "location", "LLDP-MED Location Identification");
128 tag_attr(w, "type", "Type",
129 lldpctl_atom_get_str(medlocation,
130 lldpctl_k_med_location_format));
131
132 switch (format) {
133 case LLDP_MED_LOCFORMAT_COORD:
134 tag_attr(w, "geoid", "Geoid",
135 lldpctl_atom_get_str(medlocation,
136 lldpctl_k_med_location_geoid));
137 tag_datatag(w, "lat", "Latitude",
138 lldpctl_atom_get_str(medlocation,
139 lldpctl_k_med_location_latitude));
140 tag_datatag(w, "lon", "Longitude",
141 lldpctl_atom_get_str(medlocation,
142 lldpctl_k_med_location_longitude));
143 tag_start(w, "altitude", "Altitude");
144 tag_attr(w, "unit", "", lldpctl_atom_get_str(medlocation,
145 lldpctl_k_med_location_altitude_unit));
146 tag_data(w, lldpctl_atom_get_str(medlocation,
147 lldpctl_k_med_location_altitude));
148 tag_end(w);
149 break;
150 case LLDP_MED_LOCFORMAT_CIVIC:
151 tag_datatag(w, "country", "Country",
152 lldpctl_atom_get_str(medlocation,
153 lldpctl_k_med_location_country));
154 caelements = lldpctl_atom_get(medlocation,
155 lldpctl_k_med_location_ca_elements);
156 lldpctl_atom_foreach(caelements, caelement) {
157 type = lldpctl_atom_get_str(caelement,
158 lldpctl_k_med_civicaddress_type);
159 tag_datatag(w, totag(type), type,
160 lldpctl_atom_get_str(caelement,
161 lldpctl_k_med_civicaddress_value));
162 }
163 lldpctl_atom_dec_ref(caelements);
164 break;
165 case LLDP_MED_LOCFORMAT_ELIN:
166 tag_datatag(w, "ecs", "ECS ELIN",
167 lldpctl_atom_get_str(medlocation,
168 lldpctl_k_med_location_elin));
169 break;
170 }
171
172 tag_end(w);
173 }
174 lldpctl_atom_dec_ref(medlocations);
175
176 /* LLDP MED power */
177 if (lldpctl_atom_get_int(port, lldpctl_k_med_power_type) > 0) {
178 tag_start(w, "poe", "Extended Power-over-Ethernet");
179
180 tag_datatag(w, "device-type", "Power Type & Source",
181 lldpctl_atom_get_str(port, lldpctl_k_med_power_type));
182 tag_datatag(w, "source", "Power Source",
183 lldpctl_atom_get_str(port, lldpctl_k_med_power_source));
184 tag_datatag(w, "priority", "Power priority",
185 lldpctl_atom_get_str(port, lldpctl_k_med_power_priority));
186 tag_datatag(w, "power", "Power Value",
187 lldpctl_atom_get_str(port, lldpctl_k_med_power_val));
188 }
189
190 /* LLDP MED inventory */
191 do {
192 const char *hw = lldpctl_atom_get_str(port,
193 lldpctl_k_chassis_med_inventory_hw);
194 const char *sw = lldpctl_atom_get_str(port,
195 lldpctl_k_chassis_med_inventory_sw);
196 const char *fw = lldpctl_atom_get_str(port,
197 lldpctl_k_chassis_med_inventory_fw);
198 const char *sn = lldpctl_atom_get_str(port,
199 lldpctl_k_chassis_med_inventory_sn);
200 const char *manuf = lldpctl_atom_get_str(port,
201 lldpctl_k_chassis_med_inventory_manuf);
202 const char *model = lldpctl_atom_get_str(port,
203 lldpctl_k_chassis_med_inventory_model);
204 const char *asset = lldpctl_atom_get_str(port,
205 lldpctl_k_chassis_med_inventory_asset);
206 if (!(hw || sw || fw || sn ||
207 manuf || model || asset)) break;
208
209 tag_start(w, "inventory", "Inventory");
210 tag_datatag(w, "hardware", "Hardware Revision", hw);
211 tag_datatag(w, "software", "Software Revision", sw);
212 tag_datatag(w, "firmware", "Firmware Revision", fw);
213 tag_datatag(w, "serial", "Serial Number", sn);
214 tag_datatag(w, "manufacturer", "Manufacturer", manuf);
215 tag_datatag(w, "model", "Model", model);
216 tag_datatag(w, "asset", "Asset ID", asset);
217 tag_end(w);
218 } while(0);
219
220 tag_end(w);
221 }
222
223 static void
224 display_chassis(struct writer* w, lldpctl_atom_t* neighbor, int details)
225 {
226 lldpctl_atom_t *mgmts, *mgmt;
227
228 tag_start(w, "chassis", "Chassis");
229 tag_start(w, "id", "ChassisID");
230 tag_attr (w, "type", "",
231 lldpctl_atom_get_str(neighbor,
232 lldpctl_k_chassis_id_subtype));
233 tag_data(w, lldpctl_atom_get_str(neighbor,
234 lldpctl_k_chassis_id));
235 tag_end(w);
236 tag_datatag(w, "name", "SysName",
237 lldpctl_atom_get_str(neighbor, lldpctl_k_chassis_name));
238 if (details == DISPLAY_BRIEF) {
239 tag_end(w);
240 return;
241 }
242 tag_datatag(w, "descr", "SysDescr",
243 lldpctl_atom_get_str(neighbor, lldpctl_k_chassis_descr));
244
245 /* Management addresses */
246 mgmts = lldpctl_atom_get(neighbor, lldpctl_k_chassis_mgmt);
247 lldpctl_atom_foreach(mgmts, mgmt) {
248 tag_datatag(w, "mgmt-ip", "MgmtIP",
249 lldpctl_atom_get_str(mgmt, lldpctl_k_mgmt_ip));
250 }
251 lldpctl_atom_dec_ref(mgmts);
252
253 /* Capabilities */
254 display_cap(w, neighbor, LLDP_CAP_OTHER, "Other");
255 display_cap(w, neighbor, LLDP_CAP_REPEATER, "Repeater");
256 display_cap(w, neighbor, LLDP_CAP_BRIDGE, "Bridge");
257 display_cap(w, neighbor, LLDP_CAP_ROUTER, "Router");
258 display_cap(w, neighbor, LLDP_CAP_WLAN, "Wlan");
259 display_cap(w, neighbor, LLDP_CAP_TELEPHONE, "Tel");
260 display_cap(w, neighbor, LLDP_CAP_DOCSIS, "Docsis");
261 display_cap(w, neighbor, LLDP_CAP_STATION, "Station");
262
263 tag_end(w);
264 }
265
266 static void
267 display_autoneg(struct writer * w, int advertised, int bithd, int bitfd, char *desc)
268 {
269 if (!((advertised & bithd) ||
270 (advertised & bitfd)))
271 return;
272
273 tag_start(w, "advertised", "Adv");
274 tag_attr(w, "type", "", desc);
275 if (bitfd != bithd) {
276 tag_attr(w, "hd", "HD", (advertised & bithd)?"yes":"no");
277 tag_attr(w, "fd", "FD", (advertised & bitfd)?"yes":"no");
278 }
279 tag_end (w);
280 }
281
282 static void
283 display_port(struct writer *w, lldpctl_atom_t *port, int details)
284 {
285 tag_start(w, "port", "Port");
286 tag_start(w, "id", "PortID");
287 tag_attr (w, "type", "",
288 lldpctl_atom_get_str(port, lldpctl_k_port_id_subtype));
289 tag_data(w, lldpctl_atom_get_str(port, lldpctl_k_port_id));
290 tag_end(w);
291
292 tag_datatag(w, "descr", "PortDescr",
293 lldpctl_atom_get_str(port, lldpctl_k_port_descr));
294
295 /* Dot3 */
296 if (details == DISPLAY_DETAILS) {
297 tag_datatag(w, "mfs", "MFS",
298 lldpctl_atom_get_str(port, lldpctl_k_port_dot3_mfs));
299 tag_datatag(w, "aggregation", " Port is aggregated. PortAggregID",
300 lldpctl_atom_get_str(port, lldpctl_k_port_dot3_aggregid));
301
302 long int autoneg_support, autoneg_enabled, autoneg_advertised;
303 autoneg_support = lldpctl_atom_get_int(port,
304 lldpctl_k_port_dot3_autoneg_support);
305 autoneg_enabled = lldpctl_atom_get_int(port,
306 lldpctl_k_port_dot3_autoneg_enabled);
307 autoneg_advertised = lldpctl_atom_get_int(port,
308 lldpctl_k_port_dot3_autoneg_advertised);
309 if (autoneg_support > 0 || autoneg_enabled > 0) {
310 tag_start(w, "auto-negotiation", "PMD autoneg");
311 tag_attr (w, "supported", "supported",
312 (autoneg_support > 0)?"yes":"no");
313 tag_attr (w, "enabled", "enabled",
314 (autoneg_enabled > 0)?"yes":"no");
315
316 if (autoneg_enabled > 0) {
317 if (autoneg_advertised < 0)
318 autoneg_advertised = 0;
319 display_autoneg(w, autoneg_advertised,
320 LLDP_DOT3_LINK_AUTONEG_10BASE_T,
321 LLDP_DOT3_LINK_AUTONEG_10BASET_FD,
322 "10Base-T");
323 display_autoneg(w, autoneg_advertised,
324 LLDP_DOT3_LINK_AUTONEG_100BASE_TX,
325 LLDP_DOT3_LINK_AUTONEG_100BASE_TXFD,
326 "100Base-TX");
327 display_autoneg(w, autoneg_advertised,
328 LLDP_DOT3_LINK_AUTONEG_100BASE_T2,
329 LLDP_DOT3_LINK_AUTONEG_100BASE_T2FD,
330 "100Base-T2");
331 display_autoneg(w, autoneg_advertised,
332 LLDP_DOT3_LINK_AUTONEG_100BASE_T4,
333 LLDP_DOT3_LINK_AUTONEG_100BASE_T4,
334 "100Base-T4");
335 display_autoneg(w, autoneg_advertised,
336 LLDP_DOT3_LINK_AUTONEG_1000BASE_X,
337 LLDP_DOT3_LINK_AUTONEG_1000BASE_XFD,
338 "1000Base-X");
339 display_autoneg(w, autoneg_advertised,
340 LLDP_DOT3_LINK_AUTONEG_1000BASE_T,
341 LLDP_DOT3_LINK_AUTONEG_1000BASE_TFD,
342 "1000Base-T");
343 }
344 tag_datatag(w, "current", "MAU oper type",
345 lldpctl_atom_get_str(port, lldpctl_k_port_dot3_mautype));
346 tag_end(w);
347 }
348
349 lldpctl_atom_t *dot3_power = lldpctl_atom_get(port,
350 lldpctl_k_port_dot3_power);
351 int devicetype = lldpctl_atom_get_int(dot3_power,
352 lldpctl_k_dot3_power_devicetype);
353 if (devicetype > 0) {
354 tag_start(w, "power", "MDI Power");
355 tag_attr(w, "supported", "supported",
356 (lldpctl_atom_get_int(dot3_power,
357 lldpctl_k_dot3_power_supported) > 0)?"yes":"no");
358 tag_attr(w, "enabled", "enabled",
359 (lldpctl_atom_get_int(dot3_power,
360 lldpctl_k_dot3_power_enabled) > 0)?"yes":"no");
361 tag_attr(w, "paircontrol", "pair control",
362 (lldpctl_atom_get_int(dot3_power,
363 lldpctl_k_dot3_power_paircontrol) > 0)?"yes":"no");
364 tag_start(w, "device-type", "Device type");
365 tag_data(w, lldpctl_atom_get_str(dot3_power,
366 lldpctl_k_dot3_power_devicetype));;
367 tag_end(w);
368 tag_start(w, "pairs", "Power pairs");
369 tag_data(w, lldpctl_atom_get_str(dot3_power,
370 lldpctl_k_dot3_power_pairs));
371 tag_end(w);
372 tag_start(w, "class", "Class");
373 tag_data(w, lldpctl_atom_get_str(dot3_power,
374 lldpctl_k_dot3_power_class));
375 tag_end(w);
376
377 /* 802.3at */
378 if (lldpctl_atom_get_int(dot3_power,
379 lldpctl_k_dot3_power_type) > LLDP_DOT3_POWER_8023AT_OFF) {
380 tag_start(w, "power-type", "Power type");
381 tag_data(w, lldpctl_atom_get_str(dot3_power,
382 lldpctl_k_dot3_power_type));
383 tag_end(w);
384
385 tag_start(w, "source", "Power Source");
386 tag_data(w, lldpctl_atom_get_str(dot3_power,
387 lldpctl_k_dot3_power_source));
388 tag_end(w);
389
390 tag_start(w, "priority", "Power Priority");
391 tag_data(w, lldpctl_atom_get_str(dot3_power,
392 lldpctl_k_dot3_power_priority));
393 tag_end(w);
394
395 tag_start(w, "requested", "PD requested power Value");
396 tag_data(w, lldpctl_atom_get_str(dot3_power,
397 lldpctl_k_dot3_power_requested));
398 tag_end(w);
399
400 tag_start(w, "allocated", "PSE allocated power Value");
401 tag_data(w, lldpctl_atom_get_str(dot3_power,
402 lldpctl_k_dot3_power_allocated));
403 tag_end(w);
404 }
405
406 tag_end(w);
407 }
408 lldpctl_atom_dec_ref(dot3_power);
409 }
410
411 tag_end(w);
412 }
413
414 static void
415 display_vlans(struct writer *w, lldpctl_atom_t *port)
416 {
417 lldpctl_atom_t *vlans, *vlan;
418 int foundpvid = 0;
419 int pvid, vid;
420
421 pvid = lldpctl_atom_get_int(port,
422 lldpctl_k_port_vlan_pvid);
423
424 vlans = lldpctl_atom_get(port, lldpctl_k_port_vlans);
425 lldpctl_atom_foreach(vlans, vlan) {
426 vid = lldpctl_atom_get_int(vlan,
427 lldpctl_k_vlan_id);
428 if (pvid == vid)
429 foundpvid = 1;
430
431 tag_start(w, "vlan", "VLAN");
432 tag_attr(w, "vlan-id", "",
433 lldpctl_atom_get_str(vlan, lldpctl_k_vlan_id));
434 if (pvid == vid)
435 tag_attr(w, "pvid", "pvid", "yes");
436 tag_data(w, lldpctl_atom_get_str(vlan,
437 lldpctl_k_vlan_name));
438 tag_end(w);
439 }
440 lldpctl_atom_dec_ref(vlans);
441
442 if (!foundpvid && pvid > 0) {
443 tag_start(w, "vlan", "VLAN");
444 tag_attr(w, "vlan-id", "",
445 lldpctl_atom_get_str(port,
446 lldpctl_k_port_vlan_pvid));
447 tag_attr(w, "pvid", "pvid", "yes");
448 tag_end(w);
449 }
450 }
451
452 static void
453 display_ppvids(struct writer *w, lldpctl_atom_t *port)
454 {
455 lldpctl_atom_t *ppvids, *ppvid;
456 ppvids = lldpctl_atom_get(port, lldpctl_k_port_ppvids);
457 lldpctl_atom_foreach(ppvids, ppvid) {
458 int status = lldpctl_atom_get_int(ppvid,
459 lldpctl_k_ppvid_status);
460 tag_start(w, "ppvid", "PPVID");
461 if (lldpctl_atom_get_int(ppvid,
462 lldpctl_k_ppvid_id) > 0)
463 tag_attr(w, "value", "",
464 lldpctl_atom_get_str(ppvid,
465 lldpctl_k_ppvid_id));
466 tag_attr(w, "supported", "supported",
467 (status & LLDP_PPVID_CAP_SUPPORTED)?"yes":"no");
468 tag_attr(w, "enabled", "enabled",
469 (status & LLDP_PPVID_CAP_ENABLED)?"yes":"no");
470 tag_end(w);
471 }
472 lldpctl_atom_dec_ref(ppvids);
473 }
474
475 static void
476 display_pids(struct writer *w, lldpctl_atom_t *port)
477 {
478 lldpctl_atom_t *pids, *pid;
479 pids = lldpctl_atom_get(port, lldpctl_k_port_pis);
480 lldpctl_atom_foreach(pids, pid) {
481 const char *pi = lldpctl_atom_get_str(pid, lldpctl_k_pi_id);
482 if (pi && strlen(pi) > 0)
483 tag_datatag(w, "pi", "PI", pi);
484 }
485 lldpctl_atom_dec_ref(pids);
486 }
487
488 static const char*
489 display_age(time_t lastchange)
490 {
491 static char sage[30];
492 int age = (int)(time(NULL) - lastchange);
493 if (snprintf(sage, sizeof(sage),
494 "%d day%s, %02d:%02d:%02d",
495 age / (60*60*24),
496 (age / (60*60*24) > 1)?"s":"",
497 (age / (60*60)) % 24,
498 (age / 60) % 60,
499 age % 60) >= sizeof(sage))
500 return "too much";
501 else
502 return sage;
503 }
504
505 void
506 display_interface(lldpctl_conn_t *conn, struct writer *w, int hidden,
507 lldpctl_atom_t *iface, lldpctl_atom_t *neighbor, int details)
508 {
509 if (!hidden &&
510 lldpctl_atom_get_int(neighbor, lldpctl_k_port_hidden))
511 return;
512
513 tag_start(w, "interface", "Interface");
514 tag_attr(w, "name", "",
515 lldpctl_atom_get_str(iface, lldpctl_k_interface_name));
516 tag_attr(w, "via" , "via",
517 lldpctl_atom_get_str(neighbor, lldpctl_k_port_protocol));
518 if (details > DISPLAY_BRIEF) {
519 tag_attr(w, "rid" , "RID",
520 lldpctl_atom_get_str(neighbor, lldpctl_k_chassis_index));
521 tag_attr(w, "age" , "Time",
522 display_age(lldpctl_atom_get_int(neighbor, lldpctl_k_port_age)));
523 }
524
525 display_chassis(w, neighbor, details);
526 display_port(w, neighbor, details);
527 if (details == DISPLAY_DETAILS) {
528 display_vlans(w, neighbor);
529 display_ppvids(w, neighbor);
530 display_pids(w, neighbor);
531 display_med(w, neighbor);
532 }
533
534 tag_end(w);
535 }
536
537 /**
538 * Display information about interfaces.
539 *
540 * @param conn Connection to lldpd.
541 * @param w Writer.
542 * @param hidden Whatever to show hidden ports.
543 * @param env Environment from which we may find the list of ports.
544 * @param details Level of details we need (DISPLAY_*).
545 */
546 void
547 display_interfaces(lldpctl_conn_t *conn, struct writer *w,
548 struct cmd_env *env,
549 int hidden, int details)
550 {
551 lldpctl_atom_t *iface;
552
553 tag_start(w, "lldp", "LLDP neighbors");
554 while ((iface = cmd_iterate_on_interfaces(conn, env))) {
555 lldpctl_atom_t *port;
556 lldpctl_atom_t *neighbors;
557 lldpctl_atom_t *neighbor;
558 port = lldpctl_get_port(iface);
559 neighbors = lldpctl_atom_get(port, lldpctl_k_port_neighbors);
560 lldpctl_atom_foreach(neighbors, neighbor) {
561 display_interface(conn, w, hidden, iface, neighbor, details);
562 }
563 lldpctl_atom_dec_ref(neighbors);
564 lldpctl_atom_dec_ref(port);
565 }
566 tag_end(w);
567 }
568
569 void
570 display_stat(struct writer *w, const char *tag, const char *descr,
571 long unsigned int cnt)
572 {
573 char buf[20] = {};
574
575 tag_start(w, tag, descr);
576 snprintf(buf, sizeof(buf), "%lu", cnt );
577 tag_attr(w, tag, "", buf);
578 tag_end(w);
579 }
580
581 void
582 display_interface_stats(lldpctl_conn_t *conn, struct writer *w,
583 lldpctl_atom_t *port)
584 {
585 tag_start(w, "interface", "Interface");
586 tag_attr(w, "name", "",
587 lldpctl_atom_get_str(port, lldpctl_k_port_name));
588
589 display_stat(w, "tx", "Transmitted",
590 lldpctl_atom_get_int(port, lldpctl_k_tx_cnt));
591 display_stat(w, "rx", "Received",
592 lldpctl_atom_get_int(port, lldpctl_k_rx_cnt));
593
594 display_stat(w, "rx_discarded_cnt", "Discarded",
595 lldpctl_atom_get_int(port,
596 lldpctl_k_rx_discarded_cnt));
597
598 display_stat(w, "rx_unrecognized_cnt", "Unrecognized",
599 lldpctl_atom_get_int(port,
600 lldpctl_k_rx_unrecognized_cnt));
601
602 display_stat(w, "ageout_cnt", "Ageout",
603 lldpctl_atom_get_int(port,
604 lldpctl_k_ageout_cnt));
605
606 display_stat(w, "insert_cnt", "Inserted",
607 lldpctl_atom_get_int(port,
608 lldpctl_k_insert_cnt));
609
610 display_stat(w, "delete_cnt", "Deleted",
611 lldpctl_atom_get_int(port,
612 lldpctl_k_delete_cnt));
613
614 tag_end(w);
615 }
616
617 /**
618 * Display interface stats
619 *
620 * @param conn Connection to lldpd.
621 * @param w Writer.
622 * @param hidden Whatever to show hidden ports.
623 * @param env Environment from which we may find the list of ports.
624 * @param details Level of details we need (DISPLAY_*).
625 */
626 void
627 display_interfaces_stats(lldpctl_conn_t *conn, struct writer *w,
628 struct cmd_env *env)
629 {
630 lldpctl_atom_t *iface;
631 int summary = 0;
632 u_int64_t h_tx_cnt = 0;
633 u_int64_t h_rx_cnt = 0;
634 u_int64_t h_rx_discarded_cnt = 0;
635 u_int64_t h_rx_unrecognized_cnt = 0;
636 u_int64_t h_ageout_cnt = 0;
637 u_int64_t h_insert_cnt = 0;
638 u_int64_t h_delete_cnt = 0;
639
640 if (cmdenv_get(env, "summary"))
641 summary = 1;
642
643 tag_start(w, "lldp", (summary ? "LLDP Global statistics" :
644 "LLDP statistics"));
645 while ((iface = cmd_iterate_on_interfaces(conn, env))) {
646 lldpctl_atom_t *port;
647 port = lldpctl_get_port(iface);
648 if (!summary)
649 display_interface_stats(conn, w, port);
650 else {
651 h_tx_cnt += lldpctl_atom_get_int(port,
652 lldpctl_k_tx_cnt);
653 h_rx_cnt += lldpctl_atom_get_int(port,
654 lldpctl_k_rx_cnt);
655 h_rx_discarded_cnt += lldpctl_atom_get_int(port,
656 lldpctl_k_rx_discarded_cnt);
657 h_rx_unrecognized_cnt += lldpctl_atom_get_int(port,
658 lldpctl_k_rx_unrecognized_cnt);
659 h_ageout_cnt += lldpctl_atom_get_int(port,
660 lldpctl_k_ageout_cnt);
661 h_insert_cnt += lldpctl_atom_get_int(port,
662 lldpctl_k_insert_cnt);
663 h_delete_cnt += lldpctl_atom_get_int(port,
664 lldpctl_k_delete_cnt);
665 }
666 }
667
668 if (summary) {
669 tag_start(w, "summary", "Summary of stats");
670 display_stat(w, "tx", "Transmitted", h_tx_cnt);
671 display_stat(w, "rx", "Received", h_rx_cnt);
672 display_stat(w, "rx_discarded_cnt", "Discarded",
673 h_rx_discarded_cnt);
674
675 display_stat(w, "rx_unrecognized_cnt", "Unrecognized",
676 h_rx_unrecognized_cnt);
677
678 display_stat(w, "ageout_cnt", "Ageout", h_ageout_cnt);
679
680 display_stat(w, "insert_cnt", "Inserted", h_insert_cnt);
681
682 display_stat(w, "delete_cnt", "Deleted", h_delete_cnt);
683 tag_end(w);
684 }
685 tag_end(w);
686 }
687
688 static const char *
689 N(const char *str) {
690 if (str == NULL || strlen(str) == 0) return "(none)";
691 return str;
692 }
693
694 void
695 display_configuration(lldpctl_conn_t *conn, struct writer *w)
696 {
697 lldpctl_atom_t *configuration;
698
699 configuration = lldpctl_get_configuration(conn);
700 if (!configuration) {
701 log_warnx("lldpctl", "not able to get configuration. %s",
702 lldpctl_last_strerror(conn));
703 return;
704 }
705
706 tag_start(w, "configuration", "Global configuration");
707 tag_start(w, "config", "Configuration");
708
709 tag_datatag(w, "tx-delay", "Transmit delay",
710 lldpctl_atom_get_str(configuration, lldpctl_k_config_tx_interval));
711 tag_datatag(w, "tx-hold", "Transmit hold",
712 lldpctl_atom_get_str(configuration, lldpctl_k_config_tx_hold));
713 tag_datatag(w, "rx-only", "Receive mode",
714 lldpctl_atom_get_int(configuration, lldpctl_k_config_receiveonly)?
715 "yes":"no");
716 tag_datatag(w, "mgmt-pattern", "Pattern for management addresses",
717 N(lldpctl_atom_get_str(configuration, lldpctl_k_config_mgmt_pattern)));
718 tag_datatag(w, "iface-pattern", "Interface pattern",
719 N(lldpctl_atom_get_str(configuration, lldpctl_k_config_iface_pattern)));
720 tag_datatag(w, "cid-pattern", "Interface pattern for chassis ID",
721 N(lldpctl_atom_get_str(configuration, lldpctl_k_config_cid_pattern)));
722 tag_datatag(w, "description", "Override description with",
723 N(lldpctl_atom_get_str(configuration, lldpctl_k_config_description)));
724 tag_datatag(w, "platform", "Override platform with",
725 N(lldpctl_atom_get_str(configuration, lldpctl_k_config_platform)));
726 tag_datatag(w, "hostname", "Override system name with",
727 N(lldpctl_atom_get_str(configuration, lldpctl_k_config_hostname)));
728 tag_datatag(w, "advertise-version", "Advertise version",
729 lldpctl_atom_get_int(configuration, lldpctl_k_config_advertise_version)?
730 "yes":"no");
731 tag_datatag(w, "ifdescr-update", "Update interface descriptions",
732 lldpctl_atom_get_int(configuration, lldpctl_k_config_ifdescr_update)?
733 "yes":"no");
734 tag_datatag(w, "lldpmed-no-inventory", "Disable LLDP-MED inventory",
735 (lldpctl_atom_get_int(configuration, lldpctl_k_config_lldpmed_noinventory) == 0)?
736 "no":"yes");
737 tag_datatag(w, "lldpmed-faststart", "LLDP-MED fast start mechanism",
738 (lldpctl_atom_get_int(configuration, lldpctl_k_config_fast_start_enabled) == 0)?
739 "no":"yes");
740 tag_datatag(w, "lldpmed-faststart-interval", "LLDP-MED fast start interval",
741 N(lldpctl_atom_get_str(configuration, lldpctl_k_config_fast_start_interval)));
742 tag_datatag(w, "bond-slave-src-mac-type",
743 "Source MAC for LLDP frames on bond slaves",
744 lldpctl_atom_get_str(configuration,
745 lldpctl_k_config_bond_slave_src_mac_type));
746
747 tag_end(w);
748 tag_end(w);
749
750 lldpctl_atom_dec_ref(configuration);
751 }