Module: sip-router
Branch: andrei/script_vars
Commit: 1b9b3fd68c37ac7e3b4afb753c8424ae3f6c6e0f
URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=1b9b3fd…
Author: Andrei Pelinescu-Onciul <andrei(a)iptel.org>
Committer: Andrei Pelinescu-Onciul <andrei(a)iptel.org>
Date: Thu Dec 18 14:46:05 2008 +0100
script engine: different operators for int and str +
- different operators for integer + (RVE_IPLUS_OP) and str plus
(RVE_CONCAT_OP). The generic plus (RVE_PLUS_OP) is still
present, the new operators are only used in internal
optimizations (see below) for now.
- if an expression involving the generic '+' is always of type int
or str, replace the generic '+' with the interger or string
version (makes further optimizations possible).
---
rvalue.c | 112 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
rvalue.h | 4 ++-
2 files changed, 110 insertions(+), 6 deletions(-)
diff --git a/rvalue.c b/rvalue.c
index 2a1ea88..6471e85 100644
--- a/rvalue.c
+++ b/rvalue.c
@@ -385,10 +385,13 @@ enum rval_type rve_guess_type( struct rval_expr* rve)
case RVE_LTE_OP:
case RVE_EQ_OP:
case RVE_DIFF_OP:
+ case RVE_IPLUS_OP:
return RV_INT;
case RVE_PLUS_OP:
/* '+' evaluates to the type of the left operand */
return rve_guess_type(rve->left.rve);
+ case RVE_CONCAT_OP:
+ return RV_STR;
case RVE_NONE_OP:
break;
}
@@ -437,6 +440,8 @@ int rve_is_constant(struct rval_expr* rve)
case RVE_EQ_OP:
case RVE_DIFF_OP:
case RVE_PLUS_OP:
+ case RVE_IPLUS_OP:
+ case RVE_CONCAT_OP:
return rve_is_constant(rve->left.rve) &&
rve_is_constant(rve->right.rve);
case RVE_NONE_OP:
@@ -473,6 +478,8 @@ static int rve_op_unary(enum rval_expr_op op)
case RVE_EQ_OP:
case RVE_DIFF_OP:
case RVE_PLUS_OP:
+ case RVE_IPLUS_OP:
+ case RVE_CONCAT_OP:
return 0;
case RVE_NONE_OP:
return -1;
@@ -532,6 +539,7 @@ int rve_check_type(enum rval_type* type, struct rval_expr* rve,
case RVE_GTE_OP:
case RVE_LT_OP:
case RVE_LTE_OP:
+ case RVE_IPLUS_OP:
*type=RV_INT;
if (rve_check_type(&type1, rve->left.rve, bad_rve, bad_t, exp_t)){
if (type1==RV_STR){
@@ -587,6 +595,28 @@ int rve_check_type(enum rval_type* type, struct rval_expr* rve,
return 1;
}
}
+ case RVE_CONCAT_OP:
+ *type=RV_STR;
+ if (rve_check_type(&type1, rve->left.rve, bad_rve, bad_t, exp_t)){
+ if (rve_check_type(&type2, rve->right.rve, bad_rve, bad_t,
+ exp_t)){
+ if ((type2!=type1) && (type1!=RV_NONE) &&
+ (type2!=RV_NONE) &&
+ !(type1==RV_STR && type2==RV_INT)){
+ if (bad_rve) *bad_rve=rve->right.rve;
+ if (bad_t) *bad_t=type2;
+ if (exp_t) *exp_t=type1;
+ return 0;
+ }
+ if (type1==RV_INT){
+ if (bad_rve) *bad_rve=rve->left.rve;
+ if (bad_t) *bad_t=type1;
+ if (exp_t) *exp_t=RV_STR;
+ return 0;
+ }
+ return 1;
+ }
+ }
case RVE_NONE_OP:
break;
}
@@ -936,6 +966,7 @@ inline static int int_intop2(int* res, enum rval_expr_op op, int v1, int v2)
{
switch(op){
case RVE_PLUS_OP:
+ case RVE_IPLUS_OP:
*res=v1+v2;
break;
case RVE_MINUS_OP:
@@ -981,6 +1012,10 @@ inline static int int_intop2(int* res, enum rval_expr_op op, int v1, int v2)
case RVE_DIFF_OP:
*res=v1 != v2;
break;
+ case RVE_CONCAT_OP:
+ *res=0;
+ /* invalid operand for int */
+ return -1;
default:
BUG("rv unsupported intop %d\n", op);
return -1;
@@ -1286,6 +1321,7 @@ int rval_expr_eval_int( struct run_act_ctx* h, struct sip_msg* msg,
case RVE_DIV_OP:
case RVE_MINUS_OP:
case RVE_PLUS_OP:
+ case RVE_IPLUS_OP:
case RVE_BOR_OP:
case RVE_BAND_OP:
case RVE_GT_OP:
@@ -1376,6 +1412,10 @@ int rval_expr_eval_int( struct run_act_ctx* h, struct sip_msg* msg,
rval_destroy(rv2);
break;
#endif
+ case RVE_CONCAT_OP:
+ *res=0;
+ ret=-1;
+ break;
case RVE_NONE_OP:
/*default:*/
BUG("invalid rval int expression operation %d\n", rve->op);
@@ -1446,6 +1486,7 @@ int rval_expr_eval_rvint( struct run_act_ctx* h,
case RVE_LTE_OP:
case RVE_EQ_OP:
case RVE_DIFF_OP:
+ case RVE_IPLUS_OP:
/* operator forces integer type */
ret=rval_expr_eval_int(h, msg, res_i, rve);
*res_rv=0;
@@ -1479,6 +1520,10 @@ int rval_expr_eval_rvint( struct run_act_ctx* h,
}
rval_cache_clean(&c1);
break;
+ case RVE_CONCAT_OP:
+ *res_rv=rval_expr_eval(h, msg, rve);
+ ret=-(*res_rv==0);
+ break;
case RVE_NONE_OP:
/*default:*/
BUG("invalid rval expression operation %d\n", rve->op);
@@ -1535,6 +1580,7 @@ struct rvalue* rval_expr_eval(struct run_act_ctx* h, struct sip_msg* msg,
case RVE_LTE_OP:
case RVE_EQ_OP:
case RVE_DIFF_OP:
+ case RVE_IPLUS_OP:
/* operator forces integer type */
r=rval_expr_eval_int(h, msg, &i, rve);
if (likely(r==0)){
@@ -1603,6 +1649,19 @@ struct rvalue* rval_expr_eval(struct run_act_ctx* h, struct sip_msg* msg,
}
rval_cache_clean(&c1);
break;
+ case RVE_CONCAT_OP:
+ rv1=rval_expr_eval(h, msg, rve->left.rve);
+ if (unlikely(rv1==0)){
+ ERR("rval expression evaluation failed\n");
+ goto error;
+ }
+ rv2=rval_expr_eval(h, msg, rve->right.rve);
+ if (unlikely(rv2==0)){
+ ERR("rval expression evaluation failed\n");
+ goto error;
+ }
+ ret=rval_str_add2(h, msg, rv1, 0, rv2, 0);
+ break;
case RVE_NONE_OP:
/*default:*/
BUG("invalid rval expression operation %d\n", rve->op);
@@ -1767,8 +1826,10 @@ struct rval_expr* mk_rval_expr2(enum rval_expr_op op, struct rval_expr* rve1,
case RVE_LT_OP:
case RVE_LTE_OP:
case RVE_PLUS_OP:
+ case RVE_IPLUS_OP:
case RVE_EQ_OP:
case RVE_DIFF_OP:
+ case RVE_CONCAT_OP:
break;
default:
BUG("unsupported operator %d\n", op);
@@ -1802,6 +1863,8 @@ static int rve_op_is_assoc(enum rval_expr_op op)
case RVE_MINUS_OP:
return 0;
case RVE_PLUS_OP:
+ case RVE_IPLUS_OP:
+ case RVE_CONCAT_OP:
case RVE_MUL_OP:
case RVE_BAND_OP:
case RVE_BOR_OP:
@@ -1838,6 +1901,7 @@ static int rve_op_is_commutative(enum rval_expr_op op, enum rval_type type)
return 0;
case RVE_PLUS_OP:
return type==RV_INT; /* commutative only for INT*/
+ case RVE_IPLUS_OP:
case RVE_MUL_OP:
case RVE_BAND_OP:
case RVE_BOR_OP:
@@ -1851,6 +1915,7 @@ static int rve_op_is_commutative(enum rval_expr_op op, enum rval_type type)
case RVE_LTE_OP:
case RVE_EQ_OP:
case RVE_DIFF_OP:
+ case RVE_CONCAT_OP:
return 0;
}
return 0;
@@ -2158,9 +2223,10 @@ static int rve_opt_01(struct rval_expr* rve, enum rval_type rve_type)
}
break;
case RVE_PLUS_OP:
+ case RVE_IPLUS_OP:
/* we must make sure that this is an int PLUS
(because "foo"+0 is valid => "foo0") */
- if ((i==0) && (rve_type==RV_INT)){
+ if ((i==0) && ((op==RVE_IPLUS_OP)||(rve_type==RV_INT))){
/* $v + 0 -> $v
* 0 + $v -> $v */
rve_destroy(ct_rve);
@@ -2206,14 +2272,32 @@ static int rve_opt_01(struct rval_expr* rve, enum rval_type rve_type)
op, i);
}
}
- }
- /* no optimization for strings for now
+ }else if (rv->type==RV_STR){
+ switch(op){
+ case RVE_CONCAT_OP:
+ if (rv->v.s.len==0){
+ /* $v . "" -> $v
+ "" . $v -> $v */
+ rve_destroy(ct_rve);
+ pos=rve->fpos;
+ *rve=*v_rve; /* replace current expr. with $v */
+ rve->fpos=pos;
+ pkg_free(v_rve);/* rve_destroy(v_rve) would free
+ everything*/
+ ret=1;
+ }
+ break;
+ default:
+ break;
+ }
+ /* no optimization for generic RVE_PLUS_OP for now, only for RVE_CONCAT_OP
(We could optimize $v + "" or ""+$v, but this ""+$v is a way
to force convert $v to str , it might mess up type checking
(e.g. errors w/o optimization and no errors with) and it brings
a very small benefit anyway (it's unlikely we'll see a lot of
"")
*/
+ }
if (rv) rval_destroy(rv);
return ret;
error:
@@ -2232,7 +2316,7 @@ static int rve_optimize(struct rval_expr* rve)
enum rval_expr_op op;
int flags;
struct rval_expr tmp_rve;
- enum rval_type type;
+ enum rval_type type, l_type;
struct rval_expr* bad_rve;
enum rval_type bad_type, exp_type;
@@ -2285,7 +2369,7 @@ static int rve_optimize(struct rval_expr* rve)
rv->v.l=-rv->v.l;
if (rve_replace_with_ct_rv(rve->right.rve, rv)<0)
goto error;
- rve->op=RVE_PLUS_OP;
+ rve->op=RVE_IPLUS_OP;
DBG("FIXUP RVE: optimized $v - a into $v + (%d)\n",
(int)rve->right.rve->left.rval.v.l);
}
@@ -2293,6 +2377,22 @@ static int rve_optimize(struct rval_expr* rve)
rv=0;
}
+ /* e1 PLUS_OP e2 -> change op if we know e1 basic type */
+ if (rve->op==RVE_PLUS_OP){
+ l_type=rve_guess_type(rve->left.rve);
+ if (l_type==RV_INT){
+ rve->op=RVE_IPLUS_OP;
+ DBG("FIXUP RVE (%d,%d-%d,%d): changed + into interger plus\n",
+ rve->fpos.s_line, rve->fpos.s_col,
+ rve->fpos.e_line, rve->fpos.e_col);
+ }else if (l_type==RV_STR){
+ rve->op=RVE_CONCAT_OP;
+ DBG("FIXUP RVE (%d,%d-%d,%d): changed + into string concat\n",
+ rve->fpos.s_line, rve->fpos.s_col,
+ rve->fpos.e_line, rve->fpos.e_col);
+ }
+ }
+
/* $v * 0 => 0; $v * 1 => $v (for *, /, &, |, &&, ||, +, -) */
if (rve_opt_01(rve, type)==1){
/* success, rve was changed => return now
@@ -2510,8 +2610,10 @@ int fix_rval_expr(void** p)
case RVE_LT_OP:
case RVE_LTE_OP:
case RVE_PLUS_OP:
+ case RVE_IPLUS_OP:
case RVE_EQ_OP:
case RVE_DIFF_OP:
+ case RVE_CONCAT_OP:
ret=fix_rval_expr((void**)&rve->left.rve);
if (ret<0) return ret;
ret=fix_rval_expr((void**)&rve->right.rve);
diff --git a/rvalue.h b/rvalue.h
index f36f189..a694c0d 100644
--- a/rvalue.h
+++ b/rvalue.h
@@ -59,10 +59,12 @@ enum rval_expr_op{
RVE_GTE_OP, /* 2 members, returns left >= right */
RVE_LT_OP, /* 2 members, returns left < right */
RVE_LTE_OP, /* 2 members, returns left <= right */
+ RVE_IPLUS_OP, /* 2 members, integer +, returns int(a)+int(b) */
/* common int & str */
- RVE_PLUS_OP, /* 2 members, returns left + right (int or str)*/
+ RVE_PLUS_OP, /* generic plus (int or str) returns left + right */
RVE_EQ_OP, /* 2 members, returns left == right (int)*/
RVE_DIFF_OP, /* 2 members, returns left != right (int)*/
+ RVE_CONCAT_OP,/* string concatenation, returns left . right */
/* str only */
};
Hello,
I couldn't get the message with a final decision regarding the library
naming scheme.
Andrei used libsr_xyz at some point, I also like this one. Henning
committed directly lib/trie in his branch.
I will look soon to make the library out of mi, thinking of: libsr_kmi
or libsr_mi, depending or not whether we want to mark the origin.
So, two things to decide:
- do we stick to libsr_ as prefix to all new libraries included in srouter?
- do we want to mark the origin of the library? Short term, might be
good as pattern to know what is required for k version of the module.
This can be fixed with good documentation. Long term the name might look
strange.
Cheers,
Daniel
--
Daniel-Constantin Mierla
http://www.asipto.com
Hello,
I think we need to decide about AVPs. Although not deeply investigated,
ser seems to have couple of AVPs lists. In kamailio/openser it is one list.
Can a ser developer describe a bit the AVP implementation as it is now
there?
In openser/kamailio we have more or less same architecture as for ser
0.9.6 with couple extensions, but I will detail here so we can have full
picture:
- avps are kept in shared memory
- they are bound to each sip message and moved to transaction if that
message create a transaction
- avp can have two types of names
- integer id, referred as $avp(i:number)
- string id, referred as $avp(s:string)
- there can be aliases for avp names, defined as "alias=[is]:id", so the
script writer can use $avp(alias)
- a value of an avp can be either integer or string
- not related to avp core part, but important to mention here -- tm,
controlled by a parameter, can make the avps from transaction (request)
available to onreply_route.
Also, just to have in mind, for the future we got into discussion:
- moving from linked list to a structure that allows faster search
(e.g., hash table) as number of used avps can be big some times
- adding support for structure-like values (the value to be another list
of (name,value) pairs). A typical use case is serial forking, where one
needs to store data in avps. If for one destination an avp is missing,
things get screwed. Example:
$avp(uri) = {A, B, C}
$avp(RPID) = {X, not needed, Y}
Internally will look like:
$avp(uri) = {A, B, C}
$avp(RPID) = {X, Y}
So actually, Y will be used for destination B. Workarounds are possible,
or course, but maybe we can do it nicer. so it will be like:
$avp(dst) = {{u=A,r=Y}, {u=B},{u=C,r=Y}}
A possibility to specify the access is $avp(d:dst=>u)
Finally, as pointed in another email, it is about making possible to
hold "value null" (a mark/flag) and differentiate that from "undefined"
(not existing).
Cheers,
Daniel
--
Daniel-Constantin Mierla
http://www.asipto.com
Module: sip-router
Branch: ser_core_cvs
Commit: 67e3e42ea4ad48ec225233a32e0c8c36fdba7bc4
URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=67e3e42…
Author: Andrei Pelinescu-Onciul <andrei(a)iptel.org>
Committer: Andrei Pelinescu-Onciul <andrei(a)iptel.org>
Date: Tue Dec 16 14:30:48 2008 +0000
doc: tcp tunning update
- update with epoll tunning for kernels >= 2.6.27.8
Author: Andrei Pelinescu-Onciul <andrei(a)iptel.org>
---
doc/tcp_tunning.txt | 4 ++++
1 files changed, 4 insertions(+), 0 deletions(-)
diff --git a/doc/tcp_tunning.txt b/doc/tcp_tunning.txt
index 975e793..b383a42 100644
--- a/doc/tcp_tunning.txt
+++ b/doc/tcp_tunning.txt
@@ -55,6 +55,10 @@ fs.file-max - maximum number of fds that will be allocated
1.5 other sysctl that might affect tcp connection rate or the maximum number
of open connections
+fs.epoll.max_user_instances - maximum number of devices - per user (2.6.27.8+)
+fs.epoll.max_user_watches - maximum number of "watched" fds - per user
+ (2.6.27.8+)
+
iptables - remove the ip_conntrack module (it limits the maximum tcp
connections, adds extra overhead (slow)). It's probably better to remove
all the iptables modules.