107 lines
3.1 KiB
C
107 lines
3.1 KiB
C
/*
|
|
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"
|
|
#include "send.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;
|
|
neigh->iface = iface;
|
|
iface->neigh_list = neigh;
|
|
neigh->addr = *addr;
|
|
|
|
neigh->txcost = 0xffff;
|
|
}
|
|
|
|
return neigh;
|
|
}
|
|
|
|
void ffd_neigh_unref_list(ffd_neigh_t *neigh) {
|
|
ffd_neigh_t *next;
|
|
for (; neigh; neigh = next) {
|
|
next = neigh->next;
|
|
|
|
neigh->iface = NULL;
|
|
neigh->next = NULL;
|
|
|
|
if (!neigh->ref)
|
|
free(neigh);
|
|
}
|
|
}
|
|
|
|
void ffd_neigh_unref(ffd_neigh_t *neigh) {
|
|
if (!(--neigh->ref) && !neigh->iface)
|
|
free(neigh);
|
|
}
|
|
|
|
uint16_t ffd_neigh_get_rxcost(const ffd_neigh_t *neigh) {
|
|
if (!neigh->hello_log || !neigh->hello_interval || !neigh->iface)
|
|
return 0xffff;
|
|
|
|
int timediff = timespec_diff(&now, &neigh->last_hello);
|
|
int shift = (timediff - neigh->hello_interval/2)/neigh->hello_interval;
|
|
|
|
if (shift >= 16)
|
|
return 0xffff;
|
|
|
|
int received = __builtin_popcount((neigh->hello_log << shift) & 0xffff);
|
|
|
|
if (received == 0)
|
|
return 0xffff;
|
|
else
|
|
return (0x1000/received);
|
|
}
|
|
|
|
uint16_t ffd_neigh_get_txcost(const ffd_neigh_t *neigh) {
|
|
if (timespec_diff(&now, &neigh->last_ihu) > FFD_IHU_TIMEOUT(neigh->ihu_interval) || !neigh->iface)
|
|
return 0xffff;
|
|
else
|
|
return neigh->txcost;
|
|
}
|
|
|
|
uint16_t ffd_neigh_get_cost(const ffd_neigh_t *neigh) {
|
|
if (!neigh) /* self */
|
|
return 0;
|
|
|
|
uint16_t txcost = ffd_neigh_get_txcost(neigh);
|
|
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, FFD_NODE_ID_UNSPEC, 0, 0, true /* XXX change this later */);
|
|
}
|