1 /* 2 * Copyright (c) 2004-2009 Voltaire Inc. All rights reserved. 3 * Copyright (c) 2009 HNR Consulting. All rights reserved. 4 * 5 * This software is available to you under a choice of one of two 6 * licenses. You may choose to be licensed under the terms of the GNU 7 * General Public License (GPL) Version 2, available from the file 8 * COPYING in the main directory of this source tree, or the 9 * OpenIB.org BSD license below: 10 * 11 * Redistribution and use in source and binary forms, with or 12 * without modification, are permitted provided that the following 13 * conditions are met: 14 * 15 * - Redistributions of source code must retain the above 16 * copyright notice, this list of conditions and the following 17 * disclaimer. 18 * 19 * - Redistributions in binary form must reproduce the above 20 * copyright notice, this list of conditions and the following 21 * disclaimer in the documentation and/or other materials 22 * provided with the distribution. 23 * 24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 25 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 26 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 27 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 28 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 29 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 30 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 31 * SOFTWARE. 32 * 33 */ 34 35 #if HAVE_CONFIG_H 36 # include <config.h> 37 #endif /* HAVE_CONFIG_H */ 38 39 #include <stdio.h> 40 #include <stdlib.h> 41 #include <string.h> 42 #include <arpa/inet.h> 43 #include <errno.h> 44 45 #include <infiniband/umad.h> 46 #include <infiniband/mad.h> 47 #include "mad_internal.h" 48 49 #undef DEBUG 50 #define DEBUG if (ibdebug) IBWARN 51 52 int ib_resolve_smlid_via(ib_portid_t * sm_id, int timeout, 53 const struct ibmad_port *srcport) 54 { 55 umad_port_t port; 56 int ret; 57 58 memset(sm_id, 0, sizeof(*sm_id)); 59 60 ret = umad_get_port(srcport->ca_name, srcport->portnum, &port); 61 if (ret) 62 return -1; 63 64 if (!IB_LID_VALID(port.sm_lid)) { 65 errno = ENXIO; 66 return -1; 67 } 68 sm_id->sl = port.sm_sl; 69 70 ret = ib_portid_set(sm_id, port.sm_lid, 0, 0); 71 umad_release_port(&port); 72 return ret; 73 } 74 75 int ib_resolve_smlid(ib_portid_t * sm_id, int timeout) 76 { 77 return ib_resolve_smlid_via(sm_id, timeout, ibmp); 78 } 79 80 int ib_resolve_gid_via(ib_portid_t * portid, ibmad_gid_t gid, 81 ib_portid_t * sm_id, int timeout, 82 const struct ibmad_port *srcport) 83 { 84 ib_portid_t sm_portid = { 0 }; 85 char buf[IB_SA_DATA_SIZE] = { 0 }; 86 87 if (!sm_id) 88 sm_id = &sm_portid; 89 90 if (!IB_LID_VALID(sm_id->lid)) { 91 if (ib_resolve_smlid_via(sm_id, timeout, srcport) < 0) 92 return -1; 93 } 94 95 if ((portid->lid = 96 ib_path_query_via(srcport, gid, gid, sm_id, buf)) < 0) 97 return -1; 98 99 return 0; 100 } 101 102 int ib_resolve_guid_via(ib_portid_t * portid, uint64_t * guid, 103 ib_portid_t * sm_id, int timeout, 104 const struct ibmad_port *srcport) 105 { 106 ib_portid_t sm_portid = { 0 }; 107 uint8_t buf[IB_SA_DATA_SIZE] = { 0 }; 108 uint64_t prefix; 109 ibmad_gid_t selfgid; 110 umad_port_t port; 111 112 if (!sm_id) 113 sm_id = &sm_portid; 114 115 if (!IB_LID_VALID(sm_id->lid)) { 116 if (ib_resolve_smlid_via(sm_id, timeout, srcport) < 0) 117 return -1; 118 } 119 120 if (umad_get_port(srcport->ca_name, srcport->portnum, &port)) 121 return -1; 122 123 mad_set_field64(selfgid, 0, IB_GID_PREFIX_F, ntohll(port.gid_prefix)); 124 mad_set_field64(selfgid, 0, IB_GID_GUID_F, ntohll(port.port_guid)); 125 umad_release_port(&port); 126 127 memcpy(&prefix, portid->gid, sizeof(prefix)); 128 if (!prefix) 129 mad_set_field64(portid->gid, 0, IB_GID_PREFIX_F, 130 IB_DEFAULT_SUBN_PREFIX); 131 if (guid) 132 mad_set_field64(portid->gid, 0, IB_GID_GUID_F, *guid); 133 134 if ((portid->lid = 135 ib_path_query_via(srcport, selfgid, portid->gid, sm_id, buf)) < 0) 136 return -1; 137 138 mad_decode_field(buf, IB_SA_PR_SL_F, &portid->sl); 139 return 0; 140 } 141 142 int ib_resolve_portid_str_via(ib_portid_t * portid, char *addr_str, 143 enum MAD_DEST dest_type, ib_portid_t * sm_id, 144 const struct ibmad_port *srcport) 145 { 146 ibmad_gid_t gid; 147 uint64_t guid; 148 int lid; 149 char *routepath; 150 ib_portid_t selfportid = { 0 }; 151 int selfport = 0; 152 153 memset(portid, 0, sizeof *portid); 154 155 switch (dest_type) { 156 case IB_DEST_LID: 157 lid = strtol(addr_str, 0, 0); 158 if (!IB_LID_VALID(lid)) { 159 errno = EINVAL; 160 return -1; 161 } 162 return ib_portid_set(portid, lid, 0, 0); 163 164 case IB_DEST_DRPATH: 165 if (str2drpath(&portid->drpath, addr_str, 0, 0) < 0) { 166 errno = EINVAL; 167 return -1; 168 } 169 return 0; 170 171 case IB_DEST_GUID: 172 if (!(guid = strtoull(addr_str, 0, 0))) { 173 errno = EINVAL; 174 return -1; 175 } 176 177 /* keep guid in portid? */ 178 return ib_resolve_guid_via(portid, &guid, sm_id, 0, srcport); 179 180 case IB_DEST_DRSLID: 181 lid = strtol(addr_str, &routepath, 0); 182 routepath++; 183 if (!IB_LID_VALID(lid)) { 184 errno = EINVAL; 185 return -1; 186 } 187 ib_portid_set(portid, lid, 0, 0); 188 189 /* handle DR parsing and set DrSLID to local lid */ 190 if (ib_resolve_self_via(&selfportid, &selfport, 0, srcport) < 0) 191 return -1; 192 if (str2drpath(&portid->drpath, routepath, selfportid.lid, 0) < 193 0) { 194 errno = EINVAL; 195 return -1; 196 } 197 return 0; 198 199 case IB_DEST_GID: 200 if (inet_pton(AF_INET6, addr_str, &gid) <= 0) 201 return -1; 202 return ib_resolve_gid_via(portid, gid, sm_id, 0, srcport); 203 default: 204 IBWARN("bad dest_type %d", dest_type); 205 errno = EINVAL; 206 } 207 208 return -1; 209 } 210 211 int ib_resolve_portid_str(ib_portid_t * portid, char *addr_str, 212 enum MAD_DEST dest_type, ib_portid_t * sm_id) 213 { 214 return ib_resolve_portid_str_via(portid, addr_str, dest_type, 215 sm_id, ibmp); 216 } 217 218 int ib_resolve_self_via(ib_portid_t * portid, int *portnum, ibmad_gid_t * gid, 219 const struct ibmad_port *srcport) 220 { 221 ib_portid_t self = { 0 }; 222 uint8_t portinfo[64]; 223 uint8_t nodeinfo[64]; 224 uint64_t guid, prefix; 225 226 if (!smp_query_via(nodeinfo, &self, IB_ATTR_NODE_INFO, 0, 0, srcport)) 227 return -1; 228 229 if (!smp_query_via(portinfo, &self, IB_ATTR_PORT_INFO, 0, 0, srcport)) 230 return -1; 231 232 mad_decode_field(portinfo, IB_PORT_LID_F, &portid->lid); 233 mad_decode_field(portinfo, IB_PORT_SMSL_F, &portid->sl); 234 mad_decode_field(portinfo, IB_PORT_GID_PREFIX_F, &prefix); 235 mad_decode_field(nodeinfo, IB_NODE_PORT_GUID_F, &guid); 236 237 if (portnum) 238 mad_decode_field(nodeinfo, IB_NODE_LOCAL_PORT_F, portnum); 239 if (gid) { 240 mad_encode_field(*gid, IB_GID_PREFIX_F, &prefix); 241 mad_encode_field(*gid, IB_GID_GUID_F, &guid); 242 } 243 return 0; 244 } 245 246 int ib_resolve_self(ib_portid_t * portid, int *portnum, ibmad_gid_t * gid) 247 { 248 return ib_resolve_self_via(portid, portnum, gid, ibmp); 249 } 250