[B.A.T.M.A.N.] [Patch 1/1] Staging: batman-adv: Use printk(%pM) for MAC addresses
by Andrew Lunn
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.
For kernels older than 2.6.29 the printk support from 2.6.31 has been
imported into batman-adv and will be used for formatting the output
before passing it onto the native printk() function.
Fix the typo found by Gus Wirth.
grep pMs suggests the typo only occurred once.
Stripped out all unneeded %pX functionality in bat_printk.c so that
the code is more likely to build with older kernels.
Only build bat_printk.c with kernels that require it, thanks to Simon
Wunderlich Makefile.kbuild patch.
Signed-off-by: Andrew Lunn <andrew(a)lunn.ch>
Index: Makefile.kbuild
===================================================================
--- Makefile.kbuild (revision 1524)
+++ Makefile.kbuild (working copy)
@@ -32,4 +32,4 @@
endif
obj-m += batman-adv.o
-batman-adv-objs := main.o proc.o send.o routing.o soft-interface.o device.o translation-table.o bitarray.o hash.o ring_buffer.o vis.o hard-interface.o aggregation.o originator.o
+batman-adv-objs := main.o proc.o send.o routing.o soft-interface.o device.o translation-table.o bitarray.o hash.o ring_buffer.o vis.o hard-interface.o aggregation.o originator.o $(shell [ "2" -eq "$(VERSION)" ] && [ "6" -eq "$(PATCHLEVEL)" ] && [ "$(SUBLEVEL)" -le "28" ] && echo bat_printk.o)
Index: translation-table.c
===================================================================
--- translation-table.c (revision 1524)
+++ translation-table.c (working copy)
@@ -61,7 +61,6 @@
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 @@
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,12 +198,9 @@
static void hna_local_del(struct hna_local_entry *hna_local_entry,
char *message)
{
- char hna_str[ETH_STR_LEN];
+ bat_dbg(DBG_ROUTES, "Deleting local hna entry (%pM): %s \n",
+ hna_local_entry->addr, message);
- addr_to_string(hna_str, hna_local_entry->addr);
- bat_dbg(DBG_ROUTES, "Deleting local hna entry (%s): %s \n",
- hna_str, message);
-
hash_remove(hna_local_hash, hna_local_entry->addr);
_hna_local_del(hna_local_entry);
}
@@ -278,13 +272,10 @@
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 @@
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,14 +389,10 @@
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];
+ bat_dbg(DBG_ROUTES, "Deleting global hna entry %pM (via %pM): %s \n",
+ hna_global_entry->addr, hna_global_entry->orig_node->orig,
+ message);
- 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);
-
hash_remove(hna_global_hash, hna_global_entry->addr);
kfree(hna_global_entry);
}
Index: send.c
===================================================================
--- send.c (revision 1524)
+++ send.c (working copy)
@@ -132,7 +132,6 @@
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 @@
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 @@
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 @@
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 @@
/* 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);
Index: hard-interface.c
===================================================================
--- hard-interface.c (revision 1524)
+++ hard-interface.c (working copy)
@@ -74,7 +74,6 @@
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 @@
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();
Index: originator.c
===================================================================
--- originator.c (revision 1524)
+++ originator.c (working copy)
@@ -121,7 +121,6 @@
{
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 +128,7 @@
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 +184,6 @@
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 +198,7 @@
(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 +216,14 @@
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))
Index: routing.c
===================================================================
--- routing.c (revision 1524)
+++ routing.c (working copy)
@@ -80,32 +80,24 @@
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 @@
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 @@
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 @@
{
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 @@
/* 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 @@
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 @@
}
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 @@
!(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;
}
@@ -659,7 +641,6 @@
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;
@@ -670,11 +651,8 @@
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 %pM to %pM: ttl exceeded\n", icmp_packet->orig, icmp_packet->dst);
- printk(KERN_WARNING "batman-adv:Warning - can't send packet from %s to %s: ttl exceeded\n", src_str, dst_str);
-
/* send TTL exceeded if packet is an echo request (traceroute) */
if (icmp_packet->msg_type != ECHO_REQUEST)
return NET_RX_DROP;
@@ -793,7 +771,6 @@
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;
@@ -831,10 +808,7 @@
/* 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;
}
@@ -984,5 +958,3 @@
}
return ret;
}
-
-
Index: compat.h
===================================================================
--- compat.h (revision 1524)
+++ compat.h (working copy)
@@ -73,3 +73,8 @@
ret; \
})
#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25) */
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 29)
+asmlinkage int bat_printk(const char *fmt, ...);
+#define printk bat_printk
+#endif
13 years
[B.A.T.M.A.N.] [PATCH 1/3] batman-adv: atomic variable for vis-srv activation
by Linus Lüssing
This fixes the bug discovered by Marek which did not allow turning on
the vis-server before an interface has been added. This is now being
done in a similar way as for (de)activating the aggregation mode with an
atomic variable.
Signed-off-by: Linus Lüssing <linus.luessing(a)web.de>
---
main.c | 2 ++
main.h | 1 +
proc.c | 43 ++++++++++++++++++++++++-------------------
send.c | 2 +-
vis.c | 41 +++--------------------------------------
vis.h | 2 --
6 files changed, 31 insertions(+), 60 deletions(-)
diff --git a/main.c b/main.c
index c733504..843d552 100644
--- a/main.c
+++ b/main.c
@@ -44,6 +44,7 @@ DEFINE_SPINLOCK(forw_bcast_list_lock);
atomic_t originator_interval;
atomic_t vis_interval;
+atomic_t vis_srv_enabled;
atomic_t aggregation_enabled;
int16_t num_hna;
int16_t num_ifs;
@@ -84,6 +85,7 @@ int init_module(void)
atomic_set(&originator_interval, 1000);
atomic_set(&vis_interval, 1000);/* TODO: raise this later, this is only
* for debugging now. */
+ atomic_set(&vis_srv_enabled, 0);
atomic_set(&aggregation_enabled, 1);
/* the name should not be longer than 10 chars - see
diff --git a/main.h b/main.h
index 3dfe5fe..385818f 100644
--- a/main.h
+++ b/main.h
@@ -130,6 +130,7 @@ extern spinlock_t forw_bcast_list_lock;
extern atomic_t originator_interval;
extern atomic_t vis_interval;
+extern atomic_t vis_srv_enabled;
extern atomic_t aggregation_enabled;
extern int16_t num_hna;
extern int16_t num_ifs;
diff --git a/proc.c b/proc.c
index 61e1d0d..e7b7bf3 100644
--- a/proc.c
+++ b/proc.c
@@ -325,36 +325,41 @@ static int proc_transt_global_open(struct inode *inode, struct file *file)
static ssize_t proc_vis_srv_write(struct file *file, const char __user * buffer,
size_t count, loff_t *ppos)
{
- char *vis_mode_string;
+ char *vis_srv_string;
int not_copied = 0;
+ unsigned long vis_srv_enabled_tmp;
+ int retval;
- vis_mode_string = kmalloc(count, GFP_KERNEL);
+ vis_srv_string = kmalloc(count, GFP_KERNEL);
- if (!vis_mode_string)
+ if (!vis_srv_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
+ not_copied = copy_from_user(vis_srv_string, buffer, count);
+ vis_srv_string[count - not_copied - 1] = 0;
+
+ retval = strict_strtoul(vis_srv_string, 10, &vis_srv_enabled_tmp);
+
+ /* Unknown vis mode input? */
+ if (retval == -EINVAL || vis_srv_enabled_tmp > 1) {
printk(KERN_ERR "batman-adv:Unknown VIS mode: %s\n",
- vis_mode_string);
+ vis_srv_string);
+ }
+ else {
+ if (vis_srv_enabled_tmp == 0)
+ printk(KERN_INFO "batman-adv:Setting VIS mode to client (disabling vis server)\n");
+ else
+ printk(KERN_INFO "batman-adv:Setting VIS mode to server (enabling vis server)\n");
+ atomic_set(&vis_srv_enabled, vis_srv_enabled_tmp);
+ }
- kfree(vis_mode_string);
+ kfree(vis_srv_string);
return count;
}
static int proc_vis_srv_read(struct seq_file *seq, void *offset)
{
- int vis_server = is_vis_server();
+ int vis_server = atomic_read(&vis_srv_enabled);
seq_printf(seq, "[%c] client mode (server disabled) \n",
(!vis_server) ? 'x' : ' ');
@@ -380,7 +385,7 @@ static int proc_vis_data_read(struct seq_file *seq, void *offset)
unsigned long flags;
rcu_read_lock();
- if (list_empty(&if_list) || (!is_vis_server())) {
+ if (list_empty(&if_list) || (!atomic_read(&vis_srv_enabled))) {
rcu_read_unlock();
goto end;
}
diff --git a/send.c b/send.c
index fd48f3f..92d14a6 100644
--- a/send.c
+++ b/send.c
@@ -279,7 +279,7 @@ void schedule_own_packet(struct batman_if *batman_if)
/* change sequence number to network order */
batman_packet->seqno = htons((uint16_t)atomic_read(&batman_if->seqno));
- if (is_vis_server())
+ if (atomic_read(&vis_srv_enabled))
batman_packet->flags = VIS_SERVER;
else
batman_packet->flags = 0;
diff --git a/vis.c b/vis.c
index fa8afdb..e7c14b5 100644
--- a/vis.c
+++ b/vis.c
@@ -49,41 +49,6 @@ static void free_info(void *data)
kfree(info);
}
-/* set the mode of the visualization to client or server */
-void vis_set_mode(int mode)
-{
- unsigned long flags;
- spin_lock_irqsave(&vis_hash_lock, flags);
-
- if (my_vis_info != NULL)
- my_vis_info->packet.vis_type = mode;
-
- spin_unlock_irqrestore(&vis_hash_lock, flags);
-}
-
-/* is_vis_server(), locked outside */
-static int is_vis_server_locked(void)
-{
- if (my_vis_info != NULL)
- if (my_vis_info->packet.vis_type == VIS_TYPE_SERVER_SYNC)
- return 1;
-
- return 0;
-}
-
-/* get the current set mode */
-int is_vis_server(void)
-{
- int ret = 0;
- unsigned long flags;
-
- spin_lock_irqsave(&vis_hash_lock, flags);
- ret = is_vis_server_locked();
- spin_unlock_irqrestore(&vis_hash_lock, flags);
-
- return ret;
-}
-
/* Compare two vis packets, used by the hashing algorithm */
static int vis_info_cmp(void *data1, void *data2)
{
@@ -280,7 +245,7 @@ void receive_server_sync_packet(struct vis_packet *vis_packet, int vis_info_len)
/* only if we are server ourselves and packet is newer than the one in
* hash.*/
- if (is_vis_server_locked() && is_new) {
+ if (atomic_read(&vis_srv_enabled) && is_new) {
memcpy(info->packet.target_orig, broadcastAddr, ETH_ALEN);
if (list_empty(&info->send_list))
list_add_tail(&info->send_list, &send_list);
@@ -309,7 +274,7 @@ void receive_client_update_packet(struct vis_packet *vis_packet,
/* send only if we're the target server or ... */
- if (is_vis_server_locked() &&
+ if (atomic_read(&vis_srv_enabled) &&
is_my_mac(info->packet.target_orig) &&
is_new) {
info->packet.vis_type = VIS_TYPE_SERVER_SYNC; /* upgrade! */
@@ -380,7 +345,7 @@ static int generate_vis_packet(void)
info->packet.seqno++;
info->packet.entries = 0;
- if (!is_vis_server_locked()) {
+ if (!atomic_read(&vis_srv_enabled)) {
best_tq = find_best_vis_server(info);
if (best_tq < 0) {
spin_unlock_irqrestore(&orig_hash_lock, flags);
diff --git a/vis.h b/vis.h
index 2e24258..0cdafde 100644
--- a/vis.h
+++ b/vis.h
@@ -48,8 +48,6 @@ struct recvlist_node {
extern struct hashtable_t *vis_hash;
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,
--
1.6.5.7
13 years
[B.A.T.M.A.N.] [PATCH 2/3] batman-adv: No deact of aggregation on wrong input
by Linus Lüssing
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(a)web.de>
---
proc.c | 24 ++++++++++++------------
1 files changed, 12 insertions(+), 12 deletions(-)
diff --git a/proc.c b/proc.c
index e7b7bf3..232efe3 100644
--- a/proc.c
+++ b/proc.c
@@ -433,6 +433,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);
@@ -442,22 +443,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 == -EINVAL || 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;
}
--
1.6.5.7
13 years, 1 month
[B.A.T.M.A.N.] [PATCH 3/3] batman-adv: Remove unused variable
by Linus Lüssing
The variable 'flag' is never being used in this function, therefore
removing it.
Signed-off-by: Linus Lüssing <linus.luessing(a)web.de>
---
soft-interface.c | 1 -
1 files changed, 0 insertions(+), 1 deletions(-)
diff --git a/soft-interface.c b/soft-interface.c
index 4d4d542..bc0217b 100644
--- a/soft-interface.c
+++ b/soft-interface.c
@@ -148,7 +148,6 @@ struct net_device_stats *interface_stats(struct net_device *dev)
int interface_set_mac_addr(struct net_device *dev, void *p)
{
struct sockaddr *addr = p;
- unsigned long flags;
if (!is_valid_ether_addr(addr->sa_data))
return -EADDRNOTAVAIL;
--
1.6.5.7
13 years, 1 month
[B.A.T.M.A.N.] Coccinelle tests?
by Andrew Lunn
Hi Folks
I asked Julai Lawall to run her Coccinelle
(http://coccinelle.lip6.fr/) test suite on batman-adv. Here are her
results. Some of these issues are already fixed in subversion, others
are real bugs, and some are nice to fix.
Andrew
----- Forwarded message from Julia Lawall <julia(a)diku.dk> -----
Date: Thu, 31 Dec 2009 17:40:21 +0100 (CET)
From: Julia Lawall <julia(a)diku.dk>
To: Andrew Lunn <andrew(a)lunn.ch>
Subject: Re: Standard coccinelle tests?
X-Spam-Status: No, score=-2.6 required=4.0 tests=BAYES_00 autolearn=ham
version=3.2.5
I ran all of my tests on your code, and came up with the following
results. Search for *** to see my comments about what I think should be
done. It is only the first one that seems like a serious bug. Actually,
I worked on that problem quite recently, but it must have been just before
your code showed up, or I missed it for some other reason, because I don't
have a record of having submitted a patch for that issue for your code.
julia
dev_addr.cocci
***dev->dev_addr is a pointer. The size of an address is probably 6. dev
has an addr_len field that might be initialized.
diff -u -p /var/linuxes/linux-next/drivers/staging/batman-adv/soft-interface.c /tmp/nothing
--- /var/linuxes/linux-next/drivers/staging/batman-adv/soft-interface.c 2009-12-19 09:38:58.000000000 +0100
@@ -121,7 +121,7 @@ void interface_setup(struct net_device *
/* generate random address */
random_ether_addr(dev_addr);
- memcpy(dev->dev_addr, dev_addr, sizeof(dev->dev_addr));
SET_ETHTOOL_OPS(dev, &bat_ethtool_ops);
kmalmem.cocci
*** Use kzalloc instead of kmalloc + memset. Also consider testing the result
of the kmaloc for NULL.
diff -u -p a/originator.c b/originator.c
--- a/originator.c 2009-12-19 09:38:58.000000000 +0100
+++ b/originator.c 2009-12-31 14:56:59.000000000 +0100
@@ -76,8 +76,7 @@ create_neighbor(struct orig_node *orig_n
bat_dbg(DBG_BATMAN, "Creating new last-hop neighbour of originator\n");
- neigh_node = kmalloc(sizeof(struct neigh_node), GFP_ATOMIC);
- memset(neigh_node, 0, sizeof(struct neigh_node));
+ neigh_node = kzalloc(sizeof(struct neigh_node), GFP_ATOMIC);
INIT_LIST_HEAD(&neigh_node->list);
memcpy(neigh_node->addr, neigh, ETH_ALEN);
@@ -126,8 +125,7 @@ struct orig_node *get_orig_node(uint8_t
addr_to_string(orig_str, addr);
bat_dbg(DBG_BATMAN, "Creating new originator: %s \n", orig_str);
- orig_node = kmalloc(sizeof(struct orig_node), GFP_ATOMIC);
- memset(orig_node, 0, sizeof(struct orig_node));
+ orig_node = kzalloc(sizeof(struct orig_node), GFP_ATOMIC);
INIT_LIST_HEAD(&orig_node->neigh_list);
memcpy(orig_node->orig, addr, ETH_ALEN);
@@ -137,12 +135,10 @@ struct orig_node *get_orig_node(uint8_t
size = num_ifs * sizeof(TYPE_OF_WORD) * NUM_WORDS;
- orig_node->bcast_own = kmalloc(size, GFP_ATOMIC);
- memset(orig_node->bcast_own, 0, size);
+ orig_node->bcast_own = kzalloc(size, GFP_ATOMIC);
size = num_ifs * sizeof(uint8_t);
- orig_node->bcast_own_sum = kmalloc(size, GFP_ATOMIC);
- memset(orig_node->bcast_own_sum, 0, size);
+ orig_node->bcast_own_sum = kzalloc(size, GFP_ATOMIC);
hash_add(orig_hash, orig_node);
kmbfree.cocci
*** As far as I can tell, in the following, the if after the out label is not
needed.
diff -u -p /var/linuxes/linux-next/drivers/staging/batman-adv/hard-interface.c /tmp/nothing
--- /var/linuxes/linux-next/drivers/staging/batman-adv/hard-interface.c 2009-12-19 09:38:58.000000000 +0100
@@ -335,7 +335,7 @@ int hardif_add_interface(char *dev, int
else
batman_if->packet_len = BAT_PACKET_LEN;
- batman_if->packet_buff = kmalloc(batman_if->packet_len, GFP_KERNEL);
if (!batman_if->packet_buff) {
printk(KERN_ERR "batman-adv:Can't add interface packet (%s): out of memory\n", dev);
@@ -401,7 +401,7 @@ int hardif_add_interface(char *dev, int
out:
if (batman_if->packet_buff)
kfree(batman_if->packet_buff);
- kfree(batman_if);
kfree(dev);
return -1;
}
kmtest.cocci
*** the result of kmalloc should be tested for NULL
diff -u -p /var/linuxes/linux-next/drivers/staging/batman-adv/hash.c /tmp/nothing
--- /var/linuxes/linux-next/drivers/staging/batman-adv/hash.c 2009-11-23 22:35:21.000000000 +0100
@@ -76,7 +76,7 @@ struct hash_it_t *hash_iterate(struct ha
if (iter_in == NULL) {
iter = kmalloc(sizeof(struct hash_it_t), GFP_ATOMIC);
- iter->index = -1;
iter->bucket = NULL;
iter->prev_bucket = NULL;
} else {
diff -u -p /var/linuxes/linux-next/drivers/staging/batman-adv/translation-table.c /tmp/nothing
--- /var/linuxes/linux-next/drivers/staging/batman-adv/translation-table.c 2009-12-19 09:38:58.000000000 +0100
@@ -322,7 +322,6 @@ void hna_global_add_orig(struct orig_nod
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;
}
returns.cocci
*** Perhaps there is no point to put a return by itself at the end of a
function.
diff -u -p a/routing.c b/routing.c
--- a/routing.c 2009-12-19 09:38:58.000000000 +0100
+++ b/routing.c 2009-12-31 14:59:41.000000000 +0100
@@ -307,7 +307,6 @@ static void update_orig(struct orig_node
update_hna:
update_routes(orig_node, orig_node->router, hna_buff, tmp_hna_buff_len);
- return;
}
static char count_real_packets(struct ethhdr *ethhdr,
@@ -627,7 +626,6 @@ static void recv_my_icmp_packet(struct e
}
spin_unlock(&orig_hash_lock);
- return;
}
static void recv_icmp_ttl_exceeded(struct icmp_packet *icmp_packet,
txok.cocci
*** I saw in some patch that functions store in the field .ndo_start_xmit
ought to return NETDEV_TX_OK rather than 0. I haven't submitted any patches
of my own for this situation, so I don't know for sure what the rule is.
diff -u -p a/soft-interface.c b/soft-interface.c
--- a/soft-interface.c 2009-12-19 09:38:58.000000000 +0100
+++ b/soft-interface.c 2009-12-31 15:00:31.000000000 +0100
@@ -263,7 +263,7 @@ dropped:
priv->stats.tx_dropped++;
end:
kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
}
void interface_rx(struct net_device *dev, void *packet, int packet_len)
--------------------------------
----- End forwarded message -----
13 years, 1 month
[B.A.T.M.A.N.] Changeset 1519
by Gus Wirth
I'm looking at changeset 1519 and have a question about the patch to
routing.c
On line 158 there is:
if (neigh_node)
but later at line 179 there is:
if (!neigh_node)
for essential the same functionality.
Am I confused or is one of these wrong (most likely the first one)?
Gus
13 years, 1 month
[B.A.T.M.A.N.] [PATCHv2] batman-adv: receive packets directly using skbs
by Simon Wunderlich
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.
* this might introduce new race conditions.
* aggregation and vis code still use packet buffers and are not (yet)
converted.
This is the second version of this patch to be released, i would consider
it experimental and would hereby like to as for reviews before committing
it. Some things you might want to test:
* performace differences (are there any?)
* do all components still work? (vis, batctl ping, ...)
* do high load situations or multiple interfaces cause problems
* any memory leaks i might have overlooked?
I did some tests on my 9 node qemu environment and could confirm that
usual sending/receiving, forwarding, vis, batctl ping etc works. However
i can not talk about the performance from this setup.
Things changed from the first version are:
* always keep the skb->data at the batman header within the packet
handling functions
* use skb_copy() before modifying the data, if needed
* more fragmentation friendly header handling
* use skb_headlen() instead of asking skb->len
* fix some small bugs (use kfree(skb) -> kfree_skb(skb))
Signed-off-by: Simon Wunderlich <siwu(a)hrz.tu-chemnitz.de>
---
Index: a/batman-adv-kernelland/types.h
===================================================================
--- a/batman-adv-kernelland/types.h (revision 1507)
+++ b/batman-adv-kernelland/types.h (working copy)
@@ -39,7 +39,6 @@
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 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;
Index: a/batman-adv-kernelland/send.c
===================================================================
--- a/batman-adv-kernelland/send.c (revision 1507)
+++ b/batman-adv-kernelland/send.c (working copy)
@@ -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,53 +59,71 @@
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 */
static void send_packet_to_if(struct forw_packet *forw_packet,
struct batman_if *batman_if)
@@ -331,6 +350,8 @@
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 @@
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,15 +382,17 @@
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 @@
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 @@
/* 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();
Index: a/batman-adv-kernelland/send.h
===================================================================
--- a/batman-adv-kernelland/send.h (revision 1507)
+++ b/batman-adv-kernelland/send.h (working copy)
@@ -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 @@
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);
Index: a/batman-adv-kernelland/soft-interface.c
===================================================================
--- a/batman-adv-kernelland/soft-interface.c (revision 1507)
+++ b/batman-adv-kernelland/soft-interface.c (working copy)
@@ -34,7 +34,6 @@
* 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 @@
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,6 +168,8 @@
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;
if (atomic_read(&module_state) != MODULE_ACTIVE)
@@ -185,7 +186,6 @@
goto dropped;
bcast_packet = (struct bcast_packet *)skb->data;
-
bcast_packet->version = COMPAT_VERSION;
/* batman packet type: broadcast */
@@ -194,27 +194,21 @@
/* 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(&orig_hash_lock);
/* get routing information */
orig_node = ((struct orig_node *)hash_find(orig_hash,
ethhdr->h_dest));
@@ -243,14 +237,17 @@
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(&orig_hash_lock);
+
+ send_skb_packet(skb, batman_if, dstaddr);
} else {
goto unlock;
}
-
- spin_unlock(&orig_hash_lock);
}
priv->stats.tx_packets++;
@@ -262,38 +259,40 @@
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 */
Index: a/batman-adv-kernelland/hard-interface.c
===================================================================
--- a/batman-adv-kernelland/hard-interface.c (revision 1507)
+++ b/batman-adv-kernelland/hard-interface.c (working copy)
@@ -153,9 +153,6 @@
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 @@
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 @@
/* (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 @@
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 @@
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;
}
@@ -327,7 +286,6 @@
return -1;
}
- batman_if->raw_sock = NULL;
batman_if->net_dev = NULL;
if ((if_num == 0) && (num_hna > 0))
@@ -443,6 +401,111 @@
return NOTIFY_DONE;
}
+/* find batman interface by netdev. assumes rcu_read_lock on */
+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,
};
Index: a/batman-adv-kernelland/soft-interface.h
===================================================================
--- a/batman-adv-kernelland/soft-interface.h (revision 1507)
+++ b/batman-adv-kernelland/soft-interface.h (working copy)
@@ -28,6 +28,7 @@
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[];
Index: a/batman-adv-kernelland/hard-interface.h
===================================================================
--- a/batman-adv-kernelland/hard-interface.h (revision 1507)
+++ b/batman-adv-kernelland/hard-interface.h (working copy)
@@ -32,5 +32,9 @@
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);
Index: a/batman-adv-kernelland/main.c
===================================================================
--- a/batman-adv-kernelland/main.c (revision 1507)
+++ b/batman-adv-kernelland/main.c (working copy)
@@ -50,11 +50,14 @@
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 @@
}
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 @@
soft_device = NULL;
}
+ dev_remove_pack(&batman_adv_packet_type);
+
unregister_netdevice_notifier(&hard_if_notifier);
cleanup_procfs();
@@ -162,16 +168,6 @@
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,15 +189,8 @@
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);
+ /* TODO: unregister BATMAN pack */
- kthread_task = NULL;
- }
-
originator_free();
hna_local_free();
Index: a/batman-adv-kernelland/aggregation.c
===================================================================
--- a/batman-adv-kernelland/aggregation.c (revision 1507)
+++ b/batman-adv-kernelland/aggregation.c (working copy)
@@ -115,6 +115,7 @@
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;
Index: a/batman-adv-kernelland/routing.c
===================================================================
--- a/batman-adv-kernelland/routing.c (revision 1507)
+++ b/batman-adv-kernelland/routing.c (working copy)
@@ -36,8 +36,8 @@
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);
@@ -351,10 +351,9 @@
}
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;
@@ -549,61 +548,56 @@
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;
- 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;
+ return NET_RX_DROP;
- /* 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);
+ /* 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);
+
+ 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;
+ int ret;
+ 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) */
@@ -611,34 +605,50 @@
spin_lock(&orig_hash_lock);
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)) {
+
+ /* 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),
+ send_skb_packet(skb,
orig_node->batman_if,
orig_node->router->addr);
+ ret = NET_RX_SUCCESS;
}
spin_unlock(&orig_hash_lock);
- return;
+ 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;
+ int ret;
+ 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);
@@ -646,72 +656,86 @@
/* 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);
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)) {
+
+ /* 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),
+ send_skb_packet(skb,
orig_node->batman_if,
orig_node->router->addr);
+ ret = NET_RX_SUCCESS;
}
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;
+ int hdr_size = sizeof(struct icmp_packet);
+ int ret;
+ /* 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 *) skb->data;
- icmp_packet = (struct icmp_packet *)
- (packet_buff + sizeof(struct ethhdr));
-
/* 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;
+ return recv_icmp_ttl_exceeded(skb);
}
+ ret = NET_RX_DROP;
+
/* get routing information */
spin_lock(&orig_hash_lock);
orig_node = ((struct orig_node *)
@@ -721,65 +745,77 @@
(orig_node->batman_if != NULL) &&
(orig_node->router != NULL)) {
+ /* 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),
+ send_skb_packet(skb,
orig_node->batman_if,
orig_node->router->addr);
+ ret = NET_RX_SUCCESS;
}
spin_unlock(&orig_hash_lock);
+ 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;
+ /* 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 < hdr_size)
- return;
+ unicast_packet = (struct unicast_packet *) skb->data;
- unicast_packet = (struct unicast_packet *)
- (packet_buff + sizeof(struct ethhdr));
-
/* 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);
orig_node = ((struct orig_node *)
@@ -788,50 +824,64 @@
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(&orig_hash_lock);
+
+ /* 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(&orig_hash_lock);
+ 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);
+ /* 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;
+ return NET_RX_DROP;
- /* drop packet if it has not necessary minimum size */
- if (result < hdr_size)
- return;
-
/* 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);
orig_node = ((struct orig_node *)
@@ -839,7 +889,7 @@
if (orig_node == NULL) {
spin_unlock(&orig_hash_lock);
- return;
+ return NET_RX_DROP;
}
/* check flood history */
@@ -847,7 +897,7 @@
orig_node->last_bcast_seqno,
ntohs(bcast_packet->seqno))) {
spin_unlock(&orig_hash_lock);
- return;
+ return NET_RX_DROP;
}
/* mark broadcast in flood history */
@@ -858,208 +908,57 @@
spin_unlock(&orig_hash_lock);
+ /* 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;
+ return NET_RX_DROP;
- vis_packet = (struct vis_packet *)(packet_buff + sizeof(struct ethhdr));
- vis_info_len = result - hdr_size;
-
/* 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);
-}
Index: a/batman-adv-kernelland/routing.h
===================================================================
--- a/batman-adv-kernelland/routing.h (revision 1507)
+++ b/batman-adv-kernelland/routing.h (working copy)
@@ -25,8 +25,6 @@
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,11 @@
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);
+
+
13 years, 1 month
[B.A.T.M.A.N.] [patchv2] batman-adv: Use printk(%pM) for MAC addres
by Andrew Lunn
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.
For kernels older than 2.6.29 the printk support from 2.6.31 has been
imported into batman-adv and will be used for formatting the output
before passing it onto the native printk() function.
---
Fix the typo found by Gus Wirth.
grep pMs suggests the typo only occurred once.
Signed-off-by: Andrew Lunn <andrew(a)lunn.ch>
Index: Makefile.kbuild
===================================================================
--- Makefile.kbuild (revision 1490)
+++ Makefile.kbuild (working copy)
@@ -32,4 +32,5 @@
endif
obj-m += batman-adv.o
-batman-adv-objs := main.o proc.o send.o routing.o soft-interface.o device.o translation-table.o bitarray.o hash.o ring_buffer.o vis.o hard-interface.o aggregation.o originator.o
+batman-adv-objs := main.o proc.o send.o routing.o soft-interface.o device.o translation-table.o bitarray.o hash.o ring_buffer.o vis.o hard-interface.o aggregation.o originator.o bat_printk.o
+
Index: translation-table.c
===================================================================
--- translation-table.c (revision 1490)
+++ translation-table.c (working copy)
@@ -61,7 +61,6 @@
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 @@
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,12 +198,9 @@
static void hna_local_del(struct hna_local_entry *hna_local_entry,
char *message)
{
- char hna_str[ETH_STR_LEN];
+ bat_dbg(DBG_ROUTES, "Deleting local hna entry (%pM): %s \n",
+ hna_local_entry->addr, message);
- addr_to_string(hna_str, hna_local_entry->addr);
- bat_dbg(DBG_ROUTES, "Deleting local hna entry (%s): %s \n",
- hna_str, message);
-
hash_remove(hna_local_hash, hna_local_entry->addr);
_hna_local_del(hna_local_entry);
}
@@ -263,13 +257,10 @@
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);
@@ -289,10 +280,9 @@
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);
@@ -382,14 +372,10 @@
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];
+ bat_dbg(DBG_ROUTES, "Deleting global hna entry %pM (via %pM): %s \n",
+ hna_global_entry->addr, hna_global_entry->orig_node->orig,
+ message);
- 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);
-
hash_remove(hna_global_hash, hna_global_entry->addr);
kfree(hna_global_entry);
}
Index: send.c
===================================================================
--- send.c (revision 1490)
+++ send.c (working copy)
@@ -113,7 +113,6 @@
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;
@@ -135,15 +134,14 @@
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"),
@@ -167,7 +165,6 @@
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) {
@@ -178,8 +175,6 @@
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)) ||
@@ -187,9 +182,9 @@
/* 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);
Index: bat_printk.c
===================================================================
--- bat_printk.c (revision 0)
+++ bat_printk.c (revision 0)
@@ -0,0 +1,1013 @@
+/*
+ * linux/lib/vsprintf.c
+ *
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ */
+
+/* vsprintf.c -- Lars Wirzenius & Linus Torvalds. */
+/*
+ * Wirzenius wrote this portably, Torvalds fucked it up :-)
+ */
+
+/*
+ * Fri Jul 13 2001 Crutcher Dunnavant <crutcher+kernel(a)datastacks.com>
+ * - changed to provide snprintf and vsnprintf functions
+ * So Feb 1 16:51:32 CET 2004 Juergen Quade <quade(a)hsnr.de>
+ * - scnprintf and vscnprintf
+ */
+
+#include <stdarg.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/ctype.h>
+#include <linux/kernel.h>
+#include <linux/kallsyms.h>
+#include <linux/uaccess.h>
+#include <linux/ioport.h>
+#include <net/addrconf.h>
+
+#include <asm/page.h> /* for PAGE_SIZE */
+#include <asm/div64.h>
+#include <asm/sections.h> /* for dereference_function_descriptor() */
+
+/* Works only for digits and letters, but small and fast */
+#define TOLOWER(x) ((x) | 0x20)
+
+static int skip_atoi(const char **s)
+{
+ int i = 0;
+
+ while (isdigit(**s))
+ i = i*10 + *((*s)++) - '0';
+ return i;
+}
+
+/* Decimal conversion is by far the most typical, and is used
+ * for /proc and /sys data. This directly impacts e.g. top performance
+ * with many processes running. We optimize it for speed
+ * using code from
+ * http://www.cs.uiowa.edu/~jones/bcd/decimal.html
+ * (with permission from the author, Douglas W. Jones). */
+
+/* Formats correctly any integer in [0,99999].
+ * Outputs from one to five digits depending on input.
+ * On i386 gcc 4.1.2 -O2: ~250 bytes of code. */
+static char *put_dec_trunc(char *buf, unsigned q)
+{
+ unsigned d3, d2, d1, d0;
+ d1 = (q>>4) & 0xf;
+ d2 = (q>>8) & 0xf;
+ d3 = (q>>12);
+
+ d0 = 6*(d3 + d2 + d1) + (q & 0xf);
+ q = (d0 * 0xcd) >> 11;
+ d0 = d0 - 10*q;
+ *buf++ = d0 + '0'; /* least significant digit */
+ d1 = q + 9*d3 + 5*d2 + d1;
+ if (d1 != 0) {
+ q = (d1 * 0xcd) >> 11;
+ d1 = d1 - 10*q;
+ *buf++ = d1 + '0'; /* next digit */
+
+ d2 = q + 2*d2;
+ if ((d2 != 0) || (d3 != 0)) {
+ q = (d2 * 0xd) >> 7;
+ d2 = d2 - 10*q;
+ *buf++ = d2 + '0'; /* next digit */
+
+ d3 = q + 4*d3;
+ if (d3 != 0) {
+ q = (d3 * 0xcd) >> 11;
+ d3 = d3 - 10*q;
+ *buf++ = d3 + '0'; /* next digit */
+ if (q != 0)
+ /* most sign. digit */
+ *buf++ = q + '0';
+ }
+ }
+ }
+ return buf;
+}
+/* Same with if's removed. Always emits five digits */
+static char *put_dec_full(char *buf, unsigned q)
+{
+ /* BTW, if q is in [0,9999], 8-bit ints will be enough, */
+ /* but anyway, gcc produces better code with full-sized ints */
+ unsigned d3, d2, d1, d0;
+ d1 = (q>>4) & 0xf;
+ d2 = (q>>8) & 0xf;
+ d3 = (q>>12);
+
+ /* Possible ways to approx. divide by 10 */
+ /* gcc -O2 replaces multiply with shifts and adds */
+ /* (x * 0xcd) >> 11: 11001101 - shorter code than * 0x67 (on i386) */
+ /* (x * 0x67) >> 10: 1100111 */
+ /* (x * 0x34) >> 9: 110100 - same */
+ /* (x * 0x1a) >> 8: 11010 - same */
+ /* (x * 0x0d) >> 7: 1101 - same, shortest code (on i386) */
+
+ d0 = 6*(d3 + d2 + d1) + (q & 0xf);
+ q = (d0 * 0xcd) >> 11;
+ d0 = d0 - 10*q;
+ *buf++ = d0 + '0';
+ d1 = q + 9*d3 + 5*d2 + d1;
+ q = (d1 * 0xcd) >> 11;
+ d1 = d1 - 10*q;
+ *buf++ = d1 + '0';
+
+ d2 = q + 2*d2;
+ q = (d2 * 0xd) >> 7;
+ d2 = d2 - 10*q;
+ *buf++ = d2 + '0';
+
+ d3 = q + 4*d3;
+ q = (d3 * 0xcd) >> 11; /* - shorter code */
+ /* q = (d3 * 0x67) >> 10; - would also work */
+ d3 = d3 - 10*q;
+ *buf++ = d3 + '0';
+ *buf++ = q + '0';
+ return buf;
+}
+/* No inlining helps gcc to use registers better */
+static noinline char *put_dec(char *buf, unsigned long long num)
+{
+ while (1) {
+ unsigned rem;
+ if (num < 100000)
+ return put_dec_trunc(buf, num);
+ rem = do_div(num, 100000);
+ buf = put_dec_full(buf, rem);
+ }
+}
+
+#define ZEROPAD 1 /* pad with zero */
+#define SIGN 2 /* unsigned/signed long */
+#define PLUS 4 /* show plus */
+#define SPACE 8 /* space if plus */
+#define LEFT 16 /* left justified */
+#define SMALL 32 /* Must be 32 == 0x20 */
+#define SPECIAL 64 /* 0x */
+
+enum format_type {
+ FORMAT_TYPE_NONE, /* Just a string part */
+ FORMAT_TYPE_WIDTH,
+ FORMAT_TYPE_PRECISION,
+ FORMAT_TYPE_CHAR,
+ FORMAT_TYPE_STR,
+ FORMAT_TYPE_PTR,
+ FORMAT_TYPE_PERCENT_CHAR,
+ FORMAT_TYPE_INVALID,
+ FORMAT_TYPE_LONG_LONG,
+ FORMAT_TYPE_ULONG,
+ FORMAT_TYPE_LONG,
+ FORMAT_TYPE_UBYTE,
+ FORMAT_TYPE_BYTE,
+ FORMAT_TYPE_USHORT,
+ FORMAT_TYPE_SHORT,
+ FORMAT_TYPE_UINT,
+ FORMAT_TYPE_INT,
+ FORMAT_TYPE_NRCHARS,
+ FORMAT_TYPE_SIZE_T,
+ FORMAT_TYPE_PTRDIFF
+};
+
+struct printf_spec {
+ enum format_type type;
+ int flags; /* flags to number() */
+ int field_width; /* width of output field */
+ int base;
+ int precision; /* # of digits/chars */
+ int qualifier;
+};
+
+static char *number(char *buf, char *end, unsigned long long num,
+ struct printf_spec spec)
+{
+ /* we are called with base 8, 10 or 16, only, thus don't need "G..." */
+ static const char digits[16] = "0123456789ABCDEF";
+
+ char tmp[66];
+ char sign;
+ char locase;
+ int need_pfx = ((spec.flags & SPECIAL) && spec.base != 10);
+ int i;
+
+ /* locase = 0 or 0x20. ORing digits or letters with 'locase'
+ * produces same digits or (maybe lowercased) letters */
+ locase = (spec.flags & SMALL);
+ if (spec.flags & LEFT)
+ spec.flags &= ~ZEROPAD;
+ sign = 0;
+ if (spec.flags & SIGN) {
+ if ((signed long long) num < 0) {
+ sign = '-';
+ num = -(signed long long) num;
+ spec.field_width--;
+ } else if (spec.flags & PLUS) {
+ sign = '+';
+ spec.field_width--;
+ } else if (spec.flags & SPACE) {
+ sign = ' ';
+ spec.field_width--;
+ }
+ }
+ if (need_pfx) {
+ spec.field_width--;
+ if (spec.base == 16)
+ spec.field_width--;
+ }
+
+ /* generate full string in tmp[], in reverse order */
+ i = 0;
+ if (num == 0)
+ tmp[i++] = '0';
+ /* Generic code, for any base:
+ else do {
+ tmp[i++] = (digits[do_div(num,base)] | locase);
+ } while (num != 0);
+ */
+ else if (spec.base != 10) { /* 8 or 16 */
+ int mask = spec.base - 1;
+ int shift = 3;
+ if (spec.base == 16)
+ shift = 4;
+ do {
+ tmp[i++] = (digits[((unsigned char)num) & mask]
+ | locase);
+ num >>= shift;
+ } while (num);
+ } else { /* base 10 */
+ i = put_dec(tmp, num) - tmp;
+ }
+
+ /* printing 100 using %2d gives "100", not "00" */
+ if (i > spec.precision)
+ spec.precision = i;
+ /* leading space padding */
+ spec.field_width -= spec.precision;
+ if (!(spec.flags & (ZEROPAD+LEFT))) {
+ while (--spec.field_width >= 0) {
+ if (buf < end)
+ *buf = ' ';
+ ++buf;
+ }
+ }
+ /* sign */
+ if (sign) {
+ if (buf < end)
+ *buf = sign;
+ ++buf;
+ }
+ /* "0x" / "0" prefix */
+ if (need_pfx) {
+ if (buf < end)
+ *buf = '0';
+ ++buf;
+ if (spec.base == 16) {
+ if (buf < end)
+ *buf = ('X' | locase);
+ ++buf;
+ }
+ }
+ /* zero or space padding */
+ if (!(spec.flags & LEFT)) {
+ char c = (spec.flags & ZEROPAD) ? '0' : ' ';
+ while (--spec.field_width >= 0) {
+ if (buf < end)
+ *buf = c;
+ ++buf;
+ }
+ }
+ /* hmm even more zero padding? */
+ while (i <= --spec.precision) {
+ if (buf < end)
+ *buf = '0';
+ ++buf;
+ }
+ /* actual digits of result */
+ while (--i >= 0) {
+ if (buf < end)
+ *buf = tmp[i];
+ ++buf;
+ }
+ /* trailing space padding */
+ while (--spec.field_width >= 0) {
+ if (buf < end)
+ *buf = ' ';
+ ++buf;
+ }
+ return buf;
+}
+
+static char *string(char *buf, char *end, char *s, struct printf_spec spec)
+{
+ int len, i;
+
+ if ((unsigned long)s < PAGE_SIZE)
+ s = "<NULL>";
+
+ len = strnlen(s, spec.precision);
+
+ if (!(spec.flags & LEFT)) {
+ while (len < spec.field_width--) {
+ if (buf < end)
+ *buf = ' ';
+ ++buf;
+ }
+ }
+ for (i = 0; i < len; ++i) {
+ if (buf < end)
+ *buf = *s;
+ ++buf; ++s;
+ }
+ while (len < spec.field_width--) {
+ if (buf < end)
+ *buf = ' ';
+ ++buf;
+ }
+ return buf;
+}
+
+static char *resource_string(char *buf, char *end, struct resource *res,
+ struct printf_spec spec)
+{
+#ifndef IO_RSRC_PRINTK_SIZE
+#define IO_RSRC_PRINTK_SIZE 4
+#endif
+
+#ifndef MEM_RSRC_PRINTK_SIZE
+#define MEM_RSRC_PRINTK_SIZE 8
+#endif
+ struct printf_spec num_spec = {
+ .base = 16,
+ .precision = -1,
+ .flags = SPECIAL | SMALL | ZEROPAD,
+ };
+ /* room for the actual numbers, the two "0x", -, [, ] and the final
+ zero */
+ char sym[4*sizeof(resource_size_t) + 8];
+ char *p = sym, *pend = sym + sizeof(sym);
+ int size = -1;
+
+ if (res->flags & IORESOURCE_IO)
+ size = IO_RSRC_PRINTK_SIZE;
+ else if (res->flags & IORESOURCE_MEM)
+ size = MEM_RSRC_PRINTK_SIZE;
+
+ *p++ = '[';
+ num_spec.field_width = size;
+ p = number(p, pend, res->start, num_spec);
+ *p++ = '-';
+ p = number(p, pend, res->end, num_spec);
+ *p++ = ']';
+ *p = 0;
+
+ return string(buf, end, sym, spec);
+}
+
+static char *mac_address_string(char *buf, char *end, u8 *addr,
+ struct printf_spec spec, const char *fmt)
+{
+ char mac_addr[sizeof("xx:xx:xx:xx:xx:xx")];
+ char *p = mac_addr;
+ int i;
+
+ for (i = 0; i < 6; i++) {
+ p = pack_hex_byte(p, addr[i]);
+ if (fmt[0] == 'M' && i != 5)
+ *p++ = ':';
+ }
+ *p = '\0';
+
+ return string(buf, end, mac_addr, spec);
+}
+
+static char *ip4_string(char *p, const u8 *addr, bool leading_zeros)
+{
+ int i;
+
+ for (i = 0; i < 4; i++) {
+ char temp[3]; /* hold each IP quad in reverse order */
+ int digits = put_dec_trunc(temp, addr[i]) - temp;
+ if (leading_zeros) {
+ if (digits < 3)
+ *p++ = '0';
+ if (digits < 2)
+ *p++ = '0';
+ }
+ /* reverse the digits in the quad */
+ while (digits--)
+ *p++ = temp[digits];
+ if (i < 3)
+ *p++ = '.';
+ }
+
+ *p = '\0';
+ return p;
+}
+
+static char *ip6_compressed_string(char *p, const char *addr)
+{
+ int i;
+ int j;
+ int range;
+ unsigned char zerolength[8];
+ int longest = 1;
+ int colonpos = -1;
+ u16 word;
+ u8 hi;
+ u8 lo;
+ bool needcolon = false;
+ bool useIPv4;
+ struct in6_addr in6;
+
+ memcpy(&in6, addr, sizeof(struct in6_addr));
+
+ useIPv4 = ipv6_addr_v4mapped(&in6) || ipv6_addr_is_isatap(&in6);
+
+ memset(zerolength, 0, sizeof(zerolength));
+
+ if (useIPv4)
+ range = 6;
+ else
+ range = 8;
+
+ /* find position of longest 0 run */
+ for (i = 0; i < range; i++) {
+ for (j = i; j < range; j++) {
+ if (in6.s6_addr16[j] != 0)
+ break;
+ zerolength[i]++;
+ }
+ }
+ for (i = 0; i < range; i++) {
+ if (zerolength[i] > longest) {
+ longest = zerolength[i];
+ colonpos = i;
+ }
+ }
+
+ /* emit address */
+ for (i = 0; i < range; i++) {
+ if (i == colonpos) {
+ if (needcolon || i == 0)
+ *p++ = ':';
+ *p++ = ':';
+ needcolon = false;
+ i += longest - 1;
+ continue;
+ }
+ if (needcolon) {
+ *p++ = ':';
+ needcolon = false;
+ }
+ /* hex u16 without leading 0s */
+ word = ntohs(in6.s6_addr16[i]);
+ hi = word >> 8;
+ lo = word & 0xff;
+ if (hi) {
+ if (hi > 0x0f)
+ p = pack_hex_byte(p, hi);
+ else
+ *p++ = hex_asc_lo(hi);
+ }
+ if (hi || lo > 0x0f)
+ p = pack_hex_byte(p, lo);
+ else
+ *p++ = hex_asc_lo(lo);
+ needcolon = true;
+ }
+
+ if (useIPv4) {
+ if (needcolon)
+ *p++ = ':';
+ p = ip4_string(p, &in6.s6_addr[12], false);
+ }
+
+ *p = '\0';
+ return p;
+}
+
+static char *ip6_string(char *p, const char *addr, const char *fmt)
+{
+ int i;
+ for (i = 0; i < 8; i++) {
+ p = pack_hex_byte(p, *addr++);
+ p = pack_hex_byte(p, *addr++);
+ if (fmt[0] == 'I' && i != 7)
+ *p++ = ':';
+ }
+
+ *p = '\0';
+ return p;
+}
+
+static char *ip6_addr_string(char *buf, char *end, const u8 *addr,
+ struct printf_spec spec, const char *fmt)
+{
+ char ip6_addr[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255")];
+
+ if (fmt[0] == 'I' && fmt[2] == 'c')
+ ip6_compressed_string(ip6_addr, addr);
+ else
+ ip6_string(ip6_addr, addr, fmt);
+
+ return string(buf, end, ip6_addr, spec);
+}
+
+static char *ip4_addr_string(char *buf, char *end, const u8 *addr,
+ struct printf_spec spec, const char *fmt)
+{
+ char ip4_addr[sizeof("255.255.255.255")];
+
+ ip4_string(ip4_addr, addr, fmt[0] == 'i');
+
+ return string(buf, end, ip4_addr, spec);
+}
+
+/*
+ * Show a '%p' thing. A kernel extension is that the '%p' is followed
+ * by an extra set of alphanumeric characters that are extended format
+ * specifiers.
+ *
+ * Right now we handle:
+ *
+ * - 'F' For symbolic function descriptor pointers with offset
+ * - 'f' For simple symbolic function names without offset
+ * - 'R' For a struct resource pointer, it prints the range of
+ * addresses (not the name nor the flags)
+ * - 'M' For a 6-byte MAC address, it prints the address in the
+ * usual colon-separated hex notation
+ * - 'm' For a 6-byte MAC address, it prints the hex address without colons
+ * - 'I' [46] for IPv4/IPv6 addresses printed in the usual way
+ * IPv4 uses dot-separated decimal without leading 0's (1.2.3.4)
+ * IPv6 uses colon separated network-order 16 bit hex with leading 0's
+ * - 'i' [46] for 'raw' IPv4/IPv6 addresses
+ * IPv6 omits the colons (01020304...0f)
+ * IPv4 uses dot-separated decimal with leading 0's (010.123.045.006)
+ * - 'I6c' for IPv6 addresses printed as specified by
+ * http://www.ietf.org/id/draft-kawamura-ipv6-text-representation-03.txt
+ * Note: The difference between 'S' and 'F' is that on ia64 and ppc64
+ * function pointers are really function descriptors, which contain a
+ * pointer to the real address.
+ */
+static char *pointer(const char *fmt, char *buf, char *end, void *ptr,
+ struct printf_spec spec)
+{
+ if (!ptr)
+ return string(buf, end, "(null)", spec);
+
+ switch (*fmt) {
+ case 'F':
+ case 'f':
+ ptr = dereference_function_descriptor(ptr);
+ case 'R':
+ return resource_string(buf, end, ptr, spec);
+ case 'M': /* Colon separated: 00:01:02:03:04:05 */
+ case 'm': /* Contiguous: 000102030405 */
+ return mac_address_string(buf, end, ptr, spec, fmt);
+ case 'I': /* Formatted IP supported
+ * 4: 1.2.3.4
+ * 6: 0001:0203:...:0708
+ * 6c: 1::708 or 1::1.2.3.4
+ */
+ case 'i': /* Contiguous:
+ * 4: 001.002.003.004
+ * 6: 000102...0f
+ */
+ switch (fmt[1]) {
+ case '6':
+ return ip6_addr_string(buf, end, ptr, spec, fmt);
+ case '4':
+ return ip4_addr_string(buf, end, ptr, spec, fmt);
+ }
+ break;
+ }
+ spec.flags |= SMALL;
+ if (spec.field_width == -1) {
+ spec.field_width = 2*sizeof(void *);
+ spec.flags |= ZEROPAD;
+ }
+ spec.base = 16;
+
+ return number(buf, end, (unsigned long) ptr, spec);
+}
+
+/*
+ * Helper function to decode printf style format.
+ * Each call decode a token from the format and return the
+ * number of characters read (or likely the delta where it wants
+ * to go on the next call).
+ * The decoded token is returned through the parameters
+ *
+ * 'h', 'l', or 'L' for integer fields
+ * 'z' support added 23/7/1999 S.H.
+ * 'z' changed to 'Z' --davidm 1/25/99
+ * 't' added for ptrdiff_t
+ *
+ * @fmt: the format string
+ * @type of the token returned
+ * @flags: various flags such as +, -, # tokens..
+ * @field_width: overwritten width
+ * @base: base of the number (octal, hex, ...)
+ * @precision: precision of a number
+ * @qualifier: qualifier of a number (long, size_t, ...)
+ */
+static int format_decode(const char *fmt, struct printf_spec *spec)
+{
+ const char *start = fmt;
+
+ /* we finished early by reading the field width */
+ if (spec->type == FORMAT_TYPE_WIDTH) {
+ if (spec->field_width < 0) {
+ spec->field_width = -spec->field_width;
+ spec->flags |= LEFT;
+ }
+ spec->type = FORMAT_TYPE_NONE;
+ goto precision;
+ }
+
+ /* we finished early by reading the precision */
+ if (spec->type == FORMAT_TYPE_PRECISION) {
+ if (spec->precision < 0)
+ spec->precision = 0;
+
+ spec->type = FORMAT_TYPE_NONE;
+ goto qualifier;
+ }
+
+ /* By default */
+ spec->type = FORMAT_TYPE_NONE;
+
+ for (; *fmt ; ++fmt) {
+ if (*fmt == '%')
+ break;
+ }
+
+ /* Return the current non-format string */
+ if (fmt != start || !*fmt)
+ return fmt - start;
+
+ /* Process flags */
+ spec->flags = 0;
+
+ while (1) { /* this also skips first '%' */
+ bool found = true;
+
+ ++fmt;
+
+ switch (*fmt) {
+ case '-':
+ spec->flags |= LEFT;
+ break;
+ case '+':
+ spec->flags |= PLUS;
+ break;
+ case ' ':
+ spec->flags |= SPACE;
+ break;
+ case '#':
+ spec->flags |= SPECIAL;
+ break;
+ case '0':
+ spec->flags |= ZEROPAD;
+ break;
+ default:
+ found = false;
+ }
+
+ if (!found)
+ break;
+ }
+
+ /* get field width */
+ spec->field_width = -1;
+
+ if (isdigit(*fmt))
+ spec->field_width = skip_atoi(&fmt);
+ else if (*fmt == '*') {
+ /* it's the next argument */
+ spec->type = FORMAT_TYPE_WIDTH;
+ return ++fmt - start;
+ }
+
+precision:
+ /* get the precision */
+ spec->precision = -1;
+ if (*fmt == '.') {
+ ++fmt;
+ if (isdigit(*fmt)) {
+ spec->precision = skip_atoi(&fmt);
+ if (spec->precision < 0)
+ spec->precision = 0;
+ } else if (*fmt == '*') {
+ /* it's the next argument */
+ spec->type = FORMAT_TYPE_PRECISION;
+ return ++fmt - start;
+ }
+ }
+
+qualifier:
+ /* get the conversion qualifier */
+ spec->qualifier = -1;
+ if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' ||
+ *fmt == 'Z' || *fmt == 'z' || *fmt == 't') {
+ spec->qualifier = *fmt++;
+ if (unlikely(spec->qualifier == *fmt)) {
+ if (spec->qualifier == 'l') {
+ spec->qualifier = 'L';
+ ++fmt;
+ } else if (spec->qualifier == 'h') {
+ spec->qualifier = 'H';
+ ++fmt;
+ }
+ }
+ }
+
+ /* default base */
+ spec->base = 10;
+ switch (*fmt) {
+ case 'c':
+ spec->type = FORMAT_TYPE_CHAR;
+ return ++fmt - start;
+
+ case 's':
+ spec->type = FORMAT_TYPE_STR;
+ return ++fmt - start;
+
+ case 'p':
+ spec->type = FORMAT_TYPE_PTR;
+ return fmt - start;
+ /* skip alnum */
+
+ case 'n':
+ spec->type = FORMAT_TYPE_NRCHARS;
+ return ++fmt - start;
+
+ case '%':
+ spec->type = FORMAT_TYPE_PERCENT_CHAR;
+ return ++fmt - start;
+
+ /* integer number formats - set up the flags and "break" */
+ case 'o':
+ spec->base = 8;
+ break;
+
+ case 'x':
+ spec->flags |= SMALL;
+
+ case 'X':
+ spec->base = 16;
+ break;
+
+ case 'd':
+ case 'i':
+ spec->flags |= SIGN;
+ case 'u':
+ break;
+
+ default:
+ spec->type = FORMAT_TYPE_INVALID;
+ return fmt - start;
+ }
+
+ if (spec->qualifier == 'L')
+ spec->type = FORMAT_TYPE_LONG_LONG;
+ else if (spec->qualifier == 'l') {
+ if (spec->flags & SIGN)
+ spec->type = FORMAT_TYPE_LONG;
+ else
+ spec->type = FORMAT_TYPE_ULONG;
+ } else if (spec->qualifier == 'Z' || spec->qualifier == 'z') {
+ spec->type = FORMAT_TYPE_SIZE_T;
+ } else if (spec->qualifier == 't') {
+ spec->type = FORMAT_TYPE_PTRDIFF;
+ } else if (spec->qualifier == 'H') {
+ if (spec->flags & SIGN)
+ spec->type = FORMAT_TYPE_BYTE;
+ else
+ spec->type = FORMAT_TYPE_UBYTE;
+ } else if (spec->qualifier == 'h') {
+ if (spec->flags & SIGN)
+ spec->type = FORMAT_TYPE_SHORT;
+ else
+ spec->type = FORMAT_TYPE_USHORT;
+ } else {
+ if (spec->flags & SIGN)
+ spec->type = FORMAT_TYPE_INT;
+ else
+ spec->type = FORMAT_TYPE_UINT;
+ }
+
+ return ++fmt - start;
+}
+
+/**
+ * bat_vsnprintf - Format a string and place it in a buffer
+ * @buf: The buffer to place the result into
+ * @size: The size of the buffer, including the trailing null space
+ * @fmt: The format string to use
+ * @args: Arguments for the format string
+ *
+ * This function follows C99 bat_vsnprintf, but has some extensions:
+ * %pS output the name of a text symbol with offset
+ * %ps output the name of a text symbol without offset
+ * %pF output the name of a function pointer with its offset
+ * %pf output the name of a function pointer without its offset
+ * %pR output the address range in a struct resource
+ * %n is ignored
+ *
+ * The return value is the number of characters which would
+ * be generated for the given input, excluding the trailing
+ * '\0', as per ISO C99. If you want to have the exact
+ * number of characters written into @buf as return value
+ * (not including the trailing '\0'), use vscnprintf(). If the
+ * return is greater than or equal to @size, the resulting
+ * string is truncated.
+ *
+ * Call this function if you are already dealing with a va_list.
+ * You probably want snprintf() instead.
+ */
+static int bat_vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
+{
+ unsigned long long num;
+ char *str, *end, c;
+ int read;
+ struct printf_spec spec = {0};
+
+ /* Reject out-of-range values early. Large positive sizes are
+ used for unknown buffer sizes. */
+ if (WARN_ON_ONCE((int) size < 0))
+ return 0;
+
+ str = buf;
+ end = buf + size;
+
+ /* Make sure end is always >= buf */
+ if (end < buf) {
+ end = ((void *)-1);
+ size = end - buf;
+ }
+
+ while (*fmt) {
+ const char *old_fmt = fmt;
+
+ read = format_decode(fmt, &spec);
+
+ fmt += read;
+
+ switch (spec.type) {
+ case FORMAT_TYPE_NONE: {
+ int copy = read;
+ if (str < end) {
+ if (copy > end - str)
+ copy = end - str;
+ memcpy(str, old_fmt, copy);
+ }
+ str += read;
+ break;
+ }
+
+ case FORMAT_TYPE_WIDTH:
+ spec.field_width = va_arg(args, int);
+ break;
+
+ case FORMAT_TYPE_PRECISION:
+ spec.precision = va_arg(args, int);
+ break;
+
+ case FORMAT_TYPE_CHAR:
+ if (!(spec.flags & LEFT)) {
+ while (--spec.field_width > 0) {
+ if (str < end)
+ *str = ' ';
+ ++str;
+
+ }
+ }
+ c = (unsigned char) va_arg(args, int);
+ if (str < end)
+ *str = c;
+ ++str;
+ while (--spec.field_width > 0) {
+ if (str < end)
+ *str = ' ';
+ ++str;
+ }
+ break;
+
+ case FORMAT_TYPE_STR:
+ str = string(str, end, va_arg(args, char *), spec);
+ break;
+
+ case FORMAT_TYPE_PTR:
+ str = pointer(fmt+1, str, end, va_arg(args, void *),
+ spec);
+ while (isalnum(*fmt))
+ fmt++;
+ break;
+
+ case FORMAT_TYPE_PERCENT_CHAR:
+ if (str < end)
+ *str = '%';
+ ++str;
+ break;
+
+ case FORMAT_TYPE_INVALID:
+ if (str < end)
+ *str = '%';
+ ++str;
+ break;
+
+ case FORMAT_TYPE_NRCHARS: {
+ int qualifier = spec.qualifier;
+
+ if (qualifier == 'l') {
+ long *ip = va_arg(args, long *);
+ *ip = (str - buf);
+ } else if (qualifier == 'Z' ||
+ qualifier == 'z') {
+ size_t *ip = va_arg(args, size_t *);
+ *ip = (str - buf);
+ } else {
+ int *ip = va_arg(args, int *);
+ *ip = (str - buf);
+ }
+ break;
+ }
+
+ default:
+ switch (spec.type) {
+ case FORMAT_TYPE_LONG_LONG:
+ num = va_arg(args, long long);
+ break;
+ case FORMAT_TYPE_ULONG:
+ num = va_arg(args, unsigned long);
+ break;
+ case FORMAT_TYPE_LONG:
+ num = va_arg(args, long);
+ break;
+ case FORMAT_TYPE_SIZE_T:
+ num = va_arg(args, size_t);
+ break;
+ case FORMAT_TYPE_PTRDIFF:
+ num = va_arg(args, ptrdiff_t);
+ break;
+ case FORMAT_TYPE_UBYTE:
+ num = (unsigned char) va_arg(args, int);
+ break;
+ case FORMAT_TYPE_BYTE:
+ num = (signed char) va_arg(args, int);
+ break;
+ case FORMAT_TYPE_USHORT:
+ num = (unsigned short) va_arg(args, int);
+ break;
+ case FORMAT_TYPE_SHORT:
+ num = (short) va_arg(args, int);
+ break;
+ case FORMAT_TYPE_INT:
+ num = (int) va_arg(args, int);
+ break;
+ default:
+ num = va_arg(args, unsigned int);
+ }
+
+ str = number(str, end, num, spec);
+ }
+ }
+
+ if (size > 0) {
+ if (str < end)
+ *str = '\0';
+ else
+ end[-1] = '\0';
+ }
+
+ /* the trailing null byte doesn't count towards the total */
+ return str-buf;
+
+}
+
+/**
+ * bat_printk - print a kernel message using extra %p formatting
+ * strings, forward compatible with kernel version 2.6.31 printk, minus
+ * *p[sS].
+ *
+ * @fmt: format string
+ *
+ * This is printk(). It can be called from any context. We want it to work.
+ *
+ */
+asmlinkage int bat_printk(const char *fmt, ...)
+{
+ va_list args;
+ int r;
+ char buf[256];
+
+ va_start(args, fmt);
+ r = bat_vsnprintf(buf, sizeof(buf), fmt, args);
+ va_end(args);
+
+ return printk("foo:%s", buf);
+}
Index: hard-interface.c
===================================================================
--- hard-interface.c (revision 1490)
+++ hard-interface.c (working copy)
@@ -74,7 +74,6 @@
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 @@
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();
@@ -399,8 +397,7 @@
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;
Index: originator.c
===================================================================
--- originator.c (revision 1490)
+++ originator.c (working copy)
@@ -115,7 +115,6 @@
{
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));
@@ -123,8 +122,7 @@
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);
memset(orig_node, 0, sizeof(struct orig_node));
@@ -163,13 +161,11 @@
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;
*best_neigh_node = NULL;
-
/* for all neighbours 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);
@@ -178,9 +174,7 @@
(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, "Neighbour timeout: originator %s, neighbour: %s, last_valid %lu\n", orig_str, neigh_str, (neigh_node->last_valid / HZ));
+ bat_dbg(DBG_BATMAN, "Neighbour timeout: originator %pM, neighbour: %pM, last_valid %lu\n", orig_node->orig, neigh_node->addr, (neigh_node->last_valid / HZ));
neigh_purged = true;
list_del(list_pos);
@@ -198,17 +192,14 @@
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_neigbours(orig_node, &best_neigh_node))
@@ -239,5 +230,3 @@
start_purge_timer();
}
-
-
Index: routing.c
===================================================================
--- routing.c (revision 1490)
+++ routing.c (working copy)
@@ -79,32 +79,24 @@
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)
@@ -137,12 +129,8 @@
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,
@@ -220,8 +208,8 @@
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);
@@ -358,8 +346,6 @@
{
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;
@@ -384,20 +370,16 @@
/* 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)
@@ -428,13 +410,13 @@
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;
}
@@ -471,7 +453,7 @@
}
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;
}
@@ -489,7 +471,7 @@
!(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;
}
@@ -636,14 +618,10 @@
int result,
struct batman_if *batman_if)
{
- unsigned char src_str[ETH_STR_LEN], dst_str[ETH_STR_LEN];
struct orig_node *orig_node;
- 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 %pM to %pM: ttl exceeded\n", icmp_packet->orig, icmp_packet->dst);
- printk(KERN_WARNING "batman-adv:Warning - can't send packet from %s to %s: ttl exceeded\n", src_str, dst_str);
-
/* send TTL exceeded if packet is an echo request (traceroute) */
if (icmp_packet->msg_type != ECHO_REQUEST)
return;
@@ -739,7 +717,6 @@
struct batman_if *batman_if)
{
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);
@@ -772,11 +749,8 @@
/* 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);
-
- printk(KERN_WARNING "batman-adv:Warning - can't send packet from %s to %s: ttl exceeded\n", src_str, dst_str);
+ struct ethhdr * src = (struct ethhdr *) (unicast_packet + 1);
+ printk(KERN_WARNING "batman-adv:Warning - can't send packet from %pM to %pM: ttl exceeded\n", src->h_source, unicast_packet->dest);
return;
}
@@ -1027,7 +1001,7 @@
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");
+ printk(KERN_ERR "batman-adv:Could allocate memory for the packet buffer. :(\n");
return -1;
}
Index: compat.h
===================================================================
--- compat.h (revision 1490)
+++ compat.h (working copy)
@@ -73,3 +73,8 @@
ret; \
})
#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25) */
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 29)
+asmlinkage int bat_printk(const char *fmt, ...);
+#define printk bat_printk
+#endif
Index: main.h
===================================================================
--- main.h (revision 1490)
+++ main.h (working copy)
@@ -111,6 +111,7 @@
#include <linux/workqueue.h> /* workqueue */
#include <net/sock.h> /* struct sock */
#include <linux/jiffies.h>
+#include <linux/list.h>
#include "types.h"
#ifndef REVISION_VERSION
Index: routing.h
===================================================================
--- routing.h (revision 1490)
+++ routing.h (working copy)
@@ -27,10 +27,10 @@
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,
- struct batman_if *if_incoming);
+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);
void update_routes(struct orig_node *orig_node,
- struct neigh_node *neigh_node,
- unsigned char *hna_buff, int hna_buff_len);
+ struct neigh_node *neigh_node,
+ unsigned char *hna_buff, int hna_buff_len);
13 years, 1 month