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 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 * 25 * Copyright 2015 Garrett D'Amore <garrett@damore.org> 26 * Copyright 2016 Joyent, Inc. 27 */ 28 29 /* 30 * Ethernet MAC plugin for the Nemo mac module 31 */ 32 33 #include <sys/types.h> 34 #include <sys/modctl.h> 35 #include <sys/dlpi.h> 36 #include <sys/dld_impl.h> 37 #include <sys/mac_ether.h> 38 #include <sys/ethernet.h> 39 #include <sys/byteorder.h> 40 #include <sys/strsun.h> 41 #include <inet/common.h> 42 43 static uint8_t ether_brdcst[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; 44 45 static mac_stat_info_t ether_stats[] = { 46 /* RFC1643 stats */ 47 { ETHER_STAT_ALIGN_ERRORS, "align_errors", KSTAT_DATA_UINT32, 0 }, 48 { ETHER_STAT_FCS_ERRORS, "fcs_errors", KSTAT_DATA_UINT32, 0 }, 49 { ETHER_STAT_FIRST_COLLISIONS, "first_collisions", KSTAT_DATA_UINT32, 50 0 }, 51 { ETHER_STAT_MULTI_COLLISIONS, "multi_collisions", KSTAT_DATA_UINT32, 52 0 }, 53 { ETHER_STAT_SQE_ERRORS, "sqe_errors", KSTAT_DATA_UINT32, 0}, 54 { ETHER_STAT_DEFER_XMTS, "defer_xmts", KSTAT_DATA_UINT32, 0}, 55 { ETHER_STAT_TX_LATE_COLLISIONS, "tx_late_collisions", 56 KSTAT_DATA_UINT32, 0 }, 57 { ETHER_STAT_EX_COLLISIONS, "ex_collisions", KSTAT_DATA_UINT32, 0 }, 58 { ETHER_STAT_MACXMT_ERRORS, "macxmt_errors", KSTAT_DATA_UINT32, 0 }, 59 { ETHER_STAT_CARRIER_ERRORS, "carrier_errors", KSTAT_DATA_UINT32, 0 }, 60 { ETHER_STAT_TOOLONG_ERRORS, "toolong_errors", KSTAT_DATA_UINT32, 0 }, 61 { ETHER_STAT_MACRCV_ERRORS, "macrcv_errors", KSTAT_DATA_UINT32, 0 }, 62 { ETHER_STAT_TOOSHORT_ERRORS, "runt_errors", KSTAT_DATA_UINT32, 0 }, 63 { ETHER_STAT_JABBER_ERRORS, "jabber_errors", KSTAT_DATA_UINT32, 0 }, 64 65 /* Statistics described in the ieee802.3(5) man page */ 66 { ETHER_STAT_XCVR_ADDR, "xcvr_addr", KSTAT_DATA_UINT32, 0 }, 67 { ETHER_STAT_XCVR_ID, "xcvr_id", KSTAT_DATA_UINT32, 0 }, 68 { ETHER_STAT_XCVR_INUSE, "xcvr_inuse", KSTAT_DATA_UINT32, 0 }, 69 { ETHER_STAT_CAP_5000FDX, "cap_5000fdx", KSTAT_DATA_UINT32, 0 }, 70 { ETHER_STAT_CAP_2500FDX, "cap_2500fdx", KSTAT_DATA_UINT32, 0 }, 71 { ETHER_STAT_CAP_100GFDX, "cap_100gfdx", KSTAT_DATA_UINT32, 0 }, 72 { ETHER_STAT_CAP_50GFDX, "cap_50gfdx", KSTAT_DATA_UINT32, 0 }, 73 { ETHER_STAT_CAP_40GFDX, "cap_40gfdx", KSTAT_DATA_UINT32, 0 }, 74 { ETHER_STAT_CAP_25GFDX, "cap_25gfdx", KSTAT_DATA_UINT32, 0 }, 75 { ETHER_STAT_CAP_10GFDX, "cap_10gfdx", KSTAT_DATA_UINT32, 0 }, 76 { ETHER_STAT_CAP_1000FDX, "cap_1000fdx", KSTAT_DATA_UINT32, 0 }, 77 { ETHER_STAT_CAP_1000HDX, "cap_1000hdx", KSTAT_DATA_UINT32, 0 }, 78 { ETHER_STAT_CAP_100T4, "cap_100T4", KSTAT_DATA_UINT32, 0 }, 79 { ETHER_STAT_CAP_100FDX, "cap_100fdx", KSTAT_DATA_UINT32, 0 }, 80 { ETHER_STAT_CAP_100HDX, "cap_100hdx", KSTAT_DATA_UINT32, 0 }, 81 { ETHER_STAT_CAP_10FDX, "cap_10fdx", KSTAT_DATA_UINT32, 0 }, 82 { ETHER_STAT_CAP_10HDX, "cap_10hdx", KSTAT_DATA_UINT32, 0 }, 83 { ETHER_STAT_CAP_ASMPAUSE, "cap_asmpause", KSTAT_DATA_UINT32, 0 }, 84 { ETHER_STAT_CAP_PAUSE, "cap_pause", KSTAT_DATA_UINT32, 0 }, 85 { ETHER_STAT_CAP_AUTONEG, "cap_autoneg", KSTAT_DATA_UINT32, 0 }, 86 { ETHER_STAT_CAP_REMFAULT, "cap_rem_fault", KSTAT_DATA_UINT32, 0 }, 87 { ETHER_STAT_ADV_CAP_5000FDX, "adv_cap_5000fdx", KSTAT_DATA_UINT32, 0 }, 88 { ETHER_STAT_ADV_CAP_2500FDX, "adv_cap_2500fdx", KSTAT_DATA_UINT32, 0 }, 89 { ETHER_STAT_ADV_CAP_100GFDX, "adv_cap_100gfdx", KSTAT_DATA_UINT32, 0 }, 90 { ETHER_STAT_ADV_CAP_50GFDX, "adv_cap_50gfdx", KSTAT_DATA_UINT32, 0 }, 91 { ETHER_STAT_ADV_CAP_40GFDX, "adv_cap_40gfdx", KSTAT_DATA_UINT32, 0 }, 92 { ETHER_STAT_ADV_CAP_25GFDX, "adv_cap_25gfdx", KSTAT_DATA_UINT32, 0 }, 93 { ETHER_STAT_ADV_CAP_10GFDX, "adv_cap_10gfdx", KSTAT_DATA_UINT32, 0 }, 94 { ETHER_STAT_ADV_CAP_1000FDX, "adv_cap_1000fdx", KSTAT_DATA_UINT32, 0 }, 95 { ETHER_STAT_ADV_CAP_1000HDX, "adv_cap_1000hdx", KSTAT_DATA_UINT32, 0 }, 96 { ETHER_STAT_ADV_CAP_100T4, "adv_cap_100T4", KSTAT_DATA_UINT32, 0 }, 97 { ETHER_STAT_ADV_CAP_100FDX, "adv_cap_100fdx", KSTAT_DATA_UINT32, 0}, 98 { ETHER_STAT_ADV_CAP_100HDX, "adv_cap_100hdx", KSTAT_DATA_UINT32, 0}, 99 { ETHER_STAT_ADV_CAP_10FDX, "adv_cap_10fdx", KSTAT_DATA_UINT32, 0 }, 100 { ETHER_STAT_ADV_CAP_10HDX, "adv_cap_10hdx", KSTAT_DATA_UINT32, 0 }, 101 { ETHER_STAT_ADV_CAP_ASMPAUSE, "adv_cap_asmpause", KSTAT_DATA_UINT32, 102 0 }, 103 { ETHER_STAT_ADV_CAP_PAUSE, "adv_cap_pause", KSTAT_DATA_UINT32, 0 }, 104 { ETHER_STAT_ADV_CAP_AUTONEG, "adv_cap_autoneg", KSTAT_DATA_UINT32, 0 }, 105 { ETHER_STAT_ADV_REMFAULT, "adv_rem_fault", KSTAT_DATA_UINT32, 0 }, 106 { ETHER_STAT_LP_CAP_5000FDX, "lp_cap_5000fdx", KSTAT_DATA_UINT32, 0 }, 107 { ETHER_STAT_LP_CAP_2500FDX, "lp_cap_2500fdx", KSTAT_DATA_UINT32, 0 }, 108 { ETHER_STAT_LP_CAP_100GFDX, "lp_cap_100gfdx", KSTAT_DATA_UINT32, 0 }, 109 { ETHER_STAT_LP_CAP_50GFDX, "lp_cap_50gfdx", KSTAT_DATA_UINT32, 0 }, 110 { ETHER_STAT_LP_CAP_40GFDX, "lp_cap_40gfdx", KSTAT_DATA_UINT32, 0 }, 111 { ETHER_STAT_LP_CAP_25GFDX, "lp_cap_25gfdx", KSTAT_DATA_UINT32, 0 }, 112 { ETHER_STAT_LP_CAP_10GFDX, "lp_cap_10gfdx", KSTAT_DATA_UINT32, 0 }, 113 { ETHER_STAT_LP_CAP_1000FDX, "lp_cap_1000fdx", KSTAT_DATA_UINT32, 0 }, 114 { ETHER_STAT_LP_CAP_1000HDX, "lp_cap_1000hdx", KSTAT_DATA_UINT32, 0 }, 115 { ETHER_STAT_LP_CAP_100T4, "lp_cap_100T4", KSTAT_DATA_UINT32, 0 }, 116 { ETHER_STAT_LP_CAP_100FDX, "lp_cap_100fdx", KSTAT_DATA_UINT32, 0 }, 117 { ETHER_STAT_LP_CAP_100HDX, "lp_cap_100hdx", KSTAT_DATA_UINT32, 0 }, 118 { ETHER_STAT_LP_CAP_10FDX, "lp_cap_10fdx", KSTAT_DATA_UINT32, 0 }, 119 { ETHER_STAT_LP_CAP_10HDX, "lp_cap_10hdx", KSTAT_DATA_UINT32, 0 }, 120 { ETHER_STAT_LP_CAP_ASMPAUSE, "lp_cap_asmpause", KSTAT_DATA_UINT32, 0 }, 121 { ETHER_STAT_LP_CAP_PAUSE, "lp_cap_pause", KSTAT_DATA_UINT32, 0 }, 122 { ETHER_STAT_LP_CAP_AUTONEG, "lp_cap_autoneg", KSTAT_DATA_UINT32, 0 }, 123 { ETHER_STAT_LP_REMFAULT, "lp_rem_fault", KSTAT_DATA_UINT32, 0 }, 124 { ETHER_STAT_LINK_ASMPAUSE, "link_asmpause", KSTAT_DATA_UINT32, 0 }, 125 { ETHER_STAT_LINK_PAUSE, "link_pause", KSTAT_DATA_UINT32, 0 }, 126 { ETHER_STAT_LINK_AUTONEG, "link_autoneg", KSTAT_DATA_UINT32, 0 }, 127 { ETHER_STAT_LINK_DUPLEX, "link_duplex", KSTAT_DATA_UINT32, 0 } 128 }; 129 130 static struct modlmisc mac_ether_modlmisc = { 131 &mod_miscops, 132 "Ethernet MAC plugin" 133 }; 134 135 static struct modlinkage mac_ether_modlinkage = { 136 MODREV_1, 137 &mac_ether_modlmisc, 138 NULL 139 }; 140 141 static mactype_ops_t mac_ether_type_ops; 142 143 static mac_ndd_mapping_t mac_ether_mapping[] = { 144 {"adv_autoneg_cap", MAC_PROP_AUTONEG, 0, 1, 145 sizeof (uint8_t), MAC_PROP_PERM_RW}, 146 147 {"adv_5000fdx_cap", MAC_PROP_EN_5000FDX_CAP, 0, 1, 148 sizeof (uint8_t), MAC_PROP_PERM_RW}, 149 150 {"adv_2500fdx_cap", MAC_PROP_EN_2500FDX_CAP, 0, 1, 151 sizeof (uint8_t), MAC_PROP_PERM_RW}, 152 153 {"adv_100gfdx_cap", MAC_PROP_EN_100GFDX_CAP, 0, 1, 154 sizeof (uint8_t), MAC_PROP_PERM_RW}, 155 156 {"adv_50gfdx_cap", MAC_PROP_EN_50GFDX_CAP, 0, 1, 157 sizeof (uint8_t), MAC_PROP_PERM_RW}, 158 159 {"adv_40gfdx_cap", MAC_PROP_EN_40GFDX_CAP, 0, 1, 160 sizeof (uint8_t), MAC_PROP_PERM_RW}, 161 162 {"adv_25gfdx_cap", MAC_PROP_EN_25GFDX_CAP, 0, 1, 163 sizeof (uint8_t), MAC_PROP_PERM_RW}, 164 165 {"adv_10gfdx_cap", MAC_PROP_EN_10GFDX_CAP, 0, 1, 166 sizeof (uint8_t), MAC_PROP_PERM_RW}, 167 168 {"adv_1000fdx_cap", MAC_PROP_EN_1000FDX_CAP, 0, 1, 169 sizeof (uint8_t), MAC_PROP_PERM_RW}, 170 171 {"adv_1000hdx_cap", MAC_PROP_EN_1000HDX_CAP, 0, 1, 172 sizeof (uint8_t), MAC_PROP_PERM_RW}, 173 174 {"adv_100fdx_cap", MAC_PROP_EN_100FDX_CAP, 0, 1, 175 sizeof (uint8_t), MAC_PROP_PERM_RW}, 176 177 {"adv_100hdx_cap", MAC_PROP_EN_100HDX_CAP, 0, 1, 178 sizeof (uint8_t), MAC_PROP_PERM_RW}, 179 180 {"adv_10fdx_cap", MAC_PROP_EN_10FDX_CAP, 0, 1, 181 sizeof (uint8_t), MAC_PROP_PERM_RW}, 182 183 {"adv_10hdx_cap", MAC_PROP_EN_10HDX_CAP, 0, 1, 184 sizeof (uint8_t), MAC_PROP_PERM_RW}, 185 186 {"adv_100T4_cap", MAC_PROP_EN_100T4_CAP, 0, 1, 187 sizeof (uint8_t), MAC_PROP_PERM_READ}, 188 189 {"link_status", MAC_STAT_LINK_UP, 0, 1, 190 sizeof (long), MAC_PROP_FLAGS_RK}, 191 192 {"link_speed", MAC_PROP_SPEED, 0, LONG_MAX, 193 sizeof (uint64_t), MAC_PROP_PERM_READ}, 194 195 {"link_duplex", MAC_PROP_DUPLEX, 0, 2, 196 sizeof (link_duplex_t), MAC_PROP_PERM_READ}, 197 198 {"autoneg_cap", ETHER_STAT_CAP_AUTONEG, 0, 1, 199 sizeof (long), MAC_PROP_FLAGS_RK}, 200 201 {"pause_cap", ETHER_STAT_CAP_PAUSE, 0, 1, 202 sizeof (long), MAC_PROP_FLAGS_RK}, 203 204 {"asym_pause_cap", ETHER_STAT_CAP_ASMPAUSE, 0, 1, 205 sizeof (long), MAC_PROP_FLAGS_RK}, 206 207 {"5000fdx_cap", ETHER_STAT_CAP_5000FDX, 0, 1, 208 sizeof (long), MAC_PROP_FLAGS_RK}, 209 210 {"2500fdx_cap", ETHER_STAT_CAP_2500FDX, 0, 1, 211 sizeof (long), MAC_PROP_FLAGS_RK}, 212 213 {"100gfdx_cap", ETHER_STAT_CAP_100GFDX, 0, 1, 214 sizeof (long), MAC_PROP_FLAGS_RK}, 215 216 {"50gfdx_cap", ETHER_STAT_CAP_50GFDX, 0, 1, 217 sizeof (long), MAC_PROP_FLAGS_RK}, 218 219 {"40gfdx_cap", ETHER_STAT_CAP_40GFDX, 0, 1, 220 sizeof (long), MAC_PROP_FLAGS_RK}, 221 222 {"25gfdx_cap", ETHER_STAT_CAP_25GFDX, 0, 1, 223 sizeof (long), MAC_PROP_FLAGS_RK}, 224 225 {"10gfdx_cap", ETHER_STAT_CAP_10GFDX, 0, 1, 226 sizeof (long), MAC_PROP_FLAGS_RK}, 227 228 {"1000fdx_cap", ETHER_STAT_CAP_1000FDX, 0, 1, 229 sizeof (long), MAC_PROP_FLAGS_RK}, 230 231 {"1000hdx_cap", ETHER_STAT_CAP_1000HDX, 0, 1, 232 sizeof (long), MAC_PROP_FLAGS_RK}, 233 234 {"100T4_cap", ETHER_STAT_CAP_100T4, 0, 1, 235 sizeof (long), MAC_PROP_FLAGS_RK}, 236 237 {"100fdx_cap", ETHER_STAT_CAP_100FDX, 0, 1, 238 sizeof (long), MAC_PROP_FLAGS_RK}, 239 240 {"100hdx_cap", ETHER_STAT_CAP_100HDX, 0, 1, 241 sizeof (long), MAC_PROP_FLAGS_RK}, 242 243 {"10fdx_cap", ETHER_STAT_CAP_10FDX, 0, 1, 244 sizeof (long), MAC_PROP_FLAGS_RK}, 245 246 {"10hdx_cap", ETHER_STAT_CAP_10HDX, 0, 1, 247 sizeof (long), MAC_PROP_FLAGS_RK}, 248 249 {"lp_autoneg_cap", ETHER_STAT_LP_CAP_AUTONEG, 0, 1, 250 sizeof (long), MAC_PROP_FLAGS_RK}, 251 252 {"lp_pause_cap", ETHER_STAT_LP_CAP_PAUSE, 0, 1, 253 sizeof (long), MAC_PROP_FLAGS_RK}, 254 255 {"lp_asym_pause_cap", ETHER_STAT_LP_CAP_ASMPAUSE, 0, 1, 256 sizeof (long), MAC_PROP_FLAGS_RK}, 257 258 {"lp_5000fdx_cap", ETHER_STAT_LP_CAP_5000FDX, 0, 1, 259 sizeof (long), MAC_PROP_FLAGS_RK}, 260 261 {"lp_2500fdx_cap", ETHER_STAT_LP_CAP_2500FDX, 0, 1, 262 sizeof (long), MAC_PROP_FLAGS_RK}, 263 264 {"lp_100gfdx_cap", ETHER_STAT_LP_CAP_100GFDX, 0, 1, 265 sizeof (long), MAC_PROP_FLAGS_RK}, 266 267 {"lp_50gfdx_cap", ETHER_STAT_LP_CAP_50GFDX, 0, 1, 268 sizeof (long), MAC_PROP_FLAGS_RK}, 269 270 {"lp_40gfdx_cap", ETHER_STAT_LP_CAP_40GFDX, 0, 1, 271 sizeof (long), MAC_PROP_FLAGS_RK}, 272 273 {"lp_25gfdx_cap", ETHER_STAT_LP_CAP_25GFDX, 0, 1, 274 sizeof (long), MAC_PROP_FLAGS_RK}, 275 276 {"lp_10gfdx_cap", ETHER_STAT_LP_CAP_10GFDX, 0, 1, 277 sizeof (long), MAC_PROP_FLAGS_RK}, 278 279 {"lp_1000hdx_cap", ETHER_STAT_LP_CAP_1000HDX, 0, 1, 280 sizeof (long), MAC_PROP_FLAGS_RK}, 281 282 {"lp_1000fdx_cap", ETHER_STAT_LP_CAP_1000FDX, 0, 1, 283 sizeof (long), MAC_PROP_FLAGS_RK}, 284 285 {"lp_100T4_cap", ETHER_STAT_LP_CAP_100T4, 0, 1, 286 sizeof (long), MAC_PROP_FLAGS_RK}, 287 288 {"lp_100fdx_cap", ETHER_STAT_LP_CAP_100FDX, 0, 1, 289 sizeof (long), MAC_PROP_FLAGS_RK}, 290 291 {"lp_100hdx_cap", ETHER_STAT_LP_CAP_100HDX, 0, 1, 292 sizeof (long), MAC_PROP_FLAGS_RK}, 293 294 {"lp_10fdx_cap", ETHER_STAT_LP_CAP_10FDX, 0, 1, 295 sizeof (long), MAC_PROP_FLAGS_RK}, 296 297 {"lp_10hdx_cap", ETHER_STAT_LP_CAP_10HDX, 0, 1, 298 sizeof (long), MAC_PROP_FLAGS_RK}, 299 300 {"link_autoneg", ETHER_STAT_LINK_AUTONEG, 0, 1, 301 sizeof (long), MAC_PROP_FLAGS_RK} 302 303 }; 304 305 306 int 307 _init(void) 308 { 309 mactype_register_t *mtrp; 310 int err; 311 312 if ((mtrp = mactype_alloc(MACTYPE_VERSION)) == NULL) 313 return (ENOTSUP); 314 mtrp->mtr_ident = MAC_PLUGIN_IDENT_ETHER; 315 mtrp->mtr_ops = &mac_ether_type_ops; 316 mtrp->mtr_mactype = DL_ETHER; 317 mtrp->mtr_nativetype = DL_ETHER; 318 mtrp->mtr_addrlen = ETHERADDRL; 319 mtrp->mtr_brdcst_addr = ether_brdcst; 320 mtrp->mtr_stats = ether_stats; 321 mtrp->mtr_statcount = A_CNT(ether_stats); 322 mtrp->mtr_mapping = mac_ether_mapping; 323 mtrp->mtr_mappingcount = A_CNT(mac_ether_mapping); 324 if ((err = mactype_register(mtrp)) == 0) { 325 if ((err = mod_install(&mac_ether_modlinkage)) != 0) 326 (void) mactype_unregister(MAC_PLUGIN_IDENT_ETHER); 327 } 328 mactype_free(mtrp); 329 return (err); 330 } 331 332 int 333 _fini(void) 334 { 335 int err; 336 337 if ((err = mactype_unregister(MAC_PLUGIN_IDENT_ETHER)) != 0) 338 return (err); 339 return (mod_remove(&mac_ether_modlinkage)); 340 } 341 342 int 343 _info(struct modinfo *modinfop) 344 { 345 return (mod_info(&mac_ether_modlinkage, modinfop)); 346 } 347 348 /* 349 * MAC Type plugin operations 350 */ 351 352 /* ARGSUSED */ 353 int 354 mac_ether_unicst_verify(const void *addr, void *mac_pdata) 355 { 356 /* If it's not a group address, then it's a valid unicast address. */ 357 return (((((uint8_t *)addr)[0] & 0x01) != 0) ? EINVAL : 0); 358 } 359 360 /* ARGSUSED */ 361 int 362 mac_ether_multicst_verify(const void *addr, void *mac_pdata) 363 { 364 /* The address must be a group address. */ 365 if ((((uint8_t *)addr)[0] & 0x01) == 0) 366 return (EINVAL); 367 /* The address must not be the media broadcast address. */ 368 if (bcmp(addr, ether_brdcst, ETHERADDRL) == 0) 369 return (EINVAL); 370 return (0); 371 } 372 373 /* 374 * Check the legality of an Ethernet SAP value. The following values are 375 * allowed, as specified by PSARC 2003/150: 376 * 377 * 0..ETHERMTU (1500) 802 semantics 378 * ETHERTYPE_802_MIN (1536)..ETHERTYPE_MAX (65535) ethertype semantics 379 * 380 * Note that SAP values less than or equal to ETHERMTU (1500) represent LLC 381 * channels. (See PSARC 2003/150). We strictly use SAP 0 to represent LLC 382 * channels. 383 */ 384 /* ARGSUSED */ 385 boolean_t 386 mac_ether_sap_verify(uint32_t sap, uint32_t *bind_sap, void *mac_pdata) 387 { 388 if (sap >= ETHERTYPE_802_MIN && sap <= ETHERTYPE_MAX) { 389 if (bind_sap != NULL) 390 *bind_sap = sap; 391 return (B_TRUE); 392 } 393 394 if (sap <= ETHERMTU) { 395 if (bind_sap != NULL) 396 *bind_sap = DLS_SAP_LLC; 397 return (B_TRUE); 398 } 399 return (B_FALSE); 400 } 401 402 /* ARGSUSED */ 403 mblk_t * 404 mac_ether_header(const void *saddr, const void *daddr, uint32_t sap, 405 void *mac_pdata, mblk_t *payload, size_t extra_len) 406 { 407 struct ether_header *ehp; 408 mblk_t *mp; 409 uint32_t bind_sap; 410 411 if (!mac_ether_sap_verify(sap, &bind_sap, NULL)) 412 return (NULL); 413 414 mp = allocb(sizeof (struct ether_header) + extra_len, BPRI_HI); 415 if (mp == NULL) 416 return (NULL); 417 418 ehp = (void *)mp->b_rptr; 419 bcopy(daddr, &(ehp->ether_dhost), ETHERADDRL); 420 bcopy(saddr, &(ehp->ether_shost), ETHERADDRL); 421 422 /* 423 * sap <= ETHERMTU indicates that LLC is being used. If that's the 424 * case, then the ether_type needs to be set to the payload length. 425 */ 426 if ((bind_sap == DLS_SAP_LLC) && (payload != NULL)) 427 sap = msgdsize(payload); 428 ehp->ether_type = htons(sap); 429 430 mp->b_wptr += sizeof (struct ether_header); 431 return (mp); 432 } 433 434 /* ARGSUSED */ 435 int 436 mac_ether_header_info(mblk_t *mp, void *mac_pdata, mac_header_info_t *hdr_info) 437 { 438 struct ether_header *ehp; 439 uint16_t ether_type; 440 441 if (MBLKL(mp) < sizeof (struct ether_header)) 442 return (EINVAL); 443 444 ehp = (void *)mp->b_rptr; 445 ether_type = ntohs(ehp->ether_type); 446 447 hdr_info->mhi_hdrsize = sizeof (struct ether_header); 448 hdr_info->mhi_daddr = (const uint8_t *)&(ehp->ether_dhost); 449 hdr_info->mhi_saddr = (const uint8_t *)&(ehp->ether_shost); 450 hdr_info->mhi_origsap = ether_type; 451 hdr_info->mhi_bindsap = (ether_type > ETHERMTU) ? 452 ether_type : DLS_SAP_LLC; 453 hdr_info->mhi_pktsize = (hdr_info->mhi_bindsap == DLS_SAP_LLC) ? 454 hdr_info->mhi_hdrsize + ether_type : 0; 455 456 if (mac_ether_unicst_verify(hdr_info->mhi_daddr, NULL) == 0) 457 hdr_info->mhi_dsttype = MAC_ADDRTYPE_UNICAST; 458 else if (mac_ether_multicst_verify(hdr_info->mhi_daddr, NULL) == 0) 459 hdr_info->mhi_dsttype = MAC_ADDRTYPE_MULTICAST; 460 else 461 hdr_info->mhi_dsttype = MAC_ADDRTYPE_BROADCAST; 462 463 return (0); 464 } 465 466 /*ARGSUSED3*/ 467 void 468 mac_ether_link_details(char *buf, size_t sz, mac_handle_t mh, void *mac_pdata) 469 { 470 link_duplex_t duplex; 471 uint64_t speed; 472 473 duplex = mac_stat_get(mh, ETHER_STAT_LINK_DUPLEX); 474 speed = mac_stat_get(mh, MAC_STAT_IFSPEED); 475 476 /* convert to Mbps */ 477 speed /= 1000000; 478 479 buf[0] = 0; 480 (void) snprintf(buf, sz, "%u Mbps, %s duplex", (uint32_t)speed, 481 duplex == LINK_DUPLEX_FULL ? "full" : 482 duplex == LINK_DUPLEX_HALF ? "half" : "unknown"); 483 } 484 485 static mactype_ops_t mac_ether_type_ops = { 486 MTOPS_LINK_DETAILS, 487 mac_ether_unicst_verify, 488 mac_ether_multicst_verify, 489 mac_ether_sap_verify, 490 mac_ether_header, 491 mac_ether_header_info, 492 NULL, /* pdata_verify */ 493 NULL, /* header_cook */ 494 NULL, /* header_uncook */ 495 mac_ether_link_details 496 }; 497