diff options
-rw-r--r-- | ffd/announce.c | 25 | ||||
-rw-r--r-- | ffd/ffd.c | 36 | ||||
-rw-r--r-- | ffd/ffd.h | 5 | ||||
-rw-r--r-- | ffd/send.c | 89 |
4 files changed, 109 insertions, 46 deletions
diff --git a/ffd/announce.c b/ffd/announce.c index 151d1b3..ae0a406 100644 --- a/ffd/announce.c +++ b/ffd/announce.c @@ -138,3 +138,28 @@ ffd_announce_t* ffd_announce_new(void) { return a; } + +ffd_announce_t* ffd_announce_find(const ffd_node_id_t *node, uint16_t type, uint16_t key) { + ffd_announce_t *announce; + for (announce = announce_list; announce; announce = announce->next) { + if (ffd_are_node_ids_equal(&announce->node, node) + && announce->type == type + && announce->key == key) + return announce; + } + + return NULL; +} + +ffd_announce_t* ffd_announce_get(const ffd_node_id_t *node, uint16_t type, uint16_t key) { + ffd_announce_t *announce = ffd_announce_find(node, type, key); + + if (!announce) { + announce = ffd_announce_new(); + announce->node = *node; + announce->type = type; + announce->key = key; + } + + return announce; +} @@ -198,7 +198,7 @@ static void handle_tlv_ack_req(const ffd_tlv_ack_req_t *tlv_req, size_t len, han ffd_neigh_t *neigh = get_tlv_neigh(arg); - ffd_send_ack(arg->iface, neigh, ntohs(tlv_req->nonce)); + ffd_send_ack(neigh, ntohs(tlv_req->nonce)); } static void handle_tlv_hello(const ffd_tlv_hello_t *tlv_hello, size_t len, handle_tlv_arg_t *arg) { @@ -284,24 +284,6 @@ static void handle_tlv_node_id(const ffd_tlv_node_id_t *tlv_node_id, size_t len, arg->node_id = tlv_node_id->id; } -static ffd_announce_t* get_announce(const ffd_node_id_t *node, uint16_t type, uint16_t key) { - ffd_announce_t *announce; - for (announce = announce_list; announce; announce = announce->next) { - if (ffd_are_node_ids_equal(&announce->node, node) - && announce->type == type - && announce->key == key) - return announce; - } - - /* not found */ - announce = ffd_announce_new(); - announce->node = *node; - announce->type = type; - announce->key = key; - - return announce; -} - static ffd_nexthop_t* find_nexthop(const ffd_announce_t *announce, ffd_neigh_t *neigh) { ffd_nexthop_t *nexthop; for (nexthop = announce->nexthop_list; nexthop; nexthop = nexthop->next) { @@ -342,7 +324,7 @@ static void handle_tlv_update(const ffd_tlv_update_t *tlv_update, size_t len, ha fprintf(stderr, "debug: update received from %04x%04x.\n", ntohl(*(uint32_t*)arg->node_id.id), ntohl(*(uint32_t*)(arg->node_id.id+4))); - ffd_announce_t *announce = get_announce(&arg->node_id, ntohs(tlv_update->type), ntohs(tlv_update->key)); + ffd_announce_t *announce = ffd_announce_get(&arg->node_id, ntohs(tlv_update->type), ntohs(tlv_update->key)); ffd_metric_seqno_t ms = { ntohs(tlv_update->metric), ntohs(tlv_update->seqno) }; bool feasible = ffd_is_feasible(announce, ms); @@ -387,13 +369,17 @@ static void handle_tlv_announce_req(const ffd_tlv_announce_req_t *tlv_req, size_ return; } - ffd_announce_t *announce = NULL; - - if (!ffd_is_node_id_unspec(&tlv_req->node)) { - announce = NULL; + if (ffd_is_node_id_unspec(&tlv_req->node)) { + ffd_send_update(NULL, get_tlv_neigh(arg), NULL, tlv_req->flags & FFD_UPDATE_WITH_DATA); } + else { + ffd_announce_t *announce = ffd_announce_find(&tlv_req->node, ntohs(tlv_req->type), ntohs(tlv_req->key)); - ffd_send_update(arg->iface, get_tlv_neigh(arg), announce, tlv_req->flags & FFD_UPDATE_WITH_DATA); + if (announce) + ffd_send_update(NULL, get_tlv_neigh(arg), announce, tlv_req->flags & FFD_UPDATE_WITH_DATA); + else + ffd_send_retract(get_tlv_neigh(arg), tlv_req->node, ntohs(tlv_req->type), ntohs(tlv_req->key)); + } } static void handle_tlv(ffd_tlv_type_t type, const void *data, size_t len, void *arg) { @@ -186,10 +186,13 @@ static inline bool ffd_is_feasible(const ffd_announce_t *announce, ffd_metric_se void ffd_announce_update(ffd_announce_t *announce); void ffd_announce_update_nexthop(ffd_announce_t *announce, ffd_nexthop_t *nexthop, ffd_metric_seqno_t ms, uint16_t interval); ffd_announce_t* ffd_announce_new(void); +ffd_announce_t* ffd_announce_find(const ffd_node_id_t *node, uint16_t type, uint16_t key); +ffd_announce_t* ffd_announce_get(const ffd_node_id_t *node, uint16_t type, uint16_t key); -void ffd_send_ack(ffd_iface_t *iface, ffd_neigh_t *neigh, uint16_t nonce); +void ffd_send_ack(ffd_neigh_t *neigh, uint16_t nonce); void ffd_send_hellos(void); void ffd_send_update(ffd_iface_t *iface, ffd_neigh_t *neigh, ffd_announce_t *announce, bool with_data); +void ffd_send_retract(ffd_neigh_t *neigh, ffd_node_id_t node, uint16_t type, uint16_t key); void ffd_send_announce_request(ffd_iface_t *iface, ffd_neigh_t *neigh, ffd_node_id_t node, uint16_t type, uint16_t key, bool with_data); #endif /* _FFD_FFD_H_ */ @@ -40,7 +40,7 @@ #include <sys/uio.h> -static bool send_eth(const eth_addr_t *addr, unsigned ifindex, void *buf, size_t len) { +static bool send_eth(const eth_addr_t *addr, unsigned ifindex, const void *buf, size_t len) { static const uint8_t zeros[46] = {0}; struct sockaddr_ll sa; @@ -52,7 +52,7 @@ static bool send_eth(const eth_addr_t *addr, unsigned ifindex, void *buf, size_t memcpy(sa.sll_addr, addr->d, ETH_ALEN); struct iovec vec[2] = { - { .iov_base = buf, .iov_len = len }, + { .iov_base = (void*)buf, .iov_len = len }, { .iov_base = (void*)zeros, .iov_len = sizeof(zeros) - len }, }; @@ -72,7 +72,43 @@ static bool send_eth(const eth_addr_t *addr, unsigned ifindex, void *buf, size_t return true; } -void ffd_send_ack(ffd_iface_t *iface, ffd_neigh_t *neigh, uint16_t nonce) { +static inline bool send_neigh(const ffd_neigh_t *neigh, const ffd_packet_t *packet) { + if (!neigh->iface) + return false; + + if (!send_eth(&neigh->addr, neigh->iface->ifindex, packet, sizeof(ffd_packet_t)+ntohs(packet->len))) { + fprintf(stderr, "send_eth: %m\n"); + return false; + } + + return true; +} + +static inline bool send_iface(const ffd_iface_t *iface, const ffd_packet_t *packet) { + if (!send_eth(&ffd_addr, iface->ifindex, packet, sizeof(ffd_packet_t)+ntohs(packet->len))) { + fprintf(stderr, "send_eth: %m\n"); + return false; + } + + return true; +} + +static inline void send_broadcast(const ffd_packet_t *packet) { + ffd_iface_t *iface; + for (iface = iface_list; iface; iface = iface->next) + send_iface(iface, packet); +} + +static inline void send_any(const ffd_iface_t *iface, const ffd_neigh_t *neigh, const ffd_packet_t *packet) { + if (neigh) + send_neigh(neigh, packet); + else if(iface) + send_iface(iface, packet); + else + send_broadcast(packet); +} + +void ffd_send_ack(ffd_neigh_t *neigh, uint16_t nonce) { ffd_packet_t *packet = alloca(sizeof(ffd_packet_t)+FFD_PACKET_MAX); packet->version_magic = htons(FFD_VERSION_MAGIC); @@ -84,8 +120,7 @@ void ffd_send_ack(ffd_iface_t *iface, ffd_neigh_t *neigh, uint16_t nonce) { ack->nonce = htons(nonce); - if (!send_eth(&neigh->addr, iface->ifindex, packet, sizeof(ffd_packet_t)+ntohs(packet->len))) - fprintf(stderr, "send_eth: %m\n"); + send_neigh(neigh, packet); } static void add_ihus(ffd_packet_t *packet, size_t max_len, const ffd_iface_t *iface) { @@ -127,8 +162,7 @@ void ffd_send_hellos(void) { 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"); + send_iface(iface, packet); } } @@ -192,11 +226,6 @@ void ffd_send_update(ffd_iface_t *iface, ffd_neigh_t *neigh, ffd_announce_t *ann packet->version_magic = htons(FFD_VERSION_MAGIC); packet->len = 0; - const eth_addr_t *addr = &ffd_addr; - - if (neigh) - addr = &neigh->addr; - if (announce) { add_update(packet, FFD_PACKET_MAX, NULL, announce, with_data); } @@ -206,8 +235,7 @@ void ffd_send_update(ffd_iface_t *iface, ffd_neigh_t *neigh, ffd_announce_t *ann ffd_announce_t *a; for (a = announce_list; a; a = a->next) { if (!add_update(packet, FFD_PACKET_MAX, &node_id, a, with_data)) { - if (!send_eth(addr, iface->ifindex, packet, sizeof(ffd_packet_t)+ntohs(packet->len))) - fprintf(stderr, "send_eth: %m\n"); + send_any(iface, neigh, packet); node_id = FFD_NODE_ID_UNSPEC; packet->len = 0; @@ -220,10 +248,32 @@ void ffd_send_update(ffd_iface_t *iface, ffd_neigh_t *neigh, ffd_announce_t *ann } } - if (packet->len) { - if (!send_eth(addr, iface->ifindex, packet, sizeof(ffd_packet_t)+ntohs(packet->len))) - fprintf(stderr, "send_eth: %m\n"); - } + if (packet->len) + send_any(iface, neigh, packet); +} + +void ffd_send_retract(ffd_neigh_t *neigh, ffd_node_id_t node, uint16_t type, uint16_t key) { + ffd_packet_t *packet = alloca(sizeof(ffd_packet_t)+FFD_PACKET_MAX); + + packet->version_magic = htons(FFD_VERSION_MAGIC); + packet->len = 0; + + if (!add_node_id(packet, FFD_PACKET_MAX, node)) + return; + + ffd_tlv_update_t *req = ffd_tlv_add(packet, FFD_PACKET_MAX, TLV_UPDATE, sizeof(ffd_tlv_update_t)); + if (!req) + return; + + req->flags = 0; + req->reserved = 0; + req->interval = htons(FFD_UPDATE_INTERVAL); + req->seqno = 0; + req->metric = 0xffff; /* no need to htons */ + req->type = htons(type); + req->key = htons(key); + + send_neigh(neigh, packet); } void ffd_send_announce_request(ffd_iface_t *iface, ffd_neigh_t *neigh, ffd_node_id_t node, uint16_t type, uint16_t key, bool with_data) { @@ -245,6 +295,5 @@ void ffd_send_announce_request(ffd_iface_t *iface, ffd_neigh_t *neigh, ffd_node_ if (with_data) req->flags |= FFD_UPDATE_WITH_DATA; - if (!send_eth(&ffd_addr, iface->ifindex, packet, sizeof(ffd_packet_t)+ntohs(packet->len))) - fprintf(stderr, "send_eth: %m\n"); + send_any(iface, neigh, packet); } |