/
githubmirror
/
libteam
Обзор
Документация
Войти
/
githubmirror
/
libteam
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
teamd/teamd_phys_port_check.c
144 строки
4 KB
Khem Raj
teamd: Include missing headers for strrchr and memcmp
27 сен 2022, 11:45
27 сен 2022, 11:45
42a235b
Код
Авторство
О чём код?
/* * teamd_phys_port_check.c - Physical port checking support for teamd * Copyright (C) 2013-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 <stdio.h> #include <errno.h> #include <string.h> #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> #include "teamd.h" struct pcie_addr { uint16_t domain; uint8_t bus; uint8_t slot; uint8_t function; }; static int teamd_sriov_physfn_addr(struct pcie_addr *addr, const char *ifname) { char link[256]; char *path; char *start; int ret; ret = asprintf(&path, "/sys/class/net/%s/device/physfn", ifname); if (ret == -1) return -ENOMEM; ret = readlink(path, link, sizeof(link) - 1); free(path); if (ret == -1) return -errno; link[ret] = '\0'; start = strrchr(link, '/'); if (!start) return -EINVAL; start++; memset(addr, 0, sizeof(*addr)); ret = sscanf(start, "%04x:%02x:%02x.%x", (unsigned int *) &addr->domain, (unsigned int *) &addr->bus, (unsigned int *) &addr->slot, (unsigned int *) &addr->function); if (ret != 4) return -EINVAL; return 0; } static bool teamd_phys_port_sriovsysfs_cmp(struct teamd_port *tdport1, struct teamd_port *tdport2) { struct pcie_addr physfnaddr1; struct pcie_addr physfnaddr2; int err; err = teamd_sriov_physfn_addr(&physfnaddr1, tdport1->ifname); if (err) return false; err = teamd_sriov_physfn_addr(&physfnaddr2, tdport2->ifname); if (err) return false; if (!memcmp(&physfnaddr1, &physfnaddr2, sizeof(physfnaddr1))) return true; return false; } static bool teamd_phys_port_ifinfo_cmp(struct teamd_port *tdport1, struct teamd_port *tdport2) { const char *id1 = team_get_ifinfo_phys_port_id(tdport1->team_ifinfo); const char *id2 = team_get_ifinfo_phys_port_id(tdport2->team_ifinfo); size_t id1_len = team_get_ifinfo_phys_port_id_len(tdport1->team_ifinfo); size_t id2_len = team_get_ifinfo_phys_port_id_len(tdport2->team_ifinfo); if (!id1_len || !id2_len || id1_len != id2_len) return false; if (!memcmp(id1, id2, id1_len)) return true; return false; } static int teamd_phys_port_check_event_watch_port_added(struct teamd_context *ctx, struct teamd_port *tdport, void *priv) { struct teamd_port *cur_tdport; teamd_for_each_tdport(cur_tdport, ctx) { if (cur_tdport == tdport) continue; /* Once all drivers implement ndo_get_phys_port_id() function, * teamd_phys_port_sriovsysfs_cmp() would not be needed to be * called here. */ if (teamd_phys_port_ifinfo_cmp(tdport, cur_tdport) || teamd_phys_port_sriovsysfs_cmp(tdport, cur_tdport)) teamd_log_warn("%s: device is using the same physical port as device %s. Note that teaming multiple devices which use the same physical port makes no sense.", tdport->ifname, cur_tdport->ifname); } return 0; } static const struct teamd_event_watch_ops teamd_phys_port_check_event_watch_ops = { .port_added = teamd_phys_port_check_event_watch_port_added, }; int teamd_phys_port_check_init(struct teamd_context *ctx) { int err; err = teamd_event_watch_register(ctx, &teamd_phys_port_check_event_watch_ops, NULL); if (err) { teamd_log_err("Failed to register event watch."); return err; } return 0; } void teamd_phys_port_check_fini(struct teamd_context *ctx) { teamd_event_watch_unregister(ctx, &teamd_phys_port_check_event_watch_ops, NULL); }