Hi everyone,
I've been working on those patches for seperating the link quality measurements from the OGMs and putting that into a seperate protocol with its own packets a little more. This Neighbour Discovery Protocol will allow us to have faster intervals for NDP or different intervals on different interface types, as well as creating individual convergence speed optimizations for the link quality measurements (NDP) or the path quality propagation (OGM) later.
This is a first draft and basically what we've been discussing on the WBMv3 in Italy and which was documented a little in our wiki.
I haven't added my Signed-off-by yet as I'd like to get some feedback first, especially for the last patch. Here I'm not sure if that's sufficient and ok to do it like that (the limit check seemed redundant to me) or if I'm missing something. Especially I'm not really sure what tq_own was representing as the link quality seemed to be substracted with the real_packet_count.
After the overall way of doing it is acknowledged, I'd start cleaning up the OGM handling and removing variables and redundant LQ measurements.
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. --- 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) &&
This patch adds a function for fetching and jittering an ndp interval from batman-if structure. Needed later for timing the neighbor discovery packets. --- 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. --- 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; };
/**
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. --- hard-interface.c | 5 ++++- ndp.c | 37 ++++++++++++++++++++++++++++++++++++- types.h | 5 +++++ 3 files changed, 45 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..afdf249 100644 --- a/ndp.c +++ b/ndp.c @@ -20,10 +20,24 @@ 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 batman_packet_ndp*) + batman_if->ndp_packet_buff; + int packet_len = sizeof(struct batman_packet_ndp); + struct sk_buff *skb; + + ndp_packet->seqno = atomic_read(&batman_if->ndp_seqno);
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)); + + skb = dev_alloc_skb(packet_len + sizeof(struct ethhdr)); + skb_reserve(skb, sizeof(struct ethhdr)); + + memcpy(skb_put(skb, packet_len), batman_if->ndp_packet_buff, + packet_len); + + send_skb_packet(skb, batman_if, broadcast_addr);
atomic_inc(&batman_if->ndp_seqno); start_ndp_timer(batman_if); @@ -31,14 +45,35 @@ 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_packet_buff = + kmalloc(ETH_DATA_LEN, GFP_ATOMIC); + if (!batman_if->ndp_packet_buff) { + printk(KERN_ERR "batman-adv: Can't add " + "local interface packet (%s): out of memory\n", + batman_if->net_dev->name); + goto err; + } + memset(batman_if->ndp_packet_buff, 0, batman_if->packet_len); + ndp_packet = (struct batman_packet_ndp*) + batman_if->ndp_packet_buff; + + 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); + kfree(batman_if->ndp_packet_buff); } diff --git a/types.h b/types.h index e8dfdf6..3ea8f2a 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; + unsigned char *ndp_packet_buff; atomic_t ndp_interval; atomic_t ndp_seqno; 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 07 December 2010 15:39:32 Linus Lüssing wrote:
- memcpy(skb_put(skb, packet_len), batman_if->ndp_packet_buff,
packet_len);
- send_skb_packet(skb, batman_if, broadcast_addr);
--- 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;
- unsigned char *ndp_packet_buff;
Good way to never get included in the linux kernel by David S. Miller.
Best regards, Sven
On Tue, Dec 07, 2010 at 03:51:21PM +0100, Sven Eckelmann wrote:
On Tuesday 07 December 2010 15:39:32 Linus Lüssing wrote:
- memcpy(skb_put(skb, packet_len), batman_if->ndp_packet_buff,
packet_len);
- send_skb_packet(skb, batman_if, broadcast_addr);
--- 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;
- unsigned char *ndp_packet_buff;
Good way to never get included in the linux kernel by David S. Miller.
Best regards, Sven
Argh, damn it, you noticed my secret plan and attempt to sabotage batman-adv's inclussion into the linux kernel...
Well, anyway, thanks for having a glance at it, I'll send a fixup soon :).
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. --- hard-interface.c | 5 ++ ndp.c | 148 +++++++++++++++++++++++++++++++++++++++++++++++++++++- ndp.h | 5 ++ routing.c | 38 +++++++++++++- routing.h | 1 + types.h | 5 ++ 6 files changed, 200 insertions(+), 2 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 afdf249..3442e17 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) { @@ -23,9 +25,29 @@ static void ndp_send(struct work_struct *work) struct batman_packet_ndp *ndp_packet = (struct batman_packet_ndp*) batman_if->ndp_packet_buff; int packet_len = sizeof(struct batman_packet_ndp); + struct neigh_entry *neigh_entry = (struct neigh_entry*) + (ndp_packet + 1); + struct neigh_node *neigh_node = NULL; struct sk_buff *skb;
- ndp_packet->seqno = atomic_read(&batman_if->ndp_seqno); + ndp_packet->num_neighbors = 0; + + spin_lock_bh(&batman_if->neigh_list_lock); + list_for_each_entry(neigh_node, &batman_if->neigh_list, list) { + if (packet_len + sizeof(struct neigh_entry) > ETH_DATA_LEN) + break; + + memcpy(neigh_entry->addr, neigh_node->addr, ETH_ALEN); + neigh_entry->rq = neigh_node->rq; + ndp_packet->num_neighbors++; + neigh_entry++; + packet_len += sizeof(struct neigh_entry); + } + spin_unlock_bh(&batman_if->neigh_list_lock); + + ndp_packet->seqno = htonl(atomic_read(&batman_if->ndp_seqno)); + 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", @@ -65,6 +87,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; @@ -77,3 +102,124 @@ void ndp_free(struct batman_if *batman_if) stop_ndp_timer(batman_if); kfree(batman_if->ndp_packet_buff); } + +/* 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); + 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; + } + + 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->tq_avg = my_tq; + neigh_node->last_valid = jiffies; + + // TODO: need to initialise rq-window with seqno here + + 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)) { + neigh_node = tmp_neigh_node; + ndp_update_neighbor_lq(my_tq, seqno, neigh_node, + bat_priv); + break; + } + } + + // 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); + } + + 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..1972bb8 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,42 @@ 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; + + 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 3ea8f2a..d8494b3 100644 --- a/types.h +++ b/types.h @@ -51,6 +51,8 @@ struct batman_if { atomic_t ndp_interval; atomic_t ndp_seqno; 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;
If no new packet has been received from a neighbour for a while, then delete it from memory. --- 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 3442e17..c1cd016 100644 --- a/ndp.c +++ b/ndp.c @@ -189,6 +189,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); }
Lists all neighbours and their tq/rq values detected and measured by the Neighbor Discovery Protocol (NDP). --- 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 c1cd016..22f17c6 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"
@@ -248,3 +249,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). --- 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)
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. --- 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. --- routing.c | 53 ++++++++++++++++++++++------------------------------- 1 files changed, 22 insertions(+), 31 deletions(-)
diff --git a/routing.c b/routing.c index 1972bb8..8830129 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;
if (orig_node == orig_neigh_node) { list_for_each_entry(tmp_neigh_node, @@ -180,25 +180,19 @@ static int is_bidirectional_neigh(struct orig_node *orig_node, return 0; }
- orig_node->last_valid = jiffies; + spin_lock_bh(&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; + break; + } + spin_unlock_bh(&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 +203,22 @@ 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_tq) * + (TQ_MAX_VALUE - local_tq) * + (TQ_MAX_VALUE - local_tq)) / + (TQ_MAX_VALUE * + TQ_MAX_VALUE * + TQ_MAX_VALUE);
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)); + 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 => real recv = %2i, " + "local tq: %3i, asym_penalty: %3i, total tq: %3i\n", + orig_node->orig, orig_neigh_node->orig, local_tq, orig_neigh_node->tq_asym_penalty, batman_packet_ogm->tq);
/* if link has the minimum required transmission quality
Fixing a mixup with the link quality used for the asymmetric hop penalty. This should be the local_rq, not local_tq.
Cheers, Linus
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. --- routing.c | 55 ++++++++++++++++++++++++------------------------------- 1 files changed, 24 insertions(+), 31 deletions(-)
diff --git a/routing.c b/routing.c index 1972bb8..d33680d 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,20 @@ static int is_bidirectional_neigh(struct orig_node *orig_node, return 0; }
- orig_node->last_valid = jiffies; + spin_lock_bh(&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_bh(&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 +204,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
Hi there,
The following points have been changed during the last series: - Use SKBs instead of own packet buffer (batman-adv: Send neighbor discovery packets) - Also accept first packet for packet counting already (batman-adv: Creating neighbor structures, updating LQs) - Fixing the asymmetric penalty handling (no more changes since previous PATCHv2 10/10 though) (batman-adv: Use local tq values determined by NDP on OGMs)
I've also added my Signed-off-by now, as it seems to work fine here for me and the integration now makes more sense to me after PATCHv2 10/10 :). So for me, it'd be ok to add it upstream. Does it make sense to do the OGM cleanup with these patches already or would it be fine to do them after NDP got upstream? In the first case the maintenance/rebasing of the cleanup patches might be more effort until NDP gets upstream. In the latter case, there'd be no need to hurry for doing the cleanup then, reducing the chances of breaking something :). Or would you prefer to have the full batch including the cleanup for the OGMs already?
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) &&
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; };
/**
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;
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 | 141 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ ndp.h | 5 ++ routing.c | 38 ++++++++++++++- routing.h | 1 + types.h | 5 ++ 6 files changed, 194 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..96db80c 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,120 @@ 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); + 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; + } + + 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); + + 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..1972bb8 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,42 @@ 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; + + 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;
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 96db80c..2d30d30 100644 --- a/ndp.c +++ b/ndp.c @@ -183,6 +183,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); }
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 2d30d30..81f273a 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"
@@ -242,3 +243,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)
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 | 55 ++++++++++++++++++++++++------------------------------- 1 files changed, 24 insertions(+), 31 deletions(-)
diff --git a/routing.c b/routing.c index 1972bb8..d33680d 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,20 @@ static int is_bidirectional_neigh(struct orig_node *orig_node, return 0; }
- orig_node->last_valid = jiffies; + spin_lock_bh(&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_bh(&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 +204,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
b.a.t.m.a.n@lists.open-mesh.org