1d6b92ffaSHans Petter Selasky /*
2d6b92ffaSHans Petter Selasky * Copyright (c) 2006-2009 Voltaire, Inc. All rights reserved.
3d6b92ffaSHans Petter Selasky * Copyright (c) 2002-2011 Mellanox Technologies LTD. All rights reserved.
4d6b92ffaSHans Petter Selasky * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
5d6b92ffaSHans Petter Selasky * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved.
6d6b92ffaSHans Petter Selasky *
7d6b92ffaSHans Petter Selasky * This software is available to you under a choice of one of two
8d6b92ffaSHans Petter Selasky * licenses. You may choose to be licensed under the terms of the GNU
9d6b92ffaSHans Petter Selasky * General Public License (GPL) Version 2, available from the file
10d6b92ffaSHans Petter Selasky * COPYING in the main directory of this source tree, or the
11d6b92ffaSHans Petter Selasky * OpenIB.org BSD license below:
12d6b92ffaSHans Petter Selasky *
13d6b92ffaSHans Petter Selasky * Redistribution and use in source and binary forms, with or
14d6b92ffaSHans Petter Selasky * without modification, are permitted provided that the following
15d6b92ffaSHans Petter Selasky * conditions are met:
16d6b92ffaSHans Petter Selasky *
17d6b92ffaSHans Petter Selasky * - Redistributions of source code must retain the above
18d6b92ffaSHans Petter Selasky * copyright notice, this list of conditions and the following
19d6b92ffaSHans Petter Selasky * disclaimer.
20d6b92ffaSHans Petter Selasky *
21d6b92ffaSHans Petter Selasky * - Redistributions in binary form must reproduce the above
22d6b92ffaSHans Petter Selasky * copyright notice, this list of conditions and the following
23d6b92ffaSHans Petter Selasky * disclaimer in the documentation and/or other materials
24d6b92ffaSHans Petter Selasky * provided with the distribution.
25d6b92ffaSHans Petter Selasky *
26d6b92ffaSHans Petter Selasky * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
27d6b92ffaSHans Petter Selasky * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
28d6b92ffaSHans Petter Selasky * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
29d6b92ffaSHans Petter Selasky * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
30d6b92ffaSHans Petter Selasky * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
31d6b92ffaSHans Petter Selasky * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
32d6b92ffaSHans Petter Selasky * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
33d6b92ffaSHans Petter Selasky * SOFTWARE.
34d6b92ffaSHans Petter Selasky *
35d6b92ffaSHans Petter Selasky */
36d6b92ffaSHans Petter Selasky
37d6b92ffaSHans Petter Selasky /*
38d6b92ffaSHans Petter Selasky * Abstract:
39d6b92ffaSHans Petter Selasky * Implementation of osm_mpr_rcv_t.
40d6b92ffaSHans Petter Selasky * This object represents the MultiPath Record Receiver object.
41d6b92ffaSHans Petter Selasky * This object is part of the opensm family of objects.
42d6b92ffaSHans Petter Selasky */
43d6b92ffaSHans Petter Selasky
44d6b92ffaSHans Petter Selasky #if HAVE_CONFIG_H
45d6b92ffaSHans Petter Selasky # include <config.h>
46d6b92ffaSHans Petter Selasky #endif /* HAVE_CONFIG_H */
47d6b92ffaSHans Petter Selasky
48d6b92ffaSHans Petter Selasky #if defined (VENDOR_RMPP_SUPPORT) && defined (DUAL_SIDED_RMPP)
49d6b92ffaSHans Petter Selasky
50d6b92ffaSHans Petter Selasky #include <string.h>
51d6b92ffaSHans Petter Selasky #include <iba/ib_types.h>
52d6b92ffaSHans Petter Selasky #include <complib/cl_qmap.h>
53d6b92ffaSHans Petter Selasky #include <complib/cl_passivelock.h>
54d6b92ffaSHans Petter Selasky #include <complib/cl_debug.h>
55d6b92ffaSHans Petter Selasky #include <complib/cl_qlist.h>
56d6b92ffaSHans Petter Selasky #include <opensm/osm_file_ids.h>
57d6b92ffaSHans Petter Selasky #define FILE_ID OSM_FILE_SA_MULTIPATH_RECORD_C
58d6b92ffaSHans Petter Selasky #include <vendor/osm_vendor_api.h>
59d6b92ffaSHans Petter Selasky #include <opensm/osm_port.h>
60d6b92ffaSHans Petter Selasky #include <opensm/osm_node.h>
61d6b92ffaSHans Petter Selasky #include <opensm/osm_switch.h>
62d6b92ffaSHans Petter Selasky #include <opensm/osm_partition.h>
63d6b92ffaSHans Petter Selasky #include <opensm/osm_helper.h>
64d6b92ffaSHans Petter Selasky #include <opensm/osm_qos_policy.h>
65d6b92ffaSHans Petter Selasky #include <opensm/osm_sa.h>
66d6b92ffaSHans Petter Selasky
67d6b92ffaSHans Petter Selasky #define OSM_SA_MPR_MAX_NUM_PATH 127
68d6b92ffaSHans Petter Selasky #define MAX_HOPS 64
69d6b92ffaSHans Petter Selasky
70d6b92ffaSHans Petter Selasky #define SA_MPR_RESP_SIZE SA_ITEM_RESP_SIZE(mpr_rec)
71d6b92ffaSHans Petter Selasky
sa_multipath_rec_is_tavor_port(IN const osm_port_t * p_port)72d6b92ffaSHans Petter Selasky static boolean_t sa_multipath_rec_is_tavor_port(IN const osm_port_t * p_port)
73d6b92ffaSHans Petter Selasky {
74d6b92ffaSHans Petter Selasky osm_node_t const *p_node;
75d6b92ffaSHans Petter Selasky ib_net32_t vend_id;
76d6b92ffaSHans Petter Selasky
77d6b92ffaSHans Petter Selasky p_node = p_port->p_node;
78d6b92ffaSHans Petter Selasky vend_id = ib_node_info_get_vendor_id(&p_node->node_info);
79d6b92ffaSHans Petter Selasky
80d6b92ffaSHans Petter Selasky return ((p_node->node_info.device_id == CL_HTON16(23108)) &&
81d6b92ffaSHans Petter Selasky ((vend_id == CL_HTON32(OSM_VENDOR_ID_MELLANOX)) ||
82d6b92ffaSHans Petter Selasky (vend_id == CL_HTON32(OSM_VENDOR_ID_TOPSPIN)) ||
83d6b92ffaSHans Petter Selasky (vend_id == CL_HTON32(OSM_VENDOR_ID_SILVERSTORM)) ||
84d6b92ffaSHans Petter Selasky (vend_id == CL_HTON32(OSM_VENDOR_ID_VOLTAIRE))));
85d6b92ffaSHans Petter Selasky }
86d6b92ffaSHans Petter Selasky
87d6b92ffaSHans Petter Selasky static boolean_t
sa_multipath_rec_apply_tavor_mtu_limit(IN const ib_multipath_rec_t * p_mpr,IN const osm_port_t * p_src_port,IN const osm_port_t * p_dest_port,IN const ib_net64_t comp_mask)88d6b92ffaSHans Petter Selasky sa_multipath_rec_apply_tavor_mtu_limit(IN const ib_multipath_rec_t * p_mpr,
89d6b92ffaSHans Petter Selasky IN const osm_port_t * p_src_port,
90d6b92ffaSHans Petter Selasky IN const osm_port_t * p_dest_port,
91d6b92ffaSHans Petter Selasky IN const ib_net64_t comp_mask)
92d6b92ffaSHans Petter Selasky {
93d6b92ffaSHans Petter Selasky uint8_t required_mtu;
94d6b92ffaSHans Petter Selasky
95d6b92ffaSHans Petter Selasky /* only if at least one of the ports is a Tavor device */
96d6b92ffaSHans Petter Selasky if (!sa_multipath_rec_is_tavor_port(p_src_port) &&
97d6b92ffaSHans Petter Selasky !sa_multipath_rec_is_tavor_port(p_dest_port))
98d6b92ffaSHans Petter Selasky return FALSE;
99d6b92ffaSHans Petter Selasky
100d6b92ffaSHans Petter Selasky /*
101d6b92ffaSHans Petter Selasky we can apply the patch if either:
102d6b92ffaSHans Petter Selasky 1. No MTU required
103d6b92ffaSHans Petter Selasky 2. Required MTU <
104d6b92ffaSHans Petter Selasky 3. Required MTU = 1K or 512 or 256
105d6b92ffaSHans Petter Selasky 4. Required MTU > 256 or 512
106d6b92ffaSHans Petter Selasky */
107d6b92ffaSHans Petter Selasky required_mtu = ib_multipath_rec_mtu(p_mpr);
108d6b92ffaSHans Petter Selasky if ((comp_mask & IB_MPR_COMPMASK_MTUSELEC) &&
109d6b92ffaSHans Petter Selasky (comp_mask & IB_MPR_COMPMASK_MTU)) {
110d6b92ffaSHans Petter Selasky switch (ib_multipath_rec_mtu_sel(p_mpr)) {
111d6b92ffaSHans Petter Selasky case 0: /* must be greater than */
112d6b92ffaSHans Petter Selasky case 2: /* exact match */
113d6b92ffaSHans Petter Selasky if (IB_MTU_LEN_1024 < required_mtu)
114d6b92ffaSHans Petter Selasky return FALSE;
115d6b92ffaSHans Petter Selasky break;
116d6b92ffaSHans Petter Selasky
117d6b92ffaSHans Petter Selasky case 1: /* must be less than */
118d6b92ffaSHans Petter Selasky /* can't be disqualified by this one */
119d6b92ffaSHans Petter Selasky break;
120d6b92ffaSHans Petter Selasky
121d6b92ffaSHans Petter Selasky case 3: /* largest available */
122d6b92ffaSHans Petter Selasky /* the ULP intentionally requested */
123d6b92ffaSHans Petter Selasky /* the largest MTU possible */
124d6b92ffaSHans Petter Selasky return FALSE;
125d6b92ffaSHans Petter Selasky break;
126d6b92ffaSHans Petter Selasky
127d6b92ffaSHans Petter Selasky default:
128d6b92ffaSHans Petter Selasky /* if we're here, there's a bug in ib_multipath_rec_mtu_sel() */
129d6b92ffaSHans Petter Selasky CL_ASSERT(FALSE);
130d6b92ffaSHans Petter Selasky break;
131d6b92ffaSHans Petter Selasky }
132d6b92ffaSHans Petter Selasky }
133d6b92ffaSHans Petter Selasky
134d6b92ffaSHans Petter Selasky return TRUE;
135d6b92ffaSHans Petter Selasky }
136d6b92ffaSHans Petter Selasky
mpr_rcv_get_path_parms(IN osm_sa_t * sa,IN const ib_multipath_rec_t * p_mpr,IN const osm_alias_guid_t * p_src_alias_guid,IN const osm_alias_guid_t * p_dest_alias_guid,IN const uint16_t src_lid_ho,IN const uint16_t dest_lid_ho,IN const ib_net64_t comp_mask,OUT osm_path_parms_t * p_parms)137d6b92ffaSHans Petter Selasky static ib_api_status_t mpr_rcv_get_path_parms(IN osm_sa_t * sa,
138d6b92ffaSHans Petter Selasky IN const ib_multipath_rec_t *
139d6b92ffaSHans Petter Selasky p_mpr,
140d6b92ffaSHans Petter Selasky IN const osm_alias_guid_t * p_src_alias_guid,
141d6b92ffaSHans Petter Selasky IN const osm_alias_guid_t * p_dest_alias_guid,
142d6b92ffaSHans Petter Selasky IN const uint16_t src_lid_ho,
143d6b92ffaSHans Petter Selasky IN const uint16_t dest_lid_ho,
144d6b92ffaSHans Petter Selasky IN const ib_net64_t comp_mask,
145d6b92ffaSHans Petter Selasky OUT osm_path_parms_t * p_parms)
146d6b92ffaSHans Petter Selasky {
147d6b92ffaSHans Petter Selasky const osm_node_t *p_node;
148d6b92ffaSHans Petter Selasky const osm_physp_t *p_physp, *p_physp0;
149d6b92ffaSHans Petter Selasky const osm_physp_t *p_src_physp;
150d6b92ffaSHans Petter Selasky const osm_physp_t *p_dest_physp;
151d6b92ffaSHans Petter Selasky const osm_prtn_t *p_prtn = NULL;
152d6b92ffaSHans Petter Selasky const ib_port_info_t *p_pi, *p_pi0;
153d6b92ffaSHans Petter Selasky ib_slvl_table_t *p_slvl_tbl;
154d6b92ffaSHans Petter Selasky ib_api_status_t status = IB_SUCCESS;
155d6b92ffaSHans Petter Selasky uint8_t mtu;
156d6b92ffaSHans Petter Selasky uint8_t rate, p0_extended_rate, dest_rate;
157d6b92ffaSHans Petter Selasky uint8_t pkt_life;
158d6b92ffaSHans Petter Selasky uint8_t required_mtu;
159d6b92ffaSHans Petter Selasky uint8_t required_rate;
160d6b92ffaSHans Petter Selasky ib_net16_t required_pkey;
161d6b92ffaSHans Petter Selasky uint8_t required_sl;
162d6b92ffaSHans Petter Selasky uint8_t required_pkt_life;
163d6b92ffaSHans Petter Selasky ib_net16_t dest_lid;
164d6b92ffaSHans Petter Selasky int hops = 0;
165d6b92ffaSHans Petter Selasky int in_port_num = 0;
166d6b92ffaSHans Petter Selasky uint8_t i;
167d6b92ffaSHans Petter Selasky osm_qos_level_t *p_qos_level = NULL;
168d6b92ffaSHans Petter Selasky uint16_t valid_sl_mask = 0xffff;
169d6b92ffaSHans Petter Selasky int extended, p0_extended;
170d6b92ffaSHans Petter Selasky
171d6b92ffaSHans Petter Selasky OSM_LOG_ENTER(sa->p_log);
172d6b92ffaSHans Petter Selasky
173d6b92ffaSHans Petter Selasky dest_lid = cl_hton16(dest_lid_ho);
174d6b92ffaSHans Petter Selasky
175d6b92ffaSHans Petter Selasky p_dest_physp = p_dest_alias_guid->p_base_port->p_physp;
176d6b92ffaSHans Petter Selasky p_physp = p_src_alias_guid->p_base_port->p_physp;
177d6b92ffaSHans Petter Selasky p_src_physp = p_physp;
178d6b92ffaSHans Petter Selasky p_pi = &p_physp->port_info;
179d6b92ffaSHans Petter Selasky
180d6b92ffaSHans Petter Selasky mtu = ib_port_info_get_mtu_cap(p_pi);
181d6b92ffaSHans Petter Selasky extended = p_pi->capability_mask & IB_PORT_CAP_HAS_EXT_SPEEDS;
182d6b92ffaSHans Petter Selasky rate = ib_port_info_compute_rate(p_pi, extended);
183d6b92ffaSHans Petter Selasky
184d6b92ffaSHans Petter Selasky /*
185d6b92ffaSHans Petter Selasky Mellanox Tavor device performance is better using 1K MTU.
186d6b92ffaSHans Petter Selasky If required MTU and MTU selector are such that 1K is OK
187d6b92ffaSHans Petter Selasky and at least one end of the path is Tavor we override the
188d6b92ffaSHans Petter Selasky port MTU with 1K.
189d6b92ffaSHans Petter Selasky */
190d6b92ffaSHans Petter Selasky if (sa->p_subn->opt.enable_quirks &&
191d6b92ffaSHans Petter Selasky sa_multipath_rec_apply_tavor_mtu_limit(p_mpr,
192d6b92ffaSHans Petter Selasky p_src_alias_guid->p_base_port,
193d6b92ffaSHans Petter Selasky p_dest_alias_guid->p_base_port,
194d6b92ffaSHans Petter Selasky comp_mask))
195d6b92ffaSHans Petter Selasky if (mtu > IB_MTU_LEN_1024) {
196d6b92ffaSHans Petter Selasky mtu = IB_MTU_LEN_1024;
197d6b92ffaSHans Petter Selasky OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
198d6b92ffaSHans Petter Selasky "Optimized Path MTU to 1K for Mellanox Tavor device\n");
199d6b92ffaSHans Petter Selasky }
200d6b92ffaSHans Petter Selasky
201d6b92ffaSHans Petter Selasky /*
202d6b92ffaSHans Petter Selasky Walk the subnet object from source to destination,
203d6b92ffaSHans Petter Selasky tracking the most restrictive rate and mtu values along the way...
204d6b92ffaSHans Petter Selasky
205d6b92ffaSHans Petter Selasky If source port node is a switch, then p_physp should
206d6b92ffaSHans Petter Selasky point to the port that routes the destination lid
207d6b92ffaSHans Petter Selasky */
208d6b92ffaSHans Petter Selasky
209d6b92ffaSHans Petter Selasky p_node = osm_physp_get_node_ptr(p_physp);
210d6b92ffaSHans Petter Selasky
211d6b92ffaSHans Petter Selasky if (p_node->sw) {
212d6b92ffaSHans Petter Selasky /*
213d6b92ffaSHans Petter Selasky * Source node is a switch.
214d6b92ffaSHans Petter Selasky * Make sure that p_physp points to the out port of the
215d6b92ffaSHans Petter Selasky * switch that routes to the destination lid (dest_lid_ho)
216d6b92ffaSHans Petter Selasky */
217d6b92ffaSHans Petter Selasky p_physp = osm_switch_get_route_by_lid(p_node->sw, dest_lid);
218d6b92ffaSHans Petter Selasky if (p_physp == 0) {
219d6b92ffaSHans Petter Selasky OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4514: "
220d6b92ffaSHans Petter Selasky "Can't find routing from LID %u to LID %u on "
221d6b92ffaSHans Petter Selasky "switch %s (GUID 0x%016" PRIx64 ")\n",
222d6b92ffaSHans Petter Selasky src_lid_ho, dest_lid_ho, p_node->print_desc,
223d6b92ffaSHans Petter Selasky cl_ntoh64(osm_node_get_node_guid(p_node)));
224d6b92ffaSHans Petter Selasky status = IB_NOT_FOUND;
225d6b92ffaSHans Petter Selasky goto Exit;
226d6b92ffaSHans Petter Selasky }
227d6b92ffaSHans Petter Selasky }
228d6b92ffaSHans Petter Selasky
229d6b92ffaSHans Petter Selasky if (sa->p_subn->opt.qos) {
230d6b92ffaSHans Petter Selasky
231d6b92ffaSHans Petter Selasky /*
232d6b92ffaSHans Petter Selasky * Whether this node is switch or CA, the IN port for
233d6b92ffaSHans Petter Selasky * the sl2vl table is 0, because this is a source node.
234d6b92ffaSHans Petter Selasky */
235d6b92ffaSHans Petter Selasky p_slvl_tbl = osm_physp_get_slvl_tbl(p_physp, 0);
236d6b92ffaSHans Petter Selasky
237d6b92ffaSHans Petter Selasky /* update valid SLs that still exist on this route */
238d6b92ffaSHans Petter Selasky for (i = 0; i < IB_MAX_NUM_VLS; i++) {
239d6b92ffaSHans Petter Selasky if (valid_sl_mask & (1 << i) &&
240d6b92ffaSHans Petter Selasky ib_slvl_table_get(p_slvl_tbl, i) == IB_DROP_VL)
241d6b92ffaSHans Petter Selasky valid_sl_mask &= ~(1 << i);
242d6b92ffaSHans Petter Selasky }
243d6b92ffaSHans Petter Selasky if (!valid_sl_mask) {
244d6b92ffaSHans Petter Selasky OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
245d6b92ffaSHans Petter Selasky "All the SLs lead to VL15 on this path\n");
246d6b92ffaSHans Petter Selasky status = IB_NOT_FOUND;
247d6b92ffaSHans Petter Selasky goto Exit;
248d6b92ffaSHans Petter Selasky }
249d6b92ffaSHans Petter Selasky }
250d6b92ffaSHans Petter Selasky
251d6b92ffaSHans Petter Selasky /*
252d6b92ffaSHans Petter Selasky * Same as above
253d6b92ffaSHans Petter Selasky */
254d6b92ffaSHans Petter Selasky p_node = osm_physp_get_node_ptr(p_dest_physp);
255d6b92ffaSHans Petter Selasky
256d6b92ffaSHans Petter Selasky if (p_node->sw) {
257d6b92ffaSHans Petter Selasky /*
258d6b92ffaSHans Petter Selasky * if destination is switch, we want p_dest_physp to point to port 0
259d6b92ffaSHans Petter Selasky */
260d6b92ffaSHans Petter Selasky p_dest_physp =
261d6b92ffaSHans Petter Selasky osm_switch_get_route_by_lid(p_node->sw, dest_lid);
262d6b92ffaSHans Petter Selasky
263d6b92ffaSHans Petter Selasky if (p_dest_physp == 0) {
264d6b92ffaSHans Petter Selasky OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4515: "
265d6b92ffaSHans Petter Selasky "Can't find routing from LID %u to LID %u on "
266d6b92ffaSHans Petter Selasky "switch %s (GUID 0x%016" PRIx64 ")\n",
267d6b92ffaSHans Petter Selasky src_lid_ho, dest_lid_ho, p_node->print_desc,
268d6b92ffaSHans Petter Selasky cl_ntoh64(osm_node_get_node_guid(p_node)));
269d6b92ffaSHans Petter Selasky status = IB_NOT_FOUND;
270d6b92ffaSHans Petter Selasky goto Exit;
271d6b92ffaSHans Petter Selasky }
272d6b92ffaSHans Petter Selasky
273d6b92ffaSHans Petter Selasky }
274d6b92ffaSHans Petter Selasky
275d6b92ffaSHans Petter Selasky /*
276d6b92ffaSHans Petter Selasky * Now go through the path step by step
277d6b92ffaSHans Petter Selasky */
278d6b92ffaSHans Petter Selasky
279d6b92ffaSHans Petter Selasky while (p_physp != p_dest_physp) {
280d6b92ffaSHans Petter Selasky
281d6b92ffaSHans Petter Selasky int tmp_pnum = p_physp->port_num;
282d6b92ffaSHans Petter Selasky p_node = osm_physp_get_node_ptr(p_physp);
283d6b92ffaSHans Petter Selasky p_physp = osm_physp_get_remote(p_physp);
284d6b92ffaSHans Petter Selasky
285d6b92ffaSHans Petter Selasky if (p_physp == 0) {
286d6b92ffaSHans Petter Selasky OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4505: "
287d6b92ffaSHans Petter Selasky "Can't find remote phys port of %s (GUID "
288d6b92ffaSHans Petter Selasky "0x%016" PRIx64 ") port %d "
289d6b92ffaSHans Petter Selasky "while routing from LID %u to LID %u",
290d6b92ffaSHans Petter Selasky p_node->print_desc,
291d6b92ffaSHans Petter Selasky cl_ntoh64(osm_node_get_node_guid(p_node)),
292d6b92ffaSHans Petter Selasky tmp_pnum, src_lid_ho, dest_lid_ho);
293d6b92ffaSHans Petter Selasky status = IB_ERROR;
294d6b92ffaSHans Petter Selasky goto Exit;
295d6b92ffaSHans Petter Selasky }
296d6b92ffaSHans Petter Selasky
297d6b92ffaSHans Petter Selasky /* update number of hops traversed */
298d6b92ffaSHans Petter Selasky hops++;
299d6b92ffaSHans Petter Selasky if (hops > MAX_HOPS) {
300d6b92ffaSHans Petter Selasky OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4520: "
301d6b92ffaSHans Petter Selasky "Path from GUID 0x%016" PRIx64 " (%s) to"
302d6b92ffaSHans Petter Selasky " lid %u GUID 0x%016" PRIx64 " (%s) needs"
303d6b92ffaSHans Petter Selasky " more than %d hops, max %d hops allowed\n",
304d6b92ffaSHans Petter Selasky cl_ntoh64(osm_physp_get_port_guid(p_src_physp)),
305d6b92ffaSHans Petter Selasky p_src_physp->p_node->print_desc, dest_lid_ho,
306d6b92ffaSHans Petter Selasky cl_ntoh64(osm_physp_get_port_guid
307d6b92ffaSHans Petter Selasky (p_dest_physp)),
308d6b92ffaSHans Petter Selasky p_dest_physp->p_node->print_desc, hops,
309d6b92ffaSHans Petter Selasky MAX_HOPS);
310d6b92ffaSHans Petter Selasky status = IB_NOT_FOUND;
311d6b92ffaSHans Petter Selasky goto Exit;
312d6b92ffaSHans Petter Selasky }
313d6b92ffaSHans Petter Selasky
314d6b92ffaSHans Petter Selasky in_port_num = osm_physp_get_port_num(p_physp);
315d6b92ffaSHans Petter Selasky
316d6b92ffaSHans Petter Selasky /*
317d6b92ffaSHans Petter Selasky This is point to point case (no switch in between)
318d6b92ffaSHans Petter Selasky */
319d6b92ffaSHans Petter Selasky if (p_physp == p_dest_physp)
320d6b92ffaSHans Petter Selasky break;
321d6b92ffaSHans Petter Selasky
322d6b92ffaSHans Petter Selasky p_node = osm_physp_get_node_ptr(p_physp);
323d6b92ffaSHans Petter Selasky
324d6b92ffaSHans Petter Selasky if (!p_node->sw) {
325d6b92ffaSHans Petter Selasky /*
326d6b92ffaSHans Petter Selasky There is some sort of problem in the subnet object!
327d6b92ffaSHans Petter Selasky If this isn't a switch, we should have reached
328d6b92ffaSHans Petter Selasky the destination by now!
329d6b92ffaSHans Petter Selasky */
330d6b92ffaSHans Petter Selasky OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4503: "
331d6b92ffaSHans Petter Selasky "Internal error, bad path while routing "
332d6b92ffaSHans Petter Selasky "from %s (GUID: 0x%016"PRIx64") port %d "
333d6b92ffaSHans Petter Selasky "to %s (GUID: 0x%016"PRIx64") port %d; "
334d6b92ffaSHans Petter Selasky "ended at %s port %d\n",
335d6b92ffaSHans Petter Selasky p_src_alias_guid->p_base_port->p_node->print_desc,
336d6b92ffaSHans Petter Selasky cl_ntoh64(p_src_alias_guid->p_base_port->p_node->node_info.node_guid),
337d6b92ffaSHans Petter Selasky p_src_alias_guid->p_base_port->p_physp->port_num,
338d6b92ffaSHans Petter Selasky p_dest_alias_guid->p_base_port->p_node->print_desc,
339d6b92ffaSHans Petter Selasky cl_ntoh64(p_dest_alias_guid->p_base_port->p_node->node_info.node_guid),
340d6b92ffaSHans Petter Selasky p_dest_alias_guid->p_base_port->p_physp->port_num,
341d6b92ffaSHans Petter Selasky p_node->print_desc,
342d6b92ffaSHans Petter Selasky p_physp->port_num);
343d6b92ffaSHans Petter Selasky status = IB_ERROR;
344d6b92ffaSHans Petter Selasky goto Exit;
345d6b92ffaSHans Petter Selasky }
346d6b92ffaSHans Petter Selasky
347d6b92ffaSHans Petter Selasky /*
348d6b92ffaSHans Petter Selasky Check parameters for the ingress port in this switch.
349d6b92ffaSHans Petter Selasky */
350d6b92ffaSHans Petter Selasky p_pi = &p_physp->port_info;
351d6b92ffaSHans Petter Selasky
352d6b92ffaSHans Petter Selasky if (mtu > ib_port_info_get_mtu_cap(p_pi))
353d6b92ffaSHans Petter Selasky mtu = ib_port_info_get_mtu_cap(p_pi);
354d6b92ffaSHans Petter Selasky
355d6b92ffaSHans Petter Selasky p_physp0 = osm_node_get_physp_ptr((osm_node_t *)p_node, 0);
356d6b92ffaSHans Petter Selasky p_pi0 = &p_physp0->port_info;
357d6b92ffaSHans Petter Selasky p0_extended = p_pi0->capability_mask & IB_PORT_CAP_HAS_EXT_SPEEDS;
358d6b92ffaSHans Petter Selasky p0_extended_rate = ib_port_info_compute_rate(p_pi, p0_extended);
359d6b92ffaSHans Petter Selasky if (ib_path_compare_rates(rate, p0_extended_rate) > 0)
360d6b92ffaSHans Petter Selasky rate = p0_extended_rate;
361d6b92ffaSHans Petter Selasky
362d6b92ffaSHans Petter Selasky /*
363d6b92ffaSHans Petter Selasky Continue with the egress port on this switch.
364d6b92ffaSHans Petter Selasky */
365d6b92ffaSHans Petter Selasky p_physp = osm_switch_get_route_by_lid(p_node->sw, dest_lid);
366d6b92ffaSHans Petter Selasky if (p_physp == 0) {
367d6b92ffaSHans Petter Selasky OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4516: "
368d6b92ffaSHans Petter Selasky "Dead end path on switch "
369d6b92ffaSHans Petter Selasky "%s (GUID: 0x%016"PRIx64") to LID %u\n",
370d6b92ffaSHans Petter Selasky p_node->print_desc,
371d6b92ffaSHans Petter Selasky cl_ntoh64(osm_node_get_node_guid(p_node)),
372d6b92ffaSHans Petter Selasky dest_lid_ho);
373d6b92ffaSHans Petter Selasky status = IB_ERROR;
374d6b92ffaSHans Petter Selasky goto Exit;
375d6b92ffaSHans Petter Selasky }
376d6b92ffaSHans Petter Selasky
377d6b92ffaSHans Petter Selasky p_pi = &p_physp->port_info;
378d6b92ffaSHans Petter Selasky
379d6b92ffaSHans Petter Selasky if (mtu > ib_port_info_get_mtu_cap(p_pi))
380d6b92ffaSHans Petter Selasky mtu = ib_port_info_get_mtu_cap(p_pi);
381d6b92ffaSHans Petter Selasky
382d6b92ffaSHans Petter Selasky p_physp0 = osm_node_get_physp_ptr((osm_node_t *)p_node, 0);
383d6b92ffaSHans Petter Selasky p_pi0 = &p_physp0->port_info;
384d6b92ffaSHans Petter Selasky p0_extended = p_pi0->capability_mask & IB_PORT_CAP_HAS_EXT_SPEEDS;
385d6b92ffaSHans Petter Selasky p0_extended_rate = ib_port_info_compute_rate(p_pi, p0_extended);
386d6b92ffaSHans Petter Selasky if (ib_path_compare_rates(rate, p0_extended_rate) > 0)
387d6b92ffaSHans Petter Selasky rate = p0_extended_rate;
388d6b92ffaSHans Petter Selasky
389d6b92ffaSHans Petter Selasky if (sa->p_subn->opt.qos) {
390d6b92ffaSHans Petter Selasky /*
391d6b92ffaSHans Petter Selasky * Check SL2VL table of the switch and update valid SLs
392d6b92ffaSHans Petter Selasky */
393d6b92ffaSHans Petter Selasky p_slvl_tbl =
394d6b92ffaSHans Petter Selasky osm_physp_get_slvl_tbl(p_physp, in_port_num);
395d6b92ffaSHans Petter Selasky for (i = 0; i < IB_MAX_NUM_VLS; i++) {
396d6b92ffaSHans Petter Selasky if (valid_sl_mask & (1 << i) &&
397d6b92ffaSHans Petter Selasky ib_slvl_table_get(p_slvl_tbl,
398d6b92ffaSHans Petter Selasky i) == IB_DROP_VL)
399d6b92ffaSHans Petter Selasky valid_sl_mask &= ~(1 << i);
400d6b92ffaSHans Petter Selasky }
401d6b92ffaSHans Petter Selasky if (!valid_sl_mask) {
402d6b92ffaSHans Petter Selasky OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
403d6b92ffaSHans Petter Selasky "All the SLs lead to VL15 "
404d6b92ffaSHans Petter Selasky "on this path\n");
405d6b92ffaSHans Petter Selasky status = IB_NOT_FOUND;
406d6b92ffaSHans Petter Selasky goto Exit;
407d6b92ffaSHans Petter Selasky }
408d6b92ffaSHans Petter Selasky }
409d6b92ffaSHans Petter Selasky }
410d6b92ffaSHans Petter Selasky
411d6b92ffaSHans Petter Selasky /*
412d6b92ffaSHans Petter Selasky p_physp now points to the destination
413d6b92ffaSHans Petter Selasky */
414d6b92ffaSHans Petter Selasky p_pi = &p_physp->port_info;
415d6b92ffaSHans Petter Selasky
416d6b92ffaSHans Petter Selasky if (mtu > ib_port_info_get_mtu_cap(p_pi))
417d6b92ffaSHans Petter Selasky mtu = ib_port_info_get_mtu_cap(p_pi);
418d6b92ffaSHans Petter Selasky
419d6b92ffaSHans Petter Selasky extended = p_pi->capability_mask & IB_PORT_CAP_HAS_EXT_SPEEDS;
420d6b92ffaSHans Petter Selasky dest_rate = ib_port_info_compute_rate(p_pi, extended);
421d6b92ffaSHans Petter Selasky if (ib_path_compare_rates(rate, dest_rate) > 0)
422d6b92ffaSHans Petter Selasky rate = dest_rate;
423d6b92ffaSHans Petter Selasky
424d6b92ffaSHans Petter Selasky OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
425d6b92ffaSHans Petter Selasky "Path min MTU = %u, min rate = %u\n", mtu, rate);
426d6b92ffaSHans Petter Selasky
427d6b92ffaSHans Petter Selasky /*
428d6b92ffaSHans Petter Selasky * Get QoS Level object according to the MultiPath request
429d6b92ffaSHans Petter Selasky * and adjust MultiPath parameters according to QoS settings
430d6b92ffaSHans Petter Selasky */
431d6b92ffaSHans Petter Selasky if (sa->p_subn->opt.qos && sa->p_subn->p_qos_policy &&
432d6b92ffaSHans Petter Selasky (p_qos_level =
433d6b92ffaSHans Petter Selasky osm_qos_policy_get_qos_level_by_mpr(sa->p_subn->p_qos_policy,
434d6b92ffaSHans Petter Selasky p_mpr, p_src_physp,
435d6b92ffaSHans Petter Selasky p_dest_physp, comp_mask))) {
436d6b92ffaSHans Petter Selasky
437d6b92ffaSHans Petter Selasky OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
438d6b92ffaSHans Petter Selasky "MultiPathRecord request matches QoS Level '%s' (%s)\n",
439d6b92ffaSHans Petter Selasky p_qos_level->name,
440d6b92ffaSHans Petter Selasky p_qos_level->use ? p_qos_level->use : "no description");
441d6b92ffaSHans Petter Selasky
442d6b92ffaSHans Petter Selasky if (p_qos_level->mtu_limit_set
443d6b92ffaSHans Petter Selasky && (mtu > p_qos_level->mtu_limit))
444d6b92ffaSHans Petter Selasky mtu = p_qos_level->mtu_limit;
445d6b92ffaSHans Petter Selasky
446d6b92ffaSHans Petter Selasky if (p_qos_level->rate_limit_set
447d6b92ffaSHans Petter Selasky && (ib_path_compare_rates(rate, p_qos_level->rate_limit) > 0))
448d6b92ffaSHans Petter Selasky rate = p_qos_level->rate_limit;
449d6b92ffaSHans Petter Selasky
450d6b92ffaSHans Petter Selasky if (p_qos_level->sl_set) {
451d6b92ffaSHans Petter Selasky required_sl = p_qos_level->sl;
452d6b92ffaSHans Petter Selasky if (!(valid_sl_mask & (1 << required_sl))) {
453d6b92ffaSHans Petter Selasky status = IB_NOT_FOUND;
454d6b92ffaSHans Petter Selasky goto Exit;
455d6b92ffaSHans Petter Selasky }
456d6b92ffaSHans Petter Selasky }
457d6b92ffaSHans Petter Selasky }
458d6b92ffaSHans Petter Selasky
459d6b92ffaSHans Petter Selasky /*
460d6b92ffaSHans Petter Selasky Determine if these values meet the user criteria
461d6b92ffaSHans Petter Selasky */
462d6b92ffaSHans Petter Selasky
463d6b92ffaSHans Petter Selasky /* we silently ignore cases where only the MTU selector is defined */
464d6b92ffaSHans Petter Selasky if ((comp_mask & IB_MPR_COMPMASK_MTUSELEC) &&
465d6b92ffaSHans Petter Selasky (comp_mask & IB_MPR_COMPMASK_MTU)) {
466d6b92ffaSHans Petter Selasky required_mtu = ib_multipath_rec_mtu(p_mpr);
467d6b92ffaSHans Petter Selasky switch (ib_multipath_rec_mtu_sel(p_mpr)) {
468d6b92ffaSHans Petter Selasky case 0: /* must be greater than */
469d6b92ffaSHans Petter Selasky if (mtu <= required_mtu)
470d6b92ffaSHans Petter Selasky status = IB_NOT_FOUND;
471d6b92ffaSHans Petter Selasky break;
472d6b92ffaSHans Petter Selasky
473d6b92ffaSHans Petter Selasky case 1: /* must be less than */
474d6b92ffaSHans Petter Selasky if (mtu >= required_mtu) {
475d6b92ffaSHans Petter Selasky /* adjust to use the highest mtu
476d6b92ffaSHans Petter Selasky lower then the required one */
477d6b92ffaSHans Petter Selasky if (required_mtu > 1)
478d6b92ffaSHans Petter Selasky mtu = required_mtu - 1;
479d6b92ffaSHans Petter Selasky else
480d6b92ffaSHans Petter Selasky status = IB_NOT_FOUND;
481d6b92ffaSHans Petter Selasky }
482d6b92ffaSHans Petter Selasky break;
483d6b92ffaSHans Petter Selasky
484d6b92ffaSHans Petter Selasky case 2: /* exact match */
485d6b92ffaSHans Petter Selasky if (mtu < required_mtu)
486d6b92ffaSHans Petter Selasky status = IB_NOT_FOUND;
487d6b92ffaSHans Petter Selasky else
488d6b92ffaSHans Petter Selasky mtu = required_mtu;
489d6b92ffaSHans Petter Selasky break;
490d6b92ffaSHans Petter Selasky
491d6b92ffaSHans Petter Selasky case 3: /* largest available */
492d6b92ffaSHans Petter Selasky /* can't be disqualified by this one */
493d6b92ffaSHans Petter Selasky break;
494d6b92ffaSHans Petter Selasky
495d6b92ffaSHans Petter Selasky default:
496d6b92ffaSHans Petter Selasky /* if we're here, there's a bug in ib_multipath_rec_mtu_sel() */
497d6b92ffaSHans Petter Selasky CL_ASSERT(FALSE);
498d6b92ffaSHans Petter Selasky status = IB_ERROR;
499d6b92ffaSHans Petter Selasky break;
500d6b92ffaSHans Petter Selasky }
501d6b92ffaSHans Petter Selasky }
502d6b92ffaSHans Petter Selasky if (status != IB_SUCCESS)
503d6b92ffaSHans Petter Selasky goto Exit;
504d6b92ffaSHans Petter Selasky
505d6b92ffaSHans Petter Selasky /* we silently ignore cases where only the Rate selector is defined */
506d6b92ffaSHans Petter Selasky if ((comp_mask & IB_MPR_COMPMASK_RATESELEC) &&
507d6b92ffaSHans Petter Selasky (comp_mask & IB_MPR_COMPMASK_RATE)) {
508d6b92ffaSHans Petter Selasky required_rate = ib_multipath_rec_rate(p_mpr);
509d6b92ffaSHans Petter Selasky switch (ib_multipath_rec_rate_sel(p_mpr)) {
510d6b92ffaSHans Petter Selasky case 0: /* must be greater than */
511d6b92ffaSHans Petter Selasky if (ib_path_compare_rates(rate, required_rate) <= 0)
512d6b92ffaSHans Petter Selasky status = IB_NOT_FOUND;
513d6b92ffaSHans Petter Selasky break;
514d6b92ffaSHans Petter Selasky
515d6b92ffaSHans Petter Selasky case 1: /* must be less than */
516d6b92ffaSHans Petter Selasky if (ib_path_compare_rates(rate, required_rate) >= 0) {
517d6b92ffaSHans Petter Selasky /* adjust the rate to use the highest rate
518d6b92ffaSHans Petter Selasky lower then the required one */
519d6b92ffaSHans Petter Selasky rate = ib_path_rate_get_prev(required_rate);
520d6b92ffaSHans Petter Selasky if (!rate)
521d6b92ffaSHans Petter Selasky status = IB_NOT_FOUND;
522d6b92ffaSHans Petter Selasky }
523d6b92ffaSHans Petter Selasky break;
524d6b92ffaSHans Petter Selasky
525d6b92ffaSHans Petter Selasky case 2: /* exact match */
526d6b92ffaSHans Petter Selasky if (ib_path_compare_rates(rate, required_rate))
527d6b92ffaSHans Petter Selasky status = IB_NOT_FOUND;
528d6b92ffaSHans Petter Selasky else
529d6b92ffaSHans Petter Selasky rate = required_rate;
530d6b92ffaSHans Petter Selasky break;
531d6b92ffaSHans Petter Selasky
532d6b92ffaSHans Petter Selasky case 3: /* largest available */
533d6b92ffaSHans Petter Selasky /* can't be disqualified by this one */
534d6b92ffaSHans Petter Selasky break;
535d6b92ffaSHans Petter Selasky
536d6b92ffaSHans Petter Selasky default:
537d6b92ffaSHans Petter Selasky /* if we're here, there's a bug in ib_multipath_rec_mtu_sel() */
538d6b92ffaSHans Petter Selasky CL_ASSERT(FALSE);
539d6b92ffaSHans Petter Selasky status = IB_ERROR;
540d6b92ffaSHans Petter Selasky break;
541d6b92ffaSHans Petter Selasky }
542d6b92ffaSHans Petter Selasky }
543d6b92ffaSHans Petter Selasky if (status != IB_SUCCESS)
544d6b92ffaSHans Petter Selasky goto Exit;
545d6b92ffaSHans Petter Selasky
546d6b92ffaSHans Petter Selasky /* Verify the pkt_life_time */
547d6b92ffaSHans Petter Selasky /* According to spec definition IBA 1.2 Table 205 PacketLifeTime description,
548d6b92ffaSHans Petter Selasky for loopback paths, packetLifeTime shall be zero. */
549d6b92ffaSHans Petter Selasky if (p_src_alias_guid->p_base_port == p_dest_alias_guid->p_base_port)
550d6b92ffaSHans Petter Selasky pkt_life = 0; /* loopback */
551d6b92ffaSHans Petter Selasky else if (p_qos_level && p_qos_level->pkt_life_set)
552d6b92ffaSHans Petter Selasky pkt_life = p_qos_level->pkt_life;
553d6b92ffaSHans Petter Selasky else
554d6b92ffaSHans Petter Selasky pkt_life = sa->p_subn->opt.subnet_timeout;
555d6b92ffaSHans Petter Selasky
556d6b92ffaSHans Petter Selasky /* we silently ignore cases where only the PktLife selector is defined */
557d6b92ffaSHans Petter Selasky if ((comp_mask & IB_MPR_COMPMASK_PKTLIFETIMESELEC) &&
558d6b92ffaSHans Petter Selasky (comp_mask & IB_MPR_COMPMASK_PKTLIFETIME)) {
559d6b92ffaSHans Petter Selasky required_pkt_life = ib_multipath_rec_pkt_life(p_mpr);
560d6b92ffaSHans Petter Selasky switch (ib_multipath_rec_pkt_life_sel(p_mpr)) {
561d6b92ffaSHans Petter Selasky case 0: /* must be greater than */
562d6b92ffaSHans Petter Selasky if (pkt_life <= required_pkt_life)
563d6b92ffaSHans Petter Selasky status = IB_NOT_FOUND;
564d6b92ffaSHans Petter Selasky break;
565d6b92ffaSHans Petter Selasky
566d6b92ffaSHans Petter Selasky case 1: /* must be less than */
567d6b92ffaSHans Petter Selasky if (pkt_life >= required_pkt_life) {
568d6b92ffaSHans Petter Selasky /* adjust the lifetime to use the highest possible
569d6b92ffaSHans Petter Selasky lower then the required one */
570d6b92ffaSHans Petter Selasky if (required_pkt_life > 1)
571d6b92ffaSHans Petter Selasky pkt_life = required_pkt_life - 1;
572d6b92ffaSHans Petter Selasky else
573d6b92ffaSHans Petter Selasky status = IB_NOT_FOUND;
574d6b92ffaSHans Petter Selasky }
575d6b92ffaSHans Petter Selasky break;
576d6b92ffaSHans Petter Selasky
577d6b92ffaSHans Petter Selasky case 2: /* exact match */
578d6b92ffaSHans Petter Selasky if (pkt_life < required_pkt_life)
579d6b92ffaSHans Petter Selasky status = IB_NOT_FOUND;
580d6b92ffaSHans Petter Selasky else
581d6b92ffaSHans Petter Selasky pkt_life = required_pkt_life;
582d6b92ffaSHans Petter Selasky break;
583d6b92ffaSHans Petter Selasky
584d6b92ffaSHans Petter Selasky case 3: /* smallest available */
585d6b92ffaSHans Petter Selasky /* can't be disqualified by this one */
586d6b92ffaSHans Petter Selasky break;
587d6b92ffaSHans Petter Selasky
588d6b92ffaSHans Petter Selasky default:
589d6b92ffaSHans Petter Selasky /* if we're here, there's a bug in ib_path_rec_pkt_life_sel() */
590d6b92ffaSHans Petter Selasky CL_ASSERT(FALSE);
591d6b92ffaSHans Petter Selasky status = IB_ERROR;
592d6b92ffaSHans Petter Selasky break;
593d6b92ffaSHans Petter Selasky }
594d6b92ffaSHans Petter Selasky }
595d6b92ffaSHans Petter Selasky
596d6b92ffaSHans Petter Selasky if (status != IB_SUCCESS)
597d6b92ffaSHans Petter Selasky goto Exit;
598d6b92ffaSHans Petter Selasky
599d6b92ffaSHans Petter Selasky /*
600d6b92ffaSHans Petter Selasky * set Pkey for this MultiPath record request
601d6b92ffaSHans Petter Selasky */
602d6b92ffaSHans Petter Selasky
603d6b92ffaSHans Petter Selasky if (comp_mask & IB_MPR_COMPMASK_RAWTRAFFIC &&
604d6b92ffaSHans Petter Selasky cl_ntoh32(p_mpr->hop_flow_raw) & (1 << 31))
605d6b92ffaSHans Petter Selasky required_pkey =
606d6b92ffaSHans Petter Selasky osm_physp_find_common_pkey(p_src_physp, p_dest_physp,
607d6b92ffaSHans Petter Selasky sa->p_subn->opt.allow_both_pkeys);
608d6b92ffaSHans Petter Selasky
609d6b92ffaSHans Petter Selasky else if (comp_mask & IB_MPR_COMPMASK_PKEY) {
610d6b92ffaSHans Petter Selasky /*
611d6b92ffaSHans Petter Selasky * MPR request has a specific pkey:
612d6b92ffaSHans Petter Selasky * Check that source and destination share this pkey.
613d6b92ffaSHans Petter Selasky * If QoS level has pkeys, check that this pkey exists
614d6b92ffaSHans Petter Selasky * in the QoS level pkeys.
615d6b92ffaSHans Petter Selasky * MPR returned pkey is the requested pkey.
616d6b92ffaSHans Petter Selasky */
617d6b92ffaSHans Petter Selasky required_pkey = p_mpr->pkey;
618d6b92ffaSHans Petter Selasky if (!osm_physp_share_this_pkey
619d6b92ffaSHans Petter Selasky (p_src_physp, p_dest_physp, required_pkey,
620d6b92ffaSHans Petter Selasky sa->p_subn->opt.allow_both_pkeys)) {
621d6b92ffaSHans Petter Selasky OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4518: "
622d6b92ffaSHans Petter Selasky "Ports src 0x%016"PRIx64" (%s port %d) "
623d6b92ffaSHans Petter Selasky "and dst 0x%016"PRIx64" (%s port %d) "
624d6b92ffaSHans Petter Selasky "do not share the specified PKey 0x%04x\n",
625d6b92ffaSHans Petter Selasky cl_ntoh64(osm_physp_get_port_guid(p_src_physp)),
626d6b92ffaSHans Petter Selasky p_src_physp->p_node->print_desc,
627d6b92ffaSHans Petter Selasky p_src_physp->port_num,
628d6b92ffaSHans Petter Selasky cl_ntoh64(osm_physp_get_port_guid
629d6b92ffaSHans Petter Selasky (p_dest_physp)),
630d6b92ffaSHans Petter Selasky p_dest_physp->p_node->print_desc,
631d6b92ffaSHans Petter Selasky p_dest_physp->port_num,
632d6b92ffaSHans Petter Selasky cl_ntoh16(required_pkey));
633d6b92ffaSHans Petter Selasky status = IB_NOT_FOUND;
634d6b92ffaSHans Petter Selasky goto Exit;
635d6b92ffaSHans Petter Selasky }
636d6b92ffaSHans Petter Selasky if (p_qos_level && p_qos_level->pkey_range_len &&
637d6b92ffaSHans Petter Selasky !osm_qos_level_has_pkey(p_qos_level, required_pkey)) {
638d6b92ffaSHans Petter Selasky OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 451C: "
639d6b92ffaSHans Petter Selasky "Ports src 0x%016"PRIx64" (%s port %d) "
640d6b92ffaSHans Petter Selasky "and dst 0x%016"PRIx64" (%s port %d) "
641d6b92ffaSHans Petter Selasky "do not share specified PKey (0x%04x) as "
642d6b92ffaSHans Petter Selasky "defined by QoS level \"%s\"\n",
643d6b92ffaSHans Petter Selasky cl_ntoh64(osm_physp_get_port_guid(p_src_physp)),
644d6b92ffaSHans Petter Selasky p_src_physp->p_node->print_desc,
645d6b92ffaSHans Petter Selasky p_src_physp->port_num,
646d6b92ffaSHans Petter Selasky cl_ntoh64(osm_physp_get_port_guid
647d6b92ffaSHans Petter Selasky (p_dest_physp)),
648d6b92ffaSHans Petter Selasky p_dest_physp->p_node->print_desc,
649d6b92ffaSHans Petter Selasky p_dest_physp->port_num,
650d6b92ffaSHans Petter Selasky cl_ntoh16(required_pkey),
651d6b92ffaSHans Petter Selasky p_qos_level->name);
652d6b92ffaSHans Petter Selasky status = IB_NOT_FOUND;
653d6b92ffaSHans Petter Selasky goto Exit;
654d6b92ffaSHans Petter Selasky }
655d6b92ffaSHans Petter Selasky
656d6b92ffaSHans Petter Selasky } else if (p_qos_level && p_qos_level->pkey_range_len) {
657d6b92ffaSHans Petter Selasky /*
658d6b92ffaSHans Petter Selasky * MPR request doesn't have a specific pkey, but QoS level
659d6b92ffaSHans Petter Selasky * has pkeys - get shared pkey from QoS level pkeys
660d6b92ffaSHans Petter Selasky */
661d6b92ffaSHans Petter Selasky required_pkey = osm_qos_level_get_shared_pkey(p_qos_level,
662d6b92ffaSHans Petter Selasky p_src_physp,
663d6b92ffaSHans Petter Selasky p_dest_physp,
664d6b92ffaSHans Petter Selasky sa->p_subn->opt.allow_both_pkeys);
665d6b92ffaSHans Petter Selasky if (!required_pkey) {
666d6b92ffaSHans Petter Selasky OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 451D: "
667d6b92ffaSHans Petter Selasky "Ports src 0x%016"PRIx64" (%s port %d) "
668d6b92ffaSHans Petter Selasky "and dst 0x%016"PRIx64" (%s port %d) "
669d6b92ffaSHans Petter Selasky "do not share a PKey as defined by QoS "
670d6b92ffaSHans Petter Selasky "level \"%s\"\n",
671d6b92ffaSHans Petter Selasky cl_ntoh64(osm_physp_get_port_guid(p_src_physp)),
672d6b92ffaSHans Petter Selasky p_src_physp->p_node->print_desc,
673d6b92ffaSHans Petter Selasky p_src_physp->port_num,
674d6b92ffaSHans Petter Selasky cl_ntoh64(osm_physp_get_port_guid
675d6b92ffaSHans Petter Selasky (p_dest_physp)),
676d6b92ffaSHans Petter Selasky p_dest_physp->p_node->print_desc,
677d6b92ffaSHans Petter Selasky p_dest_physp->port_num,
678d6b92ffaSHans Petter Selasky p_qos_level->name);
679d6b92ffaSHans Petter Selasky status = IB_NOT_FOUND;
680d6b92ffaSHans Petter Selasky goto Exit;
681d6b92ffaSHans Petter Selasky }
682d6b92ffaSHans Petter Selasky
683d6b92ffaSHans Petter Selasky } else {
684d6b92ffaSHans Petter Selasky /*
685d6b92ffaSHans Petter Selasky * Neither MPR request nor QoS level have pkey.
686d6b92ffaSHans Petter Selasky * Just get any shared pkey.
687d6b92ffaSHans Petter Selasky */
688d6b92ffaSHans Petter Selasky required_pkey =
689d6b92ffaSHans Petter Selasky osm_physp_find_common_pkey(p_src_physp, p_dest_physp,
690d6b92ffaSHans Petter Selasky sa->p_subn->opt.allow_both_pkeys);
691d6b92ffaSHans Petter Selasky if (!required_pkey) {
692d6b92ffaSHans Petter Selasky OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4519: "
693d6b92ffaSHans Petter Selasky "Ports src 0x%016"PRIx64" (%s port %d) "
694d6b92ffaSHans Petter Selasky "and dst 0x%016"PRIx64" (%s port %d) "
695d6b92ffaSHans Petter Selasky "do not have any shared PKeys\n",
696d6b92ffaSHans Petter Selasky cl_ntoh64(osm_physp_get_port_guid(p_src_physp)),
697d6b92ffaSHans Petter Selasky p_src_physp->p_node->print_desc,
698d6b92ffaSHans Petter Selasky p_src_physp->port_num,
699d6b92ffaSHans Petter Selasky cl_ntoh64(osm_physp_get_port_guid
700d6b92ffaSHans Petter Selasky (p_dest_physp)),
701d6b92ffaSHans Petter Selasky p_dest_physp->p_node->print_desc,
702d6b92ffaSHans Petter Selasky p_dest_physp->port_num);
703d6b92ffaSHans Petter Selasky status = IB_NOT_FOUND;
704d6b92ffaSHans Petter Selasky goto Exit;
705d6b92ffaSHans Petter Selasky }
706d6b92ffaSHans Petter Selasky }
707d6b92ffaSHans Petter Selasky
708d6b92ffaSHans Petter Selasky if (required_pkey) {
709d6b92ffaSHans Petter Selasky p_prtn =
710d6b92ffaSHans Petter Selasky (osm_prtn_t *) cl_qmap_get(&sa->p_subn->prtn_pkey_tbl,
711d6b92ffaSHans Petter Selasky required_pkey &
712d6b92ffaSHans Petter Selasky cl_ntoh16((uint16_t) ~ 0x8000));
713d6b92ffaSHans Petter Selasky if (p_prtn ==
714d6b92ffaSHans Petter Selasky (osm_prtn_t *) cl_qmap_end(&sa->p_subn->prtn_pkey_tbl))
715d6b92ffaSHans Petter Selasky p_prtn = NULL;
716d6b92ffaSHans Petter Selasky }
717d6b92ffaSHans Petter Selasky
718d6b92ffaSHans Petter Selasky /*
719d6b92ffaSHans Petter Selasky * Set MultiPathRecord SL.
720d6b92ffaSHans Petter Selasky */
721d6b92ffaSHans Petter Selasky
722d6b92ffaSHans Petter Selasky if (comp_mask & IB_MPR_COMPMASK_SL) {
723d6b92ffaSHans Petter Selasky /*
724d6b92ffaSHans Petter Selasky * Specific SL was requested
725d6b92ffaSHans Petter Selasky */
726d6b92ffaSHans Petter Selasky required_sl = ib_multipath_rec_sl(p_mpr);
727d6b92ffaSHans Petter Selasky
728d6b92ffaSHans Petter Selasky if (p_qos_level && p_qos_level->sl_set &&
729d6b92ffaSHans Petter Selasky p_qos_level->sl != required_sl) {
730d6b92ffaSHans Petter Selasky OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 451E: "
731d6b92ffaSHans Petter Selasky "QoS constraints: required MultiPathRecord SL "
732d6b92ffaSHans Petter Selasky "(%u) doesn't match QoS policy \"%s\" SL (%u) "
733d6b92ffaSHans Petter Selasky "[%s port %d <-> %s port %d]\n", required_sl,
734d6b92ffaSHans Petter Selasky p_qos_level->name,
735d6b92ffaSHans Petter Selasky p_qos_level->sl,
736d6b92ffaSHans Petter Selasky p_src_alias_guid->p_base_port->p_node->print_desc,
737d6b92ffaSHans Petter Selasky p_src_alias_guid->p_base_port->p_physp->port_num,
738d6b92ffaSHans Petter Selasky p_dest_alias_guid->p_base_port->p_node->print_desc,
739d6b92ffaSHans Petter Selasky p_dest_alias_guid->p_base_port->p_physp->port_num);
740d6b92ffaSHans Petter Selasky status = IB_NOT_FOUND;
741d6b92ffaSHans Petter Selasky goto Exit;
742d6b92ffaSHans Petter Selasky }
743d6b92ffaSHans Petter Selasky
744d6b92ffaSHans Petter Selasky } else if (p_qos_level && p_qos_level->sl_set) {
745d6b92ffaSHans Petter Selasky /*
746d6b92ffaSHans Petter Selasky * No specific SL was requested,
747d6b92ffaSHans Petter Selasky * but there is an SL in QoS level.
748d6b92ffaSHans Petter Selasky */
749d6b92ffaSHans Petter Selasky required_sl = p_qos_level->sl;
750d6b92ffaSHans Petter Selasky
751d6b92ffaSHans Petter Selasky if (required_pkey && p_prtn && p_prtn->sl != p_qos_level->sl)
752d6b92ffaSHans Petter Selasky OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
753d6b92ffaSHans Petter Selasky "QoS level SL (%u) overrides partition SL (%u)\n",
754d6b92ffaSHans Petter Selasky p_qos_level->sl, p_prtn->sl);
755d6b92ffaSHans Petter Selasky
756d6b92ffaSHans Petter Selasky } else if (required_pkey) {
757d6b92ffaSHans Petter Selasky /*
758d6b92ffaSHans Petter Selasky * No specific SL in request or in QoS level - use partition SL
759d6b92ffaSHans Petter Selasky */
760d6b92ffaSHans Petter Selasky p_prtn =
761d6b92ffaSHans Petter Selasky (osm_prtn_t *) cl_qmap_get(&sa->p_subn->prtn_pkey_tbl,
762d6b92ffaSHans Petter Selasky required_pkey &
763d6b92ffaSHans Petter Selasky cl_ntoh16((uint16_t) ~ 0x8000));
764d6b92ffaSHans Petter Selasky if (!p_prtn) {
765d6b92ffaSHans Petter Selasky required_sl = OSM_DEFAULT_SL;
766d6b92ffaSHans Petter Selasky /* this may be possible when pkey tables are created somehow in
767d6b92ffaSHans Petter Selasky previous runs or things are going wrong here */
768d6b92ffaSHans Petter Selasky OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 451A: "
769d6b92ffaSHans Petter Selasky "No partition found for PKey 0x%04x - "
770d6b92ffaSHans Petter Selasky "using default SL %d "
771d6b92ffaSHans Petter Selasky "[%s port %d <-> %s port %d]\n",
772d6b92ffaSHans Petter Selasky cl_ntoh16(required_pkey), required_sl,
773d6b92ffaSHans Petter Selasky p_src_alias_guid->p_base_port->p_node->print_desc,
774d6b92ffaSHans Petter Selasky p_src_alias_guid->p_base_port->p_physp->port_num,
775d6b92ffaSHans Petter Selasky p_dest_alias_guid->p_base_port->p_node->print_desc,
776d6b92ffaSHans Petter Selasky p_dest_alias_guid->p_base_port->p_physp->port_num);
777d6b92ffaSHans Petter Selasky } else
778d6b92ffaSHans Petter Selasky required_sl = p_prtn->sl;
779d6b92ffaSHans Petter Selasky
780d6b92ffaSHans Petter Selasky } else if (sa->p_subn->opt.qos) {
781d6b92ffaSHans Petter Selasky if (valid_sl_mask & (1 << OSM_DEFAULT_SL))
782d6b92ffaSHans Petter Selasky required_sl = OSM_DEFAULT_SL;
783d6b92ffaSHans Petter Selasky else {
784d6b92ffaSHans Petter Selasky for (i = 0; i < IB_MAX_NUM_VLS; i++)
785d6b92ffaSHans Petter Selasky if (valid_sl_mask & (1 << i))
786d6b92ffaSHans Petter Selasky break;
787d6b92ffaSHans Petter Selasky required_sl = i;
788d6b92ffaSHans Petter Selasky }
789d6b92ffaSHans Petter Selasky } else
790d6b92ffaSHans Petter Selasky required_sl = OSM_DEFAULT_SL;
791d6b92ffaSHans Petter Selasky
792d6b92ffaSHans Petter Selasky if (sa->p_subn->opt.qos && !(valid_sl_mask & (1 << required_sl))) {
793d6b92ffaSHans Petter Selasky OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 451F: "
794d6b92ffaSHans Petter Selasky "Selected SL (%u) leads to VL15 "
795d6b92ffaSHans Petter Selasky "[%s port %d <-> %s port %d]\n",
796d6b92ffaSHans Petter Selasky required_sl,
797d6b92ffaSHans Petter Selasky p_src_alias_guid->p_base_port->p_node->print_desc,
798d6b92ffaSHans Petter Selasky p_src_alias_guid->p_base_port->p_physp->port_num,
799d6b92ffaSHans Petter Selasky p_dest_alias_guid->p_base_port->p_node->print_desc,
800d6b92ffaSHans Petter Selasky p_dest_alias_guid->p_base_port->p_physp->port_num);
801d6b92ffaSHans Petter Selasky status = IB_NOT_FOUND;
802d6b92ffaSHans Petter Selasky goto Exit;
803d6b92ffaSHans Petter Selasky }
804d6b92ffaSHans Petter Selasky
805d6b92ffaSHans Petter Selasky /* reset pkey when raw traffic */
806d6b92ffaSHans Petter Selasky if (comp_mask & IB_MPR_COMPMASK_RAWTRAFFIC &&
807d6b92ffaSHans Petter Selasky cl_ntoh32(p_mpr->hop_flow_raw) & (1 << 31))
808d6b92ffaSHans Petter Selasky required_pkey = 0;
809d6b92ffaSHans Petter Selasky
810d6b92ffaSHans Petter Selasky p_parms->mtu = mtu;
811d6b92ffaSHans Petter Selasky p_parms->rate = rate;
812d6b92ffaSHans Petter Selasky p_parms->pkey = required_pkey;
813d6b92ffaSHans Petter Selasky p_parms->pkt_life = pkt_life;
814d6b92ffaSHans Petter Selasky p_parms->sl = required_sl;
815d6b92ffaSHans Petter Selasky p_parms->hops = hops;
816d6b92ffaSHans Petter Selasky
817d6b92ffaSHans Petter Selasky OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "MultiPath params:"
818d6b92ffaSHans Petter Selasky " mtu = %u, rate = %u, packet lifetime = %u,"
819d6b92ffaSHans Petter Selasky " pkey = 0x%04X, sl = %u, hops = %u\n", mtu, rate,
820d6b92ffaSHans Petter Selasky pkt_life, cl_ntoh16(required_pkey), required_sl, hops);
821d6b92ffaSHans Petter Selasky
822d6b92ffaSHans Petter Selasky Exit:
823d6b92ffaSHans Petter Selasky OSM_LOG_EXIT(sa->p_log);
824d6b92ffaSHans Petter Selasky return status;
825d6b92ffaSHans Petter Selasky }
826d6b92ffaSHans Petter Selasky
mpr_rcv_build_pr(IN osm_sa_t * sa,IN const osm_alias_guid_t * p_src_alias_guid,IN const osm_alias_guid_t * p_dest_alias_guid,IN uint16_t src_lid_ho,IN uint16_t dest_lid_ho,IN uint8_t preference,IN const osm_path_parms_t * p_parms,OUT ib_path_rec_t * p_pr)827d6b92ffaSHans Petter Selasky static void mpr_rcv_build_pr(IN osm_sa_t * sa,
828d6b92ffaSHans Petter Selasky IN const osm_alias_guid_t * p_src_alias_guid,
829d6b92ffaSHans Petter Selasky IN const osm_alias_guid_t * p_dest_alias_guid,
830d6b92ffaSHans Petter Selasky IN uint16_t src_lid_ho, IN uint16_t dest_lid_ho,
831d6b92ffaSHans Petter Selasky IN uint8_t preference,
832d6b92ffaSHans Petter Selasky IN const osm_path_parms_t * p_parms,
833d6b92ffaSHans Petter Selasky OUT ib_path_rec_t * p_pr)
834d6b92ffaSHans Petter Selasky {
835d6b92ffaSHans Petter Selasky const osm_physp_t *p_src_physp, *p_dest_physp;
836d6b92ffaSHans Petter Selasky
837d6b92ffaSHans Petter Selasky OSM_LOG_ENTER(sa->p_log);
838d6b92ffaSHans Petter Selasky
839d6b92ffaSHans Petter Selasky p_src_physp = p_src_alias_guid->p_base_port->p_physp;
840d6b92ffaSHans Petter Selasky p_dest_physp = p_dest_alias_guid->p_base_port->p_physp;
841d6b92ffaSHans Petter Selasky
842d6b92ffaSHans Petter Selasky p_pr->dgid.unicast.prefix = osm_physp_get_subnet_prefix(p_dest_physp);
843d6b92ffaSHans Petter Selasky p_pr->dgid.unicast.interface_id = p_dest_alias_guid->alias_guid;
844d6b92ffaSHans Petter Selasky
845d6b92ffaSHans Petter Selasky p_pr->sgid.unicast.prefix = osm_physp_get_subnet_prefix(p_src_physp);
846d6b92ffaSHans Petter Selasky p_pr->sgid.unicast.interface_id = p_src_alias_guid->alias_guid;
847d6b92ffaSHans Petter Selasky
848d6b92ffaSHans Petter Selasky p_pr->dlid = cl_hton16(dest_lid_ho);
849d6b92ffaSHans Petter Selasky p_pr->slid = cl_hton16(src_lid_ho);
850d6b92ffaSHans Petter Selasky
851d6b92ffaSHans Petter Selasky p_pr->hop_flow_raw &= cl_hton32(1 << 31);
852d6b92ffaSHans Petter Selasky
853d6b92ffaSHans Petter Selasky p_pr->pkey = p_parms->pkey;
854d6b92ffaSHans Petter Selasky ib_path_rec_set_qos_class(p_pr, 0);
855d6b92ffaSHans Petter Selasky ib_path_rec_set_sl(p_pr, p_parms->sl);
856d6b92ffaSHans Petter Selasky p_pr->mtu = (uint8_t) (p_parms->mtu | 0x80);
857d6b92ffaSHans Petter Selasky p_pr->rate = (uint8_t) (p_parms->rate | 0x80);
858d6b92ffaSHans Petter Selasky
859d6b92ffaSHans Petter Selasky /* According to 1.2 spec definition Table 205 PacketLifeTime description,
860d6b92ffaSHans Petter Selasky for loopback paths, packetLifeTime shall be zero. */
861d6b92ffaSHans Petter Selasky if (p_src_alias_guid->p_base_port == p_dest_alias_guid->p_base_port)
862d6b92ffaSHans Petter Selasky p_pr->pkt_life = 0x80; /* loopback */
863d6b92ffaSHans Petter Selasky else
864d6b92ffaSHans Petter Selasky p_pr->pkt_life = (uint8_t) (p_parms->pkt_life | 0x80);
865d6b92ffaSHans Petter Selasky
866d6b92ffaSHans Petter Selasky p_pr->preference = preference;
867d6b92ffaSHans Petter Selasky
868d6b92ffaSHans Petter Selasky /* always return num_path = 0 so this is only the reversible component */
869d6b92ffaSHans Petter Selasky if (p_parms->reversible)
870d6b92ffaSHans Petter Selasky p_pr->num_path = 0x80;
871d6b92ffaSHans Petter Selasky
872d6b92ffaSHans Petter Selasky OSM_LOG_EXIT(sa->p_log);
873d6b92ffaSHans Petter Selasky }
874d6b92ffaSHans Petter Selasky
mpr_rcv_get_lid_pair_path(IN osm_sa_t * sa,IN const ib_multipath_rec_t * p_mpr,IN const osm_alias_guid_t * p_src_alias_guid,IN const osm_alias_guid_t * p_dest_alias_guid,IN const uint16_t src_lid_ho,IN const uint16_t dest_lid_ho,IN const ib_net64_t comp_mask,IN const uint8_t preference)875d6b92ffaSHans Petter Selasky static osm_sa_item_t *mpr_rcv_get_lid_pair_path(IN osm_sa_t * sa,
876d6b92ffaSHans Petter Selasky IN const ib_multipath_rec_t *
877d6b92ffaSHans Petter Selasky p_mpr,
878d6b92ffaSHans Petter Selasky IN const osm_alias_guid_t *
879d6b92ffaSHans Petter Selasky p_src_alias_guid,
880d6b92ffaSHans Petter Selasky IN const osm_alias_guid_t *
881d6b92ffaSHans Petter Selasky p_dest_alias_guid,
882d6b92ffaSHans Petter Selasky IN const uint16_t src_lid_ho,
883d6b92ffaSHans Petter Selasky IN const uint16_t dest_lid_ho,
884d6b92ffaSHans Petter Selasky IN const ib_net64_t comp_mask,
885d6b92ffaSHans Petter Selasky IN const uint8_t preference)
886d6b92ffaSHans Petter Selasky {
887d6b92ffaSHans Petter Selasky osm_path_parms_t path_parms;
888d6b92ffaSHans Petter Selasky osm_path_parms_t rev_path_parms;
889d6b92ffaSHans Petter Selasky osm_sa_item_t *p_pr_item;
890d6b92ffaSHans Petter Selasky ib_api_status_t status, rev_path_status;
891d6b92ffaSHans Petter Selasky
892d6b92ffaSHans Petter Selasky OSM_LOG_ENTER(sa->p_log);
893d6b92ffaSHans Petter Selasky
894d6b92ffaSHans Petter Selasky OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Src LID %u, Dest LID %u\n",
895d6b92ffaSHans Petter Selasky src_lid_ho, dest_lid_ho);
896d6b92ffaSHans Petter Selasky
897d6b92ffaSHans Petter Selasky p_pr_item = malloc(SA_MPR_RESP_SIZE);
898d6b92ffaSHans Petter Selasky if (p_pr_item == NULL) {
899d6b92ffaSHans Petter Selasky OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4501: "
900d6b92ffaSHans Petter Selasky "Unable to allocate path record\n");
901d6b92ffaSHans Petter Selasky goto Exit;
902d6b92ffaSHans Petter Selasky }
903d6b92ffaSHans Petter Selasky memset(p_pr_item, 0, SA_MPR_RESP_SIZE);
904d6b92ffaSHans Petter Selasky
905d6b92ffaSHans Petter Selasky status = mpr_rcv_get_path_parms(sa, p_mpr, p_src_alias_guid,
906d6b92ffaSHans Petter Selasky p_dest_alias_guid,
907d6b92ffaSHans Petter Selasky src_lid_ho, dest_lid_ho,
908d6b92ffaSHans Petter Selasky comp_mask, &path_parms);
909d6b92ffaSHans Petter Selasky
910d6b92ffaSHans Petter Selasky if (status != IB_SUCCESS) {
911d6b92ffaSHans Petter Selasky free(p_pr_item);
912d6b92ffaSHans Petter Selasky p_pr_item = NULL;
913d6b92ffaSHans Petter Selasky goto Exit;
914d6b92ffaSHans Petter Selasky }
915d6b92ffaSHans Petter Selasky
916d6b92ffaSHans Petter Selasky /* now try the reversible path */
917d6b92ffaSHans Petter Selasky rev_path_status = mpr_rcv_get_path_parms(sa, p_mpr, p_dest_alias_guid,
918d6b92ffaSHans Petter Selasky p_src_alias_guid,
919d6b92ffaSHans Petter Selasky dest_lid_ho, src_lid_ho,
920d6b92ffaSHans Petter Selasky comp_mask, &rev_path_parms);
921d6b92ffaSHans Petter Selasky path_parms.reversible = (rev_path_status == IB_SUCCESS);
922d6b92ffaSHans Petter Selasky
923d6b92ffaSHans Petter Selasky /* did we get a Reversible Path compmask ? */
924d6b92ffaSHans Petter Selasky /*
925d6b92ffaSHans Petter Selasky NOTE that if the reversible component = 0, it is a don't care
926d6b92ffaSHans Petter Selasky rather then requiring non-reversible paths ...
927d6b92ffaSHans Petter Selasky see Vol1 Ver1.2 p900 l16
928d6b92ffaSHans Petter Selasky */
929d6b92ffaSHans Petter Selasky if (comp_mask & IB_MPR_COMPMASK_REVERSIBLE) {
930d6b92ffaSHans Petter Selasky if ((!path_parms.reversible && (p_mpr->num_path & 0x80))) {
931d6b92ffaSHans Petter Selasky OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
932d6b92ffaSHans Petter Selasky "Requested reversible path but failed to get one\n");
933d6b92ffaSHans Petter Selasky
934d6b92ffaSHans Petter Selasky free(p_pr_item);
935d6b92ffaSHans Petter Selasky p_pr_item = NULL;
936d6b92ffaSHans Petter Selasky goto Exit;
937d6b92ffaSHans Petter Selasky }
938d6b92ffaSHans Petter Selasky }
939d6b92ffaSHans Petter Selasky
940d6b92ffaSHans Petter Selasky p_pr_item->resp.mpr_rec.p_src_port = p_src_alias_guid->p_base_port;
941d6b92ffaSHans Petter Selasky p_pr_item->resp.mpr_rec.p_dest_port = p_dest_alias_guid->p_base_port;
942d6b92ffaSHans Petter Selasky p_pr_item->resp.mpr_rec.hops = path_parms.hops;
943d6b92ffaSHans Petter Selasky
944d6b92ffaSHans Petter Selasky mpr_rcv_build_pr(sa, p_src_alias_guid, p_dest_alias_guid, src_lid_ho,
945d6b92ffaSHans Petter Selasky dest_lid_ho, preference, &path_parms,
946d6b92ffaSHans Petter Selasky &p_pr_item->resp.mpr_rec.path_rec);
947d6b92ffaSHans Petter Selasky
948d6b92ffaSHans Petter Selasky Exit:
949d6b92ffaSHans Petter Selasky OSM_LOG_EXIT(sa->p_log);
950d6b92ffaSHans Petter Selasky return p_pr_item;
951d6b92ffaSHans Petter Selasky }
952d6b92ffaSHans Petter Selasky
mpr_rcv_get_port_pair_paths(IN osm_sa_t * sa,IN const ib_multipath_rec_t * p_mpr,IN const osm_port_t * p_req_port,IN const osm_alias_guid_t * p_src_alias_guid,IN const osm_alias_guid_t * p_dest_alias_guid,IN const uint32_t rem_paths,IN const ib_net64_t comp_mask,IN cl_qlist_t * p_list)953d6b92ffaSHans Petter Selasky static uint32_t mpr_rcv_get_port_pair_paths(IN osm_sa_t * sa,
954d6b92ffaSHans Petter Selasky IN const ib_multipath_rec_t * p_mpr,
955d6b92ffaSHans Petter Selasky IN const osm_port_t * p_req_port,
956d6b92ffaSHans Petter Selasky IN const osm_alias_guid_t * p_src_alias_guid,
957d6b92ffaSHans Petter Selasky IN const osm_alias_guid_t * p_dest_alias_guid,
958d6b92ffaSHans Petter Selasky IN const uint32_t rem_paths,
959d6b92ffaSHans Petter Selasky IN const ib_net64_t comp_mask,
960d6b92ffaSHans Petter Selasky IN cl_qlist_t * p_list)
961d6b92ffaSHans Petter Selasky {
962d6b92ffaSHans Petter Selasky osm_sa_item_t *p_pr_item;
963d6b92ffaSHans Petter Selasky uint16_t src_lid_min_ho;
964d6b92ffaSHans Petter Selasky uint16_t src_lid_max_ho;
965d6b92ffaSHans Petter Selasky uint16_t dest_lid_min_ho;
966d6b92ffaSHans Petter Selasky uint16_t dest_lid_max_ho;
967d6b92ffaSHans Petter Selasky uint16_t src_lid_ho;
968d6b92ffaSHans Petter Selasky uint16_t dest_lid_ho;
969d6b92ffaSHans Petter Selasky uint32_t path_num = 0;
970d6b92ffaSHans Petter Selasky uint8_t preference;
971d6b92ffaSHans Petter Selasky unsigned src_offset, dest_offset;
972d6b92ffaSHans Petter Selasky
973d6b92ffaSHans Petter Selasky OSM_LOG_ENTER(sa->p_log);
974d6b92ffaSHans Petter Selasky
975d6b92ffaSHans Petter Selasky OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
976d6b92ffaSHans Petter Selasky "Src port 0x%016" PRIx64 ", Dst port 0x%016" PRIx64 "\n",
977d6b92ffaSHans Petter Selasky cl_ntoh64(p_src_alias_guid->alias_guid),
978d6b92ffaSHans Petter Selasky cl_ntoh64(p_dest_alias_guid->alias_guid));
979d6b92ffaSHans Petter Selasky
980d6b92ffaSHans Petter Selasky /* Check that the req_port, src_port and dest_port all share a
981d6b92ffaSHans Petter Selasky pkey. The check is done on the default physical port of the ports. */
982d6b92ffaSHans Petter Selasky if (osm_port_share_pkey(sa->p_log, p_req_port,
983d6b92ffaSHans Petter Selasky p_src_alias_guid->p_base_port,
984d6b92ffaSHans Petter Selasky sa->p_subn->opt.allow_both_pkeys) == FALSE
985d6b92ffaSHans Petter Selasky || osm_port_share_pkey(sa->p_log, p_req_port,
986d6b92ffaSHans Petter Selasky p_dest_alias_guid->p_base_port,
987d6b92ffaSHans Petter Selasky sa->p_subn->opt.allow_both_pkeys) == FALSE
988d6b92ffaSHans Petter Selasky || osm_port_share_pkey(sa->p_log, p_src_alias_guid->p_base_port,
989d6b92ffaSHans Petter Selasky p_dest_alias_guid->p_base_port,
990d6b92ffaSHans Petter Selasky sa->p_subn->opt.allow_both_pkeys) == FALSE)
991d6b92ffaSHans Petter Selasky /* One of the pairs doesn't share a pkey so the path is disqualified. */
992d6b92ffaSHans Petter Selasky goto Exit;
993d6b92ffaSHans Petter Selasky
994d6b92ffaSHans Petter Selasky /*
995d6b92ffaSHans Petter Selasky We shouldn't be here if the paths are disqualified in some way...
996d6b92ffaSHans Petter Selasky Thus, we assume every possible connection is valid.
997d6b92ffaSHans Petter Selasky
998d6b92ffaSHans Petter Selasky We desire to return high-quality paths first.
999d6b92ffaSHans Petter Selasky In OpenSM, higher quality mean least overlap with other paths.
1000d6b92ffaSHans Petter Selasky This is acheived in practice by returning paths with
1001d6b92ffaSHans Petter Selasky different LID value on each end, which means these
1002d6b92ffaSHans Petter Selasky paths are more redundant that paths with the same LID repeated
1003d6b92ffaSHans Petter Selasky on one side. For example, in OpenSM the paths between two
1004d6b92ffaSHans Petter Selasky endpoints with LMC = 1 might be as follows:
1005d6b92ffaSHans Petter Selasky
1006d6b92ffaSHans Petter Selasky Port A, LID 1 <-> Port B, LID 3
1007d6b92ffaSHans Petter Selasky Port A, LID 1 <-> Port B, LID 4
1008d6b92ffaSHans Petter Selasky Port A, LID 2 <-> Port B, LID 3
1009d6b92ffaSHans Petter Selasky Port A, LID 2 <-> Port B, LID 4
1010d6b92ffaSHans Petter Selasky
1011d6b92ffaSHans Petter Selasky The OpenSM unicast routing algorithms attempt to disperse each path
1012d6b92ffaSHans Petter Selasky to as varied a physical path as is reasonable. 1<->3 and 1<->4 have
1013d6b92ffaSHans Petter Selasky more physical overlap (hence less redundancy) than 1<->3 and 2<->4.
1014d6b92ffaSHans Petter Selasky
1015d6b92ffaSHans Petter Selasky OpenSM ranks paths in three preference groups:
1016d6b92ffaSHans Petter Selasky
1017d6b92ffaSHans Petter Selasky Preference Value Description
1018d6b92ffaSHans Petter Selasky ---------------- -------------------------------------------
1019d6b92ffaSHans Petter Selasky 0 Redundant in both directions with other
1020d6b92ffaSHans Petter Selasky pref value = 0 paths
1021d6b92ffaSHans Petter Selasky
1022d6b92ffaSHans Petter Selasky 1 Redundant in one direction with other
1023d6b92ffaSHans Petter Selasky pref value = 0 and pref value = 1 paths
1024d6b92ffaSHans Petter Selasky
1025d6b92ffaSHans Petter Selasky 2 Not redundant in either direction with
1026d6b92ffaSHans Petter Selasky other paths
1027d6b92ffaSHans Petter Selasky
1028d6b92ffaSHans Petter Selasky 3-FF Unused
1029d6b92ffaSHans Petter Selasky
1030d6b92ffaSHans Petter Selasky SA clients don't need to know these details, only that the lower
1031d6b92ffaSHans Petter Selasky preference paths are preferred, as stated in the spec. The paths
1032d6b92ffaSHans Petter Selasky may not actually be physically redundant depending on the topology
1033d6b92ffaSHans Petter Selasky of the subnet, but the point of LMC > 0 is to offer redundancy,
1034d6b92ffaSHans Petter Selasky so I assume the subnet is physically appropriate for the specified
1035d6b92ffaSHans Petter Selasky LMC value. A more advanced implementation could inspect for physical
1036d6b92ffaSHans Petter Selasky redundancy, but I'm not going to bother with that now.
1037d6b92ffaSHans Petter Selasky */
1038d6b92ffaSHans Petter Selasky
1039d6b92ffaSHans Petter Selasky osm_port_get_lid_range_ho(p_src_alias_guid->p_base_port,
1040d6b92ffaSHans Petter Selasky &src_lid_min_ho, &src_lid_max_ho);
1041d6b92ffaSHans Petter Selasky osm_port_get_lid_range_ho(p_dest_alias_guid->p_base_port,
1042d6b92ffaSHans Petter Selasky &dest_lid_min_ho, &dest_lid_max_ho);
1043d6b92ffaSHans Petter Selasky
1044d6b92ffaSHans Petter Selasky OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Src LID [%u-%u], Dest LID [%u-%u]\n",
1045d6b92ffaSHans Petter Selasky src_lid_min_ho, src_lid_max_ho,
1046d6b92ffaSHans Petter Selasky dest_lid_min_ho, dest_lid_max_ho);
1047d6b92ffaSHans Petter Selasky
1048d6b92ffaSHans Petter Selasky src_lid_ho = src_lid_min_ho;
1049d6b92ffaSHans Petter Selasky dest_lid_ho = dest_lid_min_ho;
1050d6b92ffaSHans Petter Selasky
1051d6b92ffaSHans Petter Selasky /*
1052d6b92ffaSHans Petter Selasky Preferred paths come first in OpenSM
1053d6b92ffaSHans Petter Selasky */
1054d6b92ffaSHans Petter Selasky preference = 0;
1055d6b92ffaSHans Petter Selasky
1056d6b92ffaSHans Petter Selasky while (path_num < rem_paths) {
1057d6b92ffaSHans Petter Selasky /*
1058d6b92ffaSHans Petter Selasky These paths are "fully redundant"
1059d6b92ffaSHans Petter Selasky */
1060d6b92ffaSHans Petter Selasky p_pr_item = mpr_rcv_get_lid_pair_path(sa, p_mpr,
1061d6b92ffaSHans Petter Selasky p_src_alias_guid,
1062d6b92ffaSHans Petter Selasky p_dest_alias_guid,
1063d6b92ffaSHans Petter Selasky src_lid_ho, dest_lid_ho,
1064d6b92ffaSHans Petter Selasky comp_mask, preference);
1065d6b92ffaSHans Petter Selasky
1066d6b92ffaSHans Petter Selasky if (p_pr_item) {
1067d6b92ffaSHans Petter Selasky cl_qlist_insert_tail(p_list, &p_pr_item->list_item);
1068d6b92ffaSHans Petter Selasky ++path_num;
1069d6b92ffaSHans Petter Selasky }
1070d6b92ffaSHans Petter Selasky
1071d6b92ffaSHans Petter Selasky if (++src_lid_ho > src_lid_max_ho)
1072d6b92ffaSHans Petter Selasky break;
1073d6b92ffaSHans Petter Selasky
1074d6b92ffaSHans Petter Selasky if (++dest_lid_ho > dest_lid_max_ho)
1075d6b92ffaSHans Petter Selasky break;
1076d6b92ffaSHans Petter Selasky }
1077d6b92ffaSHans Petter Selasky
1078d6b92ffaSHans Petter Selasky /*
1079d6b92ffaSHans Petter Selasky Check if we've accumulated all the paths that the user cares to see
1080d6b92ffaSHans Petter Selasky */
1081d6b92ffaSHans Petter Selasky if (path_num == rem_paths)
1082d6b92ffaSHans Petter Selasky goto Exit;
1083d6b92ffaSHans Petter Selasky
1084d6b92ffaSHans Petter Selasky /*
1085d6b92ffaSHans Petter Selasky Don't bother reporting preference 1 paths for now.
1086d6b92ffaSHans Petter Selasky It's more trouble than it's worth and can only occur
1087d6b92ffaSHans Petter Selasky if ports have different LMC values, which isn't supported
1088d6b92ffaSHans Petter Selasky by OpenSM right now anyway.
1089d6b92ffaSHans Petter Selasky */
1090d6b92ffaSHans Petter Selasky preference = 2;
1091d6b92ffaSHans Petter Selasky src_lid_ho = src_lid_min_ho;
1092d6b92ffaSHans Petter Selasky dest_lid_ho = dest_lid_min_ho;
1093d6b92ffaSHans Petter Selasky src_offset = 0;
1094d6b92ffaSHans Petter Selasky dest_offset = 0;
1095d6b92ffaSHans Petter Selasky
1096d6b92ffaSHans Petter Selasky /*
1097d6b92ffaSHans Petter Selasky Iterate over the remaining paths
1098d6b92ffaSHans Petter Selasky */
1099d6b92ffaSHans Petter Selasky while (path_num < rem_paths) {
1100d6b92ffaSHans Petter Selasky dest_offset++;
1101d6b92ffaSHans Petter Selasky dest_lid_ho++;
1102d6b92ffaSHans Petter Selasky
1103d6b92ffaSHans Petter Selasky if (dest_lid_ho > dest_lid_max_ho) {
1104d6b92ffaSHans Petter Selasky src_offset++;
1105d6b92ffaSHans Petter Selasky src_lid_ho++;
1106d6b92ffaSHans Petter Selasky
1107d6b92ffaSHans Petter Selasky if (src_lid_ho > src_lid_max_ho)
1108d6b92ffaSHans Petter Selasky break; /* done */
1109d6b92ffaSHans Petter Selasky
1110d6b92ffaSHans Petter Selasky dest_offset = 0;
1111d6b92ffaSHans Petter Selasky dest_lid_ho = dest_lid_min_ho;
1112d6b92ffaSHans Petter Selasky }
1113d6b92ffaSHans Petter Selasky
1114d6b92ffaSHans Petter Selasky /*
1115d6b92ffaSHans Petter Selasky These paths are "fully non-redundant" with paths already
1116d6b92ffaSHans Petter Selasky identified above and consequently not of much value.
1117d6b92ffaSHans Petter Selasky
1118d6b92ffaSHans Petter Selasky Don't return paths we already identified above, as indicated
1119d6b92ffaSHans Petter Selasky by the offset values being equal.
1120d6b92ffaSHans Petter Selasky */
1121d6b92ffaSHans Petter Selasky if (src_offset == dest_offset)
1122d6b92ffaSHans Petter Selasky continue; /* already reported */
1123d6b92ffaSHans Petter Selasky
1124d6b92ffaSHans Petter Selasky p_pr_item = mpr_rcv_get_lid_pair_path(sa, p_mpr,
1125d6b92ffaSHans Petter Selasky p_src_alias_guid,
1126d6b92ffaSHans Petter Selasky p_dest_alias_guid,
1127d6b92ffaSHans Petter Selasky src_lid_ho, dest_lid_ho,
1128d6b92ffaSHans Petter Selasky comp_mask, preference);
1129d6b92ffaSHans Petter Selasky
1130d6b92ffaSHans Petter Selasky if (p_pr_item) {
1131d6b92ffaSHans Petter Selasky cl_qlist_insert_tail(p_list, &p_pr_item->list_item);
1132d6b92ffaSHans Petter Selasky ++path_num;
1133d6b92ffaSHans Petter Selasky }
1134d6b92ffaSHans Petter Selasky }
1135d6b92ffaSHans Petter Selasky
1136d6b92ffaSHans Petter Selasky Exit:
1137d6b92ffaSHans Petter Selasky OSM_LOG_EXIT(sa->p_log);
1138d6b92ffaSHans Petter Selasky return path_num;
1139d6b92ffaSHans Petter Selasky }
1140d6b92ffaSHans Petter Selasky
1141d6b92ffaSHans Petter Selasky #undef min
1142d6b92ffaSHans Petter Selasky #define min(x,y) (((x) < (y)) ? (x) : (y))
1143d6b92ffaSHans Petter Selasky
mpr_rcv_get_apm_port_pair_paths(IN osm_sa_t * sa,IN const ib_multipath_rec_t * p_mpr,IN const osm_alias_guid_t * p_src_alias_guid,IN const osm_alias_guid_t * p_dest_alias_guid,IN int base_offs,IN const ib_net64_t comp_mask,IN cl_qlist_t * p_list)1144d6b92ffaSHans Petter Selasky static osm_sa_item_t *mpr_rcv_get_apm_port_pair_paths(IN osm_sa_t * sa,
1145d6b92ffaSHans Petter Selasky IN const
1146d6b92ffaSHans Petter Selasky ib_multipath_rec_t *
1147d6b92ffaSHans Petter Selasky p_mpr,
1148d6b92ffaSHans Petter Selasky IN const osm_alias_guid_t *
1149d6b92ffaSHans Petter Selasky p_src_alias_guid,
1150d6b92ffaSHans Petter Selasky IN const osm_alias_guid_t *
1151d6b92ffaSHans Petter Selasky p_dest_alias_guid,
1152d6b92ffaSHans Petter Selasky IN int base_offs,
1153d6b92ffaSHans Petter Selasky IN const ib_net64_t
1154d6b92ffaSHans Petter Selasky comp_mask,
1155d6b92ffaSHans Petter Selasky IN cl_qlist_t * p_list)
1156d6b92ffaSHans Petter Selasky {
1157d6b92ffaSHans Petter Selasky osm_sa_item_t *p_pr_item = 0;
1158d6b92ffaSHans Petter Selasky uint16_t src_lid_min_ho;
1159d6b92ffaSHans Petter Selasky uint16_t src_lid_max_ho;
1160d6b92ffaSHans Petter Selasky uint16_t dest_lid_min_ho;
1161d6b92ffaSHans Petter Selasky uint16_t dest_lid_max_ho;
1162d6b92ffaSHans Petter Selasky uint16_t src_lid_ho;
1163d6b92ffaSHans Petter Selasky uint16_t dest_lid_ho;
1164d6b92ffaSHans Petter Selasky unsigned iterations;
1165d6b92ffaSHans Petter Selasky int src_lids, dest_lids;
1166d6b92ffaSHans Petter Selasky
1167d6b92ffaSHans Petter Selasky OSM_LOG_ENTER(sa->p_log);
1168d6b92ffaSHans Petter Selasky
1169d6b92ffaSHans Petter Selasky OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Src port 0x%016" PRIx64 ", "
1170d6b92ffaSHans Petter Selasky "Dst port 0x%016" PRIx64 ", base offs %d\n",
1171d6b92ffaSHans Petter Selasky cl_ntoh64(p_src_alias_guid->alias_guid),
1172d6b92ffaSHans Petter Selasky cl_ntoh64(p_dest_alias_guid->alias_guid),
1173d6b92ffaSHans Petter Selasky base_offs);
1174d6b92ffaSHans Petter Selasky
1175d6b92ffaSHans Petter Selasky osm_port_get_lid_range_ho(p_src_alias_guid->p_base_port,
1176d6b92ffaSHans Petter Selasky &src_lid_min_ho, &src_lid_max_ho);
1177d6b92ffaSHans Petter Selasky osm_port_get_lid_range_ho(p_dest_alias_guid->p_base_port,
1178d6b92ffaSHans Petter Selasky &dest_lid_min_ho, &dest_lid_max_ho);
1179d6b92ffaSHans Petter Selasky
1180d6b92ffaSHans Petter Selasky src_lid_ho = src_lid_min_ho;
1181d6b92ffaSHans Petter Selasky dest_lid_ho = dest_lid_min_ho;
1182d6b92ffaSHans Petter Selasky
1183d6b92ffaSHans Petter Selasky src_lids = src_lid_max_ho - src_lid_min_ho + 1;
1184d6b92ffaSHans Petter Selasky dest_lids = dest_lid_max_ho - dest_lid_min_ho + 1;
1185d6b92ffaSHans Petter Selasky
1186d6b92ffaSHans Petter Selasky src_lid_ho += base_offs % src_lids;
1187d6b92ffaSHans Petter Selasky dest_lid_ho += base_offs % dest_lids;
1188d6b92ffaSHans Petter Selasky
1189d6b92ffaSHans Petter Selasky OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
1190d6b92ffaSHans Petter Selasky "Src LIDs [%u-%u] hashed %u, "
1191d6b92ffaSHans Petter Selasky "Dest LIDs [%u-%u] hashed %u\n",
1192d6b92ffaSHans Petter Selasky src_lid_min_ho, src_lid_max_ho, src_lid_ho,
1193d6b92ffaSHans Petter Selasky dest_lid_min_ho, dest_lid_max_ho, dest_lid_ho);
1194d6b92ffaSHans Petter Selasky
1195d6b92ffaSHans Petter Selasky iterations = min(src_lids, dest_lids);
1196d6b92ffaSHans Petter Selasky
1197d6b92ffaSHans Petter Selasky while (iterations--) {
1198d6b92ffaSHans Petter Selasky /*
1199d6b92ffaSHans Petter Selasky These paths are "fully redundant"
1200d6b92ffaSHans Petter Selasky */
1201d6b92ffaSHans Petter Selasky p_pr_item = mpr_rcv_get_lid_pair_path(sa, p_mpr,
1202d6b92ffaSHans Petter Selasky p_src_alias_guid,
1203d6b92ffaSHans Petter Selasky p_dest_alias_guid,
1204d6b92ffaSHans Petter Selasky src_lid_ho, dest_lid_ho,
1205d6b92ffaSHans Petter Selasky comp_mask, 0);
1206d6b92ffaSHans Petter Selasky
1207d6b92ffaSHans Petter Selasky if (p_pr_item) {
1208d6b92ffaSHans Petter Selasky OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
1209d6b92ffaSHans Petter Selasky "Found matching path from Src LID %u to Dest LID %u with %d hops\n",
1210d6b92ffaSHans Petter Selasky src_lid_ho, dest_lid_ho, p_pr_item->resp.mpr_rec.hops);
1211d6b92ffaSHans Petter Selasky break;
1212d6b92ffaSHans Petter Selasky }
1213d6b92ffaSHans Petter Selasky
1214d6b92ffaSHans Petter Selasky if (++src_lid_ho > src_lid_max_ho)
1215d6b92ffaSHans Petter Selasky src_lid_ho = src_lid_min_ho;
1216d6b92ffaSHans Petter Selasky
1217d6b92ffaSHans Petter Selasky if (++dest_lid_ho > dest_lid_max_ho)
1218d6b92ffaSHans Petter Selasky dest_lid_ho = dest_lid_min_ho;
1219d6b92ffaSHans Petter Selasky }
1220d6b92ffaSHans Petter Selasky
1221d6b92ffaSHans Petter Selasky OSM_LOG_EXIT(sa->p_log);
1222d6b92ffaSHans Petter Selasky return p_pr_item;
1223d6b92ffaSHans Petter Selasky }
1224d6b92ffaSHans Petter Selasky
mpr_rcv_get_gids(IN osm_sa_t * sa,IN const ib_gid_t * gids,IN int ngids,IN int is_sgid,OUT osm_alias_guid_t ** pp_alias_guid)1225d6b92ffaSHans Petter Selasky static ib_net16_t mpr_rcv_get_gids(IN osm_sa_t * sa, IN const ib_gid_t * gids,
1226d6b92ffaSHans Petter Selasky IN int ngids, IN int is_sgid,
1227d6b92ffaSHans Petter Selasky OUT osm_alias_guid_t ** pp_alias_guid)
1228d6b92ffaSHans Petter Selasky {
1229d6b92ffaSHans Petter Selasky osm_alias_guid_t *p_alias_guid;
1230d6b92ffaSHans Petter Selasky ib_net16_t ib_status = IB_SUCCESS;
1231d6b92ffaSHans Petter Selasky int i;
1232d6b92ffaSHans Petter Selasky
1233d6b92ffaSHans Petter Selasky OSM_LOG_ENTER(sa->p_log);
1234d6b92ffaSHans Petter Selasky
1235d6b92ffaSHans Petter Selasky for (i = 0; i < ngids; i++, gids++) {
1236d6b92ffaSHans Petter Selasky if (!ib_gid_is_link_local(gids)) {
1237d6b92ffaSHans Petter Selasky if ((is_sgid && ib_gid_is_multicast(gids)) ||
1238d6b92ffaSHans Petter Selasky (ib_gid_get_subnet_prefix(gids) !=
1239d6b92ffaSHans Petter Selasky sa->p_subn->opt.subnet_prefix)) {
1240d6b92ffaSHans Petter Selasky /*
1241d6b92ffaSHans Petter Selasky This 'error' is the client's fault (bad gid)
1242d6b92ffaSHans Petter Selasky so don't enter it as an error in our own log.
1243d6b92ffaSHans Petter Selasky Return an error response to the client.
1244d6b92ffaSHans Petter Selasky */
1245d6b92ffaSHans Petter Selasky OSM_LOG(sa->p_log, OSM_LOG_VERBOSE, "ERR 451B: "
1246d6b92ffaSHans Petter Selasky "%sGID 0x%016" PRIx64
1247d6b92ffaSHans Petter Selasky " is multicast or non local subnet prefix\n",
1248d6b92ffaSHans Petter Selasky is_sgid ? "S" : "D",
1249d6b92ffaSHans Petter Selasky cl_ntoh64(gids->unicast.prefix));
1250d6b92ffaSHans Petter Selasky
1251d6b92ffaSHans Petter Selasky ib_status = IB_SA_MAD_STATUS_INVALID_GID;
1252d6b92ffaSHans Petter Selasky goto Exit;
1253d6b92ffaSHans Petter Selasky }
1254d6b92ffaSHans Petter Selasky }
1255d6b92ffaSHans Petter Selasky
1256d6b92ffaSHans Petter Selasky p_alias_guid =
1257d6b92ffaSHans Petter Selasky osm_get_alias_guid_by_guid(sa->p_subn,
1258d6b92ffaSHans Petter Selasky gids->unicast.interface_id);
1259d6b92ffaSHans Petter Selasky if (!p_alias_guid) {
1260d6b92ffaSHans Petter Selasky /*
1261d6b92ffaSHans Petter Selasky This 'error' is the client's fault (bad gid) so
1262d6b92ffaSHans Petter Selasky don't enter it as an error in our own log.
1263d6b92ffaSHans Petter Selasky Return an error response to the client.
1264d6b92ffaSHans Petter Selasky */
1265d6b92ffaSHans Petter Selasky OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4506: "
1266d6b92ffaSHans Petter Selasky "No port with GUID 0x%016" PRIx64 "\n",
1267d6b92ffaSHans Petter Selasky cl_ntoh64(gids->unicast.interface_id));
1268d6b92ffaSHans Petter Selasky
1269d6b92ffaSHans Petter Selasky ib_status = IB_SA_MAD_STATUS_INVALID_GID;
1270d6b92ffaSHans Petter Selasky goto Exit;
1271d6b92ffaSHans Petter Selasky }
1272d6b92ffaSHans Petter Selasky
1273d6b92ffaSHans Petter Selasky pp_alias_guid[i] = p_alias_guid;
1274d6b92ffaSHans Petter Selasky }
1275d6b92ffaSHans Petter Selasky
1276d6b92ffaSHans Petter Selasky Exit:
1277d6b92ffaSHans Petter Selasky OSM_LOG_EXIT(sa->p_log);
1278d6b92ffaSHans Petter Selasky
1279d6b92ffaSHans Petter Selasky return ib_status;
1280d6b92ffaSHans Petter Selasky }
1281d6b92ffaSHans Petter Selasky
mpr_rcv_get_end_points(IN osm_sa_t * sa,IN const osm_madw_t * p_madw,OUT osm_alias_guid_t ** pp_alias_guids,OUT int * nsrc,OUT int * ndest)1282d6b92ffaSHans Petter Selasky static ib_net16_t mpr_rcv_get_end_points(IN osm_sa_t * sa,
1283d6b92ffaSHans Petter Selasky IN const osm_madw_t * p_madw,
1284d6b92ffaSHans Petter Selasky OUT osm_alias_guid_t ** pp_alias_guids,
1285d6b92ffaSHans Petter Selasky OUT int *nsrc, OUT int *ndest)
1286d6b92ffaSHans Petter Selasky {
1287d6b92ffaSHans Petter Selasky const ib_multipath_rec_t *p_mpr;
1288d6b92ffaSHans Petter Selasky const ib_sa_mad_t *p_sa_mad;
1289d6b92ffaSHans Petter Selasky ib_net64_t comp_mask;
1290d6b92ffaSHans Petter Selasky ib_net16_t sa_status = IB_SA_MAD_STATUS_SUCCESS;
1291d6b92ffaSHans Petter Selasky ib_gid_t *gids;
1292d6b92ffaSHans Petter Selasky
1293d6b92ffaSHans Petter Selasky OSM_LOG_ENTER(sa->p_log);
1294d6b92ffaSHans Petter Selasky
1295d6b92ffaSHans Petter Selasky /*
1296d6b92ffaSHans Petter Selasky Determine what fields are valid and then get a pointer
1297d6b92ffaSHans Petter Selasky to the source and destination port objects, if possible.
1298d6b92ffaSHans Petter Selasky */
1299d6b92ffaSHans Petter Selasky p_sa_mad = osm_madw_get_sa_mad_ptr(p_madw);
1300d6b92ffaSHans Petter Selasky p_mpr = (ib_multipath_rec_t *) ib_sa_mad_get_payload_ptr(p_sa_mad);
1301d6b92ffaSHans Petter Selasky gids = (ib_gid_t *) p_mpr->gids;
1302d6b92ffaSHans Petter Selasky
1303d6b92ffaSHans Petter Selasky comp_mask = p_sa_mad->comp_mask;
1304d6b92ffaSHans Petter Selasky
1305d6b92ffaSHans Petter Selasky /*
1306d6b92ffaSHans Petter Selasky Check a few easy disqualifying cases up front before getting
1307d6b92ffaSHans Petter Selasky into the endpoints.
1308d6b92ffaSHans Petter Selasky */
1309d6b92ffaSHans Petter Selasky *nsrc = *ndest = 0;
1310d6b92ffaSHans Petter Selasky
1311d6b92ffaSHans Petter Selasky if (comp_mask & IB_MPR_COMPMASK_SGIDCOUNT) {
1312d6b92ffaSHans Petter Selasky *nsrc = p_mpr->sgid_count;
1313d6b92ffaSHans Petter Selasky if (*nsrc > IB_MULTIPATH_MAX_GIDS)
1314d6b92ffaSHans Petter Selasky *nsrc = IB_MULTIPATH_MAX_GIDS;
1315d6b92ffaSHans Petter Selasky sa_status = mpr_rcv_get_gids(sa, gids, *nsrc, 1, pp_alias_guids);
1316d6b92ffaSHans Petter Selasky if (sa_status != IB_SUCCESS)
1317d6b92ffaSHans Petter Selasky goto Exit;
1318d6b92ffaSHans Petter Selasky }
1319d6b92ffaSHans Petter Selasky
1320d6b92ffaSHans Petter Selasky if (comp_mask & IB_MPR_COMPMASK_DGIDCOUNT) {
1321d6b92ffaSHans Petter Selasky *ndest = p_mpr->dgid_count;
1322d6b92ffaSHans Petter Selasky if (*ndest + *nsrc > IB_MULTIPATH_MAX_GIDS)
1323d6b92ffaSHans Petter Selasky *ndest = IB_MULTIPATH_MAX_GIDS - *nsrc;
1324d6b92ffaSHans Petter Selasky sa_status =
1325d6b92ffaSHans Petter Selasky mpr_rcv_get_gids(sa, gids + *nsrc, *ndest, 0,
1326d6b92ffaSHans Petter Selasky pp_alias_guids + *nsrc);
1327d6b92ffaSHans Petter Selasky }
1328d6b92ffaSHans Petter Selasky
1329d6b92ffaSHans Petter Selasky Exit:
1330d6b92ffaSHans Petter Selasky OSM_LOG_EXIT(sa->p_log);
1331d6b92ffaSHans Petter Selasky return sa_status;
1332d6b92ffaSHans Petter Selasky }
1333d6b92ffaSHans Petter Selasky
1334d6b92ffaSHans Petter Selasky #define hash_lids(a, b, lmc) \
1335d6b92ffaSHans Petter Selasky (((((a) >> (lmc)) << 4) | ((b) >> (lmc))) % 103)
1336d6b92ffaSHans Petter Selasky
mpr_rcv_get_apm_paths(IN osm_sa_t * sa,IN const ib_multipath_rec_t * p_mpr,IN const osm_port_t * p_req_port,IN osm_alias_guid_t ** _pp_alias_guids,IN const ib_net64_t comp_mask,IN cl_qlist_t * p_list)1337d6b92ffaSHans Petter Selasky static void mpr_rcv_get_apm_paths(IN osm_sa_t * sa,
1338d6b92ffaSHans Petter Selasky IN const ib_multipath_rec_t * p_mpr,
1339d6b92ffaSHans Petter Selasky IN const osm_port_t * p_req_port,
1340d6b92ffaSHans Petter Selasky IN osm_alias_guid_t ** _pp_alias_guids,
1341d6b92ffaSHans Petter Selasky IN const ib_net64_t comp_mask,
1342d6b92ffaSHans Petter Selasky IN cl_qlist_t * p_list)
1343d6b92ffaSHans Petter Selasky {
1344d6b92ffaSHans Petter Selasky osm_alias_guid_t *pp_alias_guids[4];
1345d6b92ffaSHans Petter Selasky osm_sa_item_t *matrix[2][2];
1346d6b92ffaSHans Petter Selasky int base_offs, src_lid_ho, dest_lid_ho;
1347d6b92ffaSHans Petter Selasky int sumA, sumB, minA, minB;
1348d6b92ffaSHans Petter Selasky
1349d6b92ffaSHans Petter Selasky OSM_LOG_ENTER(sa->p_log);
1350d6b92ffaSHans Petter Selasky
1351d6b92ffaSHans Petter Selasky /*
1352d6b92ffaSHans Petter Selasky * We want to:
1353d6b92ffaSHans Petter Selasky * 1. use different lid offsets (from base) for the resultant paths
1354d6b92ffaSHans Petter Selasky * to increase the probability of redundant paths or in case
1355d6b92ffaSHans Petter Selasky * of Clos - to ensure it (different offset => different spine!)
1356d6b92ffaSHans Petter Selasky * 2. keep consistent paths no matter of direction and order of ports
1357d6b92ffaSHans Petter Selasky * 3. distibute the lid offsets to balance the load
1358d6b92ffaSHans Petter Selasky * So, we sort the ports (within the srcs, and within the dests),
1359d6b92ffaSHans Petter Selasky * hash the lids of S0, D0 (after the sort), and call mpr_rcv_get_apm_port_pair_paths
1360d6b92ffaSHans Petter Selasky * with base_lid for S0, D0 and base_lid + 1 for S1, D1. This way we will get
1361d6b92ffaSHans Petter Selasky * always the same offsets - order independent, and make sure different spines are used.
1362d6b92ffaSHans Petter Selasky * Note that the diagonals on a Clos have the same number of hops, so it doesn't
1363d6b92ffaSHans Petter Selasky * really matter which diagonal we use.
1364d6b92ffaSHans Petter Selasky */
1365d6b92ffaSHans Petter Selasky if (_pp_alias_guids[0]->p_base_port->guid <
1366d6b92ffaSHans Petter Selasky _pp_alias_guids[1]->p_base_port->guid) {
1367d6b92ffaSHans Petter Selasky pp_alias_guids[0] = _pp_alias_guids[0];
1368d6b92ffaSHans Petter Selasky pp_alias_guids[1] = _pp_alias_guids[1];
1369d6b92ffaSHans Petter Selasky } else {
1370d6b92ffaSHans Petter Selasky pp_alias_guids[0] = _pp_alias_guids[1];
1371d6b92ffaSHans Petter Selasky pp_alias_guids[1] = _pp_alias_guids[0];
1372d6b92ffaSHans Petter Selasky }
1373d6b92ffaSHans Petter Selasky if (_pp_alias_guids[2]->p_base_port->guid <
1374d6b92ffaSHans Petter Selasky _pp_alias_guids[3]->p_base_port->guid) {
1375d6b92ffaSHans Petter Selasky pp_alias_guids[2] = _pp_alias_guids[2];
1376d6b92ffaSHans Petter Selasky pp_alias_guids[3] = _pp_alias_guids[3];
1377d6b92ffaSHans Petter Selasky } else {
1378d6b92ffaSHans Petter Selasky pp_alias_guids[2] = _pp_alias_guids[3];
1379d6b92ffaSHans Petter Selasky pp_alias_guids[3] = _pp_alias_guids[2];
1380d6b92ffaSHans Petter Selasky }
1381d6b92ffaSHans Petter Selasky
1382d6b92ffaSHans Petter Selasky src_lid_ho = osm_port_get_base_lid(pp_alias_guids[0]->p_base_port);
1383d6b92ffaSHans Petter Selasky dest_lid_ho = osm_port_get_base_lid(pp_alias_guids[2]->p_base_port);
1384d6b92ffaSHans Petter Selasky
1385d6b92ffaSHans Petter Selasky base_offs = src_lid_ho < dest_lid_ho ?
1386d6b92ffaSHans Petter Selasky hash_lids(src_lid_ho, dest_lid_ho, sa->p_subn->opt.lmc) :
1387d6b92ffaSHans Petter Selasky hash_lids(dest_lid_ho, src_lid_ho, sa->p_subn->opt.lmc);
1388d6b92ffaSHans Petter Selasky
1389d6b92ffaSHans Petter Selasky matrix[0][0] =
1390d6b92ffaSHans Petter Selasky mpr_rcv_get_apm_port_pair_paths(sa, p_mpr, pp_alias_guids[0],
1391d6b92ffaSHans Petter Selasky pp_alias_guids[2], base_offs,
1392d6b92ffaSHans Petter Selasky comp_mask, p_list);
1393d6b92ffaSHans Petter Selasky matrix[0][1] =
1394d6b92ffaSHans Petter Selasky mpr_rcv_get_apm_port_pair_paths(sa, p_mpr, pp_alias_guids[0],
1395d6b92ffaSHans Petter Selasky pp_alias_guids[3], base_offs,
1396d6b92ffaSHans Petter Selasky comp_mask, p_list);
1397d6b92ffaSHans Petter Selasky matrix[1][0] =
1398d6b92ffaSHans Petter Selasky mpr_rcv_get_apm_port_pair_paths(sa, p_mpr, pp_alias_guids[1],
1399d6b92ffaSHans Petter Selasky pp_alias_guids[2], base_offs + 1,
1400d6b92ffaSHans Petter Selasky comp_mask, p_list);
1401d6b92ffaSHans Petter Selasky matrix[1][1] =
1402d6b92ffaSHans Petter Selasky mpr_rcv_get_apm_port_pair_paths(sa, p_mpr, pp_alias_guids[1],
1403d6b92ffaSHans Petter Selasky pp_alias_guids[3], base_offs + 1,
1404d6b92ffaSHans Petter Selasky comp_mask, p_list);
1405d6b92ffaSHans Petter Selasky
1406d6b92ffaSHans Petter Selasky OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "APM matrix:\n"
1407d6b92ffaSHans Petter Selasky "\t{0,0} 0x%X->0x%X (%d)\t| {0,1} 0x%X->0x%X (%d)\n"
1408d6b92ffaSHans Petter Selasky "\t{1,0} 0x%X->0x%X (%d)\t| {1,1} 0x%X->0x%X (%d)\n",
1409d6b92ffaSHans Petter Selasky matrix[0][0] ? matrix[0][0]->resp.mpr_rec.path_rec.slid : 0,
1410d6b92ffaSHans Petter Selasky matrix[0][0] ? matrix[0][0]->resp.mpr_rec.path_rec.dlid : 0,
1411d6b92ffaSHans Petter Selasky matrix[0][0] ? matrix[0][0]->resp.mpr_rec.hops : 0,
1412d6b92ffaSHans Petter Selasky matrix[0][1] ? matrix[0][1]->resp.mpr_rec.path_rec.slid : 0,
1413d6b92ffaSHans Petter Selasky matrix[0][1] ? matrix[0][1]->resp.mpr_rec.path_rec.dlid : 0,
1414d6b92ffaSHans Petter Selasky matrix[0][1] ? matrix[0][1]->resp.mpr_rec.hops : 0,
1415d6b92ffaSHans Petter Selasky matrix[1][0] ? matrix[1][0]->resp.mpr_rec.path_rec.slid : 0,
1416d6b92ffaSHans Petter Selasky matrix[1][0] ? matrix[1][0]->resp.mpr_rec.path_rec.dlid : 0,
1417d6b92ffaSHans Petter Selasky matrix[1][0] ? matrix[1][0]->resp.mpr_rec.hops : 0,
1418d6b92ffaSHans Petter Selasky matrix[1][1] ? matrix[1][1]->resp.mpr_rec.path_rec.slid : 0,
1419d6b92ffaSHans Petter Selasky matrix[1][1] ? matrix[1][1]->resp.mpr_rec.path_rec.dlid : 0,
1420d6b92ffaSHans Petter Selasky matrix[1][1] ? matrix[1][1]->resp.mpr_rec.hops : 0);
1421d6b92ffaSHans Petter Selasky
1422d6b92ffaSHans Petter Selasky sumA = minA = sumB = minB = 0;
1423d6b92ffaSHans Petter Selasky
1424d6b92ffaSHans Petter Selasky /* check diagonal A {(0,0), (1,1)} */
1425d6b92ffaSHans Petter Selasky if (matrix[0][0]) {
1426d6b92ffaSHans Petter Selasky sumA += matrix[0][0]->resp.mpr_rec.hops;
1427d6b92ffaSHans Petter Selasky minA = matrix[0][0]->resp.mpr_rec.hops;
1428d6b92ffaSHans Petter Selasky }
1429d6b92ffaSHans Petter Selasky if (matrix[1][1]) {
1430d6b92ffaSHans Petter Selasky sumA += matrix[1][1]->resp.mpr_rec.hops;
1431d6b92ffaSHans Petter Selasky if (minA)
1432d6b92ffaSHans Petter Selasky minA = min(minA, matrix[1][1]->resp.mpr_rec.hops);
1433d6b92ffaSHans Petter Selasky else
1434d6b92ffaSHans Petter Selasky minA = matrix[1][1]->resp.mpr_rec.hops;
1435d6b92ffaSHans Petter Selasky }
1436d6b92ffaSHans Petter Selasky
1437d6b92ffaSHans Petter Selasky /* check diagonal B {(0,1), (1,0)} */
1438d6b92ffaSHans Petter Selasky if (matrix[0][1]) {
1439d6b92ffaSHans Petter Selasky sumB += matrix[0][1]->resp.mpr_rec.hops;
1440d6b92ffaSHans Petter Selasky minB = matrix[0][1]->resp.mpr_rec.hops;
1441d6b92ffaSHans Petter Selasky }
1442d6b92ffaSHans Petter Selasky if (matrix[1][0]) {
1443d6b92ffaSHans Petter Selasky sumB += matrix[1][0]->resp.mpr_rec.hops;
1444d6b92ffaSHans Petter Selasky if (minB)
1445d6b92ffaSHans Petter Selasky minB = min(minB, matrix[1][0]->resp.mpr_rec.hops);
1446d6b92ffaSHans Petter Selasky else
1447d6b92ffaSHans Petter Selasky minB = matrix[1][0]->resp.mpr_rec.hops;
1448d6b92ffaSHans Petter Selasky }
1449d6b92ffaSHans Petter Selasky
1450d6b92ffaSHans Petter Selasky /* and the winner is... */
1451d6b92ffaSHans Petter Selasky if (minA <= minB || (minA == minB && sumA < sumB)) {
1452d6b92ffaSHans Petter Selasky /* Diag A */
1453d6b92ffaSHans Petter Selasky OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
1454d6b92ffaSHans Petter Selasky "Diag {0,0} & {1,1} is the best:\n"
1455d6b92ffaSHans Petter Selasky "\t{0,0} 0x%X->0x%X (%d)\t & {1,1} 0x%X->0x%X (%d)\n",
1456d6b92ffaSHans Petter Selasky matrix[0][0] ? matrix[0][0]->resp.mpr_rec.path_rec.slid : 0,
1457d6b92ffaSHans Petter Selasky matrix[0][0] ? matrix[0][0]->resp.mpr_rec.path_rec.dlid : 0,
1458d6b92ffaSHans Petter Selasky matrix[0][0] ? matrix[0][0]->resp.mpr_rec.hops : 0,
1459d6b92ffaSHans Petter Selasky matrix[1][1] ? matrix[1][1]->resp.mpr_rec.path_rec.slid : 0,
1460d6b92ffaSHans Petter Selasky matrix[1][1] ? matrix[1][1]->resp.mpr_rec.path_rec.dlid : 0,
1461d6b92ffaSHans Petter Selasky matrix[1][1] ? matrix[1][1]->resp.mpr_rec.hops : 0);
1462d6b92ffaSHans Petter Selasky if (matrix[0][0])
1463d6b92ffaSHans Petter Selasky cl_qlist_insert_tail(p_list, &matrix[0][0]->list_item);
1464d6b92ffaSHans Petter Selasky if (matrix[1][1])
1465d6b92ffaSHans Petter Selasky cl_qlist_insert_tail(p_list, &matrix[1][1]->list_item);
1466d6b92ffaSHans Petter Selasky free(matrix[0][1]);
1467d6b92ffaSHans Petter Selasky free(matrix[1][0]);
1468d6b92ffaSHans Petter Selasky } else {
1469d6b92ffaSHans Petter Selasky /* Diag B */
1470d6b92ffaSHans Petter Selasky OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
1471d6b92ffaSHans Petter Selasky "Diag {0,1} & {1,0} is the best:\n"
1472d6b92ffaSHans Petter Selasky "\t{0,1} 0x%X->0x%X (%d)\t & {1,0} 0x%X->0x%X (%d)\n",
1473d6b92ffaSHans Petter Selasky matrix[0][1] ? matrix[0][1]->resp.mpr_rec.path_rec.slid : 0,
1474d6b92ffaSHans Petter Selasky matrix[0][1] ? matrix[0][1]->resp.mpr_rec.path_rec.dlid : 0,
1475d6b92ffaSHans Petter Selasky matrix[0][1] ? matrix[0][1]->resp.mpr_rec.hops : 0,
1476d6b92ffaSHans Petter Selasky matrix[1][0] ? matrix[1][0]->resp.mpr_rec.path_rec.slid : 0,
1477d6b92ffaSHans Petter Selasky matrix[1][0] ? matrix[1][0]->resp.mpr_rec.path_rec.dlid: 0,
1478d6b92ffaSHans Petter Selasky matrix[1][0] ? matrix[1][0]->resp.mpr_rec.hops : 0);
1479d6b92ffaSHans Petter Selasky if (matrix[0][1])
1480d6b92ffaSHans Petter Selasky cl_qlist_insert_tail(p_list, &matrix[0][1]->list_item);
1481d6b92ffaSHans Petter Selasky if (matrix[1][0])
1482d6b92ffaSHans Petter Selasky cl_qlist_insert_tail(p_list, &matrix[1][0]->list_item);
1483d6b92ffaSHans Petter Selasky free(matrix[0][0]);
1484d6b92ffaSHans Petter Selasky free(matrix[1][1]);
1485d6b92ffaSHans Petter Selasky }
1486d6b92ffaSHans Petter Selasky
1487d6b92ffaSHans Petter Selasky OSM_LOG_EXIT(sa->p_log);
1488d6b92ffaSHans Petter Selasky }
1489d6b92ffaSHans Petter Selasky
mpr_rcv_process_pairs(IN osm_sa_t * sa,IN const ib_multipath_rec_t * p_mpr,IN osm_port_t * p_req_port,IN osm_alias_guid_t ** pp_alias_guids,IN const int nsrc,IN int ndest,IN ib_net64_t comp_mask,IN cl_qlist_t * p_list)1490d6b92ffaSHans Petter Selasky static void mpr_rcv_process_pairs(IN osm_sa_t * sa,
1491d6b92ffaSHans Petter Selasky IN const ib_multipath_rec_t * p_mpr,
1492d6b92ffaSHans Petter Selasky IN osm_port_t * p_req_port,
1493d6b92ffaSHans Petter Selasky IN osm_alias_guid_t ** pp_alias_guids,
1494d6b92ffaSHans Petter Selasky IN const int nsrc, IN int ndest,
1495d6b92ffaSHans Petter Selasky IN ib_net64_t comp_mask,
1496d6b92ffaSHans Petter Selasky IN cl_qlist_t * p_list)
1497d6b92ffaSHans Petter Selasky {
1498d6b92ffaSHans Petter Selasky osm_alias_guid_t **pp_src_alias_guid, **pp_es;
1499d6b92ffaSHans Petter Selasky osm_alias_guid_t **pp_dest_alias_guid, **pp_ed;
1500d6b92ffaSHans Petter Selasky uint32_t max_paths, num_paths, total_paths = 0;
1501d6b92ffaSHans Petter Selasky
1502d6b92ffaSHans Petter Selasky OSM_LOG_ENTER(sa->p_log);
1503d6b92ffaSHans Petter Selasky
1504d6b92ffaSHans Petter Selasky if (comp_mask & IB_MPR_COMPMASK_NUMBPATH)
1505d6b92ffaSHans Petter Selasky max_paths = p_mpr->num_path & 0x7F;
1506d6b92ffaSHans Petter Selasky else
1507d6b92ffaSHans Petter Selasky max_paths = OSM_SA_MPR_MAX_NUM_PATH;
1508d6b92ffaSHans Petter Selasky
1509d6b92ffaSHans Petter Selasky for (pp_src_alias_guid = pp_alias_guids, pp_es = pp_alias_guids + nsrc;
1510d6b92ffaSHans Petter Selasky pp_src_alias_guid < pp_es; pp_src_alias_guid++) {
1511d6b92ffaSHans Petter Selasky for (pp_dest_alias_guid = pp_es, pp_ed = pp_es + ndest;
1512d6b92ffaSHans Petter Selasky pp_dest_alias_guid < pp_ed; pp_dest_alias_guid++) {
1513d6b92ffaSHans Petter Selasky num_paths =
1514d6b92ffaSHans Petter Selasky mpr_rcv_get_port_pair_paths(sa, p_mpr, p_req_port,
1515d6b92ffaSHans Petter Selasky *pp_src_alias_guid,
1516d6b92ffaSHans Petter Selasky *pp_dest_alias_guid,
1517d6b92ffaSHans Petter Selasky max_paths - total_paths,
1518d6b92ffaSHans Petter Selasky comp_mask, p_list);
1519d6b92ffaSHans Petter Selasky total_paths += num_paths;
1520d6b92ffaSHans Petter Selasky OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
1521d6b92ffaSHans Petter Selasky "%d paths %d total paths %d max paths\n",
1522d6b92ffaSHans Petter Selasky num_paths, total_paths, max_paths);
1523d6b92ffaSHans Petter Selasky /* Just take first NumbPaths found */
1524d6b92ffaSHans Petter Selasky if (total_paths >= max_paths)
1525d6b92ffaSHans Petter Selasky goto Exit;
1526d6b92ffaSHans Petter Selasky }
1527d6b92ffaSHans Petter Selasky }
1528d6b92ffaSHans Petter Selasky
1529d6b92ffaSHans Petter Selasky Exit:
1530d6b92ffaSHans Petter Selasky OSM_LOG_EXIT(sa->p_log);
1531d6b92ffaSHans Petter Selasky }
1532d6b92ffaSHans Petter Selasky
osm_mpr_rcv_process(IN void * context,IN void * data)1533d6b92ffaSHans Petter Selasky void osm_mpr_rcv_process(IN void *context, IN void *data)
1534d6b92ffaSHans Petter Selasky {
1535d6b92ffaSHans Petter Selasky osm_sa_t *sa = context;
1536d6b92ffaSHans Petter Selasky osm_madw_t *p_madw = data;
1537d6b92ffaSHans Petter Selasky const ib_multipath_rec_t *p_mpr;
1538d6b92ffaSHans Petter Selasky ib_sa_mad_t *p_sa_mad;
1539d6b92ffaSHans Petter Selasky osm_port_t *requester_port;
1540d6b92ffaSHans Petter Selasky osm_alias_guid_t *pp_alias_guids[IB_MULTIPATH_MAX_GIDS];
1541d6b92ffaSHans Petter Selasky cl_qlist_t pr_list;
1542d6b92ffaSHans Petter Selasky ib_net16_t sa_status;
1543d6b92ffaSHans Petter Selasky int nsrc, ndest;
1544d6b92ffaSHans Petter Selasky uint8_t rate, mtu;
1545d6b92ffaSHans Petter Selasky
1546d6b92ffaSHans Petter Selasky OSM_LOG_ENTER(sa->p_log);
1547d6b92ffaSHans Petter Selasky
1548d6b92ffaSHans Petter Selasky CL_ASSERT(p_madw);
1549d6b92ffaSHans Petter Selasky
1550d6b92ffaSHans Petter Selasky p_sa_mad = osm_madw_get_sa_mad_ptr(p_madw);
1551d6b92ffaSHans Petter Selasky p_mpr = (ib_multipath_rec_t *) ib_sa_mad_get_payload_ptr(p_sa_mad);
1552d6b92ffaSHans Petter Selasky
1553d6b92ffaSHans Petter Selasky CL_ASSERT(p_sa_mad->attr_id == IB_MAD_ATTR_MULTIPATH_RECORD);
1554d6b92ffaSHans Petter Selasky
1555d6b92ffaSHans Petter Selasky if ((p_sa_mad->rmpp_flags & IB_RMPP_FLAG_ACTIVE) != IB_RMPP_FLAG_ACTIVE) {
1556d6b92ffaSHans Petter Selasky OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4510: "
1557d6b92ffaSHans Petter Selasky "Invalid request since RMPP_FLAG_ACTIVE is not set\n");
1558d6b92ffaSHans Petter Selasky osm_sa_send_error(sa, p_madw, IB_SA_MAD_STATUS_REQ_INVALID);
1559d6b92ffaSHans Petter Selasky goto Exit;
1560d6b92ffaSHans Petter Selasky }
1561d6b92ffaSHans Petter Selasky
1562d6b92ffaSHans Petter Selasky /* we only support SubnAdmGetMulti method */
1563d6b92ffaSHans Petter Selasky if (p_sa_mad->method != IB_MAD_METHOD_GETMULTI) {
1564d6b92ffaSHans Petter Selasky OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4513: "
1565d6b92ffaSHans Petter Selasky "Unsupported Method (%s) for MultiPathRecord request\n",
1566d6b92ffaSHans Petter Selasky ib_get_sa_method_str(p_sa_mad->method));
1567d6b92ffaSHans Petter Selasky osm_sa_send_error(sa, p_madw, IB_MAD_STATUS_UNSUP_METHOD_ATTR);
1568d6b92ffaSHans Petter Selasky goto Exit;
1569d6b92ffaSHans Petter Selasky }
1570d6b92ffaSHans Petter Selasky
1571d6b92ffaSHans Petter Selasky if (OSM_LOG_IS_ACTIVE_V2(sa->p_log, OSM_LOG_DEBUG))
1572d6b92ffaSHans Petter Selasky osm_dump_multipath_record_v2(sa->p_log, p_mpr, FILE_ID, OSM_LOG_DEBUG);
1573d6b92ffaSHans Petter Selasky
1574d6b92ffaSHans Petter Selasky /* Make sure required components (S/DGIDCount) are supplied */
1575d6b92ffaSHans Petter Selasky if (!(p_sa_mad->comp_mask & IB_MPR_COMPMASK_SGIDCOUNT) ||
1576d6b92ffaSHans Petter Selasky !(p_sa_mad->comp_mask & IB_MPR_COMPMASK_DGIDCOUNT)) {
1577d6b92ffaSHans Petter Selasky osm_sa_send_error(sa, p_madw, IB_SA_MAD_STATUS_INSUF_COMPS);
1578d6b92ffaSHans Petter Selasky goto Exit;
1579d6b92ffaSHans Petter Selasky }
1580d6b92ffaSHans Petter Selasky
1581d6b92ffaSHans Petter Selasky /* Validate rate if supplied */
1582d6b92ffaSHans Petter Selasky if ((p_sa_mad->comp_mask & IB_MPR_COMPMASK_RATESELEC) &&
1583d6b92ffaSHans Petter Selasky (p_sa_mad->comp_mask & IB_MPR_COMPMASK_RATE)) {
1584d6b92ffaSHans Petter Selasky rate = ib_multipath_rec_rate(p_mpr);
1585d6b92ffaSHans Petter Selasky if (!ib_rate_is_valid(rate)) {
1586d6b92ffaSHans Petter Selasky osm_sa_send_error(sa, p_madw,
1587d6b92ffaSHans Petter Selasky IB_SA_MAD_STATUS_REQ_INVALID);
1588d6b92ffaSHans Petter Selasky goto Exit;
1589d6b92ffaSHans Petter Selasky }
1590d6b92ffaSHans Petter Selasky }
1591d6b92ffaSHans Petter Selasky /* Validate MTU if supplied */
1592d6b92ffaSHans Petter Selasky if ((p_sa_mad->comp_mask & IB_MPR_COMPMASK_MTUSELEC) &&
1593d6b92ffaSHans Petter Selasky (p_sa_mad->comp_mask & IB_MPR_COMPMASK_MTU)) {
1594d6b92ffaSHans Petter Selasky mtu = ib_multipath_rec_mtu(p_mpr);
1595d6b92ffaSHans Petter Selasky if (!ib_mtu_is_valid(mtu)) {
1596d6b92ffaSHans Petter Selasky osm_sa_send_error(sa, p_madw,
1597d6b92ffaSHans Petter Selasky IB_SA_MAD_STATUS_REQ_INVALID);
1598d6b92ffaSHans Petter Selasky goto Exit;
1599d6b92ffaSHans Petter Selasky }
1600d6b92ffaSHans Petter Selasky }
1601d6b92ffaSHans Petter Selasky
1602d6b92ffaSHans Petter Selasky /* Make sure either none or both ServiceID parameters are supplied */
1603d6b92ffaSHans Petter Selasky if ((p_sa_mad->comp_mask & IB_MPR_COMPMASK_SERVICEID) != 0 &&
1604d6b92ffaSHans Petter Selasky (p_sa_mad->comp_mask & IB_MPR_COMPMASK_SERVICEID) !=
1605d6b92ffaSHans Petter Selasky IB_MPR_COMPMASK_SERVICEID) {
1606d6b92ffaSHans Petter Selasky osm_sa_send_error(sa, p_madw, IB_SA_MAD_STATUS_INSUF_COMPS);
1607d6b92ffaSHans Petter Selasky goto Exit;
1608d6b92ffaSHans Petter Selasky }
1609d6b92ffaSHans Petter Selasky
1610d6b92ffaSHans Petter Selasky cl_qlist_init(&pr_list);
1611d6b92ffaSHans Petter Selasky
1612d6b92ffaSHans Petter Selasky /*
1613d6b92ffaSHans Petter Selasky Most SA functions (including this one) are read-only on the
1614d6b92ffaSHans Petter Selasky subnet object, so we grab the lock non-exclusively.
1615d6b92ffaSHans Petter Selasky */
1616d6b92ffaSHans Petter Selasky cl_plock_acquire(sa->p_lock);
1617d6b92ffaSHans Petter Selasky
1618d6b92ffaSHans Petter Selasky /* update the requester physical port */
1619d6b92ffaSHans Petter Selasky requester_port = osm_get_port_by_mad_addr(sa->p_log, sa->p_subn,
1620d6b92ffaSHans Petter Selasky osm_madw_get_mad_addr_ptr
1621d6b92ffaSHans Petter Selasky (p_madw));
1622d6b92ffaSHans Petter Selasky if (requester_port == NULL) {
1623d6b92ffaSHans Petter Selasky cl_plock_release(sa->p_lock);
1624d6b92ffaSHans Petter Selasky OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4517: "
1625d6b92ffaSHans Petter Selasky "Cannot find requester physical port\n");
1626d6b92ffaSHans Petter Selasky goto Exit;
1627d6b92ffaSHans Petter Selasky }
1628d6b92ffaSHans Petter Selasky
1629d6b92ffaSHans Petter Selasky OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
1630d6b92ffaSHans Petter Selasky "Requester port GUID 0x%" PRIx64 "\n",
1631d6b92ffaSHans Petter Selasky cl_ntoh64(osm_port_get_guid(requester_port)));
1632d6b92ffaSHans Petter Selasky
1633d6b92ffaSHans Petter Selasky sa_status = mpr_rcv_get_end_points(sa, p_madw, pp_alias_guids,
1634d6b92ffaSHans Petter Selasky &nsrc, &ndest);
1635d6b92ffaSHans Petter Selasky
1636d6b92ffaSHans Petter Selasky if (sa_status != IB_SA_MAD_STATUS_SUCCESS || !nsrc || !ndest) {
1637d6b92ffaSHans Petter Selasky cl_plock_release(sa->p_lock);
1638d6b92ffaSHans Petter Selasky if (sa_status == IB_SA_MAD_STATUS_SUCCESS && (!nsrc || !ndest))
1639d6b92ffaSHans Petter Selasky OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4512: "
1640d6b92ffaSHans Petter Selasky "mpr_rcv_get_end_points failed, # GIDs found; "
1641d6b92ffaSHans Petter Selasky "src %d; dest %d)\n", nsrc, ndest);
1642d6b92ffaSHans Petter Selasky if (sa_status == IB_SA_MAD_STATUS_SUCCESS)
1643d6b92ffaSHans Petter Selasky osm_sa_send_error(sa, p_madw,
1644d6b92ffaSHans Petter Selasky IB_SA_MAD_STATUS_REQ_INVALID);
1645d6b92ffaSHans Petter Selasky else
1646d6b92ffaSHans Petter Selasky osm_sa_send_error(sa, p_madw, sa_status);
1647d6b92ffaSHans Petter Selasky goto Exit;
1648d6b92ffaSHans Petter Selasky }
1649d6b92ffaSHans Petter Selasky
1650d6b92ffaSHans Petter Selasky /* APM request */
1651d6b92ffaSHans Petter Selasky if (nsrc == 2 && ndest == 2 && (p_mpr->num_path & 0x7F) == 2)
1652d6b92ffaSHans Petter Selasky mpr_rcv_get_apm_paths(sa, p_mpr, requester_port, pp_alias_guids,
1653d6b92ffaSHans Petter Selasky p_sa_mad->comp_mask, &pr_list);
1654d6b92ffaSHans Petter Selasky else
1655d6b92ffaSHans Petter Selasky mpr_rcv_process_pairs(sa, p_mpr, requester_port, pp_alias_guids,
1656d6b92ffaSHans Petter Selasky nsrc, ndest, p_sa_mad->comp_mask,
1657d6b92ffaSHans Petter Selasky &pr_list);
1658d6b92ffaSHans Petter Selasky
1659d6b92ffaSHans Petter Selasky cl_plock_release(sa->p_lock);
1660d6b92ffaSHans Petter Selasky
1661d6b92ffaSHans Petter Selasky /* o15-0.2.7: If MultiPath is supported, then SA shall respond to a
1662d6b92ffaSHans Petter Selasky SubnAdmGetMulti() containing a valid MultiPathRecord attribute with
1663d6b92ffaSHans Petter Selasky a set of zero or more PathRecords satisfying the constraints
1664d6b92ffaSHans Petter Selasky indicated in the MultiPathRecord received. The PathRecord Attribute
1665d6b92ffaSHans Petter Selasky ID shall be used in the response.
1666d6b92ffaSHans Petter Selasky */
1667d6b92ffaSHans Petter Selasky p_sa_mad->attr_id = IB_MAD_ATTR_PATH_RECORD;
1668d6b92ffaSHans Petter Selasky osm_sa_respond(sa, p_madw, sizeof(ib_path_rec_t), &pr_list);
1669d6b92ffaSHans Petter Selasky
1670d6b92ffaSHans Petter Selasky Exit:
1671d6b92ffaSHans Petter Selasky OSM_LOG_EXIT(sa->p_log);
1672d6b92ffaSHans Petter Selasky }
1673d6b92ffaSHans Petter Selasky #endif
1674