commit 8293eaaab5b71f4acc6d13028868308c7ceab2bd
parent e6e4fe3bfec1f4d5793bca8670f9e18cbf6cf231
Author: Yersa Nordman <yersa@finwo.nl>
Date: Sun, 8 Oct 2023 21:05:03 +0200
Code, basic config loading working again
Diffstat:
17 files changed, 84 insertions(+), 865 deletions(-)
diff --git a/Makefile b/Makefile
@@ -35,41 +35,13 @@ build/${TARGET}: $(wildcard src/*.c src/*.h src/*/*.c src/*/*.h)
cp -rT arch/${TARGET}/ build/${TARGET}
cp -rT arch/${TARGET}/ build/${TARGET}
-build/${TARGET}/pmlag: build/${TARGET}
+build/${TARGET}/pmlag: build/${TARGET} $(wildcard build/${TARGET}/src/*.c build/${TARGET}/src/*.h build/${TARGET}/src/*/*.c build/${TARGET}/src/*/*.h)
cd build/${TARGET} && dep install
$(MAKE) --directory build/${TARGET} TARGET=${TARGET}
build/${TARGET}/pmlag-${SVC}-${TARGET}.tar.gz: build/${TARGET}/pmlag
$(MAKE) --directory build/${TARGET} TARGET=${TARGET} SVC=${SVC} pmlag-${SVC}-${TARGET}.tar.gz
-# include Makefile.pkg
-
-# %.o: %.c $(LIBS)
-# $(CC) $(CFLAGS) $(@:.o=.c) -D__NAME=\"$(BIN)\" -c -o $@
-
-# $(BIN): $(OBJ)
-# $(CC) $(CFLAGS) $(OBJ) --static -o $@
-
-# # Build manpage
-# $(BIN).1: manpage.1.md
-# env NAME=$(BIN) envsubst < manpage.1.md | pandoc --standalone --from markdown --to man -o $(BIN).1
-# env NAME=$(BIN) envsubst < manpage.1.md | pandoc --standalone --from markdown --to html -o $(BIN).html
-
-# package: default
-# rm -rf package
-
-
-# ### openwrt-amd64 ###
-# mkdir -p package/pmlag-openwrt-amd64/etc
-# mkdir -p package/pmlag-openwrt-amd64/etc/init.d
-# mkdir -p package/pmlag-openwrt-amd64/usr/bin
-# mkdir -p package/pmlag-openwrt-amd64/usr/share/man/man1
-# cp pmlag package/pmlag-openwrt-amd64/usr/bin/pmlag
-# cp pmlag.1 package/pmlag-openwrt-amd64/usr/share/man/man1/pmlag.1
-# cp service/procd/etc/init.d/pmlag package/pmlag-openwrt-amd64/etc/init.d/pmlag
-# cp service/common/etc/pmlag.ini package/pmlag-openwrt-amd64/etc/pmlag.ini
-# (cd package ; tar c pmlag-openwrt-amd64 | gzip -9 > pmlag-openwrt-amd64.tar.gz)
-
.PHONY: clean
clean:
rm -rf build
diff --git a/arch/common/Makefile b/arch/common/Makefile
@@ -38,23 +38,3 @@ $(BIN).1: manpage.1.md
${BIN}-${SVC}-${TARGET}.tar.gz: $(BIN)
package/${SVC}/build.sh
-
-# package: default
-# rm -rf package
-# ### linux-amd64 ###
-# mkdir -p package/pmlag-linux-amd64
-# cp pmlag package/pmlag-linux-amd64/pmlag
-# cp pmlag.1 package/pmlag-linux-amd64/pmlag.1
-# cp -r service package/pmlag-linux-amd64/service
-# cp Makefile.pkg package/pmlag-linux-amd64/Makefile
-# (cd package ; tar c pmlag-linux-amd64 | gzip -9 > pmlag-linux-amd64.tar.gz)
-# ### openwrt-amd64 ###
-# mkdir -p package/pmlag-openwrt-amd64/etc
-# mkdir -p package/pmlag-openwrt-amd64/etc/init.d
-# mkdir -p package/pmlag-openwrt-amd64/usr/bin
-# mkdir -p package/pmlag-openwrt-amd64/usr/share/man/man1
-# cp pmlag package/pmlag-openwrt-amd64/usr/bin/pmlag
-# cp pmlag.1 package/pmlag-openwrt-amd64/usr/share/man/man1/pmlag.1
-# cp service/procd/etc/init.d/pmlag package/pmlag-openwrt-amd64/etc/init.d/pmlag
-# cp service/common/etc/pmlag.ini package/pmlag-openwrt-amd64/etc/pmlag.ini
-# (cd package ; tar c pmlag-openwrt-amd64 | gzip -9 > pmlag-openwrt-amd64.tar.gz)
diff --git a/src/main.c b/src/main.c
@@ -1,24 +1,9 @@
-// vim: fdm=marker
-
-#include <arpa/inet.h>
-#include <errno.h>
-#include <linux/if_ether.h>
-#include <linux/if_packet.h>
-#include <net/if.h>
-#include <netinet/in.h>
-#include <netinet/ip.h>
-#include <pthread.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/ioctl.h>
-#include <sys/socket.h>
#include <stdio.h>
-#include <unistd.h>
+#include <stdlib.h>
#include "cofyc/argparse.h"
-#include "util/config.h"
-#include "task/bond.h"
+#include "util/config.h"
static const char *const usage[] = {
__NAME " [options]",
@@ -54,30 +39,20 @@ int main(int argc, const char **argv) {
argc = argparse_parse(&argparse, argc, argv);
// Load configuration file
- struct pmlag_configuration *config = config_load(config_file);
+ struct pmlag_configuration *config = config_load(config_file, NULL);
if (!config) {
return 1;
}
- // Initialize interfaces for all configured bonds
- struct pmlag_bond *bond = config->bonds;
- while(bond) {
-
- // Start the bond's thread
- if(pthread_create(&(bond->tid_bond), NULL, task_bond_thread, bond)) {
- perror("Starting bond thread");
- return 1;
+ // Display bonds
+ int b = 0;
+ int i = 0;
+ for( b = 0 ; b < config->bond_count ; b++ ) {
+ printf("%s\n", config->bond[b]->name);
+ for( i = 0 ; i < config->bond[b]->iface_count ; i++ ) {
+ printf(" - %s\n", config->bond[b]->iface[i]->name);
}
-
- bond = bond->next;
- }
-
- // Wait for all bonds to finish
- bond = config->bonds;
- while(bond) {
- pthread_join(bond->tid_bond, NULL);
- bond = bond->next;
}
- return 0;
+ return 69;
}
diff --git a/src/task/announce.c b/src/task/announce.c
@@ -1,62 +0,0 @@
-#include <linux/if_ether.h>
-#include <linux/if_packet.h>
-#include <netinet/in.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "../util/config.h"
-#include "../util/socket.h"
-#include "announce.h"
-
-void * task_announce_thread(void *arg) {
- struct pmlag_bond *bond = arg;
- struct sockaddr_ll saddr_ll;
- saddr_ll.sll_halen = ETH_ALEN;
- pmlag_iface_llist *iface_entry;
-
- uint16_t ethtype = htons(0x0666);
- size_t buflen = (ETH_ALEN*2) + sizeof(ethtype) + 46;
- size_t sendlen;
-
- unsigned char *mac = iface_mac(bond->name);
- unsigned char *buffer = calloc(1, buflen);
-
- // Prepare saddr_ll and buffer
- memcpy(saddr_ll.sll_addr, mac, ETH_ALEN);
- memset(buffer, 0xFF, ETH_ALEN); // Destination = Broadcast
- memcpy(buffer+ETH_ALEN, mac, ETH_ALEN); // Source = bond
- memcpy(buffer+(ETH_ALEN*2), ðtype, sizeof(uint16_t)); // EtherType = 0x0666 = custom
-
- int16_t bcidx = htons(rand() | 1);
-
- while(1) {
- sleep(1);
- iface_entry = bond->interfaces;
-
- // Increment bcidx
- bcidx = ntohs(bcidx);
- bcidx++;
- if (!bcidx) bcidx = 1;
- bcidx = htons(bcidx);
-
- // Store bcidx on buffer
- memcpy(buffer + (ETH_ALEN*2) + sizeof(uint16_t), &bcidx, sizeof(int16_t));
-
- // Send the buffer as-is over all ifaces
- while(iface_entry) {
- if (iface_entry->data->sockfd) {
- saddr_ll.sll_ifindex = iface_entry->data->ifidx;
- sendlen = sendto(iface_entry->data->sockfd, buffer, buflen, 0, (const struct sockaddr*)&saddr_ll, sizeof(struct sockaddr_ll));
- if (sendlen < 0) {
- perror("SENDTO");
- }
- }
- iface_entry = iface_entry->next;
- }
- }
-
- return NULL;
-}
diff --git a/src/task/announce.h b/src/task/announce.h
@@ -1,6 +0,0 @@
-#ifndef __PMLAG_TASK_ANNOUNCE_H__
-#define __PMLAG_TASK_ANNOUNCE_H__
-
-void * task_announce_thread(void *arg);
-
-#endif // __PMLAG_TASK_ANNOUNCE_H__
diff --git a/src/task/bond.c b/src/task/bond.c
@@ -1,146 +0,0 @@
-#include <linux/if_ether.h>
-#include <linux/if_packet.h>
-#include <pthread.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <sys/socket.h>
-#include <unistd.h>
-
-#include "finwo/mindex.h"
-#include "../util/config.h"
-#include "../util/routing-table.h"
-#include "../util/socket.h"
-
-#include "announce.h"
-#include "iface.h"
-
-int task_bond_onpacket(struct pmlag_bond *bond, unsigned char *buffer, size_t buflen) {
-
-#ifdef DEBUG
- // Debug: print eth header
- printf("%.2x:%.2x:%.2x:%.2x:%.2x:%.2x > %.2x:%.2x:%.2x:%.2x:%.2x:%.2x, %.4x (%ld)\n",
- buffer[6],buffer[7],buffer[8],buffer[9],buffer[10],buffer[11], // SRC
- buffer[0],buffer[1],buffer[2],buffer[3],buffer[ 4],buffer[ 5], // DST
- ((unsigned int)((unsigned char)buffer[12]) << 8) + buffer[13], // PROTO
- buflen
- );
-#endif // DEBUG
-
- // Get interface to send the packet from
- struct pmlag_iface *iface = (memcmp(buffer, "\xFF\xFF\xFF\xFF\xFF\xFF", ETH_ALEN) == 0)
- ? NULL
- : rt_find(bond->rt, &(bond->mtx_rt), buffer);
- pmlag_iface_llist *iface_entry;
- size_t send_len;
-
-#ifdef DEBUG
- printf(" got iface? %s\n", iface ? "yes" : "no");
-#endif
-
- // Broadcast on ALL interfaces if no rt entry OR broadcast packet
- if (!iface) {
- iface_entry = bond->interfaces;
- while(iface_entry) {
- send_len = sendto(iface_entry->data->sockfd, buffer, buflen, 0, NULL, 0);
- if(send_len != buflen) {
- perror("sendto");
- return 1;
- }
- iface_entry = iface_entry->next;
- }
- return 0;
- }
-
- // Forward packet to iface as-is
- send_len = sendto(iface->sockfd, buffer, buflen, 0, NULL, 0);
- if(send_len != buflen) {
- perror("sendto");
- return 1;
- }
-
- return 0;
-}
-
-// Responsible for init + calling task_bond_onpacket
-void * task_bond_thread(void *arg) {
- struct pmlag_bond *bond = arg;
-
- // Initialize routing table lock
- if (pthread_mutex_init(&(bond->mtx_rt), NULL) != 0) {
- perror("Initializing mutex for bond");
- pthread_exit(NULL);
- return NULL;
- }
-
- // Initialize routing table
- bond->rt = rt_init(bond);
-
- // Assign bond interface
- bond->sockfd = tap_alloc(bond->name, bond->hwaddr);
- if (bond->sockfd < 0) {
- perror("Allocating bond interface");
- pthread_exit(NULL);
- return NULL;
- };
-
- // Lock this bond's routing table
- pthread_mutex_lock(&(bond->mtx_rt));
-
- // Start thread for each interface of this bond
- pmlag_iface_llist *iface_entry = bond->interfaces;
- while(iface_entry) {
- if(pthread_create(&(iface_entry->data->tid), NULL, task_iface_thread, iface_entry->data)) {
- perror("Starting iface thread");
- pthread_exit((void*)1);
- return (void*)1;
- }
- iface_entry = iface_entry->next;
- }
-
- // Start an announcement thread
- if(pthread_create(&(bond->tid_announce), NULL, task_announce_thread, bond)) {
- perror("Starting announce thread");
- pthread_exit((void*)1);
- return (void*)1;
- }
-
- // Free this bond's routing table
- pthread_mutex_unlock(&(bond->mtx_rt));
-
- // Predefine things we'll re-use
- size_t buflen;
- unsigned char *buffer = (unsigned char *) malloc(RCVBUFSIZ);
-
- // TODO: replace by waiting for the iface to finish initializing
- sleep(1);
-
- // This is our life now
- while(1) {
-
- // Wait for a packet to arrive
- buflen = read(bond->sockfd, buffer, RCVBUFSIZ);
- if (buflen < 0) {
- perror("read(bond)");
- pthread_exit(NULL);
- return NULL;
- }
-
- // And let the more specific method handle the packet
- if(task_bond_onpacket(bond, buffer, buflen)) {
- pthread_exit(NULL);
- return NULL;
- }
-
- }
-
- // Wait for iface threads to finish
- iface_entry = bond->interfaces;
- while(iface_entry) {
- pthread_join(iface_entry->data->tid, NULL);
- iface_entry = iface_entry->next;
- }
-
- pthread_exit(NULL);
- return NULL;
-}
diff --git a/src/task/bond.h b/src/task/bond.h
@@ -1,7 +0,0 @@
-#ifndef __PMLAG_TASK_BOND_H__
-#define __PMLAG_TASK_BOND_H__
-
-void * task_bond_thread(void *arg);
-
-#endif // __PMLAG_TASK_BOND_H__
-
diff --git a/src/task/iface.c b/src/task/iface.c
@@ -1,96 +0,0 @@
-#include <linux/if_ether.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/socket.h>
-#include <unistd.h>
-
-#include "../util/config.h"
-#include "../util/routing-table.h"
-#include "../util/socket.h"
-
-int task_iface_onpacket(struct pmlag_iface *iface, unsigned char *buffer, size_t buflen) {
- size_t send_len;
- uint16_t proto;
- int16_t bcidx;
-
-#ifdef DEBUG
- // Debug: print eth header
- printf("%.2x:%.2x:%.2x:%.2x:%.2x:%.2x < %.2x:%.2x:%.2x:%.2x:%.2x:%.2x, %.4x (%ld)\n",
- buffer[0],buffer[1],buffer[2],buffer[3],buffer[ 4],buffer[ 5], // DST
- buffer[6],buffer[7],buffer[8],buffer[9],buffer[10],buffer[11], // SRC
- ((unsigned int)((unsigned char)buffer[12]) << 8) + buffer[13], // PROTO
- buflen
- );
-#endif // DEBUG
-
- // Update the routing table as-needed
- proto = ((uint16_t)((unsigned char)buffer[(ETH_ALEN*2)+0]) << 8) + buffer[(ETH_ALEN*2)+1];
- bcidx = 0;
- if (proto == 0x0666) {
- bcidx = ((int16_t)((unsigned char)buffer[(ETH_ALEN*2)+2]) << 8) + buffer[(ETH_ALEN*2)+3];
- }
- rt_upsert(
- iface->bond->rt,
- &(iface->bond->mtx_rt),
- iface,
- buffer+ETH_ALEN,
- bcidx
- );
- if (proto == 0x0666) {
- return 0;
- }
-
- // Redirect packet to bond socket as-is
- send_len = write(iface->bond->sockfd, buffer, buflen);
- if (buflen != send_len) {
- perror("write(bond)");
- return 1;
- }
-
- return 0;
-}
-
-void * task_iface_thread(void *arg) {
- struct pmlag_iface *iface = arg;
-
- // Open socket for the interface in the bond
- iface->sockfd = sockraw_open(iface->name);
- if (iface->sockfd < 0) {
- pthread_exit(NULL);
- return NULL;
- }
-
- // Get the interface's idx on the socket
- iface->ifidx = iface_idx(iface->sockfd, iface->name);
-
- // Reserve receive buffer, support 64k packets just in case
- size_t buflen;
- unsigned char *buffer = (unsigned char *) malloc(RCVBUFSIZ);
-
- // Wait for the bond thread to finish initializing
- pthread_mutex_lock(&(iface->bond->mtx_rt));
- pthread_mutex_unlock(&(iface->bond->mtx_rt));
-
- printf("Thread started for iface %s\n", iface->name);
-
- // This is our life now
- while(1) {
-
- // Zero out buffer, to prevent pollution, & receive packet
- buflen = recvfrom(iface->sockfd, buffer, RCVBUFSIZ, 0, NULL, 0);
- if (buflen < 0) {
- perror("recvfrom");
- pthread_exit(NULL);
- return NULL;
- }
-
- // And let the more specific method handle the packet
- if(task_iface_onpacket(iface, buffer, buflen)) {
- pthread_exit(NULL);
- return NULL;
- }
- }
-
- return NULL;
-}
diff --git a/src/task/iface.h b/src/task/iface.h
@@ -1,7 +0,0 @@
-#ifndef __PMLAG_TASK_IFACE_H__
-#define __PMLAG_TASK_IFACE_H__
-
-void * task_iface_thread(void *arg);
-
-#endif // __PMLAG_TASK_IFACE_H__
-
diff --git a/src/util/config.c b/src/util/config.c
@@ -1,11 +1,10 @@
-#include <linux/if_ether.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "benhoyt/inih.h"
+
#include "config.h"
-#include "socket.h"
static int config_load_handler(
void *user,
@@ -13,85 +12,79 @@ static int config_load_handler(
const char *name,
const char *value
) {
+ struct pmlag_bond *bond = NULL;
+ struct pmlag_iface *iface = NULL;
+ int bond_idx = 0;
+ int iface_idx = 0;
struct pmlag_configuration* config = (struct pmlag_configuration *) user;
+ printf("[%s].%s: %s\n", section, name, value);
+
+ // Ensure we have a bond list
+ if (!config->bond) config->bond = calloc(1, sizeof(void*));
- // Get bond being configured
- struct pmlag_bond *bond = config->bonds;
- while(bond) {
- if (!strcmp(bond->name, section)) {
+ // Find the bond being configured
+ for( bond_idx = 0 ; bond_idx < config->bond_count ; bond_idx ++ ) {
+ if (!strcmp(config->bond[bond_idx]->name, section)) {
+ bond = config->bond[bond_idx];
break;
}
- bond = bond->next;
}
// Create bond if not found
if (!bond) {
- bond = calloc(1, sizeof(struct pmlag_bond));
- bond->next = config->bonds;
- bond->name = strdup(section);
- config->bonds = bond;
+ config->bond[config->bond_count++] = bond = calloc(1, sizeof(struct pmlag_bond));
+ config->bond = realloc(config->bond, (config->bond_count + 1) * sizeof(void*));
+ config->bond[config->bond_count ] = NULL;
+ bond->name = strdup(section);
}
- // Get interface being configured
- pmlag_iface_llist *iface_entry = bond->interfaces;
-
if (0) {
// Intentionally empty
- } else if (!strcmp(name, "mode")) {
- // Set the mode according to found value
- if (0) {
- // Intentionally empty
- } else if (!strcmp(value, "active-backup")) {
- bond->mode = PMLAG_MODE_ACTIVE_BACKUP;
- } else if (!strcmp(value, "balanced-rr")) {
- bond->mode = PMLAG_MODE_BALANCED_RR;
- } else if (!strcmp(value, "broadcast")) {
- bond->mode = PMLAG_MODE_BROADCAST;
- } else {
- return 0;
- }
} else if (!strcmp(name, "interface")) {
- // Select the right interface
- while(iface_entry) {
- if (!strcmp(iface_entry->data->name, value)) {
+ // Ensure we have an iface list
+ if (!bond->iface) bond->iface = calloc(1, sizeof(void*));
+
+ // Find the interface you're referencing
+ for( iface_idx = 0 ; iface_idx < bond->iface_count ; iface_idx ++ ) {
+ if (!strcmp(config->bond[bond_idx]->iface[iface_idx]->name, value)) {
+ iface = config->bond[bond_idx]->iface[iface_idx];
break;
}
- iface_entry = iface_entry->next;
}
- // Create iface if not found
- if (!iface_entry) {
- // Create the list entry
- iface_entry = calloc(1, sizeof(pmlag_iface_llist));
- iface_entry->next = bond->interfaces;
- bond->interfaces = iface_entry;
- // Create the iface
- iface_entry->data = calloc(1, sizeof(struct pmlag_iface));
- iface_entry->data->name = strdup(value);
- iface_entry->data->bond = bond;
- bond->iface_cnt++;
+ // Create bond if not found
+ if (!iface) {
+ bond->iface[bond->iface_count++] = iface = calloc(1, sizeof(struct pmlag_iface));
+ bond->iface = realloc(bond->iface, (bond->iface_count + 1) * sizeof(void*));
+ bond->iface[bond->iface_count ] = NULL;
+ iface->name = strdup(value);
}
} else if (!strcmp(name, "hwaddr")) {
- // Find iface with name == value
- iface_entry = bond->interfaces;
- while(iface_entry) {
- if (!strcmp(iface_entry->data->name, value)) break;
- iface_entry = iface_entry->next;
+ // Find the interface you're referencing
+ for( iface_idx = 0 ; iface_idx < bond->iface_count ; iface_idx ++ ) {
+ if (!strcmp(config->bond[bond_idx]->iface[iface_idx]->name, value)) {
+ iface = config->bond[bond_idx]->iface[iface_idx];
+ break;
+ }
}
- if (iface_entry) {
+ if (iface) {
// Got interface by that name = use it's hwaddr
- bond->hwaddr = iface_mac(iface_entry->data->name);
+ if (bond->hwaddr) free(bond->hwaddr);
+ bond->hwaddr = NULL;
+ /* bond->hwaddr = iface_mac(iface_entry->data->name); */
+ printf("TODO: get mac from %s\n", iface->name);
} else if (!strcmp(value, "random")) {
// "random" = null, a.k.a. let the kernel generate a random mac
if (bond->hwaddr) free(bond->hwaddr);
bond->hwaddr = NULL;
} else {
// xx:xx:xx:xx:xx:xx
+ if (bond->hwaddr) free(bond->hwaddr);
bond->hwaddr = (unsigned char *)malloc(6); // ETH_ALEN should be 6, but this is safer
sscanf(value, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
&(bond->hwaddr[0]),
@@ -102,21 +95,18 @@ static int config_load_handler(
&(bond->hwaddr[5])
);
}
-
- } else {
- // Unknown key
- return 0;
}
return 1;
}
-struct pmlag_configuration * config_load(const char * filename) {
+struct pmlag_configuration * config_load(char * filepath, struct pmlag_configuration *config) {
// Load config, entry-by-entry
- struct pmlag_configuration *config = calloc(1, sizeof(struct pmlag_configuration));
- if (ini_parse(filename, config_load_handler, config) < 0) {
- fprintf(stderr, "Can not load %s\n", filename);
+ if (!config) config = calloc(1, sizeof(struct pmlag_configuration));
+ if (ini_parse(filepath, config_load_handler, config) < 0) {
+ fprintf(stderr, "Can not load %s\n", filepath);
return NULL;
}
return config;
}
+
diff --git a/src/util/config.h b/src/util/config.h
@@ -1,61 +1,36 @@
-#ifndef __PMLAG_CONFIG_H__
-#define __PMLAG_CONFIG_H__
-
-#include <pthread.h>
-#include <stdint.h>
-
-#include "finwo/mindex.h"
-
-#include "linked-list.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define PMLAG_MODE_NONE 0
-#define PMLAG_MODE_ACTIVE_BACKUP 1
-#define PMLAG_MODE_BROADCAST 2
-#define PMLAG_MODE_BALANCED_RR 3
-
-#define RCVBUFSIZ 65536
-
-#ifndef RT_MAX_ENTRIES
-#define RT_MAX_ENTRIES 64
-#endif
-
-typedef LLIST(struct pmlag_iface) pmlag_iface_llist;
+#ifndef __PMLAG_UTIL_CONFIG_H__
+#define __PMLAG_UTIL_CONFIG_H__
struct pmlag_iface {
- char *name; // name of the interface this object represents
- /* int weight; // weight of this interface within the bond */
- int sockfd; // file descriptor for the iface raw socket
- int ifidx; // index of the interface within the socket
- pthread_t tid; // thread id where the iface listener recides in
- struct pmlag_bond *bond; // reference to the bond this iface belongs to
+ char *name;
+ /* /1* int weight; // weight of this interface within the bond *1/ */
+ /* int sockfd; // file descriptor for the iface raw socket */
+ /* int ifidx; // index of the interface within the socket */
+ /* pthread_t tid; // thread id where the iface listener recides in */
+ /* struct pmlag_bond *bond; // reference to the bond this iface belongs to */
};
struct pmlag_bond {
- void *next; // linked-list next reference
- char *name; // name of the bond interface
- int mode; // which mode to run pmlag in for this bond
- int sockfd; // file descriptor for the bond socket interface
+ char *name;
+ struct pmlag_iface **iface;
+ int iface_count;
unsigned char *hwaddr; // hwaddr to use for the interface (null = random)
- pthread_t tid_bond; // thread id where the bond interface listener recides in
- pthread_t tid_announce; // thread id that'll output announces for the bond
- pthread_mutex_t mtx_rt; // lock for the routing table of the bond
- struct mindex_t *rt; // pointer to the routing table
- pmlag_iface_llist *interfaces; // linked-list of interfaces contained in the bond
- int iface_cnt; // track the number of interfaces in this bond
+
+/* int mode; // which mode to run pmlag in for this bond */
+/* int sockfd; // file descriptor for the bond socket interface */
+/* pthread_t tid_bond; // thread id where the bond interface listener recides in */
+/* pthread_t tid_announce; // thread id that'll output announces for the bond */
+/* pthread_mutex_t mtx_rt; // lock for the routing table of the bond */
+/* struct mindex_t *rt; // pointer to the routing table */
+/* pmlag_iface_llist *interfaces; // linked-list of interfaces contained in the bond */
+/* int iface_cnt; // track the number of interfaces in this bond */
};
struct pmlag_configuration {
- struct pmlag_bond *bonds;
+ struct pmlag_bond **bond;
+ int bond_count;
};
-struct pmlag_configuration * config_load(const char * filename);
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
+struct pmlag_configuration * config_load(char * filepath, struct pmlag_configuration *config);
-#endif // __PMLAG_CONFIG_H__
+#endif // __PMLAG_UTIL_CONFIG_H__
diff --git a/src/util/linked-list.h b/src/util/linked-list.h
@@ -1,6 +0,0 @@
-#ifndef __PMLAG_UTIL_LL_H__
-#define __PMLAG_UTIL_LL_H__
-
-#define LLIST(x) struct { void *next; x *data; }
-
-#endif // __PMLAG_UTIL_LL_H__
diff --git a/src/util/routing-table.c b/src/util/routing-table.c
@@ -1,135 +0,0 @@
-#include <linux/if_ether.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "config.h"
-#include "finwo/mindex.h"
-#include "routing-table.h"
-
-static int rt_compare(const void *a, const void *b, void *udata) {
- struct pmlag_rt_entry *ta = (struct pmlag_rt_entry *)a;
- struct pmlag_rt_entry *tb = (struct pmlag_rt_entry *)b;
- int result;
-
- // Same pointer = match
- if (a == b) return 0;
-
- // Check for ETH_ALEN, unrolled memcmp
- if (( result = ((int)ta->mac[0] - (int)tb->mac[0]) )) return result;
- if (( result = ((int)ta->mac[1] - (int)tb->mac[1]) )) return result;
- if (( result = ((int)ta->mac[2] - (int)tb->mac[2]) )) return result;
- if (( result = ((int)ta->mac[3] - (int)tb->mac[3]) )) return result;
- if (( result = ((int)ta->mac[4] - (int)tb->mac[4]) )) return result;
- return (int)ta->mac[5] - (int)tb->mac[5];
-}
-
-static void rt_purge(const void *item, void *udata) {
- struct pmlag_rt_entry *rt_entry = (struct pmlag_rt_entry *)item;
- free(rt_entry->interfaces);
- free(rt_entry->mac);
- free(rt_entry);
-}
-
-struct mindex_t * rt_init(void *udata) {
- return mindex_init(rt_compare, rt_purge, udata);
-}
-
-int rt_upsert(
- struct mindex_t *rt,
- pthread_mutex_t *mtx,
- struct pmlag_iface *iface,
- unsigned char *mac,
- int16_t bcidx
-) {
- int isnew = 0;
- struct pmlag_rt_entry *rt_entry;
-
- // Lock the routing table
- pthread_mutex_lock(mtx);
-
- // Attempt to fetch the rt entry
- rt_entry = mindex_get(rt, &((struct pmlag_rt_entry){ .mac = mac }));
-
- // None given, build new one
- if (!rt_entry) {
- rt_entry = calloc(1, sizeof(struct pmlag_rt_entry));
- rt_entry->mac = malloc(ETH_ALEN);
- rt_entry->bcidx = 0;
- rt_entry->interfaces = calloc(iface->bond->iface_cnt, sizeof(struct pmlag_iface *));
- memcpy(rt_entry->mac, mac, ETH_ALEN);
- isnew = 1;
- }
-
- // Bail if
- if (
- (!bcidx && rt_entry->bcidx) || // We receive a regular packet on bcidx-tracked entry
- (rt_entry->bcidx && ((bcidx - rt_entry->bcidx) < 0)) // Or the received bcidx is lower than known (old packet)
- ) {
- if (isnew) {
- rt_purge(rt_entry, NULL);
- }
- pthread_mutex_unlock(mtx);
- return 0;
- }
-
- // Clear list of known interfaces if
- if (
- (bcidx && (rt_entry->bcidx != bcidx)) || // We got a NEW broadcast index
- (!bcidx && (rt_entry->bcidx == 0)) // Or we're updating a non-pmlag remote
- ) {
- rt_entry->iface_cnt = 0;
- }
-
- // Update the rt_entry's broadcast index
- rt_entry->bcidx = bcidx;
-
- // Bail if rt_entry->iface_cnt+1 lg bond->iface_cnt
- if ((rt_entry->iface_cnt + 1) > iface->bond->iface_cnt) {
- if (isnew) {
- rt_purge(rt_entry, NULL);
- }
- pthread_mutex_unlock(mtx);
- return 0;
- }
-
- // Add our iface to the entry's interface list
- rt_entry->interfaces[rt_entry->iface_cnt] = iface;
- rt_entry->iface_cnt++;
-
- // Ensure the entry is in the rt
- if (isnew) {
- mindex_set(rt, rt_entry);
- }
-
- if (mindex_length(rt) > RT_MAX_ENTRIES) {
- rt_entry = mindex_rand(rt);
- if (rt_entry) {
- mindex_delete(rt, rt_entry);
- }
- }
-
- pthread_mutex_unlock(mtx);
- return 0;
-}
-
-struct pmlag_iface * rt_find(
- struct mindex_t *rt,
- pthread_mutex_t *mtx,
- unsigned char *mac
-) {
- struct pmlag_rt_entry *rt_entry;
-
- // Attempt to fetch the rt entry
- pthread_mutex_lock(mtx);
- rt_entry = mindex_get(rt, &((struct pmlag_rt_entry){ .mac = mac }));
- if (!rt_entry) {
- pthread_mutex_unlock(mtx);
- return NULL;
- }
-
- // Unlock the routing table again
- struct pmlag_iface *iface = rt_entry->interfaces[rand() % rt_entry->iface_cnt];
- pthread_mutex_unlock(mtx);
- return iface;
-}
diff --git a/src/util/routing-table.h b/src/util/routing-table.h
@@ -1,31 +0,0 @@
-#ifndef __PMLAG_UTIL_RT_H__
-#define __PMLAG_UTIL_RT_H__
-
-#include "config.h"
-
-#include "finwo/mindex.h"
-
-struct pmlag_rt_entry {
- unsigned char *mac; // mac address of the remote entity
- int16_t bcidx; // broadcast index last seen from the mac
- int16_t iface_cnt; // amount of interfaces this mac is available on
- struct pmlag_iface **interfaces; // list of pointers to interfaces
-};
-
-struct mindex_t * rt_init(void *udata);
-
-int rt_upsert(
- struct mindex_t *rt,
- pthread_mutex_t *mtx,
- struct pmlag_iface *iface,
- unsigned char *mac,
- int16_t bcidx
-);
-
-struct pmlag_iface * rt_find(
- struct mindex_t *rt,
- pthread_mutex_t *mtx,
- unsigned char *mac
-);
-
-#endif // __PMLAG_UTIL_RT_H__
diff --git a/src/util/socket.c b/src/util/socket.c
@@ -1,161 +0,0 @@
-#include <fcntl.h>
-#include <linux/if_arp.h>
-#include <linux/if_packet.h>
-#include <linux/if_tun.h>
-#include <linux/if.h>
-#include <netinet/in.h>
-#include <string.h>
-#include <strings.h>
-#include <sys/ioctl.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/socket.h>
-#include <unistd.h>
-
-#include "socket.h"
-
-unsigned char * iface_mac(char * ifname) {
- struct ifreq ifr;
- unsigned char *mac = calloc(1, ETH_ALEN);
- int sockfd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
- ifr.ifr_addr.sa_family = AF_PACKET;
- strncpy(ifr.ifr_name , ifname , IFNAMSIZ-1);
- ioctl(sockfd, SIOCGIFHWADDR, &ifr);
- close(sockfd);
- memcpy(mac, ifr.ifr_hwaddr.sa_data, ETH_ALEN);
- return mac;
-}
-
-int iface_idx(int sockfd, char * ifname) {
- struct ifreq ifr;
- bzero(&ifr, sizeof(ifr));
-
- // Get interface index
- strncpy((char *)ifr.ifr_name, ifname, IFNAMSIZ);
- if ((ioctl(sockfd, SIOCGIFINDEX, &ifr)) == -1) {
- fprintf(stderr, "Error getting interface index for %s\n", ifname);
- perror("Error getting interface index");
- close(sockfd);
- return -1;
- }
-
- return ifr.ifr_ifindex;
-}
-
-int if_ioctl(int cmd, struct ifreq* req) {
- int ret, sock;
- sock = socket(AF_INET, SOCK_PACKET, 0);
- if (sock < 0) {
- return -1;
- }
- ret = ioctl(sock, cmd, req);
- close(sock);
- return ret;
-}
-
-int sockraw_open(char * ifname) {
- struct ifreq ifr;
-
- // Open socket (P_ALL, due to custom ethertype field)
- int sockfd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
- if (sockfd < 0) {
- perror("Error opening socket");
- close(sockfd);
- return -1;
- }
-
- /* // Bind socket to interface */
- /* if (setsockopt(sockfd, SOL_SOCKET, SO_BINDTODEVICE, ifname, strlen(ifname)) < 0) { */
- /* perror("Error binding raw socket to interface"); */
- /* } */
-
- // Old bind to socket
- struct sockaddr_ll sll;
- bzero(&sll, sizeof(sll));
- sll.sll_family = AF_PACKET;
- sll.sll_ifindex = iface_idx(sockfd, ifname);
- sll.sll_protocol = htons(ETH_P_ALL);
- if (sll.sll_ifindex < 0) {
- // Error already printed, not reprinting
- return -1;
- }
- if((bind(sockfd, (struct sockaddr *)&sll, sizeof(sll))) == -1) {
- perror("Error binding raw socket to interface");
- close(sockfd);
- return -1;
- }
-
- // Get current iface configuration
- memset(&ifr, 0, sizeof(ifr));
- strcpy(ifr.ifr_name, ifname);
- if (if_ioctl(SIOCGIFFLAGS, &ifr) < 0) {
- perror("Get interface flags");
- }
-
- // Set iface to promiscuous mode
- ifr.ifr_flags |= IFF_PROMISC;
- if (if_ioctl(SIOCSIFFLAGS, &ifr) < 0) {
- perror("Configure interface promiscuous mode");
- }
-
- // Return the prepared socket
- return sockfd;
-}
-
-int tap_alloc(char * ifname, unsigned char * mac) {
- struct ifreq ifr;
- int fd, err;
-
- if( (fd = open("/dev/net/tun", O_RDWR)) < 0 ) {
- perror("Open tun");
- return -1;
- }
-
- // Bring up the interface
- memset(&ifr, 0, sizeof(ifr));
- ifr.ifr_flags = IFF_TAP | IFF_MULTI_QUEUE | IFF_NO_PI;
- if( *ifname ) {
- strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
- }
- if( (err = ioctl(fd, TUNSETIFF, (void *) &ifr)) < 0 ){
- perror("Open tun");
- close(fd);
- return err;
- }
- strcpy(ifname, ifr.ifr_name);
-
- // Set the interface's mac address
- if ( mac ) {
- // TODO: random, copied or specific mac address pulled from ini
- memset(&ifr, 0, sizeof(ifr));
- strcpy(ifr.ifr_name, ifname);
- ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
- memcpy(ifr.ifr_hwaddr.sa_data, mac, ETH_ALEN);
- if ((err = if_ioctl(SIOCSIFHWADDR, &ifr)) < 0) {
- perror("Set if hwaddr");
- close(fd);
- return err;
- }
- }
-
- // Fetch the current flags
- memset(&ifr, 0, sizeof(ifr));
- strcpy(ifr.ifr_name, ifname);
- if (if_ioctl(SIOCGIFFLAGS, &ifr) < 0) {
- perror("failed to get the interface flags");
- close(fd);
- return err;
- }
-
- // Bring up the interface
- if (!(ifr.ifr_flags & IFF_UP)) {
- ifr.ifr_flags |= IFF_UP;
- if (if_ioctl(SIOCSIFFLAGS, &ifr) < 0) {
- perror("failed to get the interface flags");
- close(fd);
- return err;
- }
- }
-
- return fd;
-}
diff --git a/src/util/socket.h b/src/util/socket.h
@@ -1,17 +0,0 @@
-#ifndef __PMLAG_SOCKET_H__
-#define __PMLAG_SOCKET_H__
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-unsigned char * iface_mac(char * ifname);
-int tap_alloc(char * ifname, unsigned char * mac);
-int sockraw_open(char * ifname);
-int iface_idx(int sockfd, char * ifname);
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif // __PMLAG_SOCKET_H__
diff --git a/test.ini b/test.ini
@@ -6,6 +6,7 @@
; interface=enp0s20f0u3
interface=virbr1
interface=virbr2
+interface=virbr2
hwaddr=random
hwaddr=virbr1
hwaddr=52:54:00:0B:97:66