netdev-dpdk: fix mbuf leaks
[cascardo/ovs.git] / lib / ovs-lldp.c
1 /*
2  * Copyright (c) 2015 Nicira, Inc.
3  * Copyright (c) 2014 WindRiver, Inc.
4  * Copyright (c) 2015 Avaya, Inc.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at:
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18
19 /* Implementation of Auto Attach.
20  * Based on sample implementation in 802.1ab.  Above copyright and license
21  * applies to all modifications.
22  * Limitations:
23  * - No support for multiple bridge.
24  * - Auto Attach state machine not implemented.
25  * - Auto Attach and LLDP code are bundled together.  The plan is to decoupled
26  *   them.
27  */
28
29 #include <config.h>
30 #include "ovs-lldp.h"
31 #include <arpa/inet.h>
32 #include <inttypes.h>
33 #include <netinet/in.h>
34 #include <stdbool.h>
35 #include <stdlib.h>
36 #include <sys/types.h>
37 #include "dynamic-string.h"
38 #include "flow.h"
39 #include "list.h"
40 #include "lldp/lldpd.h"
41 #include "lldp/lldpd-structs.h"
42 #include "netdev.h"
43 #include "openvswitch/types.h"
44 #include "packets.h"
45 #include "poll-loop.h"
46 #include "smap.h"
47 #include "unixctl.h"
48 #include "util.h"
49 #include "openvswitch/vlog.h"
50
51 VLOG_DEFINE_THIS_MODULE(ovs_lldp);
52
53 #define LLDP_PROTOCOL_ID        0x0000
54 #define LLDP_PROTOCOL_VERSION   0x00
55 #define LLDP_TYPE_CONFIG        0x00
56 #define LLDP_CHASSIS_TTL        120
57 #define ETH_TYPE_LLDP           0x88cc
58 #define MINIMUM_ETH_PACKET_SIZE 68
59
60 #define AA_STATUS_MULTIPLE \
61     AA_STATUS(ACTIVE,2,Active) \
62     AA_STATUS(REJECT_GENERIC,3,Reject (Generic)) \
63     AA_STATUS(REJECT_AA_RES_NOTAVAIL,4,Reject (AA resources unavailable)) \
64     AA_STATUS(REJECT_INVALID,6,Reject (Invalid)) \
65     AA_STATUS(REJECT_VLAN_RES_UNAVAIL,8,Reject (VLAN resources unavailable)) \
66     AA_STATUS(REJECT_VLAN_APP_ISSUE,9,Reject (Application interaction issue)) \
67     AA_STATUS(PENDING,255,Pending)
68
69 enum aa_status {
70 #define AA_STATUS(NAME, VALUE, STR) AA_STATUS_##NAME = VALUE,
71     AA_STATUS_MULTIPLE
72 #undef AA_STATUS
73     AA_STATUS_N_MULTIPLE
74 };
75
76 /* Internal structure for an Auto Attach mapping.
77  */
78 struct aa_mapping_internal {
79     struct hmap_node hmap_node_isid;
80     struct hmap_node hmap_node_aux;
81     uint32_t         isid;
82     uint16_t         vlan;
83     void             *aux;
84     enum aa_status   status;
85 };
86
87 static struct ovs_mutex mutex = OVS_MUTEX_INITIALIZER;
88
89 /* Hash map of all LLDP instances keyed by name (port at the moment).
90  */
91 static struct hmap all_lldps__ = HMAP_INITIALIZER(&all_lldps__);
92 static struct hmap *const all_lldps OVS_GUARDED_BY(mutex) = &all_lldps__;
93
94 /* Hash map of all the Auto Attach mappings.  Global at the moment (but will
95  * be per bridge).  Used when adding a new port to a bridge so that we can
96  * properly install all the configured mapping on the port and export them
97  * To the Auto Attach server via LLDP.
98  */
99 static struct hmap all_mappings__ = HMAP_INITIALIZER(&all_mappings__);
100 static struct hmap *const all_mappings OVS_GUARDED_BY(mutex) = &all_mappings__;
101
102 static struct lldp_aa_element_system_id system_id_null;
103
104 /* Convert an LLDP chassis ID to a string.
105  */
106 static void
107 chassisid_to_string(uint8_t *array, size_t len, char **str)
108 {
109     unsigned int i;
110
111     *str = xmalloc(len * 3);
112
113     for (i = 0; i < len; i++) {
114         snprintf(&(*str)[i * 3], 4, "%02x:", array[i]);
115     }
116     (*str)[(i * 3) - 1] = '\0';
117 }
118
119 /* Find an Auto Attach mapping keyed by I-SID.
120  */
121 static struct aa_mapping_internal *
122 mapping_find_by_isid(struct lldp *lldp, uint32_t isid)
123     OVS_REQUIRES(mutex)
124 {
125     struct aa_mapping_internal *m;
126
127     HMAP_FOR_EACH_IN_BUCKET (m, hmap_node_isid, hash_int(isid, 0),
128                              &lldp->mappings_by_isid) {
129         if (isid == m->isid) {
130             return m;
131         }
132     }
133
134     return NULL;
135 }
136
137 /* Find an Auto Attach mapping keyed by aux.  aux is an opaque pointer created
138  * by the bridge that refers to an OVSDB mapping record.
139  */
140 static struct aa_mapping_internal *
141 mapping_find_by_aux(struct lldp *lldp, const void *aux) OVS_REQUIRES(mutex)
142 {
143     struct aa_mapping_internal *m;
144
145     HMAP_FOR_EACH_IN_BUCKET (m, hmap_node_aux, hash_pointer(aux, 0),
146                              &lldp->mappings_by_aux) {
147         if (aux == m->aux) {
148             return m;
149         }
150     }
151
152     return NULL;
153 }
154
155 /* Convert an Auto Attach request status to a string.
156  */
157 static char *
158 aa_status_to_str(uint8_t status)
159 {
160     switch (status) {
161 #define AA_STATUS(NAME, VALUE, STR) case AA_STATUS_##NAME: return #STR;
162         AA_STATUS_MULTIPLE
163 #undef AA_STATUS
164         default: return "Undefined";
165     }
166 }
167
168 /* Display LLDP and Auto Attach statistics.
169  */
170 static void
171 aa_print_lldp_and_aa_stats(struct ds *ds, struct lldp *lldp)
172     OVS_REQUIRES(mutex)
173 {
174     struct lldpd_hardware *hw;
175
176     ds_put_format(ds, "Statistics: %s\n", lldp->name);
177
178     if (!lldp->lldpd) {
179         return;
180     }
181
182     LIST_FOR_EACH (hw, h_entries, &lldp->lldpd->g_hardware) {
183         ds_put_format(ds, "\ttx cnt: %"PRIu64"\n", hw->h_tx_cnt);
184         ds_put_format(ds, "\trx cnt: %"PRIu64"\n", hw->h_rx_cnt);
185         ds_put_format(ds, "\trx discarded cnt: %"PRIu64"\n",
186                       hw->h_rx_discarded_cnt);
187         ds_put_format(ds, "\trx unrecognized cnt: %"PRIu64"\n",
188                       hw->h_rx_unrecognized_cnt);
189         ds_put_format(ds, "\tageout cnt: %"PRIu64"\n", hw->h_ageout_cnt);
190         ds_put_format(ds, "\tinsert cnt: %"PRIu64"\n", hw->h_insert_cnt);
191         ds_put_format(ds, "\tdelete cnt: %"PRIu64"\n", hw->h_delete_cnt);
192         ds_put_format(ds, "\tdrop cnt: %"PRIu64"\n", hw->h_drop_cnt);
193     }
194 }
195
196 static void
197 aa_print_element_status_port(struct ds *ds, struct lldpd_hardware *hw)
198 {
199     struct lldpd_port *port;
200
201     LIST_FOR_EACH (port, p_entries, &hw->h_rports) {
202         if (memcmp(&port->p_element.system_id,
203                    &system_id_null,
204                    sizeof port->p_element.system_id)) {
205             const char *none_str = "<None>";
206             const char *descr = NULL;
207             char *id = NULL;
208             char *system;
209
210             if (port->p_chassis) {
211                 if (port->p_chassis->c_id_len > 0) {
212                     chassisid_to_string(port->p_chassis->c_id,
213                                         port->p_chassis->c_id_len, &id);
214                 }
215
216                 descr = port->p_chassis->c_descr;
217             }
218
219             chassisid_to_string((uint8_t *) &port->p_element.system_id,
220                 sizeof port->p_element.system_id, &system);
221
222             ds_put_format(ds, "\tAuto Attach Primary Server Id: %s\n",
223                           id ? id : none_str);
224             ds_put_format(ds, "\tAuto Attach Primary Server Descr: %s\n",
225                           descr ? descr : none_str);
226             ds_put_format(ds, "\tAuto Attach Primary Server System Id: %s\n",
227                           system);
228
229             free(id);
230             free(system);
231         }
232     }
233 }
234
235 /* Auto Attach server broadcast an LLDP message periodically.  Display
236  * the discovered server.
237  */
238 static void
239 aa_print_element_status(struct ds *ds, struct lldp *lldp) OVS_REQUIRES(mutex)
240 {
241     struct lldpd_hardware *hw;
242
243     ds_put_format(ds, "LLDP: %s\n", lldp->name);
244
245     if (!lldp->lldpd) {
246         return;
247     }
248
249     LIST_FOR_EACH (hw, h_entries, &lldp->lldpd->g_hardware) {
250         aa_print_element_status_port(ds, hw);
251     }
252 }
253
254 static void
255 aa_print_isid_status_port_isid(struct lldp *lldp, struct lldpd_port *port)
256     OVS_REQUIRES(mutex)
257 {
258     struct lldpd_aa_isid_vlan_maps_tlv *mapping;
259
260     if (list_is_empty(&port->p_isid_vlan_maps)) {
261         return;
262     }
263
264     LIST_FOR_EACH (mapping, m_entries, &port->p_isid_vlan_maps) {
265         uint32_t isid = mapping->isid_vlan_data.isid;
266         struct aa_mapping_internal *m = mapping_find_by_isid(lldp, isid);
267
268         VLOG_INFO("h_rport: isid=%u, vlan=%u, status=%d",
269                   isid,
270                   mapping->isid_vlan_data.vlan,
271                   mapping->isid_vlan_data.status);
272
273         /* Update the status of our internal state for the mapping. */
274         if (m) {
275             VLOG_INFO("Setting status for ISID=%"PRIu32" to %"PRIu16,
276                       isid, mapping->isid_vlan_data.status);
277             m->status = mapping->isid_vlan_data.status;
278         } else {
279             VLOG_WARN("Couldn't find mapping for I-SID=%"PRIu32, isid);
280         }
281     }
282 }
283
284 static void
285 aa_print_isid_status_port(struct lldp *lldp, struct lldpd_hardware *hw)
286     OVS_REQUIRES(mutex)
287 {
288     struct lldpd_port *port;
289
290     LIST_FOR_EACH (port, p_entries, &hw->h_rports) {
291         aa_print_isid_status_port_isid(lldp, port);
292     }
293 }
294
295 /* The Auto Attach server will broadcast the status of the configured mappings
296  * via LLDP.  Display the status.
297  */
298 static void
299 aa_print_isid_status(struct ds *ds, struct lldp *lldp) OVS_REQUIRES(mutex)
300 {
301     struct lldpd_hardware *hw;
302     struct aa_mapping_internal *m;
303
304     if (!lldp->lldpd) {
305         return;
306     }
307
308     ds_put_format(ds, "LLDP: %s\n", lldp->name);
309
310     LIST_FOR_EACH (hw, h_entries, &lldp->lldpd->g_hardware) {
311         aa_print_isid_status_port(lldp, hw);
312     }
313
314     ds_put_format(ds, "%-8s %-4s %-11s %-8s\n",
315                       "I-SID",
316                       "VLAN",
317                       "Source",
318                       "Status");
319     ds_put_format(ds, "-------- ---- ----------- --------\n");
320
321     HMAP_FOR_EACH (m, hmap_node_isid, &lldp->mappings_by_isid) {
322         ds_put_format(ds, "%-8"PRIu32" %-4"PRIu16" %-11s %-11s\n",
323                       m->isid, m->vlan, "Switch", aa_status_to_str(m->status));
324     }
325 }
326
327 static void
328 aa_unixctl_status(struct unixctl_conn *conn, int argc OVS_UNUSED,
329                   const char *argv[] OVS_UNUSED, void *aux OVS_UNUSED)
330     OVS_EXCLUDED(mutex)
331 {
332     struct lldp *lldp;
333     struct ds ds = DS_EMPTY_INITIALIZER;
334
335     ovs_mutex_lock(&mutex);
336
337     HMAP_FOR_EACH (lldp, hmap_node, all_lldps) {
338         aa_print_element_status(&ds, lldp);
339     }
340     unixctl_command_reply(conn, ds_cstr(&ds));
341     ds_destroy(&ds);
342
343     ovs_mutex_unlock(&mutex);
344 }
345
346 static void
347 aa_unixctl_show_isid(struct unixctl_conn *conn, int argc OVS_UNUSED,
348                      const char *argv[] OVS_UNUSED, void *aux OVS_UNUSED)
349     OVS_EXCLUDED(mutex)
350 {
351     struct lldp *lldp;
352     struct ds ds = DS_EMPTY_INITIALIZER;
353
354     ovs_mutex_lock(&mutex);
355
356     HMAP_FOR_EACH (lldp, hmap_node, all_lldps) {
357         aa_print_isid_status(&ds, lldp);
358     }
359     unixctl_command_reply(conn, ds_cstr(&ds));
360     ds_destroy(&ds);
361
362     ovs_mutex_unlock(&mutex);
363 }
364
365 static void
366 aa_unixctl_statistics(struct unixctl_conn *conn, int argc OVS_UNUSED,
367                       const char *argv[] OVS_UNUSED, void *aux OVS_UNUSED)
368     OVS_EXCLUDED(mutex)
369 {
370     struct ds ds = DS_EMPTY_INITIALIZER;
371     struct lldp *lldp;
372
373     ovs_mutex_lock(&mutex);
374
375     /* Cycle through all ports and dump the stats for each one */
376     HMAP_FOR_EACH (lldp, hmap_node, all_lldps) {
377         aa_print_lldp_and_aa_stats(&ds, lldp);
378     }
379
380     ovs_mutex_unlock(&mutex);
381
382     unixctl_command_reply(conn, ds_cstr(&ds));
383 }
384
385 /* An Auto Attach mapping was configured.  Populate the corresponding
386  * structures in the LLDP hardware.
387  */
388 static void
389 update_mapping_on_lldp(struct lldp *lldp, struct lldpd_hardware *hardware,
390                        struct aa_mapping_internal *m)
391 {
392     struct lldpd_aa_isid_vlan_maps_tlv *lm = xzalloc(sizeof *lm);
393
394     VLOG_INFO("\t\t hardware->h_ifname=%s", hardware->h_ifname);
395
396     lm->isid_vlan_data.isid = m->isid;
397     lm->isid_vlan_data.vlan = m->vlan;
398
399     list_push_back(&hardware->h_lport.p_isid_vlan_maps, &lm->m_entries);
400
401     /* TODO Should be done in the Auto Attach state machine when a mapping goes
402      * from "pending" to "active".
403      */
404     struct bridge_aa_vlan *node = xmalloc(sizeof *node);
405
406     node->port_name = xstrdup(hardware->h_ifname);
407     node->vlan = m->vlan;
408     node->oper = BRIDGE_AA_VLAN_OPER_ADD;
409
410     list_push_back(&lldp->active_mapping_queue, &node->list_node);
411 }
412
413 /* Bridge will poll the list of VLAN that needs to be auto configure based on
414  * the Auto Attach mappings that have been exchanged with the server.
415  */
416 int
417 aa_get_vlan_queued(struct ovs_list *list)
418 {
419     struct lldp *lldp;
420
421     ovs_mutex_lock(&mutex);
422
423     HMAP_FOR_EACH (lldp, hmap_node, all_lldps) {
424         struct bridge_aa_vlan *node;
425
426         LIST_FOR_EACH_POP (node, list_node, &lldp->active_mapping_queue) {
427             struct bridge_aa_vlan *copy;
428
429             copy = xmalloc(sizeof *copy);
430             copy->port_name = xstrdup(node->port_name);
431             copy->vlan = node->vlan;
432             copy->oper = node->oper;
433
434             list_push_back(list, &copy->list_node);
435
436             /* Cleanup */
437             free(node->port_name);
438             free(node);
439         }
440     }
441
442     ovs_mutex_unlock(&mutex);
443
444     return 0;
445 }
446
447 /* Bridge will poll whether or not VLAN have been auto-configured.
448  */
449 unsigned int
450 aa_get_vlan_queue_size(void)
451 {
452     struct lldp *lldp;
453     unsigned int size = 0;
454
455     ovs_mutex_lock(&mutex);
456
457     HMAP_FOR_EACH (lldp, hmap_node, all_lldps) {
458         size += list_size(&lldp->active_mapping_queue);
459     }
460
461     ovs_mutex_unlock(&mutex);
462
463     return size;
464 }
465
466 /* Configure Auto Attach.
467  */
468 int
469 aa_configure(const struct aa_settings *s)
470 {
471     struct lldp *lldp;
472
473     ovs_mutex_lock(&mutex);
474
475     /* TODO Change all instances for now */
476     HMAP_FOR_EACH (lldp, hmap_node, all_lldps) {
477         struct lldpd_chassis *chassis;
478
479         LIST_FOR_EACH (chassis, list, &lldp->lldpd->g_chassis) {
480             /* System Description */
481             free(chassis->c_descr);
482             chassis->c_descr = s && s->system_description[0] ?
483                 xstrdup(s->system_description) : xstrdup(PACKAGE_STRING);
484
485             /* System Name */
486             if (s) {
487                 free(chassis->c_name);
488                 chassis->c_name = xstrdup(s->system_name);
489             }
490         }
491     }
492
493     ovs_mutex_unlock(&mutex);
494
495     return 0;
496 }
497
498 /* Add a new Auto Attach mapping.
499  */
500 int
501 aa_mapping_register(void *aux, const struct aa_mapping_settings *s)
502 {
503     struct aa_mapping_internal *bridge_m;
504     struct lldp *lldp;
505
506     VLOG_INFO("Adding mapping ISID=%"PRIu32", VLAN=%"PRIu16", aux=%p",
507               s->isid, s->vlan, aux);
508
509     ovs_mutex_lock(&mutex);
510
511     /* TODO These mappings should be stores per bridge.  This is used
512      * When a port is added.  Auto Attach mappings need to be added on this
513      * port.
514      */
515     bridge_m = xzalloc(sizeof *bridge_m);
516     bridge_m->isid = s->isid;
517     bridge_m->vlan = s->vlan;
518     bridge_m->aux = aux;
519     bridge_m->status = AA_STATUS_PENDING;
520     hmap_insert(all_mappings, &bridge_m->hmap_node_isid,
521                 hash_int(bridge_m->isid, 0));
522
523
524     /* Update mapping on the all the LLDP instances. */
525     HMAP_FOR_EACH (lldp, hmap_node, all_lldps) {
526         struct lldpd_hardware *hw;
527         struct aa_mapping_internal *m;
528
529         VLOG_INFO("\t lldp->name=%s", lldp->name);
530
531         if (mapping_find_by_isid(lldp, s->isid)) {
532             continue;
533         }
534
535         m = xzalloc(sizeof *m);
536         m->isid = s->isid;
537         m->vlan = s->vlan;
538         m->status = AA_STATUS_PENDING;
539         m->aux = aux;
540         hmap_insert(&lldp->mappings_by_isid, &m->hmap_node_isid,
541                     hash_int(m->isid, 0));
542         hmap_insert(&lldp->mappings_by_aux,
543                     &m->hmap_node_aux,
544                     hash_pointer(m->aux, 0));
545
546         /* Configure the mapping on each port of the LLDP stack. */
547         LIST_FOR_EACH (hw, h_entries, &lldp->lldpd->g_hardware) {
548             update_mapping_on_lldp(lldp, hw, m);
549         }
550     }
551
552     ovs_mutex_unlock(&mutex);
553
554     return 0;
555 }
556
557 static void
558 aa_mapping_unregister_mapping(struct lldp *lldp,
559                               struct lldpd_hardware *hw,
560                               struct aa_mapping_internal *m)
561 {
562     struct lldpd_aa_isid_vlan_maps_tlv *lm, *lm_next;
563
564     LIST_FOR_EACH_SAFE (lm, lm_next, m_entries,
565                         &hw->h_lport.p_isid_vlan_maps) {
566         uint32_t isid = lm->isid_vlan_data.isid;
567
568         if (isid == m->isid) {
569             VLOG_INFO("\t\t Removing lport, isid=%u, vlan=%u",
570                       isid,
571                       lm->isid_vlan_data.vlan);
572
573             list_remove(&lm->m_entries);
574
575             /* TODO Should be done in the AA SM when a mapping goes
576              * from "pending" to "active".
577              */
578             struct bridge_aa_vlan *node = xmalloc(sizeof *node);
579
580             node->port_name = xstrdup(hw->h_ifname);
581             node->vlan = m->vlan;
582             node->oper = BRIDGE_AA_VLAN_OPER_REMOVE;
583
584             list_push_back(&lldp->active_mapping_queue, &node->list_node);
585
586             break;
587         }
588     }
589 }
590
591 /* Remove an existing Auto Attach mapping.
592  */
593 int
594 aa_mapping_unregister(void *aux)
595 {
596     struct lldp *lldp;
597
598     VLOG_INFO("Removing mapping aux=%p", aux);
599
600     ovs_mutex_lock(&mutex);
601
602     HMAP_FOR_EACH (lldp, hmap_node, all_lldps) {
603         struct lldpd_hardware *hw;
604         struct aa_mapping_internal *m = mapping_find_by_aux(lldp, aux);
605
606         /* Remove from internal hash tables. */
607         if (m) {
608             uint32_t isid = m->isid;
609             uint16_t vlan = m->vlan;
610             struct aa_mapping_internal *p = mapping_find_by_isid(lldp, isid);
611
612             VLOG_INFO("\t Removing mapping ISID=%"PRIu32", VLAN=%"PRIu16
613                       " (lldp->name=%s)", isid, vlan, lldp->name);
614
615             if (p) {
616                 hmap_remove(&lldp->mappings_by_isid, &p->hmap_node_isid);
617             }
618
619             hmap_remove(&lldp->mappings_by_aux, &m->hmap_node_aux);
620
621             /* Remove from all the lldp instances */
622             LIST_FOR_EACH (hw, h_entries, &lldp->lldpd->g_hardware) {
623                 VLOG_INFO("\t\t hardware->h_ifname=%s", hw->h_ifname);
624                 aa_mapping_unregister_mapping(lldp, hw, m);
625             }
626             free(m);
627
628             /* Remove from the all_mappings */
629             HMAP_FOR_EACH (m, hmap_node_isid, all_mappings) {
630                 if (m && isid == m->isid && vlan == m->vlan) {
631                     hmap_remove(all_mappings, &m->hmap_node_isid);
632                     break;
633                 }
634             }
635         }
636     }
637
638     ovs_mutex_unlock(&mutex);
639
640     return 0;
641 }
642
643 void
644 lldp_init(void)
645 {
646     unixctl_command_register("autoattach/status", "[bridge]", 0, 1,
647                              aa_unixctl_status, NULL);
648     unixctl_command_register("autoattach/show-isid", "[bridge]", 0, 1,
649                              aa_unixctl_show_isid, NULL);
650     unixctl_command_register("autoattach/statistics", "[bridge]", 0, 1,
651                              aa_unixctl_statistics, NULL);
652 }
653
654 /* Returns true if 'lldp' should process packets from 'flow'.  Sets
655  * fields in 'wc' that were used to make the determination.
656  */
657 bool
658 lldp_should_process_flow(struct lldp *lldp, const struct flow *flow)
659 {
660     return (flow->dl_type == htons(ETH_TYPE_LLDP) && lldp->enabled);
661 }
662
663
664 /* Process an LLDP packet that was received on a bridge port.
665  */
666 void
667 lldp_process_packet(struct lldp *lldp, const struct dp_packet *p)
668 {
669     if (lldp) {
670         lldpd_recv(lldp->lldpd, lldpd_first_hardware(lldp->lldpd),
671                    (char *) dp_packet_data(p), dp_packet_size(p));
672     }
673 }
674
675 /* This code is called periodically to check if the LLDP module has an LLDP
676  * message it wishes to send.  It is called several times every second.
677  */
678 bool
679 lldp_should_send_packet(struct lldp *cfg) OVS_EXCLUDED(mutex)
680 {
681     bool ret;
682
683     ovs_mutex_lock(&mutex);
684     ret = timer_expired(&cfg->tx_timer);
685     ovs_mutex_unlock(&mutex);
686
687     /* LLDP must be enabled */
688     ret &= cfg->enabled;
689
690     return ret;
691 }
692
693 /* Returns the next wake up time.
694  */
695 long long int
696 lldp_wake_time(const struct lldp *lldp) OVS_EXCLUDED(mutex)
697 {
698     long long int retval;
699
700     if (!lldp || !lldp->enabled) {
701         return LLONG_MAX;
702     }
703
704     ovs_mutex_lock(&mutex);
705     retval = lldp->tx_timer.t;
706     ovs_mutex_unlock(&mutex);
707
708     return retval;
709 }
710
711 /* Put the monitor thread to sleep until it's next wake time.
712  */
713 long long int
714 lldp_wait(struct lldp *lldp) OVS_EXCLUDED(mutex)
715 {
716     long long int wake_time = lldp_wake_time(lldp);
717     poll_timer_wait_until(wake_time);
718     return wake_time;
719 }
720
721 /* Prepare the LLDP packet to be sent on a bridge port.
722  */
723 void
724 lldp_put_packet(struct lldp *lldp, struct dp_packet *packet,
725                 const struct eth_addr eth_src) OVS_EXCLUDED(mutex)
726 {
727     struct lldpd *mylldpd = lldp->lldpd;
728     struct lldpd_hardware *hw = lldpd_first_hardware(mylldpd);
729     static const struct eth_addr eth_addr_lldp =
730         { { { 0x01, 0x80, 0xC2, 0x00, 0x00, 0x0e } } };
731
732     ovs_mutex_lock(&mutex);
733
734     eth_compose(packet, eth_addr_lldp, eth_src, ETH_TYPE_LLDP, 0);
735
736     lldpd_send(hw, packet);
737
738     timer_set_duration(&lldp->tx_timer, lldp->lldpd->g_config.c_tx_interval);
739     ovs_mutex_unlock(&mutex);
740 }
741
742 /* Configures the LLDP stack.
743  */
744 bool
745 lldp_configure(struct lldp *lldp, const struct smap *cfg) OVS_EXCLUDED(mutex)
746 {
747     if (lldp) {
748         if (cfg && smap_get_bool(cfg, "enable", false)) {
749             lldp->enabled = true;
750         } else {
751             lldp->enabled = false;
752         }
753
754         ovs_mutex_lock(&mutex);
755         timer_set_expired(&lldp->tx_timer);
756         timer_set_duration(&lldp->tx_timer, LLDP_DEFAULT_TRANSMIT_INTERVAL_MS);
757         lldp->lldpd->g_config.c_tx_interval =
758             LLDP_DEFAULT_TRANSMIT_INTERVAL_MS;
759         ovs_mutex_unlock(&mutex);
760     }
761
762     return true;
763 }
764
765 /* Create an LLDP stack instance.  At the moment there is one per bridge port.
766  */
767 struct lldp *
768 lldp_create(const struct netdev *netdev,
769             const uint32_t mtu,
770             const struct smap *cfg) OVS_EXCLUDED(mutex)
771 {
772     struct lldp *lldp;
773     struct lldpd_chassis *lchassis;
774     struct lldpd_hardware *hw;
775     struct aa_mapping_internal *m;
776
777     if (!cfg || !smap_get_bool(cfg, "enable", false)) {
778         return NULL;
779     }
780
781     lldp = xzalloc(sizeof *lldp);
782     lldp->name = xstrdup(netdev_get_name(netdev));
783     lldp->lldpd = xzalloc(sizeof *lldp->lldpd);
784
785     hmap_init(&lldp->mappings_by_isid);
786     hmap_init(&lldp->mappings_by_aux);
787     list_init(&lldp->active_mapping_queue);
788
789     lchassis = xzalloc(sizeof *lchassis);
790     lchassis->c_cap_available = LLDP_CAP_BRIDGE;
791     lchassis->c_cap_enabled = LLDP_CAP_BRIDGE;
792     lchassis->c_id_subtype = LLDP_CHASSISID_SUBTYPE_LLADDR;
793     lchassis->c_id_len = ETH_ADDR_LEN;
794
795     struct eth_addr *mac = xmalloc(ETH_ADDR_LEN);
796     netdev_get_etheraddr(netdev, mac);
797     lchassis->c_id = &mac->ea[0];
798
799     list_init(&lchassis->c_mgmt);
800     lchassis->c_ttl = lldp->lldpd->g_config.c_tx_interval *
801                       lldp->lldpd->g_config.c_tx_hold;
802     lchassis->c_ttl = LLDP_CHASSIS_TTL;
803     lldpd_assign_cfg_to_protocols(lldp->lldpd);
804     list_init(&lldp->lldpd->g_chassis);
805     list_push_back(&lldp->lldpd->g_chassis, &lchassis->list);
806
807     if ((hw = lldpd_alloc_hardware(lldp->lldpd,
808                                    (char *) netdev_get_name(netdev),
809                                    0)) == NULL) {
810         VLOG_WARN("Unable to allocate space for %s",
811                   (char *) netdev_get_name(netdev));
812         out_of_memory();
813     }
814
815     ovs_refcount_init(&lldp->ref_cnt);
816 #ifndef _WIN32
817     hw->h_flags |= IFF_RUNNING;
818 #endif
819     hw->h_mtu = mtu;
820     hw->h_lport.p_id_subtype = LLDP_PORTID_SUBTYPE_IFNAME;
821     hw->h_lport.p_id = xstrdup(netdev_get_name(netdev));
822
823     /* p_id is not necessarily a null terminated string. */
824     hw->h_lport.p_id_len = strlen(netdev_get_name(netdev));
825
826     /* Auto Attach element tlv */
827     hw->h_lport.p_element.type = LLDP_TLV_AA_ELEM_TYPE_CLIENT_VIRTUAL_SWITCH;
828     hw->h_lport.p_element.mgmt_vlan = 0;
829     memcpy(&hw->h_lport.p_element.system_id.system_mac,
830            lchassis->c_id, lchassis->c_id_len);
831     hw->h_lport.p_element.system_id.conn_type =
832         LLDP_TLV_AA_ELEM_CONN_TYPE_SINGLE;
833     hw->h_lport.p_element.system_id.rsvd = 0;
834     hw->h_lport.p_element.system_id.rsvd2[0] = 0;
835     hw->h_lport.p_element.system_id.rsvd2[1] = 0;
836
837     list_init(&hw->h_lport.p_isid_vlan_maps);
838     list_init(&lldp->lldpd->g_hardware);
839     list_push_back(&lldp->lldpd->g_hardware, &hw->h_entries);
840
841     ovs_mutex_lock(&mutex);
842
843     /* Update port with Auto Attach mappings configured. */
844     HMAP_FOR_EACH (m, hmap_node_isid, all_mappings) {
845         struct aa_mapping_internal *p;
846
847         if (mapping_find_by_isid(lldp, m->isid)) {
848             continue;
849         }
850
851         p = xmemdup(m, sizeof *p);
852         hmap_insert(&lldp->mappings_by_isid, &p->hmap_node_isid,
853                     hash_int(p->isid, 0));
854         hmap_insert(&lldp->mappings_by_aux,
855                     &p->hmap_node_aux,
856                     hash_pointer(p->aux, 0));
857
858         update_mapping_on_lldp(lldp, hw, p);
859     }
860
861     hmap_insert(all_lldps, &lldp->hmap_node,
862                 hash_string(netdev_get_name(netdev), 0));
863
864     ovs_mutex_unlock(&mutex);
865
866     return lldp;
867 }
868
869
870 struct lldp *
871 lldp_create_dummy(void)
872 {
873     struct lldp *lldp;
874     struct lldpd_chassis *lchassis;
875     struct lldpd_hardware *hw;
876
877     lldp = xzalloc(sizeof *lldp);
878     lldp->name = "dummy-lldp";
879     lldp->lldpd = xzalloc(sizeof *lldp->lldpd);
880
881     hmap_init(&lldp->mappings_by_isid);
882     hmap_init(&lldp->mappings_by_aux);
883     list_init(&lldp->active_mapping_queue);
884
885     lchassis = xzalloc(sizeof *lchassis);
886     lchassis->c_cap_available = LLDP_CAP_BRIDGE;
887     lchassis->c_cap_enabled = LLDP_CAP_BRIDGE;
888     lchassis->c_id_subtype = LLDP_CHASSISID_SUBTYPE_LLADDR;
889     lchassis->c_id_len = ETH_ADDR_LEN;
890
891     list_init(&lchassis->c_mgmt);
892     lchassis->c_ttl = LLDP_CHASSIS_TTL;
893     lldpd_assign_cfg_to_protocols(lldp->lldpd);
894     list_init(&lldp->lldpd->g_chassis);
895     list_push_back(&lldp->lldpd->g_chassis, &lchassis->list);
896
897     hw = lldpd_alloc_hardware(lldp->lldpd, "dummy-hw", 0);
898
899     ovs_refcount_init(&lldp->ref_cnt);
900 #ifndef _WIN32
901     hw->h_flags |= IFF_RUNNING;
902 #endif
903     hw->h_mtu = 1500;
904     hw->h_lport.p_id_subtype = LLDP_PORTID_SUBTYPE_IFNAME;
905     hw->h_lport.p_id = "dummy-port";
906
907     /* p_id is not necessarily a null terminated string. */
908     hw->h_lport.p_id_len = strlen(hw->h_lport.p_id);
909
910     /* Auto Attach element tlv */
911     hw->h_lport.p_element.type = LLDP_TLV_AA_ELEM_TYPE_CLIENT_VIRTUAL_SWITCH;
912     hw->h_lport.p_element.mgmt_vlan = 0;
913     hw->h_lport.p_element.system_id.conn_type =
914         LLDP_TLV_AA_ELEM_CONN_TYPE_SINGLE;
915     hw->h_lport.p_element.system_id.rsvd = 0;
916     hw->h_lport.p_element.system_id.rsvd2[0] = 0;
917     hw->h_lport.p_element.system_id.rsvd2[1] = 0;
918
919     list_init(&hw->h_lport.p_isid_vlan_maps);
920     list_init(&lldp->lldpd->g_hardware);
921     list_push_back(&lldp->lldpd->g_hardware, &hw->h_entries);
922
923     return lldp;
924 }
925
926 /* Unreference a specific LLDP instance.
927  */
928 void
929 lldp_unref(struct lldp *lldp)
930 {
931     if (!lldp) {
932         return;
933     }
934
935     ovs_mutex_lock(&mutex);
936     if (ovs_refcount_unref_relaxed(&lldp->ref_cnt) != 1) {
937         ovs_mutex_unlock(&mutex);
938         return;
939     }
940
941     hmap_remove(all_lldps, &lldp->hmap_node);
942     ovs_mutex_unlock(&mutex);
943
944     lldpd_cleanup(lldp->lldpd);
945     free(lldp->lldpd);
946     free(lldp->name);
947     free(lldp);
948 }
949
950 /* Reference a specific LLDP instance.
951  */
952 struct lldp *
953 lldp_ref(const struct lldp *lldp_)
954 {
955     struct lldp *lldp = CONST_CAST(struct lldp *, lldp_);
956     if (lldp) {
957         ovs_refcount_ref(&lldp->ref_cnt);
958     }
959     return lldp;
960 }
961
962 void
963 lldp_destroy_dummy(struct lldp *lldp)
964 {
965     struct lldpd_hardware *hw, *hw_next;
966     struct lldpd_chassis *chassis, *chassis_next;
967     struct lldpd *cfg;
968
969     if (!lldp) {
970         return;
971     }
972
973     cfg = lldp->lldpd;
974
975     LIST_FOR_EACH_SAFE (hw, hw_next, h_entries, &cfg->g_hardware) {
976         list_remove(&hw->h_entries);
977         free(hw->h_lport.p_lastframe);
978         free(hw);
979     }
980
981     LIST_FOR_EACH_SAFE (chassis, chassis_next, list, &cfg->g_chassis) {
982         list_remove(&chassis->list);
983         free(chassis);
984     }
985
986     free(lldp->lldpd);
987     free(lldp);
988 }
989