pmlag

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

commit 9a91e5e7fdb368d3eded4723714aba5ec3a1ea83
parent b08118b433d37df4258dc3364bf3d842f81101f0
Author: Yersa Nordman <yersa@finwo.nl>
Date:   Wed, 11 Oct 2023 00:22:03 +0200

Initialize tap and routing-table

Diffstat:
Msrc/main.c | 19++++++++++++++++++-
Msrc/util/config.h | 30+++++++++---------------------
Msrc/util/routing-table.c | 60++++++++++++++++++++++++++----------------------------------
Msrc/util/routing-table.h | 24++++++++++++------------
Msrc/util/socket.c | 58++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/util/socket.h | 1+
6 files changed, 124 insertions(+), 68 deletions(-)

diff --git a/src/main.c b/src/main.c @@ -8,6 +8,7 @@ #include "cofyc/argparse.h" #include "util/config.h" +#include "util/routing-table.h" #include "util/socket.h" static const char *const usage[] = { @@ -25,6 +26,7 @@ int main(int argc, const char **argv) { char *config_file="/etc/pmlag/pmlag.ini"; struct epoll_event *epev; int epfd; + struct pmlag_bond *bond; struct pmlag_iface *iface; // Seed random @@ -88,9 +90,24 @@ int main(int argc, const char **argv) { for( b = 0 ; b < config->bond_count ; b++ ) { // (re)open bond tap + bond = config->bond[b]; + if (!bond->sockfd) { + bond->sockfd = tap_alloc(bond->name, bond->hwaddr); + if (bond->sockfd < 0) { + perror("tap_alloc"); + bond->sockfd = 0; + continue; + } + printf("Opened tap for %s\n", bond->name); + } + + // (re)initialize routing table + if (!bond->rt) { + bond->rt = rt_init(bond); + } for( i = 0 ; i < config->bond[b]->iface_count ; i++ ) { - iface = config->bond[b]->iface[i]; + iface = bond->iface[i]; // (re)open interface socket if (!iface->sockfd) { diff --git a/src/util/config.h b/src/util/config.h @@ -6,33 +6,21 @@ #define PMLAG_ENTITY_TYPE_BOND 2 struct pmlag_iface { - PMLAG_ENTITY_TYPE type; - char *name; - struct pmlag_bond *bond; - int sockfd; + PMLAG_ENTITY_TYPE type; + char *name; + struct pmlag_bond *bond; + int sockfd; struct epoll_event *epev; - /* /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 { - PMLAG_ENTITY_TYPE type; - char *name; + PMLAG_ENTITY_TYPE type; + char *name; struct pmlag_iface **iface; int iface_count; - unsigned char *hwaddr; // hwaddr to use for the interface (null = random) - -/* 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 */ + int sockfd; + unsigned char *hwaddr; // hwaddr to use for the interface (null = random) + struct mindex_t *rt; }; struct pmlag_configuration { diff --git a/src/util/routing-table.c b/src/util/routing-table.c @@ -1,39 +1,31 @@ -/* #include <linux/if_ether.h> */ +#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); */ -/* } */ +#include <string.h> + +#include "finwo/mindex.h" + +#include "config.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; + if (a == b) return 0; + return memcmp(ta->mac, tb->mac, ETH_ALEN); +} + +static void rt_purge(void *item, void *udata) { + struct pmlag_rt_entry *rt_entry = (struct pmlag_rt_entry *)item; + if (!rt_entry) return; + if (rt_entry->iface) free(rt_entry->iface); + if (rt_entry->mac) 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, */ diff --git a/src/util/routing-table.h b/src/util/routing-table.h @@ -1,18 +1,18 @@ -/* #ifndef __PMLAG_UTIL_RT_H__ */ -/* #define __PMLAG_UTIL_RT_H__ */ +#ifndef __PMLAG_UTIL_RT_H__ +#define __PMLAG_UTIL_RT_H__ -/* #include "config.h" */ +#include "config.h" -/* #include "finwo/mindex.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 pmlag_rt_entry { + unsigned char *mac; // mac address of the remote entity + int16_t bcidx; // broadcast index last seen from the mac + struct pmlag_iface **iface; + int iface_count; +}; -/* struct mindex_t * rt_init(void *udata); */ +struct mindex_t * rt_init(void *udata); /* int rt_upsert( */ /* struct mindex_t *rt, */ @@ -28,4 +28,4 @@ /* unsigned char *mac */ /* ); */ -/* #endif // __PMLAG_UTIL_RT_H__ */ +#endif // __PMLAG_UTIL_RT_H__ diff --git a/src/util/socket.c b/src/util/socket.c @@ -96,3 +96,61 @@ int sockraw_open(char * ifname) { // 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 @@ -2,6 +2,7 @@ #define __PMLAG_UTIL_SOCKET_H__ unsigned char * iface_mac(char * ifname); +int tap_alloc(char * ifname, unsigned char * mac); int sockraw_open(char * ifname); #endif // __PMLAG_UTIL_SOCKET_H__