pmlag

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

commit ea194c8bcc25e90fef15c196ebc2fd8b57d2a159
parent a46548078336dd52d56fff29db32fc158102d6d3
Author: Yersa Nordman <yersa@finwo.nl>
Date:   Thu, 23 Feb 2023 22:49:07 +0100

WIP: segfault in list iteration

Diffstat:
Msrc/config.h | 11++++++++---
Msrc/main.c | 79+++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------------
2 files changed, 65 insertions(+), 25 deletions(-)

diff --git a/src/config.h b/src/config.h @@ -15,6 +15,10 @@ extern "C" { #define PMLAG_MODE_BROADCAST 2 #define PMLAG_MODE_BALANCED_RR 3 +#define LLIST(x) struct { void *next; x *data; } + +typedef LLIST(struct pmlag_iface) pmlag_iface_llist; + struct pmlag_iface { void *next; // linked-list next reference char *name; // name of the interface this object represents @@ -38,9 +42,9 @@ struct pmlag_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 + unsigned char *mac; // mac address of the remote entity + uint16_t bcidx; // broadcast index last seen from the mac + pmlag_iface_llist *interfaces; // list of pointers to interfaces }; struct pmlag_configuration { @@ -49,6 +53,7 @@ struct pmlag_configuration { struct pmlag_configuration * config_load(const char * filename); + #ifdef __cplusplus } // extern "C" #endif diff --git a/src/main.c b/src/main.c @@ -27,13 +27,17 @@ static const char *const usage[] = { NULL }; +void trim_rt(struct pmlag_bond *bond, size_t limit) { + +} + void iface_add_rt(struct pmlag_iface *iface, unsigned char *mac, uint16_t bcidx) { struct pmlag_rt_entry *rt_entry; int iface_list_len; struct pmlag_iface *iface_list_entry; pthread_mutex_lock(&(iface->bond->mtx_rt)); - /* printf("\nRCV bc: %s\n", iface->name); */ + printf("\nRCV bc: %s\n", iface->name); // Fetch or build rt entry rt_entry = btree_get(iface->bond->rt, &(struct pmlag_rt_entry){ .mac = mac }); @@ -41,14 +45,15 @@ void iface_add_rt(struct pmlag_iface *iface, unsigned char *mac, uint16_t bcidx) /* printf(" new mac\n"); */ // Build new entry rt_entry = malloc(sizeof(struct pmlag_rt_entry)); - rt_entry->bcidx = 0; + bzero(rt_entry, sizeof(struct pmlag_rt_entry)); + /* rt_entry->bcidx = 0; */ // Insert the mac address rt_entry->mac = malloc(ETH_ALEN); memcpy(rt_entry->mac, mac, ETH_ALEN); - // And an empty list of interfaces - rt_entry->interfaces = calloc(1, sizeof(struct pm_rt_entry *)); + /* // And an empty list of interfaces */ + /* rt_entry->interfaces = NULL; */ } else { /* printf(" known mac\n"); */ } @@ -61,12 +66,22 @@ void iface_add_rt(struct pmlag_iface *iface, unsigned char *mac, uint16_t bcidx) } // Clear list of known interfaces if + pmlag_iface_llist *iface_entry; 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 ) { - free(rt_entry->interfaces); - rt_entry->interfaces = calloc(1, sizeof(struct pm_rt_entry *)); + // Free list 1-by-1 + while(rt_entry->interfaces) { + printf("FREE LINE %d (%p)\n", __LINE__, iface_entry); + printf("FREE LINE %d (%p)\n", __LINE__, rt_entry->interfaces); + iface_entry = rt_entry->interfaces; + printf("FREE LINE %d (%p)\n", __LINE__, iface_entry); + printf("FREE LINE %d (%p)\n", __LINE__, iface_entry->next); + rt_entry->interfaces = iface_entry->next; + printf("FREE LINE %d (%p)\n", __LINE__, iface_entry); + free(iface_entry); + } rt_entry->bcidx = bcidx; /* printf(" clear interface list\n"); */ } else { @@ -75,18 +90,23 @@ void iface_add_rt(struct pmlag_iface *iface, unsigned char *mac, uint16_t bcidx) } // Add given interface to the entry's interface list - 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]; - } - - /* printf(" len before: %d\n", iface_list_len); */ - rt_entry->interfaces = realloc(rt_entry->interfaces, (iface_list_len+2) * sizeof(struct pm_rt_entry *)); - /* printf(" reallocated\n"); */ - rt_entry->interfaces[iface_list_len ] = iface; - rt_entry->interfaces[iface_list_len+1] = NULL; - /* printf(" len after: %d\n", iface_list_len+1); */ + iface_entry = malloc(sizeof(pmlag_iface_llist)); + iface_entry->next = rt_entry->interfaces; + iface_entry->data = iface; + rt_entry->interfaces = iface_entry; + + /* 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]; */ + /* } */ + + /* /1* printf(" len before: %d\n", iface_list_len); *1/ */ + /* rt_entry->interfaces = realloc(rt_entry->interfaces, (iface_list_len+2) * sizeof(struct pm_rt_entry *)); */ + /* /1* printf(" reallocated\n"); *1/ */ + /* rt_entry->interfaces[iface_list_len ] = iface; */ + /* rt_entry->interfaces[iface_list_len+1] = NULL; */ + /* /1* printf(" len after: %d\n", iface_list_len+1); *1/ */ // Save rt entry in the routing table again btree_set(iface->bond->rt, rt_entry); @@ -126,6 +146,8 @@ void * thread_iface(void *arg) { uint16_t proto; uint16_t bcidx; + size_t rt_len; + while(1) { // Zero out buffer, to prevent pollution, & receive packet {{{ @@ -155,6 +177,10 @@ void * thread_iface(void *arg) { iface_add_rt(iface, buffer+ETH_ALEN, 0); } + /* trim_rt(iface->bond, */ + rt_len = btree_count(iface->bond->rt); + printf("Current RT length: %ld\n", rt_len); + // Redirect packet to bond socket as-is send_len = write(iface->bond->sockfd, buffer, buflen); if (buflen != send_len) { @@ -176,6 +202,7 @@ void * thread_bond(void *arg) { // Assign bond interface unsigned char *mac = iface_mac(bond->interfaces->name); bond->sockfd = tap_alloc(bond->name, mac); + printf("FREE LINE %d (%p)\n", __LINE__, mac); free(mac); if (bond->sockfd < 0) { perror("Allocating bond interface"); @@ -210,7 +237,8 @@ void * thread_bond(void *arg) { struct pmlag_rt_entry *rt_entry; int iface_list_len; - struct pmlag_iface *iface_list_entry; + int iface_list_sel; + pmlag_iface_llist *iface_list_entry; sleep(1); @@ -261,13 +289,19 @@ void * thread_bond(void *arg) { // Fetch length of interface list iface_list_len = 0; - iface_list_entry = rt_entry->interfaces[iface_list_len]; + iface_list_entry = rt_entry->interfaces; while(iface_list_entry) { - iface_list_entry = rt_entry->interfaces[++iface_list_len]; + iface_list_len++; + iface_list_entry = iface_list_entry->next; } // Select interface at random - iface = rt_entry->interfaces[rand() % iface_list_len]; + iface_list_sel = rand() % iface_list_len; + iface_list_entry = rt_entry->interfaces; + while(iface_list_sel--) iface_list_entry = iface_list_entry->next; + iface = iface_list_entry->data; + + // Unlock routing table pthread_mutex_unlock(&(bond->mtx_rt)); // Prepare saddr_ll for sendto @@ -367,6 +401,7 @@ int main(int argc, const char **argv) { mac = iface_mac(bond->name); memcpy(saddr_ll.sll_addr, mac, ETH_ALEN); memcpy(buffer+ETH_ALEN, mac, ETH_ALEN); + printf("FREE LINE %d (%p)\n", __LINE__, mac); free(mac); // Set the bcidx memcpy(buffer + (ETH_ALEN*2) + sizeof(uint16_t), &(bond->bcidx), sizeof(uint16_t));