aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband
diff options
context:
space:
mode:
authorFaisal Latif <faisal.latif@intel.com>2009-04-27 16:41:06 -0400
committerRoland Dreier <rolandd@cisco.com>2009-04-27 16:41:06 -0400
commit109d67e4f12b828113ca8ccf4a735972dd984f40 (patch)
tree44b21f18ea6cb05ec6411b4ec00028152f4f1c5d /drivers/infiniband
parent4e9c390036196f89208cf9574dfd19daae146776 (diff)
RDMA/nes: Fix hang issues for large cluster dynamic connections
Running large cluster setup, we are hanging after many hours of testing. Fixing this required going over the code and making sure the rexmit entry was properly removed based on the cm_node's state and packet received. Also when receiving a FIN packet, check seq# and make sure there were no errors before calling handle_fin(). Following are the changes done in nes_cm.c: * handle_ack_pkt() needs to return error value, so in case of error, handle_fin() is not called. Some cleanup done while going over the code. * handle_rst_pkt(), handling of cm_node's NES_CM_STATE_LAST_ACK is missing. * process_packet(), in case of FIN only packet is received, call check_seq() before processing. * in handle_fin_pkt(), we are calling cleanup_retrans_entry() for all conditions, even if the packets need to be dropped. Signed-off-by: Faisal Latif <faisal.latif@intel.com> Signed-off-by: Roland Dreier <rolandd@cisco.com>
Diffstat (limited to 'drivers/infiniband')
-rw-r--r--drivers/infiniband/hw/nes/nes_cm.c56
1 files changed, 25 insertions, 31 deletions
diff --git a/drivers/infiniband/hw/nes/nes_cm.c b/drivers/infiniband/hw/nes/nes_cm.c
index 4969c386785e..2c90b38daef1 100644
--- a/drivers/infiniband/hw/nes/nes_cm.c
+++ b/drivers/infiniband/hw/nes/nes_cm.c
@@ -1326,18 +1326,20 @@ static void handle_fin_pkt(struct nes_cm_node *cm_node)
1326 nes_debug(NES_DBG_CM, "Received FIN, cm_node = %p, state = %u. " 1326 nes_debug(NES_DBG_CM, "Received FIN, cm_node = %p, state = %u. "
1327 "refcnt=%d\n", cm_node, cm_node->state, 1327 "refcnt=%d\n", cm_node, cm_node->state,
1328 atomic_read(&cm_node->ref_count)); 1328 atomic_read(&cm_node->ref_count));
1329 cm_node->tcp_cntxt.rcv_nxt++;
1330 cleanup_retrans_entry(cm_node);
1331 switch (cm_node->state) { 1329 switch (cm_node->state) {
1332 case NES_CM_STATE_SYN_RCVD: 1330 case NES_CM_STATE_SYN_RCVD:
1333 case NES_CM_STATE_SYN_SENT: 1331 case NES_CM_STATE_SYN_SENT:
1334 case NES_CM_STATE_ESTABLISHED: 1332 case NES_CM_STATE_ESTABLISHED:
1335 case NES_CM_STATE_MPAREQ_SENT: 1333 case NES_CM_STATE_MPAREQ_SENT:
1336 case NES_CM_STATE_MPAREJ_RCVD: 1334 case NES_CM_STATE_MPAREJ_RCVD:
1335 cm_node->tcp_cntxt.rcv_nxt++;
1336 cleanup_retrans_entry(cm_node);
1337 cm_node->state = NES_CM_STATE_LAST_ACK; 1337 cm_node->state = NES_CM_STATE_LAST_ACK;
1338 send_fin(cm_node, NULL); 1338 send_fin(cm_node, NULL);
1339 break; 1339 break;
1340 case NES_CM_STATE_FIN_WAIT1: 1340 case NES_CM_STATE_FIN_WAIT1:
1341 cm_node->tcp_cntxt.rcv_nxt++;
1342 cleanup_retrans_entry(cm_node);
1341 cm_node->state = NES_CM_STATE_CLOSING; 1343 cm_node->state = NES_CM_STATE_CLOSING;
1342 send_ack(cm_node, NULL); 1344 send_ack(cm_node, NULL);
1343 /* Wait for ACK as this is simultanous close.. 1345 /* Wait for ACK as this is simultanous close..
@@ -1345,11 +1347,15 @@ static void handle_fin_pkt(struct nes_cm_node *cm_node)
1345 * Just rm the node.. Done.. */ 1347 * Just rm the node.. Done.. */
1346 break; 1348 break;
1347 case NES_CM_STATE_FIN_WAIT2: 1349 case NES_CM_STATE_FIN_WAIT2:
1350 cm_node->tcp_cntxt.rcv_nxt++;
1351 cleanup_retrans_entry(cm_node);
1348 cm_node->state = NES_CM_STATE_TIME_WAIT; 1352 cm_node->state = NES_CM_STATE_TIME_WAIT;
1349 send_ack(cm_node, NULL); 1353 send_ack(cm_node, NULL);
1350 schedule_nes_timer(cm_node, NULL, NES_TIMER_TYPE_CLOSE, 1, 0); 1354 schedule_nes_timer(cm_node, NULL, NES_TIMER_TYPE_CLOSE, 1, 0);
1351 break; 1355 break;
1352 case NES_CM_STATE_TIME_WAIT: 1356 case NES_CM_STATE_TIME_WAIT:
1357 cm_node->tcp_cntxt.rcv_nxt++;
1358 cleanup_retrans_entry(cm_node);
1353 cm_node->state = NES_CM_STATE_CLOSED; 1359 cm_node->state = NES_CM_STATE_CLOSED;
1354 rem_ref_cm_node(cm_node->cm_core, cm_node); 1360 rem_ref_cm_node(cm_node->cm_core, cm_node);
1355 break; 1361 break;
@@ -1385,7 +1391,6 @@ static void handle_rst_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb,
1385 passive_state = atomic_add_return(1, &cm_node->passive_state); 1391 passive_state = atomic_add_return(1, &cm_node->passive_state);
1386 if (passive_state == NES_SEND_RESET_EVENT) 1392 if (passive_state == NES_SEND_RESET_EVENT)
1387 create_event(cm_node, NES_CM_EVENT_RESET); 1393 create_event(cm_node, NES_CM_EVENT_RESET);
1388 cleanup_retrans_entry(cm_node);
1389 cm_node->state = NES_CM_STATE_CLOSED; 1394 cm_node->state = NES_CM_STATE_CLOSED;
1390 dev_kfree_skb_any(skb); 1395 dev_kfree_skb_any(skb);
1391 break; 1396 break;
@@ -1399,17 +1404,16 @@ static void handle_rst_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb,
1399 active_open_err(cm_node, skb, reset); 1404 active_open_err(cm_node, skb, reset);
1400 break; 1405 break;
1401 case NES_CM_STATE_CLOSED: 1406 case NES_CM_STATE_CLOSED:
1402 cleanup_retrans_entry(cm_node);
1403 drop_packet(skb); 1407 drop_packet(skb);
1404 break; 1408 break;
1409 case NES_CM_STATE_LAST_ACK:
1410 cm_node->cm_id->rem_ref(cm_node->cm_id);
1405 case NES_CM_STATE_TIME_WAIT: 1411 case NES_CM_STATE_TIME_WAIT:
1406 cleanup_retrans_entry(cm_node);
1407 cm_node->state = NES_CM_STATE_CLOSED; 1412 cm_node->state = NES_CM_STATE_CLOSED;
1408 rem_ref_cm_node(cm_node->cm_core, cm_node); 1413 rem_ref_cm_node(cm_node->cm_core, cm_node);
1409 drop_packet(skb); 1414 drop_packet(skb);
1410 break; 1415 break;
1411 case NES_CM_STATE_FIN_WAIT1: 1416 case NES_CM_STATE_FIN_WAIT1:
1412 cleanup_retrans_entry(cm_node);
1413 nes_debug(NES_DBG_CM, "Bad state %s[%u]\n", __func__, __LINE__); 1417 nes_debug(NES_DBG_CM, "Bad state %s[%u]\n", __func__, __LINE__);
1414 default: 1418 default:
1415 drop_packet(skb); 1419 drop_packet(skb);
@@ -1456,6 +1460,7 @@ static void handle_rcv_mpa(struct nes_cm_node *cm_node, struct sk_buff *skb)
1456 NES_PASSIVE_STATE_INDICATED); 1460 NES_PASSIVE_STATE_INDICATED);
1457 break; 1461 break;
1458 case NES_CM_STATE_MPAREQ_SENT: 1462 case NES_CM_STATE_MPAREQ_SENT:
1463 cleanup_retrans_entry(cm_node);
1459 if (res_type == NES_MPA_REQUEST_REJECT) { 1464 if (res_type == NES_MPA_REQUEST_REJECT) {
1460 type = NES_CM_EVENT_MPA_REJECT; 1465 type = NES_CM_EVENT_MPA_REJECT;
1461 cm_node->state = NES_CM_STATE_MPAREJ_RCVD; 1466 cm_node->state = NES_CM_STATE_MPAREJ_RCVD;
@@ -1653,49 +1658,39 @@ static void handle_synack_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb,
1653 } 1658 }
1654} 1659}
1655 1660
1656static void handle_ack_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb, 1661static int handle_ack_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb,
1657 struct tcphdr *tcph) 1662 struct tcphdr *tcph)
1658{ 1663{
1659 int datasize = 0; 1664 int datasize = 0;
1660 u32 inc_sequence; 1665 u32 inc_sequence;
1661 u32 rem_seq_ack; 1666 u32 rem_seq_ack;
1662 u32 rem_seq; 1667 u32 rem_seq;
1663 int ret; 1668 int ret = 0;
1664 int optionsize; 1669 int optionsize;
1665 optionsize = (tcph->doff << 2) - sizeof(struct tcphdr); 1670 optionsize = (tcph->doff << 2) - sizeof(struct tcphdr);
1666 1671
1667 if (check_seq(cm_node, tcph, skb)) 1672 if (check_seq(cm_node, tcph, skb))
1668 return; 1673 return -EINVAL;
1669 1674
1670 skb_pull(skb, tcph->doff << 2); 1675 skb_pull(skb, tcph->doff << 2);
1671 inc_sequence = ntohl(tcph->seq); 1676 inc_sequence = ntohl(tcph->seq);
1672 rem_seq = ntohl(tcph->seq); 1677 rem_seq = ntohl(tcph->seq);
1673 rem_seq_ack = ntohl(tcph->ack_seq); 1678 rem_seq_ack = ntohl(tcph->ack_seq);
1674 datasize = skb->len; 1679 datasize = skb->len;
1675 cleanup_retrans_entry(cm_node);
1676 switch (cm_node->state) { 1680 switch (cm_node->state) {
1677 case NES_CM_STATE_SYN_RCVD: 1681 case NES_CM_STATE_SYN_RCVD:
1678 /* Passive OPEN */ 1682 /* Passive OPEN */
1683 cleanup_retrans_entry(cm_node);
1679 ret = handle_tcp_options(cm_node, tcph, skb, optionsize, 1); 1684 ret = handle_tcp_options(cm_node, tcph, skb, optionsize, 1);
1680 if (ret) 1685 if (ret)
1681 break; 1686 break;
1682 cm_node->tcp_cntxt.rem_ack_num = ntohl(tcph->ack_seq); 1687 cm_node->tcp_cntxt.rem_ack_num = ntohl(tcph->ack_seq);
1683 if (cm_node->tcp_cntxt.rem_ack_num !=
1684 cm_node->tcp_cntxt.loc_seq_num) {
1685 nes_debug(NES_DBG_CM, "rem_ack_num != loc_seq_num\n");
1686 cleanup_retrans_entry(cm_node);
1687 send_reset(cm_node, skb);
1688 return;
1689 }
1690 cm_node->state = NES_CM_STATE_ESTABLISHED; 1688 cm_node->state = NES_CM_STATE_ESTABLISHED;
1691 cleanup_retrans_entry(cm_node);
1692 if (datasize) { 1689 if (datasize) {
1693 cm_node->tcp_cntxt.rcv_nxt = inc_sequence + datasize; 1690 cm_node->tcp_cntxt.rcv_nxt = inc_sequence + datasize;
1694 handle_rcv_mpa(cm_node, skb); 1691 handle_rcv_mpa(cm_node, skb);
1695 } else { /* rcvd ACK only */ 1692 } else /* rcvd ACK only */
1696 dev_kfree_skb_any(skb); 1693 dev_kfree_skb_any(skb);
1697 cleanup_retrans_entry(cm_node);
1698 }
1699 break; 1694 break;
1700 case NES_CM_STATE_ESTABLISHED: 1695 case NES_CM_STATE_ESTABLISHED:
1701 /* Passive OPEN */ 1696 /* Passive OPEN */
@@ -1707,15 +1702,12 @@ static void handle_ack_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb,
1707 drop_packet(skb); 1702 drop_packet(skb);
1708 break; 1703 break;
1709 case NES_CM_STATE_MPAREQ_SENT: 1704 case NES_CM_STATE_MPAREQ_SENT:
1710 cleanup_retrans_entry(cm_node);
1711 cm_node->tcp_cntxt.rem_ack_num = ntohl(tcph->ack_seq); 1705 cm_node->tcp_cntxt.rem_ack_num = ntohl(tcph->ack_seq);
1712 if (datasize) { 1706 if (datasize) {
1713 cm_node->tcp_cntxt.rcv_nxt = inc_sequence + datasize; 1707 cm_node->tcp_cntxt.rcv_nxt = inc_sequence + datasize;
1714 handle_rcv_mpa(cm_node, skb); 1708 handle_rcv_mpa(cm_node, skb);
1715 } else { /* Could be just an ack pkt.. */ 1709 } else /* Could be just an ack pkt.. */
1716 cleanup_retrans_entry(cm_node);
1717 dev_kfree_skb_any(skb); 1710 dev_kfree_skb_any(skb);
1718 }
1719 break; 1711 break;
1720 case NES_CM_STATE_LISTENING: 1712 case NES_CM_STATE_LISTENING:
1721 case NES_CM_STATE_CLOSED: 1713 case NES_CM_STATE_CLOSED:
@@ -1723,11 +1715,10 @@ static void handle_ack_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb,
1723 send_reset(cm_node, skb); 1715 send_reset(cm_node, skb);
1724 break; 1716 break;
1725 case NES_CM_STATE_LAST_ACK: 1717 case NES_CM_STATE_LAST_ACK:
1718 case NES_CM_STATE_CLOSING:
1726 cleanup_retrans_entry(cm_node); 1719 cleanup_retrans_entry(cm_node);
1727 cm_node->state = NES_CM_STATE_CLOSED; 1720 cm_node->state = NES_CM_STATE_CLOSED;
1728 cm_node->cm_id->rem_ref(cm_node->cm_id); 1721 cm_node->cm_id->rem_ref(cm_node->cm_id);
1729 case NES_CM_STATE_CLOSING:
1730 cleanup_retrans_entry(cm_node);
1731 rem_ref_cm_node(cm_node->cm_core, cm_node); 1722 rem_ref_cm_node(cm_node->cm_core, cm_node);
1732 drop_packet(skb); 1723 drop_packet(skb);
1733 break; 1724 break;
@@ -1742,9 +1733,11 @@ static void handle_ack_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb,
1742 case NES_CM_STATE_MPAREQ_RCVD: 1733 case NES_CM_STATE_MPAREQ_RCVD:
1743 case NES_CM_STATE_UNKNOWN: 1734 case NES_CM_STATE_UNKNOWN:
1744 default: 1735 default:
1736 cleanup_retrans_entry(cm_node);
1745 drop_packet(skb); 1737 drop_packet(skb);
1746 break; 1738 break;
1747 } 1739 }
1740 return ret;
1748} 1741}
1749 1742
1750 1743
@@ -1850,6 +1843,7 @@ static void process_packet(struct nes_cm_node *cm_node, struct sk_buff *skb,
1850 enum nes_tcpip_pkt_type pkt_type = NES_PKT_TYPE_UNKNOWN; 1843 enum nes_tcpip_pkt_type pkt_type = NES_PKT_TYPE_UNKNOWN;
1851 struct tcphdr *tcph = tcp_hdr(skb); 1844 struct tcphdr *tcph = tcp_hdr(skb);
1852 u32 fin_set = 0; 1845 u32 fin_set = 0;
1846 int ret = 0;
1853 skb_pull(skb, ip_hdr(skb)->ihl << 2); 1847 skb_pull(skb, ip_hdr(skb)->ihl << 2);
1854 1848
1855 nes_debug(NES_DBG_CM, "process_packet: cm_node=%p state =%d syn=%d " 1849 nes_debug(NES_DBG_CM, "process_packet: cm_node=%p state =%d syn=%d "
@@ -1875,17 +1869,17 @@ static void process_packet(struct nes_cm_node *cm_node, struct sk_buff *skb,
1875 handle_synack_pkt(cm_node, skb, tcph); 1869 handle_synack_pkt(cm_node, skb, tcph);
1876 break; 1870 break;
1877 case NES_PKT_TYPE_ACK: 1871 case NES_PKT_TYPE_ACK:
1878 handle_ack_pkt(cm_node, skb, tcph); 1872 ret = handle_ack_pkt(cm_node, skb, tcph);
1879 if (fin_set) 1873 if (fin_set && !ret)
1880 handle_fin_pkt(cm_node); 1874 handle_fin_pkt(cm_node);
1881 break; 1875 break;
1882 case NES_PKT_TYPE_RST: 1876 case NES_PKT_TYPE_RST:
1883 handle_rst_pkt(cm_node, skb, tcph); 1877 handle_rst_pkt(cm_node, skb, tcph);
1884 break; 1878 break;
1885 default: 1879 default:
1886 drop_packet(skb); 1880 if ((fin_set) && (!check_seq(cm_node, tcph, skb)))
1887 if (fin_set)
1888 handle_fin_pkt(cm_node); 1881 handle_fin_pkt(cm_node);
1882 drop_packet(skb);
1889 break; 1883 break;
1890 } 1884 }
1891} 1885}