From a4e7b730f1c8c9179def7033a024183c58cf2538 Mon Sep 17 00:00:00 2001 From: Holger Schurig Date: Fri, 11 Sep 2009 10:13:53 +0200 Subject: cfg80211: use cfg80211_wext_freq() for freq conversion WEXT's "struct iw_freq" can also be used to handle a channel. This patch now uses cfg80211_wext_freq() instead of hand-converting the frequency. That allows user-space to specify channels as well, like with SIOCSIWFREQ. Signed-off-by: Holger Schurig Signed-off-by: John W. Linville --- net/wireless/scan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net') diff --git a/net/wireless/scan.c b/net/wireless/scan.c index 4c210c2..6c20b65 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c @@ -662,7 +662,7 @@ int cfg80211_wext_siwscan(struct net_device *dev, int k; int wiphy_freq = wiphy->bands[band]->channels[j].center_freq; for (k = 0; k < wreq->num_channels; k++) { - int wext_freq = wreq->channel_list[k].m / 100000; + int wext_freq = cfg80211_wext_freq(wiphy, &wreq->channel_list[k]); if (wext_freq == wiphy_freq) goto wext_freq_found; } -- cgit v1.1 From 8862dc5f25153a3c565a097220ed3de14ed72dfd Mon Sep 17 00:00:00 2001 From: Holger Schurig Date: Fri, 11 Sep 2009 10:13:55 +0200 Subject: cfg80211: minimal error handling for wext-compat freq scanning Signed-off-by: Holger Schurig Signed-off-by: John W. Linville --- net/wireless/scan.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'net') diff --git a/net/wireless/scan.c b/net/wireless/scan.c index 6c20b65..e5f92ee 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c @@ -675,6 +675,11 @@ int cfg80211_wext_siwscan(struct net_device *dev, wext_freq_not_found: ; } } + /* No channels found? */ + if (!i) { + err = -EINVAL; + goto out; + } /* Set real number of channels specified in creq->channels[] */ creq->n_channels = i; -- cgit v1.1 From 8be8057e72d7d319f8e97b26e16de8021fe63988 Mon Sep 17 00:00:00 2001 From: Mark Smith Date: Sat, 12 Sep 2009 20:48:43 +0000 Subject: Have atalk_route_packet() return NET_RX_SUCCESS not NET_XMIT_SUCCESS Have atalk_route_packet() return NET_RX_SUCCESS not NET_XMIT_SUCCESS atalk_route_packet() returns NET_RX_DROP if it's call to aarp_send_ddp() returns NET_XMIT_DROP. If aarp_send_ddp() returns anything else atalk_route_packet() should return NET_RX_SUCCESS, not NET_XMIT_SUCCESS. Signed-off-by: Mark Smith Signed-off-by: David S. Miller --- net/appletalk/ddp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net') diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c index 4a6ff2b..b1a4290 100644 --- a/net/appletalk/ddp.c +++ b/net/appletalk/ddp.c @@ -1372,7 +1372,7 @@ static int atalk_route_packet(struct sk_buff *skb, struct net_device *dev, if (aarp_send_ddp(rt->dev, skb, &ta, NULL) == NET_XMIT_DROP) return NET_RX_DROP; - return NET_XMIT_SUCCESS; + return NET_RX_SUCCESS; free_it: kfree_skb(skb); drop: -- cgit v1.1 From d136f1bd366fdb7e747ca7e0218171e7a00a98a5 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Sat, 12 Sep 2009 03:03:15 +0000 Subject: genetlink: fix netns vs. netlink table locking Since my commits introducing netns awareness into genetlink we can get this problem: BUG: scheduling while atomic: modprobe/1178/0x00000002 2 locks held by modprobe/1178: #0: (genl_mutex){+.+.+.}, at: [] genl_register_mc_grou #1: (rcu_read_lock){.+.+..}, at: [] genl_register_mc_g Pid: 1178, comm: modprobe Not tainted 2.6.31-rc8-wl-34789-g95cb731-dirty # Call Trace: [] __schedule_bug+0x85/0x90 [] schedule+0x108/0x588 [] netlink_table_grab+0xa1/0xf0 [] netlink_change_ngroups+0x47/0x100 [] genl_register_mc_group+0x12f/0x290 because I overlooked that netlink_table_grab() will schedule, thinking it was just the rwlock. However, in the contention case, that isn't actually true. Fix this by letting the code grab the netlink table lock first and then the RCU for netns protection. Signed-off-by: Johannes Berg Signed-off-by: David S. Miller --- net/netlink/af_netlink.c | 51 +++++++++++++++++++++++++++--------------------- net/netlink/genetlink.c | 5 ++++- 2 files changed, 33 insertions(+), 23 deletions(-) (limited to 'net') diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index d0ff382..c5aab6a 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c @@ -177,9 +177,11 @@ static void netlink_sock_destruct(struct sock *sk) * this, _but_ remember, it adds useless work on UP machines. */ -static void netlink_table_grab(void) +void netlink_table_grab(void) __acquires(nl_table_lock) { + might_sleep(); + write_lock_irq(&nl_table_lock); if (atomic_read(&nl_table_users)) { @@ -200,7 +202,7 @@ static void netlink_table_grab(void) } } -static void netlink_table_ungrab(void) +void netlink_table_ungrab(void) __releases(nl_table_lock) { write_unlock_irq(&nl_table_lock); @@ -1549,37 +1551,21 @@ static void netlink_free_old_listeners(struct rcu_head *rcu_head) kfree(lrh->ptr); } -/** - * netlink_change_ngroups - change number of multicast groups - * - * This changes the number of multicast groups that are available - * on a certain netlink family. Note that it is not possible to - * change the number of groups to below 32. Also note that it does - * not implicitly call netlink_clear_multicast_users() when the - * number of groups is reduced. - * - * @sk: The kernel netlink socket, as returned by netlink_kernel_create(). - * @groups: The new number of groups. - */ -int netlink_change_ngroups(struct sock *sk, unsigned int groups) +int __netlink_change_ngroups(struct sock *sk, unsigned int groups) { unsigned long *listeners, *old = NULL; struct listeners_rcu_head *old_rcu_head; struct netlink_table *tbl = &nl_table[sk->sk_protocol]; - int err = 0; if (groups < 32) groups = 32; - netlink_table_grab(); if (NLGRPSZ(tbl->groups) < NLGRPSZ(groups)) { listeners = kzalloc(NLGRPSZ(groups) + sizeof(struct listeners_rcu_head), GFP_ATOMIC); - if (!listeners) { - err = -ENOMEM; - goto out_ungrab; - } + if (!listeners) + return -ENOMEM; old = tbl->listeners; memcpy(listeners, old, NLGRPSZ(tbl->groups)); rcu_assign_pointer(tbl->listeners, listeners); @@ -1597,8 +1583,29 @@ int netlink_change_ngroups(struct sock *sk, unsigned int groups) } tbl->groups = groups; - out_ungrab: + return 0; +} + +/** + * netlink_change_ngroups - change number of multicast groups + * + * This changes the number of multicast groups that are available + * on a certain netlink family. Note that it is not possible to + * change the number of groups to below 32. Also note that it does + * not implicitly call netlink_clear_multicast_users() when the + * number of groups is reduced. + * + * @sk: The kernel netlink socket, as returned by netlink_kernel_create(). + * @groups: The new number of groups. + */ +int netlink_change_ngroups(struct sock *sk, unsigned int groups) +{ + int err; + + netlink_table_grab(); + err = __netlink_change_ngroups(sk, groups); netlink_table_ungrab(); + return err; } diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c index 66f6ba0..566941e 100644 --- a/net/netlink/genetlink.c +++ b/net/netlink/genetlink.c @@ -176,9 +176,10 @@ int genl_register_mc_group(struct genl_family *family, if (family->netnsok) { struct net *net; + netlink_table_grab(); rcu_read_lock(); for_each_net_rcu(net) { - err = netlink_change_ngroups(net->genl_sock, + err = __netlink_change_ngroups(net->genl_sock, mc_groups_longs * BITS_PER_LONG); if (err) { /* @@ -188,10 +189,12 @@ int genl_register_mc_group(struct genl_family *family, * increased on some sockets which is ok. */ rcu_read_unlock(); + netlink_table_ungrab(); goto out; } } rcu_read_unlock(); + netlink_table_ungrab(); } else { err = netlink_change_ngroups(init_net.genl_sock, mc_groups_longs * BITS_PER_LONG); -- cgit v1.1 From aa1b1ff0991b469eca6fde4456190df6ed59ff40 Mon Sep 17 00:00:00 2001 From: Gerrit Renker Date: Sat, 12 Sep 2009 07:47:01 +0000 Subject: net-next-2.6 [PATCH 1/1] dccp: ccids whitespace-cleanup / CodingStyle No code change, cosmetical changes only: * whitespace cleanup via scripts/cleanfile, * remove self-references to filename at top of files, * fix coding style (extraneous brackets), * fix documentation style (kernel-doc-nano-HOWTO). Thanks are due to Ivo Augusto Calado who raised these issues by submitting good-quality patches. Signed-off-by: Gerrit Renker Signed-off-by: David S. Miller --- net/dccp/ccids/Kconfig | 6 ++--- net/dccp/ccids/ccid2.c | 2 -- net/dccp/ccids/ccid2.h | 8 +++--- net/dccp/ccids/ccid3.c | 5 ++-- net/dccp/ccids/ccid3.h | 50 ++++++++++++++++++------------------- net/dccp/ccids/lib/loss_interval.c | 7 +++--- net/dccp/ccids/lib/loss_interval.h | 2 -- net/dccp/ccids/lib/packet_history.c | 4 +-- net/dccp/ccids/lib/packet_history.h | 1 - net/dccp/ccids/lib/tfrc.h | 4 +-- net/dccp/ccids/lib/tfrc_equation.c | 26 ++++++++----------- 11 files changed, 48 insertions(+), 67 deletions(-) (limited to 'net') diff --git a/net/dccp/ccids/Kconfig b/net/dccp/ccids/Kconfig index 4b5db44..8408398 100644 --- a/net/dccp/ccids/Kconfig +++ b/net/dccp/ccids/Kconfig @@ -66,9 +66,9 @@ config IP_DCCP_CCID3_RTO A value of 0 disables this feature by enforcing the value specified in RFC 3448. The following values have been suggested as bounds for experimental use: - * 16-20ms to match the typical multimedia inter-frame interval - * 100ms as a reasonable compromise [default] - * 1000ms corresponds to the lower TCP RTO bound (RFC 2988, 2.4) + * 16-20ms to match the typical multimedia inter-frame interval + * 100ms as a reasonable compromise [default] + * 1000ms corresponds to the lower TCP RTO bound (RFC 2988, 2.4) The default of 100ms is a compromise between a large value for efficient DCCP implementations, and a small value to avoid disrupting diff --git a/net/dccp/ccids/ccid2.c b/net/dccp/ccids/ccid2.c index d235294..e8cf99e 100644 --- a/net/dccp/ccids/ccid2.c +++ b/net/dccp/ccids/ccid2.c @@ -1,6 +1,4 @@ /* - * net/dccp/ccids/ccid2.c - * * Copyright (c) 2005, 2006 Andrea Bittau * * Changes to meet Linux coding standards, and DCCP infrastructure fixes. diff --git a/net/dccp/ccids/ccid2.h b/net/dccp/ccids/ccid2.h index 2c94ca0..326ac90 100644 --- a/net/dccp/ccids/ccid2.h +++ b/net/dccp/ccids/ccid2.h @@ -1,6 +1,4 @@ /* - * net/dccp/ccids/ccid2.h - * * Copyright (c) 2005 Andrea Bittau * * This program is free software; you can redistribute it and/or modify @@ -40,14 +38,14 @@ struct ccid2_seq { #define CCID2_SEQBUF_LEN 1024 #define CCID2_SEQBUF_MAX 128 -/** struct ccid2_hc_tx_sock - CCID2 TX half connection - * +/** + * struct ccid2_hc_tx_sock - CCID2 TX half connection * @ccid2hctx_{cwnd,ssthresh,pipe}: as per RFC 4341, section 5 * @ccid2hctx_packets_acked - Ack counter for deriving cwnd growth (RFC 3465) * @ccid2hctx_lastrtt -time RTT was last measured * @ccid2hctx_rpseq - last consecutive seqno * @ccid2hctx_rpdupack - dupacks since rpseq -*/ + */ struct ccid2_hc_tx_sock { u32 ccid2hctx_cwnd; u32 ccid2hctx_ssthresh; diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c index f596ce1..34dcc79 100644 --- a/net/dccp/ccids/ccid3.c +++ b/net/dccp/ccids/ccid3.c @@ -1,6 +1,4 @@ /* - * net/dccp/ccids/ccid3.c - * * Copyright (c) 2007 The University of Aberdeen, Scotland, UK * Copyright (c) 2005-7 The University of Waikato, Hamilton, New Zealand. * Copyright (c) 2005-7 Ian McDonald @@ -750,7 +748,8 @@ static int ccid3_hc_rx_insert_options(struct sock *sk, struct sk_buff *skb) return 0; } -/** ccid3_first_li - Implements [RFC 3448, 6.3.1] +/** + * ccid3_first_li - Implements [RFC 5348, 6.3.1] * * Determine the length of the first loss interval via inverse lookup. * Assume that X_recv can be computed by the throughput equation diff --git a/net/dccp/ccids/ccid3.h b/net/dccp/ccids/ccid3.h index 49ca32b..e5a2441 100644 --- a/net/dccp/ccids/ccid3.h +++ b/net/dccp/ccids/ccid3.h @@ -1,6 +1,4 @@ /* - * net/dccp/ccids/ccid3.h - * * Copyright (c) 2005-7 The University of Waikato, Hamilton, New Zealand. * Copyright (c) 2007 The University of Aberdeen, Scotland, UK * @@ -75,8 +73,8 @@ enum ccid3_hc_tx_states { TFRC_SSTATE_TERM, }; -/** struct ccid3_hc_tx_sock - CCID3 sender half-connection socket - * +/** + * struct ccid3_hc_tx_sock - CCID3 sender half-connection socket * @ccid3hctx_x - Current sending rate in 64 * bytes per second * @ccid3hctx_x_recv - Receive rate in 64 * bytes per second * @ccid3hctx_x_calc - Calculated rate in bytes per second @@ -119,9 +117,9 @@ struct ccid3_hc_tx_sock { static inline struct ccid3_hc_tx_sock *ccid3_hc_tx_sk(const struct sock *sk) { - struct ccid3_hc_tx_sock *hctx = ccid_priv(dccp_sk(sk)->dccps_hc_tx_ccid); - BUG_ON(hctx == NULL); - return hctx; + struct ccid3_hc_tx_sock *hctx = ccid_priv(dccp_sk(sk)->dccps_hc_tx_ccid); + BUG_ON(hctx == NULL); + return hctx; } /* TFRC receiver states */ @@ -131,22 +129,22 @@ enum ccid3_hc_rx_states { TFRC_RSTATE_TERM = 127, }; -/** struct ccid3_hc_rx_sock - CCID3 receiver half-connection socket - * - * @ccid3hcrx_x_recv - Receiver estimate of send rate (RFC 3448 4.3) - * @ccid3hcrx_rtt - Receiver estimate of rtt (non-standard) - * @ccid3hcrx_p - Current loss event rate (RFC 3448 5.4) - * @ccid3hcrx_last_counter - Tracks window counter (RFC 4342, 8.1) - * @ccid3hcrx_state - Receiver state, one of %ccid3_hc_rx_states - * @ccid3hcrx_bytes_recv - Total sum of DCCP payload bytes - * @ccid3hcrx_x_recv - Receiver estimate of send rate (RFC 3448, sec. 4.3) - * @ccid3hcrx_rtt - Receiver estimate of RTT - * @ccid3hcrx_tstamp_last_feedback - Time at which last feedback was sent - * @ccid3hcrx_tstamp_last_ack - Time at which last feedback was sent - * @ccid3hcrx_hist - Packet history (loss detection + RTT sampling) - * @ccid3hcrx_li_hist - Loss Interval database - * @ccid3hcrx_s - Received packet size in bytes - * @ccid3hcrx_pinv - Inverse of Loss Event Rate (RFC 4342, sec. 8.5) +/** + * struct ccid3_hc_rx_sock - CCID3 receiver half-connection socket + * @ccid3hcrx_x_recv - Receiver estimate of send rate (RFC 3448 4.3) + * @ccid3hcrx_rtt - Receiver estimate of rtt (non-standard) + * @ccid3hcrx_p - Current loss event rate (RFC 3448 5.4) + * @ccid3hcrx_last_counter - Tracks window counter (RFC 4342, 8.1) + * @ccid3hcrx_state - Receiver state, one of %ccid3_hc_rx_states + * @ccid3hcrx_bytes_recv - Total sum of DCCP payload bytes + * @ccid3hcrx_x_recv - Receiver estimate of send rate (RFC 3448, sec. 4.3) + * @ccid3hcrx_rtt - Receiver estimate of RTT + * @ccid3hcrx_tstamp_last_feedback - Time at which last feedback was sent + * @ccid3hcrx_tstamp_last_ack - Time at which last feedback was sent + * @ccid3hcrx_hist - Packet history (loss detection + RTT sampling) + * @ccid3hcrx_li_hist - Loss Interval database + * @ccid3hcrx_s - Received packet size in bytes + * @ccid3hcrx_pinv - Inverse of Loss Event Rate (RFC 4342, sec. 8.5) */ struct ccid3_hc_rx_sock { u8 ccid3hcrx_last_counter:4; @@ -163,9 +161,9 @@ struct ccid3_hc_rx_sock { static inline struct ccid3_hc_rx_sock *ccid3_hc_rx_sk(const struct sock *sk) { - struct ccid3_hc_rx_sock *hcrx = ccid_priv(dccp_sk(sk)->dccps_hc_rx_ccid); - BUG_ON(hcrx == NULL); - return hcrx; + struct ccid3_hc_rx_sock *hcrx = ccid_priv(dccp_sk(sk)->dccps_hc_rx_ccid); + BUG_ON(hcrx == NULL); + return hcrx; } #endif /* _DCCP_CCID3_H_ */ diff --git a/net/dccp/ccids/lib/loss_interval.c b/net/dccp/ccids/lib/loss_interval.c index 4d1e401..8fc3cbf 100644 --- a/net/dccp/ccids/lib/loss_interval.c +++ b/net/dccp/ccids/lib/loss_interval.c @@ -1,6 +1,4 @@ /* - * net/dccp/ccids/lib/loss_interval.c - * * Copyright (c) 2007 The University of Aberdeen, Scotland, UK * Copyright (c) 2005-7 The University of Waikato, Hamilton, New Zealand. * Copyright (c) 2005-7 Ian McDonald @@ -21,7 +19,7 @@ static const int tfrc_lh_weights[NINTERVAL] = { 10, 10, 10, 10, 8, 6, 4, 2 }; /* implements LIFO semantics on the array */ static inline u8 LIH_INDEX(const u8 ctr) { - return (LIH_SIZE - 1 - (ctr % LIH_SIZE)); + return LIH_SIZE - 1 - (ctr % LIH_SIZE); } /* the `counter' index always points at the next entry to be populated */ @@ -129,7 +127,8 @@ static inline u8 tfrc_lh_is_new_loss(struct tfrc_loss_interval *cur, (cur->li_is_closed || SUB16(new_loss->tfrchrx_ccval, cur->li_ccval) > 4); } -/** tfrc_lh_interval_add - Insert new record into the Loss Interval database +/** + * tfrc_lh_interval_add - Insert new record into the Loss Interval database * @lh: Loss Interval database * @rh: Receive history containing a fresh loss event * @calc_first_li: Caller-dependent routine to compute length of first interval diff --git a/net/dccp/ccids/lib/loss_interval.h b/net/dccp/ccids/lib/loss_interval.h index 246018a..d1d2f53 100644 --- a/net/dccp/ccids/lib/loss_interval.h +++ b/net/dccp/ccids/lib/loss_interval.h @@ -1,8 +1,6 @@ #ifndef _DCCP_LI_HIST_ #define _DCCP_LI_HIST_ /* - * net/dccp/ccids/lib/loss_interval.h - * * Copyright (c) 2007 The University of Aberdeen, Scotland, UK * Copyright (c) 2005-7 The University of Waikato, Hamilton, New Zealand. * Copyright (c) 2005-7 Ian McDonald diff --git a/net/dccp/ccids/lib/packet_history.c b/net/dccp/ccids/lib/packet_history.c index b7785b3..3a4f414 100644 --- a/net/dccp/ccids/lib/packet_history.c +++ b/net/dccp/ccids/lib/packet_history.c @@ -1,6 +1,4 @@ /* - * net/dccp/packet_history.c - * * Copyright (c) 2007 The University of Aberdeen, Scotland, UK * Copyright (c) 2005-7 The University of Waikato, Hamilton, New Zealand. * @@ -128,7 +126,7 @@ u32 tfrc_tx_hist_rtt(struct tfrc_tx_hist_entry *head, const u64 seqno, /* - * Receiver History Routines + * Receiver History Routines */ static struct kmem_cache *tfrc_rx_hist_slab; diff --git a/net/dccp/ccids/lib/packet_history.h b/net/dccp/ccids/lib/packet_history.h index 461cc91..7df6c52 100644 --- a/net/dccp/ccids/lib/packet_history.h +++ b/net/dccp/ccids/lib/packet_history.h @@ -70,7 +70,6 @@ struct tfrc_rx_hist_entry { /** * tfrc_rx_hist - RX history structure for TFRC-based protocols - * * @ring: Packet history for RTT sampling and loss detection * @loss_count: Number of entries in circular history * @loss_start: Movable index (for loss detection) diff --git a/net/dccp/ccids/lib/tfrc.h b/net/dccp/ccids/lib/tfrc.h index e9720b1..01bb48e 100644 --- a/net/dccp/ccids/lib/tfrc.h +++ b/net/dccp/ccids/lib/tfrc.h @@ -1,8 +1,6 @@ #ifndef _TFRC_H_ #define _TFRC_H_ /* - * net/dccp/ccids/lib/tfrc.h - * * Copyright (c) 2007 The University of Aberdeen, Scotland, UK * Copyright (c) 2005-6 The University of Waikato, Hamilton, New Zealand. * Copyright (c) 2005-6 Ian McDonald @@ -32,7 +30,7 @@ extern int tfrc_debug; /* integer-arithmetic divisions of type (a * 1000000)/b */ static inline u64 scaled_div(u64 a, u64 b) { - BUG_ON(b==0); + BUG_ON(b == 0); return div64_u64(a * 1000000, b); } diff --git a/net/dccp/ccids/lib/tfrc_equation.c b/net/dccp/ccids/lib/tfrc_equation.c index c5d3a9e..22ca1cf 100644 --- a/net/dccp/ccids/lib/tfrc_equation.c +++ b/net/dccp/ccids/lib/tfrc_equation.c @@ -1,6 +1,4 @@ /* - * net/dccp/ccids/lib/tfrc_equation.c - * * Copyright (c) 2005 The University of Waikato, Hamilton, New Zealand. * Copyright (c) 2005 Ian McDonald * Copyright (c) 2005 Arnaldo Carvalho de Melo @@ -79,10 +77,10 @@ } With the given configuration, we have, with M = TFRC_CALC_X_ARRSIZE-1, - lookup[0][0] = g(1000000/(M+1)) = 1000000 * f(0.2%) - lookup[M][0] = g(1000000) = 1000000 * f(100%) - lookup[0][1] = g(TFRC_SMALLEST_P) = 1000000 * f(0.01%) - lookup[M][1] = g(TFRC_CALC_X_SPLIT) = 1000000 * f(5%) + lookup[0][0] = g(1000000/(M+1)) = 1000000 * f(0.2%) + lookup[M][0] = g(1000000) = 1000000 * f(100%) + lookup[0][1] = g(TFRC_SMALLEST_P) = 1000000 * f(0.01%) + lookup[M][1] = g(TFRC_CALC_X_SPLIT) = 1000000 * f(5%) In summary, the two columns represent f(p) for the following ranges: * The first column is for 0.002 <= p <= 1.0 @@ -610,11 +608,10 @@ static inline u32 tfrc_binsearch(u32 fval, u8 small) /** * tfrc_calc_x - Calculate the send rate as per section 3.1 of RFC3448 - * - * @s: packet size in bytes - * @R: RTT scaled by 1000000 (i.e., microseconds) - * @p: loss ratio estimate scaled by 1000000 - * Returns X_calc in bytes per second (not scaled). + * @s: packet size in bytes + * @R: RTT scaled by 1000000 (i.e., microseconds) + * @p: loss ratio estimate scaled by 1000000 + * Returns X_calc in bytes per second (not scaled). */ u32 tfrc_calc_x(u16 s, u32 R, u32 p) { @@ -630,17 +627,17 @@ u32 tfrc_calc_x(u16 s, u32 R, u32 p) return ~0U; } - if (p <= TFRC_CALC_X_SPLIT) { /* 0.0000 < p <= 0.05 */ + if (p <= TFRC_CALC_X_SPLIT) { /* 0.0000 < p <= 0.05 */ if (p < TFRC_SMALLEST_P) { /* 0.0000 < p < 0.0001 */ DCCP_WARN("Value of p (%d) below resolution. " "Substituting %d\n", p, TFRC_SMALLEST_P); index = 0; - } else /* 0.0001 <= p <= 0.05 */ + } else /* 0.0001 <= p <= 0.05 */ index = p/TFRC_SMALLEST_P - 1; f = tfrc_calc_x_lookup[index][1]; - } else { /* 0.05 < p <= 1.00 */ + } else { /* 0.05 < p <= 1.00 */ index = p/(1000000/TFRC_CALC_X_ARRSIZE) - 1; f = tfrc_calc_x_lookup[index][0]; @@ -661,7 +658,6 @@ u32 tfrc_calc_x(u16 s, u32 R, u32 p) /** * tfrc_calc_x_reverse_lookup - try to find p given f(p) - * * @fvalue: function value to match, scaled by 1000000 * Returns closest match for p, also scaled by 1000000 */ -- cgit v1.1 From 32613090a96dba2ca2cc524c8d4749d3126fdde5 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Mon, 14 Sep 2009 12:21:47 +0000 Subject: net: constify struct net_protocol Remove long removed "inet_protocol_base" declaration. Signed-off-by: Alexey Dobriyan Signed-off-by: David S. Miller --- net/dccp/ipv4.c | 2 +- net/ipv4/af_inet.c | 18 +++++++++--------- net/ipv4/ah4.c | 2 +- net/ipv4/esp4.c | 2 +- net/ipv4/icmp.c | 2 +- net/ipv4/ip_gre.c | 2 +- net/ipv4/ip_input.c | 2 +- net/ipv4/ipcomp.c | 2 +- net/ipv4/ipmr.c | 6 +----- net/ipv4/protocol.c | 6 +++--- net/ipv4/tunnel4.c | 4 ++-- net/ipv4/udplite.c | 2 +- net/sctp/protocol.c | 2 +- 13 files changed, 24 insertions(+), 28 deletions(-) (limited to 'net') diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index d01c00d..7302e14 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c @@ -948,7 +948,7 @@ static struct proto dccp_v4_prot = { #endif }; -static struct net_protocol dccp_v4_protocol = { +static const struct net_protocol dccp_v4_protocol = { .handler = dccp_v4_rcv, .err_handler = dccp_v4_err, .no_policy = 1, diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index 6c30a73..58c4b0f 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c @@ -244,7 +244,7 @@ EXPORT_SYMBOL(build_ehash_secret); static inline int inet_netns_ok(struct net *net, int protocol) { int hash; - struct net_protocol *ipprot; + const struct net_protocol *ipprot; if (net_eq(net, &init_net)) return 1; @@ -1162,7 +1162,7 @@ EXPORT_SYMBOL(inet_sk_rebuild_header); static int inet_gso_send_check(struct sk_buff *skb) { struct iphdr *iph; - struct net_protocol *ops; + const struct net_protocol *ops; int proto; int ihl; int err = -EINVAL; @@ -1198,7 +1198,7 @@ static struct sk_buff *inet_gso_segment(struct sk_buff *skb, int features) { struct sk_buff *segs = ERR_PTR(-EINVAL); struct iphdr *iph; - struct net_protocol *ops; + const struct net_protocol *ops; int proto; int ihl; int id; @@ -1265,7 +1265,7 @@ out: static struct sk_buff **inet_gro_receive(struct sk_buff **head, struct sk_buff *skb) { - struct net_protocol *ops; + const struct net_protocol *ops; struct sk_buff **pp = NULL; struct sk_buff *p; struct iphdr *iph; @@ -1342,7 +1342,7 @@ out: static int inet_gro_complete(struct sk_buff *skb) { - struct net_protocol *ops; + const struct net_protocol *ops; struct iphdr *iph = ip_hdr(skb); int proto = iph->protocol & (MAX_INET_PROTOS - 1); int err = -ENOSYS; @@ -1427,13 +1427,13 @@ void snmp_mib_free(void *ptr[2]) EXPORT_SYMBOL_GPL(snmp_mib_free); #ifdef CONFIG_IP_MULTICAST -static struct net_protocol igmp_protocol = { +static const struct net_protocol igmp_protocol = { .handler = igmp_rcv, .netns_ok = 1, }; #endif -static struct net_protocol tcp_protocol = { +static const struct net_protocol tcp_protocol = { .handler = tcp_v4_rcv, .err_handler = tcp_v4_err, .gso_send_check = tcp_v4_gso_send_check, @@ -1444,7 +1444,7 @@ static struct net_protocol tcp_protocol = { .netns_ok = 1, }; -static struct net_protocol udp_protocol = { +static const struct net_protocol udp_protocol = { .handler = udp_rcv, .err_handler = udp_err, .gso_send_check = udp4_ufo_send_check, @@ -1453,7 +1453,7 @@ static struct net_protocol udp_protocol = { .netns_ok = 1, }; -static struct net_protocol icmp_protocol = { +static const struct net_protocol icmp_protocol = { .handler = icmp_rcv, .no_policy = 1, .netns_ok = 1, diff --git a/net/ipv4/ah4.c b/net/ipv4/ah4.c index e878e49..5c66270 100644 --- a/net/ipv4/ah4.c +++ b/net/ipv4/ah4.c @@ -311,7 +311,7 @@ static const struct xfrm_type ah_type = .output = ah_output }; -static struct net_protocol ah4_protocol = { +static const struct net_protocol ah4_protocol = { .handler = xfrm4_rcv, .err_handler = ah4_err, .no_policy = 1, diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c index 18bb383..12f7287 100644 --- a/net/ipv4/esp4.c +++ b/net/ipv4/esp4.c @@ -615,7 +615,7 @@ static const struct xfrm_type esp_type = .output = esp_output }; -static struct net_protocol esp4_protocol = { +static const struct net_protocol esp4_protocol = { .handler = xfrm4_rcv, .err_handler = esp4_err, .no_policy = 1, diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c index 97c410e..5bc13fe 100644 --- a/net/ipv4/icmp.c +++ b/net/ipv4/icmp.c @@ -655,7 +655,7 @@ static void icmp_unreach(struct sk_buff *skb) struct iphdr *iph; struct icmphdr *icmph; int hash, protocol; - struct net_protocol *ipprot; + const struct net_protocol *ipprot; u32 info = 0; struct net *net; diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index 533afaa..d9645c9 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c @@ -1288,7 +1288,7 @@ static void ipgre_fb_tunnel_init(struct net_device *dev) } -static struct net_protocol ipgre_protocol = { +static const struct net_protocol ipgre_protocol = { .handler = ipgre_rcv, .err_handler = ipgre_err, .netns_ok = 1, diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c index db46b4b..6c98b43 100644 --- a/net/ipv4/ip_input.c +++ b/net/ipv4/ip_input.c @@ -202,7 +202,7 @@ static int ip_local_deliver_finish(struct sk_buff *skb) { int protocol = ip_hdr(skb)->protocol; int hash, raw; - struct net_protocol *ipprot; + const struct net_protocol *ipprot; resubmit: raw = raw_local_deliver(skb, protocol); diff --git a/net/ipv4/ipcomp.c b/net/ipv4/ipcomp.c index 3262ce0..38fbf04 100644 --- a/net/ipv4/ipcomp.c +++ b/net/ipv4/ipcomp.c @@ -146,7 +146,7 @@ static const struct xfrm_type ipcomp_type = { .output = ipcomp_output }; -static struct net_protocol ipcomp4_protocol = { +static const struct net_protocol ipcomp4_protocol = { .handler = xfrm4_rcv, .err_handler = ipcomp4_err, .no_policy = 1, diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c index 65d421c..c43ec2d 100644 --- a/net/ipv4/ipmr.c +++ b/net/ipv4/ipmr.c @@ -99,10 +99,6 @@ static int ipmr_cache_report(struct net *net, struct sk_buff *pkt, vifi_t vifi, int assert); static int ipmr_fill_mroute(struct sk_buff *skb, struct mfc_cache *c, struct rtmsg *rtm); -#ifdef CONFIG_IP_PIMSM_V2 -static struct net_protocol pim_protocol; -#endif - static struct timer_list ipmr_expire_timer; /* Service routines creating virtual interfaces: DVMRP tunnels and PIMREG */ @@ -1945,7 +1941,7 @@ static const struct file_operations ipmr_mfc_fops = { #endif #ifdef CONFIG_IP_PIMSM_V2 -static struct net_protocol pim_protocol = { +static const struct net_protocol pim_protocol = { .handler = pim_rcv, .netns_ok = 1, }; diff --git a/net/ipv4/protocol.c b/net/ipv4/protocol.c index a2e5fc0..542f22fc9 100644 --- a/net/ipv4/protocol.c +++ b/net/ipv4/protocol.c @@ -28,14 +28,14 @@ #include #include -struct net_protocol *inet_protos[MAX_INET_PROTOS] ____cacheline_aligned_in_smp; +const struct net_protocol *inet_protos[MAX_INET_PROTOS] ____cacheline_aligned_in_smp; static DEFINE_SPINLOCK(inet_proto_lock); /* * Add a protocol handler to the hash tables */ -int inet_add_protocol(struct net_protocol *prot, unsigned char protocol) +int inet_add_protocol(const struct net_protocol *prot, unsigned char protocol) { int hash, ret; @@ -57,7 +57,7 @@ int inet_add_protocol(struct net_protocol *prot, unsigned char protocol) * Remove a protocol from the hash tables. */ -int inet_del_protocol(struct net_protocol *prot, unsigned char protocol) +int inet_del_protocol(const struct net_protocol *prot, unsigned char protocol) { int hash, ret; diff --git a/net/ipv4/tunnel4.c b/net/ipv4/tunnel4.c index cb1f0e8..3959e0c 100644 --- a/net/ipv4/tunnel4.c +++ b/net/ipv4/tunnel4.c @@ -132,7 +132,7 @@ static void tunnel64_err(struct sk_buff *skb, u32 info) } #endif -static struct net_protocol tunnel4_protocol = { +static const struct net_protocol tunnel4_protocol = { .handler = tunnel4_rcv, .err_handler = tunnel4_err, .no_policy = 1, @@ -140,7 +140,7 @@ static struct net_protocol tunnel4_protocol = { }; #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) -static struct net_protocol tunnel64_protocol = { +static const struct net_protocol tunnel64_protocol = { .handler = tunnel64_rcv, .err_handler = tunnel64_err, .no_policy = 1, diff --git a/net/ipv4/udplite.c b/net/ipv4/udplite.c index c784891..95248d7 100644 --- a/net/ipv4/udplite.c +++ b/net/ipv4/udplite.c @@ -25,7 +25,7 @@ static void udplite_err(struct sk_buff *skb, u32 info) __udp4_lib_err(skb, info, &udplite_table); } -static struct net_protocol udplite_protocol = { +static const struct net_protocol udplite_protocol = { .handler = udplite_rcv, .err_handler = udplite_err, .no_policy = 1, diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index 60093be..c557f1f 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c @@ -924,7 +924,7 @@ static struct inet_protosw sctp_stream_protosw = { }; /* Register with IP layer. */ -static struct net_protocol sctp_protocol = { +static const struct net_protocol sctp_protocol = { .handler = sctp_rcv, .err_handler = sctp_v4_err, .no_policy = 1, -- cgit v1.1 From 41135cc836a1abeb12ca1416bdb29e87ad021153 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Mon, 14 Sep 2009 12:22:28 +0000 Subject: net: constify struct inet6_protocol Signed-off-by: Alexey Dobriyan Signed-off-by: David S. Miller --- net/dccp/ipv6.c | 2 +- net/ipv6/af_inet6.c | 10 +++++----- net/ipv6/ah6.c | 2 +- net/ipv6/esp6.c | 2 +- net/ipv6/exthdrs.c | 6 +++--- net/ipv6/icmp.c | 4 ++-- net/ipv6/ip6_input.c | 2 +- net/ipv6/ip6mr.c | 6 +----- net/ipv6/ipcomp6.c | 2 +- net/ipv6/protocol.c | 6 +++--- net/ipv6/reassembly.c | 2 +- net/ipv6/tcp_ipv6.c | 2 +- net/ipv6/tunnel6.c | 4 ++-- net/ipv6/udp.c | 2 +- net/ipv6/udplite.c | 2 +- net/sctp/ipv6.c | 2 +- 16 files changed, 26 insertions(+), 30 deletions(-) (limited to 'net') diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c index 64f011c..364bfc7 100644 --- a/net/dccp/ipv6.c +++ b/net/dccp/ipv6.c @@ -1152,7 +1152,7 @@ static struct proto dccp_v6_prot = { #endif }; -static struct inet6_protocol dccp_v6_protocol = { +static const struct inet6_protocol dccp_v6_protocol = { .handler = dccp_v6_rcv, .err_handler = dccp_v6_err, .flags = INET6_PROTO_NOPOLICY | INET6_PROTO_FINAL, diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index a123a32..e127a32 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c @@ -710,7 +710,7 @@ EXPORT_SYMBOL_GPL(ipv6_opt_accepted); static int ipv6_gso_pull_exthdrs(struct sk_buff *skb, int proto) { - struct inet6_protocol *ops = NULL; + const struct inet6_protocol *ops = NULL; for (;;) { struct ipv6_opt_hdr *opth; @@ -745,7 +745,7 @@ static int ipv6_gso_pull_exthdrs(struct sk_buff *skb, int proto) static int ipv6_gso_send_check(struct sk_buff *skb) { struct ipv6hdr *ipv6h; - struct inet6_protocol *ops; + const struct inet6_protocol *ops; int err = -EINVAL; if (unlikely(!pskb_may_pull(skb, sizeof(*ipv6h)))) @@ -773,7 +773,7 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb, int features) { struct sk_buff *segs = ERR_PTR(-EINVAL); struct ipv6hdr *ipv6h; - struct inet6_protocol *ops; + const struct inet6_protocol *ops; int proto; struct frag_hdr *fptr; unsigned int unfrag_ip6hlen; @@ -840,7 +840,7 @@ struct ipv6_gro_cb { static struct sk_buff **ipv6_gro_receive(struct sk_buff **head, struct sk_buff *skb) { - struct inet6_protocol *ops; + const struct inet6_protocol *ops; struct sk_buff **pp = NULL; struct sk_buff *p; struct ipv6hdr *iph; @@ -926,7 +926,7 @@ out: static int ipv6_gro_complete(struct sk_buff *skb) { - struct inet6_protocol *ops; + const struct inet6_protocol *ops; struct ipv6hdr *iph = ipv6_hdr(skb); int err = -ENOSYS; diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c index 86f42a2..c1589e2 100644 --- a/net/ipv6/ah6.c +++ b/net/ipv6/ah6.c @@ -527,7 +527,7 @@ static const struct xfrm_type ah6_type = .hdr_offset = xfrm6_find_1stfragopt, }; -static struct inet6_protocol ah6_protocol = { +static const struct inet6_protocol ah6_protocol = { .handler = xfrm6_rcv, .err_handler = ah6_err, .flags = INET6_PROTO_NOPOLICY, diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c index 678bb95..af597c7 100644 --- a/net/ipv6/esp6.c +++ b/net/ipv6/esp6.c @@ -558,7 +558,7 @@ static const struct xfrm_type esp6_type = .hdr_offset = xfrm6_find_1stfragopt, }; -static struct inet6_protocol esp6_protocol = { +static const struct inet6_protocol esp6_protocol = { .handler = xfrm6_rcv, .err_handler = esp6_err, .flags = INET6_PROTO_NOPOLICY, diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c index 4aae658..df159ff 100644 --- a/net/ipv6/exthdrs.c +++ b/net/ipv6/exthdrs.c @@ -500,17 +500,17 @@ unknown_rh: return -1; } -static struct inet6_protocol rthdr_protocol = { +static const struct inet6_protocol rthdr_protocol = { .handler = ipv6_rthdr_rcv, .flags = INET6_PROTO_NOPOLICY | INET6_PROTO_GSO_EXTHDR, }; -static struct inet6_protocol destopt_protocol = { +static const struct inet6_protocol destopt_protocol = { .handler = ipv6_destopt_rcv, .flags = INET6_PROTO_NOPOLICY | INET6_PROTO_GSO_EXTHDR, }; -static struct inet6_protocol nodata_protocol = { +static const struct inet6_protocol nodata_protocol = { .handler = dst_discard, .flags = INET6_PROTO_NOPOLICY, }; diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index e2325f6..f23ebbe 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c @@ -86,7 +86,7 @@ static inline struct sock *icmpv6_sk(struct net *net) static int icmpv6_rcv(struct sk_buff *skb); -static struct inet6_protocol icmpv6_protocol = { +static const struct inet6_protocol icmpv6_protocol = { .handler = icmpv6_rcv, .flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL, }; @@ -583,7 +583,7 @@ out: static void icmpv6_notify(struct sk_buff *skb, u8 type, u8 code, __be32 info) { - struct inet6_protocol *ipprot; + const struct inet6_protocol *ipprot; int inner_offset; int hash; u8 nexthdr; diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c index 2d9cbaa..237e2db 100644 --- a/net/ipv6/ip6_input.c +++ b/net/ipv6/ip6_input.c @@ -159,7 +159,7 @@ drop: static int ip6_input_finish(struct sk_buff *skb) { - struct inet6_protocol *ipprot; + const struct inet6_protocol *ipprot; unsigned int nhoff; int nexthdr, raw; u8 hash; diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c index 5c8d737..3907510 100644 --- a/net/ipv6/ip6mr.c +++ b/net/ipv6/ip6mr.c @@ -83,10 +83,6 @@ static int ip6mr_cache_report(struct net *net, struct sk_buff *pkt, static int ip6mr_fill_mroute(struct sk_buff *skb, struct mfc6_cache *c, struct rtmsg *rtm); static void mroute_clean_tables(struct net *net); -#ifdef CONFIG_IPV6_PIMSM_V2 -static struct inet6_protocol pim6_protocol; -#endif - static struct timer_list ipmr_expire_timer; @@ -410,7 +406,7 @@ static int pim6_rcv(struct sk_buff *skb) return 0; } -static struct inet6_protocol pim6_protocol = { +static const struct inet6_protocol pim6_protocol = { .handler = pim6_rcv, }; diff --git a/net/ipv6/ipcomp6.c b/net/ipv6/ipcomp6.c index 79c172f..2f2a5ca 100644 --- a/net/ipv6/ipcomp6.c +++ b/net/ipv6/ipcomp6.c @@ -178,7 +178,7 @@ static const struct xfrm_type ipcomp6_type = .hdr_offset = xfrm6_find_1stfragopt, }; -static struct inet6_protocol ipcomp6_protocol = +static const struct inet6_protocol ipcomp6_protocol = { .handler = xfrm6_rcv, .err_handler = ipcomp6_err, diff --git a/net/ipv6/protocol.c b/net/ipv6/protocol.c index 568864f..1fa3468 100644 --- a/net/ipv6/protocol.c +++ b/net/ipv6/protocol.c @@ -25,11 +25,11 @@ #include #include -struct inet6_protocol *inet6_protos[MAX_INET_PROTOS]; +const struct inet6_protocol *inet6_protos[MAX_INET_PROTOS]; static DEFINE_SPINLOCK(inet6_proto_lock); -int inet6_add_protocol(struct inet6_protocol *prot, unsigned char protocol) +int inet6_add_protocol(const struct inet6_protocol *prot, unsigned char protocol) { int ret, hash = protocol & (MAX_INET_PROTOS - 1); @@ -53,7 +53,7 @@ EXPORT_SYMBOL(inet6_add_protocol); * Remove a protocol from the hash tables. */ -int inet6_del_protocol(struct inet6_protocol *prot, unsigned char protocol) +int inet6_del_protocol(const struct inet6_protocol *prot, unsigned char protocol) { int ret, hash = protocol & (MAX_INET_PROTOS - 1); diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c index 2642a41..da5bd0e 100644 --- a/net/ipv6/reassembly.c +++ b/net/ipv6/reassembly.c @@ -627,7 +627,7 @@ fail_hdr: return -1; } -static struct inet6_protocol frag_protocol = +static const struct inet6_protocol frag_protocol = { .handler = ipv6_frag_rcv, .flags = INET6_PROTO_NOPOLICY, diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 3aae0f2..7718a92 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -2093,7 +2093,7 @@ struct proto tcpv6_prot = { #endif }; -static struct inet6_protocol tcpv6_protocol = { +static const struct inet6_protocol tcpv6_protocol = { .handler = tcp_v6_rcv, .err_handler = tcp_v6_err, .gso_send_check = tcp_v6_gso_send_check, diff --git a/net/ipv6/tunnel6.c b/net/ipv6/tunnel6.c index 633ad78..51e2832 100644 --- a/net/ipv6/tunnel6.c +++ b/net/ipv6/tunnel6.c @@ -133,13 +133,13 @@ static void tunnel6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, break; } -static struct inet6_protocol tunnel6_protocol = { +static const struct inet6_protocol tunnel6_protocol = { .handler = tunnel6_rcv, .err_handler = tunnel6_err, .flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL, }; -static struct inet6_protocol tunnel46_protocol = { +static const struct inet6_protocol tunnel46_protocol = { .handler = tunnel46_rcv, .err_handler = tunnel6_err, .flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL, diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 1640406..b265b70 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -1172,7 +1172,7 @@ out: return segs; } -static struct inet6_protocol udpv6_protocol = { +static const struct inet6_protocol udpv6_protocol = { .handler = udpv6_rcv, .err_handler = udpv6_err, .gso_send_check = udp6_ufo_send_check, diff --git a/net/ipv6/udplite.c b/net/ipv6/udplite.c index 4818c48..d737a27 100644 --- a/net/ipv6/udplite.c +++ b/net/ipv6/udplite.c @@ -25,7 +25,7 @@ static void udplitev6_err(struct sk_buff *skb, __udp6_lib_err(skb, opt, type, code, offset, info, &udplite_table); } -static struct inet6_protocol udplitev6_protocol = { +static const struct inet6_protocol udplitev6_protocol = { .handler = udplitev6_rcv, .err_handler = udplitev6_err, .flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL, diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c index 6a4b190..bb280e6 100644 --- a/net/sctp/ipv6.c +++ b/net/sctp/ipv6.c @@ -949,7 +949,7 @@ static int sctp6_rcv(struct sk_buff *skb) return sctp_rcv(skb) ? -1 : 0; } -static struct inet6_protocol sctpv6_protocol = { +static const struct inet6_protocol sctpv6_protocol = { .handler = sctp6_rcv, .err_handler = sctp_v6_err, .flags = INET6_PROTO_NOPOLICY | INET6_PROTO_FINAL, -- cgit v1.1 From 5708e868dc512f055f0ea4a14d01f8252c3ca8a1 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Mon, 14 Sep 2009 12:23:23 +0000 Subject: net: constify remaining proto_ops Signed-off-by: Alexey Dobriyan Signed-off-by: David S. Miller --- net/dccp/ipv6.c | 2 +- net/iucv/af_iucv.c | 4 ++-- net/rds/af_rds.c | 2 +- net/rose/af_rose.c | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) (limited to 'net') diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c index 364bfc7..e48ca5d 100644 --- a/net/dccp/ipv6.c +++ b/net/dccp/ipv6.c @@ -1158,7 +1158,7 @@ static const struct inet6_protocol dccp_v6_protocol = { .flags = INET6_PROTO_NOPOLICY | INET6_PROTO_FINAL, }; -static struct proto_ops inet6_dccp_ops = { +static const struct proto_ops inet6_dccp_ops = { .family = PF_INET6, .owner = THIS_MODULE, .release = inet6_release, diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c index 49c15b4..3c915fb 100644 --- a/net/iucv/af_iucv.c +++ b/net/iucv/af_iucv.c @@ -34,7 +34,7 @@ static char iucv_userid[80]; -static struct proto_ops iucv_sock_ops; +static const struct proto_ops iucv_sock_ops; static struct proto iucv_proto = { .name = "AF_IUCV", @@ -1682,7 +1682,7 @@ static void iucv_callback_shutdown(struct iucv_path *path, u8 ipuser[16]) bh_unlock_sock(sk); } -static struct proto_ops iucv_sock_ops = { +static const struct proto_ops iucv_sock_ops = { .family = PF_IUCV, .owner = THIS_MODULE, .release = iucv_sock_release, diff --git a/net/rds/af_rds.c b/net/rds/af_rds.c index 108ed2e..6b58aef 100644 --- a/net/rds/af_rds.c +++ b/net/rds/af_rds.c @@ -359,7 +359,7 @@ static struct proto rds_proto = { .obj_size = sizeof(struct rds_sock), }; -static struct proto_ops rds_proto_ops = { +static const struct proto_ops rds_proto_ops = { .family = AF_RDS, .owner = THIS_MODULE, .release = rds_release, diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c index e5f478c..1e166c9 100644 --- a/net/rose/af_rose.c +++ b/net/rose/af_rose.c @@ -63,7 +63,7 @@ int sysctl_rose_window_size = ROSE_DEFAULT_WINDOW_SIZE; static HLIST_HEAD(rose_list); static DEFINE_SPINLOCK(rose_list_lock); -static struct proto_ops rose_proto_ops; +static const struct proto_ops rose_proto_ops; ax25_address rose_callsign; @@ -1515,7 +1515,7 @@ static struct net_proto_family rose_family_ops = { .owner = THIS_MODULE, }; -static struct proto_ops rose_proto_ops = { +static const struct proto_ops rose_proto_ops = { .family = PF_ROSE, .owner = THIS_MODULE, .release = rose_release, -- cgit v1.1 From b11b5165ae7b6506e0e4889b6bf6a11491e1ec6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Denis-Courmont?= Date: Mon, 14 Sep 2009 03:10:27 +0000 Subject: Phonet: Netlink event for autoconfigured addresses MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Rémi Denis-Courmont Signed-off-by: Rémi Denis-Courmont Signed-off-by: David S. Miller --- net/phonet/pn_dev.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'net') diff --git a/net/phonet/pn_dev.c b/net/phonet/pn_dev.c index 2f65dca..5f42f30 100644 --- a/net/phonet/pn_dev.c +++ b/net/phonet/pn_dev.c @@ -209,7 +209,14 @@ static int phonet_device_autoconf(struct net_device *dev) SIOCPNGAUTOCONF); if (ret < 0) return ret; - return phonet_address_add(dev, req.ifr_phonet_autoconf.device); + + ASSERT_RTNL(); + ret = phonet_address_add(dev, req.ifr_phonet_autoconf.device); + if (ret) + return ret; + phonet_address_notify(RTM_NEWADDR, dev, + req.ifr_phonet_autoconf.device); + return 0; } /* notify Phonet of device events */ -- cgit v1.1 From 036d6a673fa0a2e2c5b72a3b1d1b86114c1711c0 Mon Sep 17 00:00:00 2001 From: Jarek Poplawski Date: Sun, 13 Sep 2009 22:35:44 +0000 Subject: pkt_sched: Fix qdisc_graft WRT ingress qdisc After the recent mq change using ingress qdisc overwrites dev->qdisc; there is also a wrong old qdisc pointer passed to notify_and_destroy. Signed-off-by: Jarek Poplawski Signed-off-by: David S. Miller --- net/sched/sch_api.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'net') diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c index 692d9a4..c6e4063 100644 --- a/net/sched/sch_api.c +++ b/net/sched/sch_api.c @@ -693,13 +693,18 @@ static int qdisc_graft(struct net_device *dev, struct Qdisc *parent, if (new && i > 0) atomic_inc(&new->refcnt); - qdisc_destroy(old); + if (!ingress) + qdisc_destroy(old); } - notify_and_destroy(skb, n, classid, dev->qdisc, new); - if (new && !new->ops->attach) - atomic_inc(&new->refcnt); - dev->qdisc = new ? : &noop_qdisc; + if (!ingress) { + notify_and_destroy(skb, n, classid, dev->qdisc, new); + if (new && !new->ops->attach) + atomic_inc(&new->refcnt); + dev->qdisc = new ? : &noop_qdisc; + } else { + notify_and_destroy(skb, n, classid, old, new); + } if (dev->flags & IFF_UP) dev_activate(dev); -- cgit v1.1 From 0b6a05c1dbebe8c616e2e5b0f52b7a01fd792911 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ilpo=20J=C3=A4rvinen?= Date: Tue, 15 Sep 2009 01:30:10 -0700 Subject: tcp: fix ssthresh u16 leftover MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It was once upon time so that snd_sthresh was a 16-bit quantity. ...That has not been true for long period of time. I run across some ancient compares which still seem to trust such legacy. Put all that magic into a single place, I hopefully found all of them. Compile tested, though linking of allyesconfig is ridiculous nowadays it seems. Signed-off-by: Ilpo Järvinen Signed-off-by: David S. Miller --- net/ipv4/tcp.c | 2 +- net/ipv4/tcp_input.c | 2 +- net/ipv4/tcp_ipv4.c | 4 ++-- net/ipv4/tcp_minisocks.c | 2 +- net/ipv6/tcp_ipv6.c | 5 +++-- 5 files changed, 8 insertions(+), 7 deletions(-) (limited to 'net') diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index edeea06..19a0612 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -2012,7 +2012,7 @@ int tcp_disconnect(struct sock *sk, int flags) tp->snd_cwnd = 2; icsk->icsk_probes_out = 0; tp->packets_out = 0; - tp->snd_ssthresh = 0x7fffffff; + tp->snd_ssthresh = TCP_INFINITE_SSTHRESH; tp->snd_cwnd_cnt = 0; tp->bytes_acked = 0; tcp_set_ca_state(sk, TCP_CA_Open); diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index af6d6fa..d86784b 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -761,7 +761,7 @@ void tcp_update_metrics(struct sock *sk) set_dst_metric_rtt(dst, RTAX_RTTVAR, var); } - if (tp->snd_ssthresh >= 0xFFFF) { + if (tcp_in_initial_slowstart(tp)) { /* Slow start still did not finish. */ if (dst_metric(dst, RTAX_SSTHRESH) && !dst_metric_locked(dst, RTAX_SSTHRESH) && diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 0543561..7cda24b 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -1808,7 +1808,7 @@ static int tcp_v4_init_sock(struct sock *sk) /* See draft-stevens-tcpca-spec-01 for discussion of the * initialization of these values. */ - tp->snd_ssthresh = 0x7fffffff; /* Infinity */ + tp->snd_ssthresh = TCP_INFINITE_SSTHRESH; tp->snd_cwnd_clamp = ~0; tp->mss_cache = 536; @@ -2284,7 +2284,7 @@ static void get_tcp4_sock(struct sock *sk, struct seq_file *f, int i, int *len) jiffies_to_clock_t(icsk->icsk_ack.ato), (icsk->icsk_ack.quick << 1) | icsk->icsk_ack.pingpong, tp->snd_cwnd, - tp->snd_ssthresh >= 0xFFFF ? -1 : tp->snd_ssthresh, + tcp_in_initial_slowstart(tp) ? -1 : tp->snd_ssthresh, len); } diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c index e48c37d..045bcfd 100644 --- a/net/ipv4/tcp_minisocks.c +++ b/net/ipv4/tcp_minisocks.c @@ -410,7 +410,7 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct request_sock *req, newtp->retrans_out = 0; newtp->sacked_out = 0; newtp->fackets_out = 0; - newtp->snd_ssthresh = 0x7fffffff; + newtp->snd_ssthresh = TCP_INFINITE_SSTHRESH; /* So many TCP implementations out there (incorrectly) count the * initial SYN frame in their delayed-ACK and congestion control diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 7718a92..21d100b 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -1846,7 +1846,7 @@ static int tcp_v6_init_sock(struct sock *sk) /* See draft-stevens-tcpca-spec-01 for discussion of the * initialization of these values. */ - tp->snd_ssthresh = 0x7fffffff; + tp->snd_ssthresh = TCP_INFINITE_SSTHRESH; tp->snd_cwnd_clamp = ~0; tp->mss_cache = 536; @@ -1969,7 +1969,8 @@ static void get_tcp6_sock(struct seq_file *seq, struct sock *sp, int i) jiffies_to_clock_t(icsk->icsk_rto), jiffies_to_clock_t(icsk->icsk_ack.ato), (icsk->icsk_ack.quick << 1 ) | icsk->icsk_ack.pingpong, - tp->snd_cwnd, tp->snd_ssthresh>=0xFFFF?-1:tp->snd_ssthresh + tp->snd_cwnd, + tcp_in_initial_slowstart(tp) ? -1 : tp->snd_ssthresh ); } -- cgit v1.1 From 481a8199142c050b72bff8a1956a49fd0a75bbe0 Mon Sep 17 00:00:00 2001 From: Oliver Hartkopp Date: Tue, 15 Sep 2009 01:31:34 -0700 Subject: can: fix NOHZ local_softirq_pending 08 warning When using nanosleep() in an userspace application we get a ratelimit warning NOHZ: local_softirq_pending 08 for 10 times. The echo of CAN frames is done from process context and softirq context only. Therefore the usage of netif_rx() was wrong (for years). This patch replaces netif_rx() with netif_rx_ni() which has to be used from process/softirq context. It also adds a missing comment that can_send() must no be used from hardirq context. Signed-off-by: Oliver Hartkopp Signed-off-by: Urs Thuermann Signed-off-by: David S. Miller --- net/can/af_can.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'net') diff --git a/net/can/af_can.c b/net/can/af_can.c index ef1c43a..6068321 100644 --- a/net/can/af_can.c +++ b/net/can/af_can.c @@ -199,6 +199,8 @@ static int can_create(struct net *net, struct socket *sock, int protocol) * @skb: pointer to socket buffer with CAN frame in data section * @loop: loopback for listeners on local CAN sockets (recommended default!) * + * Due to the loopback this routine must not be called from hardirq context. + * * Return: * 0 on success * -ENETDOWN when the selected interface is down @@ -278,7 +280,7 @@ int can_send(struct sk_buff *skb, int loop) } if (newskb) - netif_rx(newskb); + netif_rx_ni(newskb); /* update statistics */ can_stats.tx_frames++; -- cgit v1.1 From 75c78500ddad74b229cd0691496b8549490496a2 Mon Sep 17 00:00:00 2001 From: Moni Shoua Date: Tue, 15 Sep 2009 02:37:40 -0700 Subject: bonding: remap muticast addresses without using dev_close() and dev_open() This patch fixes commit e36b9d16c6a6d0f59803b3ef04ff3c22c3844c10. The approach there is to call dev_close()/dev_open() whenever the device type is changed in order to remap the device IP multicast addresses to HW multicast addresses. This approach suffers from 2 drawbacks: *. It assumes tha the device is UP when calling dev_close(), or otherwise dev_close() has no affect. It is worth to mention that initscripts (Redhat) and sysconfig (Suse) doesn't act the same in this matter. *. dev_close() has other side affects, like deleting entries from the routing table, which might be unnecessary. The fix here is to directly remap the IP multicast addresses to HW multicast addresses for a bonding device that changes its type, and nothing else. Reported-by: Jason Gunthorpe Signed-off-by: Moni Shoua Signed-off-by: David S. Miller --- net/core/dev.c | 4 ++-- net/ipv4/devinet.c | 6 ++++++ net/ipv4/igmp.c | 22 ++++++++++++++++++++++ net/ipv6/addrconf.c | 19 +++++++++++++++++++ net/ipv6/mcast.c | 19 +++++++++++++++++++ 5 files changed, 68 insertions(+), 2 deletions(-) (limited to 'net') diff --git a/net/core/dev.c b/net/core/dev.c index 8494547..560c8c9 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1017,9 +1017,9 @@ void netdev_state_change(struct net_device *dev) } EXPORT_SYMBOL(netdev_state_change); -void netdev_bonding_change(struct net_device *dev) +void netdev_bonding_change(struct net_device *dev, unsigned long event) { - call_netdevice_notifiers(NETDEV_BONDING_FAILOVER, dev); + call_netdevice_notifiers(event, dev); } EXPORT_SYMBOL(netdev_bonding_change); diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c index 3863c3a..07336c6 100644 --- a/net/ipv4/devinet.c +++ b/net/ipv4/devinet.c @@ -1087,6 +1087,12 @@ static int inetdev_event(struct notifier_block *this, unsigned long event, case NETDEV_DOWN: ip_mc_down(in_dev); break; + case NETDEV_BONDING_OLDTYPE: + ip_mc_unmap(in_dev); + break; + case NETDEV_BONDING_NEWTYPE: + ip_mc_remap(in_dev); + break; case NETDEV_CHANGEMTU: if (inetdev_valid_mtu(dev->mtu)) break; diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c index 01b4284..d41e5de 100644 --- a/net/ipv4/igmp.c +++ b/net/ipv4/igmp.c @@ -1298,6 +1298,28 @@ void ip_mc_dec_group(struct in_device *in_dev, __be32 addr) } } +/* Device changing type */ + +void ip_mc_unmap(struct in_device *in_dev) +{ + struct ip_mc_list *i; + + ASSERT_RTNL(); + + for (i = in_dev->mc_list; i; i = i->next) + igmp_group_dropped(i); +} + +void ip_mc_remap(struct in_device *in_dev) +{ + struct ip_mc_list *i; + + ASSERT_RTNL(); + + for (i = in_dev->mc_list; i; i = i->next) + igmp_group_added(i); +} + /* Device going down */ void ip_mc_down(struct in_device *in_dev) diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index c9b3690..f216a41 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -137,6 +137,8 @@ static DEFINE_SPINLOCK(addrconf_verify_lock); static void addrconf_join_anycast(struct inet6_ifaddr *ifp); static void addrconf_leave_anycast(struct inet6_ifaddr *ifp); +static void addrconf_bonding_change(struct net_device *dev, + unsigned long event); static int addrconf_ifdown(struct net_device *dev, int how); static void addrconf_dad_start(struct inet6_ifaddr *ifp, u32 flags); @@ -2582,6 +2584,10 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event, return notifier_from_errno(err); } break; + case NETDEV_BONDING_OLDTYPE: + case NETDEV_BONDING_NEWTYPE: + addrconf_bonding_change(dev, event); + break; } return NOTIFY_OK; @@ -2595,6 +2601,19 @@ static struct notifier_block ipv6_dev_notf = { .priority = 0 }; +static void addrconf_bonding_change(struct net_device *dev, unsigned long event) +{ + struct inet6_dev *idev; + ASSERT_RTNL(); + + idev = __in6_dev_get(dev); + + if (event == NETDEV_BONDING_NEWTYPE) + ipv6_mc_remap(idev); + else if (event == NETDEV_BONDING_OLDTYPE) + ipv6_mc_unmap(idev); +} + static int addrconf_ifdown(struct net_device *dev, int how) { struct inet6_dev *idev; diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c index 71c3dac..f9fcf69 100644 --- a/net/ipv6/mcast.c +++ b/net/ipv6/mcast.c @@ -2249,6 +2249,25 @@ static void igmp6_timer_handler(unsigned long data) ma_put(ma); } +/* Device changing type */ + +void ipv6_mc_unmap(struct inet6_dev *idev) +{ + struct ifmcaddr6 *i; + + /* Install multicast list, except for all-nodes (already installed) */ + + read_lock_bh(&idev->lock); + for (i = idev->mc_list; i; i = i->next) + igmp6_group_dropped(i); + read_unlock_bh(&idev->lock); +} + +void ipv6_mc_remap(struct inet6_dev *idev) +{ + ipv6_mc_up(idev); +} + /* Device going down */ void ipv6_mc_down(struct inet6_dev *idev) -- cgit v1.1 From 29a020d35f629619c67fa5e32acaaac3f8a1ba90 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Tue, 15 Sep 2009 02:39:20 -0700 Subject: [PATCH] net: kmemcheck annotation in struct socket struct socket has a 16 bit hole that triggers kmemcheck warnings. As suggested by Ingo, use kmemcheck annotations Signed-off-by: Eric Dumazet Acked-by: Ingo Molnar Signed-off-by: David S. Miller --- net/socket.c | 1 + 1 file changed, 1 insertion(+) (limited to 'net') diff --git a/net/socket.c b/net/socket.c index 6d47165..2a022c0 100644 --- a/net/socket.c +++ b/net/socket.c @@ -489,6 +489,7 @@ static struct socket *sock_alloc(void) sock = SOCKET_I(inode); + kmemcheck_annotate_bitfield(sock, type); inode->i_mode = S_IFSOCK | S_IRWXUGO; inode->i_uid = current_fsuid(); inode->i_gid = current_fsgid(); -- cgit v1.1 From 8b815477f382f96deefbe5bd4404fa7b31cf5dcf Mon Sep 17 00:00:00 2001 From: David Howells Date: Mon, 14 Sep 2009 01:17:30 +0000 Subject: RxRPC: Declare the security index constants symbolically Declare the security index constants symbolically rather than just referring to them numerically. Signed-off-by: David Howells Signed-off-by: David S. Miller --- net/rxrpc/ar-key.c | 4 ++-- net/rxrpc/rxkad.c | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'net') diff --git a/net/rxrpc/ar-key.c b/net/rxrpc/ar-key.c index ad8c7a7..b3d10e7 100644 --- a/net/rxrpc/ar-key.c +++ b/net/rxrpc/ar-key.c @@ -122,7 +122,7 @@ static int rxrpc_instantiate(struct key *key, const void *data, size_t datalen) tsec->ticket[6], tsec->ticket[7]); ret = -EPROTONOSUPPORT; - if (tsec->security_index != 2) + if (tsec->security_index != RXRPC_SECURITY_RXKAD) goto error; key->type_data.x[0] = tsec->security_index; @@ -308,7 +308,7 @@ int rxrpc_get_server_data_key(struct rxrpc_connection *conn, _debug("key %d", key_serial(key)); data.kver = 1; - data.tsec.security_index = 2; + data.tsec.security_index = RXRPC_SECURITY_RXKAD; data.tsec.ticket_len = 0; data.tsec.expiry = expiry; data.tsec.kvno = 0; diff --git a/net/rxrpc/rxkad.c b/net/rxrpc/rxkad.c index ef8f910..acec762 100644 --- a/net/rxrpc/rxkad.c +++ b/net/rxrpc/rxkad.c @@ -42,7 +42,7 @@ struct rxkad_level2_hdr { __be32 checksum; /* decrypted data checksum */ }; -MODULE_DESCRIPTION("RxRPC network protocol type-2 security (Kerberos)"); +MODULE_DESCRIPTION("RxRPC network protocol type-2 security (Kerberos 4)"); MODULE_AUTHOR("Red Hat, Inc."); MODULE_LICENSE("GPL"); @@ -506,7 +506,7 @@ static int rxkad_verify_packet(const struct rxrpc_call *call, if (!call->conn->cipher) return 0; - if (sp->hdr.securityIndex != 2) { + if (sp->hdr.securityIndex != RXRPC_SECURITY_RXKAD) { *_abort_code = RXKADINCONSISTENCY; _leave(" = -EPROTO [not rxkad]"); return -EPROTO; @@ -1122,7 +1122,7 @@ static void rxkad_clear(struct rxrpc_connection *conn) static struct rxrpc_security rxkad = { .owner = THIS_MODULE, .name = "rxkad", - .security_index = RXKAD_VERSION, + .security_index = RXRPC_SECURITY_RXKAD, .init_connection_security = rxkad_init_connection_security, .prime_packet_security = rxkad_prime_packet_security, .secure_packet = rxkad_secure_packet, -- cgit v1.1 From 339412841d7620f93fea805fbd7469f08186f458 Mon Sep 17 00:00:00 2001 From: David Howells Date: Mon, 14 Sep 2009 01:17:35 +0000 Subject: RxRPC: Allow key payloads to be passed in XDR form Allow add_key() and KEYCTL_INSTANTIATE to accept key payloads in XDR form as described by openafs-1.4.10/src/auth/afs_token.xg. This provides a way of passing kaserver, Kerberos 4, Kerberos 5 and GSSAPI keys from userspace, and allows for future expansion. Signed-off-by: David Howells Signed-off-by: David S. Miller --- net/rxrpc/ar-internal.h | 16 --- net/rxrpc/ar-key.c | 308 ++++++++++++++++++++++++++++++++++++++++++------ net/rxrpc/ar-security.c | 8 +- net/rxrpc/rxkad.c | 41 +++---- 4 files changed, 298 insertions(+), 75 deletions(-) (limited to 'net') diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h index 3e7318c..46c6d88 100644 --- a/net/rxrpc/ar-internal.h +++ b/net/rxrpc/ar-internal.h @@ -402,22 +402,6 @@ struct rxrpc_call { }; /* - * RxRPC key for Kerberos (type-2 security) - */ -struct rxkad_key { - u16 security_index; /* RxRPC header security index */ - u16 ticket_len; /* length of ticket[] */ - u32 expiry; /* time at which expires */ - u32 kvno; /* key version number */ - u8 session_key[8]; /* DES session key */ - u8 ticket[0]; /* the encrypted ticket */ -}; - -struct rxrpc_key_payload { - struct rxkad_key k; -}; - -/* * locally abort an RxRPC call */ static inline void rxrpc_abort_call(struct rxrpc_call *call, u32 abort_code) diff --git a/net/rxrpc/ar-key.c b/net/rxrpc/ar-key.c index b3d10e7..a3a7acb 100644 --- a/net/rxrpc/ar-key.c +++ b/net/rxrpc/ar-key.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -55,6 +56,202 @@ struct key_type key_type_rxrpc_s = { }; /* + * parse an RxKAD type XDR format token + * - the caller guarantees we have at least 4 words + */ +static int rxrpc_instantiate_xdr_rxkad(struct key *key, const __be32 *xdr, + unsigned toklen) +{ + struct rxrpc_key_token *token; + size_t plen; + u32 tktlen; + int ret; + + _enter(",{%x,%x,%x,%x},%u", + ntohl(xdr[0]), ntohl(xdr[1]), ntohl(xdr[2]), ntohl(xdr[3]), + toklen); + + if (toklen <= 8 * 4) + return -EKEYREJECTED; + tktlen = ntohl(xdr[7]); + _debug("tktlen: %x", tktlen); + if (tktlen > AFSTOKEN_RK_TIX_MAX) + return -EKEYREJECTED; + if (8 * 4 + tktlen != toklen) + return -EKEYREJECTED; + + plen = sizeof(*token) + sizeof(*token->kad) + tktlen; + ret = key_payload_reserve(key, key->datalen + plen); + if (ret < 0) + return ret; + + plen -= sizeof(*token); + token = kmalloc(sizeof(*token), GFP_KERNEL); + if (!token) + return -ENOMEM; + + token->kad = kmalloc(plen, GFP_KERNEL); + if (!token->kad) { + kfree(token); + return -ENOMEM; + } + + token->security_index = RXRPC_SECURITY_RXKAD; + token->kad->ticket_len = tktlen; + token->kad->vice_id = ntohl(xdr[0]); + token->kad->kvno = ntohl(xdr[1]); + token->kad->start = ntohl(xdr[4]); + token->kad->expiry = ntohl(xdr[5]); + token->kad->primary_flag = ntohl(xdr[6]); + memcpy(&token->kad->session_key, &xdr[2], 8); + memcpy(&token->kad->ticket, &xdr[8], tktlen); + + _debug("SCIX: %u", token->security_index); + _debug("TLEN: %u", token->kad->ticket_len); + _debug("EXPY: %x", token->kad->expiry); + _debug("KVNO: %u", token->kad->kvno); + _debug("PRIM: %u", token->kad->primary_flag); + _debug("SKEY: %02x%02x%02x%02x%02x%02x%02x%02x", + token->kad->session_key[0], token->kad->session_key[1], + token->kad->session_key[2], token->kad->session_key[3], + token->kad->session_key[4], token->kad->session_key[5], + token->kad->session_key[6], token->kad->session_key[7]); + if (token->kad->ticket_len >= 8) + _debug("TCKT: %02x%02x%02x%02x%02x%02x%02x%02x", + token->kad->ticket[0], token->kad->ticket[1], + token->kad->ticket[2], token->kad->ticket[3], + token->kad->ticket[4], token->kad->ticket[5], + token->kad->ticket[6], token->kad->ticket[7]); + + /* count the number of tokens attached */ + key->type_data.x[0]++; + + /* attach the data */ + token->next = key->payload.data; + key->payload.data = token; + if (token->kad->expiry < key->expiry) + key->expiry = token->kad->expiry; + + _leave(" = 0"); + return 0; +} + +/* + * attempt to parse the data as the XDR format + * - the caller guarantees we have more than 7 words + */ +static int rxrpc_instantiate_xdr(struct key *key, const void *data, size_t datalen) +{ + const __be32 *xdr = data, *token; + const char *cp; + unsigned len, tmp, loop, ntoken, toklen, sec_ix; + int ret; + + _enter(",{%x,%x,%x,%x},%zu", + ntohl(xdr[0]), ntohl(xdr[1]), ntohl(xdr[2]), ntohl(xdr[3]), + datalen); + + if (datalen > AFSTOKEN_LENGTH_MAX) + goto not_xdr; + + /* XDR is an array of __be32's */ + if (datalen & 3) + goto not_xdr; + + /* the flags should be 0 (the setpag bit must be handled by + * userspace) */ + if (ntohl(*xdr++) != 0) + goto not_xdr; + datalen -= 4; + + /* check the cell name */ + len = ntohl(*xdr++); + if (len < 1 || len > AFSTOKEN_CELL_MAX) + goto not_xdr; + datalen -= 4; + tmp = (len + 3) & ~3; + if (tmp > datalen) + goto not_xdr; + + cp = (const char *) xdr; + for (loop = 0; loop < len; loop++) + if (!isprint(cp[loop])) + goto not_xdr; + if (len < tmp) + for (; loop < tmp; loop++) + if (cp[loop]) + goto not_xdr; + _debug("cellname: [%u/%u] '%*.*s'", + len, tmp, len, len, (const char *) xdr); + datalen -= tmp; + xdr += tmp >> 2; + + /* get the token count */ + if (datalen < 12) + goto not_xdr; + ntoken = ntohl(*xdr++); + datalen -= 4; + _debug("ntoken: %x", ntoken); + if (ntoken < 1 || ntoken > AFSTOKEN_MAX) + goto not_xdr; + + /* check each token wrapper */ + token = xdr; + loop = ntoken; + do { + if (datalen < 8) + goto not_xdr; + toklen = ntohl(*xdr++); + sec_ix = ntohl(*xdr); + datalen -= 4; + _debug("token: [%x/%zx] %x", toklen, datalen, sec_ix); + if (toklen < 20 || toklen > datalen) + goto not_xdr; + datalen -= (toklen + 3) & ~3; + xdr += (toklen + 3) >> 2; + + } while (--loop > 0); + + _debug("remainder: %zu", datalen); + if (datalen != 0) + goto not_xdr; + + /* okay: we're going to assume it's valid XDR format + * - we ignore the cellname, relying on the key to be correctly named + */ + do { + xdr = token; + toklen = ntohl(*xdr++); + token = xdr + ((toklen + 3) >> 2); + sec_ix = ntohl(*xdr++); + toklen -= 4; + + switch (sec_ix) { + case RXRPC_SECURITY_RXKAD: + ret = rxrpc_instantiate_xdr_rxkad(key, xdr, toklen); + if (ret != 0) + goto error; + break; + + default: + ret = -EPROTONOSUPPORT; + goto error; + } + + } while (--ntoken > 0); + + _leave(" = 0"); + return 0; + +not_xdr: + _leave(" = -EPROTO"); + return -EPROTO; +error: + _leave(" = %d", ret); + return ret; +} + +/* * instantiate an rxrpc defined key * data should be of the form: * OFFSET LEN CONTENT @@ -70,8 +267,8 @@ struct key_type key_type_rxrpc_s = { */ static int rxrpc_instantiate(struct key *key, const void *data, size_t datalen) { - const struct rxkad_key *tsec; - struct rxrpc_key_payload *upayload; + const struct rxrpc_key_data_v1 *v1; + struct rxrpc_key_token *token, **pp; size_t plen; u32 kver; int ret; @@ -82,6 +279,13 @@ static int rxrpc_instantiate(struct key *key, const void *data, size_t datalen) if (!data && datalen == 0) return 0; + /* determine if the XDR payload format is being used */ + if (datalen > 7 * 4) { + ret = rxrpc_instantiate_xdr(key, data, datalen); + if (ret != -EPROTO) + return ret; + } + /* get the key interface version number */ ret = -EINVAL; if (datalen <= 4 || !data) @@ -98,53 +302,67 @@ static int rxrpc_instantiate(struct key *key, const void *data, size_t datalen) /* deal with a version 1 key */ ret = -EINVAL; - if (datalen < sizeof(*tsec)) + if (datalen < sizeof(*v1)) goto error; - tsec = data; - if (datalen != sizeof(*tsec) + tsec->ticket_len) + v1 = data; + if (datalen != sizeof(*v1) + v1->ticket_length) goto error; - _debug("SCIX: %u", tsec->security_index); - _debug("TLEN: %u", tsec->ticket_len); - _debug("EXPY: %x", tsec->expiry); - _debug("KVNO: %u", tsec->kvno); + _debug("SCIX: %u", v1->security_index); + _debug("TLEN: %u", v1->ticket_length); + _debug("EXPY: %x", v1->expiry); + _debug("KVNO: %u", v1->kvno); _debug("SKEY: %02x%02x%02x%02x%02x%02x%02x%02x", - tsec->session_key[0], tsec->session_key[1], - tsec->session_key[2], tsec->session_key[3], - tsec->session_key[4], tsec->session_key[5], - tsec->session_key[6], tsec->session_key[7]); - if (tsec->ticket_len >= 8) + v1->session_key[0], v1->session_key[1], + v1->session_key[2], v1->session_key[3], + v1->session_key[4], v1->session_key[5], + v1->session_key[6], v1->session_key[7]); + if (v1->ticket_length >= 8) _debug("TCKT: %02x%02x%02x%02x%02x%02x%02x%02x", - tsec->ticket[0], tsec->ticket[1], - tsec->ticket[2], tsec->ticket[3], - tsec->ticket[4], tsec->ticket[5], - tsec->ticket[6], tsec->ticket[7]); + v1->ticket[0], v1->ticket[1], + v1->ticket[2], v1->ticket[3], + v1->ticket[4], v1->ticket[5], + v1->ticket[6], v1->ticket[7]); ret = -EPROTONOSUPPORT; - if (tsec->security_index != RXRPC_SECURITY_RXKAD) + if (v1->security_index != RXRPC_SECURITY_RXKAD) goto error; - key->type_data.x[0] = tsec->security_index; - - plen = sizeof(*upayload) + tsec->ticket_len; - ret = key_payload_reserve(key, plen); + plen = sizeof(*token->kad) + v1->ticket_length; + ret = key_payload_reserve(key, plen + sizeof(*token)); if (ret < 0) goto error; ret = -ENOMEM; - upayload = kmalloc(plen, GFP_KERNEL); - if (!upayload) + token = kmalloc(sizeof(*token), GFP_KERNEL); + if (!token) goto error; + token->kad = kmalloc(plen, GFP_KERNEL); + if (!token->kad) + goto error_free; + + token->security_index = RXRPC_SECURITY_RXKAD; + token->kad->ticket_len = v1->ticket_length; + token->kad->expiry = v1->expiry; + token->kad->kvno = v1->kvno; + memcpy(&token->kad->session_key, &v1->session_key, 8); + memcpy(&token->kad->ticket, v1->ticket, v1->ticket_length); /* attach the data */ - memcpy(&upayload->k, tsec, sizeof(*tsec)); - memcpy(&upayload->k.ticket, (void *)tsec + sizeof(*tsec), - tsec->ticket_len); - key->payload.data = upayload; - key->expiry = tsec->expiry; + key->type_data.x[0]++; + + pp = (struct rxrpc_key_token **)&key->payload.data; + while (*pp) + pp = &(*pp)->next; + *pp = token; + if (token->kad->expiry < key->expiry) + key->expiry = token->kad->expiry; + token = NULL; ret = 0; +error_free: + kfree(token); error: return ret; } @@ -184,7 +402,22 @@ static int rxrpc_instantiate_s(struct key *key, const void *data, */ static void rxrpc_destroy(struct key *key) { - kfree(key->payload.data); + struct rxrpc_key_token *token; + + while ((token = key->payload.data)) { + key->payload.data = token->next; + switch (token->security_index) { + case RXRPC_SECURITY_RXKAD: + kfree(token->kad); + break; + default: + printk(KERN_ERR "Unknown token type %x on rxrpc key\n", + token->security_index); + BUG(); + } + + kfree(token); + } } /* @@ -293,7 +526,7 @@ int rxrpc_get_server_data_key(struct rxrpc_connection *conn, struct { u32 kver; - struct rxkad_key tsec; + struct rxrpc_key_data_v1 v1; } data; _enter(""); @@ -308,13 +541,12 @@ int rxrpc_get_server_data_key(struct rxrpc_connection *conn, _debug("key %d", key_serial(key)); data.kver = 1; - data.tsec.security_index = RXRPC_SECURITY_RXKAD; - data.tsec.ticket_len = 0; - data.tsec.expiry = expiry; - data.tsec.kvno = 0; + data.v1.security_index = RXRPC_SECURITY_RXKAD; + data.v1.ticket_length = 0; + data.v1.expiry = expiry; + data.v1.kvno = 0; - memcpy(&data.tsec.session_key, session_key, - sizeof(data.tsec.session_key)); + memcpy(&data.v1.session_key, session_key, sizeof(data.v1.session_key)); ret = key_instantiate_and_link(key, &data, sizeof(data), NULL, NULL); if (ret < 0) diff --git a/net/rxrpc/ar-security.c b/net/rxrpc/ar-security.c index dc62920e..49b3cc31 100644 --- a/net/rxrpc/ar-security.c +++ b/net/rxrpc/ar-security.c @@ -16,6 +16,7 @@ #include #include #include +#include #include "ar-internal.h" static LIST_HEAD(rxrpc_security_methods); @@ -122,6 +123,7 @@ EXPORT_SYMBOL_GPL(rxrpc_unregister_security); */ int rxrpc_init_client_conn_security(struct rxrpc_connection *conn) { + struct rxrpc_key_token *token; struct rxrpc_security *sec; struct key *key = conn->key; int ret; @@ -135,7 +137,11 @@ int rxrpc_init_client_conn_security(struct rxrpc_connection *conn) if (ret < 0) return ret; - sec = rxrpc_security_lookup(key->type_data.x[0]); + if (!key->payload.data) + return -EKEYREJECTED; + token = key->payload.data; + + sec = rxrpc_security_lookup(token->security_index); if (!sec) return -EKEYREJECTED; conn->security = sec; diff --git a/net/rxrpc/rxkad.c b/net/rxrpc/rxkad.c index acec762..713ac59 100644 --- a/net/rxrpc/rxkad.c +++ b/net/rxrpc/rxkad.c @@ -18,6 +18,7 @@ #include #include #include +#include #define rxrpc_debug rxkad_debug #include "ar-internal.h" @@ -59,14 +60,14 @@ static DEFINE_MUTEX(rxkad_ci_mutex); */ static int rxkad_init_connection_security(struct rxrpc_connection *conn) { - struct rxrpc_key_payload *payload; struct crypto_blkcipher *ci; + struct rxrpc_key_token *token; int ret; _enter("{%d},{%x}", conn->debug_id, key_serial(conn->key)); - payload = conn->key->payload.data; - conn->security_ix = payload->k.security_index; + token = conn->key->payload.data; + conn->security_ix = token->security_index; ci = crypto_alloc_blkcipher("pcbc(fcrypt)", 0, CRYPTO_ALG_ASYNC); if (IS_ERR(ci)) { @@ -75,8 +76,8 @@ static int rxkad_init_connection_security(struct rxrpc_connection *conn) goto error; } - if (crypto_blkcipher_setkey(ci, payload->k.session_key, - sizeof(payload->k.session_key)) < 0) + if (crypto_blkcipher_setkey(ci, token->kad->session_key, + sizeof(token->kad->session_key)) < 0) BUG(); switch (conn->security_level) { @@ -110,7 +111,7 @@ error: */ static void rxkad_prime_packet_security(struct rxrpc_connection *conn) { - struct rxrpc_key_payload *payload; + struct rxrpc_key_token *token; struct blkcipher_desc desc; struct scatterlist sg[2]; struct rxrpc_crypt iv; @@ -123,8 +124,8 @@ static void rxkad_prime_packet_security(struct rxrpc_connection *conn) if (!conn->key) return; - payload = conn->key->payload.data; - memcpy(&iv, payload->k.session_key, sizeof(iv)); + token = conn->key->payload.data; + memcpy(&iv, token->kad->session_key, sizeof(iv)); desc.tfm = conn->cipher; desc.info = iv.x; @@ -197,7 +198,7 @@ static int rxkad_secure_packet_encrypt(const struct rxrpc_call *call, u32 data_size, void *sechdr) { - const struct rxrpc_key_payload *payload; + const struct rxrpc_key_token *token; struct rxkad_level2_hdr rxkhdr __attribute__((aligned(8))); /* must be all on one page */ struct rxrpc_skb_priv *sp; @@ -219,8 +220,8 @@ static int rxkad_secure_packet_encrypt(const struct rxrpc_call *call, rxkhdr.checksum = 0; /* encrypt from the session key */ - payload = call->conn->key->payload.data; - memcpy(&iv, payload->k.session_key, sizeof(iv)); + token = call->conn->key->payload.data; + memcpy(&iv, token->kad->session_key, sizeof(iv)); desc.tfm = call->conn->cipher; desc.info = iv.x; desc.flags = 0; @@ -400,7 +401,7 @@ static int rxkad_verify_packet_encrypt(const struct rxrpc_call *call, struct sk_buff *skb, u32 *_abort_code) { - const struct rxrpc_key_payload *payload; + const struct rxrpc_key_token *token; struct rxkad_level2_hdr sechdr; struct rxrpc_skb_priv *sp; struct blkcipher_desc desc; @@ -431,8 +432,8 @@ static int rxkad_verify_packet_encrypt(const struct rxrpc_call *call, skb_to_sgvec(skb, sg, 0, skb->len); /* decrypt from the session key */ - payload = call->conn->key->payload.data; - memcpy(&iv, payload->k.session_key, sizeof(iv)); + token = call->conn->key->payload.data; + memcpy(&iv, token->kad->session_key, sizeof(iv)); desc.tfm = call->conn->cipher; desc.info = iv.x; desc.flags = 0; @@ -737,7 +738,7 @@ static int rxkad_respond_to_challenge(struct rxrpc_connection *conn, struct sk_buff *skb, u32 *_abort_code) { - const struct rxrpc_key_payload *payload; + const struct rxrpc_key_token *token; struct rxkad_challenge challenge; struct rxkad_response resp __attribute__((aligned(8))); /* must be aligned for crypto */ @@ -778,7 +779,7 @@ static int rxkad_respond_to_challenge(struct rxrpc_connection *conn, if (conn->security_level < min_level) goto protocol_error; - payload = conn->key->payload.data; + token = conn->key->payload.data; /* build the response packet */ memset(&resp, 0, sizeof(resp)); @@ -797,13 +798,13 @@ static int rxkad_respond_to_challenge(struct rxrpc_connection *conn, (conn->channels[3] ? conn->channels[3]->call_id : 0); resp.encrypted.inc_nonce = htonl(nonce + 1); resp.encrypted.level = htonl(conn->security_level); - resp.kvno = htonl(payload->k.kvno); - resp.ticket_len = htonl(payload->k.ticket_len); + resp.kvno = htonl(token->kad->kvno); + resp.ticket_len = htonl(token->kad->ticket_len); /* calculate the response checksum and then do the encryption */ rxkad_calc_response_checksum(&resp); - rxkad_encrypt_response(conn, &resp, &payload->k); - return rxkad_send_response(conn, &sp->hdr, &resp, &payload->k); + rxkad_encrypt_response(conn, &resp, token->kad); + return rxkad_send_response(conn, &sp->hdr, &resp, token->kad); protocol_error: *_abort_code = abort_code; -- cgit v1.1 From ed6dd18b5aceb322da9840f01a68d648e91c8a72 Mon Sep 17 00:00:00 2001 From: David Howells Date: Mon, 14 Sep 2009 01:17:40 +0000 Subject: RxRPC: Allow RxRPC keys to be read Allow RxRPC keys to be read. This is to allow pioctl() to be implemented in userspace. RxRPC keys are read out in XDR format. Signed-off-by: David Howells Signed-off-by: David S. Miller --- net/rxrpc/ar-key.c | 109 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 109 insertions(+) (limited to 'net') diff --git a/net/rxrpc/ar-key.c b/net/rxrpc/ar-key.c index a3a7acb..bf4d623 100644 --- a/net/rxrpc/ar-key.c +++ b/net/rxrpc/ar-key.c @@ -29,6 +29,7 @@ static int rxrpc_instantiate_s(struct key *, const void *, size_t); static void rxrpc_destroy(struct key *); static void rxrpc_destroy_s(struct key *); static void rxrpc_describe(const struct key *, struct seq_file *); +static long rxrpc_read(const struct key *, char __user *, size_t); /* * rxrpc defined keys take an arbitrary string as the description and an @@ -40,6 +41,7 @@ struct key_type key_type_rxrpc = { .match = user_match, .destroy = rxrpc_destroy, .describe = rxrpc_describe, + .read = rxrpc_read, }; EXPORT_SYMBOL(key_type_rxrpc); @@ -592,3 +594,110 @@ struct key *rxrpc_get_null_key(const char *keyname) return key; } EXPORT_SYMBOL(rxrpc_get_null_key); + +/* + * read the contents of an rxrpc key + * - this returns the result in XDR form + */ +static long rxrpc_read(const struct key *key, + char __user *buffer, size_t buflen) +{ + struct rxrpc_key_token *token; + size_t size, toksize; + __be32 __user *xdr; + u32 cnlen, tktlen, ntoks, zero; + + _enter(""); + + /* we don't know what form we should return non-AFS keys in */ + if (memcmp(key->description, "afs@", 4) != 0) + return -EOPNOTSUPP; + cnlen = strlen(key->description + 4); + + /* AFS keys we return in XDR form, so we need to work out the size of + * the XDR */ + size = 2 * 4; /* flags, cellname len */ + size += (cnlen + 3) & ~3; /* cellname */ + size += 1 * 4; /* token count */ + + ntoks = 0; + for (token = key->payload.data; token; token = token->next) { + switch (token->security_index) { + case RXRPC_SECURITY_RXKAD: + size += 2 * 4; /* length, security index (switch ID) */ + size += 8 * 4; /* viceid, kvno, key*2, begin, end, + * primary, tktlen */ + size += (token->kad->ticket_len + 3) & ~3; /* ticket */ + ntoks++; + break; + + default: /* can't encode */ + break; + } + } + + if (!buffer || buflen < size) + return size; + + xdr = (__be32 __user *) buffer; + zero = 0; +#define ENCODE(x) \ + do { \ + __be32 y = htonl(x); \ + if (put_user(y, xdr++) < 0) \ + goto fault; \ + } while(0) + + ENCODE(0); /* flags */ + ENCODE(cnlen); /* cellname length */ + if (copy_to_user(xdr, key->description + 4, cnlen) != 0) + goto fault; + if (cnlen & 3 && + copy_to_user((u8 *)xdr + cnlen, &zero, 4 - (cnlen & 3)) != 0) + goto fault; + xdr += (cnlen + 3) >> 2; + ENCODE(ntoks); /* token count */ + + for (token = key->payload.data; token; token = token->next) { + toksize = 1 * 4; /* sec index */ + + switch (token->security_index) { + case RXRPC_SECURITY_RXKAD: + toksize += 8 * 4; + toksize += (token->kad->ticket_len + 3) & ~3; + ENCODE(toksize); + ENCODE(token->security_index); + ENCODE(token->kad->vice_id); + ENCODE(token->kad->kvno); + if (copy_to_user(xdr, token->kad->session_key, 8) != 0) + goto fault; + xdr += 8 >> 2; + ENCODE(token->kad->start); + ENCODE(token->kad->expiry); + ENCODE(token->kad->primary_flag); + tktlen = token->kad->ticket_len; + ENCODE(tktlen); + if (copy_to_user(xdr, token->kad->ticket, tktlen) != 0) + goto fault; + if (tktlen & 3 && + copy_to_user((u8 *)xdr + tktlen, &zero, + 4 - (tktlen & 3)) != 0) + goto fault; + xdr += (tktlen + 3) >> 2; + break; + + default: + break; + } + } + +#undef ENCODE + + ASSERTCMP((char __user *) xdr - buffer, ==, size); + _leave(" = %zu", size); + return size; + +fault: + _leave(" = -EFAULT"); + return -EFAULT; +} -- cgit v1.1 From 99455153d0670ba110e6a3b855b8369bcbd11120 Mon Sep 17 00:00:00 2001 From: David Howells Date: Mon, 14 Sep 2009 01:17:46 +0000 Subject: RxRPC: Parse security index 5 keys (Kerberos 5) Parse RxRPC security index 5 type keys (Kerberos 5 tokens). Signed-off-by: David Howells Signed-off-by: David S. Miller --- net/rxrpc/ar-key.c | 577 +++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 537 insertions(+), 40 deletions(-) (limited to 'net') diff --git a/net/rxrpc/ar-key.c b/net/rxrpc/ar-key.c index bf4d623..44836f6 100644 --- a/net/rxrpc/ar-key.c +++ b/net/rxrpc/ar-key.c @@ -64,7 +64,7 @@ struct key_type key_type_rxrpc_s = { static int rxrpc_instantiate_xdr_rxkad(struct key *key, const __be32 *xdr, unsigned toklen) { - struct rxrpc_key_token *token; + struct rxrpc_key_token *token, **pptoken; size_t plen; u32 tktlen; int ret; @@ -129,13 +129,398 @@ static int rxrpc_instantiate_xdr_rxkad(struct key *key, const __be32 *xdr, key->type_data.x[0]++; /* attach the data */ - token->next = key->payload.data; - key->payload.data = token; + for (pptoken = (struct rxrpc_key_token **)&key->payload.data; + *pptoken; + pptoken = &(*pptoken)->next) + continue; + *pptoken = token; + if (token->kad->expiry < key->expiry) + key->expiry = token->kad->expiry; + + _leave(" = 0"); + return 0; +} + +static void rxrpc_free_krb5_principal(struct krb5_principal *princ) +{ + int loop; + + if (princ->name_parts) { + for (loop = princ->n_name_parts - 1; loop >= 0; loop--) + kfree(princ->name_parts[loop]); + kfree(princ->name_parts); + } + kfree(princ->realm); +} + +static void rxrpc_free_krb5_tagged(struct krb5_tagged_data *td) +{ + kfree(td->data); +} + +/* + * free up an RxK5 token + */ +static void rxrpc_rxk5_free(struct rxk5_key *rxk5) +{ + int loop; + + rxrpc_free_krb5_principal(&rxk5->client); + rxrpc_free_krb5_principal(&rxk5->server); + rxrpc_free_krb5_tagged(&rxk5->session); + + if (rxk5->addresses) { + for (loop = rxk5->n_addresses - 1; loop >= 0; loop--) + rxrpc_free_krb5_tagged(&rxk5->addresses[loop]); + kfree(rxk5->addresses); + } + if (rxk5->authdata) { + for (loop = rxk5->n_authdata - 1; loop >= 0; loop--) + rxrpc_free_krb5_tagged(&rxk5->authdata[loop]); + kfree(rxk5->authdata); + } + + kfree(rxk5->ticket); + kfree(rxk5->ticket2); + kfree(rxk5); +} + +/* + * extract a krb5 principal + */ +static int rxrpc_krb5_decode_principal(struct krb5_principal *princ, + const __be32 **_xdr, + unsigned *_toklen) +{ + const __be32 *xdr = *_xdr; + unsigned toklen = *_toklen, n_parts, loop, tmp; + + /* there must be at least one name, and at least #names+1 length + * words */ + if (toklen <= 12) + return -EINVAL; + + _enter(",{%x,%x,%x},%u", + ntohl(xdr[0]), ntohl(xdr[1]), ntohl(xdr[2]), toklen); + + n_parts = ntohl(*xdr++); + toklen -= 4; + if (n_parts <= 0 || n_parts > AFSTOKEN_K5_COMPONENTS_MAX) + return -EINVAL; + princ->n_name_parts = n_parts; + + if (toklen <= (n_parts + 1) * 4) + return -EINVAL; + + princ->name_parts = kcalloc(sizeof(char *), n_parts, GFP_KERNEL); + if (!princ->name_parts) + return -ENOMEM; + + for (loop = 0; loop < n_parts; loop++) { + if (toklen < 4) + return -EINVAL; + tmp = ntohl(*xdr++); + toklen -= 4; + if (tmp <= 0 || tmp > AFSTOKEN_STRING_MAX) + return -EINVAL; + if (tmp > toklen) + return -EINVAL; + princ->name_parts[loop] = kmalloc(tmp + 1, GFP_KERNEL); + if (!princ->name_parts[loop]) + return -ENOMEM; + memcpy(princ->name_parts[loop], xdr, tmp); + princ->name_parts[loop][tmp] = 0; + tmp = (tmp + 3) & ~3; + toklen -= tmp; + xdr += tmp >> 2; + } + + if (toklen < 4) + return -EINVAL; + tmp = ntohl(*xdr++); + toklen -= 4; + if (tmp <= 0 || tmp > AFSTOKEN_K5_REALM_MAX) + return -EINVAL; + if (tmp > toklen) + return -EINVAL; + princ->realm = kmalloc(tmp + 1, GFP_KERNEL); + if (!princ->realm) + return -ENOMEM; + memcpy(princ->realm, xdr, tmp); + princ->realm[tmp] = 0; + tmp = (tmp + 3) & ~3; + toklen -= tmp; + xdr += tmp >> 2; + + _debug("%s/...@%s", princ->name_parts[0], princ->realm); + + *_xdr = xdr; + *_toklen = toklen; + _leave(" = 0 [toklen=%u]", toklen); + return 0; +} + +/* + * extract a piece of krb5 tagged data + */ +static int rxrpc_krb5_decode_tagged_data(struct krb5_tagged_data *td, + size_t max_data_size, + const __be32 **_xdr, + unsigned *_toklen) +{ + const __be32 *xdr = *_xdr; + unsigned toklen = *_toklen, len; + + /* there must be at least one tag and one length word */ + if (toklen <= 8) + return -EINVAL; + + _enter(",%zu,{%x,%x},%u", + max_data_size, ntohl(xdr[0]), ntohl(xdr[1]), toklen); + + td->tag = ntohl(*xdr++); + len = ntohl(*xdr++); + toklen -= 8; + if (len > max_data_size) + return -EINVAL; + td->data_len = len; + + if (len > 0) { + td->data = kmalloc(len, GFP_KERNEL); + if (!td->data) + return -ENOMEM; + memcpy(td->data, xdr, len); + len = (len + 3) & ~3; + toklen -= len; + xdr += len >> 2; + } + + _debug("tag %x len %x", td->tag, td->data_len); + + *_xdr = xdr; + *_toklen = toklen; + _leave(" = 0 [toklen=%u]", toklen); + return 0; +} + +/* + * extract an array of tagged data + */ +static int rxrpc_krb5_decode_tagged_array(struct krb5_tagged_data **_td, + u8 *_n_elem, + u8 max_n_elem, + size_t max_elem_size, + const __be32 **_xdr, + unsigned *_toklen) +{ + struct krb5_tagged_data *td; + const __be32 *xdr = *_xdr; + unsigned toklen = *_toklen, n_elem, loop; + int ret; + + /* there must be at least one count */ + if (toklen < 4) + return -EINVAL; + + _enter(",,%u,%zu,{%x},%u", + max_n_elem, max_elem_size, ntohl(xdr[0]), toklen); + + n_elem = ntohl(*xdr++); + toklen -= 4; + if (n_elem < 0 || n_elem > max_n_elem) + return -EINVAL; + *_n_elem = n_elem; + if (n_elem > 0) { + if (toklen <= (n_elem + 1) * 4) + return -EINVAL; + + _debug("n_elem %d", n_elem); + + td = kcalloc(sizeof(struct krb5_tagged_data), n_elem, + GFP_KERNEL); + if (!td) + return -ENOMEM; + *_td = td; + + for (loop = 0; loop < n_elem; loop++) { + ret = rxrpc_krb5_decode_tagged_data(&td[loop], + max_elem_size, + &xdr, &toklen); + if (ret < 0) + return ret; + } + } + + *_xdr = xdr; + *_toklen = toklen; + _leave(" = 0 [toklen=%u]", toklen); + return 0; +} + +/* + * extract a krb5 ticket + */ +static int rxrpc_krb5_decode_ticket(u8 **_ticket, uint16_t *_tktlen, + const __be32 **_xdr, unsigned *_toklen) +{ + const __be32 *xdr = *_xdr; + unsigned toklen = *_toklen, len; + + /* there must be at least one length word */ + if (toklen <= 4) + return -EINVAL; + + _enter(",{%x},%u", ntohl(xdr[0]), toklen); + + len = ntohl(*xdr++); + toklen -= 4; + if (len > AFSTOKEN_K5_TIX_MAX) + return -EINVAL; + *_tktlen = len; + + _debug("ticket len %u", len); + + if (len > 0) { + *_ticket = kmalloc(len, GFP_KERNEL); + if (!*_ticket) + return -ENOMEM; + memcpy(*_ticket, xdr, len); + len = (len + 3) & ~3; + toklen -= len; + xdr += len >> 2; + } + + *_xdr = xdr; + *_toklen = toklen; + _leave(" = 0 [toklen=%u]", toklen); + return 0; +} + +/* + * parse an RxK5 type XDR format token + * - the caller guarantees we have at least 4 words + */ +static int rxrpc_instantiate_xdr_rxk5(struct key *key, const __be32 *xdr, + unsigned toklen) +{ + struct rxrpc_key_token *token, **pptoken; + struct rxk5_key *rxk5; + const __be32 *end_xdr = xdr + (toklen >> 2); + int ret; + + _enter(",{%x,%x,%x,%x},%u", + ntohl(xdr[0]), ntohl(xdr[1]), ntohl(xdr[2]), ntohl(xdr[3]), + toklen); + + /* reserve some payload space for this subkey - the length of the token + * is a reasonable approximation */ + ret = key_payload_reserve(key, key->datalen + toklen); + if (ret < 0) + return ret; + + token = kzalloc(sizeof(*token), GFP_KERNEL); + if (!token) + return -ENOMEM; + + rxk5 = kzalloc(sizeof(*rxk5), GFP_KERNEL); + if (!rxk5) { + kfree(token); + return -ENOMEM; + } + + token->security_index = RXRPC_SECURITY_RXK5; + token->k5 = rxk5; + + /* extract the principals */ + ret = rxrpc_krb5_decode_principal(&rxk5->client, &xdr, &toklen); + if (ret < 0) + goto error; + ret = rxrpc_krb5_decode_principal(&rxk5->server, &xdr, &toklen); + if (ret < 0) + goto error; + + /* extract the session key and the encoding type (the tag field -> + * ENCTYPE_xxx) */ + ret = rxrpc_krb5_decode_tagged_data(&rxk5->session, AFSTOKEN_DATA_MAX, + &xdr, &toklen); + if (ret < 0) + goto error; + + if (toklen < 4 * 8 + 2 * 4) + goto inval; + rxk5->authtime = be64_to_cpup((const __be64 *) xdr); + xdr += 2; + rxk5->starttime = be64_to_cpup((const __be64 *) xdr); + xdr += 2; + rxk5->endtime = be64_to_cpup((const __be64 *) xdr); + xdr += 2; + rxk5->renew_till = be64_to_cpup((const __be64 *) xdr); + xdr += 2; + rxk5->is_skey = ntohl(*xdr++); + rxk5->flags = ntohl(*xdr++); + toklen -= 4 * 8 + 2 * 4; + + _debug("times: a=%llx s=%llx e=%llx rt=%llx", + rxk5->authtime, rxk5->starttime, rxk5->endtime, + rxk5->renew_till); + _debug("is_skey=%x flags=%x", rxk5->is_skey, rxk5->flags); + + /* extract the permitted client addresses */ + ret = rxrpc_krb5_decode_tagged_array(&rxk5->addresses, + &rxk5->n_addresses, + AFSTOKEN_K5_ADDRESSES_MAX, + AFSTOKEN_DATA_MAX, + &xdr, &toklen); + if (ret < 0) + goto error; + + ASSERTCMP((end_xdr - xdr) << 2, ==, toklen); + + /* extract the tickets */ + ret = rxrpc_krb5_decode_ticket(&rxk5->ticket, &rxk5->ticket_len, + &xdr, &toklen); + if (ret < 0) + goto error; + ret = rxrpc_krb5_decode_ticket(&rxk5->ticket2, &rxk5->ticket2_len, + &xdr, &toklen); + if (ret < 0) + goto error; + + ASSERTCMP((end_xdr - xdr) << 2, ==, toklen); + + /* extract the typed auth data */ + ret = rxrpc_krb5_decode_tagged_array(&rxk5->authdata, + &rxk5->n_authdata, + AFSTOKEN_K5_AUTHDATA_MAX, + AFSTOKEN_BDATALN_MAX, + &xdr, &toklen); + if (ret < 0) + goto error; + + ASSERTCMP((end_xdr - xdr) << 2, ==, toklen); + + if (toklen != 0) + goto inval; + + /* attach the payload to the key */ + for (pptoken = (struct rxrpc_key_token **)&key->payload.data; + *pptoken; + pptoken = &(*pptoken)->next) + continue; + *pptoken = token; if (token->kad->expiry < key->expiry) key->expiry = token->kad->expiry; _leave(" = 0"); return 0; + +inval: + ret = -EINVAL; +error: + rxrpc_rxk5_free(rxk5); + kfree(token); + _leave(" = %d", ret); + return ret; } /* @@ -228,6 +613,8 @@ static int rxrpc_instantiate_xdr(struct key *key, const void *data, size_t datal sec_ix = ntohl(*xdr++); toklen -= 4; + _debug("TOKEN type=%u [%p-%p]", sec_ix, xdr, token); + switch (sec_ix) { case RXRPC_SECURITY_RXKAD: ret = rxrpc_instantiate_xdr_rxkad(key, xdr, toklen); @@ -235,6 +622,12 @@ static int rxrpc_instantiate_xdr(struct key *key, const void *data, size_t datal goto error; break; + case RXRPC_SECURITY_RXK5: + ret = rxrpc_instantiate_xdr_rxk5(key, xdr, toklen); + if (ret != 0) + goto error; + break; + default: ret = -EPROTONOSUPPORT; goto error; @@ -412,6 +805,10 @@ static void rxrpc_destroy(struct key *key) case RXRPC_SECURITY_RXKAD: kfree(token->kad); break; + case RXRPC_SECURITY_RXK5: + if (token->k5) + rxrpc_rxk5_free(token->k5); + break; default: printk(KERN_ERR "Unknown token type %x on rxrpc key\n", token->security_index); @@ -602,10 +999,13 @@ EXPORT_SYMBOL(rxrpc_get_null_key); static long rxrpc_read(const struct key *key, char __user *buffer, size_t buflen) { - struct rxrpc_key_token *token; - size_t size, toksize; - __be32 __user *xdr; - u32 cnlen, tktlen, ntoks, zero; + const struct rxrpc_key_token *token; + const struct krb5_principal *princ; + size_t size; + __be32 __user *xdr, *oldxdr; + u32 cnlen, toksize, ntoks, tok, zero; + u16 toksizes[AFSTOKEN_MAX]; + int loop; _enter(""); @@ -614,28 +1014,68 @@ static long rxrpc_read(const struct key *key, return -EOPNOTSUPP; cnlen = strlen(key->description + 4); +#define RND(X) (((X) + 3) & ~3) + /* AFS keys we return in XDR form, so we need to work out the size of * the XDR */ size = 2 * 4; /* flags, cellname len */ - size += (cnlen + 3) & ~3; /* cellname */ + size += RND(cnlen); /* cellname */ size += 1 * 4; /* token count */ ntoks = 0; for (token = key->payload.data; token; token = token->next) { + toksize = 4; /* sec index */ + switch (token->security_index) { case RXRPC_SECURITY_RXKAD: - size += 2 * 4; /* length, security index (switch ID) */ - size += 8 * 4; /* viceid, kvno, key*2, begin, end, - * primary, tktlen */ - size += (token->kad->ticket_len + 3) & ~3; /* ticket */ - ntoks++; + toksize += 8 * 4; /* viceid, kvno, key*2, begin, + * end, primary, tktlen */ + toksize += RND(token->kad->ticket_len); break; - default: /* can't encode */ + case RXRPC_SECURITY_RXK5: + princ = &token->k5->client; + toksize += 4 + princ->n_name_parts * 4; + for (loop = 0; loop < princ->n_name_parts; loop++) + toksize += RND(strlen(princ->name_parts[loop])); + toksize += 4 + RND(strlen(princ->realm)); + + princ = &token->k5->server; + toksize += 4 + princ->n_name_parts * 4; + for (loop = 0; loop < princ->n_name_parts; loop++) + toksize += RND(strlen(princ->name_parts[loop])); + toksize += 4 + RND(strlen(princ->realm)); + + toksize += 8 + RND(token->k5->session.data_len); + + toksize += 4 * 8 + 2 * 4; + + toksize += 4 + token->k5->n_addresses * 8; + for (loop = 0; loop < token->k5->n_addresses; loop++) + toksize += RND(token->k5->addresses[loop].data_len); + + toksize += 4 + RND(token->k5->ticket_len); + toksize += 4 + RND(token->k5->ticket2_len); + + toksize += 4 + token->k5->n_authdata * 8; + for (loop = 0; loop < token->k5->n_authdata; loop++) + toksize += RND(token->k5->authdata[loop].data_len); break; + + default: /* we have a ticket we can't encode */ + BUG(); + continue; } + + _debug("token[%u]: toksize=%u", ntoks, toksize); + ASSERTCMP(toksize, <=, AFSTOKEN_LENGTH_MAX); + + toksizes[ntoks++] = toksize; + size += toksize + 4; /* each token has a length word */ } +#undef RND + if (!buffer || buflen < size) return size; @@ -647,52 +1087,109 @@ static long rxrpc_read(const struct key *key, if (put_user(y, xdr++) < 0) \ goto fault; \ } while(0) +#define ENCODE_DATA(l, s) \ + do { \ + u32 _l = (l); \ + ENCODE(l); \ + if (copy_to_user(xdr, (s), _l) != 0) \ + goto fault; \ + if (_l & 3 && \ + copy_to_user((u8 *)xdr + _l, &zero, 4 - (_l & 3)) != 0) \ + goto fault; \ + xdr += (_l + 3) >> 2; \ + } while(0) +#define ENCODE64(x) \ + do { \ + __be64 y = cpu_to_be64(x); \ + if (copy_to_user(xdr, &y, 8) != 0) \ + goto fault; \ + xdr += 8 >> 2; \ + } while(0) +#define ENCODE_STR(s) \ + do { \ + const char *_s = (s); \ + ENCODE_DATA(strlen(_s), _s); \ + } while(0) - ENCODE(0); /* flags */ - ENCODE(cnlen); /* cellname length */ - if (copy_to_user(xdr, key->description + 4, cnlen) != 0) - goto fault; - if (cnlen & 3 && - copy_to_user((u8 *)xdr + cnlen, &zero, 4 - (cnlen & 3)) != 0) - goto fault; - xdr += (cnlen + 3) >> 2; - ENCODE(ntoks); /* token count */ + ENCODE(0); /* flags */ + ENCODE_DATA(cnlen, key->description + 4); /* cellname */ + ENCODE(ntoks); + tok = 0; for (token = key->payload.data; token; token = token->next) { - toksize = 1 * 4; /* sec index */ + toksize = toksizes[tok++]; + ENCODE(toksize); + oldxdr = xdr; + ENCODE(token->security_index); switch (token->security_index) { case RXRPC_SECURITY_RXKAD: - toksize += 8 * 4; - toksize += (token->kad->ticket_len + 3) & ~3; - ENCODE(toksize); - ENCODE(token->security_index); ENCODE(token->kad->vice_id); ENCODE(token->kad->kvno); - if (copy_to_user(xdr, token->kad->session_key, 8) != 0) - goto fault; - xdr += 8 >> 2; + ENCODE_DATA(8, token->kad->session_key); ENCODE(token->kad->start); ENCODE(token->kad->expiry); ENCODE(token->kad->primary_flag); - tktlen = token->kad->ticket_len; - ENCODE(tktlen); - if (copy_to_user(xdr, token->kad->ticket, tktlen) != 0) - goto fault; - if (tktlen & 3 && - copy_to_user((u8 *)xdr + tktlen, &zero, - 4 - (tktlen & 3)) != 0) - goto fault; - xdr += (tktlen + 3) >> 2; + ENCODE_DATA(token->kad->ticket_len, token->kad->ticket); + break; + + case RXRPC_SECURITY_RXK5: + princ = &token->k5->client; + ENCODE(princ->n_name_parts); + for (loop = 0; loop < princ->n_name_parts; loop++) + ENCODE_STR(princ->name_parts[loop]); + ENCODE_STR(princ->realm); + + princ = &token->k5->server; + ENCODE(princ->n_name_parts); + for (loop = 0; loop < princ->n_name_parts; loop++) + ENCODE_STR(princ->name_parts[loop]); + ENCODE_STR(princ->realm); + + ENCODE(token->k5->session.tag); + ENCODE_DATA(token->k5->session.data_len, + token->k5->session.data); + + ENCODE64(token->k5->authtime); + ENCODE64(token->k5->starttime); + ENCODE64(token->k5->endtime); + ENCODE64(token->k5->renew_till); + ENCODE(token->k5->is_skey); + ENCODE(token->k5->flags); + + ENCODE(token->k5->n_addresses); + for (loop = 0; loop < token->k5->n_addresses; loop++) { + ENCODE(token->k5->addresses[loop].tag); + ENCODE_DATA(token->k5->addresses[loop].data_len, + token->k5->addresses[loop].data); + } + + ENCODE_DATA(token->k5->ticket_len, token->k5->ticket); + ENCODE_DATA(token->k5->ticket2_len, token->k5->ticket2); + + ENCODE(token->k5->n_authdata); + for (loop = 0; loop < token->k5->n_authdata; loop++) { + ENCODE(token->k5->authdata[loop].tag); + ENCODE_DATA(token->k5->authdata[loop].data_len, + token->k5->authdata[loop].data); + } break; default: + BUG(); break; } + + ASSERTCMP((unsigned long)xdr - (unsigned long)oldxdr, ==, + toksize); } +#undef ENCODE_STR +#undef ENCODE_DATA +#undef ENCODE64 #undef ENCODE + ASSERTCMP(tok, ==, ntoks); ASSERTCMP((char __user *) xdr - buffer, ==, size); _leave(" = %zu", size); return size; -- cgit v1.1 From 926e61b7c44db83013159ac2f74bccd451607b5a Mon Sep 17 00:00:00 2001 From: Jarek Poplawski Date: Tue, 15 Sep 2009 02:53:07 -0700 Subject: pkt_sched: Fix tx queue selection in tc_modify_qdisc After the recent mq change there is the new select_queue qdisc class method used in tc_modify_qdisc, but it works OK only for direct child qdiscs of mq qdisc. Grandchildren always get the first tx queue, which would give wrong qdisc_root etc. results (e.g. for sch_htb as child of sch_prio). This patch fixes it by using parent's dev_queue for such grandchildren qdiscs. The select_queue method's return type is changed BTW. With feedback from: Patrick McHardy Signed-off-by: Jarek Poplawski Signed-off-by: David S. Miller --- net/sched/sch_api.c | 10 +++++++--- net/sched/sch_mq.c | 13 +++++++++---- 2 files changed, 16 insertions(+), 7 deletions(-) (limited to 'net') diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c index c6e4063..1367aa2 100644 --- a/net/sched/sch_api.c +++ b/net/sched/sch_api.c @@ -1116,12 +1116,16 @@ create_n_graft: tcm->tcm_parent, tcm->tcm_parent, tca, &err); else { - unsigned int ntx = 0; + struct netdev_queue *dev_queue; if (p && p->ops->cl_ops && p->ops->cl_ops->select_queue) - ntx = p->ops->cl_ops->select_queue(p, tcm); + dev_queue = p->ops->cl_ops->select_queue(p, tcm); + else if (p) + dev_queue = p->dev_queue; + else + dev_queue = netdev_get_tx_queue(dev, 0); - q = qdisc_create(dev, netdev_get_tx_queue(dev, ntx), p, + q = qdisc_create(dev, dev_queue, p, tcm->tcm_parent, tcm->tcm_handle, tca, &err); } diff --git a/net/sched/sch_mq.c b/net/sched/sch_mq.c index dd5ee02..600c501 100644 --- a/net/sched/sch_mq.c +++ b/net/sched/sch_mq.c @@ -125,13 +125,18 @@ static struct netdev_queue *mq_queue_get(struct Qdisc *sch, unsigned long cl) return netdev_get_tx_queue(dev, ntx); } -static unsigned int mq_select_queue(struct Qdisc *sch, struct tcmsg *tcm) +static struct netdev_queue *mq_select_queue(struct Qdisc *sch, + struct tcmsg *tcm) { unsigned int ntx = TC_H_MIN(tcm->tcm_parent); + struct netdev_queue *dev_queue = mq_queue_get(sch, ntx); - if (!mq_queue_get(sch, ntx)) - return 0; - return ntx - 1; + if (!dev_queue) { + struct net_device *dev = qdisc_dev(sch); + + return netdev_get_tx_queue(dev, 0); + } + return dev_queue; } static int mq_graft(struct Qdisc *sch, unsigned long cl, struct Qdisc *new, -- cgit v1.1 From 066fc51275cef94d1624fd58bb3065d050a6f17e Mon Sep 17 00:00:00 2001 From: Dmitry Eremin-Solenikov Date: Tue, 15 Sep 2009 17:54:43 +0400 Subject: af_ieee802154: setsockopt optlen arg isn't __user Remove __user annotation from optlen arg as it's bogus. Signed-off-by: Dmitry Eremin-Solenikov --- net/ieee802154/dgram.c | 2 +- net/ieee802154/raw.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'net') diff --git a/net/ieee802154/dgram.c b/net/ieee802154/dgram.c index 77ae685..51593a4 100644 --- a/net/ieee802154/dgram.c +++ b/net/ieee802154/dgram.c @@ -414,7 +414,7 @@ static int dgram_getsockopt(struct sock *sk, int level, int optname, } static int dgram_setsockopt(struct sock *sk, int level, int optname, - char __user *optval, int __user optlen) + char __user *optval, int optlen) { struct dgram_sock *ro = dgram_sk(sk); int val; diff --git a/net/ieee802154/raw.c b/net/ieee802154/raw.c index 4681501..1319885 100644 --- a/net/ieee802154/raw.c +++ b/net/ieee802154/raw.c @@ -244,7 +244,7 @@ static int raw_getsockopt(struct sock *sk, int level, int optname, } static int raw_setsockopt(struct sock *sk, int level, int optname, - char __user *optval, int __user optlen) + char __user *optval, int optlen) { return -EOPNOTSUPP; } -- cgit v1.1 From c4835d81efb1795eb8bbeb40b73d74e5c04b1257 Mon Sep 17 00:00:00 2001 From: Dmitry Eremin-Solenikov Date: Thu, 10 Sep 2009 18:02:30 +0400 Subject: ieee802154: add locking for seq numbers Signed-off-by: Dmitry Eremin-Solenikov --- net/ieee802154/netlink.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'net') diff --git a/net/ieee802154/netlink.c b/net/ieee802154/netlink.c index 2106ecb..ca767bd 100644 --- a/net/ieee802154/netlink.c +++ b/net/ieee802154/netlink.c @@ -35,6 +35,7 @@ #include static unsigned int ieee802154_seq_num; +static DEFINE_SPINLOCK(ieee802154_seq_lock); static struct genl_family ieee802154_coordinator_family = { .id = GENL_ID_GENERATE, @@ -57,12 +58,15 @@ static struct sk_buff *ieee802154_nl_create(int flags, u8 req) { void *hdr; struct sk_buff *msg = nlmsg_new(NLMSG_GOODSIZE, GFP_ATOMIC); + unsigned long f; if (!msg) return NULL; + spin_lock_irqsave(&ieee802154_seq_lock, f); hdr = genlmsg_put(msg, 0, ieee802154_seq_num++, &ieee802154_coordinator_family, flags, req); + spin_unlock_irqrestore(&ieee802154_seq_lock, f); if (!hdr) { nlmsg_free(msg); return NULL; -- cgit v1.1 From 7c64b9f3f584008000cf3b960f25cd6a68fce191 Mon Sep 17 00:00:00 2001 From: Jarek Poplawski Date: Tue, 15 Sep 2009 23:42:05 -0700 Subject: pkt_sched: Fix qdisc_create on stab error handling If qdisc_get_stab returns error in qdisc_create there is skipped qdisc ops->destroy, which is necessary because it's after ops->init at the moment, so memory leaks are quite probable. Signed-off-by: Jarek Poplawski Signed-off-by: David S. Miller --- net/sched/sch_api.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'net') diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c index 1367aa2..903e418 100644 --- a/net/sched/sch_api.c +++ b/net/sched/sch_api.c @@ -809,7 +809,7 @@ qdisc_create(struct net_device *dev, struct netdev_queue *dev_queue, stab = qdisc_get_stab(tca[TCA_STAB]); if (IS_ERR(stab)) { err = PTR_ERR(stab); - goto err_out3; + goto err_out4; } sch->stab = stab; } @@ -838,7 +838,6 @@ qdisc_create(struct net_device *dev, struct netdev_queue *dev_queue, return sch; } err_out3: - qdisc_put_stab(sch->stab); dev_put(dev); kfree((char *) sch - sch->padded); err_out2: @@ -852,6 +851,7 @@ err_out4: * Any broken qdiscs that would require a ops->reset() here? * The qdisc was never in action so it shouldn't be necessary. */ + qdisc_put_stab(sch->stab); if (ops->destroy) ops->destroy(sch); goto err_out3; -- cgit v1.1 From 657e9649e745b06675aa5063c84430986cdc3afa Mon Sep 17 00:00:00 2001 From: Robert Varga Date: Tue, 15 Sep 2009 23:49:21 -0700 Subject: tcp: fix CONFIG_TCP_MD5SIG + CONFIG_PREEMPT timer BUG() I have recently came across a preemption imbalance detected by: <4>huh, entered ffffffff80644630 with preempt_count 00000102, exited with 00000101? <0>------------[ cut here ]------------ <2>kernel BUG at /usr/src/linux/kernel/timer.c:664! <0>invalid opcode: 0000 [1] PREEMPT SMP with ffffffff80644630 being inet_twdr_hangman(). This appeared after I enabled CONFIG_TCP_MD5SIG and played with it a bit, so I looked at what might have caused it. One thing that struck me as strange is tcp_twsk_destructor(), as it calls tcp_put_md5sig_pool() -- which entails a put_cpu(), causing the detected imbalance. Found on 2.6.23.9, but 2.6.31 is affected as well, as far as I can tell. Signed-off-by: Robert Varga Signed-off-by: David S. Miller --- net/ipv4/tcp_minisocks.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net') diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c index 045bcfd..624c3c9 100644 --- a/net/ipv4/tcp_minisocks.c +++ b/net/ipv4/tcp_minisocks.c @@ -363,7 +363,7 @@ void tcp_twsk_destructor(struct sock *sk) #ifdef CONFIG_TCP_MD5SIG struct tcp_timewait_sock *twsk = tcp_twsk(sk); if (twsk->tw_md5_keylen) - tcp_put_md5sig_pool(); + tcp_free_md5sig_pool(); #endif } -- cgit v1.1 From 4e36a95e591e9c58dd10bb4103c00993917c27fd Mon Sep 17 00:00:00 2001 From: David Howells Date: Wed, 16 Sep 2009 00:01:13 -0700 Subject: RxRPC: Use uX/sX rather than uintX_t/intX_t types Use uX rather than uintX_t types for consistency. Signed-off-by: David Howells Signed-off-by: David S. Miller --- net/rxrpc/ar-ack.c | 6 +++--- net/rxrpc/ar-internal.h | 16 ++++++++-------- net/rxrpc/ar-key.c | 2 +- 3 files changed, 12 insertions(+), 12 deletions(-) (limited to 'net') diff --git a/net/rxrpc/ar-ack.c b/net/rxrpc/ar-ack.c index c9f1f0a..b4a2209 100644 --- a/net/rxrpc/ar-ack.c +++ b/net/rxrpc/ar-ack.c @@ -40,7 +40,7 @@ static const s8 rxrpc_ack_priority[] = { /* * propose an ACK be sent */ -void __rxrpc_propose_ACK(struct rxrpc_call *call, uint8_t ack_reason, +void __rxrpc_propose_ACK(struct rxrpc_call *call, u8 ack_reason, __be32 serial, bool immediate) { unsigned long expiry; @@ -120,7 +120,7 @@ cancel_timer: /* * propose an ACK be sent, locking the call structure */ -void rxrpc_propose_ACK(struct rxrpc_call *call, uint8_t ack_reason, +void rxrpc_propose_ACK(struct rxrpc_call *call, u8 ack_reason, __be32 serial, bool immediate) { s8 prior = rxrpc_ack_priority[ack_reason]; @@ -520,7 +520,7 @@ static void rxrpc_zap_tx_window(struct rxrpc_call *call) struct rxrpc_skb_priv *sp; struct sk_buff *skb; unsigned long _skb, *acks_window; - uint8_t winsz = call->acks_winsz; + u8 winsz = call->acks_winsz; int tail; acks_window = call->acks_window; diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h index 46c6d88..7043b29 100644 --- a/net/rxrpc/ar-internal.h +++ b/net/rxrpc/ar-internal.h @@ -229,7 +229,7 @@ struct rxrpc_conn_bundle { int debug_id; /* debug ID for printks */ unsigned short num_conns; /* number of connections in this bundle */ __be16 service_id; /* service ID */ - uint8_t security_ix; /* security type */ + u8 security_ix; /* security type */ }; /* @@ -370,10 +370,10 @@ struct rxrpc_call { u8 channel; /* connection channel occupied by this call */ /* transmission-phase ACK management */ - uint8_t acks_head; /* offset into window of first entry */ - uint8_t acks_tail; /* offset into window of last entry */ - uint8_t acks_winsz; /* size of un-ACK'd window */ - uint8_t acks_unacked; /* lowest unacked packet in last ACK received */ + u8 acks_head; /* offset into window of first entry */ + u8 acks_tail; /* offset into window of last entry */ + u8 acks_winsz; /* size of un-ACK'd window */ + u8 acks_unacked; /* lowest unacked packet in last ACK received */ int acks_latest; /* serial number of latest ACK received */ rxrpc_seq_t acks_hard; /* highest definitively ACK'd msg seq */ unsigned long *acks_window; /* sent packet window @@ -388,7 +388,7 @@ struct rxrpc_call { rxrpc_seq_t rx_first_oos; /* first packet in rx_oos_queue (or 0) */ rxrpc_seq_t ackr_win_top; /* top of ACK window (rx_data_eaten is bottom) */ rxrpc_seq_net_t ackr_prev_seq; /* previous sequence number received */ - uint8_t ackr_reason; /* reason to ACK */ + u8 ackr_reason; /* reason to ACK */ __be32 ackr_serial; /* serial of packet being ACK'd */ atomic_t ackr_not_idle; /* number of packets in Rx queue */ @@ -434,8 +434,8 @@ extern int rxrpc_reject_call(struct rxrpc_sock *); /* * ar-ack.c */ -extern void __rxrpc_propose_ACK(struct rxrpc_call *, uint8_t, __be32, bool); -extern void rxrpc_propose_ACK(struct rxrpc_call *, uint8_t, __be32, bool); +extern void __rxrpc_propose_ACK(struct rxrpc_call *, u8, __be32, bool); +extern void rxrpc_propose_ACK(struct rxrpc_call *, u8, __be32, bool); extern void rxrpc_process_call(struct work_struct *); /* diff --git a/net/rxrpc/ar-key.c b/net/rxrpc/ar-key.c index 44836f6..74697b2 100644 --- a/net/rxrpc/ar-key.c +++ b/net/rxrpc/ar-key.c @@ -360,7 +360,7 @@ static int rxrpc_krb5_decode_tagged_array(struct krb5_tagged_data **_td, /* * extract a krb5 ticket */ -static int rxrpc_krb5_decode_ticket(u8 **_ticket, uint16_t *_tktlen, +static int rxrpc_krb5_decode_ticket(u8 **_ticket, u16 *_tktlen, const __be32 **_xdr, unsigned *_toklen) { const __be32 *xdr = *_xdr; -- cgit v1.1 From 8c6c03fe230c448e5795464a9d73efb796acf3d6 Mon Sep 17 00:00:00 2001 From: Pavel Roskin Date: Tue, 15 Sep 2009 22:24:30 -0400 Subject: rc80211_minstrel: fix contention window calculation The contention window is supposed to be a power of two minus one, i.e. 15, 31, 63, 127... minstrel_rate_init() forgets to subtract 1, so the sequence becomes 15, 32, 66, 134... Bug reported by Dan Halperin Signed-off-by: Pavel Roskin Signed-off-by: John W. Linville --- net/mac80211/rc80211_minstrel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net') diff --git a/net/mac80211/rc80211_minstrel.c b/net/mac80211/rc80211_minstrel.c index 7c51429..6e5d68b 100644 --- a/net/mac80211/rc80211_minstrel.c +++ b/net/mac80211/rc80211_minstrel.c @@ -418,7 +418,7 @@ minstrel_rate_init(void *priv, struct ieee80211_supported_band *sband, /* contention window */ tx_time_single += t_slot + min(cw, mp->cw_max); - cw = (cw + 1) << 1; + cw = (cw << 1) | 1; tx_time += tx_time_single; tx_time_cts += tx_time_single + mi->sp_ack_dur; -- cgit v1.1 From bbac31f4c0339f6c51afbd0edfb4959df9b53fa9 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 16 Sep 2009 09:04:26 -0700 Subject: cfg80211: fix SME connect There's a check saying /* we're good if we have both BSSID and channel */ if (wdev->conn->params.bssid && wdev->conn->params.channel) { but that isn't true -- we need the BSS struct. This leads to errors such as Trying to associate with 00:1b:53:11:dc:40 (SSID='TEST' freq=2412 MHz) ioctl[SIOCSIWFREQ]: No such file or directory ioctl[SIOCSIWESSID]: No such file or directory Association request to the driver failed Associated with 00:1b:53:11:dc:40 in wpa_supplicant, as reported by Holger. Instead, we really need to have the BSS struct, and if we don't, then we need to initiate a scan for it. But we may already have the BSS struct here, so hang on to it if we do and scan if we don't. Signed-off-by: Johannes Berg Tested-by: Holger Schurig Signed-off-by: John W. Linville --- net/wireless/sme.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) (limited to 'net') diff --git a/net/wireless/sme.c b/net/wireless/sme.c index 6830788..7fae7ee 100644 --- a/net/wireless/sme.c +++ b/net/wireless/sme.c @@ -188,7 +188,7 @@ void cfg80211_conn_work(struct work_struct *work) rtnl_unlock(); } -static bool cfg80211_get_conn_bss(struct wireless_dev *wdev) +static struct cfg80211_bss *cfg80211_get_conn_bss(struct wireless_dev *wdev) { struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); struct cfg80211_bss *bss; @@ -205,7 +205,7 @@ static bool cfg80211_get_conn_bss(struct wireless_dev *wdev) WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_PRIVACY, capa); if (!bss) - return false; + return NULL; memcpy(wdev->conn->bssid, bss->bssid, ETH_ALEN); wdev->conn->params.bssid = wdev->conn->bssid; @@ -213,14 +213,14 @@ static bool cfg80211_get_conn_bss(struct wireless_dev *wdev) wdev->conn->state = CFG80211_CONN_AUTHENTICATE_NEXT; schedule_work(&rdev->conn_work); - cfg80211_put_bss(bss); - return true; + return bss; } static void __cfg80211_sme_scan_done(struct net_device *dev) { struct wireless_dev *wdev = dev->ieee80211_ptr; struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); + struct cfg80211_bss *bss; ASSERT_WDEV_LOCK(wdev); @@ -234,7 +234,10 @@ static void __cfg80211_sme_scan_done(struct net_device *dev) wdev->conn->state != CFG80211_CONN_SCAN_AGAIN) return; - if (!cfg80211_get_conn_bss(wdev)) { + bss = cfg80211_get_conn_bss(wdev); + if (bss) { + cfg80211_put_bss(bss); + } else { /* not found */ if (wdev->conn->state == CFG80211_CONN_SCAN_AGAIN) schedule_work(&rdev->conn_work); @@ -670,6 +673,7 @@ int __cfg80211_connect(struct cfg80211_registered_device *rdev, { struct wireless_dev *wdev = dev->ieee80211_ptr; struct ieee80211_channel *chan; + struct cfg80211_bss *bss = NULL; int err; ASSERT_WDEV_LOCK(wdev); @@ -760,7 +764,7 @@ int __cfg80211_connect(struct cfg80211_registered_device *rdev, /* don't care about result -- but fill bssid & channel */ if (!wdev->conn->params.bssid || !wdev->conn->params.channel) - cfg80211_get_conn_bss(wdev); + bss = cfg80211_get_conn_bss(wdev); wdev->sme_state = CFG80211_SME_CONNECTING; wdev->connect_keys = connkeys; @@ -770,10 +774,11 @@ int __cfg80211_connect(struct cfg80211_registered_device *rdev, wdev->conn->prev_bssid_valid = true; } - /* we're good if we have both BSSID and channel */ - if (wdev->conn->params.bssid && wdev->conn->params.channel) { + /* we're good if we have a matching bss struct */ + if (bss) { wdev->conn->state = CFG80211_CONN_AUTHENTICATE_NEXT; err = cfg80211_conn_do_work(wdev); + cfg80211_put_bss(bss); } else { /* otherwise we'll need to scan for the AP first */ err = cfg80211_conn_scan(wdev); -- cgit v1.1 From 3933fc952a5a5af4cf23fca94e20203251c9d825 Mon Sep 17 00:00:00 2001 From: Jens Rosenboom Date: Thu, 10 Sep 2009 06:25:11 +0000 Subject: ipv6: Ignore route option with ROUTER_PREF_INVALID RFC4191 says that "If the Reserved (10) value is received, the Route Information Option MUST be ignored.", so this patch makes us conform to the RFC. This is different to the usage of the Default Router Preference, where an invalid value must indeed be treated as PREF_MEDIUM. Signed-off-by: Jens Rosenboom Signed-off-by: David S. Miller --- net/ipv6/route.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net') diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 9ccfef3..77aecbe 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -481,7 +481,7 @@ int rt6_route_rcv(struct net_device *dev, u8 *opt, int len, pref = rinfo->route_pref; if (pref == ICMPV6_ROUTER_PREF_INVALID) - pref = ICMPV6_ROUTER_PREF_MEDIUM; + return -EINVAL; lifetime = addrconf_timeout_fixup(ntohl(rinfo->lifetime), HZ); -- cgit v1.1 From 4c89d86b4df8e4f2cdccb72495e2f4664118ebf1 Mon Sep 17 00:00:00 2001 From: Ursula Braun Date: Wed, 16 Sep 2009 04:37:22 +0000 Subject: iucv: suspend/resume error msg for left over pathes During suspend IUCV exploiters have to close their IUCV connections. When restoring an image, it can be checked if all IUCV pathes had been closed before the Linux instance was suspended. If not, an error message is issued to indicate a problem in one of the used programs exploiting IUCV communication. Signed-off-by: Ursula Braun Signed-off-by: David S. Miller --- net/iucv/iucv.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'net') diff --git a/net/iucv/iucv.c b/net/iucv/iucv.c index c833481d..aabd238 100644 --- a/net/iucv/iucv.c +++ b/net/iucv/iucv.c @@ -79,6 +79,14 @@ static int iucv_bus_match(struct device *dev, struct device_driver *drv) return 0; } +enum iucv_pm_states { + IUCV_PM_INITIAL = 0, + IUCV_PM_FREEZING = 1, + IUCV_PM_THAWING = 2, + IUCV_PM_RESTORING = 3, +}; +static enum iucv_pm_states iucv_pm_state; + static int iucv_pm_prepare(struct device *); static void iucv_pm_complete(struct device *); static int iucv_pm_freeze(struct device *); @@ -1875,6 +1883,7 @@ static int iucv_pm_freeze(struct device *dev) #ifdef CONFIG_PM_DEBUG printk(KERN_WARNING "iucv_pm_freeze\n"); #endif + iucv_pm_state = IUCV_PM_FREEZING; for_each_cpu_mask_nr(cpu, iucv_irq_cpumask) smp_call_function_single(cpu, iucv_block_cpu_almost, NULL, 1); if (dev->driver && dev->driver->pm && dev->driver->pm->freeze) @@ -1899,6 +1908,7 @@ static int iucv_pm_thaw(struct device *dev) #ifdef CONFIG_PM_DEBUG printk(KERN_WARNING "iucv_pm_thaw\n"); #endif + iucv_pm_state = IUCV_PM_THAWING; if (!iucv_path_table) { rc = iucv_enable(); if (rc) @@ -1933,6 +1943,10 @@ static int iucv_pm_restore(struct device *dev) #ifdef CONFIG_PM_DEBUG printk(KERN_WARNING "iucv_pm_restore %p\n", iucv_path_table); #endif + if ((iucv_pm_state != IUCV_PM_RESTORING) && iucv_path_table) + pr_warning("Suspending Linux did not completely close all IUCV " + "connections\n"); + iucv_pm_state = IUCV_PM_RESTORING; if (cpus_empty(iucv_irq_cpumask)) { rc = iucv_query_maxconn(); rc = iucv_enable(); -- cgit v1.1 From d28ecab0c40f587fd1e28701c195747220c984e2 Mon Sep 17 00:00:00 2001 From: Hendrik Brueckner Date: Wed, 16 Sep 2009 04:37:23 +0000 Subject: iucv: fix iucv_buffer_cpumask check when calling IUCV functions Prior to calling IUCV functions, the DECLARE BUFFER function must have been called for at least one CPU to receive IUCV interrupts. With commit "iucv: establish reboot notifier" (6c005961), a check has been introduced to avoid calling IUCV functions if the current CPU does not have an interrupt buffer declared. Because one interrupt buffer is sufficient, change the condition to ensure that one interrupt buffer is available. In addition, checking the buffer on the current CPU creates a race with CPU up/down notifications: before checking the buffer, the IUCV function might be interrupted by an smp_call_function() that retrieves the interrupt buffer for the current CPU. When the IUCV function continues, the check fails and -EIO is returned. If a buffer is available on any other CPU, the IUCV function call must be invoked (instead of failing with -EIO). Signed-off-by: Hendrik Brueckner Signed-off-by: Ursula Braun Signed-off-by: David S. Miller --- net/iucv/iucv.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'net') diff --git a/net/iucv/iucv.c b/net/iucv/iucv.c index aabd238..8aaa23c 100644 --- a/net/iucv/iucv.c +++ b/net/iucv/iucv.c @@ -864,7 +864,7 @@ int iucv_path_accept(struct iucv_path *path, struct iucv_handler *handler, int rc; local_bh_disable(); - if (!cpu_isset(smp_processor_id(), iucv_buffer_cpumask)) { + if (cpus_empty(iucv_buffer_cpumask)) { rc = -EIO; goto out; } @@ -913,7 +913,7 @@ int iucv_path_connect(struct iucv_path *path, struct iucv_handler *handler, spin_lock_bh(&iucv_table_lock); iucv_cleanup_queue(); - if (!cpu_isset(smp_processor_id(), iucv_buffer_cpumask)) { + if (cpus_empty(iucv_buffer_cpumask)) { rc = -EIO; goto out; } @@ -973,7 +973,7 @@ int iucv_path_quiesce(struct iucv_path *path, u8 userdata[16]) int rc; local_bh_disable(); - if (!cpu_isset(smp_processor_id(), iucv_buffer_cpumask)) { + if (cpus_empty(iucv_buffer_cpumask)) { rc = -EIO; goto out; } @@ -1005,7 +1005,7 @@ int iucv_path_resume(struct iucv_path *path, u8 userdata[16]) int rc; local_bh_disable(); - if (!cpu_isset(smp_processor_id(), iucv_buffer_cpumask)) { + if (cpus_empty(iucv_buffer_cpumask)) { rc = -EIO; goto out; } @@ -1034,7 +1034,7 @@ int iucv_path_sever(struct iucv_path *path, u8 userdata[16]) int rc; preempt_disable(); - if (!cpu_isset(smp_processor_id(), iucv_buffer_cpumask)) { + if (cpus_empty(iucv_buffer_cpumask)) { rc = -EIO; goto out; } @@ -1068,7 +1068,7 @@ int iucv_message_purge(struct iucv_path *path, struct iucv_message *msg, int rc; local_bh_disable(); - if (!cpu_isset(smp_processor_id(), iucv_buffer_cpumask)) { + if (cpus_empty(iucv_buffer_cpumask)) { rc = -EIO; goto out; } @@ -1160,7 +1160,7 @@ int __iucv_message_receive(struct iucv_path *path, struct iucv_message *msg, if (msg->flags & IUCV_IPRMDATA) return iucv_message_receive_iprmdata(path, msg, flags, buffer, size, residual); - if (!cpu_isset(smp_processor_id(), iucv_buffer_cpumask)) { + if (cpus_empty(iucv_buffer_cpumask)) { rc = -EIO; goto out; } @@ -1233,7 +1233,7 @@ int iucv_message_reject(struct iucv_path *path, struct iucv_message *msg) int rc; local_bh_disable(); - if (!cpu_isset(smp_processor_id(), iucv_buffer_cpumask)) { + if (cpus_empty(iucv_buffer_cpumask)) { rc = -EIO; goto out; } @@ -1272,7 +1272,7 @@ int iucv_message_reply(struct iucv_path *path, struct iucv_message *msg, int rc; local_bh_disable(); - if (!cpu_isset(smp_processor_id(), iucv_buffer_cpumask)) { + if (cpus_empty(iucv_buffer_cpumask)) { rc = -EIO; goto out; } @@ -1322,7 +1322,7 @@ int __iucv_message_send(struct iucv_path *path, struct iucv_message *msg, union iucv_param *parm; int rc; - if (!cpu_isset(smp_processor_id(), iucv_buffer_cpumask)) { + if (cpus_empty(iucv_buffer_cpumask)) { rc = -EIO; goto out; } @@ -1409,7 +1409,7 @@ int iucv_message_send2way(struct iucv_path *path, struct iucv_message *msg, int rc; local_bh_disable(); - if (!cpu_isset(smp_processor_id(), iucv_buffer_cpumask)) { + if (cpus_empty(iucv_buffer_cpumask)) { rc = -EIO; goto out; } -- cgit v1.1 From b29e4da41eb1114080b06dce31326d5a0e96a15a Mon Sep 17 00:00:00 2001 From: Hendrik Brueckner Date: Wed, 16 Sep 2009 04:37:24 +0000 Subject: iucv: use correct output register in iucv_query_maxconn() The iucv_query_maxconn() function uses the wrong output register and stores the size of the interrupt buffer instead of the maximum number of connections. According to the QUERY IUCV function, general register 1 contains the maximum number of connections. If the maximum number of connections is not set properly, the following warning is displayed: Badness at /usr/src/kernel-source/2.6.30-39.x.20090806/net/iucv/iucv.c:1808 Modules linked in: netiucv fsm af_iucv sunrpc qeth_l3 dm_multipath dm_mod vmur qeth ccwgroup CPU: 0 Tainted: G W 2.6.30 #4 Process seq (pid: 16925, task: 0000000030e24a40, ksp: 000000003033bd98) Krnl PSW : 0404200180000000 000000000053b270 (iucv_external_interrupt+0x64/0x224) R:0 T:1 IO:0 EX:0 Key:0 M:1 W:0 P:0 AS:0 CC:2 PM:0 EA:3 Krnl GPRS: 00000000011279c2 00000000014bdb70 0029000000000000 0000000000000029 000000000053b236 000000000001dba4 0000000000000000 0000000000859210 0000000000a67f68 00000000008a6100 000000003f83fb90 0000000000004000 000000003f8c7bc8 00000000005a2250 000000000053b236 000000003fc2fe08 Krnl Code: 000000000053b262: e33010000021 clg %r3,0(%r1) 000000000053b268: a7440010 brc 4,53b288 000000000053b26c: a7f40001 brc 15,53b26e >000000000053b270: c03000184134 larl %r3,8434d8 000000000053b276: eb220030000c srlg %r2,%r2,48 000000000053b27c: eb6ff0a00004 lmg %r6,%r15,160(%r15) 000000000053b282: c0f4fffff6a7 brcl 15,539fd0 000000000053b288: 4310a003 ic %r1,3(%r10) Call Trace: ([<000000000053b236>] iucv_external_interrupt+0x2a/0x224) [<000000000010e09e>] do_extint+0x132/0x190 [<00000000001184b6>] ext_no_vtime+0x1e/0x22 [<0000000000549f7a>] _spin_unlock_irqrestore+0x96/0xa4 ([<0000000000549f70>] _spin_unlock_irqrestore+0x8c/0xa4) [<00000000002101d6>] pipe_write+0x3da/0x5bc [<0000000000205d14>] do_sync_write+0xe4/0x13c [<0000000000206a7e>] vfs_write+0xae/0x15c [<0000000000206c24>] SyS_write+0x54/0xac [<0000000000117c8e>] sysc_noemu+0x10/0x16 [<00000042ff8defcc>] 0x42ff8defcc Signed-off-by: Hendrik Brueckner Signed-off-by: Ursula Braun Signed-off-by: David S. Miller --- net/iucv/iucv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net') diff --git a/net/iucv/iucv.c b/net/iucv/iucv.c index 8aaa23c..3973d0e 100644 --- a/net/iucv/iucv.c +++ b/net/iucv/iucv.c @@ -362,7 +362,7 @@ static int iucv_query_maxconn(void) " srl %0,28\n" : "=d" (ccode), "+d" (reg0), "+d" (reg1) : : "cc"); if (ccode == 0) - iucv_max_pathid = reg0; + iucv_max_pathid = reg1; kfree(param); return ccode ? -EPERM : 0; } -- cgit v1.1 From d9973179aef2af88b6fe4cc1df7ced6fe7cec7d0 Mon Sep 17 00:00:00 2001 From: Hendrik Brueckner Date: Wed, 16 Sep 2009 04:37:25 +0000 Subject: af_iucv: fix race in __iucv_sock_wait() Moving prepare_to_wait before the condition to avoid a race between schedule_timeout and wake up. The race can appear during iucv_sock_connect() and iucv_callback_connack(). Signed-off-by: Hendrik Brueckner Signed-off-by: Ursula Braun Signed-off-by: David S. Miller --- net/iucv/af_iucv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net') diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c index 3c915fb..21ee68b 100644 --- a/net/iucv/af_iucv.c +++ b/net/iucv/af_iucv.c @@ -59,8 +59,8 @@ do { \ DEFINE_WAIT(__wait); \ long __timeo = timeo; \ ret = 0; \ + prepare_to_wait(sk->sk_sleep, &__wait, TASK_INTERRUPTIBLE); \ while (!(condition)) { \ - prepare_to_wait(sk->sk_sleep, &__wait, TASK_INTERRUPTIBLE); \ if (!__timeo) { \ ret = -EAGAIN; \ break; \ -- cgit v1.1 From 56a73de3889383b70ed1fef06aaab0677731b0ea Mon Sep 17 00:00:00 2001 From: Hendrik Brueckner Date: Wed, 16 Sep 2009 04:37:26 +0000 Subject: af_iucv: handle non-accepted sockets after resuming from suspend After resuming from suspend, all af_iucv sockets are disconnected. Ensure that iucv_accept_dequeue() can handle disconnected sockets which are not yet accepted. Signed-off-by: Hendrik Brueckner Signed-off-by: Ursula Braun Signed-off-by: David S. Miller --- net/iucv/af_iucv.c | 1 + 1 file changed, 1 insertion(+) (limited to 'net') diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c index 21ee68b..a48fd28 100644 --- a/net/iucv/af_iucv.c +++ b/net/iucv/af_iucv.c @@ -569,6 +569,7 @@ struct sock *iucv_accept_dequeue(struct sock *parent, struct socket *newsock) if (sk->sk_state == IUCV_CONNECTED || sk->sk_state == IUCV_SEVERED || + sk->sk_state == IUCV_DISCONN || /* due to PM restore */ !newsock) { iucv_accept_unlink(sk); if (newsock) -- cgit v1.1 From 7514bab04e567c9408fe0facbde4277f09d5eb74 Mon Sep 17 00:00:00 2001 From: Hendrik Brueckner Date: Wed, 16 Sep 2009 04:37:27 +0000 Subject: af_iucv: do not call iucv_sock_kill() twice For non-accepted sockets on the accept queue, iucv_sock_kill() is called twice (in iucv_sock_close() and iucv_sock_cleanup_listen()). This typically results in a kernel oops as shown below. Remove the duplicate call to iucv_sock_kill() and set the SOCK_ZAPPED flag in iucv_sock_close() only. The iucv_sock_kill() function frees a socket only if the socket is zapped and orphaned (sk->sk_socket == NULL): - Non-accepted sockets are always orphaned and, thus, iucv_sock_kill() frees the socket twice. - For accepted sockets or sockets created with iucv_sock_create(), sk->sk_socket is initialized. This caused the first call to iucv_sock_kill() to return immediately. To free these sockets, iucv_sock_release() uses sock_orphan() before calling iucv_sock_kill(). <1>Unable to handle kernel pointer dereference at virtual kernel address 000000003edd3000 <4>Oops: 0011 [#1] PREEMPT SMP DEBUG_PAGEALLOC <4>Modules linked in: af_iucv sunrpc qeth_l3 dm_multipath dm_mod qeth vmur ccwgroup <4>CPU: 0 Not tainted 2.6.30 #4 <4>Process iucv_sock_close (pid: 2486, task: 000000003aea4340, ksp: 000000003b75bc68) <4>Krnl PSW : 0704200180000000 000003e00168e23a (iucv_sock_kill+0x2e/0xcc [af_iucv]) <4> R:0 T:1 IO:1 EX:1 Key:0 M:1 W:0 P:0 AS:0 CC:2 PM:0 EA:3 <4>Krnl GPRS: 0000000000000000 000000003b75c000 000000003edd37f0 0000000000000001 <4> 000003e00168ec62 000000003988d960 0000000000000000 000003e0016b0608 <4> 000000003fe81b20 000000003839bb58 00000000399977f0 000000003edd37f0 <4> 000003e00168b000 000003e00168f138 000000003b75bcd0 000000003b75bc98 <4>Krnl Code: 000003e00168e22a: c0c0ffffe6eb larl %r12,3e00168b000 <4> 000003e00168e230: b90400b2 lgr %r11,%r2 <4> 000003e00168e234: e3e0f0980024 stg %r14,152(%r15) <4> >000003e00168e23a: e310225e0090 llgc %r1,606(%r2) <4> 000003e00168e240: a7110001 tmll %r1,1 <4> 000003e00168e244: a7840007 brc 8,3e00168e252 <4> 000003e00168e248: d507d00023c8 clc 0(8,%r13),968(%r2) <4> 000003e00168e24e: a7840009 brc 8,3e00168e260 <4>Call Trace: <4>([<000003e0016b0608>] afiucv_dbf+0x0/0xfffffffffffdea20 [af_iucv]) <4> [<000003e00168ec6c>] iucv_sock_close+0x130/0x368 [af_iucv] <4> [<000003e00168ef02>] iucv_sock_release+0x5e/0xe4 [af_iucv] <4> [<0000000000438e6c>] sock_release+0x44/0x104 <4> [<0000000000438f5e>] sock_close+0x32/0x50 <4> [<0000000000207898>] __fput+0xf4/0x250 <4> [<00000000002038aa>] filp_close+0x7a/0xa8 <4> [<00000000002039ba>] SyS_close+0xe2/0x148 <4> [<0000000000117c8e>] sysc_noemu+0x10/0x16 <4> [<00000042ff8deeac>] 0x42ff8deeac Signed-off-by: Hendrik Brueckner Signed-off-by: Ursula Braun Signed-off-by: David S. Miller --- net/iucv/af_iucv.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'net') diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c index a48fd28..c23ed4f 100644 --- a/net/iucv/af_iucv.c +++ b/net/iucv/af_iucv.c @@ -361,10 +361,9 @@ static void iucv_sock_cleanup_listen(struct sock *parent) } parent->sk_state = IUCV_CLOSED; - sock_set_flag(parent, SOCK_ZAPPED); } -/* Kill socket */ +/* Kill socket (only if zapped and orphaned) */ static void iucv_sock_kill(struct sock *sk) { if (!sock_flag(sk, SOCK_ZAPPED) || sk->sk_socket) @@ -426,17 +425,18 @@ static void iucv_sock_close(struct sock *sk) skb_queue_purge(&iucv->send_skb_q); skb_queue_purge(&iucv->backlog_skb_q); - - sock_set_flag(sk, SOCK_ZAPPED); break; default: sock_set_flag(sk, SOCK_ZAPPED); + /* nothing to do here */ break; } + /* mark socket for deletion by iucv_sock_kill() */ + sock_set_flag(sk, SOCK_ZAPPED); + release_sock(sk); - iucv_sock_kill(sk); } static void iucv_sock_init(struct sock *sk, struct sock *parent) -- cgit v1.1 From bf95d20fdbd602d72c28a009a55d90d5109b8a86 Mon Sep 17 00:00:00 2001 From: Hendrik Brueckner Date: Wed, 16 Sep 2009 04:37:28 +0000 Subject: af_iucv: fix race when queueing skbs on the backlog queue iucv_sock_recvmsg() and iucv_process_message()/iucv_fragment_skb race for dequeuing an skb from the backlog queue. If iucv_sock_recvmsg() dequeues first, iucv_process_message() calls sock_queue_rcv_skb() with an skb that is NULL. This results in the following kernel panic: <1>Unable to handle kernel pointer dereference at virtual kernel address (null) <4>Oops: 0004 [#1] PREEMPT SMP DEBUG_PAGEALLOC <4>Modules linked in: af_iucv sunrpc qeth_l3 dm_multipath dm_mod vmur qeth ccwgroup <4>CPU: 0 Not tainted 2.6.30 #4 <4>Process client-iucv (pid: 4787, task: 0000000034e75940, ksp: 00000000353e3710) <4>Krnl PSW : 0704000180000000 000000000043ebca (sock_queue_rcv_skb+0x7a/0x138) <4> R:0 T:1 IO:1 EX:1 Key:0 M:1 W:0 P:0 AS:0 CC:0 PM:0 EA:3 <4>Krnl GPRS: 0052900000000000 000003e0016e0fe8 0000000000000000 0000000000000000 <4> 000000000043eba8 0000000000000002 0000000000000001 00000000341aa7f0 <4> 0000000000000000 0000000000007800 0000000000000000 0000000000000000 <4> 00000000341aa7f0 0000000000594650 000000000043eba8 000000003fc2fb28 <4>Krnl Code: 000000000043ebbe: a7840006 brc 8,43ebca <4> 000000000043ebc2: 5930c23c c %r3,572(%r12) <4> 000000000043ebc6: a724004c brc 2,43ec5e <4> >000000000043ebca: e3c0b0100024 stg %r12,16(%r11) <4> 000000000043ebd0: a7190000 lghi %r1,0 <4> 000000000043ebd4: e310b0200024 stg %r1,32(%r11) <4> 000000000043ebda: c010ffffdce9 larl %r1,43a5ac <4> 000000000043ebe0: e310b0800024 stg %r1,128(%r11) <4>Call Trace: <4>([<000000000043eba8>] sock_queue_rcv_skb+0x58/0x138) <4> [<000003e0016bcf2a>] iucv_process_message+0x112/0x3cc [af_iucv] <4> [<000003e0016bd3d4>] iucv_callback_rx+0x1f0/0x274 [af_iucv] <4> [<000000000053a21a>] iucv_message_pending+0xa2/0x120 <4> [<000000000053b5a6>] iucv_tasklet_fn+0x176/0x1b8 <4> [<000000000014fa82>] tasklet_action+0xfe/0x1f4 <4> [<0000000000150a56>] __do_softirq+0x116/0x284 <4> [<0000000000111058>] do_softirq+0xe4/0xe8 <4> [<00000000001504ba>] irq_exit+0xba/0xd8 <4> [<000000000010e0b2>] do_extint+0x146/0x190 <4> [<00000000001184b6>] ext_no_vtime+0x1e/0x22 <4> [<00000000001fbf4e>] kfree+0x202/0x28c <4>([<00000000001fbf44>] kfree+0x1f8/0x28c) <4> [<000000000044205a>] __kfree_skb+0x32/0x124 <4> [<000003e0016bd8b2>] iucv_sock_recvmsg+0x236/0x41c [af_iucv] <4> [<0000000000437042>] sock_aio_read+0x136/0x160 <4> [<0000000000205e50>] do_sync_read+0xe4/0x13c <4> [<0000000000206dce>] vfs_read+0x152/0x15c <4> [<0000000000206ed0>] SyS_read+0x54/0xac <4> [<0000000000117c8e>] sysc_noemu+0x10/0x16 <4> [<00000042ff8def3c>] 0x42ff8def3c Signed-off-by: Hendrik Brueckner Signed-off-by: Ursula Braun Signed-off-by: David S. Miller --- net/iucv/af_iucv.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'net') diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c index c23ed4f..d985d16 100644 --- a/net/iucv/af_iucv.c +++ b/net/iucv/af_iucv.c @@ -1036,6 +1036,10 @@ out: return err; } +/* iucv_fragment_skb() - Fragment a single IUCV message into multiple skb's + * + * Locking: must be called with message_q.lock held + */ static int iucv_fragment_skb(struct sock *sk, struct sk_buff *skb, int len) { int dataleft, size, copied = 0; @@ -1070,6 +1074,10 @@ static int iucv_fragment_skb(struct sock *sk, struct sk_buff *skb, int len) return 0; } +/* iucv_process_message() - Receive a single outstanding IUCV message + * + * Locking: must be called with message_q.lock held + */ static void iucv_process_message(struct sock *sk, struct sk_buff *skb, struct iucv_path *path, struct iucv_message *msg) @@ -1120,6 +1128,10 @@ static void iucv_process_message(struct sock *sk, struct sk_buff *skb, skb_queue_head(&iucv_sk(sk)->backlog_skb_q, skb); } +/* iucv_process_message_q() - Process outstanding IUCV messages + * + * Locking: must be called with message_q.lock held + */ static void iucv_process_message_q(struct sock *sk) { struct iucv_sock *iucv = iucv_sk(sk); @@ -1210,6 +1222,7 @@ static int iucv_sock_recvmsg(struct kiocb *iocb, struct socket *sock, kfree_skb(skb); /* Queue backlog skbs */ + spin_lock_bh(&iucv->message_q.lock); rskb = skb_dequeue(&iucv->backlog_skb_q); while (rskb) { if (sock_queue_rcv_skb(sk, rskb)) { @@ -1221,11 +1234,10 @@ static int iucv_sock_recvmsg(struct kiocb *iocb, struct socket *sock, } } if (skb_queue_empty(&iucv->backlog_skb_q)) { - spin_lock_bh(&iucv->message_q.lock); if (!list_empty(&iucv->message_q.list)) iucv_process_message_q(sk); - spin_unlock_bh(&iucv->message_q.lock); } + spin_unlock_bh(&iucv->message_q.lock); } done: -- cgit v1.1 From 0522fea6505f7b03a82787acdc6ad3066d9b4de3 Mon Sep 17 00:00:00 2001 From: Jens Rosenboom Date: Thu, 17 Sep 2009 10:24:24 -0700 Subject: ipv6: Log the affected address when DAD failure occurs If an interface has multiple addresses, the current message for DAD failure isn't really helpful, so this patch adds the address itself to the printk. Signed-off-by: Jens Rosenboom Signed-off-by: David S. Miller --- net/ipv6/addrconf.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'net') diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index f216a41..55f486d 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -1407,8 +1407,8 @@ void addrconf_dad_failure(struct inet6_ifaddr *ifp) struct inet6_dev *idev = ifp->idev; if (net_ratelimit()) - printk(KERN_INFO "%s: IPv6 duplicate address detected!\n", - ifp->idev->dev->name); + printk(KERN_INFO "%s: IPv6 duplicate address %pI6c detected!\n", + ifp->idev->dev->name, &ifp->addr); if (idev->cnf.accept_dad > 1 && !idev->cnf.disable_ipv6) { struct in6_addr addr; -- cgit v1.1 From a19d2158439d6fba8160d7d2446f233f525f09e7 Mon Sep 17 00:00:00 2001 From: Jarek Poplawski Date: Thu, 17 Sep 2009 10:26:07 -0700 Subject: pkt_sched: Fix qstats.qlen updating in dump_stats Some classful qdiscs miss qstats.qlen updating with q.qlen of their child qdiscs in dump_stats methods. Signed-off-by: Jarek Poplawski Signed-off-by: David S. Miller --- net/sched/sch_drr.c | 4 +++- net/sched/sch_mq.c | 1 + net/sched/sch_multiq.c | 1 + net/sched/sch_prio.c | 1 + 4 files changed, 6 insertions(+), 1 deletion(-) (limited to 'net') diff --git a/net/sched/sch_drr.c b/net/sched/sch_drr.c index 12b2fb0..5a888af 100644 --- a/net/sched/sch_drr.c +++ b/net/sched/sch_drr.c @@ -274,8 +274,10 @@ static int drr_dump_class_stats(struct Qdisc *sch, unsigned long arg, struct tc_drr_stats xstats; memset(&xstats, 0, sizeof(xstats)); - if (cl->qdisc->q.qlen) + if (cl->qdisc->q.qlen) { xstats.deficit = cl->deficit; + cl->qdisc->qstats.qlen = cl->qdisc->q.qlen; + } if (gnet_stats_copy_basic(d, &cl->bstats) < 0 || gnet_stats_copy_rate_est(d, &cl->rate_est) < 0 || diff --git a/net/sched/sch_mq.c b/net/sched/sch_mq.c index 600c501..d1dea3d 100644 --- a/net/sched/sch_mq.c +++ b/net/sched/sch_mq.c @@ -193,6 +193,7 @@ static int mq_dump_class_stats(struct Qdisc *sch, unsigned long cl, struct netdev_queue *dev_queue = mq_queue_get(sch, cl); sch = dev_queue->qdisc_sleeping; + sch->qstats.qlen = sch->q.qlen; if (gnet_stats_copy_basic(d, &sch->bstats) < 0 || gnet_stats_copy_queue(d, &sch->qstats) < 0) return -1; diff --git a/net/sched/sch_multiq.c b/net/sched/sch_multiq.c index 069f81c..7db2c88 100644 --- a/net/sched/sch_multiq.c +++ b/net/sched/sch_multiq.c @@ -359,6 +359,7 @@ static int multiq_dump_class_stats(struct Qdisc *sch, unsigned long cl, struct Qdisc *cl_q; cl_q = q->queues[cl - 1]; + cl_q->qstats.qlen = cl_q->q.qlen; if (gnet_stats_copy_basic(d, &cl_q->bstats) < 0 || gnet_stats_copy_queue(d, &cl_q->qstats) < 0) return -1; diff --git a/net/sched/sch_prio.c b/net/sched/sch_prio.c index 0f73c41..93285ce 100644 --- a/net/sched/sch_prio.c +++ b/net/sched/sch_prio.c @@ -322,6 +322,7 @@ static int prio_dump_class_stats(struct Qdisc *sch, unsigned long cl, struct Qdisc *cl_q; cl_q = q->queues[cl - 1]; + cl_q->qstats.qlen = cl_q->q.qlen; if (gnet_stats_copy_basic(d, &cl_q->bstats) < 0 || gnet_stats_copy_queue(d, &cl_q->qstats) < 0) return -1; -- cgit v1.1