static int dltran_read_page(datalink_id_t link, uint_t tranid, uint_t page, uint8_t *bufp, size_t *buflen) { dld_ioc_tranio_t dti; bzero(bufp, *buflen); bzero(&dti, sizeof (dti)); dti.dti_linkid = link; dti.dti_tran_id = tranid; dti.dti_page = page; dti.dti_nbytes = *buflen; dti.dti_off = 0; dti.dti_buf = (uintptr_t)(void *)bufp; if (ioctl(dladm_dld_fd(dltran_hdl), DLDIOC_READTRAN, &dti) != 0) { (void) fprintf(stderr, "failed to read transceiver page " "0x%2x: %s\n", page, strerror(errno)); return (1); } *buflen = dti.dti_nbytes; return (0); }
/* ARGSUSED */ static dladm_status_t do_set_priority(dladm_handle_t handle, const char *flow, val_desc_t *vdp, uint_t val_cnt) { dld_ioc_modifyflow_t attr; mac_resource_props_t mrp; if (val_cnt != 1) return (DLADM_STATUS_BADVALCNT); bzero(&mrp, sizeof (mrp)); if (vdp != NULL) { bcopy(&vdp->vd_val, &mrp.mrp_priority, sizeof (mac_priority_level_t)); } else { mrp.mrp_priority = MPL_RESET; } mrp.mrp_mask = MRP_PRIORITY; bzero(&attr, sizeof (attr)); (void) strlcpy(attr.mf_name, flow, sizeof (attr.mf_name)); bcopy(&mrp, &attr.mf_resource_props, sizeof (mac_resource_props_t)); if (ioctl(dladm_dld_fd(handle), DLDIOC_MODIFYFLOW, &attr) < 0) return (dladm_errno2status(errno)); return (DLADM_STATUS_OK); }
/* ARGSUSED */ static dladm_status_t do_set_dscp(dladm_handle_t handle, const char *flow, val_desc_t *vdp, uint_t val_cnt) { dld_ioc_modifyflow_t attr; mac_resource_props_t mrp; void *val; if (val_cnt != 1) return (DLADM_STATUS_BADVALCNT); bzero(&mrp, sizeof (mrp)); if (vdp != NULL && (val = (void *)vdp->vd_val) != NULL) { bcopy(val, &mrp.mrp_dscp, sizeof (int8_t)); free(val); } else { mrp.mrp_dscp = MRP_DSCP_RESETVAL; } mrp.mrp_mask = MRP_DSCP; bzero(&attr, sizeof (attr)); (void) strlcpy(attr.mf_name, flow, sizeof (attr.mf_name)); bcopy(&mrp, &attr.mf_resource_props, sizeof (mac_resource_props_t)); if (ioctl(dladm_dld_fd(handle), DLDIOC_MODIFYFLOW, &attr) < 0) return (dladm_errno2status(errno)); return (DLADM_STATUS_OK); }
static dladm_status_t i_dladm_flow_add(dladm_handle_t handle, char *flowname, datalink_id_t linkid, flow_desc_t *flowdesc, mac_resource_props_t *mrp) { dld_ioc_addflow_t attr; /* create flow */ bzero(&attr, sizeof (attr)); bcopy(flowdesc, &attr.af_flow_desc, sizeof (flow_desc_t)); if (mrp != NULL) { bcopy(mrp, &attr.af_resource_props, sizeof (mac_resource_props_t)); } (void) strlcpy(attr.af_name, flowname, sizeof (attr.af_name)); attr.af_linkid = linkid; if (ioctl(dladm_dld_fd(handle), DLDIOC_ADDFLOW, &attr) < 0) return (dladm_errno2status(errno)); return (DLADM_STATUS_OK); }
/* * Create an instance of a transceiver with the specified id. We must create * both its port and the transceiver node. */ static int nic_create_transceiver(topo_mod_t *mod, tnode_t *pnode, dladm_handle_t handle, datalink_id_t linkid, uint_t tranid) { int ret; tnode_t *port; dld_ioc_gettran_t dgt; dld_ioc_tranio_t dti; uint8_t buf[256]; char ouibuf[16]; char *vendor = NULL, *part = NULL, *rev = NULL, *serial = NULL; nvlist_t *nvl = NULL; if ((ret = port_create_sff(mod, pnode, tranid, &port)) != 0) return (ret); bzero(&dgt, sizeof (dgt)); dgt.dgt_linkid = linkid; dgt.dgt_tran_id = tranid; if (ioctl(dladm_dld_fd(handle), DLDIOC_GETTRAN, &dgt) != 0) { if (errno == ENOTSUP) return (0); return (-1); } if (dgt.dgt_present == 0) return (0); bzero(&dti, sizeof (dti)); dti.dti_linkid = linkid; dti.dti_tran_id = tranid; dti.dti_page = 0xa0; dti.dti_nbytes = sizeof (buf); dti.dti_buf = (uintptr_t)buf; if (ioctl(dladm_dld_fd(handle), DLDIOC_READTRAN, &dti) == 0) { uchar_t *oui; uint_t nbyte; if (libsff_parse(buf, dti.dti_nbytes, dti.dti_page, &nvl) == 0) { if ((ret = nvlist_lookup_string(nvl, LIBSFF_KEY_VENDOR, &vendor)) != 0 && nvlist_lookup_byte_array(nvl, LIBSFF_KEY_OUI, &oui, &nbyte) == 0 && nbyte == 3) { if (snprintf(ouibuf, sizeof (ouibuf), "%02x:%02x:%02x", oui[0], oui[1], oui[2]) < sizeof (ouibuf)) { vendor = ouibuf; } } else if (ret != 0) { vendor = NULL; } if (nvlist_lookup_string(nvl, LIBSFF_KEY_PART, &part) != 0) { part = NULL; } if (nvlist_lookup_string(nvl, LIBSFF_KEY_REVISION, &rev) != 0) { rev = NULL; } if (nvlist_lookup_string(nvl, LIBSFF_KEY_SERIAL, &serial) != 0) { serial = NULL; } } } if (transceiver_range_create(mod, port, 0, 0) != 0) { nvlist_free(nvl); return (-1); } if (transceiver_create_sff(mod, port, 0, dgt.dgt_usable, vendor, part, rev, serial, NULL) != 0) { nvlist_free(nvl); return (-1); } nvlist_free(nvl); return (0); }
/* ARGSUSED */ static int nic_enum(topo_mod_t *mod, tnode_t *pnode, const char *name, topo_instance_t min, topo_instance_t max, void *modarg, void *data) { di_node_t din = data; datalink_id_t linkid; dladm_handle_t handle; dld_ioc_gettran_t dgt; uint_t ntrans, i; char dname[MAXNAMELEN]; if (strcmp(name, NIC) != 0) { topo_mod_dprintf(mod, "nic_enum: asked to enumerate unknown " "component: %s\n", name); return (-1); } if (din == NULL) { topo_mod_dprintf(mod, "nic_enum: missing data argument\n"); return (-1); } if ((handle = topo_mod_getspecific(mod)) == NULL) { topo_mod_dprintf(mod, "nic_enum: failed to get nic module " "specific data\n"); return (-1); } if (snprintf(dname, sizeof (dname), "%s%d", di_driver_name(din), di_instance(din)) >= sizeof (dname)) { topo_mod_dprintf(mod, "nic_enum: device name overflowed " "internal buffer\n"); return (-1); } if (dladm_dev2linkid(handle, dname, &linkid) != DLADM_STATUS_OK) return (-1); bzero(&dgt, sizeof (dgt)); dgt.dgt_linkid = linkid; dgt.dgt_tran_id = DLDIOC_GETTRAN_GETNTRAN; if (ioctl(dladm_dld_fd(handle), DLDIOC_GETTRAN, &dgt) != 0) { if (errno == ENOTSUP) return (0); return (-1); } ntrans = dgt.dgt_tran_id; if (ntrans == 0) return (0); if (port_range_create(mod, pnode, 0, ntrans - 1) != 0) return (-1); for (i = 0; i < ntrans; i++) { if (nic_create_transceiver(mod, pnode, handle, linkid, i) != 0) return (-1); } return (0); }
static int dltran_dump_transceivers(dladm_handle_t hdl, datalink_id_t linkid, void *arg) { dladm_status_t status; char name[MAXLINKNAMELEN]; dld_ioc_gettran_t gt; uint_t count, i, tranid = UINT_MAX; boolean_t tran_found = B_FALSE; uint_t *tranidp = arg; if (tranidp != NULL) tranid = *tranidp; if ((status = dladm_datalink_id2info(hdl, linkid, NULL, NULL, NULL, name, sizeof (name))) != DLADM_STATUS_OK) { (void) fprintf(stderr, "failed to get datalink name for link " "%d: %s", linkid, dladm_status2str(status, dltran_dlerrmsg)); dltran_errors++; return (DLADM_WALK_CONTINUE); } bzero(>, sizeof (gt)); gt.dgt_linkid = linkid; gt.dgt_tran_id = DLDIOC_GETTRAN_GETNTRAN; if (ioctl(dladm_dld_fd(hdl), DLDIOC_GETTRAN, >) != 0) { if (errno != ENOTSUP) { (void) fprintf(stderr, "failed to get transceiver " "count for device %s: %s\n", name, strerror(errno)); dltran_errors++; } return (DLADM_WALK_CONTINUE); } count = gt.dgt_tran_id; (void) printf("%s: discovered %d transceiver%s\n", name, count, count > 1 ? "s" : ""); for (i = 0; i < count; i++) { if (tranid != UINT_MAX && i != tranid) continue; if (tranid != UINT_MAX) tran_found = B_TRUE; bzero(>, sizeof (gt)); gt.dgt_linkid = linkid; gt.dgt_tran_id = i; if (ioctl(dladm_dld_fd(hdl), DLDIOC_GETTRAN, >) != 0) { (void) fprintf(stderr, "failed to get tran info for " "%s: %s\n", name, strerror(errno)); dltran_errors++; return (DLADM_WALK_CONTINUE); } if (dltran_hex && !gt.dgt_present) continue; if (!dltran_hex && !dltran_write) { (void) printf("\ttransceiver %d present: %s\n", i, gt.dgt_present ? "yes" : "no"); if (!gt.dgt_present) continue; (void) printf("\ttransceiver %d usable: %s\n", i, gt.dgt_usable ? "yes" : "no"); } if (dltran_verbose) { dltran_verbose_dump(linkid, i); } if (dltran_write) { if (!gt.dgt_present) { (void) fprintf(stderr, "warning: no " "transceiver present in port %d, not " "writing\n", i); dltran_errors++; continue; } dltran_write_page(linkid, i); } if (dltran_hex) { printf("transceiver %d data:\n", i); dltran_hex_dump(linkid, i); } } if (tranid != UINT_MAX && !tran_found) { dltran_errors++; (void) fprintf(stderr, "failed to find transceiver %d on " "link %s\n", tranid, name); } return (DLADM_WALK_CONTINUE); }