Skip to content

Commit

Permalink
Don't put down LAG interface when it starts in WR mode (#2257)
Browse files Browse the repository at this point in the history
* Don't put down LAG interface when it starts in WR mode

* Change logic. Don't touch carrier in WR mode. Until it could be in UP mode

* Change control plane restore logic in WR mode
  • Loading branch information
pavel-shirshov authored Nov 20, 2018
1 parent ecca7e9 commit f6f8880
Showing 1 changed file with 144 additions and 27 deletions.
171 changes: 144 additions & 27 deletions src/libteam/0005-libteam-Add-warm_reboot-mode.patch
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ index 72155ae..44de4ca 100644
}
}
diff --git a/teamd/teamd.c b/teamd/teamd.c
index c987333..53aec1d 100644
index c987333..225b8c8 100644
--- a/teamd/teamd.c
+++ b/teamd/teamd.c
@@ -116,7 +116,9 @@ static void print_help(const struct teamd_context *ctx) {
Expand Down Expand Up @@ -58,12 +58,13 @@ index c987333..53aec1d 100644
long_options, NULL)) >= 0) {

switch(opt) {
@@ -230,6 +234,17 @@ static int parse_command_line(struct teamd_context *ctx,
@@ -230,11 +234,29 @@ static int parse_command_line(struct teamd_context *ctx,
case 'u':
ctx->usock.enabled = false;
break;
+ case 'w':
+ ctx->warm_start = true;
+ ctx->warm_start_read = true;
+ ctx->warm_start_carrier = true;
+ break;
+ case 'L':
+ ctx->lacp_directory = strdup(optarg);
Expand All @@ -76,7 +77,18 @@ index c987333..53aec1d 100644
default:
return -1;
}
@@ -384,8 +399,14 @@ static int teamd_run_loop_run(struct teamd_context *ctx)
}

+ if (ctx->warm_start_read && !ctx->lacp_directory) {
+ fprintf(stderr, "Can't enable warm-start mode without lacp-directory specified\n");
+ ctx->warm_start_read = false;
+ ctx->warm_start_carrier = false;
+ }
+
if (optind < argc) {
fprintf(stderr, "Too many arguments\n");
return -1;
@@ -384,8 +406,14 @@ static int teamd_run_loop_run(struct teamd_context *ctx)
if (err != -1) {
switch(ctrl_byte) {
case 'q':
Expand All @@ -91,7 +103,7 @@ index c987333..53aec1d 100644
teamd_refresh_ports(ctx);
err = teamd_flush_ports(ctx);
if (err)
@@ -428,6 +449,12 @@ void teamd_run_loop_quit(struct teamd_context *ctx, int err)
@@ -428,6 +456,12 @@ void teamd_run_loop_quit(struct teamd_context *ctx, int err)
teamd_run_loop_sent_ctrl_byte(ctx, 'q');
}

Expand All @@ -104,7 +116,7 @@ index c987333..53aec1d 100644
void teamd_run_loop_restart(struct teamd_context *ctx)
{
teamd_run_loop_sent_ctrl_byte(ctx, 'r');
@@ -694,6 +721,10 @@ static int callback_daemon_signal(struct teamd_context *ctx, int events,
@@ -694,6 +728,10 @@ static int callback_daemon_signal(struct teamd_context *ctx, int events,
teamd_log_warn("Got SIGINT, SIGQUIT or SIGTERM.");
teamd_run_loop_quit(ctx, 0);
break;
Expand All @@ -115,7 +127,7 @@ index c987333..53aec1d 100644
}
return 0;
}
@@ -1507,7 +1538,7 @@ static int teamd_start(struct teamd_context *ctx, enum teamd_exit_code *p_ret)
@@ -1507,7 +1545,7 @@ static int teamd_start(struct teamd_context *ctx, enum teamd_exit_code *p_ret)
return -errno;
}

Expand All @@ -125,20 +137,21 @@ index c987333..53aec1d 100644
daemon_retval_send(errno);
err = -errno;
diff --git a/teamd/teamd.h b/teamd/teamd.h
index ef0fb1c..b1b6dfe 100644
index ef0fb1c..622c365 100644
--- a/teamd/teamd.h
+++ b/teamd/teamd.h
@@ -125,6 +125,9 @@ struct teamd_context {
@@ -125,6 +125,10 @@ struct teamd_context {
char * hwaddr;
uint32_t hwaddr_len;
bool hwaddr_explicit;
+ bool warm_start;
+ bool warm_start_read;
+ bool warm_start_carrier;
+ bool keep_ports;
+ char * lacp_directory;
struct {
struct list_item callback_list;
int ctrl_pipe_r;
@@ -191,12 +194,15 @@ struct teamd_event_watch_ops {
@@ -191,12 +195,15 @@ struct teamd_event_watch_ops {
struct teamd_port *tdport, void *priv);
void (*refresh)(struct teamd_context *ctx,
struct teamd_port *tdport, void *priv);
Expand Down Expand Up @@ -179,19 +192,66 @@ index 5c2ef56..50e5a08 100644
struct teamd_port *tdport)
{
diff --git a/teamd/teamd_runner_lacp.c b/teamd/teamd_runner_lacp.c
index 81324de..519f5e2 100644
index 81324de..2a453bd 100644
--- a/teamd/teamd_runner_lacp.c
+++ b/teamd/teamd_runner_lacp.c
@@ -174,6 +174,8 @@ struct lacp_port {
@@ -31,6 +31,7 @@
#include <team.h>
#include <private/misc.h>
#include <net/ethernet.h>
+#include <time.h>

#include "teamd.h"
#include "teamd_config.h"
@@ -131,6 +132,7 @@ struct lacp {
struct teamd_context *ctx;
struct lacp_port *selected_agg_lead; /* leading port of selected aggregator */
bool carrier_up;
+ time_t warm_start_carrier_timer;
struct {
bool active;
#define LACP_CFG_DFLT_ACTIVE true
@@ -174,6 +176,9 @@ struct lacp_port {
struct lacp_port *agg_lead; /* leading port of aggregator.
* NULL in case this port is not selected */
enum lacp_port_state state;
+ bool lacpdu_saved;
+ bool lacpdu_read;
+ struct lacpdu last_pdu;
struct {
uint32_t speed;
uint8_t duplex;
@@ -994,6 +996,13 @@ static int lacp_port_set_state(struct lacp_port *lacp_port,
@@ -491,15 +496,28 @@ static int lacp_update_carrier(struct lacp *lacp)
bool state;
int err;

+ #define WARM_START_CARRIER_TIMEOUT 3
+ /* wait three seconds until disable warm_start_carrier mode */
+ if (lacp->ctx->warm_start_carrier &&
+ lacp->warm_start_carrier_timer >= (time(NULL) + WARM_START_CARRIER_TIMEOUT)) {
+ lacp->ctx->warm_start_carrier = false;
+ lacp->warm_start_carrier_timer = 0;
+ }
+
ports_enabled = 0;
teamd_for_each_tdport(tdport, lacp->ctx) {
err = teamd_port_enabled(lacp->ctx, tdport, &state);
if (err)
return err;
- if (state && ++ports_enabled >= lacp->cfg.min_ports)
+ if (state && ++ports_enabled >= lacp->cfg.min_ports) {
+ lacp->ctx->warm_start_carrier = false;
return lacp_set_carrier(lacp, true);
+ }
}

+ if (lacp->ctx->warm_start_carrier)
+ return 0; /* Don't put carrier down if we're in warm_start_carrier mode */
+
return lacp_set_carrier(lacp, false);
}

@@ -994,6 +1012,13 @@ static int lacp_port_set_state(struct lacp_port *lacp_port,
break;
}

Expand All @@ -205,7 +265,7 @@ index 81324de..519f5e2 100644
teamd_log_info("%s: Changed port state: \"%s\" -> \"%s\"",
lacp_port->tdport->ifname,
lacp_port_state_name[lacp_port->state],
@@ -1084,26 +1093,23 @@ static int lacpdu_send(struct lacp_port *lacp_port)
@@ -1084,26 +1109,23 @@ static int lacpdu_send(struct lacp_port *lacp_port)
return err;
}

Expand Down Expand Up @@ -240,7 +300,7 @@ index 81324de..519f5e2 100644
err = lacp_port_partner_update(lacp_port);
if (err)
return err;
@@ -1118,7 +1124,7 @@ static int lacpdu_recv(struct lacp_port *lacp_port)
@@ -1118,7 +1140,7 @@ static int lacpdu_recv(struct lacp_port *lacp_port)

/* Check if the other side has correct info about us */
if (!lacp_port->periodic_on &&
Expand All @@ -249,7 +309,7 @@ index 81324de..519f5e2 100644
sizeof(struct lacpdu_info))) {
err = lacpdu_send(lacp_port);
if (err)
@@ -1133,6 +1139,59 @@ static int lacpdu_recv(struct lacp_port *lacp_port)
@@ -1133,6 +1155,77 @@ static int lacpdu_recv(struct lacp_port *lacp_port)
return 0;
}

Expand All @@ -273,6 +333,22 @@ index 81324de..519f5e2 100644
+ char filename[PATH_MAX];
+ struct lacpdu lacpdu;
+ int err, nitems;
+ struct teamd_port *tdport;
+ bool all_port_read = true;
+
+ /* we read saved lacpdu for the current lacp_port */
+ lacp_port->lacpdu_read = true;
+
+ /* go through all current ports, if the lacp state were read
+ for all of them, disable warm_start_read mode */
+ teamd_for_each_tdport(tdport, lacp_port->ctx) {
+ struct lacp_port *it;
+ it = lacp_port_get(lacp_port->lacp, tdport);
+ all_port_read = all_port_read && it->lacpdu_read;
+ }
+
+ if (all_port_read) /* we read lacp state for all ports */
+ lacp_port->ctx->warm_start_read = false;
+
+ strcpy(filename, lacp_port->ctx->lacp_directory);
+ if (filename[strlen(filename) - 1] != '/')
Expand All @@ -294,7 +370,7 @@ index 81324de..519f5e2 100644
+ (void)fclose(fp);
+
+ err = unlink(filename);
+ if(err < 0) {
+ if (err < 0) {
+ teamd_log_err("Can't remove file %s: %s", filename, strerror(errno));
+ }
+
Expand All @@ -303,26 +379,29 @@ index 81324de..519f5e2 100644
+ return err;
+ }
+
+ teamd_log_err("%s: LACP state was read", lacp_port->tdport->ifname);
+
+ return lacpdu_process(lacp_port, &lacpdu);
+}
+
static int lacp_callback_timeout(struct teamd_context *ctx, int events,
void *priv)
{
@@ -1299,6 +1358,12 @@ static int lacp_port_added(struct teamd_context *ctx,
@@ -1299,6 +1392,13 @@ static int lacp_port_added(struct teamd_context *ctx,
lacp_port_actor_init(lacp_port);
lacp_port_link_update(lacp_port);

+ /* Read data from file and process it */
+ if (ctx->warm_start && ctx->lacp_directory) {
+ (void)lacpdu_read(lacp_port);
+ /* Once started, keep running in normal mode */
+ if (ctx->warm_start_read) {
+ err = lacpdu_read(lacp_port);
+ if (err)
+ goto timeout_callback_del;
+ }
+
teamd_loop_callback_enable(ctx, LACP_SOCKET_CB_NAME, lacp_port);
return 0;

@@ -1321,7 +1386,11 @@ static void lacp_port_removed(struct teamd_context *ctx,
@@ -1321,7 +1421,11 @@ static void lacp_port_removed(struct teamd_context *ctx,
{
struct lacp_port *lacp_port = priv;

Expand All @@ -335,7 +414,7 @@ index 81324de..519f5e2 100644
teamd_loop_callback_del(ctx, LACP_TIMEOUT_CB_NAME, lacp_port);
teamd_loop_callback_del(ctx, LACP_PERIODIC_CB_NAME, lacp_port);
teamd_loop_callback_del(ctx, LACP_SOCKET_CB_NAME, lacp_port);
@@ -1413,6 +1482,31 @@ static void lacp_event_watch_refresh(struct teamd_context *ctx, struct teamd_por
@@ -1413,6 +1517,31 @@ static void lacp_event_watch_refresh(struct teamd_context *ctx, struct teamd_por
(void) lacpdu_send(lacp_port);
}

Expand All @@ -344,7 +423,7 @@ index 81324de..519f5e2 100644
+ struct lacp *lacp = priv;
+
+ struct lacp_port *lacp_port = lacp_port_get(lacp, tdport);
+ if(lacp_port->lacpdu_saved && lacp_port->ctx->lacp_directory) {
+ if (lacp_port->lacpdu_saved && lacp_port->ctx->lacp_directory) {
+ char filename[PATH_MAX];
+ strcpy(filename, lacp_port->ctx->lacp_directory);
+ if (filename[strlen(filename) - 1] != '/')
Expand All @@ -367,15 +446,53 @@ index 81324de..519f5e2 100644
static const struct teamd_event_watch_ops lacp_event_watch_ops = {
.hwaddr_changed = lacp_event_watch_hwaddr_changed,
.port_added = lacp_event_watch_port_added,
@@ -1420,6 +1514,7 @@ static const struct teamd_event_watch_ops lacp_event_watch_ops = {
@@ -1420,21 +1549,38 @@ static const struct teamd_event_watch_ops lacp_event_watch_ops = {
.port_changed = lacp_event_watch_port_changed,
.admin_state_changed = lacp_event_watch_admin_state_changed,
.refresh = lacp_event_watch_refresh,
+ .port_flush_data = lacp_event_watch_port_flush_data,
};

static int lacp_carrier_init(struct teamd_context *ctx, struct lacp *lacp)
@@ -1946,7 +2041,7 @@ static void lacp_fini(struct teamd_context *ctx, void *priv)
{
int err;

- /* initialize carrier control */
- err = team_carrier_set(ctx->th, false);
- if (err && err != -EOPNOTSUPP) {
- teamd_log_err("Failed to set carrier down.");
- return err;
+ if (ctx->warm_start_carrier) {
+ /* Read the current carrier state, don't change it */
+ bool state;
+ err = team_carrier_get(ctx->th, &state);
+ if (err && err != -EOPNOTSUPP) {
+ teamd_log_err("Failed to read carrier.");
+ return err;
+ }
+ lacp->carrier_up = state;
+ if (state) {
+ /* enable timer for warm_start_carrier mode */
+ lacp->warm_start_carrier_timer = time(NULL);
+ } else {
+ /* disable warm_start_carrier mode. The LAG interface is already down. */
+ ctx->warm_start_carrier = false;
+ }
+ } else {
+ err = team_carrier_set(ctx->th, false);
+ if (err && err != -EOPNOTSUPP) {
+ teamd_log_err("Failed to set carrier down.");
+ return err;
+ }
+ lacp->carrier_up = false;
}

- lacp->carrier_up = false;
-
return 0;
}

@@ -1946,7 +2092,7 @@ static void lacp_fini(struct teamd_context *ctx, void *priv)
teamd_state_val_unregister(ctx, &lacp_state_vg, lacp);
teamd_balancer_fini(lacp->tb);
teamd_event_watch_unregister(ctx, &lacp_event_watch_ops, lacp);
Expand Down

0 comments on commit f6f8880

Please sign in to comment.