aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband/core/mad.c
diff options
context:
space:
mode:
authorJack Morgenstein <jackm@mellanox.co.il>2006-06-17 23:37:34 -0400
committerRoland Dreier <rolandd@cisco.com>2006-06-17 23:37:34 -0400
commit9874e746550fbd366484621b8838b98589bb2a15 (patch)
tree8927d1f6a2c082591a539e42202c3b266a684ae0 /drivers/infiniband/core/mad.c
parent6fb9cdbf2cdb2ea187e57ec2e16cc59df2adf86a (diff)
IB/mad: Check GID/LID when matching requests
Check GID/LID for requester side when searching for request which matches received response. This is in order to guarantee uniqueness if the same TID is used when requesting via multiple source LIDs (when LMC is not zero). Use ports' cached LMC to perform the check. Further, do not perform LID check for direct-routed packets, since the permissive LID makes a proper check impossible. Signed-off-by: Jack Morgenstein <jackm@mellanox.co.il> Signed-off-by: Sean Hefty <sean.hefty@intel.com> Signed-off-by: Roland Dreier <rolandd@cisco.com>
Diffstat (limited to 'drivers/infiniband/core/mad.c')
-rw-r--r--drivers/infiniband/core/mad.c94
1 files changed, 63 insertions, 31 deletions
diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c
index 92c7362f5887..b38e02a5db35 100644
--- a/drivers/infiniband/core/mad.c
+++ b/drivers/infiniband/core/mad.c
@@ -34,6 +34,7 @@
34 * $Id: mad.c 5596 2006-03-03 01:00:07Z sean.hefty $ 34 * $Id: mad.c 5596 2006-03-03 01:00:07Z sean.hefty $
35 */ 35 */
36#include <linux/dma-mapping.h> 36#include <linux/dma-mapping.h>
37#include <rdma/ib_cache.h>
37 38
38#include "mad_priv.h" 39#include "mad_priv.h"
39#include "mad_rmpp.h" 40#include "mad_rmpp.h"
@@ -1672,20 +1673,21 @@ static inline int rcv_has_same_class(struct ib_mad_send_wr_private *wr,
1672 rwc->recv_buf.mad->mad_hdr.mgmt_class; 1673 rwc->recv_buf.mad->mad_hdr.mgmt_class;
1673} 1674}
1674 1675
1675static inline int rcv_has_same_gid(struct ib_mad_send_wr_private *wr, 1676static inline int rcv_has_same_gid(struct ib_mad_agent_private *mad_agent_priv,
1677 struct ib_mad_send_wr_private *wr,
1676 struct ib_mad_recv_wc *rwc ) 1678 struct ib_mad_recv_wc *rwc )
1677{ 1679{
1678 struct ib_ah_attr attr; 1680 struct ib_ah_attr attr;
1679 u8 send_resp, rcv_resp; 1681 u8 send_resp, rcv_resp;
1682 union ib_gid sgid;
1683 struct ib_device *device = mad_agent_priv->agent.device;
1684 u8 port_num = mad_agent_priv->agent.port_num;
1685 u8 lmc;
1680 1686
1681 send_resp = ((struct ib_mad *)(wr->send_buf.mad))-> 1687 send_resp = ((struct ib_mad *)(wr->send_buf.mad))->
1682 mad_hdr.method & IB_MGMT_METHOD_RESP; 1688 mad_hdr.method & IB_MGMT_METHOD_RESP;
1683 rcv_resp = rwc->recv_buf.mad->mad_hdr.method & IB_MGMT_METHOD_RESP; 1689 rcv_resp = rwc->recv_buf.mad->mad_hdr.method & IB_MGMT_METHOD_RESP;
1684 1690
1685 if (!send_resp && rcv_resp)
1686 /* is request/response. GID/LIDs are both local (same). */
1687 return 1;
1688
1689 if (send_resp == rcv_resp) 1691 if (send_resp == rcv_resp)
1690 /* both requests, or both responses. GIDs different */ 1692 /* both requests, or both responses. GIDs different */
1691 return 0; 1693 return 0;
@@ -1694,48 +1696,78 @@ static inline int rcv_has_same_gid(struct ib_mad_send_wr_private *wr,
1694 /* Assume not equal, to avoid false positives. */ 1696 /* Assume not equal, to avoid false positives. */
1695 return 0; 1697 return 0;
1696 1698
1697 if (!(attr.ah_flags & IB_AH_GRH) && !(rwc->wc->wc_flags & IB_WC_GRH)) 1699 if (!!(attr.ah_flags & IB_AH_GRH) !=
1698 return attr.dlid == rwc->wc->slid; 1700 !!(rwc->wc->wc_flags & IB_WC_GRH))
1699 else if ((attr.ah_flags & IB_AH_GRH) &&
1700 (rwc->wc->wc_flags & IB_WC_GRH))
1701 return memcmp(attr.grh.dgid.raw,
1702 rwc->recv_buf.grh->sgid.raw, 16) == 0;
1703 else
1704 /* one has GID, other does not. Assume different */ 1701 /* one has GID, other does not. Assume different */
1705 return 0; 1702 return 0;
1703
1704 if (!send_resp && rcv_resp) {
1705 /* is request/response. */
1706 if (!(attr.ah_flags & IB_AH_GRH)) {
1707 if (ib_get_cached_lmc(device, port_num, &lmc))
1708 return 0;
1709 return (!lmc || !((attr.src_path_bits ^
1710 rwc->wc->dlid_path_bits) &
1711 ((1 << lmc) - 1)));
1712 } else {
1713 if (ib_get_cached_gid(device, port_num,
1714 attr.grh.sgid_index, &sgid))
1715 return 0;
1716 return !memcmp(sgid.raw, rwc->recv_buf.grh->dgid.raw,
1717 16);
1718 }
1719 }
1720
1721 if (!(attr.ah_flags & IB_AH_GRH))
1722 return attr.dlid == rwc->wc->slid;
1723 else
1724 return !memcmp(attr.grh.dgid.raw, rwc->recv_buf.grh->sgid.raw,
1725 16);
1706} 1726}
1727
1728static inline int is_direct(u8 class)
1729{
1730 return (class == IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE);
1731}
1732
1707struct ib_mad_send_wr_private* 1733struct ib_mad_send_wr_private*
1708ib_find_send_mad(struct ib_mad_agent_private *mad_agent_priv, 1734ib_find_send_mad(struct ib_mad_agent_private *mad_agent_priv,
1709 struct ib_mad_recv_wc *mad_recv_wc) 1735 struct ib_mad_recv_wc *wc)
1710{ 1736{
1711 struct ib_mad_send_wr_private *mad_send_wr; 1737 struct ib_mad_send_wr_private *wr;
1712 struct ib_mad *mad; 1738 struct ib_mad *mad;
1713 1739
1714 mad = (struct ib_mad *)mad_recv_wc->recv_buf.mad; 1740 mad = (struct ib_mad *)wc->recv_buf.mad;
1715 1741
1716 list_for_each_entry(mad_send_wr, &mad_agent_priv->wait_list, 1742 list_for_each_entry(wr, &mad_agent_priv->wait_list, agent_list) {
1717 agent_list) { 1743 if ((wr->tid == mad->mad_hdr.tid) &&
1718 if ((mad_send_wr->tid == mad->mad_hdr.tid) && 1744 rcv_has_same_class(wr, wc) &&
1719 rcv_has_same_class(mad_send_wr, mad_recv_wc) && 1745 /*
1720 rcv_has_same_gid(mad_send_wr, mad_recv_wc)) 1746 * Don't check GID for direct routed MADs.
1721 return mad_send_wr; 1747 * These might have permissive LIDs.
1748 */
1749 (is_direct(wc->recv_buf.mad->mad_hdr.mgmt_class) ||
1750 rcv_has_same_gid(mad_agent_priv, wr, wc)))
1751 return wr;
1722 } 1752 }
1723 1753
1724 /* 1754 /*
1725 * It's possible to receive the response before we've 1755 * It's possible to receive the response before we've
1726 * been notified that the send has completed 1756 * been notified that the send has completed
1727 */ 1757 */
1728 list_for_each_entry(mad_send_wr, &mad_agent_priv->send_list, 1758 list_for_each_entry(wr, &mad_agent_priv->send_list, agent_list) {
1729 agent_list) { 1759 if (is_data_mad(mad_agent_priv, wr->send_buf.mad) &&
1730 if (is_data_mad(mad_agent_priv, mad_send_wr->send_buf.mad) && 1760 wr->tid == mad->mad_hdr.tid &&
1731 mad_send_wr->tid == mad->mad_hdr.tid && 1761 wr->timeout &&
1732 mad_send_wr->timeout && 1762 rcv_has_same_class(wr, wc) &&
1733 rcv_has_same_class(mad_send_wr, mad_recv_wc) && 1763 /*
1734 rcv_has_same_gid(mad_send_wr, mad_recv_wc)) { 1764 * Don't check GID for direct routed MADs.
1765 * These might have permissive LIDs.
1766 */
1767 (is_direct(wc->recv_buf.mad->mad_hdr.mgmt_class) ||
1768 rcv_has_same_gid(mad_agent_priv, wr, wc)))
1735 /* Verify request has not been canceled */ 1769 /* Verify request has not been canceled */
1736 return (mad_send_wr->status == IB_WC_SUCCESS) ? 1770 return (wr->status == IB_WC_SUCCESS) ? wr : NULL;
1737 mad_send_wr : NULL;
1738 }
1739 } 1771 }
1740 return NULL; 1772 return NULL;
1741} 1773}