[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20150122221256.GA2263247@devbig257.prn2.facebook.com>
Date: Thu, 22 Jan 2015 14:12:56 -0800
From: Shaohua Li <shli@...com>
To: David Miller <davem@...emloft.net>
CC: <netdev@...r.kernel.org>, <kafai@...com>
Subject: Re: net_test_tools: add ipv6 support for kbench_mod
On Thu, Jan 15, 2015 at 06:08:39PM -0500, David Miller wrote:
> From: Shaohua Li <shli@...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@...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) {
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Powered by blists - more mailing lists