net: drop unused 'net' package, replaced by dagger

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
This commit is contained in:
Joachim Wiberg
2023-11-17 09:49:32 +01:00
parent 1fd98758ba
commit 5031ff6224
19 changed files with 0 additions and 1675 deletions
-1
View File
@@ -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
-1
View File
@@ -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
-1
View File
@@ -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"
-6
View File
@@ -1,6 +0,0 @@
config BR2_PACKAGE_NET
bool "net"
select BR2_PACKAGE_IPROUTE2
select BR2_PACKAGE_LIBITE
help
Handles transitions between network states.
-21
View File
@@ -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))
-13
View File
@@ -1,13 +0,0 @@
*.o
*.log
*.trs
net
Makefile
Makefile.in
aclocal.m4
autom4te.cache/
aux/
config.*
configure
src/.deps/
stamp-h1
-19
View File
@@ -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.
-4
View File
@@ -1,4 +0,0 @@
SUBDIRS = src test
DISTCLEANFILES = *~ *.d
ACLOCAL_AMFLAGS = -I m4
-167
View File
@@ -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.
-3
View File
@@ -1,3 +0,0 @@
#!/bin/sh
autoreconf -W portability -vifm
-40
View File
@@ -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
-5
View File
@@ -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)
-616
View File
@@ -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
View File
@@ -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
-10
View File
@@ -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
-75
View File
@@ -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
-47
View File
@@ -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
-479
View File
@@ -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
-42
View File
@@ -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