mirror of
https://github.com/kernelkit/infix.git
synced 2026-07-22 09:13:01 +02:00
net: drop unused 'net' package, replaced by dagger
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
This commit is contained in:
@@ -124,7 +124,6 @@ BR2_PACKAGE_FINIT_PLUGIN_TTY=y
|
||||
BR2_PACKAGE_FINIT_PLUGIN_URANDOM=y
|
||||
BR2_PACKAGE_KLISH_PLUGIN_INFIX=y
|
||||
BR2_PACKAGE_LOWDOWN=y
|
||||
BR2_PACKAGE_NET=y
|
||||
BR2_PACKAGE_TETRIS=y
|
||||
BR2_PACKAGE_QUERIERD=y
|
||||
DISK_IMAGE_BOOT_BIN=y
|
||||
|
||||
@@ -128,7 +128,6 @@ BR2_PACKAGE_FINIT_PLUGIN_TTY=y
|
||||
BR2_PACKAGE_FINIT_PLUGIN_URANDOM=y
|
||||
BR2_PACKAGE_KLISH_PLUGIN_INFIX=y
|
||||
BR2_PACKAGE_LOWDOWN=y
|
||||
BR2_PACKAGE_NET=y
|
||||
BR2_PACKAGE_TETRIS=y
|
||||
BR2_PACKAGE_QUERIERD=y
|
||||
GNS3_APPLIANCE_RAM=512
|
||||
|
||||
@@ -12,7 +12,6 @@ source "$BR2_EXTERNAL_INFIX_PATH/package/klish-plugin-sysrepo/Config.in"
|
||||
source "$BR2_EXTERNAL_INFIX_PATH/package/libsrx/Config.in"
|
||||
source "$BR2_EXTERNAL_INFIX_PATH/package/lowdown/Config.in"
|
||||
source "$BR2_EXTERNAL_INFIX_PATH/package/mdnsd/Config.in"
|
||||
source "$BR2_EXTERNAL_INFIX_PATH/package/net/Config.in"
|
||||
source "$BR2_EXTERNAL_INFIX_PATH/package/podman/Config.in"
|
||||
source "$BR2_EXTERNAL_INFIX_PATH/package/skeleton-init-finit/Config.in"
|
||||
source "$BR2_EXTERNAL_INFIX_PATH/package/tetris/Config.in"
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
config BR2_PACKAGE_NET
|
||||
bool "net"
|
||||
select BR2_PACKAGE_IPROUTE2
|
||||
select BR2_PACKAGE_LIBITE
|
||||
help
|
||||
Handles transitions between network states.
|
||||
@@ -1,21 +0,0 @@
|
||||
################################################################################
|
||||
#
|
||||
# net
|
||||
#
|
||||
################################################################################
|
||||
|
||||
NET_VERSION = 1.0
|
||||
NET_LICENSE = MIT
|
||||
NET_LICENSE_FILES = LICENSE
|
||||
NET_SITE_METHOD = local
|
||||
NET_SITE = $(BR2_EXTERNAL_INFIX_PATH)/src/net
|
||||
NET_REDISTRIBUTE = NO
|
||||
NET_DEPENDENCIES = libite
|
||||
NET_AUTORECONF = YES
|
||||
|
||||
define NET_INSTALL_EXTRA
|
||||
chmod +x $(TARGET_DIR)/usr/share/net/*.sh
|
||||
endef
|
||||
NET_POST_INSTALL_TARGET_HOOKS += NET_INSTALL_EXTRA
|
||||
|
||||
$(eval $(autotools-package))
|
||||
@@ -1,13 +0,0 @@
|
||||
*.o
|
||||
*.log
|
||||
*.trs
|
||||
net
|
||||
Makefile
|
||||
Makefile.in
|
||||
aclocal.m4
|
||||
autom4te.cache/
|
||||
aux/
|
||||
config.*
|
||||
configure
|
||||
src/.deps/
|
||||
stamp-h1
|
||||
@@ -1,19 +0,0 @@
|
||||
Copyright (c) 2023 The KernelKit Authors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
@@ -1,4 +0,0 @@
|
||||
SUBDIRS = src test
|
||||
DISTCLEANFILES = *~ *.d
|
||||
ACLOCAL_AMFLAGS = -I m4
|
||||
|
||||
@@ -1,167 +0,0 @@
|
||||
net - an iproute2 wrapper
|
||||
=========================
|
||||
|
||||
The net tool is a wrapper around the iproute2 and ethtool programs to
|
||||
set up networking on a Linux system. It also handles transitions from
|
||||
a previously configured state to the next while attempting to keep the
|
||||
amount of changes needed to a minimum.
|
||||
|
||||
|
||||
Concept Overview
|
||||
----------------
|
||||
|
||||
net applies a configuration from `/run/net/next`, where `next` is a file
|
||||
that holds the number of the next net generation. It is up to the user,
|
||||
i.e., sysrepo, to create the below tree structure with commands to run.
|
||||
|
||||
The setup we start with and later move `eth4` from `lag0` to `br0`.
|
||||
|
||||
vlan1
|
||||
______/____
|
||||
[____br0____]
|
||||
/ / \ \
|
||||
eth1 eth2 eth3 lag0
|
||||
/ \
|
||||
eth4 eth5
|
||||
|
||||
Consider the case when `next` contains `0`, net reads all interfaces, in
|
||||
dependency order, from `/run/net/0/` running all `init.cmd` scripts.
|
||||
When done, it writes `0` to the file `/run/net/gen` and then removes the
|
||||
`next` file to confirm the generation has been activated.
|
||||
|
||||
**Note:** it is currently up to the user to remove any old generation.
|
||||
|
||||
/run/net/0/
|
||||
|-- br0/
|
||||
| |-- deps/
|
||||
| | |-- eth1 -> ../../eth1
|
||||
| | |-- eth2 -> ../../eth2
|
||||
| | |-- eth3 -> ../../eth3
|
||||
| | `-- lag0 -> ../../lag0
|
||||
| |-- admin-state
|
||||
| `-- init.ip
|
||||
|-- eth0/
|
||||
| |-- deps/
|
||||
| |-- admin-state
|
||||
| `-- init.ip
|
||||
|-- ethX/
|
||||
| |-- ...
|
||||
: :
|
||||
|-- lag0/
|
||||
| |-- deps/
|
||||
| | |-- eth4 -> ../../eth4
|
||||
| | `-- eth5 -> ../../eth5
|
||||
| |-- admin-state
|
||||
| `-- init.ip
|
||||
`-- vlan1/
|
||||
|-- deps/
|
||||
| `-- br0 -> ../../br0
|
||||
|-- admin-state
|
||||
`-- init.ip
|
||||
|
||||
The `deps/` sub-directory for each of the interfaces contains symlinks
|
||||
to any interfaces this interface may depend on. I.e., those interfaces
|
||||
are evaluated first.
|
||||
|
||||
Essentially, all leaves must be set up before their parents. Moving a
|
||||
leaf from one parent to another, e.g., from lag0 to br0, is tricky, it
|
||||
involves traversing the previous dependency order when removing leaves,
|
||||
and traversing the next dependency order when adding, see next section
|
||||
for an example.
|
||||
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
net is built to complement sysrepo. The idea is to listen to any added,
|
||||
deleted, modified states in sysrepo changes to a candidate configuration
|
||||
and generate the `next` generation. However, as mentioned previously,
|
||||
when moving leaves between parents we must do so in the dependency order
|
||||
of the current generation.
|
||||
|
||||
So, the user (sysrepo) needs to add `exit.cmd` scripts in the current
|
||||
tree for every leaf that leaves a parent, and `init.cmd` scripts for
|
||||
leaves that are new or added to parents in the next generation.
|
||||
|
||||
In our example, interface `eth4` is moved from `lag0` to `br0`, so we
|
||||
need to run `eth4/exit.ip` in the current generation first to remove
|
||||
`eth4` from `lag0` before its `init.ip` script in the next generation
|
||||
sets `eth4` as a bridge member instead.
|
||||
|
||||
We traverse the current generation and execute all `exit.cmd` scripts:
|
||||
|
||||
/run/net/<GEN>/
|
||||
|-- br0/
|
||||
| |-- deps/
|
||||
| | |-- eth1 -> ../../eth1
|
||||
| | |-- eth2 -> ../../eth2
|
||||
| | |-- eth3 -> ../../eth3
|
||||
| | `-- lag0 -> ../../lag0
|
||||
| |-- admin-state
|
||||
| `-- init.ip
|
||||
|-- eth0/
|
||||
| |-- deps/
|
||||
| |-- admin-state
|
||||
| `-- init.ip
|
||||
|-- eth4/
|
||||
| |-- deps/
|
||||
| |-- admin-state
|
||||
| |-- exit.ip
|
||||
| `-- init.ip
|
||||
|-- lag0/
|
||||
| |-- deps/
|
||||
| | |-- eth4 -> ../../eth4
|
||||
| | `-- eth5 -> ../../eth5
|
||||
| |-- admin-state
|
||||
| `-- init.ip
|
||||
`-- vlan1/
|
||||
|-- deps/
|
||||
| `-- br0 -> ../../br0
|
||||
|-- admin-state
|
||||
`-- init.ip
|
||||
|
||||
Now we can run all the `init.cmd` scripts in the next generation:
|
||||
|
||||
/run/net/<GEN+1>/
|
||||
|-- br0/
|
||||
| |-- deps/
|
||||
| | |-- eth1 -> ../../eth1
|
||||
| | |-- eth2 -> ../../eth2
|
||||
| | |-- eth3 -> ../../eth3
|
||||
| | |-- eth4 -> ../../eth4
|
||||
| | `-- lag0 -> ../../lag0
|
||||
| |-- admin-state
|
||||
| `-- init.ip
|
||||
|-- eth0/
|
||||
| |-- deps/
|
||||
| |-- admin-state
|
||||
| `-- init.ip
|
||||
|-- eth4/
|
||||
| |-- deps/
|
||||
| |-- admin-state
|
||||
| `-- init.ip
|
||||
|-- lag0/
|
||||
| |-- deps/
|
||||
| | `-- eth5 -> ../../eth5
|
||||
| |-- admin-state
|
||||
| `-- init.ip
|
||||
`-- vlan1/
|
||||
|-- deps/
|
||||
| `-- br0 -> ../../br0
|
||||
|-- admin-state
|
||||
`-- init.ip
|
||||
|
||||
When there are no changes compared to the previous generation, the base
|
||||
structure with deps need to remain intact, but there's no need for any
|
||||
`init.cmd` scripts. However, for the purpose of supporting the commands
|
||||
`net down` and `net up`, the user must have an `admin-state` file per
|
||||
interface which must contain one of:
|
||||
|
||||
- disabled
|
||||
- up
|
||||
- down
|
||||
|
||||
This describes the state which the user's last `init.ip` or `exit.ip`
|
||||
command, or the `net [up | down]` action, left the interface in. When
|
||||
the `disabled` keyword is used it means the net tool is not allowed to
|
||||
apply any `up` or `down` action on the interface.
|
||||
@@ -1,3 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
autoreconf -W portability -vifm
|
||||
@@ -1,40 +0,0 @@
|
||||
AC_PREREQ(2.61)
|
||||
AC_INIT([net], [1.0], [https://github.com/kernelkit/infix/issues])
|
||||
AC_CONFIG_AUX_DIR(aux)
|
||||
AM_INIT_AUTOMAKE([1.11 foreign])
|
||||
AM_SILENT_RULES([yes])
|
||||
|
||||
AC_CONFIG_SRCDIR([src/main.c])
|
||||
AC_CONFIG_HEADERS([config.h])
|
||||
AC_CONFIG_FILES([Makefile src/Makefile test/Makefile])
|
||||
AC_CONFIG_MACRO_DIR([m4])
|
||||
|
||||
AC_PROG_CC
|
||||
AC_PROG_INSTALL
|
||||
|
||||
# Check for pkg-config first, warn if it's not installed
|
||||
PKG_PROG_PKG_CONFIG
|
||||
PKG_CHECK_MODULES([libite], [libite >= 2.5.0])
|
||||
|
||||
AC_OUTPUT
|
||||
|
||||
SYSCONFDIR=`eval echo $sysconfdir`
|
||||
RUNSTATEDIR=`eval echo $runstatedir`
|
||||
RUNSTATEDIR=`eval echo $RUNSTATEDIR`
|
||||
cat <<EOF
|
||||
|
||||
------------------ Summary ------------------
|
||||
$PACKAGE_NAME version $PACKAGE_VERSION
|
||||
Prefix.........: $prefix
|
||||
Sysconfdir.....: $SYSCONFDIR
|
||||
Runstatedir....: $RUNSTATEDIR
|
||||
C Compiler.....: $CC $CFLAGS $CPPFLAGS $LDFLAGS $LIBS
|
||||
|
||||
------------- Compiler version --------------
|
||||
$($CC --version || true)
|
||||
---------------------------------------------
|
||||
|
||||
Check the above options and compile with:
|
||||
${MAKE-make}
|
||||
|
||||
EOF
|
||||
@@ -1,5 +0,0 @@
|
||||
sbin_PROGRAMS = net
|
||||
|
||||
net_SOURCES = main.c
|
||||
net_CFLAGS = $(libite_CFLAGS) -Wall -Wextra -Werror -Wno-unused-parameter
|
||||
net_LDADD = $(libite_LIBS)
|
||||
@@ -1,616 +0,0 @@
|
||||
#include <err.h>
|
||||
#include <libgen.h>
|
||||
#include <search.h>
|
||||
#include <stdlib.h>
|
||||
#include <sysexits.h>
|
||||
#include <net/if.h>
|
||||
#include <libite/lite.h>
|
||||
#include <libite/queue.h>
|
||||
|
||||
#define _PATH_NET "/run/net"
|
||||
#define dbg(fmt, args...) if (debug) warnx(fmt, ##args)
|
||||
#define log(fmt, args...) if (verbose) warnx(fmt, ##args)
|
||||
|
||||
typedef enum {
|
||||
INVAL = -1,
|
||||
DO = 0,
|
||||
UP = 1,
|
||||
DOWN = 2,
|
||||
} cmd_t;
|
||||
|
||||
struct iface {
|
||||
TAILQ_ENTRY(iface) link;
|
||||
char ifname[IFNAMSIZ];
|
||||
};
|
||||
|
||||
static TAILQ_HEAD(iflist, iface) iface_list = TAILQ_HEAD_INITIALIZER(iface_list);
|
||||
|
||||
static int debug;
|
||||
static int verbose;
|
||||
static int dep;
|
||||
|
||||
static FILE *ip, *bridge;
|
||||
static char *prognm;
|
||||
|
||||
static void addif(char *ifname)
|
||||
{
|
||||
struct iface *entry;
|
||||
|
||||
entry = malloc(sizeof(*entry));
|
||||
if (!entry)
|
||||
err(1, "malloc");
|
||||
|
||||
strlcpy(entry->ifname, ifname, sizeof(entry->ifname));
|
||||
TAILQ_INSERT_TAIL(&iface_list, entry, link);
|
||||
}
|
||||
|
||||
static int findif(char *ifname)
|
||||
{
|
||||
struct iface *iface;
|
||||
|
||||
TAILQ_FOREACH(iface, &iface_list, link) {
|
||||
if (strcmp(iface->ifname, ifname))
|
||||
continue;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void freeifs(void)
|
||||
{
|
||||
struct iface *iface, *tmp;
|
||||
|
||||
TAILQ_FOREACH_SAFE(iface, &iface_list, link, tmp) {
|
||||
TAILQ_REMOVE(&iface_list, iface, link);
|
||||
free(iface);
|
||||
}
|
||||
}
|
||||
|
||||
static void savedep(char *ipath)
|
||||
{
|
||||
char line[20];
|
||||
char *ifname;
|
||||
char *path;
|
||||
FILE *fp;
|
||||
|
||||
path = strdupa(ipath);
|
||||
if (!path)
|
||||
return;
|
||||
|
||||
ifname = basename(path);
|
||||
path = dirname(path);
|
||||
|
||||
fp = fopenf("a+", "%s/deps", path);
|
||||
if (!fp)
|
||||
return;
|
||||
|
||||
(void)fseek(fp, 0L, SEEK_SET);
|
||||
while (fgets(line, sizeof(line), fp)) {
|
||||
if (!strcmp(chomp(line), ifname))
|
||||
goto done;
|
||||
}
|
||||
|
||||
dep++;
|
||||
fprintf(fp, "%s\n", ifname);
|
||||
done:
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
static int save_rdeps(const char *path, char *gen)
|
||||
{
|
||||
return systemf("sed '1!G;h;$!d' < %s/%s/deps >%s/%s/rdeps", path, gen, path, gen);
|
||||
}
|
||||
|
||||
static FILE *pipep(const char *action)
|
||||
{
|
||||
char *ptr;
|
||||
|
||||
ptr = strrchr(action, '.');
|
||||
if (!ptr) {
|
||||
warnx("missing action type, assuming shell script: '%s'", action);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!strcmp(ptr, ".ip"))
|
||||
return ip;
|
||||
if (!strcmp(ptr, ".bridge"))
|
||||
return bridge;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int pipeit(FILE *pp, const char *action)
|
||||
{
|
||||
char line[256];
|
||||
FILE *fp;
|
||||
|
||||
fp = fopen(action, "r");
|
||||
if (!fp)
|
||||
return 0; /* nop */
|
||||
|
||||
while (fgets(line, sizeof(line), fp)) {
|
||||
chomp(line);
|
||||
dbg(">>> %s", line);
|
||||
fprintf(pp, "%s\n", line);
|
||||
}
|
||||
|
||||
return fclose(fp);
|
||||
}
|
||||
|
||||
static int run(const char *action)
|
||||
{
|
||||
FILE *pp = pipep(action);
|
||||
int rc;
|
||||
|
||||
if (pp) {
|
||||
log("running pipe action %s:", action);
|
||||
return pipeit(pp, action);
|
||||
}
|
||||
|
||||
/* other actions are plain shell scripts (.sh) */
|
||||
log("running shell action %s:", action);
|
||||
|
||||
rc = systemf("%s", action);
|
||||
if (rc)
|
||||
warn("failed %s, rc %d", action, rc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dir_filter(const char *file)
|
||||
{
|
||||
char *files[] = {
|
||||
"deps",
|
||||
"rdeps",
|
||||
"admin-state",
|
||||
};
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < NELEMS(files); i++) {
|
||||
if (!strcmp(file, files[i]))
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int deps(char *ipath, char *ifname, const char *action)
|
||||
{
|
||||
char path[strlen(ipath) + 42];
|
||||
int num, rc = -1;
|
||||
char **files;
|
||||
char *cmd;
|
||||
|
||||
snprintf(path, sizeof(path), "%s/deps", ipath);
|
||||
num = dir(path, NULL, dir_filter, &files, 0);
|
||||
for (int i = 0; i < num; i++) {
|
||||
char dpath[sizeof(path) + strlen(files[i])];
|
||||
char *ifnm = files[i];
|
||||
char *rp;
|
||||
|
||||
snprintf(dpath, sizeof(dpath), "%s/%s", path, ifnm);
|
||||
rp = realpath(dpath, NULL);
|
||||
if (!rp)
|
||||
continue;
|
||||
|
||||
deps(rp, ifnm, action);
|
||||
free(ifnm);
|
||||
free(rp);
|
||||
}
|
||||
|
||||
savedep(ipath);
|
||||
if (findif(ifname))
|
||||
return 0;
|
||||
|
||||
snprintf(path, sizeof(path), "%s/%s", ipath, action);
|
||||
cmd = realpath(path, NULL);
|
||||
if (!cmd || access(cmd, F_OK)) {
|
||||
if (errno == ENOENT || errno == ENOTDIR)
|
||||
rc = 0; /* no action for this interface */
|
||||
goto done;
|
||||
}
|
||||
|
||||
rc = run(cmd);
|
||||
done:
|
||||
free(cmd);
|
||||
addif(ifname);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int iter(char *path, size_t len, const char *action)
|
||||
{
|
||||
char **files;
|
||||
int rc = 0;
|
||||
FILE *pp;
|
||||
int num;
|
||||
|
||||
num = dir(path, NULL, dir_filter, &files, 0);
|
||||
|
||||
for (int i = 0; i < num; i++) {
|
||||
char *ifname = files[i];
|
||||
char ipath[len];
|
||||
|
||||
snprintf(ipath, sizeof(ipath), "%s/%s", path, ifname);
|
||||
dbg("Calling deps(%s, %s, %s)", ipath, ifname, action);
|
||||
rc += deps(ipath, ifname, action);
|
||||
dbg("rc => %d", rc);
|
||||
free(ifname);
|
||||
}
|
||||
|
||||
freeifs();
|
||||
|
||||
pp = pipep(action);
|
||||
if (pp) {
|
||||
log("closing pipe for %s", action);
|
||||
pclose(pp);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int rdeps(char *path, size_t len, const char *action)
|
||||
{
|
||||
char cmd[len + 20 + strlen(action)];
|
||||
char ifname[20];
|
||||
int rc = 0;
|
||||
FILE *fp;
|
||||
|
||||
fp = fopenf("r", "%s/rdeps", path);
|
||||
if (!fp)
|
||||
return 0; /* no deps in prev. generation */
|
||||
|
||||
while (fgets(ifname, sizeof(ifname), fp)) {
|
||||
snprintf(cmd, sizeof(cmd), "%s/%s/%s", path, chomp(ifname), action);
|
||||
if (access(cmd, F_OK)) {
|
||||
// dbg("skipping %s, errno %d: %s", cmd, errno, strerror(errno));
|
||||
continue;
|
||||
}
|
||||
rc += run(cmd);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int deactivate(const char *net, char *gen)
|
||||
{
|
||||
char path[strlen(net) + strlen(gen) + 5 + IFNAMSIZ];
|
||||
char *action[] = {
|
||||
"exit.bridge",
|
||||
"exit.ip",
|
||||
"exit-ethtool.sh",
|
||||
};
|
||||
int rc = 0;
|
||||
|
||||
snprintf(path, sizeof(path), "%s/%s", net, gen);
|
||||
for (size_t i = 0; i < NELEMS(action); i++)
|
||||
rc += rdeps(path, sizeof(path), action[i]);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int activate(const char *net, char *gen)
|
||||
{
|
||||
char path[strlen(net) + strlen(gen) + 5 + IFNAMSIZ];
|
||||
char *action[] = {
|
||||
"init-ethtool.sh",
|
||||
"init.ip",
|
||||
"init.bridge",
|
||||
};
|
||||
int rc = 0;
|
||||
|
||||
snprintf(path, sizeof(path), "%s/%s", net, gen);
|
||||
for (size_t i = 0; i < NELEMS(action); i++)
|
||||
rc += iter(path, sizeof(path), action[i]);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int load_gen(const char *net, char *gen, char *buf, size_t len)
|
||||
{
|
||||
FILE *fp;
|
||||
|
||||
fp = fopenf("r", "%s/%s", net, gen);
|
||||
if (!fp)
|
||||
return EX_OSFILE;
|
||||
if (!fgets(buf, len, fp))
|
||||
return EX_IOERR;
|
||||
fclose(fp);
|
||||
chomp(buf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int save_gen(const char *net, char *gen, char *buf)
|
||||
{
|
||||
FILE *fp;
|
||||
|
||||
fp = fopenf("w", "%s/%s", net, gen);
|
||||
if (!fp)
|
||||
return -1;
|
||||
fprintf(fp, "%s\n", buf);
|
||||
fclose(fp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void pipe_init(void)
|
||||
{
|
||||
ip = popen("ip -batch -", "w");
|
||||
if (!ip)
|
||||
err(1, "failed starting ip command pipe");
|
||||
|
||||
bridge = popen("bridge -batch -", "w");
|
||||
if (!bridge)
|
||||
err(1, "failed starting bridge command pipe");
|
||||
}
|
||||
|
||||
static const char *getnet(void)
|
||||
{
|
||||
const char *net = _PATH_NET;
|
||||
|
||||
if (getenv("NET_DIR"))
|
||||
net = getenv("NET_DIR");
|
||||
dbg("net directory %s", net);
|
||||
if (access(net, X_OK)) {
|
||||
if (makedir(net, 0755))
|
||||
err(1, "makedir");
|
||||
}
|
||||
|
||||
return net;
|
||||
}
|
||||
|
||||
static char *getpath(void)
|
||||
{
|
||||
const char *net = getnet();
|
||||
char path[strlen(net) + 42];
|
||||
char buf[40];
|
||||
FILE *fp;
|
||||
|
||||
snprintf(path, sizeof(path), "%s/gen", net);
|
||||
fp = fopen(path, "r");
|
||||
if (!fp)
|
||||
err(1, "cannot find %s", path);
|
||||
if (!fgets(buf, sizeof(buf), fp))
|
||||
err(1, "failed reading %s", path);
|
||||
fclose(fp);
|
||||
|
||||
snprintf(path, sizeof(path), "%s/%d", net, atoi(buf));
|
||||
return strdup(path);
|
||||
}
|
||||
|
||||
/* build list from current generation */
|
||||
static void getifs(void)
|
||||
{
|
||||
char *path = getpath();
|
||||
char **files;
|
||||
int num;
|
||||
|
||||
dbg("fetching available interfaces from %s", path);
|
||||
num = dir(path, NULL, dir_filter, &files, 0);
|
||||
for (int i = 0; i < num; i++) {
|
||||
dbg("adding %s ...", files[i]);
|
||||
addif(files[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static char *ifadmin(const char *ifname, char *buf, size_t len)
|
||||
{
|
||||
char *path = getpath();
|
||||
|
||||
if (!path)
|
||||
return NULL;
|
||||
|
||||
snprintf(buf, len, "%s/%s/admin-state", path, ifname);
|
||||
return buf;
|
||||
}
|
||||
|
||||
/* is the interface eligible for being taken up/down? */
|
||||
static int allowed(const char *ifname)
|
||||
{
|
||||
char buf[128];
|
||||
int rc = 1;
|
||||
FILE *fp;
|
||||
|
||||
if (!ifadmin(ifname, buf, sizeof(buf)))
|
||||
goto fail;
|
||||
|
||||
fp = fopen(buf, "r");
|
||||
if (fp) {
|
||||
if (fgets(buf, sizeof(buf), fp)) {
|
||||
chomp(buf);
|
||||
if (!strcmp(buf, "disabled"))
|
||||
rc = 0;
|
||||
}
|
||||
fclose(fp);
|
||||
}
|
||||
fail:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int ifupdown(int updown)
|
||||
{
|
||||
const char *action = updown ? "up" : "down";
|
||||
struct iface *iface;
|
||||
int rc = 0;
|
||||
|
||||
dbg("preparing for if%s ...", action);
|
||||
if (TAILQ_EMPTY(&iface_list))
|
||||
getifs();
|
||||
|
||||
TAILQ_FOREACH(iface, &iface_list, link) {
|
||||
int result;
|
||||
|
||||
if (!allowed(iface->ifname)) {
|
||||
// dbg("skipping if%s %s", action, iface->ifname);
|
||||
continue;
|
||||
}
|
||||
|
||||
dbg("if%s %s", action, iface->ifname);
|
||||
result = systemf("ip link set %s %s", iface->ifname, action);
|
||||
if (!result) {
|
||||
char buf[128];
|
||||
FILE *fp;
|
||||
|
||||
if (!ifadmin(iface->ifname, buf, sizeof(buf)))
|
||||
continue;
|
||||
|
||||
dbg("updating %s '%s'", buf, action);
|
||||
fp = fopen(buf, "w");
|
||||
if (fp) {
|
||||
fprintf(fp, "%s\n", action);
|
||||
fclose(fp);
|
||||
}
|
||||
}
|
||||
|
||||
rc += result;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int activate_next(void)
|
||||
{
|
||||
const char *net = getnet();
|
||||
char curr[512], next[512];
|
||||
int rc;
|
||||
|
||||
pipe_init();
|
||||
|
||||
if ((rc = load_gen(net, "next", next, sizeof(next)))) {
|
||||
if (rc == EX_IOERR)
|
||||
warnx("missing next generation");
|
||||
exit(0); /* nothing to do */
|
||||
}
|
||||
|
||||
if ((rc = load_gen(net, "gen", curr, sizeof(curr)))) {
|
||||
if (rc == EX_IOERR)
|
||||
errx(rc, "missing current generation");
|
||||
/* no current generation */
|
||||
} else {
|
||||
rc = deactivate(net, curr);
|
||||
if (rc)
|
||||
err(1, "failed deactivating current generation");
|
||||
}
|
||||
|
||||
rc = activate(net, next);
|
||||
if (rc)
|
||||
err(1, "failed activating next generation");
|
||||
|
||||
if (dep) {
|
||||
if (save_rdeps(net, next))
|
||||
err(1, "failed saving interface deps in %s", next);
|
||||
}
|
||||
|
||||
if (save_gen(net, "gen", next))
|
||||
err(1, "next generation applied, failed current");
|
||||
|
||||
if (fremove("%s/next", net))
|
||||
err(1, "failed removing %s/next", net);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int act(cmd_t cmd)
|
||||
{
|
||||
dbg("cmd %d", cmd);
|
||||
switch (cmd) {
|
||||
case DO:
|
||||
return activate_next();
|
||||
case UP:
|
||||
return ifupdown(1);
|
||||
case DOWN:
|
||||
return ifupdown(0);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
freeifs();
|
||||
|
||||
return EX_USAGE;
|
||||
}
|
||||
|
||||
cmd_t transform(char *arg0)
|
||||
{
|
||||
prognm = strrchr(arg0, '/');
|
||||
if (prognm)
|
||||
prognm++;
|
||||
else
|
||||
prognm = arg0;
|
||||
|
||||
if (!strcmp(prognm, "ifup"))
|
||||
return UP;
|
||||
if (!strcmp(prognm, "ifdown"))
|
||||
return DOWN;
|
||||
|
||||
return INVAL;
|
||||
}
|
||||
|
||||
static int usage(int code)
|
||||
{
|
||||
printf("Usage: %s [-adhv] [do | (up | down [ifname ...])]\n"
|
||||
"\n"
|
||||
"Options:\n"
|
||||
" -a Act on all interfaces, ignored, for compat only.\n"
|
||||
" -d Debug\n"
|
||||
" -h This help text\n"
|
||||
" -v Verbose, show actions taken\n"
|
||||
"\n"
|
||||
"Commands:\n"
|
||||
" do Activate next network generation\n"
|
||||
" up Bring up one/many or all interfaces in the current generation\n"
|
||||
" down Take down one/many or all interfaces in the current generation\n"
|
||||
"\n"
|
||||
"Args:\n"
|
||||
" ifname Zero, one, or more interface names to act on.\n"
|
||||
"\n", prognm);
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
cmd_t cmd;
|
||||
int c;
|
||||
|
||||
cmd = transform(argv[0]);
|
||||
|
||||
while ((c = getopt(argc, argv, "adhv")) != EOF) {
|
||||
switch (c) {
|
||||
case 'a':
|
||||
/* compat with ifup/ifdown */
|
||||
break;
|
||||
case 'd':
|
||||
debug = 1;
|
||||
break;
|
||||
case 'h':
|
||||
return usage(0);
|
||||
case 'v':
|
||||
verbose = 1;
|
||||
break;
|
||||
default:
|
||||
return usage(1);
|
||||
}
|
||||
}
|
||||
|
||||
for (c = optind; c < argc; c++) {
|
||||
if (cmd == INVAL) {
|
||||
if (!strcmp("do", argv[c]) || !strcmp("apply", argv[c]))
|
||||
cmd = DO;
|
||||
if (!strcmp("up", argv[c]))
|
||||
cmd = UP;
|
||||
if (!strcmp("down", argv[c]))
|
||||
cmd = DOWN;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
addif(argv[c]);
|
||||
}
|
||||
|
||||
if (cmd == INVAL)
|
||||
return usage(EX_USAGE);
|
||||
|
||||
return act(cmd);
|
||||
}
|
||||
-125
@@ -1,125 +0,0 @@
|
||||
#!/bin/sh
|
||||
# Generate test directory structure for verifying the net tool
|
||||
set -e
|
||||
|
||||
NET_DIR=/tmp/net
|
||||
export NET_DIR
|
||||
|
||||
gensh()
|
||||
{
|
||||
cat <<-EOF >"$1"
|
||||
|
||||
EOF
|
||||
chmod +x "$1"
|
||||
}
|
||||
|
||||
check()
|
||||
{
|
||||
if ./net -v do; then
|
||||
printf "\n[\033[1;32m OK \033[0m] Checking %s\n" "$1"
|
||||
return 0
|
||||
fi
|
||||
|
||||
printf "\n[\033[1;31FAIL\033[0m] Checking %s\n" "$1"
|
||||
return 1
|
||||
}
|
||||
|
||||
echo "Verify leaves and dependencies are evaluated first:"
|
||||
echo ""
|
||||
echo " vlan1"
|
||||
echo " ______/____"
|
||||
echo " [____br0____]"
|
||||
echo " / / \\ \\"
|
||||
echo " eth0 eth1 eth2 eth3 lag0"
|
||||
echo " / \\"
|
||||
echo " eth4 eth5"
|
||||
printf "___________________________________________________\n\n"
|
||||
|
||||
mkdir -p $NET_DIR/0
|
||||
echo 0 > $NET_DIR/next
|
||||
|
||||
mkdir -p $NET_DIR/0/eth0/deps
|
||||
mkdir -p $NET_DIR/0/eth1/deps
|
||||
mkdir -p $NET_DIR/0/eth2/deps
|
||||
mkdir -p $NET_DIR/0/eth3/deps
|
||||
mkdir -p $NET_DIR/0/eth4/deps
|
||||
mkdir -p $NET_DIR/0/eth5/deps
|
||||
|
||||
gensh $NET_DIR/0/eth0/init.ip
|
||||
gensh $NET_DIR/0/eth1/init.ip
|
||||
gensh $NET_DIR/0/eth2/init.ip
|
||||
gensh $NET_DIR/0/eth3/init.ip
|
||||
gensh $NET_DIR/0/eth4/init.ip
|
||||
gensh $NET_DIR/0/eth5/init.ip
|
||||
|
||||
mkdir -p $NET_DIR/0/lag0/deps
|
||||
ln -sf ../../eth4 $NET_DIR/0/lag0/deps/
|
||||
ln -sf ../../eth5 $NET_DIR/0/lag0/deps/
|
||||
gensh $NET_DIR/0/lag0/init.ip
|
||||
|
||||
mkdir -p $NET_DIR/0/br0/deps
|
||||
ln -sf ../../eth1 $NET_DIR/0/br0/deps/
|
||||
ln -sf ../../eth2 $NET_DIR/0/br0/deps/
|
||||
ln -sf ../../eth3 $NET_DIR/0/br0/deps/
|
||||
ln -sf ../../lag0 $NET_DIR/0/br0/deps/
|
||||
gensh $NET_DIR/0/br0/init.bridge
|
||||
gensh $NET_DIR/0/br0/init.ip
|
||||
|
||||
mkdir -p $NET_DIR/0/vlan1/deps
|
||||
ln -sf ../../br0 $NET_DIR/0/vlan1/deps/
|
||||
gensh $NET_DIR/0/vlan1/init.ip
|
||||
|
||||
check "initial startup, gen 0"
|
||||
cat $NET_DIR/0/rdeps
|
||||
|
||||
printf "___________________________________________________\n\n"
|
||||
mkdir -p $NET_DIR/1
|
||||
|
||||
mkdir -p $NET_DIR/1/eth0/deps
|
||||
mkdir -p $NET_DIR/1/eth1/deps
|
||||
mkdir -p $NET_DIR/1/eth2/deps
|
||||
mkdir -p $NET_DIR/1/eth3/deps
|
||||
mkdir -p $NET_DIR/1/eth4/deps
|
||||
mkdir -p $NET_DIR/1/eth5/deps
|
||||
|
||||
mkdir -p $NET_DIR/1/lag0/deps
|
||||
ln -sf ../../eth5 $NET_DIR/1/lag0/deps/
|
||||
|
||||
mkdir -p $NET_DIR/1/br0/deps
|
||||
ln -sf ../../eth1 $NET_DIR/1/br0/deps/
|
||||
ln -sf ../../eth2 $NET_DIR/1/br0/deps/
|
||||
ln -sf ../../eth3 $NET_DIR/1/br0/deps/
|
||||
ln -sf ../../eth4 $NET_DIR/1/br0/deps/
|
||||
ln -sf ../../lag0 $NET_DIR/1/br0/deps/
|
||||
|
||||
mkdir -p $NET_DIR/1/vlan1/deps
|
||||
ln -sf ../../br0 $NET_DIR/1/vlan1/deps/
|
||||
|
||||
gensh $NET_DIR/0/eth4/exit.ip
|
||||
gensh $NET_DIR/1/eth4/init.ip
|
||||
echo 1 > $NET_DIR/next
|
||||
|
||||
check "move eth4 from lag0 to br0"
|
||||
cat $NET_DIR/1/rdeps
|
||||
|
||||
printf "___________________________________________________\n\n"
|
||||
mkdir -p $NET_DIR/2
|
||||
|
||||
mkdir -p $NET_DIR/2/eth0/deps
|
||||
mkdir -p $NET_DIR/2/eth1/deps
|
||||
mkdir -p $NET_DIR/2/eth2/deps
|
||||
mkdir -p $NET_DIR/2/eth3/deps
|
||||
mkdir -p $NET_DIR/2/eth4/deps
|
||||
mkdir -p $NET_DIR/2/eth5/deps
|
||||
|
||||
mkdir -p $NET_DIR/2/lag0/deps
|
||||
ln -sf ../../eth5 $NET_DIR/2/lag0/deps/
|
||||
|
||||
gensh $NET_DIR/1/vlan1/exit.ip
|
||||
gensh $NET_DIR/1/br0/exit.ip
|
||||
echo 2 > $NET_DIR/next
|
||||
|
||||
check "delete vlan1 and br0"
|
||||
cat $NET_DIR/2/rdeps
|
||||
|
||||
exit 0
|
||||
@@ -1,10 +0,0 @@
|
||||
EXTRA_DIST = lib.sh $(TESTS)
|
||||
pkgdata_DATA = $(EXTRA_DIST)
|
||||
|
||||
TEST_EXTENSIONS = .sh
|
||||
TESTS_ENVIRONMENT = unshare -mrun
|
||||
TESTS = three-independent.sh
|
||||
TESTS += bridge.sh
|
||||
TESTS += bridge-lag.sh
|
||||
|
||||
CLEANFILES = *~ *.trs *.log
|
||||
@@ -1,75 +0,0 @@
|
||||
#!/bin/sh
|
||||
# vlan1
|
||||
# ______/____
|
||||
# [____br0____]
|
||||
# / / \ \
|
||||
# eth0 eth1 eth2 eth3 lag0
|
||||
# / \
|
||||
# eth4 eth5
|
||||
#
|
||||
# - Bridge with five bridge ports, one of which is a lag, and VLAN interface
|
||||
# - Move a port from lag to bridge
|
||||
# - Remove VLAN interface from bridge and remove bridge
|
||||
#
|
||||
|
||||
TEST_DIR=$(dirname "$0")
|
||||
. "$TEST_DIR/lib.sh"
|
||||
|
||||
################################################
|
||||
say "Verify bringup of bridge with three ports and an upper VLAN interface"
|
||||
|
||||
create_iface eth0 10.0.0.1/24
|
||||
create_iface eth1
|
||||
create_iface eth2
|
||||
create_iface eth3
|
||||
create_iface eth4
|
||||
create_iface eth5
|
||||
|
||||
create_lag lag0 "" eth4 eth5
|
||||
|
||||
create_bridge br0 "vlan_filtering 1" eth1 eth2 eth3 lag0
|
||||
bridge_init br0 br0 1 2 3
|
||||
|
||||
create_vlan_iface vlan1 br0 1 192.168.1.1/24
|
||||
netdo
|
||||
|
||||
#ip -d -j link show eth4 |jq -r '.[].master'
|
||||
#ip -d link show
|
||||
#bridge -d link show
|
||||
#bridge -d vlan show
|
||||
|
||||
assert_bridge_ports br0 true eth1 eth2 eth3 lag0
|
||||
assert_iface br0
|
||||
assert_iface vlan1 192.168.1.1/24
|
||||
assert_lag_ports lag0 true eth4 eth5
|
||||
|
||||
################################################
|
||||
sep
|
||||
say "Verify moving a port from lag0 to br0"
|
||||
|
||||
del_lagport lag0 eth4
|
||||
init_next_gen eth0 eth1 eth2 eth3 eth4 eth5 lag0 br0 vlan1
|
||||
init_deps br0 eth1 eth2 eth3 lag0
|
||||
init_deps lag0 eth5
|
||||
add_brport br0 eth4
|
||||
|
||||
netdo
|
||||
|
||||
assert_lag_ports lag0 true eth5
|
||||
assert_lag_ports lag0 false eth4
|
||||
|
||||
assert_bridge_ports br0 true eth1 eth2 eth3 eth4 lag0
|
||||
assert_iface br0
|
||||
|
||||
################################################
|
||||
sep
|
||||
say "Verify removing VLAN interface (vlan1) and bridge (br0)"
|
||||
remove_iface vlan1
|
||||
remove_iface br0
|
||||
init_next_gen eth0 eth1 eth2 eth3 eth4 eth5 lag0
|
||||
|
||||
netdo
|
||||
|
||||
for iface in eth0 eth1 eth2 eth3 eth4 lag0 eth5; do
|
||||
assert_iface $iface
|
||||
done
|
||||
@@ -1,47 +0,0 @@
|
||||
#!/bin/sh
|
||||
# - Basic bridge with three bridge ports
|
||||
# - Add another port
|
||||
# - Remove a port
|
||||
|
||||
TEST_DIR=$(dirname "$0")
|
||||
. "$TEST_DIR/lib.sh"
|
||||
|
||||
################################################
|
||||
say "Verify bringup of basic bridge with three ports"
|
||||
create_iface eth0
|
||||
create_iface eth1
|
||||
create_iface eth2
|
||||
create_bridge br0 "" eth0 eth1 eth2
|
||||
|
||||
netdo
|
||||
|
||||
assert_bridge_ports br0 true eth0 eth1 eth2
|
||||
assert_iface br0
|
||||
|
||||
################################################
|
||||
sep
|
||||
say "Verify add another bridge port (eth3)"
|
||||
init_next_gen eth0 eth1 eth2 br0
|
||||
init_deps br0 eth0 eth1 eth2
|
||||
|
||||
create_iface eth3
|
||||
add_brport br0 eth3
|
||||
|
||||
netdo
|
||||
|
||||
assert_bridge_ports br0 true eth0 eth1 eth2 eth3
|
||||
assert_iface br0
|
||||
|
||||
################################################
|
||||
sep
|
||||
say "Verify delete a bridge port (eth1)"
|
||||
del_brport br0 eth1
|
||||
|
||||
init_next_gen eth0 eth2 eth3 br0
|
||||
init_deps br0 eth0 eth2 eth3
|
||||
|
||||
netdo
|
||||
|
||||
assert_bridge_ports br0 true eth0 eth2 eth3
|
||||
assert_bridge_ports br0 false eth1
|
||||
assert_iface br0
|
||||
@@ -1,479 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Session set from Makefile before calling unshare -mrun
|
||||
if [ -z "$SESSION" ]; then
|
||||
SESSION=$(mktemp -d)
|
||||
TMPSESS=1
|
||||
fi
|
||||
|
||||
if [ -n "$DEBUG" ]; then
|
||||
DEBUG="-v -d"
|
||||
else
|
||||
DEBUG=""
|
||||
fi
|
||||
|
||||
# Test name, used everywhere as /tmp/$NM/foo
|
||||
NM=$(basename "$0" .sh)
|
||||
NET_DIR="${SESSION}/${NM}"
|
||||
export NET_DIR
|
||||
|
||||
gen=-1
|
||||
|
||||
NET=$(command -v net)
|
||||
if [ -n "$NET" ]; then
|
||||
# Verify we didn't find Samba net command, our net live in sbin
|
||||
if [ "$(dirname "$NET")" = "/usr/bin" ]; then
|
||||
NET=""
|
||||
fi
|
||||
fi
|
||||
[ -n "$NET" ] || NET=../src/net
|
||||
|
||||
# Exit immediately on error, treat unset variables as error
|
||||
set -eu
|
||||
|
||||
color_reset='\e[0m'
|
||||
fg_red='\e[1;31m'
|
||||
fg_green='\e[1;32m'
|
||||
fg_yellow='\e[1;33m'
|
||||
log()
|
||||
{
|
||||
test=$(basename "$0" ".sh")
|
||||
printf "\e[2m[%s]\e[0m %b%b%b %s\n" "$test" "$1" "$2" "$color_reset" "$3"
|
||||
}
|
||||
|
||||
sep()
|
||||
{
|
||||
printf "\e[2m――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――\e[0m\n"
|
||||
}
|
||||
|
||||
say()
|
||||
{
|
||||
log "$fg_yellow" "•" "$@"
|
||||
}
|
||||
|
||||
skip()
|
||||
{
|
||||
log "$fg_yellow" − "$*"
|
||||
exit 77
|
||||
}
|
||||
|
||||
fail()
|
||||
{
|
||||
log "$fg_red" ✘ "$*"
|
||||
exit 99
|
||||
}
|
||||
|
||||
assert()
|
||||
{
|
||||
__assert_msg=$1
|
||||
shift
|
||||
|
||||
if [ ! "$@" ]; then
|
||||
log "$fg_red" ✘ "$__assert_msg ($*)"
|
||||
return 1
|
||||
fi
|
||||
|
||||
log "$fg_green" ✔ "$__assert_msg"
|
||||
return 0
|
||||
}
|
||||
|
||||
signal()
|
||||
{
|
||||
echo
|
||||
if [ "$1" != "EXIT" ]; then
|
||||
print "Got signal, cleaning up"
|
||||
fi
|
||||
|
||||
rm -rf "${NET_DIR}"
|
||||
if [ -n "$TMPSESS" ] && [ -d "$SESSION" ]; then
|
||||
rm -rf "$SESSION"
|
||||
fi
|
||||
}
|
||||
|
||||
# props to https://stackoverflow.com/a/2183063/1708249
|
||||
# shellcheck disable=SC2064
|
||||
trapit()
|
||||
{
|
||||
func="$1" ; shift
|
||||
for sig ; do
|
||||
trap "$func $sig" "$sig"
|
||||
done
|
||||
}
|
||||
|
||||
# shellcheck disable=SC2120
|
||||
init_next_gen()
|
||||
{
|
||||
_=$((gen += 1))
|
||||
mkdir -p "$NET_DIR/$gen"
|
||||
echo $gen > "$NET_DIR/next"
|
||||
|
||||
# shellcheck disable=SC2068
|
||||
for iface in $@; do
|
||||
create_iface_data "$iface"
|
||||
done
|
||||
}
|
||||
|
||||
init_deps()
|
||||
{
|
||||
parent=$1
|
||||
shift
|
||||
|
||||
mkdir -p "$NET_DIR/$gen/$parent/deps"
|
||||
#shellcheck disable=SC2068
|
||||
for iface in $@; do
|
||||
ln -s "../../$iface" "$NET_DIR/$gen/$parent/deps/$iface"
|
||||
done
|
||||
}
|
||||
|
||||
setup()
|
||||
{
|
||||
say "Test start $(date)"
|
||||
init_next_gen
|
||||
|
||||
# Runs once when including lib.sh
|
||||
mkdir -p "${NET_DIR}"
|
||||
trapit signal INT TERM QUIT EXIT
|
||||
|
||||
ip link set lo up
|
||||
sep
|
||||
}
|
||||
|
||||
netdo()
|
||||
{
|
||||
if [ -n "$DEBUG" ]; then
|
||||
tree "$NET_DIR/"
|
||||
echo "Calling: $NET $DEBUG apply"
|
||||
fi
|
||||
|
||||
# shellcheck disable=SC2086
|
||||
$NET $DEBUG apply
|
||||
|
||||
if [ -n "$DEBUG" ]; then
|
||||
ip link
|
||||
ip addr
|
||||
tree "$NET_DIR/"
|
||||
fi
|
||||
}
|
||||
|
||||
netdown()
|
||||
{
|
||||
# shellcheck disable=SC2086,SC2068
|
||||
$NET $DEBUG down $@
|
||||
|
||||
if [ -n "$DEBUG" ]; then
|
||||
ip link
|
||||
ip addr
|
||||
fi
|
||||
}
|
||||
|
||||
netup()
|
||||
{
|
||||
# shellcheck disable=SC2086,SC2068
|
||||
$NET $DEBUG up $@
|
||||
|
||||
if [ -n "$DEBUG" ]; then
|
||||
ip link
|
||||
ip addr
|
||||
fi
|
||||
}
|
||||
|
||||
create_iface_data()
|
||||
{
|
||||
ifname=$1
|
||||
ifdir="$NET_DIR/$gen/$ifname"
|
||||
|
||||
mkdir -p "$ifdir/deps"
|
||||
echo "up" > "$ifdir/admin-state"
|
||||
}
|
||||
|
||||
create_iface()
|
||||
{
|
||||
ifname=$1
|
||||
ifdir="$NET_DIR/$gen/$ifname"
|
||||
if [ $# -eq 2 ]; then
|
||||
address=$2
|
||||
else
|
||||
address=""
|
||||
fi
|
||||
|
||||
create_iface_data $ifname
|
||||
|
||||
if [ ! -f "$ifdir/init.ip" ]; then
|
||||
echo "link add $ifname type dummy" > "$ifdir/init.ip"
|
||||
fi
|
||||
if [ -n "$address" ]; then
|
||||
cat <<-EOF >>"$ifdir/init.ip"
|
||||
addr add $address dev $ifname
|
||||
link set $ifname up
|
||||
EOF
|
||||
fi
|
||||
}
|
||||
|
||||
create_vlan_iface()
|
||||
{
|
||||
ifname=$1
|
||||
link=$2
|
||||
vid=$3
|
||||
if [ $# -eq 4 ]; then
|
||||
address=$4
|
||||
else
|
||||
address=""
|
||||
fi
|
||||
ifdir="$NET_DIR/$gen/$ifname"
|
||||
|
||||
mkdir -p "$ifdir/deps"
|
||||
ln -s "../../$link" "$ifdir/deps/$link"
|
||||
|
||||
cat <<-EOF >"$ifdir/init.ip"
|
||||
link add $ifname link $link type vlan id $vid
|
||||
link set $ifname up
|
||||
EOF
|
||||
if [ -n "$address" ]; then
|
||||
cat <<-EOF >>"$ifdir/init.ip"
|
||||
addr add $address dev $ifname
|
||||
EOF
|
||||
fi
|
||||
|
||||
echo "up" > "$ifdir/admin-state"
|
||||
}
|
||||
|
||||
# shellcheck disable=SC2124
|
||||
add_brport()
|
||||
{
|
||||
brname=$1
|
||||
shift
|
||||
brports=$@
|
||||
brdir="$NET_DIR/$gen/$brname"
|
||||
|
||||
mkdir -p "$brdir/deps"
|
||||
for port in $brports; do
|
||||
ln -s "../../$port" "$brdir/deps/$port"
|
||||
|
||||
cat <<-EOF >> "$brdir/init.ip"
|
||||
# Attaching port $port to bridge $brname
|
||||
link set $port master $brname
|
||||
link set $port up
|
||||
EOF
|
||||
done
|
||||
}
|
||||
|
||||
# shellcheck disable=SC2124
|
||||
del_brport()
|
||||
{
|
||||
brname=$1
|
||||
shift
|
||||
brports=$@
|
||||
brdir="$NET_DIR/$gen/$brname"
|
||||
|
||||
for port in $brports; do
|
||||
cat <<-EOF >"$brdir/exit.ip"
|
||||
link set $port nomaster
|
||||
EOF
|
||||
done
|
||||
}
|
||||
|
||||
# shellcheck disable=SC2124,SC2086
|
||||
create_bridge()
|
||||
{
|
||||
brname=$1
|
||||
bropts=$2
|
||||
shift 2
|
||||
brports=$@
|
||||
brdir="$NET_DIR/$gen/$brname"
|
||||
|
||||
mkdir -p "$brdir/deps"
|
||||
cat <<-EOF > "$brdir/init.ip"
|
||||
link add $brname type bridge $bropts
|
||||
EOF
|
||||
|
||||
add_brport "$brname" $brports
|
||||
cat <<-EOF >> "$brdir/init.ip"
|
||||
link set $brname up
|
||||
EOF
|
||||
|
||||
echo "up" > "$brdir/admin-state"
|
||||
}
|
||||
|
||||
# Create init.bridge commands to be run for $ifname on $brname
|
||||
# shellcheck disable=SC2124,SC2086
|
||||
bridge_init()
|
||||
{
|
||||
brname=$1
|
||||
ifname=$2
|
||||
shift 2
|
||||
vlans=$@
|
||||
ifdir="$NET_DIR/$gen/$ifname"
|
||||
|
||||
echo "" > "$ifdir/init.bridge"
|
||||
for vlan in $vlans; do
|
||||
echo "vlan add vid $vlan dev $brname self" >> "$ifdir/init.bridge"
|
||||
done
|
||||
}
|
||||
|
||||
# shellcheck disable=SC2124
|
||||
add_lagport()
|
||||
{
|
||||
lagnm=$1
|
||||
shift
|
||||
lagports=$@
|
||||
lagdir="$NET_DIR/$gen/$lagnm"
|
||||
|
||||
for port in $lagports; do
|
||||
ln -s "../../$port" "$lagdir/deps/$port"
|
||||
|
||||
cat <<-EOF >>"$lagdir/init.ip"
|
||||
# Attaching port $port to $lagnm
|
||||
link set $port master $lagnm
|
||||
link set $port up
|
||||
EOF
|
||||
done
|
||||
}
|
||||
|
||||
# shellcheck disable=SC2124
|
||||
del_lagport()
|
||||
{
|
||||
lagnm=$1
|
||||
shift
|
||||
lagports=$@
|
||||
lagdir="$NET_DIR/$gen/$lagnm"
|
||||
|
||||
for port in $lagports; do
|
||||
cat <<-EOF >>"$lagdir/exit.ip"
|
||||
link set $port nomaster
|
||||
EOF
|
||||
done
|
||||
}
|
||||
|
||||
# shellcheck disable=SC2124,SC2086
|
||||
create_lag()
|
||||
{
|
||||
lagnm=$1
|
||||
lagopts=$2
|
||||
shift 2
|
||||
ports=$@
|
||||
lagdir="$NET_DIR/$gen/$lagnm"
|
||||
|
||||
mkdir -p "$lagdir/deps"
|
||||
cat <<-EOF > "$lagdir/init.ip"
|
||||
link add $lagnm type bond $lagopts
|
||||
link set $lagnm up
|
||||
EOF
|
||||
|
||||
add_lagport "$lagnm" $ports
|
||||
echo "up" > "$lagdir/admin-state"
|
||||
}
|
||||
|
||||
remove_iface()
|
||||
{
|
||||
ifname=$1
|
||||
|
||||
cat <<-EOF >"$NET_DIR/$gen/$ifname/exit.ip"
|
||||
link del $ifname
|
||||
EOF
|
||||
}
|
||||
|
||||
assert_iface()
|
||||
{
|
||||
ifname=$1
|
||||
if [ $# -gt 1 ]; then
|
||||
address=$2
|
||||
else
|
||||
address=""
|
||||
fi
|
||||
state=$(tr '[:lower:]' '[:upper:]' < "$NET_DIR/$gen/$ifname/admin-state")
|
||||
|
||||
addr=$(ip -br -j addr show "$ifname" | jq -r '.[] | .addr_info[0].local')
|
||||
plen=$(ip -br -j addr show "$ifname" | jq -r '.[] | .addr_info[0].prefixlen')
|
||||
addr="$addr/$plen"
|
||||
updn=$(ip -br -j link show "$ifname" | jq -r '.[] | .flags[] | select(index("UP"))' | head -1)
|
||||
|
||||
# echo "$state => $ifname: $updn $addr"
|
||||
assert "Verify $ifname state $state" "$state" = "$updn"
|
||||
if [ -n "$address" ]; then
|
||||
assert "Verify $ifname address $address" "$address" = "$addr"
|
||||
fi
|
||||
}
|
||||
|
||||
assert_noiface()
|
||||
{
|
||||
ifname=$1
|
||||
rc=true
|
||||
|
||||
for iface in $(ip -j -br link show |jq -r '.[] .ifname'); do
|
||||
[ "$iface" = "$ifname" ] || continue
|
||||
|
||||
rc=false
|
||||
break
|
||||
done
|
||||
|
||||
assert "Verify $ifname has been removed" $rc
|
||||
}
|
||||
|
||||
assert_iface_flag()
|
||||
{
|
||||
found=false
|
||||
ifname=$2
|
||||
flag=$3
|
||||
msg=$1
|
||||
val=$4
|
||||
|
||||
for f in $(ip -j -br link show "$ifname" |jq -r '.[] .flags[]'); do
|
||||
# echo "$ifname: FLAG $f ..."
|
||||
[ "$f" = "$flag" ] || continue
|
||||
found=true
|
||||
break
|
||||
done
|
||||
|
||||
# echo "FLAG $flag found $found, expected $val"
|
||||
assert "$msg" "$found" = "$val"
|
||||
}
|
||||
|
||||
assert_bridge_ports()
|
||||
{
|
||||
br="$1"
|
||||
val="$2"
|
||||
shift 2
|
||||
# shellcheck disable=SC2124
|
||||
ports=$@
|
||||
|
||||
for port in $ports; do
|
||||
found=false
|
||||
for brport in $(bridge -j link |jq -r --arg br "$br" '.[] | select(.master == $br).ifname'); do
|
||||
if [ "$port" = "$brport" ]; then
|
||||
found=true
|
||||
break;
|
||||
fi
|
||||
done
|
||||
if [ "$val" = "false" ]; then
|
||||
not="NOT "
|
||||
else
|
||||
not=""
|
||||
fi
|
||||
assert "Port $port is ${not}a $br bridge port" "$found" = "$val"
|
||||
done
|
||||
}
|
||||
|
||||
assert_lag_ports()
|
||||
{
|
||||
lag="$1"
|
||||
val="$2"
|
||||
shift 2
|
||||
# shellcheck disable=SC2124
|
||||
ports=$@
|
||||
|
||||
for port in $ports; do
|
||||
found=false
|
||||
|
||||
if [ "$lag" = "$(ip -d -j link show $port |jq -r '.[].master')" ]; then
|
||||
found=true
|
||||
fi
|
||||
if [ "$val" = "false" ]; then
|
||||
not="NOT "
|
||||
else
|
||||
not=""
|
||||
fi
|
||||
assert "Port $port is ${not}a $lag member port" "$found" = "$val"
|
||||
done
|
||||
}
|
||||
|
||||
setup
|
||||
@@ -1,42 +0,0 @@
|
||||
#!/bin/sh
|
||||
# - Verify correct bring up of three independent interfaces
|
||||
# - Verify removal of one
|
||||
# - Verify net down
|
||||
# - Verify net up <one>
|
||||
TEST_DIR=$(dirname "$0")
|
||||
. "$TEST_DIR/lib.sh"
|
||||
|
||||
say "Verify bringup of generation $gen"
|
||||
create_iface eth0 10.0.0.1/24
|
||||
create_iface eth1 10.0.1.1/24
|
||||
create_iface eth2 10.0.2.1/24
|
||||
|
||||
netdo
|
||||
|
||||
assert_iface eth0 10.0.0.1/24
|
||||
assert_iface eth1 10.0.1.1/24
|
||||
assert_iface eth2 10.0.2.1/24
|
||||
|
||||
sep
|
||||
say "Verify removal of an interface"
|
||||
remove_iface eth1
|
||||
init_next_gen eth0 eth2
|
||||
|
||||
netdo
|
||||
|
||||
assert_iface eth0 10.0.0.1/24
|
||||
assert_noiface eth1
|
||||
assert_iface eth2 10.0.2.1/24
|
||||
|
||||
sep
|
||||
say "Verify net down"
|
||||
netdown
|
||||
assert_iface_flag "Verify eth0 DOWN" eth0 UP false
|
||||
assert_iface_flag "Verify eth2 DOWN" eth2 UP false
|
||||
|
||||
sep
|
||||
say "Verify net up eth2"
|
||||
netup eth2
|
||||
assert_iface_flag "Verify eth0 DOWN" eth0 UP false
|
||||
assert_iface_flag "Verify eth2 UP" eth2 UP true
|
||||
|
||||
Reference in New Issue
Block a user