Hi folks,
as some of you already know we are actively working towards the new routing algorithm. Since it is our fifth incarnation we named it "B.A.T.M.A.N. V". The major improvements focus on areas like mobility support, less overhead and faster network convergence. We still are in the early stages of developing the code and finalizing the concept. Interested parties / early birds may contact us to get involved. All others should wait until we issue the call for public testing & feedback.
In order to ensure a smooth transition and efficient testing later, we decided to offer a choice of routing algorithm at compile time. Those who wish to test the new code (once available) can choose it whereas the others can stick with the mature routing code base while enjoying new features / bug fixes outside of the routing algorithm.
As a first step into that direction I worked on a set of patches to assemble all B.A.T.M.A.N. IV related routing code in a single file, accessible via a routing algo API which will also be used by the new code.
Note: Although we have a new file (bat_iv_ogm.c) I kept the previous copyright information because all I did was shuffling the code around. During the process I renamed a few functions here and there but no code was changed.
Regards, Marek
The follow-up routing code changes are going to introduce additional routing packet types which make this distinction necessary.
Signed-off-by: Marek Lindner lindner_marek@yahoo.de --- aggregation.c | 48 +++++++++++--------- aggregation.h | 2 +- hard-interface.c | 49 +++++++++++--------- packet.h | 18 ++++---- routing.c | 118 ++++++++++++++++++++++++++----------------------- routing.h | 2 +- send.c | 130 ++++++++++++++++++++++++++++-------------------------- send.h | 2 +- soft-interface.c | 17 ++++--- 9 files changed, 204 insertions(+), 182 deletions(-)
diff --git a/aggregation.c b/aggregation.c index 69467fe..f20423f 100644 --- a/aggregation.c +++ b/aggregation.c @@ -27,7 +27,8 @@ #include "hard-interface.h"
/* return true if new_packet can be aggregated with forw_packet */ -static bool can_aggregate_with(const struct batman_packet *new_batman_packet, +static bool can_aggregate_with(const struct batman_ogm_packet + *new_batman_ogm_packet, struct bat_priv *bat_priv, int packet_len, unsigned long send_time, @@ -35,8 +36,8 @@ static bool can_aggregate_with(const struct batman_packet *new_batman_packet, const struct hard_iface *if_incoming, const struct forw_packet *forw_packet) { - struct batman_packet *batman_packet = - (struct batman_packet *)forw_packet->skb->data; + struct batman_ogm_packet *batman_ogm_packet = + (struct batman_ogm_packet *)forw_packet->skb->data; int aggregated_bytes = forw_packet->packet_len + packet_len; struct hard_iface *primary_if = NULL; bool res = false; @@ -71,8 +72,8 @@ static bool can_aggregate_with(const struct batman_packet *new_batman_packet, /* packets without direct link flag and high TTL * are flooded through the net */ if ((!directlink) && - (!(batman_packet->flags & DIRECTLINK)) && - (batman_packet->ttl != 1) && + (!(batman_ogm_packet->flags & DIRECTLINK)) && + (batman_ogm_packet->ttl != 1) &&
/* own packets originating non-primary * interfaces leave only that interface */ @@ -85,13 +86,13 @@ static bool can_aggregate_with(const struct batman_packet *new_batman_packet, /* if the incoming packet is sent via this one * interface only - we still can aggregate */ if ((directlink) && - (new_batman_packet->ttl == 1) && + (new_batman_ogm_packet->ttl == 1) && (forw_packet->if_incoming == if_incoming) &&
/* packets from direct neighbors or * own secondary interface packets * (= secondary interface packets in general) */ - (batman_packet->flags & DIRECTLINK || + (batman_ogm_packet->flags & DIRECTLINK || (forw_packet->own && forw_packet->if_incoming != primary_if))) { res = true; @@ -213,9 +214,11 @@ void add_bat_packet_to_list(struct bat_priv *bat_priv, */ struct forw_packet *forw_packet_aggr = NULL, *forw_packet_pos = NULL; struct hlist_node *tmp_node; - struct batman_packet *batman_packet = - (struct batman_packet *)packet_buff; - bool direct_link = batman_packet->flags & DIRECTLINK ? 1 : 0; + struct batman_ogm_packet *batman_ogm_packet; + bool direct_link; + + batman_ogm_packet = (struct batman_ogm_packet *)packet_buff; + direct_link = batman_ogm_packet->flags & DIRECTLINK ? 1 : 0;
/* find position for the packet in the forward queue */ spin_lock_bh(&bat_priv->forw_bat_list_lock); @@ -223,7 +226,7 @@ void add_bat_packet_to_list(struct bat_priv *bat_priv, if ((atomic_read(&bat_priv->aggregated_ogms)) && (!own_packet)) { hlist_for_each_entry(forw_packet_pos, tmp_node, &bat_priv->forw_bat_list, list) { - if (can_aggregate_with(batman_packet, + if (can_aggregate_with(batman_ogm_packet, bat_priv, packet_len, send_time, @@ -267,27 +270,28 @@ void receive_aggr_bat_packet(const struct ethhdr *ethhdr, unsigned char *packet_buff, int packet_len, struct hard_iface *if_incoming) { - struct batman_packet *batman_packet; + struct batman_ogm_packet *batman_ogm_packet; int buff_pos = 0; unsigned char *tt_buff;
- batman_packet = (struct batman_packet *)packet_buff; + batman_ogm_packet = (struct batman_ogm_packet *)packet_buff;
do { /* network to host order for our 32bit seqno and the orig_interval */ - batman_packet->seqno = ntohl(batman_packet->seqno); - batman_packet->tt_crc = ntohs(batman_packet->tt_crc); + batman_ogm_packet->seqno = ntohl(batman_ogm_packet->seqno); + batman_ogm_packet->tt_crc = ntohs(batman_ogm_packet->tt_crc);
- tt_buff = packet_buff + buff_pos + BAT_PACKET_LEN; + tt_buff = packet_buff + buff_pos + BATMAN_OGM_LEN;
- receive_bat_packet(ethhdr, batman_packet, tt_buff, if_incoming); + receive_bat_packet(ethhdr, batman_ogm_packet, + tt_buff, if_incoming);
- buff_pos += BAT_PACKET_LEN + - tt_len(batman_packet->tt_num_changes); + buff_pos += BATMAN_OGM_LEN + + tt_len(batman_ogm_packet->tt_num_changes);
- batman_packet = (struct batman_packet *) - (packet_buff + buff_pos); + batman_ogm_packet = (struct batman_ogm_packet *) + (packet_buff + buff_pos); } while (aggregated_packet(buff_pos, packet_len, - batman_packet->tt_num_changes)); + batman_ogm_packet->tt_num_changes)); } diff --git a/aggregation.h b/aggregation.h index df4a5a9..7fc23b0 100644 --- a/aggregation.h +++ b/aggregation.h @@ -28,7 +28,7 @@ static inline int aggregated_packet(int buff_pos, int packet_len, int tt_num_changes) { - int next_buff_pos = buff_pos + BAT_PACKET_LEN + tt_len(tt_num_changes); + int next_buff_pos = buff_pos + BATMAN_OGM_LEN + tt_len(tt_num_changes);
return (next_buff_pos <= packet_len) && (next_buff_pos <= MAX_AGGREGATION_BYTES); diff --git a/hard-interface.c b/hard-interface.c index bf91e4d..cf9f4af 100644 --- a/hard-interface.c +++ b/hard-interface.c @@ -131,7 +131,7 @@ static void primary_if_select(struct bat_priv *bat_priv, struct hard_iface *new_hard_iface) { struct hard_iface *curr_hard_iface; - struct batman_packet *batman_packet; + struct batman_ogm_packet *batman_ogm_packet;
ASSERT_RTNL();
@@ -147,9 +147,10 @@ static void primary_if_select(struct bat_priv *bat_priv, if (!new_hard_iface) return;
- batman_packet = (struct batman_packet *)(new_hard_iface->packet_buff); - batman_packet->flags = PRIMARIES_FIRST_HOP; - batman_packet->ttl = TTL; + batman_ogm_packet = (struct batman_ogm_packet *) + (new_hard_iface->packet_buff); + batman_ogm_packet->flags = PRIMARIES_FIRST_HOP; + batman_ogm_packet->ttl = TTL;
primary_if_update_addr(bat_priv); } @@ -164,9 +165,12 @@ static bool hardif_is_iface_up(const struct hard_iface *hard_iface)
static void update_mac_addresses(struct hard_iface *hard_iface) { - memcpy(((struct batman_packet *)(hard_iface->packet_buff))->orig, + struct batman_ogm_packet *batman_ogm_packet; + + batman_ogm_packet = (struct batman_ogm_packet *)hard_iface->packet_buff; + memcpy(batman_ogm_packet->orig, hard_iface->net_dev->dev_addr, ETH_ALEN); - memcpy(((struct batman_packet *)(hard_iface->packet_buff))->prev_sender, + memcpy(batman_ogm_packet->prev_sender, hard_iface->net_dev->dev_addr, ETH_ALEN); }
@@ -283,7 +287,7 @@ int hardif_enable_interface(struct hard_iface *hard_iface, const char *iface_name) { struct bat_priv *bat_priv; - struct batman_packet *batman_packet; + struct batman_ogm_packet *batman_ogm_packet; struct net_device *soft_iface; int ret;
@@ -318,7 +322,7 @@ int hardif_enable_interface(struct hard_iface *hard_iface,
hard_iface->soft_iface = soft_iface; bat_priv = netdev_priv(hard_iface->soft_iface); - hard_iface->packet_len = BAT_PACKET_LEN; + hard_iface->packet_len = BATMAN_OGM_LEN; hard_iface->packet_buff = kmalloc(hard_iface->packet_len, GFP_ATOMIC);
if (!hard_iface->packet_buff) { @@ -328,14 +332,15 @@ int hardif_enable_interface(struct hard_iface *hard_iface, goto err; }
- batman_packet = (struct batman_packet *)(hard_iface->packet_buff); - batman_packet->packet_type = BAT_PACKET; - batman_packet->version = COMPAT_VERSION; - batman_packet->flags = NO_FLAGS; - batman_packet->ttl = 2; - batman_packet->tq = TQ_MAX_VALUE; - batman_packet->tt_num_changes = 0; - batman_packet->ttvn = 0; + batman_ogm_packet = (struct batman_ogm_packet *) + (hard_iface->packet_buff); + batman_ogm_packet->packet_type = BAT_OGM; + batman_ogm_packet->version = COMPAT_VERSION; + batman_ogm_packet->flags = NO_FLAGS; + batman_ogm_packet->ttl = 2; + batman_ogm_packet->tq = TQ_MAX_VALUE; + batman_ogm_packet->tt_num_changes = 0; + batman_ogm_packet->ttvn = 0;
hard_iface->if_num = bat_priv->num_ifaces; bat_priv->num_ifaces++; @@ -580,7 +585,7 @@ static int batman_skb_recv(struct sk_buff *skb, struct net_device *dev, struct net_device *orig_dev) { struct bat_priv *bat_priv; - struct batman_packet *batman_packet; + struct batman_ogm_packet *batman_ogm_packet; struct hard_iface *hard_iface; int ret;
@@ -612,21 +617,21 @@ static int batman_skb_recv(struct sk_buff *skb, struct net_device *dev, if (hard_iface->if_status != IF_ACTIVE) goto err_free;
- batman_packet = (struct batman_packet *)skb->data; + batman_ogm_packet = (struct batman_ogm_packet *)skb->data;
- if (batman_packet->version != COMPAT_VERSION) { + if (batman_ogm_packet->version != COMPAT_VERSION) { bat_dbg(DBG_BATMAN, bat_priv, "Drop packet: incompatible batman version (%i)\n", - batman_packet->version); + batman_ogm_packet->version); goto err_free; }
/* all receive handlers return whether they received or reused * the supplied skb. if not, we have to free the skb. */
- switch (batman_packet->packet_type) { + switch (batman_ogm_packet->packet_type) { /* batman originator packet */ - case BAT_PACKET: + case BAT_OGM: ret = recv_bat_packet(skb, hard_iface); break;
diff --git a/packet.h b/packet.h index 8802eab..4d9e54c 100644 --- a/packet.h +++ b/packet.h @@ -25,14 +25,14 @@ #define ETH_P_BATMAN 0x4305 /* unofficial/not registered Ethertype */
enum bat_packettype { - BAT_PACKET = 0x01, - BAT_ICMP = 0x02, - BAT_UNICAST = 0x03, - BAT_BCAST = 0x04, - BAT_VIS = 0x05, + BAT_OGM = 0x01, + BAT_ICMP = 0x02, + BAT_UNICAST = 0x03, + BAT_BCAST = 0x04, + BAT_VIS = 0x05, BAT_UNICAST_FRAG = 0x06, - BAT_TT_QUERY = 0x07, - BAT_ROAM_ADV = 0x08 + BAT_TT_QUERY = 0x07, + BAT_ROAM_ADV = 0x08 };
/* this file is included by batctl which needs these defines */ @@ -90,7 +90,7 @@ enum tt_client_flags { TT_CLIENT_PENDING = 1 << 10 };
-struct batman_packet { +struct batman_ogm_packet { uint8_t packet_type; uint8_t version; /* batman version field */ uint8_t ttl; @@ -105,7 +105,7 @@ struct batman_packet { uint16_t tt_crc; } __packed;
-#define BAT_PACKET_LEN sizeof(struct batman_packet) +#define BATMAN_OGM_LEN sizeof(struct batman_ogm_packet)
struct icmp_packet { uint8_t packet_type; diff --git a/routing.c b/routing.c index 1949928..6efd1d0 100644 --- a/routing.c +++ b/routing.c @@ -130,7 +130,7 @@ out:
static int is_bidirectional_neigh(struct orig_node *orig_node, struct orig_node *orig_neigh_node, - struct batman_packet *batman_packet, + struct batman_ogm_packet *batman_ogm_packet, struct hard_iface *if_incoming) { struct bat_priv *bat_priv = netdev_priv(if_incoming->soft_iface); @@ -209,7 +209,8 @@ static int is_bidirectional_neigh(struct orig_node *orig_node, TQ_LOCAL_WINDOW_SIZE * TQ_LOCAL_WINDOW_SIZE);
- batman_packet->tq = ((batman_packet->tq * tq_own * tq_asym_penalty) / + batman_ogm_packet->tq = ((batman_ogm_packet->tq * tq_own + * tq_asym_penalty) / (TQ_MAX_VALUE * TQ_MAX_VALUE));
bat_dbg(DBG_BATMAN, bat_priv, @@ -218,11 +219,11 @@ static int is_bidirectional_neigh(struct orig_node *orig_node, "real recv = %2i, local tq: %3i, asym_penalty: %3i, " "total tq: %3i\n", orig_node->orig, orig_neigh_node->orig, total_count, - neigh_rq_count, tq_own, tq_asym_penalty, batman_packet->tq); + neigh_rq_count, tq_own, tq_asym_penalty, batman_ogm_packet->tq);
/* if link has the minimum required transmission quality * consider it bidirectional */ - if (batman_packet->tq >= TQ_TOTAL_BIDRECT_LIMIT) + if (batman_ogm_packet->tq >= TQ_TOTAL_BIDRECT_LIMIT) ret = 1;
out: @@ -321,9 +322,10 @@ out: /* copy primary address for bonding */ static void bonding_save_primary(const struct orig_node *orig_node, struct orig_node *orig_neigh_node, - const struct batman_packet *batman_packet) + const struct batman_ogm_packet + *batman_ogm_packet) { - if (!(batman_packet->flags & PRIMARIES_FIRST_HOP)) + if (!(batman_ogm_packet->flags & PRIMARIES_FIRST_HOP)) return;
memcpy(orig_neigh_node->primary_addr, orig_node->orig, ETH_ALEN); @@ -331,7 +333,7 @@ static void bonding_save_primary(const struct orig_node *orig_node,
static void update_orig(struct bat_priv *bat_priv, struct orig_node *orig_node, const struct ethhdr *ethhdr, - const struct batman_packet *batman_packet, + const struct batman_ogm_packet *batman_ogm_packet, struct hard_iface *if_incoming, const unsigned char *tt_buff, int is_duplicate) { @@ -386,19 +388,19 @@ static void update_orig(struct bat_priv *bat_priv, struct orig_node *orig_node,
rcu_read_unlock();
- orig_node->flags = batman_packet->flags; + orig_node->flags = batman_ogm_packet->flags; neigh_node->last_valid = jiffies;
spin_lock_bh(&neigh_node->tq_lock); ring_buffer_set(neigh_node->tq_recv, &neigh_node->tq_index, - batman_packet->tq); + batman_ogm_packet->tq); neigh_node->tq_avg = ring_buffer_avg(neigh_node->tq_recv); spin_unlock_bh(&neigh_node->tq_lock);
if (!is_duplicate) { - orig_node->last_ttl = batman_packet->ttl; - neigh_node->last_ttl = batman_packet->ttl; + orig_node->last_ttl = batman_ogm_packet->ttl; + neigh_node->last_ttl = batman_ogm_packet->ttl; }
bonding_candidate_add(orig_node, neigh_node); @@ -437,17 +439,19 @@ static void update_orig(struct bat_priv *bat_priv, struct orig_node *orig_node, update_tt: /* I have to check for transtable changes only if the OGM has been * sent through a primary interface */ - if (((batman_packet->orig != ethhdr->h_source) && - (batman_packet->ttl > 2)) || - (batman_packet->flags & PRIMARIES_FIRST_HOP)) + if (((batman_ogm_packet->orig != ethhdr->h_source) && + (batman_ogm_packet->ttl > 2)) || + (batman_ogm_packet->flags & PRIMARIES_FIRST_HOP)) tt_update_orig(bat_priv, orig_node, tt_buff, - batman_packet->tt_num_changes, - batman_packet->ttvn, batman_packet->tt_crc); + batman_ogm_packet->tt_num_changes, + batman_ogm_packet->ttvn, + batman_ogm_packet->tt_crc);
- if (orig_node->gw_flags != batman_packet->gw_flags) - gw_node_update(bat_priv, orig_node, batman_packet->gw_flags); + if (orig_node->gw_flags != batman_ogm_packet->gw_flags) + gw_node_update(bat_priv, orig_node, + batman_ogm_packet->gw_flags);
- orig_node->gw_flags = batman_packet->gw_flags; + orig_node->gw_flags = batman_ogm_packet->gw_flags;
/* restart gateway selection if fast or late switching was enabled */ if ((orig_node->gw_flags) && @@ -500,8 +504,8 @@ static int window_protected(struct bat_priv *bat_priv, * was protected. Caller should drop it. */ static int count_real_packets(const struct ethhdr *ethhdr, - const struct batman_packet *batman_packet, - const struct hard_iface *if_incoming) + const struct batman_ogm_packet *batman_ogm_packet, + const struct hard_iface *if_incoming) { struct bat_priv *bat_priv = netdev_priv(if_incoming->soft_iface); struct orig_node *orig_node; @@ -512,12 +516,12 @@ static int count_real_packets(const struct ethhdr *ethhdr, int need_update = 0; int set_mark, ret = -1;
- orig_node = get_orig_node(bat_priv, batman_packet->orig); + orig_node = get_orig_node(bat_priv, batman_ogm_packet->orig); if (!orig_node) return 0;
spin_lock_bh(&orig_node->ogm_cnt_lock); - seq_diff = batman_packet->seqno - orig_node->last_real_seqno; + seq_diff = batman_ogm_packet->seqno - orig_node->last_real_seqno;
/* signalize caller that the packet is to be dropped. */ if (window_protected(bat_priv, seq_diff, @@ -530,7 +534,7 @@ static int count_real_packets(const struct ethhdr *ethhdr,
is_duplicate |= get_bit_status(tmp_neigh_node->real_bits, orig_node->last_real_seqno, - batman_packet->seqno); + batman_ogm_packet->seqno);
if (compare_eth(tmp_neigh_node->addr, ethhdr->h_source) && (tmp_neigh_node->if_incoming == if_incoming)) @@ -551,8 +555,8 @@ static int count_real_packets(const struct ethhdr *ethhdr, if (need_update) { bat_dbg(DBG_BATMAN, bat_priv, "updating last_seqno: old %d, new %d\n", - orig_node->last_real_seqno, batman_packet->seqno); - orig_node->last_real_seqno = batman_packet->seqno; + orig_node->last_real_seqno, batman_ogm_packet->seqno); + orig_node->last_real_seqno = batman_ogm_packet->seqno; }
ret = is_duplicate; @@ -564,7 +568,7 @@ out: }
void receive_bat_packet(const struct ethhdr *ethhdr, - struct batman_packet *batman_packet, + struct batman_ogm_packet *batman_ogm_packet, const unsigned char *tt_buff, struct hard_iface *if_incoming) { @@ -587,31 +591,31 @@ void receive_bat_packet(const struct ethhdr *ethhdr, * it as an additional length. * * TODO: A more sane solution would be to have a bit in the - * batman_packet to detect whether the packet is the last + * batman_ogm_packet to detect whether the packet is the last * packet in an aggregation. Here we expect that the padding * is always zero (or not 0x01) */ - if (batman_packet->packet_type != BAT_PACKET) + if (batman_ogm_packet->packet_type != BAT_OGM) return;
/* could be changed by schedule_own_packet() */ if_incoming_seqno = atomic_read(&if_incoming->seqno);
- has_directlink_flag = (batman_packet->flags & DIRECTLINK ? 1 : 0); + has_directlink_flag = (batman_ogm_packet->flags & DIRECTLINK ? 1 : 0);
is_single_hop_neigh = (compare_eth(ethhdr->h_source, - batman_packet->orig) ? 1 : 0); + batman_ogm_packet->orig) ? 1 : 0);
bat_dbg(DBG_BATMAN, bat_priv, "Received BATMAN packet via NB: %pM, IF: %s [%pM] " "(from OG: %pM, via prev OG: %pM, seqno %d, ttvn %u, " "crc %u, changes %u, td %d, TTL %d, V %d, IDF %d)\n", ethhdr->h_source, if_incoming->net_dev->name, - if_incoming->net_dev->dev_addr, batman_packet->orig, - batman_packet->prev_sender, batman_packet->seqno, - batman_packet->ttvn, batman_packet->tt_crc, - batman_packet->tt_num_changes, batman_packet->tq, - batman_packet->ttl, batman_packet->version, + if_incoming->net_dev->dev_addr, batman_ogm_packet->orig, + batman_ogm_packet->prev_sender, batman_ogm_packet->seqno, + batman_ogm_packet->ttvn, batman_ogm_packet->tt_crc, + batman_ogm_packet->tt_num_changes, batman_ogm_packet->tq, + batman_ogm_packet->ttl, batman_ogm_packet->version, has_directlink_flag);
rcu_read_lock(); @@ -626,11 +630,11 @@ void receive_bat_packet(const struct ethhdr *ethhdr, hard_iface->net_dev->dev_addr)) is_my_addr = 1;
- if (compare_eth(batman_packet->orig, + if (compare_eth(batman_ogm_packet->orig, hard_iface->net_dev->dev_addr)) is_my_orig = 1;
- if (compare_eth(batman_packet->prev_sender, + if (compare_eth(batman_ogm_packet->prev_sender, hard_iface->net_dev->dev_addr)) is_my_oldorig = 1;
@@ -639,10 +643,10 @@ void receive_bat_packet(const struct ethhdr *ethhdr, } rcu_read_unlock();
- if (batman_packet->version != COMPAT_VERSION) { + if (batman_ogm_packet->version != COMPAT_VERSION) { bat_dbg(DBG_BATMAN, bat_priv, "Drop packet: incompatible batman version (%i)\n", - batman_packet->version); + batman_ogm_packet->version); return; }
@@ -674,13 +678,14 @@ void receive_bat_packet(const struct ethhdr *ethhdr, /* save packet seqno for bidirectional check */ if (has_directlink_flag && compare_eth(if_incoming->net_dev->dev_addr, - batman_packet->orig)) { + batman_ogm_packet->orig)) { offset = if_incoming->if_num * NUM_WORDS;
spin_lock_bh(&orig_neigh_node->ogm_cnt_lock); word = &(orig_neigh_node->bcast_own[offset]); bit_mark(word, - if_incoming_seqno - batman_packet->seqno - 2); + if_incoming_seqno - + batman_ogm_packet->seqno - 2); orig_neigh_node->bcast_own_sum[if_incoming->if_num] = bit_packet_count(word); spin_unlock_bh(&orig_neigh_node->ogm_cnt_lock); @@ -699,11 +704,12 @@ void receive_bat_packet(const struct ethhdr *ethhdr, return; }
- orig_node = get_orig_node(bat_priv, batman_packet->orig); + orig_node = get_orig_node(bat_priv, batman_ogm_packet->orig); if (!orig_node) return;
- is_duplicate = count_real_packets(ethhdr, batman_packet, if_incoming); + is_duplicate = count_real_packets(ethhdr, batman_ogm_packet, + if_incoming);
if (is_duplicate == -1) { bat_dbg(DBG_BATMAN, bat_priv, @@ -712,7 +718,7 @@ void receive_bat_packet(const struct ethhdr *ethhdr, goto out; }
- if (batman_packet->tq == 0) { + if (batman_ogm_packet->tq == 0) { bat_dbg(DBG_BATMAN, bat_priv, "Drop packet: originator packet with tq equal 0\n"); goto out; @@ -724,8 +730,9 @@ void receive_bat_packet(const struct ethhdr *ethhdr,
/* avoid temporary routing loops */ if (router && router_router && - (compare_eth(router->addr, batman_packet->prev_sender)) && - !(compare_eth(batman_packet->orig, batman_packet->prev_sender)) && + (compare_eth(router->addr, batman_ogm_packet->prev_sender)) && + !(compare_eth(batman_ogm_packet->orig, + batman_ogm_packet->prev_sender)) && (compare_eth(router->addr, router_router->addr))) { bat_dbg(DBG_BATMAN, bat_priv, "Drop packet: ignoring all rebroadcast packets that " @@ -752,24 +759,25 @@ void receive_bat_packet(const struct ethhdr *ethhdr, }
is_bidirectional = is_bidirectional_neigh(orig_node, orig_neigh_node, - batman_packet, if_incoming); + batman_ogm_packet, + if_incoming);
- bonding_save_primary(orig_node, orig_neigh_node, batman_packet); + bonding_save_primary(orig_node, orig_neigh_node, batman_ogm_packet);
/* update ranking if it is not a duplicate or has the same * seqno and similar ttl as the non-duplicate */ if (is_bidirectional && (!is_duplicate || - ((orig_node->last_real_seqno == batman_packet->seqno) && - (orig_node->last_ttl - 3 <= batman_packet->ttl)))) - update_orig(bat_priv, orig_node, ethhdr, batman_packet, + ((orig_node->last_real_seqno == batman_ogm_packet->seqno) && + (orig_node->last_ttl - 3 <= batman_ogm_packet->ttl)))) + update_orig(bat_priv, orig_node, ethhdr, batman_ogm_packet, if_incoming, tt_buff, is_duplicate);
/* is single hop (direct) neighbor */ if (is_single_hop_neigh) {
/* mark direct link on incoming interface */ - schedule_forward_packet(orig_node, ethhdr, batman_packet, + schedule_forward_packet(orig_node, ethhdr, batman_ogm_packet, 1, if_incoming);
bat_dbg(DBG_BATMAN, bat_priv, "Forwarding packet: " @@ -792,7 +800,7 @@ void receive_bat_packet(const struct ethhdr *ethhdr,
bat_dbg(DBG_BATMAN, bat_priv, "Forwarding packet: rebroadcast originator packet\n"); - schedule_forward_packet(orig_node, ethhdr, batman_packet, + schedule_forward_packet(orig_node, ethhdr, batman_ogm_packet, 0, if_incoming);
out_neigh: @@ -814,7 +822,7 @@ int recv_bat_packet(struct sk_buff *skb, struct hard_iface *hard_iface) struct ethhdr *ethhdr;
/* drop packet if it has not necessary minimum size */ - if (unlikely(!pskb_may_pull(skb, sizeof(struct batman_packet)))) + if (unlikely(!pskb_may_pull(skb, BATMAN_OGM_LEN))) return NET_RX_DROP;
ethhdr = (struct ethhdr *)skb_mac_header(skb); diff --git a/routing.h b/routing.h index fb14e95..893db7f 100644 --- a/routing.h +++ b/routing.h @@ -24,7 +24,7 @@
void slide_own_bcast_window(struct hard_iface *hard_iface); void receive_bat_packet(const struct ethhdr *ethhdr, - struct batman_packet *batman_packet, + struct batman_ogm_packet *batman_ogm_packet, const unsigned char *tt_buff, struct hard_iface *if_incoming); void update_routes(struct bat_priv *bat_priv, struct orig_node *orig_node, diff --git a/send.c b/send.c index 57ae809..40a5fcd 100644 --- a/send.c +++ b/send.c @@ -107,7 +107,7 @@ static void send_packet_to_if(struct forw_packet *forw_packet, char *fwd_str; uint8_t packet_num; int16_t buff_pos; - struct batman_packet *batman_packet; + struct batman_ogm_packet *batman_ogm_packet; struct sk_buff *skb;
if (hard_iface->if_status != IF_ACTIVE) @@ -115,20 +115,20 @@ static void send_packet_to_if(struct forw_packet *forw_packet,
packet_num = 0; buff_pos = 0; - batman_packet = (struct batman_packet *)forw_packet->skb->data; + batman_ogm_packet = (struct batman_ogm_packet *)forw_packet->skb->data;
/* adjust all flags and log packets */ while (aggregated_packet(buff_pos, forw_packet->packet_len, - batman_packet->tt_num_changes)) { + batman_ogm_packet->tt_num_changes)) {
/* we might have aggregated direct link packets with an * ordinary base packet */ if ((forw_packet->direct_link_flags & (1 << packet_num)) && (forw_packet->if_incoming == hard_iface)) - batman_packet->flags |= DIRECTLINK; + batman_ogm_packet->flags |= DIRECTLINK; else - batman_packet->flags &= ~DIRECTLINK; + batman_ogm_packet->flags &= ~DIRECTLINK;
fwd_str = (packet_num > 0 ? "Forwarding" : (forw_packet->own ? "Sending own" : @@ -137,18 +137,19 @@ static void send_packet_to_if(struct forw_packet *forw_packet, "%s %spacket (originator %pM, seqno %d, TQ %d, TTL %d," " IDF %s, ttvn %d) on interface %s [%pM]\n", fwd_str, (packet_num > 0 ? "aggregated " : ""), - batman_packet->orig, ntohl(batman_packet->seqno), - batman_packet->tq, batman_packet->ttl, - (batman_packet->flags & DIRECTLINK ? + batman_ogm_packet->orig, + ntohl(batman_ogm_packet->seqno), + batman_ogm_packet->tq, batman_ogm_packet->ttl, + (batman_ogm_packet->flags & DIRECTLINK ? "on" : "off"), - batman_packet->ttvn, hard_iface->net_dev->name, + batman_ogm_packet->ttvn, hard_iface->net_dev->name, hard_iface->net_dev->dev_addr);
- buff_pos += sizeof(*batman_packet) + - tt_len(batman_packet->tt_num_changes); + buff_pos += BATMAN_OGM_LEN + + tt_len(batman_ogm_packet->tt_num_changes); packet_num++; - batman_packet = (struct batman_packet *) - (forw_packet->skb->data + buff_pos); + batman_ogm_packet = (struct batman_ogm_packet *) + (forw_packet->skb->data + buff_pos); }
/* create clone because function is called more than once */ @@ -164,9 +165,11 @@ static void send_packet(struct forw_packet *forw_packet) struct net_device *soft_iface; struct bat_priv *bat_priv; struct hard_iface *primary_if = NULL; - struct batman_packet *batman_packet = - (struct batman_packet *)(forw_packet->skb->data); - int directlink = (batman_packet->flags & DIRECTLINK ? 1 : 0); + struct batman_ogm_packet *batman_ogm_packet = + (struct batman_ogm_packet *)(forw_packet->skb->data); + unsigned char directlink; + + directlink = (batman_ogm_packet->flags & DIRECTLINK ? 1 : 0);
if (!forw_packet->if_incoming) { pr_err("Error - can't forward packet: incoming iface not " @@ -186,7 +189,7 @@ static void send_packet(struct forw_packet *forw_packet)
/* multihomed peer assumed */ /* non-primary OGMs are only broadcasted on their interface */ - if ((directlink && (batman_packet->ttl == 1)) || + if ((directlink && (batman_ogm_packet->ttl == 1)) || (forw_packet->own && (forw_packet->if_incoming != primary_if))) {
/* FIXME: what about aggregated packets ? */ @@ -194,8 +197,9 @@ static void send_packet(struct forw_packet *forw_packet) "%s packet (originator %pM, seqno %d, TTL %d) " "on interface %s [%pM]\n", (forw_packet->own ? "Sending own" : "Forwarding"), - batman_packet->orig, ntohl(batman_packet->seqno), - batman_packet->ttl, + batman_ogm_packet->orig, + ntohl(batman_ogm_packet->seqno), + batman_ogm_packet->ttl, forw_packet->if_incoming->net_dev->name, forw_packet->if_incoming->net_dev->dev_addr);
@@ -223,17 +227,16 @@ out: }
static void realloc_packet_buffer(struct hard_iface *hard_iface, - int new_len) + int new_len) { unsigned char *new_buff; - struct batman_packet *batman_packet;
new_buff = kmalloc(new_len, GFP_ATOMIC);
/* keep old buffer if kmalloc should fail */ if (new_buff) { memcpy(new_buff, hard_iface->packet_buff, - sizeof(*batman_packet)); + BATMAN_OGM_LEN);
kfree(hard_iface->packet_buff); hard_iface->packet_buff = new_buff; @@ -246,39 +249,39 @@ static void prepare_packet_buffer(struct bat_priv *bat_priv, struct hard_iface *hard_iface) { int new_len; - struct batman_packet *batman_packet; + struct batman_ogm_packet *batman_ogm_packet;
- new_len = BAT_PACKET_LEN + + new_len = BATMAN_OGM_LEN + tt_len((uint8_t)atomic_read(&bat_priv->tt_local_changes));
/* if we have too many changes for one packet don't send any * and wait for the tt table request which will be fragmented */ if (new_len > hard_iface->soft_iface->mtu) - new_len = BAT_PACKET_LEN; + new_len = BATMAN_OGM_LEN;
realloc_packet_buffer(hard_iface, new_len); - batman_packet = (struct batman_packet *)hard_iface->packet_buff; + batman_ogm_packet = (struct batman_ogm_packet *)hard_iface->packet_buff;
atomic_set(&bat_priv->tt_crc, tt_local_crc(bat_priv));
/* reset the sending counter */ atomic_set(&bat_priv->tt_ogm_append_cnt, TT_OGM_APPEND_MAX);
- batman_packet->tt_num_changes = tt_changes_fill_buffer(bat_priv, - hard_iface->packet_buff + BAT_PACKET_LEN, - hard_iface->packet_len - BAT_PACKET_LEN); + batman_ogm_packet->tt_num_changes = tt_changes_fill_buffer(bat_priv, + hard_iface->packet_buff + BATMAN_OGM_LEN, + hard_iface->packet_len - BATMAN_OGM_LEN);
}
static void reset_packet_buffer(struct bat_priv *bat_priv, - struct hard_iface *hard_iface) + struct hard_iface *hard_iface) { - struct batman_packet *batman_packet; + struct batman_ogm_packet *batman_ogm_packet;
- realloc_packet_buffer(hard_iface, BAT_PACKET_LEN); + realloc_packet_buffer(hard_iface, BATMAN_OGM_LEN);
- batman_packet = (struct batman_packet *)hard_iface->packet_buff; - batman_packet->tt_num_changes = 0; + batman_ogm_packet = (struct batman_ogm_packet *)hard_iface->packet_buff; + batman_ogm_packet->tt_num_changes = 0; }
void schedule_own_packet(struct hard_iface *hard_iface) @@ -286,7 +289,7 @@ void schedule_own_packet(struct hard_iface *hard_iface) struct bat_priv *bat_priv = netdev_priv(hard_iface->soft_iface); struct hard_iface *primary_if; unsigned long send_time; - struct batman_packet *batman_packet; + struct batman_ogm_packet *batman_ogm_packet; int vis_server;
if ((hard_iface->if_status == IF_NOT_IN_USE) || @@ -322,26 +325,27 @@ void schedule_own_packet(struct hard_iface *hard_iface) * NOTE: packet_buff might just have been re-allocated in * prepare_packet_buffer() or in reset_packet_buffer() */ - batman_packet = (struct batman_packet *)hard_iface->packet_buff; + batman_ogm_packet = (struct batman_ogm_packet *)hard_iface->packet_buff;
/* change sequence number to network order */ - batman_packet->seqno = - htonl((uint32_t)atomic_read(&hard_iface->seqno)); + batman_ogm_packet->seqno = + htonl((uint32_t)atomic_read(&hard_iface->seqno));
- batman_packet->ttvn = atomic_read(&bat_priv->ttvn); - batman_packet->tt_crc = htons((uint16_t)atomic_read(&bat_priv->tt_crc)); + batman_ogm_packet->ttvn = atomic_read(&bat_priv->ttvn); + batman_ogm_packet->tt_crc = htons((uint16_t) + atomic_read(&bat_priv->tt_crc));
if (vis_server == VIS_TYPE_SERVER_SYNC) - batman_packet->flags |= VIS_SERVER; + batman_ogm_packet->flags |= VIS_SERVER; else - batman_packet->flags &= ~VIS_SERVER; + batman_ogm_packet->flags &= ~VIS_SERVER;
if ((hard_iface == primary_if) && (atomic_read(&bat_priv->gw_mode) == GW_MODE_SERVER)) - batman_packet->gw_flags = + batman_ogm_packet->gw_flags = (uint8_t)atomic_read(&bat_priv->gw_bandwidth); else - batman_packet->gw_flags = NO_FLAGS; + batman_ogm_packet->gw_flags = NO_FLAGS;
atomic_inc(&hard_iface->seqno);
@@ -358,7 +362,7 @@ void schedule_own_packet(struct hard_iface *hard_iface)
void schedule_forward_packet(struct orig_node *orig_node, const struct ethhdr *ethhdr, - struct batman_packet *batman_packet, + struct batman_ogm_packet *batman_ogm_packet, int directlink, struct hard_iface *if_incoming) { @@ -368,19 +372,19 @@ void schedule_forward_packet(struct orig_node *orig_node, unsigned long send_time; uint8_t tt_num_changes;
- if (batman_packet->ttl <= 1) { + if (batman_ogm_packet->ttl <= 1) { bat_dbg(DBG_BATMAN, bat_priv, "ttl exceeded\n"); return; }
router = orig_node_get_router(orig_node);
- in_tq = batman_packet->tq; - in_ttl = batman_packet->ttl; - tt_num_changes = batman_packet->tt_num_changes; + in_tq = batman_ogm_packet->tq; + in_ttl = batman_ogm_packet->ttl; + tt_num_changes = batman_ogm_packet->tt_num_changes;
- batman_packet->ttl--; - memcpy(batman_packet->prev_sender, ethhdr->h_source, ETH_ALEN); + batman_ogm_packet->ttl--; + memcpy(batman_ogm_packet->prev_sender, ethhdr->h_source, ETH_ALEN);
/* rebroadcast tq of our best ranking neighbor to ensure the rebroadcast * of our best tq value */ @@ -388,10 +392,10 @@ void schedule_forward_packet(struct orig_node *orig_node,
/* rebroadcast ogm of best ranking neighbor as is */ if (!compare_eth(router->addr, ethhdr->h_source)) { - batman_packet->tq = router->tq_avg; + batman_ogm_packet->tq = router->tq_avg;
if (router->last_ttl) - batman_packet->ttl = router->last_ttl - 1; + batman_ogm_packet->ttl = router->last_ttl - 1; }
tq_avg = router->tq_avg; @@ -401,28 +405,28 @@ void schedule_forward_packet(struct orig_node *orig_node, neigh_node_free_ref(router);
/* apply hop penalty */ - batman_packet->tq = hop_penalty(batman_packet->tq, bat_priv); + batman_ogm_packet->tq = hop_penalty(batman_ogm_packet->tq, bat_priv);
bat_dbg(DBG_BATMAN, bat_priv, "Forwarding packet: tq_orig: %i, tq_avg: %i, " "tq_forw: %i, ttl_orig: %i, ttl_forw: %i\n", - in_tq, tq_avg, batman_packet->tq, in_ttl - 1, - batman_packet->ttl); + in_tq, tq_avg, batman_ogm_packet->tq, in_ttl - 1, + batman_ogm_packet->ttl);
- batman_packet->seqno = htonl(batman_packet->seqno); - batman_packet->tt_crc = htons(batman_packet->tt_crc); + batman_ogm_packet->seqno = htonl(batman_ogm_packet->seqno); + batman_ogm_packet->tt_crc = htons(batman_ogm_packet->tt_crc);
/* switch of primaries first hop flag when forwarding */ - batman_packet->flags &= ~PRIMARIES_FIRST_HOP; + batman_ogm_packet->flags &= ~PRIMARIES_FIRST_HOP; if (directlink) - batman_packet->flags |= DIRECTLINK; + batman_ogm_packet->flags |= DIRECTLINK; else - batman_packet->flags &= ~DIRECTLINK; + batman_ogm_packet->flags &= ~DIRECTLINK;
send_time = forward_send_time(); add_bat_packet_to_list(bat_priv, - (unsigned char *)batman_packet, - sizeof(*batman_packet) + tt_len(tt_num_changes), + (unsigned char *)batman_ogm_packet, + BATMAN_OGM_LEN + tt_len(tt_num_changes), if_incoming, 0, send_time); }
diff --git a/send.h b/send.h index 1f2d1e8..8a22d84 100644 --- a/send.h +++ b/send.h @@ -27,7 +27,7 @@ int send_skb_packet(struct sk_buff *skb, struct hard_iface *hard_iface, void schedule_own_packet(struct hard_iface *hard_iface); void schedule_forward_packet(struct orig_node *orig_node, const struct ethhdr *ethhdr, - struct batman_packet *batman_packet, + struct batman_ogm_packet *batman_ogm_packet, int directlink, struct hard_iface *if_outgoing); int add_bcast_packet_to_list(struct bat_priv *bat_priv, diff --git a/soft-interface.c b/soft-interface.c index 402fd96..7d8332e 100644 --- a/soft-interface.c +++ b/soft-interface.c @@ -445,30 +445,31 @@ static void softif_batman_recv(struct sk_buff *skb, struct net_device *dev, { struct bat_priv *bat_priv = netdev_priv(dev); struct ethhdr *ethhdr = (struct ethhdr *)skb->data; - struct batman_packet *batman_packet; + struct batman_ogm_packet *batman_ogm_packet; struct softif_neigh *softif_neigh = NULL; struct hard_iface *primary_if = NULL; struct softif_neigh *curr_softif_neigh = NULL;
if (ntohs(ethhdr->h_proto) == ETH_P_8021Q) - batman_packet = (struct batman_packet *) + batman_ogm_packet = (struct batman_ogm_packet *) (skb->data + ETH_HLEN + VLAN_HLEN); else - batman_packet = (struct batman_packet *)(skb->data + ETH_HLEN); + batman_ogm_packet = (struct batman_ogm_packet *) + (skb->data + ETH_HLEN);
- if (batman_packet->version != COMPAT_VERSION) + if (batman_ogm_packet->version != COMPAT_VERSION) goto out;
- if (batman_packet->packet_type != BAT_PACKET) + if (batman_ogm_packet->packet_type != BAT_OGM) goto out;
- if (!(batman_packet->flags & PRIMARIES_FIRST_HOP)) + if (!(batman_ogm_packet->flags & PRIMARIES_FIRST_HOP)) goto out;
- if (is_my_mac(batman_packet->orig)) + if (is_my_mac(batman_ogm_packet->orig)) goto out;
- softif_neigh = softif_neigh_get(bat_priv, batman_packet->orig, vid); + softif_neigh = softif_neigh_get(bat_priv, batman_ogm_packet->orig, vid); if (!softif_neigh) goto out;
In preparation of the upcoming improved routing algorithm the code based has to be re-organized to allow choosing the routing algorithm at compile time.
Signed-off-by: Marek Lindner lindner_marek@yahoo.de --- Makefile.kbuild | 1 + aggregation.c | 31 --- aggregation.h | 3 - bat_iv_ogm.c | 639 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ bat_ogm.h | 30 +++ hard-interface.c | 2 +- originator.c | 3 +- routing.c | 606 ++------------------------------------------------- routing.h | 17 +- 9 files changed, 698 insertions(+), 634 deletions(-) create mode 100644 bat_iv_ogm.c create mode 100644 bat_ogm.h
diff --git a/Makefile.kbuild b/Makefile.kbuild index 4dda02b..3865d4d 100644 --- a/Makefile.kbuild +++ b/Makefile.kbuild @@ -34,6 +34,7 @@ endif obj-m += batman-adv.o batman-adv-y += aggregation.o batman-adv-y += bat_debugfs.o +batman-adv-y += bat_iv_ogm.o batman-adv-y += bat_sysfs.o batman-adv-y += bitarray.o batman-adv-y += gateway_client.o diff --git a/aggregation.c b/aggregation.c index f20423f..4716c93 100644 --- a/aggregation.c +++ b/aggregation.c @@ -264,34 +264,3 @@ void add_bat_packet_to_list(struct bat_priv *bat_priv, spin_unlock_bh(&bat_priv->forw_bat_list_lock); } } - -/* unpack the aggregated packets and process them one by one */ -void receive_aggr_bat_packet(const struct ethhdr *ethhdr, - unsigned char *packet_buff, int packet_len, - struct hard_iface *if_incoming) -{ - struct batman_ogm_packet *batman_ogm_packet; - int buff_pos = 0; - unsigned char *tt_buff; - - batman_ogm_packet = (struct batman_ogm_packet *)packet_buff; - - do { - /* network to host order for our 32bit seqno and the - orig_interval */ - batman_ogm_packet->seqno = ntohl(batman_ogm_packet->seqno); - batman_ogm_packet->tt_crc = ntohs(batman_ogm_packet->tt_crc); - - tt_buff = packet_buff + buff_pos + BATMAN_OGM_LEN; - - receive_bat_packet(ethhdr, batman_ogm_packet, - tt_buff, if_incoming); - - buff_pos += BATMAN_OGM_LEN + - tt_len(batman_ogm_packet->tt_num_changes); - - batman_ogm_packet = (struct batman_ogm_packet *) - (packet_buff + buff_pos); - } while (aggregated_packet(buff_pos, packet_len, - batman_ogm_packet->tt_num_changes)); -} diff --git a/aggregation.h b/aggregation.h index 7fc23b0..7a92e4c 100644 --- a/aggregation.h +++ b/aggregation.h @@ -38,8 +38,5 @@ void add_bat_packet_to_list(struct bat_priv *bat_priv, unsigned char *packet_buff, int packet_len, struct hard_iface *if_incoming, int own_packet, unsigned long send_time); -void receive_aggr_bat_packet(const struct ethhdr *ethhdr, - unsigned char *packet_buff, int packet_len, - struct hard_iface *if_incoming);
#endif /* _NET_BATMAN_ADV_AGGREGATION_H_ */ diff --git a/bat_iv_ogm.c b/bat_iv_ogm.c new file mode 100644 index 0000000..6fa2d46 --- /dev/null +++ b/bat_iv_ogm.c @@ -0,0 +1,639 @@ +/* + * Copyright (C) 2007-2011 B.A.T.M.A.N. contributors: + * + * Marek Lindner, Simon Wunderlich + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA + * + */ + +#include "main.h" +#include "bat_ogm.h" +#include "translation-table.h" +#include "ring_buffer.h" +#include "originator.h" +#include "routing.h" +#include "gateway_common.h" +#include "gateway_client.h" +#include "hard-interface.h" +#include "send.h" + +/* is there another aggregated packet here? */ +static int bat_ogm_aggr_packet(int buff_pos, int packet_len, + int tt_num_changes) +{ + int next_buff_pos = buff_pos + BATMAN_OGM_LEN + tt_len(tt_num_changes); + + return (next_buff_pos <= packet_len) && + (next_buff_pos <= MAX_AGGREGATION_BYTES); +} + +static void bat_ogm_orig_update(struct bat_priv *bat_priv, + struct orig_node *orig_node, + const struct ethhdr *ethhdr, + const struct batman_ogm_packet + *batman_ogm_packet, + struct hard_iface *if_incoming, + const unsigned char *tt_buff, int is_duplicate) +{ + struct neigh_node *neigh_node = NULL, *tmp_neigh_node = NULL; + struct neigh_node *router = NULL; + struct orig_node *orig_node_tmp; + struct hlist_node *node; + uint8_t bcast_own_sum_orig, bcast_own_sum_neigh; + + bat_dbg(DBG_BATMAN, bat_priv, "update_originator(): " + "Searching and updating originator entry of received packet\n"); + + rcu_read_lock(); + hlist_for_each_entry_rcu(tmp_neigh_node, node, + &orig_node->neigh_list, list) { + if (compare_eth(tmp_neigh_node->addr, ethhdr->h_source) && + (tmp_neigh_node->if_incoming == if_incoming) && + atomic_inc_not_zero(&tmp_neigh_node->refcount)) { + if (neigh_node) + neigh_node_free_ref(neigh_node); + neigh_node = tmp_neigh_node; + continue; + } + + if (is_duplicate) + continue; + + spin_lock_bh(&tmp_neigh_node->tq_lock); + ring_buffer_set(tmp_neigh_node->tq_recv, + &tmp_neigh_node->tq_index, 0); + tmp_neigh_node->tq_avg = + ring_buffer_avg(tmp_neigh_node->tq_recv); + spin_unlock_bh(&tmp_neigh_node->tq_lock); + } + + if (!neigh_node) { + struct orig_node *orig_tmp; + + orig_tmp = get_orig_node(bat_priv, ethhdr->h_source); + if (!orig_tmp) + goto unlock; + + neigh_node = create_neighbor(orig_node, orig_tmp, + ethhdr->h_source, if_incoming); + + orig_node_free_ref(orig_tmp); + if (!neigh_node) + goto unlock; + } else + bat_dbg(DBG_BATMAN, bat_priv, + "Updating existing last-hop neighbor of originator\n"); + + rcu_read_unlock(); + + orig_node->flags = batman_ogm_packet->flags; + neigh_node->last_valid = jiffies; + + spin_lock_bh(&neigh_node->tq_lock); + ring_buffer_set(neigh_node->tq_recv, + &neigh_node->tq_index, + batman_ogm_packet->tq); + neigh_node->tq_avg = ring_buffer_avg(neigh_node->tq_recv); + spin_unlock_bh(&neigh_node->tq_lock); + + if (!is_duplicate) { + orig_node->last_ttl = batman_ogm_packet->ttl; + neigh_node->last_ttl = batman_ogm_packet->ttl; + } + + bonding_candidate_add(orig_node, neigh_node); + + /* if this neighbor already is our next hop there is nothing + * to change */ + router = orig_node_get_router(orig_node); + if (router == neigh_node) + goto update_tt; + + /* if this neighbor does not offer a better TQ we won't consider it */ + if (router && (router->tq_avg > neigh_node->tq_avg)) + goto update_tt; + + /* if the TQ is the same and the link not more symmetric we + * won't consider it either */ + if (router && (neigh_node->tq_avg == router->tq_avg)) { + orig_node_tmp = router->orig_node; + spin_lock_bh(&orig_node_tmp->ogm_cnt_lock); + bcast_own_sum_orig = + orig_node_tmp->bcast_own_sum[if_incoming->if_num]; + spin_unlock_bh(&orig_node_tmp->ogm_cnt_lock); + + orig_node_tmp = neigh_node->orig_node; + spin_lock_bh(&orig_node_tmp->ogm_cnt_lock); + bcast_own_sum_neigh = + orig_node_tmp->bcast_own_sum[if_incoming->if_num]; + spin_unlock_bh(&orig_node_tmp->ogm_cnt_lock); + + if (bcast_own_sum_orig >= bcast_own_sum_neigh) + goto update_tt; + } + + update_route(bat_priv, orig_node, neigh_node); + +update_tt: + /* I have to check for transtable changes only if the OGM has been + * sent through a primary interface */ + if (((batman_ogm_packet->orig != ethhdr->h_source) && + (batman_ogm_packet->ttl > 2)) || + (batman_ogm_packet->flags & PRIMARIES_FIRST_HOP)) + tt_update_orig(bat_priv, orig_node, tt_buff, + batman_ogm_packet->tt_num_changes, + batman_ogm_packet->ttvn, + batman_ogm_packet->tt_crc); + + if (orig_node->gw_flags != batman_ogm_packet->gw_flags) + gw_node_update(bat_priv, orig_node, + batman_ogm_packet->gw_flags); + + orig_node->gw_flags = batman_ogm_packet->gw_flags; + + /* restart gateway selection if fast or late switching was enabled */ + if ((orig_node->gw_flags) && + (atomic_read(&bat_priv->gw_mode) == GW_MODE_CLIENT) && + (atomic_read(&bat_priv->gw_sel_class) > 2)) + gw_check_election(bat_priv, orig_node); + + goto out; + +unlock: + rcu_read_unlock(); +out: + if (neigh_node) + neigh_node_free_ref(neigh_node); + if (router) + neigh_node_free_ref(router); +} + +static int bat_ogm_calc_tq(struct orig_node *orig_node, + struct orig_node *orig_neigh_node, + struct batman_ogm_packet *batman_ogm_packet, + struct hard_iface *if_incoming) +{ + struct bat_priv *bat_priv = netdev_priv(if_incoming->soft_iface); + struct neigh_node *neigh_node = NULL, *tmp_neigh_node; + struct hlist_node *node; + uint8_t total_count; + uint8_t orig_eq_count, neigh_rq_count, tq_own; + int tq_asym_penalty, ret = 0; + + /* find corresponding one hop neighbor */ + rcu_read_lock(); + hlist_for_each_entry_rcu(tmp_neigh_node, node, + &orig_neigh_node->neigh_list, list) { + + if (!compare_eth(tmp_neigh_node->addr, orig_neigh_node->orig)) + continue; + + if (tmp_neigh_node->if_incoming != if_incoming) + continue; + + if (!atomic_inc_not_zero(&tmp_neigh_node->refcount)) + continue; + + neigh_node = tmp_neigh_node; + break; + } + rcu_read_unlock(); + + if (!neigh_node) + neigh_node = create_neighbor(orig_neigh_node, + orig_neigh_node, + orig_neigh_node->orig, + if_incoming); + + if (!neigh_node) + goto out; + + /* if orig_node is direct neighbor update neigh_node last_valid */ + if (orig_node == orig_neigh_node) + neigh_node->last_valid = jiffies; + + orig_node->last_valid = jiffies; + + /* find packet count of corresponding one hop neighbor */ + spin_lock_bh(&orig_node->ogm_cnt_lock); + orig_eq_count = orig_neigh_node->bcast_own_sum[if_incoming->if_num]; + neigh_rq_count = neigh_node->real_packet_count; + spin_unlock_bh(&orig_node->ogm_cnt_lock); + + /* pay attention to not get a value bigger than 100 % */ + total_count = (orig_eq_count > neigh_rq_count ? + neigh_rq_count : orig_eq_count); + + /* if we have too few packets (too less data) we set tq_own to zero */ + /* if we receive too few packets it is not considered bidirectional */ + if ((total_count < TQ_LOCAL_BIDRECT_SEND_MINIMUM) || + (neigh_rq_count < TQ_LOCAL_BIDRECT_RECV_MINIMUM)) + tq_own = 0; + else + /* neigh_node->real_packet_count is never zero as we + * only purge old information when getting new + * information */ + tq_own = (TQ_MAX_VALUE * total_count) / neigh_rq_count; + + /* + * 1 - ((1-x) ** 3), normalized to TQ_MAX_VALUE this does + * affect the nearly-symmetric links only a little, but + * punishes asymmetric links more. This will give a value + * between 0 and TQ_MAX_VALUE + */ + tq_asym_penalty = TQ_MAX_VALUE - (TQ_MAX_VALUE * + (TQ_LOCAL_WINDOW_SIZE - neigh_rq_count) * + (TQ_LOCAL_WINDOW_SIZE - neigh_rq_count) * + (TQ_LOCAL_WINDOW_SIZE - neigh_rq_count)) / + (TQ_LOCAL_WINDOW_SIZE * + TQ_LOCAL_WINDOW_SIZE * + TQ_LOCAL_WINDOW_SIZE); + + batman_ogm_packet->tq = ((batman_ogm_packet->tq * tq_own + * tq_asym_penalty) / + (TQ_MAX_VALUE * TQ_MAX_VALUE)); + + bat_dbg(DBG_BATMAN, bat_priv, + "bidirectional: " + "orig = %-15pM neigh = %-15pM => own_bcast = %2i, " + "real recv = %2i, local tq: %3i, asym_penalty: %3i, " + "total tq: %3i\n", + orig_node->orig, orig_neigh_node->orig, total_count, + neigh_rq_count, tq_own, tq_asym_penalty, batman_ogm_packet->tq); + + /* if link has the minimum required transmission quality + * consider it bidirectional */ + if (batman_ogm_packet->tq >= TQ_TOTAL_BIDRECT_LIMIT) + ret = 1; + +out: + if (neigh_node) + neigh_node_free_ref(neigh_node); + return ret; +} + +/* processes a batman packet for all interfaces, adjusts the sequence number and + * finds out whether it is a duplicate. + * returns: + * 1 the packet is a duplicate + * 0 the packet has not yet been received + * -1 the packet is old and has been received while the seqno window + * was protected. Caller should drop it. + */ +static int bat_ogm_update_seqnos(const struct ethhdr *ethhdr, + const struct batman_ogm_packet + *batman_ogm_packet, + const struct hard_iface *if_incoming) +{ + struct bat_priv *bat_priv = netdev_priv(if_incoming->soft_iface); + struct orig_node *orig_node; + struct neigh_node *tmp_neigh_node; + struct hlist_node *node; + int is_duplicate = 0; + int32_t seq_diff; + int need_update = 0; + int set_mark, ret = -1; + + orig_node = get_orig_node(bat_priv, batman_ogm_packet->orig); + if (!orig_node) + return 0; + + spin_lock_bh(&orig_node->ogm_cnt_lock); + seq_diff = batman_ogm_packet->seqno - orig_node->last_real_seqno; + + /* signalize caller that the packet is to be dropped. */ + if (window_protected(bat_priv, seq_diff, + &orig_node->batman_seqno_reset)) + goto out; + + rcu_read_lock(); + hlist_for_each_entry_rcu(tmp_neigh_node, node, + &orig_node->neigh_list, list) { + + is_duplicate |= get_bit_status(tmp_neigh_node->real_bits, + orig_node->last_real_seqno, + batman_ogm_packet->seqno); + + if (compare_eth(tmp_neigh_node->addr, ethhdr->h_source) && + (tmp_neigh_node->if_incoming == if_incoming)) + set_mark = 1; + else + set_mark = 0; + + /* if the window moved, set the update flag. */ + need_update |= bit_get_packet(bat_priv, + tmp_neigh_node->real_bits, + seq_diff, set_mark); + + tmp_neigh_node->real_packet_count = + bit_packet_count(tmp_neigh_node->real_bits); + } + rcu_read_unlock(); + + if (need_update) { + bat_dbg(DBG_BATMAN, bat_priv, + "updating last_seqno: old %d, new %d\n", + orig_node->last_real_seqno, batman_ogm_packet->seqno); + orig_node->last_real_seqno = batman_ogm_packet->seqno; + } + + ret = is_duplicate; + +out: + spin_unlock_bh(&orig_node->ogm_cnt_lock); + orig_node_free_ref(orig_node); + return ret; +} + +static void bat_ogm_process(const struct ethhdr *ethhdr, + struct batman_ogm_packet *batman_ogm_packet, + const unsigned char *tt_buff, + struct hard_iface *if_incoming) +{ + struct bat_priv *bat_priv = netdev_priv(if_incoming->soft_iface); + struct hard_iface *hard_iface; + struct orig_node *orig_neigh_node, *orig_node; + struct neigh_node *router = NULL, *router_router = NULL; + struct neigh_node *orig_neigh_router = NULL; + int has_directlink_flag; + int is_my_addr = 0, is_my_orig = 0, is_my_oldorig = 0; + int is_broadcast = 0, is_bidirectional, is_single_hop_neigh; + int is_duplicate; + uint32_t if_incoming_seqno; + + /* Silently drop when the batman packet is actually not a + * correct packet. + * + * This might happen if a packet is padded (e.g. Ethernet has a + * minimum frame length of 64 byte) and the aggregation interprets + * it as an additional length. + * + * TODO: A more sane solution would be to have a bit in the + * batman_ogm_packet to detect whether the packet is the last + * packet in an aggregation. Here we expect that the padding + * is always zero (or not 0x01) + */ + if (batman_ogm_packet->packet_type != BAT_OGM) + return; + + /* could be changed by schedule_own_packet() */ + if_incoming_seqno = atomic_read(&if_incoming->seqno); + + has_directlink_flag = (batman_ogm_packet->flags & DIRECTLINK ? 1 : 0); + + is_single_hop_neigh = (compare_eth(ethhdr->h_source, + batman_ogm_packet->orig) ? 1 : 0); + + bat_dbg(DBG_BATMAN, bat_priv, + "Received BATMAN packet via NB: %pM, IF: %s [%pM] " + "(from OG: %pM, via prev OG: %pM, seqno %d, ttvn %u, " + "crc %u, changes %u, td %d, TTL %d, V %d, IDF %d)\n", + ethhdr->h_source, if_incoming->net_dev->name, + if_incoming->net_dev->dev_addr, batman_ogm_packet->orig, + batman_ogm_packet->prev_sender, batman_ogm_packet->seqno, + batman_ogm_packet->ttvn, batman_ogm_packet->tt_crc, + batman_ogm_packet->tt_num_changes, batman_ogm_packet->tq, + batman_ogm_packet->ttl, batman_ogm_packet->version, + has_directlink_flag); + + rcu_read_lock(); + list_for_each_entry_rcu(hard_iface, &hardif_list, list) { + if (hard_iface->if_status != IF_ACTIVE) + continue; + + if (hard_iface->soft_iface != if_incoming->soft_iface) + continue; + + if (compare_eth(ethhdr->h_source, + hard_iface->net_dev->dev_addr)) + is_my_addr = 1; + + if (compare_eth(batman_ogm_packet->orig, + hard_iface->net_dev->dev_addr)) + is_my_orig = 1; + + if (compare_eth(batman_ogm_packet->prev_sender, + hard_iface->net_dev->dev_addr)) + is_my_oldorig = 1; + + if (is_broadcast_ether_addr(ethhdr->h_source)) + is_broadcast = 1; + } + rcu_read_unlock(); + + if (batman_ogm_packet->version != COMPAT_VERSION) { + bat_dbg(DBG_BATMAN, bat_priv, + "Drop packet: incompatible batman version (%i)\n", + batman_ogm_packet->version); + return; + } + + if (is_my_addr) { + bat_dbg(DBG_BATMAN, bat_priv, + "Drop packet: received my own broadcast (sender: %pM" + ")\n", + ethhdr->h_source); + return; + } + + if (is_broadcast) { + bat_dbg(DBG_BATMAN, bat_priv, "Drop packet: " + "ignoring all packets with broadcast source addr (sender: %pM" + ")\n", ethhdr->h_source); + return; + } + + if (is_my_orig) { + unsigned long *word; + int offset; + + orig_neigh_node = get_orig_node(bat_priv, ethhdr->h_source); + if (!orig_neigh_node) + return; + + /* neighbor has to indicate direct link and it has to + * come via the corresponding interface */ + /* save packet seqno for bidirectional check */ + if (has_directlink_flag && + compare_eth(if_incoming->net_dev->dev_addr, + batman_ogm_packet->orig)) { + offset = if_incoming->if_num * NUM_WORDS; + + spin_lock_bh(&orig_neigh_node->ogm_cnt_lock); + word = &(orig_neigh_node->bcast_own[offset]); + bit_mark(word, + if_incoming_seqno - + batman_ogm_packet->seqno - 2); + orig_neigh_node->bcast_own_sum[if_incoming->if_num] = + bit_packet_count(word); + spin_unlock_bh(&orig_neigh_node->ogm_cnt_lock); + } + + bat_dbg(DBG_BATMAN, bat_priv, "Drop packet: " + "originator packet from myself (via neighbor)\n"); + orig_node_free_ref(orig_neigh_node); + return; + } + + if (is_my_oldorig) { + bat_dbg(DBG_BATMAN, bat_priv, + "Drop packet: ignoring all rebroadcast echos (sender: " + "%pM)\n", ethhdr->h_source); + return; + } + + orig_node = get_orig_node(bat_priv, batman_ogm_packet->orig); + if (!orig_node) + return; + + is_duplicate = bat_ogm_update_seqnos(ethhdr, batman_ogm_packet, + if_incoming); + + if (is_duplicate == -1) { + bat_dbg(DBG_BATMAN, bat_priv, + "Drop packet: packet within seqno protection time " + "(sender: %pM)\n", ethhdr->h_source); + goto out; + } + + if (batman_ogm_packet->tq == 0) { + bat_dbg(DBG_BATMAN, bat_priv, + "Drop packet: originator packet with tq equal 0\n"); + goto out; + } + + router = orig_node_get_router(orig_node); + if (router) + router_router = orig_node_get_router(router->orig_node); + + /* avoid temporary routing loops */ + if (router && router_router && + (compare_eth(router->addr, batman_ogm_packet->prev_sender)) && + !(compare_eth(batman_ogm_packet->orig, + batman_ogm_packet->prev_sender)) && + (compare_eth(router->addr, router_router->addr))) { + bat_dbg(DBG_BATMAN, bat_priv, + "Drop packet: ignoring all rebroadcast packets that " + "may make me loop (sender: %pM)\n", ethhdr->h_source); + goto out; + } + + /* if sender is a direct neighbor the sender mac equals + * originator mac */ + orig_neigh_node = (is_single_hop_neigh ? + orig_node : + get_orig_node(bat_priv, ethhdr->h_source)); + if (!orig_neigh_node) + goto out; + + orig_neigh_router = orig_node_get_router(orig_neigh_node); + + /* drop packet if sender is not a direct neighbor and if we + * don't route towards it */ + if (!is_single_hop_neigh && (!orig_neigh_router)) { + bat_dbg(DBG_BATMAN, bat_priv, + "Drop packet: OGM via unknown neighbor!\n"); + goto out_neigh; + } + + is_bidirectional = bat_ogm_calc_tq(orig_node, orig_neigh_node, + batman_ogm_packet, if_incoming); + + bonding_save_primary(orig_node, orig_neigh_node, batman_ogm_packet); + + /* update ranking if it is not a duplicate or has the same + * seqno and similar ttl as the non-duplicate */ + if (is_bidirectional && + (!is_duplicate || + ((orig_node->last_real_seqno == batman_ogm_packet->seqno) && + (orig_node->last_ttl - 3 <= batman_ogm_packet->ttl)))) + bat_ogm_orig_update(bat_priv, orig_node, ethhdr, + batman_ogm_packet, if_incoming, + tt_buff, is_duplicate); + + /* is single hop (direct) neighbor */ + if (is_single_hop_neigh) { + + /* mark direct link on incoming interface */ + schedule_forward_packet(orig_node, ethhdr, batman_ogm_packet, + 1, if_incoming); + + bat_dbg(DBG_BATMAN, bat_priv, "Forwarding packet: " + "rebroadcast neighbor packet with direct link flag\n"); + goto out_neigh; + } + + /* multihop originator */ + if (!is_bidirectional) { + bat_dbg(DBG_BATMAN, bat_priv, + "Drop packet: not received via bidirectional link\n"); + goto out_neigh; + } + + if (is_duplicate) { + bat_dbg(DBG_BATMAN, bat_priv, + "Drop packet: duplicate packet received\n"); + goto out_neigh; + } + + bat_dbg(DBG_BATMAN, bat_priv, + "Forwarding packet: rebroadcast originator packet\n"); + schedule_forward_packet(orig_node, ethhdr, batman_ogm_packet, + 0, if_incoming); + +out_neigh: + if ((orig_neigh_node) && (!is_single_hop_neigh)) + orig_node_free_ref(orig_neigh_node); +out: + if (router) + neigh_node_free_ref(router); + if (router_router) + neigh_node_free_ref(router_router); + if (orig_neigh_router) + neigh_node_free_ref(orig_neigh_router); + + orig_node_free_ref(orig_node); +} + +void bat_ogm_receive(const struct ethhdr *ethhdr, unsigned char *packet_buff, + int packet_len, struct hard_iface *if_incoming) +{ + struct batman_ogm_packet *batman_ogm_packet; + int buff_pos = 0; + unsigned char *tt_buff; + + batman_ogm_packet = (struct batman_ogm_packet *)packet_buff; + + /* unpack the aggregated packets and process them one by one */ + do { + /* network to host order for our 32bit seqno and the + orig_interval */ + batman_ogm_packet->seqno = ntohl(batman_ogm_packet->seqno); + batman_ogm_packet->tt_crc = ntohs(batman_ogm_packet->tt_crc); + + tt_buff = packet_buff + buff_pos + BATMAN_OGM_LEN; + + bat_ogm_process(ethhdr, batman_ogm_packet, + tt_buff, if_incoming); + + buff_pos += BATMAN_OGM_LEN + + tt_len(batman_ogm_packet->tt_num_changes); + + batman_ogm_packet = (struct batman_ogm_packet *) + (packet_buff + buff_pos); + } while (bat_ogm_aggr_packet(buff_pos, packet_len, + batman_ogm_packet->tt_num_changes)); +} diff --git a/bat_ogm.h b/bat_ogm.h new file mode 100644 index 0000000..bdd3d1e --- /dev/null +++ b/bat_ogm.h @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2007-2011 B.A.T.M.A.N. contributors: + * + * Marek Lindner, Simon Wunderlich + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA + * + */ + +#ifndef _NET_BATMAN_ADV_OGM_H_ +#define _NET_BATMAN_ADV_OGM_H_ + +#include "main.h" + +void bat_ogm_receive(const struct ethhdr *ethhdr, unsigned char *packet_buff, + int packet_len, struct hard_iface *if_incoming); + +#endif /* _NET_BATMAN_ADV_OGM_H_ */ diff --git a/hard-interface.c b/hard-interface.c index cf9f4af..cfee017 100644 --- a/hard-interface.c +++ b/hard-interface.c @@ -632,7 +632,7 @@ static int batman_skb_recv(struct sk_buff *skb, struct net_device *dev, switch (batman_ogm_packet->packet_type) { /* batman originator packet */ case BAT_OGM: - ret = recv_bat_packet(skb, hard_iface); + ret = recv_bat_ogm_packet(skb, hard_iface); break;
/* batman icmp packet */ diff --git a/originator.c b/originator.c index d448018..cd7d256 100644 --- a/originator.c +++ b/originator.c @@ -336,8 +336,7 @@ static bool purge_orig_node(struct bat_priv *bat_priv, } else { if (purge_orig_neighbors(bat_priv, orig_node, &best_neigh_node)) { - update_routes(bat_priv, orig_node, - best_neigh_node); + update_route(bat_priv, orig_node, best_neigh_node); } }
diff --git a/routing.c b/routing.c index 6efd1d0..f961cc5 100644 --- a/routing.c +++ b/routing.c @@ -22,18 +22,14 @@ #include "main.h" #include "routing.h" #include "send.h" -#include "hash.h" #include "soft-interface.h" #include "hard-interface.h" #include "icmp_socket.h" #include "translation-table.h" #include "originator.h" -#include "ring_buffer.h" #include "vis.h" -#include "aggregation.h" -#include "gateway_common.h" -#include "gateway_client.h" #include "unicast.h" +#include "bat_ogm.h"
void slide_own_bcast_window(struct hard_iface *hard_iface) { @@ -64,9 +60,9 @@ void slide_own_bcast_window(struct hard_iface *hard_iface) } }
-static void update_route(struct bat_priv *bat_priv, - struct orig_node *orig_node, - struct neigh_node *neigh_node) +static void _update_route(struct bat_priv *bat_priv, + struct orig_node *orig_node, + struct neigh_node *neigh_node) { struct neigh_node *curr_router;
@@ -110,8 +106,8 @@ static void update_route(struct bat_priv *bat_priv, neigh_node_free_ref(curr_router); }
-void update_routes(struct bat_priv *bat_priv, struct orig_node *orig_node, - struct neigh_node *neigh_node) +void update_route(struct bat_priv *bat_priv, struct orig_node *orig_node, + struct neigh_node *neigh_node) { struct neigh_node *router = NULL;
@@ -121,117 +117,13 @@ void update_routes(struct bat_priv *bat_priv, struct orig_node *orig_node, router = orig_node_get_router(orig_node);
if (router != neigh_node) - update_route(bat_priv, orig_node, neigh_node); + _update_route(bat_priv, orig_node, neigh_node);
out: if (router) neigh_node_free_ref(router); }
-static int is_bidirectional_neigh(struct orig_node *orig_node, - struct orig_node *orig_neigh_node, - struct batman_ogm_packet *batman_ogm_packet, - struct hard_iface *if_incoming) -{ - struct bat_priv *bat_priv = netdev_priv(if_incoming->soft_iface); - struct neigh_node *neigh_node = NULL, *tmp_neigh_node; - struct hlist_node *node; - uint8_t total_count; - uint8_t orig_eq_count, neigh_rq_count, tq_own; - int tq_asym_penalty, ret = 0; - - /* find corresponding one hop neighbor */ - rcu_read_lock(); - hlist_for_each_entry_rcu(tmp_neigh_node, node, - &orig_neigh_node->neigh_list, list) { - - if (!compare_eth(tmp_neigh_node->addr, orig_neigh_node->orig)) - continue; - - if (tmp_neigh_node->if_incoming != if_incoming) - continue; - - if (!atomic_inc_not_zero(&tmp_neigh_node->refcount)) - continue; - - neigh_node = tmp_neigh_node; - break; - } - rcu_read_unlock(); - - if (!neigh_node) - neigh_node = create_neighbor(orig_neigh_node, - orig_neigh_node, - orig_neigh_node->orig, - if_incoming); - - if (!neigh_node) - goto out; - - /* if orig_node is direct neighbor update neigh_node last_valid */ - if (orig_node == orig_neigh_node) - neigh_node->last_valid = jiffies; - - orig_node->last_valid = jiffies; - - /* find packet count of corresponding one hop neighbor */ - spin_lock_bh(&orig_node->ogm_cnt_lock); - orig_eq_count = orig_neigh_node->bcast_own_sum[if_incoming->if_num]; - neigh_rq_count = neigh_node->real_packet_count; - spin_unlock_bh(&orig_node->ogm_cnt_lock); - - /* pay attention to not get a value bigger than 100 % */ - total_count = (orig_eq_count > neigh_rq_count ? - neigh_rq_count : orig_eq_count); - - /* if we have too few packets (too less data) we set tq_own to zero */ - /* if we receive too few packets it is not considered bidirectional */ - if ((total_count < TQ_LOCAL_BIDRECT_SEND_MINIMUM) || - (neigh_rq_count < TQ_LOCAL_BIDRECT_RECV_MINIMUM)) - tq_own = 0; - else - /* neigh_node->real_packet_count is never zero as we - * only purge old information when getting new - * information */ - tq_own = (TQ_MAX_VALUE * total_count) / neigh_rq_count; - - /* - * 1 - ((1-x) ** 3), normalized to TQ_MAX_VALUE this does - * affect the nearly-symmetric links only a little, but - * punishes asymmetric links more. This will give a value - * between 0 and TQ_MAX_VALUE - */ - tq_asym_penalty = TQ_MAX_VALUE - (TQ_MAX_VALUE * - (TQ_LOCAL_WINDOW_SIZE - neigh_rq_count) * - (TQ_LOCAL_WINDOW_SIZE - neigh_rq_count) * - (TQ_LOCAL_WINDOW_SIZE - neigh_rq_count)) / - (TQ_LOCAL_WINDOW_SIZE * - TQ_LOCAL_WINDOW_SIZE * - TQ_LOCAL_WINDOW_SIZE); - - batman_ogm_packet->tq = ((batman_ogm_packet->tq * tq_own - * tq_asym_penalty) / - (TQ_MAX_VALUE * TQ_MAX_VALUE)); - - bat_dbg(DBG_BATMAN, bat_priv, - "bidirectional: " - "orig = %-15pM neigh = %-15pM => own_bcast = %2i, " - "real recv = %2i, local tq: %3i, asym_penalty: %3i, " - "total tq: %3i\n", - orig_node->orig, orig_neigh_node->orig, total_count, - neigh_rq_count, tq_own, tq_asym_penalty, batman_ogm_packet->tq); - - /* if link has the minimum required transmission quality - * consider it bidirectional */ - if (batman_ogm_packet->tq >= TQ_TOTAL_BIDRECT_LIMIT) - ret = 1; - -out: - if (neigh_node) - neigh_node_free_ref(neigh_node); - return ret; -} - /* caller must hold the neigh_list_lock */ void bonding_candidate_del(struct orig_node *orig_node, struct neigh_node *neigh_node) @@ -249,8 +141,8 @@ out: return; }
-static void bonding_candidate_add(struct orig_node *orig_node, - struct neigh_node *neigh_node) +void bonding_candidate_add(struct orig_node *orig_node, + struct neigh_node *neigh_node) { struct hlist_node *node; struct neigh_node *tmp_neigh_node, *router = NULL; @@ -320,10 +212,9 @@ out: }
/* copy primary address for bonding */ -static void bonding_save_primary(const struct orig_node *orig_node, - struct orig_node *orig_neigh_node, - const struct batman_ogm_packet - *batman_ogm_packet) +void bonding_save_primary(const struct orig_node *orig_node, + struct orig_node *orig_neigh_node, + const struct batman_ogm_packet *batman_ogm_packet) { if (!(batman_ogm_packet->flags & PRIMARIES_FIRST_HOP)) return; @@ -331,153 +222,13 @@ static void bonding_save_primary(const struct orig_node *orig_node, memcpy(orig_neigh_node->primary_addr, orig_node->orig, ETH_ALEN); }
-static void update_orig(struct bat_priv *bat_priv, struct orig_node *orig_node, - const struct ethhdr *ethhdr, - const struct batman_ogm_packet *batman_ogm_packet, - struct hard_iface *if_incoming, - const unsigned char *tt_buff, int is_duplicate) -{ - struct neigh_node *neigh_node = NULL, *tmp_neigh_node = NULL; - struct neigh_node *router = NULL; - struct orig_node *orig_node_tmp; - struct hlist_node *node; - uint8_t bcast_own_sum_orig, bcast_own_sum_neigh; - - bat_dbg(DBG_BATMAN, bat_priv, "update_originator(): " - "Searching and updating originator entry of received packet\n"); - - rcu_read_lock(); - hlist_for_each_entry_rcu(tmp_neigh_node, node, - &orig_node->neigh_list, list) { - if (compare_eth(tmp_neigh_node->addr, ethhdr->h_source) && - (tmp_neigh_node->if_incoming == if_incoming) && - atomic_inc_not_zero(&tmp_neigh_node->refcount)) { - if (neigh_node) - neigh_node_free_ref(neigh_node); - neigh_node = tmp_neigh_node; - continue; - } - - if (is_duplicate) - continue; - - spin_lock_bh(&tmp_neigh_node->tq_lock); - ring_buffer_set(tmp_neigh_node->tq_recv, - &tmp_neigh_node->tq_index, 0); - tmp_neigh_node->tq_avg = - ring_buffer_avg(tmp_neigh_node->tq_recv); - spin_unlock_bh(&tmp_neigh_node->tq_lock); - } - - if (!neigh_node) { - struct orig_node *orig_tmp; - - orig_tmp = get_orig_node(bat_priv, ethhdr->h_source); - if (!orig_tmp) - goto unlock; - - neigh_node = create_neighbor(orig_node, orig_tmp, - ethhdr->h_source, if_incoming); - - orig_node_free_ref(orig_tmp); - if (!neigh_node) - goto unlock; - } else - bat_dbg(DBG_BATMAN, bat_priv, - "Updating existing last-hop neighbor of originator\n"); - - rcu_read_unlock(); - - orig_node->flags = batman_ogm_packet->flags; - neigh_node->last_valid = jiffies; - - spin_lock_bh(&neigh_node->tq_lock); - ring_buffer_set(neigh_node->tq_recv, - &neigh_node->tq_index, - batman_ogm_packet->tq); - neigh_node->tq_avg = ring_buffer_avg(neigh_node->tq_recv); - spin_unlock_bh(&neigh_node->tq_lock); - - if (!is_duplicate) { - orig_node->last_ttl = batman_ogm_packet->ttl; - neigh_node->last_ttl = batman_ogm_packet->ttl; - } - - bonding_candidate_add(orig_node, neigh_node); - - /* if this neighbor already is our next hop there is nothing - * to change */ - router = orig_node_get_router(orig_node); - if (router == neigh_node) - goto update_tt; - - /* if this neighbor does not offer a better TQ we won't consider it */ - if (router && (router->tq_avg > neigh_node->tq_avg)) - goto update_tt; - - /* if the TQ is the same and the link not more symmetric we - * won't consider it either */ - if (router && (neigh_node->tq_avg == router->tq_avg)) { - orig_node_tmp = router->orig_node; - spin_lock_bh(&orig_node_tmp->ogm_cnt_lock); - bcast_own_sum_orig = - orig_node_tmp->bcast_own_sum[if_incoming->if_num]; - spin_unlock_bh(&orig_node_tmp->ogm_cnt_lock); - - orig_node_tmp = neigh_node->orig_node; - spin_lock_bh(&orig_node_tmp->ogm_cnt_lock); - bcast_own_sum_neigh = - orig_node_tmp->bcast_own_sum[if_incoming->if_num]; - spin_unlock_bh(&orig_node_tmp->ogm_cnt_lock); - - if (bcast_own_sum_orig >= bcast_own_sum_neigh) - goto update_tt; - } - - update_routes(bat_priv, orig_node, neigh_node); - -update_tt: - /* I have to check for transtable changes only if the OGM has been - * sent through a primary interface */ - if (((batman_ogm_packet->orig != ethhdr->h_source) && - (batman_ogm_packet->ttl > 2)) || - (batman_ogm_packet->flags & PRIMARIES_FIRST_HOP)) - tt_update_orig(bat_priv, orig_node, tt_buff, - batman_ogm_packet->tt_num_changes, - batman_ogm_packet->ttvn, - batman_ogm_packet->tt_crc); - - if (orig_node->gw_flags != batman_ogm_packet->gw_flags) - gw_node_update(bat_priv, orig_node, - batman_ogm_packet->gw_flags); - - orig_node->gw_flags = batman_ogm_packet->gw_flags; - - /* restart gateway selection if fast or late switching was enabled */ - if ((orig_node->gw_flags) && - (atomic_read(&bat_priv->gw_mode) == GW_MODE_CLIENT) && - (atomic_read(&bat_priv->gw_sel_class) > 2)) - gw_check_election(bat_priv, orig_node); - - goto out; - -unlock: - rcu_read_unlock(); -out: - if (neigh_node) - neigh_node_free_ref(neigh_node); - if (router) - neigh_node_free_ref(router); -} - /* checks whether the host restarted and is in the protection time. * returns: * 0 if the packet is to be accepted * 1 if the packet is to be ignored. */ -static int window_protected(struct bat_priv *bat_priv, - int32_t seq_num_diff, - unsigned long *last_reset) +int window_protected(struct bat_priv *bat_priv, int32_t seq_num_diff, + unsigned long *last_reset) { if ((seq_num_diff <= -TQ_LOCAL_WINDOW_SIZE) || (seq_num_diff >= EXPECTED_SEQNO_RANGE)) { @@ -495,329 +246,7 @@ static int window_protected(struct bat_priv *bat_priv, return 0; }
-/* processes a batman packet for all interfaces, adjusts the sequence number and - * finds out whether it is a duplicate. - * returns: - * 1 the packet is a duplicate - * 0 the packet has not yet been received - * -1 the packet is old and has been received while the seqno window - * was protected. Caller should drop it. - */ -static int count_real_packets(const struct ethhdr *ethhdr, - const struct batman_ogm_packet *batman_ogm_packet, - const struct hard_iface *if_incoming) -{ - struct bat_priv *bat_priv = netdev_priv(if_incoming->soft_iface); - struct orig_node *orig_node; - struct neigh_node *tmp_neigh_node; - struct hlist_node *node; - int is_duplicate = 0; - int32_t seq_diff; - int need_update = 0; - int set_mark, ret = -1; - - orig_node = get_orig_node(bat_priv, batman_ogm_packet->orig); - if (!orig_node) - return 0; - - spin_lock_bh(&orig_node->ogm_cnt_lock); - seq_diff = batman_ogm_packet->seqno - orig_node->last_real_seqno; - - /* signalize caller that the packet is to be dropped. */ - if (window_protected(bat_priv, seq_diff, - &orig_node->batman_seqno_reset)) - goto out; - - rcu_read_lock(); - hlist_for_each_entry_rcu(tmp_neigh_node, node, - &orig_node->neigh_list, list) { - - is_duplicate |= get_bit_status(tmp_neigh_node->real_bits, - orig_node->last_real_seqno, - batman_ogm_packet->seqno); - - if (compare_eth(tmp_neigh_node->addr, ethhdr->h_source) && - (tmp_neigh_node->if_incoming == if_incoming)) - set_mark = 1; - else - set_mark = 0; - - /* if the window moved, set the update flag. */ - need_update |= bit_get_packet(bat_priv, - tmp_neigh_node->real_bits, - seq_diff, set_mark); - - tmp_neigh_node->real_packet_count = - bit_packet_count(tmp_neigh_node->real_bits); - } - rcu_read_unlock(); - - if (need_update) { - bat_dbg(DBG_BATMAN, bat_priv, - "updating last_seqno: old %d, new %d\n", - orig_node->last_real_seqno, batman_ogm_packet->seqno); - orig_node->last_real_seqno = batman_ogm_packet->seqno; - } - - ret = is_duplicate; - -out: - spin_unlock_bh(&orig_node->ogm_cnt_lock); - orig_node_free_ref(orig_node); - return ret; -} - -void receive_bat_packet(const struct ethhdr *ethhdr, - struct batman_ogm_packet *batman_ogm_packet, - const unsigned char *tt_buff, - struct hard_iface *if_incoming) -{ - struct bat_priv *bat_priv = netdev_priv(if_incoming->soft_iface); - struct hard_iface *hard_iface; - struct orig_node *orig_neigh_node, *orig_node; - struct neigh_node *router = NULL, *router_router = NULL; - struct neigh_node *orig_neigh_router = NULL; - int has_directlink_flag; - int is_my_addr = 0, is_my_orig = 0, is_my_oldorig = 0; - int is_broadcast = 0, is_bidirectional, is_single_hop_neigh; - int is_duplicate; - uint32_t if_incoming_seqno; - - /* Silently drop when the batman packet is actually not a - * correct packet. - * - * This might happen if a packet is padded (e.g. Ethernet has a - * minimum frame length of 64 byte) and the aggregation interprets - * it as an additional length. - * - * TODO: A more sane solution would be to have a bit in the - * batman_ogm_packet to detect whether the packet is the last - * packet in an aggregation. Here we expect that the padding - * is always zero (or not 0x01) - */ - if (batman_ogm_packet->packet_type != BAT_OGM) - return; - - /* could be changed by schedule_own_packet() */ - if_incoming_seqno = atomic_read(&if_incoming->seqno); - - has_directlink_flag = (batman_ogm_packet->flags & DIRECTLINK ? 1 : 0); - - is_single_hop_neigh = (compare_eth(ethhdr->h_source, - batman_ogm_packet->orig) ? 1 : 0); - - bat_dbg(DBG_BATMAN, bat_priv, - "Received BATMAN packet via NB: %pM, IF: %s [%pM] " - "(from OG: %pM, via prev OG: %pM, seqno %d, ttvn %u, " - "crc %u, changes %u, td %d, TTL %d, V %d, IDF %d)\n", - ethhdr->h_source, if_incoming->net_dev->name, - if_incoming->net_dev->dev_addr, batman_ogm_packet->orig, - batman_ogm_packet->prev_sender, batman_ogm_packet->seqno, - batman_ogm_packet->ttvn, batman_ogm_packet->tt_crc, - batman_ogm_packet->tt_num_changes, batman_ogm_packet->tq, - batman_ogm_packet->ttl, batman_ogm_packet->version, - has_directlink_flag); - - rcu_read_lock(); - list_for_each_entry_rcu(hard_iface, &hardif_list, list) { - if (hard_iface->if_status != IF_ACTIVE) - continue; - - if (hard_iface->soft_iface != if_incoming->soft_iface) - continue; - - if (compare_eth(ethhdr->h_source, - hard_iface->net_dev->dev_addr)) - is_my_addr = 1; - - if (compare_eth(batman_ogm_packet->orig, - hard_iface->net_dev->dev_addr)) - is_my_orig = 1; - - if (compare_eth(batman_ogm_packet->prev_sender, - hard_iface->net_dev->dev_addr)) - is_my_oldorig = 1; - - if (is_broadcast_ether_addr(ethhdr->h_source)) - is_broadcast = 1; - } - rcu_read_unlock(); - - if (batman_ogm_packet->version != COMPAT_VERSION) { - bat_dbg(DBG_BATMAN, bat_priv, - "Drop packet: incompatible batman version (%i)\n", - batman_ogm_packet->version); - return; - } - - if (is_my_addr) { - bat_dbg(DBG_BATMAN, bat_priv, - "Drop packet: received my own broadcast (sender: %pM" - ")\n", - ethhdr->h_source); - return; - } - - if (is_broadcast) { - bat_dbg(DBG_BATMAN, bat_priv, "Drop packet: " - "ignoring all packets with broadcast source addr (sender: %pM" - ")\n", ethhdr->h_source); - return; - } - - if (is_my_orig) { - unsigned long *word; - int offset; - - orig_neigh_node = get_orig_node(bat_priv, ethhdr->h_source); - if (!orig_neigh_node) - return; - - /* neighbor has to indicate direct link and it has to - * come via the corresponding interface */ - /* save packet seqno for bidirectional check */ - if (has_directlink_flag && - compare_eth(if_incoming->net_dev->dev_addr, - batman_ogm_packet->orig)) { - offset = if_incoming->if_num * NUM_WORDS; - - spin_lock_bh(&orig_neigh_node->ogm_cnt_lock); - word = &(orig_neigh_node->bcast_own[offset]); - bit_mark(word, - if_incoming_seqno - - batman_ogm_packet->seqno - 2); - orig_neigh_node->bcast_own_sum[if_incoming->if_num] = - bit_packet_count(word); - spin_unlock_bh(&orig_neigh_node->ogm_cnt_lock); - } - - bat_dbg(DBG_BATMAN, bat_priv, "Drop packet: " - "originator packet from myself (via neighbor)\n"); - orig_node_free_ref(orig_neigh_node); - return; - } - - if (is_my_oldorig) { - bat_dbg(DBG_BATMAN, bat_priv, - "Drop packet: ignoring all rebroadcast echos (sender: " - "%pM)\n", ethhdr->h_source); - return; - } - - orig_node = get_orig_node(bat_priv, batman_ogm_packet->orig); - if (!orig_node) - return; - - is_duplicate = count_real_packets(ethhdr, batman_ogm_packet, - if_incoming); - - if (is_duplicate == -1) { - bat_dbg(DBG_BATMAN, bat_priv, - "Drop packet: packet within seqno protection time " - "(sender: %pM)\n", ethhdr->h_source); - goto out; - } - - if (batman_ogm_packet->tq == 0) { - bat_dbg(DBG_BATMAN, bat_priv, - "Drop packet: originator packet with tq equal 0\n"); - goto out; - } - - router = orig_node_get_router(orig_node); - if (router) - router_router = orig_node_get_router(router->orig_node); - - /* avoid temporary routing loops */ - if (router && router_router && - (compare_eth(router->addr, batman_ogm_packet->prev_sender)) && - !(compare_eth(batman_ogm_packet->orig, - batman_ogm_packet->prev_sender)) && - (compare_eth(router->addr, router_router->addr))) { - bat_dbg(DBG_BATMAN, bat_priv, - "Drop packet: ignoring all rebroadcast packets that " - "may make me loop (sender: %pM)\n", ethhdr->h_source); - goto out; - } - - /* if sender is a direct neighbor the sender mac equals - * originator mac */ - orig_neigh_node = (is_single_hop_neigh ? - orig_node : - get_orig_node(bat_priv, ethhdr->h_source)); - if (!orig_neigh_node) - goto out; - - orig_neigh_router = orig_node_get_router(orig_neigh_node); - - /* drop packet if sender is not a direct neighbor and if we - * don't route towards it */ - if (!is_single_hop_neigh && (!orig_neigh_router)) { - bat_dbg(DBG_BATMAN, bat_priv, - "Drop packet: OGM via unknown neighbor!\n"); - goto out_neigh; - } - - is_bidirectional = is_bidirectional_neigh(orig_node, orig_neigh_node, - batman_ogm_packet, - if_incoming); - - bonding_save_primary(orig_node, orig_neigh_node, batman_ogm_packet); - - /* update ranking if it is not a duplicate or has the same - * seqno and similar ttl as the non-duplicate */ - if (is_bidirectional && - (!is_duplicate || - ((orig_node->last_real_seqno == batman_ogm_packet->seqno) && - (orig_node->last_ttl - 3 <= batman_ogm_packet->ttl)))) - update_orig(bat_priv, orig_node, ethhdr, batman_ogm_packet, - if_incoming, tt_buff, is_duplicate); - - /* is single hop (direct) neighbor */ - if (is_single_hop_neigh) { - - /* mark direct link on incoming interface */ - schedule_forward_packet(orig_node, ethhdr, batman_ogm_packet, - 1, if_incoming); - - bat_dbg(DBG_BATMAN, bat_priv, "Forwarding packet: " - "rebroadcast neighbor packet with direct link flag\n"); - goto out_neigh; - } - - /* multihop originator */ - if (!is_bidirectional) { - bat_dbg(DBG_BATMAN, bat_priv, - "Drop packet: not received via bidirectional link\n"); - goto out_neigh; - } - - if (is_duplicate) { - bat_dbg(DBG_BATMAN, bat_priv, - "Drop packet: duplicate packet received\n"); - goto out_neigh; - } - - bat_dbg(DBG_BATMAN, bat_priv, - "Forwarding packet: rebroadcast originator packet\n"); - schedule_forward_packet(orig_node, ethhdr, batman_ogm_packet, - 0, if_incoming); - -out_neigh: - if ((orig_neigh_node) && (!is_single_hop_neigh)) - orig_node_free_ref(orig_neigh_node); -out: - if (router) - neigh_node_free_ref(router); - if (router_router) - neigh_node_free_ref(router_router); - if (orig_neigh_router) - neigh_node_free_ref(orig_neigh_router); - - orig_node_free_ref(orig_node); -} - -int recv_bat_packet(struct sk_buff *skb, struct hard_iface *hard_iface) +int recv_bat_ogm_packet(struct sk_buff *skb, struct hard_iface *hard_iface) { struct ethhdr *ethhdr;
@@ -845,10 +274,7 @@ int recv_bat_packet(struct sk_buff *skb, struct hard_iface *hard_iface)
ethhdr = (struct ethhdr *)skb_mac_header(skb);
- receive_aggr_bat_packet(ethhdr, - skb->data, - skb_headlen(skb), - hard_iface); + bat_ogm_receive(ethhdr, skb->data, skb_headlen(skb), hard_iface);
kfree_skb(skb); return NET_RX_SUCCESS; diff --git a/routing.h b/routing.h index 893db7f..7aaee0f 100644 --- a/routing.h +++ b/routing.h @@ -23,19 +23,15 @@ #define _NET_BATMAN_ADV_ROUTING_H_
void slide_own_bcast_window(struct hard_iface *hard_iface); -void receive_bat_packet(const struct ethhdr *ethhdr, - struct batman_ogm_packet *batman_ogm_packet, - const unsigned char *tt_buff, - struct hard_iface *if_incoming); -void update_routes(struct bat_priv *bat_priv, struct orig_node *orig_node, - struct neigh_node *neigh_node); +void update_route(struct bat_priv *bat_priv, struct orig_node *orig_node, + struct neigh_node *neigh_node); int route_unicast_packet(struct sk_buff *skb, struct hard_iface *recv_if); int recv_icmp_packet(struct sk_buff *skb, struct hard_iface *recv_if); int recv_unicast_packet(struct sk_buff *skb, struct hard_iface *recv_if); int recv_ucast_frag_packet(struct sk_buff *skb, struct hard_iface *recv_if); int recv_bcast_packet(struct sk_buff *skb, struct hard_iface *recv_if); int recv_vis_packet(struct sk_buff *skb, struct hard_iface *recv_if); -int recv_bat_packet(struct sk_buff *skb, struct hard_iface *recv_if); +int recv_bat_ogm_packet(struct sk_buff *skb, struct hard_iface *recv_if); int recv_tt_query(struct sk_buff *skb, struct hard_iface *recv_if); int recv_roam_adv(struct sk_buff *skb, struct hard_iface *recv_if); struct neigh_node *find_router(struct bat_priv *bat_priv, @@ -43,5 +39,12 @@ struct neigh_node *find_router(struct bat_priv *bat_priv, const struct hard_iface *recv_if); void bonding_candidate_del(struct orig_node *orig_node, struct neigh_node *neigh_node); +void bonding_candidate_add(struct orig_node *orig_node, + struct neigh_node *neigh_node); +void bonding_save_primary(const struct orig_node *orig_node, + struct orig_node *orig_neigh_node, + const struct batman_ogm_packet *batman_ogm_packet); +int window_protected(struct bat_priv *bat_priv, int32_t seq_num_diff, + unsigned long *last_reset);
#endif /* _NET_BATMAN_ADV_ROUTING_H_ */
On Wednesday, August 03, 2011 09:53:00 Marek Lindner wrote:
In preparation of the upcoming improved routing algorithm the code based has to be re-organized to allow choosing the routing algorithm at compile time.
Applied in revision 3a96396.
Regards, Marek
Signed-off-by: Marek Lindner lindner_marek@yahoo.de --- bat_iv_ogm.c | 37 +++++++++++++++++++++++++++++++++++++ bat_ogm.h | 3 +++ hard-interface.c | 38 ++++++-------------------------------- 3 files changed, 46 insertions(+), 32 deletions(-)
diff --git a/bat_iv_ogm.c b/bat_iv_ogm.c index 6fa2d46..468bd5e 100644 --- a/bat_iv_ogm.c +++ b/bat_iv_ogm.c @@ -30,6 +30,43 @@ #include "hard-interface.h" #include "send.h"
+void bat_ogm_init(struct hard_iface *hard_iface) +{ + struct batman_ogm_packet *batman_ogm_packet; + + hard_iface->packet_len = BATMAN_OGM_LEN; + hard_iface->packet_buff = kmalloc(hard_iface->packet_len, GFP_ATOMIC); + + batman_ogm_packet = (struct batman_ogm_packet *)hard_iface->packet_buff; + batman_ogm_packet->packet_type = BAT_OGM; + batman_ogm_packet->version = COMPAT_VERSION; + batman_ogm_packet->flags = NO_FLAGS; + batman_ogm_packet->ttl = 2; + batman_ogm_packet->tq = TQ_MAX_VALUE; + batman_ogm_packet->tt_num_changes = 0; + batman_ogm_packet->ttvn = 0; +} + +void bat_ogm_init_primary(struct hard_iface *hard_iface) +{ + struct batman_ogm_packet *batman_ogm_packet; + + batman_ogm_packet = (struct batman_ogm_packet *)hard_iface->packet_buff; + batman_ogm_packet->flags = PRIMARIES_FIRST_HOP; + batman_ogm_packet->ttl = TTL; +} + +void bat_ogm_update_mac(struct hard_iface *hard_iface) +{ + struct batman_ogm_packet *batman_ogm_packet; + + batman_ogm_packet = (struct batman_ogm_packet *)hard_iface->packet_buff; + memcpy(batman_ogm_packet->orig, + hard_iface->net_dev->dev_addr, ETH_ALEN); + memcpy(batman_ogm_packet->prev_sender, + hard_iface->net_dev->dev_addr, ETH_ALEN); +} + /* is there another aggregated packet here? */ static int bat_ogm_aggr_packet(int buff_pos, int packet_len, int tt_num_changes) diff --git a/bat_ogm.h b/bat_ogm.h index bdd3d1e..7809b92 100644 --- a/bat_ogm.h +++ b/bat_ogm.h @@ -24,6 +24,9 @@
#include "main.h"
+void bat_ogm_init(struct hard_iface *hard_iface); +void bat_ogm_init_primary(struct hard_iface *hard_iface); +void bat_ogm_update_mac(struct hard_iface *hard_iface); void bat_ogm_receive(const struct ethhdr *ethhdr, unsigned char *packet_buff, int packet_len, struct hard_iface *if_incoming);
diff --git a/hard-interface.c b/hard-interface.c index cfee017..2a15582 100644 --- a/hard-interface.c +++ b/hard-interface.c @@ -28,6 +28,7 @@ #include "bat_sysfs.h" #include "originator.h" #include "hash.h" +#include "bat_ogm.h"
#include <linux/if_arp.h>
@@ -131,7 +132,6 @@ static void primary_if_select(struct bat_priv *bat_priv, struct hard_iface *new_hard_iface) { struct hard_iface *curr_hard_iface; - struct batman_ogm_packet *batman_ogm_packet;
ASSERT_RTNL();
@@ -147,11 +147,7 @@ static void primary_if_select(struct bat_priv *bat_priv, if (!new_hard_iface) return;
- batman_ogm_packet = (struct batman_ogm_packet *) - (new_hard_iface->packet_buff); - batman_ogm_packet->flags = PRIMARIES_FIRST_HOP; - batman_ogm_packet->ttl = TTL; - + bat_ogm_init_primary(new_hard_iface); primary_if_update_addr(bat_priv); }
@@ -163,17 +159,6 @@ static bool hardif_is_iface_up(const struct hard_iface *hard_iface) return false; }
-static void update_mac_addresses(struct hard_iface *hard_iface) -{ - struct batman_ogm_packet *batman_ogm_packet; - - batman_ogm_packet = (struct batman_ogm_packet *)hard_iface->packet_buff; - memcpy(batman_ogm_packet->orig, - hard_iface->net_dev->dev_addr, ETH_ALEN); - memcpy(batman_ogm_packet->prev_sender, - hard_iface->net_dev->dev_addr, ETH_ALEN); -} - static void check_known_mac_addr(const struct net_device *net_dev) { const struct hard_iface *hard_iface; @@ -248,7 +233,7 @@ static void hardif_activate_interface(struct hard_iface *hard_iface)
bat_priv = netdev_priv(hard_iface->soft_iface);
- update_mac_addresses(hard_iface); + bat_ogm_update_mac(hard_iface); hard_iface->if_status = IF_TO_BE_ACTIVATED;
/** @@ -287,7 +272,6 @@ int hardif_enable_interface(struct hard_iface *hard_iface, const char *iface_name) { struct bat_priv *bat_priv; - struct batman_ogm_packet *batman_ogm_packet; struct net_device *soft_iface; int ret;
@@ -322,8 +306,8 @@ int hardif_enable_interface(struct hard_iface *hard_iface,
hard_iface->soft_iface = soft_iface; bat_priv = netdev_priv(hard_iface->soft_iface); - hard_iface->packet_len = BATMAN_OGM_LEN; - hard_iface->packet_buff = kmalloc(hard_iface->packet_len, GFP_ATOMIC); + + bat_ogm_init(hard_iface);
if (!hard_iface->packet_buff) { bat_err(hard_iface->soft_iface, "Can't add interface packet " @@ -332,16 +316,6 @@ int hardif_enable_interface(struct hard_iface *hard_iface, goto err; }
- batman_ogm_packet = (struct batman_ogm_packet *) - (hard_iface->packet_buff); - batman_ogm_packet->packet_type = BAT_OGM; - batman_ogm_packet->version = COMPAT_VERSION; - batman_ogm_packet->flags = NO_FLAGS; - batman_ogm_packet->ttl = 2; - batman_ogm_packet->tq = TQ_MAX_VALUE; - batman_ogm_packet->tt_num_changes = 0; - batman_ogm_packet->ttvn = 0; - hard_iface->if_num = bat_priv->num_ifaces; bat_priv->num_ifaces++; hard_iface->if_status = IF_INACTIVE; @@ -556,7 +530,7 @@ static int hard_if_event(struct notifier_block *this, goto hardif_put;
check_known_mac_addr(hard_iface->net_dev); - update_mac_addresses(hard_iface); + bat_ogm_update_mac(hard_iface);
bat_priv = netdev_priv(hard_iface->soft_iface); primary_if = primary_if_get_selected(bat_priv);
On Wednesday, August 03, 2011 09:53:01 Marek Lindner wrote:
Signed-off-by: Marek Lindner lindner_marek@yahoo.de
bat_iv_ogm.c | 37 +++++++++++++++++++++++++++++++++++++ bat_ogm.h | 3 +++ hard-interface.c | 38 ++++++-------------------------------- 3 files changed, 46 insertions(+), 32 deletions(-)
Applied in revision eb65c17.
Regards, Marek
In the process the batman iv OGM aggregation code could be merged into the batman iv code base which makes the separate aggregation files superfluous.
Signed-off-by: Marek Lindner lindner_marek@yahoo.de --- Makefile.kbuild | 1 - aggregation.c | 266 ----------------------------- aggregation.h | 42 ----- bat_iv_ogm.c | 502 +++++++++++++++++++++++++++++++++++++++++++++++++++++- bat_ogm.h | 2 + hard-interface.c | 2 +- send.c | 297 ++------------------------------ send.h | 9 +- 8 files changed, 522 insertions(+), 599 deletions(-) delete mode 100644 aggregation.c delete mode 100644 aggregation.h
diff --git a/Makefile.kbuild b/Makefile.kbuild index 3865d4d..6377c17 100644 --- a/Makefile.kbuild +++ b/Makefile.kbuild @@ -32,7 +32,6 @@ EXTRA_CFLAGS += -DSOURCE_VERSION="$(REVISION)" endif
obj-m += batman-adv.o -batman-adv-y += aggregation.o batman-adv-y += bat_debugfs.o batman-adv-y += bat_iv_ogm.o batman-adv-y += bat_sysfs.o diff --git a/aggregation.c b/aggregation.c deleted file mode 100644 index 4716c93..0000000 --- a/aggregation.c +++ /dev/null @@ -1,266 +0,0 @@ -/* - * Copyright (C) 2007-2011 B.A.T.M.A.N. contributors: - * - * Marek Lindner, Simon Wunderlich - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA - * - */ - -#include "main.h" -#include "translation-table.h" -#include "aggregation.h" -#include "send.h" -#include "routing.h" -#include "hard-interface.h" - -/* return true if new_packet can be aggregated with forw_packet */ -static bool can_aggregate_with(const struct batman_ogm_packet - *new_batman_ogm_packet, - struct bat_priv *bat_priv, - int packet_len, - unsigned long send_time, - bool directlink, - const struct hard_iface *if_incoming, - const struct forw_packet *forw_packet) -{ - struct batman_ogm_packet *batman_ogm_packet = - (struct batman_ogm_packet *)forw_packet->skb->data; - int aggregated_bytes = forw_packet->packet_len + packet_len; - struct hard_iface *primary_if = NULL; - bool res = false; - - /** - * we can aggregate the current packet to this aggregated packet - * if: - * - * - the send time is within our MAX_AGGREGATION_MS time - * - the resulting packet wont be bigger than - * MAX_AGGREGATION_BYTES - */ - - if (time_before(send_time, forw_packet->send_time) && - time_after_eq(send_time + msecs_to_jiffies(MAX_AGGREGATION_MS), - forw_packet->send_time) && - (aggregated_bytes <= MAX_AGGREGATION_BYTES)) { - - /** - * check aggregation compatibility - * -> direct link packets are broadcasted on - * their interface only - * -> aggregate packet if the current packet is - * a "global" packet as well as the base - * packet - */ - - primary_if = primary_if_get_selected(bat_priv); - if (!primary_if) - goto out; - - /* packets without direct link flag and high TTL - * are flooded through the net */ - if ((!directlink) && - (!(batman_ogm_packet->flags & DIRECTLINK)) && - (batman_ogm_packet->ttl != 1) && - - /* own packets originating non-primary - * interfaces leave only that interface */ - ((!forw_packet->own) || - (forw_packet->if_incoming == primary_if))) { - res = true; - goto out; - } - - /* if the incoming packet is sent via this one - * interface only - we still can aggregate */ - if ((directlink) && - (new_batman_ogm_packet->ttl == 1) && - (forw_packet->if_incoming == if_incoming) && - - /* packets from direct neighbors or - * own secondary interface packets - * (= secondary interface packets in general) */ - (batman_ogm_packet->flags & DIRECTLINK || - (forw_packet->own && - forw_packet->if_incoming != primary_if))) { - res = true; - goto out; - } - } - -out: - if (primary_if) - hardif_free_ref(primary_if); - return res; -} - -/* create a new aggregated packet and add this packet to it */ -static void new_aggregated_packet(const unsigned char *packet_buff, - int packet_len, unsigned long send_time, - bool direct_link, - struct hard_iface *if_incoming, - int own_packet) -{ - struct bat_priv *bat_priv = netdev_priv(if_incoming->soft_iface); - struct forw_packet *forw_packet_aggr; - unsigned char *skb_buff; - - if (!atomic_inc_not_zero(&if_incoming->refcount)) - return; - - /* own packet should always be scheduled */ - if (!own_packet) { - if (!atomic_dec_not_zero(&bat_priv->batman_queue_left)) { - bat_dbg(DBG_BATMAN, bat_priv, - "batman packet queue full\n"); - goto out; - } - } - - forw_packet_aggr = kmalloc(sizeof(*forw_packet_aggr), GFP_ATOMIC); - if (!forw_packet_aggr) { - if (!own_packet) - atomic_inc(&bat_priv->batman_queue_left); - goto out; - } - - if ((atomic_read(&bat_priv->aggregated_ogms)) && - (packet_len < MAX_AGGREGATION_BYTES)) - forw_packet_aggr->skb = dev_alloc_skb(MAX_AGGREGATION_BYTES + - sizeof(struct ethhdr)); - else - forw_packet_aggr->skb = dev_alloc_skb(packet_len + - sizeof(struct ethhdr)); - - if (!forw_packet_aggr->skb) { - if (!own_packet) - atomic_inc(&bat_priv->batman_queue_left); - kfree(forw_packet_aggr); - goto out; - } - skb_reserve(forw_packet_aggr->skb, sizeof(struct ethhdr)); - - INIT_HLIST_NODE(&forw_packet_aggr->list); - - skb_buff = skb_put(forw_packet_aggr->skb, packet_len); - forw_packet_aggr->packet_len = packet_len; - memcpy(skb_buff, packet_buff, packet_len); - - forw_packet_aggr->own = own_packet; - forw_packet_aggr->if_incoming = if_incoming; - forw_packet_aggr->num_packets = 0; - forw_packet_aggr->direct_link_flags = NO_FLAGS; - forw_packet_aggr->send_time = send_time; - - /* save packet direct link flag status */ - if (direct_link) - forw_packet_aggr->direct_link_flags |= 1; - - /* add new packet to packet list */ - spin_lock_bh(&bat_priv->forw_bat_list_lock); - hlist_add_head(&forw_packet_aggr->list, &bat_priv->forw_bat_list); - spin_unlock_bh(&bat_priv->forw_bat_list_lock); - - /* start timer for this packet */ - INIT_DELAYED_WORK(&forw_packet_aggr->delayed_work, - send_outstanding_bat_packet); - queue_delayed_work(bat_event_workqueue, - &forw_packet_aggr->delayed_work, - send_time - jiffies); - - return; -out: - hardif_free_ref(if_incoming); -} - -/* aggregate a new packet into the existing aggregation */ -static void aggregate(struct forw_packet *forw_packet_aggr, - const unsigned char *packet_buff, int packet_len, - bool direct_link) -{ - unsigned char *skb_buff; - - skb_buff = skb_put(forw_packet_aggr->skb, packet_len); - memcpy(skb_buff, packet_buff, packet_len); - forw_packet_aggr->packet_len += packet_len; - forw_packet_aggr->num_packets++; - - /* save packet direct link flag status */ - if (direct_link) - forw_packet_aggr->direct_link_flags |= - (1 << forw_packet_aggr->num_packets); -} - -void add_bat_packet_to_list(struct bat_priv *bat_priv, - unsigned char *packet_buff, int packet_len, - struct hard_iface *if_incoming, int own_packet, - unsigned long send_time) -{ - /** - * _aggr -> pointer to the packet we want to aggregate with - * _pos -> pointer to the position in the queue - */ - struct forw_packet *forw_packet_aggr = NULL, *forw_packet_pos = NULL; - struct hlist_node *tmp_node; - struct batman_ogm_packet *batman_ogm_packet; - bool direct_link; - - batman_ogm_packet = (struct batman_ogm_packet *)packet_buff; - direct_link = batman_ogm_packet->flags & DIRECTLINK ? 1 : 0; - - /* find position for the packet in the forward queue */ - spin_lock_bh(&bat_priv->forw_bat_list_lock); - /* own packets are not to be aggregated */ - if ((atomic_read(&bat_priv->aggregated_ogms)) && (!own_packet)) { - hlist_for_each_entry(forw_packet_pos, tmp_node, - &bat_priv->forw_bat_list, list) { - if (can_aggregate_with(batman_ogm_packet, - bat_priv, - packet_len, - send_time, - direct_link, - if_incoming, - forw_packet_pos)) { - forw_packet_aggr = forw_packet_pos; - break; - } - } - } - - /* nothing to aggregate with - either aggregation disabled or no - * suitable aggregation packet found */ - if (!forw_packet_aggr) { - /* the following section can run without the lock */ - spin_unlock_bh(&bat_priv->forw_bat_list_lock); - - /** - * if we could not aggregate this packet with one of the others - * we hold it back for a while, so that it might be aggregated - * later on - */ - if ((!own_packet) && - (atomic_read(&bat_priv->aggregated_ogms))) - send_time += msecs_to_jiffies(MAX_AGGREGATION_MS); - - new_aggregated_packet(packet_buff, packet_len, - send_time, direct_link, - if_incoming, own_packet); - } else { - aggregate(forw_packet_aggr, - packet_buff, packet_len, - direct_link); - spin_unlock_bh(&bat_priv->forw_bat_list_lock); - } -} diff --git a/aggregation.h b/aggregation.h deleted file mode 100644 index 7a92e4c..0000000 --- a/aggregation.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (C) 2007-2011 B.A.T.M.A.N. contributors: - * - * Marek Lindner, Simon Wunderlich - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA - * - */ - -#ifndef _NET_BATMAN_ADV_AGGREGATION_H_ -#define _NET_BATMAN_ADV_AGGREGATION_H_ - -#include "main.h" - -/* is there another aggregated packet here? */ -static inline int aggregated_packet(int buff_pos, int packet_len, - int tt_num_changes) -{ - int next_buff_pos = buff_pos + BATMAN_OGM_LEN + tt_len(tt_num_changes); - - return (next_buff_pos <= packet_len) && - (next_buff_pos <= MAX_AGGREGATION_BYTES); -} - -void add_bat_packet_to_list(struct bat_priv *bat_priv, - unsigned char *packet_buff, int packet_len, - struct hard_iface *if_incoming, int own_packet, - unsigned long send_time); - -#endif /* _NET_BATMAN_ADV_AGGREGATION_H_ */ diff --git a/bat_iv_ogm.c b/bat_iv_ogm.c index 468bd5e..3512e25 100644 --- a/bat_iv_ogm.c +++ b/bat_iv_ogm.c @@ -67,6 +67,27 @@ void bat_ogm_update_mac(struct hard_iface *hard_iface) hard_iface->net_dev->dev_addr, ETH_ALEN); }
+/* when do we schedule our own ogm to be sent */ +static unsigned long bat_ogm_emit_send_time(const struct bat_priv *bat_priv) +{ + return jiffies + msecs_to_jiffies( + atomic_read(&bat_priv->orig_interval) - + JITTER + (random32() % 2*JITTER)); +} + +/* when do we schedule a ogm packet to be sent */ +static unsigned long bat_ogm_fwd_send_time(void) +{ + return jiffies + msecs_to_jiffies(random32() % (JITTER/2)); +} + +/* apply hop penalty for a normal link */ +static uint8_t hop_penalty(uint8_t tq, const struct bat_priv *bat_priv) +{ + int hop_penalty = atomic_read(&bat_priv->hop_penalty); + return (tq * (TQ_MAX_VALUE - hop_penalty)) / (TQ_MAX_VALUE); +} + /* is there another aggregated packet here? */ static int bat_ogm_aggr_packet(int buff_pos, int packet_len, int tt_num_changes) @@ -77,6 +98,480 @@ static int bat_ogm_aggr_packet(int buff_pos, int packet_len, (next_buff_pos <= MAX_AGGREGATION_BYTES); }
+/* send a batman ogm to a given interface */ +static void bat_ogm_send_to_if(struct forw_packet *forw_packet, + struct hard_iface *hard_iface) +{ + struct bat_priv *bat_priv = netdev_priv(hard_iface->soft_iface); + char *fwd_str; + uint8_t packet_num; + int16_t buff_pos; + struct batman_ogm_packet *batman_ogm_packet; + struct sk_buff *skb; + + if (hard_iface->if_status != IF_ACTIVE) + return; + + packet_num = 0; + buff_pos = 0; + batman_ogm_packet = (struct batman_ogm_packet *)forw_packet->skb->data; + + /* adjust all flags and log packets */ + while (bat_ogm_aggr_packet(buff_pos, forw_packet->packet_len, + batman_ogm_packet->tt_num_changes)) { + + /* we might have aggregated direct link packets with an + * ordinary base packet */ + if ((forw_packet->direct_link_flags & (1 << packet_num)) && + (forw_packet->if_incoming == hard_iface)) + batman_ogm_packet->flags |= DIRECTLINK; + else + batman_ogm_packet->flags &= ~DIRECTLINK; + + fwd_str = (packet_num > 0 ? "Forwarding" : (forw_packet->own ? + "Sending own" : + "Forwarding")); + bat_dbg(DBG_BATMAN, bat_priv, + "%s %spacket (originator %pM, seqno %d, TQ %d, TTL %d," + " IDF %s, ttvn %d) on interface %s [%pM]\n", + fwd_str, (packet_num > 0 ? "aggregated " : ""), + batman_ogm_packet->orig, + ntohl(batman_ogm_packet->seqno), + batman_ogm_packet->tq, batman_ogm_packet->ttl, + (batman_ogm_packet->flags & DIRECTLINK ? + "on" : "off"), + batman_ogm_packet->ttvn, hard_iface->net_dev->name, + hard_iface->net_dev->dev_addr); + + buff_pos += BATMAN_OGM_LEN + + tt_len(batman_ogm_packet->tt_num_changes); + packet_num++; + batman_ogm_packet = (struct batman_ogm_packet *) + (forw_packet->skb->data + buff_pos); + } + + /* create clone because function is called more than once */ + skb = skb_clone(forw_packet->skb, GFP_ATOMIC); + if (skb) + send_skb_packet(skb, hard_iface, broadcast_addr); +} + +/* send a batman ogm packet */ +void bat_ogm_emit(struct forw_packet *forw_packet) +{ + struct hard_iface *hard_iface; + struct net_device *soft_iface; + struct bat_priv *bat_priv; + struct hard_iface *primary_if = NULL; + struct batman_ogm_packet *batman_ogm_packet; + unsigned char directlink; + + batman_ogm_packet = (struct batman_ogm_packet *) + (forw_packet->skb->data); + directlink = (batman_ogm_packet->flags & DIRECTLINK ? 1 : 0); + + if (!forw_packet->if_incoming) { + pr_err("Error - can't forward packet: incoming iface not " + "specified\n"); + goto out; + } + + soft_iface = forw_packet->if_incoming->soft_iface; + bat_priv = netdev_priv(soft_iface); + + if (forw_packet->if_incoming->if_status != IF_ACTIVE) + goto out; + + primary_if = primary_if_get_selected(bat_priv); + if (!primary_if) + goto out; + + /* multihomed peer assumed */ + /* non-primary OGMs are only broadcasted on their interface */ + if ((directlink && (batman_ogm_packet->ttl == 1)) || + (forw_packet->own && (forw_packet->if_incoming != primary_if))) { + + /* FIXME: what about aggregated packets ? */ + bat_dbg(DBG_BATMAN, bat_priv, + "%s packet (originator %pM, seqno %d, TTL %d) " + "on interface %s [%pM]\n", + (forw_packet->own ? "Sending own" : "Forwarding"), + batman_ogm_packet->orig, + ntohl(batman_ogm_packet->seqno), + batman_ogm_packet->ttl, + forw_packet->if_incoming->net_dev->name, + forw_packet->if_incoming->net_dev->dev_addr); + + /* skb is only used once and than forw_packet is free'd */ + send_skb_packet(forw_packet->skb, forw_packet->if_incoming, + broadcast_addr); + forw_packet->skb = NULL; + + goto out; + } + + /* broadcast on every interface */ + rcu_read_lock(); + list_for_each_entry_rcu(hard_iface, &hardif_list, list) { + if (hard_iface->soft_iface != soft_iface) + continue; + + bat_ogm_send_to_if(forw_packet, hard_iface); + } + rcu_read_unlock(); + +out: + if (primary_if) + hardif_free_ref(primary_if); +} + +/* return true if new_packet can be aggregated with forw_packet */ +static bool bat_ogm_can_aggregate(const struct batman_ogm_packet + *new_batman_ogm_packet, + struct bat_priv *bat_priv, + int packet_len, unsigned long send_time, + bool directlink, + const struct hard_iface *if_incoming, + const struct forw_packet *forw_packet) +{ + struct batman_ogm_packet *batman_ogm_packet; + int aggregated_bytes = forw_packet->packet_len + packet_len; + struct hard_iface *primary_if = NULL; + bool res = false; + + batman_ogm_packet = (struct batman_ogm_packet *)forw_packet->skb->data; + + /** + * we can aggregate the current packet to this aggregated packet + * if: + * + * - the send time is within our MAX_AGGREGATION_MS time + * - the resulting packet wont be bigger than + * MAX_AGGREGATION_BYTES + */ + + if (time_before(send_time, forw_packet->send_time) && + time_after_eq(send_time + msecs_to_jiffies(MAX_AGGREGATION_MS), + forw_packet->send_time) && + (aggregated_bytes <= MAX_AGGREGATION_BYTES)) { + + /** + * check aggregation compatibility + * -> direct link packets are broadcasted on + * their interface only + * -> aggregate packet if the current packet is + * a "global" packet as well as the base + * packet + */ + + primary_if = primary_if_get_selected(bat_priv); + if (!primary_if) + goto out; + + /* packets without direct link flag and high TTL + * are flooded through the net */ + if ((!directlink) && + (!(batman_ogm_packet->flags & DIRECTLINK)) && + (batman_ogm_packet->ttl != 1) && + + /* own packets originating non-primary + * interfaces leave only that interface */ + ((!forw_packet->own) || + (forw_packet->if_incoming == primary_if))) { + res = true; + goto out; + } + + /* if the incoming packet is sent via this one + * interface only - we still can aggregate */ + if ((directlink) && + (new_batman_ogm_packet->ttl == 1) && + (forw_packet->if_incoming == if_incoming) && + + /* packets from direct neighbors or + * own secondary interface packets + * (= secondary interface packets in general) */ + (batman_ogm_packet->flags & DIRECTLINK || + (forw_packet->own && + forw_packet->if_incoming != primary_if))) { + res = true; + goto out; + } + } + +out: + if (primary_if) + hardif_free_ref(primary_if); + return res; +} + +/* create a new aggregated packet and add this packet to it */ +static void bat_ogm_aggregate_new(const unsigned char *packet_buff, + int packet_len, unsigned long send_time, + bool direct_link, + struct hard_iface *if_incoming, + int own_packet) +{ + struct bat_priv *bat_priv = netdev_priv(if_incoming->soft_iface); + struct forw_packet *forw_packet_aggr; + unsigned char *skb_buff; + + if (!atomic_inc_not_zero(&if_incoming->refcount)) + return; + + /* own packet should always be scheduled */ + if (!own_packet) { + if (!atomic_dec_not_zero(&bat_priv->batman_queue_left)) { + bat_dbg(DBG_BATMAN, bat_priv, + "batman packet queue full\n"); + goto out; + } + } + + forw_packet_aggr = kmalloc(sizeof(*forw_packet_aggr), GFP_ATOMIC); + if (!forw_packet_aggr) { + if (!own_packet) + atomic_inc(&bat_priv->batman_queue_left); + goto out; + } + + if ((atomic_read(&bat_priv->aggregated_ogms)) && + (packet_len < MAX_AGGREGATION_BYTES)) + forw_packet_aggr->skb = dev_alloc_skb(MAX_AGGREGATION_BYTES + + sizeof(struct ethhdr)); + else + forw_packet_aggr->skb = dev_alloc_skb(packet_len + + sizeof(struct ethhdr)); + + if (!forw_packet_aggr->skb) { + if (!own_packet) + atomic_inc(&bat_priv->batman_queue_left); + kfree(forw_packet_aggr); + goto out; + } + skb_reserve(forw_packet_aggr->skb, sizeof(struct ethhdr)); + + INIT_HLIST_NODE(&forw_packet_aggr->list); + + skb_buff = skb_put(forw_packet_aggr->skb, packet_len); + forw_packet_aggr->packet_len = packet_len; + memcpy(skb_buff, packet_buff, packet_len); + + forw_packet_aggr->own = own_packet; + forw_packet_aggr->if_incoming = if_incoming; + forw_packet_aggr->num_packets = 0; + forw_packet_aggr->direct_link_flags = NO_FLAGS; + forw_packet_aggr->send_time = send_time; + + /* save packet direct link flag status */ + if (direct_link) + forw_packet_aggr->direct_link_flags |= 1; + + /* add new packet to packet list */ + spin_lock_bh(&bat_priv->forw_bat_list_lock); + hlist_add_head(&forw_packet_aggr->list, &bat_priv->forw_bat_list); + spin_unlock_bh(&bat_priv->forw_bat_list_lock); + + /* start timer for this packet */ + INIT_DELAYED_WORK(&forw_packet_aggr->delayed_work, + send_outstanding_bat_ogm_packet); + queue_delayed_work(bat_event_workqueue, + &forw_packet_aggr->delayed_work, + send_time - jiffies); + + return; +out: + hardif_free_ref(if_incoming); +} + +/* aggregate a new packet into the existing ogm packet */ +static void bat_ogm_aggregate(struct forw_packet *forw_packet_aggr, + const unsigned char *packet_buff, + int packet_len, bool direct_link) +{ + unsigned char *skb_buff; + + skb_buff = skb_put(forw_packet_aggr->skb, packet_len); + memcpy(skb_buff, packet_buff, packet_len); + forw_packet_aggr->packet_len += packet_len; + forw_packet_aggr->num_packets++; + + /* save packet direct link flag status */ + if (direct_link) + forw_packet_aggr->direct_link_flags |= + (1 << forw_packet_aggr->num_packets); +} + +static void bat_ogm_queue_add(struct bat_priv *bat_priv, + unsigned char *packet_buff, + int packet_len, struct hard_iface *if_incoming, + int own_packet, unsigned long send_time) +{ + /** + * _aggr -> pointer to the packet we want to aggregate with + * _pos -> pointer to the position in the queue + */ + struct forw_packet *forw_packet_aggr = NULL, *forw_packet_pos = NULL; + struct hlist_node *tmp_node; + struct batman_ogm_packet *batman_ogm_packet; + bool direct_link; + + batman_ogm_packet = (struct batman_ogm_packet *)packet_buff; + direct_link = batman_ogm_packet->flags & DIRECTLINK ? 1 : 0; + + /* find position for the packet in the forward queue */ + spin_lock_bh(&bat_priv->forw_bat_list_lock); + /* own packets are not to be aggregated */ + if ((atomic_read(&bat_priv->aggregated_ogms)) && (!own_packet)) { + hlist_for_each_entry(forw_packet_pos, tmp_node, + &bat_priv->forw_bat_list, list) { + if (bat_ogm_can_aggregate(batman_ogm_packet, + bat_priv, packet_len, + send_time, direct_link, + if_incoming, + forw_packet_pos)) { + forw_packet_aggr = forw_packet_pos; + break; + } + } + } + + /* nothing to aggregate with - either aggregation disabled or no + * suitable aggregation packet found */ + if (!forw_packet_aggr) { + /* the following section can run without the lock */ + spin_unlock_bh(&bat_priv->forw_bat_list_lock); + + /** + * if we could not aggregate this packet with one of the others + * we hold it back for a while, so that it might be aggregated + * later on + */ + if ((!own_packet) && + (atomic_read(&bat_priv->aggregated_ogms))) + send_time += msecs_to_jiffies(MAX_AGGREGATION_MS); + + bat_ogm_aggregate_new(packet_buff, packet_len, + send_time, direct_link, + if_incoming, own_packet); + } else { + bat_ogm_aggregate(forw_packet_aggr, packet_buff, packet_len, + direct_link); + spin_unlock_bh(&bat_priv->forw_bat_list_lock); + } +} + +static void bat_ogm_forward(struct orig_node *orig_node, + const struct ethhdr *ethhdr, + struct batman_ogm_packet *batman_ogm_packet, + int directlink, struct hard_iface *if_incoming) +{ + struct bat_priv *bat_priv = netdev_priv(if_incoming->soft_iface); + struct neigh_node *router; + uint8_t in_tq, in_ttl, tq_avg = 0; + uint8_t tt_num_changes; + + if (batman_ogm_packet->ttl <= 1) { + bat_dbg(DBG_BATMAN, bat_priv, "ttl exceeded\n"); + return; + } + + router = orig_node_get_router(orig_node); + + in_tq = batman_ogm_packet->tq; + in_ttl = batman_ogm_packet->ttl; + tt_num_changes = batman_ogm_packet->tt_num_changes; + + batman_ogm_packet->ttl--; + memcpy(batman_ogm_packet->prev_sender, ethhdr->h_source, ETH_ALEN); + + /* rebroadcast tq of our best ranking neighbor to ensure the rebroadcast + * of our best tq value */ + if (router && router->tq_avg != 0) { + + /* rebroadcast ogm of best ranking neighbor as is */ + if (!compare_eth(router->addr, ethhdr->h_source)) { + batman_ogm_packet->tq = router->tq_avg; + + if (router->last_ttl) + batman_ogm_packet->ttl = router->last_ttl - 1; + } + + tq_avg = router->tq_avg; + } + + if (router) + neigh_node_free_ref(router); + + /* apply hop penalty */ + batman_ogm_packet->tq = hop_penalty(batman_ogm_packet->tq, bat_priv); + + bat_dbg(DBG_BATMAN, bat_priv, + "Forwarding packet: tq_orig: %i, tq_avg: %i, " + "tq_forw: %i, ttl_orig: %i, ttl_forw: %i\n", + in_tq, tq_avg, batman_ogm_packet->tq, in_ttl - 1, + batman_ogm_packet->ttl); + + batman_ogm_packet->seqno = htonl(batman_ogm_packet->seqno); + batman_ogm_packet->tt_crc = htons(batman_ogm_packet->tt_crc); + + /* switch of primaries first hop flag when forwarding */ + batman_ogm_packet->flags &= ~PRIMARIES_FIRST_HOP; + if (directlink) + batman_ogm_packet->flags |= DIRECTLINK; + else + batman_ogm_packet->flags &= ~DIRECTLINK; + + bat_ogm_queue_add(bat_priv, (unsigned char *)batman_ogm_packet, + BATMAN_OGM_LEN + tt_len(tt_num_changes), + if_incoming, 0, bat_ogm_fwd_send_time()); +} + +void bat_ogm_schedule(struct hard_iface *hard_iface, int tt_num_changes) +{ + struct bat_priv *bat_priv = netdev_priv(hard_iface->soft_iface); + struct batman_ogm_packet *batman_ogm_packet; + struct hard_iface *primary_if; + int vis_server; + + vis_server = atomic_read(&bat_priv->vis_mode); + primary_if = primary_if_get_selected(bat_priv); + + batman_ogm_packet = (struct batman_ogm_packet *)hard_iface->packet_buff; + + /* change sequence number to network order */ + batman_ogm_packet->seqno = + htonl((uint32_t)atomic_read(&hard_iface->seqno)); + + batman_ogm_packet->ttvn = atomic_read(&bat_priv->ttvn); + batman_ogm_packet->tt_crc = htons((uint16_t) + atomic_read(&bat_priv->tt_crc)); + if (tt_num_changes >= 0) + batman_ogm_packet->tt_num_changes = tt_num_changes; + + if (vis_server == VIS_TYPE_SERVER_SYNC) + batman_ogm_packet->flags |= VIS_SERVER; + else + batman_ogm_packet->flags &= ~VIS_SERVER; + + if ((hard_iface == primary_if) && + (atomic_read(&bat_priv->gw_mode) == GW_MODE_SERVER)) + batman_ogm_packet->gw_flags = + (uint8_t)atomic_read(&bat_priv->gw_bandwidth); + else + batman_ogm_packet->gw_flags = NO_FLAGS; + + atomic_inc(&hard_iface->seqno); + + slide_own_bcast_window(hard_iface); + bat_ogm_queue_add(bat_priv, hard_iface->packet_buff, + hard_iface->packet_len, hard_iface, 1, + bat_ogm_emit_send_time(bat_priv)); + + if (primary_if) + hardif_free_ref(primary_if); +} + static void bat_ogm_orig_update(struct bat_priv *bat_priv, struct orig_node *orig_node, const struct ethhdr *ethhdr, @@ -605,8 +1100,8 @@ static void bat_ogm_process(const struct ethhdr *ethhdr, if (is_single_hop_neigh) {
/* mark direct link on incoming interface */ - schedule_forward_packet(orig_node, ethhdr, batman_ogm_packet, - 1, if_incoming); + bat_ogm_forward(orig_node, ethhdr, batman_ogm_packet, + 1, if_incoming);
bat_dbg(DBG_BATMAN, bat_priv, "Forwarding packet: " "rebroadcast neighbor packet with direct link flag\n"); @@ -628,8 +1123,7 @@ static void bat_ogm_process(const struct ethhdr *ethhdr,
bat_dbg(DBG_BATMAN, bat_priv, "Forwarding packet: rebroadcast originator packet\n"); - schedule_forward_packet(orig_node, ethhdr, batman_ogm_packet, - 0, if_incoming); + bat_ogm_forward(orig_node, ethhdr, batman_ogm_packet, 0, if_incoming);
out_neigh: if ((orig_neigh_node) && (!is_single_hop_neigh)) diff --git a/bat_ogm.h b/bat_ogm.h index 7809b92..69329c1 100644 --- a/bat_ogm.h +++ b/bat_ogm.h @@ -27,6 +27,8 @@ void bat_ogm_init(struct hard_iface *hard_iface); void bat_ogm_init_primary(struct hard_iface *hard_iface); void bat_ogm_update_mac(struct hard_iface *hard_iface); +void bat_ogm_schedule(struct hard_iface *hard_iface, int tt_num_changes); +void bat_ogm_emit(struct forw_packet *forw_packet); void bat_ogm_receive(const struct ethhdr *ethhdr, unsigned char *packet_buff, int packet_len, struct hard_iface *if_incoming);
diff --git a/hard-interface.c b/hard-interface.c index 2a15582..0cc0f04 100644 --- a/hard-interface.c +++ b/hard-interface.c @@ -360,7 +360,7 @@ int hardif_enable_interface(struct hard_iface *hard_iface, hard_iface->net_dev->name);
/* begin scheduling originator messages on that interface */ - schedule_own_packet(hard_iface); + schedule_bat_ogm(hard_iface);
out: return 0; diff --git a/send.c b/send.c index 40a5fcd..8a684eb 100644 --- a/send.c +++ b/send.c @@ -26,33 +26,12 @@ #include "soft-interface.h" #include "hard-interface.h" #include "vis.h" -#include "aggregation.h" #include "gateway_common.h" #include "originator.h" +#include "bat_ogm.h"
static void send_outstanding_bcast_packet(struct work_struct *work);
-/* apply hop penalty for a normal link */ -static uint8_t hop_penalty(uint8_t tq, const struct bat_priv *bat_priv) -{ - int hop_penalty = atomic_read(&bat_priv->hop_penalty); - return (tq * (TQ_MAX_VALUE - hop_penalty)) / (TQ_MAX_VALUE); -} - -/* when do we schedule our own packet to be sent */ -static unsigned long own_send_time(const struct bat_priv *bat_priv) -{ - return jiffies + msecs_to_jiffies( - atomic_read(&bat_priv->orig_interval) - - JITTER + (random32() % 2*JITTER)); -} - -/* when do we schedule a forwarded packet to be sent */ -static unsigned long forward_send_time(void) -{ - return jiffies + msecs_to_jiffies(random32() % (JITTER/2)); -} - /* send out an already prepared packet to the given address via the * specified batman interface */ int send_skb_packet(struct sk_buff *skb, struct hard_iface *hard_iface, @@ -99,133 +78,6 @@ send_skb_err: return NET_XMIT_DROP; }
-/* Send a packet to a given interface */ -static void send_packet_to_if(struct forw_packet *forw_packet, - struct hard_iface *hard_iface) -{ - struct bat_priv *bat_priv = netdev_priv(hard_iface->soft_iface); - char *fwd_str; - uint8_t packet_num; - int16_t buff_pos; - struct batman_ogm_packet *batman_ogm_packet; - struct sk_buff *skb; - - if (hard_iface->if_status != IF_ACTIVE) - return; - - packet_num = 0; - buff_pos = 0; - batman_ogm_packet = (struct batman_ogm_packet *)forw_packet->skb->data; - - /* adjust all flags and log packets */ - while (aggregated_packet(buff_pos, - forw_packet->packet_len, - batman_ogm_packet->tt_num_changes)) { - - /* we might have aggregated direct link packets with an - * ordinary base packet */ - if ((forw_packet->direct_link_flags & (1 << packet_num)) && - (forw_packet->if_incoming == hard_iface)) - batman_ogm_packet->flags |= DIRECTLINK; - else - batman_ogm_packet->flags &= ~DIRECTLINK; - - fwd_str = (packet_num > 0 ? "Forwarding" : (forw_packet->own ? - "Sending own" : - "Forwarding")); - bat_dbg(DBG_BATMAN, bat_priv, - "%s %spacket (originator %pM, seqno %d, TQ %d, TTL %d," - " IDF %s, ttvn %d) on interface %s [%pM]\n", - fwd_str, (packet_num > 0 ? "aggregated " : ""), - batman_ogm_packet->orig, - ntohl(batman_ogm_packet->seqno), - batman_ogm_packet->tq, batman_ogm_packet->ttl, - (batman_ogm_packet->flags & DIRECTLINK ? - "on" : "off"), - batman_ogm_packet->ttvn, hard_iface->net_dev->name, - hard_iface->net_dev->dev_addr); - - buff_pos += BATMAN_OGM_LEN + - tt_len(batman_ogm_packet->tt_num_changes); - packet_num++; - batman_ogm_packet = (struct batman_ogm_packet *) - (forw_packet->skb->data + buff_pos); - } - - /* create clone because function is called more than once */ - skb = skb_clone(forw_packet->skb, GFP_ATOMIC); - if (skb) - send_skb_packet(skb, hard_iface, broadcast_addr); -} - -/* send a batman packet */ -static void send_packet(struct forw_packet *forw_packet) -{ - struct hard_iface *hard_iface; - struct net_device *soft_iface; - struct bat_priv *bat_priv; - struct hard_iface *primary_if = NULL; - struct batman_ogm_packet *batman_ogm_packet = - (struct batman_ogm_packet *)(forw_packet->skb->data); - unsigned char directlink; - - directlink = (batman_ogm_packet->flags & DIRECTLINK ? 1 : 0); - - if (!forw_packet->if_incoming) { - pr_err("Error - can't forward packet: incoming iface not " - "specified\n"); - goto out; - } - - soft_iface = forw_packet->if_incoming->soft_iface; - bat_priv = netdev_priv(soft_iface); - - if (forw_packet->if_incoming->if_status != IF_ACTIVE) - goto out; - - primary_if = primary_if_get_selected(bat_priv); - if (!primary_if) - goto out; - - /* multihomed peer assumed */ - /* non-primary OGMs are only broadcasted on their interface */ - if ((directlink && (batman_ogm_packet->ttl == 1)) || - (forw_packet->own && (forw_packet->if_incoming != primary_if))) { - - /* FIXME: what about aggregated packets ? */ - bat_dbg(DBG_BATMAN, bat_priv, - "%s packet (originator %pM, seqno %d, TTL %d) " - "on interface %s [%pM]\n", - (forw_packet->own ? "Sending own" : "Forwarding"), - batman_ogm_packet->orig, - ntohl(batman_ogm_packet->seqno), - batman_ogm_packet->ttl, - forw_packet->if_incoming->net_dev->name, - forw_packet->if_incoming->net_dev->dev_addr); - - /* skb is only used once and than forw_packet is free'd */ - send_skb_packet(forw_packet->skb, forw_packet->if_incoming, - broadcast_addr); - forw_packet->skb = NULL; - - goto out; - } - - /* broadcast on every interface */ - rcu_read_lock(); - list_for_each_entry_rcu(hard_iface, &hardif_list, list) { - if (hard_iface->soft_iface != soft_iface) - continue; - - send_packet_to_if(forw_packet, hard_iface); - } - rcu_read_unlock(); - -out: - if (primary_if) - hardif_free_ref(primary_if); -} - static void realloc_packet_buffer(struct hard_iface *hard_iface, int new_len) { @@ -245,11 +97,10 @@ static void realloc_packet_buffer(struct hard_iface *hard_iface, }
/* when calling this function (hard_iface == primary_if) has to be true */ -static void prepare_packet_buffer(struct bat_priv *bat_priv, +static int prepare_packet_buffer(struct bat_priv *bat_priv, struct hard_iface *hard_iface) { int new_len; - struct batman_ogm_packet *batman_ogm_packet;
new_len = BATMAN_OGM_LEN + tt_len((uint8_t)atomic_read(&bat_priv->tt_local_changes)); @@ -260,45 +111,34 @@ static void prepare_packet_buffer(struct bat_priv *bat_priv, new_len = BATMAN_OGM_LEN;
realloc_packet_buffer(hard_iface, new_len); - batman_ogm_packet = (struct batman_ogm_packet *)hard_iface->packet_buff;
atomic_set(&bat_priv->tt_crc, tt_local_crc(bat_priv));
/* reset the sending counter */ atomic_set(&bat_priv->tt_ogm_append_cnt, TT_OGM_APPEND_MAX);
- batman_ogm_packet->tt_num_changes = tt_changes_fill_buffer(bat_priv, - hard_iface->packet_buff + BATMAN_OGM_LEN, - hard_iface->packet_len - BATMAN_OGM_LEN); - + return tt_changes_fill_buffer(bat_priv, + hard_iface->packet_buff + BATMAN_OGM_LEN, + hard_iface->packet_len - BATMAN_OGM_LEN); }
-static void reset_packet_buffer(struct bat_priv *bat_priv, +static int reset_packet_buffer(struct bat_priv *bat_priv, struct hard_iface *hard_iface) { - struct batman_ogm_packet *batman_ogm_packet; - realloc_packet_buffer(hard_iface, BATMAN_OGM_LEN); - - batman_ogm_packet = (struct batman_ogm_packet *)hard_iface->packet_buff; - batman_ogm_packet->tt_num_changes = 0; + return 0; }
-void schedule_own_packet(struct hard_iface *hard_iface) +void schedule_bat_ogm(struct hard_iface *hard_iface) { struct bat_priv *bat_priv = netdev_priv(hard_iface->soft_iface); struct hard_iface *primary_if; - unsigned long send_time; - struct batman_ogm_packet *batman_ogm_packet; - int vis_server; + int tt_num_changes = -1;
if ((hard_iface->if_status == IF_NOT_IN_USE) || (hard_iface->if_status == IF_TO_BE_REMOVED)) return;
- vis_server = atomic_read(&bat_priv->vis_mode); - primary_if = primary_if_get_selected(bat_priv); - /** * the interface gets activated here to avoid race conditions between * the moment of activating the interface in @@ -309,125 +149,26 @@ void schedule_own_packet(struct hard_iface *hard_iface) if (hard_iface->if_status == IF_TO_BE_ACTIVATED) hard_iface->if_status = IF_ACTIVE;
+ primary_if = primary_if_get_selected(bat_priv); + if (hard_iface == primary_if) { /* if at least one change happened */ if (atomic_read(&bat_priv->tt_local_changes) > 0) { tt_commit_changes(bat_priv); - prepare_packet_buffer(bat_priv, hard_iface); + tt_num_changes = prepare_packet_buffer(bat_priv, + hard_iface); }
/* if the changes have been sent often enough */ if (!atomic_dec_not_zero(&bat_priv->tt_ogm_append_cnt)) - reset_packet_buffer(bat_priv, hard_iface); + tt_num_changes = reset_packet_buffer(bat_priv, + hard_iface); }
- /** - * NOTE: packet_buff might just have been re-allocated in - * prepare_packet_buffer() or in reset_packet_buffer() - */ - batman_ogm_packet = (struct batman_ogm_packet *)hard_iface->packet_buff; - - /* change sequence number to network order */ - batman_ogm_packet->seqno = - htonl((uint32_t)atomic_read(&hard_iface->seqno)); - - batman_ogm_packet->ttvn = atomic_read(&bat_priv->ttvn); - batman_ogm_packet->tt_crc = htons((uint16_t) - atomic_read(&bat_priv->tt_crc)); - - if (vis_server == VIS_TYPE_SERVER_SYNC) - batman_ogm_packet->flags |= VIS_SERVER; - else - batman_ogm_packet->flags &= ~VIS_SERVER; - - if ((hard_iface == primary_if) && - (atomic_read(&bat_priv->gw_mode) == GW_MODE_SERVER)) - batman_ogm_packet->gw_flags = - (uint8_t)atomic_read(&bat_priv->gw_bandwidth); - else - batman_ogm_packet->gw_flags = NO_FLAGS; - - atomic_inc(&hard_iface->seqno); - - slide_own_bcast_window(hard_iface); - send_time = own_send_time(bat_priv); - add_bat_packet_to_list(bat_priv, - hard_iface->packet_buff, - hard_iface->packet_len, - hard_iface, 1, send_time); - if (primary_if) hardif_free_ref(primary_if); -}
-void schedule_forward_packet(struct orig_node *orig_node, - const struct ethhdr *ethhdr, - struct batman_ogm_packet *batman_ogm_packet, - int directlink, - struct hard_iface *if_incoming) -{ - struct bat_priv *bat_priv = netdev_priv(if_incoming->soft_iface); - struct neigh_node *router; - uint8_t in_tq, in_ttl, tq_avg = 0; - unsigned long send_time; - uint8_t tt_num_changes; - - if (batman_ogm_packet->ttl <= 1) { - bat_dbg(DBG_BATMAN, bat_priv, "ttl exceeded\n"); - return; - } - - router = orig_node_get_router(orig_node); - - in_tq = batman_ogm_packet->tq; - in_ttl = batman_ogm_packet->ttl; - tt_num_changes = batman_ogm_packet->tt_num_changes; - - batman_ogm_packet->ttl--; - memcpy(batman_ogm_packet->prev_sender, ethhdr->h_source, ETH_ALEN); - - /* rebroadcast tq of our best ranking neighbor to ensure the rebroadcast - * of our best tq value */ - if (router && router->tq_avg != 0) { - - /* rebroadcast ogm of best ranking neighbor as is */ - if (!compare_eth(router->addr, ethhdr->h_source)) { - batman_ogm_packet->tq = router->tq_avg; - - if (router->last_ttl) - batman_ogm_packet->ttl = router->last_ttl - 1; - } - - tq_avg = router->tq_avg; - } - - if (router) - neigh_node_free_ref(router); - - /* apply hop penalty */ - batman_ogm_packet->tq = hop_penalty(batman_ogm_packet->tq, bat_priv); - - bat_dbg(DBG_BATMAN, bat_priv, - "Forwarding packet: tq_orig: %i, tq_avg: %i, " - "tq_forw: %i, ttl_orig: %i, ttl_forw: %i\n", - in_tq, tq_avg, batman_ogm_packet->tq, in_ttl - 1, - batman_ogm_packet->ttl); - - batman_ogm_packet->seqno = htonl(batman_ogm_packet->seqno); - batman_ogm_packet->tt_crc = htons(batman_ogm_packet->tt_crc); - - /* switch of primaries first hop flag when forwarding */ - batman_ogm_packet->flags &= ~PRIMARIES_FIRST_HOP; - if (directlink) - batman_ogm_packet->flags |= DIRECTLINK; - else - batman_ogm_packet->flags &= ~DIRECTLINK; - - send_time = forward_send_time(); - add_bat_packet_to_list(bat_priv, - (unsigned char *)batman_ogm_packet, - BATMAN_OGM_LEN + tt_len(tt_num_changes), - if_incoming, 0, send_time); + bat_ogm_schedule(hard_iface, tt_num_changes); }
static void forw_packet_free(struct forw_packet *forw_packet) @@ -561,7 +302,7 @@ out: atomic_inc(&bat_priv->bcast_queue_left); }
-void send_outstanding_bat_packet(struct work_struct *work) +void send_outstanding_bat_ogm_packet(struct work_struct *work) { struct delayed_work *delayed_work = container_of(work, struct delayed_work, work); @@ -577,7 +318,7 @@ void send_outstanding_bat_packet(struct work_struct *work) if (atomic_read(&bat_priv->mesh_state) == MESH_DEACTIVATING) goto out;
- send_packet(forw_packet); + bat_ogm_emit(forw_packet);
/** * we have to have at least one packet in the queue @@ -585,7 +326,7 @@ void send_outstanding_bat_packet(struct work_struct *work) * shutting down */ if (forw_packet->own) - schedule_own_packet(forw_packet->if_incoming); + schedule_bat_ogm(forw_packet->if_incoming);
out: /* don't count own packet */ diff --git a/send.h b/send.h index 8a22d84..c8ca3ef 100644 --- a/send.h +++ b/send.h @@ -24,15 +24,10 @@
int send_skb_packet(struct sk_buff *skb, struct hard_iface *hard_iface, const uint8_t *dst_addr); -void schedule_own_packet(struct hard_iface *hard_iface); -void schedule_forward_packet(struct orig_node *orig_node, - const struct ethhdr *ethhdr, - struct batman_ogm_packet *batman_ogm_packet, - int directlink, - struct hard_iface *if_outgoing); +void schedule_bat_ogm(struct hard_iface *hard_iface); int add_bcast_packet_to_list(struct bat_priv *bat_priv, const struct sk_buff *skb, unsigned long delay); -void send_outstanding_bat_packet(struct work_struct *work); +void send_outstanding_bat_ogm_packet(struct work_struct *work); void purge_outstanding_packets(struct bat_priv *bat_priv, const struct hard_iface *hard_iface);
On Wednesday, August 03, 2011 09:53:02 Marek Lindner wrote:
In the process the batman iv OGM aggregation code could be merged into the batman iv code base which makes the separate aggregation files superfluous.
Applied in revision e60d5c1.
Regards, Marek
On Wednesday, August 03, 2011 09:52:59 Marek Lindner wrote:
The follow-up routing code changes are going to introduce additional routing packet types which make this distinction necessary.
Applied in revision da9133d.
Regards, Marek
As a first step into that direction I worked on a set of patches to assemble all B.A.T.M.A.N. IV related routing code in a single file, accessible via a routing algo API which will also be used by the new code.
Hi Marek
Looking at the header files, it is not clear to me which contains this routing algo API. Is it bat_ogm.h?
Has there been any discussion if compile time is sufficient? How about making it a runtime decision? I presume mixing routing algorithms within a mesh is not going to work. However, being able to configure the algorithm per mesh should be possible. This gives a greater degree of interoperability, which might make the Linux Network maintainers happier?
Andrew
Hi,
Looking at the header files, it is not clear to me which contains this routing algo API. Is it bat_ogm.h?
yes, it is.
Has there been any discussion if compile time is sufficient? How about making it a runtime decision? I presume mixing routing algorithms within a mesh is not going to work. However, being able to configure the algorithm per mesh should be possible. This gives a greater degree of interoperability, which might make the Linux Network maintainers happier?
we discussed various options but at the end decided to move forward with the compile time option. Personally, I doubt many people will want the new routing algorithm until it has been stabilized (we will provide a 'default' option that enables B.A.T.M.A.N. IV).
Nevertheless, I am not against having the run time option if someone wants to do it. Are you going to provide the necessary patches ?
Where is the interoperability coming from ? The protocols won't be compatible. However, we are planing on integrating an extensible header format which allows to add features that will be backward compatible.
Cheers, Marek
On Wed, Aug 03, 2011 at 04:39:53PM +0200, Marek Lindner wrote:
Hi,
Looking at the header files, it is not clear to me which contains this routing algo API. Is it bat_ogm.h?
yes, it is.
Has there been any discussion if compile time is sufficient? How about making it a runtime decision? I presume mixing routing algorithms within a mesh is not going to work. However, being able to configure the algorithm per mesh should be possible. This gives a greater degree of interoperability, which might make the Linux Network maintainers happier?
we discussed various options but at the end decided to move forward with the compile time option. Personally, I doubt many people will want the new routing algorithm until it has been stabilized (we will provide a 'default' option that enables B.A.T.M.A.N. IV).
So it is maybe not needed now, but once the code does start reaching stability, run time selection becomes more interesting.
Nevertheless, I am not against having the run time option if someone wants to do it. Are you going to provide the necessary patches ?
Probably not, at least not now.
Where is the interoperability coming from ? The protocols won't be compatible.
Interoperability has many meanings. I've seen it mean the protocol does not actively destroy the operation of another protocol. I've seen this in powerline networks. Company X proprietary powerline protocol is interoperable with HomePlug in that it will not destroy the HomePlug network if run in parallel with it. It won't talk to it either...
By making it a runtime option, i don't need to recompile my kernel to swap from one to the other. I just need "batctl algo V" or "batctl algo IV". My kernel is interoperable, i just need to configure the mesh correctly for it to work.
What might also be interesting is batctl algo IV bat0 batctl algo V bat1 brctl addif br0 bat0 brctl addif br0 bat1
It won't give optimal routes, but it at least gets the two meshs talking to each other.
However, we are planing on integrating an extensible header format which allows to add features that will be backward compatible.
Ah, good. Is there any documentation about this?
Thanks Andrew
On Wednesday, August 03, 2011 18:50:18 Andrew Lunn wrote:
we discussed various options but at the end decided to move forward with the compile time option. Personally, I doubt many people will want the new routing algorithm until it has been stabilized (we will provide a 'default' option that enables B.A.T.M.A.N. IV).
So it is maybe not needed now, but once the code does start reaching stability, run time selection becomes more interesting.
Agreed.
Interoperability has many meanings. I've seen it mean the protocol does not actively destroy the operation of another protocol. I've seen this in powerline networks. Company X proprietary powerline protocol is interoperable with HomePlug in that it will not destroy the HomePlug network if run in parallel with it. It won't talk to it either...
There is no difference between compile time and run time option - both won't destroy the other.
By making it a runtime option, i don't need to recompile my kernel to swap from one to the other. I just need "batctl algo V" or "batctl algo IV". My kernel is interoperable, i just need to configure the mesh correctly for it to work.
What might also be interesting is batctl algo IV bat0 batctl algo V bat1 brctl addif br0 bat0 brctl addif br0 bat1
It won't give optimal routes, but it at least gets the two meshs talking to each other.
True. That is an interesting point you are making here.
However, we are planing on integrating an extensible header format which allows to add features that will be backward compatible.
Ah, good. Is there any documentation about this?
I'll post a follow-up once it is available.
Regards, Marek
Hey,
On Wed, Aug 03, 2011 at 06:50:18PM +0200, Andrew Lunn wrote:
On Wed, Aug 03, 2011 at 04:39:53PM +0200, Marek Lindner wrote:
Where is the interoperability coming from ? The protocols won't be compatible.
Interoperability has many meanings. I've seen it mean the protocol does not actively destroy the operation of another protocol. I've seen this in powerline networks. Company X proprietary powerline protocol is interoperable with HomePlug in that it will not destroy the HomePlug network if run in parallel with it. It won't talk to it either...
By making it a runtime option, i don't need to recompile my kernel to swap from one to the other. I just need "batctl algo V" or "batctl algo IV". My kernel is interoperable, i just need to configure the mesh correctly for it to work.
What might also be interesting is batctl algo IV bat0 batctl algo V bat1 brctl addif br0 bat0 brctl addif br0 bat1
It won't give optimal routes, but it at least gets the two meshs talking to each other.
mhm, I'm not sure if we need to let two different meshes talking (right now), but a nice compromise might be to enable selecting the algorithm at module load time as parameter - I would find it inconvenient to re-compile the module all the time. :)
This is hopefully not too hard, we could go with a struct of function pointers as many other subsystems do. This could also be enhanced later to enable "real" runtime selection, but there might be some challenges there, e.g. changing the sysfs (for algorithm-dependent parameters) and other dependencies.
What do you think?
best regards, Simon
b.a.t.m.a.n@lists.open-mesh.org