Re: [PATCH v4] tools lib traceevent: Add support for IP address formats

2015-01-15 Thread Arnaldo Carvalho de Melo
Em Thu, Jan 15, 2015 at 10:45:23AM -0500, Steven Rostedt escreveu:
> On Thu, 15 Jan 2015 08:30:18 -0700
> David Ahern  wrote:
> 
> > Steve:
> > 
> > Any comments? I think Arnaldo is waiting for your response to pick this up.
> 
> Looks fine to me.
> 
> Acked-by: Steven Rostedt 
> 

Thanks, I'll merge this into my perf/core branch soon.

- Arnaldo
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v4] tools lib traceevent: Add support for IP address formats

2015-01-15 Thread Steven Rostedt
On Thu, 15 Jan 2015 08:30:18 -0700
David Ahern  wrote:

> Steve:
> 
> Any comments? I think Arnaldo is waiting for your response to pick this up.

Looks fine to me.

Acked-by: Steven Rostedt 

-- Steve

> 
> David
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v4] tools lib traceevent: Add support for IP address formats

2015-01-15 Thread David Ahern

Steve:

Any comments? I think Arnaldo is waiting for your response to pick this up.

David

On 12/18/14 7:11 PM, David Ahern wrote:

Add helpers for the following kernel formats:
   %pi4 print an IPv4 address with leading zeros
   %pI4 print an IPv4 address without leading zeros
   %pi6 print an IPv6 address without colons
   %pI6 print an IPv6 address with colons
   %pI6c print an IPv6 address in compressed form with colons
   %pISpc print an IP address from a sockaddr

Allows these formats to be used in tracepoints.

Quite a bit of this is adapted from code in lib/vsprintf.c.

v4:
- fixed pI6c description in git commit message per Valdis' comment

v3:
- use of 'c' and 'p' requires 'I'

v2:
- pass ptr+1 to print_ip_arg per Namhyung's comments
- added field length checks to sockaddr function

Signed-off-by: David Ahern 
Cc: Namhyung Kim 
Cc: Jiri Olsa 
Cc: Steven Rostedt 
---
  tools/lib/traceevent/event-parse.c | 328 +
  1 file changed, 328 insertions(+)

diff --git a/tools/lib/traceevent/event-parse.c 
b/tools/lib/traceevent/event-parse.c
index cf3a44bf1ec3..afe20ed9fac8 100644
--- a/tools/lib/traceevent/event-parse.c
+++ b/tools/lib/traceevent/event-parse.c
@@ -32,6 +32,7 @@
  #include 
  #include 

+#include 
  #include "event-parse.h"
  #include "event-utils.h"

@@ -4149,6 +4150,324 @@ static void print_mac_arg(struct trace_seq *s, int mac, 
void *data, int size,
trace_seq_printf(s, fmt, buf[0], buf[1], buf[2], buf[3], buf[4], 
buf[5]);
  }

+static void print_ip4_addr(struct trace_seq *s, char i, unsigned char *buf)
+{
+   const char *fmt;
+
+   if (i == 'i')
+   fmt = "%03d.%03d.%03d.%03d";
+   else
+   fmt = "%d.%d.%d.%d";
+
+   trace_seq_printf(s, fmt, buf[0], buf[1], buf[2], buf[3]);
+}
+
+static inline bool ipv6_addr_v4mapped(const struct in6_addr *a)
+{
+   return ((unsigned long)(a->s6_addr32[0] | a->s6_addr32[1]) |
+   (unsigned long)(a->s6_addr32[2] ^ htonl(0x))) == 0UL;
+}
+
+static inline bool ipv6_addr_is_isatap(const struct in6_addr *addr)
+{
+   return (addr->s6_addr32[2] | htonl(0x0200)) == htonl(0x02005EFE);
+}
+
+static void print_ip6c_addr(struct trace_seq *s, unsigned char *addr)
+{
+   int i, j, range;
+   unsigned char zerolength[8];
+   int longest = 1;
+   int colonpos = -1;
+   uint16_t word;
+   uint8_t hi, lo;
+   bool needcolon = false;
+   bool useIPv4;
+   struct in6_addr in6;
+
+   memcpy(, addr, sizeof(struct in6_addr));
+
+   useIPv4 = ipv6_addr_v4mapped() || ipv6_addr_is_isatap();
+
+   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;
+   }
+   }
+   if (longest == 1)   /* don't compress a single 0 */
+   colonpos = -1;
+
+   /* emit address */
+   for (i = 0; i < range; i++) {
+   if (i == colonpos) {
+   if (needcolon || i == 0)
+   trace_seq_printf(s, ":");
+   trace_seq_printf(s, ":");
+   needcolon = false;
+   i += longest - 1;
+   continue;
+   }
+   if (needcolon) {
+   trace_seq_printf(s, ":");
+   needcolon = false;
+   }
+   /* hex u16 without leading 0s */
+   word = ntohs(in6.s6_addr16[i]);
+   hi = word >> 8;
+   lo = word & 0xff;
+   if (hi)
+   trace_seq_printf(s, "%x%02x", hi, lo);
+   else
+   trace_seq_printf(s, "%x", lo);
+
+   needcolon = true;
+   }
+
+   if (useIPv4) {
+   if (needcolon)
+   trace_seq_printf(s, ":");
+   print_ip4_addr(s, 'I', _addr[12]);
+   }
+
+   return;
+}
+
+static void print_ip6_addr(struct trace_seq *s, char i, unsigned char *buf)
+{
+   int j;
+
+   for (j = 0; j < 16; j += 2) {
+   trace_seq_printf(s, "%02x%02x", buf[j], buf[j+1]);
+   if (i == 'I' && j < 14)
+   trace_seq_printf(s, ":");
+   }
+}
+
+/*
+ * %pi4   print an IPv4 address with leading zeros
+ * %pI4   print an IPv4 address without leading zeros
+ * %pi6   print an IPv6 address without colons
+ * %pI6   print an IPv6 address with colons
+ * %pI6c  print an 

Re: [PATCH v4] tools lib traceevent: Add support for IP address formats

2015-01-15 Thread Steven Rostedt
On Thu, 15 Jan 2015 08:30:18 -0700
David Ahern dsah...@gmail.com wrote:

 Steve:
 
 Any comments? I think Arnaldo is waiting for your response to pick this up.

Looks fine to me.

Acked-by: Steven Rostedt rost...@goodmis.org

-- Steve

 
 David
 
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v4] tools lib traceevent: Add support for IP address formats

2015-01-15 Thread David Ahern

Steve:

Any comments? I think Arnaldo is waiting for your response to pick this up.

David

On 12/18/14 7:11 PM, David Ahern wrote:

Add helpers for the following kernel formats:
   %pi4 print an IPv4 address with leading zeros
   %pI4 print an IPv4 address without leading zeros
   %pi6 print an IPv6 address without colons
   %pI6 print an IPv6 address with colons
   %pI6c print an IPv6 address in compressed form with colons
   %pISpc print an IP address from a sockaddr

Allows these formats to be used in tracepoints.

Quite a bit of this is adapted from code in lib/vsprintf.c.

v4:
- fixed pI6c description in git commit message per Valdis' comment

v3:
- use of 'c' and 'p' requires 'I'

v2:
- pass ptr+1 to print_ip_arg per Namhyung's comments
- added field length checks to sockaddr function

Signed-off-by: David Ahern dsah...@gmail.com
Cc: Namhyung Kim namhy...@kernel.org
Cc: Jiri Olsa jo...@kernel.org
Cc: Steven Rostedt rost...@goodmis.org
---
  tools/lib/traceevent/event-parse.c | 328 +
  1 file changed, 328 insertions(+)

diff --git a/tools/lib/traceevent/event-parse.c 
b/tools/lib/traceevent/event-parse.c
index cf3a44bf1ec3..afe20ed9fac8 100644
--- a/tools/lib/traceevent/event-parse.c
+++ b/tools/lib/traceevent/event-parse.c
@@ -32,6 +32,7 @@
  #include stdint.h
  #include limits.h

+#include netinet/ip6.h
  #include event-parse.h
  #include event-utils.h

@@ -4149,6 +4150,324 @@ static void print_mac_arg(struct trace_seq *s, int mac, 
void *data, int size,
trace_seq_printf(s, fmt, buf[0], buf[1], buf[2], buf[3], buf[4], 
buf[5]);
  }

+static void print_ip4_addr(struct trace_seq *s, char i, unsigned char *buf)
+{
+   const char *fmt;
+
+   if (i == 'i')
+   fmt = %03d.%03d.%03d.%03d;
+   else
+   fmt = %d.%d.%d.%d;
+
+   trace_seq_printf(s, fmt, buf[0], buf[1], buf[2], buf[3]);
+}
+
+static inline bool ipv6_addr_v4mapped(const struct in6_addr *a)
+{
+   return ((unsigned long)(a-s6_addr32[0] | a-s6_addr32[1]) |
+   (unsigned long)(a-s6_addr32[2] ^ htonl(0x))) == 0UL;
+}
+
+static inline bool ipv6_addr_is_isatap(const struct in6_addr *addr)
+{
+   return (addr-s6_addr32[2] | htonl(0x0200)) == htonl(0x02005EFE);
+}
+
+static void print_ip6c_addr(struct trace_seq *s, unsigned char *addr)
+{
+   int i, j, range;
+   unsigned char zerolength[8];
+   int longest = 1;
+   int colonpos = -1;
+   uint16_t word;
+   uint8_t hi, 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;
+   }
+   }
+   if (longest == 1)   /* don't compress a single 0 */
+   colonpos = -1;
+
+   /* emit address */
+   for (i = 0; i  range; i++) {
+   if (i == colonpos) {
+   if (needcolon || i == 0)
+   trace_seq_printf(s, :);
+   trace_seq_printf(s, :);
+   needcolon = false;
+   i += longest - 1;
+   continue;
+   }
+   if (needcolon) {
+   trace_seq_printf(s, :);
+   needcolon = false;
+   }
+   /* hex u16 without leading 0s */
+   word = ntohs(in6.s6_addr16[i]);
+   hi = word  8;
+   lo = word  0xff;
+   if (hi)
+   trace_seq_printf(s, %x%02x, hi, lo);
+   else
+   trace_seq_printf(s, %x, lo);
+
+   needcolon = true;
+   }
+
+   if (useIPv4) {
+   if (needcolon)
+   trace_seq_printf(s, :);
+   print_ip4_addr(s, 'I', in6.s6_addr[12]);
+   }
+
+   return;
+}
+
+static void print_ip6_addr(struct trace_seq *s, char i, unsigned char *buf)
+{
+   int j;
+
+   for (j = 0; j  16; j += 2) {
+   trace_seq_printf(s, %02x%02x, buf[j], buf[j+1]);
+   if (i == 'I'  j  14)
+   trace_seq_printf(s, :);
+   }
+}
+
+/*
+ * %pi4   print an IPv4 address with leading zeros
+ * %pI4   print an IPv4 address without leading zeros
+ * %pi6   print an IPv6 address without 

Re: [PATCH v4] tools lib traceevent: Add support for IP address formats

2015-01-15 Thread Arnaldo Carvalho de Melo
Em Thu, Jan 15, 2015 at 10:45:23AM -0500, Steven Rostedt escreveu:
 On Thu, 15 Jan 2015 08:30:18 -0700
 David Ahern dsah...@gmail.com wrote:
 
  Steve:
  
  Any comments? I think Arnaldo is waiting for your response to pick this up.
 
 Looks fine to me.
 
 Acked-by: Steven Rostedt rost...@goodmis.org
 

Thanks, I'll merge this into my perf/core branch soon.

- Arnaldo
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v4] tools lib traceevent: Add support for IP address formats

2014-12-22 Thread David Ahern

any other comments on this one?

On 12/18/14 7:11 PM, David Ahern wrote:

Add helpers for the following kernel formats:
   %pi4 print an IPv4 address with leading zeros
   %pI4 print an IPv4 address without leading zeros
   %pi6 print an IPv6 address without colons
   %pI6 print an IPv6 address with colons
   %pI6c print an IPv6 address in compressed form with colons
   %pISpc print an IP address from a sockaddr

Allows these formats to be used in tracepoints.

Quite a bit of this is adapted from code in lib/vsprintf.c.

v4:
- fixed pI6c description in git commit message per Valdis' comment

v3:
- use of 'c' and 'p' requires 'I'

v2:
- pass ptr+1 to print_ip_arg per Namhyung's comments
- added field length checks to sockaddr function

Signed-off-by: David Ahern 
Cc: Namhyung Kim 
Cc: Jiri Olsa 
Cc: Steven Rostedt 
---
  tools/lib/traceevent/event-parse.c | 328 +
  1 file changed, 328 insertions(+)

diff --git a/tools/lib/traceevent/event-parse.c 
b/tools/lib/traceevent/event-parse.c
index cf3a44bf1ec3..afe20ed9fac8 100644
--- a/tools/lib/traceevent/event-parse.c
+++ b/tools/lib/traceevent/event-parse.c
@@ -32,6 +32,7 @@
  #include 
  #include 

+#include 
  #include "event-parse.h"
  #include "event-utils.h"

@@ -4149,6 +4150,324 @@ static void print_mac_arg(struct trace_seq *s, int mac, 
void *data, int size,
trace_seq_printf(s, fmt, buf[0], buf[1], buf[2], buf[3], buf[4], 
buf[5]);
  }

+static void print_ip4_addr(struct trace_seq *s, char i, unsigned char *buf)
+{
+   const char *fmt;
+
+   if (i == 'i')
+   fmt = "%03d.%03d.%03d.%03d";
+   else
+   fmt = "%d.%d.%d.%d";
+
+   trace_seq_printf(s, fmt, buf[0], buf[1], buf[2], buf[3]);
+}
+
+static inline bool ipv6_addr_v4mapped(const struct in6_addr *a)
+{
+   return ((unsigned long)(a->s6_addr32[0] | a->s6_addr32[1]) |
+   (unsigned long)(a->s6_addr32[2] ^ htonl(0x))) == 0UL;
+}
+
+static inline bool ipv6_addr_is_isatap(const struct in6_addr *addr)
+{
+   return (addr->s6_addr32[2] | htonl(0x0200)) == htonl(0x02005EFE);
+}
+
+static void print_ip6c_addr(struct trace_seq *s, unsigned char *addr)
+{
+   int i, j, range;
+   unsigned char zerolength[8];
+   int longest = 1;
+   int colonpos = -1;
+   uint16_t word;
+   uint8_t hi, lo;
+   bool needcolon = false;
+   bool useIPv4;
+   struct in6_addr in6;
+
+   memcpy(, addr, sizeof(struct in6_addr));
+
+   useIPv4 = ipv6_addr_v4mapped() || ipv6_addr_is_isatap();
+
+   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;
+   }
+   }
+   if (longest == 1)   /* don't compress a single 0 */
+   colonpos = -1;
+
+   /* emit address */
+   for (i = 0; i < range; i++) {
+   if (i == colonpos) {
+   if (needcolon || i == 0)
+   trace_seq_printf(s, ":");
+   trace_seq_printf(s, ":");
+   needcolon = false;
+   i += longest - 1;
+   continue;
+   }
+   if (needcolon) {
+   trace_seq_printf(s, ":");
+   needcolon = false;
+   }
+   /* hex u16 without leading 0s */
+   word = ntohs(in6.s6_addr16[i]);
+   hi = word >> 8;
+   lo = word & 0xff;
+   if (hi)
+   trace_seq_printf(s, "%x%02x", hi, lo);
+   else
+   trace_seq_printf(s, "%x", lo);
+
+   needcolon = true;
+   }
+
+   if (useIPv4) {
+   if (needcolon)
+   trace_seq_printf(s, ":");
+   print_ip4_addr(s, 'I', _addr[12]);
+   }
+
+   return;
+}
+
+static void print_ip6_addr(struct trace_seq *s, char i, unsigned char *buf)
+{
+   int j;
+
+   for (j = 0; j < 16; j += 2) {
+   trace_seq_printf(s, "%02x%02x", buf[j], buf[j+1]);
+   if (i == 'I' && j < 14)
+   trace_seq_printf(s, ":");
+   }
+}
+
+/*
+ * %pi4   print an IPv4 address with leading zeros
+ * %pI4   print an IPv4 address without leading zeros
+ * %pi6   print an IPv6 address without colons
+ * %pI6   print an IPv6 address with colons
+ * %pI6c  print an IPv6 address in compressed form with colons
+ * %pISpc print 

Re: [PATCH v4] tools lib traceevent: Add support for IP address formats

2014-12-22 Thread David Ahern

any other comments on this one?

On 12/18/14 7:11 PM, David Ahern wrote:

Add helpers for the following kernel formats:
   %pi4 print an IPv4 address with leading zeros
   %pI4 print an IPv4 address without leading zeros
   %pi6 print an IPv6 address without colons
   %pI6 print an IPv6 address with colons
   %pI6c print an IPv6 address in compressed form with colons
   %pISpc print an IP address from a sockaddr

Allows these formats to be used in tracepoints.

Quite a bit of this is adapted from code in lib/vsprintf.c.

v4:
- fixed pI6c description in git commit message per Valdis' comment

v3:
- use of 'c' and 'p' requires 'I'

v2:
- pass ptr+1 to print_ip_arg per Namhyung's comments
- added field length checks to sockaddr function

Signed-off-by: David Ahern dsah...@gmail.com
Cc: Namhyung Kim namhy...@kernel.org
Cc: Jiri Olsa jo...@kernel.org
Cc: Steven Rostedt rost...@goodmis.org
---
  tools/lib/traceevent/event-parse.c | 328 +
  1 file changed, 328 insertions(+)

diff --git a/tools/lib/traceevent/event-parse.c 
b/tools/lib/traceevent/event-parse.c
index cf3a44bf1ec3..afe20ed9fac8 100644
--- a/tools/lib/traceevent/event-parse.c
+++ b/tools/lib/traceevent/event-parse.c
@@ -32,6 +32,7 @@
  #include stdint.h
  #include limits.h

+#include netinet/ip6.h
  #include event-parse.h
  #include event-utils.h

@@ -4149,6 +4150,324 @@ static void print_mac_arg(struct trace_seq *s, int mac, 
void *data, int size,
trace_seq_printf(s, fmt, buf[0], buf[1], buf[2], buf[3], buf[4], 
buf[5]);
  }

+static void print_ip4_addr(struct trace_seq *s, char i, unsigned char *buf)
+{
+   const char *fmt;
+
+   if (i == 'i')
+   fmt = %03d.%03d.%03d.%03d;
+   else
+   fmt = %d.%d.%d.%d;
+
+   trace_seq_printf(s, fmt, buf[0], buf[1], buf[2], buf[3]);
+}
+
+static inline bool ipv6_addr_v4mapped(const struct in6_addr *a)
+{
+   return ((unsigned long)(a-s6_addr32[0] | a-s6_addr32[1]) |
+   (unsigned long)(a-s6_addr32[2] ^ htonl(0x))) == 0UL;
+}
+
+static inline bool ipv6_addr_is_isatap(const struct in6_addr *addr)
+{
+   return (addr-s6_addr32[2] | htonl(0x0200)) == htonl(0x02005EFE);
+}
+
+static void print_ip6c_addr(struct trace_seq *s, unsigned char *addr)
+{
+   int i, j, range;
+   unsigned char zerolength[8];
+   int longest = 1;
+   int colonpos = -1;
+   uint16_t word;
+   uint8_t hi, 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;
+   }
+   }
+   if (longest == 1)   /* don't compress a single 0 */
+   colonpos = -1;
+
+   /* emit address */
+   for (i = 0; i  range; i++) {
+   if (i == colonpos) {
+   if (needcolon || i == 0)
+   trace_seq_printf(s, :);
+   trace_seq_printf(s, :);
+   needcolon = false;
+   i += longest - 1;
+   continue;
+   }
+   if (needcolon) {
+   trace_seq_printf(s, :);
+   needcolon = false;
+   }
+   /* hex u16 without leading 0s */
+   word = ntohs(in6.s6_addr16[i]);
+   hi = word  8;
+   lo = word  0xff;
+   if (hi)
+   trace_seq_printf(s, %x%02x, hi, lo);
+   else
+   trace_seq_printf(s, %x, lo);
+
+   needcolon = true;
+   }
+
+   if (useIPv4) {
+   if (needcolon)
+   trace_seq_printf(s, :);
+   print_ip4_addr(s, 'I', in6.s6_addr[12]);
+   }
+
+   return;
+}
+
+static void print_ip6_addr(struct trace_seq *s, char i, unsigned char *buf)
+{
+   int j;
+
+   for (j = 0; j  16; j += 2) {
+   trace_seq_printf(s, %02x%02x, buf[j], buf[j+1]);
+   if (i == 'I'  j  14)
+   trace_seq_printf(s, :);
+   }
+}
+
+/*
+ * %pi4   print an IPv4 address with leading zeros
+ * %pI4   print an IPv4 address without leading zeros
+ * %pi6   print an IPv6 address without colons
+ * %pI6   print an IPv6 address with colons
+ * 

[PATCH v4] tools lib traceevent: Add support for IP address formats

2014-12-18 Thread David Ahern
Add helpers for the following kernel formats:
  %pi4 print an IPv4 address with leading zeros
  %pI4 print an IPv4 address without leading zeros
  %pi6 print an IPv6 address without colons
  %pI6 print an IPv6 address with colons
  %pI6c print an IPv6 address in compressed form with colons
  %pISpc print an IP address from a sockaddr

Allows these formats to be used in tracepoints.

Quite a bit of this is adapted from code in lib/vsprintf.c.

v4:
- fixed pI6c description in git commit message per Valdis' comment

v3:
- use of 'c' and 'p' requires 'I'

v2:
- pass ptr+1 to print_ip_arg per Namhyung's comments
- added field length checks to sockaddr function

Signed-off-by: David Ahern 
Cc: Namhyung Kim 
Cc: Jiri Olsa 
Cc: Steven Rostedt 
---
 tools/lib/traceevent/event-parse.c | 328 +
 1 file changed, 328 insertions(+)

diff --git a/tools/lib/traceevent/event-parse.c 
b/tools/lib/traceevent/event-parse.c
index cf3a44bf1ec3..afe20ed9fac8 100644
--- a/tools/lib/traceevent/event-parse.c
+++ b/tools/lib/traceevent/event-parse.c
@@ -32,6 +32,7 @@
 #include 
 #include 
 
+#include 
 #include "event-parse.h"
 #include "event-utils.h"
 
@@ -4149,6 +4150,324 @@ static void print_mac_arg(struct trace_seq *s, int mac, 
void *data, int size,
trace_seq_printf(s, fmt, buf[0], buf[1], buf[2], buf[3], buf[4], 
buf[5]);
 }
 
+static void print_ip4_addr(struct trace_seq *s, char i, unsigned char *buf)
+{
+   const char *fmt;
+
+   if (i == 'i')
+   fmt = "%03d.%03d.%03d.%03d";
+   else
+   fmt = "%d.%d.%d.%d";
+
+   trace_seq_printf(s, fmt, buf[0], buf[1], buf[2], buf[3]);
+}
+
+static inline bool ipv6_addr_v4mapped(const struct in6_addr *a)
+{
+   return ((unsigned long)(a->s6_addr32[0] | a->s6_addr32[1]) |
+   (unsigned long)(a->s6_addr32[2] ^ htonl(0x))) == 0UL;
+}
+
+static inline bool ipv6_addr_is_isatap(const struct in6_addr *addr)
+{
+   return (addr->s6_addr32[2] | htonl(0x0200)) == htonl(0x02005EFE);
+}
+
+static void print_ip6c_addr(struct trace_seq *s, unsigned char *addr)
+{
+   int i, j, range;
+   unsigned char zerolength[8];
+   int longest = 1;
+   int colonpos = -1;
+   uint16_t word;
+   uint8_t hi, lo;
+   bool needcolon = false;
+   bool useIPv4;
+   struct in6_addr in6;
+
+   memcpy(, addr, sizeof(struct in6_addr));
+
+   useIPv4 = ipv6_addr_v4mapped() || ipv6_addr_is_isatap();
+
+   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;
+   }
+   }
+   if (longest == 1)   /* don't compress a single 0 */
+   colonpos = -1;
+
+   /* emit address */
+   for (i = 0; i < range; i++) {
+   if (i == colonpos) {
+   if (needcolon || i == 0)
+   trace_seq_printf(s, ":");
+   trace_seq_printf(s, ":");
+   needcolon = false;
+   i += longest - 1;
+   continue;
+   }
+   if (needcolon) {
+   trace_seq_printf(s, ":");
+   needcolon = false;
+   }
+   /* hex u16 without leading 0s */
+   word = ntohs(in6.s6_addr16[i]);
+   hi = word >> 8;
+   lo = word & 0xff;
+   if (hi)
+   trace_seq_printf(s, "%x%02x", hi, lo);
+   else
+   trace_seq_printf(s, "%x", lo);
+
+   needcolon = true;
+   }
+
+   if (useIPv4) {
+   if (needcolon)
+   trace_seq_printf(s, ":");
+   print_ip4_addr(s, 'I', _addr[12]);
+   }
+
+   return;
+}
+
+static void print_ip6_addr(struct trace_seq *s, char i, unsigned char *buf)
+{
+   int j;
+
+   for (j = 0; j < 16; j += 2) {
+   trace_seq_printf(s, "%02x%02x", buf[j], buf[j+1]);
+   if (i == 'I' && j < 14)
+   trace_seq_printf(s, ":");
+   }
+}
+
+/*
+ * %pi4   print an IPv4 address with leading zeros
+ * %pI4   print an IPv4 address without leading zeros
+ * %pi6   print an IPv6 address without colons
+ * %pI6   print an IPv6 address with colons
+ * %pI6c  print an IPv6 address in compressed form with colons
+ * %pISpc print an IP address based on sockaddr; p adds port.
+ */
+static int print_ipv4_arg(struct 

[PATCH v4] tools lib traceevent: Add support for IP address formats

2014-12-18 Thread David Ahern
Add helpers for the following kernel formats:
  %pi4 print an IPv4 address with leading zeros
  %pI4 print an IPv4 address without leading zeros
  %pi6 print an IPv6 address without colons
  %pI6 print an IPv6 address with colons
  %pI6c print an IPv6 address in compressed form with colons
  %pISpc print an IP address from a sockaddr

Allows these formats to be used in tracepoints.

Quite a bit of this is adapted from code in lib/vsprintf.c.

v4:
- fixed pI6c description in git commit message per Valdis' comment

v3:
- use of 'c' and 'p' requires 'I'

v2:
- pass ptr+1 to print_ip_arg per Namhyung's comments
- added field length checks to sockaddr function

Signed-off-by: David Ahern dsah...@gmail.com
Cc: Namhyung Kim namhy...@kernel.org
Cc: Jiri Olsa jo...@kernel.org
Cc: Steven Rostedt rost...@goodmis.org
---
 tools/lib/traceevent/event-parse.c | 328 +
 1 file changed, 328 insertions(+)

diff --git a/tools/lib/traceevent/event-parse.c 
b/tools/lib/traceevent/event-parse.c
index cf3a44bf1ec3..afe20ed9fac8 100644
--- a/tools/lib/traceevent/event-parse.c
+++ b/tools/lib/traceevent/event-parse.c
@@ -32,6 +32,7 @@
 #include stdint.h
 #include limits.h
 
+#include netinet/ip6.h
 #include event-parse.h
 #include event-utils.h
 
@@ -4149,6 +4150,324 @@ static void print_mac_arg(struct trace_seq *s, int mac, 
void *data, int size,
trace_seq_printf(s, fmt, buf[0], buf[1], buf[2], buf[3], buf[4], 
buf[5]);
 }
 
+static void print_ip4_addr(struct trace_seq *s, char i, unsigned char *buf)
+{
+   const char *fmt;
+
+   if (i == 'i')
+   fmt = %03d.%03d.%03d.%03d;
+   else
+   fmt = %d.%d.%d.%d;
+
+   trace_seq_printf(s, fmt, buf[0], buf[1], buf[2], buf[3]);
+}
+
+static inline bool ipv6_addr_v4mapped(const struct in6_addr *a)
+{
+   return ((unsigned long)(a-s6_addr32[0] | a-s6_addr32[1]) |
+   (unsigned long)(a-s6_addr32[2] ^ htonl(0x))) == 0UL;
+}
+
+static inline bool ipv6_addr_is_isatap(const struct in6_addr *addr)
+{
+   return (addr-s6_addr32[2] | htonl(0x0200)) == htonl(0x02005EFE);
+}
+
+static void print_ip6c_addr(struct trace_seq *s, unsigned char *addr)
+{
+   int i, j, range;
+   unsigned char zerolength[8];
+   int longest = 1;
+   int colonpos = -1;
+   uint16_t word;
+   uint8_t hi, 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;
+   }
+   }
+   if (longest == 1)   /* don't compress a single 0 */
+   colonpos = -1;
+
+   /* emit address */
+   for (i = 0; i  range; i++) {
+   if (i == colonpos) {
+   if (needcolon || i == 0)
+   trace_seq_printf(s, :);
+   trace_seq_printf(s, :);
+   needcolon = false;
+   i += longest - 1;
+   continue;
+   }
+   if (needcolon) {
+   trace_seq_printf(s, :);
+   needcolon = false;
+   }
+   /* hex u16 without leading 0s */
+   word = ntohs(in6.s6_addr16[i]);
+   hi = word  8;
+   lo = word  0xff;
+   if (hi)
+   trace_seq_printf(s, %x%02x, hi, lo);
+   else
+   trace_seq_printf(s, %x, lo);
+
+   needcolon = true;
+   }
+
+   if (useIPv4) {
+   if (needcolon)
+   trace_seq_printf(s, :);
+   print_ip4_addr(s, 'I', in6.s6_addr[12]);
+   }
+
+   return;
+}
+
+static void print_ip6_addr(struct trace_seq *s, char i, unsigned char *buf)
+{
+   int j;
+
+   for (j = 0; j  16; j += 2) {
+   trace_seq_printf(s, %02x%02x, buf[j], buf[j+1]);
+   if (i == 'I'  j  14)
+   trace_seq_printf(s, :);
+   }
+}
+
+/*
+ * %pi4   print an IPv4 address with leading zeros
+ * %pI4   print an IPv4 address without leading zeros
+ * %pi6   print an IPv6 address without colons
+ * %pI6   print an IPv6 address with colons
+ * %pI6c  print an IPv6 address in compressed form with colons
+ * %pISpc print an IP