<!-- Module User's Guide -->

<chapter>

	<title>&adminguide;</title>

	<section id="overview" xreflabel="Overview">
	<title>Overview</title>
	<para>
		This module implements rate limiting for SIP requests. In contrast to
		the PIKE module this limits the flow based on a per SIP request type
		basis and not per source IP. The latest sources allow you to
		dynamically group several messages into some entities and limit the
		traffic based on them. The MI interface can be used to change
		tunables while running OpenSIPS.
	</para>
	<para>
		This module is integrated with the &osips; Key-Value Interface,
		providing support for distributed rate limiting using Redis or Memcached
		CacheDB backends. The internal limiting data will no longer be kept on each
		&osips; instance. It will be stored in the distributed Key-Value database
		and queried by each instance before deciding if a SIP message should be
		blocked or not.
	</para>
	<para>
		To achieve a distributed ratelimit feature, the module can also replicate
		its pipes counters to different &osips; instances using the clusterer module.
		To do that, define the <emphasis>pipe_replication_cluster</emphasis> parameter
		in your configuration script.
	</para>
	<para>
		Starting with &osips; 3.2, choosing whether to replicate a pipe over
		CacheDB backends or bin replication is triggered by the flags specified
		when the pipe is created: adding the <emphasis>/r</emphasis> suffix to the
		pipe's name will replicate through CacheDB, and adding <emphasis>/b</emphasis>
		will replicate through bin/clusterer.
	</para>
	</section>
	<section>
	<title>Use Cases</title>
	<para>
		Limiting the rate messages are processed on a system directly
		influences the load. The ratelimit module can be used to protect a
		single host or to protect an OpenSIPS cluster when run on the
		dispatching box in front.
	</para>
	<para>
		Distributed limiting is useful when the rate limit should be
		performed not only on a specific node, but on the entire platform.
	</para>
	<para>
		NOTE: that this behavior only makes sense when the pipe algorithm
		used is TAILDROP or RED.
	</para>
	<para>
		A sample configuration snippet might look like this:
	</para>
	<programlisting format="linespecific">
...
	if (!rl_check($rU, 50, "TAILDROP")) {
		sl_send_reply(503, "Server Unavailable");
		exit;
	};
...
	</programlisting>
	<para>
		Upon every incoming request listed above rl_check is invoked and
		the entity identified by the R-URI user is checked. It
		returns an OK code if the current per request load is below the
		configured threshold. If the load is exceeded the function returns an
		error and an administrator can discard requests with a stateless
		response.
	</para>
	</section>
	<section>
	<title>Static Rate Limiting Algorithms</title>
	<para>
		The ratelimit module supports two different static algorithms
		to be used by rl_check to determine whether a message should be
		blocked or not.
	</para>
	<section>
		<title>Tail Drop Algorithm (TAILDROP)</title>
		<para>
		This is a trivial algorithm that imposes some risks when used in
		conjunction with long timer intervals. At the start of each interval
		an internal counter is reset and incremented for each incoming
		message. Once the counter hits the configured limit rl_check returns
		an error.
		</para>
		<para>
		The downside of this algorithm is that it can lead to SIP client
		synchronization. During a relatively long interval only the first
		requests (i.e. REGISTERs) would make it through. Following messages
		(i.e. RE-REGISTERs) will all hit the SIP proxy at the same time when a
		common Expire timer expired. Other requests will be retransmissed
		after given time, the same on all devices with the same firmware/by
		the same vendor.
		</para>
	</section>
	<section>
		<title>Random Early Detection Algorithm (RED)</title>
		<para>
		Random Early Detection tries to circumvent the synchronization problem
		imposed by the tail drop algorithm by measuring the average load and
		adapting the drop rate dynamically. When running with the RED
		algorithm OpenSIPS will return errors to the OpenSIPS
		routing engine every n'th packet trying to evenly spread the measured
		load of the last timer interval onto the current interval. As a
		negative side effect OpenSIPS might drop messages although the limit might
		not be reached within the interval. Decrease the timer interval if you
		encounter this.
		</para>
	</section>
	<section>
		<title>Slot Based Taildropping (SBT) </title>
		<para>
			SBT holds a window consisting of one or more slots. You can set the
			<emphasis>window_size</emphasis> parameter(seconds) which means for
			how long we should look back to count the calls and
			<emphasis>slot_period</emphasis> parameter(miliseconds) which tells
			how granular the algorithm should be. The number of slots will be
			<emphasis>window_size</emphasis>/<emphasis>slot_period</emphasis>.
			If, for example, you have <emphasis>window_size</emphasis>=
			<emphasis>slot_period</emphasis>=1 second, then after each second
			you shall lose the call count, but if you set the
			<emphasis>slot_period</emphasis> to 100 milliseconds, then when your
			call will be outside the window, the calls in the first 100 milliseconds
			shall be dropped, and the rest in the next 900 shall be kept.
		</para>
	</section>
	<section>
		<title>Network Algorithm (NETWORK)</title>
		<para>
		This algorithm relies on information provided by network interfaces.
		The total amount of bytes waiting to be consumed on all the network
		interfaces is retrieved once every timer_interval seconds.
		If the returned amount exceeds the limit specified in the modparam,
		rl_check returns an error.
		</para>
	</section>
	</section>
	<section>
	<title>Dynamic Rate Limiting Algorithms</title>
	<para>
		When running &osips; on different machines, one has to adjust the drop
		rates for the static algorithms to maintain a sub 100% load average or
		packets start getting dropped in the network stack.  While this is not
		in itself difficult, it isn't neither accurate nor trivial: another
		server taking a notable fraction of the cpu time will require re-tuning
		the parameters.
	</para>
	<para>
		While tuning the drop rates from the outside based on a certain factor
		is possible, having the algorithm run inside ratelimit permits tuning
		the rates based on internal server parameters and is somewhat more
		flexible (or it will be when support for external load factors - as
		opposed to cpu load - is added).
	</para>
	<section>
		<title>Feedback Algorithm (FEEDBACK)</title>
		<para>
		Using the PID Controller model
		(see <ulink url='http://en.wikipedia.org/wiki/PID_controller'>Wikipedia page</ulink>),
		the drop rate is adjusted dynamically based on the load factor so that
		the load factor always drifts towards the specified limit (or setpoint,
		in PID terms).
		</para>
		<para>
		As reading the cpu load average is relatively expensive (opening /proc/stat,
		parsing it, etc), this only happens once every timer_interval seconds and
		consequently the FEEDBACK value is only at these intervals recomputed. This
		in turn makes it difficult for the drop rate to adjust quickly.  Worst case
		scenarios are request rates going up/down instantly by thousands - it takes
		up to 20 seconds for the controller to adapt to the new request rate.
		</para>
		<para>
		Generally though, as real life request rates drift by less, adapting should
		happen much faster.
		</para>
		<para>
		IMPORTANT NOTE: as this algorithm is diven by the load factor, the values
		for the limits must be between 0 and 100 (as percentages) and the limits
		for all the checks and pipes must be the same (only one value). Again, this
		limitation are specific to this algorithm and not to the implementation.
		</para>
	</section>
	</section>
	<section id="dependencies" xreflabel="Dependencies">
	<title>Dependencies</title>
	<section>
		<title>&osips; Modules</title>
		<para>
		The following modules must be loaded before this module:
			<itemizedlist>
			<listitem>
			<para>
				<emphasis>No dependencies on other &osips; modules</emphasis>.
			</para>
			</listitem>
			</itemizedlist>
		</para>
	</section>
	<section>
		<title>External Libraries or Applications</title>
		<para>
		The following libraries or applications must be installed before
		running &osips; with this module loaded:
			<itemizedlist>
			<listitem>
			<para>
				<emphasis>None</emphasis>.
			</para>
			</listitem>
			</itemizedlist>
		</para>
	</section>
	</section>
	<section id="exported_parameters" xreflabel="Exported Parameters">
	<title>Exported Parameters</title>
	<section id="param_timer_interval" xreflabel="timer_interval">
		<title><varname>timer_interval</varname> (integer)</title>
		<para>
			The timer interval in seconds when the Network and Feedback algorithms
			run their queries, and the other algorithms reset their counters.
		</para>
		<para>
		IMPORTANT: A too small value may lead to performance penalties due to
		timer process overloading.
		</para>
		<para>
		<emphasis>
			Default value is 10.
		</emphasis>
		</para>
		<example>
		<title>Set <varname>timer_interval</varname> parameter</title>
		<programlisting format="linespecific">
...
modparam("ratelimit", "timer_interval", 5)
...
</programlisting>
		</example>
	</section>

	<section id="param_limit_per_interval" xreflabel="limit_per_interval">
		<title><varname>limit_per_interval</varname> (integer)</title>
		<para>
			This parameter configures the way that a pipe's limit is specified
			in the <emphasis>rl_check</emphasis> function and only affects the
			Taildrop and RED algorithms. A value of 1 means that the limit is
			set per-<emphasis>timer_interval</emphasis> while a value of 0 means per-second.
		</para>
		<para>
		<emphasis>
			Default value is 0(limit per-second).
		</emphasis>
		</para>
		<example>
		<title>Set <varname>limit_per_interval</varname> parameter</title>
		<programlisting format="linespecific">
...
modparam("ratelimit", "limit_per_interval", 1)
...
</programlisting>
		</example>
	</section>

	<section id="param_expire_time" xreflabel="expire_time">
		<title><varname>expire_time</varname> (integer)</title>
		<para>
		This parameter specifies how long a pipe should be kept in memory
		after it becomes idle (no more operations are performed on the pipe)
		until deleted.
		</para>
		<para>
		<emphasis>
			Default value is 3600.
		</emphasis>
		</para>
		<example>
		<title>Set <varname>expire_time</varname> parameter</title>
		<programlisting format="linespecific">
...
modparam("ratelimit", "expire_time", 1800)
...
</programlisting>
		</example>
	</section>
	<section id="param_hash_size" xreflabel="hash_size">
		<title><varname>hash_size</varname> (integer)</title>
		<para>
		The size of the hash table internally used to keep the pipes.
		A larger table is much faster but consumes more memory. The hash size
		must be a power of 2 number.
		</para>
		<para>
		<emphasis>
			Default value is 1024.
		</emphasis>
		</para>
		<example>
		<title>Set <varname>hash_size</varname> parameter</title>
		<programlisting format="linespecific">
...
modparam("ratelimit", "hash_size", 512)
...
</programlisting>
		</example>
	</section>
	<section id="param_default_algorithm" xreflabel="default_algorithm">
		<title><varname>default_algorithm</varname> (string)</title>
		<para>
		Specifies which algorithm should be assumed in case it isn't
		explicitly specified in the <emphasis>rl_check</emphasis> function.
		</para>
		<para>
		<emphasis>
			Default value is "TAILDROP".
		</emphasis>
		</para>
		<example>
		<title>Set <varname>default_algorithm</varname> parameter</title>
		<programlisting format="linespecific">
...
modparam("ratelimit", "default_algorithm", "RED")
...
</programlisting>
		</example>
	</section>
	<section id="param_cachedb_url" xreflabel="cachedb_url">
		<title><varname>cachedb_url</varname> (string)</title>
		<para>
		Enables distributed rate limiting and specifies the backend
		that should be used by the CacheDB interface.
		</para>
		<para>
		<emphasis>
			Default value is "disabled".
		</emphasis>
		</para>
		<example>
		<title>Set <varname>cachedb_url</varname> parameter</title>
		<programlisting format="linespecific">
...
modparam("ratelimit", "cachedb_url", "redis://root:root@127.0.0.1/")
...
</programlisting>
		</example>
	</section>
	<section id="param_db_prefix" xreflabel="db_prefix">
		<title><varname>db_prefix</varname> (string)</title>
		<para>
		Specifies what prefix should be added to the pipe name. This is
		only used when distributed rate limiting is enabled.
		</para>
		<para>
		<emphasis>
			Default value is "rl_pipe_".
		</emphasis>
		</para>
		<example>
		<title>Set <varname>db_prefix</varname> parameter</title>
		<programlisting format="linespecific">
...
modparam("ratelimit", "db_prefix", "ratelimit_")
...
</programlisting>
		</example>
	</section>
	<section id="param_repl_buffer_threshold" xreflabel="repl_buffer_threshold">
		<title><varname>repl_buffer_threshold</varname> (string)</title>
		<para>
		Used to specify the length of the buffer used by the binary
		replication, in bytes, when a flush should be performed - the pipes
		gathered until then should be sent on the network. This is used
		to avoid using large amount of memory for pipes replication.
		</para>
		<para>
		<emphasis>
			Default value is 32767 bytes.
		</emphasis>
		</para>
		<example>
		<title>Set <varname>repl_buffer_threshold</varname> parameter</title>
		<programlisting format="linespecific">
...
modparam("ratelimit", "repl_buffer_threshold", 500)
...
</programlisting>
		</example>
	</section>
	<section id="param_repl_timer_interval" xreflabel="repl_timer_interval">
		<title><varname>repl_timer_interval</varname> (string)</title>
		<para>
		Timer in milliseconds, used to specify how often the module
		should replicate its counters to the other instances.
		</para>
		<para>
		<emphasis>
			Default value is 200 ms.
		</emphasis>
		</para>
		<example>
		<title>Set <varname>repl_timer_interval</varname> parameter</title>
		<programlisting format="linespecific">
...
modparam("ratelimit", "repl_timer_interval", 100)
...
</programlisting>
		</example>
	</section>
	<section id="param_repl_timer_expire" xreflabel="repl_timer_expire">
		<title><varname>repl_timer_expire</varname> (string)</title>
		<para>
		Timer in seconds, used to specify when the counter received
		from a different instance should no longer be taken into account.
		This is used to prevent obsolete values, in case an instance stops
		replicating its counters.
		</para>
		<para>
		<emphasis>
			Default value is 10 s.
		</emphasis>
		</para>
		<example>
		<title>Set <varname>repl_timer_expire</varname> parameter</title>
		<programlisting format="linespecific">
...
modparam("ratelimit", "repl_timer_expire", 10)
...
</programlisting>
		</example>
	</section>
	<section id="param_pipe_replication_cluster" xreflabel="pipe_replication_cluster">
		<title><varname>pipe_replication_cluster</varname> (integer)</title>
		<para>
			Specifies the cluster ID where pipes will be replicated to and
			received from.
		</para>
		<para>
		<emphasis>
			Default value is 0. (no replication)
		</emphasis>
		</para>
		<example>
		<title>Set <varname>pipe_replication_cluster</varname> parameter</title>
		<programlisting format="linespecific">
...
modparam("ratelimit", "pipe_replication_cluster", 1)
...
</programlisting>
		</example>
	</section>

        <section id="param_window_size" xreflabel="window_size">
		<title><varname>window_size</varname> (int)</title>
		<para>
			How long the history in SBT should be in seconds.
		</para>
		<para>
		<emphasis>
			Default value is <quote>10</quote>.
		</emphasis>
		</para>
		<example>
		<title>Set <varname>window_size</varname> parameter</title>
		<programlisting format="linespecific">
...
modparam("ratelimit", "window_size", 5)
...
</programlisting>
		</example>
	</section>

        <section id="param_slot_period" xreflabel="slot_period">
		<title><varname>slot_period</varname> (int)</title>
		<para>
			Value of one slot in milliseconds. This parameter determines
		how granular the algorithm should be. The number of slots will be
		determined by window_size/slot_period.
		</para>
		<para>
		<emphasis>
			Default value is <quote>200</quote>.
		</emphasis>
		</para>
		<example>
		<title>Set <varname>slot_period</varname> parameter</title>
		<programlisting format="linespecific">
...
modparam("ratelimit", "window_size", 5)
#we will have 50 slots of 100 milliseconds
modparam("ratelimit", "slot_period", 100)
...
</programlisting>
		</example>
	</section>



	</section>
	<section id="exported_functions" xreflabel="exported_functions">
	<title>Exported Functions</title>
	<section id="func_rl_check" xreflabel="rl_check()">
		<title>
			<function moreinfo="none">rl_check(name, limit[, algorithm])
			</function>
		</title>
		<para>
		Check the current request against the pipe identified by name and
		changes/updates the limit. If no pipe is found, then a new one is
		created with the specified limit and algorithm, if specified. If the
		algorithm parameter doesn't exist, the default one is used.
		</para>
		<para>
		NOTE: A pipe's algorithm cannot be dynamically changed. Only the one
		specified when the pipe was created will be considered.
		</para>
		<para>
		NOTE: This function increments the pipe's counter every time it is
		called, even if the call should be declined. Therefore If you are using
		ratelimit to limit only successful traffic, you need to explicitely
		decrease the counter for the declined calls using the
		<emphasis>rl_dec_count()</emphasis> function.
		</para>
		<para>
		The method will return an error code if the limit for the
		matched pipe is reached.
		</para>
		<para>Meaning of the parameters is as follows:</para>
		<itemizedlist>
			<listitem>
				<para>
				<emphasis>name</emphasis> (string) - this is the name that identifies
				the pipe which should be checked. One can also specify the
				<emphasis>/s</emphasis> suffix to indicate the pipe
				should be replicated over cached, or <emphasis>/b</emphasis>
				to replicate over bin/clusterer interface.
				</para>
			</listitem>
			<listitem>
				<para>
				<emphasis>limit</emphasis> (int) - this specifies the threshold
				limit of the pipe. It is strongly related to the algorithm
				used. Note that the limit should be specified as per-second, not
				per-timer_interval.
				</para>
			</listitem>
			<listitem>
				<para>
				<emphasis>algorithm</emphasis> (string, optional) - this parameter
				reffers to the algorithm used to check the pipe. If it is
				not set, the default value is used.
				</para>
			</listitem>

		</itemizedlist>
		<para>
			This function can be used from REQUEST_ROUTE, FAILURE_ROUTE, ONREPLY_ROUTE,
			BRANCH_ROUTE, ERROR_ROUTE, LOCAL_ROUTE, TIMER_ROUTE and EVENT_ROUTE.
		</para>
		<example>
		<title><function>rl_check</function> usage</title>
		<programlisting format="linespecific">
...
	# perform a pipe match for all INVITE methods using RED algorithm
	if (is_method("INVITE")) {
		if (!rl_check("pipe_INVITE", 100, "RED")) {
			sl_send_reply(503, "Server Unavailable");
			exit;
		};
	};
...
	# use default algorithm for each different gateway
	$var(limit) = 10;
	if (!rl_check("gw_$ru", $var(limit))) {
		sl_send_reply(503, "Server Unavailable");
		exit;
	};
...
	# count only successful calls
	if (!rl_check("gw_$ru", 100)) {
		rl_dec_count("gw_$ru");
		sl_send_reply(503, "Server Unavailable");
		exit;
	};
...
</programlisting>
		</example>
	</section>
	<section id="func_rl_dec_count" xreflabel="rl_dec_count()">
		<title>
		<function moreinfo="none">rl_dec_count(name)</function>
		</title>
		<para>
		This function decreases a counter that could have been previously
		increased by <emphasis>rl_check</emphasis> function.
		</para>
		<para>Meaning of the parameters is as follows:</para>
		<itemizedlist>
			<listitem><para>
			<emphasis>name</emphasis> (string) - identifies the name of the pipe.
			</para>
			</listitem>
		</itemizedlist>
		<para>
			This function can be used from REQUEST_ROUTE, FAILURE_ROUTE, ONREPLY_ROUTE,
			BRANCH_ROUTE, ERROR_ROUTE, LOCAL_ROUTE, TIMER_ROUTE and EVENT_ROUTE.
		</para>
		<example>
		<title><function>rl_dec_count</function> usage</title>
		<programlisting format="linespecific">
...
	if (!rl_check("gw_$ru", 100, "TAILDROP")) {
		exit;
	} else {
		rl_dec_count("gw_$ru");
	};
...
</programlisting>
		</example>
	</section>
	<section id="func_rl_reset_count" xreflabel="rl_reset_count()">
		<title>
		<function moreinfo="none">rl_reset_count(name)</function>
		</title>
		<para>
		This function resets a counter that could have been previously
		increased by <emphasis>rl_check</emphasis> function.
		</para>
		<para>Meaning of the parameters is as follows:</para>
		<itemizedlist>
			<listitem><para>
			<emphasis>name</emphasis> - identifies the name of the pipe.
			</para>
			</listitem>
		</itemizedlist>
		<para>
			This function can be used from REQUEST_ROUTE, FAILURE_ROUTE, ONREPLY_ROUTE,
			BRANCH_ROUTE, ERROR_ROUTE, LOCAL_ROUTE, TIMER_ROUTE and EVENT_ROUTE.
		</para>
		<example>
		<title><function>rl_reset_count</function> usage</title>
		<programlisting format="linespecific">
...
	if (!rl_check("gw_$ru", 100, "TAILDROP")) {
		exit;
	} else {
		rl_reset_count("gw_$ru");
	};
...
</programlisting>
		</example>
	</section>

	</section>

	<section id="exported_mi_functions" xreflabel="Exported MI Functions">
	<title>Exported MI Functions</title>
	<section id="mi_rl_list" xreflabel="rl_list">
		<title>
		<function moreinfo="none">rl_list</function>
		</title>
		<para>
		Lists the parameters and variabiles in the ratelimit module.
		</para>
		<para>
		Name: <emphasis>rl_list</emphasis>
		</para>
		<para>Parameters:</para>
		<itemizedlist>
			<listitem><para>
			<emphasis>pipe</emphasis> (optional) - indicates the name of the
			single pipe to be listed.
			</para></listitem>
			<listitem><para>
			<emphasis>filter</emphasis> (optional) - a pattern used to filter
			the active pipes to be listed. The filter is a shell wildcard
			pattern (see glob(7)).
			</para></listitem>
			<listitem><para>
			<emphasis>filter_out</emphasis> (optional) - a pattern used to 
			filter out the active pipes NOT to be listed.
			The filter is a shell wildcard pattern (see glob(7)).
			</para></listitem>
		</itemizedlist>
		<para>
		Note that you cannot combine multiple paramters when calling this
		function. If using parameters, only one is accepted.
		</para>
		<para>
		If no parameter are passed to the function, all the active pipes
		are listed.
		</para>
		<para>
		MI FIFO Command Format:
		</para>
		<programlisting  format="linespecific">
		opensips-cli -x mi rl_list pipe=gw_10.0.0.1
		opensips-cli -x mi rl_list filter=gw_*
		</programlisting>
	</section>
	<section id="mi_rl_dump_pipe" xreflabel="rl_dump_pipe">
		<title>
		<function moreinfo="none">rl_dump_pipe</function>
		</title>
		<para>
		Exposes all the details about the current runtime data (specific to the
		pipe's algorithm) of a pipe. Currently make sense for SBT.
		</para>
		<para>
		Name: <emphasis>rl_dump_pipe</emphasis>
		</para>
		<para>Parameters:</para>
		<itemizedlist>
			<listitem><para>
			<emphasis>pipe</emphasis> - indicates the name of the pipe.
			</para></listitem>
		</itemizedlist>
 		<para>
		MI FIFO Command Format:
		</para>
		<programlisting  format="linespecific">
		opensips-cli -x mi rl_dump_pipe gw_10.0.0.1
		</programlisting>
	</section>
	<section id="mi_rl_reset_pipe" xreflabel="rl_reset_pipe">
		<title>
		<function moreinfo="none">rl_reset_pipe</function>
		</title>
		<para>
		Resets the counter of a specified pipe.
		</para>
		<para>
		Name: <emphasis>rl_reset_pipe</emphasis>
		</para>
		<para>Parameters:</para>
		<itemizedlist>
			<listitem><para>
			<emphasis>pipe</emphasis> - indicates the name of the pipe whose
			counter should be reset.
			</para></listitem>
		</itemizedlist>
		<para>
		MI FIFO Command Format:
		</para>
		<programlisting  format="linespecific">
		opensips-cli -x mi rl_reset_pipe gw_10.0.0.1
		</programlisting>
	</section>
	<section id="mi_rl_set_pid" xreflabel="rl_set_pid">
		<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>
		MI FIFO Command Format:
		</para>
		<programlisting  format="linespecific">
		opensips-cli -x mi rl_set_pid 0.5 0.5 0.5
		</programlisting>
	</section>
	<section id="mi_rl_get_pid" xreflabel="rl_get_pid">
		<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>
		MI FIFO Command Format:
		</para>
		<programlisting  format="linespecific">
		opensips-cli -x mi rl_get_pid
		</programlisting>
	</section>
	<section id="mi_rl_bin_status" xreflabel="rl_bin_status">
		<title>
		<function moreinfo="none">rl_bin_status</function>
		</title>
		<para>
		Dumps each destination used for replication, as well as
		the timestamp of the last message received from them.
		</para>
		<para>
		Name: <emphasis>rl_bin_status</emphasis>
		</para>
		<para>Parameters: <emphasis>none</emphasis></para>
		<para>
		MI FIFO Command Format:
		</para>
		<programlisting  format="linespecific">
		opensips-cli -x mi rl_bin_status
		</programlisting>
	</section>
	</section>

	<section id="exported_pseudo_variables">
	<title>Exported Pseudo-Variables</title>

		<section id="pv_rl_count" xreflabel="$rl_count">
			<title><varname>$rl_count(name)</varname></title>
			<para>
			Returns the counter of a pipe. The variable is read-only.
			</para>
			<para>
			NULL will be returned if the pipe does not exist.
			</para>
		</section>

	</section>
</chapter>

