blob: eb39146adb801535af04b830bd08366eda982242 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
Roland Dreier2a1d9b72005-08-10 23:03:10 -07002 * 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.
Hal Rosenstockde493d42007-04-02 11:24:07 -04006 * Copyright (c) 2004-2007 Voltaire Corporation. All rights reserved.
Roland Dreier2a1d9b72005-08-10 23:03:10 -07007 * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
Linus Torvalds1da177e2005-04-16 15:20:36 -07008 *
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:
14 *
15 * Redistribution and use in source and binary forms, with or
16 * without modification, are permitted provided that the following
17 * conditions are met:
18 *
19 * - Redistributions of source code must retain the above
20 * copyright notice, this list of conditions and the following
21 * disclaimer.
22 *
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.
27 *
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
35 * SOFTWARE.
36 *
Linus Torvalds1da177e2005-04-16 15:20:36 -070037 */
38
Roland Dreiera4d61e82005-08-25 13:40:04 -070039#include <rdma/ib_smi.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070040#include "smi.h"
41
Ira Weiny92f15052015-06-06 14:38:25 -040042static 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,
46 u8 direction,
47 bool dr_dlid_is_permissive,
48 bool dr_slid_is_permissive)
49{
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;
54
55 if (!direction) {
56 /* C14-9:1 */
57 if (hop_cnt && *hop_ptr == 0) {
58 (*hop_ptr)++;
59 return (initial_path[*hop_ptr] ==
60 port_num ? IB_SMI_HANDLE : IB_SMI_DISCARD);
61 }
62
63 /* C14-9:2 */
64 if (*hop_ptr && *hop_ptr < hop_cnt) {
65 if (node_type != RDMA_NODE_IB_SWITCH)
66 return IB_SMI_DISCARD;
67
68 /* return_path set when received */
69 (*hop_ptr)++;
70 return (initial_path[*hop_ptr] ==
71 port_num ? IB_SMI_HANDLE : IB_SMI_DISCARD);
72 }
73
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 */
77 (*hop_ptr)++;
78 return (node_type == RDMA_NODE_IB_SWITCH ||
79 dr_dlid_is_permissive ?
80 IB_SMI_HANDLE : IB_SMI_DISCARD);
81 }
82
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);
86
87 } else {
88 /* C14-13:1 */
89 if (hop_cnt && *hop_ptr == hop_cnt + 1) {
90 (*hop_ptr)--;
91 return (return_path[*hop_ptr] ==
92 port_num ? IB_SMI_HANDLE : IB_SMI_DISCARD);
93 }
94
95 /* C14-13:2 */
96 if (2 <= *hop_ptr && *hop_ptr <= hop_cnt) {
97 if (node_type != RDMA_NODE_IB_SWITCH)
98 return IB_SMI_DISCARD;
99
100 (*hop_ptr)--;
101 return (return_path[*hop_ptr] ==
102 port_num ? IB_SMI_HANDLE : IB_SMI_DISCARD);
103 }
104
105 /* C14-13:3 -- at the end of the DR segment of path */
106 if (*hop_ptr == 1) {
107 (*hop_ptr)--;
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);
112 }
113
114 /* C14-13:4 -- hop_ptr = 0 -> should have gone to SM */
115 if (*hop_ptr == 0)
116 return IB_SMI_HANDLE;
117
118 /* C14-13:5 -- Check for unreasonable hop pointer */
119 return IB_SMI_DISCARD;
120 }
121}
122
Linus Torvalds1da177e2005-04-16 15:20:36 -0700123/*
124 * Fixup a directed route SMP for sending
Ira Weinyb78d28a2015-05-08 13:10:04 -0400125 * Return IB_SMI_DISCARD if the SMP should be discarded
Linus Torvalds1da177e2005-04-16 15:20:36 -0700126 */
Hal Rosenstockde493d42007-04-02 11:24:07 -0400127enum smi_action smi_handle_dr_smp_send(struct ib_smp *smp,
128 u8 node_type, int port_num)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700129{
Ira Weiny92f15052015-06-06 14:38:25 -0400130 return __smi_handle_dr_smp_send(node_type, port_num,
131 &smp->hop_ptr, smp->hop_cnt,
132 smp->initial_path,
133 smp->return_path,
134 ib_get_smp_direction(smp),
135 smp->dr_dlid == IB_LID_PERMISSIVE,
136 smp->dr_slid == IB_LID_PERMISSIVE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700137}
138
Ira Weiny86f0e672015-06-06 14:38:26 -0400139static enum smi_action __smi_handle_dr_smp_recv(u8 node_type, int port_num,
140 int phys_port_cnt,
141 u8 *hop_ptr, u8 hop_cnt,
142 const u8 *initial_path,
143 u8 *return_path,
144 u8 direction,
145 bool dr_dlid_is_permissive,
146 bool dr_slid_is_permissive)
147{
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;
152
153 if (!direction) {
154 /* C14-9:1 -- sender should have incremented hop_ptr */
155 if (hop_cnt && *hop_ptr == 0)
156 return IB_SMI_DISCARD;
157
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;
162
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);
167 }
168
169 /* C14-9:3 -- We're at the end of the DR segment of path */
170 if (*hop_ptr == hop_cnt) {
171 if (hop_cnt)
172 return_path[*hop_ptr] = port_num;
173 /* hop_ptr updated when sending */
174
175 return (node_type == RDMA_NODE_IB_SWITCH ||
176 dr_dlid_is_permissive ?
177 IB_SMI_HANDLE : IB_SMI_DISCARD);
178 }
179
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);
183
184 } else {
185
186 /* C14-13:1 */
187 if (hop_cnt && *hop_ptr == hop_cnt + 1) {
188 (*hop_ptr)--;
189 return (return_path[*hop_ptr] ==
190 port_num ? IB_SMI_HANDLE : IB_SMI_DISCARD);
191 }
192
193 /* C14-13:2 */
194 if (2 <= *hop_ptr && *hop_ptr <= hop_cnt) {
195 if (node_type != RDMA_NODE_IB_SWITCH)
196 return IB_SMI_DISCARD;
197
198 /* hop_ptr updated when sending */
199 return (return_path[*hop_ptr-1] <= phys_port_cnt ?
200 IB_SMI_HANDLE : IB_SMI_DISCARD);
201 }
202
203 /* C14-13:3 -- We're at the end of the DR segment of path */
204 if (*hop_ptr == 1) {
205 if (dr_slid_is_permissive) {
206 /* giving SMP to SM - update hop_ptr */
207 (*hop_ptr)--;
208 return IB_SMI_HANDLE;
209 }
210 /* hop_ptr updated when sending */
211 return (node_type == RDMA_NODE_IB_SWITCH ?
212 IB_SMI_HANDLE : IB_SMI_DISCARD);
213 }
214
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);
218 }
219}
220
Linus Torvalds1da177e2005-04-16 15:20:36 -0700221/*
222 * Adjust information for a received SMP
Ira Weinyb78d28a2015-05-08 13:10:04 -0400223 * Return IB_SMI_DISCARD if the SMP should be dropped
Linus Torvalds1da177e2005-04-16 15:20:36 -0700224 */
Hal Rosenstockde493d42007-04-02 11:24:07 -0400225enum smi_action smi_handle_dr_smp_recv(struct ib_smp *smp, u8 node_type,
226 int port_num, int phys_port_cnt)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700227{
Ira Weiny86f0e672015-06-06 14:38:26 -0400228 return __smi_handle_dr_smp_recv(node_type, port_num, phys_port_cnt,
229 &smp->hop_ptr, smp->hop_cnt,
230 smp->initial_path,
231 smp->return_path,
232 ib_get_smp_direction(smp),
233 smp->dr_dlid == IB_LID_PERMISSIVE,
234 smp->dr_slid == IB_LID_PERMISSIVE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700235}
236
Hal Rosenstockde493d42007-04-02 11:24:07 -0400237enum smi_forward_action smi_check_forward_dr_smp(struct ib_smp *smp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700238{
239 u8 hop_ptr, hop_cnt;
240
241 hop_ptr = smp->hop_ptr;
242 hop_cnt = smp->hop_cnt;
243
244 if (!ib_get_smp_direction(smp)) {
245 /* C14-9:2 -- intermediate hop */
246 if (hop_ptr && hop_ptr < hop_cnt)
Hal Rosenstock1bae4db2007-05-14 17:21:52 -0400247 return IB_SMI_FORWARD;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700248
249 /* C14-9:3 -- at the end of the DR segment of path */
250 if (hop_ptr == hop_cnt)
Hal Rosenstockde493d42007-04-02 11:24:07 -0400251 return (smp->dr_dlid == IB_LID_PERMISSIVE ?
252 IB_SMI_SEND : IB_SMI_LOCAL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700253
254 /* C14-9:4 -- hop_ptr = hop_cnt + 1 -> give to SMA/SM */
255 if (hop_ptr == hop_cnt + 1)
Hal Rosenstockde493d42007-04-02 11:24:07 -0400256 return IB_SMI_SEND;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700257 } else {
Hal Rosenstockde493d42007-04-02 11:24:07 -0400258 /* C14-13:2 -- intermediate hop */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700259 if (2 <= hop_ptr && hop_ptr <= hop_cnt)
Hal Rosenstock1bae4db2007-05-14 17:21:52 -0400260 return IB_SMI_FORWARD;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700261
262 /* C14-13:3 -- at the end of the DR segment of path */
263 if (hop_ptr == 1)
Hal Rosenstockde493d42007-04-02 11:24:07 -0400264 return (smp->dr_slid != IB_LID_PERMISSIVE ?
265 IB_SMI_SEND : IB_SMI_LOCAL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700266 }
Hal Rosenstockde493d42007-04-02 11:24:07 -0400267 return IB_SMI_LOCAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700268}
Hal Rosenstock1bae4db2007-05-14 17:21:52 -0400269
270/*
271 * Return the forwarding port number from initial_path for outgoing SMP and
272 * from return_path for returning SMP
273 */
274int smi_get_fwd_port(struct ib_smp *smp)
275{
276 return (!ib_get_smp_direction(smp) ? smp->initial_path[smp->hop_ptr+1] :
277 smp->return_path[smp->hop_ptr-1]);
278}