2 * Copyright (c) 2004, 2005 Mellanox Technologies Ltd. All rights reserved.
3 * Copyright (c) 2004, 2005 Infinicon Corporation. All rights reserved.
4 * Copyright (c) 2004, 2005 Intel Corporation. All rights reserved.
5 * Copyright (c) 2004, 2005 Topspin Corporation. All rights reserved.
6 * Copyright (c) 2004-2007 Voltaire Corporation. All rights reserved.
7 * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
9 * This software is available to you under a choice of one of two
10 * licenses. You may choose to be licensed under the terms of the GNU
11 * General Public License (GPL) Version 2, available from the file
12 * COPYING in the main directory of this source tree, or the
13 * OpenIB.org BSD license below:
15 * Redistribution and use in source and binary forms, with or
16 * without modification, are permitted provided that the following
19 * - Redistributions of source code must retain the above
20 * copyright notice, this list of conditions and the following
23 * - Redistributions in binary form must reproduce the above
24 * copyright notice, this list of conditions and the following
25 * disclaimer in the documentation and/or other materials
26 * provided with the distribution.
28 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
29 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
30 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
31 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
32 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
33 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
34 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
39 #include <rdma/ib_smi.h>
42 static enum smi_action __smi_handle_dr_smp_send(u8 node_type, int port_num,
43 u8 *hop_ptr, u8 hop_cnt,
44 const u8 *initial_path,
45 const u8 *return_path,
47 bool dr_dlid_is_permissive,
48 bool dr_slid_is_permissive)
50 /* See section 14.2.2.2, Vol 1 IB spec */
51 /* C14-6 -- valid hop_cnt values are from 0 to 63 */
52 if (hop_cnt >= IB_SMP_MAX_PATH_HOPS)
53 return IB_SMI_DISCARD;
57 if (hop_cnt && *hop_ptr == 0) {
59 return (initial_path[*hop_ptr] ==
60 port_num ? IB_SMI_HANDLE : IB_SMI_DISCARD);
64 if (*hop_ptr && *hop_ptr < hop_cnt) {
65 if (node_type != RDMA_NODE_IB_SWITCH)
66 return IB_SMI_DISCARD;
68 /* return_path set when received */
70 return (initial_path[*hop_ptr] ==
71 port_num ? IB_SMI_HANDLE : IB_SMI_DISCARD);
74 /* C14-9:3 -- We're at the end of the DR segment of path */
75 if (*hop_ptr == hop_cnt) {
76 /* return_path set when received */
78 return (node_type == RDMA_NODE_IB_SWITCH ||
79 dr_dlid_is_permissive ?
80 IB_SMI_HANDLE : IB_SMI_DISCARD);
83 /* C14-9:4 -- hop_ptr = hop_cnt + 1 -> give to SMA/SM */
84 /* C14-9:5 -- Fail unreasonable hop pointer */
85 return (*hop_ptr == hop_cnt + 1 ? IB_SMI_HANDLE : IB_SMI_DISCARD);
89 if (hop_cnt && *hop_ptr == hop_cnt + 1) {
91 return (return_path[*hop_ptr] ==
92 port_num ? IB_SMI_HANDLE : IB_SMI_DISCARD);
96 if (2 <= *hop_ptr && *hop_ptr <= hop_cnt) {
97 if (node_type != RDMA_NODE_IB_SWITCH)
98 return IB_SMI_DISCARD;
101 return (return_path[*hop_ptr] ==
102 port_num ? IB_SMI_HANDLE : IB_SMI_DISCARD);
105 /* C14-13:3 -- at the end of the DR segment of path */
108 /* C14-13:3 -- SMPs destined for SM shouldn't be here */
109 return (node_type == RDMA_NODE_IB_SWITCH ||
110 dr_slid_is_permissive ?
111 IB_SMI_HANDLE : IB_SMI_DISCARD);
114 /* C14-13:4 -- hop_ptr = 0 -> should have gone to SM */
116 return IB_SMI_HANDLE;
118 /* C14-13:5 -- Check for unreasonable hop pointer */
119 return IB_SMI_DISCARD;
124 * Fixup a directed route SMP for sending
125 * Return IB_SMI_DISCARD if the SMP should be discarded
127 enum smi_action smi_handle_dr_smp_send(struct ib_smp *smp,
128 u8 node_type, int port_num)
130 return __smi_handle_dr_smp_send(node_type, port_num,
131 &smp->hop_ptr, smp->hop_cnt,
134 ib_get_smp_direction(smp),
135 smp->dr_dlid == IB_LID_PERMISSIVE,
136 smp->dr_slid == IB_LID_PERMISSIVE);
139 static enum smi_action __smi_handle_dr_smp_recv(u8 node_type, int port_num,
141 u8 *hop_ptr, u8 hop_cnt,
142 const u8 *initial_path,
145 bool dr_dlid_is_permissive,
146 bool dr_slid_is_permissive)
148 /* See section 14.2.2.2, Vol 1 IB spec */
149 /* C14-6 -- valid hop_cnt values are from 0 to 63 */
150 if (hop_cnt >= IB_SMP_MAX_PATH_HOPS)
151 return IB_SMI_DISCARD;
154 /* C14-9:1 -- sender should have incremented hop_ptr */
155 if (hop_cnt && *hop_ptr == 0)
156 return IB_SMI_DISCARD;
158 /* C14-9:2 -- intermediate hop */
159 if (*hop_ptr && *hop_ptr < hop_cnt) {
160 if (node_type != RDMA_NODE_IB_SWITCH)
161 return IB_SMI_DISCARD;
163 return_path[*hop_ptr] = port_num;
164 /* hop_ptr updated when sending */
165 return (initial_path[*hop_ptr+1] <= phys_port_cnt ?
166 IB_SMI_HANDLE : IB_SMI_DISCARD);
169 /* C14-9:3 -- We're at the end of the DR segment of path */
170 if (*hop_ptr == hop_cnt) {
172 return_path[*hop_ptr] = port_num;
173 /* hop_ptr updated when sending */
175 return (node_type == RDMA_NODE_IB_SWITCH ||
176 dr_dlid_is_permissive ?
177 IB_SMI_HANDLE : IB_SMI_DISCARD);
180 /* C14-9:4 -- hop_ptr = hop_cnt + 1 -> give to SMA/SM */
181 /* C14-9:5 -- fail unreasonable hop pointer */
182 return (*hop_ptr == hop_cnt + 1 ? IB_SMI_HANDLE : IB_SMI_DISCARD);
187 if (hop_cnt && *hop_ptr == hop_cnt + 1) {
189 return (return_path[*hop_ptr] ==
190 port_num ? IB_SMI_HANDLE : IB_SMI_DISCARD);
194 if (2 <= *hop_ptr && *hop_ptr <= hop_cnt) {
195 if (node_type != RDMA_NODE_IB_SWITCH)
196 return IB_SMI_DISCARD;
198 /* hop_ptr updated when sending */
199 return (return_path[*hop_ptr-1] <= phys_port_cnt ?
200 IB_SMI_HANDLE : IB_SMI_DISCARD);
203 /* C14-13:3 -- We're at the end of the DR segment of path */
205 if (dr_slid_is_permissive) {
206 /* giving SMP to SM - update hop_ptr */
208 return IB_SMI_HANDLE;
210 /* hop_ptr updated when sending */
211 return (node_type == RDMA_NODE_IB_SWITCH ?
212 IB_SMI_HANDLE : IB_SMI_DISCARD);
215 /* C14-13:4 -- hop_ptr = 0 -> give to SM */
216 /* C14-13:5 -- Check for unreasonable hop pointer */
217 return (*hop_ptr == 0 ? IB_SMI_HANDLE : IB_SMI_DISCARD);
222 * Adjust information for a received SMP
223 * Return IB_SMI_DISCARD if the SMP should be dropped
225 enum smi_action smi_handle_dr_smp_recv(struct ib_smp *smp, u8 node_type,
226 int port_num, int phys_port_cnt)
228 return __smi_handle_dr_smp_recv(node_type, port_num, phys_port_cnt,
229 &smp->hop_ptr, smp->hop_cnt,
232 ib_get_smp_direction(smp),
233 smp->dr_dlid == IB_LID_PERMISSIVE,
234 smp->dr_slid == IB_LID_PERMISSIVE);
237 static enum smi_forward_action __smi_check_forward_dr_smp(u8 hop_ptr, u8 hop_cnt,
239 bool dr_dlid_is_permissive,
240 bool dr_slid_is_permissive)
243 /* C14-9:2 -- intermediate hop */
244 if (hop_ptr && hop_ptr < hop_cnt)
245 return IB_SMI_FORWARD;
247 /* C14-9:3 -- at the end of the DR segment of path */
248 if (hop_ptr == hop_cnt)
249 return (dr_dlid_is_permissive ?
250 IB_SMI_SEND : IB_SMI_LOCAL);
252 /* C14-9:4 -- hop_ptr = hop_cnt + 1 -> give to SMA/SM */
253 if (hop_ptr == hop_cnt + 1)
256 /* C14-13:2 -- intermediate hop */
257 if (2 <= hop_ptr && hop_ptr <= hop_cnt)
258 return IB_SMI_FORWARD;
260 /* C14-13:3 -- at the end of the DR segment of path */
262 return (!dr_slid_is_permissive ?
263 IB_SMI_SEND : IB_SMI_LOCAL);
269 enum smi_forward_action smi_check_forward_dr_smp(struct ib_smp *smp)
271 return __smi_check_forward_dr_smp(smp->hop_ptr, smp->hop_cnt,
272 ib_get_smp_direction(smp),
273 smp->dr_dlid == IB_LID_PERMISSIVE,
274 smp->dr_slid == IB_LID_PERMISSIVE);
278 * Return the forwarding port number from initial_path for outgoing SMP and
279 * from return_path for returning SMP
281 int smi_get_fwd_port(struct ib_smp *smp)
283 return (!ib_get_smp_direction(smp) ? smp->initial_path[smp->hop_ptr+1] :
284 smp->return_path[smp->hop_ptr-1]);