lacp: New "strict" lacp mode.
[sliver-openvswitch.git] / lib / lacp.c
1 /* Copyright (c) 2011 Nicira Networks
2  *
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15
16 #include <config.h>
17 #include "lacp.h"
18
19 #include <assert.h>
20 #include <stdlib.h>
21
22 #include "dynamic-string.h"
23 #include "hash.h"
24 #include "hmap.h"
25 #include "ofpbuf.h"
26 #include "packets.h"
27 #include "poll-loop.h"
28 #include "timer.h"
29 #include "timeval.h"
30 #include "unixctl.h"
31 #include "vlog.h"
32
33 VLOG_DEFINE_THIS_MODULE(lacp);
34
35 enum slave_status {
36     LACP_CURRENT,   /* Current State.  Partner up to date. */
37     LACP_EXPIRED,   /* Expired State.  Partner out of date. */
38     LACP_DEFAULTED, /* Defaulted State.  No partner. */
39 };
40
41 struct lacp {
42     struct list node;             /* Node in all_lacps list. */
43     char *name;                   /* Name of this lacp object. */
44     uint8_t sys_id[ETH_ADDR_LEN]; /* System ID. */
45     uint16_t sys_priority;        /* System Priority. */
46     bool active;                  /* Active or Passive. */
47
48     struct hmap slaves;      /* Slaves this LACP object controls. */
49     struct slave *key_slave; /* Slave whose ID will be the aggregation key. */
50
51     bool fast;                /* Fast or Slow LACP time. */
52     bool strict;             /* True if in strict mode. */
53     bool negotiated;         /* True if LACP negotiations were successful. */
54     bool update;             /* True if lacp_update() needs to be called. */
55 };
56
57 struct slave {
58     void *aux;                    /* Handle used to identify this slave. */
59     struct hmap_node node;        /* Node in master's slaves map. */
60
61     struct lacp *lacp;            /* LACP object containing this slave. */
62     uint16_t port_id;             /* Port ID. */
63     uint16_t port_priority;       /* Port Priority. */
64     char *name;                   /* Name of this slave. */
65
66     enum slave_status status;     /* Slave status. */
67     bool attached;                /* Attached. Traffic may flow. */
68     struct lacp_info partner;     /* Partner information. */
69     struct lacp_info ntt_actor;   /* Used to decide if we Need To Transmit. */
70     struct timer tx;              /* Next message transmission timer. */
71     struct timer rx;              /* Expected message receive timer. */
72 };
73
74 static struct list all_lacps = LIST_INITIALIZER(&all_lacps);
75
76 static void lacp_update_attached(struct lacp *);
77
78 static void slave_destroy(struct slave *);
79 static void slave_set_defaulted(struct slave *);
80 static void slave_set_expired(struct slave *);
81 static void slave_get_actor(struct slave *, struct lacp_info *actor);
82 static void slave_get_priority(struct slave *, struct lacp_info *priority);
83 static bool slave_may_tx(const struct slave *);
84 static struct slave *slave_lookup(const struct lacp *, const void *slave);
85 static bool info_tx_equal(struct lacp_info *, struct lacp_info *);
86
87 static void lacp_unixctl_show(struct unixctl_conn *, const char *args,
88                               void *aux);
89
90 /* Initializes the lacp module. */
91 void
92 lacp_init(void)
93 {
94     unixctl_command_register("lacp/show", lacp_unixctl_show, NULL);
95 }
96
97 /* Creates a LACP object. */
98 struct lacp *
99 lacp_create(void)
100 {
101     struct lacp *lacp;
102
103     lacp = xzalloc(sizeof *lacp);
104     hmap_init(&lacp->slaves);
105     list_push_back(&all_lacps, &lacp->node);
106     return lacp;
107 }
108
109 /* Destroys 'lacp' and its slaves. Does nothing if 'lacp' is NULL. */
110 void
111 lacp_destroy(struct lacp *lacp)
112 {
113     if (lacp) {
114         struct slave *slave, *next;
115
116         HMAP_FOR_EACH_SAFE (slave, next, node, &lacp->slaves) {
117             slave_destroy(slave);
118         }
119
120         hmap_destroy(&lacp->slaves);
121         list_remove(&lacp->node);
122         free(lacp->name);
123         free(lacp);
124     }
125 }
126
127 /* Configures 'lacp' with settings from 's'. */
128 void
129 lacp_configure(struct lacp *lacp, const struct lacp_settings *s)
130 {
131     if (!lacp->name || strcmp(s->name, lacp->name)) {
132         free(lacp->name);
133         lacp->name = xstrdup(s->name);
134     }
135
136     if (!eth_addr_equals(lacp->sys_id, s->id)
137         || lacp->sys_priority != s->priority
138         || lacp->strict != s->strict) {
139         memcpy(lacp->sys_id, s->id, ETH_ADDR_LEN);
140         lacp->sys_priority = s->priority;
141         lacp->strict = s->strict;
142         lacp->update = true;
143     }
144
145     lacp->active = s->active;
146     lacp->fast = s->fast;
147 }
148
149 /* Returns true if 'lacp' is configured in active mode, false if 'lacp' is
150  * configured for passive mode. */
151 bool
152 lacp_is_active(const struct lacp *lacp)
153 {
154     return lacp->active;
155 }
156
157 /* Processes 'pdu', a parsed LACP packet received on 'slave_'.  This function
158  * should be called on all packets received on 'slave_' with Ethernet Type
159  * ETH_TYPE_LACP and parsable by parse_lacp_packet(). */
160 void
161 lacp_process_pdu(struct lacp *lacp, const void *slave_,
162                  const struct lacp_pdu *pdu)
163 {
164     struct slave *slave = slave_lookup(lacp, slave_);
165
166     slave->status = LACP_CURRENT;
167     timer_set_duration(&slave->rx, (lacp->fast
168                                     ? LACP_FAST_TIME_RX
169                                     : LACP_SLOW_TIME_RX));
170
171     slave->ntt_actor = pdu->partner;
172
173     /* Update our information about our partner if it's out of date.  This may
174      * cause priorities to change so re-calculate attached status of all
175      * slaves.  */
176     if (memcmp(&slave->partner, &pdu->actor, sizeof pdu->actor)) {
177         lacp->update = true;
178         slave->partner = pdu->actor;
179     }
180 }
181
182 /* Returns true if 'lacp' has successfully negotiated with its partner.  False
183  * if 'lacp' is NULL. */
184 bool
185 lacp_negotiated(const struct lacp *lacp)
186 {
187     return lacp ? lacp->negotiated : false;
188 }
189
190 /* Registers 'slave_' as subordinate to 'lacp'.  This should be called at least
191  * once per slave in a LACP managed bond.  Should also be called whenever a
192  * slave's settings change. */
193 void
194 lacp_slave_register(struct lacp *lacp, void *slave_,
195                     const struct lacp_slave_settings *s)
196 {
197     struct slave *slave = slave_lookup(lacp, slave_);
198
199     if (!slave) {
200         slave = xzalloc(sizeof *slave);
201         slave->lacp = lacp;
202         slave->aux = slave_;
203         hmap_insert(&lacp->slaves, &slave->node, hash_pointer(slave_, 0));
204         slave_set_defaulted(slave);
205
206         if (!lacp->key_slave) {
207             lacp->key_slave = slave;
208         }
209     }
210
211     if (!slave->name || strcmp(s->name, slave->name)) {
212         free(slave->name);
213         slave->name = xstrdup(s->name);
214     }
215
216     if (slave->port_id != s->id || slave->port_priority != s->priority) {
217         slave->port_id = s->id;
218         slave->port_priority = s->priority;
219
220         lacp->update = true;
221
222         if (lacp->active || lacp->negotiated) {
223             slave_set_expired(slave);
224         }
225     }
226 }
227
228 /* Unregisters 'slave_' with 'lacp'.  */
229 void
230 lacp_slave_unregister(struct lacp *lacp, const void *slave_)
231 {
232     struct slave *slave = slave_lookup(lacp, slave_);
233
234     if (slave) {
235         slave_destroy(slave);
236         lacp->update = true;
237     }
238 }
239
240 /* This function should be called whenever the carrier status of 'slave_' has
241  * changed. */
242 void
243 lacp_slave_carrier_changed(const struct lacp *lacp, const void *slave_)
244 {
245     struct slave *slave = slave_lookup(lacp, slave_);
246
247     if (slave->status == LACP_CURRENT || slave->lacp->active) {
248         slave_set_expired(slave);
249     }
250 }
251
252 /* This function should be called before enabling 'slave_' to send or receive
253  * traffic.  If it returns false, 'slave_' should not enabled.  As a
254  * convenience, returns true if 'lacp' is NULL. */
255 bool
256 lacp_slave_may_enable(const struct lacp *lacp, const void *slave_)
257 {
258     if (lacp) {
259         struct slave *slave = slave_lookup(lacp, slave_);
260
261         /* The slave may be enabled if it's attached to an aggregator and its
262          * partner is synchronized.  The only exception is defaulted slaves.
263          * They are not required to have synchronized partners because they
264          * have no partners at all.  They will only be attached if negotiations
265          * failed on all slaves in the bond. */
266         return slave->attached && (slave->partner.state & LACP_STATE_SYNC
267                                    || slave->status == LACP_DEFAULTED);
268     } else {
269         return true;
270     }
271 }
272
273 /* Returns the port ID used for 'slave_' in LACP communications. */
274 uint16_t
275 lacp_slave_get_port_id(const struct lacp *lacp, const void *slave_)
276 {
277     struct slave *slave = slave_lookup(lacp, slave_);
278     return slave->port_id;
279 }
280
281 /* Returns true if partner information on 'slave_' is up to date.  'slave_'
282  * not being current, generally indicates a connectivity problem, or a
283  * misconfigured (or broken) partner. */
284 bool
285 lacp_slave_is_current(const struct lacp *lacp, const void *slave_)
286 {
287     return slave_lookup(lacp, slave_)->status == LACP_CURRENT;
288 }
289
290 /* This function should be called periodically to update 'lacp'. */
291 void
292 lacp_run(struct lacp *lacp, lacp_send_pdu *send_pdu)
293 {
294     struct slave *slave;
295
296     HMAP_FOR_EACH (slave, node, &lacp->slaves) {
297         if (timer_expired(&slave->rx)) {
298             if (slave->status == LACP_CURRENT) {
299                 slave_set_expired(slave);
300             } else if (slave->status == LACP_EXPIRED) {
301                 slave_set_defaulted(slave);
302             }
303         }
304     }
305
306     if (lacp->update) {
307         lacp_update_attached(lacp);
308     }
309
310     HMAP_FOR_EACH (slave, node, &lacp->slaves) {
311         struct lacp_pdu pdu;
312         struct lacp_info actor;
313
314         if (!slave_may_tx(slave)) {
315             continue;
316         }
317
318         slave_get_actor(slave, &actor);
319
320         if (timer_expired(&slave->tx)
321             || !info_tx_equal(&actor, &slave->ntt_actor)) {
322
323             slave->ntt_actor = actor;
324             compose_lacp_pdu(&actor, &slave->partner, &pdu);
325             send_pdu(slave->aux, &pdu);
326
327             timer_set_duration(&slave->tx,
328                                (slave->partner.state & LACP_STATE_TIME
329                                 ? LACP_FAST_TIME_TX
330                                 : LACP_SLOW_TIME_TX));
331         }
332     }
333 }
334
335 /* Causes poll_block() to wake up when lacp_run() needs to be called again. */
336 void
337 lacp_wait(struct lacp *lacp)
338 {
339     struct slave *slave;
340
341     HMAP_FOR_EACH (slave, node, &lacp->slaves) {
342         if (slave_may_tx(slave)) {
343             timer_wait(&slave->tx);
344         }
345
346         if (slave->status != LACP_DEFAULTED) {
347             timer_wait(&slave->rx);
348         }
349     }
350 }
351 \f
352 /* Static Helpers. */
353
354 /* Updates the attached status of all slaves controlled by 'lacp' and sets its
355  * negotiated parameter to true if any slaves are attachable. */
356 static void
357 lacp_update_attached(struct lacp *lacp)
358 {
359     struct slave *lead, *slave;
360     struct lacp_info lead_pri;
361     static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 10);
362
363     lacp->update = false;
364
365     lead = NULL;
366     HMAP_FOR_EACH (slave, node, &lacp->slaves) {
367         struct lacp_info pri;
368
369         slave->attached = true;
370
371         /* XXX: In the future allow users to configure the expected system ID.
372          * For now just special case loopback. */
373         if (eth_addr_equals(slave->partner.sys_id, slave->lacp->sys_id)) {
374             VLOG_WARN_RL(&rl, "slave %s: Loopback detected. Slave is "
375                          "connected to its own bond", slave->name);
376             slave->attached = false;
377             continue;
378         }
379
380         if (slave->status == LACP_DEFAULTED) {
381             continue;
382         }
383
384         slave_get_priority(slave, &pri);
385
386         if (!lead || memcmp(&pri, &lead_pri, sizeof pri) < 0) {
387             lead = slave;
388             lead_pri = pri;
389         }
390     }
391
392     lacp->negotiated = lead != NULL;
393
394     if (lead) {
395         HMAP_FOR_EACH (slave, node, &lacp->slaves) {
396             if (slave->status == LACP_DEFAULTED
397                 || lead->partner.key != slave->partner.key
398                 || !eth_addr_equals(lead->partner.sys_id,
399                                     slave->partner.sys_id)) {
400                 slave->attached = false;
401             }
402         }
403     } else if (lacp->strict) {
404         HMAP_FOR_EACH (slave, node, &lacp->slaves) {
405             slave->attached = false;
406         }
407     }
408 }
409
410 static void
411 slave_destroy(struct slave *slave)
412 {
413     if (slave) {
414         struct lacp *lacp = slave->lacp;
415
416         lacp->update = true;
417         hmap_remove(&lacp->slaves, &slave->node);
418
419         if (lacp->key_slave == slave) {
420             struct hmap_node *slave_node = hmap_first(&lacp->slaves);
421
422             if (slave_node) {
423                 lacp->key_slave = CONTAINER_OF(slave_node, struct slave, node);
424             } else {
425                 lacp->key_slave = NULL;
426             }
427         }
428
429         free(slave->name);
430         free(slave);
431     }
432 }
433
434 static void
435 slave_set_defaulted(struct slave *slave)
436 {
437     memset(&slave->partner, 0, sizeof slave->partner);
438
439     slave->lacp->update = true;
440     slave->status = LACP_DEFAULTED;
441 }
442
443 static void
444 slave_set_expired(struct slave *slave)
445 {
446     slave->status = LACP_EXPIRED;
447     slave->partner.state |= LACP_STATE_TIME;
448     slave->partner.state &= ~LACP_STATE_SYNC;
449     timer_set_duration(&slave->rx, LACP_FAST_TIME_RX);
450 }
451
452 static void
453 slave_get_actor(struct slave *slave, struct lacp_info *actor)
454 {
455     uint8_t state = 0;
456
457     if (slave->lacp->active) {
458         state |= LACP_STATE_ACT;
459     }
460
461     if (slave->lacp->fast) {
462         state |= LACP_STATE_TIME;
463     }
464
465     if (slave->attached) {
466         state |= LACP_STATE_SYNC;
467     }
468
469     if (slave->status == LACP_DEFAULTED) {
470         state |= LACP_STATE_DEF;
471     }
472
473     if (slave->status == LACP_EXPIRED) {
474         state |= LACP_STATE_EXP;
475     }
476
477     if (hmap_count(&slave->lacp->slaves) > 1) {
478         state |= LACP_STATE_AGG;
479     }
480
481     if (slave->attached || !slave->lacp->negotiated) {
482         state |= LACP_STATE_COL | LACP_STATE_DIST;
483     }
484
485     actor->state = state;
486     actor->key = htons(slave->lacp->key_slave->port_id);
487     actor->port_priority = htons(slave->port_priority);
488     actor->port_id = htons(slave->port_id);
489     actor->sys_priority = htons(slave->lacp->sys_priority);
490     memcpy(&actor->sys_id, slave->lacp->sys_id, ETH_ADDR_LEN);
491 }
492
493 /* Given 'slave', populates 'priority' with data representing its LACP link
494  * priority.  If two priority objects populated by this function are compared
495  * using memcmp, the higher priority link will be less than the lower priority
496  * link. */
497 static void
498 slave_get_priority(struct slave *slave, struct lacp_info *priority)
499 {
500     uint16_t partner_priority, actor_priority;
501
502     /* Choose the lacp_info of the higher priority system by comparing their
503      * system priorities and mac addresses. */
504     actor_priority = slave->lacp->sys_priority;
505     partner_priority = ntohs(slave->partner.sys_priority);
506     if (actor_priority < partner_priority) {
507         slave_get_actor(slave, priority);
508     } else if (partner_priority < actor_priority) {
509         *priority = slave->partner;
510     } else if (eth_addr_compare_3way(slave->lacp->sys_id,
511                                      slave->partner.sys_id) < 0) {
512         slave_get_actor(slave, priority);
513     } else {
514         *priority = slave->partner;
515     }
516
517     /* Key and state are not used in priority comparisons. */
518     priority->key = 0;
519     priority->state = 0;
520 }
521
522 static bool
523 slave_may_tx(const struct slave *slave)
524 {
525     return slave->lacp->active || slave->status != LACP_DEFAULTED;
526 }
527
528 static struct slave *
529 slave_lookup(const struct lacp *lacp, const void *slave_)
530 {
531     struct slave *slave;
532
533     HMAP_FOR_EACH_IN_BUCKET (slave, node, hash_pointer(slave_, 0),
534                              &lacp->slaves) {
535         if (slave->aux == slave_) {
536             return slave;
537         }
538     }
539
540     return NULL;
541 }
542
543 /* Two lacp_info structures are tx_equal if and only if they do not differ in
544  * ways which would require a lacp_pdu transmission. */
545 static bool
546 info_tx_equal(struct lacp_info *a, struct lacp_info *b)
547 {
548
549     /* LACP specification dictates that we transmit whenever the actor and
550      * remote_actor differ in the following fields: Port, Port Priority,
551      * System, System Priority, Aggregation Key, Activity State, Timeout State,
552      * Sync State, and Aggregation State. The state flags are most likely to
553      * change so are checked first. */
554     return !((a->state ^ b->state) & (LACP_STATE_ACT
555                                       | LACP_STATE_TIME
556                                       | LACP_STATE_SYNC
557                                       | LACP_STATE_AGG))
558         && a->port_id == b->port_id
559         && a->port_priority == b->port_priority
560         && a->key == b->key
561         && a->sys_priority == b->sys_priority
562         && eth_addr_equals(a->sys_id, b->sys_id);
563 }
564 \f
565 static struct lacp *
566 lacp_find(const char *name)
567 {
568     struct lacp *lacp;
569
570     LIST_FOR_EACH (lacp, node, &all_lacps) {
571         if (!strcmp(lacp->name, name)) {
572             return lacp;
573         }
574     }
575
576     return NULL;
577 }
578
579 static void
580 ds_put_lacp_state(struct ds *ds, uint8_t state)
581 {
582     if (state & LACP_STATE_ACT) {
583         ds_put_cstr(ds, "activity ");
584     }
585
586     if (state & LACP_STATE_TIME) {
587         ds_put_cstr(ds, "timeout ");
588     }
589
590     if (state & LACP_STATE_AGG) {
591         ds_put_cstr(ds, "aggregation ");
592     }
593
594     if (state & LACP_STATE_SYNC) {
595         ds_put_cstr(ds, "synchronized ");
596     }
597
598     if (state & LACP_STATE_COL) {
599         ds_put_cstr(ds, "collecting ");
600     }
601
602     if (state & LACP_STATE_DIST) {
603         ds_put_cstr(ds, "distributing ");
604     }
605
606     if (state & LACP_STATE_DEF) {
607         ds_put_cstr(ds, "defaulted ");
608     }
609
610     if (state & LACP_STATE_EXP) {
611         ds_put_cstr(ds, "expired ");
612     }
613 }
614
615 static void
616 lacp_unixctl_show(struct unixctl_conn *conn,
617                   const char *args, void *aux OVS_UNUSED)
618 {
619     struct ds ds = DS_EMPTY_INITIALIZER;
620     struct lacp *lacp;
621     struct slave *slave;
622
623     lacp = lacp_find(args);
624     if (!lacp) {
625         unixctl_command_reply(conn, 501, "no such lacp object");
626         return;
627     }
628
629     ds_put_format(&ds, "lacp: %s\n", lacp->name);
630
631     ds_put_format(&ds, "\tstatus: %s", lacp->active ? "active" : "passive");
632     if (lacp->strict) {
633         ds_put_cstr(&ds, " strict");
634     }
635     if (lacp->negotiated) {
636         ds_put_cstr(&ds, " negotiated");
637     }
638     ds_put_cstr(&ds, "\n");
639
640     ds_put_format(&ds, "\tsys_id: " ETH_ADDR_FMT "\n", ETH_ADDR_ARGS(lacp->sys_id));
641     ds_put_format(&ds, "\tsys_priority: %u\n", lacp->sys_priority);
642     ds_put_cstr(&ds, "\taggregation key: ");
643     if (lacp->key_slave) {
644         ds_put_format(&ds, "%u", lacp->key_slave->port_id);
645     } else {
646         ds_put_cstr(&ds, "none");
647     }
648     ds_put_cstr(&ds, "\n");
649
650     HMAP_FOR_EACH (slave, node, &lacp->slaves) {
651         char *status;
652         struct lacp_info actor;
653
654         slave_get_actor(slave, &actor);
655         switch (slave->status) {
656         case LACP_CURRENT:
657             status = "current";
658             break;
659         case LACP_EXPIRED:
660             status = "expired";
661             break;
662         case LACP_DEFAULTED:
663             status = "defaulted";
664             break;
665         default:
666             NOT_REACHED();
667         }
668
669         ds_put_format(&ds, "\nslave: %s: %s %s\n", slave->name, status,
670                       slave->attached ? "attached" : "detached");
671         ds_put_format(&ds, "\tport_id: %u\n", slave->port_id);
672         ds_put_format(&ds, "\tport_priority: %u\n", slave->port_priority);
673
674         ds_put_format(&ds, "\n\tactor sys_id: " ETH_ADDR_FMT "\n",
675                       ETH_ADDR_ARGS(actor.sys_id));
676         ds_put_format(&ds, "\tactor sys_priority: %u\n",
677                       ntohs(actor.sys_priority));
678         ds_put_format(&ds, "\tactor port_id: %u\n",
679                       ntohs(actor.port_id));
680         ds_put_format(&ds, "\tactor port_priority: %u\n",
681                       ntohs(actor.port_priority));
682         ds_put_format(&ds, "\tactor key: %u\n",
683                       ntohs(actor.key));
684         ds_put_cstr(&ds, "\tactor state: ");
685         ds_put_lacp_state(&ds, actor.state);
686         ds_put_cstr(&ds, "\n\n");
687
688         ds_put_format(&ds, "\tpartner sys_id: " ETH_ADDR_FMT "\n",
689                       ETH_ADDR_ARGS(slave->partner.sys_id));
690         ds_put_format(&ds, "\tpartner sys_priority: %u\n",
691                       ntohs(slave->partner.sys_priority));
692         ds_put_format(&ds, "\tpartner port_id: %u\n",
693                       ntohs(slave->partner.port_id));
694         ds_put_format(&ds, "\tpartner port_priority: %u\n",
695                       ntohs(slave->partner.port_priority));
696         ds_put_format(&ds, "\tpartner key: %u\n",
697                       ntohs(slave->partner.key));
698         ds_put_cstr(&ds, "\tpartner state: ");
699         ds_put_lacp_state(&ds, slave->partner.state);
700         ds_put_cstr(&ds, "\n");
701     }
702
703     unixctl_command_reply(conn, 200, ds_cstr(&ds));
704     ds_destroy(&ds);
705 }