pmlag

Poor man's link aggregation
git clone git://git.finwo.net/app/pmlag
Log | Files | Refs | README | LICENSE

commit 31acd3405868685c99c9406b01849e27406d8ad7
parent 677d25d6c613211f4122d4db880718e05fc9cd08
Author: Robin Bron <robin@finwo.nl>
Date:   Sat, 30 Apr 2022 16:28:23 +0200

Separated config loader from main

Diffstat:
A.github/FUNDING.yml | 3+++
Asrc/config.c | 101+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/config.h | 34++++++++++++++++++++++++++++++++++
Msrc/main.c | 151++++++++++++++-----------------------------------------------------------------
Asrc/main.h | 20++++++++++++++++++++
5 files changed, 185 insertions(+), 124 deletions(-)

diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml @@ -0,0 +1,3 @@ +# f4d2ed80-57b6-46e6-b245-5049428a931d +github: finwo +liberapay: finwo diff --git a/src/config.c b/src/config.c @@ -0,0 +1,101 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "config.h" +#include "ini.h" +#include "main.h" + +static int config_load_handler( + void *user, + const char *section, + const char *name, + const char *value +) { + pmlag_configuration* config = (pmlag_configuration *) user; + + // Get interface being configured + pmlag_interface *iface = config->interfaces; + while(iface) { + if (!strcmp(iface->name, section)) { + break; + } + iface = iface->next; + } + + // Create interface if not found + if (!iface) { + iface = calloc(1, sizeof(pmlag_interface)); + iface->next = config->interfaces; + iface->name = strdup(section); + config->interfaces = iface; + } + + + // Set found value + if (!strcmp("master", name)) { + iface->master = strdup(value); + } else if (!strcmp("weight", name)) { + iface->weight = atoi(value); + } else if (!strcmp("broadcast", name)) { + if (!strcmp("flood", value)) { + iface->broadcast = BROADCAST_FLOOD; + } else if (!strcmp("balanced", value)) { + iface->broadcast = BROADCAST_BALANCED; + } else { + fprintf(stderr, "Unknown broadcast: %s\n", value); + return 0; + } + } else if (!strcmp("mode", name)) { + if (!strcmp("slave", value)) { + iface->mode = MODE_SLAVE; + } else if (!strcmp("active-backup", value)) { + iface->mode = MODE_ACTIVE_BACKUP; + } else if (!strcmp("broadcast", value)) { + iface->mode = MODE_BROADCAST; + } else if (!strcmp("balance-rr", value)) { + iface->mode = MODE_BALANCE_RR; + } else { + fprintf(stderr, "Unknown mode: %s\n", value); + return 0; + } + } else if (!strcmp("mac", name)) { + // TODO: parse mac address + iface->mac = strdup(value); + } else { + return 0; + } + + return 1; +} + +void config_free(pmlag_configuration *config) { + if (!config) return; + pmlag_interface *iface_next; + pmlag_interface *iface = config->interfaces; + while(iface) { + iface_next = iface->next; + if (iface_next == config->interfaces) break; + if (iface->mac ) free(iface->mac); + if (iface->master) free(iface->master); + if (iface->name ) free(iface->name); + free(iface); + iface = iface_next; + } + free(config); +} + +pmlag_configuration * config_load(const char * filename) { + // Load config, entry-by-entry + pmlag_configuration *config = calloc(1, sizeof(pmlag_configuration)); + if (ini_parse(filename, config_load_handler, config) < 0) { + fprintf(stderr, "Can not load %s\n", filename); + return NULL; + } + // Loop interface list + pmlag_interface *iface = config->interfaces; + while (iface && iface->next) iface = iface->next; + if (iface) iface->next = config->interfaces; + // Return produce + return config; +} diff --git a/src/config.h b/src/config.h @@ -0,0 +1,34 @@ +#ifndef __PMLAG_CONFIG_H__ +#define __PMLAG_CONFIG_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + // Linked list + void *next; // Ref to the next interface + // Config + char *name; // Name of the interface + char *master; // Name of the controlling interface + char *mac; // Mac address to set on the interface + int broadcast; // Broadcast mode + int mode; // Balancing mode + int weight; // Weight of the interface + // Activity + int socket; // Socket file descriptor + int remainder; // Round robin remainder +} pmlag_interface; + +typedef struct { + pmlag_interface *interfaces; +} pmlag_configuration; + +void config_free(pmlag_configuration *config); +pmlag_configuration * config_load(const char * filename); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // __PMLAG_CONFIG_H__ diff --git a/src/main.c b/src/main.c @@ -9,7 +9,8 @@ #include <sys/socket.h> #include "argparse.h" -#include "ini.h" +#include "config.h" +#include "main.h" #include "socket.h" #ifdef __cplusplus @@ -20,134 +21,12 @@ extern "C" { #define NAME "pmlag" #endif -#define BROADCAST_FLOOD 1 -#define BROADCAST_BALANCED 2 - -#define MODE_SLAVE 0 -#define MODE_ACTIVE_BACKUP 1 -#define MODE_BROADCAST 2 -#define MODE_BALANCE_RR 3 - static const char *const usage[] = { NAME " [options]", NULL }; -typedef struct { - // Linked list - void *next; // Ref to the next interface - // Config - char *name; // Name of the interface - char *master; // Name of the controlling interface - char *mac; // Mac address to set on the interface - int broadcast; // Broadcast mode - int mode; // Balancing mode - int weight; // Weight of the interface - // Activity - int socket; // Socket file descriptor - int remainder; // Round robin remainder -} pmlag_interface; - -typedef struct { - pmlag_interface *interfaces; -} pmlag_configuration; - -pmlag_configuration *configuration_active = NULL; -pmlag_configuration *configuration_loading = NULL; - -static int config_load_handler( - void *user, - const char *section, - const char *name, - const char *value -) { - pmlag_configuration* config = (pmlag_configuration *) user; - - // Get interface being configured - pmlag_interface *iface = config->interfaces; - while(iface) { - if (!strcmp(iface->name, section)) { - break; - } - iface = iface->next; - } - - // Create interface if not found - if (!iface) { - iface = calloc(1, sizeof(pmlag_interface)); - iface->next = config->interfaces; - iface->name = strdup(section); - config->interfaces = iface; - } - - - // Set found value - if (!strcmp("master", name)) { - iface->master = strdup(value); - } else if (!strcmp("weight", name)) { - iface->weight = atoi(value); - } else if (!strcmp("broadcast", name)) { - if (!strcmp("flood", value)) { - iface->broadcast = BROADCAST_FLOOD; - } else if (!strcmp("balanced", value)) { - iface->broadcast = BROADCAST_BALANCED; - } else { - fprintf(stderr, "Unknown broadcast: %s\n", value); - return 0; - } - } else if (!strcmp("mode", name)) { - if (!strcmp("slave", value)) { - iface->mode = MODE_SLAVE; - } else if (!strcmp("active-backup", value)) { - iface->mode = MODE_ACTIVE_BACKUP; - } else if (!strcmp("broadcast", value)) { - iface->mode = MODE_BROADCAST; - } else if (!strcmp("balance-rr", value)) { - iface->mode = MODE_BALANCE_RR; - } else { - fprintf(stderr, "Unknown mode: %s\n", value); - return 0; - } - } else if (!strcmp("mac", name)) { - // TODO: parse mac address - iface->mac = strdup(value); - } else { - return 0; - } - - return 1; -} - -void config_free(pmlag_configuration *config) { - if (!config) return; - pmlag_interface *iface_next; - pmlag_interface *iface = config->interfaces; - while(iface) { - iface_next = iface->next; - if (iface_next == config->interfaces) break; - if (iface->mac ) free(iface->mac); - if (iface->master) free(iface->master); - if (iface->name ) free(iface->name); - free(iface); - iface = iface_next; - } - free(config); -} - -pmlag_configuration * config_load(const char * filename) { - // Load config, entry-by-entry - pmlag_configuration *config = calloc(1, sizeof(pmlag_configuration)); - if (ini_parse(filename, config_load_handler, config) < 0) { - fprintf(stderr, "Can not load %s\n", filename); - return NULL; - } - // Loop interface list - pmlag_interface *iface = config->interfaces; - while (iface && iface->next) iface = iface->next; - if (iface) iface->next = config->interfaces; - // Return produce - return config; -} +pmlag_configuration *config = NULL; int main(int argc, const char **argv) { const char *config_file = "/etc/" NAME ".conf"; @@ -179,6 +58,30 @@ int main(int argc, const char **argv) { return 1; } + // DEBUG: Show loaded configuration + fprintf(stderr, "Loaded configuration:\n"); + pmlag_interface *iface = loaded->interfaces; + while(iface) { + fprintf(stderr, " Interface: %s\n", iface->name); + fprintf(stderr, " master : %s\n", iface->master ? iface->master : ""); + fprintf(stderr, " mac : %s\n", iface->mac ? iface->mac : ""); + fprintf(stderr, " broadcast: %s%s\n", + iface->broadcast == BROADCAST_FLOOD ? "flood" : "", + iface->broadcast == BROADCAST_BALANCED ? "balanced" : "" + ); + fprintf(stderr, " mode : %s%s%s%s\n", + iface->mode == MODE_SLAVE ? "slave" : "", + iface->mode == MODE_ACTIVE_BACKUP ? "active-backup" : "", + iface->mode == MODE_BROADCAST ? "broadcast" : "", + iface->mode == MODE_BALANCE_RR ? "balance-rr" : "" + ); + fprintf(stderr, " weight : %d\n", iface->weight); + iface = iface->next; + if (iface == loaded->interfaces) break; + } + + + // TODO: // - start thread for every interface // - let thread create bond diff --git a/src/main.h b/src/main.h @@ -0,0 +1,20 @@ +#ifndef __PMLAG_MAIN_H__ +#define __PMLAG_MAIN_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#define BROADCAST_FLOOD 1 +#define BROADCAST_BALANCED 2 + +#define MODE_SLAVE 0 +#define MODE_ACTIVE_BACKUP 1 +#define MODE_BROADCAST 2 +#define MODE_BALANCE_RR 3 + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // __PMLAG_MAIN_H__