1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 /* 29 * DL_IB MAC Type plugin for the Nemo mac module 30 */ 31 32 #include <sys/types.h> 33 #include <sys/modctl.h> 34 #include <sys/dlpi.h> 35 #include <sys/ib/clients/ibd/ibd.h> 36 #include <sys/mac.h> 37 #include <sys/mac_ib.h> 38 #include <sys/dls.h> 39 #include <sys/byteorder.h> 40 #include <sys/strsun.h> 41 #include <inet/common.h> 42 #include <sys/note.h> 43 44 static uint8_t ib_brdcst[] = { 0x00, 0xff, 0xff, 0xff, 45 0xff, 0x10, 0x40, 0x1b, 0x00, 0x00, 0x00, 0x00, 46 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff }; 47 48 static struct modlmisc mac_ib_modlmisc = { 49 &mod_miscops, 50 "Infiniband MAC Type plugin 1.0" 51 }; 52 53 static struct modlinkage mac_ib_modlinkage = { 54 MODREV_1, 55 &mac_ib_modlmisc, 56 NULL 57 }; 58 59 static mactype_ops_t mac_ib_type_ops; 60 61 int 62 _init(void) 63 { 64 mactype_register_t *mtrp; 65 int err; 66 67 if ((mtrp = mactype_alloc(MACTYPE_VERSION)) == NULL) 68 return (ENOTSUP); 69 mtrp->mtr_ident = MAC_PLUGIN_IDENT_IB; 70 mtrp->mtr_ops = &mac_ib_type_ops; 71 mtrp->mtr_mactype = DL_IB; 72 mtrp->mtr_addrlen = IPOIB_ADDRL; 73 mtrp->mtr_brdcst_addr = ib_brdcst; 74 75 /* 76 * So far, generic stats maintained by GLDv3 are sufficient for IB. 77 */ 78 mtrp->mtr_stats = NULL; 79 mtrp->mtr_statcount = 0; 80 if ((err = mactype_register(mtrp)) == 0) { 81 if ((err = mod_install(&mac_ib_modlinkage)) != 0) 82 (void) mactype_unregister(MAC_PLUGIN_IDENT_IB); 83 } 84 mactype_free(mtrp); 85 return (err); 86 } 87 88 int 89 _fini(void) 90 { 91 int err; 92 93 if ((err = mactype_unregister(MAC_PLUGIN_IDENT_IB)) != 0) 94 return (err); 95 return (mod_remove(&mac_ib_modlinkage)); 96 } 97 98 int 99 _info(struct modinfo *modinfop) 100 { 101 return (mod_info(&mac_ib_modlinkage, modinfop)); 102 } 103 104 /* 105 * MAC Type plugin operations 106 */ 107 108 /* ARGSUSED */ 109 int 110 mac_ib_unicst_verify(const void *addr, void *mac_pdata) 111 { 112 ipoib_mac_t *ibaddr = (ipoib_mac_t *)addr; 113 114 /* 115 * The address must not be a multicast address. 116 */ 117 return (ntohl(ibaddr->ipoib_qpn) == IB_MC_QPN ? EINVAL : 0); 118 } 119 120 int 121 mac_ib_multicst_verify(const void *addr, void *mac_pdata) 122 { 123 ipoib_mac_t *ibaddr = (ipoib_mac_t *)addr; 124 uint8_t *p_gid = (uint8_t *)addr + sizeof (ipoib_mac_t) 125 - MAC_IB_GID_SIZE; 126 uint32_t bcst_gid[3] = { 0x0, 0x0, MAC_IB_BROADCAST_GID }; 127 128 _NOTE(ARGUNUSED(mac_pdata)); 129 130 /* 131 * The address must be a multicast address. 132 */ 133 if ((ntohl(ibaddr->ipoib_qpn) & IB_QPN_MASK) != IB_MC_QPN) 134 return (EINVAL); 135 136 /* 137 * The address must not be the broadcast address. 138 */ 139 if (bcmp(p_gid, (uint8_t *)bcst_gid + sizeof (bcst_gid) - 140 MAC_IB_GID_SIZE, MAC_IB_GID_SIZE) == 0) 141 return (EINVAL); 142 143 return (0); 144 } 145 146 /* 147 * Check the legality of a SAP value. The following values are 148 * allowed, as specified by PSARC 2003/150: 149 * 150 * min-ethertype-sap (256).. EtherType max(65535) ethertype semantics 151 * (0) .. max-802-sap(255) IEEE 802 semantics 152 */ 153 boolean_t 154 mac_ib_sap_verify(uint32_t sap, uint32_t *bind_sap, void *mac_pdata) 155 { 156 _NOTE(ARGUNUSED(mac_pdata)); 157 158 if (sap > MAC_IB_MAX_802_SAP && sap <= MAC_IB_ETHERTYPE_MAX) { 159 if (bind_sap != NULL) 160 *bind_sap = sap; 161 return (B_TRUE); 162 } 163 164 if (sap <= MAC_IB_MAX_802_SAP) { 165 if (bind_sap != NULL) 166 *bind_sap = DLS_SAP_LLC; 167 return (B_TRUE); 168 } 169 170 return (B_FALSE); 171 } 172 173 /* ARGSUSED */ 174 mblk_t * 175 mac_ib_header(const void *saddr, const void *daddr, uint32_t sap, 176 void *mac_pdata, mblk_t *payload, size_t extra_len) 177 { 178 ib_header_info_t *ibhp; 179 mblk_t *mp; 180 181 if (!mac_ib_sap_verify(sap, NULL, NULL)) 182 return (NULL); 183 184 mp = allocb(sizeof (ib_header_info_t) + extra_len, BPRI_HI); 185 if (mp == NULL) 186 return (NULL); 187 188 ibhp = (ib_header_info_t *)mp->b_rptr; 189 ibhp->ipib_rhdr.ipoib_type = htons(sap); 190 ibhp->ipib_rhdr.ipoib_mbz = 0; 191 bcopy(daddr, &ibhp->ib_dst, IPOIB_ADDRL); 192 mp->b_wptr += sizeof (ib_header_info_t); 193 return (mp); 194 } 195 196 int 197 mac_ib_header_info(mblk_t *mp, void *mac_pdata, mac_header_info_t *hdr_info) 198 { 199 ib_header_info_t *ibhp; 200 uint16_t sap; 201 202 if (MBLKL(mp) < sizeof (ib_header_info_t)) 203 return (EINVAL); 204 205 ibhp = (ib_header_info_t *)mp->b_rptr; 206 207 hdr_info->mhi_hdrsize = sizeof (ib_header_info_t); 208 hdr_info->mhi_daddr = (const uint8_t *)&(ibhp->ib_dst); 209 if (ibhp->ib_grh.ipoib_vertcflow != 0) 210 hdr_info->mhi_saddr = (const uint8_t *)&(ibhp->ib_src); 211 else 212 hdr_info->mhi_saddr = NULL; 213 214 if (mac_ib_unicst_verify(hdr_info->mhi_daddr, mac_pdata) == 0) { 215 hdr_info->mhi_dsttype = MAC_ADDRTYPE_UNICAST; 216 } else if (mac_ib_multicst_verify(hdr_info->mhi_daddr, 217 mac_pdata) == 0) { 218 hdr_info->mhi_dsttype = MAC_ADDRTYPE_MULTICAST; 219 } else { 220 hdr_info->mhi_dsttype = MAC_ADDRTYPE_BROADCAST; 221 } 222 223 sap = ntohs(ibhp->ipib_rhdr.ipoib_type); 224 hdr_info->mhi_origsap = hdr_info->mhi_bindsap = sap; 225 hdr_info->mhi_pktsize = 0; 226 227 return (0); 228 } 229 230 /* 231 * Take the provided `mp' (which is expected to have a header "dst + type"), 232 * and return a pointer to an mblk_t with a header "GRH + type". 233 * If the conversion cannot be performed, return NULL. 234 */ 235 static mblk_t * 236 mac_ib_header_cook(mblk_t *mp, void *pdata) 237 { 238 ipoib_ptxhdr_t *orig_hp; 239 mblk_t *llmp; 240 241 if (MBLKL(mp) < sizeof (ipoib_ptxhdr_t)) 242 return (NULL); 243 244 orig_hp = (ipoib_ptxhdr_t *)mp->b_rptr; 245 llmp = mac_ib_header(NULL, &orig_hp->ipoib_dest, 246 ntohs(orig_hp->ipoib_rhdr.ipoib_type), pdata, NULL, 0); 247 if (llmp == NULL) 248 return (NULL); 249 250 /* 251 * The plugin framework guarantees that we have the only reference 252 * to the mblk_t, so we can safely modify it. 253 */ 254 ASSERT(DB_REF(mp) == 1); 255 mp->b_rptr += sizeof (ipoib_ptxhdr_t); 256 llmp->b_cont = mp; 257 return (llmp); 258 } 259 260 /* 261 * Take the provided `mp' (which is expected to have a header "GRH + type"), 262 * and return a pointer to an mblk_t with a header "type". If the conversion 263 * cannot be performed, return NULL. 264 */ 265 static mblk_t * 266 mac_ib_header_uncook(mblk_t *mp, void *pdata) 267 { 268 _NOTE(ARGUNUSED(pdata)); 269 270 /* 271 * The plugin framework guarantees that we have the only reference to 272 * the mblk_t and the underlying dblk_t, so we can safely modify it. 273 */ 274 ASSERT(DB_REF(mp) == 1); 275 276 mp->b_rptr += sizeof (ib_addrs_t); 277 return (mp); 278 } 279 280 void 281 mac_ib_link_details(char *buf, size_t sz, mac_handle_t mh, void *mac_pdata) 282 { 283 uint64_t speed; 284 285 _NOTE(ARGUNUSED(mac_pdata)); 286 287 speed = mac_stat_get(mh, MAC_STAT_IFSPEED); 288 289 /* convert to Mbps */ 290 speed /= 1000000; 291 292 buf[0] = 0; 293 (void) snprintf(buf, sz, "%u Mbps", (uint32_t)speed); 294 } 295 296 static mactype_ops_t mac_ib_type_ops = { 297 MTOPS_HEADER_COOK | MTOPS_HEADER_UNCOOK | MTOPS_LINK_DETAILS, 298 mac_ib_unicst_verify, 299 mac_ib_multicst_verify, 300 mac_ib_sap_verify, 301 mac_ib_header, 302 mac_ib_header_info, 303 NULL, 304 mac_ib_header_cook, 305 mac_ib_header_uncook, 306 mac_ib_link_details 307 }; 308