1/* 2 3 * Copyright (c) 2004, 2005 Mellanox Technologies Ltd. All rights reserved. 4 * Copyright (c) 2004, 2005 Infinicon Corporation. All rights reserved. 5 * Copyright (c) 2004, 2005 Intel Corporation. All rights reserved. 6 * Copyright (c) 2004, 2005 Topspin Corporation. All rights reserved. 7 * Copyright (c) 2004-2007 Voltaire Corporation. All rights reserved. 8 * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. 9 * 10 * This software is available to you under a choice of one of two 11 * licenses. You may choose to be licensed under the terms of the GNU 12 * General Public License (GPL) Version 2, available from the file 13 * COPYING in the main directory of this source tree, or the 14 * OpenIB.org BSD license below: 15 * 16 * Redistribution and use in source and binary forms, with or 17 * without modification, are permitted provided that the following 18 * conditions are met: 19 * 20 * - Redistributions of source code must retain the above 21 * copyright notice, this list of conditions and the following 22 * disclaimer. 23 * 24 * - Redistributions in binary form must reproduce the above 25 * copyright notice, this list of conditions and the following 26 * disclaimer in the documentation and/or other materials 27 * provided with the distribution. 28 * 29 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 30 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 31 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 32 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 33 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 34 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 35 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 36 * SOFTWARE. 37 * 38 */ 39 40#include <rdma/ib_smi.h> 41#include "smi.h" 42 43/* 44 * Fixup a directed route SMP for sending 45 * Return 0 if the SMP should be discarded 46 */ 47enum smi_action smi_handle_dr_smp_send(struct ib_smp *smp, u8 node_type, 48 int port_num) { 49 u8 hop_ptr, hop_cnt; 50 51 hop_ptr = smp->hop_ptr; 52 hop_cnt = smp->hop_cnt; 53 54 /*See section 14.2.2.2, Vol 1 IB spec*/ 55 if (!ib_get_smp_direction(smp)) { 56 /*C14-9:1*/ 57 if (hop_cnt && hop_ptr == 0) { 58 smp->hop_ptr++; 59 return (smp->initial_path[smp->hop_ptr] == port_num ? 60 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 /*smp->return_path set when received*/ 69 smp->hop_ptr++; 70 return (smp->initial_path[smp->hop_ptr] == port_num ? 71 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 /*smp->return_path set when received*/ 77 smp->hop_ptr++; 78 return (node_type == RDMA_NODE_IB_SWITCH|| 79 smp->dr_dlid == IB_LID_PERMISSIVE ? IB_SMI_HANDLE : IB_SMI_DISCARD); 80 } 81 82 /*C14-9:4 -- hop_ptr = hop_cnt + 1 -> give to SMA/SM 83 C14-9:5 -- Fail unreasonable hop pointer*/ 84 return (hop_ptr == hop_cnt + 1 ? IB_SMI_HANDLE : IB_SMI_DISCARD); 85 86 } else { 87 /*C14-13:1*/ 88 if (hop_cnt && hop_ptr == hop_cnt + 1) { 89 smp->hop_ptr--; 90 return (smp->return_path[smp->hop_ptr] == port_num ? 91 IB_SMI_HANDLE : IB_SMI_DISCARD); 92 } 93 94 /*C14-13:2*/ 95 if (2 <= hop_ptr && hop_ptr <= hop_cnt) { 96 if (node_type != RDMA_NODE_IB_SWITCH) 97 return IB_SMI_DISCARD; 98 99 smp->hop_ptr--; 100 return (smp->return_path[smp->hop_ptr] == port_num ? 101 IB_SMI_HANDLE : IB_SMI_DISCARD); 102 } 103 104 /*C14-13:3 -- at the end of the DR segment of path*/ 105 if (hop_ptr == 1) { 106 smp->hop_ptr--; 107 /*C14-13:3 -- SMPs destined for SM shouldn't be here*/ 108 return (node_type == RDMA_NODE_IB_SWITCH|| 109 smp->dr_slid == IB_LID_PERMISSIVE ? IB_SMI_HANDLE : IB_SMI_DISCARD); 110 } 111 112 /*C14-13:4 -- hop_ptr = 0 -> should have gone to SM*/ 113 if (hop_ptr == 0) 114 return IB_SMI_HANDLE; 115 116 /*C14-13:5 -- Check for unreasonable hop pointer*/ 117 return IB_SMI_DISCARD; 118 } 119} 120/* 121 122 * Adjust information for a received SMP 123 * Return 0 if the SMP should be dropped 124 */ 125enum smi_action smi_handle_dr_smp_recv(struct ib_smp *smp, u8 node_type, 126 int port_num, int phys_port_cnt) { 127 u8 hop_ptr, hop_cnt; 128 129 hop_ptr = smp->hop_ptr; 130 hop_cnt = smp->hop_cnt; 131 132 /*See section 14.2.2.2, Vol 1 IB spec*/ 133 if (!ib_get_smp_direction(smp)) { 134 /*C14-9:1 -- sender should have incremented hop_ptr*/ 135 if (hop_cnt && hop_ptr == 0) 136 return IB_SMI_DISCARD; 137 138 /*C14-9:2 -- intermediate hop*/ 139 if (hop_ptr && hop_ptr < hop_cnt) { 140 if (node_type != RDMA_NODE_IB_SWITCH) 141 return IB_SMI_DISCARD; 142 143 smp->return_path[hop_ptr] = port_num; 144 /*smp->hop_ptr updated when sending*/ 145 return (smp->initial_path[hop_ptr + 1] <= phys_port_cnt ? 146 IB_SMI_HANDLE : IB_SMI_DISCARD); 147 } 148 149 /*C14-9:3 -- We're at the end of the DR segment of path*/ 150 if (hop_ptr == hop_cnt) { 151 if (hop_cnt) 152 smp->return_path[hop_ptr] = port_num; 153 /*smp->hop_ptr updated when sending*/ 154 155 return (node_type 156 == RDMA_NODE_IB_SWITCH|| smp->dr_dlid == IB_LID_PERMISSIVE ? 157 IB_SMI_HANDLE : IB_SMI_DISCARD); 158 } 159 160 /*C14-9:4 -- hop_ptr = hop_cnt + 1 -> give to SMA/SM 161 C14-9:5 -- fail unreasonable hop pointer*/ 162 return (hop_ptr == hop_cnt + 1 ? IB_SMI_HANDLE : IB_SMI_DISCARD); 163 164 } else { 165 166 /*C14-13:1*/ 167 if (hop_cnt && hop_ptr == hop_cnt + 1) { 168 smp->hop_ptr--; 169 return (smp->return_path[smp->hop_ptr] == port_num ? 170 IB_SMI_HANDLE : IB_SMI_DISCARD); 171 } 172 173 /*C14-13:2*/ 174 if (2 <= hop_ptr && hop_ptr <= hop_cnt) { 175 if (node_type != RDMA_NODE_IB_SWITCH) 176 return IB_SMI_DISCARD; 177 178 /*smp->hop_ptr updated when sending*/ 179 return (smp->return_path[hop_ptr - 1] <= phys_port_cnt ? 180 IB_SMI_HANDLE : IB_SMI_DISCARD); 181 } 182 183 /*C14-13:3 -- We're at the end of the DR segment of path*/ 184 if (hop_ptr == 1) { 185 if (smp->dr_slid == IB_LID_PERMISSIVE) { 186 /*giving SMP to SM - update hop_ptr*/ 187 smp->hop_ptr--; 188 return IB_SMI_HANDLE; 189 } 190 /* smp->hop_ptr updated when sending*/ 191 return (node_type == RDMA_NODE_IB_SWITCH ? 192 IB_SMI_HANDLE : IB_SMI_DISCARD); 193 } 194 195 /*C14-13:4 -- hop_ptr = 0 -> give to SM 196 C14-13:5 -- Check for unreasonable hop pointer*/ 197 return (hop_ptr == 0 ? IB_SMI_HANDLE : IB_SMI_DISCARD); 198 } 199} 200 201enum smi_forward_action smi_check_forward_dr_smp(struct ib_smp *smp) { 202 u8 hop_ptr, hop_cnt; 203 204 hop_ptr = smp->hop_ptr; 205 hop_cnt = smp->hop_cnt; 206 207 if (!ib_get_smp_direction(smp)) { 208 /* C14-9:2 -- intermediate hop*/ 209 if (hop_ptr && hop_ptr < hop_cnt) 210 return IB_SMI_FORWARD; 211 212 /* C14-9:3 -- at the end of the DR segment of path*/ 213 if (hop_ptr == hop_cnt) 214 return (smp->dr_dlid == IB_LID_PERMISSIVE ? 215 IB_SMI_SEND : IB_SMI_LOCAL); 216 217 /*C14-9:4 -- hop_ptr = hop_cnt + 1 -> give to SMA/SM*/ 218 if (hop_ptr == hop_cnt + 1) 219 return IB_SMI_SEND; 220 } else { 221 /*C14-13:2 -- intermediate hop*/ 222 if (2 <= hop_ptr && hop_ptr <= hop_cnt) 223 return IB_SMI_FORWARD; 224 225 /*C14-13:3 -- at the end of the DR segment of path*/ 226 if (hop_ptr == 1) 227 return (smp->dr_slid != IB_LID_PERMISSIVE ? 228 IB_SMI_SEND : IB_SMI_LOCAL); 229 } 230 return IB_SMI_LOCAL; 231} 232/* 233 234 * Return the forwarding port number from initial_path for outgoing SMP and 235 * from return_path for returning SMP 236 */ 237int smi_get_fwd_port(struct ib_smp *smp) { 238 return (!ib_get_smp_direction(smp) ? 239 smp->initial_path[smp->hop_ptr + 1] : 240 smp->return_path[smp->hop_ptr - 1]); 241} 242