static int tswtcl_destroy_action(ipp_action_id_t aid, ipp_flags_t flags) { tswtcl_data_t *tswtcl_data; tswtcl_cfg_t *cfg_parms; int rc; tswtcl_data = (tswtcl_data_t *)ipp_action_get_ptr(aid); ASSERT(tswtcl_data != NULL); cfg_parms = tswtcl_data->cfg_parms; if (cfg_parms->stats) { ipp_stat_destroy(tswtcl_data->stats); } /* unreference the action */ rc = ipp_action_unref(aid, cfg_parms->red_action, flags); ASSERT(rc == 0); rc = ipp_action_unref(aid, cfg_parms->yellow_action, flags); ASSERT(rc == 0); rc = ipp_action_unref(aid, cfg_parms->green_action, flags); ASSERT(rc == 0); mutex_destroy(&tswtcl_data->tswtcl_lock); kmem_free(cfg_parms, TSWTCL_CFG_SZ); kmem_free(tswtcl_data, TSWTCL_DATA_SZ); return (0); }
static int tokenmt_destroy_action(ipp_action_id_t aid, ipp_flags_t flags) { tokenmt_data_t *tokenmt_data; tokenmt_cfg_t *cfg_parms; int rc; tokenmt_data = (tokenmt_data_t *)ipp_action_get_ptr(aid); ASSERT(tokenmt_data != NULL); cfg_parms = tokenmt_data->cfg_parms; if (cfg_parms->stats) { ipp_stat_destroy(tokenmt_data->stats); } /* unreference the action */ rc = ipp_action_unref(aid, cfg_parms->red_action, flags); ASSERT(rc == 0); if (cfg_parms->yellow_action != TOKENMT_NO_ACTION) { rc = ipp_action_unref(aid, cfg_parms->yellow_action, flags); ASSERT(rc == 0); } rc = ipp_action_unref(aid, cfg_parms->green_action, flags); ASSERT(rc == 0); mutex_destroy(&tokenmt_data->tokenmt_lock); kmem_free(cfg_parms, TOKENMT_CFG_SZ); kmem_free(tokenmt_data, TOKENMT_DATA_SZ); return (0); }
static int dlcosmk_destroy_action(ipp_action_id_t aid, ipp_flags_t flags) { dlcosmk_data_t *dlcosmk_data; int err; dlcosmk_data = (dlcosmk_data_t *)ipp_action_get_ptr(aid); ASSERT(dlcosmk_data != NULL); /* Destroy stats, if gathered */ if (dlcosmk_data->gather_stats) { ipp_stat_destroy(dlcosmk_data->stats); } /* unreference the action */ err = ipp_action_unref(aid, dlcosmk_data->next_action, flags); ASSERT(err == 0); kmem_free(dlcosmk_data, DLCOSMK_DATA_SZ); return (0); }
static int dlcosmk_modify_action(ipp_action_id_t aid, nvlist_t **nvlpp, ipp_flags_t flags) { nvlist_t *nvlp; int err = 0; uint32_t band, dlpri; uint8_t config_type; uint8_t cos; char *next_action_name; ipp_action_id_t next_action; dlcosmk_data_t *dlcosmk_data; uint32_t bstats; ASSERT((nvlpp != NULL) && (*nvlpp != NULL)); nvlp = *nvlpp; *nvlpp = NULL; /* nvlist should be NULL when this returns */ if ((err = nvlist_lookup_byte(nvlp, IPP_CONFIG_TYPE, &config_type)) != 0) { nvlist_free(nvlp); dlcosmk0dbg(("dlcosmk_modify_action: invalid configuration "\ "type\n")); return (err); } if (config_type != IPP_SET) { nvlist_free(nvlp); dlcosmk0dbg(("dlcosmk_modify_action: invalid configuration "\ "type %d\n", config_type)); return (EINVAL); } dlcosmk_data = (dlcosmk_data_t *)ipp_action_get_ptr(aid); ASSERT(dlcosmk_data != NULL); /* parse next action name, if present */ if ((err = nvlist_lookup_string(nvlp, DLCOSMK_NEXT_ACTION_NAME, &next_action_name)) == 0) { /* lookup action name to get action id */ if ((next_action = ipp_action_lookup(next_action_name)) == IPP_ACTION_INVAL) { nvlist_free(nvlp); dlcosmk0dbg(("dlcosmk_modify_action: next_action "\ "invalid\n")); return (EINVAL); } /* reference new action */ if ((err = ipp_action_ref(aid, next_action, flags)) != 0) { nvlist_free(nvlp); dlcosmk0dbg(("dlcosmk_modify_action: ipp_action_ref "\ "returned with error %d\n", err)); return (err); } /* unref old action */ err = ipp_action_unref(aid, dlcosmk_data->next_action, flags); ASSERT(err == 0); dlcosmk_data->next_action = next_action; } /* parse cos, if present */ if ((err = nvlist_lookup_byte(nvlp, DLCOSMK_COS, &cos)) == 0) { /* parse b_band, mapped from cos */ if ((err = nvlist_lookup_uint32(nvlp, DLCOSMK_BAND, &band)) != 0) { nvlist_free(nvlp); dlcosmk0dbg(("dlcosmk_modify_action: b_band not "\ "provided\n")); return (err); } /* parse dl_priority, mapped from cos */ if ((err = nvlist_lookup_uint32(nvlp, DLCOSMK_PRI, &dlpri)) != 0) { nvlist_free(nvlp); dlcosmk0dbg(("dlcosmk_modify_action: dl_priority not "\ "provided\n")); return (err); } /* Have all the three values, change them */ dlcosmk_data->usr_pri = cos; dlcosmk_data->b_band = band; dlcosmk_data->dl_max = dlpri; } /* parse gather_stats boolean, if present */ if ((err = nvlist_lookup_uint32(nvlp, IPP_ACTION_STATS_ENABLE, &bstats)) == 0) { boolean_t val = (bstats != 0) ? B_TRUE : B_FALSE; /* Turning on stats */ if (!dlcosmk_data->gather_stats && val) { if ((err = dlcosmk_statinit(aid, dlcosmk_data)) != 0) { nvlist_free(nvlp); return (err); } /* Turning off stats */ } else if (!val && dlcosmk_data->gather_stats) { ipp_stat_destroy(dlcosmk_data->stats); } dlcosmk_data->gather_stats = val; } /* Free thenvlist */ nvlist_free(nvlp); return (0); }
static int dlcosmk_create_action(ipp_action_id_t aid, nvlist_t **nvlpp, ipp_flags_t flags) { nvlist_t *nvlp; dlcosmk_data_t *dlcosmk_data; char *next_action; int err; uint32_t bstats, param; ASSERT((nvlpp != NULL) && (*nvlpp != NULL)); nvlp = *nvlpp; *nvlpp = NULL; /* nvlist should be NULL on return */ if ((dlcosmk_data = kmem_zalloc(DLCOSMK_DATA_SZ, KM_NOSLEEP)) == NULL) { nvlist_free(nvlp); return (ENOMEM); } /* parse next action name */ if ((err = nvlist_lookup_string(nvlp, DLCOSMK_NEXT_ACTION_NAME, &next_action)) != 0) { nvlist_free(nvlp); dlcosmk0dbg(("dlcosmk_create_action: invalid config, "\ "next_action name missing\n")); kmem_free(dlcosmk_data, DLCOSMK_DATA_SZ); return (err); } if ((dlcosmk_data->next_action = ipp_action_lookup(next_action)) == IPP_ACTION_INVAL) { nvlist_free(nvlp); dlcosmk0dbg(("dlcosmk_create_action: next_action invalid\n")); kmem_free(dlcosmk_data, DLCOSMK_DATA_SZ); return (EINVAL); } /* parse cos - from the config file */ if ((err = nvlist_lookup_byte(nvlp, DLCOSMK_COS, &dlcosmk_data->usr_pri)) != 0) { nvlist_free(nvlp); dlcosmk0dbg(("dlcosmk_create_action: invalid config, "\ "cos missing\n")); kmem_free(dlcosmk_data, DLCOSMK_DATA_SZ); return (err); } /* parse b_band - mapped from cos */ if ((err = nvlist_lookup_uint32(nvlp, DLCOSMK_BAND, ¶m)) != 0) { nvlist_free(nvlp); dlcosmk0dbg(("dlcosmk_create_action: invalid config, "\ "b_band missing\n")); kmem_free(dlcosmk_data, DLCOSMK_DATA_SZ); return (err); } dlcosmk_data->b_band = param; /* parse dl_priority.dl_max - mapped from cos */ if ((err = nvlist_lookup_uint32(nvlp, DLCOSMK_PRI, ¶m)) != 0) { nvlist_free(nvlp); dlcosmk0dbg(("dlcosmk_create_action: invalid config, "\ "dl_priority missing\n")); kmem_free(dlcosmk_data, DLCOSMK_DATA_SZ); return (err); } dlcosmk_data->dl_max = param; /* parse gather_stats boolean */ if ((err = nvlist_lookup_uint32(nvlp, IPP_ACTION_STATS_ENABLE, &bstats)) != 0) { dlcosmk_data->gather_stats = B_FALSE; } else { /* If stats is needed, initialize the stats structure */ dlcosmk_data->gather_stats = (bstats != 0) ? B_TRUE : B_FALSE; if (dlcosmk_data->gather_stats) { if ((err = dlcosmk_statinit(aid, dlcosmk_data)) != 0) { nvlist_free(nvlp); kmem_free(dlcosmk_data, DLCOSMK_DATA_SZ); return (err); } } } /* Free the nvlist */ nvlist_free(nvlp); /* set action chain reference */ if ((err = ipp_action_ref(aid, dlcosmk_data->next_action, flags)) != 0) { dlcosmk0dbg(("dlcosmk_create_action: ipp_action_ref " \ "returned with error %d\n", err)); ipp_stat_destroy(dlcosmk_data->stats); kmem_free(dlcosmk_data, DLCOSMK_DATA_SZ); return (err); } ipp_action_set_ptr(aid, (void *)dlcosmk_data); return (0); }
static int tswtcl_modify_action(ipp_action_id_t aid, nvlist_t **nvlpp, ipp_flags_t flags) { nvlist_t *nvlp; int err = 0, err2; uint8_t config_type; char *next_action_name; ipp_action_id_t next_action; uint32_t rate; tswtcl_cfg_t *cfg_parms, *old_cfg; tswtcl_data_t *tswtcl_data; uint32_t bstats; nvlp = *nvlpp; *nvlpp = NULL; /* nvlist should be NULL when this returns */ if ((err = nvlist_lookup_byte(nvlp, IPP_CONFIG_TYPE, &config_type)) != 0) { nvlist_free(nvlp); tswtcl0dbg(("tswtcl_modify_action:invalid configuration type")); return (err); } if (config_type != IPP_SET) { nvlist_free(nvlp); tswtcl0dbg(("tswtcl_modify_action:invalid configuration type " \ "%d", config_type)); return (EINVAL); } tswtcl_data = (tswtcl_data_t *)ipp_action_get_ptr(aid); old_cfg = tswtcl_data->cfg_parms; cfg_parms = kmem_alloc(TSWTCL_CFG_SZ, KM_NOSLEEP); if (cfg_parms == NULL) { nvlist_free(nvlp); tswtcl0dbg(("tswtcl_modify_action:mem. allocation failure\n")); return (ENOMEM); } /* Just copy all and change as needed */ bcopy(old_cfg, cfg_parms, TSWTCL_CFG_SZ); /* parse red action name, if present */ if ((err = nvlist_lookup_string(nvlp, TSWTCL_RED_ACTION_NAME, &next_action_name)) == 0) { /* Get action id */ if ((next_action = ipp_action_lookup(next_action_name)) == IPP_ACTION_INVAL) { nvlist_free(nvlp); tswtcl0dbg(("tswtcl_modify_action: red next_action"\ " invalid\n")); kmem_free(cfg_parms, TSWTCL_CFG_SZ); return (EINVAL); } cfg_parms->red_action = next_action; } /* parse yellow action name, if present */ if ((err = nvlist_lookup_string(nvlp, TSWTCL_YELLOW_ACTION_NAME, &next_action_name)) == 0) { /* Get action id */ if ((next_action = ipp_action_lookup(next_action_name)) == IPP_ACTION_INVAL) { nvlist_free(nvlp); tswtcl0dbg(("tswtcl_modify_action: yellow next_action"\ " invalid\n")); kmem_free(cfg_parms, TSWTCL_CFG_SZ); return (EINVAL); } cfg_parms->yellow_action = next_action; } /* parse green action name, if present */ if ((err = nvlist_lookup_string(nvlp, TSWTCL_GREEN_ACTION_NAME, &next_action_name)) == 0) { /* Get action id */ if ((next_action = ipp_action_lookup(next_action_name)) == IPP_ACTION_INVAL) { nvlist_free(nvlp); tswtcl0dbg(("tswtcl_modify_action: green next_action"\ " invalid\n")); kmem_free(cfg_parms, TSWTCL_CFG_SZ); return (EINVAL); } cfg_parms->green_action = next_action; } /* parse committed rate, if present */ if ((err = nvlist_lookup_uint32(nvlp, TSWTCL_COMMITTED_RATE, &rate)) == 0) { cfg_parms->committed_rate = rate; } /* parse peak rate, if present */ if ((err = nvlist_lookup_uint32(nvlp, TSWTCL_PEAK_RATE, &rate)) == 0) { cfg_parms->peak_rate = rate; } if (cfg_parms->peak_rate < cfg_parms->committed_rate) { nvlist_free(nvlp); tswtcl0dbg(("tswtcl_create_action: invalid config, "\ " peak rate < committed rate\n")); kmem_free(cfg_parms, TSWTCL_CFG_SZ); return (EINVAL); } /* parse window - in msec */ if ((err = nvlist_lookup_uint32(nvlp, TSWTCL_WINDOW, &cfg_parms->window)) != 0) { cfg_parms->nsecwindow = (uint64_t)cfg_parms->window * METER_MSEC_TO_NSEC; } /* parse stats, if present */ if (nvlist_lookup_uint32(nvlp, IPP_ACTION_STATS_ENABLE, &bstats) == 0) { cfg_parms->stats = (boolean_t)bstats; if (cfg_parms->stats && !old_cfg->stats) { if ((err = tswtcl_statinit(aid, tswtcl_data)) != 0) { nvlist_free(nvlp); kmem_free(cfg_parms, TSWTCL_CFG_SZ); return (err); } } else if (!cfg_parms->stats && old_cfg->stats) { ipp_stat_destroy(tswtcl_data->stats); } } /* Can we ref all the new actions? */ if ((err = ipp_action_ref(aid, cfg_parms->red_action, flags)) != 0) { tswtcl0dbg(("tswtcl_modify_data: can't ref. red action\n")); nvlist_free(nvlp); kmem_free(cfg_parms, TSWTCL_CFG_SZ); return (err); } if ((err = ipp_action_ref(aid, cfg_parms->yellow_action, flags)) != 0) { tswtcl0dbg(("tswtcl_modify_data:can't ref. yellow action\n")); nvlist_free(nvlp); err2 = ipp_action_unref(aid, cfg_parms->red_action, flags); ASSERT(err2 == 0); kmem_free(cfg_parms, TSWTCL_CFG_SZ); return (err); } if ((err = ipp_action_ref(aid, cfg_parms->green_action, flags)) != 0) { tswtcl0dbg(("tswtcl_modify_data:can't ref. green action\n")); nvlist_free(nvlp); err2 = ipp_action_unref(aid, cfg_parms->red_action, flags); ASSERT(err2 == 0); err2 = ipp_action_unref(aid, cfg_parms->yellow_action, flags); ASSERT(err2 == 0); kmem_free(cfg_parms, TSWTCL_CFG_SZ); return (err); } /* Re-compute pminusc */ cfg_parms->pminusc = cfg_parms->peak_rate - cfg_parms->committed_rate; /* Actually modify the configuration */ mutex_enter(&tswtcl_data->tswtcl_lock); tswtcl_data->cfg_parms = cfg_parms; mutex_exit(&tswtcl_data->tswtcl_lock); /* Un-ref the old actions */ err = ipp_action_unref(aid, old_cfg->red_action, flags); ASSERT(err == 0); err = ipp_action_unref(aid, old_cfg->yellow_action, flags); ASSERT(err == 0); err = ipp_action_unref(aid, old_cfg->green_action, flags); ASSERT(err == 0); /* Free the old configuration */ kmem_free(old_cfg, TSWTCL_CFG_SZ); nvlist_free(nvlp); return (0); }
/* ARGSUSED */ static int tswtcl_create_action(ipp_action_id_t aid, nvlist_t **nvlpp, ipp_flags_t flags) { nvlist_t *nvlp; tswtcl_data_t *tswtcl_data; tswtcl_cfg_t *cfg_parms; char *next_action; uint32_t bstats; int rc, rc2; nvlp = *nvlpp; *nvlpp = NULL; /* nvlist should be NULL on return */ if ((cfg_parms = kmem_alloc(TSWTCL_CFG_SZ, KM_NOSLEEP)) == NULL) { nvlist_free(nvlp); return (ENOMEM); } /* parse red next action name */ if ((rc = nvlist_lookup_string(nvlp, TSWTCL_RED_ACTION_NAME, &next_action)) != 0) { nvlist_free(nvlp); tswtcl0dbg(("tswtcl_create_action:invalid config, red action" \ " name missing\n")); kmem_free(cfg_parms, TSWTCL_CFG_SZ); return (rc); } if ((cfg_parms->red_action = ipp_action_lookup(next_action)) == IPP_ACTION_INVAL) { nvlist_free(nvlp); tswtcl0dbg(("tswtcl_create_action: red action invalid\n")); kmem_free(cfg_parms, TSWTCL_CFG_SZ); return (EINVAL); } /* parse yellow next action name */ if ((rc = nvlist_lookup_string(nvlp, TSWTCL_YELLOW_ACTION_NAME, &next_action)) != 0) { nvlist_free(nvlp); tswtcl0dbg(("tswtcl_create_action:invalid config, yellow " \ "action name missing\n")); kmem_free(cfg_parms, TSWTCL_CFG_SZ); return (rc); } if ((cfg_parms->yellow_action = ipp_action_lookup(next_action)) == IPP_ACTION_INVAL) { nvlist_free(nvlp); tswtcl0dbg(("tswtcl_create_action: yellow action invalid\n")); kmem_free(cfg_parms, TSWTCL_CFG_SZ); return (EINVAL); } /* parse green next action name */ if ((rc = nvlist_lookup_string(nvlp, TSWTCL_GREEN_ACTION_NAME, &next_action)) != 0) { nvlist_free(nvlp); tswtcl0dbg(("tswtcl_create_action:invalid config, green " \ "action name missing\n")); kmem_free(cfg_parms, TSWTCL_CFG_SZ); return (rc); } if ((cfg_parms->green_action = ipp_action_lookup(next_action)) == IPP_ACTION_INVAL) { nvlist_free(nvlp); tswtcl0dbg(("tswtcl_create_action: green action invalid\n")); kmem_free(cfg_parms, TSWTCL_CFG_SZ); return (EINVAL); } /* parse committed rate - in bits / sec */ if ((rc = nvlist_lookup_uint32(nvlp, TSWTCL_COMMITTED_RATE, &cfg_parms->committed_rate)) != 0) { nvlist_free(nvlp); tswtcl0dbg(("tswtcl_create_action: invalid config, "\ " committed rate missing\n")); kmem_free(cfg_parms, TSWTCL_CFG_SZ); return (rc); } /* parse peak rate - in bits / sec */ if ((rc = nvlist_lookup_uint32(nvlp, TSWTCL_PEAK_RATE, &cfg_parms->peak_rate)) != 0) { nvlist_free(nvlp); tswtcl0dbg(("tswtcl_create_action: invalid config, "\ " peak rate missing\n")); kmem_free(cfg_parms, TSWTCL_CFG_SZ); return (rc); } if (cfg_parms->peak_rate < cfg_parms->committed_rate) { nvlist_free(nvlp); tswtcl0dbg(("tswtcl_create_action: invalid config, "\ " peak rate < committed rate\n")); kmem_free(cfg_parms, TSWTCL_CFG_SZ); return (EINVAL); } /* parse window - in msec */ if ((rc = nvlist_lookup_uint32(nvlp, TSWTCL_WINDOW, &cfg_parms->window)) != 0) { nvlist_free(nvlp); tswtcl0dbg(("tswtcl_create_action: invalid config, "\ " window missing\n")); kmem_free(cfg_parms, TSWTCL_CFG_SZ); return (rc); } /* convert to nsec */ cfg_parms->nsecwindow = (uint64_t)cfg_parms->window * METER_MSEC_TO_NSEC; /* parse stats */ if ((rc = nvlist_lookup_uint32(nvlp, IPP_ACTION_STATS_ENABLE, &bstats)) != 0) { cfg_parms->stats = B_FALSE; } else { cfg_parms->stats = (boolean_t)bstats; } nvlist_free(nvlp); /* Initialize other stuff */ tswtcl_data = kmem_zalloc(TSWTCL_DATA_SZ, KM_NOSLEEP); if (tswtcl_data == NULL) { kmem_free(cfg_parms, TSWTCL_CFG_SZ); return (ENOMEM); } if (cfg_parms->stats) { if ((rc = tswtcl_statinit(aid, tswtcl_data)) != 0) { kmem_free(cfg_parms, TSWTCL_CFG_SZ); kmem_free(tswtcl_data, TSWTCL_DATA_SZ); return (rc); } } /* set action chain reference */ if ((rc = ipp_action_ref(aid, cfg_parms->red_action, flags)) != 0) { tswtcl0dbg(("tswtcl_create_action: ipp_action_ref " \ "returned with error %d", rc)); goto cleanup; } if ((rc = ipp_action_ref(aid, cfg_parms->yellow_action, flags)) != 0) { tswtcl0dbg(("tswtcl_create_action: ipp_action_ref " \ "returned with error %d", rc)); rc2 = ipp_action_unref(aid, cfg_parms->red_action, flags); ASSERT(rc2 == 0); goto cleanup; } if ((rc = ipp_action_ref(aid, cfg_parms->green_action, flags)) != 0) { tswtcl0dbg(("tswtcl_create_action: ipp_action_ref " \ "returned with error %d", rc)); rc2 = ipp_action_unref(aid, cfg_parms->red_action, flags); ASSERT(rc2 == 0); rc2 = ipp_action_unref(aid, cfg_parms->yellow_action, flags); ASSERT(rc2 == 0); goto cleanup; } /* Initializations */ cfg_parms->pminusc = cfg_parms->peak_rate - cfg_parms->committed_rate; tswtcl_data->cfg_parms = cfg_parms; tswtcl_data->avg_rate = cfg_parms->committed_rate; mutex_init(&tswtcl_data->tswtcl_lock, NULL, MUTEX_DEFAULT, 0); tswtcl_data->win_front = gethrtime(); ipp_action_set_ptr(aid, (void *)tswtcl_data); return (0); cleanup: if (cfg_parms->stats) { ipp_stat_destroy(tswtcl_data->stats); } kmem_free(cfg_parms, TSWTCL_CFG_SZ); kmem_free(tswtcl_data, TSWTCL_DATA_SZ); return (rc); }
static int tokenmt_modify_action(ipp_action_id_t aid, nvlist_t **nvlpp, ipp_flags_t flags) { nvlist_t *nvlp; int err = 0, err2; uint8_t config_type; char *next_action_name; ipp_action_id_t next_action; uint32_t rate, cbs, pbs; tokenmt_cfg_t *cfg_parms, *old_cfg; tokenmt_data_t *tokenmt_data; uint32_t bstats, mode; int32_t *colour_tbl; uint_t nelem = 64; nvlp = *nvlpp; *nvlpp = NULL; /* nvlist should be NULL when this returns */ if ((err = nvlist_lookup_byte(nvlp, IPP_CONFIG_TYPE, &config_type)) != 0) { nvlist_free(nvlp); tokenmt0dbg(("tokenmt_modify_action: invalid configuration "\ "type")); return (err); } if (config_type != IPP_SET) { nvlist_free(nvlp); tokenmt0dbg(("tokenmt_modify_action: invalid configuration "\ "type %d", config_type)); return (EINVAL); } tokenmt_data = (tokenmt_data_t *)ipp_action_get_ptr(aid); old_cfg = tokenmt_data->cfg_parms; cfg_parms = kmem_zalloc(TOKENMT_CFG_SZ, KM_NOSLEEP); if (cfg_parms == NULL) { nvlist_free(nvlp); tokenmt0dbg(("tokenmt_modify_action: memory allocation "\ "failure\n")); return (ENOMEM); } /* Just copy all and change as needed */ bcopy(old_cfg, cfg_parms, TOKENMT_CFG_SZ); /* parse red action name, if present */ if ((err = nvlist_lookup_string(nvlp, TOKENMT_RED_ACTION_NAME, &next_action_name)) == 0) { /* Get action id */ if ((next_action = ipp_action_lookup(next_action_name)) == IPP_ACTION_INVAL) { nvlist_free(nvlp); tokenmt0dbg(("tokenmt_modify_action: next_action "\ "invalid")); kmem_free(cfg_parms, TOKENMT_CFG_SZ); return (EINVAL); } cfg_parms->red_action = next_action; } /* parse yellow action name, if present */ if ((err = nvlist_lookup_string(nvlp, TOKENMT_YELLOW_ACTION_NAME, &next_action_name)) == 0) { /* Get action id */ if ((next_action = ipp_action_lookup(next_action_name)) == IPP_ACTION_INVAL) { nvlist_free(nvlp); tokenmt0dbg(("tokenmt_modify_action: next_action "\ "invalid")); kmem_free(cfg_parms, TOKENMT_CFG_SZ); return (EINVAL); } cfg_parms->yellow_action = next_action; } else { cfg_parms->yellow_action = TOKENMT_NO_ACTION; } /* parse green action name, if present */ if ((err = nvlist_lookup_string(nvlp, TOKENMT_GREEN_ACTION_NAME, &next_action_name)) == 0) { /* Get action id */ if ((next_action = ipp_action_lookup(next_action_name)) == IPP_ACTION_INVAL) { nvlist_free(nvlp); tokenmt0dbg(("tokenmt_modify_action: next_action "\ "invalid")); kmem_free(cfg_parms, TOKENMT_CFG_SZ); return (EINVAL); } cfg_parms->green_action = next_action; } /* parse committed rate, if present */ if ((err = nvlist_lookup_uint32(nvlp, TOKENMT_COMMITTED_RATE, &rate)) == 0) { if (rate == 0) { nvlist_free(nvlp); tokenmt0dbg(("tokenmt_modify_action: invalid "\ "committed rate %u\n", cfg_parms->committed_rate)); kmem_free(cfg_parms, TOKENMT_CFG_SZ); return (EINVAL); } cfg_parms->committed_rate = rate; } /* parse committed burst, if present */ if (nvlist_lookup_uint32(nvlp, TOKENMT_COMMITTED_BURST, &cbs) == 0) { cfg_parms->committed_burst = cbs; } if (nvlist_lookup_uint32(nvlp, TOKENMT_PEAK_BURST, &pbs) == 0) { cfg_parms->peak_burst = pbs; } else { cfg_parms->peak_burst = 0; } /* If the peak rate is not specified, then it means single rate meter */ if (nvlist_lookup_uint32(nvlp, TOKENMT_PEAK_RATE, &rate) == 0) { cfg_parms->peak_rate = rate; if ((rate == 0) || (rate < cfg_parms->committed_rate)) { nvlist_free(nvlp); tokenmt0dbg(("tokenmt_modify_action: invalid "\ "committed rate %u\n", cfg_parms->committed_rate)); kmem_free(cfg_parms, TOKENMT_CFG_SZ); return (EINVAL); } cfg_parms->tokenmt_type = TRTCL_TOKENMT; } else { cfg_parms->peak_rate = 0; cfg_parms->tokenmt_type = SRTCL_TOKENMT; } if (cfg_parms->yellow_action == TOKENMT_NO_ACTION) { if ((cfg_parms->peak_burst != 0) || (cfg_parms->tokenmt_type == TRTCL_TOKENMT)) { nvlist_free(nvlp); tokenmt0dbg(("tokenmt_modify_action: yellow action "\ "missing\n")); kmem_free(cfg_parms, TOKENMT_CFG_SZ); return (EINVAL); } } else { if ((cfg_parms->tokenmt_type != TRTCL_TOKENMT) && (cfg_parms->peak_burst == 0)) { nvlist_free(nvlp); tokenmt0dbg(("tokenmt_modify_action: peak "\ "burst/rate missing\n")); kmem_free(cfg_parms, TOKENMT_CFG_SZ); return (EINVAL); } } /* Validate the committed and peak burst size */ if (cfg_parms->tokenmt_type == SRTCL_TOKENMT) { if ((cfg_parms->committed_burst == 0) && (cfg_parms->peak_burst == 0)) { nvlist_free(nvlp); tokenmt0dbg(("tokenmt_modify_action: at least one "\ "burst size must be non-zero\n")); kmem_free(cfg_parms, TOKENMT_CFG_SZ); return (EINVAL); } } else { /* TRTCL_TOKENMT */ if ((cfg_parms->committed_burst == 0) || (cfg_parms->peak_burst == 0)) { nvlist_free(nvlp); tokenmt0dbg(("tokenmt_modify_action: both the "\ "burst sizes must be non-zero\n")); kmem_free(cfg_parms, TOKENMT_CFG_SZ); return (EINVAL); } } /* parse mode */ if (nvlist_lookup_uint32(nvlp, TOKENMT_COLOUR_AWARE, &mode) == 0) { cfg_parms->colour_aware = (mode == 0) ? B_FALSE : B_TRUE; } else { cfg_parms->colour_aware = B_FALSE; } if (cfg_parms->colour_aware) { if (nvlist_lookup_int32_array(nvlp, TOKENMT_COLOUR_MAP, &colour_tbl, &nelem) == 0) { int count; for (count = 0; count < 64; count++) { if (colour_tbl[count] == -1) continue; cfg_parms->dscp_to_colour[count] = colour_tbl[count]; } } else { bcopy(default_dscp_to_colour, cfg_parms->dscp_to_colour, sizeof (default_dscp_to_colour)); } } /* parse stats, if present */ if (nvlist_lookup_uint32(nvlp, IPP_ACTION_STATS_ENABLE, &bstats) == 0) { cfg_parms->stats = (bstats == 0) ? B_FALSE : B_TRUE; if (cfg_parms->stats && !old_cfg->stats) { if ((err = tokenmt_statinit(aid, tokenmt_data)) != 0) { nvlist_free(nvlp); kmem_free(cfg_parms, TOKENMT_CFG_SZ); return (err); } } else if (!cfg_parms->stats && old_cfg->stats) { ipp_stat_destroy(tokenmt_data->stats); } } /* Can we ref all the new actions? */ if ((err = ipp_action_ref(aid, cfg_parms->red_action, flags)) != 0) { tokenmt0dbg(("tokenmt_modify_data: can't ref. red action\n")); kmem_free(cfg_parms, TOKENMT_CFG_SZ); return (err); } if ((err = ipp_action_ref(aid, cfg_parms->green_action, flags)) != 0) { tokenmt0dbg(("tokenmt_modify_data:can't ref. green action\n")); err2 = ipp_action_unref(aid, cfg_parms->red_action, flags); ASSERT(err2 == 0); kmem_free(cfg_parms, TOKENMT_CFG_SZ); return (err); } if (cfg_parms->yellow_action != TOKENMT_NO_ACTION) { if ((err = ipp_action_ref(aid, cfg_parms->yellow_action, flags)) != 0) { tokenmt0dbg(("tokenmt_modify_data:can't ref. yellow "\ "action\n")); err2 = ipp_action_unref(aid, cfg_parms->red_action, flags); ASSERT(err2 == 0); err2 = ipp_action_unref(aid, cfg_parms->green_action, flags); ASSERT(err2 == 0); kmem_free(cfg_parms, TOKENMT_CFG_SZ); return (err); } } /* Actually modify the configuration */ mutex_enter(&tokenmt_data->tokenmt_lock); tokenmt_data->cfg_parms = cfg_parms; mutex_exit(&tokenmt_data->tokenmt_lock); /* Un-ref the old actions */ err = ipp_action_unref(aid, old_cfg->red_action, flags); ASSERT(err == 0); if (old_cfg->yellow_action != TOKENMT_NO_ACTION) { err = ipp_action_unref(aid, old_cfg->yellow_action, flags); ASSERT(err == 0); } err = ipp_action_unref(aid, old_cfg->green_action, flags); ASSERT(err == 0); /* Free the old configuration */ kmem_free(old_cfg, TOKENMT_CFG_SZ); return (0); }
/* ARGSUSED */ static int tokenmt_create_action(ipp_action_id_t aid, nvlist_t **nvlpp, ipp_flags_t flags) { nvlist_t *nvlp; tokenmt_data_t *tokenmt_data; char *next_action; tokenmt_cfg_t *cfg_parms; uint32_t mode; uint32_t bstats; int rc, rc2; int32_t *colour_tbl; uint_t nelem = 64; nvlp = *nvlpp; *nvlpp = NULL; /* nvlist should be NULL on return */ if ((cfg_parms = kmem_zalloc(TOKENMT_CFG_SZ, KM_NOSLEEP)) == NULL) { nvlist_free(nvlp); return (ENOMEM); } /* parse red next action name */ if ((rc = nvlist_lookup_string(nvlp, TOKENMT_RED_ACTION_NAME, &next_action)) != 0) { nvlist_free(nvlp); tokenmt0dbg(("tokenmt_create_action:invalid config, red "\ "action name missing\n")); kmem_free(cfg_parms, TOKENMT_CFG_SZ); return (rc); } if ((cfg_parms->red_action = ipp_action_lookup(next_action)) == IPP_ACTION_INVAL) { nvlist_free(nvlp); tokenmt0dbg(("tokenmt_create_action: red action invalid\n")); kmem_free(cfg_parms, TOKENMT_CFG_SZ); return (EINVAL); } /* parse yellow next action name, if present this is Two Rate meter */ if ((rc = nvlist_lookup_string(nvlp, TOKENMT_YELLOW_ACTION_NAME, &next_action)) == 0) { if ((cfg_parms->yellow_action = ipp_action_lookup(next_action)) == IPP_ACTION_INVAL) { nvlist_free(nvlp); tokenmt0dbg(("tokenmt_create_action: yellow action "\ "invalid\n")); kmem_free(cfg_parms, TOKENMT_CFG_SZ); return (EINVAL); } } else { cfg_parms->yellow_action = TOKENMT_NO_ACTION; } /* parse green next action name */ if ((rc = nvlist_lookup_string(nvlp, TOKENMT_GREEN_ACTION_NAME, &next_action)) != 0) { nvlist_free(nvlp); tokenmt0dbg(("tokenmt_create_action:invalid config, green " \ "action name missing\n")); kmem_free(cfg_parms, TOKENMT_CFG_SZ); return (rc); } if ((cfg_parms->green_action = ipp_action_lookup(next_action)) == IPP_ACTION_INVAL) { nvlist_free(nvlp); tokenmt0dbg(("tokenmt_create_action: green action invalid\n")); kmem_free(cfg_parms, TOKENMT_CFG_SZ); return (EINVAL); } /* parse committed rate - in kilo bits / sec */ if ((rc = nvlist_lookup_uint32(nvlp, TOKENMT_COMMITTED_RATE, &cfg_parms->committed_rate)) != 0) { nvlist_free(nvlp); tokenmt0dbg(("tokenmt_create_action: invalid config, "\ " committed rate missing\n")); kmem_free(cfg_parms, TOKENMT_CFG_SZ); return (rc); } if (cfg_parms->committed_rate == 0) { nvlist_free(nvlp); tokenmt0dbg(("tokenmt_create_action: invalid committed rate, "\ "%u\n", cfg_parms->committed_rate)); kmem_free(cfg_parms, TOKENMT_CFG_SZ); return (EINVAL); } /* parse committed burst in bits */ if ((rc = nvlist_lookup_uint32(nvlp, TOKENMT_COMMITTED_BURST, &cfg_parms->committed_burst)) != 0) { nvlist_free(nvlp); tokenmt0dbg(("tokenmt_create_action: invalid config, "\ " committed burst missing\n")); kmem_free(cfg_parms, TOKENMT_CFG_SZ); return (rc); } /* * If the peak burst size is specified, make sure we have the * yellow action. */ if ((rc = nvlist_lookup_uint32(nvlp, TOKENMT_PEAK_BURST, &cfg_parms->peak_burst)) == 0) { if (cfg_parms->yellow_action == TOKENMT_NO_ACTION) { nvlist_free(nvlp); tokenmt0dbg(("tokenmt_create_action: peak burst "\ "specified without yellow action\n")); kmem_free(cfg_parms, TOKENMT_CFG_SZ); return (EINVAL); } } else if (cfg_parms->yellow_action != TOKENMT_NO_ACTION) { nvlist_free(nvlp); tokenmt0dbg(("tokenmt_create_action: peak burst must be "\ "provided with yellow action\n")); kmem_free(cfg_parms, TOKENMT_CFG_SZ); return (EINVAL); } /* Check if we have a peak_rate */ if ((rc = nvlist_lookup_uint32(nvlp, TOKENMT_PEAK_RATE, &cfg_parms->peak_rate)) == 0) { if (cfg_parms->yellow_action == TOKENMT_NO_ACTION) { nvlist_free(nvlp); tokenmt0dbg(("tokenmt_create_action: peak rate "\ "specified without yellow action\n")); kmem_free(cfg_parms, TOKENMT_CFG_SZ); return (EINVAL); } else if ((cfg_parms->peak_rate == 0) || (cfg_parms->peak_rate < cfg_parms->committed_rate)) { nvlist_free(nvlp); tokenmt0dbg(("tokenmt_create_action: invalid "\ "peak rate, %u\n", cfg_parms->peak_rate)); kmem_free(cfg_parms, TOKENMT_CFG_SZ); return (EINVAL); } cfg_parms->tokenmt_type = TRTCL_TOKENMT; } else { cfg_parms->tokenmt_type = SRTCL_TOKENMT; } /* Validate the committed and peak burst size */ if (cfg_parms->tokenmt_type == SRTCL_TOKENMT) { if ((cfg_parms->committed_burst == 0) && (cfg_parms->peak_burst == 0)) { nvlist_free(nvlp); tokenmt0dbg(("tokenmt_create_action: at least one "\ "burst size must be non-zero\n")); kmem_free(cfg_parms, TOKENMT_CFG_SZ); return (EINVAL); } } else { /* TRTCL_TOKENMT */ if ((cfg_parms->committed_burst == 0) || (cfg_parms->peak_burst == 0)) { nvlist_free(nvlp); tokenmt0dbg(("tokenmt_create_action: both the "\ "burst sizes must be non-zero\n")); kmem_free(cfg_parms, TOKENMT_CFG_SZ); return (EINVAL); } } /* just copy default colour mapping */ bcopy(default_dscp_to_colour, cfg_parms->dscp_to_colour, sizeof (default_dscp_to_colour)); /* parse mode, if present */ if ((rc = nvlist_lookup_uint32(nvlp, TOKENMT_COLOUR_AWARE, &mode)) != 0) { cfg_parms->colour_aware = B_FALSE; } else { cfg_parms->colour_aware = (mode == 0) ? B_FALSE : B_TRUE; } /* Get the dscp to colour mapping array */ if (cfg_parms->colour_aware) { if ((rc = nvlist_lookup_int32_array(nvlp, TOKENMT_COLOUR_MAP, &colour_tbl, &nelem)) == 0) { int count; for (count = 0; count < 64; count++) { if (colour_tbl[count] == -1) continue; cfg_parms->dscp_to_colour[count] = colour_tbl[count]; } } } /* parse stats */ if ((rc = nvlist_lookup_uint32(nvlp, IPP_ACTION_STATS_ENABLE, &bstats)) != 0) { cfg_parms->stats = B_FALSE; } else { cfg_parms->stats = (bstats == 0) ? B_FALSE : B_TRUE; } nvlist_free(nvlp); /* Initialize other stuff */ tokenmt_data = kmem_zalloc(TOKENMT_DATA_SZ, KM_NOSLEEP); if (tokenmt_data == NULL) { kmem_free(cfg_parms, TOKENMT_CFG_SZ); return (ENOMEM); } /* Initialize stats, if required */ if (cfg_parms->stats) { if ((rc = tokenmt_statinit(aid, tokenmt_data)) != 0) { kmem_free(cfg_parms, TOKENMT_CFG_SZ); kmem_free(tokenmt_data, TOKENMT_DATA_SZ); return (rc); } } /* set action chain reference */ if ((rc = ipp_action_ref(aid, cfg_parms->red_action, flags)) != 0) { tokenmt0dbg(("tokenmt_create_action: ipp_action_ref " \ "returned with error %d", rc)); goto cleanup; } if ((rc = ipp_action_ref(aid, cfg_parms->green_action, flags)) != 0) { tokenmt0dbg(("tokenmt_create_action: ipp_action_ref " \ "returned with error %d", rc)); rc2 = ipp_action_unref(aid, cfg_parms->red_action, flags); ASSERT(rc2 == 0); goto cleanup; } if (cfg_parms->yellow_action != TOKENMT_NO_ACTION) { if ((rc = ipp_action_ref(aid, cfg_parms->yellow_action, flags)) != 0) { tokenmt0dbg(("tokenmt_create_action: ipp_action_ref "\ "returned with error %d", rc)); rc2 = ipp_action_unref(aid, cfg_parms->red_action, flags); ASSERT(rc2 == 0); rc2 = ipp_action_unref(aid, cfg_parms->green_action, flags); ASSERT(rc2 == 0); goto cleanup; } } tokenmt_data->cfg_parms = cfg_parms; tokenmt_data->committed_tokens = cfg_parms->committed_burst; tokenmt_data->peak_tokens = cfg_parms->peak_burst; tokenmt_data->last_seen = gethrtime(); mutex_init(&tokenmt_data->tokenmt_lock, NULL, MUTEX_DEFAULT, 0); ipp_action_set_ptr(aid, (void *)tokenmt_data); return (0); cleanup: if (cfg_parms->stats) { ipp_stat_destroy(tokenmt_data->stats); } kmem_free(cfg_parms, TOKENMT_CFG_SZ); kmem_free(tokenmt_data, TOKENMT_DATA_SZ); return (rc); }