All of lore.kernel.org
 help / color / mirror / Atom feed
From: Shaohua Li <shli@fb.com>
To: David Miller <davem@davemloft.net>
Cc: <netdev@vger.kernel.org>, <kafai@fb.com>
Subject: Re: net_test_tools: add ipv6 support for kbench_mod
Date: Thu, 22 Jan 2015 14:12:56 -0800	[thread overview]
Message-ID: <20150122221256.GA2263247@devbig257.prn2.facebook.com> (raw)
In-Reply-To: <20150115.180839.2081269036058084221.davem@davemloft.net>

On Thu, Jan 15, 2015 at 06:08:39PM -0500, David Miller wrote:
> From: Shaohua Li <shli@fb.com>
> Date: Thu, 15 Jan 2015 13:17:37 -0800
> 
> > On Wed, Jan 14, 2015 at 01:35:40AM -0500, David Miller wrote:
> >> From: Shaohua Li <shli@fb.com>
> >> Date: Tue, 13 Jan 2015 21:45:48 -0800
> >> 
> >> > This patch adds ipv6 support for kbench_mod test module
> >> 
> >> This doesn't even link because ip6_route_input is not an
> >> exported symbol.
> >> 
> >> So you either didn't test this, or it depends upon custom
> >> kernel changes which you didn't mention.
> >> 
> >> Either way I can't apply this, sorry
> > 
> > Yes, we need export the sysmbol for the test. Can we export the symbol?
> > or I can delete the route input test, which one do you prefer?
> 
> There is no justification upstream to export that symbol since
> there are no modular users in-tree.

Hi,
I changed it to do the ip6_route_input test optionally. If the test is
required, somebody should change the kernel to export it and define
HAVE_IP6_ROUTE_INPUT in the test module. I thought this is fine for a
test module. How do you think?

Thanks,
Shaohua



This patch adds ipv6 support for kbench_mod test module. Since
ip6_route_input() isn't exported, it can only be tested with
HAVE_IP6_ROUTE_INPUT defined (ofcourse, changing kernel to export it)

diff --git a/kbench_mod.c b/kbench_mod.c
index fc3765c..9f5dccc 100644
--- a/kbench_mod.c
+++ b/kbench_mod.c
@@ -3,9 +3,11 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/inet.h>
+#include <linux/in6.h>
 
 #include <net/route.h>
 #include <net/ip_fib.h>
+#include <net/ip6_route.h>
 
 #include <linux/timex.h>
 
@@ -66,9 +68,13 @@ extern int ip_route_output_cycles_7;
 static int flow_oif = DEFAULT_OIF;
 static int flow_iif = DEFAULT_IIF;
 static u32 flow_mark = DEFAULT_MARK;
-static u32 flow_dst_ip_addr = DEFAULT_DST_IP_ADDR;
-static u32 flow_src_ip_addr = DEFAULT_SRC_IP_ADDR;
+static u32 ip4_flow_dst_ip_addr = DEFAULT_DST_IP_ADDR;
+static u32 ip4_flow_src_ip_addr = DEFAULT_SRC_IP_ADDR;
+static struct in6_addr ip6_flow_dst_ip_addr;
+static struct in6_addr ip6_flow_src_ip_addr;
 static int flow_tos = DEFAULT_TOS;
+static int ip6_bench;
+module_param(ip6_bench, int, 0);
 
 static char dst_string[64];
 static char src_string[64];
@@ -76,12 +82,29 @@ static char src_string[64];
 module_param_string(dst, dst_string, sizeof(dst_string), 0);
 module_param_string(src, src_string, sizeof(src_string), 0);
 
-static void __init flow_setup(void)
+static int __init flow_setup(void)
 {
+	if (ip6_bench) {
+		if (dst_string[0] &&
+		    !in6_pton(dst_string, -1, ip6_flow_dst_ip_addr.s6_addr, -1, NULL)) {
+			pr_info("cannot parse \"%s\"\n", dst_string);
+			return -1;
+		}
+
+		if (src_string[0] &&
+		    !in6_pton(src_string, -1, ip6_flow_src_ip_addr.s6_addr, -1, NULL)) {
+			pr_info("cannot parse \"%s\"\n", src_string);
+			return -1;
+		}
+
+		return 0;
+	}
+
 	if (dst_string[0])
-		flow_dst_ip_addr = in_aton(dst_string);
+		ip4_flow_dst_ip_addr = in_aton(dst_string);
 	if (src_string[0])
-		flow_src_ip_addr = in_aton(src_string);
+		ip4_flow_src_ip_addr = in_aton(src_string);
+	return 0;
 }
 
 module_param_named(oif, flow_oif, int, 0);
@@ -92,15 +115,70 @@ module_param_named(tos, flow_tos, int, 0);
 static int warmup_count = DEFAULT_WARMUP_COUNT;
 module_param_named(count, warmup_count, int, 0);
 
-static void flow_init(struct flowi4 *fl4)
+#define flow_init(fl, gen) 				\
+do {							\
+	memset((fl), 0, sizeof(*(fl)));			\
+	(fl)->flowi##gen##_oif = flow_oif;		\
+	(fl)->flowi##gen##_iif = flow_iif;		\
+	(fl)->flowi##gen##_mark = flow_mark;		\
+	(fl)->flowi##gen##_tos = flow_tos;		\
+	(fl)->daddr = ip##gen##_flow_dst_ip_addr;	\
+	(fl)->saddr = ip##gen##_flow_src_ip_addr;	\
+} while (0)
+
+#define flow_init_ip6(fl) 				\
+do {							\
+	flow_init(fl, 6);				\
+	(fl)->flowi6_proto = IPPROTO_ICMPV6;		\
+} while(0)
+
+static int skb_init_ip6(struct sk_buff *skb)
 {
-	memset(fl4, 0, sizeof(*fl4));
-	fl4->flowi4_oif = flow_oif;
-	fl4->flowi4_iif = flow_iif;
-	fl4->flowi4_mark = flow_mark;
-	fl4->flowi4_tos = flow_tos;
-	fl4->daddr = flow_dst_ip_addr;
-	fl4->saddr = flow_src_ip_addr;
+	struct ipv6hdr *hdr;
+	struct net_device *dev;
+
+	skb_reset_mac_header(skb);
+	skb_reset_network_header(skb);
+	skb_reserve(skb, MAX_HEADER + sizeof(struct ipv6hdr));
+	hdr = ipv6_hdr(skb);
+
+	hdr->priority = 0;
+	hdr->version = 6;
+	memset(hdr->flow_lbl, 0, sizeof(hdr->flow_lbl));
+	hdr->payload_len = htons(sizeof(struct icmp6hdr));
+	hdr->nexthdr = IPPROTO_ICMPV6;
+	hdr->saddr = ip6_flow_src_ip_addr;
+	hdr->daddr = ip6_flow_dst_ip_addr;
+
+	dev = __dev_get_by_index(&init_net, flow_iif);
+	if (dev == NULL) {
+		pr_info("Input device does not exist\n");
+		return -ENODEV;
+	}
+	skb->protocol = htons(ETH_P_IPV6);
+	skb->dev = dev;
+	skb->mark = flow_mark;
+	return 0;
+}
+
+static int skb_init_ip4(struct sk_buff *skb)
+{
+	struct net_device *dev;
+
+	skb_reset_mac_header(skb);
+	skb_reset_network_header(skb);
+	ip_hdr(skb)->protocol = IPPROTO_ICMP;
+	skb_reserve(skb, MAX_HEADER + sizeof(struct iphdr));
+
+	dev = __dev_get_by_index(&init_net, flow_iif);
+	if (dev == NULL) {
+		pr_info("Input device does not exist\n");
+		return -ENODEV;
+	}
+	skb->protocol = htons(ETH_P_IP);
+	skb->dev = dev;
+	skb->mark = flow_mark;
+	return 0;
 }
 
 static struct rtable *route_output(struct net *net, struct flowi4 *fl4)
@@ -108,7 +186,7 @@ static struct rtable *route_output(struct net *net, struct flowi4 *fl4)
 	return ip_route_output_key(net, fl4);
 }
 
-static void do_full_output_lookup_bench(void)
+static void do_full_output_lookup_bench_ip4(void)
 {
 	unsigned long long t1, t2, tdiff;
 	struct rtable *rt;
@@ -118,7 +196,7 @@ static void do_full_output_lookup_bench(void)
 	rt = NULL;
 
 	for (i = 0; i < warmup_count; i++) {
-		flow_init(&fl4);
+		flow_init(&fl4, 4);
 
 		rt = route_output(&init_net, &fl4);
 		if (IS_ERR(rt))
@@ -140,7 +218,7 @@ static void do_full_output_lookup_bench(void)
 	ip_route_output_cycles_7 = 0;
 #endif
 
-	flow_init(&fl4);
+	flow_init(&fl4, 4);
 
 	t1 = get_tick();
 	rt = route_output(&init_net, &fl4);
@@ -161,35 +239,73 @@ static void do_full_output_lookup_bench(void)
 #endif
 }
 
+static void do_full_output_lookup_bench_ip6(void)
+{
+	unsigned long long t1, t2, tdiff;
+	struct rt6_info *rt;
+	struct flowi6 fl6;
+	int i;
+
+	rt = NULL;
+
+	for (i = 0; i < warmup_count; i++) {
+		flow_init_ip6(&fl6);
+
+		rt = (struct rt6_info *)ip6_route_output(&init_net, NULL, &fl6);
+		if (IS_ERR(rt))
+			break;
+		ip6_rt_put(rt);
+	}
+	if (IS_ERR(rt)) {
+		pr_info("ip6_route_output: err=%ld\n", PTR_ERR(rt));
+		return;
+	}
+
+	flow_init_ip6(&fl6);
+
+	t1 = get_tick();
+	rt = (struct rt6_info *)ip6_route_output(&init_net, NULL, &fl6);
+	t2 = get_tick();
+	if (!IS_ERR(rt))
+		ip6_rt_put(rt);
+
+	tdiff = t2 - t1;
+	pr_info("ip6_route_output tdiff: %llu\n", tdiff);
+}
+
 static void do_full_input_lookup_bench(void)
 {
 	unsigned long long t1, t2, tdiff;
-	struct net_device *dev;
 	struct sk_buff *skb;
+	struct rt6_info *rt;
 	int err, i;
 
+#ifndef HAVE_IP6_ROUTE_INPUT
+#define ip6_route_input(s)
+	if (ip6_bench)
+		return;
+#endif
 	skb = alloc_skb(4096, GFP_KERNEL);
 	if (!skb) {
 		pr_info("Cannot alloc SKB for test\n");
 		return;
 	}
-	skb_reset_mac_header(skb);
-	skb_reset_network_header(skb);
-	ip_hdr(skb)->protocol = IPPROTO_ICMP;
-	skb_reserve(skb, MAX_HEADER + sizeof(struct iphdr));
-
-	dev = __dev_get_by_index(&init_net, flow_iif);
-	if (dev == NULL) {
-		pr_info("Input device does not exist\n");
+	if (ip6_bench)
+		err = skb_init_ip6(skb);
+	else
+		err = skb_init_ip4(skb);
+	if (err)
 		goto out_free;
-	}
-	skb->protocol = htons(ETH_P_IP);
-	skb->dev = dev;
-	skb->mark = flow_mark;
+
 	local_bh_disable();
 	err = 0;
 	for (i = 0; i < warmup_count; i++) {
-		err = ip_route_input(skb, flow_dst_ip_addr, flow_src_ip_addr, flow_tos, dev);
+		if (ip6_bench) {
+			ip6_route_input(skb);
+			rt = (struct rt6_info *)skb_dst(skb);
+			err = (!rt || rt == init_net.ipv6.ip6_null_entry);
+		} else
+			err = ip_route_input(skb, ip4_flow_dst_ip_addr, ip4_flow_src_ip_addr, flow_tos, skb->dev);
 		if (err)
 			break;
 		skb_dst_drop(skb);
@@ -203,7 +319,12 @@ static void do_full_input_lookup_bench(void)
 
 	local_bh_disable();
 	t1 = get_tick();
-	err = ip_route_input(skb, flow_dst_ip_addr, flow_src_ip_addr, flow_tos, dev);
+	if (ip6_bench) {
+		ip6_route_input(skb);
+		rt = (struct rt6_info *)skb_dst(skb);
+		err = (!rt || rt == init_net.ipv6.ip6_null_entry);
+	} else
+		err = ip_route_input(skb, ip4_flow_dst_ip_addr, ip4_flow_src_ip_addr, flow_tos, skb->dev);
 	t2 = get_tick();
 	local_bh_enable();
 
@@ -215,7 +336,10 @@ static void do_full_input_lookup_bench(void)
 	skb_dst_drop(skb);
 
 	tdiff = t2 - t1;
-	pr_info("ip_route_input tdiff: %llu\n", tdiff);
+	if (ip6_bench)
+		pr_info("ip6_route_input tdiff: %llu\n", tdiff);
+	else
+		pr_info("ip_route_input tdiff: %llu\n", tdiff);
 
 out_free:
 	kfree_skb(skb);
@@ -223,9 +347,12 @@ static void do_full_input_lookup_bench(void)
 
 static void do_full_lookup_bench(void)
 {
-	if (!flow_iif)
-		do_full_output_lookup_bench();
-	else
+	if (!flow_iif) {
+		if (ip6_bench)
+			do_full_output_lookup_bench_ip6();
+		else
+			do_full_output_lookup_bench_ip4();
+	} else
 		do_full_input_lookup_bench();
 }
 
@@ -240,7 +367,7 @@ static void do_full_lookup_prealloc_bench(void)
 	err = 0;
 
 	for (i = 0; i < warmup_count; i++) {
-		flow_init(&fl4);
+		flow_init(&fl4, 4);
 
 		rt = ip_route_output_flow_prealloc(&init_net, &fl4, NULL, &rt_stack.dst);
 		if (IS_ERR(rt)) {
@@ -264,7 +391,7 @@ static void do_full_lookup_prealloc_bench(void)
 	ip_route_output_cycles_7 = 0;
 #endif
 
-	flow_init(&fl4);
+	flow_init(&fl4, 4);
 
 	t1 = get_tick();
 	rt = ip_route_output_flow_prealloc(&init_net, &fl4, NULL, &rt_stack.dst);
@@ -295,7 +422,7 @@ static void do_fib_lookup_bench(void)
 	struct flowi4 fl4;
 	int err, i;
 
-	flow_init(&fl4);
+	flow_init(&fl4, 4);
 
 	for (i = 0; i < warmup_count; i++) {
 		struct fib_table *table;
@@ -398,7 +525,7 @@ static void do_new_lookup_bench(void)
 	struct flowi fl;
 	int err, i;
 
-	flow_init(&fl);
+	flow_init(&fl, 4);
 
 	for (i = 0; i < warmup_count; i++) {
 		err = new_output_lookup(&fl, &rt);
@@ -428,6 +555,8 @@ static void do_bench(void)
 	do_full_lookup_bench();
 	do_full_lookup_bench();
 
+	if (ip6_bench)
+		return;
 #ifdef IP_ROUTE_HAVE_PREALLOC
 	do_full_lookup_prealloc_bench();
 	do_full_lookup_prealloc_bench();
@@ -452,10 +581,19 @@ static int __init kbench_init(void)
 {
 	flow_setup();
 
-	pr_info("flow [IIF(%d),OIF(%d),MARK(0x%08x),D(%pI4),S(%pI4),TOS(0x%02x)]\n",
-		flow_iif, flow_oif, flow_mark,
-		&flow_dst_ip_addr,
-		&flow_src_ip_addr, flow_tos);
+	if (!ip6_bench) {
+		pr_info("flow [IIF(%d),OIF(%d),MARK(0x%08x),D(%pI4),S(%pI4),TOS(0x%02x)]\n",
+			flow_iif, flow_oif, flow_mark,
+			&ip4_flow_dst_ip_addr,
+			&ip4_flow_src_ip_addr, flow_tos);
+	} else {
+		pr_info("flow [IIF(%d),OIF(%d),MARK(0x%08x),D(%pI6),"
+			"S(%pI6),TOS(0x%02x)]\n",
+			flow_iif, flow_oif, flow_mark,
+			&ip6_flow_dst_ip_addr,
+			&ip6_flow_src_ip_addr,
+			flow_tos);
+	}
 
 #if defined(CONFIG_X86)
 	if (!cpu_has_tsc) {

  reply	other threads:[~2015-01-22 22:13 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-01-14  5:45 net_test_tools: add ipv6 support for kbench_mod Shaohua Li
2015-01-14  6:35 ` David Miller
2015-01-15 21:17   ` Shaohua Li
2015-01-15 23:08     ` David Miller
2015-01-22 22:12       ` Shaohua Li [this message]
2015-01-23  9:55         ` Daniel Borkmann
2015-01-23 15:58           ` Shaohua Li

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20150122221256.GA2263247@devbig257.prn2.facebook.com \
    --to=shli@fb.com \
    --cc=davem@davemloft.net \
    --cc=kafai@fb.com \
    --cc=netdev@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.