/
githubmirror
/
libteam
Обзор
Документация
Войти
/
githubmirror
/
libteam
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
teamd/teamd_lw_ethtool.c
222 строки
6 KB
Hangbin Liu
libteam: wapper teamd_log_dbg with teamd_log_dbgx
11 дек 2019, 13:43
11 дек 2019, 13:43
f32310b
Код
Авторство
О чём код?
/* * teamd_lw_ethtool.c - Team port ethtool link watcher * Copyright (C) 2012-2015 Jiri Pirko <jiri@resnulli.us> * Copyright (C) 2014 Erik Hugne <erik.hugne@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, "@.delay_up", cpcookie); if (!err) { if (tmp < 0) { teamd_log_err("\"delay_up\" must not be negative number."); return -EINVAL; } teamd_log_dbg(ctx, "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(ctx, "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), }, };