2013-06-14 01:56:46

by Eliezer Tamir

[permalink] [raw]
Subject: [PATCH v4 net-next 0/4] net: low latency sockets follow ups

David,

Here are three clean up patches, plus one that adds a socket option for LLS.

Patch 1 converts sysctl_net_ll_poll into an unsigned int
Patch 2 converts low latency sockets to sched_clock.
Patch 3 removes the config menu for NET_LL_RX_POLL and defaults to y.
Patch 4 adds an SO_LL socket option to allow per-socket control of busy polling.

I will reply to this thread with a patch to sockperf that enables
the socket option. (unchanged from v2)

Again, thanks to everyone for their comments.

-Eliezer


Change log:
v4
- Fixed possible overflow, pointed out by Eric Dumazet.
(reordered the patches)

v3
- Suggested by David Miller and Stephen Hemminger:
added a patch to covert from get_cycles() to sched_clock(),
remove dependency on X86_TSC.
- Suggested by Eric Dumazet:
un-exported sysctl_net_ll_poll since for now it's not needed in modules.

v2
- added a patch to convert sysctl_net_ll_poll into an unsigned int.
- suggested by Eric Dimazet: treat sk_ll_usec as a u_int rather than a u_long.
- suggested by Ben Huchings: allow unprivileged user to decrease SO_LL value,
correct return value when operation is not allowed.


2013-06-14 01:57:07

by Eliezer Tamir

[permalink] [raw]
Subject: [PATCH v4 net-next 1/4] net: change sysctl_net_ll_poll into an unsigned int

There is no reason for sysctl_net_ll_poll to be an unsigned long.
Change it into an unsigned int.
Fix the proc handler.

Signed-off-by: Eliezer Tamir <[email protected]>
---

include/net/ll_poll.h | 5 +++--
net/core/sysctl_net_core.c | 4 ++--
net/socket.c | 2 +-
3 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/include/net/ll_poll.h b/include/net/ll_poll.h
index bc262f8..44e2f70 100644
--- a/include/net/ll_poll.h
+++ b/include/net/ll_poll.h
@@ -34,7 +34,7 @@
#ifdef CONFIG_NET_LL_RX_POLL

struct napi_struct;
-extern unsigned long sysctl_net_ll_poll __read_mostly;
+extern unsigned int sysctl_net_ll_poll __read_mostly;

/* return values from ndo_ll_poll */
#define LL_FLUSH_FAILED -1
@@ -45,7 +45,8 @@ extern unsigned long sysctl_net_ll_poll __read_mostly;

static inline cycles_t ll_end_time(void)
{
- return TSC_MHZ * ACCESS_ONCE(sysctl_net_ll_poll) + get_cycles();
+ return (cycles_t)TSC_MHZ * ACCESS_ONCE(sysctl_net_ll_poll)
+ + get_cycles();
}

static inline bool sk_valid_ll(struct sock *sk)
diff --git a/net/core/sysctl_net_core.c b/net/core/sysctl_net_core.c
index 637a42e..ce9acc2 100644
--- a/net/core/sysctl_net_core.c
+++ b/net/core/sysctl_net_core.c
@@ -289,9 +289,9 @@ static struct ctl_table net_core_table[] = {
{
.procname = "low_latency_poll",
.data = &sysctl_net_ll_poll,
- .maxlen = sizeof(unsigned long),
+ .maxlen = sizeof(unsigned int),
.mode = 0644,
- .proc_handler = proc_doulongvec_minmax
+ .proc_handler = proc_dointvec
},
#endif
#endif /* CONFIG_NET */
diff --git a/net/socket.c b/net/socket.c
index 21fd29f..caaffa1 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -107,7 +107,7 @@
#include <net/ll_poll.h>

#ifdef CONFIG_NET_LL_RX_POLL
-unsigned long sysctl_net_ll_poll __read_mostly;
+unsigned int sysctl_net_ll_poll __read_mostly;
EXPORT_SYMBOL_GPL(sysctl_net_ll_poll);
#endif

2013-06-14 01:57:12

by Eliezer Tamir

[permalink] [raw]
Subject: [PATCH v4 net-next 2/4] net: convert low latency sockets to sched_clock()

Use sched_clock() instead of get_cycles().
We can use sched_clock() because we don't care much about accuracy.
Remove the dependency on X86_TSC

Signed-off-by: Eliezer Tamir <[email protected]>
---

include/net/ll_poll.h | 32 +++++++++++++++++---------------
net/Kconfig | 1 -
2 files changed, 17 insertions(+), 16 deletions(-)

diff --git a/include/net/ll_poll.h b/include/net/ll_poll.h
index 44e2f70..8608547 100644
--- a/include/net/ll_poll.h
+++ b/include/net/ll_poll.h
@@ -21,10 +21,6 @@
* e1000-devel Mailing List <[email protected]>
*/

-/*
- * For now this depends on CONFIG_X86_TSC
- */
-
#ifndef _LINUX_NET_LL_POLL_H
#define _LINUX_NET_LL_POLL_H

@@ -40,13 +36,19 @@ extern unsigned int sysctl_net_ll_poll __read_mostly;
#define LL_FLUSH_FAILED -1
#define LL_FLUSH_BUSY -2

-/* we don't mind a ~2.5% imprecision */
-#define TSC_MHZ (tsc_khz >> 10)
-
-static inline cycles_t ll_end_time(void)
+/* we can use sched_clock() because we don't care much about precision
+ * we only care that the average is bounded
+ */
+static inline u64 ll_end_time(void)
{
- return (cycles_t)TSC_MHZ * ACCESS_ONCE(sysctl_net_ll_poll)
- + get_cycles();
+ u64 end_time = ACCESS_ONCE(sysctl_net_ll_poll);
+
+ /* we don't mind a ~2.5% imprecision
+ * sysctl_net_ll_poll is a u_int so this can't overflow
+ */
+ end_time = (end_time << 10) + sched_clock();
+
+ return end_time;
}

static inline bool sk_valid_ll(struct sock *sk)
@@ -55,16 +57,16 @@ static inline bool sk_valid_ll(struct sock *sk)
!need_resched() && !signal_pending(current);
}

-static inline bool can_poll_ll(cycles_t end_time)
+static inline bool can_poll_ll(u64 end_time)
{
- return !time_after((unsigned long)get_cycles(),
+ return !time_after((unsigned long)sched_clock(),
(unsigned long)end_time);
}

static inline bool sk_poll_ll(struct sock *sk, int nonblock)
{
- cycles_t end_time = ll_end_time();
const struct net_device_ops *ops;
+ u64 end_time = ll_end_time();
struct napi_struct *napi;
int rc = false;

@@ -117,7 +119,7 @@ static inline void sk_mark_ll(struct sock *sk, struct sk_buff *skb)

#else /* CONFIG_NET_LL_RX_POLL */

-static inline cycles_t ll_end_time(void)
+static inline u64 ll_end_time(void)
{
return 0;
}
@@ -140,7 +142,7 @@ static inline void sk_mark_ll(struct sock *sk, struct sk_buff *skb)
{
}

-static inline bool can_poll_ll(cycles_t end_time)
+static inline bool can_poll_ll(u64 end_time)
{
return false;
}
diff --git a/net/Kconfig b/net/Kconfig
index d6a9ce6..e591668 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -245,7 +245,6 @@ config NETPRIO_CGROUP

config NET_LL_RX_POLL
bool "Low Latency Receive Poll"
- depends on X86_TSC
default n
---help---
Support Low Latency Receive Queue Poll.

2013-06-14 01:57:20

by Eliezer Tamir

[permalink] [raw]
Subject: [PATCH v4 net-next 3/4] net: remove NET_LL_RX_POLL config menue

Remove NET_LL_RX_POLL from the config menu.
Change default to y.
Busy polling still needs to be enabled at run time.

Signed-off-by: Eliezer Tamir <[email protected]>
---

net/Kconfig | 11 ++---------
1 files changed, 2 insertions(+), 9 deletions(-)

diff --git a/net/Kconfig b/net/Kconfig
index e591668..51da839 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -244,15 +244,8 @@ config NETPRIO_CGROUP
a per-interface basis

config NET_LL_RX_POLL
- bool "Low Latency Receive Poll"
- default n
- ---help---
- Support Low Latency Receive Queue Poll.
- (For network card drivers which support this option.)
- When waiting for data in read or poll call directly into the the device driver
- to flush packets which may be pending on the device queues into the stack.
-
- If unsure, say N.
+ boolean
+ default y

config BQL
boolean

2013-06-14 01:57:33

by Eliezer Tamir

[permalink] [raw]
Subject: [PATCH v4 net-next 4/4] net: add socket option for low latency polling

adds a socket option for low latency polling.
This allows overriding the global sysctl value with a per-socket one.
Unexport sysctl_net_ll_poll since for now it's not needed in modules.

Signed-off-by: Eliezer Tamir <[email protected]>
---

arch/alpha/include/uapi/asm/socket.h | 2 ++
arch/avr32/include/uapi/asm/socket.h | 2 ++
arch/cris/include/uapi/asm/socket.h | 2 ++
arch/frv/include/uapi/asm/socket.h | 2 ++
arch/h8300/include/uapi/asm/socket.h | 2 ++
arch/ia64/include/uapi/asm/socket.h | 2 ++
arch/m32r/include/uapi/asm/socket.h | 2 ++
arch/mips/include/uapi/asm/socket.h | 2 ++
arch/mn10300/include/uapi/asm/socket.h | 2 ++
arch/parisc/include/uapi/asm/socket.h | 2 ++
arch/powerpc/include/uapi/asm/socket.h | 2 ++
arch/s390/include/uapi/asm/socket.h | 2 ++
arch/sparc/include/uapi/asm/socket.h | 2 ++
arch/xtensa/include/uapi/asm/socket.h | 2 ++
include/net/ll_poll.h | 12 ++++++------
include/net/sock.h | 2 ++
include/uapi/asm-generic/socket.h | 2 ++
net/core/sock.c | 20 ++++++++++++++++++++
net/socket.c | 1 -
19 files changed, 58 insertions(+), 7 deletions(-)

diff --git a/arch/alpha/include/uapi/asm/socket.h b/arch/alpha/include/uapi/asm/socket.h
index eee6ea7..4885825 100644
--- a/arch/alpha/include/uapi/asm/socket.h
+++ b/arch/alpha/include/uapi/asm/socket.h
@@ -81,4 +81,6 @@

#define SO_SELECT_ERR_QUEUE 45

+#define SO_LL 46
+
#endif /* _UAPI_ASM_SOCKET_H */
diff --git a/arch/avr32/include/uapi/asm/socket.h b/arch/avr32/include/uapi/asm/socket.h
index 37401f5..79b6179 100644
--- a/arch/avr32/include/uapi/asm/socket.h
+++ b/arch/avr32/include/uapi/asm/socket.h
@@ -74,4 +74,6 @@

#define SO_SELECT_ERR_QUEUE 45

+#define SO_LL 46
+
#endif /* __ASM_AVR32_SOCKET_H */
diff --git a/arch/cris/include/uapi/asm/socket.h b/arch/cris/include/uapi/asm/socket.h
index ba409c9..47b1ec5 100644
--- a/arch/cris/include/uapi/asm/socket.h
+++ b/arch/cris/include/uapi/asm/socket.h
@@ -76,6 +76,8 @@

#define SO_SELECT_ERR_QUEUE 45

+#define SO_LL 46
+
#endif /* _ASM_SOCKET_H */


diff --git a/arch/frv/include/uapi/asm/socket.h b/arch/frv/include/uapi/asm/socket.h
index 31dbb5d..dbc0852 100644
--- a/arch/frv/include/uapi/asm/socket.h
+++ b/arch/frv/include/uapi/asm/socket.h
@@ -74,5 +74,7 @@

#define SO_SELECT_ERR_QUEUE 45

+#define SO_LL 46
+
#endif /* _ASM_SOCKET_H */

diff --git a/arch/h8300/include/uapi/asm/socket.h b/arch/h8300/include/uapi/asm/socket.h
index 5d1c6d0..a38d38a 100644
--- a/arch/h8300/include/uapi/asm/socket.h
+++ b/arch/h8300/include/uapi/asm/socket.h
@@ -74,4 +74,6 @@

#define SO_SELECT_ERR_QUEUE 45

+#define SO_LL 46
+
#endif /* _ASM_SOCKET_H */
diff --git a/arch/ia64/include/uapi/asm/socket.h b/arch/ia64/include/uapi/asm/socket.h
index 6b4329f..d3358b7 100644
--- a/arch/ia64/include/uapi/asm/socket.h
+++ b/arch/ia64/include/uapi/asm/socket.h
@@ -83,4 +83,6 @@

#define SO_SELECT_ERR_QUEUE 45

+#define SO_LL 46
+
#endif /* _ASM_IA64_SOCKET_H */
diff --git a/arch/m32r/include/uapi/asm/socket.h b/arch/m32r/include/uapi/asm/socket.h
index 2a3b59e..44aaf46 100644
--- a/arch/m32r/include/uapi/asm/socket.h
+++ b/arch/m32r/include/uapi/asm/socket.h
@@ -74,4 +74,6 @@

#define SO_SELECT_ERR_QUEUE 45

+#define SO_LL 46
+
#endif /* _ASM_M32R_SOCKET_H */
diff --git a/arch/mips/include/uapi/asm/socket.h b/arch/mips/include/uapi/asm/socket.h
index 3b21150..6a07992 100644
--- a/arch/mips/include/uapi/asm/socket.h
+++ b/arch/mips/include/uapi/asm/socket.h
@@ -92,4 +92,6 @@

#define SO_SELECT_ERR_QUEUE 45

+#define SO_LL 46
+
#endif /* _UAPI_ASM_SOCKET_H */
diff --git a/arch/mn10300/include/uapi/asm/socket.h b/arch/mn10300/include/uapi/asm/socket.h
index b4ce844..db80fd3 100644
--- a/arch/mn10300/include/uapi/asm/socket.h
+++ b/arch/mn10300/include/uapi/asm/socket.h
@@ -74,4 +74,6 @@

#define SO_SELECT_ERR_QUEUE 45

+#define SO_LL 46
+
#endif /* _ASM_SOCKET_H */
diff --git a/arch/parisc/include/uapi/asm/socket.h b/arch/parisc/include/uapi/asm/socket.h
index 70c512a..f866fff 100644
--- a/arch/parisc/include/uapi/asm/socket.h
+++ b/arch/parisc/include/uapi/asm/socket.h
@@ -73,6 +73,8 @@

#define SO_SELECT_ERR_QUEUE 0x4026

+#define SO_LL 0x4027
+
/* O_NONBLOCK clashes with the bits used for socket types. Therefore we
* have to define SOCK_NONBLOCK to a different value here.
*/
diff --git a/arch/powerpc/include/uapi/asm/socket.h b/arch/powerpc/include/uapi/asm/socket.h
index a36daf3..405fb09 100644
--- a/arch/powerpc/include/uapi/asm/socket.h
+++ b/arch/powerpc/include/uapi/asm/socket.h
@@ -81,4 +81,6 @@

#define SO_SELECT_ERR_QUEUE 45

+#define SO_LL 46
+
#endif /* _ASM_POWERPC_SOCKET_H */
diff --git a/arch/s390/include/uapi/asm/socket.h b/arch/s390/include/uapi/asm/socket.h
index 2dacb306..0c5105fb 100644
--- a/arch/s390/include/uapi/asm/socket.h
+++ b/arch/s390/include/uapi/asm/socket.h
@@ -80,4 +80,6 @@

#define SO_SELECT_ERR_QUEUE 45

+#define SO_LL 46
+
#endif /* _ASM_SOCKET_H */
diff --git a/arch/sparc/include/uapi/asm/socket.h b/arch/sparc/include/uapi/asm/socket.h
index 89f49b6..b46c3fa 100644
--- a/arch/sparc/include/uapi/asm/socket.h
+++ b/arch/sparc/include/uapi/asm/socket.h
@@ -70,6 +70,8 @@

#define SO_SELECT_ERR_QUEUE 0x0029

+#define SO_LL 0x0030
+
/* Security levels - as per NRL IPv6 - don't actually do anything */
#define SO_SECURITY_AUTHENTICATION 0x5001
#define SO_SECURITY_ENCRYPTION_TRANSPORT 0x5002
diff --git a/arch/xtensa/include/uapi/asm/socket.h b/arch/xtensa/include/uapi/asm/socket.h
index a8f44f5..b21ace4 100644
--- a/arch/xtensa/include/uapi/asm/socket.h
+++ b/arch/xtensa/include/uapi/asm/socket.h
@@ -85,4 +85,6 @@

#define SO_SELECT_ERR_QUEUE 45

+#define SO_LL 46
+
#endif /* _XTENSA_SOCKET_H */
diff --git a/include/net/ll_poll.h b/include/net/ll_poll.h
index 8608547..4fdd8c9 100644
--- a/include/net/ll_poll.h
+++ b/include/net/ll_poll.h
@@ -39,12 +39,12 @@ extern unsigned int sysctl_net_ll_poll __read_mostly;
/* we can use sched_clock() because we don't care much about precision
* we only care that the average is bounded
*/
-static inline u64 ll_end_time(void)
+static inline u64 ll_end_time(struct sock *sk)
{
- u64 end_time = ACCESS_ONCE(sysctl_net_ll_poll);
+ u64 end_time = ACCESS_ONCE(sk->sk_ll_usec);

/* we don't mind a ~2.5% imprecision
- * sysctl_net_ll_poll is a u_int so this can't overflow
+ * sk->sk_ll_usec is a u_int so this can't overflow
*/
end_time = (end_time << 10) + sched_clock();

@@ -53,7 +53,7 @@ static inline u64 ll_end_time(void)

static inline bool sk_valid_ll(struct sock *sk)
{
- return sysctl_net_ll_poll && sk->sk_napi_id &&
+ return sk->sk_ll_usec && sk->sk_napi_id &&
!need_resched() && !signal_pending(current);
}

@@ -66,7 +66,7 @@ static inline bool can_poll_ll(u64 end_time)
static inline bool sk_poll_ll(struct sock *sk, int nonblock)
{
const struct net_device_ops *ops;
- u64 end_time = ll_end_time();
+ u64 end_time = ll_end_time(sk);
struct napi_struct *napi;
int rc = false;

@@ -119,7 +119,7 @@ static inline void sk_mark_ll(struct sock *sk, struct sk_buff *skb)

#else /* CONFIG_NET_LL_RX_POLL */

-static inline u64 ll_end_time(void)
+static inline u64 ll_end_time(struct sock *sk)
{
return 0;
}
diff --git a/include/net/sock.h b/include/net/sock.h
index ac8e181..21db792 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -230,6 +230,7 @@ struct cg_proto;
* @sk_wmem_queued: persistent queue size
* @sk_forward_alloc: space allocated forward
* @sk_napi_id: id of the last napi context to receive data for sk
+ * @sk_ll_usec: usecs to busypoll when there is no data
* @sk_allocation: allocation mode
* @sk_sndbuf: size of send buffer in bytes
* @sk_flags: %SO_LINGER (l_onoff), %SO_BROADCAST, %SO_KEEPALIVE,
@@ -328,6 +329,7 @@ struct sock {
#endif
#ifdef CONFIG_NET_LL_RX_POLL
unsigned int sk_napi_id;
+ unsigned int sk_ll_usec;
#endif
atomic_t sk_drops;
int sk_rcvbuf;
diff --git a/include/uapi/asm-generic/socket.h b/include/uapi/asm-generic/socket.h
index c5d2e3a..ca3a20d 100644
--- a/include/uapi/asm-generic/socket.h
+++ b/include/uapi/asm-generic/socket.h
@@ -76,4 +76,6 @@

#define SO_SELECT_ERR_QUEUE 45

+#define SO_LL 46
+
#endif /* __ASM_GENERIC_SOCKET_H */
diff --git a/net/core/sock.c b/net/core/sock.c
index 788c0da..1e744b1 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -913,6 +913,19 @@ set_rcvbuf:
sock_valbool_flag(sk, SOCK_SELECT_ERR_QUEUE, valbool);
break;

+#ifdef CONFIG_NET_LL_RX_POLL
+ case SO_LL:
+ /* allow unprivileged users to decrease the value */
+ if ((val > sk->sk_ll_usec) && !capable(CAP_NET_ADMIN))
+ ret = -EPERM;
+ else {
+ if (val < 0)
+ ret = -EINVAL;
+ else
+ sk->sk_ll_usec = val;
+ }
+ break;
+#endif
default:
ret = -ENOPROTOOPT;
break;
@@ -1170,6 +1183,12 @@ int sock_getsockopt(struct socket *sock, int level, int optname,
v.val = sock_flag(sk, SOCK_SELECT_ERR_QUEUE);
break;

+#ifdef CONFIG_NET_LL_RX_POLL
+ case SO_LL:
+ v.val = sk->sk_ll_usec;
+ break;
+#endif
+
default:
return -ENOPROTOOPT;
}
@@ -2288,6 +2307,7 @@ void sock_init_data(struct socket *sock, struct sock *sk)

#ifdef CONFIG_NET_LL_RX_POLL
sk->sk_napi_id = 0;
+ sk->sk_ll_usec = sysctl_net_ll_poll;
#endif

/*
diff --git a/net/socket.c b/net/socket.c
index caaffa1..3eec3f7 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -108,7 +108,6 @@

#ifdef CONFIG_NET_LL_RX_POLL
unsigned int sysctl_net_ll_poll __read_mostly;
-EXPORT_SYMBOL_GPL(sysctl_net_ll_poll);
#endif

static int sock_no_open(struct inode *irrelevant, struct file *dontcare);

2013-06-14 01:58:40

by Eliezer Tamir

[permalink] [raw]
Subject: [PATCH v2 sockperf] sockperf: add SO_LL socketop support

Add lls socket option support.
use --lls (value in usecs) to override global setting.
Right now we always get and print the value of the option before we set,
to show that the option works properly.
This should be removed in an official release.
---

src/Defs.h | 3 +++
src/SockPerf.cpp | 58
+++++++++++++++++++++++++++++++++++++++++++++++++++---
2 files changed, 58 insertions(+), 3 deletions(-)

diff --git a/src/Defs.h b/src/Defs.h
index e38e3a4..041fa0d 100644
--- a/src/Defs.h
+++ b/src/Defs.h
@@ -161,6 +161,7 @@ enum {
OPT_OUTPUT_PRECISION, //35
OPT_CLIENTPORT, //36
OPT_CLIENTIP, //37
+ OPT_LLS, //38
};

#define MODULE_NAME "sockperf"
@@ -527,6 +528,8 @@ struct user_params_t {
// bool stream_mode; - use b_stream instead
int mthread_server;
struct timeval* select_timeout;
+ unsigned int lls_usecs;
+ bool lls_is_set;
int sock_buff_size;
int threads_num;
char threads_affinity[MAX_ARGV_SIZE];
diff --git a/src/SockPerf.cpp b/src/SockPerf.cpp
index 41daf95..28569c9 100644
--- a/src/SockPerf.cpp
+++ b/src/SockPerf.cpp
@@ -207,6 +207,10 @@ static const AOPT_DESC common_opt_desc[] =
"Limit the lifetime of the message (default 2)."
},
{
+ OPT_LLS, AOPT_ARG, aopt_set_literal( 0 ), aopt_set_string( "lls" ),
+ "Turn on LLS via socket option (value = us to poll)."
+ },
+ {
OPT_BUFFER_SIZE, AOPT_ARG, aopt_set_literal( 0 ),
aopt_set_string( "buffer-size" ),
"Set total socket receive/send buffer <size> in bytes (system
defined by default)."
},
@@ -292,7 +296,7 @@ static int proc_mode_help( int id, int argc, const
char **argv )
int i = 0;

printf(MODULE_NAME " is a tool for testing network latency and
throughput.\n");
- printf("version %s\n", STR(VERSION));
+ printf("version %s-lls\n", STR(VERSION));
printf("\n");
printf("Usage: " MODULE_NAME " <subcommand> [options] [args]\n");
printf("Type: \'" MODULE_NAME " <subcommand> --help\' for help on
a specific subcommand.\n");
@@ -1382,8 +1386,8 @@ static int proc_mode_server( int id, int argc,
const char **argv )
{
'B', AOPT_NOARG, aopt_set_literal( 'B' ),
aopt_set_string( "Bridge" ),
"Run in Bridge mode."
- },
-*/
+ },
+*/
{
OPT_THREADS_NUM, AOPT_ARG, aopt_set_literal( 0 ),
aopt_set_string( "threads-num" ),
"Run <N> threads on server side (requires '-f' option)."
@@ -1789,6 +1793,26 @@ static int parse_common_opt( const AOPT_OBJECT
*common_obj )
s_user_params.is_nonblocked_send = true;
}

+ if ( !rc && aopt_check(common_obj, OPT_LLS) ) {
+ const char* optarg = aopt_value(common_obj, OPT_LLS);
+ if (optarg) {
+ errno = 0;
+ int value = strtoul(optarg, NULL, 0);
+ if (errno != 0 || value < 0) {
+ log_msg("'-%d' Invalid LLS value: %s", OPT_LLS,
optarg);
+ rc = SOCKPERF_ERR_BAD_ARGUMENT;
+ }
+ else {
+ s_user_params.lls_usecs = value;
+ s_user_params.lls_is_set = true;
+ }
+ }
+ else {
+ log_msg("'-%d' Invalid value", OPT_LLS);
+ rc = SOCKPERF_ERR_BAD_ARGUMENT;
+ }
+ }
+
if ( !rc && aopt_check(common_obj, OPT_RECV_LOOPING) ) {

const char* optarg = aopt_value(common_obj, OPT_RECV_LOOPING);
@@ -2296,6 +2320,29 @@ int sock_set_reuseaddr(int fd)
return rc;
}

+#ifndef SO_LL
+#define SO_LL 46
+#endif
+int sock_set_lls(int fd)
+{
+ int rc = SOCKPERF_ERR_NONE;
+ unsigned int lls;
+ int size = sizeof(lls);
+
+ if(getsockopt(fd, SOL_SOCKET, SO_LL, &lls, (socklen_t *)&size) < 0){
+ log_err("getsockopt(SO_LL) failed");
+ return SOCKPERF_ERR_SOCKET;
+ } else
+ log_msg("socket option SO_LL default was %u, changing to %u",
lls, s_user_params.lls_usecs);
+
+ if (setsockopt(fd, SOL_SOCKET, SO_LL, &(s_user_params.lls_usecs),
sizeof(s_user_params.lls_usecs)) < 0) {
+ log_err("setsockopt(SO_LL) failed");
+ rc = SOCKPERF_ERR_SOCKET;
+ }
+ return rc;
+}
+
+
int sock_set_snd_rcv_bufs(int fd)
{
/*
@@ -2460,6 +2507,11 @@ int prepare_socket(int fd, struct fds_data *p_data)
}

if (!rc &&
+ (s_user_params.lls_is_set == true))
+ {
+ rc = sock_set_lls(fd);
+ }
+ if (!rc &&
(s_user_params.sock_buff_size > 0))
{
rc = sock_set_snd_rcv_bufs(fd);



2013-06-14 03:03:27

by Eric Dumazet

[permalink] [raw]
Subject: Re: [PATCH v4 net-next 1/4] net: change sysctl_net_ll_poll into an unsigned int

On Fri, 2013-06-14 at 04:56 +0300, Eliezer Tamir wrote:
> There is no reason for sysctl_net_ll_poll to be an unsigned long.
> Change it into an unsigned int.
> Fix the proc handler.
>
> Signed-off-by: Eliezer Tamir <[email protected]>
> ---

Acked-by: Eric Dumazet <[email protected]>

2013-06-14 03:12:57

by Eric Dumazet

[permalink] [raw]
Subject: Re: [PATCH v4 net-next 2/4] net: convert low latency sockets to sched_clock()

On Fri, 2013-06-14 at 04:57 +0300, Eliezer Tamir wrote:
> Use sched_clock() instead of get_cycles().
> We can use sched_clock() because we don't care much about accuracy.
> Remove the dependency on X86_TSC
>
> Signed-off-by: Eliezer Tamir <[email protected]>
> ---

>
> -static inline bool can_poll_ll(cycles_t end_time)
> +static inline bool can_poll_ll(u64 end_time)
> {
> - return !time_after((unsigned long)get_cycles(),
> + return !time_after((unsigned long)sched_clock(),
> (unsigned long)end_time);
> }

I do not really understand why you bother to have 64bit wide values,
and then use these "unsigned long" casts here.

On 32bit arches, this will really limit to 2^31 ns range.

You should instead either :
- use time_after_64() or
- explicitly limit sysctl_net_ll_poll range

2013-06-14 06:14:59

by Eliezer Tamir

[permalink] [raw]
Subject: Re: [PATCH v4 net-next 2/4] net: convert low latency sockets to sched_clock()

On 14/06/2013 06:12, Eric Dumazet wrote:
> On Fri, 2013-06-14 at 04:57 +0300, Eliezer Tamir wrote:
>> Use sched_clock() instead of get_cycles().
>> We can use sched_clock() because we don't care much about accuracy.
>> Remove the dependency on X86_TSC
>>
>> Signed-off-by: Eliezer Tamir <[email protected]>
>> ---
>
>>
>> -static inline bool can_poll_ll(cycles_t end_time)
>> +static inline bool can_poll_ll(u64 end_time)
>> {
>> - return !time_after((unsigned long)get_cycles(),
>> + return !time_after((unsigned long)sched_clock(),
>> (unsigned long)end_time);
>> }
>
> I do not really understand why you bother to have 64bit wide values,
> and then use these "unsigned long" casts here.
>
> On 32bit arches, this will really limit to 2^31 ns range.
>
> You should instead either :
> - use time_after_64() or
> - explicitly limit sysctl_net_ll_poll range

OK