In TCP packet is sent, and we get RST from the remote. Emulate this in SDP.
extern struct workqueue_struct *sdp_workqueue;
int sdp_cma_handler(struct rdma_cm_id *, struct rdma_cm_event *);
+void sdp_reset(struct sock *sk);
void sdp_reset_sk(struct sock *sk, int rc);
void sdp_time_wait_destroy_sk(struct sdp_sock *ssk);
void sdp_completion_handler(struct ib_cq *cq, void *cq_context);
struct sk_buff *skb;
int c;
- if (unlikely(!ssk->id))
+ if (unlikely(!ssk->id)) {
+ if (ssk->isk.sk.sk_send_head) {
+ sdp_dbg(&ssk->isk.sk,
+ "Send on socket without cmid ECONNRESET.\n");
+ /* TODO: flush send queue? */
+ sdp_reset(&ssk->isk.sk);
+ }
return;
+ }
while (ssk->bufs > SDP_MIN_BUFS &&
ssk->tx_head - ssk->tx_tail < SDP_TX_SIZE &&
sdp_dbg(&ssk->isk.sk,
"Recv completion with error. "
"Status %d\n", wc->status);
- sdp_set_error(&ssk->isk.sk, -ECONNRESET);
- wake_up(&ssk->wq);
+ sdp_reset(&ssk->isk.sk);
}
__kfree_skb(skb);
} else {
sdp_dbg(sk, "%s: destroy in time wait state\n", __func__);
sdp_time_wait_destroy_sk(ssk);
}
+
+ sk->sk_state_change(sk);
+}
+
+/* Like tcp_reset */
+/* When we get a reset (completion with error) we do this. */
+void sdp_reset(struct sock *sk)
+{
+ int err;
+
+ if (sk->sk_state != TCP_ESTABLISHED)
+ return;
+
+ /* We want the right error as BSD sees it (and indeed as we do). */
+
+ /* On fin we currently only set RCV_SHUTDOWN, so .. */
+ err = (sk->sk_shutdown & RCV_SHUTDOWN) ? EPIPE : ECONNRESET;
+
+ sdp_set_error(sk, -err);
+ wake_up(&sdp_sk(sk)->wq);
+ sk->sk_state_change(sk);
}
/* TODO: linger? */