/** * limit checking with creation of pipe if it doesn't exist */ static int pl_check_limit(sip_msg_t* msg, str *pipeid, str *alg, int limit) { pl_pipe_t *pipe = NULL; pipe = pl_pipe_get(pipeid, 1); if(pipe==NULL) { LM_DBG("pipe not found [%.*s] - trying to add it\n", pipeid->len, pipeid->s); if(pl_pipe_add(pipeid, alg, limit)<0) { LM_ERR("failed to add pipe [%.*s]\n", pipeid->len, pipeid->s); return -2; } pipe = pl_pipe_get(pipeid, 0); if(pipe==NULL) { LM_ERR("failed to retrieve pipe [%.*s]\n", pipeid->len, pipeid->s); return -2; } } else { if(limit>0) pipe->limit = limit; pl_pipe_release(&pipe->name); } return pl_check(msg, pipeid); }
/** * limit checking with creation of pipe if it doesn't exist */ static int w_pl_check3(struct sip_msg* msg, char *p1pipe, char *p2alg, char *p3limit) { int limit; str pipeid = {0, 0}; str alg = {0, 0}; pl_pipe_t *pipe = NULL; if(msg==NULL) return -1; if(fixup_get_ivalue(msg, (gparam_t*)p3limit, &limit)!=0 || limit<0) { LM_ERR("invalid limit value: %d\n", limit); return -1; } if(fixup_get_svalue(msg, (gparam_t*)p1pipe, &pipeid)!=0 || pipeid.s == 0) { LM_ERR("invalid pipeid parameter"); return -1; } if(fixup_get_svalue(msg, (gparam_t*)p2alg, &alg)!=0 || alg.s == 0) { LM_ERR("invalid algoritm parameter"); return -1; } pipe = pl_pipe_get(&pipeid, 1); if(pipe==NULL) { LM_DBG("pipe not found [%.*s] - trying to add it\n", pipeid.len, pipeid.s); if(pl_pipe_add(&pipeid, &alg, limit)<0) { LM_ERR("failed to add pipe [%.*s]\n", pipeid.len, pipeid.s); return -2; } pipe = pl_pipe_get(&pipeid, 0); if(pipe==NULL) { LM_ERR("failed to retrieve pipe [%.*s]\n", pipeid.len, pipeid.s); return -2; } } else { if(limit>0) pipe->limit = limit; pl_pipe_release(&pipe->name); } return pl_check(msg, &pipeid); }
void rpc_pl_set_pipe(rpc_t *rpc, void *c) { unsigned int algo_id, limit = 0; pl_pipe_t *it; str pipeid, algo_str; if (rpc->scan(c, "SSd", &pipeid, &algo_str, &limit) < 3) return; if (str_map_str(algo_names, &algo_str, (int*)&algo_id)) { LM_ERR("unknown algorithm: '%.*s'\n", algo_str.len, algo_str.s); rpc->fault(c, 400, "Unknown algorithm"); return; } LM_DBG("set_pipe: %.*s:%d:%d\n", pipeid.len, pipeid.s, algo_id, limit); it = pl_pipe_get(&pipeid, 1); if (it==NULL) { LM_ERR("no pipe: %.*s\n", pipeid.len, pipeid.s); rpc->fault(c, 400, "Unknown pipe id %.*s", pipeid.len, pipeid.s); return; } it->algo = algo_id; it->limit = limit; pl_pipe_release(&pipeid); if (check_feedback_setpoints(0)) { LM_ERR("feedback limits don't match\n"); rpc->fault(c, 400, "Feedback limits don't match"); return; } else { *_pl_pid_setpoint = 0.01 * (double)_pl_cfg_setpoint; } }
static int pipe_push(struct sip_msg * msg, str *pipeid) { pl_pipe_t *pipe = NULL; pipe = pl_pipe_get(pipeid, 1); if(pipe==NULL) { LM_ERR("pipe not found [%.*s]\n", pipeid->len, pipeid->s); return -2; } return pipe_push_direct(pipe); }
struct mi_root* mi_set_pipe(struct mi_root* cmd_tree, void* param) { struct mi_node *node; unsigned int algo_id, limit = 0; pl_pipe_t *it; str pipeid; node = cmd_tree->node.kids; if (node == NULL) return init_mi_tree( 400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN); if ( !node->value.s || !node->value.len) goto error; pipeid = node->value; node = node->next; if ( !node->value.s || !node->value.len) goto error; if (str_map_str(algo_names, &(node->value), (int*)&algo_id)) { LM_ERR("unknown algorithm: '%.*s'\n", node->value.len, node->value.s); goto error; } node = node->next; if ( !node->value.s || !node->value.len || strno2int(&node->value,&limit)<0) goto error; LM_DBG("set_pipe: %.*s:%d:%d\n", pipeid.len, pipeid.s, algo_id, limit); it = pl_pipe_get(&pipeid, 1); if (it==NULL) { LM_ERR("no pipe: %.*s\n", pipeid.len, pipeid.s); goto error; } it->algo = algo_id; it->limit = limit; if (check_feedback_setpoints(0)) { pl_pipe_release(&pipeid); LM_ERR("feedback limits don't match\n"); goto error; } else { *_pl_pid_setpoint = 0.01 * (double)_pl_cfg_setpoint; } pl_pipe_release(&pipeid); return init_mi_tree( 200, MI_OK_S, MI_OK_LEN); error: return init_mi_tree( 400, MI_BAD_PARM_S, MI_BAD_PARM_LEN); }
/** * runs the pipe's algorithm * (expects pl_lock to be taken), TODO revert to "return" instead of "ret =" * \return -1 if drop needed, 1 if allowed */ static int pipe_push(struct sip_msg * msg, str *pipeid) { int ret; pl_pipe_t *pipe = NULL; pipe = pl_pipe_get(pipeid, 1); if(pipe==NULL) { LM_ERR("pipe not found [%.*s]\n", pipeid->len, pipeid->s); return -2; } pipe->counter++; switch (pipe->algo) { case PIPE_ALGO_NOP: LM_ERR("no algorithm defined for pipe %.*s\n", pipeid->len, pipeid->s); ret = 2; break; case PIPE_ALGO_TAILDROP: ret = (pipe->counter <= pipe->limit * timer_interval) ? 1 : -1; break; case PIPE_ALGO_RED: if (pipe->load == 0) ret = 1; else ret = (! (pipe->counter % pipe->load)) ? 1 : -1; break; case PIPE_ALGO_FEEDBACK: ret = (hash[pipe->counter % 100] < *drop_rate) ? -1 : 1; break; case PIPE_ALGO_NETWORK: ret = -1 * pipe->load; break; default: LM_ERR("unknown ratelimit algorithm: %d\n", pipe->algo); ret = 1; } LM_DBG("pipe=%.*s algo=%d limit=%d pkg_load=%d counter=%d " "load=%2.1lf network_load=%d => %s\n", pipeid->len, pipeid->s, pipe->algo, pipe->limit, pipe->load, pipe->counter, *load_value, *network_load_value, (ret == 1) ? "ACCEPT" : "DROP"); pl_pipe_release(pipeid); return ret; }
void rpc_pl_list(rpc_t *rpc, void *c) { int i; pl_pipe_t *it; str pipeid = STR_NULL; if (rpc->scan(c, "*S", &pipeid) < 1) { pipeid.s = NULL; pipeid.len = 0; } if(pipeid.len>0) { it = pl_pipe_get(&pipeid, 1); if (it==NULL) { LM_ERR("no pipe: %.*s\n", pipeid.len, pipeid.s); rpc->fault(c, 400, "Unknown pipe id %.*s", pipeid.len, pipeid.s); return; } if(rpc_pl_list_pipe(rpc, c, it)<0) { LM_DBG("failed to list pipe: %.*s\n", it->name.len, it->name.s); } pl_pipe_release(&pipeid); return; } for(i=0; i<_pl_pipes_ht->htsize; i++) { lock_get(&_pl_pipes_ht->slots[i].lock); it = _pl_pipes_ht->slots[i].first; while(it) { if(rpc_pl_list_pipe(rpc, c, it)<0) { LM_DBG("failed to list pipe: %.*s\n", it->name.len, it->name.s); lock_release(&_pl_pipes_ht->slots[i].lock); return; } it = it->next; } lock_release(&_pl_pipes_ht->slots[i].lock); } }