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; }
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; }
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; }
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; }
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; }
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; }