1 /* -*- mode: c; c-file-style: "openbsd" -*- */
3 * Copyright (c) 2015 Vincent Bernat <vincent@bernat.im>
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.
21 #include <arpa/inet.h>
30 static lldpctl_map_t port_dot3_power_devicetype_map
[] = {
31 { LLDP_DOT3_POWER_PSE
, "PSE" },
32 { LLDP_DOT3_POWER_PD
, "PD" },
36 static lldpctl_map_t port_dot3_power_pse_source_map
[] = {
37 { LLDP_DOT3_POWER_SOURCE_BOTH
, "PSE + Local" },
38 { LLDP_DOT3_POWER_SOURCE_PSE
, "PSE" },
42 static lldpctl_map_t port_dot3_power_pd_source_map
[] = {
43 { LLDP_DOT3_POWER_SOURCE_BACKUP
, "Backup source" },
44 { LLDP_DOT3_POWER_SOURCE_PRIMARY
, "Primary power source" },
48 static struct atom_map port_dot3_power_pairs_map
= {
49 .key
= lldpctl_k_dot3_power_pairs
,
51 { LLDP_DOT3_POWERPAIRS_SIGNAL
, "signal" },
52 { LLDP_DOT3_POWERPAIRS_SPARE
, "spare" },
57 static struct atom_map port_dot3_power_class_map
= {
58 .key
= lldpctl_k_dot3_power_class
,
69 static struct atom_map port_dot3_power_priority_map
= {
70 .key
= lldpctl_k_dot3_power_priority
,
73 { LLDP_MED_POW_PRIO_CRITICAL
, "critical" },
74 { LLDP_MED_POW_PRIO_HIGH
, "high" },
75 { LLDP_MED_POW_PRIO_LOW
, "low" },
80 static struct atom_map port_dot3_power_pd_4pid_map
= {
81 .key
= lldpctl_k_dot3_power_pd_4pid
,
83 { 0, "PD does not support powering both modes" },
84 { 1, "PD supports powering both modes" },
88 static struct atom_map port_dot3_power_pse_status_map
= {
89 .key
= lldpctl_k_dot3_power_pse_status
,
92 { 1, "2-pair powering" },
93 { 2, "4-pair powering dual-signature PD" },
94 { 3, "4-pair powering single-signature PD" },
98 static struct atom_map port_dot3_power_pd_status_map
= {
99 .key
= lldpctl_k_dot3_power_pd_status
,
102 { 1, "2-pair powered PD" },
103 { 2, "4-pair powered dual-signature PD" },
104 { 3, "4-pair powered single-signature PD" },
108 static struct atom_map port_dot3_power_pse_pairs_ext_map
= {
109 .key
= lldpctl_k_dot3_power_pse_pairs_ext
,
112 { 1, "Alternative A" },
113 { 2, "Alternative B" },
114 { 3, "Both alternatives" },
118 static struct atom_map port_dot3_power_class_a_map
= {
119 .key
= lldpctl_k_dot3_power_class_a
,
128 { 7, "Single-signature PD or 2-pair only PSE" },
132 static struct atom_map port_dot3_power_class_b_map
= {
133 .key
= lldpctl_k_dot3_power_class_b
,
142 { 7, "Single-signature PD or 2-pair only PSE" },
146 static struct atom_map port_dot3_power_class_ext_map
= {
147 .key
= lldpctl_k_dot3_power_class_ext
,
164 { 15, "Dual-signature PD" },
168 static struct atom_map port_dot3_power_type_ext_map
= {
169 .key
= lldpctl_k_dot3_power_type_ext
,
171 { LLDP_DOT3_POWER_8023BT_OFF
, "802.3bt off" },
174 { 3, "Type 3 single-signature PD" },
175 { 4, "Type 3 dual-signature PD" },
176 { 5, "Type 4 single-signature PD" },
177 { 6, "Type 4 dual-signature PD" },
183 static struct atom_map port_dot3_power_pd_load_map
= {
184 .key
= lldpctl_k_dot3_power_pd_load
,
186 { 0, "PD is single- or dual-signature and power is not "
187 "electrically isolated" },
188 { 1, "PD is dual-signature and power is electrically "
194 ATOM_MAP_REGISTER(port_dot3_power_pairs_map
, 4);
195 ATOM_MAP_REGISTER(port_dot3_power_class_map
, 5);
196 ATOM_MAP_REGISTER(port_dot3_power_priority_map
, 6);
199 _lldpctl_atom_new_dot3_power(lldpctl_atom_t
*atom
, va_list ap
)
201 struct _lldpctl_atom_dot3_power_t
*dpow
=
202 (struct _lldpctl_atom_dot3_power_t
*)atom
;
203 dpow
->parent
= va_arg(ap
, struct _lldpctl_atom_port_t
*);
204 lldpctl_atom_inc_ref((lldpctl_atom_t
*)dpow
->parent
);
209 _lldpctl_atom_free_dot3_power(lldpctl_atom_t
*atom
)
211 struct _lldpctl_atom_dot3_power_t
*dpow
=
212 (struct _lldpctl_atom_dot3_power_t
*)atom
;
213 lldpctl_atom_dec_ref((lldpctl_atom_t
*)dpow
->parent
);
217 _lldpctl_atom_get_str_dot3_power(lldpctl_atom_t
*atom
, lldpctl_key_t key
)
219 struct _lldpctl_atom_dot3_power_t
*dpow
=
220 (struct _lldpctl_atom_dot3_power_t
*)atom
;
221 struct lldpd_port
*port
= dpow
->parent
->port
;
223 /* Local and remote port */
225 case lldpctl_k_dot3_power_devicetype
:
226 return map_lookup(port_dot3_power_devicetype_map
,
227 port
->p_power
.devicetype
);
228 case lldpctl_k_dot3_power_pairs
:
229 return map_lookup(port_dot3_power_pairs_map
.map
,
230 port
->p_power
.pairs
);
231 case lldpctl_k_dot3_power_class
:
232 return map_lookup(port_dot3_power_class_map
.map
,
233 port
->p_power
.class);
234 case lldpctl_k_dot3_power_source
:
235 return map_lookup((port
->p_power
.devicetype
== LLDP_DOT3_POWER_PSE
)?
236 port_dot3_power_pse_source_map
:
237 port_dot3_power_pd_source_map
,
238 port
->p_power
.source
);
239 case lldpctl_k_dot3_power_priority
:
240 return map_lookup(port_dot3_power_priority_map
.map
,
241 port
->p_power
.priority
);
242 case lldpctl_k_dot3_power_pd_4pid
:
243 return map_lookup(port_dot3_power_pd_4pid_map
.map
,
244 port
->p_power
.pd_4pid
);
245 case lldpctl_k_dot3_power_pse_status
:
246 return map_lookup(port_dot3_power_pse_status_map
.map
,
247 port
->p_power
.pse_status
);
248 case lldpctl_k_dot3_power_pd_status
:
249 return map_lookup(port_dot3_power_pd_status_map
.map
,
250 port
->p_power
.pd_status
);
251 case lldpctl_k_dot3_power_pse_pairs_ext
:
252 return map_lookup(port_dot3_power_pse_pairs_ext_map
.map
,
253 port
->p_power
.pse_pairs_ext
);
254 case lldpctl_k_dot3_power_class_a
:
255 return map_lookup(port_dot3_power_class_a_map
.map
,
256 port
->p_power
.class_a
);
257 case lldpctl_k_dot3_power_class_b
:
258 return map_lookup(port_dot3_power_class_b_map
.map
,
259 port
->p_power
.class_b
);
260 case lldpctl_k_dot3_power_class_ext
:
261 return map_lookup(port_dot3_power_class_ext_map
.map
,
262 port
->p_power
.class_ext
);
263 case lldpctl_k_dot3_power_type_ext
:
264 return map_lookup(port_dot3_power_type_ext_map
.map
,
265 port
->p_power
.type_ext
);
266 case lldpctl_k_dot3_power_pd_load
:
267 return map_lookup(port_dot3_power_pd_load_map
.map
,
268 port
->p_power
.pd_load
);
270 SET_ERROR(atom
->conn
, LLDPCTL_ERR_NOT_EXIST
);
276 _lldpctl_atom_get_int_dot3_power(lldpctl_atom_t
*atom
, lldpctl_key_t key
)
278 struct _lldpctl_atom_dot3_power_t
*dpow
=
279 (struct _lldpctl_atom_dot3_power_t
*)atom
;
280 struct lldpd_port
*port
= dpow
->parent
->port
;
282 /* Local and remote port */
284 case lldpctl_k_dot3_power_devicetype
:
285 return port
->p_power
.devicetype
;
286 case lldpctl_k_dot3_power_supported
:
287 return port
->p_power
.supported
;
288 case lldpctl_k_dot3_power_enabled
:
289 return port
->p_power
.enabled
;
290 case lldpctl_k_dot3_power_paircontrol
:
291 return port
->p_power
.paircontrol
;
292 case lldpctl_k_dot3_power_pairs
:
293 return port
->p_power
.pairs
;
294 case lldpctl_k_dot3_power_class
:
295 return port
->p_power
.class;
296 case lldpctl_k_dot3_power_type
:
297 return port
->p_power
.powertype
;
298 case lldpctl_k_dot3_power_source
:
299 return port
->p_power
.source
;
300 case lldpctl_k_dot3_power_priority
:
301 return port
->p_power
.priority
;
302 case lldpctl_k_dot3_power_requested
:
303 return port
->p_power
.requested
* 100;
304 case lldpctl_k_dot3_power_allocated
:
305 return port
->p_power
.allocated
* 100;
306 /* 802.3bt additions */
307 case lldpctl_k_dot3_power_pd_4pid
:
308 return port
->p_power
.pd_4pid
;
309 case lldpctl_k_dot3_power_requested_a
:
310 return port
->p_power
.requested_a
* 100;
311 case lldpctl_k_dot3_power_requested_b
:
312 return port
->p_power
.requested_b
* 100;
313 case lldpctl_k_dot3_power_allocated_a
:
314 return port
->p_power
.allocated_a
* 100;
315 case lldpctl_k_dot3_power_allocated_b
:
316 return port
->p_power
.allocated_b
* 100;
317 case lldpctl_k_dot3_power_pse_status
:
318 return port
->p_power
.pse_status
;
319 case lldpctl_k_dot3_power_pd_status
:
320 return port
->p_power
.pd_status
;
321 case lldpctl_k_dot3_power_pse_pairs_ext
:
322 return port
->p_power
.pse_pairs_ext
;
323 case lldpctl_k_dot3_power_class_a
:
324 return port
->p_power
.class_a
;
325 case lldpctl_k_dot3_power_class_b
:
326 return port
->p_power
.class_b
;
327 case lldpctl_k_dot3_power_class_ext
:
328 return port
->p_power
.class_ext
;
329 case lldpctl_k_dot3_power_type_ext
:
330 return port
->p_power
.type_ext
;
331 case lldpctl_k_dot3_power_pd_load
:
332 return port
->p_power
.pd_load
;
333 case lldpctl_k_dot3_power_pse_max
:
334 return port
->p_power
.pse_max
* 100;
336 return SET_ERROR(atom
->conn
, LLDPCTL_ERR_NOT_EXIST
);
340 static lldpctl_atom_t
*
341 _lldpctl_atom_set_int_dot3_power(lldpctl_atom_t
*atom
, lldpctl_key_t key
,
344 struct _lldpctl_atom_dot3_power_t
*dpow
=
345 (struct _lldpctl_atom_dot3_power_t
*)atom
;
346 struct lldpd_port
*port
= dpow
->parent
->port
;
348 /* Only local port can be modified */
349 if (!dpow
->parent
->local
) {
350 SET_ERROR(atom
->conn
, LLDPCTL_ERR_NOT_EXIST
);
355 case lldpctl_k_dot3_power_devicetype
:
357 case 0: /* Disabling */
358 case LLDP_DOT3_POWER_PSE
:
359 case LLDP_DOT3_POWER_PD
:
360 port
->p_power
.devicetype
= value
;
364 case lldpctl_k_dot3_power_supported
:
368 port
->p_power
.supported
= value
;
372 case lldpctl_k_dot3_power_enabled
:
376 port
->p_power
.enabled
= value
;
380 case lldpctl_k_dot3_power_paircontrol
:
384 port
->p_power
.paircontrol
= value
;
388 case lldpctl_k_dot3_power_pairs
:
392 port
->p_power
.pairs
= value
;
396 case lldpctl_k_dot3_power_class
:
397 if (value
< 0 || value
> 5)
399 port
->p_power
.class = value
;
401 case lldpctl_k_dot3_power_type
:
403 case LLDP_DOT3_POWER_8023AT_TYPE1
:
404 case LLDP_DOT3_POWER_8023AT_TYPE2
:
405 case LLDP_DOT3_POWER_8023AT_OFF
:
406 port
->p_power
.powertype
= value
;
410 case lldpctl_k_dot3_power_source
:
411 if (value
< 0 || value
> 3)
413 port
->p_power
.source
= value
;
415 case lldpctl_k_dot3_power_priority
:
417 case LLDP_DOT3_POWER_PRIO_UNKNOWN
:
418 case LLDP_DOT3_POWER_PRIO_CRITICAL
:
419 case LLDP_DOT3_POWER_PRIO_HIGH
:
420 case LLDP_DOT3_POWER_PRIO_LOW
:
421 port
->p_power
.priority
= value
;
425 case lldpctl_k_dot3_power_allocated
:
426 if (value
< 0) goto bad
;
427 port
->p_power
.allocated
= value
/ 100;
429 case lldpctl_k_dot3_power_requested
:
430 if (value
< 0) goto bad
;
431 port
->p_power
.requested
= value
/ 100;
433 /* 802.3bt additions */
434 case lldpctl_k_dot3_power_pd_4pid
:
435 port
->p_power
.pd_4pid
= value
;
437 case lldpctl_k_dot3_power_requested_a
:
438 port
->p_power
.requested_a
= value
/ 100;
440 case lldpctl_k_dot3_power_requested_b
:
441 port
->p_power
.requested_b
= value
/ 100;
443 case lldpctl_k_dot3_power_allocated_a
:
444 port
->p_power
.allocated_a
= value
/ 100;
446 case lldpctl_k_dot3_power_allocated_b
:
447 port
->p_power
.allocated_b
= value
/ 100;
449 case lldpctl_k_dot3_power_pse_status
:
450 port
->p_power
.pse_status
= value
;
452 case lldpctl_k_dot3_power_pd_status
:
453 port
->p_power
.pd_status
= value
;
455 case lldpctl_k_dot3_power_pse_pairs_ext
:
456 port
->p_power
.pse_pairs_ext
= value
;
458 case lldpctl_k_dot3_power_class_a
:
459 port
->p_power
.class_a
= value
;
461 case lldpctl_k_dot3_power_class_b
:
462 port
->p_power
.class_b
= value
;
464 case lldpctl_k_dot3_power_class_ext
:
465 port
->p_power
.class_ext
= value
;
467 case lldpctl_k_dot3_power_type_ext
:
468 port
->p_power
.type_ext
= value
;
470 case lldpctl_k_dot3_power_pd_load
:
471 port
->p_power
.pd_load
= value
;
473 case lldpctl_k_dot3_power_pse_max
:
474 port
->p_power
.pse_max
= value
/ 100;
477 SET_ERROR(atom
->conn
, LLDPCTL_ERR_NOT_EXIST
);
483 SET_ERROR(atom
->conn
, LLDPCTL_ERR_BAD_VALUE
);
487 static lldpctl_atom_t
*
488 _lldpctl_atom_set_str_dot3_power(lldpctl_atom_t
*atom
, lldpctl_key_t key
,
492 case lldpctl_k_dot3_power_devicetype
:
493 return _lldpctl_atom_set_int_dot3_power(atom
, key
,
494 map_reverse_lookup(port_dot3_power_devicetype_map
, value
));
495 case lldpctl_k_dot3_power_pairs
:
496 return _lldpctl_atom_set_int_dot3_power(atom
, key
,
497 map_reverse_lookup(port_dot3_power_pairs_map
.map
, value
));
498 case lldpctl_k_dot3_power_class
:
499 return _lldpctl_atom_set_int_dot3_power(atom
, key
,
500 map_reverse_lookup(port_dot3_power_class_map
.map
, value
));
501 case lldpctl_k_dot3_power_priority
:
502 return _lldpctl_atom_set_int_dot3_power(atom
, key
,
503 map_reverse_lookup(port_dot3_power_priority_map
.map
, value
));
505 SET_ERROR(atom
->conn
, LLDPCTL_ERR_NOT_EXIST
);
510 static struct atom_builder dot3_power
=
511 { atom_dot3_power
, sizeof(struct _lldpctl_atom_dot3_power_t
),
512 .init
= _lldpctl_atom_new_dot3_power
,
513 .free
= _lldpctl_atom_free_dot3_power
,
514 .get_int
= _lldpctl_atom_get_int_dot3_power
,
515 .set_int
= _lldpctl_atom_set_int_dot3_power
,
516 .get_str
= _lldpctl_atom_get_str_dot3_power
,
517 .set_str
= _lldpctl_atom_set_str_dot3_power
};
519 ATOM_BUILDER_REGISTER(dot3_power
, 8);