pmlag

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

commit 5851fbeb8f3648f336c77c47eb8c371b696bd567
parent ed433bd013ee2de115c697293baee8f117f040ba
Author: Robin Bron <robin@finwo.nl>
Date:   Sun, 12 Feb 2023 22:27:06 +0100

Tap iface created

Diffstat:
Msrc/main.c | 27+++++++++++++++++----------
Msrc/socket.c | 35++++++++++++++++++++++++++++++++++-
Msrc/socket.h | 1+
Mtest.ini | 4+---
4 files changed, 53 insertions(+), 14 deletions(-)

diff --git a/src/main.c b/src/main.c @@ -55,10 +55,6 @@ void * thread_iface(void *arg) { } // Find bond socket iface_idx - struct sockaddr_ll sadr_ll; - sadr_ll.sll_halen = ETH_ALEN; // length of destination mac address */ - int bond_fd = iface->bond->sockfd; - int bond_idx = iface_idx(bond_fd, iface->bond->name); int send_len; while(1) { @@ -74,12 +70,19 @@ void * thread_iface(void *arg) { // TODO: track received proto=0x0666 packet to update routing table + /* printf("\n"); */ + /* printf("Got packet: %d bytes\n", buflen); */ + /* printf("\n"); */ + + /* printf("Ethernet header\n"); */ + /* printf("\t|- DST %.2X-%.2X-%.2X-%.2X-%.2X-%.2X\n",buffer[0],buffer[1],buffer[2],buffer[3],buffer[ 4],buffer[ 5]); */ + /* printf("\t|- SRC %.2X-%.2X-%.2X-%.2X-%.2X-%.2X\n",buffer[6],buffer[7],buffer[8],buffer[9],buffer[10],buffer[11]); */ + /* printf("\t|- PROTO %.4X\n", ((int)((char)buffer[12]) << 8) + buffer[13]); */ + // Redirect packet to bond socket as-is - sadr_ll.sll_ifindex = bond_idx; - memcpy(sadr_ll.sll_addr, buffer, ETH_ALEN); - send_len = sendto(bond_fd, buffer, buflen, 0, (const struct sockaddr*)&sadr_ll, sizeof(struct sockaddr_ll)); + send_len = write(iface->bond->sockfd, buffer, buflen); if (buflen != send_len) { - perror("sendto"); + perror("write(bond)"); pthread_exit(NULL); return NULL; } @@ -94,7 +97,9 @@ void * thread_bond(void *arg) { struct pmlag_bond *bond = (struct pmlag_bond *)arg; printf("Thread started for bond: %s\n", bond->name); - // For each bond of config->bonds + + + // Start thread for each interface of this bond struct pmlag_iface *iface = bond->interfaces; while(iface) { if(pthread_create(&(iface->tid), NULL, thread_iface, iface)) { @@ -105,7 +110,9 @@ void * thread_bond(void *arg) { iface = iface->next; } - // TODO: open tun/tap device + // Take mac address of last iface + bond->sockfd = tap_alloc(bond->name); + // TODO: blocked listen on bond, send through routing table to other ifaces // TODO: send broadcasts to all interfaces // TODO: timer to broadcast announce our presence to ifaces (vrrp-ish) diff --git a/src/socket.c b/src/socket.c @@ -1,11 +1,13 @@ -#include <linux/if_ether.h> +#include <fcntl.h> #include <linux/if_packet.h> +#include <linux/if_tun.h> #include <net/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> @@ -18,6 +20,7 @@ int iface_idx(int sockfd, char * ifname) { // 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; @@ -55,3 +58,33 @@ int sockraw_open(char * ifname) { // Return the prepared socket return sockfd; } + +int tap_alloc(char * ifname) { + struct ifreq ifr; + int fd, err; + + if( (fd = open("/dev/net/tun", O_RDWR)) < 0 ) { + perror("Open tun"); + return -1; + } + + memset(&ifr, 0, sizeof(ifr)); + + /* Flags: IFF_TUN - TUN device (no Ethernet headers) + * IFF_TAP - TAP device + * + * IFF_NO_PI - Do not provide packet information + */ + ifr.ifr_flags = IFF_TAP | IFF_NO_PI; + if( *ifname ) { + strncpy(ifr.ifr_name, ifname, IFNAMSIZ); + } + + if( (err = ioctl(fd, TUNSETIFF, (void *) &ifr)) < 0 ){ + close(fd); + return err; + } + + strcpy(ifname, ifr.ifr_name); + return fd; +} diff --git a/src/socket.h b/src/socket.h @@ -5,6 +5,7 @@ extern "C" { #endif +int tap_alloc(char * ifname); int sockraw_open(char * ifname); int iface_idx(int sockfd, char * ifname); diff --git a/test.ini b/test.ini @@ -3,10 +3,8 @@ ; eth0 = backup, eth1 = primary [bond0] mode=active-backup -interface=enp0s13f0u1c2 +interface=docker0 weight=10 -interface=enp0s13f0u2c2 -weight=25 ; ; broadcast everything on all interfaces ; [bond1]