mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2025-01-18 19:50:54 +00:00
MEDIUM: samples: provide basic arithmetic and bitwise operators
This commit introduces a new category of converters. They are bitwise and arithmetic operators which support performing basic operations on integers. Some bitwise operations are supported (and, or, xor, cpl) and some arithmetic operations are supported (add, sub, mul, div, mod, neg). Some comparators are provided (odd, even, not, bool) which make it possible to report a match without having to write an ACL. The detailed list of new operators as they appear in the doc is : add(<value>) Adds <value> to the input value of type unsigned integer, and returns the result as an unsigned integer. and(<value>) Performs a bitwise "AND" between <value> and the input value of type unsigned integer, and returns the result as an unsigned integer. bool Returns a boolean TRUE if the input value of type unsigned integer is non-null, otherwise returns FALSE. Used in conjunction with and(), it can be used to report true/false for bit testing on input values (eg: verify the presence of a flag). cpl Takes the input value of type unsigned integer, applies a twos-complement (flips all bits) and returns the result as an unsigned integer. div(<value>) Divides the input value of type unsigned integer by <value>, and returns the result as an unsigned integer. If <value> is null, the largest unsigned integer is returned (typically 2^32-1). even Returns a boolean TRUE if the input value of type unsigned integer is even otherwise returns FALSE. It is functionally equivalent to "not,and(1),bool". mod(<value>) Divides the input value of type unsigned integer by <value>, and returns the remainder as an unsigned integer. If <value> is null, then zero is returned. mul(<value>) Multiplies the input value of type unsigned integer by <value>, and returns the product as an unsigned integer. In case of overflow, the higher bits are lost, leading to seemingly strange values. neg Takes the input value of type unsigned integer, computes the opposite value, and returns the remainder as an unsigned integer. 0 is identity. This operator is provided for reversed subtracts : in order to subtract the input from a constant, simply perform a "neg,add(value)". not Returns a boolean FALSE if the input value of type unsigned integer is non-null, otherwise returns TRUE. Used in conjunction with and(), it can be used to report true/false for bit testing on input values (eg: verify the absence of a flag). odd Returns a boolean TRUE if the input value of type unsigned integer is odd otherwise returns FALSE. It is functionally equivalent to "and(1),bool". or(<value>) Performs a bitwise "OR" between <value> and the input value of type unsigned integer, and returns the result as an unsigned integer. sub(<value>) Subtracts <value> from the input value of type unsigned integer, and returns the result as an unsigned integer. Note: in order to subtract the input from a constant, simply perform a "neg,add(value)". xor(<value>) Performs a bitwise "XOR" (exclusive OR) between <value> and the input value of type unsigned integer, and returns the result as an unsigned integer.
This commit is contained in:
parent
3180f7b554
commit
9770787e70
@ -10155,18 +10155,42 @@ sample fetch method. These keywords may equally be appended immediately after
|
||||
the fetch keyword's argument, delimited by a comma. These keywords can also
|
||||
support some arguments (eg: a netmask) which must be passed in parenthesis.
|
||||
|
||||
A certain category of converters are bitwise and arithmetic operators which
|
||||
support performing basic operations on integers. Some bitwise operations are
|
||||
supported (and, or, xor, cpl) and some arithmetic operations are supported
|
||||
(add, sub, mul, div, mod, neg). Some comparators are provided (odd, even, not,
|
||||
bool) which make it possible to report a match without having to write an ACL.
|
||||
|
||||
The currently available list of transformation keywords include :
|
||||
|
||||
add(<value>)
|
||||
Adds <value> to the input value of type unsigned integer, and returns the
|
||||
result as an unsigned integer.
|
||||
|
||||
and(<value>)
|
||||
Performs a bitwise "AND" between <value> and the input value of type unsigned
|
||||
integer, and returns the result as an unsigned integer.
|
||||
|
||||
base64
|
||||
Converts a binary input sample to a base64 string. It is used to log or
|
||||
transfer binary content in a way that can be reliably transferred (eg:
|
||||
an SSL ID can be copied in a header).
|
||||
|
||||
bool
|
||||
Returns a boolean TRUE if the input value of type unsigned integer is
|
||||
non-null, otherwise returns FALSE. Used in conjunction with and(), it can be
|
||||
used to report true/false for bit testing on input values (eg: verify the
|
||||
presence of a flag).
|
||||
|
||||
bytes(<offset>[,<length>])
|
||||
Extracts some bytes from an input binary sample. The result is a binary
|
||||
sample starting at an offset (in bytes) of the original sample and
|
||||
optionnaly truncated at the given length.
|
||||
|
||||
cpl
|
||||
Takes the input value of type unsigned integer, applies a twos-complement
|
||||
(flips all bits) and returns the result as an unsigned integer.
|
||||
|
||||
crc32([<avalanche>])
|
||||
Hashes a binary input sample into an unsigned 32-bit quantity using the CRC32
|
||||
hash function. Optionally, it is possible to apply a full avalanche hash
|
||||
@ -10180,6 +10204,11 @@ crc32([<avalanche>])
|
||||
not be used for security purposes as a 32-bit hash is trivial to break. See
|
||||
also "djb2", "sdbm", "wt6" and the "hash-type" directive.
|
||||
|
||||
div(<value>)
|
||||
Divides the input value of type unsigned integer by <value>, and returns the
|
||||
result as an unsigned integer. If <value> is null, the largest unsigned
|
||||
integer is returned (typically 2^32-1).
|
||||
|
||||
djb2([<avalanche>])
|
||||
Hashes a binary input sample into an unsigned 32-bit quantity using the DJB2
|
||||
hash function. Optionally, it is possible to apply a full avalanche hash
|
||||
@ -10191,6 +10220,10 @@ djb2([<avalanche>])
|
||||
32-bit hash is trivial to break. See also "crc32", "sdbm", "wt6" and the
|
||||
"hash-type" directive.
|
||||
|
||||
even
|
||||
Returns a boolean TRUE if the input value of type unsigned integer is even
|
||||
otherwise returns FALSE. It is functionally equivalent to "not,and(1),bool".
|
||||
|
||||
field(<index>,<delimiters>)
|
||||
Extracts the substring at the given index considering given delimiters from
|
||||
an input string. Indexes start at 1 and delimiters are a string formatted
|
||||
@ -10366,6 +10399,35 @@ map_<match_type>_<output_type>(<map_file>[,<default_value>])
|
||||
| `---------------------------- key
|
||||
`------------------------------------ leading spaces ignored
|
||||
|
||||
mod(<value>)
|
||||
Divides the input value of type unsigned integer by <value>, and returns the
|
||||
remainder as an unsigned integer. If <value> is null, then zero is returned.
|
||||
|
||||
mul(<value>)
|
||||
Multiplies the input value of type unsigned integer by <value>, and returns
|
||||
the product as an unsigned integer. In case of overflow, the higher bits are
|
||||
lost, leading to seemingly strange values.
|
||||
|
||||
neg
|
||||
Takes the input value of type unsigned integer, computes the opposite value,
|
||||
and returns the remainder as an unsigned integer. 0 is identity. This
|
||||
operator is provided for reversed subtracts : in order to subtract the input
|
||||
from a constant, simply perform a "neg,add(value)".
|
||||
|
||||
not
|
||||
Returns a boolean FALSE if the input value of type unsigned integer is
|
||||
non-null, otherwise returns TRUE. Used in conjunction with and(), it can be
|
||||
used to report true/false for bit testing on input values (eg: verify the
|
||||
absence of a flag).
|
||||
|
||||
odd
|
||||
Returns a boolean TRUE if the input value of type unsigned integer is odd
|
||||
otherwise returns FALSE. It is functionally equivalent to "and(1),bool".
|
||||
|
||||
or(<value>)
|
||||
Performs a bitwise "OR" between <value> and the input value of type unsigned
|
||||
integer, and returns the result as an unsigned integer.
|
||||
|
||||
regsub(<regex>,<subst>[,<flags>])
|
||||
Applies a regex-based substitution to the input string. It does the same
|
||||
operation as the well-known "sed" utility with "s/<regex>/<subst>/". By
|
||||
@ -10399,6 +10461,11 @@ sdbm([<avalanche>])
|
||||
32-bit hash is trivial to break. See also "crc32", "djb2", "wt6" and the
|
||||
"hash-type" directive.
|
||||
|
||||
sub(<value>)
|
||||
Subtracts <value> from the input value of type unsigned integer, and returns
|
||||
the result as an unsigned integer. Note: in order to subtract the input from
|
||||
a constant, simply perform a "neg,add(value)".
|
||||
|
||||
table_bytes_in_rate(<table>)
|
||||
Uses the string representation of the input sample to perform a look up in
|
||||
the specified table. If the key is not found in the table, integer value zero
|
||||
@ -10572,6 +10639,10 @@ wt6([<avalanche>])
|
||||
32-bit hash is trivial to break. See also "crc32", "djb2", "sdbm", and the
|
||||
"hash-type" directive.
|
||||
|
||||
xor(<value>)
|
||||
Performs a bitwise "XOR" (exclusive OR) between <value> and the input value
|
||||
of type unsigned integer, and returns the result as an unsigned integer.
|
||||
|
||||
|
||||
7.3.2. Fetching samples from internal states
|
||||
--------------------------------------------
|
||||
|
154
src/sample.c
154
src/sample.c
@ -1888,6 +1888,144 @@ static int sample_conv_regsub(const struct arg *arg_p, struct sample *smp)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Takes a UINT on input, applies a binary twos complement and returns the UINT
|
||||
* result.
|
||||
*/
|
||||
static int sample_conv_binary_cpl(const struct arg *arg_p, struct sample *smp)
|
||||
{
|
||||
smp->data.uint = ~smp->data.uint;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Takes a UINT on input, applies a binary "and" with the UINT in arg_p, and
|
||||
* returns the UINT result.
|
||||
*/
|
||||
static int sample_conv_binary_and(const struct arg *arg_p, struct sample *smp)
|
||||
{
|
||||
smp->data.uint &= arg_p->data.uint;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Takes a UINT on input, applies a binary "or" with the UINT in arg_p, and
|
||||
* returns the UINT result.
|
||||
*/
|
||||
static int sample_conv_binary_or(const struct arg *arg_p, struct sample *smp)
|
||||
{
|
||||
smp->data.uint |= arg_p->data.uint;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Takes a UINT on input, applies a binary "xor" with the UINT in arg_p, and
|
||||
* returns the UINT result.
|
||||
*/
|
||||
static int sample_conv_binary_xor(const struct arg *arg_p, struct sample *smp)
|
||||
{
|
||||
smp->data.uint ^= arg_p->data.uint;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Takes a UINT on input, applies an arithmetic "add" with the UINT in arg_p,
|
||||
* and returns the UINT result.
|
||||
*/
|
||||
static int sample_conv_arith_add(const struct arg *arg_p, struct sample *smp)
|
||||
{
|
||||
smp->data.uint += arg_p->data.uint;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Takes a UINT on input, applies an arithmetic "sub" with the UINT in arg_p,
|
||||
* and returns the UINT result.
|
||||
*/
|
||||
static int sample_conv_arith_sub(const struct arg *arg_p, struct sample *smp)
|
||||
{
|
||||
smp->data.uint -= arg_p->data.uint;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Takes a UINT on input, applies an arithmetic "mul" with the UINT in arg_p,
|
||||
* and returns the UINT result.
|
||||
*/
|
||||
static int sample_conv_arith_mul(const struct arg *arg_p, struct sample *smp)
|
||||
{
|
||||
smp->data.uint *= arg_p->data.uint;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Takes a UINT on input, applies an arithmetic "div" with the UINT in arg_p,
|
||||
* and returns the UINT result. If arg_p makes the result overflow, then the
|
||||
* largest possible quantity is returned.
|
||||
*/
|
||||
static int sample_conv_arith_div(const struct arg *arg_p, struct sample *smp)
|
||||
{
|
||||
if (arg_p->data.uint)
|
||||
smp->data.uint /= arg_p->data.uint;
|
||||
else
|
||||
smp->data.uint = ~0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Takes a UINT on input, applies an arithmetic "mod" with the UINT in arg_p,
|
||||
* and returns the UINT result. If arg_p makes the result overflow, then zero
|
||||
* is returned.
|
||||
*/
|
||||
static int sample_conv_arith_mod(const struct arg *arg_p, struct sample *smp)
|
||||
{
|
||||
if (arg_p->data.uint)
|
||||
smp->data.uint %= arg_p->data.uint;
|
||||
else
|
||||
smp->data.uint = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Takes an UINT on input, applies an arithmetic "neg" and returns the UINT
|
||||
* result.
|
||||
*/
|
||||
static int sample_conv_arith_neg(const struct arg *arg_p, struct sample *smp)
|
||||
{
|
||||
smp->data.uint = -smp->data.uint;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Takes a UINT on input, returns true is the value is non-null, otherwise
|
||||
* false. The output is a BOOL.
|
||||
*/
|
||||
static int sample_conv_arith_bool(const struct arg *arg_p, struct sample *smp)
|
||||
{
|
||||
smp->data.uint = !!smp->data.uint;
|
||||
smp->type = SMP_T_BOOL;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Takes a UINT on input, returns false is the value is non-null, otherwise
|
||||
* truee. The output is a BOOL.
|
||||
*/
|
||||
static int sample_conv_arith_not(const struct arg *arg_p, struct sample *smp)
|
||||
{
|
||||
smp->data.uint = !smp->data.uint;
|
||||
smp->type = SMP_T_BOOL;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Takes a UINT on input, returns true is the value is odd, otherwise false.
|
||||
* The output is a BOOL.
|
||||
*/
|
||||
static int sample_conv_arith_odd(const struct arg *arg_p, struct sample *smp)
|
||||
{
|
||||
smp->data.uint = smp->data.uint & 1;
|
||||
smp->type = SMP_T_BOOL;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Takes a UINT on input, returns true is the value is even, otherwise false.
|
||||
* The output is a BOOL.
|
||||
*/
|
||||
static int sample_conv_arith_even(const struct arg *arg_p, struct sample *smp)
|
||||
{
|
||||
smp->data.uint = !(smp->data.uint & 1);
|
||||
smp->type = SMP_T_BOOL;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* All supported sample fetch functions must be declared here */
|
||||
/************************************************************************/
|
||||
@ -2034,6 +2172,22 @@ static struct sample_conv_kw_list sample_conv_kws = {ILH, {
|
||||
{ "field", sample_conv_field, ARG2(2,UINT,STR), sample_conv_field_check, SMP_T_STR, SMP_T_STR },
|
||||
{ "word", sample_conv_word, ARG2(2,UINT,STR), sample_conv_field_check, SMP_T_STR, SMP_T_STR },
|
||||
{ "regsub", sample_conv_regsub, ARG3(2,REG,STR,STR), sample_conv_regsub_check, SMP_T_STR, SMP_T_STR },
|
||||
|
||||
{ "and", sample_conv_binary_and, ARG1(1,UINT), NULL, SMP_T_UINT, SMP_T_UINT },
|
||||
{ "or", sample_conv_binary_or, ARG1(1,UINT), NULL, SMP_T_UINT, SMP_T_UINT },
|
||||
{ "xor", sample_conv_binary_xor, ARG1(1,UINT), NULL, SMP_T_UINT, SMP_T_UINT },
|
||||
{ "cpl", sample_conv_binary_cpl, 0, NULL, SMP_T_UINT, SMP_T_UINT },
|
||||
{ "bool", sample_conv_arith_bool, 0, NULL, SMP_T_UINT, SMP_T_BOOL },
|
||||
{ "not", sample_conv_arith_not, 0, NULL, SMP_T_UINT, SMP_T_BOOL },
|
||||
{ "odd", sample_conv_arith_odd, 0, NULL, SMP_T_UINT, SMP_T_BOOL },
|
||||
{ "even", sample_conv_arith_even, 0, NULL, SMP_T_UINT, SMP_T_BOOL },
|
||||
{ "add", sample_conv_arith_add, ARG1(1,UINT), NULL, SMP_T_UINT, SMP_T_UINT },
|
||||
{ "sub", sample_conv_arith_sub, ARG1(1,UINT), NULL, SMP_T_UINT, SMP_T_UINT },
|
||||
{ "mul", sample_conv_arith_mul, ARG1(1,UINT), NULL, SMP_T_UINT, SMP_T_UINT },
|
||||
{ "div", sample_conv_arith_div, ARG1(1,UINT), NULL, SMP_T_UINT, SMP_T_UINT },
|
||||
{ "mod", sample_conv_arith_mod, ARG1(1,UINT), NULL, SMP_T_UINT, SMP_T_UINT },
|
||||
{ "neg", sample_conv_arith_neg, 0, NULL, SMP_T_UINT, SMP_T_UINT },
|
||||
|
||||
{ NULL, NULL, 0, 0, 0 },
|
||||
}};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user