浏览代码

modules_k/ratelimit: adding rpc interface

 - functionality provided via mi interface was extended to rpc interface
Ovidiu Sas 15 年之前
父节点
当前提交
bae720e04c

+ 154 - 4
modules_k/ratelimit/README

@@ -20,7 +20,7 @@ Hendrik Scholz
 
    Copyright © 2006 Freenet Cityline GmbH
 
-   Copyright © 2008-2009 VoIP Embedded Inc.
+   Copyright © 2008-2010 VoIP Embedded Inc.
    Revision History
    Revision $Revision$ $Date$
      __________________________________________________________________
@@ -72,7 +72,19 @@ Hendrik Scholz
               8.8. rl_push_load
               8.9. rl_set_dbg
 
-        9. Known limitations
+        9. Exported RPC Functions
+
+              9.1. rl.stats
+              9.2. rl.set_pipe
+              9.3. rl.get_pipes
+              9.4. rl.set_queue
+              9.5. rl.get_queues
+              9.6. rl.set_pid
+              9.7. rl.get_pid
+              9.8. rl.push_load
+              9.9. rl.set_dbg
+
+        10. Known limitations
 
    List of Examples
 
@@ -134,7 +146,19 @@ Chapter 1. Admin Guide
         8.8. rl_push_load
         8.9. rl_set_dbg
 
-   9. Known limitations
+   9. Exported RPC Functions
+
+        9.1. rl.stats
+        9.2. rl.set_pipe
+        9.3. rl.get_pipes
+        9.4. rl.set_queue
+        9.5. rl.get_queues
+        9.6. rl.set_pid
+        9.7. rl.get_pid
+        9.8. rl.push_load
+        9.9. rl.set_dbg
+
+   10. Known limitations
 
 1. Overview
 
@@ -621,7 +645,133 @@ sercmd cfg.set_now_string ratelimit reply_reason "Limiting"
                 1
                 _empty_line_
 
-9. Known limitations
+9. Exported RPC Functions
+
+   9.1. rl.stats
+   9.2. rl.set_pipe
+   9.3. rl.get_pipes
+   9.4. rl.set_queue
+   9.5. rl.get_queues
+   9.6. rl.set_pid
+   9.7. rl.get_pid
+   9.8. rl.push_load
+   9.9. rl.set_dbg
+
+9.1.  rl.stats
+
+   Lists the parameters and variabiles in the ratelimit module.
+
+   Name: rl.stats
+
+   Parameters: none
+
+   RPC Command Format:
+                serctl rl.stats
+
+9.2.  rl.set_pipe
+
+   Sets the pipe parameters for the given pipe id.
+
+   Name: rl.set_pipe
+
+   Parameters:
+     * pipe_id - pipe id.
+     * pipe_algorithm - the algorithm assigned to the given pipe id.
+     * pipe_limit - the limit assigned to the given pipe id.
+
+   RPC Command Format:
+                serctl rl.set_pipe 2 RED 10
+
+9.3.  rl.get_pipes
+
+   Gets the list of in use pipes.
+
+   Name: rl.get_pipes
+
+   Parameters: none
+
+   RPC Command Format:
+                serctl rl.get_pipes
+
+9.4.  rl.set_queue
+
+   Sets the queue parameters for the given queue id.
+
+   Name: rl.set_queue
+
+   Parameters:
+     * queue_id - queue id.
+     * queue_method - the method assigned to the given queue id.
+     * pipe_id - the pipe id assigned to the given queue id.
+
+   RPC Command Format:
+                serctl rl.set_queue 3 INVITE 2
+
+9.5.  rl.get_queues
+
+   Gets the list of in use queues.
+
+   Name: rl.get_queues
+
+   Parameters: none
+
+   RPC Command Format:
+                serctl rl.get_queues
+
+9.6.  rl.set_pid
+
+   Sets the PID Controller parameters for the Feedback Algorithm.
+
+   Name: rl.set_pid
+
+   Parameters:
+     * ki - the integral parameter.
+     * kp - the proportional parameter.
+     * kd - the derivative parameter.
+
+   RPC Command Format:
+                serctl rl.set_pid 0.5 0.5 0.5
+
+9.7.  rl.get_pid
+
+   Gets the list of in use PID Controller parameters.
+
+   Name: rl.get_pid
+
+   Parameters: none
+
+   RPC Command Format:
+                serctl rl.get_pid
+
+9.8.  rl.push_load
+
+   Force the value of the load parameter. This methos is usefull for
+   testing the Feedback algorithm.
+
+   Name: rl.push_load
+
+   Parameters:
+     * load - the forced value of load (it must be greater then 0.0 and
+       smaller then 1.0).
+
+   RPC Command Format:
+                serctl rl.push_load 0.85
+
+9.9.  rl.set_dbg
+
+   This MI function will enable/disable a WARNING debug log exposing the
+   internal counters for each pipe (useful in monitoring the ratelimit
+   internals).
+
+   Name: rl.set_dbg
+
+   Parameters:
+     * dbg - the debug value (0 means disable and 1 means enable).
+
+   RPC Command Format:
+                serctl rl.set_dbg 1
+
+10. Known limitations
 
    The pipes and queues are stored as static vectors, so no more than
    MAX_PIPES/MAX_QUEUES can be added without recompilation.

+ 1 - 1
modules_k/ratelimit/doc/ratelimit.xml

@@ -61,7 +61,7 @@
 		<holder>Freenet Cityline GmbH</holder>
 	</copyright>
 	<copyright>
-		<year>2008-2009</year>
+		<year>2008-2010</year>
 		<holder>VoIP Embedded Inc.</holder>
 	</copyright>
 	<revhistory>

+ 218 - 1
modules_k/ratelimit/doc/ratelimit_admin.xml

@@ -706,7 +706,224 @@ sercmd cfg.set_now_string ratelimit reply_reason "Limiting"
 		</programlisting>
 	</section>
 	</section>
-	
+
+	<section>
+	<title>Exported RPC Functions</title>
+	<section>
+		<title>
+		<function moreinfo="none">rl.stats</function>
+		</title>
+		<para>
+		Lists the parameters and variabiles in the ratelimit module.
+		</para>
+		<para>
+		Name: <emphasis>rl.stats</emphasis>
+		</para>
+		<para>Parameters: <emphasis>none</emphasis></para>
+		<para>
+		RPC Command Format:
+		</para>
+		<programlisting  format="linespecific">
+		serctl rl.stats
+		</programlisting>
+	</section>
+	<section>
+		<title>
+		<function moreinfo="none">rl.set_pipe</function>
+		</title>
+		<para>
+		Sets the pipe parameters for the given pipe id.
+		</para>
+		<para>
+		Name: <emphasis>rl.set_pipe</emphasis>
+		</para>
+		<para>Parameters:</para>
+		<itemizedlist>
+			<listitem><para>
+			<emphasis>pipe_id</emphasis> - pipe id.
+			</para></listitem>
+			<listitem><para>
+			<emphasis>pipe_algorithm</emphasis> - the
+			algorithm assigned to the given pipe id.
+			</para></listitem>
+			<listitem><para>
+			<emphasis>pipe_limit</emphasis> - the limit
+			assigned to the given pipe id.
+			</para></listitem>
+		</itemizedlist>
+		<para>
+		RPC Command Format:
+		</para>
+		<programlisting  format="linespecific">
+		serctl rl.set_pipe 2 RED 10
+		</programlisting>
+	</section>
+	<section>
+		<title>
+		<function moreinfo="none">rl.get_pipes</function>
+		</title>
+		<para>
+		Gets the list of in use pipes.
+		</para>
+		<para>
+		Name: <emphasis>rl.get_pipes</emphasis>
+		</para>
+		<para>Parameters: <emphasis>none</emphasis></para>
+		<para>
+		RPC Command Format:
+		</para>
+		<programlisting  format="linespecific">
+		serctl rl.get_pipes
+		</programlisting>
+	</section>
+	<section>
+		<title>
+		<function moreinfo="none">rl.set_queue</function>
+		</title>
+		<para>
+		Sets the queue parameters for the given queue id.
+		</para>
+		<para>
+		Name: <emphasis>rl.set_queue</emphasis>
+		</para>
+		<para>Parameters:</para>
+		<itemizedlist>
+			<listitem><para>
+			<emphasis>queue_id</emphasis> - queue id.
+			</para></listitem>
+			<listitem><para>
+			<emphasis>queue_method</emphasis> - the method
+			assigned to the given queue id.
+			</para></listitem>
+			<listitem><para>
+			<emphasis>pipe_id</emphasis> - the pipe id
+			assigned to the given queue id.
+			</para></listitem>
+		</itemizedlist>
+		<para>
+		RPC Command Format:
+		</para>
+		<programlisting  format="linespecific">
+		serctl rl.set_queue 3 INVITE 2
+		</programlisting>
+	</section>
+	<section>
+		<title>
+		<function moreinfo="none">rl.get_queues</function>
+		</title>
+		<para>
+		Gets the list of in use queues.
+		</para>
+		<para>
+		Name: <emphasis>rl.get_queues</emphasis>
+		</para>
+		<para>Parameters: <emphasis>none</emphasis></para>
+		<para>
+		RPC Command Format:
+		</para>
+		<programlisting  format="linespecific">
+		serctl rl.get_queues
+		</programlisting>
+	</section>
+	<section>
+		<title>
+		<function moreinfo="none">rl.set_pid</function>
+		</title>
+		<para>
+		Sets the PID Controller parameters for the Feedback Algorithm.
+		</para>
+		<para>
+		Name: <emphasis>rl.set_pid</emphasis>
+		</para>
+		<para>Parameters:</para>
+		<itemizedlist>
+			<listitem><para>
+			<emphasis>ki</emphasis> - the integral parameter.
+			</para></listitem>
+			<listitem><para>
+			<emphasis>kp</emphasis> - the proportional parameter.
+			</para></listitem>
+			<listitem><para>
+			<emphasis>kd</emphasis> - the derivative parameter.
+			</para></listitem>
+		</itemizedlist>
+		<para>
+		RPC Command Format:
+		</para>
+		<programlisting  format="linespecific">
+		serctl rl.set_pid 0.5 0.5 0.5
+		</programlisting>
+	</section>
+	<section>
+		<title>
+		<function moreinfo="none">rl.get_pid</function>
+		</title>
+		<para>
+		Gets the list of in use PID Controller parameters.
+		</para>
+		<para>
+		Name: <emphasis>rl.get_pid</emphasis>
+		</para>
+		<para>Parameters: <emphasis>none</emphasis></para>
+		<para>
+		RPC Command Format:
+		</para>
+		<programlisting  format="linespecific">
+		serctl rl.get_pid
+		</programlisting>
+	</section>
+	<section>
+		<title>
+		<function moreinfo="none">rl.push_load</function>
+		</title>
+		<para>
+		Force the value of the load parameter.  This methos is usefull
+		for testing the Feedback algorithm.
+		</para>
+		<para>
+		Name: <emphasis>rl.push_load</emphasis>
+		</para>
+		<para>Parameters:</para>
+		<itemizedlist>
+			<listitem><para>
+			<emphasis>load</emphasis> - the forced value of load
+			(it must be greater then 0.0 and smaller then 1.0).
+			</para></listitem>
+		</itemizedlist>
+		<para>
+		RPC Command Format:
+		</para>
+		<programlisting  format="linespecific">
+		serctl rl.push_load 0.85
+		</programlisting>
+	</section>
+	<section>
+		<title>
+		<function moreinfo="none">rl.set_dbg</function>
+		</title>
+		<para>
+		This MI function will enable/disable a WARNING debug log exposing the
+		internal counters for each pipe (useful in monitoring the ratelimit internals).
+		</para>
+		<para>
+		Name: <emphasis>rl.set_dbg</emphasis>
+		</para>
+		<para>Parameters:</para>
+		<itemizedlist>
+			<listitem><para>
+			<emphasis>dbg</emphasis> - the debug value (0 means disable and
+			1 means enable).
+			</para></listitem>
+		</itemizedlist>
+		<para>
+		RPC Command Format:
+		</para>
+		<programlisting  format="linespecific">
+		serctl rl.set_dbg 1
+		</programlisting>
+	</section>
+	</section>
+
 	<section>
 	<title>Known limitations</title>
 	<para>

+ 245 - 2
modules_k/ratelimit/ratelimit.c

@@ -4,7 +4,7 @@
  * ratelimit module
  *
  * Copyright (C) 2006 Hendrik Scholz <[email protected]>
- * Copyright (C) 2008 Ovidiu Sas <[email protected]>
+ * Copyright (C) 2008-2010 Ovidiu Sas <[email protected]>
  *
  * This file is part of Kamailio, a free SIP server.
  *
@@ -26,7 +26,8 @@
  * ---------
  *
  * 2008-01-10 ported from SER project (osas)
- * 2008-01-16 ported enhancements from openims project (osas) 
+ * 2008-01-16 ported enhancements from openims project (osas)
+ * 2020-04-28 add sip-router rpc interface (osas)
  */
 
 #include <stdio.h>
@@ -51,6 +52,7 @@
 #include "../sl/sl_api.h"
 #include "../../lib/kcore/km_ut.h"
 #include "../../lib/kmi/mi.h"
+#include "../../rpc_lookup.h"
 
 #include "config.h"
 
@@ -264,6 +266,8 @@ static mi_export_t mi_cmds [] = {
 	{0,0,0,0,0}
 };
 
+static rpc_export_t rpc_methods[];
+
 /** module exports */
 struct module_exports exports= {
 	"ratelimit",
@@ -441,6 +445,11 @@ static int mod_init(void)
 		return -1;
 	}
 
+	if (rpc_register_array(rpc_methods)!=0) {
+		LM_ERR("failed to register RPC commands\n");
+		return -1;
+	}
+
 	rl_lock = lock_alloc();
 	if (! rl_lock) {
 		LM_ERR("oom in lock_alloc()\n");
@@ -1577,3 +1586,237 @@ bad_syntax:
 	return init_mi_tree( 400, MI_BAD_PARM_S, MI_BAD_PARM_LEN);
 }
 
+
+/* rpc function documentation */
+static const char *rpc_stats_doc[2] = {
+	"Print ratelimit statistics: PIPE[<pipe_id>]: \
+<last_counter>/<pipe_limit> (drop rate: <drop_rate>)", 0
+};
+
+static const char *rpc_get_pipes_doc[2] = {
+	"Print pipes info: PIPE[<pipe_id>]: \
+<pipe_algo_id>:<pipe_algo> <last_counter>/<pipe_limit> (drop rate: <drop_rate>) [<current_counter>]", 0
+};
+
+static const char *rpc_set_pipe_doc[2] = {
+	"Sets a pipe params: <pipe_id> <pipe_algorithm> <pipe_limit>", 0
+};
+
+static const char *rpc_get_queues_doc[2] = {
+	"Print queues info: QUEUE[queue_id]: <pipe_id>:<queue_method>", 0
+};
+
+static const char *rpc_set_queue_doc[2] = {
+	"Sets queue params: <quue_id> <queue_method> <pipe_id>", 0
+};
+
+static const char *rpc_get_pid_doc[2] = {
+	"Print PID Controller parameters for the FEEDBACK algorithm: \
+<ki> <kp> <kd>", 0
+};
+
+static const char *rpc_set_pid_doc[2] = {
+	"Sets the PID Controller parameters for the FEEDBACK algorithm: \
+<ki> <kp> <kd>", 0
+};
+
+static const char *rpc_push_load_doc[2] = {
+	"Force the value of the load parameter for FEEDBACK algorithm: \
+<load>", 0
+};
+
+static const char *rpc_set_dbg_doc[2] = {
+	"Sets the ratelimit debug/monitoing logs: 0-off 1-on", 0
+};
+
+
+/* rpc function implementations */
+static void rpc_stats(rpc_t *rpc, void *c) {
+	int i;
+
+	LOCK_GET(rl_lock);
+	for (i=0; i<MAX_PIPES; i++) {
+		if (rpc->printf(c, "PIPE[%d]: %d/%d (drop rate: %d)",
+			i, *pipes[i].last_counter, *pipes[i].limit,
+			*pipes[i].load) < 0) goto error;
+	}
+error:
+	LOCK_RELEASE(rl_lock);
+}
+
+static void rpc_get_pipes(rpc_t *rpc, void *c) {
+	str algo;
+	int i;
+
+	LOCK_GET(rl_lock);
+	for (i=0; i<MAX_PIPES; i++) {
+		if (*pipes[i].algo != PIPE_ALGO_NOP) {
+			if (str_map_int(algo_names, *pipes[i].algo, &algo))
+				goto error;
+			if (rpc->printf(c, "PIPE[%d]: %d:%.*s %d/%d (drop rate: %d) [%d]",
+				i, *pipes[i].algo, algo.len, algo.s,
+				*pipes[i].last_counter, *pipes[i].limit,
+				*pipes[i].load, *pipes[i].counter) < 0) goto error;
+		}
+	}
+error:
+	LOCK_RELEASE(rl_lock);
+}
+
+static void rpc_set_pipe(rpc_t *rpc, void *c) {
+	int pipe_no = MAX_PIPES, algo_id, limit = 0;
+	str algo_str;
+
+	if (rpc->scan(c, "dSd", &pipe_no, &algo_str, &limit) < 3) return;
+
+	if (str_map_str(algo_names, &algo_str, &algo_id)) {
+		LM_ERR("unknown algorithm: '%.*s'\n", algo_str.len, algo_str.s);
+		rpc->fault(c, 400, "Unknown algorithm");
+		return;
+	}
+
+	LM_DBG("set_pipe: %d:%d:%d\n", pipe_no, algo_id, limit);
+
+	if (pipe_no >= MAX_PIPES || pipe_no < 0) {
+		LM_ERR("wrong pipe_no: %d\n", pipe_no);
+		rpc->fault(c, 400, "Unknown pipe");
+		return;
+	}
+
+	LOCK_GET(rl_lock);
+	*pipes[pipe_no].algo = algo_id;
+	*pipes[pipe_no].limit = limit;
+
+	if (check_feedback_setpoints(0)) {
+		LM_ERR("feedback limits don't match\n");
+		rpc->fault(c, 400, "Feedback limits don't match");
+	} else {
+		*pid_setpoint = 0.01 * (double)cfg_setpoint;
+	}
+
+	LOCK_RELEASE(rl_lock);
+}
+
+static void rpc_get_queues(rpc_t *rpc, void *c) {
+	int i;
+
+	LOCK_GET(rl_lock);
+	for (i=0; i<MAX_QUEUES; i++) {
+		if (queues[i].pipe) {
+			if (rpc->printf(c, "QUEUE[%d]: %d:%.*s",
+				i, *queues[i].pipe,
+				(*queues[i].method).len,
+				(*queues[i].method).s) < 0) goto error;
+		}
+	}
+error:
+	LOCK_RELEASE(rl_lock);
+}
+
+static void rpc_set_queue(rpc_t *rpc, void *c) {
+	unsigned int queue_no = MAX_QUEUES, pipe_no = MAX_PIPES;
+	str method, method_buf;
+
+
+	if (rpc->scan(c, "dSd", &queue_no, &method, &pipe_no) < 3) return;
+
+	if (pipe_no >= MAX_PIPES || pipe_no < 0) {
+		LM_ERR("Invalid pipe number: %d\n", pipe_no);
+		rpc->fault(c, 400, "Invalid pipe number");
+		return;
+	}
+
+	if (str_cpy(&method_buf, &method)) {
+		LM_ERR("out of memory\n");
+		rpc->fault(c, 400, "OOM");
+		return;
+	}
+
+	LOCK_GET(rl_lock);
+	if (queue_no >= *nqueues) {
+		LM_ERR("MAX_QUEUES reached for queue: %d\n", queue_no);
+		rpc->fault(c, 400, "MAX_QUEUES reached");
+		LOCK_RELEASE(rl_lock);
+		return;
+	}
+
+	*queues[queue_no].pipe = pipe_no;
+	if (!queues[queue_no].method->s)
+		shm_free(queues[queue_no].method->s);
+	queues[queue_no].method->s = method_buf.s;
+	queues[queue_no].method->len = method_buf.len;
+	LOCK_RELEASE(rl_lock);
+}
+
+static void rpc_get_pid(rpc_t *rpc, void *c) {
+	rpc->printf(c, "ki[%f] kp[%f] kd[%f] ", *pid_ki, *pid_kp, *pid_kd);
+}
+
+static void rpc_set_pid(rpc_t *rpc, void *c) {
+	double ki, kp, kd;
+
+	if (rpc->scan(c, "fff", &ki, &kp, &kd) < 3) return;
+
+	LOCK_GET(rl_lock);
+	*pid_ki = ki;
+	*pid_kp = kp;
+	*pid_kd = kd;
+	LOCK_RELEASE(rl_lock);
+}
+
+
+static void rpc_push_load(rpc_t *rpc, void *c) {
+	double value;
+
+	if (rpc->scan(c, "f", &value) < 1) return;
+
+	if (value < 0.0 || value > 1.0) {
+		LM_ERR("value out of range: %0.3f in not in [0.0,1.0]\n", value);
+		rpc->fault(c, 400, "Value out of range");
+		return;
+	}
+	LOCK_GET(rl_lock);
+	*load_value = value;
+	LOCK_RELEASE(rl_lock);
+
+	do_update_load();
+}
+
+static void rpc_set_dbg(rpc_t *rpc, void *c) {
+	int dbg_mode = 0;
+
+	if (rpc->scan(c, "d", &dbg_mode) < 1) return;
+
+	LOCK_GET(rl_lock);
+	if (dbg_mode) {
+		if (!rl_dbg_str->s) {
+			rl_dbg_str->len = (MAX_PIPES * 5 * sizeof(char));
+			rl_dbg_str->s = (char *)shm_malloc(rl_dbg_str->len);
+			if (!rl_dbg_str->s) {
+				rl_dbg_str->len = 0;
+				LM_ERR("oom: %d\n", rl_dbg_str->len);
+			}
+		}
+	} else {
+		if (rl_dbg_str->s) {
+			shm_free(rl_dbg_str->s);
+			rl_dbg_str->s = NULL;
+			rl_dbg_str->len = 0;
+		}
+	}
+	LOCK_RELEASE(rl_lock);
+}
+
+static rpc_export_t rpc_methods[] = {
+	{"rl.stats",		rpc_stats,	rpc_stats_doc,		0},
+	{"rl.get_pipes",	rpc_get_pipes,	rpc_get_pipes_doc,	0},
+	{"rl.set_pipe",		rpc_set_pipe,	rpc_set_pipe_doc,	0},
+	{"rl.get_queues",	rpc_get_queues,	rpc_get_queues_doc,	0},
+	{"rl.set_queue",	rpc_set_queue,	rpc_set_queue_doc,	0},
+	{"rl.get_pid",		rpc_get_pid,	rpc_get_pid_doc,	0},
+	{"rl.set_pid",		rpc_set_pid,	rpc_set_pid_doc,	0},
+	{"rl.push_load",	rpc_push_load,	rpc_push_load_doc,	0},
+	{"rl.set_dbg",		rpc_set_dbg,	rpc_set_dbg_doc,	0},
+	{0, 0, 0, 0}
+};
+