Example #1
0
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);
}
Example #2
0
/**
 * 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);
}
Example #3
0
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;
	}
}
Example #4
0
/**
 * 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);
}
Example #5
0
/**
 * 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;     
}
Example #6
0
/**
 * 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_direct(pl_pipe_t *pipe)
{
	int ret;

	pipe->counter++;

	switch (pipe->algo) {
		case PIPE_ALGO_NOP:
			LM_ERR("no algorithm defined for pipe %.*s\n",
					pipe->name.len, pipe->name.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",
		pipe->name.len, pipe->name.s,
		pipe->algo, pipe->limit,
		pipe->load, pipe->counter,
		*load_value, *network_load_value, (ret == 1) ? "ACCEPT" : "DROP");

	pl_pipe_release(&pipe->name);

	return ret;     
}
Example #7
0
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);
	}
}