Module: sip-router
Branch: master
Commit: 79bcd31ae4f30a60c6d3f2a88b505a35ba0f6927
URL:
http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=79bcd31…
Author: Jason Penton <jason.penton(a)gmail.com>
Committer: Jason Penton <jason.penton(a)gmail.com>
Date: Thu May 29 13:04:33 2014 +0200
modules/cdp: added loadbalancing across diameter peers within the same realm and with the
same metric
---
modules/cdp/cdp_rpc.c | 32 ++++++++++++++++++++++++++++----
modules/cdp/diameter_comm.c | 2 +-
modules/cdp/peer.h | 1 +
modules/cdp/routing.c | 41 ++++++++++++++++++++++++++++++++++++++---
4 files changed, 68 insertions(+), 8 deletions(-)
diff --git a/modules/cdp/cdp_rpc.c b/modules/cdp/cdp_rpc.c
index 0db5b26..8b7310c 100644
--- a/modules/cdp/cdp_rpc.c
+++ b/modules/cdp/cdp_rpc.c
@@ -66,7 +66,10 @@ static void cdp_rpc_list_peers(rpc_t* rpc, void* ctx)
void *peers_header;
void *peers_container;
void *peerdetail_container;
- peer *i;
+ void *peerapplication_container;
+ peer *i, *j;
+ int c;
+ char buf[100];
if (rpc->add(ctx, "{", &peers_header) < 0) {
rpc->fault(ctx, 500, "Internal error creating top rpc");
@@ -91,19 +94,40 @@ static void cdp_rpc_list_peers(rpc_t* rpc, void* ctx)
lock_get(peer_list_lock);
i = peer_list->head;
while (i) {
- if (rpc->struct_add(peers_container, "S{",
+ lock_get(i->lock);
+ if (rpc->struct_add(peers_container, "S{",
"FQDN", &i->fqdn,
"Details", &peerdetail_container) < 0) {
rpc->fault(ctx, 500, "Internal error creating peers container
struct");
+ lock_release(i->lock);
return;
}
- if (rpc->struct_add(peerdetail_container, "ss",
+ if (rpc->struct_add(peerdetail_container, "ssd",
"State", dp_states[(int)i->state],
- "Disabled",
i->disabled?"True":"False") < 0) {
+ "Disabled",
i->disabled?"True":"False",
+ "Last used", i->last_selected) < 0) {
rpc->fault(ctx, 500, "Internal error creating peer detail
container struct");
+ lock_release(i->lock);
return;
}
+ if (rpc->struct_add(peerdetail_container, "{",
"Applications", &peerapplication_container) < 0) {
+ rpc->fault(ctx, 500, "Internal error creating peer application
container struct");
+ lock_release(i->lock);
+ return;
+ }
+
+ for (c = 0; c < i->applications_cnt; c++) {
+ snprintf(buf, 100, "%d:%d", i->applications[c].id,
i->applications[c].vendor);
+ if (rpc->struct_add(peerapplication_container, "s",
+ "appid:vendorid", buf) < 0) {
+ rpc->fault(ctx, 500, "Internal error creating appid/vendorid
information");
+ lock_release(i->lock);
+ return;
+ }
+ }
+ j=i;
i = i->next;
+ lock_release(j->lock);
}
lock_release(peer_list_lock);
}
diff --git a/modules/cdp/diameter_comm.c b/modules/cdp/diameter_comm.c
index 5e28e91..fc29596 100644
--- a/modules/cdp/diameter_comm.c
+++ b/modules/cdp/diameter_comm.c
@@ -195,7 +195,7 @@ AAAReturnCode AAASendMessageToPeer(
LM_ERR("AAASendMessageToPeer(): can't add transaction callback for
answer.\n");
}
-// if (!peer_send_msg(p,message))
+ p->last_selected = time(NULL);
if (!sm_process(p,Send_Message,message,0,0))
goto error;
diff --git a/modules/cdp/peer.h b/modules/cdp/peer.h
index cf0451a..a16393a 100644
--- a/modules/cdp/peer.h
+++ b/modules/cdp/peer.h
@@ -111,6 +111,7 @@ typedef struct _peer_t{
int R_sock; /**< socket used as receiver */
time_t activity; /**< timestamp of last activity */
+ time_t last_selected; /**< timestamp this peer was last selected for routing - used
in least recently used load balancing across metric */
int is_dynamic; /**< whether this peer was accepted although it was not initially
configured */
int disabled; /**< administratively enable/disable a peer - ie remove/re-add from
service dynamically */
int waitingDWA; /**< if a Diameter Watch-dog Request was sent out and waiting for
an answer */
diff --git a/modules/cdp/routing.c b/modules/cdp/routing.c
index 4e84be2..499519a 100644
--- a/modules/cdp/routing.c
+++ b/modules/cdp/routing.c
@@ -48,7 +48,10 @@
#include "peermanager.h"
#include "diameter_api.h"
+#define LB_MAX_PEERS 20 /**< maximum peers that can be loadbalanced accross i.e.
same metric */
+
extern dp_config *config; /**< Configuration for this diameter peer */
+int gcount = 0;
/**
* Returns if the peer advertised support for an Application ID
@@ -74,11 +77,19 @@ int peer_handles_application(peer *p,int app_id,int vendor_id)
*/
peer* get_first_connected_route(routing_entry *r,int app_id,int vendor_id)
{
+ peer *peers[LB_MAX_PEERS];
+ int peer_count=0;
+ int prev_metric=0;
routing_entry *i;
peer *p;
+ int j;
+ time_t least_recent_time;
+
LM_DBG("get_first_connected_route in list %p for app_id %d and vendor_id
%d\n",
r,app_id,vendor_id);
for(i=r;i;i=i->next){
+ if (peer_count >= LB_MAX_PEERS)
+ break;
p = get_peer_by_fqdn(&(i->fqdn));
if (!p)
LM_DBG("The peer %.*s does not seem to be connected or configured\n",
@@ -88,10 +99,31 @@ peer* get_first_connected_route(routing_entry *r,int app_id,int
vendor_id)
(p->state==I_Open||p->state==R_Open)?"opened":"closed");
if (p && !p->disabled && (p->state==I_Open ||
p->state==R_Open) && peer_handles_application(p,app_id,vendor_id)) {
LM_DBG("The peer %.*s matches - will forward
there\n",i->fqdn.len,i->fqdn.s);
- return p;
+ if (peer_count!=0) {//check the metric
+ if (i->metric != prev_metric)
+ break;
+ //metric must be the same
+ peers[peer_count++] = p;
+ } else {//we're first
+ prev_metric = i->metric;
+ peers[peer_count++] = p;
+ }
}
}
- return 0;
+
+ if (peer_count==0)
+ return 0;
+
+ least_recent_time = peers[0]->last_selected;
+ p = peers[0];
+ for (j=1; j<peer_count; j++) {
+ if (peers[j]->last_selected < least_recent_time) {
+ least_recent_time = peers[j]->last_selected;
+ p = peers[j];
+ }
+ }
+
+ return p;
}
/**
@@ -153,7 +185,10 @@ peer* get_routing_peer(AAAMessage *m)
if (destination_host.len){
/* There is a destination host present in the message try and route directly there */
p = get_peer_by_fqdn(&destination_host);
- if (p && (p->state==I_Open || p->state==R_Open) &&
peer_handles_application(p,app_id,vendor_id)) return p;
+ if (p && (p->state==I_Open || p->state==R_Open) &&
peer_handles_application(p,app_id,vendor_id)) {
+ p->last_selected = time(NULL);
+ return p;
+ }
/* the destination host peer is not connected at the moment, try a normal route then
*/
}