* [PATCH 01/13] Bluetooth: Remove max_tx and tx_window module paramenters from L2CAP
From: Marcel Holtmann @ 2010-07-08 19:59 UTC (permalink / raw)
To: David Miller; +Cc: netdev
In-Reply-To: <cover.1278619047.git.marcel@holtmann.org>
From: Gustavo F. Padovan <padovan@profusion.mobi>
We don't need these parameters anymore since we have socket options for
them.
Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
---
net/bluetooth/l2cap.c | 12 ++----------
1 files changed, 2 insertions(+), 10 deletions(-)
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index 1b682a5..5c636b3 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -60,8 +60,6 @@ static int enable_ertm = 1;
#else
static int enable_ertm = 0;
#endif
-static int max_transmit = L2CAP_DEFAULT_MAX_TX;
-static int tx_window = L2CAP_DEFAULT_TX_WINDOW;
static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN;
static u8 l2cap_fixed_chan[8] = { 0x02, };
@@ -808,9 +806,9 @@ static void l2cap_sock_init(struct sock *sk, struct sock *parent)
pi->mode = L2CAP_MODE_ERTM;
else
pi->mode = L2CAP_MODE_BASIC;
- pi->max_tx = max_transmit;
+ pi->max_tx = L2CAP_DEFAULT_MAX_TX;
pi->fcs = L2CAP_FCS_CRC16;
- pi->tx_win = tx_window;
+ pi->tx_win = L2CAP_DEFAULT_TX_WINDOW;
pi->sec_level = BT_SECURITY_LOW;
pi->role_switch = 0;
pi->force_reliable = 0;
@@ -4674,12 +4672,6 @@ module_exit(l2cap_exit);
module_param(enable_ertm, bool, 0644);
MODULE_PARM_DESC(enable_ertm, "Enable enhanced retransmission mode");
-module_param(max_transmit, uint, 0644);
-MODULE_PARM_DESC(max_transmit, "Max transmit value (default = 3)");
-
-module_param(tx_window, uint, 0644);
-MODULE_PARM_DESC(tx_window, "Transmission window size value (default = 63)");
-
MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
MODULE_DESCRIPTION("Bluetooth L2CAP ver " VERSION);
MODULE_VERSION(VERSION);
--
1.7.1.1
^ permalink raw reply related
* [PATCH 02/13] Bluetooth: Remove L2CAP Extended Features from Kconfig
From: Marcel Holtmann @ 2010-07-08 19:59 UTC (permalink / raw)
To: David Miller; +Cc: netdev
In-Reply-To: <cover.1278619047.git.marcel@holtmann.org>
From: Gustavo F. Padovan <padovan@profusion.mobi>
This reverts commit 84fb0a6334af0ccad3544f6972c055d90fbb9fbe which adds
the L2CAP Extended Features to the Kconfig, that is actually not needed.
One can use other mechanisms to enable L2CAP Extended Features.
Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
---
net/bluetooth/Kconfig | 13 -------------
net/bluetooth/l2cap.c | 4 ----
2 files changed, 0 insertions(+), 17 deletions(-)
diff --git a/net/bluetooth/Kconfig b/net/bluetooth/Kconfig
index ee3b304..ed37168 100644
--- a/net/bluetooth/Kconfig
+++ b/net/bluetooth/Kconfig
@@ -43,19 +43,6 @@ config BT_L2CAP
Say Y here to compile L2CAP support into the kernel or say M to
compile it as module (l2cap).
-config BT_L2CAP_EXT_FEATURES
- bool "L2CAP Extended Features support (EXPERIMENTAL)"
- depends on BT_L2CAP && EXPERIMENTAL
- help
- This option enables the L2CAP Extended Features support. These
- new features include the Enhanced Retransmission and Streaming
- Modes, the Frame Check Sequence (FCS), and Segmentation and
- Reassembly (SAR) for L2CAP packets. They are a required for the
- new Alternate MAC/PHY and the Bluetooth Medical Profile.
-
- You should say N unless you know what you are doing. Note that
- this is in an experimental state yet.
-
config BT_SCO
tristate "SCO links support"
depends on BT
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index 5c636b3..e036419 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -55,11 +55,7 @@
#define VERSION "2.14"
-#ifdef CONFIG_BT_L2CAP_EXT_FEATURES
-static int enable_ertm = 1;
-#else
static int enable_ertm = 0;
-#endif
static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN;
static u8 l2cap_fixed_chan[8] = { 0x02, };
--
1.7.1.1
^ permalink raw reply related
* [PATCH 03/13] Bluetooth: Fix drop of packets with invalid req_seq/tx_seq
From: Marcel Holtmann @ 2010-07-08 19:59 UTC (permalink / raw)
To: David Miller; +Cc: netdev
In-Reply-To: <cover.1278619047.git.marcel@holtmann.org>
From: Gustavo F. Padovan <padovan@profusion.mobi>
We shall not use an unsigned var since we are expecting negatives value
there. Using unsigned causes ERTM connection to close due to invalid
ReqSeq numbers.
Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
---
net/bluetooth/l2cap.c | 5 +++--
1 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index e036419..b08731d 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -3789,7 +3789,7 @@ static inline int l2cap_data_channel_iframe(struct sock *sk, u16 rx_control, str
u8 tx_seq = __get_txseq(rx_control);
u8 req_seq = __get_reqseq(rx_control);
u8 sar = rx_control >> L2CAP_CTRL_SAR_SHIFT;
- u8 tx_seq_offset, expected_tx_seq_offset;
+ int tx_seq_offset, expected_tx_seq_offset;
int num_to_ack = (pi->tx_win/6) + 1;
int err = 0;
@@ -4074,7 +4074,8 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk
struct sock *sk;
struct l2cap_pinfo *pi;
u16 control, len;
- u8 tx_seq, req_seq, next_tx_seq_offset, req_seq_offset;
+ u8 tx_seq, req_seq;
+ int next_tx_seq_offset, req_seq_offset;
sk = l2cap_get_chan_by_scid(&conn->chan_list, cid);
if (!sk) {
--
1.7.1.1
^ permalink raw reply related
* [PATCH 04/13] Bluetooth: Fix bug with ERTM vars increment
From: Marcel Holtmann @ 2010-07-08 19:59 UTC (permalink / raw)
To: David Miller; +Cc: netdev
In-Reply-To: <cover.1278619047.git.marcel@holtmann.org>
From: Gustavo F. Padovan <padovan@profusion.mobi>
All ERTM operations regarding the txWindow should be modulo 64,
otherwise we confuse the ERTM logic and connections will break.
Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
Reviewed-by: João Paulo Rechi Vita <jprvita@profusion.mobi>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
---
net/bluetooth/l2cap.c | 7 ++++---
1 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index b08731d..bca8c41 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -3741,7 +3741,7 @@ static void l2cap_check_srej_gap(struct sock *sk, u8 tx_seq)
l2cap_ertm_reassembly_sdu(sk, skb, control);
l2cap_pi(sk)->buffer_seq_srej =
(l2cap_pi(sk)->buffer_seq_srej + 1) % 64;
- tx_seq++;
+ tx_seq = (tx_seq + 1) % 64;
}
}
@@ -3777,10 +3777,11 @@ static void l2cap_send_srejframe(struct sock *sk, u8 tx_seq)
l2cap_send_sframe(pi, control);
new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC);
- new->tx_seq = pi->expected_tx_seq++;
+ new->tx_seq = pi->expected_tx_seq;
+ pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
list_add_tail(&new->list, SREJ_LIST(sk));
}
- pi->expected_tx_seq++;
+ pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
}
static inline int l2cap_data_channel_iframe(struct sock *sk, u16 rx_control, struct sk_buff *skb)
--
1.7.1.1
^ permalink raw reply related
* [PATCH 05/13] Bluetooth: Only check SAR bits if frame is an I-frame
From: Marcel Holtmann @ 2010-07-08 19:59 UTC (permalink / raw)
To: David Miller; +Cc: netdev
In-Reply-To: <cover.1278619047.git.marcel@holtmann.org>
From: Gustavo F. Padovan <padovan@profusion.mobi>
The SAR bits doesn't make sense for an S-frame. It doesn't use SAR.
Checking SAR for a S-frames can lead to L2CAP errors, it could close
the channel with an invalid packet length, since we was removing the 2
of the of any frame that match SAR start bits, without check if it is
an I-frame.
Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
---
net/bluetooth/l2cap.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index bca8c41..fa842cc 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -4110,7 +4110,7 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk
skb_pull(skb, 2);
len = skb->len;
- if (__is_sar_start(control))
+ if (__is_sar_start(control) && __is_iframe(control))
len -= 2;
if (pi->fcs == L2CAP_FCS_CRC16)
--
1.7.1.1
^ permalink raw reply related
* [PATCH 06/13] Bluetooth: Fix bug in l2cap_ertm_send() behavior
From: Marcel Holtmann @ 2010-07-08 19:59 UTC (permalink / raw)
To: David Miller; +Cc: netdev
In-Reply-To: <cover.1278619047.git.marcel@holtmann.org>
From: Gustavo F. Padovan <padovan@profusion.mobi>
This patch makes l2cap_ertm_send() similar to the Send-Data action of
the ERTM spec. We shall not check for RemoteBusy or WAIT_F state
inside l2cap_ertm_send().
Such checks were causing a bug in the retransmission logic of ERTM and
making ERTM stalls until the ACL is dropped.
Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
Reviewed-by: João Paulo Rechi Vita <jprvita@profusion.mobi>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
---
net/bluetooth/l2cap.c | 12 ++++++------
1 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index fa842cc..4df5473 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -1407,11 +1407,8 @@ static int l2cap_ertm_send(struct sock *sk)
u16 control, fcs;
int nsent = 0;
- if (pi->conn_state & L2CAP_CONN_WAIT_F)
- return 0;
- while ((skb = sk->sk_send_head) && (!l2cap_tx_window_full(sk)) &&
- !(pi->conn_state & L2CAP_CONN_REMOTE_BUSY)) {
+ while ((skb = sk->sk_send_head) && (!l2cap_tx_window_full(sk))) {
if (pi->remote_max_tx &&
bt_cb(skb)->retries == pi->remote_max_tx) {
@@ -1784,6 +1781,11 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms
if (pi->mode == L2CAP_MODE_STREAMING) {
err = l2cap_streaming_send(sk);
} else {
+ if (pi->conn_state & L2CAP_CONN_REMOTE_BUSY &&
+ pi->conn_state && L2CAP_CONN_WAIT_F) {
+ err = len;
+ break;
+ }
spin_lock_bh(&pi->send_lock);
err = l2cap_ertm_send(sk);
spin_unlock_bh(&pi->send_lock);
@@ -3371,8 +3373,6 @@ static inline void l2cap_send_i_or_rr_or_rnr(struct sock *sk)
if (pi->conn_state & L2CAP_CONN_REMOTE_BUSY && pi->unacked_frames > 0)
__mod_retrans_timer();
- pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
-
spin_lock_bh(&pi->send_lock);
l2cap_ertm_send(sk);
spin_unlock_bh(&pi->send_lock);
--
1.7.1.1
^ permalink raw reply related
* [PATCH 07/13] Bluetooth: Fix SREJ_QUEUE corruption in L2CAP
From: Marcel Holtmann @ 2010-07-08 19:59 UTC (permalink / raw)
To: David Miller; +Cc: netdev
In-Reply-To: <cover.1278619047.git.marcel@holtmann.org>
From: João Paulo Rechi Vita <jprvita@profusion.mobi>
Since all TxSeq values are modulo, we shall not compare them directly. We
have to compare their offset inside the TxWindow instead.
Signed-off-by: João Paulo Rechi Vita <jprvita@profusion.mobi>
Acked-by: Gustavo F. Padovan <padovan@profusion.mobi>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
---
net/bluetooth/l2cap.c | 13 ++++++++++++-
1 files changed, 12 insertions(+), 1 deletions(-)
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index 4df5473..df21cdc 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -3387,6 +3387,8 @@ static inline void l2cap_send_i_or_rr_or_rnr(struct sock *sk)
static int l2cap_add_to_srej_queue(struct sock *sk, struct sk_buff *skb, u8 tx_seq, u8 sar)
{
struct sk_buff *next_skb;
+ struct l2cap_pinfo *pi = l2cap_pi(sk);
+ int tx_seq_offset, next_tx_seq_offset;
bt_cb(skb)->tx_seq = tx_seq;
bt_cb(skb)->sar = sar;
@@ -3397,11 +3399,20 @@ static int l2cap_add_to_srej_queue(struct sock *sk, struct sk_buff *skb, u8 tx_s
return 0;
}
+ tx_seq_offset = (tx_seq - pi->buffer_seq) % 64;
+ if (tx_seq_offset < 0)
+ tx_seq_offset += 64;
+
do {
if (bt_cb(next_skb)->tx_seq == tx_seq)
return -EINVAL;
- if (bt_cb(next_skb)->tx_seq > tx_seq) {
+ next_tx_seq_offset = (bt_cb(next_skb)->tx_seq -
+ pi->buffer_seq) % 64;
+ if (next_tx_seq_offset < 0)
+ next_tx_seq_offset += 64;
+
+ if (next_tx_seq_offset > tx_seq_offset) {
__skb_queue_before(SREJ_QUEUE(sk), next_skb, skb);
return 0;
}
--
1.7.1.1
^ permalink raw reply related
* [PATCH 08/13] Bluetooth: Fix bug with ERTM minimum packet length
From: Marcel Holtmann @ 2010-07-08 19:59 UTC (permalink / raw)
To: David Miller; +Cc: netdev
In-Reply-To: <cover.1278619047.git.marcel@holtmann.org>
From: Nathan Holstein <nathan@lampreynetworks.com>
ERTM and streaming mode L2CAP sockets have no minimum packet length. Only
basic mode connections have minimum length.
Instead, validate the packet containing all necessary control, FCS,
and SAR fields.
The patch fixes the drop of valid packets with length lower than 4.
Signed-off-by: Nathan Holstein <ngh@isomerica.net>
Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
---
net/bluetooth/l2cap.c | 8 ++++----
1 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index df21cdc..63b0a7d 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -4085,9 +4085,9 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk
{
struct sock *sk;
struct l2cap_pinfo *pi;
- u16 control, len;
+ u16 control;
u8 tx_seq, req_seq;
- int next_tx_seq_offset, req_seq_offset;
+ int len, next_tx_seq_offset, req_seq_offset;
sk = l2cap_get_chan_by_scid(&conn->chan_list, cid);
if (!sk) {
@@ -4157,7 +4157,7 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk
}
if (__is_iframe(control)) {
- if (len < 4) {
+ if (len < 0) {
l2cap_send_disconn_req(pi->conn, sk);
goto drop;
}
@@ -4185,7 +4185,7 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk
if (pi->fcs == L2CAP_FCS_CRC16)
len -= 2;
- if (len > pi->mps || len < 4 || __is_sframe(control))
+ if (len > pi->mps || len < 0 || __is_sframe(control))
goto drop;
if (l2cap_check_fcs(pi, skb))
--
1.7.1.1
^ permalink raw reply related
* [PATCH 09/13] Bluetooth: Proper shutdown ERTM when closing the channel
From: Marcel Holtmann @ 2010-07-08 19:59 UTC (permalink / raw)
To: David Miller; +Cc: netdev
In-Reply-To: <cover.1278619047.git.marcel@holtmann.org>
From: Gustavo F. Padovan <padovan@profusion.mobi>
Fix a crash regarding the Monitor Timeout, it was running even after the
shutdown of the ACL connection, which doesn't make sense.
The same code also fixes another issue, before this patch L2CAP was sending
many Disconnections Requests while we have to send only one.
The issues are related to each other, a expired Monitor Timeout can
trigger a Disconnection Request and then we may have a crash if the link
was already deleted.
Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
---
net/bluetooth/l2cap.c | 59 ++++++++++++++++++++++++++++++------------------
1 files changed, 37 insertions(+), 22 deletions(-)
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index 63b0a7d..41c9887 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -272,6 +272,24 @@ static void l2cap_chan_del(struct sock *sk, int err)
parent->sk_data_ready(parent, 0);
} else
sk->sk_state_change(sk);
+
+ skb_queue_purge(TX_QUEUE(sk));
+
+ if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) {
+ struct srej_list *l, *tmp;
+
+ del_timer(&l2cap_pi(sk)->retrans_timer);
+ del_timer(&l2cap_pi(sk)->monitor_timer);
+ del_timer(&l2cap_pi(sk)->ack_timer);
+
+ skb_queue_purge(SREJ_QUEUE(sk));
+ skb_queue_purge(BUSY_QUEUE(sk));
+
+ list_for_each_entry_safe(l, tmp, SREJ_LIST(sk), list) {
+ list_del(&l->list);
+ kfree(l);
+ }
+ }
}
/* Service level security */
@@ -345,8 +363,12 @@ static inline void l2cap_send_sframe(struct l2cap_pinfo *pi, u16 control)
struct sk_buff *skb;
struct l2cap_hdr *lh;
struct l2cap_conn *conn = pi->conn;
+ struct sock *sk = (struct sock *)pi;
int count, hlen = L2CAP_HDR_SIZE + 2;
+ if (sk->sk_state != BT_CONNECTED)
+ return;
+
if (pi->fcs == L2CAP_FCS_CRC16)
hlen += 2;
@@ -432,10 +454,23 @@ static void l2cap_send_disconn_req(struct l2cap_conn *conn, struct sock *sk)
{
struct l2cap_disconn_req req;
+ if (!conn)
+ return;
+
+ skb_queue_purge(TX_QUEUE(sk));
+
+ if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) {
+ del_timer(&l2cap_pi(sk)->retrans_timer);
+ del_timer(&l2cap_pi(sk)->monitor_timer);
+ del_timer(&l2cap_pi(sk)->ack_timer);
+ }
+
req.dcid = cpu_to_le16(l2cap_pi(sk)->dcid);
req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
l2cap_send_cmd(conn, l2cap_get_ident(conn),
L2CAP_DISCONN_REQ, sizeof(req), &req);
+
+ sk->sk_state = BT_DISCONN;
}
/* ---- L2CAP connections ---- */
@@ -726,7 +761,6 @@ static void __l2cap_sock_close(struct sock *sk, int reason)
sk->sk_type == SOCK_STREAM) {
struct l2cap_conn *conn = l2cap_pi(sk)->conn;
- sk->sk_state = BT_DISCONN;
l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
l2cap_send_disconn_req(conn, sk);
} else
@@ -1407,6 +1441,8 @@ static int l2cap_ertm_send(struct sock *sk)
u16 control, fcs;
int nsent = 0;
+ if (sk->sk_state != BT_CONNECTED)
+ return -ENOTCONN;
while ((skb = sk->sk_send_head) && (!l2cap_tx_window_full(sk))) {
@@ -3065,7 +3101,6 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr
}
default:
- sk->sk_state = BT_DISCONN;
sk->sk_err = ECONNRESET;
l2cap_sock_set_timer(sk, HZ * 5);
l2cap_send_disconn_req(conn, sk);
@@ -3119,16 +3154,6 @@ static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd
sk->sk_shutdown = SHUTDOWN_MASK;
- skb_queue_purge(TX_QUEUE(sk));
-
- if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) {
- skb_queue_purge(SREJ_QUEUE(sk));
- skb_queue_purge(BUSY_QUEUE(sk));
- del_timer(&l2cap_pi(sk)->retrans_timer);
- del_timer(&l2cap_pi(sk)->monitor_timer);
- del_timer(&l2cap_pi(sk)->ack_timer);
- }
-
l2cap_chan_del(sk, ECONNRESET);
bh_unlock_sock(sk);
@@ -3151,16 +3176,6 @@ static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd
if (!sk)
return 0;
- skb_queue_purge(TX_QUEUE(sk));
-
- if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) {
- skb_queue_purge(SREJ_QUEUE(sk));
- skb_queue_purge(BUSY_QUEUE(sk));
- del_timer(&l2cap_pi(sk)->retrans_timer);
- del_timer(&l2cap_pi(sk)->monitor_timer);
- del_timer(&l2cap_pi(sk)->ack_timer);
- }
-
l2cap_chan_del(sk, 0);
bh_unlock_sock(sk);
--
1.7.1.1
^ permalink raw reply related
* [PATCH 10/13] Bluetooth: Fix L2CAP control bit field corruption
From: Marcel Holtmann @ 2010-07-08 19:59 UTC (permalink / raw)
To: David Miller; +Cc: netdev
In-Reply-To: <cover.1278619047.git.marcel@holtmann.org>
From: Gustavo F. Padovan <padovan@profusion.mobi>
When resending an I-frame, ERTM was reusing the control bits from the last
time it was sent, that was causing a corruption in the new control field
due to it dirty fields.
This patches extracts only the SAR bits from the old field and reuse it to
resend the packet, the others bits should be reset and receive the
updated value.
Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
---
net/bluetooth/l2cap.c | 4 ++++
1 files changed, 4 insertions(+), 0 deletions(-)
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index 41c9887..6785e52 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -1422,6 +1422,8 @@ static void l2cap_retransmit_one_frame(struct sock *sk, u8 tx_seq)
tx_skb = skb_clone(skb, GFP_ATOMIC);
bt_cb(skb)->retries++;
control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
+ control &= L2CAP_CTRL_SAR;
+
control |= (pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
| (tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
@@ -1457,6 +1459,8 @@ static int l2cap_ertm_send(struct sock *sk)
bt_cb(skb)->retries++;
control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
+ control &= L2CAP_CTRL_SAR;
+
if (pi->conn_state & L2CAP_CONN_SEND_FBIT) {
control |= L2CAP_CTRL_FINAL;
pi->conn_state &= ~L2CAP_CONN_SEND_FBIT;
--
1.7.1.1
^ permalink raw reply related
* [PATCH 11/13] Bluetooth: Check L2CAP pending status before sending connect request
From: Marcel Holtmann @ 2010-07-08 20:00 UTC (permalink / raw)
To: David Miller; +Cc: netdev
In-Reply-To: <cover.1278619047.git.marcel@holtmann.org>
From: Andrei Emeltchenko <andrei.emeltchenko@nokia.com>
Due to race condition in L2CAP state machine L2CAP Connection Request
may be sent twice for SDP with the same source channel id. Problems
reported connecting to Apple products, some carkit, Blackberry phones.
...
2010-06-07 21:18:03.651031 < ACL data: handle 1 flags 0x02 dlen 12
L2CAP(s): Connect req: psm 1 scid 0x0040
2010-06-07 21:18:03.653473 > HCI Event: Number of Completed Packets (0x13) plen 5
handle 1 packets 1
2010-06-07 21:18:03.653808 > HCI Event: Auth Complete (0x06) plen 3
status 0x00 handle 1
2010-06-07 21:18:03.653869 < ACL data: handle 1 flags 0x02 dlen 12
L2CAP(s): Connect req: psm 1 scid 0x0040
...
Patch uses L2CAP_CONF_CONNECT_PEND flag to mark that L2CAP Connection
Request has been sent already.
Modified version of patch from Ville Tervo.
Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@nokia.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
---
net/bluetooth/l2cap.c | 14 +++++++++++---
1 files changed, 11 insertions(+), 3 deletions(-)
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index 6785e52..c2fb26d 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -417,6 +417,11 @@ static inline void l2cap_send_rr_or_rnr(struct l2cap_pinfo *pi, u16 control)
l2cap_send_sframe(pi, control);
}
+static inline int __l2cap_no_conn_pending(struct sock *sk)
+{
+ return !(l2cap_pi(sk)->conf_state & L2CAP_CONF_CONNECT_PEND);
+}
+
static void l2cap_do_start(struct sock *sk)
{
struct l2cap_conn *conn = l2cap_pi(sk)->conn;
@@ -425,12 +430,13 @@ static void l2cap_do_start(struct sock *sk)
if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE))
return;
- if (l2cap_check_security(sk)) {
+ if (l2cap_check_security(sk) && __l2cap_no_conn_pending(sk)) {
struct l2cap_conn_req req;
req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
req.psm = l2cap_pi(sk)->psm;
l2cap_pi(sk)->ident = l2cap_get_ident(conn);
+ l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
L2CAP_CONN_REQ, sizeof(req), &req);
@@ -493,12 +499,14 @@ static void l2cap_conn_start(struct l2cap_conn *conn)
}
if (sk->sk_state == BT_CONNECT) {
- if (l2cap_check_security(sk)) {
+ if (l2cap_check_security(sk) &&
+ __l2cap_no_conn_pending(sk)) {
struct l2cap_conn_req req;
req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
req.psm = l2cap_pi(sk)->psm;
l2cap_pi(sk)->ident = l2cap_get_ident(conn);
+ l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
L2CAP_CONN_REQ, sizeof(req), &req);
@@ -2948,7 +2956,6 @@ static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hd
l2cap_pi(sk)->ident = 0;
l2cap_pi(sk)->dcid = dcid;
l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
-
l2cap_pi(sk)->conf_state &= ~L2CAP_CONF_CONNECT_PEND;
l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
@@ -4430,6 +4437,7 @@ static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
req.psm = l2cap_pi(sk)->psm;
l2cap_pi(sk)->ident = l2cap_get_ident(conn);
+ l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
L2CAP_CONN_REQ, sizeof(req), &req);
--
1.7.1.1
^ permalink raw reply related
* [PATCH 12/13] Bluetooth: Reset the security level after an authentication failure
From: Marcel Holtmann @ 2010-07-08 20:00 UTC (permalink / raw)
To: David Miller; +Cc: netdev
In-Reply-To: <cover.1278619047.git.marcel@holtmann.org>
From: Johan Hedberg <johan.hedberg@nokia.com>
When authentication fails for a connection the assumed security level
should be set back to BT_SECURITY_LOW so that subsequent connect
attempts over the same link don't falsely assume that security is
adequate enough.
Signed-off-by: Johan Hedberg <johan.hedberg@nokia.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
---
net/bluetooth/hci_event.c | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 6c57fc7..786b5de 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -1049,6 +1049,8 @@ static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *s
if (conn) {
if (!ev->status)
conn->link_mode |= HCI_LM_AUTH;
+ else
+ conn->sec_level = BT_SECURITY_LOW;
clear_bit(HCI_CONN_AUTH_PEND, &conn->pend);
--
1.7.1.1
^ permalink raw reply related
* [PATCH 13/13] Bluetooth: Update sec_level/auth_type for already existing connections
From: Marcel Holtmann @ 2010-07-08 20:00 UTC (permalink / raw)
To: David Miller; +Cc: netdev
In-Reply-To: <cover.1278619047.git.marcel@holtmann.org>
From: Ville Tervo <ville.tervo@nokia.com>
Update auth level for already existing connections if it is lower
than required by new connection.
Signed-off-by: Ville Tervo <ville.tervo@nokia.com>
Reviewed-by: Emeltchenko Andrei <andrei.emeltchenko@nokia.com>
Signed-off-by: Luciano Coelho <luciano.coelho@nokia.com>
Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@nokia.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
---
net/bluetooth/hci_conn.c | 5 +++++
1 files changed, 5 insertions(+), 0 deletions(-)
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index b10e3cd..800b6b9 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -358,6 +358,11 @@ struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8
acl->sec_level = sec_level;
acl->auth_type = auth_type;
hci_acl_connect(acl);
+ } else {
+ if (acl->sec_level < sec_level)
+ acl->sec_level = sec_level;
+ if (acl->auth_type < auth_type)
+ acl->auth_type = auth_type;
}
if (type == ACL_LINK)
--
1.7.1.1
^ permalink raw reply related
* [PATCH 3/6 net-next-2.6] vxge: Fix multicast issues (corrected)
From: Jon Mason @ 2010-07-08 20:06 UTC (permalink / raw)
To: David Miller; +Cc: netdev@vger.kernel.org, Sreenivasa Honnur, Ramkrishna Vepa
In-Reply-To: <20100708192213.GC15167@exar.com>
Fix error in multicast flag check, add calls to restore the status of
multicast and promiscuous mode settings after change_mtu, and style
cleanups to shorten the function calls by using a temporary variable.
Signed-off-by: Jon Mason <jon.mason@exar.com>
Signed-off-by: Sreenivasa Honnur <sreenivasa.honnur@exar.com>
Signed-off-by: Ramkrishna Vepa <ramkrishna.vepa@exar.com>
---
drivers/net/vxge/vxge-main.c | 270 +++++++++++++++++++++++-------------------
1 files changed, 146 insertions(+), 124 deletions(-)
diff --git a/drivers/net/vxge/vxge-main.c b/drivers/net/vxge/vxge-main.c
index b8eed71..f921196 100644
--- a/drivers/net/vxge/vxge-main.c
+++ b/drivers/net/vxge/vxge-main.c
@@ -1091,7 +1091,8 @@ static void vxge_set_multicast(struct net_device *dev)
struct netdev_hw_addr *ha;
struct vxgedev *vdev;
int i, mcast_cnt = 0;
- struct __vxge_hw_device *hldev;
+ struct __vxge_hw_device *hldev;
+ struct vxge_vpath *vpath;
enum vxge_hw_status status = VXGE_HW_OK;
struct macInfo mac_info;
int vpath_idx = 0;
@@ -1111,46 +1112,48 @@ static void vxge_set_multicast(struct net_device *dev)
if ((dev->flags & IFF_ALLMULTI) && (!vdev->all_multi_flg)) {
for (i = 0; i < vdev->no_of_vpath; i++) {
- vxge_assert(vdev->vpaths[i].is_open);
- status = vxge_hw_vpath_mcast_enable(
- vdev->vpaths[i].handle);
+ vpath = &vdev->vpaths[i];
+ vxge_assert(vpath->is_open);
+ status = vxge_hw_vpath_mcast_enable(vpath->handle);
+ if (status != VXGE_HW_OK)
+ vxge_debug_init(VXGE_ERR, "failed to enable "
+ "multicast, status %d", status);
vdev->all_multi_flg = 1;
}
- } else if ((dev->flags & IFF_ALLMULTI) && (vdev->all_multi_flg)) {
+ } else if (!(dev->flags & IFF_ALLMULTI) && (vdev->all_multi_flg)) {
for (i = 0; i < vdev->no_of_vpath; i++) {
- vxge_assert(vdev->vpaths[i].is_open);
- status = vxge_hw_vpath_mcast_disable(
- vdev->vpaths[i].handle);
- vdev->all_multi_flg = 1;
+ vpath = &vdev->vpaths[i];
+ vxge_assert(vpath->is_open);
+ status = vxge_hw_vpath_mcast_disable(vpath->handle);
+ if (status != VXGE_HW_OK)
+ vxge_debug_init(VXGE_ERR, "failed to disable "
+ "multicast, status %d", status);
+ vdev->all_multi_flg = 0;
}
}
- if (status != VXGE_HW_OK)
- vxge_debug_init(VXGE_ERR,
- "failed to %s multicast, status %d",
- dev->flags & IFF_ALLMULTI ?
- "enable" : "disable", status);
if (!vdev->config.addr_learn_en) {
- if (dev->flags & IFF_PROMISC) {
- for (i = 0; i < vdev->no_of_vpath; i++) {
- vxge_assert(vdev->vpaths[i].is_open);
+ for (i = 0; i < vdev->no_of_vpath; i++) {
+ vpath = &vdev->vpaths[i];
+ vxge_assert(vpath->is_open);
+
+ if (dev->flags & IFF_PROMISC)
status = vxge_hw_vpath_promisc_enable(
- vdev->vpaths[i].handle);
- }
- } else {
- for (i = 0; i < vdev->no_of_vpath; i++) {
- vxge_assert(vdev->vpaths[i].is_open);
+ vpath->handle);
+ else
status = vxge_hw_vpath_promisc_disable(
- vdev->vpaths[i].handle);
- }
+ vpath->handle);
+ if (status != VXGE_HW_OK)
+ vxge_debug_init(VXGE_ERR, "failed to %s promisc"
+ ", status %d", dev->flags&IFF_PROMISC ?
+ "enable" : "disable", status);
}
}
memset(&mac_info, 0, sizeof(struct macInfo));
/* Update individual M_CAST address list */
if ((!vdev->all_multi_flg) && netdev_mc_count(dev)) {
-
mcast_cnt = vdev->vpaths[0].mcast_addr_cnt;
list_head = &vdev->vpaths[0].mac_addr_list;
if ((netdev_mc_count(dev) +
@@ -1160,14 +1163,7 @@ static void vxge_set_multicast(struct net_device *dev)
/* Delete previous MC's */
for (i = 0; i < mcast_cnt; i++) {
- if (!list_empty(list_head))
- mac_entry = (struct vxge_mac_addrs *)
- list_first_entry(list_head,
- struct vxge_mac_addrs,
- item);
-
list_for_each_safe(entry, next, list_head) {
-
mac_entry = (struct vxge_mac_addrs *) entry;
/* Copy the mac address to delete */
mac_address = (u8 *)&mac_entry->macaddr;
@@ -1210,9 +1206,7 @@ _set_all_mcast:
mcast_cnt = vdev->vpaths[0].mcast_addr_cnt;
/* Delete previous MC's */
for (i = 0; i < mcast_cnt; i++) {
-
list_for_each_safe(entry, next, list_head) {
-
mac_entry = (struct vxge_mac_addrs *) entry;
/* Copy the mac address to delete */
mac_address = (u8 *)&mac_entry->macaddr;
@@ -1232,9 +1226,10 @@ _set_all_mcast:
/* Enable all multicast */
for (i = 0; i < vdev->no_of_vpath; i++) {
- vxge_assert(vdev->vpaths[i].is_open);
- status = vxge_hw_vpath_mcast_enable(
- vdev->vpaths[i].handle);
+ vpath = &vdev->vpaths[i];
+ vxge_assert(vpath->is_open);
+
+ status = vxge_hw_vpath_mcast_enable(vpath->handle);
if (status != VXGE_HW_OK) {
vxge_debug_init(VXGE_ERR,
"%s:%d Enabling all multicasts failed",
@@ -1395,6 +1390,7 @@ void vxge_vpath_intr_disable(struct vxgedev *vdev, int vp_id)
static int vxge_reset_vpath(struct vxgedev *vdev, int vp_id)
{
enum vxge_hw_status status = VXGE_HW_OK;
+ struct vxge_vpath *vpath = &vdev->vpaths[vp_id];
int ret = 0;
/* check if device is down already */
@@ -1405,12 +1401,10 @@ static int vxge_reset_vpath(struct vxgedev *vdev, int vp_id)
if (test_bit(__VXGE_STATE_RESET_CARD, &vdev->state))
return 0;
- if (vdev->vpaths[vp_id].handle) {
- if (vxge_hw_vpath_reset(vdev->vpaths[vp_id].handle)
- == VXGE_HW_OK) {
+ if (vpath->handle) {
+ if (vxge_hw_vpath_reset(vpath->handle) == VXGE_HW_OK) {
if (is_vxge_card_up(vdev) &&
- vxge_hw_vpath_recover_from_reset(
- vdev->vpaths[vp_id].handle)
+ vxge_hw_vpath_recover_from_reset(vpath->handle)
!= VXGE_HW_OK) {
vxge_debug_init(VXGE_ERR,
"vxge_hw_vpath_recover_from_reset"
@@ -1426,11 +1420,20 @@ static int vxge_reset_vpath(struct vxgedev *vdev, int vp_id)
} else
return VXGE_HW_FAIL;
- vxge_restore_vpath_mac_addr(&vdev->vpaths[vp_id]);
- vxge_restore_vpath_vid_table(&vdev->vpaths[vp_id]);
+ vxge_restore_vpath_mac_addr(vpath);
+ vxge_restore_vpath_vid_table(vpath);
/* Enable all broadcast */
- vxge_hw_vpath_bcast_enable(vdev->vpaths[vp_id].handle);
+ vxge_hw_vpath_bcast_enable(vpath->handle);
+
+ /* Enable all multicast */
+ if (vdev->all_multi_flg) {
+ status = vxge_hw_vpath_mcast_enable(vpath->handle);
+ if (status != VXGE_HW_OK)
+ vxge_debug_init(VXGE_ERR,
+ "%s:%d Enabling multicast failed",
+ __func__, __LINE__);
+ }
/* Enable the interrupts */
vxge_vpath_intr_enable(vdev, vp_id);
@@ -1438,17 +1441,17 @@ static int vxge_reset_vpath(struct vxgedev *vdev, int vp_id)
smp_wmb();
/* Enable the flow of traffic through the vpath */
- vxge_hw_vpath_enable(vdev->vpaths[vp_id].handle);
+ vxge_hw_vpath_enable(vpath->handle);
smp_wmb();
- vxge_hw_vpath_rx_doorbell_init(vdev->vpaths[vp_id].handle);
- vdev->vpaths[vp_id].ring.last_status = VXGE_HW_OK;
+ vxge_hw_vpath_rx_doorbell_init(vpath->handle);
+ vpath->ring.last_status = VXGE_HW_OK;
/* Vpath reset done */
clear_bit(vp_id, &vdev->vp_reset);
/* Start the vpath queue */
- vxge_wake_tx_queue(&vdev->vpaths[vp_id].fifo);
+ vxge_wake_tx_queue(&vpath->fifo);
return ret;
}
@@ -1482,9 +1485,9 @@ static int do_vxge_reset(struct vxgedev *vdev, int event)
vxge_debug_init(VXGE_ERR,
"%s: execution mode is debug, returning..",
vdev->ndev->name);
- clear_bit(__VXGE_STATE_CARD_UP, &vdev->state);
- netif_tx_stop_all_queues(vdev->ndev);
- return 0;
+ clear_bit(__VXGE_STATE_CARD_UP, &vdev->state);
+ netif_tx_stop_all_queues(vdev->ndev);
+ return 0;
}
}
@@ -1631,8 +1634,7 @@ out:
*/
int vxge_reset(struct vxgedev *vdev)
{
- do_vxge_reset(vdev, VXGE_LL_FULL_RESET);
- return 0;
+ return do_vxge_reset(vdev, VXGE_LL_FULL_RESET);
}
/**
@@ -1995,17 +1997,17 @@ enum vxge_hw_status vxge_restore_vpath_mac_addr(struct vxge_vpath *vpath)
/* reset vpaths */
enum vxge_hw_status vxge_reset_all_vpaths(struct vxgedev *vdev)
{
- int i;
enum vxge_hw_status status = VXGE_HW_OK;
+ struct vxge_vpath *vpath;
+ int i;
- for (i = 0; i < vdev->no_of_vpath; i++)
- if (vdev->vpaths[i].handle) {
- if (vxge_hw_vpath_reset(vdev->vpaths[i].handle)
- == VXGE_HW_OK) {
+ for (i = 0; i < vdev->no_of_vpath; i++) {
+ vpath = &vdev->vpaths[i];
+ if (vpath->handle) {
+ if (vxge_hw_vpath_reset(vpath->handle) == VXGE_HW_OK) {
if (is_vxge_card_up(vdev) &&
vxge_hw_vpath_recover_from_reset(
- vdev->vpaths[i].handle)
- != VXGE_HW_OK) {
+ vpath->handle) != VXGE_HW_OK) {
vxge_debug_init(VXGE_ERR,
"vxge_hw_vpath_recover_"
"from_reset failed for vpath: "
@@ -2019,83 +2021,87 @@ enum vxge_hw_status vxge_reset_all_vpaths(struct vxgedev *vdev)
return status;
}
}
+ }
+
return status;
}
/* close vpaths */
void vxge_close_vpaths(struct vxgedev *vdev, int index)
{
+ struct vxge_vpath *vpath;
int i;
+
for (i = index; i < vdev->no_of_vpath; i++) {
- if (vdev->vpaths[i].handle && vdev->vpaths[i].is_open) {
- vxge_hw_vpath_close(vdev->vpaths[i].handle);
+ vpath = &vdev->vpaths[i];
+
+ if (vpath->handle && vpath->is_open) {
+ vxge_hw_vpath_close(vpath->handle);
vdev->stats.vpaths_open--;
}
- vdev->vpaths[i].is_open = 0;
- vdev->vpaths[i].handle = NULL;
+ vpath->is_open = 0;
+ vpath->handle = NULL;
}
}
/* open vpaths */
int vxge_open_vpaths(struct vxgedev *vdev)
{
+ struct vxge_hw_vpath_attr attr;
enum vxge_hw_status status;
- int i;
+ struct vxge_vpath *vpath;
u32 vp_id = 0;
- struct vxge_hw_vpath_attr attr;
+ int i;
for (i = 0; i < vdev->no_of_vpath; i++) {
- vxge_assert(vdev->vpaths[i].is_configured);
- attr.vp_id = vdev->vpaths[i].device_id;
+ vpath = &vdev->vpaths[i];
+
+ vxge_assert(vpath->is_configured);
+ attr.vp_id = vpath->device_id;
attr.fifo_attr.callback = vxge_xmit_compl;
attr.fifo_attr.txdl_term = vxge_tx_term;
attr.fifo_attr.per_txdl_space = sizeof(struct vxge_tx_priv);
- attr.fifo_attr.userdata = (void *)&vdev->vpaths[i].fifo;
+ attr.fifo_attr.userdata = &vpath->fifo;
attr.ring_attr.callback = vxge_rx_1b_compl;
attr.ring_attr.rxd_init = vxge_rx_initial_replenish;
attr.ring_attr.rxd_term = vxge_rx_term;
attr.ring_attr.per_rxd_space = sizeof(struct vxge_rx_priv);
- attr.ring_attr.userdata = (void *)&vdev->vpaths[i].ring;
+ attr.ring_attr.userdata = &vpath->ring;
- vdev->vpaths[i].ring.ndev = vdev->ndev;
- vdev->vpaths[i].ring.pdev = vdev->pdev;
- status = vxge_hw_vpath_open(vdev->devh, &attr,
- &(vdev->vpaths[i].handle));
+ vpath->ring.ndev = vdev->ndev;
+ vpath->ring.pdev = vdev->pdev;
+ status = vxge_hw_vpath_open(vdev->devh, &attr, &vpath->handle);
if (status == VXGE_HW_OK) {
- vdev->vpaths[i].fifo.handle =
+ vpath->fifo.handle =
(struct __vxge_hw_fifo *)attr.fifo_attr.userdata;
- vdev->vpaths[i].ring.handle =
+ vpath->ring.handle =
(struct __vxge_hw_ring *)attr.ring_attr.userdata;
- vdev->vpaths[i].fifo.tx_steering_type =
+ vpath->fifo.tx_steering_type =
vdev->config.tx_steering_type;
- vdev->vpaths[i].fifo.ndev = vdev->ndev;
- vdev->vpaths[i].fifo.pdev = vdev->pdev;
- vdev->vpaths[i].fifo.indicate_max_pkts =
+ vpath->fifo.ndev = vdev->ndev;
+ vpath->fifo.pdev = vdev->pdev;
+ vpath->fifo.indicate_max_pkts =
vdev->config.fifo_indicate_max_pkts;
- vdev->vpaths[i].ring.rx_vector_no = 0;
- vdev->vpaths[i].ring.rx_csum = vdev->rx_csum;
- vdev->vpaths[i].is_open = 1;
- vdev->vp_handles[i] = vdev->vpaths[i].handle;
- vdev->vpaths[i].ring.gro_enable =
- vdev->config.gro_enable;
- vdev->vpaths[i].ring.vlan_tag_strip =
- vdev->vlan_tag_strip;
+ vpath->ring.rx_vector_no = 0;
+ vpath->ring.rx_csum = vdev->rx_csum;
+ vpath->is_open = 1;
+ vdev->vp_handles[i] = vpath->handle;
+ vpath->ring.gro_enable = vdev->config.gro_enable;
+ vpath->ring.vlan_tag_strip = vdev->vlan_tag_strip;
vdev->stats.vpaths_open++;
} else {
vdev->stats.vpath_open_fail++;
vxge_debug_init(VXGE_ERR,
"%s: vpath: %d failed to open "
"with status: %d",
- vdev->ndev->name, vdev->vpaths[i].device_id,
+ vdev->ndev->name, vpath->device_id,
status);
vxge_close_vpaths(vdev, 0);
return -EPERM;
}
- vp_id =
- ((struct __vxge_hw_vpath_handle *)vdev->vpaths[i].handle)->
- vpath->vp_id;
+ vp_id = vpath->handle->vpath->vp_id;
vdev->vpaths_deployed |= vxge_mBIT(vp_id);
}
return VXGE_HW_OK;
@@ -2269,7 +2275,6 @@ start:
vdev->vxge_entries[j].in_use = 0;
ret = pci_enable_msix(vdev->pdev, vdev->entries, vdev->intr_cnt);
-
if (ret > 0) {
vxge_debug_init(VXGE_ERR,
"%s: MSI-X enable failed for %d vectors, ret: %d",
@@ -2315,17 +2320,16 @@ static int vxge_enable_msix(struct vxgedev *vdev)
ret = vxge_alloc_msix(vdev);
if (!ret) {
for (i = 0; i < vdev->no_of_vpath; i++) {
+ struct vxge_vpath *vpath = &vdev->vpaths[i];
- /* If fifo or ring are not enabled
- the MSIX vector for that should be set to 0
- Hence initializeing this array to all 0s.
- */
- vdev->vpaths[i].ring.rx_vector_no =
- (vdev->vpaths[i].device_id *
- VXGE_HW_VPATH_MSIX_ACTIVE) + 1;
+ /* If fifo or ring are not enabled, the MSIX vector for
+ * it should be set to 0.
+ */
+ vpath->ring.rx_vector_no = (vpath->device_id *
+ VXGE_HW_VPATH_MSIX_ACTIVE) + 1;
- vxge_hw_vpath_msix_set(vdev->vpaths[i].handle,
- tim_msix_id, VXGE_ALARM_MSIX_ID);
+ vxge_hw_vpath_msix_set(vpath->handle, tim_msix_id,
+ VXGE_ALARM_MSIX_ID);
}
}
@@ -2540,9 +2544,10 @@ static void vxge_poll_vp_reset(unsigned long data)
static void vxge_poll_vp_lockup(unsigned long data)
{
struct vxgedev *vdev = (struct vxgedev *)data;
- int i;
- struct vxge_ring *ring;
enum vxge_hw_status status = VXGE_HW_OK;
+ struct vxge_vpath *vpath;
+ struct vxge_ring *ring;
+ int i;
for (i = 0; i < vdev->no_of_vpath; i++) {
ring = &vdev->vpaths[i].ring;
@@ -2556,13 +2561,13 @@ static void vxge_poll_vp_lockup(unsigned long data)
/* schedule vpath reset */
if (!test_and_set_bit(i, &vdev->vp_reset)) {
+ vpath = &vdev->vpaths[i];
/* disable interrupts for this vpath */
vxge_vpath_intr_disable(vdev, i);
/* stop the queue for this vpath */
- vxge_stop_tx_queue(&vdev->vpaths[i].
- fifo);
+ vxge_stop_tx_queue(&vpath->fifo);
continue;
}
}
@@ -2591,6 +2596,7 @@ vxge_open(struct net_device *dev)
enum vxge_hw_status status;
struct vxgedev *vdev;
struct __vxge_hw_device *hldev;
+ struct vxge_vpath *vpath;
int ret = 0;
int i;
u64 val64, function_mode;
@@ -2629,15 +2635,17 @@ vxge_open(struct net_device *dev)
netif_napi_add(dev, &vdev->napi, vxge_poll_inta,
vdev->config.napi_weight);
napi_enable(&vdev->napi);
- for (i = 0; i < vdev->no_of_vpath; i++)
- vdev->vpaths[i].ring.napi_p = &vdev->napi;
+ for (i = 0; i < vdev->no_of_vpath; i++) {
+ vpath = &vdev->vpaths[i];
+ vpath->ring.napi_p = &vdev->napi;
+ }
} else {
for (i = 0; i < vdev->no_of_vpath; i++) {
- netif_napi_add(dev, &vdev->vpaths[i].ring.napi,
+ vpath = &vdev->vpaths[i];
+ netif_napi_add(dev, &vpath->ring.napi,
vxge_poll_msix, vdev->config.napi_weight);
- napi_enable(&vdev->vpaths[i].ring.napi);
- vdev->vpaths[i].ring.napi_p =
- &vdev->vpaths[i].ring.napi;
+ napi_enable(&vpath->ring.napi);
+ vpath->ring.napi_p = &vpath->ring.napi;
}
}
@@ -2654,9 +2662,10 @@ vxge_open(struct net_device *dev)
}
for (i = 0; i < vdev->no_of_vpath; i++) {
+ vpath = &vdev->vpaths[i];
+
/* set initial mtu before enabling the device */
- status = vxge_hw_vpath_mtu_set(vdev->vpaths[i].handle,
- vdev->mtu);
+ status = vxge_hw_vpath_mtu_set(vpath->handle, vdev->mtu);
if (status != VXGE_HW_OK) {
vxge_debug_init(VXGE_ERR,
"%s: fatal: can not set new MTU", dev->name);
@@ -2670,10 +2679,21 @@ vxge_open(struct net_device *dev)
"%s: MTU is %d", vdev->ndev->name, vdev->mtu);
VXGE_DEVICE_DEBUG_LEVEL_SET(VXGE_ERR, VXGE_COMPONENT_LL, vdev);
- /* Reprogram the DA table with populated mac addresses */
- for (i = 0; i < vdev->no_of_vpath; i++) {
- vxge_restore_vpath_mac_addr(&vdev->vpaths[i]);
- vxge_restore_vpath_vid_table(&vdev->vpaths[i]);
+ /* Restore the DA, VID table and also multicast and promiscuous mode
+ * states
+ */
+ if (vdev->all_multi_flg) {
+ for (i = 0; i < vdev->no_of_vpath; i++) {
+ vpath = &vdev->vpaths[i];
+ vxge_restore_vpath_mac_addr(vpath);
+ vxge_restore_vpath_vid_table(vpath);
+
+ status = vxge_hw_vpath_mcast_enable(vpath->handle);
+ if (status != VXGE_HW_OK)
+ vxge_debug_init(VXGE_ERR,
+ "%s:%d Enabling multicast failed",
+ __func__, __LINE__);
+ }
}
/* Enable vpath to sniff all unicast/multicast traffic that not
@@ -2702,14 +2722,14 @@ vxge_open(struct net_device *dev)
/* Enabling Bcast and mcast for all vpath */
for (i = 0; i < vdev->no_of_vpath; i++) {
- status = vxge_hw_vpath_bcast_enable(vdev->vpaths[i].handle);
+ vpath = &vdev->vpaths[i];
+ status = vxge_hw_vpath_bcast_enable(vpath->handle);
if (status != VXGE_HW_OK)
vxge_debug_init(VXGE_ERR,
"%s : Can not enable bcast for vpath "
"id %d", dev->name, i);
if (vdev->config.addr_learn_en) {
- status =
- vxge_hw_vpath_mcast_enable(vdev->vpaths[i].handle);
+ status = vxge_hw_vpath_mcast_enable(vpath->handle);
if (status != VXGE_HW_OK)
vxge_debug_init(VXGE_ERR,
"%s : Can not enable mcast for vpath "
@@ -2744,9 +2764,11 @@ vxge_open(struct net_device *dev)
smp_wmb();
for (i = 0; i < vdev->no_of_vpath; i++) {
- vxge_hw_vpath_enable(vdev->vpaths[i].handle);
+ vpath = &vdev->vpaths[i];
+
+ vxge_hw_vpath_enable(vpath->handle);
smp_wmb();
- vxge_hw_vpath_rx_doorbell_init(vdev->vpaths[i].handle);
+ vxge_hw_vpath_rx_doorbell_init(vpath->handle);
}
netif_tx_start_all_queues(vdev->ndev);
^ permalink raw reply related
* Re: bnx2/5709: Strange interrupts spread
From: Christophe Ngo Van Duc @ 2010-07-08 20:06 UTC (permalink / raw)
To: Rick Jones; +Cc: netdev@vger.kernel.org
In-Reply-To: <4C326318.8050006@hp.com>
Traffic is IP no doubt about that. Lots of TCP and UDP traffic. I can
provide a very short pcap if you want (lots of traffic so pcap can be
big really quickly).
- The 2 interfaces that have this problems are running in promiscuous
mode (without having an assiged IP address to the interface) inside a
linux bridge interface (br0), but the traffic that is bridged is IP.
- The other 2 that works correctly: are not in promiscuous and have an
IP assigned to the network card.
So I am thinking that for some reason the RSS is activating only when
a specific configuration is set on the interface but not just on if it
is IP traffic or not.
Best Regards,
Christophe.
On Mon, Jul 5, 2010 at 7:56 PM, Rick Jones <rick.jones2@hp.com> wrote:
> Christophe Ngo Van Duc wrote:
>>
>> Is it a requirement that the interface has an IP address for the TX
>> and RX hash to work?
>
> At the risk of typing into Michael's keyboard, chances are, what the NIC
> does is follow Microsoft's specs for RSS, which as far as I can tell,
> discusses hashing either just on the IP addresses (v4 or v6) or the IP
> addresses and TCP port numbers, so unless Broadcom has an
> enhancement/extension, if the traffic arriving is not TCP/IP and not
> multiple connections, it probably does not get spread-out.
>
> rick jones
>
^ permalink raw reply
* [PATCH v2 -net-2.6] ll_temac: fix DMA resources leak
From: Denis Kirjanov @ 2010-07-08 20:24 UTC (permalink / raw)
To: davem; +Cc: segooon, john.linn, brian.hill, grant.likely, jpirko, netdev
V2: Check pointers before releasing resources.
Fix DMA resources leak.
Signed-off-by: Denis Kirjanov <dkirjanov@kernel.org>
Signed-off-by: Kulikov Vasiliy <segooon@gmail.com>
---
1 files changed, 32 insertions(+), 0 deletions(-)
diff --git a/drivers/net/ll_temac_main.c b/drivers/net/ll_temac_main.c
index fa303c8..b57d0ff 100644
--- a/drivers/net/ll_temac_main.c
+++ b/drivers/net/ll_temac_main.c
@@ -193,6 +193,35 @@ static int temac_dcr_setup(struct temac_local *lp, struct of_device *op,
#endif
/**
+ * * temac_dma_bd_release - Release buffer descriptor rings
+ */
+static void temac_dma_bd_release(struct net_device *ndev)
+{
+ struct temac_local *lp = netdev_priv(ndev);
+ int i;
+
+ for (i = 0; i < RX_BD_NUM; i++) {
+ if (!lp->rx_skb[i])
+ break;
+ else {
+ dma_unmap_single(ndev->dev.parent, lp->rx_bd_v[i].phys,
+ XTE_MAX_JUMBO_FRAME_SIZE, DMA_FROM_DEVICE);
+ dev_kfree_skb(lp->rx_skb[i]);
+ }
+ }
+ if (lp->rx_bd_v)
+ dma_free_coherent(ndev->dev.parent,
+ sizeof(*lp->rx_bd_v) * RX_BD_NUM,
+ lp->rx_bd_v, lp->rx_bd_p);
+ if (lp->tx_bd_v)
+ dma_free_coherent(ndev->dev.parent,
+ sizeof(*lp->tx_bd_v) * TX_BD_NUM,
+ lp->tx_bd_v, lp->tx_bd_p);
+ if (lp->rx_skb)
+ kfree(lp->rx_skb);
+}
+
+/**
* temac_dma_bd_init - Setup buffer descriptor rings
*/
static int temac_dma_bd_init(struct net_device *ndev)
@@ -275,6 +304,7 @@ static int temac_dma_bd_init(struct net_device *ndev)
return 0;
out:
+ temac_dma_bd_release(ndev);
return -ENOMEM;
}
@@ -858,6 +888,8 @@ static int temac_stop(struct net_device *ndev)
phy_disconnect(lp->phy_dev);
lp->phy_dev = NULL;
+ temac_dma_bd_release(ndev);
+
return 0;
}
^ permalink raw reply related
* Re: [PATCH 1/1] Bluetooth: hidp: Add support for hidraw HIDIOCGFEATURE and HIDIOCSFEATURE
From: Marcel Holtmann @ 2010-07-08 21:11 UTC (permalink / raw)
To: Alan Ott
Cc: David S Miller, Jiri Kosina, Michael Poole, Bastien Nocera,
Eric Dumazet, linux-bluetooth, linux-kernel, netdev
In-Reply-To: <1276467601-9066-1-git-send-email-alan@signal11.us>
Hi Alan,
> This patch adds support or getting and setting feature reports for bluetooth
> HID devices from HIDRAW.
>
> Signed-off-by: Alan Ott <alan@signal11.us>
> ---
> net/bluetooth/hidp/core.c | 121 +++++++++++++++++++++++++++++++++++++++++++--
> net/bluetooth/hidp/hidp.h | 8 +++
> 2 files changed, 125 insertions(+), 4 deletions(-)
>
> diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c
> index bfe641b..0f068a0 100644
> --- a/net/bluetooth/hidp/core.c
> +++ b/net/bluetooth/hidp/core.c
> @@ -36,6 +36,7 @@
> #include <linux/file.h>
> #include <linux/init.h>
> #include <linux/wait.h>
> +#include <linux/mutex.h>
> #include <net/sock.h>
>
> #include <linux/input.h>
> @@ -313,6 +314,93 @@ static int hidp_send_report(struct hidp_session *session, struct hid_report *rep
> return hidp_queue_report(session, buf, rsize);
> }
>
> +static int hidp_get_raw_report(struct hid_device *hid,
> + unsigned char report_number,
> + unsigned char *data, size_t count,
> + unsigned char report_type)
> +{
> + struct hidp_session *session = hid->driver_data;
> + struct sk_buff *skb;
> + size_t len;
> + int numbered_reports = hid->report_enum[report_type].numbered;
> +
> + switch (report_type) {
> + case HID_FEATURE_REPORT:
> + report_type = HIDP_TRANS_GET_REPORT | HIDP_DATA_RTYPE_FEATURE;
> + break;
> + case HID_INPUT_REPORT:
> + report_type = HIDP_TRANS_GET_REPORT | HIDP_DATA_RTYPE_INPUT;
> + break;
> + case HID_OUTPUT_REPORT:
> + report_type = HIDP_TRANS_GET_REPORT | HIDP_DATA_RTYPE_OUPUT;
> + break;
> + default:
> + return -EINVAL;
> + }
> +
> + if (mutex_lock_interruptible(&session->report_mutex))
> + return -ERESTARTSYS;
> +
> + /* Set up our wait, and send the report request to the device. */
> + session->waiting_report_type = report_type & HIDP_DATA_RTYPE_MASK;
> + session->waiting_report_number = numbered_reports ? report_number : -1;
> + set_bit(HIDP_WAITING_FOR_RETURN, &session->flags);
> + data[0] = report_number;
> + if (hidp_send_ctrl_message(hid->driver_data, report_type, data, 1))
> + goto err_eio;
> +
> + /* Wait for the return of the report. The returned report
> + gets put in session->report_return. */
> + while (test_bit(HIDP_WAITING_FOR_RETURN, &session->flags)) {
> + int res;
> +
> + res = wait_event_interruptible_timeout(session->report_queue,
> + !test_bit(HIDP_WAITING_FOR_RETURN, &session->flags),
> + 5*HZ);
> + if (res == 0) {
> + /* timeout */
> + goto err_eio;
> + }
> + if (res < 0) {
> + /* signal */
> + goto err_restartsys;
> + }
> + }
> +
> + skb = session->report_return;
> + if (skb) {
> + if (numbered_reports) {
> + /* Strip off the report number. */
> + size_t rpt_len = skb->len-1;
> + len = rpt_len < count ? rpt_len : count;
> + memcpy(data, skb->data+1, len);
> + } else {
> + len = skb->len < count ? skb->len : count;
> + memcpy(data, skb->data, len);
> + }
> +
> + kfree_skb(skb);
> + session->report_return = NULL;
> + } else {
> + /* Device returned a HANDSHAKE, indicating protocol error. */
> + len = -EIO;
> + }
> +
> + clear_bit(HIDP_WAITING_FOR_RETURN, &session->flags);
> + mutex_unlock(&session->report_mutex);
> +
> + return len;
> +
> +err_restartsys:
> + clear_bit(HIDP_WAITING_FOR_RETURN, &session->flags);
> + mutex_unlock(&session->report_mutex);
> + return -ERESTARTSYS;
> +err_eio:
> + clear_bit(HIDP_WAITING_FOR_RETURN, &session->flags);
> + mutex_unlock(&session->report_mutex);
> + return -EIO;
> +}
> +
> static int hidp_output_raw_report(struct hid_device *hid, unsigned char *data, size_t count,
> unsigned char report_type)
> {
> @@ -367,6 +455,10 @@ static void hidp_process_handshake(struct hidp_session *session,
> case HIDP_HSHK_ERR_INVALID_REPORT_ID:
> case HIDP_HSHK_ERR_UNSUPPORTED_REQUEST:
> case HIDP_HSHK_ERR_INVALID_PARAMETER:
> + if (test_bit(HIDP_WAITING_FOR_RETURN, &session->flags)) {
> + clear_bit(HIDP_WAITING_FOR_RETURN, &session->flags);
> + wake_up_interruptible(&session->report_queue);
> + }
> /* FIXME: Call into SET_ GET_ handlers here */
> break;
>
> @@ -403,9 +495,11 @@ static void hidp_process_hid_control(struct hidp_session *session,
> }
> }
>
> -static void hidp_process_data(struct hidp_session *session, struct sk_buff *skb,
> +/* Returns true if the passed-in skb should be freed by the caller. */
> +static int hidp_process_data(struct hidp_session *session, struct sk_buff *skb,
> unsigned char param)
> {
> + int done_with_skb = 1;
> BT_DBG("session %p skb %p len %d param 0x%02x", session, skb, skb->len, param);
>
> switch (param) {
> @@ -417,7 +511,6 @@ static void hidp_process_data(struct hidp_session *session, struct sk_buff *skb,
>
> if (session->hid)
> hid_input_report(session->hid, HID_INPUT_REPORT, skb->data, skb->len, 0);
> -
> break;
>
> case HIDP_DATA_RTYPE_OTHER:
> @@ -429,12 +522,27 @@ static void hidp_process_data(struct hidp_session *session, struct sk_buff *skb,
> __hidp_send_ctrl_message(session,
> HIDP_TRANS_HANDSHAKE | HIDP_HSHK_ERR_INVALID_PARAMETER, NULL, 0);
> }
> +
> + if (test_bit(HIDP_WAITING_FOR_RETURN, &session->flags) &&
> + param == session->waiting_report_type) {
> + if (session->waiting_report_number < 0 ||
> + session->waiting_report_number == skb->data[0]) {
> + /* hidp_get_raw_report() is waiting on this report. */
> + session->report_return = skb;
> + done_with_skb = 0;
> + clear_bit(HIDP_WAITING_FOR_RETURN, &session->flags);
> + wake_up_interruptible(&session->report_queue);
> + }
> + }
> +
> + return done_with_skb;
> }
>
> static void hidp_recv_ctrl_frame(struct hidp_session *session,
> struct sk_buff *skb)
> {
> unsigned char hdr, type, param;
> + int free_skb = 1;
>
> BT_DBG("session %p skb %p len %d", session, skb, skb->len);
>
> @@ -454,7 +562,7 @@ static void hidp_recv_ctrl_frame(struct hidp_session *session,
> break;
>
> case HIDP_TRANS_DATA:
> - hidp_process_data(session, skb, param);
> + free_skb = hidp_process_data(session, skb, param);
> break;
>
> default:
> @@ -463,7 +571,8 @@ static void hidp_recv_ctrl_frame(struct hidp_session *session,
> break;
> }
>
> - kfree_skb(skb);
> + if (free_skb)
> + kfree_skb(skb);
> }
>
> static void hidp_recv_intr_frame(struct hidp_session *session,
> @@ -797,6 +906,7 @@ static int hidp_setup_hid(struct hidp_session *session,
> hid->dev.parent = hidp_get_device(session);
> hid->ll_driver = &hidp_hid_driver;
>
> + hid->hid_get_raw_report = hidp_get_raw_report;
> hid->hid_output_raw_report = hidp_output_raw_report;
>
> err = hid_add_device(hid);
> @@ -857,6 +967,9 @@ int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock,
> skb_queue_head_init(&session->ctrl_transmit);
> skb_queue_head_init(&session->intr_transmit);
>
> + mutex_init(&session->report_mutex);
> + init_waitqueue_head(&session->report_queue);
> +
> session->flags = req->flags & (1 << HIDP_BLUETOOTH_VENDOR_ID);
> session->idle_to = req->idle_to;
>
> diff --git a/net/bluetooth/hidp/hidp.h b/net/bluetooth/hidp/hidp.h
> index 8d934a1..00e71dd 100644
> --- a/net/bluetooth/hidp/hidp.h
> +++ b/net/bluetooth/hidp/hidp.h
> @@ -80,6 +80,7 @@
> #define HIDP_VIRTUAL_CABLE_UNPLUG 0
> #define HIDP_BOOT_PROTOCOL_MODE 1
> #define HIDP_BLUETOOTH_VENDOR_ID 9
> +#define HIDP_WAITING_FOR_RETURN 10
>
> struct hidp_connadd_req {
> int ctrl_sock; // Connected control socket
> @@ -154,6 +155,13 @@ struct hidp_session {
> struct sk_buff_head ctrl_transmit;
> struct sk_buff_head intr_transmit;
>
> + /* Used in hidp_get_raw_report() */
> + int waiting_report_type; /* HIDP_DATA_RTYPE_* */
> + int waiting_report_number; /* -1 for not numbered */
> + struct mutex report_mutex;
> + struct sk_buff *report_return;
> + wait_queue_head_t report_queue;
> +
> /* Report descriptor */
> __u8 *rd_data;
> uint rd_size;
I looked at this and I am bit worried that this should not be done in
this detail in the HIDP driver. Essentially HIDP is a pure transport
driver. It should not handle all these details. Can we make this a bit
easier for the transport drivers to support such features?
Regards
Marcel
^ permalink raw reply
* Re: [PATCH 1/1] Bluetooth: hidp: Add support for hidraw HIDIOCGFEATURE and HIDIOCSFEATURE
From: Marcel Holtmann @ 2010-07-08 21:08 UTC (permalink / raw)
To: Andrei Emeltchenko
Cc: David Miller, ospite, alan, jkosina, mdpoole, hadess,
eric.dumazet, linux-bluetooth, linux-kernel, netdev
In-Reply-To: <AANLkTiktvYWdZmpQs_k7mJRqMCqgfhy1b0T8tX8emmtU@mail.gmail.com>
Hi Andrei,
> >> On Sun, 13 Jun 2010 18:20:01 -0400
> >> Alan Ott <alan@signal11.us> wrote:
> >>
> >>> This patch adds support or getting and setting feature reports for bluetooth
> >>> HID devices from HIDRAW.
> >>>
> >>> Signed-off-by: Alan Ott <alan@signal11.us>
> >>> ---
> >>
> >> Ping.
> >
> > We effectively don't have a bluetooth maintainer at the current point
> > in time. I've tried to let patches sit for a while hoping the listed
> > maintainer would do something, at least occaisionally, but that simply
> > isn't happening.
> > So I'll just pick patches up directly as I find time to review them,
> > but I have to warn that for me it's going to be done in a very low
> > priority way because I really don't find bluetooth all that exciting. :-)
>
> This would be good. We have a backlog of bluetooth kernel patches
> waiting for several months.
> This takes too much time to return to them again and again...
>
> Please keep this ML informed.
as soon as Ville is back from vacation, he should be helping out with
patch review and maintenance.
Regards
Marcel
^ permalink raw reply
* Re: [PATCH] sysfs: Don't allow the creation of symlinks we can't remove
From: Greg KH @ 2010-07-08 21:19 UTC (permalink / raw)
To: Eric W. Biederman
Cc: Greg KH, Andrew Morton, Rafael J. Wysocki, Maciej W. Rozycki,
Kay Sievers, Johannes Berg, netdev
In-Reply-To: <m1630q7x5v.fsf_-_@fess.ebiederm.org>
On Thu, Jul 08, 2010 at 09:31:24AM -0700, Eric W. Biederman wrote:
>
> Recently my tagged sysfs support revealed a flaw in the device core
> that a few rare drivers are running into such that we don't always put
> network devices in a class subdirectory named net/.
>
> Since we are not creating the class directory the network devices wind
> up in a non-tagged directory, but the symlinks to the network devices
> from /sys/class/net are in a tagged directory. All of which works
> until we go to remove or rename the symlink. When we remove or rename
> a symlink we look in the namespace of the target of the symlink.
> Since the target of the symlink is in a non-tagged sysfs directory we
> don't have a namespace to look in, and we fail to remove the symlink.
>
> Detect this problem up front and simply don't create symlinks we won't
> be able to remove later. This prevents symlink leakage and fails in
> a much clearer and more understandable way.
With this patch, how does the existing code fail as the drivers aren't
fixed up?
I like this change, just worried it will cause problems if it gets into
.35, without your RFC patch. Will it?
thanks,
greg k-h
^ permalink raw reply
* Re: [Bugme-new] [Bug 16350] New: RTL8103EL interface new tcp connections get stuck on SYN_SENT state after 10 hours uptime
From: Andrew Morton @ 2010-07-08 21:25 UTC (permalink / raw)
To: netdev; +Cc: bugzilla-daemon, bugme-daemon, Francois Romieu, zic422
In-Reply-To: <bug-16350-10286@https.bugzilla.kernel.org/>
(switched to email. Please respond via emailed reply-to-all, not via the
bugzilla web interface).
On Wed, 7 Jul 2010 14:04:59 GMT
bugzilla-daemon@bugzilla.kernel.org wrote:
> https://bugzilla.kernel.org/show_bug.cgi?id=16350
>
> Summary: RTL8103EL interface new tcp connections get stuck on
> SYN_SENT state after 10 hours uptime
> Product: Networking
> Version: 2.5
> Kernel Version: 2.6.34.1
> Platform: All
> OS/Version: Linux
> Tree: Mainline
> Status: NEW
> Severity: normal
> Priority: P1
> Component: IPV4
> AssignedTo: shemminger@linux-foundation.org
> ReportedBy: zic422@gmail.com
> Regression: No
>
>
> Created an attachment (id=27038)
> --> (https://bugzilla.kernel.org/attachment.cgi?id=27038)
> ioports, iomem, lspci, ver_linux and kernel config
>
> After 9-11 hours uptime network interface of RTL8103EL card cannot make new tcp
> connections to internet and correctly close existing ones. ICMP and UDP works
> fine. Besides r8169 driver I tried also the r8101-1.015.00 one from realtek
> site with older kernel and bug were in place.
>
> Connections inside home network work normally. I tried to reboot router but
> nor reconnecting ethernet cable nor restarting network daemon nor reloading
> kernel module does not make any help. Bug disappears only after rebooting my
> pc.
>
> repeatability of bug is 100% on arch, debian and gentoo
>
> default kernel config
>
> http://bugs.archlinux.org/task/19162 (this bug)
^ permalink raw reply
* Re: Squid hang up on 2.6.34
From: Eric Dumazet @ 2010-07-08 22:06 UTC (permalink / raw)
To: Felipe W Damasio; +Cc: linux-kernel, netdev
In-Reply-To: <AANLkTimn8A0cYZmwNZYitRkBHKKFe4HQ5GU626DLugkk@mail.gmail.com>
Le jeudi 08 juillet 2010 à 16:03 -0300, Felipe W Damasio a écrit :
> Hi All,
>
CC netdev
> I've been using squid for a few months now.
>
> It worked great until recently, when we upgraded to kernel 2.6.34.
>
> We're using squid on bridge scenario with TProxy.
>
> Squid simply hung up (connections with squidclient didn't work), and
> the process didn't respond to kill. I had to use "kill -9".
>
> The dmesg output was:
>
> kernel: general protection fault: 0000 [#1] SMP
> kernel: last sysfs file: /sys/devices/pci0000:00/0000:00:1f.3/i2c-0/name
> kernel: CPU 1
> kernel: Modules linked in:
>
> kernel: Pid: 18351, comm: squid Not tainted 2.6.34 #1 DX58SO/
> kernel: RIP: 0010:[<ffffffff81360c2a>] [<ffffffff81360c2a>]
> sock_rfree+0x26/0x37
> kernel: RSP: 0018:ffff88041c28fc20 EFLAGS: 00010206
> kernel: RAX: dce8dce85d415d41 RBX: ffff88038f098c00 RCX: 0000000000000720
dereferencing RAX, and RAX contains garbage (ascii chars :
"A ] A ]" ...)
At this point, RAX is supposed to contain a pointer to sk->sk_prot
static inline int sk_has_account(struct sock *sk)
{
/* return true if protocol supports memory accounting */
return !!sk->sk_prot->memory_allocated;
}
> kernel: RDX: ffff8804053b2e00 RSI: ffff88032564ee0c RDI: ffff88038f098c00
> kernel: RBP: ffff8804051b2e00 R08: 0000000000000000 R09: 0000000000000000
> kernel: R10: 0000000000020860 R11: ffff8804051b2e00 R12: 00000000000005a8
> kernel: R13: 00000000000005a8 R14: 0000000000003d21 R15: 0000000000000000
> kernel: FS: 00007f214fa8c710(0000) GS:ffff880001840000(0000)
> knlGS:0000000000000000
> kernel: CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
> kernel: CR2: 000000000b388000 CR3: 000000041c4c4000 CR4: 00000000000006e0
> kernel: DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
> kernel: DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400
> kernel: Process squid (pid: 18351, threadinfo ffff88041c28e000, task
> ffff88042e0fcec0)
> kernel: Stack:
> kernel: ffffffff81365dda ffff88038f098c00 ffffffff81365b8c ffff88038f098c00
> kernel: <0> ffffffff813a222a 00000000000000d0 ffffffff81366af9 000000002e0fcec0
> kernel: <0> ffff88042e0fcec0 ffff88042e0fcec0 ffff88042e0fcec0 0000000014d31cc0
> kernel: Call Trace:
> kernel: [<ffffffff81365dda>] ? skb_release_head_state+0x6d/0xb7
> kernel: [<ffffffff81365b8c>] ? __kfree_skb+0x9/0x7d
> kernel: [<ffffffff813a222a>] ? tcp_recvmsg+0x6a3/0x89a
> kernel: [<ffffffff81366af9>] ? __alloc_skb+0x5e/0x14e
> kernel: [<ffffffff81360ede>] ? sock_common_recvmsg+0x30/0x45
> kernel: [<ffffffff8135ec0f>] ? sock_aio_read+0xdd/0xf1
> kernel: [<ffffffff810ac500>] ? do_sync_read+0xb0/0xf2
> kernel: [<ffffffff8142a25e>] ? _raw_spin_lock_bh+0x9/0x1f
> kernel: [<ffffffff810acf32>] ? vfs_read+0xb9/0xff
> kernel: [<ffffffff810ad034>] ? sys_read+0x45/0x6e
> kernel: [<ffffffff8100292b>] ? system_call_fastpath+0x16/0x1b
> kernel: Code: ff ff ff ff c3 48 8b 57 18 8b 87 d8 00 00 00 48 8d 8a ac
> 00 00 00 f0 29 82 ac 00 00 00 48 8b 57 18 8b 8f d8 00 00 00 48 8b 42
> 38 <48> 83 b8 b0 00 00 00 00 74 06 01 8a f4 00 00 00 c3 41 57 41 89
> kernel: RIP [<ffffffff81360c2a>] sock_rfree+0x26/0x37
> kernel: RSP <ffff88041c28fc20>
> kernel: ---[ end trace bcd320fe508cc071 ]---
>
> Can anybody help me?
>
> What information can I provide you to track down this issue?
>
> Cheers,
>
> Felipe Damasio
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at http://www.tux.org/lkml/
^ permalink raw reply
* Re: Squid hang up on 2.6.34
From: Eric Dumazet @ 2010-07-08 22:08 UTC (permalink / raw)
To: Felipe W Damasio; +Cc: linux-kernel, netdev
In-Reply-To: <AANLkTil49m6Ul2bauiH4Pwn-6ykrYTFmSO6_SxqQgD_e@mail.gmail.com>
Le jeudi 08 juillet 2010 à 18:30 -0300, Felipe W Damasio a écrit :
> Hi again,
>
> Just FYI: After squid hung up, I started it again.
>
> A few minutes later, the machine frooze...after a reboot, syslog
> didn't show any messages.
>
> So the message below is the only tip of what happened.
>
> Cheers,
Please try to reproduce a new report.
It looks like a memory corruption, and it would be good to see if a
common pattern is occurring.
^ permalink raw reply
* Re: [PATCH] sysfs: Don't allow the creation of symlinks we can't remove
From: Eric W. Biederman @ 2010-07-08 22:28 UTC (permalink / raw)
To: Greg KH
Cc: Greg KH, Andrew Morton, Rafael J. Wysocki, Maciej W. Rozycki,
Kay Sievers, Johannes Berg, netdev
In-Reply-To: <20100708211930.GA15385@kroah.com>
Greg KH <greg@kroah.com> writes:
> With this patch, how does the existing code fail as the drivers aren't
> fixed up?
>
> I like this change, just worried it will cause problems if it gets into
> .35, without your RFC patch. Will it?
It don't expect this patch to be worse than where we are current at.
Network devices are renamed, and come and go enough that both the
mac80211_hwsim and the bnep driver are currently unusable with a
failure only the rename and remove.
This patch simply moves the failure into creation where we are a little more
prepared to deal with problems, and this patch is limited to mac80211_hwsim,
bnep, and any hypothetically undiscovered other network devices that
have the same problem.
mac80211_hwsim with just this patch becomes somewhat usable as it's primary
network device gets registered and the module can be loaded and unloaded. It
just doesn't create the wlan0 and wlan1 interfaces for the wifi interfaces.
On a slightly unrelated note, what got us on trying to convert
mac80211_hwsim was that everything happens in a single module which
makes avoiding cleanup races hard. I am hoping bnep is structured
enough differently so we can convert it to a bus device using the
existing infrastructure. I haven't figured out bnep yet though ;(
Eric
^ permalink raw reply
* [PATCH] netfilter: add CHECKSUM target
From: Michael S. Tsirkin @ 2010-07-08 22:29 UTC (permalink / raw)
To: Michael S. Tsirkin, Patrick McHardy, David S. Miller,
Alexey Kuznetsov, "Pekka Savola (ipv6)" <pek
This adds a `CHECKSUM' target, which can be used in the iptables mangle
table.
You can use this target to compute and fill in the checksum in
an IP packet that lacks a checksum. This is particularly useful,
if you need to work around old applications such as dhcp clients,
that do not work well with checksum offloads, but don't want to
disable checksum offload in your device.
The problem happens in the field with virtualized applications.
For reference, see Red Hat bz 605555, as well as
http://www.spinics.net/lists/kvm/msg37660.html
Typical expected use (helps old dhclient binary running in a VM):
iptables -A POSTROUTING -t mangle -p udp --dport 68 -j CHECKSUM
--checksum-fill
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---
Lightly tested. Please review for 2.6.36. Thanks!
include/linux/netfilter_ipv4/ipt_CHECKSUM.h | 18 +++++++
net/ipv4/netfilter/Kconfig | 16 ++++++
net/ipv4/netfilter/Makefile | 1 +
net/ipv4/netfilter/ipt_CHECKSUM.c | 72 +++++++++++++++++++++++++++
4 files changed, 107 insertions(+), 0 deletions(-)
create mode 100644 include/linux/netfilter_ipv4/ipt_CHECKSUM.h
create mode 100644 net/ipv4/netfilter/ipt_CHECKSUM.c
diff --git a/include/linux/netfilter_ipv4/ipt_CHECKSUM.h b/include/linux/netfilter_ipv4/ipt_CHECKSUM.h
new file mode 100644
index 0000000..0b0f660
--- /dev/null
+++ b/include/linux/netfilter_ipv4/ipt_CHECKSUM.h
@@ -0,0 +1,18 @@
+/* Header file for iptables ipt_CHECKSUM target
+ *
+ * (C) 2002 by Harald Welte <laforge@gnumonks.org>
+ * (C) 2010 Red Hat Inc
+ * Author: Michael S. Tsirkin <mst@redhat.com>
+ *
+ * This software is distributed under GNU GPL v2, 1991
+*/
+#ifndef _IPT_CHECKSUM_TARGET_H
+#define _IPT_CHECKSUM_TARGET_H
+
+#define IPT_CHECKSUM_OP_FILL 0x01 /* fill in checksum in IPv4 header */
+
+struct ipt_CHECKSUM_info {
+ u_int8_t operation; /* bitset of operations */
+};
+
+#endif /* _IPT_CHECKSUM_TARGET_H */
diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig
index 1833bdb..2fb979b 100644
--- a/net/ipv4/netfilter/Kconfig
+++ b/net/ipv4/netfilter/Kconfig
@@ -322,6 +322,22 @@ config IP_NF_TARGET_ECN
To compile it as a module, choose M here. If unsure, say N.
+config IP_NF_TARGET_CHECKSUM
+ tristate "CHECKSUM target support"
+ depends on IP_NF_MANGLE
+ depends on NETFILTER_ADVANCED
+ ---help---
+ This option adds a `CHECKSUM' target, which can be used in the iptables mangle
+ table.
+
+ You can use this target to compute and fill in the checksum in
+ an IP packet that lacks a checksum. This is particularly useful,
+ if you need to work around old applications such as dhcp clients,
+ that do not work well with checksum offloads, but don't want to disable
+ checksum offload in your device.
+
+ To compile it as a module, choose M here. If unsure, say N.
+
config IP_NF_TARGET_TTL
tristate '"TTL" target support'
depends on NETFILTER_ADVANCED
diff --git a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile
index 4811159..d7047bb 100644
--- a/net/ipv4/netfilter/Makefile
+++ b/net/ipv4/netfilter/Makefile
@@ -55,6 +55,7 @@ obj-$(CONFIG_IP_NF_MATCH_ECN) += ipt_ecn.o
# targets
obj-$(CONFIG_IP_NF_TARGET_CLUSTERIP) += ipt_CLUSTERIP.o
obj-$(CONFIG_IP_NF_TARGET_ECN) += ipt_ECN.o
+obj-$(CONFIG_IP_NF_TARGET_CHECKSUM) += ipt_CHECKSUM.o
obj-$(CONFIG_IP_NF_TARGET_LOG) += ipt_LOG.o
obj-$(CONFIG_IP_NF_TARGET_MASQUERADE) += ipt_MASQUERADE.o
obj-$(CONFIG_IP_NF_TARGET_NETMAP) += ipt_NETMAP.o
diff --git a/net/ipv4/netfilter/ipt_CHECKSUM.c b/net/ipv4/netfilter/ipt_CHECKSUM.c
new file mode 100644
index 0000000..b8346a1
--- /dev/null
+++ b/net/ipv4/netfilter/ipt_CHECKSUM.c
@@ -0,0 +1,72 @@
+/* iptables module for the IPv4 CHECKSUM
+ *
+ * (C) 2002 by Harald Welte <laforge@netfilter.org>
+ * (C) 2010 Red Hat, Inc.
+ *
+ * Author: Michael S. Tsirkin <mst@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#include <linux/in.h>
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter_ipv4/ipt_CHECKSUM.h>
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Michael S. Tsirkin <mst@redhat.com>");
+MODULE_DESCRIPTION("Xtables: checksum modification");
+
+static unsigned int
+checksum_tg(struct sk_buff *skb, const struct xt_action_param *par)
+{
+ if (skb->ip_summed == CHECKSUM_PARTIAL) {
+ skb_checksum_help(skb);
+ }
+
+ return XT_CONTINUE;
+}
+
+static int checksum_tg_check(const struct xt_tgchk_param *par)
+{
+ const struct ipt_CHECKSUM_info *einfo = par->targinfo;
+
+ if (einfo->operation & ~IPT_CHECKSUM_OP_FILL) {
+ pr_info("unsupported CHECKSUM operation %x\n", einfo->operation);
+ return -EINVAL;
+ }
+ if (!einfo->operation) {
+ pr_info("no CHECKSUM operation enabled\n");
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static struct xt_target checksum_tg_reg __read_mostly = {
+ .name = "CHECKSUM",
+ .family = NFPROTO_IPV4,
+ .target = checksum_tg,
+ .targetsize = sizeof(struct ipt_CHECKSUM_info),
+ .table = "mangle",
+ .checkentry = checksum_tg_check,
+ .me = THIS_MODULE,
+};
+
+static int __init checksum_tg_init(void)
+{
+ return xt_register_target(&checksum_tg_reg);
+}
+
+static void __exit checksum_tg_exit(void)
+{
+ xt_unregister_target(&checksum_tg_reg);
+}
+
+module_init(checksum_tg_init);
+module_exit(checksum_tg_exit);
--
1.7.2.rc0.14.g41c1c
^ permalink raw reply related
* [PATCH] extensions: libipt_CHECKSUM extension
From: Michael S. Tsirkin @ 2010-07-08 22:35 UTC (permalink / raw)
To: Patrick McHardy, David S. Miller, Alexey Kuznetsov,
Pekka Savola (ipv6), James Morris <jmorris@
In-Reply-To: <20100708222913.GA4475@redhat.com>
This adds a `CHECKSUM' target, which can be used in the iptables mangle
table.
You can use this target to compute and fill in the checksum in
an IP packet that lacks a checksum. This is particularly useful,
if you need to work around old applications such as dhcp clients,
that do not work well with checksum offloads, but don't want to disable
checksum offload in your device.
The problem happens in the field with virtualized applications.
For reference, see Red Hat bz 605555, as well as
http://www.spinics.net/lists/kvm/msg37660.html
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---
This patch adds userspace support for the CHECKSUM kernel module I sent previously.
extensions/libipt_CHECKSUM.c | 100 ++++++++++++++++++++++++++++++++++++++++
extensions/libipt_CHECKSUM.man | 8 +++
2 files changed, 108 insertions(+), 0 deletions(-)
create mode 100644 extensions/libipt_CHECKSUM.c
create mode 100644 extensions/libipt_CHECKSUM.man
diff --git a/extensions/libipt_CHECKSUM.c b/extensions/libipt_CHECKSUM.c
new file mode 100644
index 0000000..93d3e3f
--- /dev/null
+++ b/extensions/libipt_CHECKSUM.c
@@ -0,0 +1,100 @@
+/* Shared library add-on to iptables for CHECKSUM
+ *
+ * (C) 2002 by Harald Welte <laforge@gnumonks.org>
+ * (C) 2010 by Red Hat, Inc
+ * Author: Michael S. Tsirkin <mst@redhat.com>
+ *
+ * This program is distributed under the terms of GNU GPL v2, 1991
+ *
+ * libipt_CHECKSUM.c borrowed heavily from libipt_ECN.c
+ *
+ * $Id$
+ */
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <getopt.h>
+
+#include <xtables.h>
+#include <linux/netfilter_ipv4/ipt_CHECKSUM.h>
+
+static void CHECKSUM_help(void)
+{
+ printf(
+"CHECKSUM target options\n"
+" --checksum-fill Fill in packet checksum.\n");
+}
+
+static const struct option CHECKSUM_opts[] = {
+ { "checksum-fill", 0, NULL, 'F' },
+ { .name = NULL }
+};
+
+static int CHECKSUM_parse(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_target **target)
+{
+ unsigned int result;
+ struct ipt_CHECKSUM_info *einfo
+ = (struct ipt_CHECKSUM_info *)(*target)->data;
+
+ switch (c) {
+ case 'F':
+ if (*flags)
+ xtables_error(PARAMETER_PROBLEM,
+ "CHECKSUM target: Only use --checksum-fill ONCE!");
+ einfo->operation = IPT_CHECKSUM_OP_FILL;
+ *flags |= IPT_CHECKSUM_OP_FILL;
+ break;
+ default:
+ return 0;
+ }
+
+ return 1;
+}
+
+static void CHECKSUM_check(unsigned int flags)
+{
+ if (!flags)
+ xtables_error(PARAMETER_PROBLEM,
+ "CHECKSUM target: Parameter --checksum-fill is required");
+}
+
+static void CHECKSUM_print(const void *ip, const struct xt_entry_target *target,
+ int numeric)
+{
+ const struct ipt_CHECKSUM_info *einfo =
+ (const struct ipt_CHECKSUM_info *)target->data;
+
+ printf("CHECKSUM ");
+
+ if (einfo->operation & IPT_CHECKSUM_OP_FILL)
+ printf("fill ");
+}
+
+static void CHECKSUM_save(const void *ip, const struct xt_entry_target *target)
+{
+ const struct ipt_CHECKSUM_info *einfo =
+ (const struct ipt_CHECKSUM_info *)target->data;
+
+ if (einfo->operation & IPT_CHECKSUM_OP_FILL)
+ printf("--checksum-fill ");
+}
+
+static struct xtables_target checksum_tg_reg = {
+ .name = "CHECKSUM",
+ .version = XTABLES_VERSION,
+ .family = NFPROTO_IPV4,
+ .size = XT_ALIGN(sizeof(struct ipt_CHECKSUM_info)),
+ .userspacesize = XT_ALIGN(sizeof(struct ipt_CHECKSUM_info)),
+ .help = CHECKSUM_help,
+ .parse = CHECKSUM_parse,
+ .final_check = CHECKSUM_check,
+ .print = CHECKSUM_print,
+ .save = CHECKSUM_save,
+ .extra_opts = CHECKSUM_opts,
+};
+
+void _init(void)
+{
+ xtables_register_target(&checksum_tg_reg);
+}
diff --git a/extensions/libipt_CHECKSUM.man b/extensions/libipt_CHECKSUM.man
new file mode 100644
index 0000000..4f83335
--- /dev/null
+++ b/extensions/libipt_CHECKSUM.man
@@ -0,0 +1,8 @@
+This target allows to selectively work around broken/old applications.
+It can only be used in the mangle table.
+.TP
+\fB\-\-checksum\-fill\fP
+Compute and fill in the checksum in an IP packet that lacks a checksum.
+This is particularly useful, if you need to work around old applications
+such as dhcp clients, that do not work well with checksum offloads,
+but don't want to disable checksum offload in your device.
--
1.7.2.rc0.14.g41c1c
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox