Hi everyone,
another small, but important update on the NDP patches: * linearize NDP packet's skb before looking at its neighbor entries * Avoid disabling bottom halves twice when receiving/processing OGMs
Cheers, Linus
This patch creates the new neighbor discovery packet type (which is not actually being used with this patch). It will later be responsible to detect neighbors and calculate the link quality to them.
Signed-off-by: Linus Lüssing linus.luessing@ascom.ch --- aggregation.c | 44 +++++++++++----------- aggregation.h | 2 +- hard-interface.c | 43 +++++++++++---------- packet.h | 28 ++++++++++---- routing.c | 101 ++++++++++++++++++++++++------------------------ routing.h | 2 +- send.c | 106 ++++++++++++++++++++++++++------------------------- send.h | 2 +- soft-interface.c | 18 +++++---- translation-table.c | 2 +- 10 files changed, 183 insertions(+), 165 deletions(-)
diff --git a/aggregation.c b/aggregation.c index 0c92e3b..c158df2 100644 --- a/aggregation.c +++ b/aggregation.c @@ -25,21 +25,21 @@ #include "routing.h"
/* calculate the size of the hna information for a given packet */ -static int hna_len(struct batman_packet *batman_packet) +static int hna_len(struct batman_packet_ogm *batman_packet_ogm) { - return batman_packet->num_hna * ETH_ALEN; + return batman_packet_ogm->num_hna * ETH_ALEN; }
/* return true if new_packet can be aggregated with forw_packet */ -static bool can_aggregate_with(struct batman_packet *new_batman_packet, +static bool can_aggregate_with(struct batman_packet_ogm *new_batman_packet_ogm, int packet_len, unsigned long send_time, bool directlink, struct batman_if *if_incoming, struct forw_packet *forw_packet) { - struct batman_packet *batman_packet = - (struct batman_packet *)forw_packet->skb->data; + struct batman_packet_ogm *batman_packet_ogm = + (struct batman_packet_ogm *)forw_packet->skb->data; int aggregated_bytes = forw_packet->packet_len + packet_len;
/** @@ -68,8 +68,8 @@ static bool can_aggregate_with(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_packet_ogm->flags & DIRECTLINK)) && + (batman_packet_ogm->ttl != 1) &&
/* own packets originating non-primary * interfaces leave only that interface */ @@ -80,13 +80,13 @@ static bool can_aggregate_with(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_packet_ogm->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_packet_ogm->flags & DIRECTLINK || (forw_packet->own && forw_packet->if_incoming->if_num != 0))) return true; @@ -197,9 +197,9 @@ 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_packet_ogm *batman_packet_ogm = + (struct batman_packet_ogm *)packet_buff; + bool direct_link = batman_packet_ogm->flags & DIRECTLINK ? 1 : 0;
/* find position for the packet in the forward queue */ spin_lock_bh(&bat_priv->forw_bat_list_lock); @@ -207,7 +207,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_packet_ogm, packet_len, send_time, direct_link, @@ -249,25 +249,25 @@ void add_bat_packet_to_list(struct bat_priv *bat_priv, void receive_aggr_bat_packet(struct ethhdr *ethhdr, unsigned char *packet_buff, int packet_len, struct batman_if *if_incoming) { - struct batman_packet *batman_packet; + struct batman_packet_ogm *batman_packet_ogm; int buff_pos = 0; unsigned char *hna_buff;
- batman_packet = (struct batman_packet *)packet_buff; + batman_packet_ogm = (struct batman_packet_ogm *)packet_buff;
do { /* network to host order for our 32bit seqno, and the orig_interval. */ - batman_packet->seqno = ntohl(batman_packet->seqno); + batman_packet_ogm->seqno = ntohl(batman_packet_ogm->seqno);
- hna_buff = packet_buff + buff_pos + BAT_PACKET_LEN; - receive_bat_packet(ethhdr, batman_packet, - hna_buff, hna_len(batman_packet), + hna_buff = packet_buff + buff_pos + BAT_PACKET_OGM_LEN; + receive_bat_packet(ethhdr, batman_packet_ogm, + hna_buff, hna_len(batman_packet_ogm), if_incoming);
- buff_pos += BAT_PACKET_LEN + hna_len(batman_packet); - batman_packet = (struct batman_packet *) + buff_pos += BAT_PACKET_OGM_LEN + hna_len(batman_packet_ogm); + batman_packet_ogm = (struct batman_packet_ogm *) (packet_buff + buff_pos); } while (aggregated_packet(buff_pos, packet_len, - batman_packet->num_hna)); + batman_packet_ogm->num_hna)); } diff --git a/aggregation.h b/aggregation.h index 71a91b3..1a7a0b6 100644 --- a/aggregation.h +++ b/aggregation.h @@ -27,7 +27,7 @@ /* is there another aggregated packet here? */ static inline int aggregated_packet(int buff_pos, int packet_len, int num_hna) { - int next_buff_pos = buff_pos + BAT_PACKET_LEN + (num_hna * ETH_ALEN); + int next_buff_pos = buff_pos + BAT_PACKET_OGM_LEN + (num_hna * ETH_ALEN);
return (next_buff_pos <= packet_len) && (next_buff_pos <= MAX_AGGREGATION_BYTES); diff --git a/hard-interface.c b/hard-interface.c index 4f95777..784c475 100644 --- a/hard-interface.c +++ b/hard-interface.c @@ -128,7 +128,7 @@ static void update_primary_addr(struct bat_priv *bat_priv) static void set_primary_if(struct bat_priv *bat_priv, struct batman_if *batman_if) { - struct batman_packet *batman_packet; + struct batman_packet_ogm *batman_packet_ogm; struct batman_if *old_if;
if (batman_if) @@ -143,9 +143,9 @@ static void set_primary_if(struct bat_priv *bat_priv, if (!bat_priv->primary_if) return;
- batman_packet = (struct batman_packet *)(batman_if->packet_buff); - batman_packet->flags = PRIMARIES_FIRST_HOP; - batman_packet->ttl = TTL; + batman_packet_ogm = (struct batman_packet_ogm *)batman_if->packet_buff; + batman_packet_ogm->flags = PRIMARIES_FIRST_HOP; + batman_packet_ogm->ttl = TTL;
update_primary_addr(bat_priv);
@@ -166,9 +166,10 @@ static bool hardif_is_iface_up(struct batman_if *batman_if)
static void update_mac_addresses(struct batman_if *batman_if) { - memcpy(((struct batman_packet *)(batman_if->packet_buff))->orig, + memcpy(((struct batman_packet_ogm *)(batman_if->packet_buff))->orig, batman_if->net_dev->dev_addr, ETH_ALEN); - memcpy(((struct batman_packet *)(batman_if->packet_buff))->prev_sender, + memcpy(((struct batman_packet_ogm *) + (batman_if->packet_buff))->prev_sender, batman_if->net_dev->dev_addr, ETH_ALEN); }
@@ -279,7 +280,7 @@ static void hardif_deactivate_interface(struct batman_if *batman_if) int hardif_enable_interface(struct batman_if *batman_if, char *iface_name) { struct bat_priv *bat_priv; - struct batman_packet *batman_packet; + struct batman_packet_ogm *batman_packet_ogm;
if (batman_if->if_status != IF_NOT_IN_USE) goto out; @@ -297,7 +298,7 @@ int hardif_enable_interface(struct batman_if *batman_if, char *iface_name) }
bat_priv = netdev_priv(batman_if->soft_iface); - batman_if->packet_len = BAT_PACKET_LEN; + batman_if->packet_len = BAT_PACKET_OGM_LEN; batman_if->packet_buff = kmalloc(batman_if->packet_len, GFP_ATOMIC);
if (!batman_if->packet_buff) { @@ -306,13 +307,13 @@ int hardif_enable_interface(struct batman_if *batman_if, char *iface_name) goto err; }
- batman_packet = (struct batman_packet *)(batman_if->packet_buff); - batman_packet->packet_type = BAT_PACKET; - batman_packet->version = COMPAT_VERSION; - batman_packet->flags = 0; - batman_packet->ttl = 2; - batman_packet->tq = TQ_MAX_VALUE; - batman_packet->num_hna = 0; + batman_packet_ogm = (struct batman_packet_ogm *)(batman_if->packet_buff); + batman_packet_ogm->packet_type = BAT_PACKET_OGM; + batman_packet_ogm->version = COMPAT_VERSION; + batman_packet_ogm->flags = 0; + batman_packet_ogm->ttl = 2; + batman_packet_ogm->tq = TQ_MAX_VALUE; + batman_packet_ogm->num_hna = 0;
batman_if->if_num = bat_priv->num_ifaces; bat_priv->num_ifaces++; @@ -553,7 +554,7 @@ int batman_skb_recv(struct sk_buff *skb, struct net_device *dev, struct packet_type *ptype, struct net_device *orig_dev) { struct bat_priv *bat_priv; - struct batman_packet *batman_packet; + struct batman_packet_ogm *batman_packet_ogm; struct batman_if *batman_if; int ret;
@@ -585,21 +586,21 @@ int batman_skb_recv(struct sk_buff *skb, struct net_device *dev, if (batman_if->if_status != IF_ACTIVE) goto err_free;
- batman_packet = (struct batman_packet *)skb->data; + batman_packet_ogm = (struct batman_packet_ogm *)skb->data;
- if (batman_packet->version != COMPAT_VERSION) { + if (batman_packet_ogm->version != COMPAT_VERSION) { bat_dbg(DBG_BATMAN, bat_priv, "Drop packet: incompatible batman version (%i)\n", - batman_packet->version); + batman_packet_ogm->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_packet_ogm->packet_type) { /* batman originator packet */ - case BAT_PACKET: + case BAT_PACKET_OGM: ret = recv_bat_packet(skb, batman_if); break;
diff --git a/packet.h b/packet.h index b49fdf7..beb1b56 100644 --- a/packet.h +++ b/packet.h @@ -24,12 +24,13 @@
#define ETH_P_BATMAN 0x4305 /* unofficial/not registered Ethertype */
-#define BAT_PACKET 0x01 -#define BAT_ICMP 0x02 -#define BAT_UNICAST 0x03 -#define BAT_BCAST 0x04 -#define BAT_VIS 0x05 -#define BAT_UNICAST_FRAG 0x06 +#define BAT_PACKET_NDP 0x01 +#define BAT_PACKET_OGM 0x02 +#define BAT_ICMP 0x03 +#define BAT_UNICAST 0x04 +#define BAT_BCAST 0x05 +#define BAT_VIS 0x06 +#define BAT_UNICAST_FRAG 0x07
/* this file is included by batctl which needs these defines */ #define COMPAT_VERSION 12 @@ -51,7 +52,18 @@ /* fragmentation defines */ #define UNI_FRAG_HEAD 0x01
-struct batman_packet { +/* Neighbor discovery packet */ +struct batman_packet_ndp { + uint8_t packet_type; + uint8_t version; /* batman version field */ + uint8_t orig[6]; + uint32_t seqno; + uint8_t num_neighbors; + uint8_t align[3]; +} __attribute__((packed)); + +/* Originator message packet */ +struct batman_packet_ogm { uint8_t packet_type; uint8_t version; /* batman version field */ uint8_t flags; /* 0x40: DIRECTLINK flag, 0x20 VIS_SERVER flag... */ @@ -65,7 +77,7 @@ struct batman_packet { uint8_t align; } __attribute__((packed));
-#define BAT_PACKET_LEN sizeof(struct batman_packet) +#define BAT_PACKET_OGM_LEN sizeof(struct batman_packet_ogm)
struct icmp_packet { uint8_t packet_type; diff --git a/routing.c b/routing.c index d8b0c5a..a9406ba 100644 --- a/routing.c +++ b/routing.c @@ -130,7 +130,7 @@ void update_routes(struct bat_priv *bat_priv, struct orig_node *orig_node,
static int is_bidirectional_neigh(struct orig_node *orig_node, struct orig_node *orig_neigh_node, - struct batman_packet *batman_packet, + struct batman_packet_ogm *batman_packet_ogm, struct batman_if *if_incoming) { struct bat_priv *bat_priv = netdev_priv(if_incoming->soft_iface); @@ -215,7 +215,7 @@ static int is_bidirectional_neigh(struct orig_node *orig_node, TQ_LOCAL_WINDOW_SIZE * TQ_LOCAL_WINDOW_SIZE);
- batman_packet->tq = ((batman_packet->tq * + batman_packet_ogm->tq = ((batman_packet_ogm->tq * orig_neigh_node->tq_own * orig_neigh_node->tq_asym_penalty) / (TQ_MAX_VALUE * TQ_MAX_VALUE)); @@ -227,11 +227,11 @@ static int is_bidirectional_neigh(struct orig_node *orig_node, "total tq: %3i\n", orig_node->orig, orig_neigh_node->orig, total_count, neigh_node->real_packet_count, orig_neigh_node->tq_own, - orig_neigh_node->tq_asym_penalty, batman_packet->tq); + orig_neigh_node->tq_asym_penalty, batman_packet_ogm->tq);
/* if link has the minimum required transmission quality * consider it bidirectional */ - if (batman_packet->tq >= TQ_TOTAL_BIDRECT_LIMIT) + if (batman_packet_ogm->tq >= TQ_TOTAL_BIDRECT_LIMIT) return 1;
return 0; @@ -240,7 +240,7 @@ static int is_bidirectional_neigh(struct orig_node *orig_node, static void update_orig(struct bat_priv *bat_priv, struct orig_node *orig_node, struct ethhdr *ethhdr, - struct batman_packet *batman_packet, + struct batman_packet_ogm *batman_packet_ogm, struct batman_if *if_incoming, unsigned char *hna_buff, int hna_buff_len, char is_duplicate) @@ -282,21 +282,21 @@ static void update_orig(struct bat_priv *bat_priv, bat_dbg(DBG_BATMAN, bat_priv, "Updating existing last-hop neighbor of originator\n");
- orig_node->flags = batman_packet->flags; + orig_node->flags = batman_packet_ogm->flags; neigh_node->last_valid = jiffies;
ring_buffer_set(neigh_node->tq_recv, &neigh_node->tq_index, - batman_packet->tq); + batman_packet_ogm->tq); neigh_node->tq_avg = ring_buffer_avg(neigh_node->tq_recv);
if (!is_duplicate) { - orig_node->last_ttl = batman_packet->ttl; - neigh_node->last_ttl = batman_packet->ttl; + orig_node->last_ttl = batman_packet_ogm->ttl; + neigh_node->last_ttl = batman_packet_ogm->ttl; }
- tmp_hna_buff_len = (hna_buff_len > batman_packet->num_hna * ETH_ALEN ? - batman_packet->num_hna * ETH_ALEN : hna_buff_len); + tmp_hna_buff_len = (hna_buff_len > batman_packet_ogm->num_hna * ETH_ALEN ? + batman_packet_ogm->num_hna * ETH_ALEN : hna_buff_len);
/* if this neighbor already is our next hop there is nothing * to change */ @@ -325,10 +325,11 @@ update_hna: hna_buff, tmp_hna_buff_len);
update_gw: - 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_packet_ogm->gw_flags) + gw_node_update(bat_priv, orig_node, + batman_packet_ogm->gw_flags);
- orig_node->gw_flags = batman_packet->gw_flags; + orig_node->gw_flags = batman_packet_ogm->gw_flags;
/* restart gateway selection if fast or late switching was enabled */ if ((orig_node->gw_flags) && @@ -371,7 +372,7 @@ static int window_protected(struct bat_priv *bat_priv, * was protected. Caller should drop it. */ static char count_real_packets(struct ethhdr *ethhdr, - struct batman_packet *batman_packet, + struct batman_packet_ogm *batman_packet_ogm, struct batman_if *if_incoming) { struct bat_priv *bat_priv = netdev_priv(if_incoming->soft_iface); @@ -382,11 +383,11 @@ static char count_real_packets(struct ethhdr *ethhdr, int need_update = 0; int set_mark;
- orig_node = get_orig_node(bat_priv, batman_packet->orig); + orig_node = get_orig_node(bat_priv, batman_packet_ogm->orig); if (orig_node == NULL) return 0;
- seq_diff = batman_packet->seqno - orig_node->last_real_seqno; + seq_diff = batman_packet_ogm->seqno - orig_node->last_real_seqno;
/* signalize caller that the packet is to be dropped. */ if (window_protected(bat_priv, seq_diff, @@ -397,7 +398,7 @@ static char count_real_packets(struct ethhdr *ethhdr,
is_duplicate |= get_bit_status(tmp_neigh_node->real_bits, orig_node->last_real_seqno, - batman_packet->seqno); + batman_packet_ogm->seqno);
if (compare_orig(tmp_neigh_node->addr, ethhdr->h_source) && (tmp_neigh_node->if_incoming == if_incoming)) @@ -417,8 +418,8 @@ static char count_real_packets(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_packet_ogm->seqno); + orig_node->last_real_seqno = batman_packet_ogm->seqno; }
return is_duplicate; @@ -428,10 +429,10 @@ static char count_real_packets(struct ethhdr *ethhdr, static void mark_bonding_address(struct bat_priv *bat_priv, struct orig_node *orig_node, struct orig_node *orig_neigh_node, - struct batman_packet *batman_packet) + struct batman_packet_ogm *batman_packet_ogm)
{ - if (batman_packet->flags & PRIMARIES_FIRST_HOP) + if (batman_packet_ogm->flags & PRIMARIES_FIRST_HOP) memcpy(orig_neigh_node->primary_addr, orig_node->orig, ETH_ALEN);
@@ -532,7 +533,7 @@ void update_bonding_candidates(struct bat_priv *bat_priv, }
void receive_bat_packet(struct ethhdr *ethhdr, - struct batman_packet *batman_packet, + struct batman_packet_ogm *batman_packet_ogm, unsigned char *hna_buff, int hna_buff_len, struct batman_if *if_incoming) { @@ -553,30 +554,30 @@ void receive_bat_packet(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_packet_ogm 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_packet_ogm->packet_type != BAT_PACKET_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_packet_ogm->flags & DIRECTLINK ? 1 : 0);
is_single_hop_neigh = (compare_orig(ethhdr->h_source, - batman_packet->orig) ? 1 : 0); + batman_packet_ogm->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, tq %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->tq, batman_packet->ttl, batman_packet->version, - has_directlink_flag); + if_incoming->net_dev->dev_addr, batman_packet_ogm->orig, + batman_packet_ogm->prev_sender, batman_packet_ogm->seqno, + batman_packet_ogm->tq, batman_packet_ogm->ttl, + batman_packet_ogm->version, has_directlink_flag);
rcu_read_lock(); list_for_each_entry_rcu(batman_if, &if_list, list) { @@ -590,11 +591,11 @@ void receive_bat_packet(struct ethhdr *ethhdr, batman_if->net_dev->dev_addr)) is_my_addr = 1;
- if (compare_orig(batman_packet->orig, + if (compare_orig(batman_packet_ogm->orig, batman_if->net_dev->dev_addr)) is_my_orig = 1;
- if (compare_orig(batman_packet->prev_sender, + if (compare_orig(batman_packet_ogm->prev_sender, batman_if->net_dev->dev_addr)) is_my_oldorig = 1;
@@ -603,10 +604,10 @@ void receive_bat_packet(struct ethhdr *ethhdr, } rcu_read_unlock();
- if (batman_packet->version != COMPAT_VERSION) { + if (batman_packet_ogm->version != COMPAT_VERSION) { bat_dbg(DBG_BATMAN, bat_priv, "Drop packet: incompatible batman version (%i)\n", - batman_packet->version); + batman_packet_ogm->version); return; }
@@ -640,8 +641,8 @@ void receive_bat_packet(struct ethhdr *ethhdr, * seqno for bidirectional check */ if (has_directlink_flag && compare_orig(if_incoming->net_dev->dev_addr, - batman_packet->orig) && - (batman_packet->seqno - if_incoming_seqno + 2 == 0)) { + batman_packet_ogm->orig) && + (batman_packet_ogm->seqno - if_incoming_seqno + 2 == 0)) { offset = if_incoming->if_num * NUM_WORDS; word = &(orig_neigh_node->bcast_own[offset]); bit_mark(word, 0); @@ -661,11 +662,11 @@ void receive_bat_packet(struct ethhdr *ethhdr, return; }
- orig_node = get_orig_node(bat_priv, batman_packet->orig); + orig_node = get_orig_node(bat_priv, batman_packet_ogm->orig); if (orig_node == NULL) return;
- is_duplicate = count_real_packets(ethhdr, batman_packet, if_incoming); + is_duplicate = count_real_packets(ethhdr, batman_packet_ogm, if_incoming);
if (is_duplicate == -1) { bat_dbg(DBG_BATMAN, bat_priv, @@ -674,7 +675,7 @@ void receive_bat_packet(struct ethhdr *ethhdr, return; }
- if (batman_packet->tq == 0) { + if (batman_packet_ogm->tq == 0) { bat_dbg(DBG_BATMAN, bat_priv, "Drop packet: originator packet with tq equal 0\n"); return; @@ -684,8 +685,8 @@ void receive_bat_packet(struct ethhdr *ethhdr, if ((orig_node->router) && (orig_node->router->orig_node->router) && (compare_orig(orig_node->router->addr, - batman_packet->prev_sender)) && - !(compare_orig(batman_packet->orig, batman_packet->prev_sender)) && + batman_packet_ogm->prev_sender)) && + !(compare_orig(batman_packet_ogm->orig, batman_packet_ogm->prev_sender)) && (compare_orig(orig_node->router->addr, orig_node->router->orig_node->router->addr))) { bat_dbg(DBG_BATMAN, bat_priv, @@ -712,26 +713,26 @@ void receive_bat_packet(struct ethhdr *ethhdr, }
is_bidirectional = is_bidirectional_neigh(orig_node, orig_neigh_node, - batman_packet, if_incoming); + batman_packet_ogm, if_incoming);
/* 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_packet_ogm->seqno) && + (orig_node->last_ttl - 3 <= batman_packet_ogm->ttl)))) + update_orig(bat_priv, orig_node, ethhdr, batman_packet_ogm, if_incoming, hna_buff, hna_buff_len, is_duplicate);
mark_bonding_address(bat_priv, orig_node, - orig_neigh_node, batman_packet); + orig_neigh_node, batman_packet_ogm); update_bonding_candidates(bat_priv, orig_node);
/* 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_packet_ogm, 1, hna_buff_len, if_incoming);
bat_dbg(DBG_BATMAN, bat_priv, "Forwarding packet: " @@ -754,7 +755,7 @@ void receive_bat_packet(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_packet_ogm, 0, hna_buff_len, if_incoming); }
@@ -764,7 +765,7 @@ int recv_bat_packet(struct sk_buff *skb, struct batman_if *batman_if) 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, sizeof(struct batman_packet_ogm)))) return NET_RX_DROP;
ethhdr = (struct ethhdr *)skb_mac_header(skb); diff --git a/routing.h b/routing.h index f108f23..81e27d5 100644 --- a/routing.h +++ b/routing.h @@ -26,7 +26,7 @@
void slide_own_bcast_window(struct batman_if *batman_if); void receive_bat_packet(struct ethhdr *ethhdr, - struct batman_packet *batman_packet, + struct batman_packet_ogm *batman_packet_ogm, unsigned char *hna_buff, int hna_buff_len, struct batman_if *if_incoming); void update_routes(struct bat_priv *bat_priv, struct orig_node *orig_node, diff --git a/send.c b/send.c index b89b9f7..eb9c1e3 100644 --- a/send.c +++ b/send.c @@ -109,7 +109,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_packet_ogm *batman_packet_ogm; struct sk_buff *skb;
if (batman_if->if_status != IF_ACTIVE) @@ -117,20 +117,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_packet_ogm = (struct batman_packet_ogm *)forw_packet->skb->data;
/* adjust all flags and log packets */ while (aggregated_packet(buff_pos, forw_packet->packet_len, - batman_packet->num_hna)) { + batman_packet_ogm->num_hna)) {
/* 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 == batman_if)) - batman_packet->flags |= DIRECTLINK; + batman_packet_ogm->flags |= DIRECTLINK; else - batman_packet->flags &= ~DIRECTLINK; + batman_packet_ogm->flags &= ~DIRECTLINK;
fwd_str = (packet_num > 0 ? "Forwarding" : (forw_packet->own ? "Sending own" : @@ -139,16 +139,16 @@ static void send_packet_to_if(struct forw_packet *forw_packet, "%s %spacket (originator %pM, seqno %d, TQ %d, TTL %d," " IDF %s) 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_packet_ogm->orig, ntohl(batman_packet_ogm->seqno), + batman_packet_ogm->tq, batman_packet_ogm->ttl, + (batman_packet_ogm->flags & DIRECTLINK ? "on" : "off"), batman_if->net_dev->name, batman_if->net_dev->dev_addr);
- buff_pos += sizeof(struct batman_packet) + - (batman_packet->num_hna * ETH_ALEN); + buff_pos += sizeof(struct batman_packet_ogm) + + (batman_packet_ogm->num_hna * ETH_ALEN); packet_num++; - batman_packet = (struct batman_packet *) + batman_packet_ogm = (struct batman_packet_ogm *) (forw_packet->skb->data + buff_pos); }
@@ -164,9 +164,10 @@ static void send_packet(struct forw_packet *forw_packet) struct batman_if *batman_if; struct net_device *soft_iface; struct bat_priv *bat_priv; - struct batman_packet *batman_packet = - (struct batman_packet *)(forw_packet->skb->data); - unsigned char directlink = (batman_packet->flags & DIRECTLINK ? 1 : 0); + struct batman_packet_ogm *batman_packet_ogm = + (struct batman_packet_ogm *)(forw_packet->skb->data); + unsigned char directlink = + (batman_packet_ogm->flags & DIRECTLINK ? 1 : 0);
if (!forw_packet->if_incoming) { pr_err("Error - can't forward packet: incoming iface not " @@ -182,7 +183,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_packet_ogm->ttl == 1)) || (forw_packet->own && (forw_packet->if_incoming->if_num > 0))) {
/* FIXME: what about aggregated packets ? */ @@ -190,8 +191,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_packet_ogm->orig, + ntohl(batman_packet_ogm->seqno), + batman_packet_ogm->ttl, forw_packet->if_incoming->net_dev->name, forw_packet->if_incoming->net_dev->dev_addr);
@@ -214,26 +216,26 @@ static void send_packet(struct forw_packet *forw_packet) rcu_read_unlock(); }
-static void rebuild_batman_packet(struct bat_priv *bat_priv, - struct batman_if *batman_if) +static void rebuild_batman_packet_ogm(struct bat_priv *bat_priv, + struct batman_if *batman_if) { int new_len; unsigned char *new_buff; - struct batman_packet *batman_packet; + struct batman_packet_ogm *batman_packet_ogm;
- new_len = sizeof(struct batman_packet) + + new_len = sizeof(struct batman_packet_ogm) + (bat_priv->num_local_hna * ETH_ALEN); new_buff = kmalloc(new_len, GFP_ATOMIC);
/* keep old buffer if kmalloc should fail */ if (new_buff) { memcpy(new_buff, batman_if->packet_buff, - sizeof(struct batman_packet)); - batman_packet = (struct batman_packet *)new_buff; + sizeof(struct batman_packet_ogm)); + batman_packet_ogm = (struct batman_packet_ogm *)new_buff;
- batman_packet->num_hna = hna_local_fill_buffer(bat_priv, - new_buff + sizeof(struct batman_packet), - new_len - sizeof(struct batman_packet)); + batman_packet_ogm->num_hna = hna_local_fill_buffer(bat_priv, + new_buff + sizeof(struct batman_packet_ogm), + new_len - sizeof(struct batman_packet_ogm));
kfree(batman_if->packet_buff); batman_if->packet_buff = new_buff; @@ -245,7 +247,7 @@ void schedule_own_packet(struct batman_if *batman_if) { struct bat_priv *bat_priv = netdev_priv(batman_if->soft_iface); unsigned long send_time; - struct batman_packet *batman_packet; + struct batman_packet_ogm *batman_packet_ogm; int vis_server;
if ((batman_if->if_status == IF_NOT_IN_USE) || @@ -267,29 +269,29 @@ void schedule_own_packet(struct batman_if *batman_if) /* if local hna has changed and interface is a primary interface */ if ((atomic_read(&bat_priv->hna_local_changed)) && (batman_if == bat_priv->primary_if)) - rebuild_batman_packet(bat_priv, batman_if); + rebuild_batman_packet_ogm(bat_priv, batman_if);
/** * NOTE: packet_buff might just have been re-allocated in - * rebuild_batman_packet() + * rebuild_batman_packet_ogm() */ - batman_packet = (struct batman_packet *)batman_if->packet_buff; + batman_packet_ogm = (struct batman_packet_ogm *)batman_if->packet_buff;
/* change sequence number to network order */ - batman_packet->seqno = + batman_packet_ogm->seqno = htonl((uint32_t)atomic_read(&batman_if->seqno));
if (vis_server == VIS_TYPE_SERVER_SYNC) - batman_packet->flags |= VIS_SERVER; + batman_packet_ogm->flags |= VIS_SERVER; else - batman_packet->flags &= ~VIS_SERVER; + batman_packet_ogm->flags &= ~VIS_SERVER;
if ((batman_if == bat_priv->primary_if) && (atomic_read(&bat_priv->gw_mode) == GW_MODE_SERVER)) - batman_packet->gw_flags = + batman_packet_ogm->gw_flags = (uint8_t)atomic_read(&bat_priv->gw_bandwidth); else - batman_packet->gw_flags = 0; + batman_packet_ogm->gw_flags = 0;
atomic_inc(&batman_if->seqno);
@@ -303,7 +305,7 @@ void schedule_own_packet(struct batman_if *batman_if)
void schedule_forward_packet(struct orig_node *orig_node, struct ethhdr *ethhdr, - struct batman_packet *batman_packet, + struct batman_packet_ogm *batman_packet_ogm, uint8_t directlink, int hna_buff_len, struct batman_if *if_incoming) { @@ -311,16 +313,16 @@ void schedule_forward_packet(struct orig_node *orig_node, unsigned char in_tq, in_ttl, tq_avg = 0; unsigned long send_time;
- if (batman_packet->ttl <= 1) { + if (batman_packet_ogm->ttl <= 1) { bat_dbg(DBG_BATMAN, bat_priv, "ttl exceeded\n"); return; }
- in_tq = batman_packet->tq; - in_ttl = batman_packet->ttl; + in_tq = batman_packet_ogm->tq; + in_ttl = batman_packet_ogm->ttl;
- batman_packet->ttl--; - memcpy(batman_packet->prev_sender, ethhdr->h_source, ETH_ALEN); + batman_packet_ogm->ttl--; + memcpy(batman_packet_ogm->prev_sender, ethhdr->h_source, ETH_ALEN);
/* rebroadcast tq of our best ranking neighbor to ensure the rebroadcast * of our best tq value */ @@ -328,10 +330,10 @@ void schedule_forward_packet(struct orig_node *orig_node,
/* rebroadcast ogm of best ranking neighbor as is */ if (!compare_orig(orig_node->router->addr, ethhdr->h_source)) { - batman_packet->tq = orig_node->router->tq_avg; + batman_packet_ogm->tq = orig_node->router->tq_avg;
if (orig_node->router->last_ttl) - batman_packet->ttl = orig_node->router->last_ttl + batman_packet_ogm->ttl = orig_node->router->last_ttl - 1; }
@@ -339,27 +341,27 @@ void schedule_forward_packet(struct orig_node *orig_node, }
/* apply hop penalty */ - batman_packet->tq = hop_penalty(batman_packet->tq, bat_priv); + batman_packet_ogm->tq = hop_penalty(batman_packet_ogm->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_packet_ogm->tq, in_ttl - 1, + batman_packet_ogm->ttl);
- batman_packet->seqno = htonl(batman_packet->seqno); + batman_packet_ogm->seqno = htonl(batman_packet_ogm->seqno);
/* switch of primaries first hop flag when forwarding */ - batman_packet->flags &= ~PRIMARIES_FIRST_HOP; + batman_packet_ogm->flags &= ~PRIMARIES_FIRST_HOP; if (directlink) - batman_packet->flags |= DIRECTLINK; + batman_packet_ogm->flags |= DIRECTLINK; else - batman_packet->flags &= ~DIRECTLINK; + batman_packet_ogm->flags &= ~DIRECTLINK;
send_time = forward_send_time(bat_priv); add_bat_packet_to_list(bat_priv, - (unsigned char *)batman_packet, - sizeof(struct batman_packet) + hna_buff_len, + (unsigned char *)batman_packet_ogm, + sizeof(struct batman_packet_ogm) + hna_buff_len, if_incoming, 0, send_time); }
diff --git a/send.h b/send.h index c4cefa8..acf59e7 100644 --- a/send.h +++ b/send.h @@ -30,7 +30,7 @@ int send_skb_packet(struct sk_buff *skb, void schedule_own_packet(struct batman_if *batman_if); void schedule_forward_packet(struct orig_node *orig_node, struct ethhdr *ethhdr, - struct batman_packet *batman_packet, + struct batman_packet_ogm *batman_packet_ogm, uint8_t directlink, int hna_buff_len, struct batman_if *if_outgoing); int add_bcast_packet_to_list(struct bat_priv *bat_priv, struct sk_buff *skb); diff --git a/soft-interface.c b/soft-interface.c index e89ede1..ac65bc1 100644 --- a/soft-interface.c +++ b/soft-interface.c @@ -221,28 +221,30 @@ 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_packet_ogm *batman_packet_ogm; struct softif_neigh *softif_neigh, *softif_neigh_tmp;
if (ntohs(ethhdr->h_proto) == ETH_P_8021Q) - batman_packet = (struct batman_packet *) + batman_packet_ogm = (struct batman_packet_ogm *) (skb->data + ETH_HLEN + VLAN_HLEN); else - batman_packet = (struct batman_packet *)(skb->data + ETH_HLEN); + batman_packet_ogm = (struct batman_packet_ogm *) + (skb->data + ETH_HLEN);
- if (batman_packet->version != COMPAT_VERSION) + if (batman_packet_ogm->version != COMPAT_VERSION) goto err;
- if (batman_packet->packet_type != BAT_PACKET) + if (batman_packet_ogm->packet_type != BAT_PACKET_OGM) goto err;
- if (!(batman_packet->flags & PRIMARIES_FIRST_HOP)) + if (!(batman_packet_ogm->flags & PRIMARIES_FIRST_HOP)) goto err;
- if (is_my_mac(batman_packet->orig)) + if (is_my_mac(batman_packet_ogm->orig)) goto err;
- softif_neigh = softif_neigh_get(bat_priv, batman_packet->orig, vid); + softif_neigh = softif_neigh_get(bat_priv, batman_packet_ogm->orig, + vid);
if (!softif_neigh) goto err; diff --git a/translation-table.c b/translation-table.c index 4b0a107..6d5d3ec 100644 --- a/translation-table.c +++ b/translation-table.c @@ -77,7 +77,7 @@ void hna_local_add(struct net_device *soft_iface, uint8_t *addr) space in batman_packet->num_hna That also should give a limit to MAC-flooding. */ required_bytes = (bat_priv->num_local_hna + 1) * ETH_ALEN; - required_bytes += BAT_PACKET_LEN; + required_bytes += BAT_PACKET_OGM_LEN;
if ((required_bytes > ETH_DATA_LEN) || (atomic_read(&bat_priv->aggregated_ogms) &&
On Tuesday 14 December 2010 10:58:07 Linus Lüssing wrote:
This patch creates the new neighbor discovery packet type (which is not actually being used with this patch). It will later be responsible to detect neighbors and calculate the link quality to them.
In fact, most of the patch renames batman_packet to batman_packet_ogm. Why not making this a rename patch only ? The next patch still renames some more stuff which could go into this patch as well (e.g. schedule_own_packet).
How about renaming batman_packet to batman_ogm and batman_packet_ndp to batman_ndp ? Or ogm_packet / ndp_packet ? The 80 chars per line limitation does not make these long names very handy ...
-#define BAT_PACKET 0x01 -#define BAT_ICMP 0x02 -#define BAT_UNICAST 0x03 -#define BAT_BCAST 0x04 -#define BAT_VIS 0x05 -#define BAT_UNICAST_FRAG 0x06 +#define BAT_PACKET_NDP 0x01 +#define BAT_PACKET_OGM 0x02 +#define BAT_ICMP 0x03 +#define BAT_UNICAST 0x04 +#define BAT_BCAST 0x05 +#define BAT_VIS 0x06 +#define BAT_UNICAST_FRAG 0x07
Although I like this reordering (I would like to see BAT_UNICAST followed by BAT_UNICAST_FRAG) I think we can't easily touch this without annoying the wireshark folks. Maybe we don't care because they hate us already ?
-struct batman_packet { +/* Neighbor discovery packet */ +struct batman_packet_ndp {
- uint8_t packet_type;
- uint8_t version; /* batman version field */
- uint8_t orig[6];
- uint32_t seqno;
- uint8_t num_neighbors;
- uint8_t align[3];
+} __attribute__((packed));
This should go into one of the later patches where it is used.
Cheers, Marek
-#define BAT_PACKET 0x01 -#define BAT_ICMP 0x02 -#define BAT_UNICAST 0x03 -#define BAT_BCAST 0x04 -#define BAT_VIS 0x05 -#define BAT_UNICAST_FRAG 0x06 +#define BAT_PACKET_NDP 0x01 +#define BAT_PACKET_OGM 0x02 +#define BAT_ICMP 0x03 +#define BAT_UNICAST 0x04 +#define BAT_BCAST 0x05 +#define BAT_VIS 0x06 +#define BAT_UNICAST_FRAG 0x07
Although I like this reordering (I would like to see BAT_UNICAST followed by BAT_UNICAST_FRAG) I think we can't easily touch this without annoying the wireshark folks. Maybe we don't care because they hate us already ?
It will also be interesting to see what David Miller says the first time you increment the version number, or make some other backward incompatible change.
Andrew
This patch adds a function for fetching and jittering an ndp interval from batman-if structure. Needed later for timing the neighbor discovery packets.
Signed-off-by: Linus Lüssing linus.luessing@ascom.ch --- hard-interface.c | 2 +- routing.c | 2 +- send.c | 18 +++++++++++++----- send.h | 3 ++- types.h | 1 + 5 files changed, 18 insertions(+), 8 deletions(-)
diff --git a/hard-interface.c b/hard-interface.c index 784c475..da7b9a9 100644 --- a/hard-interface.c +++ b/hard-interface.c @@ -360,7 +360,7 @@ int hardif_enable_interface(struct batman_if *batman_if, char *iface_name) batman_if->net_dev->name);
/* begin scheduling originator messages on that interface */ - schedule_own_packet(batman_if); + schedule_own_ogm_packet(batman_if);
out: return 0; diff --git a/routing.c b/routing.c index a9406ba..7ebb631 100644 --- a/routing.c +++ b/routing.c @@ -561,7 +561,7 @@ void receive_bat_packet(struct ethhdr *ethhdr, if (batman_packet_ogm->packet_type != BAT_PACKET_OGM) return;
- /* could be changed by schedule_own_packet() */ + /* could be changed by schedule_own_ogm_packet() */ if_incoming_seqno = atomic_read(&if_incoming->seqno);
has_directlink_flag = (batman_packet_ogm->flags & DIRECTLINK ? 1 : 0); diff --git a/send.c b/send.c index eb9c1e3..910411c 100644 --- a/send.c +++ b/send.c @@ -40,8 +40,16 @@ static uint8_t hop_penalty(const uint8_t tq, struct bat_priv *bat_priv) 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(struct bat_priv *bat_priv) +/* when do we schedule our own neighbor discovery packet to be sent */ +unsigned long own_ndp_send_time(struct batman_if *batman_if) +{ + return jiffies + msecs_to_jiffies( + atomic_read(&batman_if->ndp_interval) - + JITTER + (random32() % 2*JITTER)); +} + +/* when do we schedule our own originator packet to be sent */ +static unsigned long own_ogm_send_time(struct bat_priv *bat_priv) { return jiffies + msecs_to_jiffies( atomic_read(&bat_priv->orig_interval) - @@ -243,7 +251,7 @@ static void rebuild_batman_packet_ogm(struct bat_priv *bat_priv, } }
-void schedule_own_packet(struct batman_if *batman_if) +void schedule_own_ogm_packet(struct batman_if *batman_if) { struct bat_priv *bat_priv = netdev_priv(batman_if->soft_iface); unsigned long send_time; @@ -296,7 +304,7 @@ void schedule_own_packet(struct batman_if *batman_if) atomic_inc(&batman_if->seqno);
slide_own_bcast_window(batman_if); - send_time = own_send_time(bat_priv); + send_time = own_ogm_send_time(bat_priv); add_bat_packet_to_list(bat_priv, batman_if->packet_buff, batman_if->packet_len, @@ -513,7 +521,7 @@ void send_outstanding_bat_packet(struct work_struct *work) * shutting down */ if (forw_packet->own) - schedule_own_packet(forw_packet->if_incoming); + schedule_own_ogm_packet(forw_packet->if_incoming);
out: /* don't count own packet */ diff --git a/send.h b/send.h index acf59e7..b626ddf 100644 --- a/send.h +++ b/send.h @@ -27,7 +27,8 @@ int send_skb_packet(struct sk_buff *skb, struct batman_if *batman_if, uint8_t *dst_addr); -void schedule_own_packet(struct batman_if *batman_if); +unsigned long own_ndp_send_time(struct batman_if *batman_if); +void schedule_own_ogm_packet(struct batman_if *batman_if); void schedule_forward_packet(struct orig_node *orig_node, struct ethhdr *ethhdr, struct batman_packet_ogm *batman_packet_ogm, diff --git a/types.h b/types.h index 1d00849..8921e20 100644 --- a/types.h +++ b/types.h @@ -47,6 +47,7 @@ struct batman_if { struct packet_type batman_adv_ptype; struct net_device *soft_iface; struct rcu_head rcu; + atomic_t ndp_interval; };
/**
The new neighbor discovery packets will later need their own interval per interface. For instance on a wifi interface which has regularly changing link qualities the ndp interval should be faster than on a static cable link where we would need some probes from time to time only.
This patch adds a workqueue per interface used by batman-adv. When an interface is active, a ndp_send() with the according batman_if structure will be called every second now.
Signed-off-by: Linus Lüssing linus.luessing@ascom.ch --- Makefile.kbuild | 1 + hard-interface.c | 6 ++++++ ndp.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ ndp.h | 6 ++++++ types.h | 2 ++ 5 files changed, 59 insertions(+), 0 deletions(-) create mode 100644 ndp.c create mode 100644 ndp.h
diff --git a/Makefile.kbuild b/Makefile.kbuild index e99c198..094eb31 100644 --- a/Makefile.kbuild +++ b/Makefile.kbuild @@ -42,6 +42,7 @@ batman-adv-y += hard-interface.o batman-adv-y += hash.o batman-adv-y += icmp_socket.o batman-adv-y += main.o +batman-adv-y += ndp.o batman-adv-y += originator.o batman-adv-y += ring_buffer.o batman-adv-y += routing.o diff --git a/hard-interface.c b/hard-interface.c index da7b9a9..cb81c13 100644 --- a/hard-interface.c +++ b/hard-interface.c @@ -26,6 +26,7 @@ #include "translation-table.h" #include "routing.h" #include "bat_sysfs.h" +#include "ndp.h" #include "originator.h" #include "hash.h"
@@ -260,6 +261,7 @@ static void hardif_activate_interface(struct batman_if *batman_if) batman_if->net_dev->name);
update_min_mtu(batman_if->soft_iface); + start_ndp_timer(batman_if); return; }
@@ -274,6 +276,7 @@ static void hardif_deactivate_interface(struct batman_if *batman_if) bat_info(batman_if->soft_iface, "Interface deactivated: %s\n", batman_if->net_dev->name);
+ stop_ndp_timer(batman_if); update_min_mtu(batman_if->soft_iface); }
@@ -328,6 +331,8 @@ int hardif_enable_interface(struct batman_if *batman_if, char *iface_name)
atomic_set(&batman_if->seqno, 1); atomic_set(&batman_if->frag_seqno, 1); + ndp_init(batman_if); + bat_info(batman_if->soft_iface, "Adding interface: %s\n", batman_if->net_dev->name);
@@ -381,6 +386,7 @@ void hardif_disable_interface(struct batman_if *batman_if)
bat_info(batman_if->soft_iface, "Removing interface: %s\n", batman_if->net_dev->name); + ndp_free(batman_if); dev_remove_pack(&batman_if->batman_adv_ptype); kref_put(&batman_if->refcount, hardif_free_ref);
diff --git a/ndp.c b/ndp.c new file mode 100644 index 0000000..2dfb06d --- /dev/null +++ b/ndp.c @@ -0,0 +1,44 @@ +#include "main.h" +#include "send.h" +#include "ndp.h" + +void start_ndp_timer(struct batman_if *batman_if) +{ + // adding some jitter + unsigned long ndp_interval = own_ndp_send_time(batman_if); + queue_delayed_work(bat_event_workqueue, &batman_if->ndp_wq, + ndp_interval - jiffies); +} + +void stop_ndp_timer(struct batman_if *batman_if) +{ + cancel_delayed_work_sync(&batman_if->ndp_wq); +} + +static void ndp_send(struct work_struct *work) +{ + struct batman_if *batman_if = container_of(work, struct batman_if, + ndp_wq.work); + struct bat_priv *bat_priv = netdev_priv(batman_if->soft_iface); + + bat_dbg(DBG_BATMAN, bat_priv, + "batman-adv:Sending ndp packet on interface %s, seqno %d\n", + batman_if->net_dev, atomic_read(&batman_if->ndp_seqno)); + + atomic_inc(&batman_if->ndp_seqno); + start_ndp_timer(batman_if); +} + +int ndp_init(struct batman_if *batman_if) +{ + atomic_set(&batman_if->ndp_interval, 500); + atomic_set(&batman_if->ndp_seqno, 0); + INIT_DELAYED_WORK(&batman_if->ndp_wq, ndp_send); + + return 0; +} + +void ndp_free(struct batman_if *batman_if) +{ + stop_ndp_timer(batman_if); +} diff --git a/ndp.h b/ndp.h new file mode 100644 index 0000000..de85910 --- /dev/null +++ b/ndp.h @@ -0,0 +1,6 @@ + +void start_ndp_timer(struct batman_if *batman_if); +void stop_ndp_timer(struct batman_if *batman_if); + +int ndp_init(struct batman_if *batman_if); +void ndp_free(struct batman_if *batman_if); diff --git a/types.h b/types.h index 8921e20..e8dfdf6 100644 --- a/types.h +++ b/types.h @@ -48,6 +48,8 @@ struct batman_if { struct net_device *soft_iface; struct rcu_head rcu; atomic_t ndp_interval; + atomic_t ndp_seqno; + struct delayed_work ndp_wq; };
/**
On Tuesday 14 December 2010 10:58:09 Linus Lüssing wrote:
diff --git a/ndp.c b/ndp.c new file mode 100644 index 0000000..2dfb06d --- /dev/null +++ b/ndp.c @@ -0,0 +1,44 @@ +#include "main.h" +#include "send.h"
I think it would make more sense to have own_ndp_send_time() in ndp.c as it is not used anywhere else. We don't have to repeat the mistakes from the past. ;-)
+void start_ndp_timer(struct batman_if *batman_if) +{
- // adding some jitter
- unsigned long ndp_interval = own_ndp_send_time(batman_if);
- queue_delayed_work(bat_event_workqueue, &batman_if->ndp_wq,
ndp_interval - jiffies);
+}
+void stop_ndp_timer(struct batman_if *batman_if) +{
- cancel_delayed_work_sync(&batman_if->ndp_wq);
+}
Would you mind renaming these functions, so that they begin with ndp_*() ? Checkpatch does not like C99 style comments ("//").
+int ndp_init(struct batman_if *batman_if) +{
- atomic_set(&batman_if->ndp_interval, 500);
- atomic_set(&batman_if->ndp_seqno, 0);
- INIT_DELAYED_WORK(&batman_if->ndp_wq, ndp_send);
- return 0;
+}
Wouldn't it be better to initialize the ndp_interval in hardif_add_interface(), so that an interface disable/enable does not overwrite user specified ndp intervals ?
Cheers, Marek
This patch makes use of the previously introduced periodic tasks per interface and actually sends neighbor discovery packets on these now. Note: The TQ values of each neighbor are not being added yet to these NDPs and also no evaluation of these packets is being done.
Signed-off-by: Linus Lüssing linus.luessing@ascom.ch --- hard-interface.c | 5 ++++- ndp.c | 36 +++++++++++++++++++++++++++++++++++- types.h | 5 +++++ 3 files changed, 44 insertions(+), 2 deletions(-)
diff --git a/hard-interface.c b/hard-interface.c index cb81c13..887f794 100644 --- a/hard-interface.c +++ b/hard-interface.c @@ -284,6 +284,7 @@ int hardif_enable_interface(struct batman_if *batman_if, char *iface_name) { struct bat_priv *bat_priv; struct batman_packet_ogm *batman_packet_ogm; + int ret;
if (batman_if->if_status != IF_NOT_IN_USE) goto out; @@ -331,7 +332,9 @@ int hardif_enable_interface(struct batman_if *batman_if, char *iface_name)
atomic_set(&batman_if->seqno, 1); atomic_set(&batman_if->frag_seqno, 1); - ndp_init(batman_if); + ret = ndp_init(batman_if); + if (ret) + goto err;
bat_info(batman_if->soft_iface, "Adding interface: %s\n", batman_if->net_dev->name); diff --git a/ndp.c b/ndp.c index 2dfb06d..94d1971 100644 --- a/ndp.c +++ b/ndp.c @@ -20,10 +20,21 @@ static void ndp_send(struct work_struct *work) struct batman_if *batman_if = container_of(work, struct batman_if, ndp_wq.work); struct bat_priv *bat_priv = netdev_priv(batman_if->soft_iface); + struct batman_packet_ndp *ndp_packet; + struct sk_buff *skb; + + skb = skb_clone(batman_if->ndp_skb, GFP_ATOMIC); + ndp_packet = (struct batman_packet_ndp*)skb->data; + ndp_packet->seqno = htonl(atomic_read(&batman_if->ndp_seqno)); + ndp_packet->num_neighbors = 0; + memcpy(ndp_packet->orig, bat_priv->primary_if->net_dev->dev_addr, + ETH_ALEN);
bat_dbg(DBG_BATMAN, bat_priv, "batman-adv:Sending ndp packet on interface %s, seqno %d\n", - batman_if->net_dev, atomic_read(&batman_if->ndp_seqno)); + batman_if->net_dev, ntohl(ndp_packet->seqno)); + + send_skb_packet(skb, batman_if, broadcast_addr);
atomic_inc(&batman_if->ndp_seqno); start_ndp_timer(batman_if); @@ -31,14 +42,37 @@ static void ndp_send(struct work_struct *work)
int ndp_init(struct batman_if *batman_if) { + struct batman_packet_ndp *ndp_packet; + atomic_set(&batman_if->ndp_interval, 500); atomic_set(&batman_if->ndp_seqno, 0); + + batman_if->ndp_skb = + dev_alloc_skb(ETH_DATA_LEN + sizeof(struct ethhdr)); + if (!batman_if->ndp_skb) { + printk(KERN_ERR "batman-adv: Can't add " + "local interface packet (%s): out of memory\n", + batman_if->net_dev->name); + goto err; + } + skb_reserve(batman_if->ndp_skb, sizeof(struct ethhdr) + + sizeof(struct batman_packet_ndp)); + ndp_packet = (struct batman_packet_ndp*) + skb_push(batman_if->ndp_skb, sizeof(struct batman_packet_ndp)); + memset(ndp_packet, 0, sizeof(struct batman_packet_ndp)); + + ndp_packet->packet_type = BAT_PACKET_NDP; + ndp_packet->version = COMPAT_VERSION; + INIT_DELAYED_WORK(&batman_if->ndp_wq, ndp_send);
return 0; +err: + return 1; }
void ndp_free(struct batman_if *batman_if) { stop_ndp_timer(batman_if); + dev_kfree_skb(batman_if->ndp_skb); } diff --git a/types.h b/types.h index e8dfdf6..c5a26a7 100644 --- a/types.h +++ b/types.h @@ -49,6 +49,7 @@ struct batman_if { struct rcu_head rcu; atomic_t ndp_interval; atomic_t ndp_seqno; + struct sk_buff *ndp_skb; struct delayed_work ndp_wq; };
@@ -122,6 +123,10 @@ struct neigh_node { struct batman_if *if_incoming; };
+struct neigh_entry { + uint8_t addr[ETH_ALEN]; + uint8_t rq; +};
struct bat_priv { atomic_t mesh_state;
On Tuesday 14 December 2010 10:58:10 Linus Lüssing wrote:
@@ -331,7 +332,9 @@ int hardif_enable_interface(struct batman_if *batman_if, char *iface_name)
atomic_set(&batman_if->seqno, 1); atomic_set(&batman_if->frag_seqno, 1);
- ndp_init(batman_if);
- ret = ndp_init(batman_if);
- if (ret)
goto err;
This introduces a potential memory leak, next to other problems. If the code jumps to "err" batman_if->packet_buff is not free()'d, bat_priv->num_ifaces is wrong, the orig_hash has one interface too much, etc. Please check the error handling here and make sure that there is a clean rollback.
- skb = skb_clone(batman_if->ndp_skb, GFP_ATOMIC);
- ndp_packet = (struct batman_packet_ndp*)skb->data;
- ndp_packet->seqno = htonl(atomic_read(&batman_if->ndp_seqno));
- ndp_packet->num_neighbors = 0;
- memcpy(ndp_packet->orig, bat_priv->primary_if->net_dev->dev_addr,
ETH_ALEN);
I don't think you want to use skb_clone() here as it "only" copies the sk_buff and not skb->data. That means all threads write on the same skb->data ...
+struct neigh_entry {
- uint8_t addr[ETH_ALEN];
- uint8_t rq;
+};
Again, this struct is not used and can be added later.
Checkpatch gives 2 errors ..
Cheers, Marek
It will now be checked if a neighbor discovery packet from a new neighbor on a certain interface has been received. If so, structures in memory will be allocated for further seqno-tracking and RQ calculations, and TQ reception, which will be updated frequently from this commit on.
Signed-off-by: Linus Lüssing linus.luessing@ascom.ch --- hard-interface.c | 5 ++ ndp.c | 142 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ ndp.h | 5 ++ routing.c | 42 ++++++++++++++++- routing.h | 1 + types.h | 5 ++ 6 files changed, 199 insertions(+), 1 deletions(-)
diff --git a/hard-interface.c b/hard-interface.c index 887f794..820121a 100644 --- a/hard-interface.c +++ b/hard-interface.c @@ -608,6 +608,11 @@ int batman_skb_recv(struct sk_buff *skb, struct net_device *dev, * the supplied skb. if not, we have to free the skb. */
switch (batman_packet_ogm->packet_type) { + /* batman neighbor discovery protocol packet */ + case BAT_PACKET_NDP: + ret = recv_ndp_packet(skb, batman_if); + break; + /* batman originator packet */ case BAT_PACKET_OGM: ret = recv_bat_packet(skb, batman_if); diff --git a/ndp.c b/ndp.c index 94d1971..408dd70 100644 --- a/ndp.c +++ b/ndp.c @@ -1,6 +1,8 @@ #include "main.h" #include "send.h" #include "ndp.h" +#include "soft-interface.h" +#include "originator.h"
void start_ndp_timer(struct batman_if *batman_if) { @@ -21,6 +23,9 @@ static void ndp_send(struct work_struct *work) ndp_wq.work); struct bat_priv *bat_priv = netdev_priv(batman_if->soft_iface); struct batman_packet_ndp *ndp_packet; + struct neigh_entry *neigh_entry; + struct neigh_node *neigh_node = NULL; + int entries_len = 0; struct sk_buff *skb;
skb = skb_clone(batman_if->ndp_skb, GFP_ATOMIC); @@ -30,6 +35,22 @@ static void ndp_send(struct work_struct *work) memcpy(ndp_packet->orig, bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN);
+ neigh_entry = (struct neigh_entry*)(ndp_packet + 1); + spin_lock_bh(&batman_if->neigh_list_lock); + list_for_each_entry(neigh_node, &batman_if->neigh_list, list) { + if (entries_len + sizeof(struct neigh_entry) > + skb_tailroom(skb)) + break; + + memcpy(neigh_entry->addr, neigh_node->addr, ETH_ALEN); + neigh_entry->rq = neigh_node->rq; + ndp_packet->num_neighbors++; + neigh_entry++; + entries_len += sizeof(struct neigh_entry); + } + spin_unlock_bh(&batman_if->neigh_list_lock); + skb_put(skb, entries_len); + bat_dbg(DBG_BATMAN, bat_priv, "batman-adv:Sending ndp packet on interface %s, seqno %d\n", batman_if->net_dev, ntohl(ndp_packet->seqno)); @@ -64,6 +85,9 @@ int ndp_init(struct batman_if *batman_if) ndp_packet->packet_type = BAT_PACKET_NDP; ndp_packet->version = COMPAT_VERSION;
+ INIT_LIST_HEAD(&batman_if->neigh_list); + spin_lock_init(&batman_if->neigh_list_lock); + INIT_DELAYED_WORK(&batman_if->ndp_wq, ndp_send);
return 0; @@ -76,3 +100,121 @@ void ndp_free(struct batman_if *batman_if) stop_ndp_timer(batman_if); dev_kfree_skb(batman_if->ndp_skb); } + +/* extract my own tq to neighbor from the ndp packet */ +uint8_t ndp_fetch_tq(struct batman_packet_ndp *packet, + uint8_t *my_if_addr) +{ + struct neigh_entry *neigh_entry = (struct neigh_entry*)(packet + 1); + uint8_t tq = 0; + int i; + + for (i = 0; i < packet->num_neighbors; i++) { + if (compare_orig(my_if_addr, neigh_entry->addr)) { + tq = neigh_entry->rq; + break; + } + neigh_entry++; + } + return tq; +} + +static void ndp_update_neighbor_lq(uint8_t tq, uint32_t seqno, + struct neigh_node *neigh_node, + struct bat_priv *bat_priv) +{ + char is_duplicate = 0; + int32_t seq_diff; + int need_update = 0; + + seq_diff = seqno - neigh_node->last_rq_seqno; + + is_duplicate |= get_bit_status(neigh_node->rq_real_bits, + neigh_node->last_rq_seqno, + seqno); + + /* if the window moved, set the update flag. */ + need_update |= bit_get_packet(bat_priv, neigh_node->rq_real_bits, + seq_diff, 1); + // TODO: rename TQ_LOCAL_WINDOW_SIZE to RQ_LOCAL... + neigh_node->rq = + (bit_packet_count(neigh_node->rq_real_bits) * TQ_MAX_VALUE) + / TQ_LOCAL_WINDOW_SIZE; + + if (need_update) { + bat_dbg(DBG_BATMAN, bat_priv, "batman-adv: ndp: " + "updating last_seqno of neighbor %pM: old %d, new %d\n", + neigh_node->addr, neigh_node->last_rq_seqno, seqno); + // TODO: this is not really an average here, + // need to change the variable name later + neigh_node->tq_avg = tq; + neigh_node->last_valid = jiffies; + neigh_node->last_rq_seqno = seqno; + } + + if (is_duplicate) + bat_dbg(DBG_BATMAN, bat_priv, + "seqno %d of neighbor %pM was a duplicate!\n", + seqno, neigh_node->addr); + + bat_dbg(DBG_BATMAN, bat_priv, "batman-adv: ndp: " + "new rq/tq of neighbor %pM: rq %d, tq %d\n", + neigh_node->addr, neigh_node->rq, neigh_node->tq_avg); +} + +static struct neigh_node *ndp_create_neighbor(uint8_t my_tq, uint32_t seqno, + uint8_t *neigh_addr, + struct bat_priv *bat_priv) +{ + struct neigh_node *neigh_node; + + bat_dbg(DBG_BATMAN, bat_priv, + "batman-adv: ndp: Creating new neighbor %pM, " + "initial tq %d, initial seqno %d\n", + neigh_addr, my_tq, seqno); + + neigh_node = kzalloc(sizeof(struct neigh_node), GFP_ATOMIC); + if (!neigh_node) + return NULL; + + INIT_LIST_HEAD(&neigh_node->list); + memcpy(neigh_node->addr, neigh_addr, ETH_ALEN); + neigh_node->last_rq_seqno = seqno; + + return neigh_node; +} + +int ndp_update_neighbor(uint8_t my_tq, uint32_t seqno, + struct batman_if *batman_if, uint8_t *neigh_addr) +{ + struct bat_priv *bat_priv = netdev_priv(batman_if->soft_iface); + struct neigh_node *neigh_node = NULL, *tmp_neigh_node = NULL; + int ret = 1; + + spin_lock_bh(&batman_if->neigh_list_lock); + // old neighbor? + list_for_each_entry(tmp_neigh_node, &batman_if->neigh_list, list) { + if (!compare_orig(tmp_neigh_node->addr, neigh_addr)) + continue; + + neigh_node = tmp_neigh_node; + } + + // new neighbor? + if (!neigh_node) { + neigh_node = ndp_create_neighbor(my_tq, seqno, neigh_addr, + bat_priv); + if (!neigh_node) + goto ret; + + list_add_tail(&neigh_node->list, &batman_if->neigh_list); + } + + ndp_update_neighbor_lq(my_tq, seqno, neigh_node, bat_priv); + + ret = 0; + +ret: + spin_unlock_bh(&batman_if->neigh_list_lock); + return ret; +} diff --git a/ndp.h b/ndp.h index de85910..35146ce 100644 --- a/ndp.h +++ b/ndp.h @@ -4,3 +4,8 @@ void stop_ndp_timer(struct batman_if *batman_if);
int ndp_init(struct batman_if *batman_if); void ndp_free(struct batman_if *batman_if); + +uint8_t ndp_fetch_tq(struct batman_packet_ndp *packet, + uint8_t *my_if_addr); +int ndp_update_neighbor(uint8_t my_tq, uint32_t seqno, + struct batman_if *batman_if, uint8_t *neigh_addr); diff --git a/routing.c b/routing.c index 7ebb631..dbea97f 100644 --- a/routing.c +++ b/routing.c @@ -27,6 +27,7 @@ #include "hard-interface.h" #include "icmp_socket.h" #include "translation-table.h" +#include "ndp.h" #include "originator.h" #include "types.h" #include "ring_buffer.h" @@ -759,7 +760,46 @@ void receive_bat_packet(struct ethhdr *ethhdr, 0, hna_buff_len, if_incoming); }
-int recv_bat_packet(struct sk_buff *skb, struct batman_if *batman_if) +int recv_ndp_packet(struct sk_buff *skb, struct batman_if *batman_if) +{ + struct ethhdr *ethhdr; + struct batman_packet_ndp *packet; + int ret; + uint8_t my_tq; + + /* drop packet if it has not necessary minimum size */ + if (unlikely(!pskb_may_pull(skb, sizeof(struct batman_packet_ndp)))) + return NET_RX_DROP; + + ethhdr = (struct ethhdr *)skb_mac_header(skb); + + /* packet with broadcast indication but unicast recipient */ + if (!is_broadcast_ether_addr(ethhdr->h_dest)) + return NET_RX_DROP; + + /* packet with broadcast sender address */ + if (is_broadcast_ether_addr(ethhdr->h_source)) + return NET_RX_DROP; + + /* keep skb linear */ + if (skb_linearize(skb) < 0) + return NET_RX_DROP; + + packet = (struct batman_packet_ndp*)(ethhdr + 1); + + my_tq = ndp_fetch_tq(packet, batman_if->net_dev->dev_addr); + + ret = ndp_update_neighbor(my_tq, ntohl(packet->seqno), + batman_if, ethhdr->h_source); + if (ret) + return NET_RX_DROP; + + kfree_skb(skb); + return NET_RX_SUCCESS; +} + +int recv_bat_packet(struct sk_buff *skb, + struct batman_if *batman_if) { struct bat_priv *bat_priv = netdev_priv(batman_if->soft_iface); struct ethhdr *ethhdr; diff --git a/routing.h b/routing.h index 81e27d5..a319714 100644 --- a/routing.h +++ b/routing.h @@ -39,6 +39,7 @@ int recv_unicast_packet(struct sk_buff *skb, struct batman_if *recv_if); int recv_ucast_frag_packet(struct sk_buff *skb, struct batman_if *recv_if); int recv_bcast_packet(struct sk_buff *skb, struct batman_if *recv_if); int recv_vis_packet(struct sk_buff *skb, struct batman_if *recv_if); +int recv_ndp_packet(struct sk_buff *skb, struct batman_if *recv_if); int recv_bat_packet(struct sk_buff *skb, struct batman_if *recv_if); struct neigh_node *find_router(struct bat_priv *bat_priv, struct orig_node *orig_node, struct batman_if *recv_if); diff --git a/types.h b/types.h index c5a26a7..d3efb53 100644 --- a/types.h +++ b/types.h @@ -51,6 +51,8 @@ struct batman_if { atomic_t ndp_seqno; struct sk_buff *ndp_skb; struct delayed_work ndp_wq; + struct list_head neigh_list; + spinlock_t neigh_list_lock; };
/** @@ -112,6 +114,9 @@ struct neigh_node { struct list_head list; uint8_t addr[ETH_ALEN]; uint8_t real_packet_count; + uint8_t rq; + uint32_t last_rq_seqno; + TYPE_OF_WORD rq_real_bits[NUM_WORDS]; uint8_t tq_recv[TQ_GLOBAL_WINDOW_SIZE]; uint8_t tq_index; uint8_t tq_avg;
The skb has to be linearized before setting any pointers to avoid etthdr/packet pointing to the wrong, outdated memory addresses.
Cheers, Linus
It will now be checked if a neighbor discovery packet from a new neighbor on a certain interface has been received. If so, structures in memory will be allocated for further seqno-tracking and RQ calculations, and TQ reception, which will be updated frequently from this commit on.
Signed-off-by: Linus Lüssing linus.luessing@ascom.ch --- hard-interface.c | 5 ++ ndp.c | 142 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ ndp.h | 5 ++ routing.c | 42 ++++++++++++++++- routing.h | 1 + types.h | 5 ++ 6 files changed, 199 insertions(+), 1 deletions(-)
diff --git a/hard-interface.c b/hard-interface.c index 887f794..820121a 100644 --- a/hard-interface.c +++ b/hard-interface.c @@ -608,6 +608,11 @@ int batman_skb_recv(struct sk_buff *skb, struct net_device *dev, * the supplied skb. if not, we have to free the skb. */
switch (batman_packet_ogm->packet_type) { + /* batman neighbor discovery protocol packet */ + case BAT_PACKET_NDP: + ret = recv_ndp_packet(skb, batman_if); + break; + /* batman originator packet */ case BAT_PACKET_OGM: ret = recv_bat_packet(skb, batman_if); diff --git a/ndp.c b/ndp.c index 94d1971..408dd70 100644 --- a/ndp.c +++ b/ndp.c @@ -1,6 +1,8 @@ #include "main.h" #include "send.h" #include "ndp.h" +#include "soft-interface.h" +#include "originator.h"
void start_ndp_timer(struct batman_if *batman_if) { @@ -21,6 +23,9 @@ static void ndp_send(struct work_struct *work) ndp_wq.work); struct bat_priv *bat_priv = netdev_priv(batman_if->soft_iface); struct batman_packet_ndp *ndp_packet; + struct neigh_entry *neigh_entry; + struct neigh_node *neigh_node = NULL; + int entries_len = 0; struct sk_buff *skb;
skb = skb_clone(batman_if->ndp_skb, GFP_ATOMIC); @@ -30,6 +35,22 @@ static void ndp_send(struct work_struct *work) memcpy(ndp_packet->orig, bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN);
+ neigh_entry = (struct neigh_entry*)(ndp_packet + 1); + spin_lock_bh(&batman_if->neigh_list_lock); + list_for_each_entry(neigh_node, &batman_if->neigh_list, list) { + if (entries_len + sizeof(struct neigh_entry) > + skb_tailroom(skb)) + break; + + memcpy(neigh_entry->addr, neigh_node->addr, ETH_ALEN); + neigh_entry->rq = neigh_node->rq; + ndp_packet->num_neighbors++; + neigh_entry++; + entries_len += sizeof(struct neigh_entry); + } + spin_unlock_bh(&batman_if->neigh_list_lock); + skb_put(skb, entries_len); + bat_dbg(DBG_BATMAN, bat_priv, "batman-adv:Sending ndp packet on interface %s, seqno %d\n", batman_if->net_dev, ntohl(ndp_packet->seqno)); @@ -64,6 +85,9 @@ int ndp_init(struct batman_if *batman_if) ndp_packet->packet_type = BAT_PACKET_NDP; ndp_packet->version = COMPAT_VERSION;
+ INIT_LIST_HEAD(&batman_if->neigh_list); + spin_lock_init(&batman_if->neigh_list_lock); + INIT_DELAYED_WORK(&batman_if->ndp_wq, ndp_send);
return 0; @@ -76,3 +100,121 @@ void ndp_free(struct batman_if *batman_if) stop_ndp_timer(batman_if); dev_kfree_skb(batman_if->ndp_skb); } + +/* extract my own tq to neighbor from the ndp packet */ +uint8_t ndp_fetch_tq(struct batman_packet_ndp *packet, + uint8_t *my_if_addr) +{ + struct neigh_entry *neigh_entry = (struct neigh_entry*)(packet + 1); + uint8_t tq = 0; + int i; + + for (i = 0; i < packet->num_neighbors; i++) { + if (compare_orig(my_if_addr, neigh_entry->addr)) { + tq = neigh_entry->rq; + break; + } + neigh_entry++; + } + return tq; +} + +static void ndp_update_neighbor_lq(uint8_t tq, uint32_t seqno, + struct neigh_node *neigh_node, + struct bat_priv *bat_priv) +{ + char is_duplicate = 0; + int32_t seq_diff; + int need_update = 0; + + seq_diff = seqno - neigh_node->last_rq_seqno; + + is_duplicate |= get_bit_status(neigh_node->rq_real_bits, + neigh_node->last_rq_seqno, + seqno); + + /* if the window moved, set the update flag. */ + need_update |= bit_get_packet(bat_priv, neigh_node->rq_real_bits, + seq_diff, 1); + // TODO: rename TQ_LOCAL_WINDOW_SIZE to RQ_LOCAL... + neigh_node->rq = + (bit_packet_count(neigh_node->rq_real_bits) * TQ_MAX_VALUE) + / TQ_LOCAL_WINDOW_SIZE; + + if (need_update) { + bat_dbg(DBG_BATMAN, bat_priv, "batman-adv: ndp: " + "updating last_seqno of neighbor %pM: old %d, new %d\n", + neigh_node->addr, neigh_node->last_rq_seqno, seqno); + // TODO: this is not really an average here, + // need to change the variable name later + neigh_node->tq_avg = tq; + neigh_node->last_valid = jiffies; + neigh_node->last_rq_seqno = seqno; + } + + if (is_duplicate) + bat_dbg(DBG_BATMAN, bat_priv, + "seqno %d of neighbor %pM was a duplicate!\n", + seqno, neigh_node->addr); + + bat_dbg(DBG_BATMAN, bat_priv, "batman-adv: ndp: " + "new rq/tq of neighbor %pM: rq %d, tq %d\n", + neigh_node->addr, neigh_node->rq, neigh_node->tq_avg); +} + +static struct neigh_node *ndp_create_neighbor(uint8_t my_tq, uint32_t seqno, + uint8_t *neigh_addr, + struct bat_priv *bat_priv) +{ + struct neigh_node *neigh_node; + + bat_dbg(DBG_BATMAN, bat_priv, + "batman-adv: ndp: Creating new neighbor %pM, " + "initial tq %d, initial seqno %d\n", + neigh_addr, my_tq, seqno); + + neigh_node = kzalloc(sizeof(struct neigh_node), GFP_ATOMIC); + if (!neigh_node) + return NULL; + + INIT_LIST_HEAD(&neigh_node->list); + memcpy(neigh_node->addr, neigh_addr, ETH_ALEN); + neigh_node->last_rq_seqno = seqno; + + return neigh_node; +} + +int ndp_update_neighbor(uint8_t my_tq, uint32_t seqno, + struct batman_if *batman_if, uint8_t *neigh_addr) +{ + struct bat_priv *bat_priv = netdev_priv(batman_if->soft_iface); + struct neigh_node *neigh_node = NULL, *tmp_neigh_node = NULL; + int ret = 1; + + spin_lock_bh(&batman_if->neigh_list_lock); + // old neighbor? + list_for_each_entry(tmp_neigh_node, &batman_if->neigh_list, list) { + if (!compare_orig(tmp_neigh_node->addr, neigh_addr)) + continue; + + neigh_node = tmp_neigh_node; + } + + // new neighbor? + if (!neigh_node) { + neigh_node = ndp_create_neighbor(my_tq, seqno, neigh_addr, + bat_priv); + if (!neigh_node) + goto ret; + + list_add_tail(&neigh_node->list, &batman_if->neigh_list); + } + + ndp_update_neighbor_lq(my_tq, seqno, neigh_node, bat_priv); + + ret = 0; + +ret: + spin_unlock_bh(&batman_if->neigh_list_lock); + return ret; +} diff --git a/ndp.h b/ndp.h index de85910..35146ce 100644 --- a/ndp.h +++ b/ndp.h @@ -4,3 +4,8 @@ void stop_ndp_timer(struct batman_if *batman_if);
int ndp_init(struct batman_if *batman_if); void ndp_free(struct batman_if *batman_if); + +uint8_t ndp_fetch_tq(struct batman_packet_ndp *packet, + uint8_t *my_if_addr); +int ndp_update_neighbor(uint8_t my_tq, uint32_t seqno, + struct batman_if *batman_if, uint8_t *neigh_addr); diff --git a/routing.c b/routing.c index 7ebb631..36f2e43 100644 --- a/routing.c +++ b/routing.c @@ -27,6 +27,7 @@ #include "hard-interface.h" #include "icmp_socket.h" #include "translation-table.h" +#include "ndp.h" #include "originator.h" #include "types.h" #include "ring_buffer.h" @@ -759,7 +760,46 @@ void receive_bat_packet(struct ethhdr *ethhdr, 0, hna_buff_len, if_incoming); }
-int recv_bat_packet(struct sk_buff *skb, struct batman_if *batman_if) +int recv_ndp_packet(struct sk_buff *skb, struct batman_if *batman_if) +{ + struct ethhdr *ethhdr; + struct batman_packet_ndp *packet; + int ret; + uint8_t my_tq; + + /* keep skb linear */ + if (skb_linearize(skb) < 0) + return NET_RX_DROP; + + /* drop packet if it has not necessary minimum size */ + if (unlikely(!pskb_may_pull(skb, sizeof(struct batman_packet_ndp)))) + return NET_RX_DROP; + + ethhdr = (struct ethhdr *)skb_mac_header(skb); + + /* packet with broadcast indication but unicast recipient */ + if (!is_broadcast_ether_addr(ethhdr->h_dest)) + return NET_RX_DROP; + + /* packet with broadcast sender address */ + if (is_broadcast_ether_addr(ethhdr->h_source)) + return NET_RX_DROP; + + packet = (struct batman_packet_ndp*)(ethhdr + 1); + + my_tq = ndp_fetch_tq(packet, batman_if->net_dev->dev_addr); + + ret = ndp_update_neighbor(my_tq, ntohl(packet->seqno), + batman_if, ethhdr->h_source); + if (ret) + return NET_RX_DROP; + + kfree_skb(skb); + return NET_RX_SUCCESS; +} + +int recv_bat_packet(struct sk_buff *skb, + struct batman_if *batman_if) { struct bat_priv *bat_priv = netdev_priv(batman_if->soft_iface); struct ethhdr *ethhdr; diff --git a/routing.h b/routing.h index 81e27d5..a319714 100644 --- a/routing.h +++ b/routing.h @@ -39,6 +39,7 @@ int recv_unicast_packet(struct sk_buff *skb, struct batman_if *recv_if); int recv_ucast_frag_packet(struct sk_buff *skb, struct batman_if *recv_if); int recv_bcast_packet(struct sk_buff *skb, struct batman_if *recv_if); int recv_vis_packet(struct sk_buff *skb, struct batman_if *recv_if); +int recv_ndp_packet(struct sk_buff *skb, struct batman_if *recv_if); int recv_bat_packet(struct sk_buff *skb, struct batman_if *recv_if); struct neigh_node *find_router(struct bat_priv *bat_priv, struct orig_node *orig_node, struct batman_if *recv_if); diff --git a/types.h b/types.h index c5a26a7..d3efb53 100644 --- a/types.h +++ b/types.h @@ -51,6 +51,8 @@ struct batman_if { atomic_t ndp_seqno; struct sk_buff *ndp_skb; struct delayed_work ndp_wq; + struct list_head neigh_list; + spinlock_t neigh_list_lock; };
/** @@ -112,6 +114,9 @@ struct neigh_node { struct list_head list; uint8_t addr[ETH_ALEN]; uint8_t real_packet_count; + uint8_t rq; + uint32_t last_rq_seqno; + TYPE_OF_WORD rq_real_bits[NUM_WORDS]; uint8_t tq_recv[TQ_GLOBAL_WINDOW_SIZE]; uint8_t tq_index; uint8_t tq_avg;
On Wednesday 15 December 2010 18:09:29 Linus Lüssing wrote:
It will now be checked if a neighbor discovery packet from a new neighbor on a certain interface has been received. If so, structures in memory will be allocated for further seqno-tracking and RQ calculations, and TQ reception, which will be updated frequently from this commit on.
Checkpatch found 8 errors - please make all your patches "checkpatch clean". I also noticed that the new ndp files ndp.c / ndp.h lack a proper licence header.
@@ -1,6 +1,8 @@ #include "main.h" #include "send.h" #include "ndp.h" +#include "soft-interface.h"
This include is not necessary as far as I can tell.
+int ndp_update_neighbor(uint8_t my_tq, uint32_t seqno,
struct batman_if *batman_if, uint8_t *neigh_addr)
+{
- struct bat_priv *bat_priv = netdev_priv(batman_if->soft_iface);
- struct neigh_node *neigh_node = NULL, *tmp_neigh_node = NULL;
- int ret = 1;
- spin_lock_bh(&batman_if->neigh_list_lock);
- // old neighbor?
- list_for_each_entry(tmp_neigh_node, &batman_if->neigh_list, list) {
if (!compare_orig(tmp_neigh_node->addr, neigh_addr))
continue;
neigh_node = tmp_neigh_node;
A "break" could be added here.
- }
- // new neighbor?
- if (!neigh_node) {
neigh_node = ndp_create_neighbor(my_tq, seqno, neigh_addr,
bat_priv);
if (!neigh_node)
goto ret;
list_add_tail(&neigh_node->list, &batman_if->neigh_list);
- }
- ndp_update_neighbor_lq(my_tq, seqno, neigh_node, bat_priv);
- ret = 0;
+ret:
- spin_unlock_bh(&batman_if->neigh_list_lock);
- return ret;
+}
Instead of holding a spinlock all the time to protect a single neigh_node pointer you should protect the NDP neighbor list with RCU locks and the pointers with refcounting.
- ret = ndp_update_neighbor(my_tq, ntohl(packet->seqno),
batman_if, ethhdr->h_source);
- if (ret)
return NET_RX_DROP;
- kfree_skb(skb);
- return NET_RX_SUCCESS;
Why not simply returning NET_RX_DROP ?
- struct list_head neigh_list;
- spinlock_t neigh_list_lock;
We already have a neigh_list and a neigh_list_lock. Either the old one gets removed or we should pick another name to avoid confusion.
- TYPE_OF_WORD rq_real_bits[NUM_WORDS];
rq_real_bits is not a very good name. I know, the current OGM code uses the same bad name but I believe we can safely break with the tradition here. How about something more descriptive like "rq_ndp_window" ?
Cheers, Marek
If no new packet has been received from a neighbour for a while, then delete it from memory.
Signed-off-by: Linus Lüssing linus.luessing@ascom.ch --- ndp.c | 25 +++++++++++++++++++++++++ ndp.h | 1 + originator.c | 2 ++ 3 files changed, 28 insertions(+), 0 deletions(-)
diff --git a/ndp.c b/ndp.c index 408dd70..80b30f1 100644 --- a/ndp.c +++ b/ndp.c @@ -184,6 +184,31 @@ static struct neigh_node *ndp_create_neighbor(uint8_t my_tq, uint32_t seqno, return neigh_node; }
+void ndp_purge_neighbors(void) +{ + struct neigh_node *neigh_node, *neigh_node_tmp; + struct batman_if *batman_if; + + rcu_read_lock(); + list_for_each_entry_rcu(batman_if, &if_list, list) { + if (batman_if->if_status != IF_ACTIVE) + continue; + + spin_lock_bh(&batman_if->neigh_list_lock); + list_for_each_entry_safe(neigh_node, neigh_node_tmp, + &batman_if->neigh_list, list) { + if (time_before(jiffies, + neigh_node->last_valid + PURGE_TIMEOUT * HZ)) + continue; + + list_del(&neigh_node->list); + kfree(neigh_node); + } + spin_unlock_bh(&batman_if->neigh_list_lock); + } + rcu_read_unlock(); +} + int ndp_update_neighbor(uint8_t my_tq, uint32_t seqno, struct batman_if *batman_if, uint8_t *neigh_addr) { diff --git a/ndp.h b/ndp.h index 35146ce..5679f36 100644 --- a/ndp.h +++ b/ndp.h @@ -7,5 +7,6 @@ void ndp_free(struct batman_if *batman_if);
uint8_t ndp_fetch_tq(struct batman_packet_ndp *packet, uint8_t *my_if_addr); +void ndp_purge_neighbors(void); int ndp_update_neighbor(uint8_t my_tq, uint32_t seqno, struct batman_if *batman_if, uint8_t *neigh_addr); diff --git a/originator.c b/originator.c index 89ec021..ad31bf7 100644 --- a/originator.c +++ b/originator.c @@ -22,6 +22,7 @@ /* increase the reference counter for this originator */
#include "main.h" +#include "ndp.h" #include "originator.h" #include "hash.h" #include "translation-table.h" @@ -307,6 +308,7 @@ static void purge_orig(struct work_struct *work) container_of(delayed_work, struct bat_priv, orig_work);
_purge_orig(bat_priv); + ndp_purge_neighbors(); start_purge_timer(bat_priv); }
On Tuesday 14 December 2010 10:58:12 Linus Lüssing wrote:
list_for_each_entry_safe(neigh_node, neigh_node_tmp,
&batman_if->neigh_list, list) {
if (time_before(jiffies,
neigh_node->last_valid + PURGE_TIMEOUT * HZ))
continue;
We should continue to use msecs_to_jiffies() for readability reasons.
Cheers, Marek
Lists all neighbours and their tq/rq values detected and measured by the Neighbor Discovery Protocol (NDP).
Signed-off-by: Linus Lüssing linus.luessing@ascom.ch --- bat_debugfs.c | 9 ++++++++ ndp.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ndp.h | 1 + 3 files changed, 70 insertions(+), 0 deletions(-)
diff --git a/bat_debugfs.c b/bat_debugfs.c index 0ae81d0..602aa15 100644 --- a/bat_debugfs.c +++ b/bat_debugfs.c @@ -25,6 +25,7 @@
#include "bat_debugfs.h" #include "translation-table.h" +#include "ndp.h" #include "originator.h" #include "hard-interface.h" #include "gateway_common.h" @@ -222,6 +223,12 @@ static void debug_log_cleanup(struct bat_priv *bat_priv) } #endif
+static int neighbors_open(struct inode *inode, struct file *file) +{ + struct net_device *net_dev = (struct net_device *)inode->i_private; + return single_open(file, ndp_seq_print_text, net_dev); +} + static int originators_open(struct inode *inode, struct file *file) { struct net_device *net_dev = (struct net_device *)inode->i_private; @@ -275,6 +282,7 @@ struct bat_debuginfo bat_debuginfo_##_name = { \ } \ };
+static BAT_DEBUGINFO(neighbors, S_IRUGO, neighbors_open); static BAT_DEBUGINFO(originators, S_IRUGO, originators_open); static BAT_DEBUGINFO(gateways, S_IRUGO, gateways_open); static BAT_DEBUGINFO(softif_neigh, S_IRUGO, softif_neigh_open); @@ -283,6 +291,7 @@ static BAT_DEBUGINFO(transtable_local, S_IRUGO, transtable_local_open); static BAT_DEBUGINFO(vis_data, S_IRUGO, vis_data_open);
static struct bat_debuginfo *mesh_debuginfos[] = { + &bat_debuginfo_neighbors, &bat_debuginfo_originators, &bat_debuginfo_gateways, &bat_debuginfo_softif_neigh, diff --git a/ndp.c b/ndp.c index 80b30f1..2acff6e 100644 --- a/ndp.c +++ b/ndp.c @@ -1,6 +1,7 @@ #include "main.h" #include "send.h" #include "ndp.h" +#include "hard-interface.h" #include "soft-interface.h" #include "originator.h"
@@ -243,3 +244,62 @@ ret: spin_unlock_bh(&batman_if->neigh_list_lock); return ret; } + +int ndp_seq_print_text(struct seq_file *seq, void *offset) +{ + struct neigh_node *neigh_node; + struct batman_if *batman_if; + int last_seen_secs; + int last_seen_msecs; + int batman_count = 0; + struct net_device *net_dev = (struct net_device *)seq->private; + struct bat_priv *bat_priv = netdev_priv(net_dev); + + if ((!bat_priv->primary_if) || + (bat_priv->primary_if->if_status != IF_ACTIVE)) { + if (!bat_priv->primary_if) + return seq_printf(seq, "BATMAN mesh %s disabled - " + "please specify interfaces to enable it\n", + net_dev->name); + + return seq_printf(seq, "BATMAN mesh %s " + "disabled - primary interface not active\n", + net_dev->name); + } + + seq_printf(seq, "[B.A.T.M.A.N. adv %s%s, MainIF/MAC: %s/%pM (%s)]\n", + SOURCE_VERSION, REVISION_VERSION_STR, + bat_priv->primary_if->net_dev->name, + bat_priv->primary_if->net_dev->dev_addr, net_dev->name); + seq_printf(seq, " %-15s %s (%s/%i) [%10s]\n", + "Neighbor", "last-seen", "#TQ,#RQ", TQ_MAX_VALUE, "IF"); + + rcu_read_lock(); + list_for_each_entry_rcu(batman_if, &if_list, list) { + if (batman_if->if_status != IF_ACTIVE) + continue; + + spin_lock_bh(&batman_if->neigh_list_lock); + list_for_each_entry(neigh_node, &batman_if->neigh_list, + list) { + last_seen_secs = jiffies_to_msecs(jiffies - + neigh_node->last_valid) / 1000; + last_seen_msecs = jiffies_to_msecs(jiffies - + neigh_node->last_valid) % 1000; + + seq_printf(seq, "%pM %4i.%03is (%3i,%3i) [%10s]\n", + neigh_node->addr, last_seen_secs, + last_seen_msecs, neigh_node->tq_avg, + neigh_node->rq, batman_if->net_dev->name); + + batman_count++; + } + spin_unlock_bh(&batman_if->neigh_list_lock); + } + rcu_read_unlock(); + + if ((batman_count == 0)) + seq_printf(seq, "No batman nodes in range ...\n"); + + return 0; +} diff --git a/ndp.h b/ndp.h index 5679f36..26be41f 100644 --- a/ndp.h +++ b/ndp.h @@ -10,3 +10,4 @@ uint8_t ndp_fetch_tq(struct batman_packet_ndp *packet, void ndp_purge_neighbors(void); int ndp_update_neighbor(uint8_t my_tq, uint32_t seqno, struct batman_if *batman_if, uint8_t *neigh_addr); +int ndp_seq_print_text(struct seq_file *seq, void *offset);
This allows us to easily add a sysfs parameter for an unsigned int later, which is not for a batman mesh interface (e.g. bat0), but for a common interface instead. It allows reading and writing an atomic_t in batman_if (instead of bat_priv compared to the mesh variant).
Signed-off-by: Linus Lüssing linus.luessing@ascom.ch --- bat_sysfs.c | 27 +++++++++++++++++++++++++++ 1 files changed, 27 insertions(+), 0 deletions(-)
diff --git a/bat_sysfs.c b/bat_sysfs.c index cd7bb51..98c10a3 100644 --- a/bat_sysfs.c +++ b/bat_sysfs.c @@ -94,6 +94,33 @@ ssize_t show_##_name(struct kobject *kobj, struct attribute *attr, \ static BAT_ATTR(_name, _mode, show_##_name, store_##_name)
+#define BAT_ATTR_IF_STORE_UINT(_name, _min, _max, _post_func) \ +ssize_t store_##_name(struct kobject *kobj, struct attribute *attr, \ + char *buff, size_t count) \ +{ \ + struct net_device *net_dev = kobj_to_netdev(kobj); \ + struct batman_if *batman_if = get_batman_if_by_netdev(net_dev); \ + return __store_uint_attr(buff, count, _min, _max, _post_func, \ + attr, &batman_if->_name, net_dev); \ +} + +#define BAT_ATTR_IF_SHOW_UINT(_name) \ +ssize_t show_##_name(struct kobject *kobj, struct attribute *attr, \ + char *buff) \ +{ \ + struct net_device *net_dev = kobj_to_netdev(kobj); \ + struct batman_if *batman_if = get_batman_if_by_netdev(net_dev); \ + return sprintf(buff, "%i\n", atomic_read(&batman_if->_name)); \ +} \ + +/* Use this, if you are going to set [name] in batman_if to unsigned integer + * values only */ +#define BAT_ATTR_IF_UINT(_name, _mode, _min, _max, _post_func) \ + static BAT_ATTR_IF_STORE_UINT(_name, _min, _max, _post_func) \ + static BAT_ATTR_IF_SHOW_UINT(_name) \ + static BAT_ATTR(_name, _mode, show_##_name, store_##_name) + + static int store_bool_attr(char *buff, size_t count, struct net_device *net_dev, char *attr_name, atomic_t *attr)
On Tuesday 14 December 2010 10:58:14 Linus Lüssing wrote:
+#define BAT_ATTR_IF_STORE_UINT(_name, _min, _max, _post_func) \ +ssize_t store_##_name(struct kobject *kobj, struct attribute *attr, \
char *buff, size_t count) \
+{ \
struct net_device *net_dev = kobj_to_netdev(kobj); \
struct batman_if *batman_if = get_batman_if_by_netdev(net_dev); \
return __store_uint_attr(buff, count, _min, _max, _post_func, \
attr, &batman_if->_name, net_dev); \
+}
+#define BAT_ATTR_IF_SHOW_UINT(_name) \ +ssize_t show_##_name(struct kobject *kobj, struct attribute *attr, \
char *buff) \
+{ \
struct net_device *net_dev = kobj_to_netdev(kobj); \
struct batman_if *batman_if = get_batman_if_by_netdev(net_dev); \
return sprintf(buff, "%i\n", atomic_read(&batman_if->_name)); \
+}
get_batman_if_by_netdev() increases the batman_if refcount which is never decreased. Check the other get_batman_if_by_netdev() calls in the same file to get an idea how to handle this,
Cheers, Marek
This parameter can be set individually on each interface and allows the configuration of the ndp interval for the link quality measurements during runtime. Usually it is desirable to set it to a higher (= slower) value on interfaces which have a more static characteristic (e.g. wired interfaces) or very dense neighbourhoods to reduce overhead.
Signed-off-by: Linus Lüssing linus.luessing@ascom.ch --- bat_sysfs.c | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/bat_sysfs.c b/bat_sysfs.c index 98c10a3..1dcd986 100644 --- a/bat_sysfs.c +++ b/bat_sysfs.c @@ -572,10 +572,12 @@ static ssize_t show_iface_status(struct kobject *kobj, struct attribute *attr, static BAT_ATTR(mesh_iface, S_IRUGO | S_IWUSR, show_mesh_iface, store_mesh_iface); static BAT_ATTR(iface_status, S_IRUGO, show_iface_status, NULL); +BAT_ATTR_IF_UINT(ndp_interval, S_IRUGO | S_IWUSR, 2 * JITTER, INT_MAX, NULL);
static struct bat_attribute *batman_attrs[] = { &bat_attr_mesh_iface, &bat_attr_iface_status, + &bat_attr_ndp_interval, NULL, };
With this commit not the local transmit quality values determined by the OGMs themselves are applied on received OGMs, but the local transmit quality detemined by NDP instead. Usually the link quality measurements of NDP are more up-to-date than the one of the OGMs, as NDP is using a more frequent interval because NDP's packets are not being flooded through the whole mesh.
Signed-off-by: Linus Lüssing linus.luessing@ascom.ch --- routing.c | 58 +++++++++++++++++++++++++++------------------------------- 1 files changed, 27 insertions(+), 31 deletions(-)
diff --git a/routing.c b/routing.c index dbea97f..16e1377 100644 --- a/routing.c +++ b/routing.c @@ -136,7 +136,7 @@ static int is_bidirectional_neigh(struct orig_node *orig_node, { struct bat_priv *bat_priv = netdev_priv(if_incoming->soft_iface); struct neigh_node *neigh_node = NULL, *tmp_neigh_node = NULL; - unsigned char total_count; + uint8_t local_tq = 0, local_rq = 0;
if (orig_node == orig_neigh_node) { list_for_each_entry(tmp_neigh_node, @@ -180,25 +180,22 @@ static int is_bidirectional_neigh(struct orig_node *orig_node, return 0; }
- orig_node->last_valid = jiffies; + /* note, bottom halves are already deactivated outside in + * recv_bat_packet() */ + spin_lock(&if_incoming->neigh_list_lock); + list_for_each_entry(neigh_node, &if_incoming->neigh_list, list) { + if (!compare_orig(neigh_node->addr, orig_neigh_node->orig)) + continue;
- /* pay attention to not get a value bigger than 100 % */ - total_count = (orig_neigh_node->bcast_own_sum[if_incoming->if_num] > - neigh_node->real_packet_count ? - neigh_node->real_packet_count : - orig_neigh_node->bcast_own_sum[if_incoming->if_num]); + orig_node->last_valid = jiffies; + local_tq = neigh_node->tq_avg; + local_rq = neigh_node->rq; + break; + } + spin_unlock(&if_incoming->neigh_list_lock);
- /* 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_node->real_packet_count < TQ_LOCAL_BIDRECT_RECV_MINIMUM)) - orig_neigh_node->tq_own = 0; - else - /* neigh_node->real_packet_count is never zero as we - * only purge old information when getting new - * information */ - orig_neigh_node->tq_own = (TQ_MAX_VALUE * total_count) / - neigh_node->real_packet_count; + if (local_tq == 0) + return 0;
/* * 1 - ((1-x) ** 3), normalized to TQ_MAX_VALUE this does @@ -209,25 +206,23 @@ static int is_bidirectional_neigh(struct orig_node *orig_node, orig_neigh_node->tq_asym_penalty = TQ_MAX_VALUE - (TQ_MAX_VALUE * - (TQ_LOCAL_WINDOW_SIZE - neigh_node->real_packet_count) * - (TQ_LOCAL_WINDOW_SIZE - neigh_node->real_packet_count) * - (TQ_LOCAL_WINDOW_SIZE - neigh_node->real_packet_count)) / - (TQ_LOCAL_WINDOW_SIZE * - TQ_LOCAL_WINDOW_SIZE * - TQ_LOCAL_WINDOW_SIZE); + (TQ_MAX_VALUE - local_rq) * + (TQ_MAX_VALUE - local_rq) * + (TQ_MAX_VALUE - local_rq)) / + (TQ_MAX_VALUE * + TQ_MAX_VALUE * + TQ_MAX_VALUE);
batman_packet_ogm->tq = ((batman_packet_ogm->tq * - orig_neigh_node->tq_own * + local_tq * orig_neigh_node->tq_asym_penalty) / - (TQ_MAX_VALUE * TQ_MAX_VALUE)); + (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_node->real_packet_count, orig_neigh_node->tq_own, + "orig = %-15pM neigh = %-15pM => local tq = %3i, " + "local rq: %3i, asym_penalty: %3i, total tq: %3i\n", + orig_node->orig, orig_neigh_node->orig, local_tq, local_rq, orig_neigh_node->tq_asym_penalty, batman_packet_ogm->tq);
/* if link has the minimum required transmission quality @@ -828,6 +823,7 @@ int recv_bat_packet(struct sk_buff *skb,
ethhdr = (struct ethhdr *)skb_mac_header(skb);
+ /* note, is_bidirectional_neigh() relies on deactivated bottom halves */ spin_lock_bh(&bat_priv->orig_hash_lock); receive_aggr_bat_packet(ethhdr, skb->data,
b.a.t.m.a.n@lists.open-mesh.org