From: Erik Hugne <erik.hugne(a)ericsson.com>
All ethtool specific code is moved to teamd_lw_ethtool.c,
and the generic link watcher types and functions are moved
to a common header file, teamd_link_watch.h
Signed-off-by: Erik Hugne <erik.hugne(a)ericsson.com>
---
teamd/Makefile.am | 3 +-
teamd/teamd_link_watch.c | 231 ++---------------------------------------------
teamd/teamd_link_watch.h | 33 +++++++
teamd/teamd_lw_ethtool.c | 223 +++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 264 insertions(+), 226 deletions(-)
create mode 100644 teamd/teamd_link_watch.h
create mode 100644 teamd/teamd_lw_ethtool.c
diff --git a/teamd/Makefile.am b/teamd/Makefile.am
index dc7ca07..2a0f5ea 100644
--- a/teamd/Makefile.am
+++ b/teamd/Makefile.am
@@ -13,7 +13,8 @@ teamd_LDADD = $(top_builddir)/libteam/libteam.la $(LIBDAEMON_LIBS)
$(JANSSON_LIB
bin_PROGRAMS=teamd
teamd_SOURCES=teamd.c teamd_common.c teamd_json.c teamd_config.c teamd_state.c \
teamd_workq.c teamd_events.c teamd_per_port.c \
- teamd_option_watch.c teamd_ifinfo_watch.c teamd_link_watch.c \
+ teamd_option_watch.c teamd_ifinfo_watch.c teamd_lw_ethtool.c \
+ teamd_link_watch.c \
teamd_ctl.c teamd_dbus.c teamd_zmq.c teamd_usock.c \
teamd_phys_port_check.c teamd_bpf_chef.c teamd_hash_func.c \
teamd_balancer.c teamd_runner_basic_ones.c \
diff --git a/teamd/teamd_link_watch.c b/teamd/teamd_link_watch.c
index d35ff86..c11b256 100644
--- a/teamd/teamd_link_watch.c
+++ b/teamd/teamd_link_watch.c
@@ -39,23 +39,9 @@
#include "teamd.h"
#include "teamd_config.h"
-#include "teamd_state.h"
+#include "teamd_link_watch.h"
-struct lw_common_port_priv {
- unsigned int id;
- const struct teamd_link_watch *link_watch;
- struct teamd_context *ctx;
- struct teamd_port *tdport;
- bool link_up;
- bool forced_send;
- struct teamd_config_path_cookie *cpcookie;
-};
-
-struct teamd_link_watch {
- const char *name;
- const struct teamd_state_val state_vg;
- struct teamd_port_priv port_priv;
-};
+extern const struct teamd_link_watch teamd_link_watch_ethtool;
static int __set_sockaddr(struct sockaddr *sa, socklen_t sa_len,
sa_family_t family, const char *hostname)
@@ -136,16 +122,10 @@ static char *str_sockaddr_in6(struct sockaddr_in6 *sin6)
sizeof(*sin6), AF_INET6);
}
-static bool teamd_link_watch_link_up_differs(struct lw_common_port_priv *common_ppriv,
- bool new_link_up)
-{
- return new_link_up != common_ppriv->link_up;
-}
-
-static int teamd_link_watch_check_link_up(struct teamd_context *ctx,
- struct teamd_port *tdport,
- struct lw_common_port_priv *common_ppriv,
- bool new_link_up)
+int teamd_link_watch_check_link_up(struct teamd_context *ctx,
+ struct teamd_port *tdport,
+ struct lw_common_port_priv *common_ppriv,
+ bool new_link_up)
{
const char *lw_name = common_ppriv->link_watch->name;
@@ -159,205 +139,6 @@ static int teamd_link_watch_check_link_up(struct teamd_context
*ctx,
/*
- * Ethtool link watch
- */
-
-struct lw_ethtool_port_priv {
- struct lw_common_port_priv common; /* must be first */
- struct timespec delay_up;
- struct timespec delay_down;
-};
-
-static struct lw_ethtool_port_priv *
-lw_ethtool_ppriv_get(struct lw_common_port_priv *common_ppriv)
-{
- return (struct lw_ethtool_port_priv *) common_ppriv;
-}
-
-#define LW_ETHTOOL_DELAY_CB_NAME "lw_ethtool_delay"
-
-static int lw_ethtool_event_watch_port_changed(struct teamd_context *ctx,
- struct teamd_port *tdport,
- void *priv)
-{
- struct lw_common_port_priv *common_ppriv = priv;
- struct lw_ethtool_port_priv *ethtool_ppriv = priv;
- bool link_up;
- struct timespec *delay;
- int err;
-
- if (common_ppriv->tdport != tdport ||
- !team_is_port_changed(tdport->team_port))
- return 0;
-
- /*
- * Link changed for sure, so if there is some delay in progress,
- * cancel it before proceeding.
- */
- teamd_loop_callback_disable(ctx, LW_ETHTOOL_DELAY_CB_NAME, priv);
- link_up = team_is_port_link_up(tdport->team_port);
- if (!teamd_link_watch_link_up_differs(common_ppriv, link_up))
- return 0;
-
- if (link_up) {
- if (timespec_is_zero(ðtool_ppriv->delay_up))
- goto nodelay;
- delay = ðtool_ppriv->delay_up;
- } else {
- if (timespec_is_zero(ðtool_ppriv->delay_down))
- goto nodelay;
- delay = ðtool_ppriv->delay_down;
- }
-
- err = teamd_loop_callback_timer_set(ctx, LW_ETHTOOL_DELAY_CB_NAME,
- priv, NULL, delay);
- if (err) {
- teamd_log_err("Failed to set delay timer.");
- return err;
- }
- teamd_loop_callback_enable(ctx, LW_ETHTOOL_DELAY_CB_NAME, priv);
- return 0;
-
-nodelay:
- return teamd_link_watch_check_link_up(ctx, tdport, common_ppriv,
- link_up);
-}
-
-static int lw_ethtool_callback_delay(struct teamd_context *ctx, int events,
- void *priv)
-{
- struct lw_common_port_priv *common_ppriv = priv;
- struct teamd_port *tdport;
- bool link_up;
-
- tdport = common_ppriv->tdport;
- link_up = team_is_port_link_up(tdport->team_port);
- return teamd_link_watch_check_link_up(ctx, tdport, common_ppriv,
- link_up);
-}
-
-static int lw_ethtool_load_options(struct teamd_context *ctx,
- struct teamd_port *tdport,
- struct lw_ethtool_port_priv *ethtool_ppriv)
-{
- struct teamd_config_path_cookie *cpcookie = ethtool_ppriv->common.cpcookie;
- int err;
- int tmp;
-
- err = teamd_config_int_get(ctx, &tmp, "@.queue_id", cpcookie);
- if (!err) {
- if (tmp < 0) {
- teamd_log_err("\"delay_up\" must not be negative number.");
- return -EINVAL;
- }
- teamd_log_dbg("delay_up \"%d\".", tmp);
- ms_to_timespec(ðtool_ppriv->delay_up, tmp);
- }
- err = teamd_config_int_get(ctx, &tmp, "@.delay_down", cpcookie);
- if (!err) {
- if (tmp < 0) {
- teamd_log_err("\"delay_down\" must not be negative number.");
- return -EINVAL;
- }
- teamd_log_dbg("delay_down \"%d\".", tmp);
- ms_to_timespec(ðtool_ppriv->delay_down, tmp);
- }
- return 0;
-}
-
-static const struct teamd_event_watch_ops lw_ethtool_port_watch_ops = {
- .port_changed = lw_ethtool_event_watch_port_changed,
-};
-
-static int lw_ethtool_port_added(struct teamd_context *ctx,
- struct teamd_port *tdport,
- void *priv, void *creator_priv)
-{
- int err;
-
- err = lw_ethtool_load_options(ctx, tdport, priv);
- if (err) {
- teamd_log_err("Failed to load options.");
- return err;
- }
- err = teamd_loop_callback_timer_add(ctx, LW_ETHTOOL_DELAY_CB_NAME,
- priv, lw_ethtool_callback_delay);
- if (err) {
- teamd_log_err("Failed add delay callback timer");
- return err;
- }
- err = teamd_event_watch_register(ctx, &lw_ethtool_port_watch_ops, priv);
- if (err) {
- teamd_log_err("Failed to register event watch.");
- goto delay_callback_del;
- }
- return 0;
-
-delay_callback_del:
- teamd_loop_callback_del(ctx, LW_ETHTOOL_DELAY_CB_NAME, priv);
- return err;
-}
-
-static void lw_ethtool_port_removed(struct teamd_context *ctx,
- struct teamd_port *tdport,
- void *priv, void *creator_priv)
-{
- teamd_event_watch_unregister(ctx, &lw_ethtool_port_watch_ops, priv);
- teamd_loop_callback_del(ctx, LW_ETHTOOL_DELAY_CB_NAME, priv);
-}
-
-static int lw_ethtool_state_delay_up_get(struct teamd_context *ctx,
- struct team_state_gsc *gsc,
- void *priv)
-{
- struct lw_common_port_priv *common_ppriv = priv;
- struct timespec *ts;
-
- ts = &lw_ethtool_ppriv_get(common_ppriv)->delay_up;
- gsc->data.int_val = timespec_to_ms(ts);
- return 0;
-}
-
-static int lw_ethtool_state_delay_down_get(struct teamd_context *ctx,
- struct team_state_gsc *gsc,
- void *priv)
-{
- struct lw_common_port_priv *common_ppriv = priv;
- struct timespec *ts;
-
- ts = &lw_ethtool_ppriv_get(common_ppriv)->delay_down;
- gsc->data.int_val = timespec_to_ms(ts);
- return 0;
-}
-
-static const struct teamd_state_val lw_ethtool_state_vals[] = {
- {
- .subpath = "delay_up",
- .type = TEAMD_STATE_ITEM_TYPE_INT,
- .getter = lw_ethtool_state_delay_up_get,
- },
- {
- .subpath = "delay_down",
- .type = TEAMD_STATE_ITEM_TYPE_INT,
- .getter = lw_ethtool_state_delay_down_get,
- },
-};
-
-static const struct teamd_link_watch teamd_link_watch_ethtool = {
- .name = "ethtool",
- .state_vg = {
- .vals = lw_ethtool_state_vals,
- .vals_count = ARRAY_SIZE(lw_ethtool_state_vals),
- },
- .port_priv = {
- .init = lw_ethtool_port_added,
- .fini = lw_ethtool_port_removed,
- .priv_size = sizeof(struct lw_ethtool_port_priv),
- },
-};
-
-
-/*
* Generic periodic send/receive link watch "template"
*/
diff --git a/teamd/teamd_link_watch.h b/teamd/teamd_link_watch.h
new file mode 100644
index 0000000..27e2025
--- /dev/null
+++ b/teamd/teamd_link_watch.h
@@ -0,0 +1,33 @@
+#ifndef _TEAMD_LINK_WATCH_H_
+#define _TEAMD_LINK_WATCH_H_
+
+#include "teamd_state.h"
+
+struct teamd_link_watch {
+ const char *name;
+ const struct teamd_state_val state_vg;
+ struct teamd_port_priv port_priv;
+};
+
+struct lw_common_port_priv {
+ unsigned int id;
+ const struct teamd_link_watch *link_watch;
+ struct teamd_context *ctx;
+ struct teamd_port *tdport;
+ bool link_up;
+ bool forced_send;
+ struct teamd_config_path_cookie *cpcookie;
+};
+
+static inline bool teamd_link_watch_link_up_differs(struct lw_common_port_priv
*common_ppriv,
+ bool new_link_up)
+{
+ return new_link_up != common_ppriv->link_up;
+}
+
+int teamd_link_watch_check_link_up(struct teamd_context *ctx,
+ struct teamd_port *tdport,
+ struct lw_common_port_priv *common_ppriv,
+ bool new_link_up);
+
+#endif
diff --git a/teamd/teamd_lw_ethtool.c b/teamd/teamd_lw_ethtool.c
new file mode 100644
index 0000000..b323eb7
--- /dev/null
+++ b/teamd/teamd_lw_ethtool.c
@@ -0,0 +1,223 @@
+/*
+ * teamd_lw_ethtool.c - Team port ethtool link watcher
+ * Copyright (C) 2012-2013 Jiri Pirko <jiri(a)resnulli.us>
+ * Copyright (C) 2014 Erik Hugne <erik.hugne(a)ericsson.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <private/misc.h>
+#include "teamd.h"
+#include "teamd_link_watch.h"
+#include "teamd_config.h"
+
+/*
+ * Ethtool link watch
+ */
+
+struct lw_ethtool_port_priv {
+ struct lw_common_port_priv common; /* must be first */
+ struct timespec delay_up;
+ struct timespec delay_down;
+};
+
+static struct lw_ethtool_port_priv *
+lw_ethtool_ppriv_get(struct lw_common_port_priv *common_ppriv)
+{
+ return (struct lw_ethtool_port_priv *) common_ppriv;
+}
+
+#define LW_ETHTOOL_DELAY_CB_NAME "lw_ethtool_delay"
+
+static int lw_ethtool_event_watch_port_changed(struct teamd_context *ctx,
+ struct teamd_port *tdport,
+ void *priv)
+{
+ struct lw_common_port_priv *common_ppriv = priv;
+ struct lw_ethtool_port_priv *ethtool_ppriv = priv;
+ bool link_up;
+ struct timespec *delay;
+ int err;
+
+ if (common_ppriv->tdport != tdport ||
+ !team_is_port_changed(tdport->team_port))
+ return 0;
+
+ /*
+ * Link changed for sure, so if there is some delay in progress,
+ * cancel it before proceeding.
+ */
+ teamd_loop_callback_disable(ctx, LW_ETHTOOL_DELAY_CB_NAME, priv);
+ link_up = team_is_port_link_up(tdport->team_port);
+ if (!teamd_link_watch_link_up_differs(common_ppriv, link_up))
+ return 0;
+
+ if (link_up) {
+ if (timespec_is_zero(ðtool_ppriv->delay_up))
+ goto nodelay;
+ delay = ðtool_ppriv->delay_up;
+ } else {
+ if (timespec_is_zero(ðtool_ppriv->delay_down))
+ goto nodelay;
+ delay = ðtool_ppriv->delay_down;
+ }
+
+ err = teamd_loop_callback_timer_set(ctx, LW_ETHTOOL_DELAY_CB_NAME,
+ priv, NULL, delay);
+ if (err) {
+ teamd_log_err("Failed to set delay timer.");
+ return err;
+ }
+ teamd_loop_callback_enable(ctx, LW_ETHTOOL_DELAY_CB_NAME, priv);
+ return 0;
+
+nodelay:
+ return teamd_link_watch_check_link_up(ctx, tdport, common_ppriv,
+ link_up);
+}
+
+static int lw_ethtool_callback_delay(struct teamd_context *ctx, int events,
+ void *priv)
+{
+ struct lw_common_port_priv *common_ppriv = priv;
+ struct teamd_port *tdport;
+ bool link_up;
+
+ tdport = common_ppriv->tdport;
+ link_up = team_is_port_link_up(tdport->team_port);
+ return teamd_link_watch_check_link_up(ctx, tdport, common_ppriv,
+ link_up);
+}
+
+static int lw_ethtool_load_options(struct teamd_context *ctx,
+ struct teamd_port *tdport,
+ struct lw_ethtool_port_priv *ethtool_ppriv)
+{
+ struct teamd_config_path_cookie *cpcookie = ethtool_ppriv->common.cpcookie;
+ int err;
+ int tmp;
+
+ err = teamd_config_int_get(ctx, &tmp, "@.queue_id", cpcookie);
+ if (!err) {
+ if (tmp < 0) {
+ teamd_log_err("\"delay_up\" must not be negative number.");
+ return -EINVAL;
+ }
+ teamd_log_dbg("delay_up \"%d\".", tmp);
+ ms_to_timespec(ðtool_ppriv->delay_up, tmp);
+ }
+ err = teamd_config_int_get(ctx, &tmp, "@.delay_down", cpcookie);
+ if (!err) {
+ if (tmp < 0) {
+ teamd_log_err("\"delay_down\" must not be negative number.");
+ return -EINVAL;
+ }
+ teamd_log_dbg("delay_down \"%d\".", tmp);
+ ms_to_timespec(ðtool_ppriv->delay_down, tmp);
+ }
+ return 0;
+}
+
+static const struct teamd_event_watch_ops lw_ethtool_port_watch_ops = {
+ .port_changed = lw_ethtool_event_watch_port_changed,
+};
+
+static int lw_ethtool_port_added(struct teamd_context *ctx,
+ struct teamd_port *tdport,
+ void *priv, void *creator_priv)
+{
+ int err;
+
+ err = lw_ethtool_load_options(ctx, tdport, priv);
+ if (err) {
+ teamd_log_err("Failed to load options.");
+ return err;
+ }
+ err = teamd_loop_callback_timer_add(ctx, LW_ETHTOOL_DELAY_CB_NAME,
+ priv, lw_ethtool_callback_delay);
+ if (err) {
+ teamd_log_err("Failed add delay callback timer");
+ return err;
+ }
+ err = teamd_event_watch_register(ctx, &lw_ethtool_port_watch_ops, priv);
+ if (err) {
+ teamd_log_err("Failed to register event watch.");
+ goto delay_callback_del;
+ }
+ return 0;
+
+delay_callback_del:
+ teamd_loop_callback_del(ctx, LW_ETHTOOL_DELAY_CB_NAME, priv);
+ return err;
+}
+
+static void lw_ethtool_port_removed(struct teamd_context *ctx,
+ struct teamd_port *tdport,
+ void *priv, void *creator_priv)
+{
+ teamd_event_watch_unregister(ctx, &lw_ethtool_port_watch_ops, priv);
+ teamd_loop_callback_del(ctx, LW_ETHTOOL_DELAY_CB_NAME, priv);
+}
+
+static int lw_ethtool_state_delay_up_get(struct teamd_context *ctx,
+ struct team_state_gsc *gsc,
+ void *priv)
+{
+ struct lw_common_port_priv *common_ppriv = priv;
+ struct timespec *ts;
+
+ ts = &lw_ethtool_ppriv_get(common_ppriv)->delay_up;
+ gsc->data.int_val = timespec_to_ms(ts);
+ return 0;
+}
+
+static int lw_ethtool_state_delay_down_get(struct teamd_context *ctx,
+ struct team_state_gsc *gsc,
+ void *priv)
+{
+ struct lw_common_port_priv *common_ppriv = priv;
+ struct timespec *ts;
+
+ ts = &lw_ethtool_ppriv_get(common_ppriv)->delay_down;
+ gsc->data.int_val = timespec_to_ms(ts);
+ return 0;
+}
+
+static const struct teamd_state_val lw_ethtool_state_vals[] = {
+ {
+ .subpath = "delay_up",
+ .type = TEAMD_STATE_ITEM_TYPE_INT,
+ .getter = lw_ethtool_state_delay_up_get,
+ },
+ {
+ .subpath = "delay_down",
+ .type = TEAMD_STATE_ITEM_TYPE_INT,
+ .getter = lw_ethtool_state_delay_down_get,
+ },
+};
+
+const struct teamd_link_watch teamd_link_watch_ethtool = {
+ .name = "ethtool",
+ .state_vg = {
+ .vals = lw_ethtool_state_vals,
+ .vals_count = ARRAY_SIZE(lw_ethtool_state_vals),
+ },
+ .port_priv = {
+ .init = lw_ethtool_port_added,
+ .fini = lw_ethtool_port_removed,
+ .priv_size = sizeof(struct lw_ethtool_port_priv),
+ },
+};
+
--
1.8.3.2