/
githubmirror
/
libteam
Обзор
Документация
Войти
/
githubmirror
/
libteam
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
teamd/teamd_events.c
270 строк
7 KB
Jiri Pirko
teamd: lacp: set port to disabled state during removal
07 дек 2022, 15:47
07 дек 2022, 15:47
fd26b37
Код
Авторство
О чём код?
/* * teamd_events.c - Infrastructure for watching all sorts of events * Copyright (C) 2012-2015 Jiri Pirko <jiri@resnulli.us> * * 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 <stdlib.h> #include <string.h> #include <errno.h> #include <inttypes.h> #include <string.h> #include <private/list.h> #include <private/misc.h> #include <team.h> #include "teamd.h" struct event_watch_item { struct list_item list; const struct teamd_event_watch_ops *ops; void *priv; }; int teamd_event_port_added(struct teamd_context *ctx, struct teamd_port *tdport) { struct event_watch_item *watch; int err; list_for_each_node_entry(watch, &ctx->event_watch_list, list) { if (!watch->ops->port_added) continue; err = watch->ops->port_added(ctx, tdport, watch->priv); if (err) return err; } return 0; } void teamd_event_port_removing(struct teamd_context *ctx, struct teamd_port *tdport) { struct event_watch_item *watch; list_for_each_node_entry(watch, &ctx->event_watch_list, list) { if (!watch->ops->port_removing) continue; watch->ops->port_removing(ctx, tdport, watch->priv); } } void teamd_event_port_removed(struct teamd_context *ctx, struct teamd_port *tdport) { struct event_watch_item *watch; list_for_each_node_entry(watch, &ctx->event_watch_list, list) { if (!watch->ops->port_removed) continue; watch->ops->port_removed(ctx, tdport, watch->priv); } } int teamd_event_port_changed(struct teamd_context *ctx, struct teamd_port *tdport) { struct event_watch_item *watch; int err; list_for_each_node_entry(watch, &ctx->event_watch_list, list) { if (!watch->ops->port_changed) continue; err = watch->ops->port_changed(ctx, tdport, watch->priv); if (err) return err; } return 0; } int teamd_event_port_link_changed(struct teamd_context *ctx, struct teamd_port *tdport) { struct event_watch_item *watch; int err; list_for_each_node_entry(watch, &ctx->event_watch_list, list) { if (!watch->ops->port_link_changed) continue; err = watch->ops->port_link_changed(ctx, tdport, watch->priv); if (err) return err; } return 0; } int teamd_event_option_changed(struct teamd_context *ctx, struct team_option *option) { struct event_watch_item *watch; int err; list_for_each_node_entry(watch, &ctx->event_watch_list, list) { if (!watch->ops->option_changed) continue; if (watch->ops->option_changed_match_name && strcmp(team_get_option_name(option), watch->ops->option_changed_match_name)) continue; err = watch->ops->option_changed(ctx, option, watch->priv); if (err) return err; } return 0; } int teamd_event_ifinfo_hwaddr_changed(struct teamd_context *ctx, struct team_ifinfo *ifinfo) { struct event_watch_item *watch; uint32_t ifindex = team_get_ifinfo_ifindex(ifinfo); struct teamd_port *tdport = teamd_get_port(ctx, ifindex); int err; list_for_each_node_entry(watch, &ctx->event_watch_list, list) { if (watch->ops->hwaddr_changed && ctx->ifindex == ifindex) { /* ctx->hwaddr is previously set to * team_get_ifinfo_hwaddr(ctx->ifinfo) in teamd_init. * We set hwaddr_len there as well, but when it changes, * we need to set it again now. */ ctx->hwaddr_len = team_get_ifinfo_hwaddr_len(ifinfo); err = watch->ops->hwaddr_changed(ctx, watch->priv); if (err) return err; } else if (watch->ops->port_hwaddr_changed && tdport) { err = watch->ops->port_hwaddr_changed(ctx, tdport, watch->priv); if (err) return err; } } return 0; } int teamd_event_ifinfo_ifname_changed(struct teamd_context *ctx, struct team_ifinfo *ifinfo) { struct event_watch_item *watch; uint32_t ifindex = team_get_ifinfo_ifindex(ifinfo); struct teamd_port *tdport = teamd_get_port(ctx, ifindex); int err; list_for_each_node_entry(watch, &ctx->event_watch_list, list) { if (watch->ops->ifname_changed && ctx->ifindex == ifindex) { err = watch->ops->ifname_changed(ctx, watch->priv); if (err) return err; } else if (watch->ops->port_ifname_changed && tdport) { err = watch->ops->port_ifname_changed(ctx, tdport, watch->priv); if (err) return err; } } return 0; } int teamd_event_ifinfo_master_ifindex_changed(struct teamd_context *ctx, struct team_ifinfo *ifinfo) { struct event_watch_item *watch; uint32_t ifindex = team_get_ifinfo_ifindex(ifinfo); struct teamd_port *tdport = teamd_get_port(ctx, ifindex); int err; list_for_each_node_entry(watch, &ctx->event_watch_list, list) { if (watch->ops->port_master_ifindex_changed && tdport) { err = watch->ops->port_master_ifindex_changed(ctx, tdport, watch->priv); if (err) return err; } } return 0; } int teamd_event_ifinfo_admin_state_changed(struct teamd_context *ctx, struct team_ifinfo *ifinfo) { struct event_watch_item *watch; uint32_t ifindex = team_get_ifinfo_ifindex(ifinfo); int err; list_for_each_node_entry(watch, &ctx->event_watch_list, list) { if (watch->ops->admin_state_changed && ctx->ifindex == ifindex) { err = watch->ops->admin_state_changed(ctx, watch->priv); if (err) return err; } } return 0; } int teamd_events_init(struct teamd_context *ctx) { list_init(&ctx->event_watch_list); return 0; } void teamd_events_fini(struct teamd_context *ctx) { } static struct event_watch_item * __find_event_watch(struct teamd_context *ctx, const struct teamd_event_watch_ops *ops, void *priv) { struct event_watch_item *watch; list_for_each_node_entry(watch, &ctx->event_watch_list, list) { if (watch->ops == ops && watch->priv == priv) return watch; } return NULL; } int teamd_event_watch_register(struct teamd_context *ctx, const struct teamd_event_watch_ops *ops, void *priv) { struct event_watch_item *watch; if (__find_event_watch(ctx, ops, priv)) return -EEXIST; watch = malloc(sizeof(*watch)); if (!watch) return -ENOMEM; watch->ops = ops; watch->priv = priv; list_add_tail(&ctx->event_watch_list, &watch->list); return 0; } void teamd_event_watch_unregister(struct teamd_context *ctx, const struct teamd_event_watch_ops *ops, void *priv) { struct event_watch_item *watch; watch = __find_event_watch(ctx, ops, priv); if (!watch) return; list_del(&watch->list); free(watch); }