diff options
| author | WENTAO YANG <Wentao.Yang@Sun.COM> | 2008-11-19 15:29:21 -0800 |
|---|---|---|
| committer | WENTAO YANG <Wentao.Yang@Sun.COM> | 2008-11-19 15:29:21 -0800 |
| commit | 6ab6cb20c72ce71fe6022b1c164f36dfe716e425 (patch) | |
| tree | 7f5de78e2d8aed9c7af8364a72e26d9a5697534a /usr/src/uts/sun4v/io | |
| parent | 354507029a42e4bcb1ea64fc4685f2bfd4792db8 (diff) | |
| download | illumos-joyent-6ab6cb20c72ce71fe6022b1c164f36dfe716e425.tar.gz | |
6747464 NIU HybridIO needs stats to reflect the assignment and traffic
Diffstat (limited to 'usr/src/uts/sun4v/io')
| -rw-r--r-- | usr/src/uts/sun4v/io/vnet.c | 219 | ||||
| -rw-r--r-- | usr/src/uts/sun4v/io/vsw_hio.c | 133 |
2 files changed, 352 insertions, 0 deletions
diff --git a/usr/src/uts/sun4v/io/vnet.c b/usr/src/uts/sun4v/io/vnet.c index 3d471190ff..191cfba92b 100644 --- a/usr/src/uts/sun4v/io/vnet.c +++ b/usr/src/uts/sun4v/io/vnet.c @@ -95,6 +95,12 @@ static void vnet_res_start_task(void *arg); static void vnet_handle_res_err(vio_net_handle_t vrh, vio_net_err_val_t err); int vnet_mtu_update(vnet_t *vnetp, uint32_t mtu); +static kstat_t *vnet_hio_setup_kstats(char *ks_mod, char *ks_name, + vnet_res_t *vresp); +static int vnet_hio_update_kstats(kstat_t *ksp, int rw); +static void vnet_hio_get_stats(vnet_res_t *vresp, vnet_hio_stats_t *statsp); +static void vnet_hio_destroy_kstats(kstat_t *ksp); + /* Exported to to vnet_dds */ int vnet_send_dds_msg(vnet_t *vnetp, void *dmsg); @@ -112,6 +118,7 @@ extern void vdds_cleanup(vnet_t *vnetp); extern void vdds_process_dds_msg(vnet_t *vnetp, vio_dds_msg_t *dmsg); extern void vdds_cleanup_hybrid_res(void *arg); +#define DRV_NAME "vnet" #define VNET_FDBE_REFHOLD(p) \ { \ atomic_inc_32(&(p)->refcnt); \ @@ -1177,6 +1184,16 @@ int vio_net_resource_reg(mac_register_t *macp, vio_net_res_type_t type, return (ENXIO); } + /* Setup kstats for hio resource */ + if (vresp->type == VIO_NET_RES_HYBRID) { + vresp->ksp = vnet_hio_setup_kstats(DRV_NAME, "hio", vresp); + if (vresp->ksp == NULL) { + DWARN(NULL, "Cannot create kstats for hio resource"); + kmem_free(vresp, sizeof (vnet_res_t)); + return (ENXIO); + } + } + *vhp = vresp; vcb->vio_net_rx_cb = vnet_rx; vcb->vio_net_tx_update = vnet_tx_update; @@ -1196,6 +1213,7 @@ vio_net_resource_unreg(vio_net_handle_t vhp) vnet_res_t *vresp = (vnet_res_t *)vhp; vnet_t *vnetp = vresp->vnetp; vnet_res_t *vrp; + kstat_t *ksp = NULL; DBG1(NULL, "Resource Registerig hdl=0x%p", vhp); @@ -1215,9 +1233,14 @@ vio_net_resource_unreg(vio_net_handle_t vhp) vrp = vrp->nextp; } } + + ksp = vresp->ksp; + vresp->ksp = NULL; + vresp->vnetp = NULL; vresp->nextp = NULL; RW_EXIT(&vnetp->vrwlock); + vnet_hio_destroy_kstats(ksp); KMEM_FREE(vresp); } @@ -1373,3 +1396,199 @@ vnet_stop_resources(vnet_t *vnetp) } DBG1(vnetp, "exit\n"); } + +/* + * Setup kstats for the HIO statistics. + * NOTE: the synchronization for the statistics is the + * responsibility of the caller. + */ +kstat_t * +vnet_hio_setup_kstats(char *ks_mod, char *ks_name, vnet_res_t *vresp) +{ + kstat_t *ksp; + vnet_t *vnetp = vresp->vnetp; + vnet_hio_kstats_t *hiokp; + size_t size; + + ASSERT(vnetp != NULL); + size = sizeof (vnet_hio_kstats_t) / sizeof (kstat_named_t); + ksp = kstat_create(ks_mod, vnetp->instance, ks_name, "net", + KSTAT_TYPE_NAMED, size, 0); + if (ksp == NULL) { + return (NULL); + } + + hiokp = (vnet_hio_kstats_t *)ksp->ks_data; + kstat_named_init(&hiokp->ipackets, "ipackets", + KSTAT_DATA_ULONG); + kstat_named_init(&hiokp->ierrors, "ierrors", + KSTAT_DATA_ULONG); + kstat_named_init(&hiokp->opackets, "opackets", + KSTAT_DATA_ULONG); + kstat_named_init(&hiokp->oerrors, "oerrors", + KSTAT_DATA_ULONG); + + + /* MIB II kstat variables */ + kstat_named_init(&hiokp->rbytes, "rbytes", + KSTAT_DATA_ULONG); + kstat_named_init(&hiokp->obytes, "obytes", + KSTAT_DATA_ULONG); + kstat_named_init(&hiokp->multircv, "multircv", + KSTAT_DATA_ULONG); + kstat_named_init(&hiokp->multixmt, "multixmt", + KSTAT_DATA_ULONG); + kstat_named_init(&hiokp->brdcstrcv, "brdcstrcv", + KSTAT_DATA_ULONG); + kstat_named_init(&hiokp->brdcstxmt, "brdcstxmt", + KSTAT_DATA_ULONG); + kstat_named_init(&hiokp->norcvbuf, "norcvbuf", + KSTAT_DATA_ULONG); + kstat_named_init(&hiokp->noxmtbuf, "noxmtbuf", + KSTAT_DATA_ULONG); + + ksp->ks_update = vnet_hio_update_kstats; + ksp->ks_private = (void *)vresp; + kstat_install(ksp); + return (ksp); +} + +/* + * Destroy kstats. + */ +static void +vnet_hio_destroy_kstats(kstat_t *ksp) +{ + if (ksp != NULL) + kstat_delete(ksp); +} + +/* + * Update the kstats. + */ +static int +vnet_hio_update_kstats(kstat_t *ksp, int rw) +{ + vnet_t *vnetp; + vnet_res_t *vresp; + vnet_hio_stats_t statsp; + vnet_hio_kstats_t *hiokp; + + vresp = (vnet_res_t *)ksp->ks_private; + vnetp = vresp->vnetp; + + bzero(&statsp, sizeof (vnet_hio_stats_t)); + + READ_ENTER(&vnetp->vsw_fp_rw); + if (vnetp->hio_fp == NULL) { + /* not using hio resources, just return */ + RW_EXIT(&vnetp->vsw_fp_rw); + return (0); + } + VNET_FDBE_REFHOLD(vnetp->hio_fp); + RW_EXIT(&vnetp->vsw_fp_rw); + vnet_hio_get_stats(vnetp->hio_fp, &statsp); + VNET_FDBE_REFRELE(vnetp->hio_fp); + + hiokp = (vnet_hio_kstats_t *)ksp->ks_data; + + if (rw == KSTAT_READ) { + /* Link Input/Output stats */ + hiokp->ipackets.value.ul = (uint32_t)statsp.ipackets; + hiokp->ipackets64.value.ull = statsp.ipackets; + hiokp->ierrors.value.ul = statsp.ierrors; + hiokp->opackets.value.ul = (uint32_t)statsp.opackets; + hiokp->opackets64.value.ull = statsp.opackets; + hiokp->oerrors.value.ul = statsp.oerrors; + + /* MIB II kstat variables */ + hiokp->rbytes.value.ul = (uint32_t)statsp.rbytes; + hiokp->rbytes64.value.ull = statsp.rbytes; + hiokp->obytes.value.ul = (uint32_t)statsp.obytes; + hiokp->obytes64.value.ull = statsp.obytes; + hiokp->multircv.value.ul = statsp.multircv; + hiokp->multixmt.value.ul = statsp.multixmt; + hiokp->brdcstrcv.value.ul = statsp.brdcstrcv; + hiokp->brdcstxmt.value.ul = statsp.brdcstxmt; + hiokp->norcvbuf.value.ul = statsp.norcvbuf; + hiokp->noxmtbuf.value.ul = statsp.noxmtbuf; + } else { + return (EACCES); + } + + return (0); +} + +static void +vnet_hio_get_stats(vnet_res_t *vresp, vnet_hio_stats_t *statsp) +{ + mac_register_t *macp; + mac_callbacks_t *cbp; + uint64_t val; + int stat; + + /* + * get the specified statistics from the underlying nxge. + */ + macp = &vresp->macreg; + cbp = macp->m_callbacks; + for (stat = MAC_STAT_MIN; stat < MAC_STAT_OVERFLOWS; stat++) { + if (cbp->mc_getstat(macp->m_driver, stat, &val) == 0) { + switch (stat) { + case MAC_STAT_IPACKETS: + statsp->ipackets = val; + break; + + case MAC_STAT_IERRORS: + statsp->ierrors = val; + break; + + case MAC_STAT_OPACKETS: + statsp->opackets = val; + break; + + case MAC_STAT_OERRORS: + statsp->oerrors = val; + break; + + case MAC_STAT_RBYTES: + statsp->rbytes = val; + break; + + case MAC_STAT_OBYTES: + statsp->obytes = val; + break; + + case MAC_STAT_MULTIRCV: + statsp->multircv = val; + break; + + case MAC_STAT_MULTIXMT: + statsp->multixmt = val; + break; + + case MAC_STAT_BRDCSTRCV: + statsp->brdcstrcv = val; + break; + + case MAC_STAT_BRDCSTXMT: + statsp->brdcstxmt = val; + break; + + case MAC_STAT_NOXMTBUF: + statsp->noxmtbuf = val; + break; + + case MAC_STAT_NORCVBUF: + statsp->norcvbuf = val; + break; + + default: + /* + * parameters not interested. + */ + break; + } + } + } +} diff --git a/usr/src/uts/sun4v/io/vsw_hio.c b/usr/src/uts/sun4v/io/vsw_hio.c index a99d54125c..278896d977 100644 --- a/usr/src/uts/sun4v/io/vsw_hio.c +++ b/usr/src/uts/sun4v/io/vsw_hio.c @@ -109,6 +109,9 @@ static void vsw_hio_unbind_macaddr(vsw_share_t *vsharep); static boolean_t vsw_hio_reboot_callb(void *arg, int code); static boolean_t vsw_hio_panic_callb(void *arg, int code); +static kstat_t *vsw_hio_setup_kstats(char *ks_mod, char *ks_name, vsw_t *vswp); +static void vsw_hio_destroy_kstats(vsw_t *vswp); +static int vsw_hio_kstats_update(kstat_t *ksp, int rw); /* * vsw_hio_init -- Initialize the HybridIO related info. @@ -164,6 +167,12 @@ vsw_hio_init(vsw_t *vswp) vswp->hio_panic_cb_id = callb_add(vsw_hio_panic_callb, (void *)vswp, CB_CL_PANIC, "vsw_hio"); + /* setup kstats for hybrid resources */ + hiop->vh_ksp = vsw_hio_setup_kstats(DRV_NAME, "hio", vswp); + if (hiop->vh_ksp == NULL) { + DERR(vswp, "%s: kstats setup failed", __func__); + } + D2(vswp, "%s: %s is HybridIO capable num_shares=%d\n", __func__, vswp->physname, hiop->vh_num_shares); D1(vswp, "%s:exit\n", __func__); @@ -382,6 +391,7 @@ vsw_hio_free_share(vsw_share_t *vsharep) /* free share */ hcapab->ms_sfree(vsharep->vs_shdl); vsharep->vs_state = VSW_SHARE_FREE; + vsharep->vs_macaddr = 0; /* DERR only for printing by default */ DERR(vswp, "Share freed for ldc_id=0x%lx Cookie=0x%lX", @@ -409,6 +419,7 @@ vsw_hio_cleanup(vsw_t *vswp) vswp->hio_panic_cb_id = 0; } vsw_hio_free_all_shares(vswp, B_FALSE); + vsw_hio_destroy_kstats(vswp); D1(vswp, "%s:exit\n", __func__); } @@ -993,3 +1004,125 @@ vsw_hio_panic_callb(void *arg, int code) D1(vswp, "%s:exit\n", __func__); return (B_TRUE); } + +/* + * Setup kstats for hio statistics. + */ +static kstat_t * +vsw_hio_setup_kstats(char *ks_mod, char *ks_name, vsw_t *vswp) +{ + kstat_t *ksp; + vsw_hio_kstats_t *hiokp; + vsw_hio_t *hiop; + char share_assigned_info[MAXNAMELEN]; + size_t size; + int i; + + hiop = &vswp->vhio; + /* + * vsw_hio_stats_t structure is variable size structure + * having fields defined only for one share. So, we need + * allocate additional space for the rest of the shares. + */ + size = sizeof (vsw_hio_kstats_t) / sizeof (kstat_named_t); + ASSERT(hiop->vh_num_shares >= 1); + size += ((hiop->vh_num_shares - 1) * 2); + + ksp = kstat_create(ks_mod, vswp->instance, ks_name, "misc", + KSTAT_TYPE_NAMED, size, KSTAT_FLAG_VIRTUAL); + + if (ksp == NULL) { + return (NULL); + } + hiokp = (vsw_hio_kstats_t *)kmem_zalloc(sizeof (kstat_named_t) * + size, KM_SLEEP); + ksp->ks_data = hiokp; + + hiop->vh_ksp = ksp; + hiop->vh_kstatsp = hiokp; + hiop->vh_kstat_size = size; + + kstat_named_init(&hiokp->hio_capable, "hio_capable", KSTAT_DATA_CHAR); + kstat_named_init(&hiokp->hio_num_shares, "hio_num_shares", + KSTAT_DATA_ULONG); + + for (i = 0; i < hiop->vh_num_shares; i++) { + (void) sprintf(share_assigned_info, "%s%d", "hio_share_", i); + kstat_named_init(&(hiokp->share[i].assigned), + share_assigned_info, KSTAT_DATA_ULONG); + + (void) sprintf(share_assigned_info, "%s%d%s", + "hio_share_", i, "_state"); + kstat_named_init(&(hiokp->share[i].state), + share_assigned_info, KSTAT_DATA_ULONG); + } + + ksp->ks_update = vsw_hio_kstats_update; + ksp->ks_private = (void *)vswp; + kstat_install(ksp); + return (ksp); +} + +/* + * Destroy hio kstats. + */ +static void +vsw_hio_destroy_kstats(vsw_t *vswp) +{ + kstat_t *ksp; + vsw_hio_t *hiop; + + ASSERT(vswp != NULL); + + ksp = vswp->vhio.vh_ksp; + hiop = &vswp->vhio; + if (ksp != NULL) { + kmem_free(hiop->vh_kstatsp, sizeof (kstat_named_t) * + hiop->vh_kstat_size); + kstat_delete(ksp); + hiop->vh_kstatsp = NULL; + hiop->vh_ksp = NULL; + } +} + +/* + * Update hio kstats. + */ +static int +vsw_hio_kstats_update(kstat_t *ksp, int rw) +{ + vsw_t *vswp; + vsw_hio_t *hiop; + vsw_hio_kstats_t *hiokp; + int i; + + vswp = (vsw_t *)ksp->ks_private; + ASSERT(vswp != NULL); + + hiop = &vswp->vhio; + hiokp = hiop->vh_kstatsp; + + if (rw == KSTAT_READ) { + if (vswp->hio_capable) { + (void) strcpy(hiokp->hio_capable.value.c, "Yes"); + } else { + /* not hio capable, just return */ + (void) strcpy(hiokp->hio_capable.value.c, "No"); + return (0); + } + + mutex_enter(&vswp->hw_lock); + hiokp->hio_num_shares.value.ul = (uint32_t)hiop->vh_num_shares; + for (i = 0; i < hiop->vh_num_shares; i++) { + hiokp->share[i].assigned.value.ul = + hiop->vh_shares[i].vs_macaddr; + hiokp->share[i].state.value.ul = + hiop->vh_shares[i].vs_state; + } + mutex_exit(&vswp->hw_lock); + } else { + return (EACCES); + } + + return (0); +} |
