diff options
author | Faisal Latif <faisal.latif@intel.com> | 2008-11-21 21:50:52 -0500 |
---|---|---|
committer | Roland Dreier <rolandd@cisco.com> | 2008-12-05 14:00:19 -0500 |
commit | abb77256761bc3ee7a21cc28f6f12a938964e83f (patch) | |
tree | 33d435dfedb2bac2d74a515d04e817d8be90833b /drivers/infiniband | |
parent | 4a14f6a79f5110c6033f0c61d77d07c449c2d083 (diff) |
RDMA/nes: Fix TCP compliance test failures
ANVL testing showed we are not handling all cm_node states during
connection establishment. Add missing state handlers and fix sequence
number send reset in handle_tcp_options().
Signed-off-by: Faisal Latif <faisal.latif@intel.com>
Signed-off-by: Chien Tung <chien.tin.tung@intel.com>
Signed-off-by: Roland Dreier <rolandd@cisco.com>
Diffstat (limited to 'drivers/infiniband')
-rw-r--r-- | drivers/infiniband/hw/nes/nes_cm.c | 44 |
1 files changed, 37 insertions, 7 deletions
diff --git a/drivers/infiniband/hw/nes/nes_cm.c b/drivers/infiniband/hw/nes/nes_cm.c index f34fa6f77a81..0997c7b8cd9b 100644 --- a/drivers/infiniband/hw/nes/nes_cm.c +++ b/drivers/infiniband/hw/nes/nes_cm.c | |||
@@ -1508,7 +1508,7 @@ static void handle_syn_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb, | |||
1508 | int optionsize; | 1508 | int optionsize; |
1509 | 1509 | ||
1510 | optionsize = (tcph->doff << 2) - sizeof(struct tcphdr); | 1510 | optionsize = (tcph->doff << 2) - sizeof(struct tcphdr); |
1511 | skb_pull(skb, tcph->doff << 2); | 1511 | skb_trim(skb, 0); |
1512 | inc_sequence = ntohl(tcph->seq); | 1512 | inc_sequence = ntohl(tcph->seq); |
1513 | 1513 | ||
1514 | switch (cm_node->state) { | 1514 | switch (cm_node->state) { |
@@ -1541,6 +1541,10 @@ static void handle_syn_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb, | |||
1541 | cm_node->state = NES_CM_STATE_SYN_RCVD; | 1541 | cm_node->state = NES_CM_STATE_SYN_RCVD; |
1542 | send_syn(cm_node, 1, skb); | 1542 | send_syn(cm_node, 1, skb); |
1543 | break; | 1543 | break; |
1544 | case NES_CM_STATE_CLOSED: | ||
1545 | cleanup_retrans_entry(cm_node); | ||
1546 | send_reset(cm_node, skb); | ||
1547 | break; | ||
1544 | case NES_CM_STATE_TSA: | 1548 | case NES_CM_STATE_TSA: |
1545 | case NES_CM_STATE_ESTABLISHED: | 1549 | case NES_CM_STATE_ESTABLISHED: |
1546 | case NES_CM_STATE_FIN_WAIT1: | 1550 | case NES_CM_STATE_FIN_WAIT1: |
@@ -1549,7 +1553,6 @@ static void handle_syn_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb, | |||
1549 | case NES_CM_STATE_LAST_ACK: | 1553 | case NES_CM_STATE_LAST_ACK: |
1550 | case NES_CM_STATE_CLOSING: | 1554 | case NES_CM_STATE_CLOSING: |
1551 | case NES_CM_STATE_UNKNOWN: | 1555 | case NES_CM_STATE_UNKNOWN: |
1552 | case NES_CM_STATE_CLOSED: | ||
1553 | default: | 1556 | default: |
1554 | drop_packet(skb); | 1557 | drop_packet(skb); |
1555 | break; | 1558 | break; |
@@ -1565,7 +1568,7 @@ static void handle_synack_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb, | |||
1565 | int optionsize; | 1568 | int optionsize; |
1566 | 1569 | ||
1567 | optionsize = (tcph->doff << 2) - sizeof(struct tcphdr); | 1570 | optionsize = (tcph->doff << 2) - sizeof(struct tcphdr); |
1568 | skb_pull(skb, tcph->doff << 2); | 1571 | skb_trim(skb, 0); |
1569 | inc_sequence = ntohl(tcph->seq); | 1572 | inc_sequence = ntohl(tcph->seq); |
1570 | switch (cm_node->state) { | 1573 | switch (cm_node->state) { |
1571 | case NES_CM_STATE_SYN_SENT: | 1574 | case NES_CM_STATE_SYN_SENT: |
@@ -1589,6 +1592,12 @@ static void handle_synack_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb, | |||
1589 | /* passive open, so should not be here */ | 1592 | /* passive open, so should not be here */ |
1590 | passive_open_err(cm_node, skb, 1); | 1593 | passive_open_err(cm_node, skb, 1); |
1591 | break; | 1594 | break; |
1595 | case NES_CM_STATE_LISTENING: | ||
1596 | case NES_CM_STATE_CLOSED: | ||
1597 | cm_node->tcp_cntxt.loc_seq_num = ntohl(tcph->ack_seq); | ||
1598 | cleanup_retrans_entry(cm_node); | ||
1599 | send_reset(cm_node, skb); | ||
1600 | break; | ||
1592 | case NES_CM_STATE_ESTABLISHED: | 1601 | case NES_CM_STATE_ESTABLISHED: |
1593 | case NES_CM_STATE_FIN_WAIT1: | 1602 | case NES_CM_STATE_FIN_WAIT1: |
1594 | case NES_CM_STATE_FIN_WAIT2: | 1603 | case NES_CM_STATE_FIN_WAIT2: |
@@ -1596,7 +1605,6 @@ static void handle_synack_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb, | |||
1596 | case NES_CM_STATE_TSA: | 1605 | case NES_CM_STATE_TSA: |
1597 | case NES_CM_STATE_CLOSING: | 1606 | case NES_CM_STATE_CLOSING: |
1598 | case NES_CM_STATE_UNKNOWN: | 1607 | case NES_CM_STATE_UNKNOWN: |
1599 | case NES_CM_STATE_CLOSED: | ||
1600 | case NES_CM_STATE_MPAREQ_SENT: | 1608 | case NES_CM_STATE_MPAREQ_SENT: |
1601 | default: | 1609 | default: |
1602 | drop_packet(skb); | 1610 | drop_packet(skb); |
@@ -1611,6 +1619,13 @@ static void handle_ack_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb, | |||
1611 | u32 inc_sequence; | 1619 | u32 inc_sequence; |
1612 | u32 rem_seq_ack; | 1620 | u32 rem_seq_ack; |
1613 | u32 rem_seq; | 1621 | u32 rem_seq; |
1622 | int ret; | ||
1623 | int optionsize; | ||
1624 | u32 temp_seq = cm_node->tcp_cntxt.loc_seq_num; | ||
1625 | |||
1626 | optionsize = (tcph->doff << 2) - sizeof(struct tcphdr); | ||
1627 | cm_node->tcp_cntxt.loc_seq_num = ntohl(tcph->ack_seq); | ||
1628 | |||
1614 | if (check_seq(cm_node, tcph, skb)) | 1629 | if (check_seq(cm_node, tcph, skb)) |
1615 | return; | 1630 | return; |
1616 | 1631 | ||
@@ -1623,7 +1638,18 @@ static void handle_ack_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb, | |||
1623 | switch (cm_node->state) { | 1638 | switch (cm_node->state) { |
1624 | case NES_CM_STATE_SYN_RCVD: | 1639 | case NES_CM_STATE_SYN_RCVD: |
1625 | /* Passive OPEN */ | 1640 | /* Passive OPEN */ |
1641 | ret = handle_tcp_options(cm_node, tcph, skb, optionsize, 1); | ||
1642 | if (ret) | ||
1643 | break; | ||
1626 | cm_node->tcp_cntxt.rem_ack_num = ntohl(tcph->ack_seq); | 1644 | cm_node->tcp_cntxt.rem_ack_num = ntohl(tcph->ack_seq); |
1645 | cm_node->tcp_cntxt.loc_seq_num = temp_seq; | ||
1646 | if (cm_node->tcp_cntxt.rem_ack_num != | ||
1647 | cm_node->tcp_cntxt.loc_seq_num) { | ||
1648 | nes_debug(NES_DBG_CM, "rem_ack_num != loc_seq_num\n"); | ||
1649 | cleanup_retrans_entry(cm_node); | ||
1650 | send_reset(cm_node, skb); | ||
1651 | return; | ||
1652 | } | ||
1627 | cm_node->state = NES_CM_STATE_ESTABLISHED; | 1653 | cm_node->state = NES_CM_STATE_ESTABLISHED; |
1628 | if (datasize) { | 1654 | if (datasize) { |
1629 | cm_node->tcp_cntxt.rcv_nxt = inc_sequence + datasize; | 1655 | cm_node->tcp_cntxt.rcv_nxt = inc_sequence + datasize; |
@@ -1655,11 +1681,15 @@ static void handle_ack_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb, | |||
1655 | dev_kfree_skb_any(skb); | 1681 | dev_kfree_skb_any(skb); |
1656 | } | 1682 | } |
1657 | break; | 1683 | break; |
1684 | case NES_CM_STATE_LISTENING: | ||
1685 | case NES_CM_STATE_CLOSED: | ||
1686 | cleanup_retrans_entry(cm_node); | ||
1687 | send_reset(cm_node, skb); | ||
1688 | break; | ||
1658 | case NES_CM_STATE_FIN_WAIT1: | 1689 | case NES_CM_STATE_FIN_WAIT1: |
1659 | case NES_CM_STATE_SYN_SENT: | 1690 | case NES_CM_STATE_SYN_SENT: |
1660 | case NES_CM_STATE_FIN_WAIT2: | 1691 | case NES_CM_STATE_FIN_WAIT2: |
1661 | case NES_CM_STATE_TSA: | 1692 | case NES_CM_STATE_TSA: |
1662 | case NES_CM_STATE_CLOSED: | ||
1663 | case NES_CM_STATE_MPAREQ_RCVD: | 1693 | case NES_CM_STATE_MPAREQ_RCVD: |
1664 | case NES_CM_STATE_LAST_ACK: | 1694 | case NES_CM_STATE_LAST_ACK: |
1665 | case NES_CM_STATE_CLOSING: | 1695 | case NES_CM_STATE_CLOSING: |
@@ -1682,9 +1712,9 @@ static int handle_tcp_options(struct nes_cm_node *cm_node, struct tcphdr *tcph, | |||
1682 | nes_debug(NES_DBG_CM, "%s: Node %p, Sending RESET\n", | 1712 | nes_debug(NES_DBG_CM, "%s: Node %p, Sending RESET\n", |
1683 | __func__, cm_node); | 1713 | __func__, cm_node); |
1684 | if (passive) | 1714 | if (passive) |
1685 | passive_open_err(cm_node, skb, 0); | 1715 | passive_open_err(cm_node, skb, 1); |
1686 | else | 1716 | else |
1687 | active_open_err(cm_node, skb, 0); | 1717 | active_open_err(cm_node, skb, 1); |
1688 | return 1; | 1718 | return 1; |
1689 | } | 1719 | } |
1690 | } | 1720 | } |