pmlag

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

commit 2f1d32c23cf7427b9d824672c3361116a9ca4b11
parent 1105cc0c95cfc62d1abe9268c34980b04d3fb084
Author: Robin Bron <robin@finwo.nl>
Date:   Wed,  8 Mar 2023 20:59:06 +0100

Added rt_find and using the rt to select an iface

Diffstat:
Msrc/task/bond.c | 75++++++++++++++++++++++++++++++++++++++++++---------------------------------
Msrc/task/iface.c | 4----
Msrc/util/routing-table.c | 68+++++++++++++++++++++++++++++++++++++++++++++++++++++---------------
Msrc/util/routing-table.h | 6++++++
4 files changed, 101 insertions(+), 52 deletions(-)

diff --git a/src/task/bond.c b/src/task/bond.c @@ -18,31 +18,38 @@ int task_bond_onpacket(struct pmlag_bond *bond, unsigned char *buffer, size_t bu saddr_ll.sll_halen = ETH_ALEN; // Debug: print eth header - printf("%.2x:%.2x:%.2x:%.2x:%.2x:%.2x > %.2x:%.2x:%.2x:%.2x:%.2x:%.2x, %.4x (%ld)\n", + printf("%.2x:%.2x:%.2x:%.2x:%.2x:%.2x > %.2x:%.2x:%.2x:%.2x:%.2x:%.2x, %.4x (%ld), %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 + buflen, + mindex_length(bond->rt) ); - // Send packet to the first available iface - struct pmlag_iface *iface = bond->interfaces->data; - -/* // Select interface at random */ -/* 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 - saddr_ll.sll_ifindex = iface->ifidx; + // Get interface to send the packet from memcpy(saddr_ll.sll_addr, buffer, ETH_ALEN); + struct pmlag_iface *iface = rt_find(bond->rt, &(bond->mtx_rt), buffer); + pmlag_iface_llist *iface_entry; + size_t send_len; + + // Broadcast on ALL interfaces if no rt entry OR broadcast packet + if ((!iface) || (memcmp(buffer, "\xFF\xFF\xFF\xFF\xFF\xFF", ETH_ALEN) == 0)) { + iface_entry = bond->interfaces; + while(iface_entry) { + saddr_ll.sll_ifindex = iface_entry->data->ifidx; + send_len = sendto(iface_entry->data->sockfd, buffer, buflen, 0, (const struct sockaddr*)&saddr_ll, sizeof(struct sockaddr_ll)); + if(send_len != buflen) { + perror("sendto"); + return 1; + } + iface_entry = iface_entry->next; + } + return 0; + } // Forward packet to iface as-is - size_t send_len = sendto(iface->sockfd, buffer, buflen, 0, (const struct sockaddr*)&saddr_ll, sizeof(struct sockaddr_ll)); + saddr_ll.sll_ifindex = iface->ifidx; + send_len = sendto(iface->sockfd, buffer, buflen, 0, (const struct sockaddr*)&saddr_ll, sizeof(struct sockaddr_ll)); if(send_len != buflen) { perror("sendto"); return 1; @@ -144,22 +151,24 @@ void * task_bond_thread(void *arg) { /* pthread_mutex_lock(&(bond->mtx_rt)); */ /* rt_entry = mindex_get(bond->rt, &(struct pmlag_rt_entry){ .mac = buffer }); */ -/* // Broadcast on ALL interfaces if no rt entry OR broadcast packet */ -/* if ((!rt_entry) || (memcmp(buffer, "\xFF\xFF\xFF\xFF\xFF\xFF", ETH_ALEN) == 0)) { */ -/* pthread_mutex_unlock(&(bond->mtx_rt)); */ -/* iface = bond->interfaces; */ -/* while(iface) { */ -/* saddr_ll.sll_ifindex = iface->ifidx; */ -/* send_len = sendto(iface->sockfd, buffer, buflen, 0, (const struct sockaddr*)&saddr_ll, sizeof(struct sockaddr_ll)); */ -/* if(send_len != buflen) { */ -/* perror("sendto"); */ -/* /1* pthread_exit(NULL); *1/ */ -/* /1* return NULL; *1/ */ -/* } */ -/* iface = iface->next; */ -/* } */ -/* continue; */ -/* } */ + + + + + + + + + + + + + + + + + + /* // Fetch length of interface list */ /* iface_list_len = 0; */ diff --git a/src/task/iface.c b/src/task/iface.c @@ -95,7 +95,3 @@ void * task_iface_thread(void *arg) { return NULL; } - - - - diff --git a/src/util/routing-table.c b/src/util/routing-table.c @@ -11,10 +11,10 @@ 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; - printf("\nCMP\n A = %.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n B = %.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n", - ta->mac[0],ta->mac[1],ta->mac[2],ta->mac[3],ta->mac[4],ta->mac[5], - tb->mac[0],tb->mac[1],tb->mac[2],tb->mac[3],tb->mac[4],tb->mac[5] - ); + /* printf("\nCMP\n A = %.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n B = %.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n", */ + /* ta->mac[0],ta->mac[1],ta->mac[2],ta->mac[3],ta->mac[4],ta->mac[5], */ + /* tb->mac[0],tb->mac[1],tb->mac[2],tb->mac[3],tb->mac[4],tb->mac[5] */ + /* ); */ return memcmp(ta->mac, tb->mac, ETH_ALEN); } @@ -34,10 +34,10 @@ int rt_upsert( unsigned char *mac, int16_t bcidx ) { - /* int isnew = 0; */ + int isnew = 0; struct pmlag_rt_entry *rt_entry; - printf("\nUpserting RT, %d\n", bcidx); + /* printf("\nUpserting RT, %d\n", bcidx); */ // Lock the routing table pthread_mutex_lock(mtx); @@ -45,11 +45,11 @@ int rt_upsert( // Attempt to fetch the rt entry rt_entry = mindex_get(rt, &((struct pmlag_rt_entry){ .mac = mac })); - /* int16_t obcidx = 0; */ - if (rt_entry) { - /* obcidx = rt_entry->bcidx; */ - printf(" Found, %d\n", rt_entry->bcidx); - } + /* /1* int16_t obcidx = 0; *1/ */ + /* if (rt_entry) { */ + /* /1* obcidx = rt_entry->bcidx; *1/ */ + /* printf(" Found, %d\n", rt_entry->bcidx); */ + /* } */ // None given, build new one if (!rt_entry) { @@ -58,7 +58,7 @@ int rt_upsert( /* rt_entry->bcidx = 0; */ rt_entry->interfaces = NULL; memcpy(rt_entry->mac, mac, ETH_ALEN); - /* isnew = 1; */ + isnew = 1; } /* printf(" Old bcidx, %d\n", rt_entry->bcidx); */ @@ -103,11 +103,49 @@ int rt_upsert( rt_entry->interfaces = iface_entry; // Ensure the entry is in the rt - mindex_set(rt, rt_entry); + if (isnew) { + mindex_set(rt, rt_entry); + } - /* printf(" or now, %d\n", rt_entry->bcidx); */ - printf(" RT is now %ld\n\n", mindex_length(rt)); + /* /1* printf(" or now, %d\n", rt_entry->bcidx); *1/ */ + /* printf(" RT is now %ld\n\n", mindex_length(rt)); */ pthread_mutex_unlock(mtx); return 0; } + +struct pmlag_iface * rt_find( + struct mindex_t *rt, + pthread_mutex_t *mtx, + unsigned char *mac +) { + // Lock the routing table + pthread_mutex_lock(mtx); + struct pmlag_rt_entry *rt_entry; + int llist_len = 0; + + // Attempt to fetch the rt entry + rt_entry = mindex_get(rt, &((struct pmlag_rt_entry){ .mac = mac })); + if (!rt_entry) { + pthread_mutex_unlock(mtx); + return NULL; + } + + // Get the list length + pmlag_iface_llist *iface_entry = rt_entry->interfaces; + while(iface_entry) { + llist_len++; + iface_entry = iface_entry->next; + } + + // Select an interface at random + int sel = rand() % llist_len; + iface_entry = rt_entry->interfaces; + while(--sel) { + iface_entry = iface_entry->next; + } + + // Unlock the routing table again + pthread_mutex_unlock(mtx); + return iface_entry->data; +} diff --git a/src/util/routing-table.h b/src/util/routing-table.h @@ -21,4 +21,10 @@ int rt_upsert( int16_t bcidx ); +struct pmlag_iface * rt_find( + struct mindex_t *rt, + pthread_mutex_t *mtx, + unsigned char *mac +); + #endif // __PMLAG_UTIL_RT_H__