[patchv2] batman-adv: Use printk(%pM) for MAC addres

Message ID 20091213190149.GA22421@pandem0nium (mailing list archive)
State Superseded, archived
Headers

Commit Message

Simon Wunderlich Dec. 13, 2009, 7:01 p.m. UTC
  Hello Andrew,

i've checked your patch against older kernel, and there seem to be some
compile problems. E.g. compiling against 2.6.26, i find:

  CC [M]  /home/dotslash/msrc/batman-svn/batman-adv-kernelland/bat_printk.o
/home/dotslash/msrc/batman-svn/batman-adv-kernelland/bat_printk.c: In function ‘pointer’:
/home/dotslash/msrc/batman-svn/batman-adv-kernelland/bat_printk.c:564: error: implicit declaration of function ‘dereference_function_descriptor’
/home/dotslash/msrc/batman-svn/batman-adv-kernelland/bat_printk.c:564: warning: assignment makes pointer from integer without a cast

against 2.6.21, there are a lot more lines of warnings and errors, while 
2.6.20 works mostly fine. Could you please review your patch in this regard? 
I have nearly all kernels installed so i can give you a list of compile logs if you
are interested.

Furthermore, i'd suggest to link the bat_printk only if needed to avoid loading
a lot of dead code. Something like this could be done in the Makefile (which i 
don't consider the prettiest, but it works ...):



Another approach would be to have a big ifdef in the bat_printk file,
but marek did not like this idea. Any other ideas about this?

best regards
	Simon

On Fri, Dec 04, 2009 at 10:42:51PM +0100, Andrew Lunn wrote:
> 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@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@datastacks.com>
> + * - changed to provide snprintf and vsnprintf functions
> + * So Feb  1 16:51:32 CET 2004 Juergen Quade <quade@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);
> _______________________________________________
> B.A.T.M.A.N mailing list
> B.A.T.M.A.N@lists.open-mesh.net
> https://lists.open-mesh.net/mm/listinfo/b.a.t.m.a.n
>
  

Comments

Andrew Lunn Dec. 31, 2009, 10:56 a.m. UTC | #1
On Sun, Dec 13, 2009 at 08:01:49PM +0100, Simon Wunderlich wrote:
> Hello Andrew,
> 
> i've checked your patch against older kernel, and there seem to be some
> compile problems. E.g. compiling against 2.6.26, i find:
> 
>   CC [M]  /home/dotslash/msrc/batman-svn/batman-adv-kernelland/bat_printk.o
> /home/dotslash/msrc/batman-svn/batman-adv-kernelland/bat_printk.c: In function ???pointer???:
> /home/dotslash/msrc/batman-svn/batman-adv-kernelland/bat_printk.c:564: error: implicit declaration of function ???dereference_function_descriptor???
> /home/dotslash/msrc/batman-svn/batman-adv-kernelland/bat_printk.c:564: warning: assignment makes pointer from integer without a cast
> 
> against 2.6.21, there are a lot more lines of warnings and errors, while 
> 2.6.20 works mostly fine. Could you please review your patch in this regard? 
> I have nearly all kernels installed so i can give you a list of compile logs if you
> are interested.

Hi Simon

I just posted an updated version of the patch. It would be great if
you could test it on a few different kernels. I tried
2.6.21. bat_printk.c now compiles, but other parts of batman-adv fail.
I think it was your skbuff patches which broke it, but i could be
wrong.

	Andrew
  

Patch

Index: Makefile.kbuild
===================================================================
--- Makefile.kbuild	(revision 1491)
+++ 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 $(shell [ "2" -eq "$(VERSION)" ] && [ "6" -eq "$(PATCHLEVEL)" ] && [ "$(SUBLEVEL)" -le "28" ] && echo bat_printk.o)
+