]>
Commit | Line | Data |
---|---|---|
1da177e4 | 1 | /* |
2a1d9b7f RD |
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. | |
de493d47 | 6 | * Copyright (c) 2004-2007 Voltaire Corporation. All rights reserved. |
2a1d9b7f | 7 | * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. |
1da177e4 LT |
8 | * |
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 | * | |
1da177e4 LT |
37 | */ |
38 | ||
a4d61e84 | 39 | #include <rdma/ib_smi.h> |
1da177e4 LT |
40 | #include "smi.h" |
41 | ||
92f15056 IW |
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, | |
46 | u8 direction, | |
47 | bool dr_dlid_is_permissive, | |
48 | bool dr_slid_is_permissive) | |
1da177e4 | 49 | { |
1da177e4 | 50 | /* See section 14.2.2.2, Vol 1 IB spec */ |
60f2b652 RD |
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 | ||
92f15056 | 55 | if (!direction) { |
1da177e4 | 56 | /* C14-9:1 */ |
92f15056 IW |
57 | if (hop_cnt && *hop_ptr == 0) { |
58 | (*hop_ptr)++; | |
59 | return (initial_path[*hop_ptr] == | |
de493d47 | 60 | port_num ? IB_SMI_HANDLE : IB_SMI_DISCARD); |
1da177e4 LT |
61 | } |
62 | ||
63 | /* C14-9:2 */ | |
92f15056 | 64 | if (*hop_ptr && *hop_ptr < hop_cnt) { |
07ebafba | 65 | if (node_type != RDMA_NODE_IB_SWITCH) |
de493d47 | 66 | return IB_SMI_DISCARD; |
1da177e4 | 67 | |
92f15056 IW |
68 | /* return_path set when received */ |
69 | (*hop_ptr)++; | |
70 | return (initial_path[*hop_ptr] == | |
de493d47 | 71 | port_num ? IB_SMI_HANDLE : IB_SMI_DISCARD); |
1da177e4 LT |
72 | } |
73 | ||
74 | /* C14-9:3 -- We're at the end of the DR segment of path */ | |
92f15056 IW |
75 | if (*hop_ptr == hop_cnt) { |
76 | /* return_path set when received */ | |
77 | (*hop_ptr)++; | |
07ebafba | 78 | return (node_type == RDMA_NODE_IB_SWITCH || |
92f15056 | 79 | dr_dlid_is_permissive ? |
de493d47 | 80 | IB_SMI_HANDLE : IB_SMI_DISCARD); |
1da177e4 LT |
81 | } |
82 | ||
83 | /* C14-9:4 -- hop_ptr = hop_cnt + 1 -> give to SMA/SM */ | |
84 | /* C14-9:5 -- Fail unreasonable hop pointer */ | |
92f15056 | 85 | return (*hop_ptr == hop_cnt + 1 ? IB_SMI_HANDLE : IB_SMI_DISCARD); |
1da177e4 LT |
86 | |
87 | } else { | |
88 | /* C14-13:1 */ | |
92f15056 IW |
89 | if (hop_cnt && *hop_ptr == hop_cnt + 1) { |
90 | (*hop_ptr)--; | |
91 | return (return_path[*hop_ptr] == | |
de493d47 | 92 | port_num ? IB_SMI_HANDLE : IB_SMI_DISCARD); |
1da177e4 LT |
93 | } |
94 | ||
95 | /* C14-13:2 */ | |
92f15056 | 96 | if (2 <= *hop_ptr && *hop_ptr <= hop_cnt) { |
07ebafba | 97 | if (node_type != RDMA_NODE_IB_SWITCH) |
de493d47 | 98 | return IB_SMI_DISCARD; |
1da177e4 | 99 | |
92f15056 IW |
100 | (*hop_ptr)--; |
101 | return (return_path[*hop_ptr] == | |
de493d47 | 102 | port_num ? IB_SMI_HANDLE : IB_SMI_DISCARD); |
1da177e4 LT |
103 | } |
104 | ||
105 | /* C14-13:3 -- at the end of the DR segment of path */ | |
92f15056 IW |
106 | if (*hop_ptr == 1) { |
107 | (*hop_ptr)--; | |
1da177e4 | 108 | /* C14-13:3 -- SMPs destined for SM shouldn't be here */ |
07ebafba | 109 | return (node_type == RDMA_NODE_IB_SWITCH || |
92f15056 | 110 | dr_slid_is_permissive ? |
de493d47 | 111 | IB_SMI_HANDLE : IB_SMI_DISCARD); |
1da177e4 LT |
112 | } |
113 | ||
114 | /* C14-13:4 -- hop_ptr = 0 -> should have gone to SM */ | |
92f15056 | 115 | if (*hop_ptr == 0) |
de493d47 | 116 | return IB_SMI_HANDLE; |
1da177e4 LT |
117 | |
118 | /* C14-13:5 -- Check for unreasonable hop pointer */ | |
de493d47 | 119 | return IB_SMI_DISCARD; |
1da177e4 LT |
120 | } |
121 | } | |
122 | ||
92f15056 IW |
123 | /* |
124 | * Fixup a directed route SMP for sending | |
125 | * Return IB_SMI_DISCARD if the SMP should be discarded | |
126 | */ | |
127 | enum smi_action smi_handle_dr_smp_send(struct ib_smp *smp, | |
128 | u8 node_type, int port_num) | |
129 | { | |
130 | 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); | |
137 | } | |
138 | ||
1da177e4 LT |
139 | /* |
140 | * Adjust information for a received SMP | |
b78d28a2 | 141 | * Return IB_SMI_DISCARD if the SMP should be dropped |
1da177e4 | 142 | */ |
de493d47 HR |
143 | enum smi_action smi_handle_dr_smp_recv(struct ib_smp *smp, u8 node_type, |
144 | int port_num, int phys_port_cnt) | |
1da177e4 LT |
145 | { |
146 | u8 hop_ptr, hop_cnt; | |
147 | ||
148 | hop_ptr = smp->hop_ptr; | |
149 | hop_cnt = smp->hop_cnt; | |
150 | ||
151 | /* See section 14.2.2.2, Vol 1 IB spec */ | |
60f2b652 RD |
152 | /* C14-6 -- valid hop_cnt values are from 0 to 63 */ |
153 | if (hop_cnt >= IB_SMP_MAX_PATH_HOPS) | |
154 | return IB_SMI_DISCARD; | |
155 | ||
1da177e4 LT |
156 | if (!ib_get_smp_direction(smp)) { |
157 | /* C14-9:1 -- sender should have incremented hop_ptr */ | |
158 | if (hop_cnt && hop_ptr == 0) | |
de493d47 | 159 | return IB_SMI_DISCARD; |
1da177e4 LT |
160 | |
161 | /* C14-9:2 -- intermediate hop */ | |
162 | if (hop_ptr && hop_ptr < hop_cnt) { | |
07ebafba | 163 | if (node_type != RDMA_NODE_IB_SWITCH) |
de493d47 | 164 | return IB_SMI_DISCARD; |
1da177e4 LT |
165 | |
166 | smp->return_path[hop_ptr] = port_num; | |
167 | /* smp->hop_ptr updated when sending */ | |
de493d47 HR |
168 | return (smp->initial_path[hop_ptr+1] <= phys_port_cnt ? |
169 | IB_SMI_HANDLE : IB_SMI_DISCARD); | |
1da177e4 LT |
170 | } |
171 | ||
172 | /* C14-9:3 -- We're at the end of the DR segment of path */ | |
173 | if (hop_ptr == hop_cnt) { | |
174 | if (hop_cnt) | |
175 | smp->return_path[hop_ptr] = port_num; | |
176 | /* smp->hop_ptr updated when sending */ | |
177 | ||
07ebafba | 178 | return (node_type == RDMA_NODE_IB_SWITCH || |
de493d47 HR |
179 | smp->dr_dlid == IB_LID_PERMISSIVE ? |
180 | IB_SMI_HANDLE : IB_SMI_DISCARD); | |
1da177e4 LT |
181 | } |
182 | ||
183 | /* C14-9:4 -- hop_ptr = hop_cnt + 1 -> give to SMA/SM */ | |
184 | /* C14-9:5 -- fail unreasonable hop pointer */ | |
de493d47 | 185 | return (hop_ptr == hop_cnt + 1 ? IB_SMI_HANDLE : IB_SMI_DISCARD); |
1da177e4 LT |
186 | |
187 | } else { | |
188 | ||
189 | /* C14-13:1 */ | |
190 | if (hop_cnt && hop_ptr == hop_cnt + 1) { | |
191 | smp->hop_ptr--; | |
192 | return (smp->return_path[smp->hop_ptr] == | |
de493d47 | 193 | port_num ? IB_SMI_HANDLE : IB_SMI_DISCARD); |
1da177e4 LT |
194 | } |
195 | ||
196 | /* C14-13:2 */ | |
197 | if (2 <= hop_ptr && hop_ptr <= hop_cnt) { | |
07ebafba | 198 | if (node_type != RDMA_NODE_IB_SWITCH) |
de493d47 | 199 | return IB_SMI_DISCARD; |
1da177e4 LT |
200 | |
201 | /* smp->hop_ptr updated when sending */ | |
de493d47 HR |
202 | return (smp->return_path[hop_ptr-1] <= phys_port_cnt ? |
203 | IB_SMI_HANDLE : IB_SMI_DISCARD); | |
1da177e4 LT |
204 | } |
205 | ||
206 | /* C14-13:3 -- We're at the end of the DR segment of path */ | |
207 | if (hop_ptr == 1) { | |
208 | if (smp->dr_slid == IB_LID_PERMISSIVE) { | |
209 | /* giving SMP to SM - update hop_ptr */ | |
210 | smp->hop_ptr--; | |
de493d47 | 211 | return IB_SMI_HANDLE; |
1da177e4 LT |
212 | } |
213 | /* smp->hop_ptr updated when sending */ | |
de493d47 | 214 | return (node_type == RDMA_NODE_IB_SWITCH ? |
1bae4dbf | 215 | IB_SMI_HANDLE : IB_SMI_DISCARD); |
1da177e4 LT |
216 | } |
217 | ||
218 | /* C14-13:4 -- hop_ptr = 0 -> give to SM */ | |
219 | /* C14-13:5 -- Check for unreasonable hop pointer */ | |
de493d47 | 220 | return (hop_ptr == 0 ? IB_SMI_HANDLE : IB_SMI_DISCARD); |
1da177e4 LT |
221 | } |
222 | } | |
223 | ||
de493d47 | 224 | enum smi_forward_action smi_check_forward_dr_smp(struct ib_smp *smp) |
1da177e4 LT |
225 | { |
226 | u8 hop_ptr, hop_cnt; | |
227 | ||
228 | hop_ptr = smp->hop_ptr; | |
229 | hop_cnt = smp->hop_cnt; | |
230 | ||
231 | if (!ib_get_smp_direction(smp)) { | |
232 | /* C14-9:2 -- intermediate hop */ | |
233 | if (hop_ptr && hop_ptr < hop_cnt) | |
1bae4dbf | 234 | return IB_SMI_FORWARD; |
1da177e4 LT |
235 | |
236 | /* C14-9:3 -- at the end of the DR segment of path */ | |
237 | if (hop_ptr == hop_cnt) | |
de493d47 HR |
238 | return (smp->dr_dlid == IB_LID_PERMISSIVE ? |
239 | IB_SMI_SEND : IB_SMI_LOCAL); | |
1da177e4 LT |
240 | |
241 | /* C14-9:4 -- hop_ptr = hop_cnt + 1 -> give to SMA/SM */ | |
242 | if (hop_ptr == hop_cnt + 1) | |
de493d47 | 243 | return IB_SMI_SEND; |
1da177e4 | 244 | } else { |
de493d47 | 245 | /* C14-13:2 -- intermediate hop */ |
1da177e4 | 246 | if (2 <= hop_ptr && hop_ptr <= hop_cnt) |
1bae4dbf | 247 | return IB_SMI_FORWARD; |
1da177e4 LT |
248 | |
249 | /* C14-13:3 -- at the end of the DR segment of path */ | |
250 | if (hop_ptr == 1) | |
de493d47 HR |
251 | return (smp->dr_slid != IB_LID_PERMISSIVE ? |
252 | IB_SMI_SEND : IB_SMI_LOCAL); | |
1da177e4 | 253 | } |
de493d47 | 254 | return IB_SMI_LOCAL; |
1da177e4 | 255 | } |
1bae4dbf HR |
256 | |
257 | /* | |
258 | * Return the forwarding port number from initial_path for outgoing SMP and | |
259 | * from return_path for returning SMP | |
260 | */ | |
261 | int smi_get_fwd_port(struct ib_smp *smp) | |
262 | { | |
263 | return (!ib_get_smp_direction(smp) ? smp->initial_path[smp->hop_ptr+1] : | |
264 | smp->return_path[smp->hop_ptr-1]); | |
265 | } |