Module: sip-router Branch: master Commit: 81287cb27c87c641f3d314fbabc921345323b864 URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=81287cb2...
Author: Jason Penton jason.penton@gmail.com Committer: Jason Penton jason.penton@gmail.com Date: Tue May 27 20:55:11 2014 +0200
modules/cdp: new RPC commands to disable/enable a peer dynamically - this is useful to disable a particular diameter peer in a cluster
---
modules/cdp/cdp_rpc.c | 66 +++++++++++++++++++++++++++++++++++++++++ modules/cdp/cdp_rpc.h | 16 ++++++++++ modules/cdp/config.h | 2 +- modules/cdp/diameter_comm.c | 1 + modules/cdp/doc/cdp_admin.xml | 24 +++++++++++++-- modules/cdp/mod.c | 8 ++++- modules/cdp/peer.h | 1 + modules/cdp/peermanager.c | 18 ++++++++++- modules/cdp/routing.c | 5 ++- 9 files changed, 133 insertions(+), 8 deletions(-)
diff --git a/modules/cdp/cdp_rpc.c b/modules/cdp/cdp_rpc.c new file mode 100644 index 0000000..53aabe5 --- /dev/null +++ b/modules/cdp/cdp_rpc.c @@ -0,0 +1,66 @@ +/* + * rpc.c + * + * Created on: 27 May 2014 + * Author: jaybeepee + */ +#include "cdp_rpc.h" +#include "peermanager.h" +#include "peerstatemachine.h" +#include "receiver.h" +#include "../../str.h" +#include "../../dprint.h" + +extern dp_config *config; + +static const char* cdp_rpc_disable_peer_doc[2] = {"disable diameter peer", 0 }; +static const char* cdp_rpc_enable_peer_doc[2] = {"enable diameter peer", 0 }; + + +static void cdp_rpc_enable_peer(rpc_t* rpc, void* ctx) +{ + peer *cdp_peer; + str peer_fqdn; + + if (rpc->scan(ctx, "S", &peer_fqdn) < 1) { + rpc->fault(ctx, 400, "required peer fqdn argument"); + return; + } + + cdp_peer = get_peer_by_fqdn(&peer_fqdn); + if (cdp_peer != NULL) { + LM_DBG("Enabling CDP Peer: [%.*s]\n", peer_fqdn.len, peer_fqdn.s); + cdp_peer->disabled = 0; + return; + } + rpc->fault(ctx, 400, "peer not found"); + return; +} + +static void cdp_rpc_disable_peer(rpc_t* rpc, void* ctx) +{ + peer *cdp_peer; + str peer_fqdn; + + if (rpc->scan(ctx, "S", &peer_fqdn) < 1) { + rpc->fault(ctx, 400, "required peer fqdn argument"); + return; + } + cdp_peer = get_peer_by_fqdn(&peer_fqdn); + if (cdp_peer != NULL) { + LM_DBG("Disabling CDP peer: [%.*s]\n", peer_fqdn.len, peer_fqdn.s); + cdp_peer->disabled = 1; + return; + } + + rpc->fault(ctx, 400, "peer not found"); + return; + +} + +rpc_export_t cdp_rpc[] = { + {"cdp.disable_peer", cdp_rpc_disable_peer, cdp_rpc_disable_peer_doc, 0}, + {"cdp.enable_peer", cdp_rpc_enable_peer, cdp_rpc_enable_peer_doc, 0}, + {0, 0, 0, 0} +}; + diff --git a/modules/cdp/cdp_rpc.h b/modules/cdp/cdp_rpc.h new file mode 100644 index 0000000..ea7524a --- /dev/null +++ b/modules/cdp/cdp_rpc.h @@ -0,0 +1,16 @@ +/* + * rpc.h + * + * Created on: 27 May 2014 + * Author: jaybeepee + */ + +#ifndef RPC_H_ +#define RPC_H_ + +#include "../../rpc.h" +#include "config.h" + +extern rpc_export_t cdp_rpc[]; + +#endif /* RPC_H_ */ diff --git a/modules/cdp/config.h b/modules/cdp/config.h index 2cda05f..c011893 100644 --- a/modules/cdp/config.h +++ b/modules/cdp/config.h @@ -124,7 +124,7 @@ typedef struct { acceptor_config *acceptors; /**< list of acceptors */ int acceptors_cnt; /**< size of the list of acceptors */ - app_config *applications; /**< list of supporter applications */ + app_config *applications; /**< list of supported applications */ int applications_cnt; /**< size of list of supported applications*/
int *supported_vendors; /**< list of supported vendor ids */ diff --git a/modules/cdp/diameter_comm.c b/modules/cdp/diameter_comm.c index 82d05c4..5e28e91 100644 --- a/modules/cdp/diameter_comm.c +++ b/modules/cdp/diameter_comm.c @@ -138,6 +138,7 @@ AAAReturnCode AAASendMessage( LM_ERR("AAASendMessage(): Can't find a suitable connected peer in the routing table.\n"); goto error; } + LM_DBG("Found diameter peer [%.*s] from routing table\n", p->fqdn.len, p->fqdn.s); if (p->state!=I_Open && p->state!=R_Open){ LM_ERR("AAASendMessage(): Peer not connected to %.*s\n",p->fqdn.len,p->fqdn.s); goto error; diff --git a/modules/cdp/doc/cdp_admin.xml b/modules/cdp/doc/cdp_admin.xml index 52d7907..904b193 100644 --- a/modules/cdp/doc/cdp_admin.xml +++ b/modules/cdp/doc/cdp_admin.xml @@ -15,9 +15,9 @@ <para>CDP (C Diameter Peer) allows Diameter communication to and from Kamailio. Most of the code is inherited from DISC http://developer.berlios.de/projects/disc/ and OpenIMS and modified for - use within Kamailio. A few improvements and new functionality has been added - along the way, for example, threshold reporting on Diameter calls that are - serviced above a certain threshold.</para> + use within Kamailio. A few improvements and new functionality has been + added along the way, for example, threshold reporting on Diameter calls + that are serviced above a certain threshold.</para> </section>
<section> @@ -138,6 +138,24 @@ modparam("cdp", "latency_threshold", 1000) </section>
<section> + <title>RPC Commands</title> + + <para>exported RPC commands.</para> + + <section> + <title>cdp.disable_peer</title> + + <para>instantly disable a particular diameter peer.</para> + </section> + + <section> + <title>cdp.enable_peer</title> + + <para>enabe/re-enable a diameter peer</para> + </section> + </section> + + <section> <title>Configuration Examples</title>
<section> diff --git a/modules/cdp/mod.c b/modules/cdp/mod.c index 0f12b4c..655ae86 100644 --- a/modules/cdp/mod.c +++ b/modules/cdp/mod.c @@ -51,7 +51,9 @@ #include "diameter_peer.h" #include "config.h" #include "cdp_load.h" - +#include "cdp_rpc.h" +#include "../../rpc.h" +#include "../../rpc_lookup.h" #include "../../cfg/cfg_struct.h"
MODULE_VERSION @@ -198,6 +200,10 @@ struct module_exports exports = { */ static int cdp_init( void ) { + if (rpc_register_array(cdp_rpc) != 0) { + LM_ERR("failed to register RPC commands for CDP module\n"); + return -1; + } #ifdef STATISTICS /* register statistics */ if ( register_stat("cdp", "replies_response_time", &replies_response_time,0 )!=0 ) { diff --git a/modules/cdp/peer.h b/modules/cdp/peer.h index 112e7f8..cf0451a 100644 --- a/modules/cdp/peer.h +++ b/modules/cdp/peer.h @@ -112,6 +112,7 @@ typedef struct _peer_t{ time_t activity; /**< timestamp of last activity */ 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 */ str send_pipe_name; /**< pipe to signal messages to be sent out*/ diff --git a/modules/cdp/peermanager.c b/modules/cdp/peermanager.c index e2cb4d4..9a0729f 100644 --- a/modules/cdp/peermanager.c +++ b/modules/cdp/peermanager.c @@ -264,6 +264,16 @@ int peer_timer(time_t now,void *ptr) while(p){ lock_get(p->lock); n = p->next; + + if (p->disabled && (p->state != Closed || p->state != Closing)) { + LM_DBG("Peer [%.*s] has been disabled - shutting down\n", p->fqdn.len, p->fqdn.s); + if (p->state == I_Open) sm_process(p, Stop, 0, 1, p->I_sock); + if (p->state == R_Open) sm_process(p, Stop, 0, 1, p->R_sock); + lock_release(p->lock); + p = n; + continue; + } + if (p->activity+config->tc<=now){ LM_INFO("peer_timer(): Peer %.*s \tState %d \n",p->fqdn.len,p->fqdn.s,p->state); switch (p->state){ @@ -274,8 +284,10 @@ int peer_timer(time_t now,void *ptr) free_peer(p,1); break; } - touch_peer(p); - sm_process(p,Start,0,1,0); + if (!p->disabled) { + touch_peer(p); + sm_process(p,Start,0,1,0); + } break; /* timeouts */ case Wait_Conn_Ack: @@ -293,10 +305,12 @@ int peer_timer(time_t now,void *ptr) p->waitingDWA = 0; if (p->state==I_Open) sm_process(p,I_Peer_Disc,0,1,p->I_sock); if (p->state==R_Open) sm_process(p,R_Peer_Disc,0,1,p->R_sock); + LM_WARN("Inactivity on peer [%.*s] and no DWA, Closing peer...\n", p->fqdn.len, p->fqdn.s); } else { p->waitingDWA = 1; Snd_DWR(p); touch_peer(p); + LM_WARN("Inactivity on peer [%.*s], sending DWR... - if we don't get a reply, the peer will be closed\n", p->fqdn.len, p->fqdn.s); } break; /* ignored states */ diff --git a/modules/cdp/routing.c b/modules/cdp/routing.c index f468e11..4e84be2 100644 --- a/modules/cdp/routing.c +++ b/modules/cdp/routing.c @@ -86,7 +86,7 @@ peer* get_first_connected_route(routing_entry *r,int app_id,int vendor_id) else LM_DBG("The peer %.*s state is %s\n",i->fqdn.len,i->fqdn.s, (p->state==I_Open||p->state==R_Open)?"opened":"closed"); - if (p && (p->state==I_Open || p->state==R_Open) && peer_handles_application(p,app_id,vendor_id)) { + 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; } @@ -112,6 +112,8 @@ peer* get_routing_peer(AAAMessage *m) routing_realm *rr; int app_id=0,vendor_id=0; + LM_DBG("getting diameter routing peer for realm: [%.*s]\n", m->dest_realm->data.len, m->dest_realm->data.s); + app_id = m->applicationId; avp = AAAFindMatchingAVP(m,0,AVP_Vendor_Specific_Application_Id,0,AAA_FORWARD_SEARCH); if (avp){ @@ -178,6 +180,7 @@ peer* get_routing_peer(AAAMessage *m) } /* if not found in the realms or no destination_realm, * get the first connected host in default routes */ + LM_DBG("no routing peer found, trying default route\n"); p = get_first_connected_route(config->r_table->routes,app_id,vendor_id); if (!p){ LM_ERR("get_routing_peer(): No connected DefaultRoute peer found for app_id %d and vendor id %d.\n",