* [PATCH] ipv4: Early TCP socket demux.
From: David Miller @ 2012-06-19 2:40 UTC (permalink / raw)
To: netdev
You know you want it.
Signed-off-by: David S. Miller <davem@davemloft.net>
diff --git a/include/net/protocol.h b/include/net/protocol.h
index 875f489..6c47bf8 100644
--- a/include/net/protocol.h
+++ b/include/net/protocol.h
@@ -34,6 +34,7 @@
/* This is used to register protocols. */
struct net_protocol {
+ int (*early_demux)(struct sk_buff *skb);
int (*handler)(struct sk_buff *skb);
void (*err_handler)(struct sk_buff *skb, u32 info);
int (*gso_send_check)(struct sk_buff *skb);
diff --git a/include/net/sock.h b/include/net/sock.h
index 4a45216..87b424a 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -319,6 +319,7 @@ struct sock {
unsigned long sk_flags;
struct dst_entry *sk_dst_cache;
spinlock_t sk_dst_lock;
+ struct dst_entry *sk_rx_dst;
atomic_t sk_wmem_alloc;
atomic_t sk_omem_alloc;
int sk_sndbuf;
@@ -1426,6 +1427,7 @@ extern struct sk_buff *sock_rmalloc(struct sock *sk,
gfp_t priority);
extern void sock_wfree(struct sk_buff *skb);
extern void sock_rfree(struct sk_buff *skb);
+extern void sock_edemux(struct sk_buff *skb);
extern int sock_setsockopt(struct socket *sock, int level,
int op, char __user *optval,
diff --git a/include/net/tcp.h b/include/net/tcp.h
index 9332f34..6660ffc 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -325,6 +325,7 @@ extern void tcp_v4_err(struct sk_buff *skb, u32);
extern void tcp_shutdown (struct sock *sk, int how);
+extern int tcp_v4_early_demux(struct sk_buff *skb);
extern int tcp_v4_rcv(struct sk_buff *skb);
extern struct inet_peer *tcp_v4_get_peer(struct sock *sk);
diff --git a/net/core/sock.c b/net/core/sock.c
index 9e5b71f..929bdcc 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -1465,6 +1465,11 @@ void sock_rfree(struct sk_buff *skb)
}
EXPORT_SYMBOL(sock_rfree);
+void sock_edemux(struct sk_buff *skb)
+{
+ sock_put(skb->sk);
+}
+EXPORT_SYMBOL(sock_edemux);
int sock_i_uid(struct sock *sk)
{
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index e4e8e00..a2bd2d2 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -157,6 +157,7 @@ void inet_sock_destruct(struct sock *sk)
kfree(rcu_dereference_protected(inet->inet_opt, 1));
dst_release(rcu_dereference_check(sk->sk_dst_cache, 1));
+ dst_release(sk->sk_rx_dst);
sk_refcnt_debug_dec(sk);
}
EXPORT_SYMBOL(inet_sock_destruct);
@@ -1520,14 +1521,15 @@ static const struct net_protocol igmp_protocol = {
#endif
static const struct net_protocol tcp_protocol = {
- .handler = tcp_v4_rcv,
- .err_handler = tcp_v4_err,
- .gso_send_check = tcp_v4_gso_send_check,
- .gso_segment = tcp_tso_segment,
- .gro_receive = tcp4_gro_receive,
- .gro_complete = tcp4_gro_complete,
- .no_policy = 1,
- .netns_ok = 1,
+ .early_demux = tcp_v4_early_demux,
+ .handler = tcp_v4_rcv,
+ .err_handler = tcp_v4_err,
+ .gso_send_check = tcp_v4_gso_send_check,
+ .gso_segment = tcp_tso_segment,
+ .gro_receive = tcp4_gro_receive,
+ .gro_complete = tcp4_gro_complete,
+ .no_policy = 1,
+ .netns_ok = 1,
};
static const struct net_protocol udp_protocol = {
diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c
index 8590144..cb883e1 100644
--- a/net/ipv4/ip_input.c
+++ b/net/ipv4/ip_input.c
@@ -324,19 +324,34 @@ static int ip_rcv_finish(struct sk_buff *skb)
* how the packet travels inside Linux networking.
*/
if (skb_dst(skb) == NULL) {
- int err = ip_route_input_noref(skb, iph->daddr, iph->saddr,
- iph->tos, skb->dev);
- if (unlikely(err)) {
- if (err == -EHOSTUNREACH)
- IP_INC_STATS_BH(dev_net(skb->dev),
- IPSTATS_MIB_INADDRERRORS);
- else if (err == -ENETUNREACH)
- IP_INC_STATS_BH(dev_net(skb->dev),
- IPSTATS_MIB_INNOROUTES);
- else if (err == -EXDEV)
- NET_INC_STATS_BH(dev_net(skb->dev),
- LINUX_MIB_IPRPFILTER);
- goto drop;
+ const struct net_protocol *ipprot;
+ int protocol = iph->protocol;
+ int hash, err;
+
+ hash = protocol & (MAX_INET_PROTOS - 1);
+
+ rcu_read_lock();
+ ipprot = rcu_dereference(inet_protos[hash]);
+ err = -ENOENT;
+ if (ipprot && ipprot->early_demux)
+ err = ipprot->early_demux(skb);
+ rcu_read_unlock();
+
+ if (err) {
+ err = ip_route_input_noref(skb, iph->daddr, iph->saddr,
+ iph->tos, skb->dev);
+ if (unlikely(err)) {
+ if (err == -EHOSTUNREACH)
+ IP_INC_STATS_BH(dev_net(skb->dev),
+ IPSTATS_MIB_INADDRERRORS);
+ else if (err == -ENETUNREACH)
+ IP_INC_STATS_BH(dev_net(skb->dev),
+ IPSTATS_MIB_INNOROUTES);
+ else if (err == -EXDEV)
+ NET_INC_STATS_BH(dev_net(skb->dev),
+ LINUX_MIB_IPRPFILTER);
+ goto drop;
+ }
}
}
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index fda2ca1..bd90181 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -1671,6 +1671,50 @@ csum_err:
}
EXPORT_SYMBOL(tcp_v4_do_rcv);
+int tcp_v4_early_demux(struct sk_buff *skb)
+{
+ struct net *net = dev_net(skb->dev);
+ const struct iphdr *iph;
+ const struct tcphdr *th;
+ struct sock *sk;
+ int err;
+
+ err = -ENOENT;
+ if (skb->pkt_type != PACKET_HOST)
+ goto out_err;
+
+ if (!pskb_may_pull(skb, ip_hdrlen(skb) + sizeof(struct tcphdr)))
+ goto out_err;
+
+ iph = ip_hdr(skb);
+ th = (struct tcphdr *) ((char *)iph + ip_hdrlen(skb));
+
+ if (th->doff < sizeof(struct tcphdr) / 4)
+ goto out_err;
+
+ if (!pskb_may_pull(skb, ip_hdrlen(skb) + th->doff * 4))
+ goto out_err;
+
+ sk = __inet_lookup_established(net, &tcp_hashinfo,
+ iph->saddr, th->source,
+ iph->daddr, th->dest,
+ skb->dev->ifindex);
+ if (sk) {
+ skb->sk = sk;
+ skb->destructor = sock_edemux;
+ if (sk->sk_state != TCP_TIME_WAIT) {
+ struct dst_entry *dst = sk->sk_rx_dst;
+ if (dst) {
+ skb_dst_set_noref(skb, dst);
+ err = 0;
+ }
+ }
+ }
+
+out_err:
+ return err;
+}
+
/*
* From tcp_input.c
*/
diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c
index cb01531..72b7c63 100644
--- a/net/ipv4/tcp_minisocks.c
+++ b/net/ipv4/tcp_minisocks.c
@@ -445,6 +445,8 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct request_sock *req,
struct tcp_sock *oldtp = tcp_sk(sk);
struct tcp_cookie_values *oldcvp = oldtp->cookie_values;
+ newsk->sk_rx_dst = dst_clone(skb_dst(skb));
+
/* TCP Cookie Transactions require space for the cookie pair,
* as it differs for each connection. There is no need to
* copy any s_data_payload stored at the original socket.
^ permalink raw reply related
* Re: [PATCH] ipv6: Move ipv6 proc file registration to end of init order
From: David Miller @ 2012-06-19 1:39 UTC (permalink / raw)
To: tgraf; +Cc: netdev
In-Reply-To: <1432a6aff6ee203a688e78b06ed8000475385564.1340057223.git.tgraf@suug.ch>
From: Thomas Graf <tgraf@suug.ch>
Date: Tue, 19 Jun 2012 00:08:33 +0200
> /proc/net/ipv6_route reflects the contents of fib_table_hash. The proc
> handler is installed in ip6_route_net_init() whereas fib_table_hash is
> allocated in fib6_net_init() _after_ the proc handler has been installed.
>
> This opens up a short time frame to access fib_table_hash with its pants
> down.
>
> Move the registration of the proc files to a later point in the init
> order to avoid the race.
>
> Tested :-)
>
> Signed-off-by: Thomas Graf <tgraf@suug.ch>
This looks a lot better, applied, thanks Thomas.
^ permalink raw reply
* Re: [PATCH] [XFRM] Fix unexpected SA hard expiration after changing date
From: Fan Du @ 2012-06-19 1:34 UTC (permalink / raw)
To: Steffen Klassert; +Cc: davem, herbert, netdev, fdu
In-Reply-To: <20120618110523.GA29295@secunet.com>
On 2012年06月18日 19:05, Steffen Klassert wrote:
> On Mon, Jun 18, 2012 at 04:24:16PM +0800, fan.du wrote:
>> After SA is setup, one timer is armed to detect soft/hard expiration,
>> however the timer handler uses xtime to do the math. This makes hard
>> expiration occurs first before soft expiration after setting new date
>> with big interval. As a result new child SA is deleted before rekeying
>> the new one.
>>
>> Signed-off-by: fan.du<fan.du@windriver.com>
>> ---
>> include/net/xfrm.h | 2 ++
>> net/xfrm/xfrm_state.c | 22 ++++++++++++++++++----
>> 2 files changed, 20 insertions(+), 4 deletions(-)
>>
>> diff --git a/include/net/xfrm.h b/include/net/xfrm.h
>> index 2933d74..1734acc 100644
>> --- a/include/net/xfrm.h
>> +++ b/include/net/xfrm.h
>> @@ -214,6 +214,8 @@ struct xfrm_state
>> /* Private data of this transformer, format is opaque,
>> * interpreted by xfrm_type methods. */
>> void *data;
>> + u32 flags;
>
> We already have the xflags field, it holds exactly one flag
> at the moment. So I think we don't need yet another u32 that
> holds one flag too.
>
good point!
I will make it in the next version.
--
Love each day!
--fan
^ permalink raw reply
* Re: [RFC] TCP: Support configurable delayed-ack parameters.
From: Stephen Hemminger @ 2012-06-19 1:27 UTC (permalink / raw)
To: greearb; +Cc: netdev, Daniel Baluta
In-Reply-To: <1340067163-29329-1-git-send-email-greearb@candelatech.com>
On Mon, 18 Jun 2012 17:52:43 -0700
greearb@candelatech.com wrote:
> From: Ben Greear <greearb@candelatech.com>
>
> RFC2581 ($4.2) specifies when an ACK should be generated as follows:
>
> " .. an ACK SHOULD be generated for at least every second
> full-sized segment, and MUST be generated within 500 ms
> of the arrival of the first unacknowledged packet.
> "
>
> We export the number of segments and the timeout limits
> specified above, so that a user can tune them according
> to their needs.
>
> Specifically:
> * /proc/sys/net/ipv4/tcp_default_delack_segs, represents
> the threshold for the number of segments.
> * /proc/sys/net/ipv4/tcp_default_delack_min, specifies
> the minimum timeout value
> * /proc/sys/net/ipv4/tcp_default_delack_max, specifies
> the maximum timeout value.
>
> In addition, new TCP socket options are added to allow
> per-socket configuration:
>
> TCP_DELACK_SEGS
> TCP_DELACK_MIN
> TCP_DELACK_MAX
>
> In order to keep a multiply out of the hot path, the segs * mss
> computation is recalculated and cached whenever segs or mss changes.
>
> Signed-off-by: Daniel Baluta <dbaluta@ixiacom.com>
> Signed-off-by: Ben Greear <greearb@candelatech.com>
What is the justification (other than standard) for making this
tunable. Why would you want to do this? Why shouldn't the stack be adjusting
it for you (based on other heuristics)? Or is this just for testing interoperation
with TCP stacks that have wonky ACK policies. There are already too many TCP tunable
parameters for general usage.
^ permalink raw reply
* [RFC] TCP: Support configurable delayed-ack parameters.
From: greearb @ 2012-06-19 0:52 UTC (permalink / raw)
To: netdev; +Cc: Ben Greear, Daniel Baluta
From: Ben Greear <greearb@candelatech.com>
RFC2581 ($4.2) specifies when an ACK should be generated as follows:
" .. an ACK SHOULD be generated for at least every second
full-sized segment, and MUST be generated within 500 ms
of the arrival of the first unacknowledged packet.
"
We export the number of segments and the timeout limits
specified above, so that a user can tune them according
to their needs.
Specifically:
* /proc/sys/net/ipv4/tcp_default_delack_segs, represents
the threshold for the number of segments.
* /proc/sys/net/ipv4/tcp_default_delack_min, specifies
the minimum timeout value
* /proc/sys/net/ipv4/tcp_default_delack_max, specifies
the maximum timeout value.
In addition, new TCP socket options are added to allow
per-socket configuration:
TCP_DELACK_SEGS
TCP_DELACK_MIN
TCP_DELACK_MAX
In order to keep a multiply out of the hot path, the segs * mss
computation is recalculated and cached whenever segs or mss changes.
Signed-off-by: Daniel Baluta <dbaluta@ixiacom.com>
Signed-off-by: Ben Greear <greearb@candelatech.com>
---
Compile-tested only at this point.
Documentation/networking/ip-sysctl.txt | 13 +++++++++++++
include/linux/tcp.h | 3 +++
include/net/inet_connection_sock.h | 31 ++++++++++++++++++++++++++++---
include/net/tcp.h | 13 ++++++++++---
net/dccp/output.c | 5 +++--
net/dccp/timer.c | 2 +-
net/ipv4/inet_connection_sock.c | 13 +++++++++++++
net/ipv4/sysctl_net_ipv4.c | 21 +++++++++++++++++++++
net/ipv4/tcp.c | 23 +++++++++++++++++++----
net/ipv4/tcp_input.c | 24 ++++++++++++++----------
net/ipv4/tcp_output.c | 22 +++++++++++++++-------
net/ipv4/tcp_timer.c | 3 ++-
12 files changed, 142 insertions(+), 31 deletions(-)
diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt
index 6f896b9..89675d8 100644
--- a/Documentation/networking/ip-sysctl.txt
+++ b/Documentation/networking/ip-sysctl.txt
@@ -551,6 +551,19 @@ tcp_thin_dupack - BOOLEAN
Documentation/networking/tcp-thin.txt
Default: 0
+tcp_default_delack_segs: - INTEGER
+ Sets the default minimal number of full-sized TCP segments
+ received after which an ACK should be sent.
+ Default: 1 (as specified in RFC2582, S4.2)
+
+tcp_default_delack_min: - INTEGER
+ Sets the default minimum time (in miliseconds) to delay before sending an ACK.
+ Default: 40ms
+
+tcp_default_delack_max: - INTEGER
+ Sets the maximum time (in miliseconds) to delay before sending an ACK.
+ Default: 200ms
+
UDP variables:
udp_mem - vector of 3 INTEGERs: min, pressure, max
diff --git a/include/linux/tcp.h b/include/linux/tcp.h
index 5f359db..bc73d8c 100644
--- a/include/linux/tcp.h
+++ b/include/linux/tcp.h
@@ -110,6 +110,9 @@ enum {
#define TCP_REPAIR_QUEUE 20
#define TCP_QUEUE_SEQ 21
#define TCP_REPAIR_OPTIONS 22
+#define TCP_DELACK_SEGS 23 /* Number of segments per delayed ack */
+#define TCP_DELACK_MIN 24 /* minimum delayed ack, in miliseconds */
+#define TCP_DELACK_MAX 25 /* maximum delayed ack, in miliseconds */
struct tcp_repair_opt {
__u32 opt_code;
diff --git a/include/net/inet_connection_sock.h b/include/net/inet_connection_sock.h
index 7d83f90..2ada03c 100644
--- a/include/net/inet_connection_sock.h
+++ b/include/net/inet_connection_sock.h
@@ -113,7 +113,12 @@ struct inet_connection_sock {
unsigned long timeout; /* Currently scheduled timeout */
__u32 lrcvtime; /* timestamp of last received data packet */
__u16 last_seg_size; /* Size of last incoming segment */
- __u16 rcv_mss; /* MSS used for delayed ACK decisions */
+ __u16 _rcv_mss; /* MSS used for delayed ACK decisions */
+ __u32 calc_thresh; /* rcv_mss * tcp_delack_segs */
+ __u16 tcp_delack_min; /* Minimum ack delay in ms */
+ __u16 tcp_delack_max; /* Minimum ack delay in ms */
+ __u16 tcp_delack_segs;/* Delay # of segs before sending ack */
+ __u16 UNUSED_HOLE; /* Add new member(s) here */
} icsk_ack;
struct {
int enabled;
@@ -171,11 +176,31 @@ static inline int inet_csk_ack_scheduled(const struct sock *sk)
return inet_csk(sk)->icsk_ack.pending & ICSK_ACK_SCHED;
}
-static inline void inet_csk_delack_init(struct sock *sk)
+static inline __u16 inet_csk_get_rcv_mss(const struct sock *sk)
{
- memset(&inet_csk(sk)->icsk_ack, 0, sizeof(inet_csk(sk)->icsk_ack));
+ return inet_csk(sk)->icsk_ack._rcv_mss;
}
+static inline void inet_csk_recalc_delack_thresh(struct sock *sk)
+{
+ struct inet_connection_sock *icsk = inet_csk(sk);
+ icsk->icsk_ack.calc_thresh =
+ icsk->icsk_ack._rcv_mss * icsk->icsk_ack.tcp_delack_segs;
+}
+
+static inline void inet_csk_set_rcv_mss(struct sock *sk, __u16 rcv_mss)
+{
+ inet_csk(sk)->icsk_ack._rcv_mss = rcv_mss;
+ inet_csk_recalc_delack_thresh(sk);
+}
+
+static inline u32 inet_csk_delack_thresh(const struct sock *sk)
+{
+ return inet_csk(sk)->icsk_ack.calc_thresh;
+}
+
+extern void inet_csk_delack_init(struct sock *sk);
+
extern void inet_csk_delete_keepalive_timer(struct sock *sk);
extern void inet_csk_reset_keepalive_timer(struct sock *sk, unsigned long timeout);
diff --git a/include/net/tcp.h b/include/net/tcp.h
index e79aa48..d6cb650 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -113,14 +113,18 @@ extern void tcp_time_wait(struct sock *sk, int state, int timeo);
* TIME-WAIT timer.
*/
-#define TCP_DELACK_MAX ((unsigned)(HZ/5)) /* maximal time to delay before sending an ACK */
+/* default maximum time to delay before sending an ACK */
+#define TCP_DELACK_MAX_DEFAULT ((unsigned)(HZ/5))
+
#if HZ >= 100
-#define TCP_DELACK_MIN ((unsigned)(HZ/25)) /* minimal time to delay before sending an ACK */
+/* default minimum time to delay before sending an ACK */
+#define TCP_DELACK_MIN_DEFAULT ((unsigned)(HZ/25))
#define TCP_ATO_MIN ((unsigned)(HZ/25))
#else
-#define TCP_DELACK_MIN 4U
+#define TCP_DELACK_MIN_DEFAULT 4U
#define TCP_ATO_MIN 4U
#endif
+
#define TCP_RTO_MAX ((unsigned)(120*HZ))
#define TCP_RTO_MIN ((unsigned)(HZ/5))
#define TCP_TIMEOUT_INIT ((unsigned)(1*HZ)) /* RFC6298 2.1 initial RTO value */
@@ -253,6 +257,9 @@ extern int sysctl_tcp_cookie_size;
extern int sysctl_tcp_thin_linear_timeouts;
extern int sysctl_tcp_thin_dupack;
extern int sysctl_tcp_early_retrans;
+extern int sysctl_tcp_default_delack_segs;
+extern int sysctl_tcp_default_delack_min;
+extern int sysctl_tcp_default_delack_max;
extern atomic_long_t tcp_memory_allocated;
extern struct percpu_counter tcp_sockets_allocated;
diff --git a/net/dccp/output.c b/net/dccp/output.c
index 7873673..984a19a 100644
--- a/net/dccp/output.c
+++ b/net/dccp/output.c
@@ -574,10 +574,11 @@ void dccp_send_ack(struct sock *sk)
GFP_ATOMIC);
if (skb == NULL) {
+ struct inet_connection_sock *icsk = inet_csk(sk);
inet_csk_schedule_ack(sk);
- inet_csk(sk)->icsk_ack.ato = TCP_ATO_MIN;
+ icsk->icsk_ack.ato = TCP_ATO_MIN;
inet_csk_reset_xmit_timer(sk, ICSK_TIME_DACK,
- TCP_DELACK_MAX,
+ icsk->icsk_ack.tcp_delack_max,
DCCP_RTO_MAX);
return;
}
diff --git a/net/dccp/timer.c b/net/dccp/timer.c
index 16f0b22..2fc883c 100644
--- a/net/dccp/timer.c
+++ b/net/dccp/timer.c
@@ -203,7 +203,7 @@ static void dccp_delack_timer(unsigned long data)
icsk->icsk_ack.blocked = 1;
NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_DELAYEDACKLOCKED);
sk_reset_timer(sk, &icsk->icsk_delack_timer,
- jiffies + TCP_DELACK_MIN);
+ jiffies + icsk->icsk_ack.tcp_delack_min);
goto out;
}
diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
index f9ee741..4206b79 100644
--- a/net/ipv4/inet_connection_sock.c
+++ b/net/ipv4/inet_connection_sock.c
@@ -366,6 +366,19 @@ void inet_csk_reset_keepalive_timer(struct sock *sk, unsigned long len)
}
EXPORT_SYMBOL(inet_csk_reset_keepalive_timer);
+extern int sysctl_tcp_default_delack_min;
+extern int sysctl_tcp_default_delack_max;
+extern int sysctl_tcp_default_delack_segs;
+void inet_csk_delack_init(struct sock *sk)
+{
+ struct inet_connection_sock *icsk = inet_csk(sk);
+ memset(&icsk->icsk_ack, 0, sizeof(icsk->icsk_ack));
+ icsk->icsk_ack.tcp_delack_min = sysctl_tcp_default_delack_min;
+ icsk->icsk_ack.tcp_delack_max = sysctl_tcp_default_delack_max;
+ icsk->icsk_ack.tcp_delack_segs = sysctl_tcp_default_delack_segs;
+}
+EXPORT_SYMBOL(inet_csk_delack_init);
+
struct dst_entry *inet_csk_route_req(struct sock *sk,
struct flowi4 *fl4,
const struct request_sock *req)
diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c
index ef32956..e898a2e 100644
--- a/net/ipv4/sysctl_net_ipv4.c
+++ b/net/ipv4/sysctl_net_ipv4.c
@@ -687,6 +687,27 @@ static struct ctl_table ipv4_table[] = {
.extra2 = &two,
},
{
+ .procname = "tcp_default_delack_segs",
+ .data = &sysctl_tcp_default_delack_segs,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = proc_dointvec
+ },
+ {
+ .procname = "tcp_default_delack_min",
+ .data = &sysctl_tcp_default_delack_min,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = proc_dointvec_ms_jiffies
+ },
+ {
+ .procname = "tcp_default_delack_max",
+ .data = &sysctl_tcp_default_delack_max,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = proc_dointvec_ms_jiffies
+ },
+ {
.procname = "udp_mem",
.data = &sysctl_udp_mem,
.maxlen = sizeof(sysctl_udp_mem),
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index 3ba605f..55a4597 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -1305,8 +1305,9 @@ void tcp_cleanup_rbuf(struct sock *sk, int copied)
/* Delayed ACKs frequently hit locked sockets during bulk
* receive. */
if (icsk->icsk_ack.blocked ||
- /* Once-per-two-segments ACK was not sent by tcp_input.c */
- tp->rcv_nxt - tp->rcv_wup > icsk->icsk_ack.rcv_mss ||
+ /* More than once-per-tcp_delack_segs-segments ACK
+ * was not sent by tcp_input.c */
+ tp->rcv_nxt - tp->rcv_wup > inet_csk_delack_thresh(sk) ||
/*
* If this read emptied read buffer, we send ACK, if
* connection is not bidirectional, user drained
@@ -2436,7 +2437,7 @@ static int do_tcp_setsockopt(struct sock *sk, int level,
case TCP_NODELAY:
if (val) {
/* TCP_NODELAY is weaker than TCP_CORK, so that
- * this option on corked socket is remembered, but
+ * thiso ption on corked socket is remembered, but
* it is not activated until cork is cleared.
*
* However, when TCP_NODELAY is set we make
@@ -2627,6 +2628,20 @@ static int do_tcp_setsockopt(struct sock *sk, int level,
*/
icsk->icsk_user_timeout = msecs_to_jiffies(val);
break;
+
+ case TCP_DELACK_SEGS:
+ icsk->icsk_ack.tcp_delack_segs = val;
+ inet_csk_recalc_delack_thresh(sk);
+ break;
+
+ case TCP_DELACK_MIN:
+ icsk->icsk_ack.tcp_delack_min = val;
+ break;
+
+ case TCP_DELACK_MAX:
+ icsk->icsk_ack.tcp_delack_max = val;
+ break;
+
default:
err = -ENOPROTOOPT;
break;
@@ -2693,7 +2708,7 @@ void tcp_get_info(const struct sock *sk, struct tcp_info *info)
info->tcpi_rto = jiffies_to_usecs(icsk->icsk_rto);
info->tcpi_ato = jiffies_to_usecs(icsk->icsk_ack.ato);
info->tcpi_snd_mss = tp->mss_cache;
- info->tcpi_rcv_mss = icsk->icsk_ack.rcv_mss;
+ info->tcpi_rcv_mss = inet_csk_get_rcv_mss(sk);
if (sk->sk_state == TCP_LISTEN) {
info->tcpi_unacked = sk->sk_ack_backlog;
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index b224eb8..6c0f901 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -101,6 +101,8 @@ int sysctl_tcp_moderate_rcvbuf __read_mostly = 1;
int sysctl_tcp_abc __read_mostly;
int sysctl_tcp_early_retrans __read_mostly = 2;
+int sysctl_tcp_default_delack_segs __read_mostly = 1;
+
#define FLAG_DATA 0x01 /* Incoming frame contained data. */
#define FLAG_WIN_UPDATE 0x02 /* Incoming ACK was a window update. */
#define FLAG_DATA_ACKED 0x04 /* This ACK acknowledged new data. */
@@ -139,8 +141,8 @@ static void tcp_measure_rcv_mss(struct sock *sk, const struct sk_buff *skb)
* sends good full-sized frames.
*/
len = skb_shinfo(skb)->gso_size ? : skb->len;
- if (len >= icsk->icsk_ack.rcv_mss) {
- icsk->icsk_ack.rcv_mss = len;
+ if (len >= inet_csk_get_rcv_mss(sk)) {
+ inet_csk_set_rcv_mss(sk, len);
} else {
/* Otherwise, we make more careful check taking into account,
* that SACKs block is variable.
@@ -163,7 +165,7 @@ static void tcp_measure_rcv_mss(struct sock *sk, const struct sk_buff *skb)
len -= tcp_sk(sk)->tcp_header_len;
icsk->icsk_ack.last_seg_size = len;
if (len == lss) {
- icsk->icsk_ack.rcv_mss = len;
+ inet_csk_set_rcv_mss(sk, len);
return;
}
}
@@ -176,7 +178,8 @@ static void tcp_measure_rcv_mss(struct sock *sk, const struct sk_buff *skb)
static void tcp_incr_quickack(struct sock *sk)
{
struct inet_connection_sock *icsk = inet_csk(sk);
- unsigned int quickacks = tcp_sk(sk)->rcv_wnd / (2 * icsk->icsk_ack.rcv_mss);
+ unsigned int quickacks;
+ quickacks = tcp_sk(sk)->rcv_wnd / (2 * inet_csk_get_rcv_mss(sk));
if (quickacks == 0)
quickacks = 2;
@@ -310,7 +313,7 @@ static int __tcp_grow_window(const struct sock *sk, const struct sk_buff *skb)
while (tp->rcv_ssthresh <= window) {
if (truesize <= skb->len)
- return 2 * inet_csk(sk)->icsk_ack.rcv_mss;
+ return 2 * inet_csk_get_rcv_mss(sk);
truesize >>= 1;
window >>= 1;
@@ -440,7 +443,7 @@ void tcp_initialize_rcv_mss(struct sock *sk)
hint = min(hint, TCP_MSS_DEFAULT);
hint = max(hint, TCP_MIN_MSS);
- inet_csk(sk)->icsk_ack.rcv_mss = hint;
+ inet_csk_set_rcv_mss(sk, hint);
}
EXPORT_SYMBOL(tcp_initialize_rcv_mss);
@@ -510,7 +513,7 @@ static inline void tcp_rcv_rtt_measure_ts(struct sock *sk,
struct tcp_sock *tp = tcp_sk(sk);
if (tp->rx_opt.rcv_tsecr &&
(TCP_SKB_CB(skb)->end_seq -
- TCP_SKB_CB(skb)->seq >= inet_csk(sk)->icsk_ack.rcv_mss))
+ TCP_SKB_CB(skb)->seq >= inet_csk_get_rcv_mss(sk)))
tcp_rcv_rtt_update(tp, tcp_time_stamp - tp->rx_opt.rcv_tsecr, 0);
}
@@ -5206,8 +5209,8 @@ static void __tcp_ack_snd_check(struct sock *sk, int ofo_possible)
{
struct tcp_sock *tp = tcp_sk(sk);
- /* More than one full frame received... */
- if (((tp->rcv_nxt - tp->rcv_wup) > inet_csk(sk)->icsk_ack.rcv_mss &&
+ /* More than tcp_delack_segs full frame(s) received... */
+ if (((tp->rcv_nxt - tp->rcv_wup) > inet_csk_delack_thresh(sk) &&
/* ... and right edge of window advances far enough.
* (tcp_recvmsg() will send ACK otherwise). Or...
*/
@@ -5909,7 +5912,8 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb,
icsk->icsk_ack.lrcvtime = tcp_time_stamp;
tcp_enter_quickack_mode(sk);
inet_csk_reset_xmit_timer(sk, ICSK_TIME_DACK,
- TCP_DELACK_MAX, TCP_RTO_MAX);
+ icsk->icsk_ack.tcp_delack_max,
+ TCP_RTO_MAX);
discard:
__kfree_skb(skb);
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index 803cbfe..25f4e45 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -65,6 +65,11 @@ int sysctl_tcp_slow_start_after_idle __read_mostly = 1;
int sysctl_tcp_cookie_size __read_mostly = 0; /* TCP_COOKIE_MAX */
EXPORT_SYMBOL_GPL(sysctl_tcp_cookie_size);
+int sysctl_tcp_default_delack_min __read_mostly = TCP_DELACK_MIN_DEFAULT;
+EXPORT_SYMBOL(sysctl_tcp_default_delack_min);
+
+int sysctl_tcp_default_delack_max __read_mostly = TCP_DELACK_MAX_DEFAULT;
+EXPORT_SYMBOL(sysctl_tcp_default_delack_max);
/* Account for new data that has been sent to the network. */
static void tcp_event_new_data_sent(struct sock *sk, const struct sk_buff *skb)
@@ -1927,7 +1932,7 @@ u32 __tcp_select_window(struct sock *sk)
* but may be worse for the performance because of rcv_mss
* fluctuations. --SAW 1998/11/1
*/
- int mss = icsk->icsk_ack.rcv_mss;
+ int mss = inet_csk_get_rcv_mss(sk);
int free_space = tcp_space(sk);
int full_space = min_t(int, tp->window_clamp, tcp_full_space(sk));
int window;
@@ -2699,14 +2704,14 @@ void tcp_send_delayed_ack(struct sock *sk)
struct inet_connection_sock *icsk = inet_csk(sk);
int ato = icsk->icsk_ack.ato;
unsigned long timeout;
+ const struct tcp_sock *tp = tcp_sk(sk);
- if (ato > TCP_DELACK_MIN) {
- const struct tcp_sock *tp = tcp_sk(sk);
+ if (ato > icsk->icsk_ack.tcp_delack_min) {
int max_ato = HZ / 2;
if (icsk->icsk_ack.pingpong ||
(icsk->icsk_ack.pending & ICSK_ACK_PUSHED))
- max_ato = TCP_DELACK_MAX;
+ max_ato = icsk->icsk_ack.tcp_delack_max;
/* Slow path, intersegment interval is "high". */
@@ -2715,7 +2720,8 @@ void tcp_send_delayed_ack(struct sock *sk)
* directly.
*/
if (tp->srtt) {
- int rtt = max(tp->srtt >> 3, TCP_DELACK_MIN);
+ int rtt = max_t(unsigned, tp->srtt >> 3,
+ icsk->icsk_ack.tcp_delack_min);
if (rtt < max_ato)
max_ato = rtt;
@@ -2750,6 +2756,7 @@ void tcp_send_delayed_ack(struct sock *sk)
void tcp_send_ack(struct sock *sk)
{
struct sk_buff *buff;
+ struct inet_connection_sock *icsk = inet_csk(sk);
/* If we have been reset, we may not send again. */
if (sk->sk_state == TCP_CLOSE)
@@ -2762,9 +2769,10 @@ void tcp_send_ack(struct sock *sk)
buff = alloc_skb(MAX_TCP_HEADER, GFP_ATOMIC);
if (buff == NULL) {
inet_csk_schedule_ack(sk);
- inet_csk(sk)->icsk_ack.ato = TCP_ATO_MIN;
+ icsk->icsk_ack.ato = TCP_ATO_MIN;
inet_csk_reset_xmit_timer(sk, ICSK_TIME_DACK,
- TCP_DELACK_MAX, TCP_RTO_MAX);
+ icsk->icsk_ack.tcp_delack_max,
+ TCP_RTO_MAX);
return;
}
diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c
index e911e6c..4bd85fd 100644
--- a/net/ipv4/tcp_timer.c
+++ b/net/ipv4/tcp_timer.c
@@ -216,7 +216,8 @@ static void tcp_delack_timer(unsigned long data)
/* Try again later. */
icsk->icsk_ack.blocked = 1;
NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_DELAYEDACKLOCKED);
- sk_reset_timer(sk, &icsk->icsk_delack_timer, jiffies + TCP_DELACK_MIN);
+ sk_reset_timer(sk, &icsk->icsk_delack_timer,
+ jiffies + icsk->icsk_ack.tcp_delack_min);
goto out_unlock;
}
--
1.7.7.6
^ permalink raw reply related
* [PATCH net-next] ixgbe: simplify padding and length checks (v2)
From: Stephen Hemminger @ 2012-06-18 23:31 UTC (permalink / raw)
To: Alexander Duyck
Cc: Jeff Kirsher, Bruce Allan, Carolyn Wyborny, Don Skidmore,
Greg Rose, Peter P Waskiewicz Jr, David S. Miller, e1000-devel,
netdev
In-Reply-To: <4FDF9B37.3030804@intel.com>
The check for length <= 0 is bogus because length is unsigned, and network
stack never sends zero length packets (unless it is totally broken).
The check for really small packets can be optimized (using unlikely)
and calling skb_pad directly.
Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c 2012-06-18 10:53:09.130376800 -0700
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c 2012-06-18 15:20:44.364951004 -0700
@@ -6380,17 +6380,12 @@ static netdev_tx_t ixgbe_xmit_frame(stru
struct ixgbe_adapter *adapter = netdev_priv(netdev);
struct ixgbe_ring *tx_ring;
- if (skb->len <= 0) {
- dev_kfree_skb_any(skb);
- return NETDEV_TX_OK;
- }
-
/*
* The minimum packet size for olinfo paylen is 17 so pad the skb
* in order to meet this minimum size requirement.
*/
- if (skb->len < 17) {
- if (skb_padto(skb, 17))
+ if (unlikely(skb->len < 17)) {
+ if (skb_pad(skb, 17 - skb->len))
return NETDEV_TX_OK;
skb->len = 17;
}
^ permalink raw reply
* Re: [RFC] Introduce to batch variants of accept() and epoll_ctl() syscall
From: Andi Kleen @ 2012-06-18 23:27 UTC (permalink / raw)
To: Eric Dumazet
Cc: Li Yu, Changli Gao, Linux Netdev List, Linux Kernel Mailing List,
davidel
In-Reply-To: <1339750318.7491.70.camel@edumazet-glaptop>
Eric Dumazet <eric.dumazet@gmail.com> writes:
>
> I believe accept() is the problem here, because it contends with the
> softirq processing the tcp session handshake.
The MOSBENCH people some time ago did a per CPU accept queue. This is
probably overkill, but there are clearly some scaling problems here
with enough cores.
-Andi
--
ak@linux.intel.com -- Speaking for myself only
^ permalink raw reply
* [PATCH] ipv6: Move ipv6 proc file registration to end of init order
From: Thomas Graf @ 2012-06-18 22:08 UTC (permalink / raw)
To: davem; +Cc: netdev
/proc/net/ipv6_route reflects the contents of fib_table_hash. The proc
handler is installed in ip6_route_net_init() whereas fib_table_hash is
allocated in fib6_net_init() _after_ the proc handler has been installed.
This opens up a short time frame to access fib_table_hash with its pants
down.
Move the registration of the proc files to a later point in the init
order to avoid the race.
Tested :-)
Signed-off-by: Thomas Graf <tgraf@suug.ch>
---
net/ipv6/route.c | 41 +++++++++++++++++++++++++++++++----------
1 files changed, 31 insertions(+), 10 deletions(-)
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 999a982..becb048 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -2957,10 +2957,6 @@ static int __net_init ip6_route_net_init(struct net *net)
net->ipv6.sysctl.ip6_rt_mtu_expires = 10*60*HZ;
net->ipv6.sysctl.ip6_rt_min_advmss = IPV6_MIN_MTU - 20 - 40;
-#ifdef CONFIG_PROC_FS
- proc_net_fops_create(net, "ipv6_route", 0, &ipv6_route_proc_fops);
- proc_net_fops_create(net, "rt6_stats", S_IRUGO, &rt6_stats_seq_fops);
-#endif
net->ipv6.ip6_rt_gc_expire = 30*HZ;
ret = 0;
@@ -2981,10 +2977,6 @@ out_ip6_dst_ops:
static void __net_exit ip6_route_net_exit(struct net *net)
{
-#ifdef CONFIG_PROC_FS
- proc_net_remove(net, "ipv6_route");
- proc_net_remove(net, "rt6_stats");
-#endif
kfree(net->ipv6.ip6_null_entry);
#ifdef CONFIG_IPV6_MULTIPLE_TABLES
kfree(net->ipv6.ip6_prohibit_entry);
@@ -2993,11 +2985,33 @@ static void __net_exit ip6_route_net_exit(struct net *net)
dst_entries_destroy(&net->ipv6.ip6_dst_ops);
}
+static int __net_init ip6_route_net_init_late(struct net *net)
+{
+#ifdef CONFIG_PROC_FS
+ proc_net_fops_create(net, "ipv6_route", 0, &ipv6_route_proc_fops);
+ proc_net_fops_create(net, "rt6_stats", S_IRUGO, &rt6_stats_seq_fops);
+#endif
+ return 0;
+}
+
+static void __net_exit ip6_route_net_exit_late(struct net *net)
+{
+#ifdef CONFIG_PROC_FS
+ proc_net_remove(net, "ipv6_route");
+ proc_net_remove(net, "rt6_stats");
+#endif
+}
+
static struct pernet_operations ip6_route_net_ops = {
.init = ip6_route_net_init,
.exit = ip6_route_net_exit,
};
+static struct pernet_operations ip6_route_net_late_ops = {
+ .init = ip6_route_net_init_late,
+ .exit = ip6_route_net_exit_late,
+};
+
static struct notifier_block ip6_route_dev_notifier = {
.notifier_call = ip6_route_dev_notify,
.priority = 0,
@@ -3047,19 +3061,25 @@ int __init ip6_route_init(void)
if (ret)
goto xfrm6_init;
+ ret = register_pernet_subsys(&ip6_route_net_late_ops);
+ if (ret)
+ goto fib6_rules_init;
+
ret = -ENOBUFS;
if (__rtnl_register(PF_INET6, RTM_NEWROUTE, inet6_rtm_newroute, NULL, NULL) ||
__rtnl_register(PF_INET6, RTM_DELROUTE, inet6_rtm_delroute, NULL, NULL) ||
__rtnl_register(PF_INET6, RTM_GETROUTE, inet6_rtm_getroute, NULL, NULL))
- goto fib6_rules_init;
+ goto out_register_late_subsys;
ret = register_netdevice_notifier(&ip6_route_dev_notifier);
if (ret)
- goto fib6_rules_init;
+ goto out_register_late_subsys;
out:
return ret;
+out_register_late_subsys:
+ unregister_pernet_subsys(&ip6_route_net_late_ops);
fib6_rules_init:
fib6_rules_cleanup();
xfrm6_init:
@@ -3078,6 +3098,7 @@ out_kmem_cache:
void ip6_route_cleanup(void)
{
unregister_netdevice_notifier(&ip6_route_dev_notifier);
+ unregister_pernet_subsys(&ip6_route_net_late_ops);
fib6_rules_cleanup();
xfrm6_fini();
fib6_gc_cleanup();
--
1.7.7.6
^ permalink raw reply related
* Re: pull request: wireless 2012-06-18
From: David Miller @ 2012-06-18 21:48 UTC (permalink / raw)
To: linville; +Cc: linux-wireless, netdev, linux-kernel
In-Reply-To: <20120618195947.GA30590@tuxdriver.com>
From: "John W. Linville" <linville@tuxdriver.com>
Date: Mon, 18 Jun 2012 15:59:48 -0400
> This is a batch of fixes intended for 3.5...
>
> This includes pulls from the mac80211 and bluetooth trees -- soon
> I'll be completely irrelevant!
Don't forget to keep taking all the credit, that's the trick :)
> Please let me know if there are problems!
Pulled, thanks a lot John.
^ permalink raw reply
* Re: [PATCH] c_can_pci: generic module for C_CAN/D_CAN on PCI
From: Federico Vaga @ 2012-06-18 21:23 UTC (permalink / raw)
To: Marc Kleine-Budde
Cc: Wolfgang Grandegger, Giancarlo Asnaghi, Alan Cox, linux-can,
netdev, linux-kernel, Bhupesh SHARMA, AnilKumar Chimata,
Alessandro Rubini
In-Reply-To: <4FDF83A5.6060703@pengutronix.de>
> I get this warning:
>
> socketcan/linux/drivers/net/can/c_can/c_can_pci.c: In function 'c_can_pci_probe':
> socketcan/linux/drivers/net/can/c_can/c_can_pci.c:71: warning: 'priv' may be used uninitialized in this function
>
> What about:
>
> - pci_iounmap(pdev, priv->base);
> + pci_iounmap(pdev, addr);
I didn't get this warning, but I read again the code and the warning
is correct, so pci_iounmap(pdev, addr) is the right way.
--
Federico Vaga
^ permalink raw reply
* Re: [PATCH 1/2 net-next] ixgbe: use skb_padto
From: Alexander Duyck @ 2012-06-18 21:18 UTC (permalink / raw)
To: Stephen Hemminger
Cc: Jeff Kirsher, Bruce Allan, Carolyn Wyborny, Don Skidmore,
Greg Rose, Peter P Waskiewicz Jr, David S. Miller, e1000-devel,
netdev
In-Reply-To: <20120618105816.5fdd0b90@nehalam.linuxnetplumber.net>
On 06/18/2012 10:58 AM, Stephen Hemminger wrote:
> The code to pad packets here is the same effective code as
> the existing inline function skb_padto(). There is a minor
> performance gain since skb_padto() also uses unlikely().
>
> Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>
>
>
> --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c 2012-06-18 10:53:09.130376800 -0700
> +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c 2012-06-18 10:55:13.104540844 -0700
> @@ -6389,11 +6389,8 @@ static netdev_tx_t ixgbe_xmit_frame(stru
> * The minimum packet size for olinfo paylen is 17 so pad the skb
> * in order to meet this minimum size requirement.
> */
> - if (skb->len < 17) {
> - if (skb_padto(skb, 17))
> - return NETDEV_TX_OK;
> - skb->len = 17;
> - }
> + if (skb_padto(skb, 17))
> + return NETDEV_TX_OK;
>
> tx_ring = adapter->tx_ring[skb->queue_mapping];
> return ixgbe_xmit_frame_ring(skb, adapter, tx_ring);
I don't think this will work. We need to update the skb->len and last I
knew skb_padto doesn't do that.
Thanks,
Alex
^ permalink raw reply
* [PATCH] sctp: fix warning when compiling without IPv6
From: Daniel Halperin @ 2012-06-18 21:04 UTC (permalink / raw)
To: netdev
net/sctp/protocol.c: In function ‘sctp_addr_wq_timeout_handler’:
net/sctp/protocol.c:676: warning: label ‘free_next’ defined but not used
Signed-off-by: Daniel Halperin <dhalperi@cs.washington.edu>
---
net/sctp/protocol.c | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
index 5942d27..9c90811 100644
--- a/net/sctp/protocol.c
+++ b/net/sctp/protocol.c
@@ -673,7 +673,9 @@ void sctp_addr_wq_timeout_handler(unsigned long arg)
SCTP_DEBUG_PRINTK("sctp_addrwq_timo_handler: sctp_asconf_mgmt failed\n");
sctp_bh_unlock_sock(sk);
}
+#if IS_ENABLED(CONFIG_IPV6)
free_next:
+#endif
list_del(&addrw->list);
kfree(addrw);
}
--
1.7.0.4
^ permalink raw reply related
* драсссти ..!!)
From: Аллчик Гуслякова @ 2012-06-18 18:38 UTC (permalink / raw)
To: netdev
Привеет, Фома скинула адрессок имейл твой.)))
открой мою страничку www.demo1.restaurant.edge7tech.com/picture.php Марианчик Хорошилова записана я там.!)
если скучно и хош подружиться..!
^ permalink raw reply
* RE: divide by 0 error in igbvf_set_coalesce - ab50a2a
From: Williams, Mitch A @ 2012-06-18 20:45 UTC (permalink / raw)
To: David Ahern; +Cc: netdev@vger.kernel.org
In-Reply-To: <4FDF706D.7080509@cisco.com>
> -----Original Message-----
> From: David Ahern [mailto:daahern@cisco.com]
> Sent: Monday, June 18, 2012 11:16 AM
> To: Williams, Mitch A
> Cc: netdev@vger.kernel.org
> Subject: divide by 0 error in igbvf_set_coalesce - ab50a2a
>
> Mitch:
>
> I have a VM using a 82576 based VF. Running:
> $ ethtool -C eth2 rx-usecs 0
>
> generates the following trace on console:
>
> [ 894.683322] divide error: 0000 [#1] SMP [ 894.684020] CPU 1 [
Thanks for letting me know, David. I'll look into it and get a patch out soon. Shouldn't be that big of a deal to fix.
In the meantime, my advice to you is, "Don't do that."
-Mitch
> 894.684020] Modules linked in: sunrpc virtio_net igbvf virtio_blk
> virtio_pci virtio_ring virtio [ 894.684020] [ 894.684020] Pid: 7310,
> comm: ethtool Not tainted 3.5.0-rc1 #0 Bochs Bochs [ 894.684020] RIP:
> 0010:[<ffffffffa00259ec>] [<ffffffffa00259ec>]
> igbvf_set_coalesce+0x5b/0x8b [igbvf] [ 894.684020] RSP:
> 0018:ffff88003cd51c38 EFLAGS: 00010246 [ 894.684020] RAX:
> 000000003b9aca00 RBX: ffff88003aa42000 RCX:
> 0000000000000000
> [ 894.684020] RDX: 0000000000000000 RSI: ffff88003cd51c48 RDI:
> ffff88003aa42780
> [ 894.684020] RBP: ffff88003cd51c38 R08: 0000000000000000 R09:
> 0000000000000000
> [ 894.684020] R10: 0000000000000000 R11: ffff88003cd51ec8 R12:
> ffff88003cd51c48
> [ 894.684020] R13: 000000000000000f R14: 00000000ffffffff R15:
> 00000000fffffff2
> [ 894.684020] FS: 00007f8142ccb720(0000) GS:ffff88003fd00000(0000)
> knlGS:0000000000000000
> [ 894.684020] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [
> 894.684020] CR2: 000000000040466c CR3: 000000003c754000 CR4:
> 00000000000007e0
> [ 894.684020] DR0: 0000000000000000 DR1: 0000000000000000 DR2:
> 0000000000000000
> [ 894.684020] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7:
> 0000000000000400
> [ 894.684020] Process ethtool (pid: 7310, threadinfo ffff88003cd50000,
> task ffff88003b984470) [ 894.684020] Stack:
> [ 894.684020] ffff88003cd51cb8 ffffffff8132bcf5 000000000000000f
> 0000000000000000
> [ 894.684020] 0000000000000000 0000000000000000 0000000000000000
> 0000000000000000
> [ 894.684020] 0000000000000000 0000000000000000 0000000000000000
> 0000000000000000
> [ 894.684020] Call Trace:
> [ 894.684020] [<ffffffff8132bcf5>] ethtool_set_coalesce+0x54/0x5d [
> 894.684020] [<ffffffff8132d0c9>] dev_ethtool+0x5dc/0x175b [
> 894.684020] [<ffffffff81057921>] ? need_resched+0x1e/0x28 [
> 894.684020] [<ffffffff81057934>] ? should_resched+0x9/0x29 [
> 894.684020] [<ffffffff813be822>] ? _cond_resched+0xe/0x22 [
> 894.684020] [<ffffffff8132b227>] dev_ioctl+0x517/0x684 [ 894.684020]
> [<ffffffff810ec91f>] ? pmd_offset+0x14/0x3b [ 894.684020]
> [<ffffffff81315045>] sock_do_ioctl+0x3d/0x48 [ 894.684020]
> [<ffffffff8131545f>] sock_ioctl+0x1f8/0x207 [ 894.684020]
> [<ffffffff8111f6fa>] do_vfs_ioctl+0x475/0x4b6 [ 894.684020]
> [<ffffffff811f8e70>] ?
> inode_has_perm.clone.19.clone.27+0x33/0x35
> [ 894.684020] [<ffffffff811f9298>] ? file_has_perm+0x73/0x7e [
> 894.684020] [<ffffffff8110f6cf>] ? fd_install+0x57/0x60 [ 894.684020]
> [<ffffffff8111f791>] sys_ioctl+0x56/0x79 [ 894.684020]
> [<ffffffff813c5de9>] system_call_fastpath+0x16/0x1b [ 894.684020] Code:
> 83 f8 02 77 0f c7 87 0c 03 00 00 e8 01 00 00 8b 46
> 04 eb 19 8d 04 8d 00 00 00 00 31 d2 89 87 0c 03 00 00 c1 e1 0a b8 00 ca
> 9a 3b <f7> f1 89 87 08 03 00 00 8b 97 0c 03 00 00 48 8b 87 80 03 00 00 [
> 894.684020] RIP [<ffffffffa00259ec>] igbvf_set_coalesce+0x5b/0x8b
> [igbvf] [ 894.684020] RSP <ffff88003cd51c38> [ 894.779474] ---[ end
> trace 162bed6b66df758d ]---
>
>
> This commit introduced the problem:
>
> commit ab50a2a430693b0961dc7b7d9fe2a4bd77d11ea6
> Author: Mitch A Williams <mitch.a.williams@intel.com>
> Date: Sat Jan 14 08:10:50 2012 +0000
>
> igbvf: refactor Interrupt Throttle Rate code
>
> David
^ permalink raw reply
* NETDEV WATCHDOG: eth0 (forcedeth): transmit queue 0 timed out
From: Borislav Petkov @ 2012-06-18 20:43 UTC (permalink / raw)
To: netdev; +Cc: lkml
Just got the below on -rc3 after resuming. No network afterwards.
Rebooting fixed it.
[15473.272994] Restarting tasks ... done.
[15473.685535] forcedeth 0000:00:08.0: eth0: link up
[15483.926079] ------------[ cut here ]------------
[15483.926095] WARNING: at net/sched/sch_generic.c:255 dev_watchdog+0x16f/0x213()
[15483.926099] Hardware name:
[15483.926103] NETDEV WATCHDOG: eth0 (forcedeth): transmit queue 0 timed out
[15483.926160] Modules linked in: nls_iso8859_15 nls_cp437 tun cpufreq_powersave cpufreq_userspace ip6table_filter cpufreq_conservative ip6_tables cpufreq_stats iptable_filter ip_tables x_tables binfmt_misc fuse dm_crypt ipv6 vfat fat dm_mod powernow_k8 mperf kvm_amd kvm radeon drm_kms_helper ttm edac_core k10temp microcode cfbfillrect cfbimgblt cfbcopyarea
[15483.926166] Pid: 0, comm: swapper/0 Not tainted 3.5.0-rc3+ #3
[15483.926170] Call Trace:
[15483.926180] <IRQ> [<ffffffff8137b500>] ? dev_watchdog+0x72/0x213
[15483.926189] [<ffffffff8102b354>] warn_slowpath_common+0x83/0x9b
[15483.926195] [<ffffffff8102b40f>] warn_slowpath_fmt+0x46/0x48
[15483.926203] [<ffffffff8137b5fd>] dev_watchdog+0x16f/0x213
[15483.926211] [<ffffffff8103a4a9>] run_timer_softirq+0x37b/0x58f
[15483.926217] [<ffffffff8103a354>] ? run_timer_softirq+0x226/0x58f
[15483.926224] [<ffffffff8105e56e>] ? local_clock+0x2a/0x3b
[15483.926231] [<ffffffff81051842>] ? hrtimer_interrupt+0x118/0x1b4
[15483.926237] [<ffffffff8137b48e>] ? pfifo_fast_dequeue+0xc2/0xc2
[15483.926245] [<ffffffff81075638>] ? trace_hardirqs_off_caller+0x1f/0x10e
[15483.926256] [<ffffffff81032c26>] __do_softirq+0x17f/0x32d
[15483.926262] [<ffffffff810720c2>] ? clockevents_program_event+0xab/0xc7
[15483.926269] [<ffffffff813fe40c>] call_softirq+0x1c/0x30
[15483.926277] [<ffffffff810035bf>] do_softirq+0x3d/0x86
[15483.926282] [<ffffffff81033021>] irq_exit+0x53/0xbb
[15483.926290] [<ffffffff813fea2d>] smp_apic_timer_interrupt+0x8a/0x98
[15483.926296] [<ffffffff813fdbdc>] apic_timer_interrupt+0x6c/0x80
[15483.926304] <EOI> [<ffffffff810532b0>] ? __atomic_notifier_call_chain+0xdb/0x109
[15483.926313] [<ffffffff81009a40>] ? default_idle+0x113/0x24e
[15483.926319] [<ffffffff81009a3e>] ? default_idle+0x111/0x24e
[15483.926326] [<ffffffff81009d06>] amd_e400_idle+0xe5/0xe7
[15483.926332] [<ffffffff8100a4ae>] cpu_idle+0x6c/0xc8
[15483.926339] [<ffffffff813e044c>] rest_init+0x130/0x137
[15483.926345] [<ffffffff813e031c>] ? csum_partial_copy_generic+0x16c/0x16c
[15483.926353] [<ffffffff8186fa30>] start_kernel+0x2d2/0x2df
[15483.926359] [<ffffffff8186f567>] ? repair_env_string+0x56/0x56
[15483.926366] [<ffffffff8186f27a>] x86_64_start_reservations+0x7e/0x82
[15483.926373] [<ffffffff8186f36e>] x86_64_start_kernel+0xf0/0xf7
[15483.926377] ---[ end trace bd46b3883a3ab819 ]---
[15483.926385] forcedeth 0000:00:08.0: eth0: Got tx_timeout. irq status: 00000020
[15488.929896] forcedeth 0000:00:08.0: eth0: Got tx_timeout. irq status: 00000020
[15498.921512] forcedeth 0000:00:08.0: eth0: Got tx_timeout. irq status: 00000020
[15508.913144] forcedeth 0000:00:08.0: eth0: Got tx_timeout. irq status: 00000020
[15518.904786] forcedeth 0000:00:08.0: eth0: Got tx_timeout. irq status: 00000020
[15528.896409] forcedeth 0000:00:08.0: eth0: Got tx_timeout. irq status: 00000020
[15538.888039] forcedeth 0000:00:08.0: eth0: Got tx_timeout. irq status: 00000020
[15548.879678] forcedeth 0000:00:08.0: eth0: Got tx_timeout. irq status: 00000020
[15558.871309] forcedeth 0000:00:08.0: eth0: Got tx_timeout. irq status: 00000020
[15568.862929] forcedeth 0000:00:08.0: eth0: Got tx_timeout. irq status: 00000020
[15578.854570] forcedeth 0000:00:08.0: eth0: Got tx_timeout. irq status: 00000020
[15588.846189] forcedeth 0000:00:08.0: eth0: Got tx_timeout. irq status: 00000020
[15598.837828] forcedeth 0000:00:08.0: eth0: Got tx_timeout. irq status: 00000020
[15608.829441] forcedeth 0000:00:08.0: eth0: Got tx_timeout. irq status: 00000020
[15618.821083] forcedeth 0000:00:08.0: eth0: Got tx_timeout. irq status: 00000020
[15628.812722] forcedeth 0000:00:08.0: eth0: Got tx_timeout. irq status: 00000020
[15638.804350] forcedeth 0000:00:08.0: eth0: Got tx_timeout. irq status: 00000020
[15648.795974] forcedeth 0000:00:08.0: eth0: Got tx_timeout. irq status: 00000020
[15658.787605] forcedeth 0000:00:08.0: eth0: Got tx_timeout. irq status: 00000020
[15668.779222] forcedeth 0000:00:08.0: eth0: Got tx_timeout. irq status: 00000020
[15678.770871] forcedeth 0000:00:08.0: eth0: Got tx_timeout. irq status: 00000020
[15688.762501] forcedeth 0000:00:08.0: eth0: Got tx_timeout. irq status: 00000020
[15698.754136] forcedeth 0000:00:08.0: eth0: Got tx_timeout. irq status: 00000020
[15708.745764] forcedeth 0000:00:08.0: eth0: Got tx_timeout. irq status: 00000020
[15718.737391] forcedeth 0000:00:08.0: eth0: Got tx_timeout. irq status: 00000020
[15728.729019] forcedeth 0000:00:08.0: eth0: Got tx_timeout. irq status: 00000020
[15738.720654] forcedeth 0000:00:08.0: eth0: Got tx_timeout. irq status: 00000020
[15748.712280] forcedeth 0000:00:08.0: eth0: Got tx_timeout. irq status: 00000020
[15754.570157] forcedeth 0000:00:08.0: eth0: link down
[15756.972392] forcedeth 0000:00:08.0: eth0: link up
[15762.700565] forcedeth 0000:00:08.0: eth0: Got tx_timeout. irq status: 00000020
[15777.679993] forcedeth 0000:00:08.0: eth0: Got tx_timeout. irq status: 00000020
[15787.671642] forcedeth 0000:00:08.0: eth0: Got tx_timeout. irq status: 00000020
[15797.663285] forcedeth 0000:00:08.0: eth0: Got tx_timeout. irq status: 00000020
[15802.667092] forcedeth 0000:00:08.0: eth0: Got tx_timeout. irq status: 00000020
[15812.658701] forcedeth 0000:00:08.0: eth0: Got tx_timeout. irq status: 00000020
[15822.650341] forcedeth 0000:00:08.0: eth0: Got tx_timeout. irq status: 00000020
[15832.641980] forcedeth 0000:00:08.0: eth0: Got tx_timeout. irq status: 00000020
[15882.600137] forcedeth 0000:00:08.0: eth0: Got tx_timeout. irq status: 00000020
[15892.591755] forcedeth 0000:00:08.0: eth0: Got tx_timeout. irq status: 00000020
[15917.562840] forcedeth 0000:00:08.0: eth0: Got tx_timeout. irq status: 00000020
[15932.558276] forcedeth 0000:00:08.0: eth0: Got tx_timeout. irq status: 00000020
[15962.533183] forcedeth 0000:00:08.0: eth0: Got tx_timeout. irq status: 00000020
[15972.524806] forcedeth 0000:00:08.0: eth0: Got tx_timeout. irq status: 00000020
[15982.516438] forcedeth 0000:00:08.0: eth0: Got tx_timeout. irq status: 00000020
[15992.508077] forcedeth 0000:00:08.0: eth0: Got tx_timeout. irq status: 00000020
[16002.499699] forcedeth 0000:00:08.0: eth0: Got tx_timeout. irq status: 00000020
[16012.491327] forcedeth 0000:00:08.0: eth0: Got tx_timeout. irq status: 00000020
[16022.482969] forcedeth 0000:00:08.0: eth0: Got tx_timeout. irq status: 00000020
[16032.474585] forcedeth 0000:00:08.0: eth0: Got tx_timeout. irq status: 00000020
--
Regards/Gruss,
Boris.
^ permalink raw reply
* Re: [PATCH 2/2 net-next] ixgbe: remove xmit length check
From: Jeff Kirsher @ 2012-06-18 20:39 UTC (permalink / raw)
To: Stephen Hemminger; +Cc: e1000-devel, Bruce Allan, netdev, David S. Miller
In-Reply-To: <20120618115558.1ef26a48@nehalam.linuxnetplumber.net>
[-- Attachment #1.1: Type: text/plain, Size: 349 bytes --]
On Mon, 2012-06-18 at 11:55 -0700, Stephen Hemminger wrote:
> The check here is bogus. Since len is unsigned, it can never
> be negative. And it would be a bug in network stack to ever
> send a zero length packet to device.
>
> Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>
Thanks, I have added this patch as well to my queue.
[-- Attachment #1.2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 836 bytes --]
[-- Attachment #2: Type: text/plain, Size: 395 bytes --]
------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and
threat landscape has changed and how IT managers can respond. Discussions
will include endpoint security, mobile security and the latest in malware
threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
[-- Attachment #3: Type: text/plain, Size: 257 bytes --]
_______________________________________________
E1000-devel mailing list
E1000-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/e1000-devel
To learn more about Intel® Ethernet, visit http://communities.intel.com/community/wired
^ permalink raw reply
* [PATCH 19/19] batman-adv: only store changed gw_bandwidth values
From: Antonio Quartulli @ 2012-06-18 20:39 UTC (permalink / raw)
To: davem; +Cc: netdev, b.a.t.m.a.n, Marek Lindner, Sven Eckelmann,
Antonio Quartulli
In-Reply-To: <1340051963-14836-1-git-send-email-ordex@autistici.org>
From: Marek Lindner <lindner_marek@yahoo.de>
Signed-off-by: Marek Lindner <lindner_marek@yahoo.de>
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Signed-off-by: Antonio Quartulli <ordex@autistici.org>
---
net/batman-adv/gateway_common.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/net/batman-adv/gateway_common.c b/net/batman-adv/gateway_common.c
index ca57ac7..6e3b052 100644
--- a/net/batman-adv/gateway_common.c
+++ b/net/batman-adv/gateway_common.c
@@ -162,6 +162,9 @@ ssize_t gw_bandwidth_set(struct net_device *net_dev, char *buff, size_t count)
**/
gw_bandwidth_to_kbit((uint8_t)gw_bandwidth_tmp, &down, &up);
+ if (atomic_read(&bat_priv->gw_bandwidth) == gw_bandwidth_tmp)
+ return count;
+
gw_deselect(bat_priv);
bat_info(net_dev,
"Changing gateway bandwidth from: '%i' to: '%ld' (propagating: %d%s/%d%s)\n",
--
1.7.9.4
^ permalink raw reply related
* [PATCH 18/19] batman-adv: fix locking in hash_add()
From: Antonio Quartulli @ 2012-06-18 20:39 UTC (permalink / raw)
To: davem
Cc: netdev, b.a.t.m.a.n, Matthias Schiffer, Sven Eckelmann,
Antonio Quartulli
In-Reply-To: <1340051963-14836-1-git-send-email-ordex@autistici.org>
From: Matthias Schiffer <mschiffer@universe-factory.net>
To ensure an entry isn't added twice all comparisons have to be protected by the
hash line write spinlock. This doesn't really hurt as the case that it is tried
to add an element already present to the hash shouldn't occur very often, so in
most cases the lock would have have to be taken anyways.
Signed-off-by: Matthias Schiffer <mschiffer@universe-factory.net>
Acked-by: Sven Eckelmann <sven@narfation.org>
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Signed-off-by: Antonio Quartulli <ordex@autistici.org>
---
net/batman-adv/hash.h | 15 ++++++---------
1 file changed, 6 insertions(+), 9 deletions(-)
diff --git a/net/batman-adv/hash.h b/net/batman-adv/hash.h
index 93b3c71..3d67ce4 100644
--- a/net/batman-adv/hash.h
+++ b/net/batman-adv/hash.h
@@ -110,26 +110,23 @@ static inline int hash_add(struct hashtable_t *hash,
head = &hash->table[index];
list_lock = &hash->list_locks[index];
- rcu_read_lock();
- __hlist_for_each_rcu(node, head) {
+ spin_lock_bh(list_lock);
+
+ hlist_for_each(node, head) {
if (!compare(node, data))
continue;
ret = 1;
- goto err_unlock;
+ goto unlock;
}
- rcu_read_unlock();
/* no duplicate found in list, add new element */
- spin_lock_bh(list_lock);
hlist_add_head_rcu(data_node, head);
- spin_unlock_bh(list_lock);
ret = 0;
- goto out;
-err_unlock:
- rcu_read_unlock();
+unlock:
+ spin_unlock_bh(list_lock);
out:
return ret;
}
--
1.7.9.4
^ permalink raw reply related
* [PATCH 17/19] batman-adv: use DBG_ALL in log_level sysfs definition
From: Antonio Quartulli @ 2012-06-18 20:39 UTC (permalink / raw)
To: davem; +Cc: netdev, b.a.t.m.a.n, Antonio Quartulli, Sven Eckelmann
In-Reply-To: <1340051963-14836-1-git-send-email-ordex@autistici.org>
Each time a new log level is added the developer must change either the DBG_ALL
enum definition and the hard coded value in the bat_sysfs.c for the log_level
attribute max value. This is extremely error prone.
With this patch the code directly uses DBG_ALL in the sysfs definition
Signed-off-by: Antonio Quartulli <ordex@autistici.org>
Signed-off-by: Sven Eckelmann <sven@narfation.org>
---
net/batman-adv/bat_sysfs.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/batman-adv/bat_sysfs.c b/net/batman-adv/bat_sysfs.c
index 62f4f6c..dc1edbe 100644
--- a/net/batman-adv/bat_sysfs.c
+++ b/net/batman-adv/bat_sysfs.c
@@ -445,7 +445,7 @@ BAT_ATTR_SIF_UINT(gw_sel_class, S_IRUGO | S_IWUSR, 1, TQ_MAX_VALUE,
static BAT_ATTR(gw_bandwidth, S_IRUGO | S_IWUSR, show_gw_bwidth,
store_gw_bwidth);
#ifdef CONFIG_BATMAN_ADV_DEBUG
-BAT_ATTR_SIF_UINT(log_level, S_IRUGO | S_IWUSR, 0, 15, NULL);
+BAT_ATTR_SIF_UINT(log_level, S_IRUGO | S_IWUSR, 0, DBG_ALL, NULL);
#endif
static struct bat_attribute *mesh_attrs[] = {
--
1.7.9.4
^ permalink raw reply related
* [PATCH 16/19] batman-adv: turn tt commit code into routing protocol agnostic API
From: Antonio Quartulli @ 2012-06-18 20:39 UTC (permalink / raw)
To: davem; +Cc: netdev, b.a.t.m.a.n, Marek Lindner, Sven Eckelmann,
Antonio Quartulli
In-Reply-To: <1340051963-14836-1-git-send-email-ordex@autistici.org>
From: Marek Lindner <lindner_marek@yahoo.de>
Prior to this patch the translation table code made assumptions about how
the routing protocol works and where its buffers are stored (to directly
modify them).
Each protocol now calls the tt code with the relevant pointers, thereby
abstracting the code.
Signed-off-by: Marek Lindner <lindner_marek@yahoo.de>
Acked-by: Antonio Quartulli <ordex@autistici.org>
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Signed-off-by: Antonio Quartulli <ordex@autistici.org>
---
net/batman-adv/bat_iv_ogm.c | 14 ++--
net/batman-adv/send.c | 74 +--------------------
net/batman-adv/translation-table.c | 124 ++++++++++++++++++++++++++++++------
net/batman-adv/translation-table.h | 7 +-
net/batman-adv/types.h | 3 +-
5 files changed, 118 insertions(+), 104 deletions(-)
diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c
index ec3542c..6e0859f 100644
--- a/net/batman-adv/bat_iv_ogm.c
+++ b/net/batman-adv/bat_iv_ogm.c
@@ -559,22 +559,28 @@ static void bat_iv_ogm_forward(struct orig_node *orig_node,
if_incoming, 0, bat_iv_ogm_fwd_send_time());
}
-static void bat_iv_ogm_schedule(struct hard_iface *hard_iface,
- int tt_num_changes)
+static void bat_iv_ogm_schedule(struct hard_iface *hard_iface)
{
struct bat_priv *bat_priv = netdev_priv(hard_iface->soft_iface);
struct batman_ogm_packet *batman_ogm_packet;
struct hard_iface *primary_if;
- int vis_server;
+ int vis_server, tt_num_changes = 0;
vis_server = atomic_read(&bat_priv->vis_mode);
primary_if = primary_if_get_selected(bat_priv);
+ if (hard_iface == primary_if)
+ tt_num_changes = batadv_tt_append_diff(bat_priv,
+ &hard_iface->packet_buff,
+ &hard_iface->packet_len,
+ BATMAN_OGM_HLEN);
+
batman_ogm_packet = (struct batman_ogm_packet *)hard_iface->packet_buff;
/* change sequence number to network order */
batman_ogm_packet->seqno =
htonl((uint32_t)atomic_read(&hard_iface->seqno));
+ atomic_inc(&hard_iface->seqno);
batman_ogm_packet->ttvn = atomic_read(&bat_priv->ttvn);
batman_ogm_packet->tt_crc = htons(bat_priv->tt_crc);
@@ -593,8 +599,6 @@ static void bat_iv_ogm_schedule(struct hard_iface *hard_iface,
else
batman_ogm_packet->gw_flags = NO_FLAGS;
- atomic_inc(&hard_iface->seqno);
-
slide_own_bcast_window(hard_iface);
bat_iv_ogm_queue_add(bat_priv, hard_iface->packet_buff,
hard_iface->packet_len, hard_iface, 1,
diff --git a/net/batman-adv/send.c b/net/batman-adv/send.c
index f5ff364..79f8973 100644
--- a/net/batman-adv/send.c
+++ b/net/batman-adv/send.c
@@ -77,62 +77,9 @@ send_skb_err:
return NET_XMIT_DROP;
}
-static void realloc_packet_buffer(struct hard_iface *hard_iface,
- int new_len)
-{
- unsigned char *new_buff;
-
- new_buff = kmalloc(new_len, GFP_ATOMIC);
-
- /* keep old buffer if kmalloc should fail */
- if (new_buff) {
- memcpy(new_buff, hard_iface->packet_buff,
- BATMAN_OGM_HLEN);
-
- kfree(hard_iface->packet_buff);
- hard_iface->packet_buff = new_buff;
- hard_iface->packet_len = new_len;
- }
-}
-
-/* when calling this function (hard_iface == primary_if) has to be true */
-static int prepare_packet_buffer(struct bat_priv *bat_priv,
- struct hard_iface *hard_iface)
-{
- int new_len;
-
- new_len = BATMAN_OGM_HLEN +
- tt_len((uint8_t)atomic_read(&bat_priv->tt_local_changes));
-
- /* if we have too many changes for one packet don't send any
- * and wait for the tt table request which will be fragmented */
- if (new_len > hard_iface->soft_iface->mtu)
- new_len = BATMAN_OGM_HLEN;
-
- realloc_packet_buffer(hard_iface, new_len);
-
- bat_priv->tt_crc = tt_local_crc(bat_priv);
-
- /* reset the sending counter */
- atomic_set(&bat_priv->tt_ogm_append_cnt, TT_OGM_APPEND_MAX);
-
- return tt_changes_fill_buffer(bat_priv,
- hard_iface->packet_buff + BATMAN_OGM_HLEN,
- hard_iface->packet_len - BATMAN_OGM_HLEN);
-}
-
-static int reset_packet_buffer(struct bat_priv *bat_priv,
- struct hard_iface *hard_iface)
-{
- realloc_packet_buffer(hard_iface, BATMAN_OGM_HLEN);
- return 0;
-}
-
void schedule_bat_ogm(struct hard_iface *hard_iface)
{
struct bat_priv *bat_priv = netdev_priv(hard_iface->soft_iface);
- struct hard_iface *primary_if;
- int tt_num_changes = -1;
if ((hard_iface->if_status == IF_NOT_IN_USE) ||
(hard_iface->if_status == IF_TO_BE_REMOVED))
@@ -148,26 +95,7 @@ void schedule_bat_ogm(struct hard_iface *hard_iface)
if (hard_iface->if_status == IF_TO_BE_ACTIVATED)
hard_iface->if_status = IF_ACTIVE;
- primary_if = primary_if_get_selected(bat_priv);
-
- if (hard_iface == primary_if) {
- /* if at least one change happened */
- if (atomic_read(&bat_priv->tt_local_changes) > 0) {
- tt_commit_changes(bat_priv);
- tt_num_changes = prepare_packet_buffer(bat_priv,
- hard_iface);
- }
-
- /* if the changes have been sent often enough */
- if (!atomic_dec_not_zero(&bat_priv->tt_ogm_append_cnt))
- tt_num_changes = reset_packet_buffer(bat_priv,
- hard_iface);
- }
-
- if (primary_if)
- hardif_free_ref(primary_if);
-
- bat_priv->bat_algo_ops->bat_ogm_schedule(hard_iface, tt_num_changes);
+ bat_priv->bat_algo_ops->bat_ogm_schedule(hard_iface);
}
static void forw_packet_free(struct forw_packet *forw_packet)
diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c
index 88cfe2a..a1a51cc 100644
--- a/net/batman-adv/translation-table.c
+++ b/net/batman-adv/translation-table.c
@@ -275,14 +275,64 @@ out:
tt_global_entry_free_ref(tt_global_entry);
}
-int tt_changes_fill_buffer(struct bat_priv *bat_priv,
- unsigned char *buff, int buff_len)
+static void tt_realloc_packet_buff(unsigned char **packet_buff,
+ int *packet_buff_len, int min_packet_len,
+ int new_packet_len)
+{
+ unsigned char *new_buff;
+
+ new_buff = kmalloc(new_packet_len, GFP_ATOMIC);
+
+ /* keep old buffer if kmalloc should fail */
+ if (new_buff) {
+ memcpy(new_buff, *packet_buff, min_packet_len);
+ kfree(*packet_buff);
+ *packet_buff = new_buff;
+ *packet_buff_len = new_packet_len;
+ }
+}
+
+static void tt_prepare_packet_buff(struct bat_priv *bat_priv,
+ unsigned char **packet_buff,
+ int *packet_buff_len, int min_packet_len)
+{
+ struct hard_iface *primary_if;
+ int req_len;
+
+ primary_if = primary_if_get_selected(bat_priv);
+
+ req_len = min_packet_len;
+ req_len += tt_len(atomic_read(&bat_priv->tt_local_changes));
+
+ /* if we have too many changes for one packet don't send any
+ * and wait for the tt table request which will be fragmented
+ */
+ if ((!primary_if) || (req_len > primary_if->soft_iface->mtu))
+ req_len = min_packet_len;
+
+ tt_realloc_packet_buff(packet_buff, packet_buff_len,
+ min_packet_len, req_len);
+
+ if (primary_if)
+ hardif_free_ref(primary_if);
+}
+
+static int tt_changes_fill_buff(struct bat_priv *bat_priv,
+ unsigned char **packet_buff,
+ int *packet_buff_len, int min_packet_len)
{
- int count = 0, tot_changes = 0;
struct tt_change_node *entry, *safe;
+ int count = 0, tot_changes = 0, new_len;
+ unsigned char *tt_buff;
- if (buff_len > 0)
- tot_changes = buff_len / tt_len(1);
+ tt_prepare_packet_buff(bat_priv, packet_buff,
+ packet_buff_len, min_packet_len);
+
+ new_len = *packet_buff_len - min_packet_len;
+ tt_buff = *packet_buff + min_packet_len;
+
+ if (new_len > 0)
+ tot_changes = new_len / tt_len(1);
spin_lock_bh(&bat_priv->tt_changes_list_lock);
atomic_set(&bat_priv->tt_local_changes, 0);
@@ -290,7 +340,7 @@ int tt_changes_fill_buffer(struct bat_priv *bat_priv,
list_for_each_entry_safe(entry, safe, &bat_priv->tt_changes_list,
list) {
if (count < tot_changes) {
- memcpy(buff + tt_len(count),
+ memcpy(tt_buff + tt_len(count),
&entry->change, sizeof(struct tt_change));
count++;
}
@@ -304,17 +354,15 @@ int tt_changes_fill_buffer(struct bat_priv *bat_priv,
kfree(bat_priv->tt_buff);
bat_priv->tt_buff_len = 0;
bat_priv->tt_buff = NULL;
- /* We check whether this new OGM has no changes due to size
- * problems */
- if (buff_len > 0) {
- /**
- * if kmalloc() fails we will reply with the full table
+ /* check whether this new OGM has no changes due to size problems */
+ if (new_len > 0) {
+ /* if kmalloc() fails we will reply with the full table
* instead of providing the diff
*/
- bat_priv->tt_buff = kmalloc(buff_len, GFP_ATOMIC);
+ bat_priv->tt_buff = kmalloc(new_len, GFP_ATOMIC);
if (bat_priv->tt_buff) {
- memcpy(bat_priv->tt_buff, buff, buff_len);
- bat_priv->tt_buff_len = buff_len;
+ memcpy(bat_priv->tt_buff, tt_buff, new_len);
+ bat_priv->tt_buff_len = new_len;
}
}
spin_unlock_bh(&bat_priv->tt_buff_lock);
@@ -1105,7 +1153,7 @@ static uint16_t tt_global_crc(struct bat_priv *bat_priv,
}
/* Calculates the checksum of the local table */
-uint16_t tt_local_crc(struct bat_priv *bat_priv)
+static uint16_t batadv_tt_local_crc(struct bat_priv *bat_priv)
{
uint16_t total = 0, total_one;
struct hashtable_t *hash = bat_priv->tt_local_hash;
@@ -2025,20 +2073,56 @@ static void tt_local_purge_pending_clients(struct bat_priv *bat_priv)
}
-void tt_commit_changes(struct bat_priv *bat_priv)
+static int tt_commit_changes(struct bat_priv *bat_priv,
+ unsigned char **packet_buff, int *packet_buff_len,
+ int packet_min_len)
{
- uint16_t changed_num = tt_set_flags(bat_priv->tt_local_hash,
- TT_CLIENT_NEW, false);
- /* all the reset entries have now to be effectively counted as local
- * entries */
+ uint16_t changed_num = 0;
+
+ if (atomic_read(&bat_priv->tt_local_changes) < 1)
+ return -ENOENT;
+
+ changed_num = tt_set_flags(bat_priv->tt_local_hash,
+ TT_CLIENT_NEW, false);
+
+ /* all reset entries have to be counted as local entries */
atomic_add(changed_num, &bat_priv->num_local_tt);
tt_local_purge_pending_clients(bat_priv);
+ bat_priv->tt_crc = batadv_tt_local_crc(bat_priv);
/* Increment the TTVN only once per OGM interval */
atomic_inc(&bat_priv->ttvn);
bat_dbg(DBG_TT, bat_priv, "Local changes committed, updating to ttvn %u\n",
(uint8_t)atomic_read(&bat_priv->ttvn));
bat_priv->tt_poss_change = false;
+
+ /* reset the sending counter */
+ atomic_set(&bat_priv->tt_ogm_append_cnt, TT_OGM_APPEND_MAX);
+
+ return tt_changes_fill_buff(bat_priv, packet_buff,
+ packet_buff_len, packet_min_len);
+}
+
+/* when calling this function (hard_iface == primary_if) has to be true */
+int batadv_tt_append_diff(struct bat_priv *bat_priv,
+ unsigned char **packet_buff, int *packet_buff_len,
+ int packet_min_len)
+{
+ int tt_num_changes;
+
+ /* if at least one change happened */
+ tt_num_changes = tt_commit_changes(bat_priv, packet_buff,
+ packet_buff_len, packet_min_len);
+
+ /* if the changes have been sent often enough */
+ if ((tt_num_changes < 0) &&
+ (!atomic_dec_not_zero(&bat_priv->tt_ogm_append_cnt))) {
+ tt_realloc_packet_buff(packet_buff, packet_buff_len,
+ packet_min_len, packet_min_len);
+ tt_num_changes = 0;
+ }
+
+ return tt_num_changes;
}
bool is_ap_isolated(struct bat_priv *bat_priv, uint8_t *src, uint8_t *dst)
diff --git a/net/batman-adv/translation-table.h b/net/batman-adv/translation-table.h
index c43374d..d6ea30f 100644
--- a/net/batman-adv/translation-table.h
+++ b/net/batman-adv/translation-table.h
@@ -23,8 +23,6 @@
#define _NET_BATMAN_ADV_TRANSLATION_TABLE_H_
int tt_len(int changes_num);
-int tt_changes_fill_buffer(struct bat_priv *bat_priv,
- unsigned char *buff, int buff_len);
int tt_init(struct bat_priv *bat_priv);
void tt_local_add(struct net_device *soft_iface, const uint8_t *addr,
int ifindex);
@@ -41,18 +39,19 @@ void tt_global_del_orig(struct bat_priv *bat_priv,
struct orig_node *orig_node, const char *message);
struct orig_node *transtable_search(struct bat_priv *bat_priv,
const uint8_t *src, const uint8_t *addr);
-uint16_t tt_local_crc(struct bat_priv *bat_priv);
void tt_free(struct bat_priv *bat_priv);
bool send_tt_response(struct bat_priv *bat_priv,
struct tt_query_packet *tt_request);
bool is_my_client(struct bat_priv *bat_priv, const uint8_t *addr);
void handle_tt_response(struct bat_priv *bat_priv,
struct tt_query_packet *tt_response);
-void tt_commit_changes(struct bat_priv *bat_priv);
bool is_ap_isolated(struct bat_priv *bat_priv, uint8_t *src, uint8_t *dst);
void tt_update_orig(struct bat_priv *bat_priv, struct orig_node *orig_node,
const unsigned char *tt_buff, uint8_t tt_num_changes,
uint8_t ttvn, uint16_t tt_crc);
+int batadv_tt_append_diff(struct bat_priv *bat_priv,
+ unsigned char **packet_buff, int *packet_buff_len,
+ int packet_min_len);
bool tt_global_client_is_roaming(struct bat_priv *bat_priv, uint8_t *addr);
diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h
index 6b569de..bf71d52 100644
--- a/net/batman-adv/types.h
+++ b/net/batman-adv/types.h
@@ -405,8 +405,7 @@ struct bat_algo_ops {
/* called when primary interface is selected / changed */
void (*bat_primary_iface_set)(struct hard_iface *hard_iface);
/* prepare a new outgoing OGM for the send queue */
- void (*bat_ogm_schedule)(struct hard_iface *hard_iface,
- int tt_num_changes);
+ void (*bat_ogm_schedule)(struct hard_iface *hard_iface);
/* send scheduled OGM */
void (*bat_ogm_emit)(struct forw_packet *forw_packet);
};
--
1.7.9.4
^ permalink raw reply related
* [PATCH 15/19] batman-adv: fix visualization output without neighbors on the primary interface
From: Antonio Quartulli @ 2012-06-18 20:39 UTC (permalink / raw)
To: davem
Cc: netdev, b.a.t.m.a.n, Matthias Schiffer, Sven Eckelmann,
Antonio Quartulli
In-Reply-To: <1340051963-14836-1-git-send-email-ordex@autistici.org>
From: Matthias Schiffer <mschiffer@universe-factory.net>
The primary entry and the corresponding secondary entries are missing when there
are no neighbors on the primary interface. This also causes the TT entries to
miss and makes nodes with multiply secondary interface fall apart since there
is no way to see they are related without a primary entry.
Fix this by always emitting a primary entry.
Signed-off-by: Matthias Schiffer <mschiffer@universe-factory.net>
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Signed-off-by: Antonio Quartulli <ordex@autistici.org>
---
net/batman-adv/vis.c | 21 ++++++++++++++-------
1 file changed, 14 insertions(+), 7 deletions(-)
diff --git a/net/batman-adv/vis.c b/net/batman-adv/vis.c
index 411c0e1..01d5da5 100644
--- a/net/batman-adv/vis.c
+++ b/net/batman-adv/vis.c
@@ -207,7 +207,6 @@ int vis_seq_print_text(struct seq_file *seq, void *offset)
int vis_server = atomic_read(&bat_priv->vis_mode);
size_t buff_pos, buf_size;
char *buff;
- int compare;
primary_if = primary_if_get_selected(bat_priv);
if (!primary_if)
@@ -228,14 +227,18 @@ int vis_seq_print_text(struct seq_file *seq, void *offset)
entries = (struct vis_info_entry *)
((char *)packet + sizeof(*packet));
+ vis_data_insert_interface(packet->vis_orig,
+ &vis_if_list, true);
+
for (j = 0; j < packet->entries; j++) {
if (entries[j].quality == 0)
continue;
- compare =
- compare_eth(entries[j].src, packet->vis_orig);
+ if (compare_eth(entries[j].src,
+ packet->vis_orig))
+ continue;
vis_data_insert_interface(entries[j].src,
&vis_if_list,
- compare);
+ false);
}
hlist_for_each_entry(entry, pos, &vis_if_list, list) {
@@ -276,14 +279,18 @@ int vis_seq_print_text(struct seq_file *seq, void *offset)
entries = (struct vis_info_entry *)
((char *)packet + sizeof(*packet));
+ vis_data_insert_interface(packet->vis_orig,
+ &vis_if_list, true);
+
for (j = 0; j < packet->entries; j++) {
if (entries[j].quality == 0)
continue;
- compare =
- compare_eth(entries[j].src, packet->vis_orig);
+ if (compare_eth(entries[j].src,
+ packet->vis_orig))
+ continue;
vis_data_insert_interface(entries[j].src,
&vis_if_list,
- compare);
+ false);
}
hlist_for_each_entry(entry, pos, &vis_if_list, list) {
--
1.7.9.4
^ permalink raw reply related
* [PATCH 14/19] batman-adv: don't bother flipping ->tt_crc
From: Antonio Quartulli @ 2012-06-18 20:39 UTC (permalink / raw)
To: davem
Cc: netdev, b.a.t.m.a.n, Al Viro, Al Viro, Sven Eckelmann,
Antonio Quartulli
In-Reply-To: <1340051963-14836-1-git-send-email-ordex@autistici.org>
From: Al Viro <viro@ZenIV.linux.org.uk>
Keep it net-endian
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Signed-off-by: Antonio Quartulli <ordex@autistici.org>
---
net/batman-adv/bat_iv_ogm.c | 10 ++--------
net/batman-adv/packet.h | 2 +-
2 files changed, 3 insertions(+), 9 deletions(-)
diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c
index 896287e..ec3542c 100644
--- a/net/batman-adv/bat_iv_ogm.c
+++ b/net/batman-adv/bat_iv_ogm.c
@@ -547,8 +547,6 @@ static void bat_iv_ogm_forward(struct orig_node *orig_node,
"Forwarding packet: tq: %i, ttl: %i\n",
batman_ogm_packet->tq, batman_ogm_packet->header.ttl);
- batman_ogm_packet->tt_crc = htons(batman_ogm_packet->tt_crc);
-
/* switch of primaries first hop flag when forwarding */
batman_ogm_packet->flags &= ~PRIMARIES_FIRST_HOP;
if (is_single_hop_neigh)
@@ -724,7 +722,7 @@ update_tt:
tt_update_orig(bat_priv, orig_node, tt_buff,
batman_ogm_packet->tt_num_changes,
batman_ogm_packet->ttvn,
- batman_ogm_packet->tt_crc);
+ ntohs(batman_ogm_packet->tt_crc));
if (orig_node->gw_flags != batman_ogm_packet->gw_flags)
gw_node_update(bat_priv, orig_node,
@@ -972,7 +970,7 @@ static void bat_iv_ogm_process(const struct ethhdr *ethhdr,
ethhdr->h_source, if_incoming->net_dev->name,
if_incoming->net_dev->dev_addr, batman_ogm_packet->orig,
batman_ogm_packet->prev_sender, ntohl(batman_ogm_packet->seqno),
- batman_ogm_packet->ttvn, batman_ogm_packet->tt_crc,
+ batman_ogm_packet->ttvn, ntohs(batman_ogm_packet->tt_crc),
batman_ogm_packet->tt_num_changes, batman_ogm_packet->tq,
batman_ogm_packet->header.ttl,
batman_ogm_packet->header.version, has_directlink_flag);
@@ -1219,10 +1217,6 @@ static int bat_iv_ogm_receive(struct sk_buff *skb,
/* unpack the aggregated packets and process them one by one */
do {
- /* network to host order for our 32bit seqno and the
- orig_interval */
- batman_ogm_packet->tt_crc = ntohs(batman_ogm_packet->tt_crc);
-
tt_buff = packet_buff + buff_pos + BATMAN_OGM_HLEN;
bat_iv_ogm_process(ethhdr, batman_ogm_packet,
diff --git a/net/batman-adv/packet.h b/net/batman-adv/packet.h
index 372fc88..033d994 100644
--- a/net/batman-adv/packet.h
+++ b/net/batman-adv/packet.h
@@ -124,7 +124,7 @@ struct batman_ogm_packet {
uint8_t tq;
uint8_t tt_num_changes;
uint8_t ttvn; /* translation table version number */
- uint16_t tt_crc;
+ __be16 tt_crc;
} __packed;
#define BATMAN_OGM_HLEN sizeof(struct batman_ogm_packet)
--
1.7.9.4
^ permalink raw reply related
* [PATCH 13/19] batman-adv: don't bother flipping ->tt_data
From: Antonio Quartulli @ 2012-06-18 20:39 UTC (permalink / raw)
To: davem
Cc: netdev, b.a.t.m.a.n, Al Viro, Al Viro, Marek Lindner,
Sven Eckelmann, Antonio Quartulli
In-Reply-To: <1340051963-14836-1-git-send-email-ordex@autistici.org>
From: Al Viro <viro@ZenIV.linux.org.uk>
just keep it net-endian all along
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
[lindner_marek@yahoo.de: fix checkpatch warnings]
Signed-off-by: Marek Lindner <lindner_marek@yahoo.de>
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Signed-off-by: Antonio Quartulli <ordex@autistici.org>
---
net/batman-adv/packet.h | 2 +-
net/batman-adv/routing.c | 10 +++-------
net/batman-adv/translation-table.c | 10 ++++++----
3 files changed, 10 insertions(+), 12 deletions(-)
diff --git a/net/batman-adv/packet.h b/net/batman-adv/packet.h
index 5bf567b..372fc88 100644
--- a/net/batman-adv/packet.h
+++ b/net/batman-adv/packet.h
@@ -206,7 +206,7 @@ struct tt_query_packet {
* if TT_REQUEST: crc associated with the
* ttvn
* if TT_RESPONSE: table_size */
- uint16_t tt_data;
+ __be16 tt_data;
} __packed;
struct roam_adv_packet {
diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c
index 369604c..9cfd23c 100644
--- a/net/batman-adv/routing.c
+++ b/net/batman-adv/routing.c
@@ -573,7 +573,7 @@ int recv_tt_query(struct sk_buff *skb, struct hard_iface *recv_if)
{
struct bat_priv *bat_priv = netdev_priv(recv_if->soft_iface);
struct tt_query_packet *tt_query;
- uint16_t tt_len;
+ uint16_t tt_size;
struct ethhdr *ethhdr;
/* drop packet if it has not necessary minimum size */
@@ -596,8 +596,6 @@ int recv_tt_query(struct sk_buff *skb, struct hard_iface *recv_if)
tt_query = (struct tt_query_packet *)skb->data;
- tt_query->tt_data = ntohs(tt_query->tt_data);
-
switch (tt_query->flags & TT_QUERY_TYPE_MASK) {
case TT_REQUEST:
batadv_inc_counter(bat_priv, BAT_CNT_TT_REQUEST_RX);
@@ -609,7 +607,6 @@ int recv_tt_query(struct sk_buff *skb, struct hard_iface *recv_if)
"Routing TT_REQUEST to %pM [%c]\n",
tt_query->dst,
(tt_query->flags & TT_FULL_TABLE ? 'F' : '.'));
- tt_query->tt_data = htons(tt_query->tt_data);
return route_unicast_packet(skb, recv_if);
}
break;
@@ -624,11 +621,11 @@ int recv_tt_query(struct sk_buff *skb, struct hard_iface *recv_if)
/* skb_linearize() possibly changed skb->data */
tt_query = (struct tt_query_packet *)skb->data;
- tt_len = tt_query->tt_data * sizeof(struct tt_change);
+ tt_size = tt_len(ntohs(tt_query->tt_data));
/* Ensure we have all the claimed data */
if (unlikely(skb_headlen(skb) <
- sizeof(struct tt_query_packet) + tt_len))
+ sizeof(struct tt_query_packet) + tt_size))
goto out;
handle_tt_response(bat_priv, tt_query);
@@ -637,7 +634,6 @@ int recv_tt_query(struct sk_buff *skb, struct hard_iface *recv_if)
"Routing TT_RESPONSE to %pM [%c]\n",
tt_query->dst,
(tt_query->flags & TT_FULL_TABLE ? 'F' : '.'));
- tt_query->tt_data = htons(tt_query->tt_data);
return route_unicast_packet(skb, recv_if);
}
break;
diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c
index 24e691d..88cfe2a 100644
--- a/net/batman-adv/translation-table.c
+++ b/net/batman-adv/translation-table.c
@@ -1418,7 +1418,7 @@ static bool send_other_tt_response(struct bat_priv *bat_priv,
/* I don't have the requested data */
if (orig_ttvn != req_ttvn ||
- tt_request->tt_data != req_dst_orig_node->tt_crc)
+ tt_request->tt_data != htons(req_dst_orig_node->tt_crc))
goto out;
/* If the full table has been explicitly requested */
@@ -1678,7 +1678,7 @@ static void tt_fill_gtable(struct bat_priv *bat_priv,
_tt_update_changes(bat_priv, orig_node,
(struct tt_change *)(tt_response + 1),
- tt_response->tt_data, tt_response->ttvn);
+ ntohs(tt_response->tt_data), tt_response->ttvn);
spin_lock_bh(&orig_node->tt_buff_lock);
kfree(orig_node->tt_buff);
@@ -1733,7 +1733,8 @@ void handle_tt_response(struct bat_priv *bat_priv,
bat_dbg(DBG_TT, bat_priv,
"Received TT_RESPONSE from %pM for ttvn %d t_size: %d [%c]\n",
- tt_response->src, tt_response->ttvn, tt_response->tt_data,
+ tt_response->src, tt_response->ttvn,
+ ntohs(tt_response->tt_data),
(tt_response->flags & TT_FULL_TABLE ? 'F' : '.'));
/* we should have never asked a backbone gw */
@@ -1747,7 +1748,8 @@ void handle_tt_response(struct bat_priv *bat_priv,
if (tt_response->flags & TT_FULL_TABLE)
tt_fill_gtable(bat_priv, tt_response);
else
- tt_update_changes(bat_priv, orig_node, tt_response->tt_data,
+ tt_update_changes(bat_priv, orig_node,
+ ntohs(tt_response->tt_data),
tt_response->ttvn,
(struct tt_change *)(tt_response + 1));
--
1.7.9.4
^ permalink raw reply related
* [PATCH 12/19] batman-adv: Return error codes instead of -1 on failures
From: Antonio Quartulli @ 2012-06-18 20:39 UTC (permalink / raw)
To: davem; +Cc: netdev, b.a.t.m.a.n, Sven Eckelmann, Antonio Quartulli
In-Reply-To: <1340051963-14836-1-git-send-email-ordex@autistici.org>
From: Sven Eckelmann <sven@narfation.org>
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Signed-off-by: Antonio Quartulli <ordex@autistici.org>
---
net/batman-adv/bat_debugfs.c | 11 +++++++----
net/batman-adv/bat_iv_ogm.c | 2 +-
net/batman-adv/bat_sysfs.c | 2 +-
net/batman-adv/bridge_loop_avoidance.c | 6 +++---
net/batman-adv/hard-interface.c | 4 +---
net/batman-adv/icmp_socket.c | 4 ++--
net/batman-adv/main.c | 27 ++++++++++++++++-----------
net/batman-adv/originator.c | 18 +++++++++---------
net/batman-adv/translation-table.c | 24 ++++++++++++++----------
net/batman-adv/vis.c | 8 ++++----
10 files changed, 58 insertions(+), 48 deletions(-)
diff --git a/net/batman-adv/bat_debugfs.c b/net/batman-adv/bat_debugfs.c
index 3b588f8..db8273c 100644
--- a/net/batman-adv/bat_debugfs.c
+++ b/net/batman-adv/bat_debugfs.c
@@ -195,13 +195,13 @@ static int debug_log_setup(struct bat_priv *bat_priv)
d = debugfs_create_file("log", S_IFREG | S_IRUSR,
bat_priv->debug_dir, bat_priv, &log_fops);
- if (d)
+ if (!d)
goto err;
return 0;
err:
- return 1;
+ return -ENOMEM;
}
static void debug_log_cleanup(struct bat_priv *bat_priv)
@@ -348,8 +348,11 @@ int debugfs_add_meshif(struct net_device *dev)
if (!bat_priv->debug_dir)
goto out;
- bat_socket_setup(bat_priv);
- debug_log_setup(bat_priv);
+ if (bat_socket_setup(bat_priv) < 0)
+ goto rem_attr;
+
+ if (debug_log_setup(bat_priv) < 0)
+ goto rem_attr;
for (bat_debug = mesh_debuginfos; *bat_debug; ++bat_debug) {
file = debugfs_create_file(((*bat_debug)->attr).name,
diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c
index 56b6d78..896287e 100644
--- a/net/batman-adv/bat_iv_ogm.c
+++ b/net/batman-adv/bat_iv_ogm.c
@@ -60,7 +60,7 @@ static int bat_iv_ogm_iface_enable(struct hard_iface *hard_iface)
{
struct batman_ogm_packet *batman_ogm_packet;
uint32_t random_seqno;
- int res = -1;
+ int res = -ENOMEM;
/* randomize initial seqno to avoid collision */
get_random_bytes(&random_seqno, sizeof(random_seqno));
diff --git a/net/batman-adv/bat_sysfs.c b/net/batman-adv/bat_sysfs.c
index 5bc7b66..62f4f6c 100644
--- a/net/batman-adv/bat_sysfs.c
+++ b/net/batman-adv/bat_sysfs.c
@@ -680,7 +680,7 @@ void sysfs_del_hardif(struct kobject **hardif_obj)
int throw_uevent(struct bat_priv *bat_priv, enum uev_type type,
enum uev_action action, const char *data)
{
- int ret = -1;
+ int ret = -ENOMEM;
struct hard_iface *primary_if = NULL;
struct kobject *bat_kobj;
char *uevent_env[4] = { NULL, NULL, NULL, NULL };
diff --git a/net/batman-adv/bridge_loop_avoidance.c b/net/batman-adv/bridge_loop_avoidance.c
index 0355c48..314e37b 100644
--- a/net/batman-adv/bridge_loop_avoidance.c
+++ b/net/batman-adv/bridge_loop_avoidance.c
@@ -1164,13 +1164,13 @@ int bla_init(struct bat_priv *bat_priv)
bat_priv->bcast_duplist_curr = 0;
if (bat_priv->claim_hash)
- return 1;
+ return 0;
bat_priv->claim_hash = hash_new(128);
bat_priv->backbone_hash = hash_new(32);
if (!bat_priv->claim_hash || !bat_priv->backbone_hash)
- return -1;
+ return -ENOMEM;
batadv_hash_set_lock_class(bat_priv->claim_hash,
&claim_hash_lock_class_key);
@@ -1180,7 +1180,7 @@ int bla_init(struct bat_priv *bat_priv)
bat_dbg(DBG_BLA, bat_priv, "bla hashes initialized\n");
bla_start_timer(bat_priv);
- return 1;
+ return 0;
}
/**
diff --git a/net/batman-adv/hard-interface.c b/net/batman-adv/hard-interface.c
index dc334fa..ce78c6d 100644
--- a/net/batman-adv/hard-interface.c
+++ b/net/batman-adv/hard-interface.c
@@ -306,10 +306,8 @@ int hardif_enable_interface(struct hard_iface *hard_iface,
bat_priv = netdev_priv(hard_iface->soft_iface);
ret = bat_priv->bat_algo_ops->bat_iface_enable(hard_iface);
- if (ret < 0) {
- ret = -ENOMEM;
+ if (ret < 0)
goto err_dev;
- }
hard_iface->if_num = bat_priv->num_ifaces;
bat_priv->num_ifaces++;
diff --git a/net/batman-adv/icmp_socket.c b/net/batman-adv/icmp_socket.c
index 2e98a57..d27db81 100644
--- a/net/batman-adv/icmp_socket.c
+++ b/net/batman-adv/icmp_socket.c
@@ -285,13 +285,13 @@ int bat_socket_setup(struct bat_priv *bat_priv)
d = debugfs_create_file(ICMP_SOCKET, S_IFREG | S_IWUSR | S_IRUSR,
bat_priv->debug_dir, bat_priv, &fops);
- if (d)
+ if (!d)
goto err;
return 0;
err:
- return 1;
+ return -ENOMEM;
}
static void bat_socket_add_packet(struct socket_client *socket_client,
diff --git a/net/batman-adv/main.c b/net/batman-adv/main.c
index 8610b5c..46ba302 100644
--- a/net/batman-adv/main.c
+++ b/net/batman-adv/main.c
@@ -92,6 +92,7 @@ static void __exit batman_exit(void)
int mesh_init(struct net_device *soft_iface)
{
struct bat_priv *bat_priv = netdev_priv(soft_iface);
+ int ret;
spin_lock_init(&bat_priv->forw_bat_list_lock);
spin_lock_init(&bat_priv->forw_bcast_list_lock);
@@ -110,30 +111,32 @@ int mesh_init(struct net_device *soft_iface)
INIT_LIST_HEAD(&bat_priv->tt_req_list);
INIT_LIST_HEAD(&bat_priv->tt_roam_list);
- if (originator_init(bat_priv) < 1)
+ ret = originator_init(bat_priv);
+ if (ret < 0)
goto err;
- if (tt_init(bat_priv) < 1)
+ ret = tt_init(bat_priv);
+ if (ret < 0)
goto err;
tt_local_add(soft_iface, soft_iface->dev_addr, NULL_IFINDEX);
- if (vis_init(bat_priv) < 1)
+ ret = vis_init(bat_priv);
+ if (ret < 0)
goto err;
- if (bla_init(bat_priv) < 1)
+ ret = bla_init(bat_priv);
+ if (ret < 0)
goto err;
atomic_set(&bat_priv->gw_reselect, 0);
atomic_set(&bat_priv->mesh_state, MESH_ACTIVE);
- goto end;
+
+ return 0;
err:
mesh_free(soft_iface);
- return -1;
-
-end:
- return 0;
+ return ret;
}
void mesh_free(struct net_device *soft_iface)
@@ -319,12 +322,13 @@ static struct bat_algo_ops *bat_algo_get(char *name)
int bat_algo_register(struct bat_algo_ops *bat_algo_ops)
{
struct bat_algo_ops *bat_algo_ops_tmp;
- int ret = -1;
+ int ret;
bat_algo_ops_tmp = bat_algo_get(bat_algo_ops->name);
if (bat_algo_ops_tmp) {
pr_info("Trying to register already registered routing algorithm: %s\n",
bat_algo_ops->name);
+ ret = -EEXIST;
goto out;
}
@@ -337,6 +341,7 @@ int bat_algo_register(struct bat_algo_ops *bat_algo_ops)
!bat_algo_ops->bat_ogm_emit) {
pr_info("Routing algo '%s' does not implement required ops\n",
bat_algo_ops->name);
+ ret = -EINVAL;
goto out;
}
@@ -351,7 +356,7 @@ out:
int bat_algo_select(struct bat_priv *bat_priv, char *name)
{
struct bat_algo_ops *bat_algo_ops;
- int ret = -1;
+ int ret = -EINVAL;
bat_algo_ops = bat_algo_get(name);
if (!bat_algo_ops)
diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c
index 41147942..cf83c54 100644
--- a/net/batman-adv/originator.c
+++ b/net/batman-adv/originator.c
@@ -50,7 +50,7 @@ static int compare_orig(const struct hlist_node *node, const void *data2)
int originator_init(struct bat_priv *bat_priv)
{
if (bat_priv->orig_hash)
- return 1;
+ return 0;
bat_priv->orig_hash = hash_new(1024);
@@ -58,10 +58,10 @@ int originator_init(struct bat_priv *bat_priv)
goto err;
start_purge_timer(bat_priv);
- return 1;
+ return 0;
err:
- return 0;
+ return -ENOMEM;
}
void neigh_node_free_ref(struct neigh_node *neigh_node)
@@ -488,7 +488,7 @@ static int orig_node_add_if(struct orig_node *orig_node, int max_if_num)
data_ptr = kmalloc(max_if_num * sizeof(unsigned long) * NUM_WORDS,
GFP_ATOMIC);
if (!data_ptr)
- return -1;
+ return -ENOMEM;
memcpy(data_ptr, orig_node->bcast_own,
(max_if_num - 1) * sizeof(unsigned long) * NUM_WORDS);
@@ -497,7 +497,7 @@ static int orig_node_add_if(struct orig_node *orig_node, int max_if_num)
data_ptr = kmalloc(max_if_num * sizeof(uint8_t), GFP_ATOMIC);
if (!data_ptr)
- return -1;
+ return -ENOMEM;
memcpy(data_ptr, orig_node->bcast_own_sum,
(max_if_num - 1) * sizeof(uint8_t));
@@ -528,7 +528,7 @@ int orig_hash_add_if(struct hard_iface *hard_iface, int max_if_num)
ret = orig_node_add_if(orig_node, max_if_num);
spin_unlock_bh(&orig_node->ogm_cnt_lock);
- if (ret == -1)
+ if (ret == -ENOMEM)
goto err;
}
rcu_read_unlock();
@@ -554,7 +554,7 @@ static int orig_node_del_if(struct orig_node *orig_node,
chunk_size = sizeof(unsigned long) * NUM_WORDS;
data_ptr = kmalloc(max_if_num * chunk_size, GFP_ATOMIC);
if (!data_ptr)
- return -1;
+ return -ENOMEM;
/* copy first part */
memcpy(data_ptr, orig_node->bcast_own, del_if_num * chunk_size);
@@ -573,7 +573,7 @@ free_bcast_own:
data_ptr = kmalloc(max_if_num * sizeof(uint8_t), GFP_ATOMIC);
if (!data_ptr)
- return -1;
+ return -ENOMEM;
memcpy(data_ptr, orig_node->bcast_own_sum,
del_if_num * sizeof(uint8_t));
@@ -612,7 +612,7 @@ int orig_hash_del_if(struct hard_iface *hard_iface, int max_if_num)
hard_iface->if_num);
spin_unlock_bh(&orig_node->ogm_cnt_lock);
- if (ret == -1)
+ if (ret == -ENOMEM)
goto err;
}
rcu_read_unlock();
diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c
index f9675b7..24e691d 100644
--- a/net/batman-adv/translation-table.c
+++ b/net/batman-adv/translation-table.c
@@ -181,14 +181,14 @@ int tt_len(int changes_num)
static int tt_local_init(struct bat_priv *bat_priv)
{
if (bat_priv->tt_local_hash)
- return 1;
+ return 0;
bat_priv->tt_local_hash = hash_new(1024);
if (!bat_priv->tt_local_hash)
- return 0;
+ return -ENOMEM;
- return 1;
+ return 0;
}
void tt_local_add(struct net_device *soft_iface, const uint8_t *addr,
@@ -491,14 +491,14 @@ static void tt_local_table_free(struct bat_priv *bat_priv)
static int tt_global_init(struct bat_priv *bat_priv)
{
if (bat_priv->tt_global_hash)
- return 1;
+ return 0;
bat_priv->tt_global_hash = hash_new(1024);
if (!bat_priv->tt_global_hash)
- return 0;
+ return -ENOMEM;
- return 1;
+ return 0;
}
static void tt_changes_list_free(struct bat_priv *bat_priv)
@@ -1773,11 +1773,15 @@ out:
int tt_init(struct bat_priv *bat_priv)
{
- if (!tt_local_init(bat_priv))
- return 0;
+ int ret;
- if (!tt_global_init(bat_priv))
- return 0;
+ ret = tt_local_init(bat_priv);
+ if (ret < 0)
+ return ret;
+
+ ret = tt_global_init(bat_priv);
+ if (ret < 0)
+ return ret;
tt_start_timer(bat_priv);
diff --git a/net/batman-adv/vis.c b/net/batman-adv/vis.c
index cec216f..411c0e1 100644
--- a/net/batman-adv/vis.c
+++ b/net/batman-adv/vis.c
@@ -626,7 +626,7 @@ static int generate_vis_packet(struct bat_priv *bat_priv)
best_tq = find_best_vis_server(bat_priv, info);
if (best_tq < 0)
- return -1;
+ return best_tq;
}
for (i = 0; i < hash->size; i++) {
@@ -878,7 +878,7 @@ int vis_init(struct bat_priv *bat_priv)
int hash_added;
if (bat_priv->vis_hash)
- return 1;
+ return 0;
spin_lock_bh(&bat_priv->vis_hash_lock);
@@ -929,7 +929,7 @@ int vis_init(struct bat_priv *bat_priv)
spin_unlock_bh(&bat_priv->vis_hash_lock);
start_vis_timer(bat_priv);
- return 1;
+ return 0;
free_info:
kfree(bat_priv->my_vis_info);
@@ -937,7 +937,7 @@ free_info:
err:
spin_unlock_bh(&bat_priv->vis_hash_lock);
vis_quit(bat_priv);
- return 0;
+ return -ENOMEM;
}
/* Decrease the reference count on a hash item info */
--
1.7.9.4
^ permalink raw reply related
* [PATCH 11/19] batman-adv: keep batman_ogm_packet ->seqno net-endian all along
From: Antonio Quartulli @ 2012-06-18 20:39 UTC (permalink / raw)
To: davem
Cc: netdev, b.a.t.m.a.n, Al Viro, Al Viro, Sven Eckelmann,
Antonio Quartulli
In-Reply-To: <1340051963-14836-1-git-send-email-ordex@autistici.org>
From: Al Viro <viro@ZenIV.linux.org.uk>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Signed-off-by: Antonio Quartulli <ordex@autistici.org>
---
net/batman-adv/bat_iv_ogm.c | 22 +++++++++++-----------
net/batman-adv/packet.h | 2 +-
2 files changed, 12 insertions(+), 12 deletions(-)
diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c
index e94ac0b..56b6d78 100644
--- a/net/batman-adv/bat_iv_ogm.c
+++ b/net/batman-adv/bat_iv_ogm.c
@@ -34,11 +34,12 @@ static struct neigh_node *bat_iv_ogm_neigh_new(struct hard_iface *hard_iface,
const uint8_t *neigh_addr,
struct orig_node *orig_node,
struct orig_node *orig_neigh,
- uint32_t seqno)
+ __be32 seqno)
{
struct neigh_node *neigh_node;
- neigh_node = batadv_neigh_node_new(hard_iface, neigh_addr, seqno);
+ neigh_node = batadv_neigh_node_new(hard_iface, neigh_addr,
+ ntohl(seqno));
if (!neigh_node)
goto out;
@@ -546,7 +547,6 @@ static void bat_iv_ogm_forward(struct orig_node *orig_node,
"Forwarding packet: tq: %i, ttl: %i\n",
batman_ogm_packet->tq, batman_ogm_packet->header.ttl);
- batman_ogm_packet->seqno = htonl(batman_ogm_packet->seqno);
batman_ogm_packet->tt_crc = htons(batman_ogm_packet->tt_crc);
/* switch of primaries first hop flag when forwarding */
@@ -871,13 +871,14 @@ static int bat_iv_ogm_update_seqnos(const struct ethhdr *ethhdr,
int32_t seq_diff;
int need_update = 0;
int set_mark, ret = -1;
+ uint32_t seqno = ntohl(batman_ogm_packet->seqno);
orig_node = get_orig_node(bat_priv, batman_ogm_packet->orig);
if (!orig_node)
return 0;
spin_lock_bh(&orig_node->ogm_cnt_lock);
- seq_diff = batman_ogm_packet->seqno - orig_node->last_real_seqno;
+ seq_diff = seqno - orig_node->last_real_seqno;
/* signalize caller that the packet is to be dropped. */
if (!hlist_empty(&orig_node->neigh_list) &&
@@ -891,7 +892,7 @@ static int bat_iv_ogm_update_seqnos(const struct ethhdr *ethhdr,
is_duplicate |= bat_test_bit(tmp_neigh_node->real_bits,
orig_node->last_real_seqno,
- batman_ogm_packet->seqno);
+ seqno);
if (compare_eth(tmp_neigh_node->addr, ethhdr->h_source) &&
(tmp_neigh_node->if_incoming == if_incoming))
@@ -913,8 +914,8 @@ static int bat_iv_ogm_update_seqnos(const struct ethhdr *ethhdr,
if (need_update) {
bat_dbg(DBG_BATMAN, bat_priv,
"updating last_seqno: old %u, new %u\n",
- orig_node->last_real_seqno, batman_ogm_packet->seqno);
- orig_node->last_real_seqno = batman_ogm_packet->seqno;
+ orig_node->last_real_seqno, seqno);
+ orig_node->last_real_seqno = seqno;
}
ret = is_duplicate;
@@ -970,7 +971,7 @@ static void bat_iv_ogm_process(const struct ethhdr *ethhdr,
"Received BATMAN packet via NB: %pM, IF: %s [%pM] (from OG: %pM, via prev OG: %pM, seqno %u, ttvn %u, crc %u, changes %u, td %d, TTL %d, V %d, IDF %d)\n",
ethhdr->h_source, if_incoming->net_dev->name,
if_incoming->net_dev->dev_addr, batman_ogm_packet->orig,
- batman_ogm_packet->prev_sender, batman_ogm_packet->seqno,
+ batman_ogm_packet->prev_sender, ntohl(batman_ogm_packet->seqno),
batman_ogm_packet->ttvn, batman_ogm_packet->tt_crc,
batman_ogm_packet->tt_num_changes, batman_ogm_packet->tq,
batman_ogm_packet->header.ttl,
@@ -1042,7 +1043,7 @@ static void bat_iv_ogm_process(const struct ethhdr *ethhdr,
word = &(orig_neigh_node->bcast_own[offset]);
bat_set_bit(word,
if_incoming_seqno -
- batman_ogm_packet->seqno - 2);
+ ntohl(batman_ogm_packet->seqno) - 2);
orig_neigh_node->bcast_own_sum[if_incoming->if_num] =
bitmap_weight(word, TQ_LOCAL_WINDOW_SIZE);
spin_unlock_bh(&orig_neigh_node->ogm_cnt_lock);
@@ -1135,7 +1136,7 @@ static void bat_iv_ogm_process(const struct ethhdr *ethhdr,
* seqno and similar ttl as the non-duplicate */
if (is_bidirectional &&
(!is_duplicate ||
- ((orig_node->last_real_seqno == batman_ogm_packet->seqno) &&
+ ((orig_node->last_real_seqno == ntohl(batman_ogm_packet->seqno)) &&
(orig_node->last_ttl - 3 <= batman_ogm_packet->header.ttl))))
bat_iv_ogm_orig_update(bat_priv, orig_node, ethhdr,
batman_ogm_packet, if_incoming,
@@ -1220,7 +1221,6 @@ static int bat_iv_ogm_receive(struct sk_buff *skb,
do {
/* network to host order for our 32bit seqno and the
orig_interval */
- batman_ogm_packet->seqno = ntohl(batman_ogm_packet->seqno);
batman_ogm_packet->tt_crc = ntohs(batman_ogm_packet->tt_crc);
tt_buff = packet_buff + buff_pos + BATMAN_OGM_HLEN;
diff --git a/net/batman-adv/packet.h b/net/batman-adv/packet.h
index eaa6028..5bf567b 100644
--- a/net/batman-adv/packet.h
+++ b/net/batman-adv/packet.h
@@ -117,7 +117,7 @@ struct batman_header {
struct batman_ogm_packet {
struct batman_header header;
uint8_t flags; /* 0x40: DIRECTLINK flag, 0x20 VIS_SERVER flag... */
- uint32_t seqno;
+ __be32 seqno;
uint8_t orig[ETH_ALEN];
uint8_t prev_sender[ETH_ALEN];
uint8_t gw_flags; /* flags related to gateway class */
--
1.7.9.4
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox