Ejemplo n.º 1
0
int rl_get_counter_value(str *key)
{
	unsigned int hash_idx;
	rl_pipe_t **pipe;
	int ret = -1;

	hash_idx = RL_GET_INDEX(*key);
	RL_GET_LOCK(hash_idx);

	/* try to get the value */
	pipe = RL_FIND_PIPE(hash_idx, *key);
	if (!pipe || !*pipe) {
		LM_DBG("cannot find any pipe named %.*s\n", key->len, key->s);
		goto release;
	}

	if (RL_USE_CDB(*pipe)) {
		if (rl_get_counter(key, *pipe) < 0) {
			LM_ERR("cannot get the counter's value\n");
			goto release;
		}
	}
	ret = rl_get_all_counters(*pipe);

release:
	RL_RELEASE_LOCK(hash_idx);
	return ret;
}
Ejemplo n.º 2
0
/* NOTE: assumes that the pipe has been locked. If fails, releases the lock */
static int rl_get_counter(str *name, rl_pipe_t * pipe)
{
	str res;
	unsigned int hid = RL_GET_INDEX(*name);
	int new_counter;

	RL_SET_PENDING(pipe);
	RL_RELEASE_LOCK(hid);

	if (rl_set_name(name) < 0)
		return -1;
	if (cdbf.get(cdbc, &rl_name_buffer, &res) < 0) {
		LM_ERR("cannot retrieve key\n");
		return -1;
	}
	if (str2sint(&res, &new_counter) < 0) {
		LM_ERR("invalid value %.*s - should be integer\n", res.len, res.s);
		return -1;
	}
	if (res.s)
		pkg_free(res.s);
	RL_GET_LOCK(hid);
	RL_RESET_PENDING(pipe);
	pipe->counter = new_counter;
	return 0;
}
Ejemplo n.º 3
0
int rl_stats(struct mi_node *rpl, str * value)
{
	rl_pipe_t **pipe;
	int i;

	if (value && value->s && value->len) {
		i = RL_GET_INDEX(*value);
		RL_GET_LOCK(i);
		pipe = RL_FIND_PIPE(i, *value);
		if (!pipe || !*pipe) {
			LM_DBG("pipe %.*s not found\n", value->len, value->s);
			goto error;
		}
		if (rl_map_print(rpl, *value, *pipe)) {
			LM_ERR("cannot print value for key %.*s\n",
					value->len, value->s);
			goto error;
		}
		RL_RELEASE_LOCK(i);
	} else {
		/* iterate through each map */
		for (i = 0; i < rl_htable.size; i++) {
			RL_GET_LOCK(i);
			if (map_for_each(rl_htable.maps[i], rl_map_print, rpl)) {
				LM_ERR("cannot print values\n");
				goto error;
			}
			RL_RELEASE_LOCK(i);
		}
	}
	return 0;
error:
	RL_RELEASE_LOCK(i);
	return -1;
}
Ejemplo n.º 4
0
int rl_stats(mi_item_t *resp_obj, str * value)
{
	mi_item_t *pipe_item, *pipe_arr;
	rl_pipe_t **pipe;
	int i;

	if (value && value->s && value->len) {
		i = RL_GET_INDEX(*value);
		RL_GET_LOCK(i);
		pipe = RL_FIND_PIPE(i, *value);
		if (!pipe || !*pipe) {
			LM_DBG("pipe %.*s not found\n", value->len, value->s);
			goto error;
		}
		pipe_item = add_mi_object(resp_obj, MI_SSTR("Pipe"));
		if (!pipe_item)
			goto error;
		if (rl_map_print(pipe_item, *value, *pipe)) {
			LM_ERR("cannot print value for key %.*s\n",
				value->len, value->s);
			goto error;
		}
		RL_RELEASE_LOCK(i);
	} else {
		/* iterate through each map */
		pipe_arr = add_mi_array(resp_obj, MI_SSTR("Pipes"));
		if (!pipe_arr)
			return -1;
		for (i = 0; i < rl_htable.size; i++) {
			pipe_item = add_mi_object(pipe_arr, NULL, 0);
			if (!pipe_item)
				return -1;
			RL_GET_LOCK(i);
			if (map_for_each(rl_htable.maps[i], rl_map_print, pipe_item)) {
				LM_ERR("cannot print values\n");
				goto error;
			}
			RL_RELEASE_LOCK(i);
		}
	}
	return 0;
error:
	RL_RELEASE_LOCK(i);
	return -1;
}
Ejemplo n.º 5
0
/* NOTE: assumes that the pipe has been locked. If fails, releases the lock */
static int rl_change_counter(str *name, rl_pipe_t *pipe, int c)
{
	unsigned int hid = RL_GET_INDEX(*name);
	int new_counter;

	RL_SET_PENDING(pipe);
	RL_RELEASE_LOCK(hid);
	if (rl_set_name(name) < 0)
		return -1;

	/* if the command should be reset */
	/* XXX: This is not needed since add takes also negative numbers 
	if (c > 0) {
		if (cdbf.add(cdbc, &rl_name_buffer, c, rl_expire_time, &new_counter)<0){
			LM_ERR("cannot increase buffer for pipe %.*s\n",
					name->len, name->s);
			return -1;
		}
	} else {
		if (cdbf.sub(cdbc, &rl_name_buffer, c ? c : pipe->my_counter,
					rl_expire_time, &new_counter) < 0){
			LM_ERR("cannot change counter for pipe %.*s with %d\n",
					name->len, name->s, c);
			return -1;
		}
	}
	*/
	if (cdbf.add(cdbc, &rl_name_buffer, c ? c : -(pipe->my_counter),
				rl_expire_time, &new_counter) < 0){
		LM_ERR("cannot change counter for pipe %.*s with %d\n",
				name->len, name->s, c);
		return -1;
	}

	RL_GET_LOCK(hid);
	RL_RESET_PENDING(pipe);
	pipe->my_counter = c ? pipe->my_counter + c : 0;
	pipe->counter = new_counter;
	LM_DBG("changed with %d; my_counter: %d; counter: %d\n",
			c, pipe->my_counter, new_counter);

	return 0;
}
Ejemplo n.º 6
0
int rl_stats(struct mi_root *rpl_tree, str * value)
{
	rl_pipe_t **pipe;
	struct rl_param_t param;
	int i;

	memset(&param, 0, sizeof(struct rl_param_t));
	param.node = &rpl_tree->node;
	param.root = rpl_tree;

	if (value && value->s && value->len) {
		i = RL_GET_INDEX(*value);
		RL_GET_LOCK(i);
		pipe = RL_FIND_PIPE(i, *value);
		if (!pipe || !*pipe) {
			LM_DBG("pipe %.*s not found\n", value->len, value->s);
			goto error;
		}
		if (rl_map_print(&param, *value, *pipe)) {
			LM_ERR("cannot print value for key %.*s\n",
					value->len, value->s);
			goto error;
		}
		RL_RELEASE_LOCK(i);
	} else {
		/* iterate through each map */
		for (i = 0; i < rl_htable.size; i++) {
			RL_GET_LOCK(i);
			if (map_for_each(rl_htable.maps[i], rl_map_print, &param)) {
				LM_ERR("cannot print values\n");
				goto error;
			}
			RL_RELEASE_LOCK(i);
		}
	}
	return 0;
error:
	RL_RELEASE_LOCK(i);
	return -1;
}
Ejemplo n.º 7
0
int w_rl_set_count(str key, int val)
{
	unsigned int hash_idx;
	int ret = -1;
	rl_pipe_t **pipe;

	hash_idx = RL_GET_INDEX(key);
	RL_GET_LOCK(hash_idx);

	/* try to get the value */
	pipe = RL_FIND_PIPE(hash_idx, key);
	if (!pipe || !*pipe) {
		LM_DBG("cannot find any pipe named %.*s\n", key.len, key.s);
		goto release;
	}

	if (RL_USE_CDB(*pipe)) {
		if (rl_change_counter(&key, *pipe, val) < 0) {
			LM_ERR("cannot decrease counter\n");
			goto release;
		}
	} else if ((*pipe)->algo == PIPE_ALGO_HISTORY) {
		hist_set_count(*pipe, val);
	} else {
		if (val && (val + (*pipe)->counter >= 0)) {
			(*pipe)->counter += val;
		} else {
			(*pipe)->counter = 0;
		}
	}

	LM_DBG("new counter for key %.*s is %d\n",
		key.len, key.s, (*pipe)->counter);

	ret = 0;

release:
	RL_RELEASE_LOCK(hash_idx);
	return ret;
}
Ejemplo n.º 8
0
void rl_rcv_bin(int packet_type, struct receive_info *ri)
{
	rl_algo_t algo;
	int limit;
	int counter;
	str name;
	int index;
	char *ip;
	unsigned short port;
	rl_pipe_t **pipe;
	unsigned int hash_idx;
	time_t now;

	if (packet_type != RL_PIPE_COUNTER)
		return;

	/* match the server */
	for (index = 0; index < rl_dests_nr; index++) {
		 if (su_cmp(&ri->src_su, &rl_dests[index].to))
			break;
	}

	if (index == rl_dests_nr) {
		get_su_info(&ri->src_su.s, ip, port);
		LM_WARN("received bin packet from unknown source: %s:%hu\n",
				ip, port);
		return;
	}
	now = time(0);
	*rl_dests[index].last_msg = now;

	for (;;) {
		if (bin_pop_str(&name) == 1)
			break; /* pop'ed all pipes */

		if (bin_pop_int(&algo) < 0) {
			LM_ERR("cannot pop pipe's algorithm\n");
			return;
		}

		if (bin_pop_int(&limit) < 0) {
			LM_ERR("cannot pop pipe's limit\n");
			return;
		}

		if (bin_pop_int(&counter) < 0) {
			LM_ERR("cannot pop pipe's counter\n");
			return;
		}

		hash_idx = RL_GET_INDEX(name);
		RL_GET_LOCK(hash_idx);

		/* try to get the value */
		pipe = RL_GET_PIPE(hash_idx, name);
		if (!pipe) {
			LM_ERR("cannot get the index\n");
			goto release;
		}

		if (!*pipe) {
			/* if the pipe does not exist, alocate it in case we need it later */
			*pipe = shm_malloc(sizeof(rl_pipe_t) +
					rl_dests_nr * sizeof(rl_repl_counter_t));
			if (!*pipe) {
				LM_ERR("no more shm memory\n");
				goto release;
			}
			memset(*pipe, 0, sizeof(rl_pipe_t) +
					rl_dests_nr * sizeof(rl_repl_counter_t));
			(*pipe)->dsts = (rl_repl_counter_t *)((*pipe) + 1);
			LM_DBG("Pipe %.*s doesn't exist, but was created %p\n",
					name.len, name.s, *pipe);
			(*pipe)->algo = algo;
			(*pipe)->limit = limit;
		} else {
			LM_DBG("Pipe %.*s found: %p - last used %lu\n",
					name.len, name.s, *pipe, (*pipe)->last_used);
			if ((*pipe)->algo != algo)
				LM_WARN("algorithm %d different from the initial one %d for "
						"pipe %.*s", algo, (*pipe)->algo, name.len, name.s);
			if ((*pipe)->limit != limit)
				LM_WARN("limit %d different from the initial one %d for "
						"pipe %.*s", limit, (*pipe)->limit, name.len, name.s);
		}
		/* set the last used time */
		(*pipe)->last_used = time(0);
		/* set the destination's counter */
		(*pipe)->dsts[index].counter = counter;
		(*pipe)->dsts[index].update = now;

		RL_RELEASE_LOCK(hash_idx);
	}
	return;

release:
	RL_RELEASE_LOCK(hash_idx);
}
Ejemplo n.º 9
0
int w_rl_check_3(struct sip_msg *_m, char *_n, char *_l, char *_a)
{
	str name;
	int limit = 0, ret = 1, should_update = 0;
	str algorithm;
	unsigned int hash_idx;
	rl_pipe_t **pipe;

	rl_algo_t algo = -1;

	/* retrieve and check parameters */
	if (!_n || !_l) {
		LM_ERR("invalid parameters\n");
		goto end;
	}
	if (fixup_get_svalue(_m, (gparam_p)_n, &name) < 0) {
		LM_ERR("cannot retrieve identifier\n");
		goto end;
	}
	if (fixup_get_ivalue(_m, (gparam_p)_l, &limit) < 0) {
		LM_ERR("cannot retrieve limit\n");
		goto end;
	}
	algorithm.s = 0;
	if (!_a || fixup_get_svalue(_m, (gparam_p)_a, &algorithm) < 0 ||
			(algo = get_rl_algo(algorithm)) < 0) {
		algo = PIPE_ALGO_NOP;
	}

	/* get limit for FEEDBACK algorithm */
	if (algo == PIPE_ALGO_FEEDBACK) {
		lock_get(rl_lock);
		if (*rl_feedback_limit) {
			if (*rl_feedback_limit != limit) {
				LM_WARN("FEEDBACK limit should be the same for all pipes, but"
						" new limit %d differs - setting to %d\n",
						limit, *rl_feedback_limit);
				limit = *rl_feedback_limit;
			}
		} else {
			if (limit <= 0 || limit >= 100) {
				LM_ERR("invalid limit for FEEDBACK algorithm "
					"(must be between 0 and 100)\n");
				lock_release(rl_lock);
				goto end;
			}
			*rl_feedback_limit = limit;
			pid_setpoint_limit(limit);
		}
		lock_release(rl_lock);
	}

	hash_idx = RL_GET_INDEX(name);
	RL_GET_LOCK(hash_idx);

	/* try to get the value */
	pipe = RL_GET_PIPE(hash_idx, name);
	if (!pipe) {
		LM_ERR("cannot get the index\n");
		goto release;
	}

	if (!*pipe) {
		/* allocate new pipe */
		*pipe = shm_malloc(sizeof(rl_pipe_t) +
				rl_dests_nr * sizeof(rl_repl_counter_t));
		if (!*pipe) {
			LM_ERR("no more shm memory\n");
			goto release;
		}
		memset(*pipe, 0, sizeof(rl_pipe_t) + rl_dests_nr * sizeof(rl_repl_counter_t));
		(*pipe)->dsts = (rl_repl_counter_t *)((*pipe) + 1);
		LM_DBG("Pipe %.*s doens't exist, but was created %p\n",
				name.len, name.s, *pipe);
		if (algo == PIPE_ALGO_NETWORK)
			should_update = 1;
		(*pipe)->algo = (algo == PIPE_ALGO_NOP) ? rl_default_algo : algo;
	} else {
		LM_DBG("Pipe %.*s found: %p - last used %lu\n",
				name.len, name.s, *pipe, (*pipe)->last_used);
		if (algo != PIPE_ALGO_NOP && (*pipe)->algo != algo) {
			LM_WARN("algorithm %d different from the initial one %d for pipe "
					"%.*s", algo, (*pipe)->algo, name.len, name.s);
		}
	}

	/* set/update the limit */
	(*pipe)->limit = limit;

	/* set the last used time */
	(*pipe)->last_used = time(0);
	if (RL_USE_CDB(*pipe)) {
		/* release the counter for a while */
		if (rl_change_counter(&name, *pipe, 1) < 0) {
			LM_ERR("cannot increase counter\n");
			goto end;
		}
	} else {
		(*pipe)->counter++;
	}

	ret = rl_pipe_check(*pipe);
	LM_DBG("Pipe %.*s counter:%d load:%d limit:%d should %sbe blocked (%p)\n",
			name.len, name.s, (*pipe)->counter, (*pipe)->load,
			(*pipe)->limit, ret == 1? "NOT " : "", *pipe);


release:
	RL_RELEASE_LOCK(hash_idx);
	if (should_update) {
		lock_get(rl_lock);
		(*rl_network_count)++;
		lock_release(rl_lock);
	}
end:
	return ret;
}
Ejemplo n.º 10
0
void rl_rcv_bin(bin_packet_t *packet)
{
	rl_algo_t algo;
	int limit;
	int counter;
	str name;
	rl_pipe_t **pipe;
	unsigned int hash_idx;
	time_t now;
	rl_repl_counter_t *destination;

	if (packet->type != RL_PIPE_COUNTER) {
		LM_WARN("Invalid binary packet command: %d (from node: %d in cluster: %d)\n",
			packet->type, packet->src_id, rl_repl_cluster);
		return;
	}

	now = time(0);

	for (;;) {
		if (bin_pop_str(packet, &name) == 1)
			break; /* pop'ed all pipes */

		if (bin_pop_int(packet, &algo) < 0) {
			LM_ERR("cannot pop pipe's algorithm\n");
			return;
		}

		if (bin_pop_int(packet, &limit) < 0) {
			LM_ERR("cannot pop pipe's limit\n");
			return;
		}

		if (bin_pop_int(packet, &counter) < 0) {
			LM_ERR("cannot pop pipe's counter\n");
			return;
		}

		hash_idx = RL_GET_INDEX(name);
		RL_GET_LOCK(hash_idx);

		/* try to get the value */
		pipe = RL_GET_PIPE(hash_idx, name);
		if (!pipe) {
			LM_ERR("cannot get the index\n");
			goto release;
		}

		if (!*pipe) {
			/* if the pipe does not exist, allocate it in case we need it later */
			if (!(*pipe = rl_create_pipe(limit, algo)))
				goto release;
			LM_DBG("Pipe %.*s doesn't exist, but was created %p\n",
				name.len, name.s, *pipe);

		} else {
			LM_DBG("Pipe %.*s found: %p - last used %lu\n",
				name.len, name.s, *pipe, (*pipe)->last_used);
			if ((*pipe)->algo != algo)
				LM_WARN("algorithm %d different from the initial one %d for "
				"pipe %.*s", algo, (*pipe)->algo, name.len, name.s);
			/*
			 * XXX: do not output these warnings since they can be triggered
			 * when a custom limit is used
			if ((*pipe)->limit != limit)
				LM_WARN("limit %d different from the initial one %d for "
				"pipe %.*s", limit, (*pipe)->limit, name.len, name.s);
			 */
		}
		/* set the last used time */
		(*pipe)->last_used = time(0);
		/* set the destination's counter */
		destination = find_destination(*pipe, packet->src_id);
		if (!destination)
			goto release;
		destination->counter = counter;
		destination->update = now;
		RL_RELEASE_LOCK(hash_idx);
	}
	return;

release:
	RL_RELEASE_LOCK(hash_idx);
}
Ejemplo n.º 11
0
int w_rl_check(struct sip_msg *_m, str *name, int *limit, str *algorithm)
{
	int ret = 1, should_update = 0;
	unsigned int hash_idx;
	rl_pipe_t **pipe;

	rl_algo_t algo = -1;

	if (!algorithm || (algo = get_rl_algo(*algorithm)) == PIPE_ALGO_NOP) {
		algo = PIPE_ALGO_NOP;
	}

	/* get limit for FEEDBACK algorithm */
	if (algo == PIPE_ALGO_FEEDBACK) {
		lock_get(rl_lock);
		if (*rl_feedback_limit) {
			if (*rl_feedback_limit != *limit) {
				LM_WARN("FEEDBACK limit should be the same for all pipes, but"
					" new limit %d differs - setting to %d\n",
					*limit, *rl_feedback_limit);
				*limit = *rl_feedback_limit;
			}
		} else {
			if (*limit <= 0 || *limit >= 100) {
				LM_ERR("invalid limit for FEEDBACK algorithm "
					"(must be between 0 and 100)\n");
				lock_release(rl_lock);
				goto end;
			}
			*rl_feedback_limit = *limit;
			pid_setpoint_limit(*limit);
		}
		lock_release(rl_lock);
	}

	hash_idx = RL_GET_INDEX(*name);
	RL_GET_LOCK(hash_idx);

	/* try to get the value */
	pipe = RL_GET_PIPE(hash_idx, *name);
	if (!pipe) {
		LM_ERR("cannot get the index\n");
		goto release;
	}

	if (!*pipe) {
		/* allocate new pipe */
		if (!(*pipe = rl_create_pipe(*limit, algo)))
			goto release;

		LM_DBG("Pipe %.*s doesn't exist, but was created %p\n",
				name->len, name->s, *pipe);
		if ((*pipe)->algo == PIPE_ALGO_NETWORK)
			should_update = 1;
	} else {
		LM_DBG("Pipe %.*s found: %p - last used %lu\n",
			name->len, name->s, *pipe, (*pipe)->last_used);
		if (algo != PIPE_ALGO_NOP && (*pipe)->algo != algo) {
			LM_WARN("algorithm %d different from the initial one %d for pipe "
				"%.*s", algo, (*pipe)->algo, name->len, name->s);
		}
		/* update the limit */
		(*pipe)->limit = *limit;
	}

	/* set the last used time */
	(*pipe)->last_used = time(0);
	if (RL_USE_CDB(*pipe)) {
		/* release the counter for a while */
		if (rl_change_counter(name, *pipe, 1) < 0) {
			LM_ERR("cannot increase counter\n");
			goto release;
		}
	} else {
		(*pipe)->counter++;
	}

	ret = rl_pipe_check(*pipe);
	LM_DBG("Pipe %.*s counter:%d load:%d limit:%d should %sbe blocked (%p)\n",
		name->len, name->s, (*pipe)->counter, (*pipe)->load,
		(*pipe)->limit, ret == 1 ? "NOT " : "", *pipe);


release:
	RL_RELEASE_LOCK(hash_idx);
	if (should_update) {
		lock_get(rl_lock);
		(*rl_network_count)++;
		lock_release(rl_lock);
	}
end:
	return ret;
}
Ejemplo n.º 12
0
void rl_rcv_bin(int packet_type, struct receive_info *ri, int server_id)
{
	rl_algo_t algo;
	int limit;
	int counter;
	str name;
	char *ip;
	unsigned short port;
	rl_pipe_t **pipe;
	unsigned int hash_idx;
	time_t now;
	rl_repl_counter_t *destination;
	
	if (packet_type == SERVER_TEMP_DISABLED) {
 		get_su_info(&ri->src_su.s, ip, port);
		LM_WARN("server: %s:%hu temporary disabled\n", ip, port);
 		return;
 	}

	if (packet_type == SERVER_TIMEOUT) {
		LM_WARN("server with clustererer id %d timeout\n", server_id);
		return;
	}
	
	if(get_bin_pkg_version() != BIN_VERSION){
		LM_ERR("incompatible bin protocol version\n");
		return;
	}

	if (packet_type != RL_PIPE_COUNTER)
		return;

	if (packet_type != RL_PIPE_COUNTER)
		return;

	now = time(0);

	for (;;) {
		if (bin_pop_str(&name) == 1)
			break; /* pop'ed all pipes */

		if (bin_pop_int(&algo) < 0) {
			LM_ERR("cannot pop pipe's algorithm\n");
			return;
		}

		if (bin_pop_int(&limit) < 0) {
			LM_ERR("cannot pop pipe's limit\n");
			return;
		}

		if (bin_pop_int(&counter) < 0) {
			LM_ERR("cannot pop pipe's counter\n");
			return;
		}

		hash_idx = RL_GET_INDEX(name);
		RL_GET_LOCK(hash_idx);

		/* try to get the value */
		pipe = RL_GET_PIPE(hash_idx, name);
		if (!pipe) {
			LM_ERR("cannot get the index\n");
			goto release;
		}

		if (!*pipe) {
			/* if the pipe does not exist, alocate it in case we need it later */
			*pipe = shm_malloc(sizeof(rl_pipe_t));
			if (!*pipe) {
				LM_ERR("no more shm memory\n");
				goto release;
			}
			memset(*pipe, 0, sizeof(rl_pipe_t));
			LM_DBG("Pipe %.*s doesn't exist, but was created %p\n",
				name.len, name.s, *pipe);
			(*pipe)->algo = algo;
			(*pipe)->limit = limit;
		} else {
			LM_DBG("Pipe %.*s found: %p - last used %lu\n",
				name.len, name.s, *pipe, (*pipe)->last_used);
			if ((*pipe)->algo != algo)
				LM_WARN("algorithm %d different from the initial one %d for "
				"pipe %.*s", algo, (*pipe)->algo, name.len, name.s);
			if ((*pipe)->limit != limit)
				LM_WARN("limit %d different from the initial one %d for "
				"pipe %.*s", limit, (*pipe)->limit, name.len, name.s);
		}
		/* set the last used time */
		(*pipe)->last_used = time(0);
		/* set the destination's counter */
		destination = find_destination(*pipe, server_id);
		destination->counter = counter;
		destination->update = now;
		RL_RELEASE_LOCK(hash_idx);
	}
	return;

release:
	RL_RELEASE_LOCK(hash_idx);
}
Ejemplo n.º 13
0
void rl_rcv_bin(int packet_type, struct receive_info *ri)
{
	rl_algo_t algo;
	int limit;
	int counter;
	int rc;
	int server_id;
	str name;
	char *ip;
	unsigned short port;
	rl_pipe_t **pipe;
	unsigned int hash_idx;
	time_t now;
	rl_repl_counter_t *destination;

	LM_DBG("received a binary packet [%d]!\n", packet_type);
	
	if (packet_type != RL_PIPE_COUNTER)
		return;
	
	rc = bin_pop_int(&server_id);
	if (rc < 0)
		return;
	
	if (!clusterer_api.check(accept_repl_pipes, &ri->src_su, server_id, ri->proto)){
		get_su_info(&ri->src_su.s, ip, port);
		LM_WARN("received bin packet from unknown source: %s:%hu\n",
				ip, port);
		return;
	}
	now = time(0);

	for (;;) {
		if (bin_pop_str(&name) == 1)
			break; /* pop'ed all pipes */

		if (bin_pop_int(&algo) < 0) {
			LM_ERR("cannot pop pipe's algorithm\n");
			return;
		}

		if (bin_pop_int(&limit) < 0) {
			LM_ERR("cannot pop pipe's limit\n");
			return;
		}

		if (bin_pop_int(&counter) < 0) {
			LM_ERR("cannot pop pipe's counter\n");
			return;
		}

		hash_idx = RL_GET_INDEX(name);
		RL_GET_LOCK(hash_idx);

		/* try to get the value */
		pipe = RL_GET_PIPE(hash_idx, name);
		if (!pipe) {
			LM_ERR("cannot get the index\n");
			goto release;
		}

		if (!*pipe) {
			/* if the pipe does not exist, alocate it in case we need it later */
			*pipe = shm_malloc(sizeof(rl_pipe_t));
			if (!*pipe) {
				LM_ERR("no more shm memory\n");
				goto release;
			}
			memset(*pipe, 0, sizeof(rl_pipe_t));
			LM_DBG("Pipe %.*s doesn't exist, but was created %p\n",
					name.len, name.s, *pipe);
			(*pipe)->algo = algo;
			(*pipe)->limit = limit;
		} else {
			LM_DBG("Pipe %.*s found: %p - last used %lu\n",
					name.len, name.s, *pipe, (*pipe)->last_used);
			if ((*pipe)->algo != algo)
				LM_WARN("algorithm %d different from the initial one %d for "
						"pipe %.*s", algo, (*pipe)->algo, name.len, name.s);
			if ((*pipe)->limit != limit)
				LM_WARN("limit %d different from the initial one %d for "
						"pipe %.*s", limit, (*pipe)->limit, name.len, name.s);
		}
		/* set the last used time */
		(*pipe)->last_used = time(0);
		/* set the destination's counter */
		destination = find_destination(*pipe, server_id);
		destination->counter = counter;
		destination->update = now;
		RL_RELEASE_LOCK(hash_idx);
	}
	return;

release:
	RL_RELEASE_LOCK(hash_idx);
}