pmlag

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

commit dee2f5cf9ef6f300c6fdb1affcb3e7800275339a
parent ce4e853aeb77251b876641d4aecb5756a2d41dcf
Author: Yersa Nordman <yersa@finwo.nl>
Date:   Tue,  7 Feb 2023 21:28:24 +0100

Loading ini file now functional

Diffstat:
Asrc/config.c | 92+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/config.h | 36++++++++++++++++++++++++++++++++++++
Msrc/main.c | 399+++++++++++++++++++++++++++++++++++--------------------------------------------
Asrc/socket.c | 57+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/socket.h | 15+++++++++++++++
Atest.ini | 23+++++++++++++++++++++++
6 files changed, 397 insertions(+), 225 deletions(-)

diff --git a/src/config.c b/src/config.c @@ -0,0 +1,92 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "benhoyt/inih.h" +#include "config.h" + +static int config_load_handler( + void *user, + const char *section, + const char *name, + const char *value +) { + struct pmlag_configuration* config = (struct pmlag_configuration *) user; + + // Get bond being configured + struct pmlag_bond *bond = config->bonds; + while(bond) { + if (!strcmp(bond->name, section)) { + break; + } + bond = bond->next; + } + + // Create bond if not found + if (!bond) { + bond = calloc(1, sizeof(struct pmlag_bond)); + bond->next = config->bonds; + bond->name = strdup(section); + config->bonds = bond; + } + + // Get interface being configured + struct pmlag_interface *iface = bond->interfaces; + + if (0) { + // Intentionally empty + } else if (!strcmp(name, "mode")) { + // Set the mode according to found value + if (0) { + // Intentionally empty + } else if (!strcmp(value, "active-backup")) { + bond->mode = PMLAG_MODE_ACTIVE_BACKUP; + } else if (!strcmp(value, "balanced-rr")) { + bond->mode = PMLAG_MODE_BALANCED_RR; + } else if (!strcmp(value, "broadcast")) { + bond->mode = PMLAG_MODE_BROADCAST; + } else { + return 0; + } + } else if (!strcmp(name, "interface")) { + + // Select the right interface + while(iface) { + if (!strcmp(iface->name, value)) { + break; + } + iface = iface->next; + } + + // Create iface if not found + if (!iface) { + iface = calloc(1, sizeof(struct pmlag_interface)); + iface->next = bond->interfaces; + iface->name = strdup(value); + iface->weight = 10; + bond->interfaces = iface; + } + + } else if (!strcmp(name, "weight")) { + if (!iface) { + return 0; + } + + iface->weight = atoi(value); + } else { + // Unknown key + return 0; + } + + return 1; +} + +struct pmlag_configuration * config_load(const char * filename) { + // Load config, entry-by-entry + struct pmlag_configuration *config = calloc(1, sizeof(struct pmlag_configuration)); + if (ini_parse(filename, config_load_handler, config) < 0) { + fprintf(stderr, "Can not load %s\n", filename); + return NULL; + } + return config; +} diff --git a/src/config.h b/src/config.h @@ -0,0 +1,36 @@ +#ifndef __PMLAG_CONFIG_H__ +#define __PMLAG_CONFIG_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#define PMLAG_MODE_NONE 0 +#define PMLAG_MODE_ACTIVE_BACKUP 1 +#define PMLAG_MODE_BROADCAST 2 +#define PMLAG_MODE_BALANCED_RR 3 + +struct pmlag_interface { + void *next; + char *name; + int weight; +}; + +struct pmlag_bond { + void *next; + char *name; + int mode; + struct pmlag_interface *interfaces; +}; + +struct pmlag_configuration { + struct pmlag_bond *bonds; +}; + +struct pmlag_configuration * config_load(const char * filename); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // __PMLAG_CONFIG_H__ diff --git a/src/main.c b/src/main.c @@ -1,96 +1,34 @@ -#include "cofyc/argparse.h" - -#include <stdio.h> - #include <arpa/inet.h> -#include <net/ethernet.h> +#include <errno.h> +#include <linux/if_ether.h> +#include <linux/if_packet.h> #include <net/if.h> +#include <netinet/in.h> +#include <netinet/ip.h> #include <stdlib.h> #include <string.h> #include <sys/ioctl.h> #include <sys/socket.h> -#include <unistd.h> -#include <linux/if_packet.h> -#include <netinet/ip.h> +#include <stdio.h> -#include <errno.h> +#include "cofyc/argparse.h" +#include "config.h" +#include "socket.h" #define INTERFACE "docker0" - static const char *const usage[] = { __NAME " [options]", NULL }; -/* typedef struct { */ -/* // Linked list */ -/* void *next; // Ref to the next interface */ -/* // Config */ -/* char *name; // Name of the interface */ -/* char *mac; // Mac address to set on the interface */ -/* // Activity */ -/* int socket; // Socket file descriptor */ -/* } pmlag_interface; */ - -int iface_idx(int sockfd, char * ifname) { - struct ifreq ifr; - bzero(&ifr, sizeof(ifr)); - - // Get interface index - strncpy((char *)ifr.ifr_name, ifname, IFNAMSIZ); - if ((ioctl(sockfd, SIOCGIFINDEX, &ifr)) == -1) { - perror("Error getting interface index"); - close(sockfd); - return -1; - } - - return ifr.ifr_ifindex; -} - -int sockraw_open(char * ifname) { - - // Open socket - int sockfd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); - if (sockfd < 0) { - perror("Error opening socket"); - close(sockfd); - return -1; - } - - // Bind socket to interface - struct sockaddr_ll sll; - bzero(&sll, sizeof(sll)); - sll.sll_family = AF_PACKET; - sll.sll_ifindex = iface_idx(sockfd, ifname); - sll.sll_protocol = htons(ETH_P_ALL); - if (sll.sll_ifindex < 0) { - // Error already printed, not reprinting - return -1; - } - if((bind(sockfd, (struct sockaddr *)&sll, sizeof(sll))) == -1) { - perror("Error binding raw socket to interface"); - close(sockfd); - return -1; - } - - // Return the prepared socket - return sockfd; -} - int main(int argc, const char **argv) { char *config_file="/etc/pmlag/pmlag.ini"; - - int tx = 0; - int rx = 0; - // Define which options we support struct argparse_option options[] = { OPT_HELP(), OPT_STRING('c', "config", &config_file, "Config file to use", NULL, 0, 0), - OPT_BOOLEAN('t', "tx", &tx, "Send a message", NULL, 0, 0), - OPT_BOOLEAN('r', "rx", &rx, "Send a message", NULL, 0, 0), OPT_END(), }; @@ -105,168 +43,179 @@ int main(int argc, const char **argv) { ); argc = argparse_parse(&argparse, argc, argv); - /* while(iface) { */ - /* fprintf(stderr, " Interface: %s\n", iface->name); */ - /* fprintf(stderr, " master : %s\n", iface->master ? iface->master : ""); */ - /* fprintf(stderr, " mac : %s\n", iface->mac ? iface->mac : ""); */ - /* fprintf(stderr, " broadcast: %s%s\n", */ - /* iface->broadcast == BROADCAST_FLOOD ? "flood" : "", */ - /* iface->broadcast == BROADCAST_BALANCED ? "balanced" : "" */ - /* ); */ - /* fprintf(stderr, " mode : %s%s%s%s\n", */ - /* iface->mode == MODE_SLAVE ? "slave" : "", */ - /* iface->mode == MODE_ACTIVE_BACKUP ? "active-backup" : "", */ - /* iface->mode == MODE_BROADCAST ? "broadcast" : "", */ - /* iface->mode == MODE_BALANCE_RR ? "balance-rr" : "" */ - /* ); */ - /* fprintf(stderr, " weight : %d\n", iface->weight); */ - /* iface = iface->next; */ - /* if (iface == loaded->interfaces) break; */ - /* } */ - - - - - - int sockfd = sockraw_open(INTERFACE); - if (sockfd < 0) { + // Load configuration file + struct pmlag_configuration *config = config_load(config_file); + if (!config) { return 1; } - if (rx) { - - // Prepare ingress buffer - int buflen; - unsigned char *buffer = (unsigned char *) malloc(65536); - memset(buffer, 0, 65536); - struct sockaddr saddr; - int saddr_len = sizeof(saddr); - - struct ethhdr *eth = (struct ethhdr *)(buffer); - struct sockaddr_in source; - struct sockaddr_in dest; - - while(1) { - - // Fetch a packet - buflen = recvfrom(sockfd, buffer, 65536, 0, &saddr, (socklen_t *)&saddr_len); - if (buflen < 0) { - perror("recvfrom"); - exit(EXIT_FAILURE); - } - - 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",eth->h_dest[0],eth->h_dest[1],eth->h_dest[2],eth->h_dest[3],eth->h_dest[4],eth->h_dest[5]); - printf("\t|- SRC %.2X-%.2X-%.2X-%.2X-%.2X-%.2X\n",eth->h_source[0],eth->h_source[1],eth->h_source[2],eth->h_source[3],eth->h_source[4],eth->h_source[5]); - printf("\t|- PROTO %.4X\n",be16toh(eth->h_proto)); - - printf("\n"); - - if (be16toh(eth->h_proto) == 0x0800) { - unsigned short iphdrlen; - struct iphdr *ip = (struct iphdr*)(buffer + sizeof(struct ethhdr)); - memset(&source, 0, sizeof(source)); - source.sin_addr.s_addr = ip->saddr; - memset(&dest, 0, sizeof(dest)); - dest.sin_addr.s_addr = ip->daddr; - - printf("IP header\n"); - printf("\t|- Version %d\n",(unsigned int)ip->version); - printf("\t|- Internet hlen %d DWORDS or %d Bytes\n",(unsigned int)ip->ihl,((unsigned int)(ip->ihl))*4); - printf("\t|- Type Of Service %d\n",(unsigned int)ip->tos); - printf("\t|- Total Length %d Bytes\n",ntohs(ip->tot_len)); - printf("\t|- Identification %d\n",ntohs(ip->id)); - printf("\t|- Time To Live %d\n",(unsigned int)ip->ttl); - printf("\t|- Protocol %d\n",(unsigned int)ip->protocol); - printf("\t|- Header Checksum %d\n",ntohs(ip->check)); - printf("\t|- Source IP %s\n", inet_ntoa(source.sin_addr)); - printf("\t|- Destination IP %s\n",inet_ntoa(dest.sin_addr)); - - printf("\n"); - } - + printf("Loaded configuration:\n"); + // For each bond of config->bonds + struct pmlag_bond *bond = config->bonds; + struct pmlag_interface *iface; + while(bond) { + printf("\n%s:\n", bond->name); + printf(" mode: %s\n", ( + bond->mode == PMLAG_MODE_NONE + ? "NONE" + : ( + bond->mode == PMLAG_MODE_BROADCAST + ? "BROADCAST" + : ( + bond->mode == PMLAG_MODE_BALANCED_RR + ? "BROADCAST" + : "ACTIVE_BACKUP" + ) + ) + )); + iface = bond->interfaces; + // For each iface of config->interfaces + while(iface) { + printf("\n %s:\n", iface->name); + printf(" weight: %d\n", iface->weight); + iface = iface->next; } - + bond = bond->next; } - if (tx) { - - // Prepare egress buffer - int buflen; - unsigned char *buffer = (unsigned char *) malloc(65536); - memset(buffer, 0, 65536); - struct sockaddr_ll saddr; - int saddr_len = sizeof(saddr); - - // Get MAC address of the interface - struct ifreq ifreq_c; - memset(&ifreq_c,0,sizeof(ifreq_c)); - strncpy(ifreq_c.ifr_name,INTERFACE,IFNAMSIZ-1);//giving name of Interface - if((ioctl(sockfd,SIOCGIFHWADDR,&ifreq_c))<0) { - perror("error in SIOCGIFHWADDR ioctl reading"); - return 1; - } + /* int sockfd = sockraw_open(INTERFACE); */ + /* if (sockfd < 0) { */ + /* return 1; */ + /* } */ - // Get ethhdr reference to the buffer - struct ethhdr *eth = (struct ethhdr *)(buffer); - - // Fill ethernet source address - memcpy(eth->h_source, ifreq_c.ifr_hwaddr.sa_data, 6); - /* eth->h_source[0] = (unsigned char)(ifreq_c.ifr_hwaddr.sa_data[0]); */ - /* eth->h_source[1] = (unsigned char)(ifreq_c.ifr_hwaddr.sa_data[1]); */ - /* eth->h_source[2] = (unsigned char)(ifreq_c.ifr_hwaddr.sa_data[2]); */ - /* eth->h_source[3] = (unsigned char)(ifreq_c.ifr_hwaddr.sa_data[3]); */ - /* eth->h_source[4] = (unsigned char)(ifreq_c.ifr_hwaddr.sa_data[4]); */ - /* eth->h_source[5] = (unsigned char)(ifreq_c.ifr_hwaddr.sa_data[5]); */ - - // Broadcast packet - eth->h_dest[0] = 0xFF; - eth->h_dest[1] = 0xFF; - eth->h_dest[2] = 0xFF; - eth->h_dest[3] = 0xFF; - eth->h_dest[4] = 0xFF; - eth->h_dest[5] = 0xFF; - - // Custom protocol (not shown as registered on https://www.iana.org/assignments/ieee-802-numbers/ieee-802-numbers.xhtml) - eth->h_proto = htons(0x0666); - - struct sockaddr_ll sadr_ll; - sadr_ll.sll_ifindex = iface_idx(sockfd, INTERFACE); - sadr_ll.sll_halen = ETH_ALEN; // length of destination mac address - memcpy(sadr_ll.sll_addr, eth->h_dest, ETH_ALEN); - - /* sadr_ll.sll_addr[0] = 0xFF; */ - /* sadr_ll.sll_addr[1] = 0xFF; */ - /* sadr_ll.sll_addr[2] = 0xFF; */ - /* sadr_ll.sll_addr[3] = 0xFF; */ - /* sadr_ll.sll_addr[4] = 0xFF; */ - /* sadr_ll.sll_addr[5] = 0xFF; */ - - /* saddr.sll_ifindex = ifreq_i.ifr_ifindex; // index of interface */ - /* saddr.sll_halen = ETH_ALEN; // length of destination mac address */ - /* saddr.sll_addr[0] = DESTMAC0; */ - /* saddr.sll_addr[1] = DESTMAC1; */ - /* saddr.sll_addr[2] = DESTMAC2; */ - /* saddr.sll_addr[3] = DESTMAC3; */ - /* saddr.sll_addr[4] = DESTMAC4; */ - /* saddr.sll_addr[5] = DESTMAC5; */ - - - int send_len = sendto(sockfd,buffer,64,0,(const struct sockaddr*)&sadr_ll,sizeof(struct sockaddr_ll)); - if(send_len<0) { - printf("error in sending....sendlen=%d....errno=%d\n",send_len,errno); - return -1; - } + /* if (rx) { */ + +/* // Prepare ingress buffer */ +/* int buflen; */ +/* unsigned char *buffer = (unsigned char *) malloc(65536); */ +/* memset(buffer, 0, 65536); */ +/* struct sockaddr saddr; */ +/* int saddr_len = sizeof(saddr); */ + +/* struct ethhdr *eth = (struct ethhdr *)(buffer); */ +/* struct sockaddr_in source; */ +/* struct sockaddr_in dest; */ + +/* while(1) { */ + +/* // Fetch a packet */ +/* buflen = recvfrom(sockfd, buffer, 65536, 0, &saddr, (socklen_t *)&saddr_len); */ +/* if (buflen < 0) { */ +/* perror("recvfrom"); */ +/* exit(EXIT_FAILURE); */ +/* } */ + +/* 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",eth->h_dest[0],eth->h_dest[1],eth->h_dest[2],eth->h_dest[3],eth->h_dest[4],eth->h_dest[5]); */ +/* printf("\t|- SRC %.2X-%.2X-%.2X-%.2X-%.2X-%.2X\n",eth->h_source[0],eth->h_source[1],eth->h_source[2],eth->h_source[3],eth->h_source[4],eth->h_source[5]); */ +/* printf("\t|- PROTO %.4X\n",be16toh(eth->h_proto)); */ + +/* printf("\n"); */ + +/* if (be16toh(eth->h_proto) == 0x0800) { */ +/* unsigned short iphdrlen; */ +/* struct iphdr *ip = (struct iphdr*)(buffer + sizeof(struct ethhdr)); */ +/* memset(&source, 0, sizeof(source)); */ +/* source.sin_addr.s_addr = ip->saddr; */ +/* memset(&dest, 0, sizeof(dest)); */ +/* dest.sin_addr.s_addr = ip->daddr; */ + +/* printf("IP header\n"); */ +/* printf("\t|- Version %d\n",(unsigned int)ip->version); */ +/* printf("\t|- Internet hlen %d DWORDS or %d Bytes\n",(unsigned int)ip->ihl,((unsigned int)(ip->ihl))*4); */ +/* printf("\t|- Type Of Service %d\n",(unsigned int)ip->tos); */ +/* printf("\t|- Total Length %d Bytes\n",ntohs(ip->tot_len)); */ +/* printf("\t|- Identification %d\n",ntohs(ip->id)); */ +/* printf("\t|- Time To Live %d\n",(unsigned int)ip->ttl); */ +/* printf("\t|- Protocol %d\n",(unsigned int)ip->protocol); */ +/* printf("\t|- Header Checksum %d\n",ntohs(ip->check)); */ +/* printf("\t|- Source IP %s\n", inet_ntoa(source.sin_addr)); */ +/* printf("\t|- Destination IP %s\n",inet_ntoa(dest.sin_addr)); */ + +/* printf("\n"); */ +/* } */ + +/* } */ - printf("Hello there!\n"); - } + /* } */ + + /* if (tx) { */ + +/* // Prepare egress buffer */ +/* int buflen; */ +/* unsigned char *buffer = (unsigned char *) malloc(65536); */ +/* memset(buffer, 0, 65536); */ +/* struct sockaddr_ll saddr; */ +/* int saddr_len = sizeof(saddr); */ + +/* // Get MAC address of the interface */ +/* struct ifreq ifreq_c; */ +/* memset(&ifreq_c,0,sizeof(ifreq_c)); */ +/* strncpy(ifreq_c.ifr_name,INTERFACE,IFNAMSIZ-1);//giving name of Interface */ +/* if((ioctl(sockfd,SIOCGIFHWADDR,&ifreq_c))<0) { */ +/* perror("error in SIOCGIFHWADDR ioctl reading"); */ +/* return 1; */ +/* } */ + +/* // Get ethhdr reference to the buffer */ +/* struct ethhdr *eth = (struct ethhdr *)(buffer); */ + +/* // Fill ethernet source address */ +/* memcpy(eth->h_source, ifreq_c.ifr_hwaddr.sa_data, 6); */ +/* /1* eth->h_source[0] = (unsigned char)(ifreq_c.ifr_hwaddr.sa_data[0]); *1/ */ +/* /1* eth->h_source[1] = (unsigned char)(ifreq_c.ifr_hwaddr.sa_data[1]); *1/ */ +/* /1* eth->h_source[2] = (unsigned char)(ifreq_c.ifr_hwaddr.sa_data[2]); *1/ */ +/* /1* eth->h_source[3] = (unsigned char)(ifreq_c.ifr_hwaddr.sa_data[3]); *1/ */ +/* /1* eth->h_source[4] = (unsigned char)(ifreq_c.ifr_hwaddr.sa_data[4]); *1/ */ +/* /1* eth->h_source[5] = (unsigned char)(ifreq_c.ifr_hwaddr.sa_data[5]); *1/ */ + +/* // Broadcast packet */ +/* eth->h_dest[0] = 0xFF; */ +/* eth->h_dest[1] = 0xFF; */ +/* eth->h_dest[2] = 0xFF; */ +/* eth->h_dest[3] = 0xFF; */ +/* eth->h_dest[4] = 0xFF; */ +/* eth->h_dest[5] = 0xFF; */ + +/* // Custom protocol (not shown as registered on https://www.iana.org/assignments/ieee-802-numbers/ieee-802-numbers.xhtml) */ +/* eth->h_proto = htons(0x0666); */ + +/* struct sockaddr_ll sadr_ll; */ +/* sadr_ll.sll_ifindex = iface_idx(sockfd, INTERFACE); */ +/* sadr_ll.sll_halen = ETH_ALEN; // length of destination mac address */ +/* memcpy(sadr_ll.sll_addr, eth->h_dest, ETH_ALEN); */ + +/* /1* sadr_ll.sll_addr[0] = 0xFF; *1/ */ +/* /1* sadr_ll.sll_addr[1] = 0xFF; *1/ */ +/* /1* sadr_ll.sll_addr[2] = 0xFF; *1/ */ +/* /1* sadr_ll.sll_addr[3] = 0xFF; *1/ */ +/* /1* sadr_ll.sll_addr[4] = 0xFF; *1/ */ +/* /1* sadr_ll.sll_addr[5] = 0xFF; *1/ */ + +/* /1* saddr.sll_ifindex = ifreq_i.ifr_ifindex; // index of interface *1/ */ +/* /1* saddr.sll_halen = ETH_ALEN; // length of destination mac address *1/ */ +/* /1* saddr.sll_addr[0] = DESTMAC0; *1/ */ +/* /1* saddr.sll_addr[1] = DESTMAC1; *1/ */ +/* /1* saddr.sll_addr[2] = DESTMAC2; *1/ */ +/* /1* saddr.sll_addr[3] = DESTMAC3; *1/ */ +/* /1* saddr.sll_addr[4] = DESTMAC4; *1/ */ +/* /1* saddr.sll_addr[5] = DESTMAC5; *1/ */ + + +/* int send_len = sendto(sockfd,buffer,60,0,(const struct sockaddr*)&sadr_ll,sizeof(struct sockaddr_ll)); */ +/* if(send_len<0) { */ +/* printf("error in sending....sendlen=%d....errno=%d\n",send_len,errno); */ +/* return -1; */ +/* } */ + + /* } */ - printf("name: %s\n", __NAME); - printf("conf: %s\n", config_file); - printf("sock: %d\n", sockfd); + /* printf("name: %s\n", __NAME); */ + /* printf("conf: %s\n", config_file); */ + /* printf("sock: %d\n", sockfd); */ return 42; } diff --git a/src/socket.c b/src/socket.c @@ -0,0 +1,57 @@ +#include <linux/if_ether.h> +#include <linux/if_packet.h> +#include <net/if.h> +#include <netinet/in.h> +#include <string.h> +#include <strings.h> +#include <sys/ioctl.h> +#include <stdio.h> +#include <sys/socket.h> +#include <unistd.h> + +#include "socket.h" + +int iface_idx(int sockfd, char * ifname) { + struct ifreq ifr; + bzero(&ifr, sizeof(ifr)); + + // Get interface index + strncpy((char *)ifr.ifr_name, ifname, IFNAMSIZ); + if ((ioctl(sockfd, SIOCGIFINDEX, &ifr)) == -1) { + perror("Error getting interface index"); + close(sockfd); + return -1; + } + + return ifr.ifr_ifindex; +} + +int sockraw_open(char * ifname) { + + // Open socket + int sockfd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); + if (sockfd < 0) { + perror("Error opening socket"); + close(sockfd); + return -1; + } + + // Bind socket to interface + struct sockaddr_ll sll; + bzero(&sll, sizeof(sll)); + sll.sll_family = AF_PACKET; + sll.sll_ifindex = iface_idx(sockfd, ifname); + sll.sll_protocol = htons(ETH_P_ALL); + if (sll.sll_ifindex < 0) { + // Error already printed, not reprinting + return -1; + } + if((bind(sockfd, (struct sockaddr *)&sll, sizeof(sll))) == -1) { + perror("Error binding raw socket to interface"); + close(sockfd); + return -1; + } + + // Return the prepared socket + return sockfd; +} diff --git a/src/socket.h b/src/socket.h @@ -0,0 +1,15 @@ +#ifndef __PMLAG_SOCKET_H__ +#define __PMLAG_SOCKET_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +int sockraw_open(char * ifname); +int iface_idx(int sockfd, char * ifname); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // __PMLAG_SOCKET_H__ diff --git a/test.ini b/test.ini @@ -0,0 +1,23 @@ +; This is an example configuration, showcasing how you might configure multiple types of bonds + +; eth0 = backup, eth1 = primary +[bond0] +mode=active-backup +interface=eth0 +weight=10 +interface=eth1 +weight=25 + +; broadcast everything on all interfaces +[bond1] +mode=broadcast +interface=eth2 +interface=eth3 + +; use both at the same time +[bond2] +mode=balanced-rr +interface=eth4 +weight=10 +interface=eth5 +weight=25