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 52int 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 75int ib_resolve_smlid(ib_portid_t * sm_id, int timeout) 76{ 77 return ib_resolve_smlid_via(sm_id, timeout, ibmp); 78} 79 80int 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 102int 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 142int 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 211int 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 218int 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 246int 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