diff --git a/modules/load_balancer/lb_data.c b/modules/load_balancer/lb_data.c index 6c14da2e3d6..4654dc385ab 100644 --- a/modules/load_balancer/lb_data.c +++ b/modules/load_balancer/lb_data.c @@ -330,6 +330,7 @@ int add_lb_dsturi( struct lb_data *data, int id, int group, char *uri, data->last_dst = dst; } data->dst_no++; + dst->queue_loc = data->dst_no; pkg_free(lb_rl); return 0; @@ -459,7 +460,7 @@ int lb_route(struct sip_msg *req, int group, struct lb_res_str_list *rl, struct lb_dst *it_d; struct lb_resource *it_r; int load, it_l; - int i, j, cond, cnt_aval_dst; + int i, j, cond, cnt_aval_dst, q_lowest; /* init control vars state */ @@ -666,7 +667,7 @@ int lb_route(struct sip_msg *req, int group, struct lb_res_str_list *rl, /* init selected destinations buff */ dsts_cur = NULL; - dsts_size_max = (flags & LB_FLAGS_RANDOM) ? data->dst_no : 1; + dsts_size_max = (flags & (LB_FLAGS_RANDOM|LB_FLAGS_QUEUE)) ? data->dst_no : 1; if( dsts_size_max > 1 ) { if( dsts_size_max > dsts_size ) { dsts = (struct lb_dst **)pkg_realloc @@ -778,7 +779,16 @@ int lb_route(struct sip_msg *req, int group, struct lb_res_str_list *rl, } /* choose one destination among selected */ if( dsts_size_cur > 0 ) { - if( (dsts_size_cur > 1) && (flags & LB_FLAGS_RANDOM) ) { + if((dsts_size_cur > 1) && (flags & LB_FLAGS_QUEUE)){ + //Find lowest queue number in virtual queue + q_lowest = data->dst_no; + for( i=0 ; iqueue_loc < q_lowest){ + q_lowest = dsts_cur[i]->queue_loc; + dst = dsts_cur[i]; + } + } + }else if( (dsts_size_cur > 1) && (flags & LB_FLAGS_RANDOM) ) { dst = dsts_cur[rand() % dsts_size_cur]; } else { dst = dsts_cur[0]; @@ -807,6 +817,15 @@ int lb_route(struct sip_msg *req, int group, struct lb_res_str_list *rl, if( it_d == dst ) { dst_bitmap_cur[i] &= ~(1 << j); break; } if( ++j == (8 * sizeof(unsigned int)) ) { i++; j=0; } } + + //Move members around in virtual queue + for( it_d=data->dsts; it_d; it_d=it_d->next){ + if(it_d->queue_loc > dst->queue_loc){it_d->queue_loc--;} + } + + //Move chosen dst to end of virtual queue + dst->queue_loc = data->dst_no; + } else { LM_DBG("%s call of LB - no destination found\n", (reuse ? "sequential" : "initial")); @@ -905,6 +924,7 @@ int do_lb_reset(struct sip_msg *req, struct lb_data *data) struct usr_avp *res_avp, *del_res_avp; int_str id_val; int_str res_val; + int i; struct dlg_cell *dlg; struct lb_dst *it_d, *last_dst; @@ -961,6 +981,13 @@ int do_lb_reset(struct sip_msg *req, struct lb_data *data) } } + //Refresh Queue Order (Starts at 1) + i=1; + for(it_d=data->dsts; it_d; it_d=it_d->next){ + it_d->queue_loc=i; + i++; + } + return 0; } @@ -1076,6 +1103,7 @@ int lb_count_call(struct lb_data *data, struct sip_msg *req,struct ip_addr *ip, struct dlg_cell *dlg; struct lb_resource *res; struct lb_dst *dst; + struct lb_dst *it_d; int i,k; /* search for the destination we need to count for */ @@ -1099,10 +1127,16 @@ int lb_count_call(struct lb_data *data, struct sip_msg *req,struct ip_addr *ip, return -1; } + //Move chosen dst in virtual queue (won't be used unless flag is set when session starts) + for( it_d=data->dsts ; it_d; it_d=it_d->next){ + if(it_d->queue_loc > dst->queue_loc){it_d->queue_loc--;} + } + dst->queue_loc = data->dst_no; + /* get references to the resources */ if (rl->n>call_res_no) { call_res = (struct lb_resource**)pkg_realloc - (call_res, rl->n*sizeof(struct lb_resorce*)); + (call_res, rl->n*sizeof(struct lb_resource*)); if (call_res==NULL) { call_res_no = 0; LM_ERR("no more pkg mem - res ptr realloc\n"); diff --git a/modules/load_balancer/lb_data.h b/modules/load_balancer/lb_data.h index 3cc9c50150b..fe4976c8cb8 100644 --- a/modules/load_balancer/lb_data.h +++ b/modules/load_balancer/lb_data.h @@ -39,6 +39,7 @@ #define LB_FLAGS_RELATIVE (1<<0) /* do relative versus absolute estimation. default is absolute */ #define LB_FLAGS_NEGATIVE (1<<1) /* do not skip negative loads. default to skip */ #define LB_FLAGS_RANDOM (1<<2) /* pick a random destination among all selected dsts with equal load */ +#define LB_FLAGS_QUEUE (1<<3) /* picks the next destination in the virtual queue*/ #define LB_FLAGS_DEFAULT 0 #define LB_DST_PING_DSBL_FLAG (1<<0) @@ -76,6 +77,7 @@ struct lb_dst { unsigned short int protos[LB_MAX_IPS]; /* Protocol of the request URI */ unsigned short ips_cnt; struct lb_dst *next; + unsigned int queue_loc; }; struct lb_data { diff --git a/modules/load_balancer/load_balancer.c b/modules/load_balancer/load_balancer.c index 4692eb6a779..a7e3113e6de 100644 --- a/modules/load_balancer/load_balancer.c +++ b/modules/load_balancer/load_balancer.c @@ -232,7 +232,7 @@ static int fixup_resources(void** param, int param_no) /* try first as number */ s.s = (char*)*param; s.len = strlen(s.s); - if (str2int(&s, (unsigned int*)&lbgp->grp_no)==0) { + if (str2sint(&s, (int*)&lbgp->grp_no)==0) { lbgp->grp_pv = NULL; pkg_free(*param); } else { @@ -608,6 +608,10 @@ static int w_lb_start(struct sip_msg *req, char *grp, char *rl, char *fl) flags |= LB_FLAGS_RANDOM; LM_DBG("pick a random destination among all selected dsts with equal load\n"); break; + case 'q': + flags |= LB_FLAGS_QUEUE; + LM_DBG("cycle destinations through a virtual queue"); + break; default: LM_DBG("skipping unknown flag: [%c]\n", *f); }