1560 |
1560 |
1561 if (user_param->r_flag->unsorted) { |
1561 if (user_param->r_flag->unsorted) { |
1562 diff -r -u /tmp/perftest-1.3.0/send_bw.c perftest-1.3.0/send_bw.c |
1562 diff -r -u /tmp/perftest-1.3.0/send_bw.c perftest-1.3.0/send_bw.c |
1563 --- /tmp/perftest-1.3.0/send_bw.c Thu Jan 20 07:37:18 2011 |
1563 --- /tmp/perftest-1.3.0/send_bw.c Thu Jan 20 07:37:18 2011 |
1564 +++ perftest-1.3.0/send_bw.c Fri Feb 11 04:12:47 2011 |
1564 +++ perftest-1.3.0/send_bw.c Fri Feb 11 04:12:47 2011 |
1565 @@ -1,1162 +1,1166 @@ |
1565 @@ -320,7 +320,7 @@ |
1566 -/* |
1566 user_parm->size = MTU_SIZE(user_parm->curr_mtu); |
1567 - * Copyright (c) 2005 Topspin Communications. All rights reserved. |
1567 } |
1568 - * Copyright (c) 2005 Mellanox Technologies Ltd. All rights reserved. |
1568 |
1569 - * Copyright (c) 2009 HNR Consulting. All rights reserved. |
|
1570 - * |
|
1571 - * This software is available to you under a choice of one of two |
|
1572 - * licenses. You may choose to be licensed under the terms of the GNU |
|
1573 - * General Public License (GPL) Version 2, available from the file |
|
1574 - * COPYING in the main directory of this source tree, or the |
|
1575 - * OpenIB.org BSD license below: |
|
1576 - * |
|
1577 - * Redistribution and use in source and binary forms, with or |
|
1578 - * without modification, are permitted provided that the following |
|
1579 - * conditions are met: |
|
1580 - * |
|
1581 - * - Redistributions of source code must retain the above |
|
1582 - * copyright notice, this list of conditions and the following |
|
1583 - * disclaimer. |
|
1584 - * |
|
1585 - * - Redistributions in binary form must reproduce the above |
|
1586 - * copyright notice, this list of conditions and the following |
|
1587 - * disclaimer in the documentation and/or other materials |
|
1588 - * provided with the distribution. |
|
1589 - * |
|
1590 - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
|
1591 - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
|
1592 - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
|
1593 - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS |
|
1594 - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN |
|
1595 - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
|
1596 - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
|
1597 - * SOFTWARE. |
|
1598 - * |
|
1599 - * $Id$ |
|
1600 - */ |
|
1601 - |
|
1602 -#if HAVE_CONFIG_H |
|
1603 -# include <config.h> |
|
1604 -#endif /* HAVE_CONFIG_H */ |
|
1605 - |
|
1606 -#include <stdio.h> |
|
1607 -#include <stdlib.h> |
|
1608 -#include <unistd.h> |
|
1609 -#include <string.h> |
|
1610 -#include <limits.h> |
|
1611 -#include <malloc.h> |
|
1612 -#include <getopt.h> |
|
1613 -#include <time.h> |
|
1614 -#include <errno.h> |
|
1615 -#include <infiniband/verbs.h> |
|
1616 - |
|
1617 -#include "get_clock.h" |
|
1618 -#include "multicast_resources.h" |
|
1619 -#include "perftest_resources.h" |
|
1620 - |
|
1621 -#define VERSION 2.1 |
|
1622 - |
|
1623 -static int page_size; |
|
1624 -cycles_t *tposted; |
|
1625 -cycles_t *tcompleted; |
|
1626 - |
|
1627 -struct pingpong_context { |
|
1628 - struct ibv_context *context; |
|
1629 - struct ibv_comp_channel *channel; |
|
1630 - struct ibv_pd *pd; |
|
1631 - struct ibv_mr **mr; |
|
1632 - struct ibv_cq *cq; |
|
1633 - struct ibv_qp **qp; |
|
1634 - struct ibv_sge list; |
|
1635 - struct ibv_send_wr wr; |
|
1636 - struct ibv_sge *sge_list; |
|
1637 - struct ibv_recv_wr *rwr; |
|
1638 - struct ibv_ah *ah; |
|
1639 - void **buf; |
|
1640 - unsigned size; |
|
1641 - uint64_t *my_addr; |
|
1642 -}; |
|
1643 - |
|
1644 -/****************************************************************************** |
|
1645 - * |
|
1646 - ******************************************************************************/ |
|
1647 -static int set_mcast_group(struct pingpong_context *ctx, |
|
1648 - struct perftest_parameters *user_parm, |
|
1649 - struct mcast_parameters *mcg_params) { |
|
1650 - |
|
1651 - struct ibv_port_attr port_attr; |
|
1652 - |
|
1653 - if (ibv_query_gid(ctx->context,user_parm->ib_port,user_parm->gid_index,&mcg_params->port_gid)) { |
|
1654 - return 1; |
|
1655 - } |
|
1656 - |
|
1657 - if (ibv_query_pkey(ctx->context,user_parm->ib_port,DEF_PKEY_IDX,&mcg_params->pkey)) { |
|
1658 - return 1; |
|
1659 - } |
|
1660 - |
|
1661 - if (ibv_query_port(ctx->context,user_parm->ib_port,&port_attr)) { |
|
1662 - return 1; |
|
1663 - } |
|
1664 - mcg_params->sm_lid = port_attr.sm_lid; |
|
1665 - mcg_params->sm_sl = port_attr.sm_sl; |
|
1666 - mcg_params->ib_port = user_parm->ib_port; |
|
1667 - |
|
1668 - if (!strcmp(link_layer_str(user_parm->link_type),"IB")) { |
|
1669 - // Request for Mcast group create registery in SM. |
|
1670 - if (join_multicast_group(SUBN_ADM_METHOD_SET,mcg_params)) { |
|
1671 - fprintf(stderr,"Couldn't Register the Mcast group on the SM\n"); |
|
1672 - return 1; |
|
1673 - } |
|
1674 - } |
|
1675 - return 0; |
|
1676 -} |
|
1677 - |
|
1678 -/****************************************************************************** |
|
1679 - * |
|
1680 - ******************************************************************************/ |
|
1681 -static int set_up_connection(struct pingpong_context *ctx, |
|
1682 - struct perftest_parameters *user_parm, |
|
1683 - struct pingpong_dest *my_dest, |
|
1684 - struct mcast_parameters *mcg_params) { |
|
1685 - |
|
1686 - int i = (user_parm->duplex) ? 1 : 0; |
|
1687 - |
|
1688 - if (user_parm->use_mcg && (user_parm->duplex || user_parm->machine == SERVER)) { |
|
1689 - |
|
1690 - set_multicast_gid(mcg_params,ctx->qp[0]->qp_num,(int)user_parm->machine); |
|
1691 - if (set_mcast_group(ctx,user_parm,mcg_params)) { |
|
1692 - return 1; |
|
1693 - } |
|
1694 - |
|
1695 - while (i < user_parm->num_of_qps) { |
|
1696 - if (ibv_attach_mcast(ctx->qp[i],&mcg_params->mgid,mcg_params->mlid)) { |
|
1697 - fprintf(stderr, "Couldn't attach QP to MultiCast group"); |
|
1698 - return 1; |
|
1699 - } |
|
1700 - i++; |
|
1701 - } |
|
1702 - |
|
1703 - mcg_params->mcast_state |= MCAST_IS_ATTACHED; |
|
1704 - my_dest->gid = mcg_params->mgid; |
|
1705 - my_dest->lid = mcg_params->mlid; |
|
1706 - my_dest->qpn = QPNUM_MCAST; |
|
1707 - |
|
1708 - } else { |
|
1709 - if (user_parm->gid_index != -1) { |
|
1710 - if (ibv_query_gid(ctx->context,user_parm->ib_port,user_parm->gid_index,&my_dest->gid)) { |
|
1711 - return -1; |
|
1712 - } |
|
1713 - } |
|
1714 - my_dest->lid = ctx_get_local_lid(ctx->context,user_parm->ib_port); |
|
1715 - my_dest->qpn = ctx->qp[0]->qp_num; |
|
1716 - } |
|
1717 - my_dest->psn = lrand48() & 0xffffff; |
|
1718 - |
|
1719 - // We do not fail test upon lid above RoCE. |
|
1720 - |
|
1721 - if (user_parm->gid_index < 0) { |
|
1722 - if (!my_dest->lid) { |
|
1723 - fprintf(stderr," Local lid 0x0 detected,without any use of gid. Is SM running?\n"); |
|
1724 - return -1; |
|
1725 - } |
|
1726 - } |
|
1727 - return 0; |
|
1728 -} |
|
1729 - |
|
1730 -/****************************************************************************** |
|
1731 - * |
|
1732 - ******************************************************************************/ |
|
1733 -static int init_connection(struct perftest_parameters *params, |
|
1734 - struct pingpong_dest *my_dest) { |
|
1735 - |
|
1736 - params->side = LOCAL; |
|
1737 - ctx_print_pingpong_data(my_dest,params); |
|
1738 - |
|
1739 - if (params->machine == CLIENT) |
|
1740 - params->sockfd = ctx_client_connect(params->servername,params->port); |
|
1741 - else |
|
1742 - params->sockfd = ctx_server_connect(params->port); |
|
1743 - |
|
1744 - |
|
1745 - if(params->sockfd < 0) { |
|
1746 - fprintf(stderr,"Unable to open file descriptor for socket connection"); |
|
1747 - return 1; |
|
1748 - } |
|
1749 - return 0; |
|
1750 -} |
|
1751 - |
|
1752 -/****************************************************************************** |
|
1753 - * |
|
1754 - ******************************************************************************/ |
|
1755 -static int destroy_ctx_resources(struct pingpong_context *ctx, |
|
1756 - struct perftest_parameters *user_parm, |
|
1757 - struct pingpong_dest *my_dest, |
|
1758 - struct pingpong_dest *rem_dest, |
|
1759 - struct mcast_parameters *mcg_params) { |
|
1760 - |
|
1761 - int test_result = 0; |
|
1762 - int i = (user_parm->duplex) ? 1 : 0; |
|
1763 - |
|
1764 - if (user_parm->use_mcg) { |
|
1765 - |
|
1766 - if (user_parm->machine == SERVER || user_parm->duplex) { |
|
1767 - |
|
1768 - while (i < user_parm->num_of_qps) { |
|
1769 - if (ibv_detach_mcast(ctx->qp[i],&my_dest->gid,my_dest->lid)) { |
|
1770 - fprintf(stderr, "Couldn't deattach QP from MultiCast group\n"); |
|
1771 - return 1; |
|
1772 - } |
|
1773 - i++; |
|
1774 - } |
|
1775 - mcg_params->mgid = my_dest->gid; |
|
1776 - if (!strcmp(link_layer_str(user_parm->link_type),"IB")) { |
|
1777 - if (join_multicast_group(SUBN_ADM_METHOD_DELETE,mcg_params)) { |
|
1778 - fprintf(stderr,"Couldn't Unregister the Mcast group on the SM\n"); |
|
1779 - return 1; |
|
1780 - } |
|
1781 - } |
|
1782 - } |
|
1783 - |
|
1784 - if (user_parm->machine == CLIENT || user_parm->duplex) { |
|
1785 - |
|
1786 - mcg_params->mgid = rem_dest->gid; |
|
1787 - if (!strcmp(link_layer_str(user_parm->link_type),"IB")) { |
|
1788 - if (join_multicast_group(SUBN_ADM_METHOD_DELETE,mcg_params)) { |
|
1789 - fprintf(stderr,"Couldn't Unregister the Mcast group on the SM\n"); |
|
1790 - return 1; |
|
1791 - } |
|
1792 - } |
|
1793 - |
|
1794 - } |
|
1795 - } |
|
1796 - |
|
1797 - if (ctx->ah) { |
|
1798 - if (ibv_destroy_ah(ctx->ah)) { |
|
1799 - fprintf(stderr, "failed to destroy AH\n"); |
|
1800 - test_result = 1; |
|
1801 - } |
|
1802 - } |
|
1803 - |
|
1804 - for(i = 0; i < user_parm->num_of_qps; i++) { |
|
1805 - if (ibv_destroy_qp(ctx->qp[i])) { |
|
1806 - test_result = 1; |
|
1807 - } |
|
1808 - } |
|
1809 - free(ctx->qp); |
|
1810 - |
|
1811 - if (ibv_destroy_cq(ctx->cq)) { |
|
1812 - test_result = 1; |
|
1813 - } |
|
1814 - |
|
1815 - for(i = 0; i < user_parm->num_of_qps; i++) { |
|
1816 - |
|
1817 - if (ibv_dereg_mr(ctx->mr[i])) { |
|
1818 - test_result = 1; |
|
1819 - } |
|
1820 - free(ctx->buf[i]); |
|
1821 - } |
|
1822 - |
|
1823 - if (ibv_dealloc_pd(ctx->pd)) { |
|
1824 - test_result = 1; |
|
1825 - } |
|
1826 - |
|
1827 - if (ctx->channel) { |
|
1828 - if (ibv_destroy_comp_channel(ctx->channel)) { |
|
1829 - test_result = 1; |
|
1830 - } |
|
1831 - } |
|
1832 - |
|
1833 - if (ibv_close_device(ctx->context)) { |
|
1834 - test_result = 1; |
|
1835 - } |
|
1836 - |
|
1837 - if (user_parm->machine == SERVER || user_parm->duplex) { |
|
1838 - free(ctx->rwr); |
|
1839 - free(ctx->sge_list); |
|
1840 - free(ctx->my_addr); |
|
1841 - } |
|
1842 - |
|
1843 - free(ctx->mr); |
|
1844 - free(ctx->buf); |
|
1845 - free(ctx); |
|
1846 - free(tposted); |
|
1847 - free(tcompleted); |
|
1848 - return test_result; |
|
1849 -} |
|
1850 - |
|
1851 -/****************************************************************************** |
|
1852 - * |
|
1853 - ******************************************************************************/ |
|
1854 -static struct pingpong_context *pp_init_ctx(struct ibv_device *ib_dev, |
|
1855 - struct perftest_parameters *user_parm) { |
|
1856 - |
|
1857 - int i,m_size; |
|
1858 - int duplex_ind; |
|
1859 - struct pingpong_context *ctx; |
|
1860 - |
|
1861 - ALLOCATE(ctx,struct pingpong_context,1); |
|
1862 - ALLOCATE(ctx->buf,void*,user_parm->num_of_qps); |
|
1863 - ALLOCATE(ctx->mr,struct ibv_mr*,user_parm->num_of_qps); |
|
1864 - |
|
1865 - ctx->ah = NULL; |
|
1866 - ctx->channel = NULL; |
|
1867 - |
|
1868 - duplex_ind = (user_parm->duplex && !user_parm->use_mcg) ? 2 : 1; |
|
1869 - |
|
1870 - ctx->context = ibv_open_device(ib_dev); |
|
1871 - if (!ctx->context) { |
|
1872 - fprintf(stderr, "Couldn't get context for %s\n", |
|
1873 - ibv_get_device_name(ib_dev)); |
|
1874 - return NULL; |
|
1875 - } |
|
1876 - |
|
1877 - // Configure the Link MTU acoording to the user or the active mtu. |
|
1878 - if (ctx_set_mtu(ctx->context,user_parm)) { |
|
1879 - fprintf(stderr, "Couldn't set the link layer\n"); |
|
1880 - return NULL; |
|
1881 - } |
|
1882 - |
|
1883 - if (user_parm->connection_type == UD && user_parm->size > MTU_SIZE(user_parm->curr_mtu)) { |
|
1884 - printf(" Max msg size in UD is MTU - %d . changing to MTU\n",MTU_SIZE(user_parm->curr_mtu)); |
|
1885 - user_parm->size = MTU_SIZE(user_parm->curr_mtu); |
|
1886 - } |
|
1887 - |
|
1888 - if (is_dev_hermon(ctx->context) != NOT_HERMON && user_parm->inline_size != 0) |
1569 - if (is_dev_hermon(ctx->context) != NOT_HERMON && user_parm->inline_size != 0) |
1889 - user_parm->inline_size = 0; |
|
1890 - |
|
1891 - printf(" Inline data is used up to %d bytes message\n", user_parm->inline_size); |
|
1892 - |
|
1893 - ctx->size = user_parm->size; |
|
1894 - |
|
1895 - // Finds the link type and configure the HCA accordingly. |
|
1896 - if (ctx_set_link_layer(ctx->context,user_parm)) { |
|
1897 - fprintf(stderr, " Couldn't set the link layer\n"); |
|
1898 - return NULL; |
|
1899 - } |
|
1900 - |
|
1901 - if (user_parm->use_event) { |
|
1902 - ctx->channel = ibv_create_comp_channel(ctx->context); |
|
1903 - if (!ctx->channel) { |
|
1904 - fprintf(stderr, "Couldn't create completion channel\n"); |
|
1905 - return NULL; |
|
1906 - } |
|
1907 - } else |
|
1908 - ctx->channel = NULL; |
|
1909 - |
|
1910 - ctx->pd = ibv_alloc_pd(ctx->context); |
|
1911 - if (!ctx->pd) { |
|
1912 - fprintf(stderr, "Couldn't allocate PD\n"); |
|
1913 - return NULL; |
|
1914 - } |
|
1915 - |
|
1916 - for (i = 0; i < user_parm->num_of_qps; i++) { |
|
1917 - |
|
1918 - m_size = (BUFF_SIZE(user_parm->size) + IF_UD_ADD(user_parm->connection_type))*duplex_ind; |
|
1919 - ctx->buf[i] = memalign(page_size,m_size); |
|
1920 - if (!ctx->buf[i]) { |
|
1921 - fprintf(stderr, "Couldn't allocate work buf.\n"); |
|
1922 - return NULL; |
|
1923 - } |
|
1924 - memset(ctx->buf[i],0,m_size); |
|
1925 - |
|
1926 - // We dont really want IBV_ACCESS_LOCAL_WRITE, but IB spec says : |
|
1927 - // The Consumer is not allowed to assign Remote Write or Remote Atomic to |
|
1928 - // a Memory Region that has not been assigned Local Write. |
|
1929 - ctx->mr[i] = ibv_reg_mr(ctx->pd, |
|
1930 - ctx->buf[i], |
|
1931 - m_size, |
|
1932 - IBV_ACCESS_REMOTE_WRITE | |
|
1933 - IBV_ACCESS_LOCAL_WRITE); |
|
1934 - |
|
1935 - if (!ctx->mr[i]) { |
|
1936 - fprintf(stderr, "Couldn't allocate MR\n"); |
|
1937 - return NULL; |
|
1938 - } |
|
1939 - } |
|
1940 - |
|
1941 - // Create the CQ according to Client/Server or Duplex setting. |
|
1942 - ctx->cq = ctx_cq_create(ctx->context,ctx->channel,user_parm); |
|
1943 - if (ctx->cq == NULL) { |
|
1944 - fprintf(stderr, "Couldn't create CQ \n"); |
|
1945 - return NULL; |
|
1946 - } |
|
1947 - |
|
1948 - ALLOCATE(ctx->qp,struct ibv_qp*,user_parm->num_of_qps); |
|
1949 - |
|
1950 - for(i=0; i < user_parm->num_of_qps; i++) { |
|
1951 - ctx->qp[i] = ctx_qp_create(ctx->pd,ctx->cq,ctx->cq,user_parm); |
|
1952 - if (ctx->qp[i] == NULL) { |
|
1953 - return NULL; |
|
1954 - } |
|
1955 - |
|
1956 - if(ctx_modify_qp_to_init(ctx->qp[i],user_parm)) { |
|
1957 - return NULL; |
|
1958 - } |
|
1959 - } |
|
1960 - |
|
1961 - return ctx; |
|
1962 -} |
|
1963 - |
|
1964 -/****************************************************************************** |
|
1965 - * |
|
1966 - ******************************************************************************/ |
|
1967 -static int pp_connect_ctx(struct pingpong_context *ctx,int my_psn, |
|
1968 - struct pingpong_dest *dest, |
|
1969 - struct perftest_parameters *user_parm) |
|
1970 -{ |
|
1971 - struct ibv_qp_attr attr; |
|
1972 - memset(&attr, 0, sizeof attr); |
|
1973 - int i; |
|
1974 - |
|
1975 - attr.qp_state = IBV_QPS_RTR; |
|
1976 - attr.path_mtu = user_parm->curr_mtu; |
|
1977 - attr.dest_qp_num = dest->qpn; |
|
1978 - attr.rq_psn = dest->psn; |
|
1979 - attr.ah_attr.dlid = dest->lid; |
|
1980 - if (user_parm->connection_type == RC) { |
|
1981 - attr.max_dest_rd_atomic = 1; |
|
1982 - attr.min_rnr_timer = 12; |
|
1983 - } |
|
1984 - if (user_parm->gid_index < 0) { |
|
1985 - attr.ah_attr.is_global = 0; |
|
1986 - attr.ah_attr.sl = user_parm->sl; |
|
1987 - } else { |
|
1988 - attr.ah_attr.is_global = 1; |
|
1989 - attr.ah_attr.grh.dgid = dest->gid; |
|
1990 - attr.ah_attr.grh.sgid_index = user_parm->gid_index; |
|
1991 - attr.ah_attr.grh.hop_limit = 1; |
|
1992 - attr.ah_attr.sl = 0; |
|
1993 - } |
|
1994 - attr.ah_attr.src_path_bits = 0; |
|
1995 - attr.ah_attr.port_num = user_parm->ib_port; |
|
1996 - |
|
1997 - if (user_parm->connection_type == RC) { |
|
1998 - if (ibv_modify_qp(ctx->qp[0], &attr, |
|
1999 - IBV_QP_STATE | |
|
2000 - IBV_QP_AV | |
|
2001 - IBV_QP_PATH_MTU | |
|
2002 - IBV_QP_DEST_QPN | |
|
2003 - IBV_QP_RQ_PSN | |
|
2004 - IBV_QP_MIN_RNR_TIMER | |
|
2005 - IBV_QP_MAX_DEST_RD_ATOMIC)) { |
|
2006 - fprintf(stderr, "Failed to modify RC QP to RTR\n"); |
|
2007 - return 1; |
|
2008 - } |
|
2009 - attr.timeout = user_parm->qp_timeout; |
|
2010 - attr.retry_cnt = 7; |
|
2011 - attr.rnr_retry = 7; |
|
2012 - } else if (user_parm->connection_type == UC) { |
|
2013 - if (ibv_modify_qp(ctx->qp[0], &attr, |
|
2014 - IBV_QP_STATE | |
|
2015 - IBV_QP_AV | |
|
2016 - IBV_QP_PATH_MTU | |
|
2017 - IBV_QP_DEST_QPN | |
|
2018 - IBV_QP_RQ_PSN)) { |
|
2019 - fprintf(stderr, "Failed to modify UC QP to RTR\n"); |
|
2020 - return 1; |
|
2021 - } |
|
2022 - } |
|
2023 - |
|
2024 - else { |
|
2025 - for (i = 0; i < user_parm->num_of_qps; i++) { |
|
2026 - if (ibv_modify_qp(ctx->qp[i],&attr,IBV_QP_STATE )) { |
|
2027 - fprintf(stderr, "Failed to modify UD QP to RTR\n"); |
|
2028 - return 1; |
|
2029 - } |
|
2030 - } |
|
2031 - if (user_parm->machine == CLIENT || user_parm->duplex) { |
|
2032 - ctx->ah = ibv_create_ah(ctx->pd,&attr.ah_attr); |
|
2033 - if (!ctx->ah) { |
|
2034 - fprintf(stderr, "Failed to create AH for UD\n"); |
|
2035 - return 1; |
|
2036 - } |
|
2037 - } |
|
2038 - } |
|
2039 - |
|
2040 - if (user_parm->machine == CLIENT || user_parm->duplex) { |
|
2041 - |
|
2042 - attr.qp_state = IBV_QPS_RTS; |
|
2043 - attr.sq_psn = my_psn; |
|
2044 - if (user_parm->connection_type == RC) { |
|
2045 - attr.max_rd_atomic = 1; |
|
2046 - if (ibv_modify_qp(ctx->qp[0], &attr, |
|
2047 - IBV_QP_STATE | |
|
2048 - IBV_QP_SQ_PSN | |
|
2049 - IBV_QP_TIMEOUT | |
|
2050 - IBV_QP_RETRY_CNT | |
|
2051 - IBV_QP_RNR_RETRY | |
|
2052 - IBV_QP_MAX_QP_RD_ATOMIC)) { |
|
2053 - fprintf(stderr, "Failed to modify RC QP to RTS\n"); |
|
2054 - return 1; |
|
2055 - } |
|
2056 - |
|
2057 - } else { |
|
2058 - if(ibv_modify_qp(ctx->qp[0],&attr,IBV_QP_STATE |IBV_QP_SQ_PSN)) { |
|
2059 - fprintf(stderr, "Failed to modify UC QP to RTS\n"); |
|
2060 - return 1; |
|
2061 - } |
|
2062 - } |
|
2063 - } |
|
2064 - |
|
2065 - return 0; |
|
2066 -} |
|
2067 - |
|
2068 -/****************************************************************************** |
|
2069 - * |
|
2070 - ******************************************************************************/ |
|
2071 -static int set_recv_wqes(struct pingpong_context *ctx, |
|
2072 - struct perftest_parameters *user_param) { |
|
2073 - |
|
2074 - int i,j,buff_size; |
|
2075 - int duplex_ind; |
|
2076 - struct ibv_recv_wr *bad_wr_recv; |
|
2077 - |
|
2078 - i = (user_param->duplex && user_param->use_mcg) ? 1 : 0; |
|
2079 - duplex_ind = (user_param->duplex && !user_param->use_mcg) ? 1 : 0; |
|
2080 - |
|
2081 - buff_size = BUFF_SIZE(ctx->size) + IF_UD_ADD(user_param->connection_type); |
|
2082 - |
|
2083 - while (i < user_param->num_of_qps) { |
|
2084 - |
|
2085 - ctx->sge_list[i].addr = (uintptr_t)ctx->buf[i] + duplex_ind*buff_size; |
|
2086 - |
|
2087 - if (user_param->connection_type == UD) |
|
2088 - ctx->sge_list[i].addr += (CACHE_LINE_SIZE - UD_ADDITION); |
|
2089 - |
|
2090 - ctx->sge_list[i].length = SIZE(user_param->connection_type,user_param->size); |
|
2091 - ctx->sge_list[i].lkey = ctx->mr[i]->lkey; |
|
2092 - ctx->rwr[i].sg_list = &ctx->sge_list[i]; |
|
2093 - ctx->rwr[i].wr_id = i; |
|
2094 - ctx->rwr[i].next = NULL; |
|
2095 - ctx->rwr[i].num_sge = MAX_RECV_SGE; |
|
2096 - ctx->my_addr[i] = (uintptr_t)ctx->buf[i] + duplex_ind*buff_size; |
|
2097 - |
|
2098 - for (j = 0; j < user_param->rx_depth; ++j) { |
|
2099 - |
|
2100 - if (ibv_post_recv(ctx->qp[i],&ctx->rwr[i],&bad_wr_recv)) { |
|
2101 - fprintf(stderr, "Couldn't post recv Qp = %d: counter=%d\n",i,j); |
|
2102 - return 1; |
|
2103 - } |
|
2104 - |
|
2105 - if (user_param->size <= (CYCLE_BUFFER / 2)) |
|
2106 - increase_loc_addr(&ctx->sge_list[i],user_param->size,j,ctx->my_addr[i],user_param->connection_type); |
|
2107 - } |
|
2108 - i++; |
|
2109 - } |
|
2110 - return 0; |
|
2111 -} |
|
2112 - |
|
2113 -/****************************************************************************** |
|
2114 - * |
|
2115 - ******************************************************************************/ |
|
2116 -static void set_send_wqe(struct pingpong_context *ctx,int rem_qpn, |
|
2117 - struct perftest_parameters *user_param) { |
|
2118 - |
|
2119 - ctx->list.addr = (uintptr_t)ctx->buf[0]; |
|
2120 - ctx->list.lkey = ctx->mr[0]->lkey; |
|
2121 - |
|
2122 - ctx->wr.sg_list = &ctx->list; |
|
2123 - ctx->wr.num_sge = 1; |
|
2124 - ctx->wr.opcode = IBV_WR_SEND; |
|
2125 - ctx->wr.next = NULL; |
|
2126 - ctx->wr.wr_id = PINGPONG_SEND_WRID; |
|
2127 - ctx->wr.send_flags = IBV_SEND_SIGNALED; |
|
2128 - |
|
2129 - if (user_param->connection_type == UD) { |
|
2130 - ctx->wr.wr.ud.ah = ctx->ah; |
|
2131 - ctx->wr.wr.ud.remote_qkey = DEF_QKEY; |
|
2132 - ctx->wr.wr.ud.remote_qpn = rem_qpn; |
|
2133 - } |
|
2134 -} |
|
2135 - |
|
2136 -/****************************************************************************** |
|
2137 - * |
|
2138 - ******************************************************************************/ |
|
2139 -static int pp_drain_qp(struct pingpong_context *ctx, |
|
2140 - struct perftest_parameters *user_param, |
|
2141 - int psn,struct pingpong_dest *dest, |
|
2142 - struct mcast_parameters *mcg_params) { |
|
2143 - |
|
2144 - struct ibv_qp_attr attr; |
|
2145 - struct ibv_wc wc; |
|
2146 - int i; |
|
2147 - |
|
2148 - memset(&attr, 0, sizeof attr); |
|
2149 - attr.qp_state = IBV_QPS_ERR; |
|
2150 - |
|
2151 - for (i = 0; i < user_param->num_of_qps; i++) { |
|
2152 - |
|
2153 - if (ibv_modify_qp(ctx->qp[i],&attr,IBV_QP_STATE)) { |
|
2154 - fprintf(stderr, "Failed to modify RC QP to ERR\n"); |
|
2155 - return 1; |
|
2156 - } |
|
2157 - |
|
2158 - while (ibv_poll_cq(ctx->cq,1,&wc)); |
|
2159 - |
|
2160 - attr.qp_state = IBV_QPS_RESET; |
|
2161 - |
|
2162 - if (ibv_modify_qp(ctx->qp[i],&attr,IBV_QP_STATE)) { |
|
2163 - fprintf(stderr, "Failed to modify RC QP to RESET\n"); |
|
2164 - return 1; |
|
2165 - } |
|
2166 - |
|
2167 - if(ctx_modify_qp_to_init(ctx->qp[i],user_param)) { |
|
2168 - return 1; |
|
2169 - } |
|
2170 - |
|
2171 - if (user_param->use_mcg) { |
|
2172 - |
|
2173 - if ((!user_param->duplex && user_param->machine == SERVER) || (user_param->duplex && i > 0)) { |
|
2174 - if (ibv_attach_mcast(ctx->qp[i],&mcg_params->mgid,mcg_params->mlid)) { |
|
2175 - fprintf(stderr, "Couldn't attach QP to MultiCast group"); |
|
2176 - return 1; |
|
2177 - } |
|
2178 - } |
|
2179 - } |
|
2180 - } |
|
2181 - |
|
2182 - if (pp_connect_ctx(ctx,psn,dest,user_param)) { |
|
2183 - return 1; |
|
2184 - } |
|
2185 - |
|
2186 - return 0; |
|
2187 -} |
|
2188 - |
|
2189 -/****************************************************************************** |
|
2190 - * |
|
2191 - ******************************************************************************/ |
|
2192 -static void print_report(struct perftest_parameters *user_param) { |
|
2193 - |
|
2194 - double cycles_to_units; |
|
2195 - unsigned long tsize; /* Transferred size, in megabytes */ |
|
2196 - int i, j; |
|
2197 - int opt_posted = 0, opt_completed = 0; |
|
2198 - cycles_t opt_delta; |
|
2199 - cycles_t t; |
|
2200 - |
|
2201 - |
|
2202 - opt_delta = tcompleted[opt_posted] - tposted[opt_completed]; |
|
2203 - |
|
2204 - if (user_param->noPeak == OFF) { |
|
2205 - /* Find the peak bandwidth, unless asked not to in command line */ |
|
2206 - for (i = 0; i < user_param->iters; ++i) |
|
2207 - for (j = i; j < user_param->iters; ++j) { |
|
2208 - t = (tcompleted[j] - tposted[i]) / (j - i + 1); |
|
2209 - if (t < opt_delta) { |
|
2210 - opt_delta = t; |
|
2211 - opt_posted = i; |
|
2212 - opt_completed = j; |
|
2213 - } |
|
2214 - } |
|
2215 - } |
|
2216 - |
|
2217 - cycles_to_units = get_cpu_mhz(user_param->cpu_freq_f) * 1000000; |
|
2218 - |
|
2219 - tsize = user_param->duplex ? 2 : 1; |
|
2220 - tsize = tsize * user_param->size; |
|
2221 - printf(REPORT_FMT,user_param->size,user_param->iters,(user_param->noPeak == OFF) * tsize * cycles_to_units / opt_delta / 0x100000, |
|
2222 - tsize * user_param->iters * cycles_to_units /(tcompleted[user_param->iters - 1] - tposted[0]) / 0x100000); |
|
2223 -} |
|
2224 - |
|
2225 -/****************************************************************************** |
|
2226 - * Important note : |
|
2227 - * In case of UD/UC this is NOT the way to measureBW since we are running with |
|
2228 - * loop on the send side , while we should run on the recieve side or enable |
|
2229 - * retry in SW , Since the sender may be faster than the reciver. |
|
2230 - * Although we had posted recieve it is not enough and might end this will |
|
2231 - * result in deadlock of test since both sides are stuck on poll cq. |
|
2232 - * In this test i do not solve this for the general test ,need to write |
|
2233 - * seperate test for UC/UD but in case the tx_depth is ~1/3 from the |
|
2234 - * number of iterations this should be ok . |
|
2235 - * Also note that the sender is limited in the number of send, ans |
|
2236 - * i try to make the reciver full . |
|
2237 - ******************************************************************************/ |
|
2238 -int run_iter_bi(struct pingpong_context *ctx, |
|
2239 - struct perftest_parameters *user_param) { |
|
2240 - |
|
2241 - int scnt = 0; |
|
2242 - int ccnt = 0; |
|
2243 - int rcnt = 0; |
|
2244 - int i = 0; |
|
2245 - int num_of_qps = user_param->num_of_qps; |
|
2246 - int ne; |
|
2247 - struct ibv_wc *wc = NULL; |
|
2248 - int *rcnt_for_qp = NULL; |
|
2249 - struct ibv_recv_wr *bad_wr_recv = NULL; |
|
2250 - struct ibv_send_wr *bad_wr = NULL; |
|
2251 - |
|
2252 - ALLOCATE(rcnt_for_qp,int,user_param->num_of_qps); |
|
2253 - ALLOCATE(wc,struct ibv_wc,DEF_WC_SIZE); |
|
2254 - memset(rcnt_for_qp,0,sizeof(int)*user_param->num_of_qps); |
|
2255 - |
|
2256 - if (user_param->use_mcg) |
|
2257 - num_of_qps--; |
|
2258 - |
|
2259 - // Set the length of the scatter in case of ALL option. |
|
2260 - ctx->list.length = user_param->size; |
|
2261 - ctx->list.addr = (uintptr_t)ctx->buf[0]; |
|
2262 - ctx->wr.send_flags = IBV_SEND_SIGNALED; |
|
2263 - |
|
2264 - if (user_param->size <= user_param->inline_size) |
|
2265 - ctx->wr.send_flags |= IBV_SEND_INLINE; |
|
2266 - |
|
2267 - while (ccnt < user_param->iters || rcnt < user_param->iters) { |
|
2268 - |
|
2269 - while (scnt < user_param->iters && (scnt - ccnt) < user_param->tx_depth / 2) { |
|
2270 - |
|
2271 - if (scnt % CQ_MODERATION == 0 && CQ_MODERATION > 1) |
|
2272 - ctx->wr.send_flags &= ~IBV_SEND_SIGNALED; |
|
2273 - |
|
2274 - tposted[scnt] = get_cycles(); |
|
2275 - if (ibv_post_send(ctx->qp[0],&ctx->wr, &bad_wr)) { |
|
2276 - fprintf(stderr, "Couldn't post send: scnt=%d\n",scnt); |
|
2277 - return 1; |
|
2278 - } |
|
2279 - |
|
2280 - if (user_param->size <= (CYCLE_BUFFER / 2)) |
|
2281 - increase_loc_addr(&ctx->list,user_param->size,scnt,(uintptr_t)ctx->buf[0],0); |
|
2282 - |
|
2283 - ++scnt; |
|
2284 - |
|
2285 - if ((scnt % CQ_MODERATION) == (CQ_MODERATION - 1) || scnt == (user_param->iters - 1)) |
|
2286 - ctx->wr.send_flags |= IBV_SEND_SIGNALED; |
|
2287 - } |
|
2288 - |
|
2289 - if (user_param->use_event) { |
|
2290 - |
|
2291 - if (ctx_notify_events(ctx->cq,ctx->channel)) { |
|
2292 - fprintf(stderr,"Failed to notify events to CQ"); |
|
2293 - return 1; |
|
2294 - } |
|
2295 - } |
|
2296 - |
|
2297 - do { |
|
2298 - ne = ibv_poll_cq(ctx->cq,DEF_WC_SIZE,wc); |
|
2299 - if (ne > 0) { |
|
2300 - for (i = 0; i < ne; i++) { |
|
2301 - |
|
2302 - if (wc[i].status != IBV_WC_SUCCESS) |
|
2303 - NOTIFY_COMP_ERROR_SEND(wc[i],scnt,ccnt); |
|
2304 - |
|
2305 - if ((int) wc[i].wr_id == PINGPONG_SEND_WRID) { |
|
2306 - ccnt += CQ_MODERATION; |
|
2307 - if (ccnt >= user_param->iters - 1) |
|
2308 - tcompleted[user_param->iters - 1] = get_cycles(); |
|
2309 - |
|
2310 - else |
|
2311 - tcompleted[ccnt - 1] = get_cycles(); |
|
2312 - } |
|
2313 - |
|
2314 - else { |
|
2315 - |
|
2316 - rcnt_for_qp[wc[i].wr_id]++; |
|
2317 - rcnt++; |
|
2318 - if (ibv_post_recv(ctx->qp[wc[i].wr_id],&ctx->rwr[wc[i].wr_id],&bad_wr_recv)) { |
|
2319 - fprintf(stderr, "Couldn't post recv Qp=%d rcnt=%d\n",(int)wc[i].wr_id , rcnt_for_qp[wc[i].wr_id]); |
|
2320 - return 15; |
|
2321 - } |
|
2322 - |
|
2323 - if (user_param->size <= (CYCLE_BUFFER / 2)) |
|
2324 - increase_loc_addr(&ctx->sge_list[wc[i].wr_id], |
|
2325 - user_param->size,rcnt_for_qp[wc[i].wr_id] + user_param->rx_depth - 1, |
|
2326 - ctx->my_addr[wc[i].wr_id],user_param->connection_type); |
|
2327 - } |
|
2328 - } |
|
2329 - } |
|
2330 - } while (ne > 0); |
|
2331 - |
|
2332 - if (ne < 0) { |
|
2333 - fprintf(stderr, "poll CQ failed %d\n", ne); |
|
2334 - return 1; |
|
2335 - } |
|
2336 - } |
|
2337 - |
|
2338 - if (user_param->size <= user_param->inline_size) |
|
2339 - ctx->wr.send_flags &= ~IBV_SEND_INLINE; |
|
2340 - |
|
2341 - free(rcnt_for_qp); |
|
2342 - free(wc); |
|
2343 - return 0; |
|
2344 -} |
|
2345 - |
|
2346 -/****************************************************************************** |
|
2347 - * |
|
2348 - ******************************************************************************/ |
|
2349 -int run_iter_uni_server(struct pingpong_context *ctx, |
|
2350 - struct perftest_parameters *user_param) { |
|
2351 - |
|
2352 - int rcnt = 0; |
|
2353 - int ne,i; |
|
2354 - int *rcnt_for_qp = NULL; |
|
2355 - struct ibv_wc *wc = NULL; |
|
2356 - struct ibv_recv_wr *bad_wr_recv = NULL; |
|
2357 - |
|
2358 - ALLOCATE(wc,struct ibv_wc,DEF_WC_SIZE); |
|
2359 - ALLOCATE(rcnt_for_qp,int,user_param->num_of_qps); |
|
2360 - |
|
2361 - memset(rcnt_for_qp,0,sizeof(int)*user_param->num_of_qps); |
|
2362 - |
|
2363 - while (rcnt < user_param->iters) { |
|
2364 - |
|
2365 - if (user_param->use_event) { |
|
2366 - if (ctx_notify_events(ctx->cq,ctx->channel)) { |
|
2367 - fprintf(stderr ," Failed to notify events to CQ"); |
|
2368 - return 1; |
|
2369 - } |
|
2370 - } |
|
2371 - |
|
2372 - do { |
|
2373 - ne = ibv_poll_cq(ctx->cq,DEF_WC_SIZE,wc); |
|
2374 - if (ne > 0) { |
|
2375 - for (i = 0; i < ne; i++) { |
|
2376 - |
|
2377 - if (wc[i].status != IBV_WC_SUCCESS) |
|
2378 - NOTIFY_COMP_ERROR_RECV(wc[i],rcnt_for_qp[wc[i].wr_id]); |
|
2379 - |
|
2380 - rcnt_for_qp[wc[i].wr_id]++; |
|
2381 - tcompleted[rcnt++] = get_cycles(); |
|
2382 - |
|
2383 - if (ibv_post_recv(ctx->qp[wc[i].wr_id],&ctx->rwr[wc[i].wr_id],&bad_wr_recv)) { |
|
2384 - fprintf(stderr, "Couldn't post recv Qp=%d rcnt=%d\n",(int)wc[i].wr_id,rcnt_for_qp[wc[i].wr_id]); |
|
2385 - return 15; |
|
2386 - } |
|
2387 - |
|
2388 - if (user_param->size <= (CYCLE_BUFFER / 2)) |
|
2389 - increase_loc_addr(&ctx->sge_list[wc[i].wr_id],user_param->size, |
|
2390 - rcnt_for_qp[wc[i].wr_id] + user_param->rx_depth, |
|
2391 - ctx->my_addr[wc[i].wr_id],user_param->connection_type); |
|
2392 - } |
|
2393 - } |
|
2394 - } while (ne > 0); |
|
2395 - |
|
2396 - if (ne < 0) { |
|
2397 - fprintf(stderr, "Poll Recieve CQ failed %d\n", ne); |
|
2398 - return 1; |
|
2399 - } |
|
2400 - } |
|
2401 - |
|
2402 - tposted[0] = tcompleted[0]; |
|
2403 - free(wc); |
|
2404 - free(rcnt_for_qp); |
|
2405 - return 0; |
|
2406 -} |
|
2407 - |
|
2408 -/****************************************************************************** |
|
2409 - * |
|
2410 - ******************************************************************************/ |
|
2411 -int run_iter_uni_client(struct pingpong_context *ctx, |
|
2412 - struct perftest_parameters *user_param) { |
|
2413 - |
|
2414 - int ne; |
|
2415 - int i = 0; |
|
2416 - int scnt = 0; |
|
2417 - int ccnt = 0; |
|
2418 - struct ibv_wc *wc = NULL; |
|
2419 - struct ibv_send_wr *bad_wr = NULL; |
|
2420 - |
|
2421 - ALLOCATE(wc,struct ibv_wc,DEF_WC_SIZE); |
|
2422 - |
|
2423 - // Set the lenght of the scatter in case of ALL option. |
|
2424 - ctx->list.length = user_param->size; |
|
2425 - ctx->list.addr = (uintptr_t)ctx->buf[0]; |
|
2426 - ctx->wr.send_flags = IBV_SEND_SIGNALED; |
|
2427 - |
|
2428 - if (user_param->size <= user_param->inline_size) |
|
2429 - ctx->wr.send_flags |= IBV_SEND_INLINE; |
|
2430 - |
|
2431 - |
|
2432 - while (scnt < user_param->iters || ccnt < user_param->iters) { |
|
2433 - while (scnt < user_param->iters && (scnt - ccnt) < user_param->tx_depth ) { |
|
2434 - |
|
2435 - if (scnt % CQ_MODERATION == 0 && CQ_MODERATION > 1) |
|
2436 - ctx->wr.send_flags &= ~IBV_SEND_SIGNALED; |
|
2437 - |
|
2438 - tposted[scnt] = get_cycles(); |
|
2439 - if (ibv_post_send(ctx->qp[0], &ctx->wr, &bad_wr)) { |
|
2440 - fprintf(stderr, "Couldn't post send: scnt=%d\n",scnt); |
|
2441 - return 1; |
|
2442 - } |
|
2443 - |
|
2444 - if (user_param->size <= (CYCLE_BUFFER / 2)) |
|
2445 - increase_loc_addr(&ctx->list,user_param->size,scnt,(uintptr_t)ctx->buf[0],0); |
|
2446 - |
|
2447 - scnt++; |
|
2448 - |
|
2449 - if ((scnt % CQ_MODERATION) == (CQ_MODERATION - 1) || scnt == (user_param->iters - 1)) |
|
2450 - ctx->wr.send_flags |= IBV_SEND_SIGNALED; |
|
2451 - } |
|
2452 - |
|
2453 - if (ccnt < user_param->iters) { |
|
2454 - |
|
2455 - if (user_param->use_event) { |
|
2456 - if (ctx_notify_events(ctx->cq,ctx->channel)) { |
|
2457 - fprintf(stderr , " Failed to notify events to CQ"); |
|
2458 - return 1; |
|
2459 - } |
|
2460 - } |
|
2461 - do { |
|
2462 - ne = ibv_poll_cq(ctx->cq,DEF_WC_SIZE,wc); |
|
2463 - if (ne > 0) { |
|
2464 - for (i = 0; i < DEF_WC_SIZE; i++) { |
|
2465 - |
|
2466 - if (wc[i].status != IBV_WC_SUCCESS) |
|
2467 - NOTIFY_COMP_ERROR_SEND(wc[i],scnt,ccnt); |
|
2468 - |
|
2469 - ccnt += CQ_MODERATION; |
|
2470 - if (ccnt >= user_param->iters - 1) |
|
2471 - tcompleted[user_param->iters - 1] = get_cycles(); |
|
2472 - |
|
2473 - else |
|
2474 - tcompleted[ccnt - 1] = get_cycles(); |
|
2475 - } |
|
2476 - } |
|
2477 - |
|
2478 - |
|
2479 - } while (ne > 0); |
|
2480 - |
|
2481 - if (ne < 0) { |
|
2482 - fprintf(stderr, "poll CQ failed\n"); |
|
2483 - return 1; |
|
2484 - } |
|
2485 - } |
|
2486 - } |
|
2487 - |
|
2488 - if (user_param->size <= user_param->inline_size) |
|
2489 - ctx->wr.send_flags &= ~IBV_SEND_INLINE; |
|
2490 - |
|
2491 - free(wc); |
|
2492 - return 0; |
|
2493 -} |
|
2494 - |
|
2495 -/****************************************************************************** |
|
2496 - * |
|
2497 - ******************************************************************************/ |
|
2498 -int main(int argc, char *argv[]) |
|
2499 -{ |
|
2500 - struct ibv_device *ib_dev = NULL; |
|
2501 - struct pingpong_context *ctx; |
|
2502 - struct pingpong_dest my_dest,rem_dest; |
|
2503 - struct perftest_parameters user_param; |
|
2504 - struct mcast_parameters mcg_params; |
|
2505 - int i = 0; |
|
2506 - int size_max_pow = 24; |
|
2507 - int size_of_arr; |
|
2508 - |
|
2509 - // Pointer to The relevent function of run_iter according to machine type. |
|
2510 - int (*ptr_to_run_iter_uni)(struct pingpong_context*,struct perftest_parameters*); |
|
2511 - |
|
2512 - /* init default values to user's parameters */ |
|
2513 - memset(&user_param, 0 , sizeof(struct perftest_parameters)); |
|
2514 - memset(&mcg_params, 0 , sizeof(struct mcast_parameters)); |
|
2515 - memset(&my_dest , 0 , sizeof(struct pingpong_dest)); |
|
2516 - memset(&rem_dest , 0 , sizeof(struct pingpong_dest)); |
|
2517 - |
|
2518 - user_param.verb = SEND; |
|
2519 - user_param.tst = BW; |
|
2520 - user_param.version = VERSION; |
|
2521 - |
|
2522 - if (parser(&user_param,argv,argc)) |
|
2523 - return 1; |
|
2524 - |
|
2525 - printf(RESULT_LINE); |
|
2526 - |
|
2527 - user_param.rx_depth = (user_param.iters < user_param.rx_depth) ? user_param.iters : user_param.rx_depth ; |
|
2528 - |
|
2529 - if (user_param.use_mcg) { |
|
2530 - |
|
2531 - user_param.connection_type = UD; |
|
2532 - if (user_param.duplex) { |
|
2533 - user_param.num_of_qps++; |
|
2534 - printf(" Send Bidirectional BW - Multicast Test\n"); |
|
2535 - } |
|
2536 - else { |
|
2537 - printf(" Send BW - Multicast Test\n"); |
|
2538 - if (user_param.machine == CLIENT) |
|
2539 - user_param.num_of_qps = 1; |
|
2540 - } |
|
2541 - } |
|
2542 - |
|
2543 - else if (user_param.duplex) { |
|
2544 - printf(" Send Bidirectional BW Test\n"); |
|
2545 - } else |
|
2546 - printf(" Send BW Test\n"); |
|
2547 - |
|
2548 - if (user_param.use_event) |
|
2549 - printf(" Test with events.\n"); |
|
2550 - |
|
2551 - if (user_param.connection_type == RC) |
|
2552 - printf(" Connection type : RC\n"); |
|
2553 - else if (user_param.connection_type == UC) |
|
2554 - printf(" Connection type : UC\n"); |
|
2555 - else{ |
|
2556 - printf(" Connection type : UD\n"); |
|
2557 - } |
|
2558 - |
|
2559 - // Done with parameter parsing. Perform setup. |
|
2560 - if (user_param.all == ON) { |
|
2561 - // since we run all sizes |
|
2562 - user_param.size = MAX_SIZE; |
|
2563 - } |
|
2564 - |
|
2565 - srand48(getpid() * time(NULL)); |
|
2566 - page_size = sysconf(_SC_PAGESIZE); |
|
2567 - |
|
2568 - ib_dev = ctx_find_dev(user_param.ib_devname); |
|
2569 - if (!ib_dev) |
|
2570 - return 7; |
|
2571 - |
|
2572 - mcg_params.ib_devname = ibv_get_device_name(ib_dev); |
|
2573 - |
|
2574 - ctx = pp_init_ctx(ib_dev,&user_param); |
|
2575 - if (!ctx) |
|
2576 - return 1; |
|
2577 - |
|
2578 - // Set up the Connection. |
|
2579 - if (set_up_connection(ctx,&user_param,&my_dest,&mcg_params)) { |
|
2580 - fprintf(stderr," Unable to set up socket connection\n"); |
|
2581 - return 1; |
|
2582 - } |
|
2583 - |
|
2584 - // Init the connection and print the local data. |
|
2585 - if (init_connection(&user_param,&my_dest)) { |
|
2586 - fprintf(stderr," Unable to init the socket connection\n"); |
|
2587 - return 1; |
|
2588 - } |
|
2589 - |
|
2590 - // shaking hands and gather the other side info. |
|
2591 - if (ctx_hand_shake(&user_param,&my_dest,&rem_dest)) { |
|
2592 - fprintf(stderr,"Failed to exchange date between server and clients\n"); |
|
2593 - return 1; |
|
2594 - |
|
2595 - } |
|
2596 - // For printing only MGID in the remote side. |
|
2597 - user_param.side = REMOTE; |
|
2598 - ctx_print_pingpong_data(&rem_dest,&user_param); |
|
2599 - |
|
2600 - // Joining the Send side port the Mcast gid |
|
2601 - if (user_param.use_mcg && (user_param.machine == CLIENT || user_param.duplex)) { |
|
2602 - memcpy(mcg_params.mgid.raw, rem_dest.gid.raw, 16); |
|
2603 - if (set_mcast_group(ctx,&user_param,&mcg_params)) { |
|
2604 - fprintf(stderr," Unable to Join Sender to Mcast gid\n"); |
|
2605 - return 1; |
|
2606 - } |
|
2607 - } |
|
2608 - |
|
2609 - // Prepare IB resources for rtr/rts. |
|
2610 - if (pp_connect_ctx(ctx,my_dest.psn,&rem_dest,&user_param)) { |
|
2611 - fprintf(stderr," Unable to Connect the HCA's through the link\n"); |
|
2612 - return 1; |
|
2613 - } |
|
2614 - |
|
2615 - // shaking hands and gather the other side info. |
|
2616 - if (ctx_hand_shake(&user_param,&my_dest,&rem_dest)) { |
|
2617 - fprintf(stderr,"Failed to exchange date between server and clients\n"); |
|
2618 - return 1; |
|
2619 - |
|
2620 - } |
|
2621 - |
|
2622 - if (user_param.use_event) { |
|
2623 - if (ibv_req_notify_cq(ctx->cq, 0)) { |
|
2624 - fprintf(stderr, " Couldn't request CQ notification\n"); |
|
2625 - return 1; |
|
2626 - } |
|
2627 - } |
|
2628 - |
|
2629 - printf(RESULT_LINE); |
|
2630 - printf(RESULT_FMT); |
|
2631 - |
|
2632 - size_of_arr = (user_param.duplex) ? 1 : user_param.num_of_qps; |
|
2633 - |
|
2634 - ALLOCATE(tposted,cycles_t,user_param.iters*size_of_arr); |
|
2635 - ALLOCATE(tcompleted,cycles_t,user_param.iters*size_of_arr); |
|
2636 - |
|
2637 - if (user_param.machine == SERVER || user_param.duplex) { |
|
2638 - ALLOCATE(ctx->rwr,struct ibv_recv_wr,user_param.num_of_qps); |
|
2639 - ALLOCATE(ctx->sge_list,struct ibv_sge,user_param.num_of_qps); |
|
2640 - ALLOCATE(ctx->my_addr ,uint64_t ,user_param.num_of_qps); |
|
2641 - } |
|
2642 - |
|
2643 - ptr_to_run_iter_uni = (user_param.machine == CLIENT) ? &run_iter_uni_client : &run_iter_uni_server; |
|
2644 - |
|
2645 - if (user_param.machine == SERVER && !user_param.duplex) { |
|
2646 - user_param.noPeak = ON; |
|
2647 - } |
|
2648 - |
|
2649 - if (user_param.machine == CLIENT || user_param.duplex) { |
|
2650 - set_send_wqe(ctx,rem_dest.qpn,&user_param); |
|
2651 - } |
|
2652 - |
|
2653 - if (user_param.all == ON) { |
|
2654 - |
|
2655 - if (user_param.connection_type == UD) |
|
2656 - size_max_pow = (int)UD_MSG_2_EXP(MTU_SIZE(user_param.curr_mtu)) + 1; |
|
2657 - |
|
2658 - for (i = 1; i < size_max_pow ; ++i) { |
|
2659 - user_param.size = 1 << i; |
|
2660 - |
|
2661 - if (user_param.machine == SERVER || user_param.duplex) { |
|
2662 - if (set_recv_wqes(ctx,&user_param)) { |
|
2663 - fprintf(stderr," Failed to post receive recv_wqes\n"); |
|
2664 - return 1; |
|
2665 - } |
|
2666 - } |
|
2667 - |
|
2668 - if (ctx_hand_shake(&user_param,&my_dest,&rem_dest)) { |
|
2669 - fprintf(stderr,"Failed to exchange date between server and clients\n"); |
|
2670 - return 1; |
|
2671 - } |
|
2672 - |
|
2673 - if (user_param.duplex) { |
|
2674 - if(run_iter_bi(ctx,&user_param)) |
|
2675 - return 17; |
|
2676 - } else { |
|
2677 - if((*ptr_to_run_iter_uni)(ctx,&user_param)) |
|
2678 - return 17; |
|
2679 - } |
|
2680 - print_report(&user_param); |
|
2681 - |
|
2682 - if (pp_drain_qp(ctx,&user_param,my_dest.psn,&rem_dest,&mcg_params)) { |
|
2683 - fprintf(stderr,"Failed to drain Recv queue (performance optimization)\n"); |
|
2684 - return 1; |
|
2685 - } |
|
2686 - |
|
2687 - if (ctx_hand_shake(&user_param,&my_dest,&rem_dest)) { |
|
2688 - fprintf(stderr,"Failed to exchange date between server and clients\n"); |
|
2689 - return 1; |
|
2690 - } |
|
2691 - |
|
2692 - } |
|
2693 - |
|
2694 - } else { |
|
2695 - |
|
2696 - if (user_param.machine == SERVER || user_param.duplex) { |
|
2697 - if (set_recv_wqes(ctx,&user_param)) { |
|
2698 - fprintf(stderr," Failed to post receive recv_wqes\n"); |
|
2699 - return 1; |
|
2700 - } |
|
2701 - } |
|
2702 - |
|
2703 - if (ctx_hand_shake(&user_param,&my_dest,&rem_dest)) { |
|
2704 - fprintf(stderr,"Failed to exchange date between server and clients\n"); |
|
2705 - return 1; |
|
2706 - } |
|
2707 - |
|
2708 - if (user_param.duplex) { |
|
2709 - if(run_iter_bi(ctx,&user_param)) |
|
2710 - return 18; |
|
2711 - |
|
2712 - } else { |
|
2713 - if((*ptr_to_run_iter_uni)(ctx,&user_param)) |
|
2714 - return 18; |
|
2715 - } |
|
2716 - |
|
2717 - print_report(&user_param); |
|
2718 - } |
|
2719 - |
|
2720 - if (ctx_close_connection(&user_param,&my_dest,&rem_dest)) { |
|
2721 - fprintf(stderr," Failed to close connection between server and client\n"); |
|
2722 - return 1; |
|
2723 - } |
|
2724 - |
|
2725 - printf(RESULT_LINE); |
|
2726 - return destroy_ctx_resources(ctx,&user_param,&my_dest,&rem_dest,&mcg_params); |
|
2727 -} |
|
2728 +/* |
|
2729 + * Copyright (c) 2005 Topspin Communications. All rights reserved. |
|
2730 + * Copyright (c) 2005 Mellanox Technologies Ltd. All rights reserved. |
|
2731 + * Copyright (c) 2009 HNR Consulting. All rights reserved. |
|
2732 + * |
|
2733 + * This software is available to you under a choice of one of two |
|
2734 + * licenses. You may choose to be licensed under the terms of the GNU |
|
2735 + * General Public License (GPL) Version 2, available from the file |
|
2736 + * COPYING in the main directory of this source tree, or the |
|
2737 + * OpenIB.org BSD license below: |
|
2738 + * |
|
2739 + * Redistribution and use in source and binary forms, with or |
|
2740 + * without modification, are permitted provided that the following |
|
2741 + * conditions are met: |
|
2742 + * |
|
2743 + * - Redistributions of source code must retain the above |
|
2744 + * copyright notice, this list of conditions and the following |
|
2745 + * disclaimer. |
|
2746 + * |
|
2747 + * - Redistributions in binary form must reproduce the above |
|
2748 + * copyright notice, this list of conditions and the following |
|
2749 + * disclaimer in the documentation and/or other materials |
|
2750 + * provided with the distribution. |
|
2751 + * |
|
2752 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
|
2753 + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
|
2754 + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
|
2755 + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS |
|
2756 + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN |
|
2757 + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
|
2758 + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
|
2759 + * SOFTWARE. |
|
2760 + * |
|
2761 + * $Id$ |
|
2762 + */ |
|
2763 + |
|
2764 +#if HAVE_CONFIG_H |
|
2765 +# include <config.h> |
|
2766 +#endif /* HAVE_CONFIG_H */ |
|
2767 + |
|
2768 +#include <stdio.h> |
|
2769 +#include <stdlib.h> |
|
2770 +#include <unistd.h> |
|
2771 +#include <string.h> |
|
2772 +#include <limits.h> |
|
2773 +#include <malloc.h> |
|
2774 +#include <getopt.h> |
|
2775 +#include <time.h> |
|
2776 +#include <errno.h> |
|
2777 +#include <infiniband/verbs.h> |
|
2778 + |
|
2779 +#include "get_clock.h" |
|
2780 +#include "multicast_resources.h" |
|
2781 +#include "perftest_resources.h" |
|
2782 + |
|
2783 +#define VERSION 2.1 |
|
2784 + |
|
2785 +static int page_size; |
|
2786 +cycles_t *tposted; |
|
2787 +cycles_t *tcompleted; |
|
2788 + |
|
2789 +struct pingpong_context { |
|
2790 + struct ibv_context *context; |
|
2791 + struct ibv_comp_channel *channel; |
|
2792 + struct ibv_pd *pd; |
|
2793 + struct ibv_mr **mr; |
|
2794 + struct ibv_cq *cq; |
|
2795 + struct ibv_qp **qp; |
|
2796 + struct ibv_sge list; |
|
2797 + struct ibv_send_wr wr; |
|
2798 + struct ibv_sge *sge_list; |
|
2799 + struct ibv_recv_wr *rwr; |
|
2800 + struct ibv_ah *ah; |
|
2801 + void **buf; |
|
2802 + unsigned size; |
|
2803 + uint64_t *my_addr; |
|
2804 +}; |
|
2805 + |
|
2806 +/****************************************************************************** |
|
2807 + * |
|
2808 + ******************************************************************************/ |
|
2809 +static int set_mcast_group(struct pingpong_context *ctx, |
|
2810 + struct perftest_parameters *user_parm, |
|
2811 + struct mcast_parameters *mcg_params) { |
|
2812 + |
|
2813 + struct ibv_port_attr port_attr; |
|
2814 + |
|
2815 + if (ibv_query_gid(ctx->context,user_parm->ib_port,user_parm->gid_index,&mcg_params->port_gid)) { |
|
2816 + return 1; |
|
2817 + } |
|
2818 + |
|
2819 + if (ibv_query_pkey(ctx->context,user_parm->ib_port,DEF_PKEY_IDX,&mcg_params->pkey)) { |
|
2820 + return 1; |
|
2821 + } |
|
2822 + |
|
2823 + if (ibv_query_port(ctx->context,user_parm->ib_port,&port_attr)) { |
|
2824 + return 1; |
|
2825 + } |
|
2826 + mcg_params->sm_lid = port_attr.sm_lid; |
|
2827 + mcg_params->sm_sl = port_attr.sm_sl; |
|
2828 + mcg_params->ib_port = user_parm->ib_port; |
|
2829 + |
|
2830 + if (!strcmp(link_layer_str(user_parm->link_type),"IB")) { |
|
2831 + // Request for Mcast group create registery in SM. |
|
2832 + if (join_multicast_group(SUBN_ADM_METHOD_SET,mcg_params)) { |
|
2833 + fprintf(stderr,"Couldn't Register the Mcast group on the SM\n"); |
|
2834 + return 1; |
|
2835 + } |
|
2836 + } |
|
2837 + return 0; |
|
2838 +} |
|
2839 + |
|
2840 +/****************************************************************************** |
|
2841 + * |
|
2842 + ******************************************************************************/ |
|
2843 +static int set_up_connection(struct pingpong_context *ctx, |
|
2844 + struct perftest_parameters *user_parm, |
|
2845 + struct pingpong_dest *my_dest, |
|
2846 + struct mcast_parameters *mcg_params) { |
|
2847 + |
|
2848 + int i = (user_parm->duplex) ? 1 : 0; |
|
2849 + |
|
2850 + if (user_parm->use_mcg && (user_parm->duplex || user_parm->machine == SERVER)) { |
|
2851 + |
|
2852 + set_multicast_gid(mcg_params,ctx->qp[0]->qp_num,(int)user_parm->machine); |
|
2853 + if (set_mcast_group(ctx,user_parm,mcg_params)) { |
|
2854 + return 1; |
|
2855 + } |
|
2856 + |
|
2857 + while (i < user_parm->num_of_qps) { |
|
2858 + if (ibv_attach_mcast(ctx->qp[i],&mcg_params->mgid,mcg_params->mlid)) { |
|
2859 + fprintf(stderr, "Couldn't attach QP to MultiCast group"); |
|
2860 + return 1; |
|
2861 + } |
|
2862 + i++; |
|
2863 + } |
|
2864 + |
|
2865 + mcg_params->mcast_state |= MCAST_IS_ATTACHED; |
|
2866 + my_dest->gid = mcg_params->mgid; |
|
2867 + my_dest->lid = mcg_params->mlid; |
|
2868 + my_dest->qpn = QPNUM_MCAST; |
|
2869 + |
|
2870 + } else { |
|
2871 + if (user_parm->gid_index != -1) { |
|
2872 + if (ibv_query_gid(ctx->context,user_parm->ib_port,user_parm->gid_index,&my_dest->gid)) { |
|
2873 + return -1; |
|
2874 + } |
|
2875 + } |
|
2876 + my_dest->lid = ctx_get_local_lid(ctx->context,user_parm->ib_port); |
|
2877 + my_dest->qpn = ctx->qp[0]->qp_num; |
|
2878 + } |
|
2879 + my_dest->psn = lrand48() & 0xffffff; |
|
2880 + |
|
2881 + // We do not fail test upon lid above RoCE. |
|
2882 + |
|
2883 + if (user_parm->gid_index < 0) { |
|
2884 + if (!my_dest->lid) { |
|
2885 + fprintf(stderr," Local lid 0x0 detected,without any use of gid. Is SM running?\n"); |
|
2886 + return -1; |
|
2887 + } |
|
2888 + } |
|
2889 + return 0; |
|
2890 +} |
|
2891 + |
|
2892 +/****************************************************************************** |
|
2893 + * |
|
2894 + ******************************************************************************/ |
|
2895 +static int init_connection(struct perftest_parameters *params, |
|
2896 + struct pingpong_dest *my_dest) { |
|
2897 + |
|
2898 + params->side = LOCAL; |
|
2899 + ctx_print_pingpong_data(my_dest,params); |
|
2900 + |
|
2901 + if (params->machine == CLIENT) |
|
2902 + params->sockfd = ctx_client_connect(params->servername,params->port); |
|
2903 + else |
|
2904 + params->sockfd = ctx_server_connect(params->port); |
|
2905 + |
|
2906 + |
|
2907 + if(params->sockfd < 0) { |
|
2908 + fprintf(stderr,"Unable to open file descriptor for socket connection"); |
|
2909 + return 1; |
|
2910 + } |
|
2911 + return 0; |
|
2912 +} |
|
2913 + |
|
2914 +/****************************************************************************** |
|
2915 + * |
|
2916 + ******************************************************************************/ |
|
2917 +static int destroy_ctx_resources(struct pingpong_context *ctx, |
|
2918 + struct perftest_parameters *user_parm, |
|
2919 + struct pingpong_dest *my_dest, |
|
2920 + struct pingpong_dest *rem_dest, |
|
2921 + struct mcast_parameters *mcg_params) { |
|
2922 + |
|
2923 + int test_result = 0; |
|
2924 + int i = (user_parm->duplex) ? 1 : 0; |
|
2925 + |
|
2926 + if (user_parm->use_mcg) { |
|
2927 + |
|
2928 + if (user_parm->machine == SERVER || user_parm->duplex) { |
|
2929 + |
|
2930 + while (i < user_parm->num_of_qps) { |
|
2931 + if (ibv_detach_mcast(ctx->qp[i],&my_dest->gid,my_dest->lid)) { |
|
2932 + fprintf(stderr, "Couldn't deattach QP from MultiCast group\n"); |
|
2933 + return 1; |
|
2934 + } |
|
2935 + i++; |
|
2936 + } |
|
2937 + mcg_params->mgid = my_dest->gid; |
|
2938 + if (!strcmp(link_layer_str(user_parm->link_type),"IB")) { |
|
2939 + if (join_multicast_group(SUBN_ADM_METHOD_DELETE,mcg_params)) { |
|
2940 + fprintf(stderr,"Couldn't Unregister the Mcast group on the SM\n"); |
|
2941 + return 1; |
|
2942 + } |
|
2943 + } |
|
2944 + } |
|
2945 + |
|
2946 + if (user_parm->machine == CLIENT || user_parm->duplex) { |
|
2947 + |
|
2948 + mcg_params->mgid = rem_dest->gid; |
|
2949 + if (!strcmp(link_layer_str(user_parm->link_type),"IB")) { |
|
2950 + if (join_multicast_group(SUBN_ADM_METHOD_DELETE,mcg_params)) { |
|
2951 + fprintf(stderr,"Couldn't Unregister the Mcast group on the SM\n"); |
|
2952 + return 1; |
|
2953 + } |
|
2954 + } |
|
2955 + |
|
2956 + } |
|
2957 + } |
|
2958 + |
|
2959 + if (ctx->ah) { |
|
2960 + if (ibv_destroy_ah(ctx->ah)) { |
|
2961 + fprintf(stderr, "failed to destroy AH\n"); |
|
2962 + test_result = 1; |
|
2963 + } |
|
2964 + } |
|
2965 + |
|
2966 + for(i = 0; i < user_parm->num_of_qps; i++) { |
|
2967 + if (ibv_destroy_qp(ctx->qp[i])) { |
|
2968 + test_result = 1; |
|
2969 + } |
|
2970 + } |
|
2971 + free(ctx->qp); |
|
2972 + |
|
2973 + if (ibv_destroy_cq(ctx->cq)) { |
|
2974 + test_result = 1; |
|
2975 + } |
|
2976 + |
|
2977 + for(i = 0; i < user_parm->num_of_qps; i++) { |
|
2978 + |
|
2979 + if (ibv_dereg_mr(ctx->mr[i])) { |
|
2980 + test_result = 1; |
|
2981 + } |
|
2982 + free(ctx->buf[i]); |
|
2983 + } |
|
2984 + |
|
2985 + if (ibv_dealloc_pd(ctx->pd)) { |
|
2986 + test_result = 1; |
|
2987 + } |
|
2988 + |
|
2989 + if (ctx->channel) { |
|
2990 + if (ibv_destroy_comp_channel(ctx->channel)) { |
|
2991 + test_result = 1; |
|
2992 + } |
|
2993 + } |
|
2994 + |
|
2995 + if (ibv_close_device(ctx->context)) { |
|
2996 + test_result = 1; |
|
2997 + } |
|
2998 + |
|
2999 + if (user_parm->machine == SERVER || user_parm->duplex) { |
|
3000 + free(ctx->rwr); |
|
3001 + free(ctx->sge_list); |
|
3002 + free(ctx->my_addr); |
|
3003 + } |
|
3004 + |
|
3005 + free(ctx->mr); |
|
3006 + free(ctx->buf); |
|
3007 + free(ctx); |
|
3008 + free(tposted); |
|
3009 + free(tcompleted); |
|
3010 + return test_result; |
|
3011 +} |
|
3012 + |
|
3013 +/****************************************************************************** |
|
3014 + * |
|
3015 + ******************************************************************************/ |
|
3016 +static struct pingpong_context *pp_init_ctx(struct ibv_device *ib_dev, |
|
3017 + struct perftest_parameters *user_parm) { |
|
3018 + |
|
3019 + int i,m_size; |
|
3020 + int duplex_ind; |
|
3021 + struct pingpong_context *ctx; |
|
3022 + |
|
3023 + ALLOCATE(ctx,struct pingpong_context,1); |
|
3024 + ALLOCATE(ctx->buf,void*,user_parm->num_of_qps); |
|
3025 + ALLOCATE(ctx->mr,struct ibv_mr*,user_parm->num_of_qps); |
|
3026 + |
|
3027 + ctx->ah = NULL; |
|
3028 + ctx->channel = NULL; |
|
3029 + |
|
3030 + duplex_ind = (user_parm->duplex && !user_parm->use_mcg) ? 2 : 1; |
|
3031 + |
|
3032 + ctx->context = ibv_open_device(ib_dev); |
|
3033 + if (!ctx->context) { |
|
3034 + fprintf(stderr, "Couldn't get context for %s\n", |
|
3035 + ibv_get_device_name(ib_dev)); |
|
3036 + return NULL; |
|
3037 + } |
|
3038 + |
|
3039 + // Configure the Link MTU acoording to the user or the active mtu. |
|
3040 + if (ctx_set_mtu(ctx->context,user_parm)) { |
|
3041 + fprintf(stderr, "Couldn't set the link layer\n"); |
|
3042 + return NULL; |
|
3043 + } |
|
3044 + |
|
3045 + if (user_parm->connection_type == UD && user_parm->size > MTU_SIZE(user_parm->curr_mtu)) { |
|
3046 + printf(" Max msg size in UD is MTU - %d . changing to MTU\n",MTU_SIZE(user_parm->curr_mtu)); |
|
3047 + user_parm->size = MTU_SIZE(user_parm->curr_mtu); |
|
3048 + } |
|
3049 + |
|
3050 + if (is_dev_hermon(ctx->context) == NOT_HERMON && user_parm->inline_size != 0) |
1570 + if (is_dev_hermon(ctx->context) == NOT_HERMON && user_parm->inline_size != 0) |
3051 + user_parm->inline_size = 0; |
1571 user_parm->inline_size = 0; |
3052 + |
1572 |
3053 + printf(" Inline data is used up to %d bytes message\n", user_parm->inline_size); |
1573 printf(" Inline data is used up to %d bytes message\n", user_parm->inline_size); |
3054 + |
1574 @@ -649,7 +649,11 @@ |
3055 + ctx->size = user_parm->size; |
1575 } |
3056 + |
1576 } |
3057 + // Finds the link type and configure the HCA accordingly. |
1577 |
3058 + if (ctx_set_link_layer(ctx->context,user_parm)) { |
1578 +#if !(defined(__SVR4) && defined(__sun)) |
3059 + fprintf(stderr, " Couldn't set the link layer\n"); |
1579 cycles_to_units = get_cpu_mhz(user_param->cpu_freq_f) * 1000000; |
3060 + return NULL; |
|
3061 + } |
|
3062 + |
|
3063 + if (user_parm->use_event) { |
|
3064 + ctx->channel = ibv_create_comp_channel(ctx->context); |
|
3065 + if (!ctx->channel) { |
|
3066 + fprintf(stderr, "Couldn't create completion channel\n"); |
|
3067 + return NULL; |
|
3068 + } |
|
3069 + } else |
|
3070 + ctx->channel = NULL; |
|
3071 + |
|
3072 + ctx->pd = ibv_alloc_pd(ctx->context); |
|
3073 + if (!ctx->pd) { |
|
3074 + fprintf(stderr, "Couldn't allocate PD\n"); |
|
3075 + return NULL; |
|
3076 + } |
|
3077 + |
|
3078 + for (i = 0; i < user_parm->num_of_qps; i++) { |
|
3079 + |
|
3080 + m_size = (BUFF_SIZE(user_parm->size) + IF_UD_ADD(user_parm->connection_type))*duplex_ind; |
|
3081 + ctx->buf[i] = memalign(page_size,m_size); |
|
3082 + if (!ctx->buf[i]) { |
|
3083 + fprintf(stderr, "Couldn't allocate work buf.\n"); |
|
3084 + return NULL; |
|
3085 + } |
|
3086 + memset(ctx->buf[i],0,m_size); |
|
3087 + |
|
3088 + // We dont really want IBV_ACCESS_LOCAL_WRITE, but IB spec says : |
|
3089 + // The Consumer is not allowed to assign Remote Write or Remote Atomic to |
|
3090 + // a Memory Region that has not been assigned Local Write. |
|
3091 + ctx->mr[i] = ibv_reg_mr(ctx->pd, |
|
3092 + ctx->buf[i], |
|
3093 + m_size, |
|
3094 + IBV_ACCESS_REMOTE_WRITE | |
|
3095 + IBV_ACCESS_LOCAL_WRITE); |
|
3096 + |
|
3097 + if (!ctx->mr[i]) { |
|
3098 + fprintf(stderr, "Couldn't allocate MR\n"); |
|
3099 + return NULL; |
|
3100 + } |
|
3101 + } |
|
3102 + |
|
3103 + // Create the CQ according to Client/Server or Duplex setting. |
|
3104 + ctx->cq = ctx_cq_create(ctx->context,ctx->channel,user_parm); |
|
3105 + if (ctx->cq == NULL) { |
|
3106 + fprintf(stderr, "Couldn't create CQ \n"); |
|
3107 + return NULL; |
|
3108 + } |
|
3109 + |
|
3110 + ALLOCATE(ctx->qp,struct ibv_qp*,user_parm->num_of_qps); |
|
3111 + |
|
3112 + for(i=0; i < user_parm->num_of_qps; i++) { |
|
3113 + ctx->qp[i] = ctx_qp_create(ctx->pd,ctx->cq,ctx->cq,user_parm); |
|
3114 + if (ctx->qp[i] == NULL) { |
|
3115 + return NULL; |
|
3116 + } |
|
3117 + |
|
3118 + if(ctx_modify_qp_to_init(ctx->qp[i],user_parm)) { |
|
3119 + return NULL; |
|
3120 + } |
|
3121 + } |
|
3122 + |
|
3123 + return ctx; |
|
3124 +} |
|
3125 + |
|
3126 +/****************************************************************************** |
|
3127 + * |
|
3128 + ******************************************************************************/ |
|
3129 +static int pp_connect_ctx(struct pingpong_context *ctx,int my_psn, |
|
3130 + struct pingpong_dest *dest, |
|
3131 + struct perftest_parameters *user_parm) |
|
3132 +{ |
|
3133 + struct ibv_qp_attr attr; |
|
3134 + memset(&attr, 0, sizeof attr); |
|
3135 + int i; |
|
3136 + |
|
3137 + attr.qp_state = IBV_QPS_RTR; |
|
3138 + attr.path_mtu = user_parm->curr_mtu; |
|
3139 + attr.dest_qp_num = dest->qpn; |
|
3140 + attr.rq_psn = dest->psn; |
|
3141 + attr.ah_attr.dlid = dest->lid; |
|
3142 + if (user_parm->connection_type == RC) { |
|
3143 + attr.max_dest_rd_atomic = 1; |
|
3144 + attr.min_rnr_timer = 12; |
|
3145 + } |
|
3146 + if (user_parm->gid_index < 0) { |
|
3147 + attr.ah_attr.is_global = 0; |
|
3148 + attr.ah_attr.sl = user_parm->sl; |
|
3149 + } else { |
|
3150 + attr.ah_attr.is_global = 1; |
|
3151 + attr.ah_attr.grh.dgid = dest->gid; |
|
3152 + attr.ah_attr.grh.sgid_index = user_parm->gid_index; |
|
3153 + attr.ah_attr.grh.hop_limit = 1; |
|
3154 + attr.ah_attr.sl = 0; |
|
3155 + } |
|
3156 + attr.ah_attr.src_path_bits = 0; |
|
3157 + attr.ah_attr.port_num = user_parm->ib_port; |
|
3158 + |
|
3159 + if (user_parm->connection_type == RC) { |
|
3160 + if (ibv_modify_qp(ctx->qp[0], &attr, |
|
3161 + IBV_QP_STATE | |
|
3162 + IBV_QP_AV | |
|
3163 + IBV_QP_PATH_MTU | |
|
3164 + IBV_QP_DEST_QPN | |
|
3165 + IBV_QP_RQ_PSN | |
|
3166 + IBV_QP_MIN_RNR_TIMER | |
|
3167 + IBV_QP_MAX_DEST_RD_ATOMIC)) { |
|
3168 + fprintf(stderr, "Failed to modify RC QP to RTR\n"); |
|
3169 + return 1; |
|
3170 + } |
|
3171 + attr.timeout = user_parm->qp_timeout; |
|
3172 + attr.retry_cnt = 7; |
|
3173 + attr.rnr_retry = 7; |
|
3174 + } else if (user_parm->connection_type == UC) { |
|
3175 + if (ibv_modify_qp(ctx->qp[0], &attr, |
|
3176 + IBV_QP_STATE | |
|
3177 + IBV_QP_AV | |
|
3178 + IBV_QP_PATH_MTU | |
|
3179 + IBV_QP_DEST_QPN | |
|
3180 + IBV_QP_RQ_PSN)) { |
|
3181 + fprintf(stderr, "Failed to modify UC QP to RTR\n"); |
|
3182 + return 1; |
|
3183 + } |
|
3184 + } |
|
3185 + |
|
3186 + else { |
|
3187 + for (i = 0; i < user_parm->num_of_qps; i++) { |
|
3188 + if (ibv_modify_qp(ctx->qp[i],&attr,IBV_QP_STATE )) { |
|
3189 + fprintf(stderr, "Failed to modify UD QP to RTR\n"); |
|
3190 + return 1; |
|
3191 + } |
|
3192 + } |
|
3193 + if (user_parm->machine == CLIENT || user_parm->duplex) { |
|
3194 + ctx->ah = ibv_create_ah(ctx->pd,&attr.ah_attr); |
|
3195 + if (!ctx->ah) { |
|
3196 + fprintf(stderr, "Failed to create AH for UD\n"); |
|
3197 + return 1; |
|
3198 + } |
|
3199 + } |
|
3200 + } |
|
3201 + |
|
3202 + if (user_parm->machine == CLIENT || user_parm->duplex) { |
|
3203 + |
|
3204 + attr.qp_state = IBV_QPS_RTS; |
|
3205 + attr.sq_psn = my_psn; |
|
3206 + if (user_parm->connection_type == RC) { |
|
3207 + attr.max_rd_atomic = 1; |
|
3208 + if (ibv_modify_qp(ctx->qp[0], &attr, |
|
3209 + IBV_QP_STATE | |
|
3210 + IBV_QP_SQ_PSN | |
|
3211 + IBV_QP_TIMEOUT | |
|
3212 + IBV_QP_RETRY_CNT | |
|
3213 + IBV_QP_RNR_RETRY | |
|
3214 + IBV_QP_MAX_QP_RD_ATOMIC)) { |
|
3215 + fprintf(stderr, "Failed to modify RC QP to RTS\n"); |
|
3216 + return 1; |
|
3217 + } |
|
3218 + |
|
3219 + } else { |
|
3220 + if(ibv_modify_qp(ctx->qp[0],&attr,IBV_QP_STATE |IBV_QP_SQ_PSN)) { |
|
3221 + fprintf(stderr, "Failed to modify UC QP to RTS\n"); |
|
3222 + return 1; |
|
3223 + } |
|
3224 + } |
|
3225 + } |
|
3226 + |
|
3227 + return 0; |
|
3228 +} |
|
3229 + |
|
3230 +/****************************************************************************** |
|
3231 + * |
|
3232 + ******************************************************************************/ |
|
3233 +static int set_recv_wqes(struct pingpong_context *ctx, |
|
3234 + struct perftest_parameters *user_param) { |
|
3235 + |
|
3236 + int i,j,buff_size; |
|
3237 + int duplex_ind; |
|
3238 + struct ibv_recv_wr *bad_wr_recv; |
|
3239 + |
|
3240 + i = (user_param->duplex && user_param->use_mcg) ? 1 : 0; |
|
3241 + duplex_ind = (user_param->duplex && !user_param->use_mcg) ? 1 : 0; |
|
3242 + |
|
3243 + buff_size = BUFF_SIZE(ctx->size) + IF_UD_ADD(user_param->connection_type); |
|
3244 + |
|
3245 + while (i < user_param->num_of_qps) { |
|
3246 + |
|
3247 + ctx->sge_list[i].addr = (uintptr_t)ctx->buf[i] + duplex_ind*buff_size; |
|
3248 + |
|
3249 + if (user_param->connection_type == UD) |
|
3250 + ctx->sge_list[i].addr += (CACHE_LINE_SIZE - UD_ADDITION); |
|
3251 + |
|
3252 + ctx->sge_list[i].length = SIZE(user_param->connection_type,user_param->size); |
|
3253 + ctx->sge_list[i].lkey = ctx->mr[i]->lkey; |
|
3254 + ctx->rwr[i].sg_list = &ctx->sge_list[i]; |
|
3255 + ctx->rwr[i].wr_id = i; |
|
3256 + ctx->rwr[i].next = NULL; |
|
3257 + ctx->rwr[i].num_sge = MAX_RECV_SGE; |
|
3258 + ctx->my_addr[i] = (uintptr_t)ctx->buf[i] + duplex_ind*buff_size; |
|
3259 + |
|
3260 + for (j = 0; j < user_param->rx_depth; ++j) { |
|
3261 + |
|
3262 + if (ibv_post_recv(ctx->qp[i],&ctx->rwr[i],&bad_wr_recv)) { |
|
3263 + fprintf(stderr, "Couldn't post recv Qp = %d: counter=%d\n",i,j); |
|
3264 + return 1; |
|
3265 + } |
|
3266 + |
|
3267 + if (user_param->size <= (CYCLE_BUFFER / 2)) |
|
3268 + increase_loc_addr(&ctx->sge_list[i],user_param->size,j,ctx->my_addr[i],user_param->connection_type); |
|
3269 + } |
|
3270 + i++; |
|
3271 + } |
|
3272 + return 0; |
|
3273 +} |
|
3274 + |
|
3275 +/****************************************************************************** |
|
3276 + * |
|
3277 + ******************************************************************************/ |
|
3278 +static void set_send_wqe(struct pingpong_context *ctx,int rem_qpn, |
|
3279 + struct perftest_parameters *user_param) { |
|
3280 + |
|
3281 + ctx->list.addr = (uintptr_t)ctx->buf[0]; |
|
3282 + ctx->list.lkey = ctx->mr[0]->lkey; |
|
3283 + |
|
3284 + ctx->wr.sg_list = &ctx->list; |
|
3285 + ctx->wr.num_sge = 1; |
|
3286 + ctx->wr.opcode = IBV_WR_SEND; |
|
3287 + ctx->wr.next = NULL; |
|
3288 + ctx->wr.wr_id = PINGPONG_SEND_WRID; |
|
3289 + ctx->wr.send_flags = IBV_SEND_SIGNALED; |
|
3290 + |
|
3291 + if (user_param->connection_type == UD) { |
|
3292 + ctx->wr.wr.ud.ah = ctx->ah; |
|
3293 + ctx->wr.wr.ud.remote_qkey = DEF_QKEY; |
|
3294 + ctx->wr.wr.ud.remote_qpn = rem_qpn; |
|
3295 + } |
|
3296 +} |
|
3297 + |
|
3298 +/****************************************************************************** |
|
3299 + * |
|
3300 + ******************************************************************************/ |
|
3301 +static int pp_drain_qp(struct pingpong_context *ctx, |
|
3302 + struct perftest_parameters *user_param, |
|
3303 + int psn,struct pingpong_dest *dest, |
|
3304 + struct mcast_parameters *mcg_params) { |
|
3305 + |
|
3306 + struct ibv_qp_attr attr; |
|
3307 + struct ibv_wc wc; |
|
3308 + int i; |
|
3309 + |
|
3310 + memset(&attr, 0, sizeof attr); |
|
3311 + attr.qp_state = IBV_QPS_ERR; |
|
3312 + |
|
3313 + for (i = 0; i < user_param->num_of_qps; i++) { |
|
3314 + |
|
3315 + if (ibv_modify_qp(ctx->qp[i],&attr,IBV_QP_STATE)) { |
|
3316 + fprintf(stderr, "Failed to modify RC QP to ERR\n"); |
|
3317 + return 1; |
|
3318 + } |
|
3319 + |
|
3320 + while (ibv_poll_cq(ctx->cq,1,&wc)); |
|
3321 + |
|
3322 + attr.qp_state = IBV_QPS_RESET; |
|
3323 + |
|
3324 + if (ibv_modify_qp(ctx->qp[i],&attr,IBV_QP_STATE)) { |
|
3325 + fprintf(stderr, "Failed to modify RC QP to RESET\n"); |
|
3326 + return 1; |
|
3327 + } |
|
3328 + |
|
3329 + if(ctx_modify_qp_to_init(ctx->qp[i],user_param)) { |
|
3330 + return 1; |
|
3331 + } |
|
3332 + |
|
3333 + if (user_param->use_mcg) { |
|
3334 + |
|
3335 + if ((!user_param->duplex && user_param->machine == SERVER) || (user_param->duplex && i > 0)) { |
|
3336 + if (ibv_attach_mcast(ctx->qp[i],&mcg_params->mgid,mcg_params->mlid)) { |
|
3337 + fprintf(stderr, "Couldn't attach QP to MultiCast group"); |
|
3338 + return 1; |
|
3339 + } |
|
3340 + } |
|
3341 + } |
|
3342 + } |
|
3343 + |
|
3344 + if (pp_connect_ctx(ctx,psn,dest,user_param)) { |
|
3345 + return 1; |
|
3346 + } |
|
3347 + |
|
3348 + return 0; |
|
3349 +} |
|
3350 + |
|
3351 +/****************************************************************************** |
|
3352 + * |
|
3353 + ******************************************************************************/ |
|
3354 +static void print_report(struct perftest_parameters *user_param) { |
|
3355 + |
|
3356 + double cycles_to_units; |
|
3357 + unsigned long tsize; /* Transferred size, in megabytes */ |
|
3358 + int i, j; |
|
3359 + int opt_posted = 0, opt_completed = 0; |
|
3360 + cycles_t opt_delta; |
|
3361 + cycles_t t; |
|
3362 + |
|
3363 + |
|
3364 + opt_delta = tcompleted[opt_posted] - tposted[opt_completed]; |
|
3365 + |
|
3366 + if (user_param->noPeak == OFF) { |
|
3367 + /* Find the peak bandwidth, unless asked not to in command line */ |
|
3368 + for (i = 0; i < user_param->iters; ++i) |
|
3369 + for (j = i; j < user_param->iters; ++j) { |
|
3370 + t = (tcompleted[j] - tposted[i]) / (j - i + 1); |
|
3371 + if (t < opt_delta) { |
|
3372 + opt_delta = t; |
|
3373 + opt_posted = i; |
|
3374 + opt_completed = j; |
|
3375 + } |
|
3376 + } |
|
3377 + } |
|
3378 + |
|
3379 +#if !(defined(__SVR4) && defined(__sun)) |
|
3380 + cycles_to_units = get_cpu_mhz(user_param->cpu_freq_f) * 1000000; |
|
3381 +#else |
1580 +#else |
3382 + cycles_to_units = 1000000000; |
1581 + cycles_to_units = 1000000000; |
3383 +#endif |
1582 +#endif |
3384 + |
1583 |
3385 + tsize = user_param->duplex ? 2 : 1; |
1584 tsize = user_param->duplex ? 2 : 1; |
3386 + tsize = tsize * user_param->size; |
1585 tsize = tsize * user_param->size; |
3387 + printf(REPORT_FMT,user_param->size,user_param->iters,(user_param->noPeak == OFF) * tsize * cycles_to_units / opt_delta / 0x100000, |
|
3388 + tsize * user_param->iters * cycles_to_units /(tcompleted[user_param->iters - 1] - tposted[0]) / 0x100000); |
|
3389 +} |
|
3390 + |
|
3391 +/****************************************************************************** |
|
3392 + * Important note : |
|
3393 + * In case of UD/UC this is NOT the way to measureBW since we are running with |
|
3394 + * loop on the send side , while we should run on the recieve side or enable |
|
3395 + * retry in SW , Since the sender may be faster than the reciver. |
|
3396 + * Although we had posted recieve it is not enough and might end this will |
|
3397 + * result in deadlock of test since both sides are stuck on poll cq. |
|
3398 + * In this test i do not solve this for the general test ,need to write |
|
3399 + * seperate test for UC/UD but in case the tx_depth is ~1/3 from the |
|
3400 + * number of iterations this should be ok . |
|
3401 + * Also note that the sender is limited in the number of send, ans |
|
3402 + * i try to make the reciver full . |
|
3403 + ******************************************************************************/ |
|
3404 +int run_iter_bi(struct pingpong_context *ctx, |
|
3405 + struct perftest_parameters *user_param) { |
|
3406 + |
|
3407 + int scnt = 0; |
|
3408 + int ccnt = 0; |
|
3409 + int rcnt = 0; |
|
3410 + int i = 0; |
|
3411 + int num_of_qps = user_param->num_of_qps; |
|
3412 + int ne; |
|
3413 + struct ibv_wc *wc = NULL; |
|
3414 + int *rcnt_for_qp = NULL; |
|
3415 + struct ibv_recv_wr *bad_wr_recv = NULL; |
|
3416 + struct ibv_send_wr *bad_wr = NULL; |
|
3417 + |
|
3418 + ALLOCATE(rcnt_for_qp,int,user_param->num_of_qps); |
|
3419 + ALLOCATE(wc,struct ibv_wc,DEF_WC_SIZE); |
|
3420 + memset(rcnt_for_qp,0,sizeof(int)*user_param->num_of_qps); |
|
3421 + |
|
3422 + if (user_param->use_mcg) |
|
3423 + num_of_qps--; |
|
3424 + |
|
3425 + // Set the length of the scatter in case of ALL option. |
|
3426 + ctx->list.length = user_param->size; |
|
3427 + ctx->list.addr = (uintptr_t)ctx->buf[0]; |
|
3428 + ctx->wr.send_flags = IBV_SEND_SIGNALED; |
|
3429 + |
|
3430 + if (user_param->size <= user_param->inline_size) |
|
3431 + ctx->wr.send_flags |= IBV_SEND_INLINE; |
|
3432 + |
|
3433 + while (ccnt < user_param->iters || rcnt < user_param->iters) { |
|
3434 + |
|
3435 + while (scnt < user_param->iters && (scnt - ccnt) < user_param->tx_depth / 2) { |
|
3436 + |
|
3437 + if (scnt % CQ_MODERATION == 0 && CQ_MODERATION > 1) |
|
3438 + ctx->wr.send_flags &= ~IBV_SEND_SIGNALED; |
|
3439 + |
|
3440 + tposted[scnt] = get_cycles(); |
|
3441 + if (ibv_post_send(ctx->qp[0],&ctx->wr, &bad_wr)) { |
|
3442 + fprintf(stderr, "Couldn't post send: scnt=%d\n",scnt); |
|
3443 + return 1; |
|
3444 + } |
|
3445 + |
|
3446 + if (user_param->size <= (CYCLE_BUFFER / 2)) |
|
3447 + increase_loc_addr(&ctx->list,user_param->size,scnt,(uintptr_t)ctx->buf[0],0); |
|
3448 + |
|
3449 + ++scnt; |
|
3450 + |
|
3451 + if ((scnt % CQ_MODERATION) == (CQ_MODERATION - 1) || scnt == (user_param->iters - 1)) |
|
3452 + ctx->wr.send_flags |= IBV_SEND_SIGNALED; |
|
3453 + } |
|
3454 + |
|
3455 + if (user_param->use_event) { |
|
3456 + |
|
3457 + if (ctx_notify_events(ctx->cq,ctx->channel)) { |
|
3458 + fprintf(stderr,"Failed to notify events to CQ"); |
|
3459 + return 1; |
|
3460 + } |
|
3461 + } |
|
3462 + |
|
3463 + do { |
|
3464 + ne = ibv_poll_cq(ctx->cq,DEF_WC_SIZE,wc); |
|
3465 + if (ne > 0) { |
|
3466 + for (i = 0; i < ne; i++) { |
|
3467 + |
|
3468 + if (wc[i].status != IBV_WC_SUCCESS) |
|
3469 + NOTIFY_COMP_ERROR_SEND(wc[i],scnt,ccnt); |
|
3470 + |
|
3471 + if ((int) wc[i].wr_id == PINGPONG_SEND_WRID) { |
|
3472 + ccnt += CQ_MODERATION; |
|
3473 + if (ccnt >= user_param->iters - 1) |
|
3474 + tcompleted[user_param->iters - 1] = get_cycles(); |
|
3475 + |
|
3476 + else |
|
3477 + tcompleted[ccnt - 1] = get_cycles(); |
|
3478 + } |
|
3479 + |
|
3480 + else { |
|
3481 + |
|
3482 + rcnt_for_qp[wc[i].wr_id]++; |
|
3483 + rcnt++; |
|
3484 + if (ibv_post_recv(ctx->qp[wc[i].wr_id],&ctx->rwr[wc[i].wr_id],&bad_wr_recv)) { |
|
3485 + fprintf(stderr, "Couldn't post recv Qp=%d rcnt=%d\n",(int)wc[i].wr_id , rcnt_for_qp[wc[i].wr_id]); |
|
3486 + return 15; |
|
3487 + } |
|
3488 + |
|
3489 + if (user_param->size <= (CYCLE_BUFFER / 2)) |
|
3490 + increase_loc_addr(&ctx->sge_list[wc[i].wr_id], |
|
3491 + user_param->size,rcnt_for_qp[wc[i].wr_id] + user_param->rx_depth - 1, |
|
3492 + ctx->my_addr[wc[i].wr_id],user_param->connection_type); |
|
3493 + } |
|
3494 + } |
|
3495 + } |
|
3496 + } while (ne > 0); |
|
3497 + |
|
3498 + if (ne < 0) { |
|
3499 + fprintf(stderr, "poll CQ failed %d\n", ne); |
|
3500 + return 1; |
|
3501 + } |
|
3502 + } |
|
3503 + |
|
3504 + if (user_param->size <= user_param->inline_size) |
|
3505 + ctx->wr.send_flags &= ~IBV_SEND_INLINE; |
|
3506 + |
|
3507 + free(rcnt_for_qp); |
|
3508 + free(wc); |
|
3509 + return 0; |
|
3510 +} |
|
3511 + |
|
3512 +/****************************************************************************** |
|
3513 + * |
|
3514 + ******************************************************************************/ |
|
3515 +int run_iter_uni_server(struct pingpong_context *ctx, |
|
3516 + struct perftest_parameters *user_param) { |
|
3517 + |
|
3518 + int rcnt = 0; |
|
3519 + int ne,i; |
|
3520 + int *rcnt_for_qp = NULL; |
|
3521 + struct ibv_wc *wc = NULL; |
|
3522 + struct ibv_recv_wr *bad_wr_recv = NULL; |
|
3523 + |
|
3524 + ALLOCATE(wc,struct ibv_wc,DEF_WC_SIZE); |
|
3525 + ALLOCATE(rcnt_for_qp,int,user_param->num_of_qps); |
|
3526 + |
|
3527 + memset(rcnt_for_qp,0,sizeof(int)*user_param->num_of_qps); |
|
3528 + |
|
3529 + while (rcnt < user_param->iters) { |
|
3530 + |
|
3531 + if (user_param->use_event) { |
|
3532 + if (ctx_notify_events(ctx->cq,ctx->channel)) { |
|
3533 + fprintf(stderr ," Failed to notify events to CQ"); |
|
3534 + return 1; |
|
3535 + } |
|
3536 + } |
|
3537 + |
|
3538 + do { |
|
3539 + ne = ibv_poll_cq(ctx->cq,DEF_WC_SIZE,wc); |
|
3540 + if (ne > 0) { |
|
3541 + for (i = 0; i < ne; i++) { |
|
3542 + |
|
3543 + if (wc[i].status != IBV_WC_SUCCESS) |
|
3544 + NOTIFY_COMP_ERROR_RECV(wc[i],rcnt_for_qp[wc[i].wr_id]); |
|
3545 + |
|
3546 + rcnt_for_qp[wc[i].wr_id]++; |
|
3547 + tcompleted[rcnt++] = get_cycles(); |
|
3548 + |
|
3549 + if (ibv_post_recv(ctx->qp[wc[i].wr_id],&ctx->rwr[wc[i].wr_id],&bad_wr_recv)) { |
|
3550 + fprintf(stderr, "Couldn't post recv Qp=%d rcnt=%d\n",(int)wc[i].wr_id,rcnt_for_qp[wc[i].wr_id]); |
|
3551 + return 15; |
|
3552 + } |
|
3553 + |
|
3554 + if (user_param->size <= (CYCLE_BUFFER / 2)) |
|
3555 + increase_loc_addr(&ctx->sge_list[wc[i].wr_id],user_param->size, |
|
3556 + rcnt_for_qp[wc[i].wr_id] + user_param->rx_depth, |
|
3557 + ctx->my_addr[wc[i].wr_id],user_param->connection_type); |
|
3558 + } |
|
3559 + } |
|
3560 + } while (ne > 0); |
|
3561 + |
|
3562 + if (ne < 0) { |
|
3563 + fprintf(stderr, "Poll Recieve CQ failed %d\n", ne); |
|
3564 + return 1; |
|
3565 + } |
|
3566 + } |
|
3567 + |
|
3568 + tposted[0] = tcompleted[0]; |
|
3569 + free(wc); |
|
3570 + free(rcnt_for_qp); |
|
3571 + return 0; |
|
3572 +} |
|
3573 + |
|
3574 +/****************************************************************************** |
|
3575 + * |
|
3576 + ******************************************************************************/ |
|
3577 +int run_iter_uni_client(struct pingpong_context *ctx, |
|
3578 + struct perftest_parameters *user_param) { |
|
3579 + |
|
3580 + int ne; |
|
3581 + int i = 0; |
|
3582 + int scnt = 0; |
|
3583 + int ccnt = 0; |
|
3584 + struct ibv_wc *wc = NULL; |
|
3585 + struct ibv_send_wr *bad_wr = NULL; |
|
3586 + |
|
3587 + ALLOCATE(wc,struct ibv_wc,DEF_WC_SIZE); |
|
3588 + |
|
3589 + // Set the lenght of the scatter in case of ALL option. |
|
3590 + ctx->list.length = user_param->size; |
|
3591 + ctx->list.addr = (uintptr_t)ctx->buf[0]; |
|
3592 + ctx->wr.send_flags = IBV_SEND_SIGNALED; |
|
3593 + |
|
3594 + if (user_param->size <= user_param->inline_size) |
|
3595 + ctx->wr.send_flags |= IBV_SEND_INLINE; |
|
3596 + |
|
3597 + |
|
3598 + while (scnt < user_param->iters || ccnt < user_param->iters) { |
|
3599 + while (scnt < user_param->iters && (scnt - ccnt) < user_param->tx_depth ) { |
|
3600 + |
|
3601 + if (scnt % CQ_MODERATION == 0 && CQ_MODERATION > 1) |
|
3602 + ctx->wr.send_flags &= ~IBV_SEND_SIGNALED; |
|
3603 + |
|
3604 + tposted[scnt] = get_cycles(); |
|
3605 + if (ibv_post_send(ctx->qp[0], &ctx->wr, &bad_wr)) { |
|
3606 + fprintf(stderr, "Couldn't post send: scnt=%d\n",scnt); |
|
3607 + return 1; |
|
3608 + } |
|
3609 + |
|
3610 + if (user_param->size <= (CYCLE_BUFFER / 2)) |
|
3611 + increase_loc_addr(&ctx->list,user_param->size,scnt,(uintptr_t)ctx->buf[0],0); |
|
3612 + |
|
3613 + scnt++; |
|
3614 + |
|
3615 + if ((scnt % CQ_MODERATION) == (CQ_MODERATION - 1) || scnt == (user_param->iters - 1)) |
|
3616 + ctx->wr.send_flags |= IBV_SEND_SIGNALED; |
|
3617 + } |
|
3618 + |
|
3619 + if (ccnt < user_param->iters) { |
|
3620 + |
|
3621 + if (user_param->use_event) { |
|
3622 + if (ctx_notify_events(ctx->cq,ctx->channel)) { |
|
3623 + fprintf(stderr , " Failed to notify events to CQ"); |
|
3624 + return 1; |
|
3625 + } |
|
3626 + } |
|
3627 + do { |
|
3628 + ne = ibv_poll_cq(ctx->cq,DEF_WC_SIZE,wc); |
|
3629 + if (ne > 0) { |
|
3630 + for (i = 0; i < DEF_WC_SIZE; i++) { |
|
3631 + |
|
3632 + if (wc[i].status != IBV_WC_SUCCESS) |
|
3633 + NOTIFY_COMP_ERROR_SEND(wc[i],scnt,ccnt); |
|
3634 + |
|
3635 + ccnt += CQ_MODERATION; |
|
3636 + if (ccnt >= user_param->iters - 1) |
|
3637 + tcompleted[user_param->iters - 1] = get_cycles(); |
|
3638 + |
|
3639 + else |
|
3640 + tcompleted[ccnt - 1] = get_cycles(); |
|
3641 + } |
|
3642 + } |
|
3643 + |
|
3644 + |
|
3645 + } while (ne > 0); |
|
3646 + |
|
3647 + if (ne < 0) { |
|
3648 + fprintf(stderr, "poll CQ failed\n"); |
|
3649 + return 1; |
|
3650 + } |
|
3651 + } |
|
3652 + } |
|
3653 + |
|
3654 + if (user_param->size <= user_param->inline_size) |
|
3655 + ctx->wr.send_flags &= ~IBV_SEND_INLINE; |
|
3656 + |
|
3657 + free(wc); |
|
3658 + return 0; |
|
3659 +} |
|
3660 + |
|
3661 +/****************************************************************************** |
|
3662 + * |
|
3663 + ******************************************************************************/ |
|
3664 +int main(int argc, char *argv[]) |
|
3665 +{ |
|
3666 + struct ibv_device *ib_dev = NULL; |
|
3667 + struct pingpong_context *ctx; |
|
3668 + struct pingpong_dest my_dest,rem_dest; |
|
3669 + struct perftest_parameters user_param; |
|
3670 + struct mcast_parameters mcg_params; |
|
3671 + int i = 0; |
|
3672 + int size_max_pow = 24; |
|
3673 + int size_of_arr; |
|
3674 + |
|
3675 + // Pointer to The relevent function of run_iter according to machine type. |
|
3676 + int (*ptr_to_run_iter_uni)(struct pingpong_context*,struct perftest_parameters*); |
|
3677 + |
|
3678 + /* init default values to user's parameters */ |
|
3679 + memset(&user_param, 0 , sizeof(struct perftest_parameters)); |
|
3680 + memset(&mcg_params, 0 , sizeof(struct mcast_parameters)); |
|
3681 + memset(&my_dest , 0 , sizeof(struct pingpong_dest)); |
|
3682 + memset(&rem_dest , 0 , sizeof(struct pingpong_dest)); |
|
3683 + |
|
3684 + user_param.verb = SEND; |
|
3685 + user_param.tst = BW; |
|
3686 + user_param.version = VERSION; |
|
3687 + |
|
3688 + if (parser(&user_param,argv,argc)) |
|
3689 + return 1; |
|
3690 + |
|
3691 + printf(RESULT_LINE); |
|
3692 + |
|
3693 + user_param.rx_depth = (user_param.iters < user_param.rx_depth) ? user_param.iters : user_param.rx_depth ; |
|
3694 + |
|
3695 + if (user_param.use_mcg) { |
|
3696 + |
|
3697 + user_param.connection_type = UD; |
|
3698 + if (user_param.duplex) { |
|
3699 + user_param.num_of_qps++; |
|
3700 + printf(" Send Bidirectional BW - Multicast Test\n"); |
|
3701 + } |
|
3702 + else { |
|
3703 + printf(" Send BW - Multicast Test\n"); |
|
3704 + if (user_param.machine == CLIENT) |
|
3705 + user_param.num_of_qps = 1; |
|
3706 + } |
|
3707 + } |
|
3708 + |
|
3709 + else if (user_param.duplex) { |
|
3710 + printf(" Send Bidirectional BW Test\n"); |
|
3711 + } else |
|
3712 + printf(" Send BW Test\n"); |
|
3713 + |
|
3714 + if (user_param.use_event) |
|
3715 + printf(" Test with events.\n"); |
|
3716 + |
|
3717 + if (user_param.connection_type == RC) |
|
3718 + printf(" Connection type : RC\n"); |
|
3719 + else if (user_param.connection_type == UC) |
|
3720 + printf(" Connection type : UC\n"); |
|
3721 + else{ |
|
3722 + printf(" Connection type : UD\n"); |
|
3723 + } |
|
3724 + |
|
3725 + // Done with parameter parsing. Perform setup. |
|
3726 + if (user_param.all == ON) { |
|
3727 + // since we run all sizes |
|
3728 + user_param.size = MAX_SIZE; |
|
3729 + } |
|
3730 + |
|
3731 + srand48(getpid() * time(NULL)); |
|
3732 + page_size = sysconf(_SC_PAGESIZE); |
|
3733 + |
|
3734 + ib_dev = ctx_find_dev(user_param.ib_devname); |
|
3735 + if (!ib_dev) |
|
3736 + return 7; |
|
3737 + |
|
3738 + mcg_params.ib_devname = ibv_get_device_name(ib_dev); |
|
3739 + |
|
3740 + ctx = pp_init_ctx(ib_dev,&user_param); |
|
3741 + if (!ctx) |
|
3742 + return 1; |
|
3743 + |
|
3744 + // Set up the Connection. |
|
3745 + if (set_up_connection(ctx,&user_param,&my_dest,&mcg_params)) { |
|
3746 + fprintf(stderr," Unable to set up socket connection\n"); |
|
3747 + return 1; |
|
3748 + } |
|
3749 + |
|
3750 + // Init the connection and print the local data. |
|
3751 + if (init_connection(&user_param,&my_dest)) { |
|
3752 + fprintf(stderr," Unable to init the socket connection\n"); |
|
3753 + return 1; |
|
3754 + } |
|
3755 + |
|
3756 + // shaking hands and gather the other side info. |
|
3757 + if (ctx_hand_shake(&user_param,&my_dest,&rem_dest)) { |
|
3758 + fprintf(stderr,"Failed to exchange date between server and clients\n"); |
|
3759 + return 1; |
|
3760 + |
|
3761 + } |
|
3762 + // For printing only MGID in the remote side. |
|
3763 + user_param.side = REMOTE; |
|
3764 + ctx_print_pingpong_data(&rem_dest,&user_param); |
|
3765 + |
|
3766 + // Joining the Send side port the Mcast gid |
|
3767 + if (user_param.use_mcg && (user_param.machine == CLIENT || user_param.duplex)) { |
|
3768 + memcpy(mcg_params.mgid.raw, rem_dest.gid.raw, 16); |
|
3769 + if (set_mcast_group(ctx,&user_param,&mcg_params)) { |
|
3770 + fprintf(stderr," Unable to Join Sender to Mcast gid\n"); |
|
3771 + return 1; |
|
3772 + } |
|
3773 + } |
|
3774 + |
|
3775 + // Prepare IB resources for rtr/rts. |
|
3776 + if (pp_connect_ctx(ctx,my_dest.psn,&rem_dest,&user_param)) { |
|
3777 + fprintf(stderr," Unable to Connect the HCA's through the link\n"); |
|
3778 + return 1; |
|
3779 + } |
|
3780 + |
|
3781 + // shaking hands and gather the other side info. |
|
3782 + if (ctx_hand_shake(&user_param,&my_dest,&rem_dest)) { |
|
3783 + fprintf(stderr,"Failed to exchange date between server and clients\n"); |
|
3784 + return 1; |
|
3785 + |
|
3786 + } |
|
3787 + |
|
3788 + if (user_param.use_event) { |
|
3789 + if (ibv_req_notify_cq(ctx->cq, 0)) { |
|
3790 + fprintf(stderr, " Couldn't request CQ notification\n"); |
|
3791 + return 1; |
|
3792 + } |
|
3793 + } |
|
3794 + |
|
3795 + printf(RESULT_LINE); |
|
3796 + printf(RESULT_FMT); |
|
3797 + |
|
3798 + size_of_arr = (user_param.duplex) ? 1 : user_param.num_of_qps; |
|
3799 + |
|
3800 + ALLOCATE(tposted,cycles_t,user_param.iters*size_of_arr); |
|
3801 + ALLOCATE(tcompleted,cycles_t,user_param.iters*size_of_arr); |
|
3802 + |
|
3803 + if (user_param.machine == SERVER || user_param.duplex) { |
|
3804 + ALLOCATE(ctx->rwr,struct ibv_recv_wr,user_param.num_of_qps); |
|
3805 + ALLOCATE(ctx->sge_list,struct ibv_sge,user_param.num_of_qps); |
|
3806 + ALLOCATE(ctx->my_addr ,uint64_t ,user_param.num_of_qps); |
|
3807 + } |
|
3808 + |
|
3809 + ptr_to_run_iter_uni = (user_param.machine == CLIENT) ? &run_iter_uni_client : &run_iter_uni_server; |
|
3810 + |
|
3811 + if (user_param.machine == SERVER && !user_param.duplex) { |
|
3812 + user_param.noPeak = ON; |
|
3813 + } |
|
3814 + |
|
3815 + if (user_param.machine == CLIENT || user_param.duplex) { |
|
3816 + set_send_wqe(ctx,rem_dest.qpn,&user_param); |
|
3817 + } |
|
3818 + |
|
3819 + if (user_param.all == ON) { |
|
3820 + |
|
3821 + if (user_param.connection_type == UD) |
|
3822 + size_max_pow = (int)UD_MSG_2_EXP(MTU_SIZE(user_param.curr_mtu)) + 1; |
|
3823 + |
|
3824 + for (i = 1; i < size_max_pow ; ++i) { |
|
3825 + user_param.size = 1 << i; |
|
3826 + |
|
3827 + if (user_param.machine == SERVER || user_param.duplex) { |
|
3828 + if (set_recv_wqes(ctx,&user_param)) { |
|
3829 + fprintf(stderr," Failed to post receive recv_wqes\n"); |
|
3830 + return 1; |
|
3831 + } |
|
3832 + } |
|
3833 + |
|
3834 + if (ctx_hand_shake(&user_param,&my_dest,&rem_dest)) { |
|
3835 + fprintf(stderr,"Failed to exchange date between server and clients\n"); |
|
3836 + return 1; |
|
3837 + } |
|
3838 + |
|
3839 + if (user_param.duplex) { |
|
3840 + if(run_iter_bi(ctx,&user_param)) |
|
3841 + return 17; |
|
3842 + } else { |
|
3843 + if((*ptr_to_run_iter_uni)(ctx,&user_param)) |
|
3844 + return 17; |
|
3845 + } |
|
3846 + print_report(&user_param); |
|
3847 + |
|
3848 + if (pp_drain_qp(ctx,&user_param,my_dest.psn,&rem_dest,&mcg_params)) { |
|
3849 + fprintf(stderr,"Failed to drain Recv queue (performance optimization)\n"); |
|
3850 + return 1; |
|
3851 + } |
|
3852 + |
|
3853 + if (ctx_hand_shake(&user_param,&my_dest,&rem_dest)) { |
|
3854 + fprintf(stderr,"Failed to exchange date between server and clients\n"); |
|
3855 + return 1; |
|
3856 + } |
|
3857 + |
|
3858 + } |
|
3859 + |
|
3860 + } else { |
|
3861 + |
|
3862 + if (user_param.machine == SERVER || user_param.duplex) { |
|
3863 + if (set_recv_wqes(ctx,&user_param)) { |
|
3864 + fprintf(stderr," Failed to post receive recv_wqes\n"); |
|
3865 + return 1; |
|
3866 + } |
|
3867 + } |
|
3868 + |
|
3869 + if (ctx_hand_shake(&user_param,&my_dest,&rem_dest)) { |
|
3870 + fprintf(stderr,"Failed to exchange date between server and clients\n"); |
|
3871 + return 1; |
|
3872 + } |
|
3873 + |
|
3874 + if (user_param.duplex) { |
|
3875 + if(run_iter_bi(ctx,&user_param)) |
|
3876 + return 18; |
|
3877 + |
|
3878 + } else { |
|
3879 + if((*ptr_to_run_iter_uni)(ctx,&user_param)) |
|
3880 + return 18; |
|
3881 + } |
|
3882 + |
|
3883 + print_report(&user_param); |
|
3884 + } |
|
3885 + |
|
3886 + if (ctx_close_connection(&user_param,&my_dest,&rem_dest)) { |
|
3887 + fprintf(stderr," Failed to close connection between server and client\n"); |
|
3888 + return 1; |
|
3889 + } |
|
3890 + |
|
3891 + printf(RESULT_LINE); |
|
3892 + return destroy_ctx_resources(ctx,&user_param,&my_dest,&rem_dest,&mcg_params); |
|
3893 +} |
|
3894 diff -r -u /tmp/perftest-1.3.0/send_lat.c perftest-1.3.0/send_lat.c |
1586 diff -r -u /tmp/perftest-1.3.0/send_lat.c perftest-1.3.0/send_lat.c |
3895 --- /tmp/perftest-1.3.0/send_lat.c Wed Mar 2 16:04:50 2011 |
1587 --- /tmp/perftest-1.3.0/send_lat.c Wed Mar 2 16:04:50 2011 |
3896 +++ perftest-1.3.0/send_lat.c Fri Aug 26 05:29:53 2011 |
1588 +++ perftest-1.3.0/send_lat.c Fri Aug 26 05:29:53 2011 |
3897 @@ -61,7 +61,8 @@ |
1589 @@ -61,7 +61,8 @@ |
3898 struct ibv_sge *sge_list; |
1590 struct ibv_sge *sge_list; |