1 /* -*- mode: c; c-file-style: "openbsd" -*- */
3 * Copyright (c) 2008 Vincent Bernat <bernat@luffy.cx>
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.
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.
24 #include <sys/types.h>
25 #include <sys/socket.h>
27 #include <arpa/inet.h>
34 display_cap(struct writer
* w
, lldpctl_atom_t
*chassis
, u_int8_t bit
, char *symbol
)
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
)?
47 display_med_capability(struct writer
*w
, long int available
, int cap
,
50 if (available
& cap
) {
51 tag_start(w
, "capability", "Capability");
52 tag_attr(w
, "type", "", symbol
);
53 tag_attr(w
, "available", "", "yes");
59 display_med(struct writer
*w
, lldpctl_atom_t
*port
, lldpctl_atom_t
*chassis
)
61 lldpctl_atom_t
*medpolicies
, *medpolicy
;
62 lldpctl_atom_t
*medlocations
, *medlocation
;
63 lldpctl_atom_t
*caelements
, *caelement
;
64 lldpctl_atom_t
*medpower
;
65 long int cap
= lldpctl_atom_get_int(chassis
, lldpctl_k_chassis_med_cap
);
68 if (lldpctl_atom_get_int(chassis
, lldpctl_k_chassis_med_type
) <= 0)
71 tag_start(w
, "lldp-med", "LLDP-MED");
73 tag_datatag(w
, "device-type", "Device Type",
74 lldpctl_atom_get_str(chassis
, lldpctl_k_chassis_med_type
));
76 display_med_capability(w
, cap
, LLDP_MED_CAP_CAP
, "Capabilities");
77 display_med_capability(w
, cap
, LLDP_MED_CAP_POLICY
, "Policy");
78 display_med_capability(w
, cap
, LLDP_MED_CAP_LOCATION
, "Location");
79 display_med_capability(w
, cap
, LLDP_MED_CAP_MDI_PSE
, "MDI/PSE");
80 display_med_capability(w
, cap
, LLDP_MED_CAP_MDI_PD
, "MDI/PD");
81 display_med_capability(w
, cap
, LLDP_MED_CAP_IV
, "Inventory");
83 /* LLDP MED policies */
84 medpolicies
= lldpctl_atom_get(port
, lldpctl_k_port_med_policies
);
85 lldpctl_atom_foreach(medpolicies
, medpolicy
) {
86 if (lldpctl_atom_get_int(medpolicy
,
87 lldpctl_k_med_policy_type
) <= 0) continue;
89 tag_start(w
, "policy", "LLDP-MED Network Policy for");
90 tag_attr(w
, "apptype", "", lldpctl_atom_get_str(medpolicy
, lldpctl_k_med_policy_type
));
91 tag_attr(w
, "defined", "Defined",
92 (lldpctl_atom_get_int(medpolicy
,
93 lldpctl_k_med_policy_unknown
) > 0)?"no":"yes");
95 if (lldpctl_atom_get_int(medpolicy
,
96 lldpctl_k_med_policy_tagged
) > 0) {
97 int vid
= lldpctl_atom_get_int(medpolicy
,
98 lldpctl_k_med_policy_vid
);
99 tag_start(w
, "vlan", "VLAN");
101 tag_attr(w
, "vid", "", "priority");
102 } else if (vid
== 4095) {
103 tag_attr(w
, "vid", "", "reserved");
105 tag_attr(w
, "vid", "",
106 lldpctl_atom_get_str(medpolicy
,
107 lldpctl_k_med_policy_vid
));
112 tag_datatag(w
, "priority", "Priority",
113 lldpctl_atom_get_str(medpolicy
,
114 lldpctl_k_med_policy_priority
));
115 /* Also give a numeric value */
116 int pcp
= lldpctl_atom_get_int(medpolicy
,
117 lldpctl_k_med_policy_priority
);
118 char spcp
[2] = { pcp
+ '0', '\0' };
119 tag_datatag(w
, "pcp", "PCP", spcp
);
120 tag_datatag(w
, "dscp", "DSCP Value",
121 lldpctl_atom_get_str(medpolicy
,
122 lldpctl_k_med_policy_dscp
));
126 lldpctl_atom_dec_ref(medpolicies
);
128 /* LLDP MED locations */
129 medlocations
= lldpctl_atom_get(port
, lldpctl_k_port_med_locations
);
130 lldpctl_atom_foreach(medlocations
, medlocation
) {
131 int format
= lldpctl_atom_get_int(medlocation
,
132 lldpctl_k_med_location_format
);
133 if (format
<= 0) continue;
134 tag_start(w
, "location", "LLDP-MED Location Identification");
135 tag_attr(w
, "type", "Type",
136 lldpctl_atom_get_str(medlocation
,
137 lldpctl_k_med_location_format
));
140 case LLDP_MED_LOCFORMAT_COORD
:
141 tag_attr(w
, "geoid", "Geoid",
142 lldpctl_atom_get_str(medlocation
,
143 lldpctl_k_med_location_geoid
));
144 tag_datatag(w
, "lat", "Latitude",
145 lldpctl_atom_get_str(medlocation
,
146 lldpctl_k_med_location_latitude
));
147 tag_datatag(w
, "lon", "Longitude",
148 lldpctl_atom_get_str(medlocation
,
149 lldpctl_k_med_location_longitude
));
150 tag_start(w
, "altitude", "Altitude");
151 tag_attr(w
, "unit", "", lldpctl_atom_get_str(medlocation
,
152 lldpctl_k_med_location_altitude_unit
));
153 tag_data(w
, lldpctl_atom_get_str(medlocation
,
154 lldpctl_k_med_location_altitude
));
157 case LLDP_MED_LOCFORMAT_CIVIC
:
158 tag_datatag(w
, "country", "Country",
159 lldpctl_atom_get_str(medlocation
,
160 lldpctl_k_med_location_country
));
161 caelements
= lldpctl_atom_get(medlocation
,
162 lldpctl_k_med_location_ca_elements
);
163 lldpctl_atom_foreach(caelements
, caelement
) {
164 type
= lldpctl_atom_get_str(caelement
,
165 lldpctl_k_med_civicaddress_type
);
166 tag_datatag(w
, totag(type
), type
,
167 lldpctl_atom_get_str(caelement
,
168 lldpctl_k_med_civicaddress_value
));
170 lldpctl_atom_dec_ref(caelements
);
172 case LLDP_MED_LOCFORMAT_ELIN
:
173 tag_datatag(w
, "ecs", "ECS ELIN",
174 lldpctl_atom_get_str(medlocation
,
175 lldpctl_k_med_location_elin
));
181 lldpctl_atom_dec_ref(medlocations
);
184 medpower
= lldpctl_atom_get(port
, lldpctl_k_port_med_power
);
185 if (lldpctl_atom_get_int(medpower
, lldpctl_k_med_power_type
) > 0) {
186 tag_start(w
, "poe", "Extended Power-over-Ethernet");
188 tag_datatag(w
, "device-type", "Power Type & Source",
189 lldpctl_atom_get_str(medpower
, lldpctl_k_med_power_type
));
190 tag_datatag(w
, "source", "Power Source",
191 lldpctl_atom_get_str(medpower
, lldpctl_k_med_power_source
));
192 tag_datatag(w
, "priority", "Power priority",
193 lldpctl_atom_get_str(medpower
, lldpctl_k_med_power_priority
));
194 tag_datatag(w
, "power", "Power Value",
195 lldpctl_atom_get_str(medpower
, lldpctl_k_med_power_val
));
199 lldpctl_atom_dec_ref(medpower
);
201 /* LLDP MED inventory */
203 const char *hw
= lldpctl_atom_get_str(chassis
,
204 lldpctl_k_chassis_med_inventory_hw
);
205 const char *sw
= lldpctl_atom_get_str(chassis
,
206 lldpctl_k_chassis_med_inventory_sw
);
207 const char *fw
= lldpctl_atom_get_str(chassis
,
208 lldpctl_k_chassis_med_inventory_fw
);
209 const char *sn
= lldpctl_atom_get_str(chassis
,
210 lldpctl_k_chassis_med_inventory_sn
);
211 const char *manuf
= lldpctl_atom_get_str(chassis
,
212 lldpctl_k_chassis_med_inventory_manuf
);
213 const char *model
= lldpctl_atom_get_str(chassis
,
214 lldpctl_k_chassis_med_inventory_model
);
215 const char *asset
= lldpctl_atom_get_str(chassis
,
216 lldpctl_k_chassis_med_inventory_asset
);
217 if (!(hw
|| sw
|| fw
|| sn
||
218 manuf
|| model
|| asset
)) break;
220 tag_start(w
, "inventory", "Inventory");
221 tag_datatag(w
, "hardware", "Hardware Revision", hw
);
222 tag_datatag(w
, "software", "Software Revision", sw
);
223 tag_datatag(w
, "firmware", "Firmware Revision", fw
);
224 tag_datatag(w
, "serial", "Serial Number", sn
);
225 tag_datatag(w
, "manufacturer", "Manufacturer", manuf
);
226 tag_datatag(w
, "model", "Model", model
);
227 tag_datatag(w
, "asset", "Asset ID", asset
);
235 display_chassis(struct writer
* w
, lldpctl_atom_t
* chassis
, int details
)
237 lldpctl_atom_t
*mgmts
, *mgmt
;
239 tag_start(w
, "chassis", "Chassis");
240 tag_start(w
, "id", "ChassisID");
241 tag_attr (w
, "type", "",
242 lldpctl_atom_get_str(chassis
,
243 lldpctl_k_chassis_id_subtype
));
244 tag_data(w
, lldpctl_atom_get_str(chassis
,
245 lldpctl_k_chassis_id
));
247 tag_datatag(w
, "name", "SysName",
248 lldpctl_atom_get_str(chassis
, lldpctl_k_chassis_name
));
249 if (details
== DISPLAY_BRIEF
) {
253 tag_datatag(w
, "descr", "SysDescr",
254 lldpctl_atom_get_str(chassis
, lldpctl_k_chassis_descr
));
256 /* Management addresses */
257 mgmts
= lldpctl_atom_get(chassis
, lldpctl_k_chassis_mgmt
);
258 lldpctl_atom_foreach(mgmts
, mgmt
) {
259 tag_datatag(w
, "mgmt-ip", "MgmtIP",
260 lldpctl_atom_get_str(mgmt
, lldpctl_k_mgmt_ip
));
262 lldpctl_atom_dec_ref(mgmts
);
265 display_cap(w
, chassis
, LLDP_CAP_OTHER
, "Other");
266 display_cap(w
, chassis
, LLDP_CAP_REPEATER
, "Repeater");
267 display_cap(w
, chassis
, LLDP_CAP_BRIDGE
, "Bridge");
268 display_cap(w
, chassis
, LLDP_CAP_ROUTER
, "Router");
269 display_cap(w
, chassis
, LLDP_CAP_WLAN
, "Wlan");
270 display_cap(w
, chassis
, LLDP_CAP_TELEPHONE
, "Tel");
271 display_cap(w
, chassis
, LLDP_CAP_DOCSIS
, "Docsis");
272 display_cap(w
, chassis
, LLDP_CAP_STATION
, "Station");
278 display_custom_tlvs(struct writer
* w
, lldpctl_atom_t
* neighbor
)
280 lldpctl_atom_t
*custom_list
, *custom
;
281 int have_custom_tlvs
= 0;
283 const uint8_t *oui
, *oui_info
;
284 char buf
[1600]; /* should be enough for printing */
286 custom_list
= lldpctl_atom_get(neighbor
, lldpctl_k_custom_tlvs
);
287 lldpctl_atom_foreach(custom_list
, custom
) {
288 /* This tag gets added only once, if there are any custom TLVs */
289 if (!have_custom_tlvs
) {
290 tag_start(w
, "unknown-tlvs", "Unknown TLVs");
294 oui
= lldpctl_atom_get_buffer(custom
, lldpctl_k_custom_tlv_oui
, &len
);
296 oui_info
= lldpctl_atom_get_buffer(custom
, lldpctl_k_custom_tlv_oui_info_string
, &len
);
299 tag_start(w
, "unknown-tlv", "TLV");
301 /* Add OUI as attribute */
302 snprintf(buf
, sizeof(buf
), "%02X,%02X,%02X", oui
[0], oui
[1], oui
[2]);
303 tag_attr(w
, "oui", "OUI", buf
);
304 snprintf(buf
, sizeof(buf
), "%d",
305 (int)lldpctl_atom_get_int(custom
, lldpctl_k_custom_tlv_oui_subtype
));
306 tag_attr(w
, "subtype", "SubType", buf
);
307 snprintf(buf
, sizeof(buf
), "%d", (int)len
);
308 tag_attr(w
, "len", "Len", buf
);
310 for (slen
=0, i
=0; i
< len
; ++i
)
311 slen
+= snprintf(buf
+ slen
, sizeof(buf
) > slen
? sizeof(buf
) - slen
: 0,
312 "%02X%s", oui_info
[i
], ((i
< len
- 1) ? "," : ""));
317 lldpctl_atom_dec_ref(custom_list
);
319 if (have_custom_tlvs
)
325 display_autoneg(struct writer
* w
, int advertised
, int bithd
, int bitfd
, char *desc
)
327 if (!((advertised
& bithd
) ||
328 (advertised
& bitfd
)))
331 tag_start(w
, "advertised", "Adv");
332 tag_attr(w
, "type", "", desc
);
333 if (bitfd
!= bithd
) {
334 tag_attr(w
, "hd", "HD", (advertised
& bithd
)?"yes":"no");
335 tag_attr(w
, "fd", "FD", (advertised
& bitfd
)?"yes":"no");
341 display_port(struct writer
*w
, lldpctl_atom_t
*port
, int details
)
343 tag_start(w
, "port", "Port");
344 tag_start(w
, "id", "PortID");
345 tag_attr (w
, "type", "",
346 lldpctl_atom_get_str(port
, lldpctl_k_port_id_subtype
));
347 tag_data(w
, lldpctl_atom_get_str(port
, lldpctl_k_port_id
));
350 tag_datatag(w
, "descr", "PortDescr",
351 lldpctl_atom_get_str(port
, lldpctl_k_port_descr
));
353 lldpctl_atom_get_int(port
, lldpctl_k_port_ttl
) > 0)
354 tag_datatag(w
, "ttl", "TTL",
355 lldpctl_atom_get_str(port
, lldpctl_k_port_ttl
));
358 if (details
== DISPLAY_DETAILS
) {
359 tag_datatag(w
, "mfs", "MFS",
360 lldpctl_atom_get_str(port
, lldpctl_k_port_dot3_mfs
));
361 tag_datatag(w
, "aggregation", "Port is aggregated. PortAggregID",
362 lldpctl_atom_get_str(port
, lldpctl_k_port_dot3_aggregid
));
364 long int autoneg_support
, autoneg_enabled
, autoneg_advertised
, mautype
;
365 autoneg_support
= lldpctl_atom_get_int(port
,
366 lldpctl_k_port_dot3_autoneg_support
);
367 autoneg_enabled
= lldpctl_atom_get_int(port
,
368 lldpctl_k_port_dot3_autoneg_enabled
);
369 autoneg_advertised
= lldpctl_atom_get_int(port
,
370 lldpctl_k_port_dot3_autoneg_advertised
);
371 mautype
= lldpctl_atom_get_int(port
, lldpctl_k_port_dot3_mautype
);
372 if (autoneg_support
> 0 || autoneg_enabled
> 0 || mautype
> 0) {
373 tag_start(w
, "auto-negotiation", "PMD autoneg");
374 tag_attr (w
, "supported", "supported",
375 (autoneg_support
> 0)?"yes":"no");
376 tag_attr (w
, "enabled", "enabled",
377 (autoneg_enabled
> 0)?"yes":"no");
379 if (autoneg_enabled
> 0) {
380 if (autoneg_advertised
< 0)
381 autoneg_advertised
= 0;
382 display_autoneg(w
, autoneg_advertised
,
383 LLDP_DOT3_LINK_AUTONEG_10BASE_T
,
384 LLDP_DOT3_LINK_AUTONEG_10BASET_FD
,
386 display_autoneg(w
, autoneg_advertised
,
387 LLDP_DOT3_LINK_AUTONEG_100BASE_TX
,
388 LLDP_DOT3_LINK_AUTONEG_100BASE_TXFD
,
390 display_autoneg(w
, autoneg_advertised
,
391 LLDP_DOT3_LINK_AUTONEG_100BASE_T2
,
392 LLDP_DOT3_LINK_AUTONEG_100BASE_T2FD
,
394 display_autoneg(w
, autoneg_advertised
,
395 LLDP_DOT3_LINK_AUTONEG_100BASE_T4
,
396 LLDP_DOT3_LINK_AUTONEG_100BASE_T4
,
398 display_autoneg(w
, autoneg_advertised
,
399 LLDP_DOT3_LINK_AUTONEG_1000BASE_X
,
400 LLDP_DOT3_LINK_AUTONEG_1000BASE_XFD
,
402 display_autoneg(w
, autoneg_advertised
,
403 LLDP_DOT3_LINK_AUTONEG_1000BASE_T
,
404 LLDP_DOT3_LINK_AUTONEG_1000BASE_TFD
,
407 tag_datatag(w
, "current", "MAU oper type",
408 lldpctl_atom_get_str(port
, lldpctl_k_port_dot3_mautype
));
412 lldpctl_atom_t
*dot3_power
= lldpctl_atom_get(port
,
413 lldpctl_k_port_dot3_power
);
414 int devicetype
= lldpctl_atom_get_int(dot3_power
,
415 lldpctl_k_dot3_power_devicetype
);
416 if (devicetype
> 0) {
417 tag_start(w
, "power", "MDI Power");
418 tag_attr(w
, "supported", "supported",
419 (lldpctl_atom_get_int(dot3_power
,
420 lldpctl_k_dot3_power_supported
) > 0)?"yes":"no");
421 tag_attr(w
, "enabled", "enabled",
422 (lldpctl_atom_get_int(dot3_power
,
423 lldpctl_k_dot3_power_enabled
) > 0)?"yes":"no");
424 tag_attr(w
, "paircontrol", "pair control",
425 (lldpctl_atom_get_int(dot3_power
,
426 lldpctl_k_dot3_power_paircontrol
) > 0)?"yes":"no");
427 tag_start(w
, "device-type", "Device type");
428 tag_data(w
, lldpctl_atom_get_str(dot3_power
,
429 lldpctl_k_dot3_power_devicetype
));;
431 tag_start(w
, "pairs", "Power pairs");
432 tag_data(w
, lldpctl_atom_get_str(dot3_power
,
433 lldpctl_k_dot3_power_pairs
));
435 tag_start(w
, "class", "Class");
436 tag_data(w
, lldpctl_atom_get_str(dot3_power
,
437 lldpctl_k_dot3_power_class
));
441 if (lldpctl_atom_get_int(dot3_power
,
442 lldpctl_k_dot3_power_type
) > LLDP_DOT3_POWER_8023AT_OFF
) {
443 tag_start(w
, "power-type", "Power type");
444 tag_data(w
, lldpctl_atom_get_str(dot3_power
,
445 lldpctl_k_dot3_power_type
));
448 tag_start(w
, "source", "Power Source");
449 tag_data(w
, lldpctl_atom_get_str(dot3_power
,
450 lldpctl_k_dot3_power_source
));
453 tag_start(w
, "priority", "Power Priority");
454 tag_data(w
, lldpctl_atom_get_str(dot3_power
,
455 lldpctl_k_dot3_power_priority
));
458 tag_start(w
, "requested", "PD requested power Value");
459 tag_data(w
, lldpctl_atom_get_str(dot3_power
,
460 lldpctl_k_dot3_power_requested
));
463 tag_start(w
, "allocated", "PSE allocated power Value");
464 tag_data(w
, lldpctl_atom_get_str(dot3_power
,
465 lldpctl_k_dot3_power_allocated
));
471 lldpctl_atom_dec_ref(dot3_power
);
478 display_local_ttl(struct writer
*w
, lldpctl_conn_t
*conn
, int details
)
482 long int tx_interval
;
484 lldpctl_atom_t
*configuration
;
485 configuration
= lldpctl_get_configuration(conn
);
486 if (!configuration
) {
487 log_warnx("lldpctl", "not able to get configuration. %s",
488 lldpctl_last_strerror(conn
));
492 tx_hold
= lldpctl_atom_get_int(configuration
, lldpctl_k_config_tx_hold
);
493 tx_interval
= lldpctl_atom_get_int(configuration
, lldpctl_k_config_tx_interval
);
495 if (asprintf(&ttl
, "%lu", tx_hold
*tx_interval
) == -1) {
496 log_warnx("lldpctl", "not enough memory to build TTL.");
500 tag_start(w
, "ttl", "TTL");
501 tag_attr(w
, "ttl", "", ttl
);
505 lldpctl_atom_dec_ref(configuration
);
510 display_vlans(struct writer
*w
, lldpctl_atom_t
*port
)
512 lldpctl_atom_t
*vlans
, *vlan
;
516 pvid
= lldpctl_atom_get_int(port
,
517 lldpctl_k_port_vlan_pvid
);
519 vlans
= lldpctl_atom_get(port
, lldpctl_k_port_vlans
);
520 lldpctl_atom_foreach(vlans
, vlan
) {
521 vid
= lldpctl_atom_get_int(vlan
,
526 tag_start(w
, "vlan", "VLAN");
527 tag_attr(w
, "vlan-id", "",
528 lldpctl_atom_get_str(vlan
, lldpctl_k_vlan_id
));
530 tag_attr(w
, "pvid", "pvid", "yes");
531 tag_data(w
, lldpctl_atom_get_str(vlan
,
532 lldpctl_k_vlan_name
));
535 lldpctl_atom_dec_ref(vlans
);
537 if (!foundpvid
&& pvid
> 0) {
538 tag_start(w
, "vlan", "VLAN");
539 tag_attr(w
, "vlan-id", "",
540 lldpctl_atom_get_str(port
,
541 lldpctl_k_port_vlan_pvid
));
542 tag_attr(w
, "pvid", "pvid", "yes");
548 display_ppvids(struct writer
*w
, lldpctl_atom_t
*port
)
550 lldpctl_atom_t
*ppvids
, *ppvid
;
551 ppvids
= lldpctl_atom_get(port
, lldpctl_k_port_ppvids
);
552 lldpctl_atom_foreach(ppvids
, ppvid
) {
553 int status
= lldpctl_atom_get_int(ppvid
,
554 lldpctl_k_ppvid_status
);
555 tag_start(w
, "ppvid", "PPVID");
556 if (lldpctl_atom_get_int(ppvid
,
557 lldpctl_k_ppvid_id
) > 0)
558 tag_attr(w
, "value", "",
559 lldpctl_atom_get_str(ppvid
,
560 lldpctl_k_ppvid_id
));
561 tag_attr(w
, "supported", "supported",
562 (status
& LLDP_PPVID_CAP_SUPPORTED
)?"yes":"no");
563 tag_attr(w
, "enabled", "enabled",
564 (status
& LLDP_PPVID_CAP_ENABLED
)?"yes":"no");
567 lldpctl_atom_dec_ref(ppvids
);
571 display_pids(struct writer
*w
, lldpctl_atom_t
*port
)
573 lldpctl_atom_t
*pids
, *pid
;
574 pids
= lldpctl_atom_get(port
, lldpctl_k_port_pis
);
575 lldpctl_atom_foreach(pids
, pid
) {
576 const char *pi
= lldpctl_atom_get_str(pid
, lldpctl_k_pi_id
);
577 if (pi
&& strlen(pi
) > 0)
578 tag_datatag(w
, "pi", "PI", pi
);
580 lldpctl_atom_dec_ref(pids
);
584 display_age(time_t lastchange
)
586 static char sage
[30];
587 int age
= (int)(time(NULL
) - lastchange
);
588 if (snprintf(sage
, sizeof(sage
),
589 "%d day%s, %02d:%02d:%02d",
591 (age
/ (60*60*24) > 1)?"s":"",
592 (age
/ (60*60)) % 24,
594 age
% 60) >= sizeof(sage
))
601 display_local_chassis(lldpctl_conn_t
*conn
, struct writer
*w
,
602 struct cmd_env
*env
, int details
)
604 tag_start(w
, "local-chassis", "Local chassis");
606 lldpctl_atom_t
*chassis
= lldpctl_get_local_chassis(conn
);
607 display_chassis(w
, chassis
, details
);
608 if (details
== DISPLAY_DETAILS
) {
609 display_med(w
, NULL
, chassis
);
611 lldpctl_atom_dec_ref(chassis
);
617 display_interface(lldpctl_conn_t
*conn
, struct writer
*w
, int hidden
,
618 lldpctl_atom_t
*iface
, lldpctl_atom_t
*port
, int details
, int protocol
)
623 lldpctl_atom_get_int(port
, lldpctl_k_port_hidden
))
626 /* user might have specified protocol to filter on display */
627 if ((protocol
!= LLDPD_MODE_MAX
) &&
628 (protocol
!= lldpctl_atom_get_int(port
, lldpctl_k_port_protocol
)))
631 /* Infer local / remote port from the port index (remote == 0) */
632 local
= lldpctl_atom_get_int(port
, lldpctl_k_port_index
)>0?1:0;
634 lldpctl_atom_t
*chassis
= lldpctl_atom_get(port
, lldpctl_k_port_chassis
);
636 tag_start(w
, "interface", "Interface");
637 tag_attr(w
, "name", "",
638 lldpctl_atom_get_str(iface
, lldpctl_k_interface_name
));
639 tag_attr(w
, "via" , "via",
640 lldpctl_atom_get_str(port
, lldpctl_k_port_protocol
));
641 if (details
> DISPLAY_BRIEF
) {
643 tag_attr(w
, "rid" , "RID",
644 lldpctl_atom_get_str(chassis
, lldpctl_k_chassis_index
));
645 tag_attr(w
, "age" , "Time",
646 display_age(lldpctl_atom_get_int(port
, lldpctl_k_port_age
)));
649 display_chassis(w
, chassis
, details
);
650 display_port(w
, port
, details
);
651 if (details
&& local
)
652 display_local_ttl(w
, conn
, details
);
653 if (details
== DISPLAY_DETAILS
) {
654 display_vlans(w
, port
);
655 display_ppvids(w
, port
);
656 display_pids(w
, port
);
657 display_med(w
, port
, chassis
);
660 lldpctl_atom_dec_ref(chassis
);
662 display_custom_tlvs(w
, port
);
668 * Display information about interfaces.
670 * @param conn Connection to lldpd.
672 * @param hidden Whatever to show hidden ports.
673 * @param env Environment from which we may find the list of ports.
674 * @param details Level of details we need (DISPLAY_*).
677 display_interfaces(lldpctl_conn_t
*conn
, struct writer
*w
,
679 int hidden
, int details
)
681 lldpctl_atom_t
*iface
;
682 int protocol
= LLDPD_MODE_MAX
;
683 const char *proto_str
;
685 /* user might have specified protocol to filter display results */
686 proto_str
= cmdenv_get(env
, "protocol");
689 log_debug("display", "filter protocol: %s ", proto_str
);
692 for (lldpctl_map_t
*protocol_map
=
693 lldpctl_key_get_map(lldpctl_k_port_protocol
);
694 protocol_map
->string
;
696 if (!strcasecmp(proto_str
, protocol_map
->string
)) {
697 protocol
= protocol_map
->value
;
703 tag_start(w
, "lldp", "LLDP neighbors");
704 while ((iface
= cmd_iterate_on_interfaces(conn
, env
))) {
705 lldpctl_atom_t
*port
;
706 lldpctl_atom_t
*neighbors
;
707 lldpctl_atom_t
*neighbor
;
708 port
= lldpctl_get_port(iface
);
709 neighbors
= lldpctl_atom_get(port
, lldpctl_k_port_neighbors
);
710 lldpctl_atom_foreach(neighbors
, neighbor
) {
711 display_interface(conn
, w
, hidden
, iface
, neighbor
, details
, protocol
);
713 lldpctl_atom_dec_ref(neighbors
);
714 lldpctl_atom_dec_ref(port
);
721 * Display information about local interfaces.
723 * @param conn Connection to lldpd.
725 * @param hidden Whatever to show hidden ports.
726 * @param env Environment from which we may find the list of ports.
727 * @param details Level of details we need (DISPLAY_*).
730 display_local_interfaces(lldpctl_conn_t
*conn
, struct writer
*w
,
732 int hidden
, int details
)
734 lldpctl_atom_t
*iface
;
735 int protocol
= LLDPD_MODE_MAX
;
737 tag_start(w
, "lldp", "LLDP interfaces");
738 while ((iface
= cmd_iterate_on_interfaces(conn
, env
))) {
739 lldpctl_atom_t
*port
;
740 port
= lldpctl_get_port(iface
);
741 display_interface(conn
, w
, hidden
, iface
, port
, details
, protocol
);
742 lldpctl_atom_dec_ref(port
);
748 display_stat(struct writer
*w
, const char *tag
, const char *descr
,
749 long unsigned int cnt
)
753 tag_start(w
, tag
, descr
);
754 snprintf(buf
, sizeof(buf
), "%lu", cnt
);
755 tag_attr(w
, tag
, "", buf
);
760 display_interface_stats(lldpctl_conn_t
*conn
, struct writer
*w
,
761 lldpctl_atom_t
*port
)
763 tag_start(w
, "interface", "Interface");
764 tag_attr(w
, "name", "",
765 lldpctl_atom_get_str(port
, lldpctl_k_port_name
));
767 display_stat(w
, "tx", "Transmitted",
768 lldpctl_atom_get_int(port
, lldpctl_k_tx_cnt
));
769 display_stat(w
, "rx", "Received",
770 lldpctl_atom_get_int(port
, lldpctl_k_rx_cnt
));
772 display_stat(w
, "rx_discarded_cnt", "Discarded",
773 lldpctl_atom_get_int(port
,
774 lldpctl_k_rx_discarded_cnt
));
776 display_stat(w
, "rx_unrecognized_cnt", "Unrecognized",
777 lldpctl_atom_get_int(port
,
778 lldpctl_k_rx_unrecognized_cnt
));
780 display_stat(w
, "ageout_cnt", "Ageout",
781 lldpctl_atom_get_int(port
,
782 lldpctl_k_ageout_cnt
));
784 display_stat(w
, "insert_cnt", "Inserted",
785 lldpctl_atom_get_int(port
,
786 lldpctl_k_insert_cnt
));
788 display_stat(w
, "delete_cnt", "Deleted",
789 lldpctl_atom_get_int(port
,
790 lldpctl_k_delete_cnt
));
796 * Display interface stats
798 * @param conn Connection to lldpd.
800 * @param env Environment from which we may find the list of ports.
803 display_interfaces_stats(lldpctl_conn_t
*conn
, struct writer
*w
,
806 lldpctl_atom_t
*iface
;
808 u_int64_t h_tx_cnt
= 0;
809 u_int64_t h_rx_cnt
= 0;
810 u_int64_t h_rx_discarded_cnt
= 0;
811 u_int64_t h_rx_unrecognized_cnt
= 0;
812 u_int64_t h_ageout_cnt
= 0;
813 u_int64_t h_insert_cnt
= 0;
814 u_int64_t h_delete_cnt
= 0;
816 if (cmdenv_get(env
, "summary"))
819 tag_start(w
, "lldp", (summary
? "LLDP Global statistics" :
821 while ((iface
= cmd_iterate_on_interfaces(conn
, env
))) {
822 lldpctl_atom_t
*port
;
823 port
= lldpctl_get_port(iface
);
825 display_interface_stats(conn
, w
, port
);
827 h_tx_cnt
+= lldpctl_atom_get_int(port
,
829 h_rx_cnt
+= lldpctl_atom_get_int(port
,
831 h_rx_discarded_cnt
+= lldpctl_atom_get_int(port
,
832 lldpctl_k_rx_discarded_cnt
);
833 h_rx_unrecognized_cnt
+= lldpctl_atom_get_int(port
,
834 lldpctl_k_rx_unrecognized_cnt
);
835 h_ageout_cnt
+= lldpctl_atom_get_int(port
,
836 lldpctl_k_ageout_cnt
);
837 h_insert_cnt
+= lldpctl_atom_get_int(port
,
838 lldpctl_k_insert_cnt
);
839 h_delete_cnt
+= lldpctl_atom_get_int(port
,
840 lldpctl_k_delete_cnt
);
842 lldpctl_atom_dec_ref(port
);
846 tag_start(w
, "summary", "Summary of stats");
847 display_stat(w
, "tx", "Transmitted", h_tx_cnt
);
848 display_stat(w
, "rx", "Received", h_rx_cnt
);
849 display_stat(w
, "rx_discarded_cnt", "Discarded",
852 display_stat(w
, "rx_unrecognized_cnt", "Unrecognized",
853 h_rx_unrecognized_cnt
);
855 display_stat(w
, "ageout_cnt", "Ageout", h_ageout_cnt
);
857 display_stat(w
, "insert_cnt", "Inserted", h_insert_cnt
);
859 display_stat(w
, "delete_cnt", "Deleted", h_delete_cnt
);
867 if (str
== NULL
|| strlen(str
) == 0) return "(none)";
872 display_configuration(lldpctl_conn_t
*conn
, struct writer
*w
)
874 lldpctl_atom_t
*configuration
;
876 configuration
= lldpctl_get_configuration(conn
);
877 if (!configuration
) {
878 log_warnx("lldpctl", "not able to get configuration. %s",
879 lldpctl_last_strerror(conn
));
883 tag_start(w
, "configuration", "Global configuration");
884 tag_start(w
, "config", "Configuration");
886 tag_datatag(w
, "tx-delay", "Transmit delay",
887 lldpctl_atom_get_str(configuration
, lldpctl_k_config_tx_interval
));
888 tag_datatag(w
, "tx-hold", "Transmit hold",
889 lldpctl_atom_get_str(configuration
, lldpctl_k_config_tx_hold
));
890 tag_datatag(w
, "rx-only", "Receive mode",
891 lldpctl_atom_get_int(configuration
, lldpctl_k_config_receiveonly
)?
893 tag_datatag(w
, "mgmt-pattern", "Pattern for management addresses",
894 N(lldpctl_atom_get_str(configuration
, lldpctl_k_config_mgmt_pattern
)));
895 tag_datatag(w
, "iface-pattern", "Interface pattern",
896 N(lldpctl_atom_get_str(configuration
, lldpctl_k_config_iface_pattern
)));
897 tag_datatag(w
, "cid-pattern", "Interface pattern for chassis ID",
898 N(lldpctl_atom_get_str(configuration
, lldpctl_k_config_cid_pattern
)));
899 tag_datatag(w
, "description", "Override description with",
900 N(lldpctl_atom_get_str(configuration
, lldpctl_k_config_description
)));
901 tag_datatag(w
, "platform", "Override platform with",
902 N(lldpctl_atom_get_str(configuration
, lldpctl_k_config_platform
)));
903 tag_datatag(w
, "hostname", "Override system name with",
904 N(lldpctl_atom_get_str(configuration
, lldpctl_k_config_hostname
)));
905 tag_datatag(w
, "advertise-version", "Advertise version",
906 lldpctl_atom_get_int(configuration
, lldpctl_k_config_advertise_version
)?
908 tag_datatag(w
, "ifdescr-update", "Update interface descriptions",
909 lldpctl_atom_get_int(configuration
, lldpctl_k_config_ifdescr_update
)?
911 tag_datatag(w
, "iface-promisc", "Promiscuous mode on managed interfaces",
912 lldpctl_atom_get_int(configuration
, lldpctl_k_config_iface_promisc
)?
914 tag_datatag(w
, "lldpmed-no-inventory", "Disable LLDP-MED inventory",
915 (lldpctl_atom_get_int(configuration
, lldpctl_k_config_lldpmed_noinventory
) == 0)?
917 tag_datatag(w
, "lldpmed-faststart", "LLDP-MED fast start mechanism",
918 (lldpctl_atom_get_int(configuration
, lldpctl_k_config_fast_start_enabled
) == 0)?
920 tag_datatag(w
, "lldpmed-faststart-interval", "LLDP-MED fast start interval",
921 N(lldpctl_atom_get_str(configuration
, lldpctl_k_config_fast_start_interval
)));
922 tag_datatag(w
, "bond-slave-src-mac-type",
923 "Source MAC for LLDP frames on bond slaves",
924 lldpctl_atom_get_str(configuration
,
925 lldpctl_k_config_bond_slave_src_mac_type
));
926 tag_datatag(w
, "lldp-portid-type",
927 "Port ID TLV subtype for LLDP frames",
928 lldpctl_atom_get_str(configuration
,
929 lldpctl_k_config_lldp_portid_type
));
930 tag_datatag(w
, "lldp-agent-type",
932 lldpctl_atom_get_str(configuration
,
933 lldpctl_k_config_lldp_agent_type
));
938 lldpctl_atom_dec_ref(configuration
);