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