Module: sip-router
Branch: master
Commit: 79bcd31ae4f30a60c6d3f2a88b505a35ba0f6927
URL:    
http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=79bcd31ae4f30a60c6d3f2a88b505a35ba0f6927

Author: Jason Penton <[email protected]>
Committer: Jason Penton <[email protected]>
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 */
        }
        


_______________________________________________
sr-dev mailing list
[email protected]
http://lists.sip-router.org/cgi-bin/mailman/listinfo/sr-dev

Reply via email to