Ejemplo n.º 1
0
static int w_load_balance(struct sip_msg *req, char *grp, char *rl, char *al)
{
	int ret;
	int grp_no;
	struct lb_grp_param *lbgp = (struct lb_grp_param *)grp;
	pv_value_t val;
	struct lb_res_str_list *lb_rl;
	struct lb_res_parse *lbp;
	pv_elem_t *model;
	str dest;

	if (lbgp->grp_pv) {
		if (pv_get_spec_value( req, (pv_spec_p)lbgp->grp_pv, &val)!=0) {
			LM_ERR("failed to get PV value\n");
			return -1;
		}
		if ( (val.flags&PV_VAL_INT)==0 ) {
			LM_ERR("PV vals is not integer\n");
			return -1;
		}
		grp_no = val.ri;
	} else {
		grp_no = lbgp->grp_no;
	}

	lbp = (struct lb_res_parse *)rl;
	if (lbp->type & RES_ELEM) {
		model = (pv_elem_p)lbp->param;
		if (pv_printf_s(req, model, &dest) || dest.len <= 0) {
			LM_ERR("cannot create resource string\n");
			return -1;
		}
		lb_rl = parse_resources_list(dest.s, 0);
		if (!lb_rl) {
			LM_ERR("cannot create resource list\n");
			return -1;
		}
	} else
		lb_rl = (struct lb_res_str_list *)lbp->param;

	lock_start_read( ref_lock );

	/* do lb */
	ret = do_load_balance(req, grp_no, lb_rl,
			(unsigned int)(long)al, *curr_data);

	lock_stop_read( ref_lock );

	if (lbp->type & RES_ELEM)
		pkg_free(lb_rl);

	if (ret<0)
		return ret;
	return 1;
}
Ejemplo n.º 2
0
int add_lb_dsturi( struct lb_data *data, int id, int group, char *uri,
											char* resource, unsigned int flags)
{
	struct lb_res_str_list *lb_rl;
	struct lb_res_str *r;
	struct lb_dst *dst;
	struct lb_resource *res;
	struct sip_uri puri;
	struct proxy_l *proxy;
	union sockaddr_union sau;
	int len;
	int i;

	LM_DBG("uri=<%s>, grp=%d, res=<%s>\n",uri, group, resource);

	/* check uri */
	len = strlen(uri);
	if(parse_uri(uri, len, &puri)!=0 ) {
		LM_ERR("bad uri [%.*s] for destination\n", len, uri);
		return -1;
	}

	/* parse the resources string */
	lb_rl = parse_resources_list( resource, 1);
	if (lb_rl==NULL) {
		LM_ERR("failed to parse resourse string <%s>\n",resource);
		return -1;
	}

	/*add new destination */
	dst = (struct lb_dst*)shm_malloc( sizeof(struct lb_dst)
		+ lb_rl->n*sizeof(struct lb_resource_map) + len +
		(3+2*sizeof(struct lb_dst*)));
	if (dst==NULL) {
		LM_ERR("failed to get shmem\n");
		goto error;
	}
	memset( dst, 0, sizeof(struct lb_dst)+
		lb_rl->n*sizeof(struct lb_resource_map) + len +
		(3+2*sizeof(struct lb_dst*)) );

	dst->rmap = (struct lb_resource_map*)(dst+1);

	dst->uri.s = (char*)(dst->rmap + lb_rl->n);
	dst->uri.len = len;
	memcpy( dst->uri.s , uri, len);

	dst->profile_id.s = dst->uri.s + len;
	dst->profile_id.len = snprintf(dst->profile_id.s,
		2+2*sizeof(struct lb_dst*), "%X", id);

	dst->id = id;
	dst->group = group;
	dst->rmap_no = lb_rl->n;
	dst->flags = flags;

	/* add or update resource list */
	for( i=0 ; i<lb_rl->n ; i++) {
		r = lb_rl->resources + i;
		LM_DBG(" setting for uri=<%s> (%d) resource=<%.*s>, val=%d\n",
			uri, data->dst_no+1, r->name.len, r->name.s, r->val);
		res = get_resource_by_name( data, &r->name);
		if (res==NULL) {
			/* add new resource */
			res = add_lb_resource(data, &r->name);
			if (res==NULL) {
				LM_ERR("failed to create new resource\n");
				goto error;
			}
		}
		/* set the proper bit in the resource */
		if (lb_set_resource_bitmask( res, data->dst_no)==-1 ) {
			LM_ERR("failed to set destination bit\n");
			goto error;
		}
		/* set the pointer and the max load */
		dst->rmap[i].resource = res;
		dst->rmap[i].max_load = r->val;
	}

	/* Do a SIP wise DNS-Lookup for the domain part */
	proxy = mk_proxy( &puri.host, puri.port_no, puri.proto,
		(puri.type==SIPS_URI_T));
	if (proxy==NULL) {
		LM_ERR("could not resolve %.*s\n", puri.host.len, puri.host.s);
		goto error;
	}
	hostent2ip_addr( &dst->ips[0], &proxy->host, proxy->addr_idx);
	dst->ports[0] = proxy->port;
	dst->ips_cnt = 1;
	LM_DBG("first dst ip addr [%s]:%d\n",
		ip_addr2a(&dst->ips[0]), dst->ports[0]);
	/* get the next available IPs from DNS */
	while (dst->ips_cnt<LB_MAX_IPS && (get_next_su( proxy, &sau, 0)==0) ) {
		su2ip_addr( &dst->ips[dst->ips_cnt], &sau);
		dst->ports[dst->ips_cnt] = proxy->port;
		LM_DBG("additional dst ip addr [%s]:%d\n",
			ip_addr2a(&dst->ips[dst->ips_cnt]), dst->ports[dst->ips_cnt]);
		/* one more IP found */
		dst->ips_cnt++;
	}
	/* free al the helper structures */
	free_proxy(proxy);
	pkg_free(proxy);

	/* link at the end */
	if (data->last_dst==NULL) {
		data->dsts = data->last_dst = dst;
	} else {
		data->last_dst->next = dst;
		data->last_dst = dst;
	}
	data->dst_no++;

	pkg_free(lb_rl);
	return 0;
error:
	shm_free(dst);
	pkg_free(lb_rl);
	return -1;
}
Ejemplo n.º 3
0
static int w_lb_count_call(struct sip_msg *req, char *ip, char *port, char *grp,
			char *rl, char *dir)
{
	struct lb_grp_param *lbgp = (struct lb_grp_param *)grp;
	struct lb_res_str_list *lb_rl;
	struct lb_res_parse *lbp;
	struct ip_addr *ipa;
	pv_value_t val;
	pv_elem_t *model;
	int grp_no;
	int port_no;
	str dest;
	int ret;

	/* get the ip address */
	if (pv_get_spec_value( req, (pv_spec_t*)ip, &val)!=0) {
		LM_ERR("failed to get IP value from PV\n");
		return -1;
	}
	if ( (val.flags&PV_VAL_STR)==0 ) {
		LM_ERR("IP PV val is not string\n");
		return -1;
	}
	if ( (ipa=str2ip( &val.rs ))==NULL ) {
		LM_ERR("IP val is not IP <%.*s>\n",val.rs.len,val.rs.s);
		return -1;
	}

	/* get the port */
	if (port) {
		if (fixup_get_ivalue( req, (gparam_p)port, &port_no)!=0) {
			LM_ERR("failed to get PORT value from PV\n");
			return -1;
		}
	} else {
		port_no = 0;
	}

	/* get the group */
	if (lbgp->grp_pv) {
		if (pv_get_spec_value( req, (pv_spec_p)lbgp->grp_pv, &val)!=0) {
			LM_ERR("failed to get PV value\n");
			return -1;
		}
		if ( (val.flags&PV_VAL_INT)==0 ) {
			LM_ERR("PV vals is not integer\n");
			return -1;
		}
		grp_no = val.ri;
	} else {
		grp_no = lbgp->grp_no;
	}

	/* get the resources list */
	lbp = (struct lb_res_parse *)rl;
	if (lbp->type & RES_ELEM) {
		model = (pv_elem_p)lbp->param;
		if (pv_printf_s(req, model, &dest) || dest.len <= 0) {
			LM_ERR("cannot create resource string\n");
			return -1;
		}
		lb_rl = parse_resources_list(dest.s, 0);
		if (!lb_rl) {
			LM_ERR("cannot create resource list\n");
			return -1;
		}
	} else
		lb_rl = (struct lb_res_str_list *)lbp->param;

	lock_start_read( ref_lock );

	ret = lb_count_call( *curr_data, req, ipa, port_no, grp_no, lb_rl,
			dir ? (int)*(unsigned int *)dir : 0);

	lock_stop_read( ref_lock );

	if (lbp->type & RES_ELEM)
		pkg_free(lb_rl);

	if (ret<0)
		return ret;
	return 1;
}
Ejemplo n.º 4
0
static int w_lb_start(struct sip_msg *req, char *grp, char *rl, char *fl)
{
	int ret;

	int grp_no;
	struct lb_grp_param *lbgp = (struct lb_grp_param *)grp;
	pv_value_t val;

	struct lb_res_str_list *lb_rl;
	struct lb_res_parse *lbp;
	pv_elem_t *model;
	str dest;

	str flstr = {0,0};
	int flags=LB_FLAGS_DEFAULT;
	char *f;

	if (lbgp->grp_pv) {
		if (pv_get_spec_value( req, (pv_spec_p)lbgp->grp_pv, &val)!=0) {
			LM_ERR("failed to get PV value\n");
			return -1;
		}
		if ( (val.flags&PV_VAL_INT)==0 ) {
			LM_ERR("PV vals is not integer\n");
			return -1;
		}
		grp_no = val.ri;
	} else {
		grp_no = lbgp->grp_no;
	}

	lbp = (struct lb_res_parse *)rl;
	if (lbp->type & RES_ELEM) {
		model = (pv_elem_p)lbp->param;
		if (pv_printf_s(req, model, &dest) || dest.len <= 0) {
			LM_ERR("cannot create resource string\n");
			return -1;
		}
		lb_rl = parse_resources_list(dest.s, 0);
		if (!lb_rl) {
			LM_ERR("cannot create resource list\n");
			return -1;
		}
	} else
		lb_rl = (struct lb_res_str_list *)lbp->param;

	if( fl ) {
		if( fixup_get_svalue(req, (gparam_p)fl, &flstr) != 0 ) {
			LM_ERR("failed to extract flags\n");
			return -1;
		}
		for( f=flstr.s ; f<flstr.s+flstr.len ; f++ ) {
			switch( *f ) {
				case 'r':
					flags |= LB_FLAGS_RELATIVE;
					LM_DBG("using relative versus absolute estimation\n");
					break;
				case 'n':
					flags |= LB_FLAGS_NEGATIVE;
					LM_DBG("do not skip negative loads\n");
					break;
				case 's':
					flags |= LB_FLAGS_RANDOM;
					LM_DBG("pick a random destination among all selected dsts with equal load\n");
					break;
				default:
					LM_DBG("skipping unknown flag: [%c]\n", *f);
			}
		}
	}

	lock_start_read( ref_lock );

	/* do lb */
	ret = do_lb_start(req, grp_no, lb_rl, flags, *curr_data);

	lock_stop_read( ref_lock );

	if (lbp->type & RES_ELEM)
		pkg_free(lb_rl);

	if (ret<0)
		return ret;
	return 1;
}
Ejemplo n.º 5
0
static int fixup_resources(void** param, int param_no)
{
	struct lb_res_str_list *lb_rl;
	struct lb_grp_param *lbgp;
	struct lb_res_parse *lbp;
	pv_elem_t *model=NULL;
	str s;

	if (param_no==1) {

		lbgp = (struct lb_grp_param *)pkg_malloc(sizeof(struct lb_grp_param));
		if (lbgp==NULL) {
			LM_ERR("no more pkg mem\n");
			return E_OUT_OF_MEM;
		}
		/* try first as number */
		s.s = (char*)*param;
		s.len = strlen(s.s);
		if (str2int(&s, (unsigned int*)&lbgp->grp_no)==0) {
			lbgp->grp_pv = NULL;
			pkg_free(*param);
		} else {
			lbgp->grp_pv = (pv_spec_t*)pkg_malloc(sizeof(pv_spec_t));
			if (lbgp->grp_pv==NULL) {
				LM_ERR("no pkg memory left\n");
				return E_OUT_OF_MEM;
			}
			if (pv_parse_spec(&s, lbgp->grp_pv)==0 ||
			lbgp->grp_pv->type==PVT_NULL) {
				LM_ERR("%s is not integer nor PV !\n", (char*)*param);
				return E_UNSPEC;
			}
		}
		*param=(void *)(unsigned long)lbgp;
		return 0;

	} else if (param_no==2) {

		/* parameter is string (semi-colon separated list)
		 * of needed resources */
		lbp = (struct lb_res_parse *)pkg_malloc(sizeof(struct lb_res_parse));
		if (!lbp) {
			LM_ERR("no more pkg mem\n");
			return E_OUT_OF_MEM;
		}
		s.s = (char*)*param;
		s.len = strlen(s.s);

		if(pv_parse_format(&s ,&model) || model==NULL) {
			LM_ERR("wrong format [%s] in resource list!\n", s.s);
			return E_CFG;
		}
		/* check if there is any pv in string */
		if (!model->spec.getf && !model->next)
			lbp->type = RES_TEXT;
		else
			lbp->type = RES_ELEM;

		if (lbp->type & RES_TEXT) {
			lb_rl = parse_resources_list( (char *)(*param), 0);
			if (lb_rl==NULL) {
				LM_ERR("invalid parameter %s\n",(char *)(*param));
				return E_CFG;
			}
			pkg_free(*param);
			lbp->param = (void*)(unsigned long)lb_rl;
		} else {
			lbp->param = (void*)(unsigned long)model;
		}
		*param = (void *)(unsigned long)lbp;
		return 0;

	} else if (param_no==3) {
		/* string with flags */
		return fixup_sgp(param);

	}

	LM_CRIT("error - wrong params count (%d)\n",param_no);
	return -1;
}
Ejemplo n.º 6
0
int add_lb_dsturi( struct lb_data *data, int id, int group, char *uri,
											char* resource, unsigned int flags)
{
	struct lb_res_str_list *lb_rl;
	struct lb_res_str *r;
	struct lb_dst *dst;
	struct lb_resource *res;
	int len;
	int i;

	LM_DBG("uri=<%s>, grp=%d, res=<%s>\n",uri, group, resource);

	/* parse the resources string */
	lb_rl = parse_resources_list( resource, 1);
	if (lb_rl==NULL) {
		LM_ERR("failed to parse resourse string <%s>\n",resource);
		return -1;
	}

	len = strlen(uri);

	/*add new destination */
	dst = (struct lb_dst*)shm_malloc( sizeof(struct lb_dst)
		+ lb_rl->n*sizeof(struct lb_resource_map) + len +
		(3+2*sizeof(struct lb_dst*)));
	if (dst==NULL) {
		LM_ERR("failed to get shmem\n");
		goto error;
	}
	memset( dst, 0, sizeof(struct lb_dst)+
		lb_rl->n*sizeof(struct lb_resource_map) + len +
		(3+2*sizeof(struct lb_dst*)) );

	dst->rmap = (struct lb_resource_map*)(dst+1);

	dst->uri.s = (char*)(dst->rmap + lb_rl->n);
	dst->uri.len = len;
	memcpy( dst->uri.s , uri, len);

	dst->profile_id.s = dst->uri.s + len;
	dst->profile_id.len = snprintf(dst->profile_id.s, 
		2+2*sizeof(struct lb_dst*), "%X", id);

	dst->id = id;
	dst->group = group;
	dst->rmap_no = lb_rl->n;
	dst->flags = flags;

	/* add or update resource list */
	for( i=0 ; i<lb_rl->n ; i++) {
		r = lb_rl->resources + i;
		LM_DBG(" setting for uri=<%s> (%d) resource=<%.*s>, val=%d\n",
			uri, data->dst_no+1, r->name.len, r->name.s, r->val);
		res = get_resource_by_name( data, &r->name);
		if (res==NULL) {
			/* add new resource */
			res = add_lb_resource(data, &r->name);
			if (res==NULL) {
				LM_ERR("failed to create new resource\n");
				goto error;
			}
		}
		/* set the proper bit in the resource */
		if (lb_set_resource_bitmask( res, data->dst_no)==-1 ) {
			LM_ERR("failed to set destination bit\n");
			goto error;
		}
		/* set the pointer and the max load */
		dst->rmap[i].resource = res;
		dst->rmap[i].max_load = r->val;
	}

	/* link at the end */
	if (data->last_dst==NULL) {
		data->dsts = data->last_dst = dst;
	} else {
		data->last_dst->next = dst;
		data->last_dst = dst;
	}
	data->dst_no++;

	pkg_free(lb_rl);
	return 0;
error:
	shm_free(dst);
	pkg_free(lb_rl);
	return -1;
}