summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/base/main.c252
-rw-r--r--src/base/state.c76
-rw-r--r--src/base/state.h17
3 files changed, 191 insertions, 154 deletions
diff --git a/src/base/main.c b/src/base/main.c
index 60d76b4..6721701 100644
--- a/src/base/main.c
+++ b/src/base/main.c
@@ -1,5 +1,6 @@
#include "state.h"
#include <netgraph.h>
+#include <sys/param.h>
#include "../util.h"
static char const *Arg0;
@@ -215,28 +216,7 @@ start_link_(link_ *R)
fprintf(stderr, "Failed to create netgraph socket: %s\n", strerror(errno));
return -1;
}
- int Result;
- switch(R->Configuration.Type)
- {
- case link_type_direct:
- {
- Result =
- ng_connect(Control, R->Peer[0].Address, R->Peer[1].Address, R->Peer[0].Hook, R->Peer[1].Hook);
- break;
- }
- case link_type_pipe:
- {
- Result = Create_pipe(&R->pipe.ID,
- Control,
- R->Peer[0].Address,
- R->Peer[1].Address,
- R->Peer[0].Hook,
- R->Peer[1].Hook);
- break;
- }
- case link_type_COUNT:
- default: __builtin_unreachable();
- }
+ int Result = ng_connect(Control, R->Peer[0].Address, R->Peer[1].Address, R->Peer[0].Hook, R->Peer[1].Hook);
close(Control);
return Result;
}
@@ -250,31 +230,25 @@ stop_link_(link_ *R)
fprintf(stderr, "Failed to create netgraph socket: %s\n", strerror(errno));
return -1;
}
- switch(R->Configuration.Type)
+ if(R->PipeID)
{
- case link_type_direct:
- {
- struct ngm_rmhook D;
- char Path0[NG_PATHSIZ];
- strncpy(Path0, R->Peer[0].Address, sizeof(Path0));
- strncpy(D.ourhook, R->Peer[0].Hook, sizeof(D.ourhook));
- if(NgSendMsg(Control, Path0, NGM_GENERIC_COOKIE, NGM_RMHOOK, &D, sizeof(D)) == -1)
- {
- fprintf(stderr, "ngctl rmhook %s %s: %s\n", Path0, D.ourhook, strerror(errno));
- close(Control);
- return -1;
- }
- close(Control);
- return 0;
- }
- case link_type_pipe:
+ int Result = DestroyNetgraphNode(R->PipeID, Control);
+ close(Control);
+ return Result;
+ } else
+ {
+ struct ngm_rmhook D;
+ char Path0[NG_PATHSIZ];
+ strncpy(Path0, R->Peer[0].Address, sizeof(Path0));
+ strncpy(D.ourhook, R->Peer[0].Hook, sizeof(D.ourhook));
+ if(NgSendMsg(Control, Path0, NGM_GENERIC_COOKIE, NGM_RMHOOK, &D, sizeof(D)) == -1)
{
- int Result = DestroyNetgraphNode(R->pipe.ID, Control);
+ fprintf(stderr, "ngctl rmhook %s %s: %s\n", Path0, D.ourhook, strerror(errno));
close(Control);
- return Result;
+ return -1;
}
- case link_type_COUNT:
- default: __builtin_unreachable();
+ close(Control);
+ return 0;
}
}
@@ -284,8 +258,7 @@ start_link(experiment *E,
char const *NodeA,
char const *InterfaceA,
char const *NodeB,
- char const *InterfaceB,
- link_type Type)
+ char const *InterfaceB)
{
if(FindLinkIndex(E, Name) != SIZE_MAX)
{
@@ -298,7 +271,6 @@ start_link(experiment *E,
C.Peer[0].Interface = strdup(InterfaceA);
C.Peer[1].Node = strdup(NodeB);
C.Peer[1].Interface = strdup(InterfaceB);
- C.Type = Type;
}
link_ R;
{ // Start
@@ -622,16 +594,30 @@ LoadState(experiment *E, fd FD)
static void __attribute__((noreturn)) usage(void)
{
+ // NOTE: I couldn't find a way to make string precision work with '$'.
+ // We could skip all this buffer nonsense that way.
+ size_t Length = strlen(Arg0);
+ char Buffer[PATH_MAX];
+ if(Length > sizeof(Buffer)) Length = sizeof(Buffer) - 1;
+ memset(Buffer, ' ', Length);
+ Buffer[Length] = 0;
fprintf(
stderr,
"usage: %1$s show\n"
- " %1$s node start [node-name] [configuration]\n"
- " %1$s node stop [node-name]\n"
- " %1$s link start [link-name] [node-A-name] [interface-A-name] [node-B-name] [interface-B-name] [?type]\n"
- " %1$s link stop [link-name]\n"
- " %1$s node cmd [node-name] [command...]\n"
- " %1$s node mod [node-name] [command...]\n",
- Arg0);
+ " %1$s node start [node-name] [configuration]\n"
+ " %2$s stop [node-name]\n"
+ " %2$s cmd [node-name] [command...]\n"
+ " %2$s mod [node-name] [command...]\n"
+ " %1$s link start [link-name] [node-A-name] [interface-A-name] [node-B-name] [interface-B-name]\n"
+ " %2$s stop [link-name]\n"
+ " %2$s setcfg [link-name] [configuration]\n"
+ " %2$s getcfg [link-name]\n"
+ " %2$s clrcfg [link-name]\n"
+ " %2$s getstats [link-name]\n"
+ " %2$s clrstats [link-name]\n"
+ " %2$s getclrstats [link-name]\n",
+ Arg0,
+ Buffer);
exit(EX_USAGE);
}
@@ -723,6 +709,101 @@ Command_node(experiment *E, fd StateFD, int ArgCount, char **Arg)
}
static int
+link_unpipe(link_ *E, fd Control)
+{
+ if(E->PipeID == 0) return 0;
+ if(DestroyNetgraphNode(E->PipeID, Control) == -1) return -1;
+ E->PipeID = 0;
+ if(ng_connect(Control, E->Peer[0].Address, E->Peer[1].Address, E->Peer[0].Hook, E->Peer[1].Hook) == -1)
+ return -1;
+ return 0;
+}
+
+static int
+link_pipe(link_ *E, fd Control)
+{
+ if(E->PipeID != 0) return 0;
+ struct ngm_rmhook D;
+ char Path0[NG_PATHSIZ];
+ strncpy(Path0, E->Peer[0].Address, sizeof(Path0));
+ strncpy(D.ourhook, E->Peer[0].Hook, sizeof(D.ourhook));
+ if(NgSendMsg(Control, Path0, NGM_GENERIC_COOKIE, NGM_RMHOOK, &D, sizeof(D)) == -1)
+ {
+ fprintf(stderr, "ngctl rmhook %s %s: %s\n", Path0, D.ourhook, strerror(errno));
+ return -1;
+ }
+ return Create_pipe(&E->PipeID,
+ Control,
+ E->Peer[0].Address,
+ E->Peer[1].Address,
+ E->Peer[0].Hook,
+ E->Peer[1].Hook);
+}
+
+static int
+link_setcfg(link_ *E, fd Control, char const *Config)
+{
+ if(link_pipe(E, Control) == -1) goto error;
+ if(*Config == '\0') return 0;
+ char Path[NG_PATHSIZ];
+ snprintf(Path, sizeof(Path), "[%x]:", E->PipeID);
+ if(NgSendAsciiMsg(Control, Path, "setcfg {%s}", Config) < 0)
+ {
+ // NOTE: We do not save if return code is not 0.
+ // We should probably always save configuration.
+ // We do not want to create a node and not save it.
+ fprintf(stderr, "NgSendAsciiMsg failed: %s\n", strerror(errno));
+ }
+ return 0;
+error:
+ return -1;
+}
+
+static int
+link_get(link_ *E, fd Control, char const *What)
+{
+ if(E->PipeID == 0)
+ {
+ fprintf(stderr, "link is not a pipe\n");
+ return -1;
+ }
+ char Path[NG_PATHSIZ];
+ snprintf(Path, sizeof(Path), "[%x]:", E->PipeID);
+ if(NgSendAsciiMsg(Control, Path, "%s", What) < 0)
+ {
+ fprintf(stderr, "NgSendAsciiMsg failed: %s\n", strerror(errno));
+ return -1;
+ }
+ struct ng_mesg *Message;
+ if(NgAllocRecvAsciiMsg(Control, &Message, Path) < 0)
+ {
+ fprintf(stderr, "NgAllocRecvAsciiMsg failed: %s\n", strerror(errno));
+ return -1;
+ }
+ printf("%s", Message->data);
+ free(Message);
+ return 0;
+}
+
+static int
+link_clrstats(link_ *E, fd Control)
+{
+ if(E->PipeID == 0)
+ {
+ fprintf(stderr, "link is not a pipe\n");
+ return -1;
+ }
+ char Path[NG_PATHSIZ];
+ snprintf(Path, sizeof(Path), "[%x]:", E->PipeID);
+ if(NgSendAsciiMsg(Control, Path, "clrstats") < 0)
+ {
+ fprintf(stderr, "NgSendAsciiMsg failed: %s\n", strerror(errno));
+ return -1;
+ }
+ return 0;
+}
+
+static int
Command_link(experiment *E, fd StateFD, int ArgCount, char **Arg)
{
if(ArgCount < 2) usage();
@@ -738,32 +819,57 @@ Command_link(experiment *E, fd StateFD, int ArgCount, char **Arg)
int Result;
if(strcmp(Command, "start") == 0)
{
- if(ArgCount == 4)
- {
- Result = start_link(E, LinkName, Arg[0], Arg[1], Arg[2], Arg[3], link_type_direct);
- } else if(ArgCount == 5)
- {
- link_type Type;
- if(FromString_link_type(Arg[4], &Type) == -1)
- {
- fprintf(stderr, "Unknown link type '%s'\n", Arg[4]);
- Result = -1;
- } else
- {
- Result = start_link(E, LinkName, Arg[0], Arg[1], Arg[2], Arg[3], Type);
- }
- } else
- {
- usage();
- }
+ if(ArgCount != 4) usage();
+ Result = start_link(E, LinkName, Arg[0], Arg[1], Arg[2], Arg[3]);
} else if(strcmp(Command, "stop") == 0)
{
if(ArgCount != 0) usage();
Result = stop_link(E, LinkName);
} else
{
- fprintf(stderr, "unknown argument: %s\n", Command);
- usage();
+ size_t LinkIndex = FindLinkIndex(E, LinkName);
+ if(LinkIndex == SIZE_MAX)
+ {
+ fprintf(stderr, "Link %s does not exists\n", LinkName);
+ return -1;
+ }
+ link_ *R = E->Link + LinkIndex;
+ fd Control;
+ if(NgMkSockNode(NULL, &Control, NULL) == -1)
+ {
+ fprintf(stderr, "Failed to create netgraph socket: %s\n", strerror(errno));
+ return -1;
+ }
+ if(strcmp(Command, "setcfg") == 0)
+ {
+ if(ArgCount != 1) usage();
+ Result = link_setcfg(R, Control, Arg[0]);
+ } else if(strcmp(Command, "getcfg") == 0)
+ {
+ if(ArgCount != 0) usage();
+ Result = link_get(R, Control, "getcfg");
+ } else if(strcmp(Command, "clrcfg") == 0)
+ {
+ if(ArgCount != 0) usage();
+ Result = link_unpipe(R, Control);
+ } else if(strcmp(Command, "getstats") == 0)
+ {
+ if(ArgCount != 0) usage();
+ Result = link_get(R, Control, "getstats");
+ } else if(strcmp(Command, "clrstats") == 0)
+ {
+ if(ArgCount != 0) usage();
+ Result = link_clrstats(R, Control);
+ } else if(strcmp(Command, "getclrstats") == 0)
+ {
+ if(ArgCount != 0) usage();
+ Result = link_get(R, Control, "getclrstats");
+ } else
+ {
+ fprintf(stderr, "unknown argument: %s\n", Command);
+ usage();
+ }
+ close(Control);
}
if(Result == 0) SaveState(E, StateFD);
return Result;
diff --git a/src/base/state.c b/src/base/state.c
index 652c943..acef753 100644
--- a/src/base/state.c
+++ b/src/base/state.c
@@ -103,50 +103,12 @@ error:
return Error;
}
-int
-FromString_link_type(char const *S, link_type *Type)
-{
- for(link_type i = 0; i < link_type_COUNT; ++i)
- {
- if(strcmp(link_type_Names[i], S) == 0)
- {
- *Type = i;
- return 0;
- }
- }
- return -1;
-}
-
-char *
-Parse_link_type(link_type *E, ucl_object_t const *root, char const *Position)
-{
- if(root == NULL)
- {
- *E = link_type_direct;
- return NULL;
- }
- char *Error;
- UCL_CHECK_ROOT(STRING);
- char const *S = ucl_object_tostring(root);
- if(FromString_link_type(S, E) == 0) return NULL;
- asprintf(&Error, "%s invalid link type '%s'", Position, S);
-error:
- return Error;
-}
-
char *
Parse_link_configuration(link_configuration *E, ucl_object_t const *root, char const *Position)
{
char *Error;
size_t EndpointAt = 0;
UCL_CHECK_ROOT(OBJECT);
- {
- char *NewPosition;
- asprintf(&NewPosition, "%s.type", Position);
- Error = Parse_link_type(&E->Type, ucl_object_lookup(root, "type"), NewPosition);
- free(NewPosition);
- if(Error != NULL) goto error;
- }
ucl_object_t const *peer0 = ucl_object_lookup(root, "peer0");
{
char *NewPosition;
@@ -178,6 +140,8 @@ Parse_link(link_ *E, ucl_object_t const *root, char const *Position)
size_t EndpointAt = 0;
bool Configuration = false;
UCL_CHECK_ROOT(OBJECT);
+ ucl_object_t const *id = ucl_object_lookup(root, "id");
+ UCL_CHECK_OPTIONAL(id, INT);
ucl_object_t const *configuration = ucl_object_lookup(root, "configuration");
{
char *NewPosition;
@@ -187,24 +151,15 @@ Parse_link(link_ *E, ucl_object_t const *root, char const *Position)
if(Error != NULL) goto error;
Configuration = true;
}
- switch(E->Configuration.Type)
+ if(id != NULL)
{
- case link_type_direct: break;
- case link_type_pipe:
+ s64 ID = ucl_object_toint(id);
+ if(ID < 0 || ID > INT32_MAX)
{
- ucl_object_t const *id = ucl_object_lookup(root, "id");
- UCL_CHECK(id, INT);
- s64 ID = ucl_object_toint(id);
- if(ID < 0 || ID > INT32_MAX)
- {
- asprintf(&Error, "%s id invalid (%ld)", Position, ID);
- goto error;
- }
- E->pipe.ID = (u32)ID;
- break;
+ asprintf(&Error, "%s id invalid (%ld)", Position, ID);
+ goto error;
}
- case link_type_COUNT:
- default: __builtin_unreachable();
+ E->PipeID = (u32)ID;
}
ucl_object_t const *peer0 = ucl_object_lookup(root, "peer0");
{
@@ -365,8 +320,6 @@ void
Save_link_configuration(jprint_state *S, link_configuration const *E)
{
JPrintObjectBegin(S);
- JPrintMember(S, "type");
- JPrint_string(S, link_type_Names[E->Type]);
JPrintMember(S, "peer0");
Save_endpoint_configuration(S, E->Peer + 0);
JPrintMember(S, "peer1");
@@ -380,17 +333,10 @@ Save_link(jprint_state *S, link_ const *E)
JPrintObjectBegin(S);
JPrintMember(S, "configuration");
Save_link_configuration(S, &E->Configuration);
- switch(E->Configuration.Type)
+ if(E->PipeID != 0)
{
- case link_type_direct: break;
- case link_type_pipe:
- {
- JPrintMember(S, "id");
- JPrint_ssize_t(S, E->pipe.ID);
- break;
- }
- case link_type_COUNT:
- default: __builtin_unreachable();
+ JPrintMember(S, "id");
+ JPrint_ssize_t(S, E->PipeID);
}
JPrintMember(S, "peer0");
Save_endpoint(S, E->Peer + 0);
diff --git a/src/base/state.h b/src/base/state.h
index 82db1e0..5aa29bd 100644
--- a/src/base/state.h
+++ b/src/base/state.h
@@ -14,12 +14,9 @@ struct
char *Interface;
} typedef endpoint_configuration;
-NAMED_ENUM(link_type, direct, pipe, );
-
struct
{
endpoint_configuration Peer[2];
- link_type Type;
} typedef link_configuration;
struct
@@ -27,16 +24,7 @@ struct
char *Name;
link_configuration Configuration;
endpoint Peer[2];
- union
- {
- struct
- {
- } direct;
- struct
- {
- u32 ID;
- } pipe;
- };
+ u32 PipeID;
} typedef link_;
struct
@@ -60,8 +48,6 @@ struct
link_ *Link;
} typedef experiment;
-int FromString_link_type(char const *, link_type *);
-
void Free_endpoint(endpoint *);
void Free_endpoint_configuration(endpoint_configuration *);
void Free_link_configuration(link_configuration *);
@@ -72,7 +58,6 @@ void Free_experiment(experiment *);
char *Parse_endpoint(endpoint *, ucl_object_t const *, char const *Position);
char *Parse_endpoint_configuration(endpoint_configuration *, ucl_object_t const *, char const *Position);
-char *Parse_link_type(link_type *, ucl_object_t const *, char const *Position);
char *Parse_link_configuration(link_configuration *, ucl_object_t const *, char const *Position);
char *Parse_link(link_ *, ucl_object_t const *, char const *Position);
char *Parse_node_configuration(node_configuration *, ucl_object_t const *, char const *Position);