mirror of https://gitee.com/openkylin/linux.git
RDMA/nes: Handle MPA Reject message properly
While doing testing, there are failures as MPA Reject call is not handled. To handle MPA Reject call, following changes are done: *Handle inbound/outbound MPA Reject response message. When nes_reject() is called for pending MPA request reply, send the MPA Reject message to its peer (active side)cm_node. The peer cm_node (active side) will indicate Reject message event for the pending Connect Request. *Handle MPA Reject response message for loopback connections and listener. When MPA Request is rejected, check if it is a loopback connection and if it is then it will send Reject message event to its peer loopback node. Also when destroying listener, check if the cm_nodes for that listener are loopback or not. *Add gracefull connection close with the MPA Reject response message. Send gracefull close (FIN, FIN ACK..) to terminate the cm_nodes. *Some code re-org while making the above changes. Removed recv_list and recv_list_lock from the cm_node structure as there can be only one receive close entry on the timer. Also implemented handle_recv_entry() as receive close entry is processed from both nes_rem_ref_cm_node() as well as nes_cm_timer_tick(). Signed-off-by: Faisal Latif <faisal.latif@intel.com> Signed-off-by: Roland Dreier <rolandd@cisco.com>
This commit is contained in:
parent
0145f341a9
commit
9d5ab13325
|
@ -103,6 +103,7 @@ static int nes_disconnect(struct nes_qp *nesqp, int abrupt);
|
||||||
static void nes_disconnect_worker(struct work_struct *work);
|
static void nes_disconnect_worker(struct work_struct *work);
|
||||||
|
|
||||||
static int send_mpa_request(struct nes_cm_node *, struct sk_buff *);
|
static int send_mpa_request(struct nes_cm_node *, struct sk_buff *);
|
||||||
|
static int send_mpa_reject(struct nes_cm_node *);
|
||||||
static int send_syn(struct nes_cm_node *, u32, struct sk_buff *);
|
static int send_syn(struct nes_cm_node *, u32, struct sk_buff *);
|
||||||
static int send_reset(struct nes_cm_node *, struct sk_buff *);
|
static int send_reset(struct nes_cm_node *, struct sk_buff *);
|
||||||
static int send_ack(struct nes_cm_node *cm_node, struct sk_buff *skb);
|
static int send_ack(struct nes_cm_node *cm_node, struct sk_buff *skb);
|
||||||
|
@ -113,8 +114,7 @@ static void process_packet(struct nes_cm_node *, struct sk_buff *,
|
||||||
static void active_open_err(struct nes_cm_node *, struct sk_buff *, int);
|
static void active_open_err(struct nes_cm_node *, struct sk_buff *, int);
|
||||||
static void passive_open_err(struct nes_cm_node *, struct sk_buff *, int);
|
static void passive_open_err(struct nes_cm_node *, struct sk_buff *, int);
|
||||||
static void cleanup_retrans_entry(struct nes_cm_node *);
|
static void cleanup_retrans_entry(struct nes_cm_node *);
|
||||||
static void handle_rcv_mpa(struct nes_cm_node *, struct sk_buff *,
|
static void handle_rcv_mpa(struct nes_cm_node *, struct sk_buff *);
|
||||||
enum nes_cm_event_type);
|
|
||||||
static void free_retrans_entry(struct nes_cm_node *cm_node);
|
static void free_retrans_entry(struct nes_cm_node *cm_node);
|
||||||
static int handle_tcp_options(struct nes_cm_node *cm_node, struct tcphdr *tcph,
|
static int handle_tcp_options(struct nes_cm_node *cm_node, struct tcphdr *tcph,
|
||||||
struct sk_buff *skb, int optionsize, int passive);
|
struct sk_buff *skb, int optionsize, int passive);
|
||||||
|
@ -124,6 +124,8 @@ static void cm_event_connected(struct nes_cm_event *);
|
||||||
static void cm_event_connect_error(struct nes_cm_event *);
|
static void cm_event_connect_error(struct nes_cm_event *);
|
||||||
static void cm_event_reset(struct nes_cm_event *);
|
static void cm_event_reset(struct nes_cm_event *);
|
||||||
static void cm_event_mpa_req(struct nes_cm_event *);
|
static void cm_event_mpa_req(struct nes_cm_event *);
|
||||||
|
static void cm_event_mpa_reject(struct nes_cm_event *);
|
||||||
|
static void handle_recv_entry(struct nes_cm_node *cm_node, u32 rem_node);
|
||||||
|
|
||||||
static void print_core(struct nes_cm_core *core);
|
static void print_core(struct nes_cm_core *core);
|
||||||
|
|
||||||
|
@ -196,7 +198,6 @@ static struct nes_cm_event *create_event(struct nes_cm_node *cm_node,
|
||||||
*/
|
*/
|
||||||
static int send_mpa_request(struct nes_cm_node *cm_node, struct sk_buff *skb)
|
static int send_mpa_request(struct nes_cm_node *cm_node, struct sk_buff *skb)
|
||||||
{
|
{
|
||||||
int ret;
|
|
||||||
if (!skb) {
|
if (!skb) {
|
||||||
nes_debug(NES_DBG_CM, "skb set to NULL\n");
|
nes_debug(NES_DBG_CM, "skb set to NULL\n");
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -206,11 +207,27 @@ static int send_mpa_request(struct nes_cm_node *cm_node, struct sk_buff *skb)
|
||||||
form_cm_frame(skb, cm_node, NULL, 0, &cm_node->mpa_frame,
|
form_cm_frame(skb, cm_node, NULL, 0, &cm_node->mpa_frame,
|
||||||
cm_node->mpa_frame_size, SET_ACK);
|
cm_node->mpa_frame_size, SET_ACK);
|
||||||
|
|
||||||
ret = schedule_nes_timer(cm_node, skb, NES_TIMER_TYPE_SEND, 1, 0);
|
return schedule_nes_timer(cm_node, skb, NES_TIMER_TYPE_SEND, 1, 0);
|
||||||
if (ret < 0)
|
}
|
||||||
return ret;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
|
static int send_mpa_reject(struct nes_cm_node *cm_node)
|
||||||
|
{
|
||||||
|
struct sk_buff *skb = NULL;
|
||||||
|
|
||||||
|
skb = dev_alloc_skb(MAX_CM_BUFFER);
|
||||||
|
if (!skb) {
|
||||||
|
nes_debug(NES_DBG_CM, "Failed to get a Free pkt\n");
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* send an MPA reject frame */
|
||||||
|
form_cm_frame(skb, cm_node, NULL, 0, &cm_node->mpa_frame,
|
||||||
|
cm_node->mpa_frame_size, SET_ACK | SET_FIN);
|
||||||
|
|
||||||
|
cm_node->state = NES_CM_STATE_FIN_WAIT1;
|
||||||
|
return schedule_nes_timer(cm_node, skb, NES_TIMER_TYPE_SEND, 1, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -218,14 +235,17 @@ static int send_mpa_request(struct nes_cm_node *cm_node, struct sk_buff *skb)
|
||||||
* recv_mpa - process a received TCP pkt, we are expecting an
|
* recv_mpa - process a received TCP pkt, we are expecting an
|
||||||
* IETF MPA frame
|
* IETF MPA frame
|
||||||
*/
|
*/
|
||||||
static int parse_mpa(struct nes_cm_node *cm_node, u8 *buffer, u32 len)
|
static int parse_mpa(struct nes_cm_node *cm_node, u8 *buffer, u32 *type,
|
||||||
|
u32 len)
|
||||||
{
|
{
|
||||||
struct ietf_mpa_frame *mpa_frame;
|
struct ietf_mpa_frame *mpa_frame;
|
||||||
|
|
||||||
|
*type = NES_MPA_REQUEST_ACCEPT;
|
||||||
|
|
||||||
/* assume req frame is in tcp data payload */
|
/* assume req frame is in tcp data payload */
|
||||||
if (len < sizeof(struct ietf_mpa_frame)) {
|
if (len < sizeof(struct ietf_mpa_frame)) {
|
||||||
nes_debug(NES_DBG_CM, "The received ietf buffer was too small (%x)\n", len);
|
nes_debug(NES_DBG_CM, "The received ietf buffer was too small (%x)\n", len);
|
||||||
return -1;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
mpa_frame = (struct ietf_mpa_frame *)buffer;
|
mpa_frame = (struct ietf_mpa_frame *)buffer;
|
||||||
|
@ -234,14 +254,25 @@ static int parse_mpa(struct nes_cm_node *cm_node, u8 *buffer, u32 len)
|
||||||
if (cm_node->mpa_frame_size + sizeof(struct ietf_mpa_frame) != len) {
|
if (cm_node->mpa_frame_size + sizeof(struct ietf_mpa_frame) != len) {
|
||||||
nes_debug(NES_DBG_CM, "The received ietf buffer was not right"
|
nes_debug(NES_DBG_CM, "The received ietf buffer was not right"
|
||||||
" complete (%x + %x != %x)\n",
|
" complete (%x + %x != %x)\n",
|
||||||
cm_node->mpa_frame_size, (u32)sizeof(struct ietf_mpa_frame), len);
|
cm_node->mpa_frame_size,
|
||||||
return -1;
|
(u32)sizeof(struct ietf_mpa_frame), len);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
/* make sure it does not exceed the max size */
|
||||||
|
if (len > MAX_CM_BUFFER) {
|
||||||
|
nes_debug(NES_DBG_CM, "The received ietf buffer was too large"
|
||||||
|
" (%x + %x != %x)\n",
|
||||||
|
cm_node->mpa_frame_size,
|
||||||
|
(u32)sizeof(struct ietf_mpa_frame), len);
|
||||||
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* copy entire MPA frame to our cm_node's frame */
|
/* copy entire MPA frame to our cm_node's frame */
|
||||||
memcpy(cm_node->mpa_frame_buf, buffer + sizeof(struct ietf_mpa_frame),
|
memcpy(cm_node->mpa_frame_buf, buffer + sizeof(struct ietf_mpa_frame),
|
||||||
cm_node->mpa_frame_size);
|
cm_node->mpa_frame_size);
|
||||||
|
|
||||||
|
if (mpa_frame->flags & IETF_MPA_FLAGS_REJECT)
|
||||||
|
*type = NES_MPA_REQUEST_REJECT;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -380,7 +411,7 @@ int schedule_nes_timer(struct nes_cm_node *cm_node, struct sk_buff *skb,
|
||||||
|
|
||||||
new_send = kzalloc(sizeof(*new_send), GFP_ATOMIC);
|
new_send = kzalloc(sizeof(*new_send), GFP_ATOMIC);
|
||||||
if (!new_send)
|
if (!new_send)
|
||||||
return -1;
|
return -ENOMEM;
|
||||||
|
|
||||||
/* new_send->timetosend = currenttime */
|
/* new_send->timetosend = currenttime */
|
||||||
new_send->retrycount = NES_DEFAULT_RETRYS;
|
new_send->retrycount = NES_DEFAULT_RETRYS;
|
||||||
|
@ -394,9 +425,11 @@ int schedule_nes_timer(struct nes_cm_node *cm_node, struct sk_buff *skb,
|
||||||
|
|
||||||
if (type == NES_TIMER_TYPE_CLOSE) {
|
if (type == NES_TIMER_TYPE_CLOSE) {
|
||||||
new_send->timetosend += (HZ/10);
|
new_send->timetosend += (HZ/10);
|
||||||
spin_lock_irqsave(&cm_node->recv_list_lock, flags);
|
if (cm_node->recv_entry) {
|
||||||
list_add_tail(&new_send->list, &cm_node->recv_list);
|
WARN_ON(1);
|
||||||
spin_unlock_irqrestore(&cm_node->recv_list_lock, flags);
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
cm_node->recv_entry = new_send;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type == NES_TIMER_TYPE_SEND) {
|
if (type == NES_TIMER_TYPE_SEND) {
|
||||||
|
@ -435,24 +468,78 @@ int schedule_nes_timer(struct nes_cm_node *cm_node, struct sk_buff *skb,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void nes_retrans_expired(struct nes_cm_node *cm_node)
|
||||||
|
{
|
||||||
|
switch (cm_node->state) {
|
||||||
|
case NES_CM_STATE_SYN_RCVD:
|
||||||
|
case NES_CM_STATE_CLOSING:
|
||||||
|
rem_ref_cm_node(cm_node->cm_core, cm_node);
|
||||||
|
break;
|
||||||
|
case NES_CM_STATE_LAST_ACK:
|
||||||
|
case NES_CM_STATE_FIN_WAIT1:
|
||||||
|
case NES_CM_STATE_MPAREJ_RCVD:
|
||||||
|
send_reset(cm_node, NULL);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
create_event(cm_node, NES_CM_EVENT_ABORTED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void handle_recv_entry(struct nes_cm_node *cm_node, u32 rem_node)
|
||||||
|
{
|
||||||
|
struct nes_timer_entry *recv_entry = cm_node->recv_entry;
|
||||||
|
struct iw_cm_id *cm_id = cm_node->cm_id;
|
||||||
|
struct nes_qp *nesqp;
|
||||||
|
unsigned long qplockflags;
|
||||||
|
|
||||||
|
if (!recv_entry)
|
||||||
|
return;
|
||||||
|
nesqp = (struct nes_qp *)recv_entry->skb;
|
||||||
|
if (nesqp) {
|
||||||
|
spin_lock_irqsave(&nesqp->lock, qplockflags);
|
||||||
|
if (nesqp->cm_id) {
|
||||||
|
nes_debug(NES_DBG_CM, "QP%u: cm_id = %p, "
|
||||||
|
"refcount = %d: HIT A "
|
||||||
|
"NES_TIMER_TYPE_CLOSE with something "
|
||||||
|
"to do!!!\n", nesqp->hwqp.qp_id, cm_id,
|
||||||
|
atomic_read(&nesqp->refcount));
|
||||||
|
nesqp->hw_tcp_state = NES_AEQE_TCP_STATE_CLOSED;
|
||||||
|
nesqp->last_aeq = NES_AEQE_AEID_RESET_SENT;
|
||||||
|
nesqp->ibqp_state = IB_QPS_ERR;
|
||||||
|
spin_unlock_irqrestore(&nesqp->lock, qplockflags);
|
||||||
|
nes_cm_disconn(nesqp);
|
||||||
|
} else {
|
||||||
|
spin_unlock_irqrestore(&nesqp->lock, qplockflags);
|
||||||
|
nes_debug(NES_DBG_CM, "QP%u: cm_id = %p, "
|
||||||
|
"refcount = %d: HIT A "
|
||||||
|
"NES_TIMER_TYPE_CLOSE with nothing "
|
||||||
|
"to do!!!\n", nesqp->hwqp.qp_id, cm_id,
|
||||||
|
atomic_read(&nesqp->refcount));
|
||||||
|
}
|
||||||
|
} else if (rem_node) {
|
||||||
|
/* TIME_WAIT state */
|
||||||
|
rem_ref_cm_node(cm_node->cm_core, cm_node);
|
||||||
|
}
|
||||||
|
if (cm_node->cm_id)
|
||||||
|
cm_id->rem_ref(cm_id);
|
||||||
|
kfree(recv_entry);
|
||||||
|
cm_node->recv_entry = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* nes_cm_timer_tick
|
* nes_cm_timer_tick
|
||||||
*/
|
*/
|
||||||
static void nes_cm_timer_tick(unsigned long pass)
|
static void nes_cm_timer_tick(unsigned long pass)
|
||||||
{
|
{
|
||||||
unsigned long flags, qplockflags;
|
unsigned long flags;
|
||||||
unsigned long nexttimeout = jiffies + NES_LONG_TIME;
|
unsigned long nexttimeout = jiffies + NES_LONG_TIME;
|
||||||
struct iw_cm_id *cm_id;
|
|
||||||
struct nes_cm_node *cm_node;
|
struct nes_cm_node *cm_node;
|
||||||
struct nes_timer_entry *send_entry, *recv_entry;
|
struct nes_timer_entry *send_entry, *recv_entry;
|
||||||
struct list_head *list_core, *list_core_temp;
|
struct list_head *list_core_temp;
|
||||||
struct list_head *list_node, *list_node_temp;
|
struct list_head *list_node;
|
||||||
struct nes_cm_core *cm_core = g_cm_core;
|
struct nes_cm_core *cm_core = g_cm_core;
|
||||||
struct nes_qp *nesqp;
|
|
||||||
u32 settimer = 0;
|
u32 settimer = 0;
|
||||||
int ret = NETDEV_TX_OK;
|
int ret = NETDEV_TX_OK;
|
||||||
enum nes_cm_node_state last_state;
|
|
||||||
|
|
||||||
struct list_head timer_list;
|
struct list_head timer_list;
|
||||||
INIT_LIST_HEAD(&timer_list);
|
INIT_LIST_HEAD(&timer_list);
|
||||||
|
@ -461,7 +548,7 @@ static void nes_cm_timer_tick(unsigned long pass)
|
||||||
list_for_each_safe(list_node, list_core_temp,
|
list_for_each_safe(list_node, list_core_temp,
|
||||||
&cm_core->connected_nodes) {
|
&cm_core->connected_nodes) {
|
||||||
cm_node = container_of(list_node, struct nes_cm_node, list);
|
cm_node = container_of(list_node, struct nes_cm_node, list);
|
||||||
if (!list_empty(&cm_node->recv_list) || (cm_node->send_entry)) {
|
if ((cm_node->recv_entry) || (cm_node->send_entry)) {
|
||||||
add_ref_cm_node(cm_node);
|
add_ref_cm_node(cm_node);
|
||||||
list_add(&cm_node->timer_entry, &timer_list);
|
list_add(&cm_node->timer_entry, &timer_list);
|
||||||
}
|
}
|
||||||
|
@ -471,54 +558,18 @@ static void nes_cm_timer_tick(unsigned long pass)
|
||||||
list_for_each_safe(list_node, list_core_temp, &timer_list) {
|
list_for_each_safe(list_node, list_core_temp, &timer_list) {
|
||||||
cm_node = container_of(list_node, struct nes_cm_node,
|
cm_node = container_of(list_node, struct nes_cm_node,
|
||||||
timer_entry);
|
timer_entry);
|
||||||
spin_lock_irqsave(&cm_node->recv_list_lock, flags);
|
recv_entry = cm_node->recv_entry;
|
||||||
list_for_each_safe(list_core, list_node_temp,
|
|
||||||
&cm_node->recv_list) {
|
if (recv_entry) {
|
||||||
recv_entry = container_of(list_core,
|
|
||||||
struct nes_timer_entry, list);
|
|
||||||
if (!recv_entry)
|
|
||||||
break;
|
|
||||||
if (time_after(recv_entry->timetosend, jiffies)) {
|
if (time_after(recv_entry->timetosend, jiffies)) {
|
||||||
if (nexttimeout > recv_entry->timetosend ||
|
if (nexttimeout > recv_entry->timetosend ||
|
||||||
!settimer) {
|
!settimer) {
|
||||||
nexttimeout = recv_entry->timetosend;
|
nexttimeout = recv_entry->timetosend;
|
||||||
settimer = 1;
|
settimer = 1;
|
||||||
}
|
}
|
||||||
continue;
|
} else
|
||||||
}
|
handle_recv_entry(cm_node, 1);
|
||||||
list_del(&recv_entry->list);
|
|
||||||
cm_id = cm_node->cm_id;
|
|
||||||
spin_unlock_irqrestore(&cm_node->recv_list_lock, flags);
|
|
||||||
nesqp = (struct nes_qp *)recv_entry->skb;
|
|
||||||
spin_lock_irqsave(&nesqp->lock, qplockflags);
|
|
||||||
if (nesqp->cm_id) {
|
|
||||||
nes_debug(NES_DBG_CM, "QP%u: cm_id = %p, "
|
|
||||||
"refcount = %d: HIT A "
|
|
||||||
"NES_TIMER_TYPE_CLOSE with something "
|
|
||||||
"to do!!!\n", nesqp->hwqp.qp_id, cm_id,
|
|
||||||
atomic_read(&nesqp->refcount));
|
|
||||||
nesqp->hw_tcp_state = NES_AEQE_TCP_STATE_CLOSED;
|
|
||||||
nesqp->last_aeq = NES_AEQE_AEID_RESET_SENT;
|
|
||||||
nesqp->ibqp_state = IB_QPS_ERR;
|
|
||||||
spin_unlock_irqrestore(&nesqp->lock,
|
|
||||||
qplockflags);
|
|
||||||
nes_cm_disconn(nesqp);
|
|
||||||
} else {
|
|
||||||
spin_unlock_irqrestore(&nesqp->lock,
|
|
||||||
qplockflags);
|
|
||||||
nes_debug(NES_DBG_CM, "QP%u: cm_id = %p, "
|
|
||||||
"refcount = %d: HIT A "
|
|
||||||
"NES_TIMER_TYPE_CLOSE with nothing "
|
|
||||||
"to do!!!\n", nesqp->hwqp.qp_id, cm_id,
|
|
||||||
atomic_read(&nesqp->refcount));
|
|
||||||
}
|
|
||||||
if (cm_id)
|
|
||||||
cm_id->rem_ref(cm_id);
|
|
||||||
|
|
||||||
kfree(recv_entry);
|
|
||||||
spin_lock_irqsave(&cm_node->recv_list_lock, flags);
|
|
||||||
}
|
}
|
||||||
spin_unlock_irqrestore(&cm_node->recv_list_lock, flags);
|
|
||||||
|
|
||||||
spin_lock_irqsave(&cm_node->retrans_list_lock, flags);
|
spin_lock_irqsave(&cm_node->retrans_list_lock, flags);
|
||||||
do {
|
do {
|
||||||
|
@ -533,12 +584,11 @@ static void nes_cm_timer_tick(unsigned long pass)
|
||||||
nexttimeout =
|
nexttimeout =
|
||||||
send_entry->timetosend;
|
send_entry->timetosend;
|
||||||
settimer = 1;
|
settimer = 1;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
free_retrans_entry(cm_node);
|
free_retrans_entry(cm_node);
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((cm_node->state == NES_CM_STATE_TSA) ||
|
if ((cm_node->state == NES_CM_STATE_TSA) ||
|
||||||
|
@ -550,16 +600,12 @@ static void nes_cm_timer_tick(unsigned long pass)
|
||||||
if (!send_entry->retranscount ||
|
if (!send_entry->retranscount ||
|
||||||
!send_entry->retrycount) {
|
!send_entry->retrycount) {
|
||||||
cm_packets_dropped++;
|
cm_packets_dropped++;
|
||||||
last_state = cm_node->state;
|
|
||||||
cm_node->state = NES_CM_STATE_CLOSED;
|
|
||||||
free_retrans_entry(cm_node);
|
free_retrans_entry(cm_node);
|
||||||
|
|
||||||
spin_unlock_irqrestore(
|
spin_unlock_irqrestore(
|
||||||
&cm_node->retrans_list_lock, flags);
|
&cm_node->retrans_list_lock, flags);
|
||||||
if (last_state == NES_CM_STATE_SYN_RCVD)
|
nes_retrans_expired(cm_node);
|
||||||
rem_ref_cm_node(cm_core, cm_node);
|
cm_node->state = NES_CM_STATE_CLOSED;
|
||||||
else
|
|
||||||
create_event(cm_node,
|
|
||||||
NES_CM_EVENT_ABORTED);
|
|
||||||
spin_lock_irqsave(&cm_node->retrans_list_lock,
|
spin_lock_irqsave(&cm_node->retrans_list_lock,
|
||||||
flags);
|
flags);
|
||||||
break;
|
break;
|
||||||
|
@ -714,7 +760,7 @@ static int send_reset(struct nes_cm_node *cm_node, struct sk_buff *skb)
|
||||||
skb = dev_alloc_skb(MAX_CM_BUFFER);
|
skb = dev_alloc_skb(MAX_CM_BUFFER);
|
||||||
if (!skb) {
|
if (!skb) {
|
||||||
nes_debug(NES_DBG_CM, "Failed to get a Free pkt\n");
|
nes_debug(NES_DBG_CM, "Failed to get a Free pkt\n");
|
||||||
return -1;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
form_cm_frame(skb, cm_node, NULL, 0, NULL, 0, flags);
|
form_cm_frame(skb, cm_node, NULL, 0, NULL, 0, flags);
|
||||||
|
@ -871,7 +917,8 @@ static int add_hte_node(struct nes_cm_core *cm_core, struct nes_cm_node *cm_node
|
||||||
static int mini_cm_dec_refcnt_listen(struct nes_cm_core *cm_core,
|
static int mini_cm_dec_refcnt_listen(struct nes_cm_core *cm_core,
|
||||||
struct nes_cm_listener *listener, int free_hanging_nodes)
|
struct nes_cm_listener *listener, int free_hanging_nodes)
|
||||||
{
|
{
|
||||||
int ret = 1;
|
int ret = -EINVAL;
|
||||||
|
int err = 0;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
struct list_head *list_pos = NULL;
|
struct list_head *list_pos = NULL;
|
||||||
struct list_head *list_temp = NULL;
|
struct list_head *list_temp = NULL;
|
||||||
|
@ -900,10 +947,60 @@ static int mini_cm_dec_refcnt_listen(struct nes_cm_core *cm_core,
|
||||||
|
|
||||||
list_for_each_safe(list_pos, list_temp, &reset_list) {
|
list_for_each_safe(list_pos, list_temp, &reset_list) {
|
||||||
cm_node = container_of(list_pos, struct nes_cm_node,
|
cm_node = container_of(list_pos, struct nes_cm_node,
|
||||||
reset_entry);
|
reset_entry);
|
||||||
cleanup_retrans_entry(cm_node);
|
{
|
||||||
send_reset(cm_node, NULL);
|
struct nes_cm_node *loopback = cm_node->loopbackpartner;
|
||||||
rem_ref_cm_node(cm_node->cm_core, cm_node);
|
if (NES_CM_STATE_FIN_WAIT1 <= cm_node->state) {
|
||||||
|
rem_ref_cm_node(cm_node->cm_core, cm_node);
|
||||||
|
} else {
|
||||||
|
if (!loopback) {
|
||||||
|
cleanup_retrans_entry(cm_node);
|
||||||
|
err = send_reset(cm_node, NULL);
|
||||||
|
if (err) {
|
||||||
|
cm_node->state =
|
||||||
|
NES_CM_STATE_CLOSED;
|
||||||
|
WARN_ON(1);
|
||||||
|
} else {
|
||||||
|
cm_node->state =
|
||||||
|
NES_CM_STATE_CLOSED;
|
||||||
|
rem_ref_cm_node(
|
||||||
|
cm_node->cm_core,
|
||||||
|
cm_node);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
struct nes_cm_event event;
|
||||||
|
|
||||||
|
event.cm_node = loopback;
|
||||||
|
event.cm_info.rem_addr =
|
||||||
|
loopback->rem_addr;
|
||||||
|
event.cm_info.loc_addr =
|
||||||
|
loopback->loc_addr;
|
||||||
|
event.cm_info.rem_port =
|
||||||
|
loopback->rem_port;
|
||||||
|
event.cm_info.loc_port =
|
||||||
|
loopback->loc_port;
|
||||||
|
event.cm_info.cm_id = loopback->cm_id;
|
||||||
|
cm_event_connect_error(&event);
|
||||||
|
loopback->state = NES_CM_STATE_CLOSED;
|
||||||
|
|
||||||
|
event.cm_node = cm_node;
|
||||||
|
event.cm_info.rem_addr =
|
||||||
|
cm_node->rem_addr;
|
||||||
|
event.cm_info.loc_addr =
|
||||||
|
cm_node->loc_addr;
|
||||||
|
event.cm_info.rem_port =
|
||||||
|
cm_node->rem_port;
|
||||||
|
event.cm_info.loc_port =
|
||||||
|
cm_node->loc_port;
|
||||||
|
event.cm_info.cm_id = cm_node->cm_id;
|
||||||
|
cm_event_reset(&event);
|
||||||
|
|
||||||
|
rem_ref_cm_node(cm_node->cm_core,
|
||||||
|
cm_node);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
spin_lock_irqsave(&cm_core->listen_list_lock, flags);
|
spin_lock_irqsave(&cm_core->listen_list_lock, flags);
|
||||||
|
@ -964,6 +1061,7 @@ static inline int mini_cm_accelerated(struct nes_cm_core *cm_core,
|
||||||
if (cm_node->accept_pend) {
|
if (cm_node->accept_pend) {
|
||||||
BUG_ON(!cm_node->listener);
|
BUG_ON(!cm_node->listener);
|
||||||
atomic_dec(&cm_node->listener->pend_accepts_cnt);
|
atomic_dec(&cm_node->listener->pend_accepts_cnt);
|
||||||
|
cm_node->accept_pend = 0;
|
||||||
BUG_ON(atomic_read(&cm_node->listener->pend_accepts_cnt) < 0);
|
BUG_ON(atomic_read(&cm_node->listener->pend_accepts_cnt) < 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -990,7 +1088,7 @@ static int nes_addr_resolve_neigh(struct nes_vnic *nesvnic, u32 dst_ip)
|
||||||
memset(&fl, 0, sizeof fl);
|
memset(&fl, 0, sizeof fl);
|
||||||
fl.nl_u.ip4_u.daddr = htonl(dst_ip);
|
fl.nl_u.ip4_u.daddr = htonl(dst_ip);
|
||||||
if (ip_route_output_key(&init_net, &rt, &fl)) {
|
if (ip_route_output_key(&init_net, &rt, &fl)) {
|
||||||
printk("%s: ip_route_output_key failed for 0x%08X\n",
|
printk(KERN_ERR "%s: ip_route_output_key failed for 0x%08X\n",
|
||||||
__func__, dst_ip);
|
__func__, dst_ip);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
@ -1053,8 +1151,6 @@ static struct nes_cm_node *make_cm_node(struct nes_cm_core *cm_core,
|
||||||
cm_node->cm_id);
|
cm_node->cm_id);
|
||||||
|
|
||||||
spin_lock_init(&cm_node->retrans_list_lock);
|
spin_lock_init(&cm_node->retrans_list_lock);
|
||||||
INIT_LIST_HEAD(&cm_node->recv_list);
|
|
||||||
spin_lock_init(&cm_node->recv_list_lock);
|
|
||||||
|
|
||||||
cm_node->loopbackpartner = NULL;
|
cm_node->loopbackpartner = NULL;
|
||||||
atomic_set(&cm_node->ref_count, 1);
|
atomic_set(&cm_node->ref_count, 1);
|
||||||
|
@ -1122,10 +1218,7 @@ static int add_ref_cm_node(struct nes_cm_node *cm_node)
|
||||||
static int rem_ref_cm_node(struct nes_cm_core *cm_core,
|
static int rem_ref_cm_node(struct nes_cm_core *cm_core,
|
||||||
struct nes_cm_node *cm_node)
|
struct nes_cm_node *cm_node)
|
||||||
{
|
{
|
||||||
unsigned long flags, qplockflags;
|
unsigned long flags;
|
||||||
struct nes_timer_entry *recv_entry;
|
|
||||||
struct iw_cm_id *cm_id;
|
|
||||||
struct list_head *list_core, *list_node_temp;
|
|
||||||
struct nes_qp *nesqp;
|
struct nes_qp *nesqp;
|
||||||
|
|
||||||
if (!cm_node)
|
if (!cm_node)
|
||||||
|
@ -1146,38 +1239,9 @@ static int rem_ref_cm_node(struct nes_cm_core *cm_core,
|
||||||
atomic_dec(&cm_node->listener->pend_accepts_cnt);
|
atomic_dec(&cm_node->listener->pend_accepts_cnt);
|
||||||
BUG_ON(atomic_read(&cm_node->listener->pend_accepts_cnt) < 0);
|
BUG_ON(atomic_read(&cm_node->listener->pend_accepts_cnt) < 0);
|
||||||
}
|
}
|
||||||
BUG_ON(cm_node->send_entry);
|
WARN_ON(cm_node->send_entry);
|
||||||
spin_lock_irqsave(&cm_node->recv_list_lock, flags);
|
if (cm_node->recv_entry)
|
||||||
list_for_each_safe(list_core, list_node_temp, &cm_node->recv_list) {
|
handle_recv_entry(cm_node, 0);
|
||||||
recv_entry = container_of(list_core, struct nes_timer_entry,
|
|
||||||
list);
|
|
||||||
list_del(&recv_entry->list);
|
|
||||||
cm_id = cm_node->cm_id;
|
|
||||||
spin_unlock_irqrestore(&cm_node->recv_list_lock, flags);
|
|
||||||
nesqp = (struct nes_qp *)recv_entry->skb;
|
|
||||||
spin_lock_irqsave(&nesqp->lock, qplockflags);
|
|
||||||
if (nesqp->cm_id) {
|
|
||||||
nes_debug(NES_DBG_CM, "QP%u: cm_id = %p: HIT A "
|
|
||||||
"NES_TIMER_TYPE_CLOSE with something to do!\n",
|
|
||||||
nesqp->hwqp.qp_id, cm_id);
|
|
||||||
nesqp->hw_tcp_state = NES_AEQE_TCP_STATE_CLOSED;
|
|
||||||
nesqp->last_aeq = NES_AEQE_AEID_RESET_SENT;
|
|
||||||
nesqp->ibqp_state = IB_QPS_ERR;
|
|
||||||
spin_unlock_irqrestore(&nesqp->lock, qplockflags);
|
|
||||||
nes_cm_disconn(nesqp);
|
|
||||||
} else {
|
|
||||||
spin_unlock_irqrestore(&nesqp->lock, qplockflags);
|
|
||||||
nes_debug(NES_DBG_CM, "QP%u: cm_id = %p: HIT A "
|
|
||||||
"NES_TIMER_TYPE_CLOSE with nothing to do!\n",
|
|
||||||
nesqp->hwqp.qp_id, cm_id);
|
|
||||||
}
|
|
||||||
cm_id->rem_ref(cm_id);
|
|
||||||
|
|
||||||
kfree(recv_entry);
|
|
||||||
spin_lock_irqsave(&cm_node->recv_list_lock, flags);
|
|
||||||
}
|
|
||||||
spin_unlock_irqrestore(&cm_node->recv_list_lock, flags);
|
|
||||||
|
|
||||||
if (cm_node->listener) {
|
if (cm_node->listener) {
|
||||||
mini_cm_dec_refcnt_listen(cm_core, cm_node->listener, 0);
|
mini_cm_dec_refcnt_listen(cm_core, cm_node->listener, 0);
|
||||||
} else {
|
} else {
|
||||||
|
@ -1262,8 +1326,7 @@ static void drop_packet(struct sk_buff *skb)
|
||||||
dev_kfree_skb_any(skb);
|
dev_kfree_skb_any(skb);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handle_fin_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb,
|
static void handle_fin_pkt(struct nes_cm_node *cm_node)
|
||||||
struct tcphdr *tcph)
|
|
||||||
{
|
{
|
||||||
nes_debug(NES_DBG_CM, "Received FIN, cm_node = %p, state = %u. "
|
nes_debug(NES_DBG_CM, "Received FIN, cm_node = %p, state = %u. "
|
||||||
"refcnt=%d\n", cm_node, cm_node->state,
|
"refcnt=%d\n", cm_node, cm_node->state,
|
||||||
|
@ -1275,23 +1338,30 @@ static void handle_fin_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb,
|
||||||
case NES_CM_STATE_SYN_SENT:
|
case NES_CM_STATE_SYN_SENT:
|
||||||
case NES_CM_STATE_ESTABLISHED:
|
case NES_CM_STATE_ESTABLISHED:
|
||||||
case NES_CM_STATE_MPAREQ_SENT:
|
case NES_CM_STATE_MPAREQ_SENT:
|
||||||
|
case NES_CM_STATE_MPAREJ_RCVD:
|
||||||
cm_node->state = NES_CM_STATE_LAST_ACK;
|
cm_node->state = NES_CM_STATE_LAST_ACK;
|
||||||
send_fin(cm_node, skb);
|
send_fin(cm_node, NULL);
|
||||||
break;
|
break;
|
||||||
case NES_CM_STATE_FIN_WAIT1:
|
case NES_CM_STATE_FIN_WAIT1:
|
||||||
cm_node->state = NES_CM_STATE_CLOSING;
|
cm_node->state = NES_CM_STATE_CLOSING;
|
||||||
send_ack(cm_node, skb);
|
send_ack(cm_node, NULL);
|
||||||
|
/* Wait for ACK as this is simultanous close..
|
||||||
|
* After we receive ACK, do not send anything..
|
||||||
|
* Just rm the node.. Done.. */
|
||||||
break;
|
break;
|
||||||
case NES_CM_STATE_FIN_WAIT2:
|
case NES_CM_STATE_FIN_WAIT2:
|
||||||
cm_node->state = NES_CM_STATE_TIME_WAIT;
|
cm_node->state = NES_CM_STATE_TIME_WAIT;
|
||||||
send_ack(cm_node, skb);
|
send_ack(cm_node, NULL);
|
||||||
|
schedule_nes_timer(cm_node, NULL, NES_TIMER_TYPE_CLOSE, 1, 0);
|
||||||
|
break;
|
||||||
|
case NES_CM_STATE_TIME_WAIT:
|
||||||
cm_node->state = NES_CM_STATE_CLOSED;
|
cm_node->state = NES_CM_STATE_CLOSED;
|
||||||
|
rem_ref_cm_node(cm_node->cm_core, cm_node);
|
||||||
break;
|
break;
|
||||||
case NES_CM_STATE_TSA:
|
case NES_CM_STATE_TSA:
|
||||||
default:
|
default:
|
||||||
nes_debug(NES_DBG_CM, "Error Rcvd FIN for node-%p state = %d\n",
|
nes_debug(NES_DBG_CM, "Error Rcvd FIN for node-%p state = %d\n",
|
||||||
cm_node, cm_node->state);
|
cm_node, cm_node->state);
|
||||||
drop_packet(skb);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1337,23 +1407,35 @@ static void handle_rst_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb,
|
||||||
cleanup_retrans_entry(cm_node);
|
cleanup_retrans_entry(cm_node);
|
||||||
drop_packet(skb);
|
drop_packet(skb);
|
||||||
break;
|
break;
|
||||||
|
case NES_CM_STATE_TIME_WAIT:
|
||||||
|
cleanup_retrans_entry(cm_node);
|
||||||
|
cm_node->state = NES_CM_STATE_CLOSED;
|
||||||
|
rem_ref_cm_node(cm_node->cm_core, cm_node);
|
||||||
|
drop_packet(skb);
|
||||||
|
break;
|
||||||
|
case NES_CM_STATE_FIN_WAIT1:
|
||||||
|
cleanup_retrans_entry(cm_node);
|
||||||
|
nes_debug(NES_DBG_CM, "Bad state %s[%u]\n", __func__, __LINE__);
|
||||||
default:
|
default:
|
||||||
drop_packet(skb);
|
drop_packet(skb);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handle_rcv_mpa(struct nes_cm_node *cm_node, struct sk_buff *skb,
|
|
||||||
enum nes_cm_event_type type)
|
static void handle_rcv_mpa(struct nes_cm_node *cm_node, struct sk_buff *skb)
|
||||||
{
|
{
|
||||||
|
|
||||||
int ret;
|
int ret = 0;
|
||||||
int datasize = skb->len;
|
int datasize = skb->len;
|
||||||
u8 *dataloc = skb->data;
|
u8 *dataloc = skb->data;
|
||||||
ret = parse_mpa(cm_node, dataloc, datasize);
|
|
||||||
if (ret < 0) {
|
enum nes_cm_event_type type = NES_CM_EVENT_UNKNOWN;
|
||||||
|
u32 res_type;
|
||||||
|
ret = parse_mpa(cm_node, dataloc, &res_type, datasize);
|
||||||
|
if (ret) {
|
||||||
nes_debug(NES_DBG_CM, "didn't like MPA Request\n");
|
nes_debug(NES_DBG_CM, "didn't like MPA Request\n");
|
||||||
if (type == NES_CM_EVENT_CONNECTED) {
|
if (cm_node->state == NES_CM_STATE_MPAREQ_SENT) {
|
||||||
nes_debug(NES_DBG_CM, "%s[%u] create abort for "
|
nes_debug(NES_DBG_CM, "%s[%u] create abort for "
|
||||||
"cm_node=%p listener=%p state=%d\n", __func__,
|
"cm_node=%p listener=%p state=%d\n", __func__,
|
||||||
__LINE__, cm_node, cm_node->listener,
|
__LINE__, cm_node, cm_node->listener,
|
||||||
|
@ -1362,18 +1444,38 @@ static void handle_rcv_mpa(struct nes_cm_node *cm_node, struct sk_buff *skb,
|
||||||
} else {
|
} else {
|
||||||
passive_open_err(cm_node, skb, 1);
|
passive_open_err(cm_node, skb, 1);
|
||||||
}
|
}
|
||||||
} else {
|
return;
|
||||||
cleanup_retrans_entry(cm_node);
|
|
||||||
dev_kfree_skb_any(skb);
|
|
||||||
if (type == NES_CM_EVENT_CONNECTED)
|
|
||||||
cm_node->state = NES_CM_STATE_TSA;
|
|
||||||
else
|
|
||||||
atomic_set(&cm_node->passive_state,
|
|
||||||
NES_PASSIVE_STATE_INDICATED);
|
|
||||||
create_event(cm_node, type);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
return ;
|
|
||||||
|
switch (cm_node->state) {
|
||||||
|
case NES_CM_STATE_ESTABLISHED:
|
||||||
|
if (res_type == NES_MPA_REQUEST_REJECT) {
|
||||||
|
/*BIG problem as we are receiving the MPA.. So should
|
||||||
|
* not be REJECT.. This is Passive Open.. We can
|
||||||
|
* only receive it Reject for Active Open...*/
|
||||||
|
WARN_ON(1);
|
||||||
|
}
|
||||||
|
cm_node->state = NES_CM_STATE_MPAREQ_RCVD;
|
||||||
|
type = NES_CM_EVENT_MPA_REQ;
|
||||||
|
atomic_set(&cm_node->passive_state,
|
||||||
|
NES_PASSIVE_STATE_INDICATED);
|
||||||
|
break;
|
||||||
|
case NES_CM_STATE_MPAREQ_SENT:
|
||||||
|
if (res_type == NES_MPA_REQUEST_REJECT) {
|
||||||
|
type = NES_CM_EVENT_MPA_REJECT;
|
||||||
|
cm_node->state = NES_CM_STATE_MPAREJ_RCVD;
|
||||||
|
} else {
|
||||||
|
type = NES_CM_EVENT_CONNECTED;
|
||||||
|
cm_node->state = NES_CM_STATE_TSA;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
WARN_ON(1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
dev_kfree_skb_any(skb);
|
||||||
|
create_event(cm_node, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void indicate_pkt_err(struct nes_cm_node *cm_node, struct sk_buff *skb)
|
static void indicate_pkt_err(struct nes_cm_node *cm_node, struct sk_buff *skb)
|
||||||
|
@ -1461,8 +1563,6 @@ static void handle_syn_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb,
|
||||||
break;
|
break;
|
||||||
case NES_CM_STATE_LISTENING:
|
case NES_CM_STATE_LISTENING:
|
||||||
/* Passive OPEN */
|
/* Passive OPEN */
|
||||||
cm_node->accept_pend = 1;
|
|
||||||
atomic_inc(&cm_node->listener->pend_accepts_cnt);
|
|
||||||
if (atomic_read(&cm_node->listener->pend_accepts_cnt) >
|
if (atomic_read(&cm_node->listener->pend_accepts_cnt) >
|
||||||
cm_node->listener->backlog) {
|
cm_node->listener->backlog) {
|
||||||
nes_debug(NES_DBG_CM, "drop syn due to backlog "
|
nes_debug(NES_DBG_CM, "drop syn due to backlog "
|
||||||
|
@ -1480,6 +1580,9 @@ static void handle_syn_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb,
|
||||||
}
|
}
|
||||||
cm_node->tcp_cntxt.rcv_nxt = inc_sequence + 1;
|
cm_node->tcp_cntxt.rcv_nxt = inc_sequence + 1;
|
||||||
BUG_ON(cm_node->send_entry);
|
BUG_ON(cm_node->send_entry);
|
||||||
|
cm_node->accept_pend = 1;
|
||||||
|
atomic_inc(&cm_node->listener->pend_accepts_cnt);
|
||||||
|
|
||||||
cm_node->state = NES_CM_STATE_SYN_RCVD;
|
cm_node->state = NES_CM_STATE_SYN_RCVD;
|
||||||
send_syn(cm_node, 1, skb);
|
send_syn(cm_node, 1, skb);
|
||||||
break;
|
break;
|
||||||
|
@ -1514,6 +1617,7 @@ static void handle_synack_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb,
|
||||||
inc_sequence = ntohl(tcph->seq);
|
inc_sequence = ntohl(tcph->seq);
|
||||||
switch (cm_node->state) {
|
switch (cm_node->state) {
|
||||||
case NES_CM_STATE_SYN_SENT:
|
case NES_CM_STATE_SYN_SENT:
|
||||||
|
cleanup_retrans_entry(cm_node);
|
||||||
/* active open */
|
/* active open */
|
||||||
if (check_syn(cm_node, tcph, skb))
|
if (check_syn(cm_node, tcph, skb))
|
||||||
return;
|
return;
|
||||||
|
@ -1563,10 +1667,7 @@ static void handle_ack_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb,
|
||||||
u32 rem_seq;
|
u32 rem_seq;
|
||||||
int ret;
|
int ret;
|
||||||
int optionsize;
|
int optionsize;
|
||||||
u32 temp_seq = cm_node->tcp_cntxt.loc_seq_num;
|
|
||||||
|
|
||||||
optionsize = (tcph->doff << 2) - sizeof(struct tcphdr);
|
optionsize = (tcph->doff << 2) - sizeof(struct tcphdr);
|
||||||
cm_node->tcp_cntxt.loc_seq_num = ntohl(tcph->ack_seq);
|
|
||||||
|
|
||||||
if (check_seq(cm_node, tcph, skb))
|
if (check_seq(cm_node, tcph, skb))
|
||||||
return;
|
return;
|
||||||
|
@ -1576,7 +1677,7 @@ static void handle_ack_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb,
|
||||||
rem_seq = ntohl(tcph->seq);
|
rem_seq = ntohl(tcph->seq);
|
||||||
rem_seq_ack = ntohl(tcph->ack_seq);
|
rem_seq_ack = ntohl(tcph->ack_seq);
|
||||||
datasize = skb->len;
|
datasize = skb->len;
|
||||||
|
cleanup_retrans_entry(cm_node);
|
||||||
switch (cm_node->state) {
|
switch (cm_node->state) {
|
||||||
case NES_CM_STATE_SYN_RCVD:
|
case NES_CM_STATE_SYN_RCVD:
|
||||||
/* Passive OPEN */
|
/* Passive OPEN */
|
||||||
|
@ -1584,7 +1685,6 @@ static void handle_ack_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb,
|
||||||
if (ret)
|
if (ret)
|
||||||
break;
|
break;
|
||||||
cm_node->tcp_cntxt.rem_ack_num = ntohl(tcph->ack_seq);
|
cm_node->tcp_cntxt.rem_ack_num = ntohl(tcph->ack_seq);
|
||||||
cm_node->tcp_cntxt.loc_seq_num = temp_seq;
|
|
||||||
if (cm_node->tcp_cntxt.rem_ack_num !=
|
if (cm_node->tcp_cntxt.rem_ack_num !=
|
||||||
cm_node->tcp_cntxt.loc_seq_num) {
|
cm_node->tcp_cntxt.loc_seq_num) {
|
||||||
nes_debug(NES_DBG_CM, "rem_ack_num != loc_seq_num\n");
|
nes_debug(NES_DBG_CM, "rem_ack_num != loc_seq_num\n");
|
||||||
|
@ -1593,31 +1693,30 @@ static void handle_ack_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
cm_node->state = NES_CM_STATE_ESTABLISHED;
|
cm_node->state = NES_CM_STATE_ESTABLISHED;
|
||||||
|
cleanup_retrans_entry(cm_node);
|
||||||
if (datasize) {
|
if (datasize) {
|
||||||
cm_node->tcp_cntxt.rcv_nxt = inc_sequence + datasize;
|
cm_node->tcp_cntxt.rcv_nxt = inc_sequence + datasize;
|
||||||
cm_node->state = NES_CM_STATE_MPAREQ_RCVD;
|
handle_rcv_mpa(cm_node, skb);
|
||||||
handle_rcv_mpa(cm_node, skb, NES_CM_EVENT_MPA_REQ);
|
} else { /* rcvd ACK only */
|
||||||
} else { /* rcvd ACK only */
|
|
||||||
dev_kfree_skb_any(skb);
|
dev_kfree_skb_any(skb);
|
||||||
cleanup_retrans_entry(cm_node);
|
cleanup_retrans_entry(cm_node);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case NES_CM_STATE_ESTABLISHED:
|
case NES_CM_STATE_ESTABLISHED:
|
||||||
/* Passive OPEN */
|
/* Passive OPEN */
|
||||||
/* We expect mpa frame to be received only */
|
cleanup_retrans_entry(cm_node);
|
||||||
if (datasize) {
|
if (datasize) {
|
||||||
cm_node->tcp_cntxt.rcv_nxt = inc_sequence + datasize;
|
cm_node->tcp_cntxt.rcv_nxt = inc_sequence + datasize;
|
||||||
cm_node->state = NES_CM_STATE_MPAREQ_RCVD;
|
handle_rcv_mpa(cm_node, skb);
|
||||||
handle_rcv_mpa(cm_node, skb,
|
|
||||||
NES_CM_EVENT_MPA_REQ);
|
|
||||||
} else
|
} else
|
||||||
drop_packet(skb);
|
drop_packet(skb);
|
||||||
break;
|
break;
|
||||||
case NES_CM_STATE_MPAREQ_SENT:
|
case NES_CM_STATE_MPAREQ_SENT:
|
||||||
|
cleanup_retrans_entry(cm_node);
|
||||||
cm_node->tcp_cntxt.rem_ack_num = ntohl(tcph->ack_seq);
|
cm_node->tcp_cntxt.rem_ack_num = ntohl(tcph->ack_seq);
|
||||||
if (datasize) {
|
if (datasize) {
|
||||||
cm_node->tcp_cntxt.rcv_nxt = inc_sequence + datasize;
|
cm_node->tcp_cntxt.rcv_nxt = inc_sequence + datasize;
|
||||||
handle_rcv_mpa(cm_node, skb, NES_CM_EVENT_CONNECTED);
|
handle_rcv_mpa(cm_node, skb);
|
||||||
} else { /* Could be just an ack pkt.. */
|
} else { /* Could be just an ack pkt.. */
|
||||||
cleanup_retrans_entry(cm_node);
|
cleanup_retrans_entry(cm_node);
|
||||||
dev_kfree_skb_any(skb);
|
dev_kfree_skb_any(skb);
|
||||||
|
@ -1628,13 +1727,24 @@ static void handle_ack_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb,
|
||||||
cleanup_retrans_entry(cm_node);
|
cleanup_retrans_entry(cm_node);
|
||||||
send_reset(cm_node, skb);
|
send_reset(cm_node, skb);
|
||||||
break;
|
break;
|
||||||
|
case NES_CM_STATE_LAST_ACK:
|
||||||
|
cleanup_retrans_entry(cm_node);
|
||||||
|
cm_node->state = NES_CM_STATE_CLOSED;
|
||||||
|
cm_node->cm_id->rem_ref(cm_node->cm_id);
|
||||||
|
case NES_CM_STATE_CLOSING:
|
||||||
|
cleanup_retrans_entry(cm_node);
|
||||||
|
rem_ref_cm_node(cm_node->cm_core, cm_node);
|
||||||
|
drop_packet(skb);
|
||||||
|
break;
|
||||||
case NES_CM_STATE_FIN_WAIT1:
|
case NES_CM_STATE_FIN_WAIT1:
|
||||||
|
cleanup_retrans_entry(cm_node);
|
||||||
|
drop_packet(skb);
|
||||||
|
cm_node->state = NES_CM_STATE_FIN_WAIT2;
|
||||||
|
break;
|
||||||
case NES_CM_STATE_SYN_SENT:
|
case NES_CM_STATE_SYN_SENT:
|
||||||
case NES_CM_STATE_FIN_WAIT2:
|
case NES_CM_STATE_FIN_WAIT2:
|
||||||
case NES_CM_STATE_TSA:
|
case NES_CM_STATE_TSA:
|
||||||
case NES_CM_STATE_MPAREQ_RCVD:
|
case NES_CM_STATE_MPAREQ_RCVD:
|
||||||
case NES_CM_STATE_LAST_ACK:
|
|
||||||
case NES_CM_STATE_CLOSING:
|
|
||||||
case NES_CM_STATE_UNKNOWN:
|
case NES_CM_STATE_UNKNOWN:
|
||||||
default:
|
default:
|
||||||
drop_packet(skb);
|
drop_packet(skb);
|
||||||
|
@ -1744,6 +1854,7 @@ static void process_packet(struct nes_cm_node *cm_node, struct sk_buff *skb,
|
||||||
{
|
{
|
||||||
enum nes_tcpip_pkt_type pkt_type = NES_PKT_TYPE_UNKNOWN;
|
enum nes_tcpip_pkt_type pkt_type = NES_PKT_TYPE_UNKNOWN;
|
||||||
struct tcphdr *tcph = tcp_hdr(skb);
|
struct tcphdr *tcph = tcp_hdr(skb);
|
||||||
|
u32 fin_set = 0;
|
||||||
skb_pull(skb, ip_hdr(skb)->ihl << 2);
|
skb_pull(skb, ip_hdr(skb)->ihl << 2);
|
||||||
|
|
||||||
nes_debug(NES_DBG_CM, "process_packet: cm_node=%p state =%d syn=%d "
|
nes_debug(NES_DBG_CM, "process_packet: cm_node=%p state =%d syn=%d "
|
||||||
|
@ -1756,10 +1867,10 @@ static void process_packet(struct nes_cm_node *cm_node, struct sk_buff *skb,
|
||||||
pkt_type = NES_PKT_TYPE_SYN;
|
pkt_type = NES_PKT_TYPE_SYN;
|
||||||
if (tcph->ack)
|
if (tcph->ack)
|
||||||
pkt_type = NES_PKT_TYPE_SYNACK;
|
pkt_type = NES_PKT_TYPE_SYNACK;
|
||||||
} else if (tcph->fin)
|
} else if (tcph->ack)
|
||||||
pkt_type = NES_PKT_TYPE_FIN;
|
|
||||||
else if (tcph->ack)
|
|
||||||
pkt_type = NES_PKT_TYPE_ACK;
|
pkt_type = NES_PKT_TYPE_ACK;
|
||||||
|
if (tcph->fin)
|
||||||
|
fin_set = 1;
|
||||||
|
|
||||||
switch (pkt_type) {
|
switch (pkt_type) {
|
||||||
case NES_PKT_TYPE_SYN:
|
case NES_PKT_TYPE_SYN:
|
||||||
|
@ -1770,15 +1881,16 @@ static void process_packet(struct nes_cm_node *cm_node, struct sk_buff *skb,
|
||||||
break;
|
break;
|
||||||
case NES_PKT_TYPE_ACK:
|
case NES_PKT_TYPE_ACK:
|
||||||
handle_ack_pkt(cm_node, skb, tcph);
|
handle_ack_pkt(cm_node, skb, tcph);
|
||||||
|
if (fin_set)
|
||||||
|
handle_fin_pkt(cm_node);
|
||||||
break;
|
break;
|
||||||
case NES_PKT_TYPE_RST:
|
case NES_PKT_TYPE_RST:
|
||||||
handle_rst_pkt(cm_node, skb, tcph);
|
handle_rst_pkt(cm_node, skb, tcph);
|
||||||
break;
|
break;
|
||||||
case NES_PKT_TYPE_FIN:
|
|
||||||
handle_fin_pkt(cm_node, skb, tcph);
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
drop_packet(skb);
|
drop_packet(skb);
|
||||||
|
if (fin_set)
|
||||||
|
handle_fin_pkt(cm_node);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1921,7 +2033,7 @@ static struct nes_cm_node *mini_cm_connect(struct nes_cm_core *cm_core,
|
||||||
loopbackremotenode->tcp_cntxt.rcv_wscale;
|
loopbackremotenode->tcp_cntxt.rcv_wscale;
|
||||||
loopbackremotenode->tcp_cntxt.snd_wscale =
|
loopbackremotenode->tcp_cntxt.snd_wscale =
|
||||||
cm_node->tcp_cntxt.rcv_wscale;
|
cm_node->tcp_cntxt.rcv_wscale;
|
||||||
|
loopbackremotenode->state = NES_CM_STATE_MPAREQ_RCVD;
|
||||||
create_event(loopbackremotenode, NES_CM_EVENT_MPA_REQ);
|
create_event(loopbackremotenode, NES_CM_EVENT_MPA_REQ);
|
||||||
}
|
}
|
||||||
return cm_node;
|
return cm_node;
|
||||||
|
@ -1976,7 +2088,11 @@ static int mini_cm_reject(struct nes_cm_core *cm_core,
|
||||||
struct ietf_mpa_frame *mpa_frame, struct nes_cm_node *cm_node)
|
struct ietf_mpa_frame *mpa_frame, struct nes_cm_node *cm_node)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
int err = 0;
|
||||||
int passive_state;
|
int passive_state;
|
||||||
|
struct nes_cm_event event;
|
||||||
|
struct iw_cm_id *cm_id = cm_node->cm_id;
|
||||||
|
struct nes_cm_node *loopback = cm_node->loopbackpartner;
|
||||||
|
|
||||||
nes_debug(NES_DBG_CM, "%s cm_node=%p type=%d state=%d\n",
|
nes_debug(NES_DBG_CM, "%s cm_node=%p type=%d state=%d\n",
|
||||||
__func__, cm_node, cm_node->tcp_cntxt.client, cm_node->state);
|
__func__, cm_node, cm_node->tcp_cntxt.client, cm_node->state);
|
||||||
|
@ -1985,12 +2101,38 @@ static int mini_cm_reject(struct nes_cm_core *cm_core,
|
||||||
return ret;
|
return ret;
|
||||||
cleanup_retrans_entry(cm_node);
|
cleanup_retrans_entry(cm_node);
|
||||||
|
|
||||||
passive_state = atomic_add_return(1, &cm_node->passive_state);
|
if (!loopback) {
|
||||||
cm_node->state = NES_CM_STATE_CLOSED;
|
passive_state = atomic_add_return(1, &cm_node->passive_state);
|
||||||
if (passive_state == NES_SEND_RESET_EVENT)
|
if (passive_state == NES_SEND_RESET_EVENT) {
|
||||||
|
cm_node->state = NES_CM_STATE_CLOSED;
|
||||||
|
rem_ref_cm_node(cm_core, cm_node);
|
||||||
|
} else {
|
||||||
|
ret = send_mpa_reject(cm_node);
|
||||||
|
if (ret) {
|
||||||
|
cm_node->state = NES_CM_STATE_CLOSED;
|
||||||
|
err = send_reset(cm_node, NULL);
|
||||||
|
if (err)
|
||||||
|
WARN_ON(1);
|
||||||
|
} else
|
||||||
|
cm_id->add_ref(cm_id);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
cm_node->cm_id = NULL;
|
||||||
|
event.cm_node = loopback;
|
||||||
|
event.cm_info.rem_addr = loopback->rem_addr;
|
||||||
|
event.cm_info.loc_addr = loopback->loc_addr;
|
||||||
|
event.cm_info.rem_port = loopback->rem_port;
|
||||||
|
event.cm_info.loc_port = loopback->loc_port;
|
||||||
|
event.cm_info.cm_id = loopback->cm_id;
|
||||||
|
cm_event_mpa_reject(&event);
|
||||||
rem_ref_cm_node(cm_core, cm_node);
|
rem_ref_cm_node(cm_core, cm_node);
|
||||||
else
|
loopback->state = NES_CM_STATE_CLOSING;
|
||||||
ret = send_reset(cm_node, NULL);
|
|
||||||
|
cm_id = loopback->cm_id;
|
||||||
|
rem_ref_cm_node(cm_core, loopback);
|
||||||
|
cm_id->rem_ref(cm_id);
|
||||||
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2027,6 +2169,7 @@ static int mini_cm_close(struct nes_cm_core *cm_core, struct nes_cm_node *cm_nod
|
||||||
case NES_CM_STATE_CLOSING:
|
case NES_CM_STATE_CLOSING:
|
||||||
ret = -1;
|
ret = -1;
|
||||||
break;
|
break;
|
||||||
|
case NES_CM_STATE_MPAREJ_RCVD:
|
||||||
case NES_CM_STATE_LISTENING:
|
case NES_CM_STATE_LISTENING:
|
||||||
case NES_CM_STATE_UNKNOWN:
|
case NES_CM_STATE_UNKNOWN:
|
||||||
case NES_CM_STATE_INITED:
|
case NES_CM_STATE_INITED:
|
||||||
|
@ -2223,15 +2366,15 @@ static int mini_cm_set(struct nes_cm_core *cm_core, u32 type, u32 value)
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case NES_CM_SET_PKT_SIZE:
|
case NES_CM_SET_PKT_SIZE:
|
||||||
cm_core->mtu = value;
|
cm_core->mtu = value;
|
||||||
break;
|
break;
|
||||||
case NES_CM_SET_FREE_PKT_Q_SIZE:
|
case NES_CM_SET_FREE_PKT_Q_SIZE:
|
||||||
cm_core->free_tx_pkt_max = value;
|
cm_core->free_tx_pkt_max = value;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
/* unknown set option */
|
/* unknown set option */
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -2621,9 +2764,7 @@ int nes_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
|
||||||
NES_QPCONTEXT_ORDIRD_WRPDU);
|
NES_QPCONTEXT_ORDIRD_WRPDU);
|
||||||
} else {
|
} else {
|
||||||
nesqp->nesqp_context->ird_ord_sizes |=
|
nesqp->nesqp_context->ird_ord_sizes |=
|
||||||
cpu_to_le32((NES_QPCONTEXT_ORDIRD_LSMM_PRESENT |
|
cpu_to_le32(NES_QPCONTEXT_ORDIRD_WRPDU);
|
||||||
NES_QPCONTEXT_ORDIRD_WRPDU |
|
|
||||||
NES_QPCONTEXT_ORDIRD_ALSMM));
|
|
||||||
}
|
}
|
||||||
nesqp->skip_lsmm = 1;
|
nesqp->skip_lsmm = 1;
|
||||||
|
|
||||||
|
@ -2745,23 +2886,35 @@ int nes_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
|
||||||
int nes_reject(struct iw_cm_id *cm_id, const void *pdata, u8 pdata_len)
|
int nes_reject(struct iw_cm_id *cm_id, const void *pdata, u8 pdata_len)
|
||||||
{
|
{
|
||||||
struct nes_cm_node *cm_node;
|
struct nes_cm_node *cm_node;
|
||||||
|
struct nes_cm_node *loopback;
|
||||||
|
|
||||||
struct nes_cm_core *cm_core;
|
struct nes_cm_core *cm_core;
|
||||||
|
|
||||||
atomic_inc(&cm_rejects);
|
atomic_inc(&cm_rejects);
|
||||||
cm_node = (struct nes_cm_node *) cm_id->provider_data;
|
cm_node = (struct nes_cm_node *) cm_id->provider_data;
|
||||||
|
loopback = cm_node->loopbackpartner;
|
||||||
cm_core = cm_node->cm_core;
|
cm_core = cm_node->cm_core;
|
||||||
|
cm_node->cm_id = cm_id;
|
||||||
cm_node->mpa_frame_size = sizeof(struct ietf_mpa_frame) + pdata_len;
|
cm_node->mpa_frame_size = sizeof(struct ietf_mpa_frame) + pdata_len;
|
||||||
|
|
||||||
strcpy(&cm_node->mpa_frame.key[0], IEFT_MPA_KEY_REP);
|
if (cm_node->mpa_frame_size > MAX_CM_BUFFER)
|
||||||
memcpy(&cm_node->mpa_frame.priv_data, pdata, pdata_len);
|
return -EINVAL;
|
||||||
|
|
||||||
|
strcpy(&cm_node->mpa_frame.key[0], IEFT_MPA_KEY_REP);
|
||||||
|
if (loopback) {
|
||||||
|
memcpy(&loopback->mpa_frame.priv_data, pdata, pdata_len);
|
||||||
|
loopback->mpa_frame.priv_data_len = pdata_len;
|
||||||
|
loopback->mpa_frame_size = sizeof(struct ietf_mpa_frame) +
|
||||||
|
pdata_len;
|
||||||
|
} else {
|
||||||
|
memcpy(&cm_node->mpa_frame.priv_data, pdata, pdata_len);
|
||||||
|
cm_node->mpa_frame.priv_data_len = cpu_to_be16(pdata_len);
|
||||||
|
}
|
||||||
|
|
||||||
cm_node->mpa_frame.priv_data_len = cpu_to_be16(pdata_len);
|
|
||||||
cm_node->mpa_frame.rev = mpa_version;
|
cm_node->mpa_frame.rev = mpa_version;
|
||||||
cm_node->mpa_frame.flags = IETF_MPA_FLAGS_CRC | IETF_MPA_FLAGS_REJECT;
|
cm_node->mpa_frame.flags = IETF_MPA_FLAGS_CRC | IETF_MPA_FLAGS_REJECT;
|
||||||
|
|
||||||
cm_core->api->reject(cm_core, &cm_node->mpa_frame, cm_node);
|
return cm_core->api->reject(cm_core, &cm_node->mpa_frame, cm_node);
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -3270,13 +3423,56 @@ static void cm_event_mpa_req(struct nes_cm_event *event)
|
||||||
cm_event.remote_addr.sin_family = AF_INET;
|
cm_event.remote_addr.sin_family = AF_INET;
|
||||||
cm_event.remote_addr.sin_port = htons(event->cm_info.rem_port);
|
cm_event.remote_addr.sin_port = htons(event->cm_info.rem_port);
|
||||||
cm_event.remote_addr.sin_addr.s_addr = htonl(event->cm_info.rem_addr);
|
cm_event.remote_addr.sin_addr.s_addr = htonl(event->cm_info.rem_addr);
|
||||||
|
cm_event.private_data = cm_node->mpa_frame_buf;
|
||||||
cm_event.private_data = cm_node->mpa_frame_buf;
|
cm_event.private_data_len = (u8) cm_node->mpa_frame_size;
|
||||||
cm_event.private_data_len = (u8) cm_node->mpa_frame_size;
|
|
||||||
|
|
||||||
ret = cm_id->event_handler(cm_id, &cm_event);
|
ret = cm_id->event_handler(cm_id, &cm_event);
|
||||||
if (ret)
|
if (ret)
|
||||||
printk("%s[%u] OFA CM event_handler returned, ret=%d\n",
|
printk(KERN_ERR "%s[%u] OFA CM event_handler returned, ret=%d\n",
|
||||||
|
__func__, __LINE__, ret);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void cm_event_mpa_reject(struct nes_cm_event *event)
|
||||||
|
{
|
||||||
|
struct iw_cm_id *cm_id;
|
||||||
|
struct iw_cm_event cm_event;
|
||||||
|
struct nes_cm_node *cm_node;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
cm_node = event->cm_node;
|
||||||
|
if (!cm_node)
|
||||||
|
return;
|
||||||
|
cm_id = cm_node->cm_id;
|
||||||
|
|
||||||
|
atomic_inc(&cm_connect_reqs);
|
||||||
|
nes_debug(NES_DBG_CM, "cm_node = %p - cm_id = %p, jiffies = %lu\n",
|
||||||
|
cm_node, cm_id, jiffies);
|
||||||
|
|
||||||
|
cm_event.event = IW_CM_EVENT_CONNECT_REPLY;
|
||||||
|
cm_event.status = -ECONNREFUSED;
|
||||||
|
cm_event.provider_data = cm_id->provider_data;
|
||||||
|
|
||||||
|
cm_event.local_addr.sin_family = AF_INET;
|
||||||
|
cm_event.local_addr.sin_port = htons(event->cm_info.loc_port);
|
||||||
|
cm_event.local_addr.sin_addr.s_addr = htonl(event->cm_info.loc_addr);
|
||||||
|
|
||||||
|
cm_event.remote_addr.sin_family = AF_INET;
|
||||||
|
cm_event.remote_addr.sin_port = htons(event->cm_info.rem_port);
|
||||||
|
cm_event.remote_addr.sin_addr.s_addr = htonl(event->cm_info.rem_addr);
|
||||||
|
|
||||||
|
cm_event.private_data = cm_node->mpa_frame_buf;
|
||||||
|
cm_event.private_data_len = (u8) cm_node->mpa_frame_size;
|
||||||
|
|
||||||
|
nes_debug(NES_DBG_CM, "call CM_EVENT_MPA_REJECTED, local_addr=%08x, "
|
||||||
|
"remove_addr=%08x\n",
|
||||||
|
cm_event.local_addr.sin_addr.s_addr,
|
||||||
|
cm_event.remote_addr.sin_addr.s_addr);
|
||||||
|
|
||||||
|
ret = cm_id->event_handler(cm_id, &cm_event);
|
||||||
|
if (ret)
|
||||||
|
printk(KERN_ERR "%s[%u] OFA CM event_handler returned, ret=%d\n",
|
||||||
__func__, __LINE__, ret);
|
__func__, __LINE__, ret);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
@ -3341,6 +3537,14 @@ static void nes_cm_event_handler(struct work_struct *work)
|
||||||
cm_event_connected(event);
|
cm_event_connected(event);
|
||||||
nes_debug(NES_DBG_CM, "CM Event: CONNECTED\n");
|
nes_debug(NES_DBG_CM, "CM Event: CONNECTED\n");
|
||||||
break;
|
break;
|
||||||
|
case NES_CM_EVENT_MPA_REJECT:
|
||||||
|
if ((!event->cm_node->cm_id) ||
|
||||||
|
(event->cm_node->state == NES_CM_STATE_TSA))
|
||||||
|
break;
|
||||||
|
cm_event_mpa_reject(event);
|
||||||
|
nes_debug(NES_DBG_CM, "CM Event: REJECT\n");
|
||||||
|
break;
|
||||||
|
|
||||||
case NES_CM_EVENT_ABORTED:
|
case NES_CM_EVENT_ABORTED:
|
||||||
if ((!event->cm_node->cm_id) ||
|
if ((!event->cm_node->cm_id) ||
|
||||||
(event->cm_node->state == NES_CM_STATE_TSA))
|
(event->cm_node->state == NES_CM_STATE_TSA))
|
||||||
|
|
|
@ -39,6 +39,9 @@
|
||||||
#define NES_MANAGE_APBVT_DEL 0
|
#define NES_MANAGE_APBVT_DEL 0
|
||||||
#define NES_MANAGE_APBVT_ADD 1
|
#define NES_MANAGE_APBVT_ADD 1
|
||||||
|
|
||||||
|
#define NES_MPA_REQUEST_ACCEPT 1
|
||||||
|
#define NES_MPA_REQUEST_REJECT 2
|
||||||
|
|
||||||
/* IETF MPA -- defines, enums, structs */
|
/* IETF MPA -- defines, enums, structs */
|
||||||
#define IEFT_MPA_KEY_REQ "MPA ID Req Frame"
|
#define IEFT_MPA_KEY_REQ "MPA ID Req Frame"
|
||||||
#define IEFT_MPA_KEY_REP "MPA ID Rep Frame"
|
#define IEFT_MPA_KEY_REP "MPA ID Rep Frame"
|
||||||
|
@ -186,6 +189,7 @@ enum nes_cm_node_state {
|
||||||
NES_CM_STATE_ACCEPTING,
|
NES_CM_STATE_ACCEPTING,
|
||||||
NES_CM_STATE_MPAREQ_SENT,
|
NES_CM_STATE_MPAREQ_SENT,
|
||||||
NES_CM_STATE_MPAREQ_RCVD,
|
NES_CM_STATE_MPAREQ_RCVD,
|
||||||
|
NES_CM_STATE_MPAREJ_RCVD,
|
||||||
NES_CM_STATE_TSA,
|
NES_CM_STATE_TSA,
|
||||||
NES_CM_STATE_FIN_WAIT1,
|
NES_CM_STATE_FIN_WAIT1,
|
||||||
NES_CM_STATE_FIN_WAIT2,
|
NES_CM_STATE_FIN_WAIT2,
|
||||||
|
@ -278,13 +282,12 @@ struct nes_cm_node {
|
||||||
struct nes_timer_entry *send_entry;
|
struct nes_timer_entry *send_entry;
|
||||||
|
|
||||||
spinlock_t retrans_list_lock;
|
spinlock_t retrans_list_lock;
|
||||||
struct list_head recv_list;
|
struct nes_timer_entry *recv_entry;
|
||||||
spinlock_t recv_list_lock;
|
|
||||||
|
|
||||||
int send_write0;
|
int send_write0;
|
||||||
union {
|
union {
|
||||||
struct ietf_mpa_frame mpa_frame;
|
struct ietf_mpa_frame mpa_frame;
|
||||||
u8 mpa_frame_buf[NES_CM_DEFAULT_MTU];
|
u8 mpa_frame_buf[MAX_CM_BUFFER];
|
||||||
};
|
};
|
||||||
u16 mpa_frame_size;
|
u16 mpa_frame_size;
|
||||||
struct iw_cm_id *cm_id;
|
struct iw_cm_id *cm_id;
|
||||||
|
@ -326,6 +329,7 @@ enum nes_cm_event_type {
|
||||||
NES_CM_EVENT_MPA_REQ,
|
NES_CM_EVENT_MPA_REQ,
|
||||||
NES_CM_EVENT_MPA_CONNECT,
|
NES_CM_EVENT_MPA_CONNECT,
|
||||||
NES_CM_EVENT_MPA_ACCEPT,
|
NES_CM_EVENT_MPA_ACCEPT,
|
||||||
|
NES_CM_EVENT_MPA_REJECT,
|
||||||
NES_CM_EVENT_MPA_ESTABLISHED,
|
NES_CM_EVENT_MPA_ESTABLISHED,
|
||||||
NES_CM_EVENT_CONNECTED,
|
NES_CM_EVENT_CONNECTED,
|
||||||
NES_CM_EVENT_CLOSED,
|
NES_CM_EVENT_CLOSED,
|
||||||
|
|
Loading…
Reference in New Issue