1 /* -*- mode: c; c-file-style: "openbsd" -*- */
3 * Copyright (c) 2015 Nicira, Inc.
4 * Copyright (c) 2008 Vincent Bernat <bernat@luffy.cx>
5 * Copyright (c) 2014 Michael Chapman
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
25 #include <sys/ioctl.h>
26 #include <sys/socket.h>
27 #include <sys/types.h>
29 #include "dp-packet.h"
32 VLOG_DEFINE_THIS_MODULE(lldp);
34 /* This set of macro are used to parse packets. The current position in buffer
35 * is `pos'. The length of the remaining space in buffer is `length'. There is
36 * no check on boundaries.
39 #define PEEK(type, func) \
41 memcpy(&type, pos, sizeof type), \
42 length -= sizeof type, \
46 #define PEEK_UINT8 PEEK(types.f_uint8, )
47 #define PEEK_UINT16 PEEK(types.f_uint16, ntohs)
48 #define PEEK_UINT32 PEEK(types.f_uint32, ntohl)
49 #define PEEK_BYTES(value, bytes) \
51 memcpy(value, pos, bytes); \
55 #define PEEK_DISCARD(bytes) \
60 #define PEEK_DISCARD_UINT8 PEEK_DISCARD(1)
61 #define PEEK_DISCARD_UINT16 PEEK_DISCARD(2)
62 #define PEEK_DISCARD_UINT32 PEEK_DISCARD(3)
63 #define PEEK_CMP(value, bytes) \
66 memcmp(pos-bytes, value, bytes))
67 #define CHECK_TLV_SIZE(x, name) \
69 if (tlv_size < (x)) { \
70 VLOG_WARN(name " TLV too short received on %s", \
71 hardware->h_ifname); \
75 #define PEEK_SAVE(where) (where = pos, 1)
84 lldpd_af_to_lldp_proto(int af)
88 return LLDP_MGMT_ADDR_IP4;
90 return LLDP_MGMT_ADDR_IP6;
92 return LLDP_MGMT_ADDR_NONE;
97 lldpd_af_from_lldp_proto(int proto)
100 case LLDP_MGMT_ADDR_IP4:
101 return LLDPD_AF_IPV4;
102 case LLDP_MGMT_ADDR_IP6:
103 return LLDPD_AF_IPV6;
105 return LLDPD_AF_UNSPEC;
110 lldp_tlv_put_u8(struct dp_packet *p, uint8_t x)
112 dp_packet_put(p, &x, sizeof x);
116 lldp_tlv_put_u16(struct dp_packet *p, uint16_t x)
118 ovs_be16 nx = htons(x);
119 dp_packet_put(p, &nx, sizeof nx);
123 lldp_tlv_put_u32(struct dp_packet *p, uint32_t x)
125 ovs_be32 nx = htonl(x);
126 dp_packet_put(p, &nx, sizeof nx);
130 lldp_tlv_put_isid(struct dp_packet *p, uint32_t isid)
132 uint8_t *data = dp_packet_put_uninit(p, 3);
133 data[0] = isid >> 16;
139 lldp_tlv_start(struct dp_packet *p, uint8_t tlv, unsigned int *start)
141 *start = dp_packet_size(p);
142 lldp_tlv_put_u16(p, tlv << 9);
146 lldp_tlv_end(struct dp_packet *p, unsigned int start)
148 ovs_be16 *tlv = dp_packet_at_assert(p, start, 2);
149 *tlv |= htons((dp_packet_size(p) - (start + 2)) & 0x1ff);
153 lldp_send(struct lldpd *global OVS_UNUSED,
154 struct lldpd_hardware *hardware,
157 unsigned int orig_size = dp_packet_size(p);
160 struct lldpd_port *port;
161 struct lldpd_chassis *chassis;
162 struct lldpd_mgmt *mgmt;
163 const uint8_t avaya[] = LLDP_TLV_ORG_AVAYA;
164 struct lldpd_aa_isid_vlan_maps_tlv *vlan_isid_map;
165 uint8_t msg_auth_digest[LLDP_TLV_AA_ISID_VLAN_DIGEST_LENGTH];
167 port = &hardware->h_lport;
168 chassis = port->p_chassis;
170 /* The ethernet header is filled in elsewhere, we must save room for it. */
171 VLOG_DBG("LLDP PDU send to %s mtu %d incoming",
172 hardware->h_ifname, hardware->h_mtu);
175 lldp_tlv_start(p, LLDP_TLV_CHASSIS_ID, &start);
176 lldp_tlv_put_u8(p, chassis->c_id_subtype);
177 dp_packet_put(p, chassis->c_id, chassis->c_id_len);
178 lldp_tlv_end(p, start);
181 lldp_tlv_start(p, LLDP_TLV_PORT_ID, &start);
182 lldp_tlv_put_u8(p, port->p_id_subtype);
183 dp_packet_put(p, port->p_id, port->p_id_len);
184 lldp_tlv_end(p, start);
187 lldp_tlv_start(p, LLDP_TLV_TTL, &start);
188 lldp_tlv_put_u16(p, chassis->c_ttl);
189 lldp_tlv_end(p, start);
192 if (chassis->c_name && *chassis->c_name != '\0') {
193 lldp_tlv_start(p, LLDP_TLV_SYSTEM_NAME, &start);
194 dp_packet_put(p, chassis->c_name, strlen(chassis->c_name));
195 lldp_tlv_end(p, start);
198 /* System description (skip it if empty) */
199 if (chassis->c_descr && *chassis->c_descr != '\0') {
200 lldp_tlv_start(p, LLDP_TLV_SYSTEM_DESCR, &start);
201 dp_packet_put(p, chassis->c_descr, strlen(chassis->c_descr));
202 lldp_tlv_end(p, start);
205 /* System capabilities */
206 lldp_tlv_start(p, LLDP_TLV_SYSTEM_CAP, &start);
207 lldp_tlv_put_u16(p, chassis->c_cap_available);
208 lldp_tlv_put_u16(p, chassis->c_cap_enabled);
209 lldp_tlv_end(p, start);
211 LIST_FOR_EACH (mgmt, m_entries, &chassis->c_mgmt) {
212 lldp_tlv_start(p, LLDP_TLV_MGMT_ADDR, &start);
213 lldp_tlv_put_u8(p, mgmt->m_addrsize + 1);
214 lldp_tlv_put_u8(p, lldpd_af_to_lldp_proto(mgmt->m_family));
215 dp_packet_put(p, &mgmt->m_addr, mgmt->m_addrsize);
217 /* Interface port type, OID */
218 if (mgmt->m_iface == 0) {
219 /* We don't know the management interface */
220 lldp_tlv_put_u8(p, LLDP_MGMT_IFACE_UNKNOWN);
221 lldp_tlv_put_u32(p, 0);
223 /* We have the index of the management interface */
224 lldp_tlv_put_u8(p, LLDP_MGMT_IFACE_IFINDEX);
225 lldp_tlv_put_u32(p, mgmt->m_iface);
227 lldp_tlv_put_u8(p, 0);
228 lldp_tlv_end(p, start);
231 /* Port description */
232 if (port->p_descr && *port->p_descr != '\0') {
233 lldp_tlv_start(p, LLDP_TLV_PORT_DESCR, &start);
234 dp_packet_put(p, port->p_descr, strlen(port->p_descr));
235 lldp_tlv_end(p, start);
238 /* Add Auto Attach tlvs V3.1 to packet. LLDP FA element v3.1 format:
239 TLV Type[127] TLV Length[50 octets] Avaya OUI[00-04-0D] Subtype[11]
240 7 bits 9 bits 3 octets 1 octet
241 HMAC-SHA Digest Element Type State Mgmt VLAN Rsvd System ID
242 32 octets 6 bits 6 bits 12 bits 1 octet 10 octets
245 if (port->p_element.type != 0) {
246 u_int16_t aa_element_first_word = 0;
247 u_int16_t aa_element_second_word = 0;
248 u_int16_t aa_element_state = 0;
249 u_int8_t aa_elem_sys_id_first_byte;
250 u_int8_t aa_elem_sys_id_second_byte;
252 /* Link VLAN Tagging Requirements (bit 1),
253 * Automatic Provisioning Mode (bit 2/3) (left to right, 1 based) */
254 aa_element_state = ((port->p_element.vlan_tagging & 0x1) << 5) |
255 ((port->p_element.auto_prov_mode & 0x3) << 3);
257 /* Element first word should be first 6 most significant bits of
258 * element type, bitwise OR that with the next 6 bits of the state,
259 * bitwise OR with the first 4 bits of mgmt vlan id.
260 * Element type should be LLDP_TLV_AA_ELEM_TYPE_VIRTUAL_SWITCH for
262 aa_element_first_word = (port->p_element.type << 10) |
263 (aa_element_state << 4) |
264 ((port->p_element.mgmt_vlan & 0x0F00)>> 8);
266 /* Element second type should be the first 8 most significant bits
267 * of the remaining 8 bits of mgmt vlan id. */
268 aa_element_second_word = (port->p_element.mgmt_vlan & 0xFF) << 8;
270 /* System id first byte should be first 3 most significant bits of
271 * connecion type, bitwise OR that with the device state and bitwise
272 * OR that with the first 2 most significant bitsof rsvd (10 bits). */
273 aa_elem_sys_id_first_byte =
274 ((port->p_element.system_id.conn_type & 0x7) << 5) |
275 ((port->p_element.system_id.rsvd >> 8) & 0x3);
277 /* Second byte should just be the remaining 8 bits of 10 bits rsvd */
278 aa_elem_sys_id_second_byte =
279 (port->p_element.system_id.rsvd & 0xFF);
281 memset(msg_auth_digest, 0, sizeof msg_auth_digest);
283 lldp_tlv_start(p, LLDP_TLV_ORG, &start);
284 dp_packet_put(p, avaya, sizeof avaya);
285 lldp_tlv_put_u8(p, LLDP_TLV_AA_ELEMENT_SUBTYPE);
286 dp_packet_put(p, msg_auth_digest, sizeof msg_auth_digest);
287 lldp_tlv_put_u16(p, aa_element_first_word);
288 lldp_tlv_put_u16(p, aa_element_second_word);
289 dp_packet_put(p, &port->p_element.system_id.system_mac,
290 sizeof port->p_element.system_id.system_mac);
291 lldp_tlv_put_u8(p, aa_elem_sys_id_first_byte);
292 lldp_tlv_put_u8(p, aa_elem_sys_id_second_byte);
293 dp_packet_put(p, &port->p_element.system_id.rsvd2,
294 sizeof port->p_element.system_id.rsvd2);
295 lldp_tlv_end(p, start);
298 if (!list_is_empty(&port->p_isid_vlan_maps)) {
300 memset(msg_auth_digest, 0, sizeof msg_auth_digest);
302 lldp_tlv_start(p, LLDP_TLV_ORG, &start);
303 dp_packet_put(p, avaya, sizeof avaya);
304 lldp_tlv_put_u8(p, LLDP_TLV_AA_ISID_VLAN_ASGNS_SUBTYPE);
305 dp_packet_put(p, msg_auth_digest, sizeof msg_auth_digest);
307 LIST_FOR_EACH (vlan_isid_map,
309 &hardware->h_lport.p_isid_vlan_maps) {
310 u_int16_t status_vlan_word;
312 (vlan_isid_map->isid_vlan_data.status << 12) |
313 vlan_isid_map->isid_vlan_data.vlan;
315 lldp_tlv_put_u16(p, status_vlan_word);
316 lldp_tlv_put_isid(p, vlan_isid_map->isid_vlan_data.isid);
319 lldp_tlv_end(p, start);
323 lldp_tlv_start(p, LLDP_TLV_END, &start);
324 lldp_tlv_end(p, start);
326 hardware->h_tx_cnt++;
328 const char *lldp = dp_packet_at_assert(p, orig_size, 0);
329 unsigned int lldp_len = dp_packet_size(p) - orig_size;
330 if (!hardware->h_lport.p_lastframe
331 || hardware->h_lport.p_lastframe->size != lldp_len
332 || memcmp(hardware->h_lport.p_lastframe->frame, lldp, lldp_len)) {
334 struct lldpd_frame *frame = xmalloc(sizeof *frame + lldp_len);
335 frame->size = lldp_len;
336 memcpy(frame->frame, lldp, lldp_len);
337 free(hardware->h_lport.p_lastframe);
338 hardware->h_lport.p_lastframe = frame;
339 hardware->h_lport.p_lastchange = time(NULL);
342 return dp_packet_size(p);
346 lldp_decode(struct lldpd *cfg OVS_UNUSED, char *frame, int s,
347 struct lldpd_hardware *hardware, struct lldpd_chassis **newchassis,
348 struct lldpd_port **newport)
350 struct lldpd_chassis *chassis;
351 struct lldpd_port *port;
352 const struct eth_addr lldpaddr = LLDP_MULTICAST_ADDR;
353 const char dot1[] = LLDP_TLV_ORG_DOT1;
354 const char dot3[] = LLDP_TLV_ORG_DOT3;
355 const char med[] = LLDP_TLV_ORG_MED;
356 const char avaya_oid[] = LLDP_TLV_ORG_AVAYA;
357 const char dcbx[] = LLDP_TLV_ORG_DCBX;
361 bool ttl_received = false;
362 int tlv_size, tlv_type, tlv_subtype;
365 struct lldpd_aa_isid_vlan_maps_tlv *isid_vlan_map = NULL;
366 u_int8_t msg_auth_digest[LLDP_TLV_AA_ISID_VLAN_DIGEST_LENGTH];
367 struct lldpd_mgmt *mgmt;
368 u_int8_t addr_str_length, addr_str_buffer[32];
369 u_int8_t addr_family, addr_length, *addr_ptr, iface_subtype;
370 u_int32_t iface_number, iface;
372 VLOG_DBG("receive LLDP PDU on %s", hardware->h_ifname);
374 chassis = xzalloc(sizeof *chassis);
375 list_init(&chassis->c_mgmt);
377 port = xzalloc(sizeof *port);
378 list_init(&port->p_isid_vlan_maps);
381 pos = (u_int8_t*) frame;
383 if (length < 2 * ETH_ADDR_LEN + sizeof(u_int16_t)) {
384 VLOG_WARN("too short frame received on %s", hardware->h_ifname);
387 if (PEEK_CMP(&lldpaddr, ETH_ADDR_LEN) != 0) {
388 VLOG_INFO("frame not targeted at LLDP multicast address "
389 "received on %s", hardware->h_ifname);
393 PEEK_DISCARD(ETH_ADDR_LEN); /* Skip source address */
394 if (PEEK_UINT16 != ETHERTYPE_LLDP) {
395 VLOG_INFO("non LLDP frame received on %s", hardware->h_ifname);
399 while (length && !gotend) {
401 VLOG_WARN("tlv header too short received on %s",
405 tlv_size = PEEK_UINT16;
406 tlv_type = tlv_size >> 9;
407 tlv_size = tlv_size & 0x1ff;
408 (void) PEEK_SAVE(tlv);
409 if (length < tlv_size) {
410 VLOG_WARN("frame too short for tlv received on %s",
418 VLOG_WARN("lldp end received with size not null on %s",
423 VLOG_DBG("extra data after lldp end on %s",
429 case LLDP_TLV_CHASSIS_ID:
430 case LLDP_TLV_PORT_ID:
431 CHECK_TLV_SIZE(2, "Port Id");
432 tlv_subtype = PEEK_UINT8;
433 if (tlv_subtype == 0 || tlv_subtype > 7) {
434 VLOG_WARN("unknown subtype for tlv id received on %s",
438 b = xzalloc(tlv_size - 1);
439 PEEK_BYTES(b, tlv_size - 1);
440 if (tlv_type == LLDP_TLV_PORT_ID) {
441 port->p_id_subtype = tlv_subtype;
443 port->p_id_len = tlv_size - 1;
445 chassis->c_id_subtype = tlv_subtype;
447 chassis->c_id_len = tlv_size - 1;
452 CHECK_TLV_SIZE(2, "TTL");
453 chassis->c_ttl = PEEK_UINT16;
457 case LLDP_TLV_PORT_DESCR:
458 case LLDP_TLV_SYSTEM_NAME:
459 case LLDP_TLV_SYSTEM_DESCR:
461 VLOG_DBG("empty tlv received on %s", hardware->h_ifname);
464 b = xzalloc(tlv_size + 1);
465 PEEK_BYTES(b, tlv_size);
466 if (tlv_type == LLDP_TLV_PORT_DESCR) {
468 } else if (tlv_type == LLDP_TLV_SYSTEM_NAME) {
471 chassis->c_descr = b;
475 case LLDP_TLV_SYSTEM_CAP:
476 CHECK_TLV_SIZE(4, "System capabilities");
477 chassis->c_cap_available = PEEK_UINT16;
478 chassis->c_cap_enabled = PEEK_UINT16;
481 case LLDP_TLV_MGMT_ADDR:
482 CHECK_TLV_SIZE(1, "Management address");
483 addr_str_length = PEEK_UINT8;
484 CHECK_TLV_SIZE(1 + addr_str_length, "Management address");
485 PEEK_BYTES(addr_str_buffer, addr_str_length);
486 addr_length = addr_str_length - 1;
487 addr_family = addr_str_buffer[0];
488 addr_ptr = &addr_str_buffer[1];
489 CHECK_TLV_SIZE(1 + addr_str_length + 5, "Management address");
490 iface_subtype = PEEK_UINT8;
491 iface_number = PEEK_UINT32;
493 af = lldpd_af_from_lldp_proto(addr_family);
494 if (af == LLDPD_AF_UNSPEC) {
497 iface = iface_subtype == LLDP_MGMT_IFACE_IFINDEX ?
499 mgmt = lldpd_alloc_mgmt(af, addr_ptr, addr_length, iface);
501 VLOG_WARN("unable to allocate memory for management address");
504 list_push_back(&chassis->c_mgmt, &mgmt->m_entries);
508 CHECK_TLV_SIZE(4, "Organisational");
509 PEEK_BYTES(orgid, sizeof orgid);
510 tlv_subtype = PEEK_UINT8;
511 if (memcmp(dot1, orgid, sizeof orgid) == 0) {
512 hardware->h_rx_unrecognized_cnt++;
513 } else if (memcmp(dot3, orgid, sizeof orgid) == 0) {
514 hardware->h_rx_unrecognized_cnt++;
515 } else if (memcmp(med, orgid, sizeof orgid) == 0) {
517 hardware->h_rx_unrecognized_cnt++;
518 } else if (memcmp(avaya_oid, orgid, sizeof orgid) == 0) {
519 u_int32_t aa_element_dword;
520 u_int16_t aa_system_id_word;
521 u_int16_t aa_status_vlan_word;
522 u_int8_t aa_element_state;
523 unsigned short num_mappings;
525 switch(tlv_subtype) {
526 case LLDP_TLV_AA_ELEMENT_SUBTYPE:
527 PEEK_BYTES(&msg_auth_digest, sizeof msg_auth_digest);
529 aa_element_dword = PEEK_UINT32;
531 /* Type is first 6 most-significant bits of
532 * aa_element_dword */
533 port->p_element.type = aa_element_dword >> 26;
535 /* State is 6 most significant bits of aa_element_dword */
536 aa_element_state = (aa_element_dword >> 20) & 0x3F;
538 /* vlan tagging requirement is the bit 1(left to right)
539 * of the 6 bits state (1 based) */
540 port->p_element.vlan_tagging =
541 (aa_element_state >> 5) & 0x1;
543 /* Automatic provision mode is the bit 2/3(left to right)
544 * of the 6 bits state (1 based) */
545 port->p_element.auto_prov_mode =
546 (aa_element_state >> 3) & 0x3;
548 /* mgmt_vlan is the 12 bits of aa_element_dword from
550 port->p_element.mgmt_vlan =
551 (aa_element_dword >> 8) & 0xFFF;
552 VLOG_INFO("Element type: %X, vlan tagging %X, "
553 "auto prov mode %x, Mgmt vlan: %X",
554 port->p_element.type,
555 port->p_element.vlan_tagging,
556 port->p_element.auto_prov_mode,
557 port->p_element.mgmt_vlan);
559 PEEK_BYTES(&port->p_element.system_id.system_mac,
560 sizeof port->p_element.system_id.system_mac);
561 VLOG_INFO("System mac: "ETH_ADDR_FMT,
562 ETH_ADDR_ARGS(port->p_element.system_id.system_mac));
563 aa_system_id_word = PEEK_UINT16;
564 port->p_element.system_id.conn_type =
565 aa_system_id_word >> 13;
566 port->p_element.system_id.rsvd = aa_system_id_word &
568 PEEK_BYTES(&port->p_element.system_id.rsvd2,
569 sizeof port->p_element.system_id.rsvd2);
572 case LLDP_TLV_AA_ISID_VLAN_ASGNS_SUBTYPE:
573 PEEK_BYTES(&msg_auth_digest, sizeof msg_auth_digest);
575 /* Subtract off tlv type and length (2Bytes) + OUI (3B) +
576 * Subtype (1B) + MSG DIGEST (32B).
578 num_mappings = tlv_size - 4 -
579 LLDP_TLV_AA_ISID_VLAN_DIGEST_LENGTH;
580 if (num_mappings % 5 != 0) {
581 VLOG_INFO("malformed vlan-isid mappings tlv received");
585 num_mappings /= 5; /* Each mapping is 5 Bytes */
586 for(; num_mappings > 0; num_mappings--) {
589 isid_vlan_map = xzalloc(sizeof *isid_vlan_map);
590 aa_status_vlan_word = PEEK_UINT16;
592 /* Status is first 4 most-significant bits. */
593 isid_vlan_map->isid_vlan_data.status =
594 aa_status_vlan_word >> 12;
596 /* Vlan is last 12 bits */
597 isid_vlan_map->isid_vlan_data.vlan =
598 aa_status_vlan_word & 0x0FFF;
600 isid_vlan_map->isid_vlan_data.isid =
601 (isid[0] << 16) | (isid[1] << 8) | isid[2];
602 list_push_back(&port->p_isid_vlan_maps,
603 &isid_vlan_map->m_entries);
604 isid_vlan_map = NULL;
609 hardware->h_rx_unrecognized_cnt++;
610 VLOG_INFO("Unrecogised tlv subtype received");
613 } else if (memcmp(dcbx, orgid, sizeof orgid) == 0) {
614 VLOG_DBG("unsupported DCBX tlv received on %s "
615 "- ignore", hardware->h_ifname);
616 hardware->h_rx_unrecognized_cnt++;
618 VLOG_INFO("unknown org tlv [%02x:%02x:%02x] received "
619 "on %s", orgid[0], orgid[1], orgid[2],
621 hardware->h_rx_unrecognized_cnt++;
625 VLOG_WARN("unknown tlv (%d) received on %s",
630 if (pos > tlv + tlv_size) {
631 VLOG_WARN("BUG: already past TLV!");
634 PEEK_DISCARD(tlv + tlv_size - pos);
637 /* Some random check */
638 if (!chassis->c_id || !port->p_id || !ttl_received || !gotend) {
639 VLOG_WARN("some mandatory tlv are missing for frame received "
640 "on %s", hardware->h_ifname);
643 *newchassis = chassis;
648 lldpd_chassis_cleanup(chassis, true);
649 lldpd_port_cleanup(port, true);