commit 0ec1e7463d3d03d551dd2362de8265516fefb99f
parent b6a8b216f920638b60eeced4a39d83826164dd78
Author: Yersa Nordman <yersa@finwo.nl>
Date: Tue, 21 Feb 2023 23:11:00 +0100
First routing table tracking attempt
Diffstat:
5 files changed, 103 insertions(+), 11 deletions(-)
diff --git a/pmlag.1 b/pmlag.1
@@ -22,3 +22,9 @@ pmlag - Poor man\[cq]s link aggregator
.SH SYNOPSIS
.PP
\f[V]pmlag [options]\f[R]
+.SH LICENSE
+.PP
+This project is a work in progress, the license(s) shown here are not
+complete
+.PP
+TODO: - benhoyt/inih - cofyc/argparse - tidwall/btree
diff --git a/pmlag.html b/pmlag.html
@@ -166,5 +166,9 @@
<p>pmlag - Poor man’s link aggregator</p>
<h1 id="synopsis">SYNOPSIS</h1>
<p><code>pmlag [options]</code></p>
+<h1 id="license">LICENSE</h1>
+<p>This project is a work in progress, the license(s) shown here are not
+complete</p>
+<p>TODO: - benhoyt/inih - cofyc/argparse - tidwall/btree</p>
</body>
</html>
diff --git a/src/config.c b/src/config.c
@@ -63,17 +63,16 @@ static int config_load_handler(
iface = calloc(1, sizeof(struct pmlag_iface));
iface->next = bond->interfaces;
iface->name = strdup(value);
- iface->weight = 10;
+ /* iface->weight = 10; */
iface->bond = bond;
bond->interfaces = iface;
}
- } else if (!strcmp(name, "weight")) {
- if (!iface) {
- return 0;
- }
-
- iface->weight = atoi(value);
+ /* } else if (!strcmp(name, "weight")) { */
+ /* if (!iface) { */
+ /* return 0; */
+ /* } */
+ /* iface->weight = atoi(value); */
} else {
// Unknown key
return 0;
diff --git a/src/config.h b/src/config.h
@@ -4,6 +4,8 @@
#include <pthread.h>
#include <stdint.h>
+#include "tidwall/btree.h"
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -16,7 +18,7 @@ extern "C" {
struct pmlag_iface {
void *next; // linked-list next reference
char *name; // name of the interface this object represents
- int weight; // weight of this interface within the bond
+ /* 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
@@ -31,9 +33,16 @@ struct pmlag_bond {
uint16_t bcidx; // big-endian broadcast index for quickly detecting dead paths
pthread_t tid; // thread id where the bond interface listener recides in
pthread_mutex_t mtx_rt; // lock for the routing table of the bond
+ struct btree *rt; // pointer to the routing table
struct pmlag_iface *interfaces; // linked-list of interfaces contained in the bond
};
+struct pmlag_rt_entry {
+ unsigned char *mac; // mac address of the remote entity
+ uint16_t bcidx; // broadcast index last seen from the mac
+ struct pmlag_iface **interfaces; // list of pointers to interfaces
+};
+
struct pmlag_configuration {
struct pmlag_bond *bonds;
};
diff --git a/src/main.c b/src/main.c
@@ -1,3 +1,5 @@
+// vim: fdm=marker :
+
#include <arpa/inet.h>
#include <errno.h>
#include <linux/if_ether.h>
@@ -13,6 +15,7 @@
#include <stdio.h>
#include <unistd.h>
+#include "tidwall/btree.h"
#include "cofyc/argparse.h"
#include "config.h"
#include "socket.h"
@@ -52,10 +55,14 @@ void * thread_iface(void *arg) {
// Find bond socket iface_idx
int send_len;
uint16_t proto;
+ uint16_t bcidx;
+ struct pmlag_rt_entry *rt_entry;
+ int iface_list_len;
+ struct pmlag_iface *iface_list_entry;
while(1) {
- // Zero out buffer, to prevent pollution, & receive packet
+ // Zero out buffer, to prevent pollution, & receive packet {{{
/* memset(buffer, 0, RCVBUFSIZ); */
buflen = recvfrom(iface->sockfd, buffer, RCVBUFSIZ, 0, &saddr, (socklen_t *)&saddr_len);
if (buflen < 0) {
@@ -63,11 +70,69 @@ void * thread_iface(void *arg) {
pthread_exit(NULL);
return NULL;
}
+ // }}}
// Update routing table if our custom protocol is seen
- proto = ((uint16_t)((unsigned char)buffer[12]) << 8) + buffer[13];
+ proto = ((uint16_t)((unsigned char)buffer[(ETH_ALEN*2)+0]) << 8) + buffer[(ETH_ALEN*2)+1];
if (proto == 0x0666) {
pthread_mutex_lock(&(iface->bond->mtx_rt));
+ printf("RCV bc:\n");
+
+ // Fetch or build routing table entry {{{
+ rt_entry = btree_get(iface->bond->rt, &(struct pmlag_rt_entry){ .mac = (buffer+ETH_ALEN) });
+ if (!rt_entry) {
+ printf(" known mac\n");
+ // Build new entry
+ rt_entry = malloc(sizeof(struct pmlag_rt_entry));
+
+ // Insert the mac address
+ rt_entry->mac = malloc(ETH_ALEN);
+ memcpy(rt_entry->mac, buffer+ETH_ALEN, ETH_ALEN);
+
+ // Insert the bcidx
+ rt_entry->bcidx = ((uint16_t)((unsigned char)buffer[(ETH_ALEN*2)+2]) << 8) + buffer[(ETH_ALEN*2)+3];
+
+ // And an empty list of interfaces
+ rt_entry->interfaces = calloc(1, sizeof(struct pm_rt_entry *));
+ } else {
+ printf(" new mac\n");
+ }
+ // }}}
+
+ // New bcidx = empty interface list {{{
+ bcidx = ((uint16_t)((unsigned char)buffer[(ETH_ALEN*2)+2]) << 8) + buffer[(ETH_ALEN*2)+3];
+ if (rt_entry->bcidx != bcidx) {
+ printf(" new bcidx\n");
+ free(rt_entry->interfaces);
+ rt_entry->interfaces = calloc(1, sizeof(struct pm_rt_entry *));
+ } else {
+ printf(" new bcidx\n");
+ }
+ // }}}
+
+ // Add self to the list of interfaces {{{
+
+ // Fetch length of interfaces {{{
+ iface_list_len = 0;
+ iface_list_entry = rt_entry->interfaces[iface_list_len];
+ while(iface_list_entry) {
+ iface_list_entry = rt_entry->interfaces[++iface_list_len];
+ }
+ // }}}
+ // Realloc list to have the expanded length {{{
+ rt_entry->interfaces = realloc(rt_entry->interfaces, (iface_list_len+2) * sizeof(struct pm_rt_entry *));
+ // }}}
+ // Actually add receiving interface to the known interfaces for the mac address {{{
+ rt_entry->interfaces[iface_list_len ] = iface;
+ rt_entry->interfaces[iface_list_len+1] = NULL;
+ // }}}
+
+ // }}}
+
+ // Save rt entry in the routing table again
+ btree_set(iface->bond->rt, rt_entry);
+ printf("\n");
+
// TODO: update routing table
pthread_mutex_unlock(&(iface->bond->mtx_rt));
continue; // Don't forward the packet
@@ -190,6 +255,12 @@ void * thread_bond(void *arg) {
return NULL;
}
+static int compare_rt_entries(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;
+ return memcmp(ta->mac, tb->mac, ETH_ALEN);
+}
+
int main(int argc, const char **argv) {
char *config_file="/etc/pmlag/pmlag.ini";
@@ -227,6 +298,8 @@ int main(int argc, const char **argv) {
return 1;
}
+ // Initialize routing table
+ bond->rt = btree_new(sizeof(void*), 0, compare_rt_entries, bond);
// Start the bond's thread
if(pthread_create(&(bond->tid), NULL, thread_bond, bond)) {
@@ -282,7 +355,8 @@ int main(int argc, const char **argv) {
bond->bcidx = htons(ntohs(bond->bcidx)+1);
bond = bond->next;
}
- usleep(10000); // 10ms
+ /* usleep(100000); // 100ms */
+ sleep(1);
}