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_nativetype = DL_IB; 73 mtrp->mtr_addrlen = IPOIB_ADDRL; 74 mtrp->mtr_brdcst_addr = ib_brdcst; 75 76 /* 77 * So far, generic stats maintained by GLDv3 are sufficient for IB. 78 */ 79 mtrp->mtr_stats = NULL; 80 mtrp->mtr_statcount = 0; 81 if ((err = mactype_register(mtrp)) == 0) { 82 if ((err = mod_install(&mac_ib_modlinkage)) != 0) 83 (void) mactype_unregister(MAC_PLUGIN_IDENT_IB); 84 } 85 mactype_free(mtrp); 86 return (err); 87 } 88 89 int 90 _fini(void) 91 { 92 int err; 93 94 if ((err = mactype_unregister(MAC_PLUGIN_IDENT_IB)) != 0) 95 return (err); 96 return (mod_remove(&mac_ib_modlinkage)); 97 } 98 99 int 100 _info(struct modinfo *modinfop) 101 { 102 return (mod_info(&mac_ib_modlinkage, modinfop)); 103 } 104 105 /* 106 * MAC Type plugin operations 107 */ 108 109 /* ARGSUSED */ 110 int 111 mac_ib_unicst_verify(const void *addr, void *mac_pdata) 112 { 113 ipoib_mac_t *ibaddr = (ipoib_mac_t *)addr; 114 115 /* 116 * The address must not be a multicast address. 117 */ 118 return (ntohl(ibaddr->ipoib_qpn) == IB_MC_QPN ? EINVAL : 0); 119 } 120 121 int 122 mac_ib_multicst_verify(const void *addr, void *mac_pdata) 123 { 124 ipoib_mac_t *ibaddr = (ipoib_mac_t *)addr; 125 uint8_t *p_gid = (uint8_t *)addr + sizeof (ipoib_mac_t) 126 - MAC_IB_GID_SIZE; 127 uint32_t bcst_gid[3] = { 0x0, 0x0, MAC_IB_BROADCAST_GID }; 128 129 _NOTE(ARGUNUSED(mac_pdata)); 130 131 /* 132 * The address must be a multicast address. 133 */ 134 if ((ntohl(ibaddr->ipoib_qpn) & IB_QPN_MASK) != IB_MC_QPN) 135 return (EINVAL); 136 137 /* 138 * The address must not be the broadcast address. 139 */ 140 if (bcmp(p_gid, (uint8_t *)bcst_gid + sizeof (bcst_gid) - 141 MAC_IB_GID_SIZE, MAC_IB_GID_SIZE) == 0) 142 return (EINVAL); 143 144 return (0); 145 } 146 147 /* 148 * Check the legality of a SAP value. The following values are 149 * allowed, as specified by PSARC 2003/150: 150 * 151 * min-ethertype-sap (256).. EtherType max(65535) ethertype semantics 152 * (0) .. max-802-sap(255) IEEE 802 semantics 153 */ 154 boolean_t 155 mac_ib_sap_verify(uint32_t sap, uint32_t *bind_sap, void *mac_pdata) 156 { 157 _NOTE(ARGUNUSED(mac_pdata)); 158 159 if (sap > MAC_IB_MAX_802_SAP && sap <= MAC_IB_ETHERTYPE_MAX) { 160 if (bind_sap != NULL) 161 *bind_sap = sap; 162 return (B_TRUE); 163 } 164 165 if (sap <= MAC_IB_MAX_802_SAP) { 166 if (bind_sap != NULL) 167 *bind_sap = DLS_SAP_LLC; 168 return (B_TRUE); 169 } 170 171 return (B_FALSE); 172 } 173 174 /* ARGSUSED */ 175 mblk_t * 176 mac_ib_header(const void *saddr, const void *daddr, uint32_t sap, 177 void *mac_pdata, mblk_t *payload, size_t extra_len) 178 { 179 ib_header_info_t *ibhp; 180 mblk_t *mp; 181 182 if (!mac_ib_sap_verify(sap, NULL, NULL)) 183 return (NULL); 184 185 mp = allocb(sizeof (ib_header_info_t) + extra_len, BPRI_HI); 186 if (mp == NULL) 187 return (NULL); 188 189 ibhp = (ib_header_info_t *)mp->b_rptr; 190 ibhp->ipib_rhdr.ipoib_type = htons(sap); 191 ibhp->ipib_rhdr.ipoib_mbz = 0; 192 bcopy(daddr, &ibhp->ib_dst, IPOIB_ADDRL); 193 mp->b_wptr += sizeof (ib_header_info_t); 194 return (mp); 195 } 196 197 int 198 mac_ib_header_info(mblk_t *mp, void *mac_pdata, mac_header_info_t *hdr_info) 199 { 200 ib_header_info_t *ibhp; 201 uint16_t sap; 202 203 if (MBLKL(mp) < sizeof (ib_header_info_t)) 204 return (EINVAL); 205 206 ibhp = (ib_header_info_t *)mp->b_rptr; 207 208 hdr_info->mhi_hdrsize = sizeof (ib_header_info_t); 209 hdr_info->mhi_daddr = (const uint8_t *)&(ibhp->ib_dst); 210 if (ibhp->ib_grh.ipoib_vertcflow != 0) 211 hdr_info->mhi_saddr = (const uint8_t *)&(ibhp->ib_src); 212 else 213 hdr_info->mhi_saddr = NULL; 214 215 if (mac_ib_unicst_verify(hdr_info->mhi_daddr, mac_pdata) == 0) { 216 hdr_info->mhi_dsttype = MAC_ADDRTYPE_UNICAST; 217 } else if (mac_ib_multicst_verify(hdr_info->mhi_daddr, 218 mac_pdata) == 0) { 219 hdr_info->mhi_dsttype = MAC_ADDRTYPE_MULTICAST; 220 } else { 221 hdr_info->mhi_dsttype = MAC_ADDRTYPE_BROADCAST; 222 } 223 224 sap = ntohs(ibhp->ipib_rhdr.ipoib_type); 225 hdr_info->mhi_origsap = hdr_info->mhi_bindsap = sap; 226 hdr_info->mhi_pktsize = 0; 227 228 return (0); 229 } 230 231 /* 232 * Take the provided `mp' (which is expected to have a header "dst + type"), 233 * and return a pointer to an mblk_t with a header "GRH + type". 234 * If the conversion cannot be performed, return NULL. 235 */ 236 static mblk_t * 237 mac_ib_header_cook(mblk_t *mp, void *pdata) 238 { 239 ipoib_ptxhdr_t *orig_hp; 240 mblk_t *llmp; 241 242 if (MBLKL(mp) < sizeof (ipoib_ptxhdr_t)) 243 return (NULL); 244 245 orig_hp = (ipoib_ptxhdr_t *)mp->b_rptr; 246 llmp = mac_ib_header(NULL, &orig_hp->ipoib_dest, 247 ntohs(orig_hp->ipoib_rhdr.ipoib_type), pdata, NULL, 0); 248 if (llmp == NULL) 249 return (NULL); 250 251 /* 252 * The plugin framework guarantees that we have the only reference 253 * to the mblk_t, so we can safely modify it. 254 */ 255 ASSERT(DB_REF(mp) == 1); 256 mp->b_rptr += sizeof (ipoib_ptxhdr_t); 257 llmp->b_cont = mp; 258 return (llmp); 259 } 260 261 /* 262 * Take the provided `mp' (which is expected to have a header "GRH + type"), 263 * and return a pointer to an mblk_t with a header "type". If the conversion 264 * cannot be performed, return NULL. 265 */ 266 static mblk_t * 267 mac_ib_header_uncook(mblk_t *mp, void *pdata) 268 { 269 _NOTE(ARGUNUSED(pdata)); 270 271 /* 272 * The plugin framework guarantees that we have the only reference to 273 * the mblk_t and the underlying dblk_t, so we can safely modify it. 274 */ 275 ASSERT(DB_REF(mp) == 1); 276 277 mp->b_rptr += sizeof (ib_addrs_t); 278 return (mp); 279 } 280 281 void 282 mac_ib_link_details(char *buf, size_t sz, mac_handle_t mh, void *mac_pdata) 283 { 284 uint64_t speed; 285 286 _NOTE(ARGUNUSED(mac_pdata)); 287 288 speed = mac_stat_get(mh, MAC_STAT_IFSPEED); 289 290 /* convert to Mbps */ 291 speed /= 1000000; 292 293 buf[0] = 0; 294 (void) snprintf(buf, sz, "%u Mbps", (uint32_t)speed); 295 } 296 297 static mactype_ops_t mac_ib_type_ops = { 298 MTOPS_HEADER_COOK | MTOPS_HEADER_UNCOOK | MTOPS_LINK_DETAILS, 299 mac_ib_unicst_verify, 300 mac_ib_multicst_verify, 301 mac_ib_sap_verify, 302 mac_ib_header, 303 mac_ib_header_info, 304 NULL, 305 mac_ib_header_cook, 306 mac_ib_header_uncook, 307 mac_ib_link_details 308 }; 309