Restructure source files
This commit is contained in:
parent
ae4505db19
commit
e03169f859
6 changed files with 288 additions and 152 deletions
|
@ -2,7 +2,9 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${FFD_BINARY_DIR} ${CMAKE_CURREN
|
|||
|
||||
add_executable(ffd
|
||||
ffd.c
|
||||
neigh.c
|
||||
netif.c
|
||||
send.c
|
||||
tlv.c
|
||||
util.c
|
||||
)
|
||||
|
|
169
ffd/ffd.c
169
ffd/ffd.c
|
@ -25,6 +25,7 @@
|
|||
|
||||
|
||||
#include "ffd.h"
|
||||
#include "neigh.h"
|
||||
#include "netif.h"
|
||||
#include "packet.h"
|
||||
#include "tlv.h"
|
||||
|
@ -40,24 +41,17 @@
|
|||
#include <netpacket/packet.h>
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <sys/uio.h>
|
||||
|
||||
|
||||
#define FFD_PROTO 0xffd
|
||||
|
||||
static const eth_addr_t ffd_addr = {{0x03, 0x00, 0x00, 0x00, 0x0f, 0xfd}};
|
||||
|
||||
#define HELLO_INTERVAL 400
|
||||
#define IHU_INTERVAL (3*HELLO_INTERVAL)
|
||||
#define PACKET_MAX 1000
|
||||
const eth_addr_t ffd_addr = {{0x03, 0x00, 0x00, 0x00, 0x0f, 0xfd}};
|
||||
|
||||
|
||||
static char *mesh = "bat0";
|
||||
|
||||
static int sockfd;
|
||||
static struct timespec now;
|
||||
int sockfd;
|
||||
struct timespec now;
|
||||
|
||||
static ffd_iface_t *iface_list = NULL;
|
||||
ffd_iface_t *iface_list = NULL;
|
||||
|
||||
static ffd_neigh_t self;
|
||||
//static ffd_orig_t own_data;
|
||||
|
@ -156,62 +150,6 @@ static void update_netif(const char *ifname, unsigned ifindex, void *arg) {
|
|||
iface->addr = netif_get_eth_addr(ifname);
|
||||
}
|
||||
|
||||
static inline ffd_neigh_t* get_neigh(const ffd_iface_t *iface, const eth_addr_t *addr) {
|
||||
ffd_neigh_t *neigh;
|
||||
for (neigh = iface->neigh_list; neigh; neigh = neigh->next) {
|
||||
if (are_eth_addrs_equal(addr, &neigh->addr))
|
||||
return neigh;
|
||||
}
|
||||
|
||||
return neigh;
|
||||
}
|
||||
|
||||
static ffd_neigh_t* get_neigh_create(ffd_iface_t *iface, const eth_addr_t *addr) {
|
||||
ffd_neigh_t *neigh = get_neigh(iface, addr);
|
||||
if (!neigh) {
|
||||
neigh = calloc(1, sizeof(ffd_neigh_t));
|
||||
neigh->next = iface->neigh_list;
|
||||
iface->neigh_list = neigh;
|
||||
neigh->addr = *addr;
|
||||
|
||||
neigh->txcost = 0xffff;
|
||||
}
|
||||
|
||||
return neigh;
|
||||
}
|
||||
|
||||
static void free_neighs(ffd_neigh_t *neigh) {
|
||||
ffd_neigh_t *next;
|
||||
for (; neigh; neigh = next) {
|
||||
next = neigh->next;
|
||||
free(neigh);
|
||||
}
|
||||
}
|
||||
|
||||
static uint16_t get_neigh_rxcost(const ffd_neigh_t *neigh) {
|
||||
int timediff = timespec_diff(&now, &neigh->last_hello)/10;
|
||||
int shift = (timediff - neigh->hello_interval/2)/neigh->hello_interval;
|
||||
int received = __builtin_popcount(neigh->hello_log << shift);
|
||||
|
||||
if (received == 0)
|
||||
return 0xffff;
|
||||
else
|
||||
return (0x1000/received);
|
||||
}
|
||||
|
||||
static uint16_t get_neigh_cost(const ffd_neigh_t *neigh) {
|
||||
uint16_t txcost = neigh->txcost;
|
||||
if (txcost < 256)
|
||||
txcost = 256;
|
||||
|
||||
uint32_t cost = (txcost * get_neigh_rxcost(neigh)) >> 8;
|
||||
|
||||
if (cost > 0xffff)
|
||||
return 0xffff;
|
||||
else
|
||||
return cost;
|
||||
}
|
||||
|
||||
static void update_netifs() {
|
||||
ffd_iface_t *iface, **cur;
|
||||
|
||||
|
@ -227,7 +165,7 @@ static void update_netifs() {
|
|||
if (iface->type == IF_UNSPEC) {
|
||||
*cur = iface->next;
|
||||
|
||||
free_neighs(iface->neigh_list);
|
||||
ffd_neigh_free_list(iface->neigh_list);
|
||||
free(iface);
|
||||
}
|
||||
else {
|
||||
|
@ -236,82 +174,6 @@ static void update_netifs() {
|
|||
}
|
||||
}
|
||||
|
||||
static bool send_eth(const eth_addr_t *addr, unsigned ifindex, void *buf, size_t len) {
|
||||
static const uint8_t zeros[46] = {0};
|
||||
|
||||
struct sockaddr_ll sa;
|
||||
memset(&sa, 0, sizeof(sa));
|
||||
sa.sll_family = AF_PACKET;
|
||||
sa.sll_protocol = htons(FFD_PROTO);
|
||||
sa.sll_ifindex = ifindex;
|
||||
sa.sll_halen = ETH_ALEN;
|
||||
memcpy(sa.sll_addr, addr->d, ETH_ALEN);
|
||||
|
||||
struct iovec vec[2] = {
|
||||
{ .iov_base = buf, .iov_len = len },
|
||||
{ .iov_base = (void*)zeros, .iov_len = sizeof(zeros) - len },
|
||||
};
|
||||
|
||||
struct msghdr msg;
|
||||
memset(&msg, 0, sizeof(msg));
|
||||
msg.msg_name = &sa;
|
||||
msg.msg_namelen = sizeof(sa);
|
||||
msg.msg_iov = vec;
|
||||
msg.msg_iovlen = (len < 46) ? 2 : 1;
|
||||
|
||||
|
||||
while (sendmsg(sockfd, &msg, 0) < 0) {
|
||||
if (errno != EINTR)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void add_ihus(ffd_packet_t *packet, size_t max_len, const ffd_iface_t *iface) {
|
||||
const ffd_neigh_t *neigh;
|
||||
|
||||
for (neigh = iface->neigh_list; neigh; neigh = neigh->next) {
|
||||
ffd_tlv_ihu_t *ihu = ffd_tlv_add(packet, PACKET_MAX, TLV_IHU, sizeof(ffd_tlv_ihu_t)+sizeof(eth_addr_t));
|
||||
if (!ihu)
|
||||
return;
|
||||
|
||||
ihu->ae = ADDR_ENC_ETH;
|
||||
ihu->reserved = 0;
|
||||
ihu->rxcost = htons(get_neigh_rxcost(neigh));
|
||||
ihu->interval = htons(IHU_INTERVAL);
|
||||
memcpy(ihu->address, &neigh->addr, sizeof(eth_addr_t));
|
||||
}
|
||||
}
|
||||
|
||||
static void send_hellos() {
|
||||
ffd_packet_t *packet = alloca(sizeof(ffd_packet_t)+PACKET_MAX);
|
||||
|
||||
packet->version_magic = htons(FFD_VERSION_MAGIC);
|
||||
packet->len = 0;
|
||||
|
||||
ffd_tlv_hello_t *hello = ffd_tlv_add(packet, PACKET_MAX, TLV_HELLO, sizeof(ffd_tlv_hello_t));
|
||||
if (!hello)
|
||||
return;
|
||||
|
||||
hello->reserved = 0;
|
||||
hello->interval = htons(HELLO_INTERVAL);
|
||||
|
||||
uint16_t len = packet->len;
|
||||
|
||||
ffd_iface_t *iface;
|
||||
for (iface = iface_list; iface; iface = iface->next) {
|
||||
hello->seqno = htons(iface->seqno++);
|
||||
|
||||
packet->len = len;
|
||||
|
||||
add_ihus(packet, PACKET_MAX, iface);
|
||||
|
||||
if (!send_eth(&ffd_addr, iface->ifindex, packet, sizeof(ffd_packet_t)+ntohs(packet->len)))
|
||||
fprintf(stderr, "send_eth: %m\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void handle_tlv_hello(const ffd_tlv_hello_t *tlv_hello, size_t len, const eth_addr_t *addr, ffd_iface_t *iface) {
|
||||
if (len < sizeof(ffd_tlv_hello_t)) {
|
||||
fprintf(stderr, "warn: received short hello TLV.\n");
|
||||
|
@ -320,7 +182,7 @@ static void handle_tlv_hello(const ffd_tlv_hello_t *tlv_hello, size_t len, const
|
|||
|
||||
fprintf(stderr, "debug: received hello with seqno %u.\n", ntohs(tlv_hello->seqno));
|
||||
|
||||
ffd_neigh_t *neigh = get_neigh_create(iface, addr);
|
||||
ffd_neigh_t *neigh = ffd_neigh_get(iface, addr);
|
||||
|
||||
uint16_t seqno = ntohs(tlv_hello->seqno);
|
||||
|
||||
|
@ -352,7 +214,10 @@ static void handle_tlv_hello(const ffd_tlv_hello_t *tlv_hello, size_t len, const
|
|||
neigh->last_seqno = seqno;
|
||||
neigh->last_hello = now;
|
||||
|
||||
fprintf(stderr, "debug: accepted hello, log %04x, rxcost is %u, cost is %u now.\n", neigh->hello_log, get_neigh_rxcost(neigh), get_neigh_cost(neigh));
|
||||
if (neigh->hello_log == 1) /* new or reset neighbour */
|
||||
ffd_neigh_reset(iface, neigh);
|
||||
|
||||
fprintf(stderr, "debug: accepted hello, log %04x, rxcost is %u, cost is %u now.\n", neigh->hello_log, ffd_neigh_get_rxcost(neigh), ffd_neigh_get_cost(neigh));
|
||||
}
|
||||
|
||||
static void handle_tlv_ihu(const ffd_tlv_ihu_t *tlv_ihu, size_t len, const eth_addr_t *addr, ffd_iface_t *iface) {
|
||||
|
@ -374,11 +239,11 @@ static void handle_tlv_ihu(const ffd_tlv_ihu_t *tlv_ihu, size_t len, const eth_a
|
|||
return;
|
||||
}
|
||||
|
||||
ffd_neigh_t *neigh = get_neigh_create(iface, addr);
|
||||
ffd_neigh_t *neigh = ffd_neigh_get(iface, addr);
|
||||
neigh->last_ihu = now;
|
||||
neigh->txcost = ntohs(tlv_ihu->rxcost);
|
||||
|
||||
fprintf(stderr, "debug: accepted IHU, txcost is %u, cost is %u now.\n", neigh->txcost, get_neigh_cost(neigh));
|
||||
fprintf(stderr, "debug: accepted IHU, txcost is %u, cost is %u now.\n", neigh->txcost, ffd_neigh_get_cost(neigh));
|
||||
}
|
||||
|
||||
static void handle_tlv(ffd_tlv_type_t type, const void *data, size_t len, void *arg) {
|
||||
|
@ -405,11 +270,11 @@ static void handle_tlv(ffd_tlv_type_t type, const void *data, size_t len, void *
|
|||
}
|
||||
|
||||
static void receive_packet() {
|
||||
ffd_packet_t *packet = alloca(sizeof(ffd_packet_t)+PACKET_MAX);
|
||||
ffd_packet_t *packet = alloca(sizeof(ffd_packet_t)+FFD_PACKET_MAX);
|
||||
struct sockaddr_ll from;
|
||||
socklen_t fromlen = sizeof(from);
|
||||
|
||||
ssize_t readlen = recvfrom(sockfd, packet, sizeof(ffd_packet_t)+PACKET_MAX, 0, (struct sockaddr*)&from, &fromlen);
|
||||
ssize_t readlen = recvfrom(sockfd, packet, sizeof(ffd_packet_t)+FFD_PACKET_MAX, 0, (struct sockaddr*)&from, &fromlen);
|
||||
|
||||
if (readlen < 0) {
|
||||
fprintf(stderr, "error: recvfrom: %m\n");
|
||||
|
@ -458,9 +323,9 @@ int main() {
|
|||
int timeout = timespec_diff(&next_hello, &now);
|
||||
|
||||
if (timeout <= 0) {
|
||||
send_hellos();
|
||||
ffd_send_hellos();
|
||||
|
||||
add_interval(&next_hello, HELLO_INTERVAL);
|
||||
add_interval(&next_hello, FFD_HELLO_INTERVAL);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
20
ffd/ffd.h
20
ffd/ffd.h
|
@ -33,6 +33,14 @@
|
|||
#include <net/if.h>
|
||||
|
||||
|
||||
#define FFD_PACKET_MAX 1000
|
||||
|
||||
#define FFD_PROTO 0xffd
|
||||
|
||||
#define FFD_HELLO_INTERVAL 400
|
||||
#define FFD_IHU_INTERVAL (3*FFD_HELLO_INTERVAL)
|
||||
|
||||
|
||||
typedef struct _ffd_announce_t {
|
||||
struct _ffd_announce_t *next;
|
||||
|
||||
|
@ -68,4 +76,16 @@ typedef struct _ffd_iface_t {
|
|||
ffd_neigh_t *neigh_list;
|
||||
} ffd_iface_t;
|
||||
|
||||
|
||||
extern const eth_addr_t ffd_addr;
|
||||
|
||||
extern ffd_iface_t *iface_list;
|
||||
|
||||
extern int sockfd;
|
||||
extern struct timespec now;
|
||||
|
||||
|
||||
void ffd_send_hellos();
|
||||
void ffd_send_announce_request(ffd_iface_t *iface, ffd_neigh_t *neigh, void *announce);
|
||||
|
||||
#endif /* _FFD_FFD_H_ */
|
||||
|
|
78
ffd/neigh.c
Normal file
78
ffd/neigh.c
Normal file
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
Copyright (c) 2012, Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
#include "neigh.h"
|
||||
|
||||
|
||||
ffd_neigh_t* ffd_neigh_get(ffd_iface_t *iface, const eth_addr_t *addr) {
|
||||
ffd_neigh_t *neigh = ffd_neigh_find(iface, addr);
|
||||
if (!neigh) {
|
||||
neigh = calloc(1, sizeof(ffd_neigh_t));
|
||||
neigh->next = iface->neigh_list;
|
||||
iface->neigh_list = neigh;
|
||||
neigh->addr = *addr;
|
||||
|
||||
neigh->txcost = 0xffff;
|
||||
}
|
||||
|
||||
return neigh;
|
||||
}
|
||||
|
||||
void ffd_neigh_free_list(ffd_neigh_t *neigh) {
|
||||
ffd_neigh_t *next;
|
||||
for (; neigh; neigh = next) {
|
||||
next = neigh->next;
|
||||
free(neigh);
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t ffd_neigh_get_rxcost(const ffd_neigh_t *neigh) {
|
||||
int timediff = timespec_diff(&now, &neigh->last_hello)/10;
|
||||
int shift = (timediff - neigh->hello_interval/2)/neigh->hello_interval;
|
||||
int received = __builtin_popcount(neigh->hello_log << shift);
|
||||
|
||||
if (received == 0)
|
||||
return 0xffff;
|
||||
else
|
||||
return (0x1000/received);
|
||||
}
|
||||
|
||||
uint16_t ffd_neigh_get_cost(const ffd_neigh_t *neigh) {
|
||||
uint16_t txcost = neigh->txcost;
|
||||
if (txcost < 256)
|
||||
txcost = 256;
|
||||
|
||||
uint32_t cost = (txcost * ffd_neigh_get_rxcost(neigh)) >> 8;
|
||||
|
||||
if (cost > 0xffff)
|
||||
return 0xffff;
|
||||
else
|
||||
return cost;
|
||||
}
|
||||
|
||||
void ffd_neigh_reset(ffd_iface_t *iface, ffd_neigh_t *neigh) {
|
||||
ffd_send_announce_request(iface, neigh, NULL);
|
||||
}
|
50
ffd/neigh.h
Normal file
50
ffd/neigh.h
Normal file
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
Copyright (c) 2012, Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _FFD_NEIGH_H_
|
||||
#define _FFD_NEIGH_H_
|
||||
|
||||
#include "ffd.h"
|
||||
|
||||
|
||||
static inline ffd_neigh_t* ffd_neigh_find(const ffd_iface_t *iface, const eth_addr_t *addr) {
|
||||
ffd_neigh_t *neigh;
|
||||
for (neigh = iface->neigh_list; neigh; neigh = neigh->next) {
|
||||
if (are_eth_addrs_equal(addr, &neigh->addr))
|
||||
return neigh;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ffd_neigh_t* ffd_neigh_get(ffd_iface_t *iface, const eth_addr_t *addr);
|
||||
void ffd_neigh_free_list(ffd_neigh_t *neigh);
|
||||
|
||||
uint16_t ffd_neigh_get_rxcost(const ffd_neigh_t *neigh);
|
||||
uint16_t ffd_neigh_get_cost(const ffd_neigh_t *neigh);
|
||||
void ffd_neigh_reset(ffd_iface_t *iface, ffd_neigh_t *neigh);
|
||||
|
||||
#endif /* _FFD_NEIGH_H_ */
|
121
ffd/send.c
Normal file
121
ffd/send.c
Normal file
|
@ -0,0 +1,121 @@
|
|||
/*
|
||||
Copyright (c) 2012, Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
#include "ffd.h"
|
||||
#include "neigh.h"
|
||||
#include "packet.h"
|
||||
#include "tlv.h"
|
||||
#include "tlv_types.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <netpacket/packet.h>
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <sys/uio.h>
|
||||
|
||||
|
||||
static bool send_eth(const eth_addr_t *addr, unsigned ifindex, void *buf, size_t len) {
|
||||
static const uint8_t zeros[46] = {0};
|
||||
|
||||
struct sockaddr_ll sa;
|
||||
memset(&sa, 0, sizeof(sa));
|
||||
sa.sll_family = AF_PACKET;
|
||||
sa.sll_protocol = htons(FFD_PROTO);
|
||||
sa.sll_ifindex = ifindex;
|
||||
sa.sll_halen = ETH_ALEN;
|
||||
memcpy(sa.sll_addr, addr->d, ETH_ALEN);
|
||||
|
||||
struct iovec vec[2] = {
|
||||
{ .iov_base = buf, .iov_len = len },
|
||||
{ .iov_base = (void*)zeros, .iov_len = sizeof(zeros) - len },
|
||||
};
|
||||
|
||||
struct msghdr msg;
|
||||
memset(&msg, 0, sizeof(msg));
|
||||
msg.msg_name = &sa;
|
||||
msg.msg_namelen = sizeof(sa);
|
||||
msg.msg_iov = vec;
|
||||
msg.msg_iovlen = (len < 46) ? 2 : 1;
|
||||
|
||||
|
||||
while (sendmsg(sockfd, &msg, 0) < 0) {
|
||||
if (errno != EINTR)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void add_ihus(ffd_packet_t *packet, size_t max_len, const ffd_iface_t *iface) {
|
||||
const ffd_neigh_t *neigh;
|
||||
|
||||
for (neigh = iface->neigh_list; neigh; neigh = neigh->next) {
|
||||
ffd_tlv_ihu_t *ihu = ffd_tlv_add(packet, FFD_PACKET_MAX, TLV_IHU, sizeof(ffd_tlv_ihu_t)+sizeof(eth_addr_t));
|
||||
if (!ihu)
|
||||
return;
|
||||
|
||||
ihu->ae = ADDR_ENC_ETH;
|
||||
ihu->reserved = 0;
|
||||
ihu->rxcost = htons(ffd_neigh_get_rxcost(neigh));
|
||||
ihu->interval = htons(FFD_IHU_INTERVAL);
|
||||
memcpy(ihu->address, &neigh->addr, sizeof(eth_addr_t));
|
||||
}
|
||||
}
|
||||
|
||||
void ffd_send_hellos() {
|
||||
ffd_packet_t *packet = alloca(sizeof(ffd_packet_t)+FFD_PACKET_MAX);
|
||||
|
||||
packet->version_magic = htons(FFD_VERSION_MAGIC);
|
||||
packet->len = 0;
|
||||
|
||||
ffd_tlv_hello_t *hello = ffd_tlv_add(packet, FFD_PACKET_MAX, TLV_HELLO, sizeof(ffd_tlv_hello_t));
|
||||
if (!hello)
|
||||
return;
|
||||
|
||||
hello->reserved = 0;
|
||||
hello->interval = htons(FFD_HELLO_INTERVAL);
|
||||
|
||||
uint16_t len = packet->len;
|
||||
|
||||
ffd_iface_t *iface;
|
||||
for (iface = iface_list; iface; iface = iface->next) {
|
||||
hello->seqno = htons(iface->seqno++);
|
||||
|
||||
packet->len = len;
|
||||
|
||||
add_ihus(packet, FFD_PACKET_MAX, iface);
|
||||
|
||||
if (!send_eth(&ffd_addr, iface->ifindex, packet, sizeof(ffd_packet_t)+ntohs(packet->len)))
|
||||
fprintf(stderr, "send_eth: %m\n");
|
||||
}
|
||||
}
|
||||
|
||||
void ffd_send_announce_request(ffd_iface_t *iface, ffd_neigh_t *neigh, void *announce) {
|
||||
|
||||
}
|
Reference in a new issue