From: Sven Eckelmann sven.eckelmann@gmx.de
It is safe to call kfree(NULL) which makes this extra check unneeded. It was found using checkpatch.pl from linux-2.6
Signed-off-by: Sven Eckelmann sven.eckelmann@gmx.de Acked-by: Simon Wunderlich siwu@hrz.tu-chemnitz.de Signed-off-by: Andrew Lunn andrew@lunn.ch --- drivers/staging/batman-adv/hard-interface.c | 3 +-- 1 files changed, 1 insertions(+), 2 deletions(-)
diff --git a/drivers/staging/batman-adv/hard-interface.c b/drivers/staging/batman-adv/hard-interface.c index e9cb977..28d02f6 100644 --- a/drivers/staging/batman-adv/hard-interface.c +++ b/drivers/staging/batman-adv/hard-interface.c @@ -399,8 +399,7 @@ int hardif_add_interface(char *dev, int if_num) return 1;
out: - if (batman_if->packet_buff) - kfree(batman_if->packet_buff); + kfree(batman_if->packet_buff); kfree(batman_if); kfree(dev); return -1;
From: Simon Wunderlich siwu@hrz.tu-chemnitz.de
state in the README that we also (compile) support 2.6.32
Signed-off-by: Simon Wunderlich siwu@hrz.tu-chemnitz.de Signed-off-by: Andrew Lunn andrew@lunn.ch --- drivers/staging/batman-adv/README | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/staging/batman-adv/README b/drivers/staging/batman-adv/README index a6a419d..2bedcbe 100644 --- a/drivers/staging/batman-adv/README +++ b/drivers/staging/batman-adv/README @@ -1,4 +1,4 @@ -[state: 13-11-2009] +[state: 13-12-2009]
BATMAN-ADV ---------- @@ -15,7 +15,7 @@ above B.A.T.M.A.N. Advanced, prominent examples are: IPv4, IPv6, DHCP, IPX. This is batman-advanced implemented as Linux kernel driver. It does not depend on any network (other) driver, and can be used on wifi as well as ethernet, vpn, etc ... (anything with ethernet-style layer 2). -It compiles against and should work with Linux 2.6.20 - 2.6.31. Supporting older +It compiles against and should work with Linux 2.6.20 - 2.6.32. Supporting older versions is not planned, but it's probably easy to backport it. If you work on a backport, feel free to contact us. :-)
Ameya Palande requested we replace printk(KERN_DEBUG "") by pr_debug() I decided it was better to use our debug macro.
Signed-off-by: Andrew Lunn andrew@lunn.ch Acked-by: Marek Lindner lindner_marek@yahoo.de --- drivers/staging/batman-adv/TODO | 6 ------ drivers/staging/batman-adv/device.c | 6 +++--- 2 files changed, 3 insertions(+), 9 deletions(-)
diff --git a/drivers/staging/batman-adv/TODO b/drivers/staging/batman-adv/TODO index ea6dcf9..8c2b89e 100644 --- a/drivers/staging/batman-adv/TODO +++ b/drivers/staging/batman-adv/TODO @@ -29,12 +29,6 @@ -> PRIMARY)
=> logging -* the log level LOG_TYPE_CRIT, LOG_TYPE_WARN & LOG_TYPE_NOTICE will be -* unified to use printk -* LOG_TYPE_BATMAN & LOG_TYPE_ROUTES will also use printk but only after the -* internal debug level has been raised -* the internal debug level can be modified using a module parameter (debug) -* or at run time via /sys/module/batman-adv/parameters/debug * make use of printk %pM support instead of converting mac addresses * manually
diff --git a/drivers/staging/batman-adv/device.c b/drivers/staging/batman-adv/device.c index 12f2de9..92cf8d5 100644 --- a/drivers/staging/batman-adv/device.c +++ b/drivers/staging/batman-adv/device.c @@ -207,7 +207,7 @@ ssize_t bat_device_write(struct file *file, const char __user *buff, struct batman_if *batman_if;
if (len < sizeof(struct icmp_packet)) { - printk(KERN_DEBUG "batman-adv:Error - can't send packet from char device: invalid packet size\n"); + bat_dbg(DBG_BATMAN, "batman-adv:Error - can't send packet from char device: invalid packet size\n"); return -EINVAL; }
@@ -218,12 +218,12 @@ ssize_t bat_device_write(struct file *file, const char __user *buff, return -EFAULT;
if (icmp_packet.packet_type != BAT_ICMP) { - printk(KERN_DEBUG "batman-adv:Error - can't send packet from char device: got bogus packet type (expected: BAT_ICMP)\n"); + bat_dbg(DBG_BATMAN, "batman-adv:Error - can't send packet from char device: got bogus packet type (expected: BAT_ICMP)\n"); return -EINVAL; }
if (icmp_packet.msg_type != ECHO_REQUEST) { - printk(KERN_DEBUG "batman-adv:Error - can't send packet from char device: got bogus message type (expected: ECHO_REQUEST)\n"); + bat_dbg(DBG_BATMAN, "batman-adv:Error - can't send packet from char device: got bogus message type (expected: ECHO_REQUEST)\n"); return -EINVAL; }
From: Simon Wunderlich siwu@hrz.tu-chemnitz.de
instead of dynamically registering hash iterators, calling functions are changed to register the iterator objects statically. The two advantages are:
* no memory leaks when aborting from hash_iterate() * no calls to kmalloc/kfree, therefore a little faster/safer
Tested with 9 QEMU instances, no obvious regression found.
Signed-off-by: Simon Wunderlich siwu@hrz.tu-chemnitz.de Signed-off-by: Andrew Lunn andrew@lunn.ch --- drivers/staging/batman-adv/hard-interface.c | 6 ++-- drivers/staging/batman-adv/hash.c | 23 ++++++----------- drivers/staging/batman-adv/hash.h | 5 +++ drivers/staging/batman-adv/originator.c | 8 +++--- drivers/staging/batman-adv/proc.c | 12 ++++---- drivers/staging/batman-adv/routing.c | 6 ++-- drivers/staging/batman-adv/translation-table.c | 24 ++++++++-------- drivers/staging/batman-adv/vis.c | 33 +++++++++++------------ 8 files changed, 57 insertions(+), 60 deletions(-)
diff --git a/drivers/staging/batman-adv/hard-interface.c b/drivers/staging/batman-adv/hard-interface.c index 28d02f6..7c88592 100644 --- a/drivers/staging/batman-adv/hard-interface.c +++ b/drivers/staging/batman-adv/hard-interface.c @@ -318,7 +318,7 @@ int hardif_add_interface(char *dev, int if_num) struct batman_if *batman_if; struct batman_packet *batman_packet; struct orig_node *orig_node; - struct hash_it_t *hashit = NULL; + HASHIT(hashit);
batman_if = kmalloc(sizeof(struct batman_if), GFP_KERNEL);
@@ -377,8 +377,8 @@ int hardif_add_interface(char *dev, int if_num) * if_num */ spin_lock(&orig_hash_lock);
- while (NULL != (hashit = hash_iterate(orig_hash, hashit))) { - orig_node = hashit->bucket->data; + while (hash_iterate(orig_hash, &hashit)) { + orig_node = hashit.bucket->data; if (resize_orig(orig_node, if_num) == -1) { spin_unlock(&orig_hash_lock); goto out; diff --git a/drivers/staging/batman-adv/hash.c b/drivers/staging/batman-adv/hash.c index 61cb4a2..5a2018d 100644 --- a/drivers/staging/batman-adv/hash.c +++ b/drivers/staging/batman-adv/hash.c @@ -64,24 +64,18 @@ void hash_destroy(struct hashtable_t *hash) kfree(hash); }
-/* iterate though the hash. first element is selected with iter_in NULL. use - * the returned iterator to access the elements until hash_it_t returns NULL. */ +/* iterate though the hash. First element is selected if an iterator + * initialized with HASHIT() is supplied as iter. Use the returned + * (or supplied) iterator to access the elements until hash_iterate returns + * NULL. */ + struct hash_it_t *hash_iterate(struct hashtable_t *hash, - struct hash_it_t *iter_in) + struct hash_it_t *iter) { - struct hash_it_t *iter; - if (!hash) return NULL; - - if (iter_in == NULL) { - iter = kmalloc(sizeof(struct hash_it_t), GFP_ATOMIC); - iter->index = -1; - iter->bucket = NULL; - iter->prev_bucket = NULL; - } else { - iter = iter_in; - } + if (!iter) + return NULL;
/* sanity checks first (if our bucket got deleted in the last * iteration): */ @@ -139,7 +133,6 @@ struct hash_it_t *hash_iterate(struct hashtable_t *hash, }
/* nothing to iterate over anymore */ - kfree(iter); return NULL; }
diff --git a/drivers/staging/batman-adv/hash.h b/drivers/staging/batman-adv/hash.h index bb60f08..a70d6d6 100644 --- a/drivers/staging/batman-adv/hash.h +++ b/drivers/staging/batman-adv/hash.h @@ -21,6 +21,11 @@
#ifndef _BATMAN_HASH_H #define _BATMAN_HASH_H +#define HASHIT(name) struct hash_it_t name = { \ + .index = -1, .bucket = NULL, \ + .prev_bucket = NULL, \ + .first_bucket = NULL } +
typedef int (*hashdata_compare_cb)(void *, void *); typedef int (*hashdata_choose_cb)(void *, int); diff --git a/drivers/staging/batman-adv/originator.c b/drivers/staging/batman-adv/originator.c index 80106f7..9ac8da3 100644 --- a/drivers/staging/batman-adv/originator.c +++ b/drivers/staging/batman-adv/originator.c @@ -221,16 +221,16 @@ static bool purge_orig_node(struct orig_node *orig_node)
void purge_orig(struct work_struct *work) { - struct hash_it_t *hashit = NULL; + HASHIT(hashit); struct orig_node *orig_node;
spin_lock(&orig_hash_lock);
/* for all origins... */ - while (NULL != (hashit = hash_iterate(orig_hash, hashit))) { - orig_node = hashit->bucket->data; + while (hash_iterate(orig_hash, &hashit)) { + orig_node = hashit.bucket->data; if (purge_orig_node(orig_node)) { - hash_remove_bucket(orig_hash, hashit); + hash_remove_bucket(orig_hash, &hashit); free_orig_node(orig_node); } } diff --git a/drivers/staging/batman-adv/proc.c b/drivers/staging/batman-adv/proc.c index f476d9c..f693a0e 100644 --- a/drivers/staging/batman-adv/proc.c +++ b/drivers/staging/batman-adv/proc.c @@ -186,7 +186,7 @@ static int proc_orig_interval_open(struct inode *inode, struct file *file)
static int proc_originators_read(struct seq_file *seq, void *offset) { - struct hash_it_t *hashit = NULL; + HASHIT(hashit); struct orig_node *orig_node; struct neigh_node *neigh_node; int batman_count = 0; @@ -215,9 +215,9 @@ static int proc_originators_read(struct seq_file *seq, void *offset) rcu_read_unlock(); spin_lock(&orig_hash_lock);
- while (NULL != (hashit = hash_iterate(orig_hash, hashit))) { + while (hash_iterate(orig_hash, &hashit)) {
- orig_node = hashit->bucket->data; + orig_node = hashit.bucket->data;
if (!orig_node->router) continue; @@ -413,7 +413,7 @@ static void proc_vis_read_entry(struct seq_file *seq,
static int proc_vis_read(struct seq_file *seq, void *offset) { - struct hash_it_t *hashit = NULL; + HASHIT(hashit); struct vis_info *info; struct vis_info_entry *entries; struct vis_if_list *if_entries = NULL; @@ -440,8 +440,8 @@ static int proc_vis_read(struct seq_file *seq, void *offset) seq_printf(seq, "digraph {\n");
spin_lock(&vis_hash_lock); - while (NULL != (hashit = hash_iterate(vis_hash, hashit))) { - info = hashit->bucket->data; + while (hash_iterate(vis_hash, &hashit)) { + info = hashit.bucket->data; entries = (struct vis_info_entry *) ((char *)info + sizeof(struct vis_info));
diff --git a/drivers/staging/batman-adv/routing.c b/drivers/staging/batman-adv/routing.c index 87d7552..89d7faa 100644 --- a/drivers/staging/batman-adv/routing.c +++ b/drivers/staging/batman-adv/routing.c @@ -40,14 +40,14 @@ static atomic_t data_ready_cond; atomic_t exit_cond; void slide_own_bcast_window(struct batman_if *batman_if) { - struct hash_it_t *hashit = NULL; + HASHIT(hashit); struct orig_node *orig_node; TYPE_OF_WORD *word;
spin_lock(&orig_hash_lock);
- while (NULL != (hashit = hash_iterate(orig_hash, hashit))) { - orig_node = hashit->bucket->data; + while (hash_iterate(orig_hash, &hashit)) { + orig_node = hashit.bucket->data; word = &(orig_node->bcast_own[batman_if->if_num * NUM_WORDS]);
bit_get_packet(word, 1, 0); diff --git a/drivers/staging/batman-adv/translation-table.c b/drivers/staging/batman-adv/translation-table.c index c7122da..088715b 100644 --- a/drivers/staging/batman-adv/translation-table.c +++ b/drivers/staging/batman-adv/translation-table.c @@ -134,18 +134,18 @@ void hna_local_add(uint8_t *addr) int hna_local_fill_buffer(unsigned char *buff, int buff_len) { struct hna_local_entry *hna_local_entry; - struct hash_it_t *hashit = NULL; + HASHIT(hashit); int i = 0; unsigned long flags;
spin_lock_irqsave(&hna_local_hash_lock, flags);
- while (NULL != (hashit = hash_iterate(hna_local_hash, hashit))) { + while (hash_iterate(hna_local_hash, &hashit)) {
if (buff_len < (i + 1) * ETH_ALEN) break;
- hna_local_entry = hashit->bucket->data; + hna_local_entry = hashit.bucket->data; memcpy(buff + (i * ETH_ALEN), hna_local_entry->addr, ETH_ALEN);
i++; @@ -163,18 +163,18 @@ int hna_local_fill_buffer(unsigned char *buff, int buff_len) int hna_local_fill_buffer_text(unsigned char *buff, int buff_len) { struct hna_local_entry *hna_local_entry; - struct hash_it_t *hashit = NULL; + HASHIT(hashit); int bytes_written = 0; unsigned long flags;
spin_lock_irqsave(&hna_local_hash_lock, flags);
- while (NULL != (hashit = hash_iterate(hna_local_hash, hashit))) { + while (hash_iterate(hna_local_hash, &hashit)) {
if (buff_len < bytes_written + ETH_STR_LEN + 4) break;
- hna_local_entry = hashit->bucket->data; + hna_local_entry = hashit.bucket->data;
bytes_written += snprintf(buff + bytes_written, ETH_STR_LEN + 4, " * %02x:%02x:%02x:%02x:%02x:%02x\n", @@ -214,14 +214,14 @@ static void hna_local_del(struct hna_local_entry *hna_local_entry, void hna_local_purge(struct work_struct *work) { struct hna_local_entry *hna_local_entry; - struct hash_it_t *hashit = NULL; + HASHIT(hashit); unsigned long flags; unsigned long timeout;
spin_lock_irqsave(&hna_local_hash_lock, flags);
- while (NULL != (hashit = hash_iterate(hna_local_hash, hashit))) { - hna_local_entry = hashit->bucket->data; + while (hash_iterate(hna_local_hash, &hashit)) { + hna_local_entry = hashit.bucket->data;
timeout = hna_local_entry->last_seen + ((LOCAL_HNA_TIMEOUT / 1000) * HZ); @@ -345,17 +345,17 @@ void hna_global_add_orig(struct orig_node *orig_node, int hna_global_fill_buffer_text(unsigned char *buff, int buff_len) { struct hna_global_entry *hna_global_entry; - struct hash_it_t *hashit = NULL; + HASHIT(hashit); int bytes_written = 0; unsigned long flags;
spin_lock_irqsave(&hna_global_hash_lock, flags);
- while (NULL != (hashit = hash_iterate(hna_global_hash, hashit))) { + while (hash_iterate(hna_global_hash, &hashit)) { if (buff_len < bytes_written + (2 * ETH_STR_LEN) + 10) break;
- hna_global_entry = hashit->bucket->data; + hna_global_entry = hashit.bucket->data;
bytes_written += snprintf(buff + bytes_written, (2 * ETH_STR_LEN) + 10, diff --git a/drivers/staging/batman-adv/vis.c b/drivers/staging/batman-adv/vis.c index c26d48c..ac7c7c5 100644 --- a/drivers/staging/batman-adv/vis.c +++ b/drivers/staging/batman-adv/vis.c @@ -266,12 +266,12 @@ end: * Must be called with the originator hash locked */ static int find_best_vis_server(struct vis_info *info) { - struct hash_it_t *hashit = NULL; + HASHIT(hashit); struct orig_node *orig_node; int best_tq = -1;
- while (NULL != (hashit = hash_iterate(orig_hash, hashit))) { - orig_node = hashit->bucket->data; + while (hash_iterate(orig_hash, &hashit)) { + orig_node = hashit.bucket->data; if ((orig_node != NULL) && (orig_node->router != NULL) && (orig_node->flags & VIS_SERVER) && @@ -297,7 +297,8 @@ static bool vis_packet_full(struct vis_info *info) * returns 0 on success, -1 if no packet could be generated */ static int generate_vis_packet(void) { - struct hash_it_t *hashit = NULL; + HASHIT(hashit_local); + HASHIT(hashit_global); struct orig_node *orig_node; struct vis_info *info = (struct vis_info *)my_vis_info; struct vis_info_entry *entry, *entry_array; @@ -320,13 +321,12 @@ static int generate_vis_packet(void) return -1; } } - hashit = NULL;
entry_array = (struct vis_info_entry *) ((char *)info + sizeof(struct vis_info));
- while (NULL != (hashit = hash_iterate(orig_hash, hashit))) { - orig_node = hashit->bucket->data; + while (hash_iterate(orig_hash, &hashit_global)) { + orig_node = hashit_global.bucket->data; if (orig_node->router != NULL && compare_orig(orig_node->router->addr, orig_node->orig) && orig_node->batman_if @@ -349,10 +349,9 @@ static int generate_vis_packet(void)
spin_unlock(&orig_hash_lock);
- hashit = NULL; spin_lock_irqsave(&hna_local_hash_lock, flags); - while (NULL != (hashit = hash_iterate(hna_local_hash, hashit))) { - hna_local_entry = hashit->bucket->data; + while (hash_iterate(hna_local_hash, &hashit_local)) { + hna_local_entry = hashit_local.bucket->data; entry = &entry_array[info->packet.entries]; memset(entry->src, 0, ETH_ALEN); memcpy(entry->dest, hna_local_entry->addr, ETH_ALEN); @@ -370,16 +369,16 @@ static int generate_vis_packet(void)
static void purge_vis_packets(void) { - struct hash_it_t *hashit = NULL; + HASHIT(hashit); struct vis_info *info;
- while (NULL != (hashit = hash_iterate(vis_hash, hashit))) { - info = hashit->bucket->data; + while (hash_iterate(vis_hash, &hashit)) { + info = hashit.bucket->data; if (info == my_vis_info) /* never purge own data. */ continue; if (time_after(jiffies, info->first_seen + (VIS_TIMEOUT/1000)*HZ)) { - hash_remove_bucket(vis_hash, hashit); + hash_remove_bucket(vis_hash, &hashit); free_info(info); } } @@ -387,14 +386,14 @@ static void purge_vis_packets(void)
static void broadcast_vis_packet(struct vis_info *info, int packet_length) { - struct hash_it_t *hashit = NULL; + HASHIT(hashit); struct orig_node *orig_node;
spin_lock(&orig_hash_lock);
/* send to all routers in range. */ - while (NULL != (hashit = hash_iterate(orig_hash, hashit))) { - orig_node = hashit->bucket->data; + while (hash_iterate(orig_hash, &hashit)) { + orig_node = hashit.bucket->data;
/* if it's a vis server and reachable, send it. */ if (orig_node &&
From: Simon Wunderlich siwu@hrz.tu-chemnitz.de
we have written "neighbors", "neighbours" and bad spelled versions of this word, this patch should make it consistent.
Signed-off-by: Simon Wunderlich siwu@hrz.tu-chemnitz.de Signed-off-by: Andrew Lunn andrew@lunn.ch --- drivers/staging/batman-adv/originator.c | 12 ++++++------ drivers/staging/batman-adv/packet.h | 2 +- drivers/staging/batman-adv/proc.c | 2 +- drivers/staging/batman-adv/routing.c | 10 +++++----- drivers/staging/batman-adv/types.h | 2 +- 5 files changed, 14 insertions(+), 14 deletions(-)
diff --git a/drivers/staging/batman-adv/originator.c b/drivers/staging/batman-adv/originator.c index 9ac8da3..f2b295b 100644 --- a/drivers/staging/batman-adv/originator.c +++ b/drivers/staging/batman-adv/originator.c @@ -74,7 +74,7 @@ create_neighbor(struct orig_node *orig_node, struct orig_node *orig_neigh_node, { struct neigh_node *neigh_node;
- bat_dbg(DBG_BATMAN, "Creating new last-hop neighbour of originator\n"); + bat_dbg(DBG_BATMAN, "Creating new last-hop neighbor of originator\n");
neigh_node = kmalloc(sizeof(struct neigh_node), GFP_ATOMIC); memset(neigh_node, 0, sizeof(struct neigh_node)); @@ -94,7 +94,7 @@ void free_orig_node(void *data) struct neigh_node *neigh_node; struct orig_node *orig_node = (struct orig_node *)data;
- /* for all neighbours towards this originator ... */ + /* for all neighbors towards this originator ... */ list_for_each_safe(list_pos, list_pos_tmp, &orig_node->neigh_list) { neigh_node = list_entry(list_pos, struct neigh_node, list);
@@ -159,7 +159,7 @@ struct orig_node *get_orig_node(uint8_t *addr) return orig_node; }
-static bool purge_orig_neigbours(struct orig_node *orig_node, +static bool purge_orig_neighbors(struct orig_node *orig_node, struct neigh_node **best_neigh_node) { struct list_head *list_pos, *list_pos_tmp; @@ -170,7 +170,7 @@ static bool purge_orig_neigbours(struct orig_node *orig_node, *best_neigh_node = NULL;
- /* for all neighbours towards this originator ... */ + /* for all neighbors towards this originator ... */ list_for_each_safe(list_pos, list_pos_tmp, &orig_node->neigh_list) { neigh_node = list_entry(list_pos, struct neigh_node, list);
@@ -180,7 +180,7 @@ static bool purge_orig_neigbours(struct orig_node *orig_node,
addr_to_string(neigh_str, neigh_node->addr); addr_to_string(orig_str, orig_node->orig); - bat_dbg(DBG_BATMAN, "Neighbour timeout: originator %s, neighbour: %s, last_valid %lu\n", orig_str, neigh_str, (neigh_node->last_valid / HZ)); + bat_dbg(DBG_BATMAN, "neighbor timeout: originator %s, neighbor: %s, last_valid %lu\n", orig_str, neigh_str, (neigh_node->last_valid / HZ));
neigh_purged = true; list_del(list_pos); @@ -211,7 +211,7 @@ static bool purge_orig_node(struct orig_node *orig_node) orig_str, (orig_node->last_valid / HZ)); return true; } else { - if (purge_orig_neigbours(orig_node, &best_neigh_node)) + if (purge_orig_neighbors(orig_node, &best_neigh_node)) update_routes(orig_node, best_neigh_node, orig_node->hna_buff, orig_node->hna_buff_len); diff --git a/drivers/staging/batman-adv/packet.h b/drivers/staging/batman-adv/packet.h index 5627ca3..ad006ce 100644 --- a/drivers/staging/batman-adv/packet.h +++ b/drivers/staging/batman-adv/packet.h @@ -90,7 +90,7 @@ struct vis_packet { uint8_t entries; /* number of entries behind this struct */ uint8_t ttl; /* TTL */ uint8_t vis_orig[6]; /* originator that informs about its - * neighbours */ + * neighbors */ uint8_t target_orig[6]; /* who should receive this packet */ uint8_t sender_orig[6]; /* who sent or rebroadcasted this packet */ } __attribute__((packed)); diff --git a/drivers/staging/batman-adv/proc.c b/drivers/staging/batman-adv/proc.c index f693a0e..22471ee 100644 --- a/drivers/staging/batman-adv/proc.c +++ b/drivers/staging/batman-adv/proc.c @@ -404,7 +404,7 @@ static void proc_vis_read_entry(struct seq_file *seq, from, to, int_part, frac_part); } else { seq_printf(seq, - "%s\t{ router : "%s", neighbour : "%s", label : %d.%d }", + "%s\t{ router : "%s", neighbor : "%s", label : %d.%d }", (first_line ? "" : ",\n"), from, to, int_part, frac_part); } } diff --git a/drivers/staging/batman-adv/routing.c b/drivers/staging/batman-adv/routing.c index 89d7faa..adde460 100644 --- a/drivers/staging/batman-adv/routing.c +++ b/drivers/staging/batman-adv/routing.c @@ -266,7 +266,7 @@ static void update_orig(struct orig_node *orig_node, struct ethhdr *ethhdr, ethhdr->h_source, if_incoming); else bat_dbg(DBG_BATMAN, - "Updating existing last-hop neighbour of originator\n"); + "Updating existing last-hop neighbor of originator\n");
orig_node->flags = batman_packet->flags; neigh_node->last_valid = jiffies; @@ -444,7 +444,7 @@ void receive_bat_packet(struct ethhdr *ethhdr,
orig_neigh_node = get_orig_node(ethhdr->h_source);
- /* neighbour has to indicate direct link and it has to + /* neighbor has to indicate direct link and it has to * come via the corresponding interface */ /* if received seqno equals last send seqno save new * seqno for bidirectional check */ @@ -459,7 +459,7 @@ void receive_bat_packet(struct ethhdr *ethhdr, bit_packet_count(word); }
- bat_dbg(DBG_BATMAN, "Drop packet: originator packet from myself (via neighbour) \n"); + bat_dbg(DBG_BATMAN, "Drop packet: originator packet from myself (via neighbor) \n"); return; }
@@ -520,14 +520,14 @@ void receive_bat_packet(struct ethhdr *ethhdr, update_orig(orig_node, ethhdr, batman_packet, if_incoming, hna_buff, hna_buff_len, is_duplicate);
- /* is single hop (direct) neighbour */ + /* is single hop (direct) neighbor */ if (is_single_hop_neigh) {
/* mark direct link on incoming interface */ schedule_forward_packet(orig_node, ethhdr, batman_packet, 1, hna_buff_len, if_incoming);
- bat_dbg(DBG_BATMAN, "Forwarding packet: rebroadcast neighbour packet with direct link flag\n"); + bat_dbg(DBG_BATMAN, "Forwarding packet: rebroadcast neighbor packet with direct link flag\n"); return; }
diff --git a/drivers/staging/batman-adv/types.h b/drivers/staging/batman-adv/types.h index 3a0ef0c..9739358 100644 --- a/drivers/staging/batman-adv/types.h +++ b/drivers/staging/batman-adv/types.h @@ -75,7 +75,7 @@ struct neigh_node { uint8_t tq_index; uint8_t tq_avg; uint8_t last_ttl; - unsigned long last_valid; /* when last packet via this neighbour was received */ + unsigned long last_valid; /* when last packet via this neighbor was received */ TYPE_OF_WORD real_bits[NUM_WORDS]; struct orig_node *orig_node; struct batman_if *if_incoming;
From: Sven Eckelmann sven.eckelmann@gmx.de
forw_bcast_list_lock is spin_locked in both process and softirq context. SoftIRQ calls the spinlock with disabled IRQ and normal process context with enabled IRQs.
When process context is inside an spin_locked area protected by forw_bcast_list_lock and gets interrupted by an IRQ, it could happen that something tries to lock forw_bcast_list_lock again in SoftIRQ context. It cannot proceed further since the lock is already taken somewhere else, but no reschedule will happen inside the SoftIRQ context. This leads to an complete kernel hang without any chance of resurrection.
All functions called in process context must disable IRQs when they try to get get that lock to to prevent any reschedule due to IRQs.
Signed-off-by: Sven Eckelmann sven.eckelmann@gmx.de Acked-by: Marek Lindner lindner_marek@yahoo.de Signed-off-by: Andrew Lunn andrew@lunn.ch --- drivers/staging/batman-adv/send.c | 19 +++++++++++-------- 1 files changed, 11 insertions(+), 8 deletions(-)
diff --git a/drivers/staging/batman-adv/send.c b/drivers/staging/batman-adv/send.c index fc4953f..49b1534 100644 --- a/drivers/staging/batman-adv/send.c +++ b/drivers/staging/batman-adv/send.c @@ -338,12 +338,13 @@ static void forw_packet_free(struct forw_packet *forw_packet) static void _add_bcast_packet_to_list(struct forw_packet *forw_packet, unsigned long send_time) { + unsigned long flags; INIT_HLIST_NODE(&forw_packet->list);
/* add new packet to packet list */ - spin_lock(&forw_bcast_list_lock); + spin_lock_irqsave(&forw_bcast_list_lock, flags); hlist_add_head(&forw_packet->list, &forw_bcast_list); - spin_unlock(&forw_bcast_list_lock); + spin_unlock_irqrestore(&forw_bcast_list_lock, flags);
/* start timer for this packet */ INIT_DELAYED_WORK(&forw_packet->delayed_work, @@ -382,10 +383,11 @@ void send_outstanding_bcast_packet(struct work_struct *work) container_of(work, struct delayed_work, work); struct forw_packet *forw_packet = container_of(delayed_work, struct forw_packet, delayed_work); + unsigned long flags;
- spin_lock(&forw_bcast_list_lock); + spin_lock_irqsave(&forw_bcast_list_lock, flags); hlist_del(&forw_packet->list); - spin_unlock(&forw_bcast_list_lock); + spin_unlock_irqrestore(&forw_bcast_list_lock, flags);
/* rebroadcast packet */ rcu_read_lock(); @@ -436,24 +438,25 @@ void purge_outstanding_packets(void) { struct forw_packet *forw_packet; struct hlist_node *tmp_node, *safe_tmp_node; + unsigned long flags;
bat_dbg(DBG_BATMAN, "purge_outstanding_packets()\n");
/* free bcast list */ - spin_lock(&forw_bcast_list_lock); + spin_lock_irqsave(&forw_bcast_list_lock, flags); hlist_for_each_entry_safe(forw_packet, tmp_node, safe_tmp_node, &forw_bcast_list, list) {
- spin_unlock(&forw_bcast_list_lock); + spin_unlock_irqrestore(&forw_bcast_list_lock, flags);
/** * send_outstanding_bcast_packet() will lock the list to * delete the item from the list */ cancel_delayed_work_sync(&forw_packet->delayed_work); - spin_lock(&forw_bcast_list_lock); + spin_lock_irqsave(&forw_bcast_list_lock, flags); } - spin_unlock(&forw_bcast_list_lock); + spin_unlock_irqrestore(&forw_bcast_list_lock, flags);
/* free batman packet list */ spin_lock(&forw_bat_list_lock);
From: Linus Lüssing linus.luessing@web.de
This patches fixes two rounding issues in vis.c for sending and purging vis packets. Before, the timers and timeouts always got rounded down to seconds, though we want a precision in milliseconds.
This also fixes a kernel panic that occures when lowering the timer for sending vis packets (vis_interval) to less than 1000ms in main.c manually.
Signed-off-by: Linus Lüssing linus.luessing@web.de Acked-by: Marek Lindner lindner_marek@yahoo.de Signed-off-by: Andrew Lunn andrew@lunn.ch --- drivers/staging/batman-adv/vis.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/staging/batman-adv/vis.c b/drivers/staging/batman-adv/vis.c index ac7c7c5..0eb23d2 100644 --- a/drivers/staging/batman-adv/vis.c +++ b/drivers/staging/batman-adv/vis.c @@ -377,7 +377,7 @@ static void purge_vis_packets(void) if (info == my_vis_info) /* never purge own data. */ continue; if (time_after(jiffies, - info->first_seen + (VIS_TIMEOUT/1000)*HZ)) { + info->first_seen + (VIS_TIMEOUT*HZ)/1000)) { hash_remove_bucket(vis_hash, &hashit); free_info(info); } @@ -556,5 +556,5 @@ void vis_quit(void) static void start_vis_timer(void) { queue_delayed_work(bat_event_workqueue, &vis_timer_wq, - (atomic_read(&vis_interval)/1000) * HZ); + (atomic_read(&vis_interval) * HZ) / 1000); }
From: Marek Lindner lindner_marek@yahoo.de
The originator table contained a TAB instead of a space which broke the layout as well as the batctl parser.
Signed-off-by: Marek Lindner lindner_marek@yahoo.de Signed-off-by: Andrew Lunn andrew@lunn.ch --- drivers/staging/batman-adv/proc.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/staging/batman-adv/proc.c b/drivers/staging/batman-adv/proc.c index 22471ee..e48b820 100644 --- a/drivers/staging/batman-adv/proc.c +++ b/drivers/staging/batman-adv/proc.c @@ -230,7 +230,7 @@ static int proc_originators_read(struct seq_file *seq, void *offset) addr_to_string(orig_str, orig_node->orig); addr_to_string(router_str, orig_node->router->addr);
- seq_printf(seq, "%-17s (%3i) %17s [%10s]:", + seq_printf(seq, "%-17s (%3i) %17s [%10s]:", orig_str, orig_node->router->tq_avg, router_str, orig_node->router->if_incoming->dev);
The batman-adv kernel module is able to output visualization data using the dot draw or JSON format. This patch transforms the output into a generic format (called vis raw). User space tool may convert the raw data to support a variety of formats without the need of modifying the kernel module.
Signed-off-by: Andrew Lunn andrew@lunn.ch Signed-off-by: Marek Lindner lindner_marek@yahoo.de --- drivers/staging/batman-adv/TODO | 11 --- drivers/staging/batman-adv/proc.c | 171 +++++++++++++------------------------ drivers/staging/batman-adv/proc.h | 9 -- 3 files changed, 61 insertions(+), 130 deletions(-)
diff --git a/drivers/staging/batman-adv/TODO b/drivers/staging/batman-adv/TODO index 8c2b89e..b1e369c 100644 --- a/drivers/staging/batman-adv/TODO +++ b/drivers/staging/batman-adv/TODO @@ -17,17 +17,6 @@ -> transtable_global (read-only) [outputs the global translation table] -> transtable_local (read-only) [outputs the local translation table]
-=> vis "raw" data output -* the raw format shall replace dot draw / json to offer a neutral that can -* be converted -* the format (comma seperated entries): --> "mac" -> mac address of an originator (each line begins with it) --> "TQ mac value" -> src mac's link quality towards mac address --> "HNA mac" -> HNA announced by source mac --> "PRIMARY" -> this is a primary interface --> "SEC mac" -> secondary mac address of source (requires preceeding --> PRIMARY) - => logging * make use of printk %pM support instead of converting mac addresses * manually diff --git a/drivers/staging/batman-adv/proc.c b/drivers/staging/batman-adv/proc.c index e48b820..352b883 100644 --- a/drivers/staging/batman-adv/proc.c +++ b/drivers/staging/batman-adv/proc.c @@ -322,166 +322,117 @@ static int proc_transt_global_open(struct inode *inode, struct file *file) return single_open(file, proc_transt_global_read, NULL); }
-/* insert interface to the list of interfaces of one originator */ +/* While scanning for vis-entries of a particular vis-originator + * this list collects its interfaces to create a subgraph/cluster + * out of them later + */ +struct if_list_entry { + uint8_t addr[ETH_ALEN]; + bool primary; + struct hlist_node list; +};
+/* insert interface to the list of interfaces of one originator, if it + * does not already exist in the list */ static void proc_vis_insert_interface(const uint8_t *interface, - struct vis_if_list **if_entry, + struct hlist_head *if_list, bool primary) { - /* Did we get an empty list? (then insert imediately) */ - if (*if_entry == NULL) { - *if_entry = kmalloc(sizeof(struct vis_if_list), GFP_KERNEL); - if (*if_entry == NULL) + struct if_list_entry *entry; + struct hlist_node *pos; + + hlist_for_each_entry(entry, pos, if_list, list) { + if (compare_orig(entry->addr, (void *)interface)) return; + }
- (*if_entry)->primary = primary; - (*if_entry)->next = NULL; - memcpy((*if_entry)->addr, interface, ETH_ALEN); - } else { - struct vis_if_list *head_if_entry = *if_entry; - /* Do we already have this interface in our list? */ - while (!compare_orig((*if_entry)->addr, (void *)interface)) { - - /* Or did we reach the end (then append the interface) */ - if ((*if_entry)->next == NULL) { - (*if_entry)->next = kmalloc(sizeof(struct vis_if_list), GFP_KERNEL); - if ((*if_entry)->next == NULL) - return; - - memcpy((*if_entry)->next->addr, interface, ETH_ALEN); - (*if_entry)->next->primary = primary; - (*if_entry)->next->next = NULL; - break; - } - *if_entry = (*if_entry)->next; + /* its a new address, add it to the list */ + entry = kmalloc(sizeof(*entry), GFP_KERNEL); + if (!entry) + return; + memcpy(entry->addr, interface, ETH_ALEN); + entry->primary = primary; + hlist_add_head(&entry->list, if_list); +} + +static void proc_vis_read_prim_sec(struct seq_file *seq, + struct hlist_head *if_list) +{ + struct if_list_entry *entry; + struct hlist_node *pos, *n; + char tmp_addr_str[ETH_STR_LEN]; + + hlist_for_each_entry_safe(entry, pos, n, if_list, list) { + if (entry->primary) { + seq_printf(seq, "PRIMARY, "); + } else { + addr_to_string(tmp_addr_str, entry->addr); + seq_printf(seq, "SEC %s, ", tmp_addr_str); } - /* Rewind the list to its head */ - *if_entry = head_if_entry; + + hlist_del(&entry->list); + kfree(entry); } } -/* read an entry */
+/* read an entry */ static void proc_vis_read_entry(struct seq_file *seq, struct vis_info_entry *entry, - struct vis_if_list **if_entry, - uint8_t *vis_orig, - uint8_t current_format, - uint8_t first_line) + struct hlist_head *if_list, + uint8_t *vis_orig) { - char from[40]; char to[40]; - int int_part, frac_part;
addr_to_string(to, entry->dest); if (entry->quality == 0) { -#ifndef VIS_SUBCLUSTERS_DISABLED - proc_vis_insert_interface(vis_orig, if_entry, true); -#endif /* VIS_SUBCLUSTERS_DISABLED */ - addr_to_string(from, vis_orig); - if (current_format == DOT_DRAW) { - seq_printf(seq, "\t"%s" -> "%s" [label="HNA"]\n", - from, to); - } else { - seq_printf(seq, - "%s\t{ router : "%s", gateway : "%s", label : "HNA" }", - (first_line ? "" : ",\n"), from, to); - } + proc_vis_insert_interface(vis_orig, if_list, true); + seq_printf(seq, "HNA %s, ", to); } else { -#ifndef VIS_SUBCLUSTERS_DISABLED - proc_vis_insert_interface(entry->src, if_entry, compare_orig(entry->src, vis_orig)); -#endif /* VIS_SUBCLUSTERS_DISABLED */ - addr_to_string(from, entry->src); - - /* kernel has no printf-support for %f? it'd be better to return - * this in float. */ - - int_part = TQ_MAX_VALUE / entry->quality; - frac_part = 1000 * TQ_MAX_VALUE / entry->quality - int_part * 1000; - - if (current_format == DOT_DRAW) { - seq_printf(seq, - "\t"%s" -> "%s" [label="%d.%d"]\n", - from, to, int_part, frac_part); - } else { - seq_printf(seq, - "%s\t{ router : "%s", neighbor : "%s", label : %d.%d }", - (first_line ? "" : ",\n"), from, to, int_part, frac_part); - } + proc_vis_insert_interface(entry->src, if_list, + compare_orig(entry->src, vis_orig)); + seq_printf(seq, "TQ %s %d, ", to, entry->quality); } }
- static int proc_vis_read(struct seq_file *seq, void *offset) { HASHIT(hashit); struct vis_info *info; struct vis_info_entry *entries; - struct vis_if_list *if_entries = NULL; + HLIST_HEAD(vis_if_list); int i; - uint8_t current_format, first_line = 1; -#ifndef VIS_SUBCLUSTERS_DISABLED + uint8_t current_format; char tmp_addr_str[ETH_STR_LEN]; - struct vis_if_list *tmp_if_next; -#endif /* VIS_SUBCLUSTERS_DISABLED */
current_format = vis_format;
rcu_read_lock(); if (list_empty(&if_list) || (!is_vis_server())) { rcu_read_unlock(); - if (current_format == DOT_DRAW) - seq_printf(seq, "digraph {\n}\n"); goto end; }
rcu_read_unlock();
- if (current_format == DOT_DRAW) - seq_printf(seq, "digraph {\n"); - spin_lock(&vis_hash_lock); while (hash_iterate(vis_hash, &hashit)) { info = hashit.bucket->data; entries = (struct vis_info_entry *) ((char *)info + sizeof(struct vis_info)); + addr_to_string(tmp_addr_str, info->packet.vis_orig); + seq_printf(seq, "%s,", tmp_addr_str);
for (i = 0; i < info->packet.entries; i++) { - proc_vis_read_entry(seq, &entries[i], &if_entries, - info->packet.vis_orig, - current_format, first_line); - if (first_line) - first_line = 0; + proc_vis_read_entry(seq, &entries[i], &vis_if_list, + info->packet.vis_orig); }
-#ifndef VIS_SUBCLUSTERS_DISABLED - /* Generate subgraphs from the collected items */ - if (current_format == DOT_DRAW) { - - addr_to_string(tmp_addr_str, info->packet.vis_orig); - seq_printf(seq, "\tsubgraph "cluster_%s" {\n", tmp_addr_str); - while (if_entries != NULL) { - - addr_to_string(tmp_addr_str, if_entries->addr); - if (if_entries->primary) - seq_printf(seq, "\t\t"%s" [peripheries=2]\n", tmp_addr_str); - else - seq_printf(seq, "\t\t"%s"\n", tmp_addr_str); - - /* ... and empty the list while doing this */ - tmp_if_next = if_entries->next; - kfree(if_entries); - if_entries = tmp_if_next; - } - seq_printf(seq, "\t}\n"); - } -#endif /* VIS_SUBCLUSTERS_DISABLED */ + /* add primary/secondary records */ + proc_vis_read_prim_sec(seq, &vis_if_list); + seq_printf(seq, "\n"); } spin_unlock(&vis_hash_lock);
- if (current_format == DOT_DRAW) - seq_printf(seq, "}\n"); - else - seq_printf(seq, "\n"); end: return 0; } diff --git a/drivers/staging/batman-adv/proc.h b/drivers/staging/batman-adv/proc.h index 16d3efd..761c5f8 100644 --- a/drivers/staging/batman-adv/proc.h +++ b/drivers/staging/batman-adv/proc.h @@ -38,12 +38,3 @@ void cleanup_procfs(void); int setup_procfs(void);
-/* While scanning for vis-entries of a particular vis-originator - * this list collects its interfaces to create a subgraph/cluster - * out of them later - */ -struct vis_if_list { - uint8_t addr[ETH_ALEN]; - bool primary; - struct vis_if_list *next; -};
From: Linus Luessing linus.luessing@web.de
batman-adv used to export the vis data using different formats that were switchable via /proc/net/batman-adv/vis_format. The various formats moved to user space and rendered this configuration switch useless.
Signed-off-by: Linus Luessing linus.luessing@web.de Signed-off-by: Marek Lindner lindner_marek@yahoo.de Signed-off-by: Andrew Lunn andrew@lunn.ch --- drivers/staging/batman-adv/proc.c | 79 +------------------------------------ drivers/staging/batman-adv/vis.h | 5 -- 2 files changed, 1 insertions(+), 83 deletions(-)
diff --git a/drivers/staging/batman-adv/proc.c b/drivers/staging/batman-adv/proc.c index 352b883..f1adf57 100644 --- a/drivers/staging/batman-adv/proc.c +++ b/drivers/staging/batman-adv/proc.c @@ -29,13 +29,11 @@ #include "vis.h" #include "compat.h"
-static uint8_t vis_format = DOT_DRAW; - static struct proc_dir_entry *proc_batman_dir, *proc_interface_file; static struct proc_dir_entry *proc_orig_interval_file, *proc_originators_file; static struct proc_dir_entry *proc_transt_local_file; static struct proc_dir_entry *proc_transt_global_file; -static struct proc_dir_entry *proc_vis_file, *proc_vis_format_file; +static struct proc_dir_entry *proc_vis_file; static struct proc_dir_entry *proc_aggr_file;
static int proc_interfaces_read(struct seq_file *seq, void *offset) @@ -401,11 +399,8 @@ static int proc_vis_read(struct seq_file *seq, void *offset) struct vis_info_entry *entries; HLIST_HEAD(vis_if_list); int i; - uint8_t current_format; char tmp_addr_str[ETH_STR_LEN];
- current_format = vis_format; - rcu_read_lock(); if (list_empty(&if_list) || (!is_vis_server())) { rcu_read_unlock(); @@ -471,55 +466,6 @@ static int proc_vis_open(struct inode *inode, struct file *file) return single_open(file, proc_vis_read, NULL); }
-static int proc_vis_format_read(struct seq_file *seq, void *offset) -{ - uint8_t current_format = vis_format; - - seq_printf(seq, "[%c] %s\n", - (current_format == DOT_DRAW) ? 'x' : ' ', - VIS_FORMAT_DD_NAME); - seq_printf(seq, "[%c] %s\n", - (current_format == JSON) ? 'x' : ' ', - VIS_FORMAT_JSON_NAME); - return 0; -} - -static int proc_vis_format_open(struct inode *inode, struct file *file) -{ - return single_open(file, proc_vis_format_read, NULL); -} - -static ssize_t proc_vis_format_write(struct file *file, - const char __user *buffer, - size_t count, loff_t *ppos) -{ - char *vis_format_string; - int not_copied = 0; - - vis_format_string = kmalloc(count, GFP_KERNEL); - - if (!vis_format_string) - return -ENOMEM; - - not_copied = copy_from_user(vis_format_string, buffer, count); - vis_format_string[count - not_copied - 1] = 0; - - if (strcmp(vis_format_string, VIS_FORMAT_DD_NAME) == 0) { - printk(KERN_INFO "batman-adv:Setting VIS output format to: %s\n", - VIS_FORMAT_DD_NAME); - vis_format = DOT_DRAW; - } else if (strcmp(vis_format_string, VIS_FORMAT_JSON_NAME) == 0) { - printk(KERN_INFO "batman-adv:Setting VIS output format to: %s\n", - VIS_FORMAT_JSON_NAME); - vis_format = JSON; - } else - printk(KERN_ERR "batman-adv:Unknown VIS output format: %s\n", - vis_format_string); - - kfree(vis_format_string); - return count; -} - static int proc_aggr_read(struct seq_file *seq, void *offset) { seq_printf(seq, "%i\n", atomic_read(&aggregation_enabled)); @@ -583,15 +529,6 @@ static const struct file_operations proc_aggr_fops = { .release = single_release, };
-static const struct file_operations proc_vis_format_fops = { - .owner = THIS_MODULE, - .open = proc_vis_format_open, - .read = seq_read, - .write = proc_vis_format_write, - .llseek = seq_lseek, - .release = single_release, -}; - static const struct file_operations proc_vis_fops = { .owner = THIS_MODULE, .open = proc_vis_open, @@ -666,9 +603,6 @@ void cleanup_procfs(void) if (proc_vis_file) remove_proc_entry(PROC_FILE_VIS, proc_batman_dir);
- if (proc_vis_format_file) - remove_proc_entry(PROC_FILE_VIS_FORMAT, proc_batman_dir); - if (proc_aggr_file) remove_proc_entry(PROC_FILE_AGGR, proc_batman_dir);
@@ -755,17 +689,6 @@ int setup_procfs(void) return -EFAULT; }
- proc_vis_format_file = create_proc_entry(PROC_FILE_VIS_FORMAT, - S_IWUSR | S_IRUGO, - proc_batman_dir); - if (proc_vis_format_file) { - proc_vis_format_file->proc_fops = &proc_vis_format_fops; - } else { - printk(KERN_ERR "batman-adv: Registering the '/proc/net/%s/%s' file failed\n", PROC_ROOT_DIR, PROC_FILE_VIS_FORMAT); - cleanup_procfs(); - return -EFAULT; - } - proc_aggr_file = create_proc_entry(PROC_FILE_AGGR, S_IWUSR | S_IRUGO, proc_batman_dir); if (proc_aggr_file) { diff --git a/drivers/staging/batman-adv/vis.h b/drivers/staging/batman-adv/vis.h index 276faba..ff88a43 100644 --- a/drivers/staging/batman-adv/vis.h +++ b/drivers/staging/batman-adv/vis.h @@ -45,11 +45,6 @@ struct recvlist_node { uint8_t mac[ETH_ALEN]; };
-enum vis_formats { - DOT_DRAW, - JSON, -}; - extern struct hashtable_t *vis_hash; extern spinlock_t vis_hash_lock;
From: Marek Lindner lindner_marek@yahoo.de
The /proc vis file was used to enable/disable the vis server and to output the vis data at the same time. This behaviour was confusing and lacked a proper method to display the current vis server status. This patch seperates the 2 functionalities: * use vis_server to enable/disable the vis server and to retrieve its status * use vis_data to retrieve the vis raw data (if the server is enabled)
Signed-off-by: Marek Lindner lindner_marek@yahoo.de Signed-off-by: Andrew Lunn andrew@lunn.ch --- drivers/staging/batman-adv/proc.c | 172 +++++++++++++++--------------------- drivers/staging/batman-adv/proc.h | 4 +- drivers/staging/batman-adv/types.h | 10 ++ drivers/staging/batman-adv/vis.c | 62 +++++++++++++ drivers/staging/batman-adv/vis.h | 6 ++ 5 files changed, 151 insertions(+), 103 deletions(-)
diff --git a/drivers/staging/batman-adv/proc.c b/drivers/staging/batman-adv/proc.c index f1adf57..d9fde94 100644 --- a/drivers/staging/batman-adv/proc.c +++ b/drivers/staging/batman-adv/proc.c @@ -33,7 +33,7 @@ static struct proc_dir_entry *proc_batman_dir, *proc_interface_file; static struct proc_dir_entry *proc_orig_interval_file, *proc_originators_file; static struct proc_dir_entry *proc_transt_local_file; static struct proc_dir_entry *proc_transt_global_file; -static struct proc_dir_entry *proc_vis_file; +static struct proc_dir_entry *proc_vis_srv_file, *proc_vis_data_file; static struct proc_dir_entry *proc_aggr_file;
static int proc_interfaces_read(struct seq_file *seq, void *offset) @@ -320,79 +320,55 @@ static int proc_transt_global_open(struct inode *inode, struct file *file) return single_open(file, proc_transt_global_read, NULL); }
-/* While scanning for vis-entries of a particular vis-originator - * this list collects its interfaces to create a subgraph/cluster - * out of them later - */ -struct if_list_entry { - uint8_t addr[ETH_ALEN]; - bool primary; - struct hlist_node list; -}; - -/* insert interface to the list of interfaces of one originator, if it - * does not already exist in the list */ -static void proc_vis_insert_interface(const uint8_t *interface, - struct hlist_head *if_list, - bool primary) +/* setting the mode of the vis server by the user */ +static ssize_t proc_vis_srv_write(struct file *file, const char __user * buffer, + size_t count, loff_t *ppos) { - struct if_list_entry *entry; - struct hlist_node *pos; + char *vis_mode_string; + int not_copied = 0;
- hlist_for_each_entry(entry, pos, if_list, list) { - if (compare_orig(entry->addr, (void *)interface)) - return; - } + vis_mode_string = kmalloc(count, GFP_KERNEL);
- /* its a new address, add it to the list */ - entry = kmalloc(sizeof(*entry), GFP_KERNEL); - if (!entry) - return; - memcpy(entry->addr, interface, ETH_ALEN); - entry->primary = primary; - hlist_add_head(&entry->list, if_list); + if (!vis_mode_string) + return -ENOMEM; + + not_copied = copy_from_user(vis_mode_string, buffer, count); + vis_mode_string[count - not_copied - 1] = 0; + + if ((strcmp(vis_mode_string, "client") == 0) || + (strcmp(vis_mode_string, "disabled") == 0)) { + printk(KERN_INFO "batman-adv:Setting VIS mode to client (disabling vis server)\n"); + vis_set_mode(VIS_TYPE_CLIENT_UPDATE); + } else if ((strcmp(vis_mode_string, "server") == 0) || + (strcmp(vis_mode_string, "enabled") == 0)) { + printk(KERN_INFO "batman-adv:Setting VIS mode to server (enabling vis server)\n"); + vis_set_mode(VIS_TYPE_SERVER_SYNC); + } else + printk(KERN_ERR "batman-adv:Unknown VIS mode: %s\n", + vis_mode_string); + + kfree(vis_mode_string); + return count; }
-static void proc_vis_read_prim_sec(struct seq_file *seq, - struct hlist_head *if_list) +static int proc_vis_srv_read(struct seq_file *seq, void *offset) { - struct if_list_entry *entry; - struct hlist_node *pos, *n; - char tmp_addr_str[ETH_STR_LEN]; + int vis_server = is_vis_server();
- hlist_for_each_entry_safe(entry, pos, n, if_list, list) { - if (entry->primary) { - seq_printf(seq, "PRIMARY, "); - } else { - addr_to_string(tmp_addr_str, entry->addr); - seq_printf(seq, "SEC %s, ", tmp_addr_str); - } + seq_printf(seq, "[%c] client mode (server disabled) \n", + (!vis_server) ? 'x' : ' '); + seq_printf(seq, "[%c] server mode (server enabled) \n", + (vis_server) ? 'x' : ' ');
- hlist_del(&entry->list); - kfree(entry); - } + return 0; }
-/* read an entry */ -static void proc_vis_read_entry(struct seq_file *seq, - struct vis_info_entry *entry, - struct hlist_head *if_list, - uint8_t *vis_orig) +static int proc_vis_srv_open(struct inode *inode, struct file *file) { - char to[40]; - - addr_to_string(to, entry->dest); - if (entry->quality == 0) { - proc_vis_insert_interface(vis_orig, if_list, true); - seq_printf(seq, "HNA %s, ", to); - } else { - proc_vis_insert_interface(entry->src, if_list, - compare_orig(entry->src, vis_orig)); - seq_printf(seq, "TQ %s %d, ", to, entry->quality); - } + return single_open(file, proc_vis_srv_read, NULL); }
-static int proc_vis_read(struct seq_file *seq, void *offset) +static int proc_vis_data_read(struct seq_file *seq, void *offset) { HASHIT(hashit); struct vis_info *info; @@ -432,38 +408,9 @@ end: return 0; }
-/* setting the mode of the vis server by the user */ -static ssize_t proc_vis_write(struct file *file, const char __user * buffer, - size_t count, loff_t *ppos) +static int proc_vis_data_open(struct inode *inode, struct file *file) { - char *vis_mode_string; - int not_copied = 0; - - vis_mode_string = kmalloc(count, GFP_KERNEL); - - if (!vis_mode_string) - return -ENOMEM; - - not_copied = copy_from_user(vis_mode_string, buffer, count); - vis_mode_string[count - not_copied - 1] = 0; - - if (strcmp(vis_mode_string, "client") == 0) { - printk(KERN_INFO "batman-adv:Setting VIS mode to client\n"); - vis_set_mode(VIS_TYPE_CLIENT_UPDATE); - } else if (strcmp(vis_mode_string, "server") == 0) { - printk(KERN_INFO "batman-adv:Setting VIS mode to server\n"); - vis_set_mode(VIS_TYPE_SERVER_SYNC); - } else - printk(KERN_ERR "batman-adv:Unknown VIS mode: %s\n", - vis_mode_string); - - kfree(vis_mode_string); - return count; -} - -static int proc_vis_open(struct inode *inode, struct file *file) -{ - return single_open(file, proc_vis_read, NULL); + return single_open(file, proc_vis_data_read, NULL); }
static int proc_aggr_read(struct seq_file *seq, void *offset) @@ -529,11 +476,20 @@ static const struct file_operations proc_aggr_fops = { .release = single_release, };
-static const struct file_operations proc_vis_fops = { +static const struct file_operations proc_vis_srv_fops = { .owner = THIS_MODULE, - .open = proc_vis_open, + .open = proc_vis_srv_open, .read = seq_read, - .write = proc_vis_write, + .write = proc_vis_srv_write, + .llseek = seq_lseek, + .release = single_release, +}; + +static const struct file_operations proc_vis_data_fops = { + .owner = THIS_MODULE, + .open = proc_vis_data_open, + .read = seq_read, + .write = proc_dummy_write, .llseek = seq_lseek, .release = single_release, }; @@ -600,8 +556,11 @@ void cleanup_procfs(void) if (proc_interface_file) remove_proc_entry(PROC_FILE_INTERFACES, proc_batman_dir);
- if (proc_vis_file) - remove_proc_entry(PROC_FILE_VIS, proc_batman_dir); + if (proc_vis_data_file) + remove_proc_entry(PROC_FILE_VIS_DATA, proc_batman_dir); + + if (proc_vis_srv_file) + remove_proc_entry(PROC_FILE_VIS_SRV, proc_batman_dir);
if (proc_aggr_file) remove_proc_entry(PROC_FILE_AGGR, proc_batman_dir); @@ -679,12 +638,23 @@ int setup_procfs(void) return -EFAULT; }
- proc_vis_file = create_proc_entry(PROC_FILE_VIS, S_IWUSR | S_IRUGO, + proc_vis_srv_file = create_proc_entry(PROC_FILE_VIS_SRV, + S_IWUSR | S_IRUGO, + proc_batman_dir); + if (proc_vis_srv_file) { + proc_vis_srv_file->proc_fops = &proc_vis_srv_fops; + } else { + printk(KERN_ERR "batman-adv: Registering the '/proc/net/%s/%s' file failed\n", PROC_ROOT_DIR, PROC_FILE_VIS_SRV); + cleanup_procfs(); + return -EFAULT; + } + + proc_vis_data_file = create_proc_entry(PROC_FILE_VIS_DATA, S_IRUGO, proc_batman_dir); - if (proc_vis_file) { - proc_vis_file->proc_fops = &proc_vis_fops; + if (proc_vis_data_file) { + proc_vis_data_file->proc_fops = &proc_vis_data_fops; } else { - printk(KERN_ERR "batman-adv: Registering the '/proc/net/%s/%s' file failed\n", PROC_ROOT_DIR, PROC_FILE_VIS); + printk(KERN_ERR "batman-adv: Registering the '/proc/net/%s/%s' file failed\n", PROC_ROOT_DIR, PROC_FILE_VIS_DATA); cleanup_procfs(); return -EFAULT; } diff --git a/drivers/staging/batman-adv/proc.h b/drivers/staging/batman-adv/proc.h index 761c5f8..cd690e0 100644 --- a/drivers/staging/batman-adv/proc.h +++ b/drivers/staging/batman-adv/proc.h @@ -31,8 +31,8 @@ #define PROC_FILE_LOG_LEVEL "log_level" #define PROC_FILE_TRANST_LOCAL "transtable_local" #define PROC_FILE_TRANST_GLOBAL "transtable_global" -#define PROC_FILE_VIS "vis" -#define PROC_FILE_VIS_FORMAT "vis_format" +#define PROC_FILE_VIS_SRV "vis_server" +#define PROC_FILE_VIS_DATA "vis_data" #define PROC_FILE_AGGR "aggregate_ogm"
void cleanup_procfs(void); diff --git a/drivers/staging/batman-adv/types.h b/drivers/staging/batman-adv/types.h index 9739358..d708e6f 100644 --- a/drivers/staging/batman-adv/types.h +++ b/drivers/staging/batman-adv/types.h @@ -121,4 +121,14 @@ struct forw_packet { /* structure for forw_list maintaining packet struct batman_if *if_incoming; };
+/* While scanning for vis-entries of a particular vis-originator + * this list collects its interfaces to create a subgraph/cluster + * out of them later + */ +struct if_list_entry { + uint8_t addr[ETH_ALEN]; + bool primary; + struct hlist_node list; +}; + #endif diff --git a/drivers/staging/batman-adv/vis.c b/drivers/staging/batman-adv/vis.c index 0eb23d2..3c66645 100644 --- a/drivers/staging/batman-adv/vis.c +++ b/drivers/staging/batman-adv/vis.c @@ -114,6 +114,68 @@ static int vis_info_choose(void *data, int size) return hash % size; }
+/* insert interface to the list of interfaces of one originator, if it + * does not already exist in the list */ +static void proc_vis_insert_interface(const uint8_t *interface, + struct hlist_head *if_list, + bool primary) +{ + struct if_list_entry *entry; + struct hlist_node *pos; + + hlist_for_each_entry(entry, pos, if_list, list) { + if (compare_orig(entry->addr, (void *)interface)) + return; + } + + /* its a new address, add it to the list */ + entry = kmalloc(sizeof(*entry), GFP_KERNEL); + if (!entry) + return; + memcpy(entry->addr, interface, ETH_ALEN); + entry->primary = primary; + hlist_add_head(&entry->list, if_list); +} + +void proc_vis_read_prim_sec(struct seq_file *seq, + struct hlist_head *if_list) +{ + struct if_list_entry *entry; + struct hlist_node *pos, *n; + char tmp_addr_str[ETH_STR_LEN]; + + hlist_for_each_entry_safe(entry, pos, n, if_list, list) { + if (entry->primary) { + seq_printf(seq, "PRIMARY, "); + } else { + addr_to_string(tmp_addr_str, entry->addr); + seq_printf(seq, "SEC %s, ", tmp_addr_str); + } + + hlist_del(&entry->list); + kfree(entry); + } +} + +/* read an entry */ +void proc_vis_read_entry(struct seq_file *seq, + struct vis_info_entry *entry, + struct hlist_head *if_list, + uint8_t *vis_orig) +{ + char to[40]; + + addr_to_string(to, entry->dest); + if (entry->quality == 0) { + proc_vis_insert_interface(vis_orig, if_list, true); + seq_printf(seq, "HNA %s, ", to); + } else { + proc_vis_insert_interface(entry->src, if_list, + compare_orig(entry->src, vis_orig)); + seq_printf(seq, "TQ %s %d, ", to, entry->quality); + } +} + /* tries to add one entry to the receive list. */ static void recv_list_add(struct list_head *recv_list, char *mac) { diff --git a/drivers/staging/batman-adv/vis.h b/drivers/staging/batman-adv/vis.h index ff88a43..2e24258 100644 --- a/drivers/staging/batman-adv/vis.h +++ b/drivers/staging/batman-adv/vis.h @@ -50,6 +50,12 @@ extern spinlock_t vis_hash_lock;
void vis_set_mode(int mode); int is_vis_server(void); +void proc_vis_read_entry(struct seq_file *seq, + struct vis_info_entry *entry, + struct hlist_head *if_list, + uint8_t *vis_orig); +void proc_vis_read_prim_sec(struct seq_file *seq, + struct hlist_head *if_list); void receive_server_sync_packet(struct vis_packet *vis_packet, int vis_info_len); void receive_client_update_packet(struct vis_packet *vis_packet,
From: Simon Wunderlich siwu@hrz.tu-chemnitz.de
there are some kmallocs left which are not checked whether they succeeds or not, which might lead to corrupted data structures if the system memory is full. This patch should clean up the remaining unchecked kmalloc()s.
Signed-off-by: Simon Wunderlich siwu@hrz.tu-chemnitz.de Signed-off-by: Andrew Lunn andrew@lunn.ch --- drivers/staging/batman-adv/originator.c | 22 ++++++++++++++++++- drivers/staging/batman-adv/routing.c | 27 +++++++++++++++++++---- drivers/staging/batman-adv/translation-table.c | 18 ++++++++------- 3 files changed, 53 insertions(+), 14 deletions(-)
diff --git a/drivers/staging/batman-adv/originator.c b/drivers/staging/batman-adv/originator.c index f2b295b..849e480 100644 --- a/drivers/staging/batman-adv/originator.c +++ b/drivers/staging/batman-adv/originator.c @@ -77,6 +77,9 @@ create_neighbor(struct orig_node *orig_node, struct orig_node *orig_neigh_node, bat_dbg(DBG_BATMAN, "Creating new last-hop neighbor of originator\n");
neigh_node = kmalloc(sizeof(struct neigh_node), GFP_ATOMIC); + if (!neigh_node) + return NULL; + memset(neigh_node, 0, sizeof(struct neigh_node)); INIT_LIST_HEAD(&neigh_node->list);
@@ -127,6 +130,9 @@ struct orig_node *get_orig_node(uint8_t *addr) bat_dbg(DBG_BATMAN, "Creating new originator: %s \n", orig_str);
orig_node = kmalloc(sizeof(struct orig_node), GFP_ATOMIC); + if (!orig_node) + return NULL; + memset(orig_node, 0, sizeof(struct orig_node)); INIT_LIST_HEAD(&orig_node->neigh_list);
@@ -138,13 +144,20 @@ struct orig_node *get_orig_node(uint8_t *addr) size = num_ifs * sizeof(TYPE_OF_WORD) * NUM_WORDS;
orig_node->bcast_own = kmalloc(size, GFP_ATOMIC); + if (!orig_node->bcast_own) + goto free_orig_node; + memset(orig_node->bcast_own, 0, size);
size = num_ifs * sizeof(uint8_t); orig_node->bcast_own_sum = kmalloc(size, GFP_ATOMIC); + if (!orig_node->bcast_own_sum) + goto free_bcast_own; + memset(orig_node->bcast_own_sum, 0, size);
- hash_add(orig_hash, orig_node); + if (hash_add(orig_hash, orig_node) < 0) + goto free_bcast_own_sum;
if (orig_hash->elements * 4 > orig_hash->size) { swaphash = hash_resize(orig_hash, orig_hash->size * 2); @@ -157,6 +170,13 @@ struct orig_node *get_orig_node(uint8_t *addr) }
return orig_node; +free_bcast_own_sum: + kfree(orig_node->bcast_own_sum); +free_bcast_own: + kfree(orig_node->bcast_own); +free_orig_node: + kfree(orig_node); + return NULL; }
static bool purge_orig_neighbors(struct orig_node *orig_node, diff --git a/drivers/staging/batman-adv/routing.c b/drivers/staging/batman-adv/routing.c index adde460..25a1424 100644 --- a/drivers/staging/batman-adv/routing.c +++ b/drivers/staging/batman-adv/routing.c @@ -154,11 +154,14 @@ static int isBidirectionalNeigh(struct orig_node *orig_node, neigh_node = tmp_neigh_node; }
- if (neigh_node == NULL) + if (!neigh_node) neigh_node = create_neighbor(orig_node, orig_neigh_node, orig_neigh_node->orig, if_incoming); + /* create_neighbor failed, return 0 */ + if (!neigh_node) + return 0;
neigh_node->last_valid = jiffies; } else { @@ -172,11 +175,14 @@ static int isBidirectionalNeigh(struct orig_node *orig_node, neigh_node = tmp_neigh_node; }
- if (neigh_node == NULL) + if (!neigh_node) neigh_node = create_neighbor(orig_neigh_node, orig_neigh_node, orig_neigh_node->orig, if_incoming); + /* create_neighbor failed, return 0 */ + if (!neigh_node) + return 0; }
orig_node->last_valid = jiffies; @@ -260,11 +266,19 @@ static void update_orig(struct orig_node *orig_node, struct ethhdr *ethhdr, ring_buffer_avg(tmp_neigh_node->tq_recv); }
- if (neigh_node == NULL) + if (!neigh_node) { + struct orig_node *orig_tmp; + + orig_tmp = get_orig_node(ethhdr->h_source); + if (!orig_tmp) + return; + neigh_node = create_neighbor(orig_node, - get_orig_node(ethhdr->h_source), + orig_tmp, ethhdr->h_source, if_incoming); - else + if (!neigh_node) + return; + } else bat_dbg(DBG_BATMAN, "Updating existing last-hop neighbor of originator\n");
@@ -444,6 +458,9 @@ void receive_bat_packet(struct ethhdr *ethhdr,
orig_neigh_node = get_orig_node(ethhdr->h_source);
+ if (!orig_neigh_node) + return; + /* neighbor has to indicate direct link and it has to * come via the corresponding interface */ /* if received seqno equals last send seqno save new diff --git a/drivers/staging/batman-adv/translation-table.c b/drivers/staging/batman-adv/translation-table.c index 088715b..8c8136b 100644 --- a/drivers/staging/batman-adv/translation-table.c +++ b/drivers/staging/batman-adv/translation-table.c @@ -317,14 +317,16 @@ void hna_global_add_orig(struct orig_node *orig_node, hna_buff_count++; }
- orig_node->hna_buff_len = hna_buff_len; - - if (orig_node->hna_buff_len > 0) { - orig_node->hna_buff = kmalloc(orig_node->hna_buff_len, - GFP_ATOMIC); - memcpy(orig_node->hna_buff, hna_buff, orig_node->hna_buff_len); - } else { - orig_node->hna_buff = NULL; + /* initialize, and overwrite if malloc succeeds */ + orig_node->hna_buff = NULL; + orig_node->hna_buff_len = 0; + + if (hna_buff_len > 0) { + orig_node->hna_buff = kmalloc(hna_buff_len, GFP_ATOMIC); + if (orig_node->hna_buff) { + memcpy(orig_node->hna_buff, hna_buff, hna_buff_len); + orig_node->hna_buff_len = hna_buff_len; + } }
spin_lock_irqsave(&hna_global_hash_lock, flags);
From: Simon Wunderlich siwu@hrz.tu-chemnitz.de
This patch removes the (ugly and racy) packet receiving thread and the kernel socket usage. Instead, packets are received directly by registering the ethernet type and handling skbs instead of self-allocated buffers.
Some consequences and comments:
* we don't copy the payload data when forwarding/sending/receiving data anymore. This should boost performance. * packets from/to different interfaces can be (theoretically) processed simultaneously. Only the big originator hash lock might be in the way. * no more polling or sleeping/wakeup/scheduling issues when receiving packets * this might introduce new race conditions. * aggregation and vis code still use packet buffers and are not (yet) converted. * all spinlocks were converted to irqsave/restore versions to solve some lifelock issues when preempted. This might be overkill, some of these locks might be reverted later. * skb copies are only done if neccesary to avoid overhead
performance differences:
* we made some "benchmarks" with intel laptops. * bandwidth on Gigabit Ethernet increased from ~500 MBit/s to ~920 MBit/s * ping latency decresed from ~2ms to ~0.2 ms
I did some tests on my 9 node qemu environment and could confirm that usual sending/receiving, forwarding, vis, batctl ping etc works.
Signed-off-by: Simon Wunderlich siwu@hrz.tu-chemnitz.de Acked-by: Sven Eckelmann sven.eckelmann@gmx.de Acked-by: Marek Lindner lindner_marek@yahoo.de Acked-by: Linus Lüssing linus.luessing@web.de Signed-off-by: Andrew Lunn andrew@lunn.ch --- drivers/staging/batman-adv/aggregation.c | 13 +- drivers/staging/batman-adv/device.c | 24 +- drivers/staging/batman-adv/hard-interface.c | 154 ++++++--- drivers/staging/batman-adv/hard-interface.h | 4 + drivers/staging/batman-adv/main.c | 29 +- drivers/staging/batman-adv/originator.c | 18 +- drivers/staging/batman-adv/proc.c | 10 +- drivers/staging/batman-adv/routing.c | 561 ++++++++++++--------------- drivers/staging/batman-adv/routing.h | 8 +- drivers/staging/batman-adv/send.c | 93 +++-- drivers/staging/batman-adv/send.h | 5 +- drivers/staging/batman-adv/soft-interface.c | 76 ++-- drivers/staging/batman-adv/soft-interface.h | 3 +- drivers/staging/batman-adv/types.h | 2 +- drivers/staging/batman-adv/vis.c | 55 ++-- 15 files changed, 548 insertions(+), 507 deletions(-)
diff --git a/drivers/staging/batman-adv/aggregation.c b/drivers/staging/batman-adv/aggregation.c index 9c6e681..7917322 100644 --- a/drivers/staging/batman-adv/aggregation.c +++ b/drivers/staging/batman-adv/aggregation.c @@ -96,6 +96,7 @@ static void new_aggregated_packet(unsigned char *packet_buff, int own_packet) { struct forw_packet *forw_packet_aggr; + unsigned long flags;
forw_packet_aggr = kmalloc(sizeof(struct forw_packet), GFP_ATOMIC); if (!forw_packet_aggr) @@ -115,6 +116,7 @@ static void new_aggregated_packet(unsigned char *packet_buff, packet_buff, forw_packet_aggr->packet_len);
+ forw_packet_aggr->skb = NULL; forw_packet_aggr->own = own_packet; forw_packet_aggr->if_incoming = if_incoming; forw_packet_aggr->num_packets = 0; @@ -126,9 +128,9 @@ static void new_aggregated_packet(unsigned char *packet_buff, forw_packet_aggr->direct_link_flags |= 1;
/* add new packet to packet list */ - spin_lock(&forw_bat_list_lock); + spin_lock_irqsave(&forw_bat_list_lock, flags); hlist_add_head(&forw_packet_aggr->list, &forw_bat_list); - spin_unlock(&forw_bat_list_lock); + spin_unlock_irqrestore(&forw_bat_list_lock, flags);
/* start timer for this packet */ INIT_DELAYED_WORK(&forw_packet_aggr->delayed_work, @@ -168,9 +170,10 @@ void add_bat_packet_to_list(unsigned char *packet_buff, int packet_len, struct batman_packet *batman_packet = (struct batman_packet *)packet_buff; bool direct_link = batman_packet->flags & DIRECTLINK ? 1 : 0; + unsigned long flags;
/* find position for the packet in the forward queue */ - spin_lock(&forw_bat_list_lock); + spin_lock_irqsave(&forw_bat_list_lock, flags); /* own packets are not to be aggregated */ if ((atomic_read(&aggregation_enabled)) && (!own_packet)) { hlist_for_each_entry(forw_packet_pos, tmp_node, &forw_bat_list, @@ -191,7 +194,7 @@ void add_bat_packet_to_list(unsigned char *packet_buff, int packet_len, * suitable aggregation packet found */ if (forw_packet_aggr == NULL) { /* the following section can run without the lock */ - spin_unlock(&forw_bat_list_lock); + spin_unlock_irqrestore(&forw_bat_list_lock, flags); new_aggregated_packet(packet_buff, packet_len, send_time, direct_link, if_incoming, own_packet); @@ -199,7 +202,7 @@ void add_bat_packet_to_list(unsigned char *packet_buff, int packet_len, aggregate(forw_packet_aggr, packet_buff, packet_len, direct_link); - spin_unlock(&forw_bat_list_lock); + spin_unlock_irqrestore(&forw_bat_list_lock, flags); } }
diff --git a/drivers/staging/batman-adv/device.c b/drivers/staging/batman-adv/device.c index 92cf8d5..ab2b0b1 100644 --- a/drivers/staging/batman-adv/device.c +++ b/drivers/staging/batman-adv/device.c @@ -133,8 +133,9 @@ int bat_device_release(struct inode *inode, struct file *file) (struct device_client *)file->private_data; struct device_packet *device_packet; struct list_head *list_pos, *list_pos_tmp; + unsigned long flags;
- spin_lock(&device_client->lock); + spin_lock_irqsave(&device_client->lock, flags);
/* for all packets in the queue ... */ list_for_each_safe(list_pos, list_pos_tmp, &device_client->queue_list) { @@ -146,7 +147,7 @@ int bat_device_release(struct inode *inode, struct file *file) }
device_client_hash[device_client->index] = NULL; - spin_unlock(&device_client->lock); + spin_unlock_irqrestore(&device_client->lock, flags);
kfree(device_client); dec_module_count(); @@ -161,6 +162,7 @@ ssize_t bat_device_read(struct file *file, char __user *buf, size_t count, (struct device_client *)file->private_data; struct device_packet *device_packet; int error; + unsigned long flags;
if ((file->f_flags & O_NONBLOCK) && (device_client->queue_len == 0)) return -EAGAIN; @@ -177,14 +179,14 @@ ssize_t bat_device_read(struct file *file, char __user *buf, size_t count, if (error) return error;
- spin_lock(&device_client->lock); + spin_lock_irqsave(&device_client->lock, flags);
device_packet = list_first_entry(&device_client->queue_list, struct device_packet, list); list_del(&device_packet->list); device_client->queue_len--;
- spin_unlock(&device_client->lock); + spin_unlock_irqrestore(&device_client->lock, flags);
error = __copy_to_user(buf, &device_packet->icmp_packet, sizeof(struct icmp_packet)); @@ -205,6 +207,7 @@ ssize_t bat_device_write(struct file *file, const char __user *buff, struct icmp_packet icmp_packet; struct orig_node *orig_node; struct batman_if *batman_if; + unsigned long flags;
if (len < sizeof(struct icmp_packet)) { bat_dbg(DBG_BATMAN, "batman-adv:Error - can't send packet from char device: invalid packet size\n"); @@ -239,7 +242,7 @@ ssize_t bat_device_write(struct file *file, const char __user *buff, if (atomic_read(&module_state) != MODULE_ACTIVE) goto dst_unreach;
- spin_lock(&orig_hash_lock); + spin_lock_irqsave(&orig_hash_lock, flags); orig_node = ((struct orig_node *)hash_find(orig_hash, icmp_packet.dst));
if (!orig_node) @@ -261,11 +264,11 @@ ssize_t bat_device_write(struct file *file, const char __user *buff, sizeof(struct icmp_packet), batman_if, orig_node->router->addr);
- spin_unlock(&orig_hash_lock); + spin_unlock_irqrestore(&orig_hash_lock, flags); goto out;
unlock: - spin_unlock(&orig_hash_lock); + spin_unlock_irqrestore(&orig_hash_lock, flags); dst_unreach: icmp_packet.msg_type = DESTINATION_UNREACHABLE; bat_device_add_packet(device_client, &icmp_packet); @@ -290,6 +293,7 @@ void bat_device_add_packet(struct device_client *device_client, struct icmp_packet *icmp_packet) { struct device_packet *device_packet; + unsigned long flags;
device_packet = kmalloc(sizeof(struct device_packet), GFP_KERNEL);
@@ -300,12 +304,12 @@ void bat_device_add_packet(struct device_client *device_client, memcpy(&device_packet->icmp_packet, icmp_packet, sizeof(struct icmp_packet));
- spin_lock(&device_client->lock); + spin_lock_irqsave(&device_client->lock, flags);
/* while waiting for the lock the device_client could have been * deleted */ if (!device_client_hash[icmp_packet->uid]) { - spin_unlock(&device_client->lock); + spin_unlock_irqrestore(&device_client->lock, flags); kfree(device_packet); return; } @@ -322,7 +326,7 @@ void bat_device_add_packet(struct device_client *device_client, device_client->queue_len--; }
- spin_unlock(&device_client->lock); + spin_unlock_irqrestore(&device_client->lock, flags);
wake_up(&device_client->queue_wait); } diff --git a/drivers/staging/batman-adv/hard-interface.c b/drivers/staging/batman-adv/hard-interface.c index 7c88592..cc59c30 100644 --- a/drivers/staging/batman-adv/hard-interface.c +++ b/drivers/staging/batman-adv/hard-interface.c @@ -153,9 +153,6 @@ void hardif_deactivate_interface(struct batman_if *batman_if) if (batman_if->if_active != IF_ACTIVE) return;
- if (batman_if->raw_sock) - sock_release(batman_if->raw_sock); - /** * batman_if->net_dev has been acquired by dev_get_by_name() in * proc_interfaces_write() and has to be unreferenced. @@ -164,9 +161,6 @@ void hardif_deactivate_interface(struct batman_if *batman_if) if (batman_if->net_dev) dev_put(batman_if->net_dev);
- batman_if->raw_sock = NULL; - batman_if->net_dev = NULL; - batman_if->if_active = IF_INACTIVE; active_ifs--;
@@ -177,9 +171,6 @@ void hardif_deactivate_interface(struct batman_if *batman_if) /* (re)activate given interface. */ static void hardif_activate_interface(struct batman_if *batman_if) { - struct sockaddr_ll bind_addr; - int retval; - if (batman_if->if_active != IF_INACTIVE) return;
@@ -191,35 +182,8 @@ static void hardif_activate_interface(struct batman_if *batman_if) if (!batman_if->net_dev) goto dev_err;
- retval = sock_create_kern(PF_PACKET, SOCK_RAW, - __constant_htons(ETH_P_BATMAN), - &batman_if->raw_sock); - - if (retval < 0) { - printk(KERN_ERR "batman-adv:Can't create raw socket: %i\n", - retval); - goto sock_err; - } - - bind_addr.sll_family = AF_PACKET; - bind_addr.sll_ifindex = batman_if->net_dev->ifindex; - bind_addr.sll_protocol = 0; /* is set by the kernel */ - - retval = kernel_bind(batman_if->raw_sock, - (struct sockaddr *)&bind_addr, sizeof(bind_addr)); - - if (retval < 0) { - printk(KERN_ERR "batman-adv:Can't create bind raw socket: %i\n", - retval); - goto bind_err; - } - check_known_mac_addr(batman_if->net_dev->dev_addr);
- batman_if->raw_sock->sk->sk_user_data = - batman_if->raw_sock->sk->sk_data_ready; - batman_if->raw_sock->sk->sk_data_ready = batman_data_ready; - addr_to_string(batman_if->addr_str, batman_if->net_dev->dev_addr);
memcpy(((struct batman_packet *)(batman_if->packet_buff))->orig, @@ -239,12 +203,7 @@ static void hardif_activate_interface(struct batman_if *batman_if)
return;
-bind_err: - sock_release(batman_if->raw_sock); -sock_err: - dev_put(batman_if->net_dev); dev_err: - batman_if->raw_sock = NULL; batman_if->net_dev = NULL; }
@@ -318,6 +277,7 @@ int hardif_add_interface(char *dev, int if_num) struct batman_if *batman_if; struct batman_packet *batman_packet; struct orig_node *orig_node; + unsigned long flags; HASHIT(hashit);
batman_if = kmalloc(sizeof(struct batman_if), GFP_KERNEL); @@ -327,7 +287,6 @@ int hardif_add_interface(char *dev, int if_num) return -1; }
- batman_if->raw_sock = NULL; batman_if->net_dev = NULL;
if ((if_num == 0) && (num_hna > 0)) @@ -375,17 +334,17 @@ int hardif_add_interface(char *dev, int if_num)
/* resize all orig nodes because orig_node->bcast_own(_sum) depend on * if_num */ - spin_lock(&orig_hash_lock); + spin_lock_irqsave(&orig_hash_lock, flags);
while (hash_iterate(orig_hash, &hashit)) { orig_node = hashit.bucket->data; if (resize_orig(orig_node, if_num) == -1) { - spin_unlock(&orig_hash_lock); + spin_unlock_irqrestore(&orig_hash_lock, flags); goto out; } }
- spin_unlock(&orig_hash_lock); + spin_unlock_irqrestore(&orig_hash_lock, flags);
if (!hardif_is_interface_up(batman_if->dev)) printk(KERN_ERR "batman-adv:Not using interface %s (retrying later): interface not active\n", batman_if->dev); @@ -443,6 +402,111 @@ out: return NOTIFY_DONE; }
+/* find batman interface by netdev. assumes rcu_read_lock on */ +static struct batman_if *find_batman_if(struct net_device *dev) +{ + struct batman_if *batman_if; + + rcu_read_lock(); + list_for_each_entry_rcu(batman_if, &if_list, list) { + if (batman_if->net_dev == dev) { + rcu_read_unlock(); + return batman_if; + } + } + rcu_read_unlock(); + return NULL; +} + + +/* receive a packet with the batman ethertype coming on a hard + * interface */ +int batman_skb_recv(struct sk_buff *skb, struct net_device *dev, + struct packet_type *ptype, struct net_device *orig_dev) +{ + struct batman_packet *batman_packet; + struct batman_if *batman_if; + struct net_device_stats *stats; + int ret; + + skb = skb_share_check(skb, GFP_ATOMIC); + + if (skb == NULL) + goto err_free; + + /* packet should hold at least type and version */ + if (unlikely(skb_headlen(skb) < 2)) + goto err_free; + + /* expect a valid ethernet header here. */ + if (unlikely(skb->mac_len != sizeof(struct ethhdr) + || !skb_mac_header(skb))) + goto err_free; + + batman_if = find_batman_if(skb->dev); + if (!batman_if) + goto err_free; + + stats = &skb->dev->stats; + stats->rx_packets++; + stats->rx_bytes += skb->len; + + batman_packet = (struct batman_packet *)skb->data; + + if (batman_packet->version != COMPAT_VERSION) { + bat_dbg(DBG_BATMAN, + "Drop packet: incompatible batman version (%i)\n", + batman_packet->version); + goto err_free; + } + + /* all receive handlers return whether they received or reused + * the supplied skb. if not, we have to free the skb. */ + + switch (batman_packet->packet_type) { + /* batman originator packet */ + case BAT_PACKET: + ret = recv_bat_packet(skb, batman_if); + break; + + /* batman icmp packet */ + case BAT_ICMP: + ret = recv_icmp_packet(skb); + break; + + /* unicast packet */ + case BAT_UNICAST: + ret = recv_unicast_packet(skb); + break; + + /* broadcast packet */ + case BAT_BCAST: + ret = recv_bcast_packet(skb); + break; + + /* vis packet */ + case BAT_VIS: + ret = recv_vis_packet(skb); + break; + default: + ret = NET_RX_DROP; + } + if (ret == NET_RX_DROP) + kfree_skb(skb); + + /* return NET_RX_SUCCESS in any case as we + * most probably dropped the packet for + * routing-logical reasons. */ + + return NET_RX_SUCCESS; + +err_free: + kfree_skb(skb); + return NET_RX_DROP; + +} + + struct notifier_block hard_if_notifier = { .notifier_call = hard_if_event, }; diff --git a/drivers/staging/batman-adv/hard-interface.h b/drivers/staging/batman-adv/hard-interface.h index 742358c..97c6ecb 100644 --- a/drivers/staging/batman-adv/hard-interface.h +++ b/drivers/staging/batman-adv/hard-interface.h @@ -32,5 +32,9 @@ void hardif_deactivate_interface(struct batman_if *batman_if); char hardif_get_active_if_num(void); void hardif_check_interfaces_status(void); void hardif_check_interfaces_status_wq(struct work_struct *work); +int batman_skb_recv(struct sk_buff *skb, + struct net_device *dev, + struct packet_type *ptype, + struct net_device *orig_dev); int hardif_min_mtu(void); void update_min_mtu(void); diff --git a/drivers/staging/batman-adv/main.c b/drivers/staging/batman-adv/main.c index 434c600..c733504 100644 --- a/drivers/staging/batman-adv/main.c +++ b/drivers/staging/batman-adv/main.c @@ -50,11 +50,14 @@ int16_t num_ifs;
struct net_device *soft_device;
-static struct task_struct *kthread_task; - unsigned char broadcastAddr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; atomic_t module_state;
+static struct packet_type batman_adv_packet_type __read_mostly = { + .type = cpu_to_be16(ETH_P_BATMAN), + .func = batman_skb_recv, +}; + struct workqueue_struct *bat_event_workqueue;
#ifdef CONFIG_BATMAN_ADV_DEBUG @@ -113,6 +116,7 @@ int init_module(void) }
register_netdevice_notifier(&hard_if_notifier); + dev_add_pack(&batman_adv_packet_type);
printk(KERN_INFO "batman-adv:B.A.T.M.A.N. advanced %s%s (compatibility version %i) loaded \n", SOURCE_VERSION, REVISION_VERSION_STR, COMPAT_VERSION); @@ -135,6 +139,8 @@ void cleanup_module(void) soft_device = NULL; }
+ dev_remove_pack(&batman_adv_packet_type); + unregister_netdevice_notifier(&hard_if_notifier); cleanup_procfs();
@@ -162,16 +168,6 @@ void activate_module(void) if (vis_init() < 1) goto err;
- /* (re)start kernel thread for packet processing */ - if (!kthread_task) { - kthread_task = kthread_run(packet_recv_thread, NULL, "batman-adv"); - - if (IS_ERR(kthread_task)) { - printk(KERN_ERR "batman-adv:Unable to start packet receive thread\n"); - kthread_task = NULL; - } - } - update_min_mtu(); atomic_set(&module_state, MODULE_ACTIVE); goto end; @@ -193,14 +189,7 @@ void shutdown_module(void)
vis_quit();
- /* deactivate kernel thread for packet processing (if running) */ - if (kthread_task) { - atomic_set(&exit_cond, 1); - wake_up_interruptible(&thread_wait); - kthread_stop(kthread_task); - - kthread_task = NULL; - } + /* TODO: unregister BATMAN pack */
originator_free();
diff --git a/drivers/staging/batman-adv/originator.c b/drivers/staging/batman-adv/originator.c index 849e480..3fa7baf 100644 --- a/drivers/staging/batman-adv/originator.c +++ b/drivers/staging/batman-adv/originator.c @@ -37,35 +37,38 @@ static void start_purge_timer(void)
int originator_init(void) { + unsigned long flags; if (orig_hash) return 1;
- spin_lock(&orig_hash_lock); + spin_lock_irqsave(&orig_hash_lock, flags); orig_hash = hash_new(128, compare_orig, choose_orig);
if (!orig_hash) goto err;
- spin_unlock(&orig_hash_lock); + spin_unlock_irqrestore(&orig_hash_lock, flags); start_purge_timer(); return 1;
err: - spin_unlock(&orig_hash_lock); + spin_unlock_irqrestore(&orig_hash_lock, flags); return 0; }
void originator_free(void) { + unsigned long flags; + if (!orig_hash) return;
cancel_delayed_work_sync(&purge_orig_wq);
- spin_lock(&orig_hash_lock); + spin_lock_irqsave(&orig_hash_lock, flags); hash_delete(orig_hash, free_orig_node); orig_hash = NULL; - spin_unlock(&orig_hash_lock); + spin_unlock_irqrestore(&orig_hash_lock, flags); }
struct neigh_node * @@ -243,8 +246,9 @@ void purge_orig(struct work_struct *work) { HASHIT(hashit); struct orig_node *orig_node; + unsigned long flags;
- spin_lock(&orig_hash_lock); + spin_lock_irqsave(&orig_hash_lock, flags);
/* for all origins... */ while (hash_iterate(orig_hash, &hashit)) { @@ -255,7 +259,7 @@ void purge_orig(struct work_struct *work) } }
- spin_unlock(&orig_hash_lock); + spin_unlock_irqrestore(&orig_hash_lock, flags);
start_purge_timer(); } diff --git a/drivers/staging/batman-adv/proc.c b/drivers/staging/batman-adv/proc.c index d9fde94..61e1d0d 100644 --- a/drivers/staging/batman-adv/proc.c +++ b/drivers/staging/batman-adv/proc.c @@ -189,6 +189,7 @@ static int proc_originators_read(struct seq_file *seq, void *offset) struct neigh_node *neigh_node; int batman_count = 0; char orig_str[ETH_STR_LEN], router_str[ETH_STR_LEN]; + unsigned long flags;
rcu_read_lock(); if (list_empty(&if_list)) { @@ -211,7 +212,7 @@ static int proc_originators_read(struct seq_file *seq, void *offset) ((struct batman_if *)if_list.next)->addr_str);
rcu_read_unlock(); - spin_lock(&orig_hash_lock); + spin_lock_irqsave(&orig_hash_lock, flags);
while (hash_iterate(orig_hash, &hashit)) {
@@ -242,7 +243,7 @@ static int proc_originators_read(struct seq_file *seq, void *offset)
}
- spin_unlock(&orig_hash_lock); + spin_unlock_irqrestore(&orig_hash_lock, flags);
if (batman_count == 0) seq_printf(seq, "No batman nodes in range ... \n"); @@ -376,6 +377,7 @@ static int proc_vis_data_read(struct seq_file *seq, void *offset) HLIST_HEAD(vis_if_list); int i; char tmp_addr_str[ETH_STR_LEN]; + unsigned long flags;
rcu_read_lock(); if (list_empty(&if_list) || (!is_vis_server())) { @@ -385,7 +387,7 @@ static int proc_vis_data_read(struct seq_file *seq, void *offset)
rcu_read_unlock();
- spin_lock(&vis_hash_lock); + spin_lock_irqsave(&vis_hash_lock, flags); while (hash_iterate(vis_hash, &hashit)) { info = hashit.bucket->data; entries = (struct vis_info_entry *) @@ -402,7 +404,7 @@ static int proc_vis_data_read(struct seq_file *seq, void *offset) proc_vis_read_prim_sec(seq, &vis_if_list); seq_printf(seq, "\n"); } - spin_unlock(&vis_hash_lock); + spin_unlock_irqrestore(&vis_hash_lock, flags);
end: return 0; diff --git a/drivers/staging/batman-adv/routing.c b/drivers/staging/batman-adv/routing.c index 25a1424..9cf1ee5 100644 --- a/drivers/staging/batman-adv/routing.c +++ b/drivers/staging/batman-adv/routing.c @@ -36,15 +36,16 @@
DECLARE_WAIT_QUEUE_HEAD(thread_wait);
-static atomic_t data_ready_cond; atomic_t exit_cond; + void slide_own_bcast_window(struct batman_if *batman_if) { HASHIT(hashit); struct orig_node *orig_node; TYPE_OF_WORD *word; + unsigned long flags;
- spin_lock(&orig_hash_lock); + spin_lock_irqsave(&orig_hash_lock, flags);
while (hash_iterate(orig_hash, &hashit)) { orig_node = hashit.bucket->data; @@ -55,7 +56,7 @@ void slide_own_bcast_window(struct batman_if *batman_if) bit_packet_count(word); }
- spin_unlock(&orig_hash_lock); + spin_unlock_irqrestore(&orig_hash_lock, flags); }
static void update_HNA(struct orig_node *orig_node, @@ -365,10 +366,9 @@ static char count_real_packets(struct ethhdr *ethhdr, }
void receive_bat_packet(struct ethhdr *ethhdr, - struct batman_packet *batman_packet, - unsigned char *hna_buff, - int hna_buff_len, - struct batman_if *if_incoming) + struct batman_packet *batman_packet, + unsigned char *hna_buff, int hna_buff_len, + struct batman_if *if_incoming) { struct batman_if *batman_if; struct orig_node *orig_neigh_node, *orig_node; @@ -566,95 +566,118 @@ void receive_bat_packet(struct ethhdr *ethhdr, 0, hna_buff_len, if_incoming); }
- -static int receive_raw_packet(struct socket *raw_sock, - unsigned char *packet_buff, int packet_buff_len) +int recv_bat_packet(struct sk_buff *skb, + struct batman_if *batman_if) { - struct kvec iov; - struct msghdr msg; + struct ethhdr *ethhdr; + unsigned long flags;
- iov.iov_base = packet_buff; - iov.iov_len = packet_buff_len; + /* drop packet if it has not necessary minimum size */ + if (skb_headlen(skb) < sizeof(struct batman_packet)) + return NET_RX_DROP;
- msg.msg_flags = MSG_DONTWAIT; /* non-blocking */ - msg.msg_name = NULL; - msg.msg_namelen = 0; - msg.msg_control = NULL; + ethhdr = (struct ethhdr *)skb_mac_header(skb);
- return kernel_recvmsg(raw_sock, &msg, &iov, 1, packet_buff_len, - MSG_DONTWAIT); -} - -static void recv_bat_packet(struct ethhdr *ethhdr, - unsigned char *packet_buff, - int result, - struct batman_if *batman_if) -{ /* packet with broadcast indication but unicast recipient */ if (!is_bcast(ethhdr->h_dest)) - return; + return NET_RX_DROP;
/* packet with broadcast sender address */ if (is_bcast(ethhdr->h_source)) - return; - - /* drop packet if it has not at least one batman packet as payload */ - if (result < sizeof(struct ethhdr) + sizeof(struct batman_packet)) - return; - - spin_lock(&orig_hash_lock); + return NET_RX_DROP; + + spin_lock_irqsave(&orig_hash_lock, flags); + /* TODO: we use headlen instead of "length", because + * only this data is paged in. */ + /* TODO: is another skb_copy needed here? there will be + * written on the data, but nobody (?) should further use + * this data */ receive_aggr_bat_packet(ethhdr, - packet_buff + sizeof(struct ethhdr), - result - sizeof(struct ethhdr), + skb->data, + skb_headlen(skb), batman_if); - spin_unlock(&orig_hash_lock); + spin_unlock_irqrestore(&orig_hash_lock, flags); + + kfree_skb(skb); + return NET_RX_SUCCESS; }
-static void recv_my_icmp_packet(struct ethhdr *ethhdr, - struct icmp_packet *icmp_packet, - unsigned char *packet_buff, - int result) +static int recv_my_icmp_packet(struct sk_buff *skb) { struct orig_node *orig_node; + struct icmp_packet *icmp_packet; + struct ethhdr *ethhdr; + struct sk_buff *skb_old; + struct batman_if *batman_if; + int ret; + unsigned long flags; + uint8_t dstaddr[ETH_ALEN]; + + icmp_packet = (struct icmp_packet *) skb->data; + ethhdr = (struct ethhdr *) skb_mac_header(skb);
/* add data to device queue */ if (icmp_packet->msg_type != ECHO_REQUEST) { bat_device_receive_packet(icmp_packet); - return; + return NET_RX_DROP; }
/* answer echo request (ping) */ /* get routing information */ - spin_lock(&orig_hash_lock); + spin_lock_irqsave(&orig_hash_lock, flags); orig_node = ((struct orig_node *)hash_find(orig_hash, icmp_packet->orig)); + ret = NET_RX_DROP;
if ((orig_node != NULL) && (orig_node->batman_if != NULL) && (orig_node->router != NULL)) { + + /* don't lock while sending the packets ... we therefore + * copy the required data before sending */ + batman_if = orig_node->batman_if; + memcpy(dstaddr, orig_node->router->addr, ETH_ALEN); + spin_unlock_irqrestore(&orig_hash_lock, flags); + + /* create a copy of the skb, if needed, to modify it. */ + skb_old = NULL; + if (!skb_clone_writable(skb, sizeof(struct icmp_packet))) { + skb_old = skb; + skb = skb_copy(skb, GFP_ATOMIC); + if (!skb) + return NET_RX_DROP; + icmp_packet = (struct icmp_packet *) skb->data; + kfree_skb(skb_old); + } + memcpy(icmp_packet->dst, icmp_packet->orig, ETH_ALEN); memcpy(icmp_packet->orig, ethhdr->h_dest, ETH_ALEN); icmp_packet->msg_type = ECHO_REPLY; icmp_packet->ttl = TTL;
- send_raw_packet(packet_buff + sizeof(struct ethhdr), - result - sizeof(struct ethhdr), - orig_node->batman_if, - orig_node->router->addr); - } + send_skb_packet(skb, batman_if, dstaddr); + ret = NET_RX_SUCCESS;
- spin_unlock(&orig_hash_lock); - return; + } else + spin_unlock_irqrestore(&orig_hash_lock, flags); + + return ret; }
-static void recv_icmp_ttl_exceeded(struct icmp_packet *icmp_packet, - struct ethhdr *ethhdr, - unsigned char *packet_buff, - int result, - struct batman_if *batman_if) +static int recv_icmp_ttl_exceeded(struct sk_buff *skb) { unsigned char src_str[ETH_STR_LEN], dst_str[ETH_STR_LEN]; struct orig_node *orig_node; + struct icmp_packet *icmp_packet; + struct ethhdr *ethhdr; + struct sk_buff *skb_old; + struct batman_if *batman_if; + int ret; + unsigned long flags; + uint8_t dstaddr[ETH_ALEN]; + + icmp_packet = (struct icmp_packet *) skb->data; + ethhdr = (struct ethhdr *) skb_mac_header(skb);
addr_to_string(src_str, icmp_packet->orig); addr_to_string(dst_str, icmp_packet->dst); @@ -663,74 +686,93 @@ static void recv_icmp_ttl_exceeded(struct icmp_packet *icmp_packet,
/* send TTL exceeded if packet is an echo request (traceroute) */ if (icmp_packet->msg_type != ECHO_REQUEST) - return; + return NET_RX_DROP;
/* get routing information */ - spin_lock(&orig_hash_lock); + spin_lock_irqsave(&orig_hash_lock, flags); orig_node = ((struct orig_node *) hash_find(orig_hash, icmp_packet->orig)); + ret = NET_RX_DROP;
if ((orig_node != NULL) && (orig_node->batman_if != NULL) && (orig_node->router != NULL)) { + + /* don't lock while sending the packets ... we therefore + * copy the required data before sending */ + batman_if = orig_node->batman_if; + memcpy(dstaddr, orig_node->router->addr, ETH_ALEN); + spin_unlock_irqrestore(&orig_hash_lock, flags); + + /* create a copy of the skb, if needed, to modify it. */ + if (!skb_clone_writable(skb, sizeof(struct icmp_packet))) { + skb_old = skb; + skb = skb_copy(skb, GFP_ATOMIC); + if (!skb) + return NET_RX_DROP; + icmp_packet = (struct icmp_packet *) skb->data; + kfree_skb(skb_old); + } + memcpy(icmp_packet->dst, icmp_packet->orig, ETH_ALEN); memcpy(icmp_packet->orig, ethhdr->h_dest, ETH_ALEN); icmp_packet->msg_type = TTL_EXCEEDED; icmp_packet->ttl = TTL;
- send_raw_packet(packet_buff + sizeof(struct ethhdr), - result - sizeof(struct ethhdr), - orig_node->batman_if, - orig_node->router->addr); + send_skb_packet(skb, batman_if, dstaddr); + ret = NET_RX_SUCCESS;
- } + } else + spin_unlock_irqrestore(&orig_hash_lock, flags);
- spin_unlock(&orig_hash_lock); + return ret; }
- -static void recv_icmp_packet(struct ethhdr *ethhdr, - unsigned char *packet_buff, - int result, - struct batman_if *batman_if) +int recv_icmp_packet(struct sk_buff *skb) { struct icmp_packet *icmp_packet; + struct ethhdr *ethhdr; struct orig_node *orig_node; + struct sk_buff *skb_old; + struct batman_if *batman_if; + int hdr_size = sizeof(struct icmp_packet); + int ret; + unsigned long flags; + uint8_t dstaddr[ETH_ALEN]; + + /* drop packet if it has not necessary minimum size */ + if (skb_headlen(skb) < hdr_size) + return NET_RX_DROP; + + ethhdr = (struct ethhdr *)skb_mac_header(skb);
/* packet with unicast indication but broadcast recipient */ if (is_bcast(ethhdr->h_dest)) - return; + return NET_RX_DROP;
/* packet with broadcast sender address */ if (is_bcast(ethhdr->h_source)) - return; + return NET_RX_DROP;
/* not for me */ if (!is_my_mac(ethhdr->h_dest)) - return; + return NET_RX_DROP;
- /* drop packet if it has not necessary minimum size */ - if (result < sizeof(struct ethhdr) + sizeof(struct icmp_packet)) - return; - - icmp_packet = (struct icmp_packet *) - (packet_buff + sizeof(struct ethhdr)); + icmp_packet = (struct icmp_packet *) skb->data;
/* packet for me */ if (is_my_mac(icmp_packet->dst)) - recv_my_icmp_packet(ethhdr, icmp_packet, packet_buff, result); + return recv_my_icmp_packet(skb);
/* TTL exceeded */ - if (icmp_packet->ttl < 2) { - recv_icmp_ttl_exceeded(icmp_packet, ethhdr, packet_buff, result, - batman_if); - return; + if (icmp_packet->ttl < 2) + return recv_icmp_ttl_exceeded(skb);
- } + ret = NET_RX_DROP;
/* get routing information */ - spin_lock(&orig_hash_lock); + spin_lock_irqsave(&orig_hash_lock, flags); orig_node = ((struct orig_node *) hash_find(orig_hash, icmp_packet->dst));
@@ -738,133 +780,169 @@ static void recv_icmp_packet(struct ethhdr *ethhdr, (orig_node->batman_if != NULL) && (orig_node->router != NULL)) {
+ /* don't lock while sending the packets ... we therefore + * copy the required data before sending */ + batman_if = orig_node->batman_if; + memcpy(dstaddr, orig_node->router->addr, ETH_ALEN); + spin_unlock_irqrestore(&orig_hash_lock, flags); + + /* create a copy of the skb, if needed, to modify it. */ + if (!skb_clone_writable(skb, sizeof(struct icmp_packet))) { + skb_old = skb; + skb = skb_copy(skb, GFP_ATOMIC); + if (!skb) + return NET_RX_DROP; + icmp_packet = (struct icmp_packet *) skb->data; + kfree_skb(skb_old); + } + /* decrement ttl */ icmp_packet->ttl--;
/* route it */ - send_raw_packet(packet_buff + sizeof(struct ethhdr), - result - sizeof(struct ethhdr), - orig_node->batman_if, - orig_node->router->addr); - } - spin_unlock(&orig_hash_lock); + send_skb_packet(skb, batman_if, dstaddr); + ret = NET_RX_SUCCESS; + + } else + spin_unlock_irqrestore(&orig_hash_lock, flags); + + return ret; }
-static void recv_unicast_packet(struct ethhdr *ethhdr, - unsigned char *packet_buff, - int result, - struct batman_if *batman_if) +int recv_unicast_packet(struct sk_buff *skb) { struct unicast_packet *unicast_packet; unsigned char src_str[ETH_STR_LEN], dst_str[ETH_STR_LEN]; struct orig_node *orig_node; - int hdr_size = sizeof(struct ethhdr) + sizeof(struct unicast_packet); + struct ethhdr *ethhdr; + struct batman_if *batman_if; + struct sk_buff *skb_old; + uint8_t dstaddr[ETH_ALEN]; + int hdr_size = sizeof(struct unicast_packet); + int ret; + unsigned long flags; + + /* drop packet if it has not necessary minimum size */ + if (skb_headlen(skb) < hdr_size) + return NET_RX_DROP; + + ethhdr = (struct ethhdr *) skb_mac_header(skb);
/* packet with unicast indication but broadcast recipient */ if (is_bcast(ethhdr->h_dest)) - return; + return NET_RX_DROP;
/* packet with broadcast sender address */ if (is_bcast(ethhdr->h_source)) - return; + return NET_RX_DROP;
/* not for me */ if (!is_my_mac(ethhdr->h_dest)) - return; - - /* drop packet if it has not necessary minimum size */ - if (result < hdr_size) - return; + return NET_RX_DROP;
- unicast_packet = (struct unicast_packet *) - (packet_buff + sizeof(struct ethhdr)); + unicast_packet = (struct unicast_packet *) skb->data;
/* packet for me */ if (is_my_mac(unicast_packet->dest)) { - interface_rx(soft_device, packet_buff + hdr_size, - result - hdr_size); - return; - + interface_rx(skb, hdr_size); + return NET_RX_SUCCESS; }
/* TTL exceeded */ if (unicast_packet->ttl < 2) { - addr_to_string(src_str, ((struct ethhdr *) - (unicast_packet + 1))->h_source); - addr_to_string(dst_str, unicast_packet->dest); + addr_to_string(src_str, ethhdr->h_source); + addr_to_string(dst_str, ethhdr->h_dest);
printk(KERN_WARNING "batman-adv:Warning - can't send packet from %s to %s: ttl exceeded\n", src_str, dst_str); - return; + return NET_RX_DROP; }
+ ret = NET_RX_DROP; /* get routing information */ - spin_lock(&orig_hash_lock); + spin_lock_irqsave(&orig_hash_lock, flags); orig_node = ((struct orig_node *) hash_find(orig_hash, unicast_packet->dest));
if ((orig_node != NULL) && (orig_node->batman_if != NULL) && (orig_node->router != NULL)) { + + /* don't lock while sending the packets ... we therefore + * copy the required data before sending */ + batman_if = orig_node->batman_if; + memcpy(dstaddr, orig_node->router->addr, ETH_ALEN); + spin_unlock_irqrestore(&orig_hash_lock, flags); + + /* create a copy of the skb, if needed, to modify it. */ + if (!skb_clone_writable(skb, sizeof(struct unicast_packet))) { + skb_old = skb; + skb = skb_copy(skb, GFP_ATOMIC); + if (!skb) + return NET_RX_DROP; + unicast_packet = (struct unicast_packet *) skb->data; + kfree_skb(skb_old); + } /* decrement ttl */ unicast_packet->ttl--;
/* route it */ - send_raw_packet(packet_buff + sizeof(struct ethhdr), - result - sizeof(struct ethhdr), - orig_node->batman_if, - orig_node->router->addr); - } - spin_unlock(&orig_hash_lock); + send_skb_packet(skb, batman_if, dstaddr); + ret = NET_RX_SUCCESS; + + } else + spin_unlock_irqrestore(&orig_hash_lock, flags); + + return ret; }
-static void recv_bcast_packet(struct ethhdr *ethhdr, - unsigned char *packet_buff, - int result, - struct batman_if *batman_if) +int recv_bcast_packet(struct sk_buff *skb) { struct orig_node *orig_node; struct bcast_packet *bcast_packet; - int hdr_size = sizeof(struct ethhdr) + sizeof(struct bcast_packet); + struct ethhdr *ethhdr; + int hdr_size = sizeof(struct bcast_packet); + unsigned long flags; + + /* drop packet if it has not necessary minimum size */ + if (skb_headlen(skb) < hdr_size) + return NET_RX_DROP; + + ethhdr = (struct ethhdr *)skb_mac_header(skb);
/* packet with broadcast indication but unicast recipient */ if (!is_bcast(ethhdr->h_dest)) - return; + return NET_RX_DROP;
/* packet with broadcast sender address */ if (is_bcast(ethhdr->h_source)) - return; - - /* drop packet if it has not necessary minimum size */ - if (result < hdr_size) - return; + return NET_RX_DROP;
/* ignore broadcasts sent by myself */ if (is_my_mac(ethhdr->h_source)) - return; + return NET_RX_DROP;
- bcast_packet = (struct bcast_packet *) - (packet_buff + sizeof(struct ethhdr)); + bcast_packet = (struct bcast_packet *) skb->data;
/* ignore broadcasts originated by myself */ if (is_my_mac(bcast_packet->orig)) - return; + return NET_RX_DROP;
- spin_lock(&orig_hash_lock); + spin_lock_irqsave(&orig_hash_lock, flags); orig_node = ((struct orig_node *) hash_find(orig_hash, bcast_packet->orig));
if (orig_node == NULL) { - spin_unlock(&orig_hash_lock); - return; + spin_unlock_irqrestore(&orig_hash_lock, flags); + return NET_RX_DROP; }
/* check flood history */ if (get_bit_status(orig_node->bcast_bits, orig_node->last_bcast_seqno, ntohs(bcast_packet->seqno))) { - spin_unlock(&orig_hash_lock); - return; + spin_unlock_irqrestore(&orig_hash_lock, flags); + return NET_RX_DROP; }
/* mark broadcast in flood history */ @@ -873,210 +951,59 @@ static void recv_bcast_packet(struct ethhdr *ethhdr, orig_node->last_bcast_seqno, 1)) orig_node->last_bcast_seqno = ntohs(bcast_packet->seqno);
- spin_unlock(&orig_hash_lock); + spin_unlock_irqrestore(&orig_hash_lock, flags); + + /* rebroadcast packet */ + add_bcast_packet_to_list(skb);
/* broadcast for me */ - interface_rx(soft_device, packet_buff + hdr_size, result - hdr_size); + interface_rx(skb, hdr_size);
- /* rebroadcast packet */ - add_bcast_packet_to_list(packet_buff + sizeof(struct ethhdr), - result - sizeof(struct ethhdr)); + return NET_RX_SUCCESS; }
-static void recv_vis_packet(struct ethhdr *ethhdr, - unsigned char *packet_buff, - int result) +int recv_vis_packet(struct sk_buff *skb) { struct vis_packet *vis_packet; - int hdr_size = sizeof(struct ethhdr) + sizeof(struct vis_packet); - int vis_info_len; + struct ethhdr *ethhdr; + int hdr_size = sizeof(struct vis_packet); + int ret;
- /* drop if too short. */ - if (result < hdr_size) - return; + if (skb_headlen(skb) < hdr_size) + return NET_RX_DROP; + + vis_packet = (struct vis_packet *) skb->data; + ethhdr = (struct ethhdr *)skb_mac_header(skb);
/* not for me */ if (!is_my_mac(ethhdr->h_dest)) - return; - - vis_packet = (struct vis_packet *)(packet_buff + sizeof(struct ethhdr)); - vis_info_len = result - hdr_size; + return NET_RX_DROP;
/* ignore own packets */ if (is_my_mac(vis_packet->vis_orig)) - return; + return NET_RX_DROP;
if (is_my_mac(vis_packet->sender_orig)) - return; + return NET_RX_DROP;
switch (vis_packet->vis_type) { case VIS_TYPE_SERVER_SYNC: - receive_server_sync_packet(vis_packet, vis_info_len); + /* TODO: handle fragmented skbs properly */ + receive_server_sync_packet(vis_packet, skb_headlen(skb)); + ret = NET_RX_SUCCESS; break;
case VIS_TYPE_CLIENT_UPDATE: - receive_client_update_packet(vis_packet, vis_info_len); + /* TODO: handle fragmented skbs properly */ + receive_client_update_packet(vis_packet, skb_headlen(skb)); + ret = NET_RX_SUCCESS; break;
default: /* ignore unknown packet */ + ret = NET_RX_DROP; break; } + return ret; }
-static int recv_one_packet(struct batman_if *batman_if, - unsigned char *packet_buff) -{ - int result; - struct ethhdr *ethhdr; - struct batman_packet *batman_packet; - - result = receive_raw_packet(batman_if->raw_sock, packet_buff, - PACKBUFF_SIZE); - if (result <= 0) - return result; - - if (result < sizeof(struct ethhdr) + 2) - return 0; - - ethhdr = (struct ethhdr *)packet_buff; - batman_packet = (struct batman_packet *) - (packet_buff + sizeof(struct ethhdr)); - - if (batman_packet->version != COMPAT_VERSION) { - bat_dbg(DBG_BATMAN, - "Drop packet: incompatible batman version (%i)\n", - batman_packet->version); - return 0; - } - - switch (batman_packet->packet_type) { - /* batman originator packet */ - case BAT_PACKET: - recv_bat_packet(ethhdr, packet_buff, result, batman_if); - break; - - /* batman icmp packet */ - case BAT_ICMP: - recv_icmp_packet(ethhdr, packet_buff, result, batman_if); - break; - - /* unicast packet */ - case BAT_UNICAST: - recv_unicast_packet(ethhdr, packet_buff, result, batman_if); - break; - - /* broadcast packet */ - case BAT_BCAST: - recv_bcast_packet(ethhdr, - packet_buff, result, batman_if); - break; - - /* vis packet */ - case BAT_VIS: - recv_vis_packet(ethhdr, packet_buff, result); - break; - } - return 0; -} - - -static int discard_one_packet(struct batman_if *batman_if, - unsigned char *packet_buff) -{ - int result = -EAGAIN; - - if (batman_if->raw_sock) { - result = receive_raw_packet(batman_if->raw_sock, - packet_buff, - PACKBUFF_SIZE); - } - return result; -} - - -static bool is_interface_active(struct batman_if *batman_if) -{ - if (batman_if->if_active != IF_ACTIVE) - return false; - - return true; -} - -static void service_interface(struct batman_if *batman_if, - unsigned char *packet_buff) - -{ - int result; - - do { - if (is_interface_active(batman_if)) - result = recv_one_packet(batman_if, packet_buff); - else - result = discard_one_packet(batman_if, packet_buff); - } while (result >= 0); - - /* we perform none blocking reads, so EAGAIN indicates there - are no more packets to read. Anything else is a real - error.*/
- if ((result < 0) && (result != -EAGAIN)) - printk(KERN_ERR "batman-adv:Could not receive packet from interface %s: %i\n", batman_if->dev, result); -} - -static void service_interfaces(unsigned char *packet_buffer) -{ - struct batman_if *batman_if; - rcu_read_lock(); - list_for_each_entry_rcu(batman_if, &if_list, list) { - rcu_read_unlock(); - service_interface(batman_if, packet_buffer); - rcu_read_lock(); - } - rcu_read_unlock(); -} - - -int packet_recv_thread(void *data) -{ - unsigned char *packet_buff; - - atomic_set(&data_ready_cond, 0); - atomic_set(&exit_cond, 0); - packet_buff = kmalloc(PACKBUFF_SIZE, GFP_KERNEL); - if (!packet_buff) { - printk(KERN_ERR"batman-adv:Could allocate memory for the packet buffer. :(\n"); - return -1; - } - - while ((!kthread_should_stop()) && (!atomic_read(&exit_cond))) { - - wait_event_interruptible(thread_wait, - (atomic_read(&data_ready_cond) || - atomic_read(&exit_cond))); - - atomic_set(&data_ready_cond, 0); - - if (kthread_should_stop() || atomic_read(&exit_cond)) - break; - - service_interfaces(packet_buff); - } - kfree(packet_buff); - - /* do not exit until kthread_stop() is actually called, - * otherwise it will wait for us forever. */ - while (!kthread_should_stop()) - schedule(); - - return 0; -} - -void batman_data_ready(struct sock *sk, int len) -{ - void (*data_ready)(struct sock *, int) = sk->sk_user_data; - - data_ready(sk, len); - - atomic_set(&data_ready_cond, 1); - wake_up_interruptible(&thread_wait); -} diff --git a/drivers/staging/batman-adv/routing.h b/drivers/staging/batman-adv/routing.h index 890a4f5..c217241 100644 --- a/drivers/staging/batman-adv/routing.h +++ b/drivers/staging/batman-adv/routing.h @@ -25,8 +25,6 @@ extern wait_queue_head_t thread_wait; extern atomic_t exit_cond;
void slide_own_bcast_window(struct batman_if *batman_if); -void batman_data_ready(struct sock *sk, int len); -int packet_recv_thread(void *data); void receive_bat_packet(struct ethhdr *ethhdr, struct batman_packet *batman_packet, unsigned char *hna_buff, int hna_buff_len, @@ -34,3 +32,9 @@ void receive_bat_packet(struct ethhdr *ethhdr, void update_routes(struct orig_node *orig_node, struct neigh_node *neigh_node, unsigned char *hna_buff, int hna_buff_len); +int recv_icmp_packet(struct sk_buff *skb); +int recv_unicast_packet(struct sk_buff *skb); +int recv_bcast_packet(struct sk_buff *skb); +int recv_vis_packet(struct sk_buff *skb); +int recv_bat_packet(struct sk_buff *skb, + struct batman_if *batman_if); diff --git a/drivers/staging/batman-adv/send.c b/drivers/staging/batman-adv/send.c index 49b1534..fd48f3f 100644 --- a/drivers/staging/batman-adv/send.c +++ b/drivers/staging/batman-adv/send.c @@ -23,6 +23,7 @@ #include "send.h" #include "routing.h" #include "translation-table.h" +#include "soft-interface.h" #include "hard-interface.h" #include "types.h" #include "vis.h" @@ -58,51 +59,69 @@ static unsigned long forward_send_time(void) return send_time; }
-/* sends a raw packet. */ -void send_raw_packet(unsigned char *pack_buff, int pack_buff_len, - struct batman_if *batman_if, uint8_t *dst_addr) +/* send out an already prepared packet to the given address via the + * specified batman interface */ +int send_skb_packet(struct sk_buff *skb, + struct batman_if *batman_if, + uint8_t *dst_addr) { struct ethhdr *ethhdr; - struct sk_buff *skb; - int retval; - char *data;
if (batman_if->if_active != IF_ACTIVE) - return; + goto send_skb_err; + + if (unlikely(!batman_if->net_dev)) + goto send_skb_err;
if (!(batman_if->net_dev->flags & IFF_UP)) { printk(KERN_WARNING "batman-adv:Interface %s is not up - can't send packet via that interface!\n", batman_if->dev); - return; + goto send_skb_err; }
- skb = dev_alloc_skb(pack_buff_len + sizeof(struct ethhdr)); - if (!skb) - return; - data = skb_put(skb, pack_buff_len + sizeof(struct ethhdr)); + /* push to the ethernet header. */ + if (my_skb_push(skb, sizeof(struct ethhdr)) < 0) + goto send_skb_err;
- memcpy(data + sizeof(struct ethhdr), pack_buff, pack_buff_len); + skb_reset_mac_header(skb);
- ethhdr = (struct ethhdr *) data; + ethhdr = (struct ethhdr *) skb_mac_header(skb); memcpy(ethhdr->h_source, batman_if->net_dev->dev_addr, ETH_ALEN); memcpy(ethhdr->h_dest, dst_addr, ETH_ALEN); ethhdr->h_proto = __constant_htons(ETH_P_BATMAN);
- skb_reset_mac_header(skb); skb_set_network_header(skb, ETH_HLEN); skb->priority = TC_PRIO_CONTROL; skb->protocol = __constant_htons(ETH_P_BATMAN); + skb->dev = batman_if->net_dev;
/* dev_queue_xmit() returns a negative result on error. However on * congestion and traffic shaping, it drops and returns NET_XMIT_DROP * (which is > 0). This will not be treated as an error. */ - retval = dev_queue_xmit(skb); - if (retval < 0) - printk(KERN_WARNING - "batman-adv:Can't write to raw socket: %i\n", - retval); + + return dev_queue_xmit(skb); +send_skb_err: + kfree_skb(skb); + return NET_XMIT_DROP; +} + +/* sends a raw packet. */ +void send_raw_packet(unsigned char *pack_buff, int pack_buff_len, + struct batman_if *batman_if, uint8_t *dst_addr) +{ + struct sk_buff *skb; + char *data; + + skb = dev_alloc_skb(pack_buff_len + sizeof(struct ethhdr)); + if (!skb) + return; + data = skb_put(skb, pack_buff_len + sizeof(struct ethhdr)); + memcpy(data + sizeof(struct ethhdr), pack_buff, pack_buff_len); + /* pull back to the batman "network header" */ + skb_pull(skb, sizeof(struct ethhdr)); + send_skb_packet(skb, batman_if, dst_addr); }
/* Send a packet to a given interface */ @@ -331,6 +350,8 @@ void schedule_forward_packet(struct orig_node *orig_node,
static void forw_packet_free(struct forw_packet *forw_packet) { + if (forw_packet->skb) + kfree_skb(forw_packet->skb); kfree(forw_packet->packet_buff); kfree(forw_packet); } @@ -353,7 +374,7 @@ static void _add_bcast_packet_to_list(struct forw_packet *forw_packet, send_time); }
-void add_bcast_packet_to_list(unsigned char *packet_buff, int packet_len) +void add_bcast_packet_to_list(struct sk_buff *skb) { struct forw_packet *forw_packet;
@@ -361,14 +382,16 @@ void add_bcast_packet_to_list(unsigned char *packet_buff, int packet_len) if (!forw_packet) return;
- forw_packet->packet_buff = kmalloc(packet_len, GFP_ATOMIC); - if (!forw_packet->packet_buff) { + skb = skb_copy(skb, GFP_ATOMIC); + if (!skb) { kfree(forw_packet); return; }
- forw_packet->packet_len = packet_len; - memcpy(forw_packet->packet_buff, packet_buff, forw_packet->packet_len); + skb_reset_mac_header(skb); + + forw_packet->skb = skb; + forw_packet->packet_buff = NULL;
/* how often did we send the bcast packet ? */ forw_packet->num_packets = 0; @@ -384,6 +407,7 @@ void send_outstanding_bcast_packet(struct work_struct *work) struct forw_packet *forw_packet = container_of(delayed_work, struct forw_packet, delayed_work); unsigned long flags; + struct sk_buff *skb1;
spin_lock_irqsave(&forw_bcast_list_lock, flags); hlist_del(&forw_packet->list); @@ -392,8 +416,10 @@ void send_outstanding_bcast_packet(struct work_struct *work) /* rebroadcast packet */ rcu_read_lock(); list_for_each_entry_rcu(batman_if, &if_list, list) { - send_raw_packet(forw_packet->packet_buff, - forw_packet->packet_len, + /* send a copy of the saved skb */ + skb1 = skb_copy(forw_packet->skb, GFP_ATOMIC); + if (skb1) + send_skb_packet(skb1, batman_if, broadcastAddr); } rcu_read_unlock(); @@ -415,10 +441,11 @@ void send_outstanding_bat_packet(struct work_struct *work) container_of(work, struct delayed_work, work); struct forw_packet *forw_packet = container_of(delayed_work, struct forw_packet, delayed_work); + unsigned long flags;
- spin_lock(&forw_bat_list_lock); + spin_lock_irqsave(&forw_bat_list_lock, flags); hlist_del(&forw_packet->list); - spin_unlock(&forw_bat_list_lock); + spin_unlock_irqrestore(&forw_bat_list_lock, flags);
send_packet(forw_packet);
@@ -459,18 +486,18 @@ void purge_outstanding_packets(void) spin_unlock_irqrestore(&forw_bcast_list_lock, flags);
/* free batman packet list */ - spin_lock(&forw_bat_list_lock); + spin_lock_irqsave(&forw_bat_list_lock, flags); hlist_for_each_entry_safe(forw_packet, tmp_node, safe_tmp_node, &forw_bat_list, list) {
- spin_unlock(&forw_bat_list_lock); + spin_unlock_irqrestore(&forw_bat_list_lock, flags);
/** * send_outstanding_bat_packet() will lock the list to * delete the item from the list */ cancel_delayed_work_sync(&forw_packet->delayed_work); - spin_lock(&forw_bat_list_lock); + spin_lock_irqsave(&forw_bat_list_lock, flags); } - spin_unlock(&forw_bat_list_lock); + spin_unlock_irqrestore(&forw_bat_list_lock, flags); } diff --git a/drivers/staging/batman-adv/send.h b/drivers/staging/batman-adv/send.h index 59d5009..5fc6f34 100644 --- a/drivers/staging/batman-adv/send.h +++ b/drivers/staging/batman-adv/send.h @@ -22,6 +22,9 @@ #include "types.h"
void send_own_packet_work(struct work_struct *work); +int send_skb_packet(struct sk_buff *skb, + struct batman_if *batman_if, + uint8_t *dst_addr); void send_raw_packet(unsigned char *pack_buff, int pack_buff_len, struct batman_if *batman_if, uint8_t *dst_addr); void schedule_own_packet(struct batman_if *batman_if); @@ -30,7 +33,7 @@ void schedule_forward_packet(struct orig_node *orig_node, struct batman_packet *batman_packet, uint8_t directlink, int hna_buff_len, struct batman_if *if_outgoing); -void add_bcast_packet_to_list(unsigned char *packet_buff, int packet_len); +void add_bcast_packet_to_list(struct sk_buff *skb); void send_outstanding_bcast_packet(struct work_struct *work); void send_outstanding_bat_packet(struct work_struct *work); void purge_outstanding_packets(void); diff --git a/drivers/staging/batman-adv/soft-interface.c b/drivers/staging/batman-adv/soft-interface.c index 168a4e1..8ae3483 100644 --- a/drivers/staging/batman-adv/soft-interface.c +++ b/drivers/staging/batman-adv/soft-interface.c @@ -34,7 +34,6 @@ static uint16_t bcast_seqno = 1; /* give own bcast messages seq numbers to avoid * broadcast storms */ static int32_t skb_packets; static int32_t skb_bad_packets; -static int32_t lock_dropped;
unsigned char mainIfAddr[ETH_ALEN]; static unsigned char mainIfAddr_default[ETH_ALEN]; @@ -67,12 +66,12 @@ int main_if_was_up(void) return (memcmp(mainIfAddr, mainIfAddr_default, ETH_ALEN) != 0 ? 1 : 0); }
-static int my_skb_push(struct sk_buff *skb, unsigned int len) +int my_skb_push(struct sk_buff *skb, unsigned int len) { int result = 0;
skb_packets++; - if (skb->data - len < skb->head) { + if (skb_headroom(skb) < len) { skb_bad_packets++; result = pskb_expand_head(skb, len, 0, GFP_ATOMIC);
@@ -169,7 +168,10 @@ int interface_tx(struct sk_buff *skb, struct net_device *dev) struct orig_node *orig_node; struct ethhdr *ethhdr = (struct ethhdr *)skb->data; struct bat_priv *priv = netdev_priv(dev); + struct batman_if *batman_if; + uint8_t dstaddr[6]; int data_len = skb->len; + unsigned long flags;
if (atomic_read(&module_state) != MODULE_ACTIVE) goto dropped; @@ -185,7 +187,6 @@ int interface_tx(struct sk_buff *skb, struct net_device *dev) goto dropped;
bcast_packet = (struct bcast_packet *)skb->data; - bcast_packet->version = COMPAT_VERSION;
/* batman packet type: broadcast */ @@ -194,27 +195,21 @@ int interface_tx(struct sk_buff *skb, struct net_device *dev) /* hw address of first interface is the orig mac because only * this mac is known throughout the mesh */ memcpy(bcast_packet->orig, mainIfAddr, ETH_ALEN); + /* set broadcast sequence number */ bcast_packet->seqno = htons(bcast_seqno);
bcast_seqno++;
/* broadcast packet */ - add_bcast_packet_to_list(skb->data, skb->len); + add_bcast_packet_to_list(skb); + /* a copy is stored in the bcast list, therefore removing + * the original skb. */ + kfree_skb(skb);
/* unicast packet */ } else { - - /* simply spin_lock()ing can deadlock when the lock is already - * hold. */ - /* TODO: defer the work in a working queue instead of - * dropping */ - if (!spin_trylock(&orig_hash_lock)) { - lock_dropped++; - printk(KERN_WARNING "batman-adv:%d packets dropped because lock was hold\n", lock_dropped); - goto dropped; - } - + spin_lock_irqsave(&orig_hash_lock, flags); /* get routing information */ orig_node = ((struct orig_node *)hash_find(orig_hash, ethhdr->h_dest)); @@ -243,14 +238,17 @@ int interface_tx(struct sk_buff *skb, struct net_device *dev) if (orig_node->batman_if->if_active != IF_ACTIVE) goto unlock;
- send_raw_packet(skb->data, skb->len, - orig_node->batman_if, - orig_node->router->addr); + /* don't lock while sending the packets ... we therefore + * copy the required data before sending */ + + batman_if = orig_node->batman_if; + memcpy(dstaddr, orig_node->router->addr, ETH_ALEN); + spin_unlock_irqrestore(&orig_hash_lock, flags); + + send_skb_packet(skb, batman_if, dstaddr); } else { goto unlock; } - - spin_unlock(&orig_hash_lock); }
priv->stats.tx_packets++; @@ -258,42 +256,44 @@ int interface_tx(struct sk_buff *skb, struct net_device *dev) goto end;
unlock: - spin_unlock(&orig_hash_lock); + spin_unlock_irqrestore(&orig_hash_lock, flags); dropped: priv->stats.tx_dropped++; end: - kfree_skb(skb); return 0; }
-void interface_rx(struct net_device *dev, void *packet, int packet_len) +void interface_rx(struct sk_buff *skb, int hdr_size) { - struct sk_buff *skb; + struct net_device *dev = soft_device; struct bat_priv *priv = netdev_priv(dev);
- skb = dev_alloc_skb(packet_len); - - if (!skb) { - priv->stats.rx_dropped++; - goto out; + /* check if enough space is available for pulling, and pull */ + if (!pskb_may_pull(skb, hdr_size)) { + kfree_skb(skb); + return; } + skb_pull_rcsum(skb, hdr_size); +/* skb_set_mac_header(skb, -sizeof(struct ethhdr));*/
- memcpy(skb_put(skb, packet_len), packet, packet_len); - - /* Write metadata, and then pass to the receive level */ skb->dev = dev; skb->protocol = eth_type_trans(skb, dev); - skb->ip_summed = CHECKSUM_UNNECESSARY; + + /* should not be neccesary anymore as we use skb_pull_rcsum() + * TODO: please verify this and remove this TODO + * -- Dec 21st 2009, Simon Wunderlich */ + +/* skb->ip_summed = CHECKSUM_UNNECESSARY;*/ + + /* TODO: set skb->pkt_type to PACKET_BROADCAST, PACKET_MULTICAST, + * PACKET_OTHERHOST or PACKET_HOST */
priv->stats.rx_packets++; - priv->stats.rx_bytes += packet_len; + priv->stats.rx_bytes += skb->len;
dev->last_rx = jiffies;
netif_rx(skb); - -out: - return; }
/* ethtool */ diff --git a/drivers/staging/batman-adv/soft-interface.h b/drivers/staging/batman-adv/soft-interface.h index 515e276..c0cad81 100644 --- a/drivers/staging/batman-adv/soft-interface.h +++ b/drivers/staging/batman-adv/soft-interface.h @@ -28,6 +28,7 @@ struct net_device_stats *interface_stats(struct net_device *dev); int interface_set_mac_addr(struct net_device *dev, void *addr); int interface_change_mtu(struct net_device *dev, int new_mtu); int interface_tx(struct sk_buff *skb, struct net_device *dev); -void interface_rx(struct net_device *dev, void *packet, int packet_len); +void interface_rx(struct sk_buff *skb, int hdr_size); +int my_skb_push(struct sk_buff *skb, unsigned int len);
extern unsigned char mainIfAddr[]; diff --git a/drivers/staging/batman-adv/types.h b/drivers/staging/batman-adv/types.h index d708e6f..dec1b54 100644 --- a/drivers/staging/batman-adv/types.h +++ b/drivers/staging/batman-adv/types.h @@ -39,7 +39,6 @@ struct batman_if { char if_active; char addr_str[ETH_STR_LEN]; struct net_device *net_dev; - struct socket *raw_sock; atomic_t seqno; unsigned char *packet_buff; int packet_len; @@ -113,6 +112,7 @@ struct forw_packet { /* structure for forw_list maintaining packet struct hlist_node list; unsigned long send_time; uint8_t own; + struct sk_buff *skb; unsigned char *packet_buff; uint16_t packet_len; uint32_t direct_link_flags; diff --git a/drivers/staging/batman-adv/vis.c b/drivers/staging/batman-adv/vis.c index 3c66645..2633d0f 100644 --- a/drivers/staging/batman-adv/vis.c +++ b/drivers/staging/batman-adv/vis.c @@ -52,12 +52,13 @@ static void free_info(void *data) /* set the mode of the visualization to client or server */ void vis_set_mode(int mode) { - spin_lock(&vis_hash_lock); + unsigned long flags; + spin_lock_irqsave(&vis_hash_lock, flags);
if (my_vis_info != NULL) my_vis_info->packet.vis_type = mode;
- spin_unlock(&vis_hash_lock); + spin_unlock_irqrestore(&vis_hash_lock, flags); }
/* is_vis_server(), locked outside */ @@ -74,10 +75,11 @@ static int is_vis_server_locked(void) int is_vis_server(void) { int ret = 0; + unsigned long flags;
- spin_lock(&vis_hash_lock); + spin_lock_irqsave(&vis_hash_lock, flags); ret = is_vis_server_locked(); - spin_unlock(&vis_hash_lock); + spin_unlock_irqrestore(&vis_hash_lock, flags);
return ret; } @@ -269,8 +271,9 @@ void receive_server_sync_packet(struct vis_packet *vis_packet, int vis_info_len) { struct vis_info *info; int is_new; + unsigned long flags;
- spin_lock(&vis_hash_lock); + spin_lock_irqsave(&vis_hash_lock, flags); info = add_packet(vis_packet, vis_info_len, &is_new); if (info == NULL) goto end; @@ -283,7 +286,7 @@ void receive_server_sync_packet(struct vis_packet *vis_packet, int vis_info_len) list_add_tail(&info->send_list, &send_list); } end: - spin_unlock(&vis_hash_lock); + spin_unlock_irqrestore(&vis_hash_lock, flags); }
/* handle an incoming client update packet and schedule forward if needed. */ @@ -292,12 +295,13 @@ void receive_client_update_packet(struct vis_packet *vis_packet, { struct vis_info *info; int is_new; + unsigned long flags;
/* clients shall not broadcast. */ if (is_bcast(vis_packet->target_orig)) return;
- spin_lock(&vis_hash_lock); + spin_lock_irqsave(&vis_hash_lock, flags); info = add_packet(vis_packet, vis_info_len, &is_new); if (info == NULL) goto end; @@ -319,7 +323,7 @@ void receive_client_update_packet(struct vis_packet *vis_packet, list_add_tail(&info->send_list, &send_list); } end: - spin_unlock(&vis_hash_lock); + spin_unlock_irqrestore(&vis_hash_lock, flags); }
/* Walk the originators and find the VIS server with the best tq. Set the packet @@ -370,7 +374,7 @@ static int generate_vis_packet(void)
info->first_seen = jiffies;
- spin_lock(&orig_hash_lock); + spin_lock_irqsave(&orig_hash_lock, flags); memcpy(info->packet.target_orig, broadcastAddr, ETH_ALEN); info->packet.ttl = TTL; info->packet.seqno++; @@ -379,7 +383,7 @@ static int generate_vis_packet(void) if (!is_vis_server_locked()) { best_tq = find_best_vis_server(info); if (best_tq < 0) { - spin_unlock(&orig_hash_lock); + spin_unlock_irqrestore(&orig_hash_lock, flags); return -1; } } @@ -403,13 +407,13 @@ static int generate_vis_packet(void) info->packet.entries++;
if (vis_packet_full(info)) { - spin_unlock(&orig_hash_lock); + spin_unlock_irqrestore(&orig_hash_lock, flags); return 0; } } }
- spin_unlock(&orig_hash_lock); + spin_unlock_irqrestore(&orig_hash_lock, flags);
spin_lock_irqsave(&hna_local_hash_lock, flags); while (hash_iterate(hna_local_hash, &hashit_local)) { @@ -450,8 +454,9 @@ static void broadcast_vis_packet(struct vis_info *info, int packet_length) { HASHIT(hashit); struct orig_node *orig_node; + unsigned long flags;
- spin_lock(&orig_hash_lock); + spin_lock_irqsave(&orig_hash_lock, flags);
/* send to all routers in range. */ while (hash_iterate(orig_hash, &hashit)) { @@ -478,14 +483,15 @@ static void broadcast_vis_packet(struct vis_info *info, int packet_length) } } memcpy(info->packet.target_orig, broadcastAddr, ETH_ALEN); - spin_unlock(&orig_hash_lock); + spin_unlock_irqrestore(&orig_hash_lock, flags); }
static void unicast_vis_packet(struct vis_info *info, int packet_length) { struct orig_node *orig_node; + unsigned long flags;
- spin_lock(&orig_hash_lock); + spin_lock_irqsave(&orig_hash_lock, flags); orig_node = ((struct orig_node *) hash_find(orig_hash, info->packet.target_orig));
@@ -496,7 +502,7 @@ static void unicast_vis_packet(struct vis_info *info, int packet_length) orig_node->batman_if, orig_node->router->addr); } - spin_unlock(&orig_hash_lock); + spin_unlock_irqrestore(&orig_hash_lock, flags); }
/* only send one vis packet. called from send_vis_packets() */ @@ -526,8 +532,9 @@ static void send_vis_packet(struct vis_info *info) static void send_vis_packets(struct work_struct *work) { struct vis_info *info, *temp; + unsigned long flags;
- spin_lock(&vis_hash_lock); + spin_lock_irqsave(&vis_hash_lock, flags); purge_vis_packets();
if (generate_vis_packet() == 0) @@ -538,7 +545,7 @@ static void send_vis_packets(struct work_struct *work) list_del_init(&info->send_list); send_vis_packet(info); } - spin_unlock(&vis_hash_lock); + spin_unlock_irqrestore(&vis_hash_lock, flags); start_vis_timer(); } static DECLARE_DELAYED_WORK(vis_timer_wq, send_vis_packets); @@ -547,10 +554,11 @@ static DECLARE_DELAYED_WORK(vis_timer_wq, send_vis_packets); * initialized (e.g. bat0 is initialized, interfaces have been added) */ int vis_init(void) { + unsigned long flags; if (vis_hash) return 1;
- spin_lock(&vis_hash_lock); + spin_lock_irqsave(&vis_hash_lock, flags);
vis_hash = hash_new(256, vis_info_cmp, vis_info_choose); if (!vis_hash) { @@ -588,12 +596,12 @@ int vis_init(void) goto err; }
- spin_unlock(&vis_hash_lock); + spin_unlock_irqrestore(&vis_hash_lock, flags); start_vis_timer(); return 1;
err: - spin_unlock(&vis_hash_lock); + spin_unlock_irqrestore(&vis_hash_lock, flags); vis_quit(); return 0; } @@ -601,17 +609,18 @@ err: /* shutdown vis-server */ void vis_quit(void) { + unsigned long flags; if (!vis_hash) return;
cancel_delayed_work_sync(&vis_timer_wq);
- spin_lock(&vis_hash_lock); + spin_lock_irqsave(&vis_hash_lock, flags); /* properly remove, kill timers ... */ hash_delete(vis_hash, free_info); vis_hash = NULL; my_vis_info = NULL; - spin_unlock(&vis_hash_lock); + spin_unlock_irqrestore(&vis_hash_lock, flags); }
/* schedule packets for (re)transmission */
Some embedded devices have very limited sources of entropy for the random number generator. It has been observed that the random MAC address on the interface bat0 is not always random. When testing with a collection of identical hardware, sometimes the bat0 device the same MAC address on multiple devices, causing mayhem. This patch allows the MAC address to be set by the user.
Signed-off-by: Andrew Lunn andrew@lunn.ch Signed-off-by: Simon Wunderlich siwu@hrz.tu-chemnitz.de --- drivers/staging/batman-adv/soft-interface.c | 13 +++++++++++-- drivers/staging/batman-adv/translation-table.c | 15 +++++++++++++++ drivers/staging/batman-adv/translation-table.h | 1 + 3 files changed, 27 insertions(+), 2 deletions(-)
diff --git a/drivers/staging/batman-adv/soft-interface.c b/drivers/staging/batman-adv/soft-interface.c index 8ae3483..bc0217b 100644 --- a/drivers/staging/batman-adv/soft-interface.c +++ b/drivers/staging/batman-adv/soft-interface.c @@ -145,9 +145,18 @@ struct net_device_stats *interface_stats(struct net_device *dev) return &priv->stats; }
-int interface_set_mac_addr(struct net_device *dev, void *addr) +int interface_set_mac_addr(struct net_device *dev, void *p) { - return -EBUSY; + struct sockaddr *addr = p; + + if (!is_valid_ether_addr(addr->sa_data)) + return -EADDRNOTAVAIL; + + hna_local_remove(dev->dev_addr, "mac address changed"); + memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN); + hna_local_add(dev->dev_addr); + + return 0; }
int interface_change_mtu(struct net_device *dev, int new_mtu) diff --git a/drivers/staging/batman-adv/translation-table.c b/drivers/staging/batman-adv/translation-table.c index 8c8136b..53a054e 100644 --- a/drivers/staging/batman-adv/translation-table.c +++ b/drivers/staging/batman-adv/translation-table.c @@ -211,6 +211,21 @@ static void hna_local_del(struct hna_local_entry *hna_local_entry, _hna_local_del(hna_local_entry); }
+void hna_local_remove(uint8_t *addr, char *message) +{ + struct hna_local_entry *hna_local_entry; + unsigned long flags; + + spin_lock_irqsave(&hna_local_hash_lock, flags); + + hna_local_entry = (struct hna_local_entry *) + hash_find(hna_local_hash, addr); + if (hna_local_entry) + hna_local_del(hna_local_entry, message); + + spin_unlock_irqrestore(&hna_local_hash_lock, flags); +} + void hna_local_purge(struct work_struct *work) { struct hna_local_entry *hna_local_entry; diff --git a/drivers/staging/batman-adv/translation-table.h b/drivers/staging/batman-adv/translation-table.h index f7da811..281125b 100644 --- a/drivers/staging/batman-adv/translation-table.h +++ b/drivers/staging/batman-adv/translation-table.h @@ -23,6 +23,7 @@
int hna_local_init(void); void hna_local_add(uint8_t *addr); +void hna_local_remove(uint8_t *addr, char *message); int hna_local_fill_buffer(unsigned char *buff, int buff_len); int hna_local_fill_buffer_text(unsigned char *buff, int buff_len); void hna_local_purge(struct work_struct *work);
printk() since kernel version 2.6.29 has supported printing MAC addresses directly, as an extension to the %p processing. This patch makes use of this for printk() and bat_dbg(). This will remove the overhead of using addr_to_string() which is normally never actually output.
Fixed a typo found by Gus Wirth.
Signed-off-by: Andrew Lunn andrew@lunn.ch Signed-off-by: Simon Wunderlich siwu@hrz.tu-chemnitz.de --- drivers/staging/batman-adv/TODO | 4 - drivers/staging/batman-adv/compat.h | 82 ++++++++++++++++++----- drivers/staging/batman-adv/device.c | 1 + drivers/staging/batman-adv/hard-interface.c | 14 ++-- drivers/staging/batman-adv/main.c | 2 +- drivers/staging/batman-adv/originator.c | 17 ++---- drivers/staging/batman-adv/routing.c | 66 ++++++-------------- drivers/staging/batman-adv/send.c | 13 +--- drivers/staging/batman-adv/translation-table.c | 34 +++------- 9 files changed, 111 insertions(+), 122 deletions(-)
diff --git a/drivers/staging/batman-adv/TODO b/drivers/staging/batman-adv/TODO index b1e369c..2122adc 100644 --- a/drivers/staging/batman-adv/TODO +++ b/drivers/staging/batman-adv/TODO @@ -17,10 +17,6 @@ -> transtable_global (read-only) [outputs the global translation table] -> transtable_local (read-only) [outputs the local translation table]
-=> logging -* make use of printk %pM support instead of converting mac addresses -* manually - => strip out all backward compatibility support to older kernels (only found in compat.h)
diff --git a/drivers/staging/batman-adv/compat.h b/drivers/staging/batman-adv/compat.h index f4e0a45..ded1e6e 100644 --- a/drivers/staging/batman-adv/compat.h +++ b/drivers/staging/batman-adv/compat.h @@ -35,41 +35,87 @@ #define list_first_entry(ptr, type, member) \ list_entry((ptr)->next, type, member)
-#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) */ +#define skb_mac_header(_skb) \ + ((_skb)->mac.raw)
+#define skb_network_header(_skb) \ + ((_skb)->nh.raw) + +#define skb_mac_header(_skb) \ + ((_skb)->mac.raw) + +#endif /* < KERNEL_VERSION(2,6,22) */ + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 23) + +static inline int skb_clone_writable(struct sk_buff *skb, unsigned int len) +{ + /* skb->hdr_len not available, just "not writable" to enforce a copy */ + return 0; +} + +#define cancel_delayed_work_sync(wq) cancel_rearming_delayed_work(wq) + +#endif /* < KERNEL_VERSION(2, 6, 23) */ + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25) + +#define strict_strtoul(cp, base, res) \ + ({ \ + int ret = 0; \ + char *endp; \ + *res = simple_strtoul(cp, &endp, base); \ + if (cp == endp) \ + ret = -EINVAL; \ + ret; \ +}) + +#endif /* < KERNEL_VERSION(2, 6, 25) */
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26)
+static const char hex_asc[] = "0123456789abcdef"; +#define hex_asc_lo(x) hex_asc[((x) & 0x0f)] +#define hex_asc_hi(x) hex_asc[((x) & 0xf0) >> 4] +static inline char *pack_hex_byte(char *buf, u8 byte) +{ + *buf++ = hex_asc_hi(byte); + *buf++ = hex_asc_lo(byte); + return buf; +} + #define device_create(_cls, _parent, _devt, _device, _fmt) \ class_device_create(_cls, _parent, _devt, _device, _fmt)
#define device_destroy(_cls, _device) \ class_device_destroy(_cls, _device)
-#else +#endif /* < KERNEL_VERSION(2, 6, 26) */
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 27)
+#ifndef dereference_function_descriptor +#define dereference_function_descriptor(p) (p) +#endif + +#ifndef device_create #define device_create(_cls, _parent, _devt, _device, _fmt) \ device_create_drvdata(_cls, _parent, _devt, _device, _fmt) +#endif
-#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 27) */ +#endif /* < KERNEL_VERSION(2, 6, 27) */
-#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 29)
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 23) +asmlinkage int bat_printk(const char *fmt, ...); +#define printk bat_printk
-#define cancel_delayed_work_sync(wq) cancel_rearming_delayed_work(wq) +static inline struct net_device_stats *dev_get_stats(struct net_device *dev) +{ + if (dev->get_stats) + return dev->get_stats(dev); + else + return NULL; +}
-#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 23) */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25) -#define strict_strtoul(cp, base, res) \ - ({ \ - int ret = 0; \ - char *endp; \ - *res = simple_strtoul(cp, &endp, base); \ - if (cp == endp) \ - ret = -EINVAL; \ - ret; \ -}) -#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25) */ +#endif /* < KERNEL_VERSION(2, 6, 29) */ diff --git a/drivers/staging/batman-adv/device.c b/drivers/staging/batman-adv/device.c index ab2b0b1..72306ac 100644 --- a/drivers/staging/batman-adv/device.c +++ b/drivers/staging/batman-adv/device.c @@ -19,6 +19,7 @@ * */
+#include <linux/device.h> #include "main.h" #include "device.h" #include "send.h" diff --git a/drivers/staging/batman-adv/hard-interface.c b/drivers/staging/batman-adv/hard-interface.c index cc59c30..db264bd 100644 --- a/drivers/staging/batman-adv/hard-interface.c +++ b/drivers/staging/batman-adv/hard-interface.c @@ -74,7 +74,6 @@ int hardif_min_mtu(void) static void check_known_mac_addr(uint8_t *addr) { struct batman_if *batman_if; - char mac_string[ETH_STR_LEN];
rcu_read_lock(); list_for_each_entry_rcu(batman_if, &if_list, list) { @@ -85,9 +84,8 @@ static void check_known_mac_addr(uint8_t *addr) if (!compare_orig(batman_if->net_dev->dev_addr, addr)) continue;
- addr_to_string(mac_string, addr); - printk(KERN_WARNING "batman-adv:The newly added mac address (%s) already exists on: %s\n", - mac_string, batman_if->dev); + printk(KERN_WARNING "batman-adv:The newly added mac address (%pM) already exists on: %s\n", + addr, batman_if->dev); printk(KERN_WARNING "batman-adv:It is strongly recommended to keep mac addresses unique to avoid problems!\n"); } rcu_read_unlock(); @@ -447,9 +445,11 @@ int batman_skb_recv(struct sk_buff *skb, struct net_device *dev, if (!batman_if) goto err_free;
- stats = &skb->dev->stats; - stats->rx_packets++; - stats->rx_bytes += skb->len; + stats = (struct net_device_stats *) dev_get_stats(skb->dev); + if (stats) { + stats->rx_packets++; + stats->rx_bytes += skb->len; + }
batman_packet = (struct batman_packet *)skb->data;
diff --git a/drivers/staging/batman-adv/main.c b/drivers/staging/batman-adv/main.c index c733504..1d80ea3 100644 --- a/drivers/staging/batman-adv/main.c +++ b/drivers/staging/batman-adv/main.c @@ -54,7 +54,7 @@ unsigned char broadcastAddr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; atomic_t module_state;
static struct packet_type batman_adv_packet_type __read_mostly = { - .type = cpu_to_be16(ETH_P_BATMAN), + .type = __constant_htons(ETH_P_BATMAN), .func = batman_skb_recv, };
diff --git a/drivers/staging/batman-adv/originator.c b/drivers/staging/batman-adv/originator.c index 3fa7baf..85c3d1f 100644 --- a/drivers/staging/batman-adv/originator.c +++ b/drivers/staging/batman-adv/originator.c @@ -26,6 +26,7 @@ #include "hash.h" #include "translation-table.h" #include "routing.h" +#include "compat.h"
static DECLARE_DELAYED_WORK(purge_orig_wq, purge_orig); @@ -121,7 +122,6 @@ struct orig_node *get_orig_node(uint8_t *addr) { struct orig_node *orig_node; struct hashtable_t *swaphash; - char orig_str[ETH_STR_LEN]; int size;
orig_node = ((struct orig_node *)hash_find(orig_hash, addr)); @@ -129,8 +129,7 @@ struct orig_node *get_orig_node(uint8_t *addr) if (orig_node != NULL) return orig_node;
- addr_to_string(orig_str, addr); - bat_dbg(DBG_BATMAN, "Creating new originator: %s \n", orig_str); + bat_dbg(DBG_BATMAN, "Creating new originator: %pM \n", addr);
orig_node = kmalloc(sizeof(struct orig_node), GFP_ATOMIC); if (!orig_node) @@ -186,7 +185,6 @@ static bool purge_orig_neighbors(struct orig_node *orig_node, struct neigh_node **best_neigh_node) { struct list_head *list_pos, *list_pos_tmp; - char neigh_str[ETH_STR_LEN], orig_str[ETH_STR_LEN]; struct neigh_node *neigh_node; bool neigh_purged = false;
@@ -201,9 +199,7 @@ static bool purge_orig_neighbors(struct orig_node *orig_node, (neigh_node->last_valid + ((PURGE_TIMEOUT * HZ) / 1000)))) {
- addr_to_string(neigh_str, neigh_node->addr); - addr_to_string(orig_str, orig_node->orig); - bat_dbg(DBG_BATMAN, "neighbor timeout: originator %s, neighbor: %s, last_valid %lu\n", orig_str, neigh_str, (neigh_node->last_valid / HZ)); + bat_dbg(DBG_BATMAN, "neighbor timeout: originator %pM, neighbor: %pM, last_valid %lu\n", orig_node->orig, neigh_node->addr, (neigh_node->last_valid / HZ));
neigh_purged = true; list_del(list_pos); @@ -221,17 +217,14 @@ static bool purge_orig_neighbors(struct orig_node *orig_node, static bool purge_orig_node(struct orig_node *orig_node) { struct neigh_node *best_neigh_node; - char orig_str[ETH_STR_LEN]; - - addr_to_string(orig_str, orig_node->orig);
if (time_after(jiffies, (orig_node->last_valid + ((2 * PURGE_TIMEOUT * HZ) / 1000)))) {
bat_dbg(DBG_BATMAN, - "Originator timeout: originator %s, last_valid %lu\n", - orig_str, (orig_node->last_valid / HZ)); + "Originator timeout: originator %pM, last_valid %lu\n", + orig_node->orig, (orig_node->last_valid / HZ)); return true; } else { if (purge_orig_neighbors(orig_node, &best_neigh_node)) diff --git a/drivers/staging/batman-adv/routing.c b/drivers/staging/batman-adv/routing.c index 9cf1ee5..bab7a73 100644 --- a/drivers/staging/batman-adv/routing.c +++ b/drivers/staging/batman-adv/routing.c @@ -80,32 +80,24 @@ static void update_route(struct orig_node *orig_node, struct neigh_node *neigh_node, unsigned char *hna_buff, int hna_buff_len) { - char orig_str[ETH_STR_LEN], neigh_str[ETH_STR_LEN]; - char router_str[ETH_STR_LEN]; - - addr_to_string(orig_str, orig_node->orig); - /* route deleted */ if ((orig_node->router != NULL) && (neigh_node == NULL)) {
- bat_dbg(DBG_ROUTES, "Deleting route towards: %s\n", - orig_str); + bat_dbg(DBG_ROUTES, "Deleting route towards: %pM\n", + orig_node->orig); hna_global_del_orig(orig_node, "originator timed out");
/* route added */ } else if ((orig_node->router == NULL) && (neigh_node != NULL)) {
- addr_to_string(neigh_str, neigh_node->addr); bat_dbg(DBG_ROUTES, - "Adding route towards: %s (via %s)\n", - orig_str, neigh_str); + "Adding route towards: %pM (via %pM)\n", + orig_node->orig, neigh_node->addr); hna_global_add_orig(orig_node, hna_buff, hna_buff_len);
/* route changed */ } else { - addr_to_string(neigh_str, neigh_node->addr); - addr_to_string(router_str, orig_node->router->addr); - bat_dbg(DBG_ROUTES, "Changing route towards: %s (now via %s - was via %s)\n", orig_str, neigh_str, router_str); + bat_dbg(DBG_ROUTES, "Changing route towards: %pM (now via %pM - was via %pM)\n", orig_node->orig, neigh_node->addr, orig_node->router->addr); }
if (neigh_node != NULL) @@ -138,12 +130,8 @@ static int isBidirectionalNeigh(struct orig_node *orig_node, struct batman_if *if_incoming) { struct neigh_node *neigh_node = NULL, *tmp_neigh_node = NULL; - char orig_str[ETH_STR_LEN], neigh_str[ETH_STR_LEN]; unsigned char total_count;
- addr_to_string(orig_str, orig_node->orig); - addr_to_string(neigh_str, orig_neigh_node->orig); - if (orig_node == orig_neigh_node) { list_for_each_entry(tmp_neigh_node, &orig_node->neigh_list, @@ -227,8 +215,8 @@ static int isBidirectionalNeigh(struct orig_node *orig_node, orig_neigh_node->tq_asym_penalty) / (TQ_MAX_VALUE * TQ_MAX_VALUE));
- bat_dbg(DBG_BATMAN, "bidirectional: orig = %-15s neigh = %-15s => own_bcast = %2i, real recv = %2i, local tq: %3i, asym_penalty: %3i, total tq: %3i \n", - orig_str, neigh_str, total_count, + bat_dbg(DBG_BATMAN, "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_neigh_node->tq_asym_penalty, batman_packet->tq);
@@ -372,8 +360,6 @@ void receive_bat_packet(struct ethhdr *ethhdr, { struct batman_if *batman_if; struct orig_node *orig_neigh_node, *orig_node; - char orig_str[ETH_STR_LEN], prev_sender_str[ETH_STR_LEN]; - char neigh_str[ETH_STR_LEN]; char has_directlink_flag; char is_my_addr = 0, is_my_orig = 0, is_my_oldorig = 0; char is_broadcast = 0, is_bidirectional, is_single_hop_neigh; @@ -398,20 +384,16 @@ void receive_bat_packet(struct ethhdr *ethhdr, /* could be changed by schedule_own_packet() */ if_incoming_seqno = atomic_read(&if_incoming->seqno);
- addr_to_string(orig_str, batman_packet->orig); - addr_to_string(prev_sender_str, batman_packet->prev_sender); - addr_to_string(neigh_str, ethhdr->h_source); - has_directlink_flag = (batman_packet->flags & DIRECTLINK ? 1 : 0);
is_single_hop_neigh = (compare_orig(ethhdr->h_source, batman_packet->orig) ? 1 : 0);
- bat_dbg(DBG_BATMAN, "Received BATMAN packet via NB: %s, IF: %s [%s] (from OG: %s, via prev OG: %s, seqno %d, tq %d, TTL %d, V %d, IDF %d) \n", - neigh_str, if_incoming->dev, if_incoming->addr_str, - orig_str, prev_sender_str, batman_packet->seqno, - batman_packet->tq, batman_packet->ttl, batman_packet->version, - has_directlink_flag); + bat_dbg(DBG_BATMAN, "Received BATMAN packet via NB: %pM, IF: %s [%s] (from OG: %pM, via prev OG: %pM, seqno %d, tq %d, TTL %d, V %d, IDF %d) \n", + ethhdr->h_source, if_incoming->dev, if_incoming->addr_str, + batman_packet->orig, batman_packet->prev_sender, + batman_packet->seqno, batman_packet->tq, batman_packet->ttl, + batman_packet->version, has_directlink_flag);
list_for_each_entry_rcu(batman_if, &if_list, list) { if (batman_if->if_active != IF_ACTIVE) @@ -442,13 +424,13 @@ void receive_bat_packet(struct ethhdr *ethhdr,
if (is_my_addr) { bat_dbg(DBG_BATMAN, - "Drop packet: received my own broadcast (sender: %s)\n", - neigh_str); + "Drop packet: received my own broadcast (sender: %pM)\n", + ethhdr->h_source); return; }
if (is_broadcast) { - bat_dbg(DBG_BATMAN, "Drop packet: ignoring all packets with broadcast source addr (sender: %s) \n", neigh_str); + bat_dbg(DBG_BATMAN, "Drop packet: ignoring all packets with broadcast source addr (sender: %pM) \n", ethhdr->h_source); return; }
@@ -488,7 +470,7 @@ void receive_bat_packet(struct ethhdr *ethhdr, }
if (is_my_oldorig) { - bat_dbg(DBG_BATMAN, "Drop packet: ignoring all rebroadcast echos (sender: %s) \n", neigh_str); + bat_dbg(DBG_BATMAN, "Drop packet: ignoring all rebroadcast echos (sender: %pM) \n", ethhdr->h_source); return; }
@@ -506,7 +488,7 @@ void receive_bat_packet(struct ethhdr *ethhdr, !(compare_orig(batman_packet->orig, batman_packet->prev_sender)) && (compare_orig(orig_node->router->addr, orig_node->router->orig_node->router->addr))) { - bat_dbg(DBG_BATMAN, "Drop packet: ignoring all rebroadcast packets that may make me loop (sender: %s) \n", neigh_str); + bat_dbg(DBG_BATMAN, "Drop packet: ignoring all rebroadcast packets that may make me loop (sender: %pM) \n", ethhdr->h_source); return; }
@@ -666,7 +648,6 @@ static int recv_my_icmp_packet(struct sk_buff *skb)
static int recv_icmp_ttl_exceeded(struct sk_buff *skb) { - unsigned char src_str[ETH_STR_LEN], dst_str[ETH_STR_LEN]; struct orig_node *orig_node; struct icmp_packet *icmp_packet; struct ethhdr *ethhdr; @@ -679,10 +660,7 @@ static int recv_icmp_ttl_exceeded(struct sk_buff *skb) icmp_packet = (struct icmp_packet *) skb->data; ethhdr = (struct ethhdr *) skb_mac_header(skb);
- addr_to_string(src_str, icmp_packet->orig); - addr_to_string(dst_str, icmp_packet->dst); - - printk(KERN_WARNING "batman-adv:Warning - can't send packet from %s to %s: ttl exceeded\n", src_str, dst_str); + printk(KERN_WARNING "batman-adv:Warning - can't send packet from %pM to %pM: ttl exceeded\n", icmp_packet->orig, icmp_packet->dst);
/* send TTL exceeded if packet is an echo request (traceroute) */ if (icmp_packet->msg_type != ECHO_REQUEST) @@ -812,7 +790,6 @@ int recv_icmp_packet(struct sk_buff *skb) int recv_unicast_packet(struct sk_buff *skb) { struct unicast_packet *unicast_packet; - unsigned char src_str[ETH_STR_LEN], dst_str[ETH_STR_LEN]; struct orig_node *orig_node; struct ethhdr *ethhdr; struct batman_if *batman_if; @@ -850,10 +827,7 @@ int recv_unicast_packet(struct sk_buff *skb)
/* TTL exceeded */ if (unicast_packet->ttl < 2) { - addr_to_string(src_str, ethhdr->h_source); - addr_to_string(dst_str, ethhdr->h_dest); - - printk(KERN_WARNING "batman-adv:Warning - can't send packet from %s to %s: ttl exceeded\n", src_str, dst_str); + printk(KERN_WARNING "batman-adv:Warning - can't send packet from %pM to %pM: ttl exceeded\n", ethhdr->h_source, unicast_packet->dest); return NET_RX_DROP; }
@@ -1005,5 +979,3 @@ int recv_vis_packet(struct sk_buff *skb) } return ret; } - - diff --git a/drivers/staging/batman-adv/send.c b/drivers/staging/batman-adv/send.c index fd48f3f..edfdd5d 100644 --- a/drivers/staging/batman-adv/send.c +++ b/drivers/staging/batman-adv/send.c @@ -132,7 +132,6 @@ static void send_packet_to_if(struct forw_packet *forw_packet, uint8_t packet_num; int16_t buff_pos; struct batman_packet *batman_packet; - char orig_str[ETH_STR_LEN];
if (batman_if->if_active != IF_ACTIVE) return; @@ -154,15 +153,14 @@ static void send_packet_to_if(struct forw_packet *forw_packet, else batman_packet->flags &= ~DIRECTLINK;
- addr_to_string(orig_str, batman_packet->orig); fwd_str = (packet_num > 0 ? "Forwarding" : (forw_packet->own ? "Sending own" : "Forwarding")); bat_dbg(DBG_BATMAN, - "%s %spacket (originator %s, seqno %d, TQ %d, TTL %d, IDF %s) on interface %s [%s]\n", + "%s %spacket (originator %pM, seqno %d, TQ %d, TTL %d, IDF %s) on interface %s [%s]\n", fwd_str, (packet_num > 0 ? "aggregated " : ""), - orig_str, ntohs(batman_packet->seqno), + batman_packet->orig, ntohs(batman_packet->seqno), batman_packet->tq, batman_packet->ttl, (batman_packet->flags & DIRECTLINK ? "on" : "off"), @@ -186,7 +184,6 @@ static void send_packet(struct forw_packet *forw_packet) struct batman_if *batman_if; struct batman_packet *batman_packet = (struct batman_packet *)(forw_packet->packet_buff); - char orig_str[ETH_STR_LEN]; unsigned char directlink = (batman_packet->flags & DIRECTLINK ? 1 : 0);
if (!forw_packet->if_incoming) { @@ -197,8 +194,6 @@ static void send_packet(struct forw_packet *forw_packet) if (forw_packet->if_incoming->if_active != IF_ACTIVE) return;
- addr_to_string(orig_str, batman_packet->orig); - /* multihomed peer assumed */ /* non-primary OGMs are only broadcasted on their interface */ if ((directlink && (batman_packet->ttl == 1)) || @@ -206,9 +201,9 @@ static void send_packet(struct forw_packet *forw_packet)
/* FIXME: what about aggregated packets ? */ bat_dbg(DBG_BATMAN, - "%s packet (originator %s, seqno %d, TTL %d) on interface %s [%s]\n", + "%s packet (originator %pM, seqno %d, TTL %d) on interface %s [%s]\n", (forw_packet->own ? "Sending own" : "Forwarding"), - orig_str, ntohs(batman_packet->seqno), + batman_packet->orig, ntohs(batman_packet->seqno), batman_packet->ttl, forw_packet->if_incoming->dev, forw_packet->if_incoming->addr_str);
diff --git a/drivers/staging/batman-adv/translation-table.c b/drivers/staging/batman-adv/translation-table.c index 53a054e..398a808 100644 --- a/drivers/staging/batman-adv/translation-table.c +++ b/drivers/staging/batman-adv/translation-table.c @@ -61,7 +61,6 @@ void hna_local_add(uint8_t *addr) struct hna_local_entry *hna_local_entry; struct hna_global_entry *hna_global_entry; struct hashtable_t *swaphash; - char hna_str[ETH_STR_LEN]; unsigned long flags;
spin_lock_irqsave(&hna_local_hash_lock, flags); @@ -74,19 +73,17 @@ void hna_local_add(uint8_t *addr) return; }
- addr_to_string(hna_str, addr); - /* only announce as many hosts as possible in the batman-packet and space in batman_packet->num_hna That also should give a limit to MAC-flooding. */ if ((num_hna + 1 > (ETH_DATA_LEN - BAT_PACKET_LEN) / ETH_ALEN) || (num_hna + 1 > 255)) { - bat_dbg(DBG_ROUTES, "Can't add new local hna entry (%s): number of local hna entries exceeds packet size \n", hna_str); + bat_dbg(DBG_ROUTES, "Can't add new local hna entry (%pM): number of local hna entries exceeds packet size \n", addr); return; }
- bat_dbg(DBG_ROUTES, "Creating new local hna entry: %s \n", - hna_str); + bat_dbg(DBG_ROUTES, "Creating new local hna entry: %pM \n", + addr);
hna_local_entry = kmalloc(sizeof(struct hna_local_entry), GFP_ATOMIC); if (!hna_local_entry) @@ -201,11 +198,8 @@ static void _hna_local_del(void *data) static void hna_local_del(struct hna_local_entry *hna_local_entry, char *message) { - char hna_str[ETH_STR_LEN]; - - addr_to_string(hna_str, hna_local_entry->addr); - bat_dbg(DBG_ROUTES, "Deleting local hna entry (%s): %s \n", - hna_str, message); + bat_dbg(DBG_ROUTES, "Deleting local hna entry (%pM): %s \n", + hna_local_entry->addr, message);
hash_remove(hna_local_hash, hna_local_entry->addr); _hna_local_del(hna_local_entry); @@ -278,13 +272,10 @@ void hna_global_add_orig(struct orig_node *orig_node, struct hna_global_entry *hna_global_entry; struct hna_local_entry *hna_local_entry; struct hashtable_t *swaphash; - char hna_str[ETH_STR_LEN], orig_str[ETH_STR_LEN]; int hna_buff_count = 0; unsigned long flags; unsigned char *hna_ptr;
- addr_to_string(orig_str, orig_node->orig); - while ((hna_buff_count + 1) * ETH_ALEN <= hna_buff_len) { spin_lock_irqsave(&hna_global_hash_lock, flags);
@@ -304,10 +295,9 @@ void hna_global_add_orig(struct orig_node *orig_node,
memcpy(hna_global_entry->addr, hna_ptr, ETH_ALEN);
- addr_to_string(hna_str, hna_global_entry->addr); bat_dbg(DBG_ROUTES, - "Creating new global hna entry: %s (via %s)\n", - hna_str, orig_str); + "Creating new global hna entry: %pM (via %pM)\n", + hna_global_entry->addr, orig_node->orig);
spin_lock_irqsave(&hna_global_hash_lock, flags); hash_add(hna_global_hash, hna_global_entry); @@ -399,13 +389,9 @@ int hna_global_fill_buffer_text(unsigned char *buff, int buff_len) void _hna_global_del_orig(struct hna_global_entry *hna_global_entry, char *message) { - char hna_str[ETH_STR_LEN], orig_str[ETH_STR_LEN]; - - addr_to_string(orig_str, hna_global_entry->orig_node->orig); - addr_to_string(hna_str, hna_global_entry->addr); - - bat_dbg(DBG_ROUTES, "Deleting global hna entry %s (via %s): %s \n", - hna_str, orig_str, message); + bat_dbg(DBG_ROUTES, "Deleting global hna entry %pM (via %pM): %s \n", + hna_global_entry->addr, hna_global_entry->orig_node->orig, + message);
hash_remove(hna_global_hash, hna_global_entry->addr); kfree(hna_global_entry);
From: Simon Wunderlich siwu@hrz.tu-chemnitz.de
Since we are now part of mainline, we don't need compat.h to allow building of the module with old versions of the kernel.
Signed-off-by: Andrew Lunn andrew@lunn.ch --- drivers/staging/batman-adv/TODO | 3 - drivers/staging/batman-adv/compat.h | 121 ------------------------ drivers/staging/batman-adv/device.c | 2 - drivers/staging/batman-adv/hard-interface.c | 1 - drivers/staging/batman-adv/main.c | 1 - drivers/staging/batman-adv/originator.c | 16 +--- drivers/staging/batman-adv/proc.c | 1 - drivers/staging/batman-adv/routing.c | 2 - drivers/staging/batman-adv/send.c | 2 - drivers/staging/batman-adv/soft-interface.c | 6 +- drivers/staging/batman-adv/translation-table.c | 1 - drivers/staging/batman-adv/vis.c | 1 - 12 files changed, 6 insertions(+), 151 deletions(-) delete mode 100644 drivers/staging/batman-adv/compat.h
diff --git a/drivers/staging/batman-adv/TODO b/drivers/staging/batman-adv/TODO index 2122adc..2f15136 100644 --- a/drivers/staging/batman-adv/TODO +++ b/drivers/staging/batman-adv/TODO @@ -17,9 +17,6 @@ -> transtable_global (read-only) [outputs the global translation table] -> transtable_local (read-only) [outputs the local translation table]
-=> strip out all backward compatibility support to older kernels - (only found in compat.h) - => fix checkpatch.pl errors
Please send all patches to: diff --git a/drivers/staging/batman-adv/compat.h b/drivers/staging/batman-adv/compat.h deleted file mode 100644 index ded1e6e..0000000 --- a/drivers/staging/batman-adv/compat.h +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright (C) 2007-2009 B.A.T.M.A.N. contributors: - * - * Marek Lindner, Simon Wunderlich - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA - * - * - * This file contains macros for maintaining compatibility with older versions - * of the Linux kernel. - */ - -#include <linux/version.h> /* LINUX_VERSION_CODE */ - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) - -#define skb_set_network_header(_skb, _offset) \ - do { (_skb)->nh.raw = (_skb)->data + (_offset); } while (0) - -#define skb_reset_mac_header(_skb) \ - do { (_skb)->mac.raw = (_skb)->data; } while (0) - -#define list_first_entry(ptr, type, member) \ - list_entry((ptr)->next, type, member) - -#define skb_mac_header(_skb) \ - ((_skb)->mac.raw) - -#define skb_network_header(_skb) \ - ((_skb)->nh.raw) - -#define skb_mac_header(_skb) \ - ((_skb)->mac.raw) - -#endif /* < KERNEL_VERSION(2,6,22) */ - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 23) - -static inline int skb_clone_writable(struct sk_buff *skb, unsigned int len) -{ - /* skb->hdr_len not available, just "not writable" to enforce a copy */ - return 0; -} - -#define cancel_delayed_work_sync(wq) cancel_rearming_delayed_work(wq) - -#endif /* < KERNEL_VERSION(2, 6, 23) */ - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25) - -#define strict_strtoul(cp, base, res) \ - ({ \ - int ret = 0; \ - char *endp; \ - *res = simple_strtoul(cp, &endp, base); \ - if (cp == endp) \ - ret = -EINVAL; \ - ret; \ -}) - -#endif /* < KERNEL_VERSION(2, 6, 25) */ - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) - -static const char hex_asc[] = "0123456789abcdef"; -#define hex_asc_lo(x) hex_asc[((x) & 0x0f)] -#define hex_asc_hi(x) hex_asc[((x) & 0xf0) >> 4] -static inline char *pack_hex_byte(char *buf, u8 byte) -{ - *buf++ = hex_asc_hi(byte); - *buf++ = hex_asc_lo(byte); - return buf; -} - -#define device_create(_cls, _parent, _devt, _device, _fmt) \ - class_device_create(_cls, _parent, _devt, _device, _fmt) - -#define device_destroy(_cls, _device) \ - class_device_destroy(_cls, _device) - -#endif /* < KERNEL_VERSION(2, 6, 26) */ - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 27) - -#ifndef dereference_function_descriptor -#define dereference_function_descriptor(p) (p) -#endif - -#ifndef device_create -#define device_create(_cls, _parent, _devt, _device, _fmt) \ - device_create_drvdata(_cls, _parent, _devt, _device, _fmt) -#endif - -#endif /* < KERNEL_VERSION(2, 6, 27) */ - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 29) - -asmlinkage int bat_printk(const char *fmt, ...); -#define printk bat_printk - -static inline struct net_device_stats *dev_get_stats(struct net_device *dev) -{ - if (dev->get_stats) - return dev->get_stats(dev); - else - return NULL; -} - -#endif /* < KERNEL_VERSION(2, 6, 29) */ diff --git a/drivers/staging/batman-adv/device.c b/drivers/staging/batman-adv/device.c index 72306ac..a3e7429 100644 --- a/drivers/staging/batman-adv/device.c +++ b/drivers/staging/batman-adv/device.c @@ -26,8 +26,6 @@ #include "types.h" #include "hash.h"
-#include "compat.h" - static struct class *batman_class;
static int Major; /* Major number assigned to our device driver */ diff --git a/drivers/staging/batman-adv/hard-interface.c b/drivers/staging/batman-adv/hard-interface.c index db264bd..f8b1ba3 100644 --- a/drivers/staging/batman-adv/hard-interface.c +++ b/drivers/staging/batman-adv/hard-interface.c @@ -26,7 +26,6 @@ #include "translation-table.h" #include "routing.h" #include "hash.h" -#include "compat.h"
#define MIN(x, y) ((x) < (y) ? (x) : (y))
diff --git a/drivers/staging/batman-adv/main.c b/drivers/staging/batman-adv/main.c index 1d80ea3..3f78075 100644 --- a/drivers/staging/batman-adv/main.c +++ b/drivers/staging/batman-adv/main.c @@ -31,7 +31,6 @@ #include "types.h" #include "vis.h" #include "hash.h" -#include "compat.h"
struct list_head if_list; struct hlist_head forw_bat_list; diff --git a/drivers/staging/batman-adv/originator.c b/drivers/staging/batman-adv/originator.c index 85c3d1f..bf9688a 100644 --- a/drivers/staging/batman-adv/originator.c +++ b/drivers/staging/batman-adv/originator.c @@ -26,8 +26,6 @@ #include "hash.h" #include "translation-table.h" #include "routing.h" -#include "compat.h" -
static DECLARE_DELAYED_WORK(purge_orig_wq, purge_orig);
@@ -80,11 +78,10 @@ create_neighbor(struct orig_node *orig_node, struct orig_node *orig_neigh_node,
bat_dbg(DBG_BATMAN, "Creating new last-hop neighbor of originator\n");
- neigh_node = kmalloc(sizeof(struct neigh_node), GFP_ATOMIC); + neigh_node = kzalloc(sizeof(struct neigh_node), GFP_ATOMIC); if (!neigh_node) return NULL;
- memset(neigh_node, 0, sizeof(struct neigh_node)); INIT_LIST_HEAD(&neigh_node->list);
memcpy(neigh_node->addr, neigh, ETH_ALEN); @@ -131,11 +128,10 @@ struct orig_node *get_orig_node(uint8_t *addr)
bat_dbg(DBG_BATMAN, "Creating new originator: %pM \n", addr);
- orig_node = kmalloc(sizeof(struct orig_node), GFP_ATOMIC); + orig_node = kzalloc(sizeof(struct orig_node), GFP_ATOMIC); if (!orig_node) return NULL;
- memset(orig_node, 0, sizeof(struct orig_node)); INIT_LIST_HEAD(&orig_node->neigh_list);
memcpy(orig_node->orig, addr, ETH_ALEN); @@ -145,19 +141,15 @@ struct orig_node *get_orig_node(uint8_t *addr)
size = num_ifs * sizeof(TYPE_OF_WORD) * NUM_WORDS;
- orig_node->bcast_own = kmalloc(size, GFP_ATOMIC); + orig_node->bcast_own = kzalloc(size, GFP_ATOMIC); if (!orig_node->bcast_own) goto free_orig_node;
- memset(orig_node->bcast_own, 0, size); - size = num_ifs * sizeof(uint8_t); - orig_node->bcast_own_sum = kmalloc(size, GFP_ATOMIC); + orig_node->bcast_own_sum = kzalloc(size, GFP_ATOMIC); if (!orig_node->bcast_own_sum) goto free_bcast_own;
- memset(orig_node->bcast_own_sum, 0, size); - if (hash_add(orig_hash, orig_node) < 0) goto free_bcast_own_sum;
diff --git a/drivers/staging/batman-adv/proc.c b/drivers/staging/batman-adv/proc.c index 61e1d0d..6a7c8bb 100644 --- a/drivers/staging/batman-adv/proc.c +++ b/drivers/staging/batman-adv/proc.c @@ -27,7 +27,6 @@ #include "types.h" #include "hash.h" #include "vis.h" -#include "compat.h"
static struct proc_dir_entry *proc_batman_dir, *proc_interface_file; static struct proc_dir_entry *proc_orig_interval_file, *proc_originators_file; diff --git a/drivers/staging/batman-adv/routing.c b/drivers/staging/batman-adv/routing.c index bab7a73..09917e5 100644 --- a/drivers/staging/batman-adv/routing.c +++ b/drivers/staging/batman-adv/routing.c @@ -32,7 +32,6 @@ #include "ring_buffer.h" #include "vis.h" #include "aggregation.h" -#include "compat.h"
DECLARE_WAIT_QUEUE_HEAD(thread_wait);
@@ -310,7 +309,6 @@ static void update_orig(struct orig_node *orig_node, struct ethhdr *ethhdr,
update_hna: update_routes(orig_node, orig_node->router, hna_buff, tmp_hna_buff_len); - return; }
static char count_real_packets(struct ethhdr *ethhdr, diff --git a/drivers/staging/batman-adv/send.c b/drivers/staging/batman-adv/send.c index edfdd5d..944b2cd 100644 --- a/drivers/staging/batman-adv/send.c +++ b/drivers/staging/batman-adv/send.c @@ -29,8 +29,6 @@ #include "vis.h" #include "aggregation.h"
-#include "compat.h" - /* apply hop penalty for a normal link */ static uint8_t hop_penalty(const uint8_t tq) { diff --git a/drivers/staging/batman-adv/soft-interface.c b/drivers/staging/batman-adv/soft-interface.c index bc0217b..c9b35d9 100644 --- a/drivers/staging/batman-adv/soft-interface.c +++ b/drivers/staging/batman-adv/soft-interface.c @@ -28,7 +28,6 @@ #include "hash.h" #include <linux/ethtool.h> #include <linux/etherdevice.h> -#include "compat.h"
static uint16_t bcast_seqno = 1; /* give own bcast messages seq numbers to avoid * broadcast storms */ @@ -120,7 +119,7 @@ void interface_setup(struct net_device *dev)
/* generate random address */ random_ether_addr(dev_addr); - memcpy(dev->dev_addr, dev_addr, sizeof(dev->dev_addr)); + memcpy(dev->dev_addr, dev_addr, ETH_ALEN);
SET_ETHTOOL_OPS(dev, &bat_ethtool_ops);
@@ -269,7 +268,7 @@ unlock: dropped: priv->stats.tx_dropped++; end: - return 0; + return NETDEV_TX_OK; }
void interface_rx(struct sk_buff *skb, int hdr_size) @@ -338,7 +337,6 @@ static u32 bat_get_msglevel(struct net_device *dev)
static void bat_set_msglevel(struct net_device *dev, u32 value) { - return; }
static u32 bat_get_link(struct net_device *dev) diff --git a/drivers/staging/batman-adv/translation-table.c b/drivers/staging/batman-adv/translation-table.c index 398a808..d56f665 100644 --- a/drivers/staging/batman-adv/translation-table.c +++ b/drivers/staging/batman-adv/translation-table.c @@ -24,7 +24,6 @@ #include "soft-interface.h" #include "types.h" #include "hash.h" -#include "compat.h"
struct hashtable_t *hna_local_hash; static struct hashtable_t *hna_global_hash; diff --git a/drivers/staging/batman-adv/vis.c b/drivers/staging/batman-adv/vis.c index 2633d0f..bb02917 100644 --- a/drivers/staging/batman-adv/vis.c +++ b/drivers/staging/batman-adv/vis.c @@ -26,7 +26,6 @@ #include "soft-interface.h" #include "hard-interface.h" #include "hash.h" -#include "compat.h"
struct hashtable_t *vis_hash; DEFINE_SPINLOCK(vis_hash_lock);
From: Linus Lüssing linus.luessing@web.de
A non-integer changes the aggregation mode. Therefore this patch changes the behaviour to explicitly check strict_strtoul()'s return code.
Signed-off-by: Linus Lüssing linus.luessing@web.de Acked-by: Simon Wunderlich siwu@hrz.tu-chemnitz.de Signed-off-by: Andrew Lunn andrew@lunn.ch --- drivers/staging/batman-adv/proc.c | 24 ++++++++++++------------ 1 files changed, 12 insertions(+), 12 deletions(-)
diff --git a/drivers/staging/batman-adv/proc.c b/drivers/staging/batman-adv/proc.c index 6a7c8bb..2aeee7a 100644 --- a/drivers/staging/batman-adv/proc.c +++ b/drivers/staging/batman-adv/proc.c @@ -427,6 +427,7 @@ static ssize_t proc_aggr_write(struct file *file, const char __user *buffer, char *aggr_string; int not_copied = 0; unsigned long aggregation_enabled_tmp; + int retval;
aggr_string = kmalloc(count, GFP_KERNEL);
@@ -436,22 +437,21 @@ static ssize_t proc_aggr_write(struct file *file, const char __user *buffer, not_copied = copy_from_user(aggr_string, buffer, count); aggr_string[count - not_copied - 1] = 0;
- strict_strtoul(aggr_string, 10, &aggregation_enabled_tmp); + retval = strict_strtoul(aggr_string, 10, &aggregation_enabled_tmp);
- if ((aggregation_enabled_tmp != 0) && (aggregation_enabled_tmp != 1)) { + if (retval || aggregation_enabled_tmp > 1) { printk(KERN_ERR "batman-adv:Aggregation can only be enabled (1) or disabled (0), given value: %li\n", aggregation_enabled_tmp); - goto end; + } else { + printk(KERN_INFO "batman-adv:Changing aggregation from: %s (%i) to: %s (%li)\n", + (atomic_read(&aggregation_enabled) == 1 ? + "enabled" : "disabled"), + atomic_read(&aggregation_enabled), + (aggregation_enabled_tmp == 1 ? "enabled" : "disabled"), + aggregation_enabled_tmp); + atomic_set(&aggregation_enabled, + (unsigned)aggregation_enabled_tmp); }
- printk(KERN_INFO "batman-adv:Changing aggregation from: %s (%i) to: %s (%li)\n", - (atomic_read(&aggregation_enabled) == 1 ? - "enabled" : "disabled"), - atomic_read(&aggregation_enabled), - (aggregation_enabled_tmp == 1 ? "enabled" : "disabled"), - aggregation_enabled_tmp); - - atomic_set(&aggregation_enabled, (unsigned)aggregation_enabled_tmp); -end: kfree(aggr_string); return count; }
On Sat, Jan 02, 2010 at 11:30:37AM +0100, Andrew Lunn wrote:
From: Simon Wunderlich siwu@hrz.tu-chemnitz.de
state in the README that we also (compile) support 2.6.32
Wouldn't it make more sense to just drop this line now that the code is in the main kernel tree?
thanks,
greg k-h
On Tue, Jan 05, 2010 at 02:40:30PM -0800, Greg KH wrote:
On Sat, Jan 02, 2010 at 11:30:37AM +0100, Andrew Lunn wrote:
From: Simon Wunderlich siwu@hrz.tu-chemnitz.de
state in the README that we also (compile) support 2.6.32
Wouldn't it make more sense to just drop this line now that the code is in the main kernel tree?
Yes it does. Also, the README is out of date in some other places as well. A patch is on its way to fix this.
Thanks Andrew
b.a.t.m.a.n@lists.open-mesh.org