ltm rule command class
iRule(1) BIG-IP TMSH Manual iRule(1)
class
Advanced access of classes.
SYNOPSIS
class 'match' (((CLASS_SEARCH_OPTION) ('-all'))#)? ('--')? ITEM
CLASS_OPERATOR CLASS_OBJ
DESCRIPTION
class match attempts to match the provided - to an element in
by applying the to the
- .
The return value depends on the option specified. If no option was
specified, the return value is 1 for a match and 0 for a no-match.
This command form is equivalent to the current iRule command:
matchclass
-
Example:
class match [HTTP::uri] ends_with image_class read as, does the URI
end with an element from image_class.
Example:
class match [IP::client_addr] equals client_ip_class read as, does
the client IP address exist in the client_ip_class.
class 'search' (((CLASS_SEARCH_OPTION) ('-all'))#)? ('--')?
CLASS_OBJ CLASS_OPERATOR ITEM
DESCRIPTION
class search attempts to match the provided
- to an element in
by applying the to the element.
The return value depends on the option specified. If no option was
specified, the return value is 1 for a match and 0 for a no-match.
This command form is equivalent to the current iRule command:
matchclass
-
Example:
class search blocked_paths starts_with [HTTP::uri] read as, does
blocked_paths contain an element that starts with the URI.
class match & class search difference: Notice that there are
differences between the two forms: - The order in which you specify
- and . - The item on which the operator is applied for
operations other than equals.
The table below describes the semantics of the different operators when
used in each of the commands. See also the example below for a code
snippet depicting the differences:
operator class match
class search equals return a value indicating has an
element that is equal to
- return a value indicating
has an element that is equal to
- starts_with return
a value indicating there is a element that matches the start of
- return a value indicating
- value matches the start
of a element ends_with return a value indicating there is a
element that matches the end of
- return a value
indicating
- value matches the end of a element contains
return a value indicating
- value contains a element
return a value indicating there is a element that contains
-
class match & class search optional arguments: The for both
of the above forms of the class command can be: -index Changes the
return value to be the index of the matching class element. -name
Changes the return value to be the name of the matching class element.
-value Changes the return value to be the value of the matching
class element. -element Changes the return value to be a list of the
name and value of the matching class element. -list Changes the
return value to always be a list even if only one element. -all
If used with -index, -name, -value, -element, changes the return value
to all of the matching class elements. (added in v11.0) --
Terminates option processing (useful if the
- or begins
with a hyphen).
The for both of the above forms can be: equals, starts_with,
ends_with, contains
class 'lookup' ITEM CLASS_OBJ
DESCRIPTION
Equivalent to: class match -value
- equals
class 'element' (-name | -value)? ('--')? INDEX CLASS_OBJ
DESCRIPTION
Returns a list containing the name and value of the element found at
in .
Note: class indexes are not guaranteed to be consistent and may change
when a datagroup is modified. This could happen if the event execution
becomes suspended or across executions of different events.
The for this command can be:
-name Changes the return value to be the name of the class
element at the index.
-value Changes the return value to be the value of the class
element at the index.
-- Terminates option processing.
class 'type' CLASS_OBJ
DESCRIPTION
Returns the type of the , currently only string, IP, or value.
class 'exists' CLASS_OBJ
DESCRIPTION
Returns 1 or 0 depending on whether a class named actually
exists.
class 'size' CLASS_OBJ
DESCRIPTION
Returns the number of elements currently found in .
class 'names' (-nocase)? (-list)? ('--')? CLASS_OBJ (PATTERN)?
DESCRIPTION
Returns the names of the class elements.
class 'get' (-nocase)? (-list)? ('--')? CLASS_OBJ (PATTERN)?
DESCRIPTION
Returns a list containing the names or a list of the name and value
currently found in . An optional may be specified to
restrict the list to names that match the Tcl glob pattern.
Additionally, the switch -nocase may be specified to enable case-
insensitive pattern matching. This command provides a way to access
the class as a Tcl list similar to previously access the global
variable named the same as the list.
Note: Use class get only if you want to manage a class as a list. If
you are looking for an element within the class, class search and class
match are far more efficient. This is particularly important when using
large classes.
class 'startsearch' CLASS_OBJ
DESCRIPTION
Returns a to be used with each of the following commands.
class ('anymore' | 'donesearch' | 'nextelement') (-name | -value |
-index | -element | -list)? ('--')? CLASS_OBJ (CLASS_SEARCH_ID)?
DESCRIPTION
Subcommand nextelement returns a list containing the name and value of
the next element in the current search.
-index Changes the return value to be the index of the next class
element. -name Changes the return value to be the name of the
next class element. -value Changes the return value to be the
value of the next class element. -list Changes the return value
to always be a list, even if just one element. -- Terminates
option processing.
Subcommand anymore returns 1 or 0 depending on whether there are more
elements to iterate on in the .
Subcommand donesearch terminates the search. After using this command,
executing 'class anymore' or 'class nextelement' will cause a runtime
error. To exit a loop early, use break . Once done with the search and
outside any loop referencing the search id, use 'class donesearch' to
clean up the memory associated with the search.
DESCRIPTION
The class command, implemented in v10.0.0, allows you to query data
groups and data group properties.
These commands work for both internal (defined in the bigip.conf) and
external (custom file) data groups. Internal data groups were not able
to make use of the name/value pairing with the := separator until
version 10.1. As of 10.1 all classes support the name/value pairing.
The class command deprecates the findclass and matchclass commands as
it offers better functionality and performance than the older commands.
Note -
You should not use a $:: or :: prefix on the datagroup name when
using the class command (or in any datagroup reference on 9.4.4 or
later).
In v9.4.4 - 10, using $::datagroup_name will work but demote the virtual server from running on all TMMs. For details, see the CMP compatibility page.
In v11, using $::datagroup_name will result in a TCL runtime error and a reset being sent to the client!
Note -
Starting in v11, any data-groups that are configured in a partition
other than Common must be referenced by
/Partition_Name/Data-Group_Name, even by iRules configured in that
partition. Data-groups referenced only by name are implicitly presumed
to be /Common/Data-Group_Name.
Note -
When using the equals operator on IP classes, or when using the
starts_with or ends_with operators, if multiple possible matches are
found in the class, then the longest match is always chosen. This is
not true when using the contains operator. See the example below for
more details.
RETURN VALUE
VALID DURING
CLASS_FUNCTION, GLOBAL_GTM, INFORMATIONAL_COMMAND
EXAMPLES
# External Class Format (v10):
# class namevalue {
# "name1" := "value",
# "name2" := "value",
# }
# Internal Class Format (v10.1):
# class namevalue {
# {
# "name1" { "value1" }
# "name2" { "value2" }
# }
# }
# Internal Class Format (v11.0):
# ltm data-group internal name_value_dg {
# records {
# name1 {
# data value1
# }
# name2 {
# data "value2 with spaces"
# }
# }
# type string
# }
#
# The example below demonstrates the differences between class match and class search when applied to a data group using different keys and operations (note that no option was specified, so the return value shown in the tables below is the operation result code). The iRule first gets the contents of the data group being queried and then performs the various operations using both forms. When a match occurs, the matching data group key is shown as well.
when RULE_INIT {
log local0.info "dg_test_class: [class get dg_test_class]"
foreach val {p://a.b p://a.b/x p://a.b/x/y p://a.b/x/y/z } {
log local0.info "+[string repeat - 15]|[string repeat - 15]|[string repeat - 15]|[string repeat - 15]+"
log local0.info "[format |%-15s|%15s|%15s|%15s| value operation {class match} {class search}]"
foreach oper {equals starts_with ends_with contains} {
set rc_match "[class match -name $val $oper dg_test_class]:[class match $val $oper dg_test_class]"
set rc_search "[class search -name dg_test_class $oper $val]:[class search dg_test_class $oper $val]"
log local0.info "[format |%-15s|%15s|%15s|%15s| $val $oper $rc_match $rc_search ]"
}
log local0.info "+[string repeat - 15]|[string repeat - 15]|[string repeat - 15]|[string repeat - 15]+"
}
}
# Below is the resulting log output (note the line prefix was stripped for brevity):
# "/Common/rl_test_dg : dg_test_class: {p://a.b/x/y a_b_x_y} {p://y.y/x y_y_x} {p://u.v/w u_v_w}"
# "/Common/rl_test_dg : +---------------|---------------|---------------|---------------+"
# "/Common/rl_test_dg : |value | operation| class match| class search|"
# "/Common/rl_test_dg : |p://a.b | equals| :0| :0|"
# "/Common/rl_test_dg : |p://a.b | starts_with| :0| p://a.b/x/y:1|"
# "/Common/rl_test_dg : |p://a.b | ends_with| :0| :0|"
# "/Common/rl_test_dg : |p://a.b | contains| :0| p://a.b/x/y:1|"
# "/Common/rl_test_dg : +---------------|---------------|---------------|---------------+"
# "/Common/rl_test_dg : +---------------|---------------|---------------|---------------+"
# "/Common/rl_test_dg : |value | operation| class match| class search|"
# "/Common/rl_test_dg : |p://a.b/x | equals| :0| :0|"
# "/Common/rl_test_dg : |p://a.b/x | starts_with| :0| p://a.b/x/y:1|"
# "/Common/rl_test_dg : |p://a.b/x | ends_with| :0| :0|"
# "/Common/rl_test_dg : |p://a.b/x | contains| :0| p://a.b/x/y:1|"
# "/Common/rl_test_dg : +---------------|---------------|---------------|---------------+"
# "/Common/rl_test_dg : +---------------|---------------|---------------|---------------+"
# "/Common/rl_test_dg : |value | operation| class match| class search|"
# "/Common/rl_test_dg : |p://a.b/x/y | equals| p://a.b/x/y:1| p://a.b/x/y:1|"
# "/Common/rl_test_dg : |p://a.b/x/y | starts_with| p://a.b/x/y:1| p://a.b/x/y:1|"
# "/Common/rl_test_dg : |p://a.b/x/y | ends_with| p://a.b/x/y:1| p://a.b/x/y:1|"
# "/Common/rl_test_dg : |p://a.b/x/y | contains| p://a.b/x/y:1| p://a.b/x/y:1|"
# "/Common/rl_test_dg : +---------------|---------------|---------------|---------------+"
# "/Common/rl_test_dg : +---------------|---------------|---------------|---------------+"
# "/Common/rl_test_dg : |value | operation| class match| class search|"
# "/Common/rl_test_dg : |p://a.b/x/y/z | equals| :0| :0|"
# "/Common/rl_test_dg : |p://a.b/x/y/z | starts_with| p://a.b/x/y:1| :0|"
# "/Common/rl_test_dg : |p://a.b/x/y/z | ends_with| :0| :0|"
# "/Common/rl_test_dg : |p://a.b/x/y/z | contains| p://a.b/x/y:1| :0|"
# "/Common/rl_test_dg : +---------------|---------------|---------------|---------------+"
# This example disables compression based on source IP's in an address type datagroup named localusers_dg
when HTTP_REQUEST {
if { [class match [IP::client_addr] equals "localusers_dg" ] } {
COMPRESS::disable
}
}
# This v10 example chooses a pool based on the URI requested:
# /config/app_class.dat:
# "/trxdef/" := "trx_pool",
# "/aaa/" := "aaa_pool",
# "/abscon/" := "abs_pool",
# class app_class {
# type string
# filename app_class.dat
# }
rule appl_director {
when HTTP_REQUEST {
set app_pool [class match -value -- [HTTP::uri] starts_with app_class]
if {$app_pool ne ""} {
pool $app_pool
} else {
pool default_pool
}
}
}
# This example chooses a pool based on the time of day:
# /config/daily_schedule.dat:
# 0 := early_morning_pool,
# 7 := morning_rush,
# 10 := midday_pool,
# 15 := afternoon_rush,
# 18 := evening_pool,
# class daily_schedule {
# type value
# filename daily_schedule.dat
# }
rule daily_director {
# Initialize a variable to track the closest hour match
# as we loop through the datagroup elements.
# We want to find the lowest hour in the datagroup that is
# greater or equal to the current hour.
#
# Note: The order of datagroup elements is not guaranteed
# so we must loop through all elements to find the best match.
when HTTP_REQUEST {
# Get the hour of day
set hour_now [clock format [clock seconds] -format {%H}]
# Save a search ID for the daily_schedule datagroup
set id [class startsearch daily_schedule]
# Initialize a variable to track the closest hour match
# By setting this to higher than the highest hour of the day,
# any match in the datagroup will override this default value.
set best_match 24
# Loop through the datagroup
while { [class anymore daily_schedule $id] } {
# Save the current element's key and value to a TCL list
set x [class nextelement daily_schedule $id]
# Save the current datagroup element's hour field (the first list element)
# to a variable so we don't rerun the lindex several times
set hour_class [lindex $x 0]
# Check if the current hour is greater than the the current element key
if {$hour_now >= $hour_class && $hour_class < $best_match} {
# Save the currently matched hour to see if it's the best match
set best_match $hour_class
# Save the value as the pool name
set pool [lindex $x 1]
}
}
# Assign the best match's corresponding pool
pool $pool
}
}
# This example demostrates how to loop through each element in a datagroup using 'class startsearch' and exit the loop once a match is found. Cleanup of internal structures is done using 'class donesearch':
when RULE_INIT {
# Save a class name to search through
set class_name numbers_class
# Save a search ID for the datagroup
set id [class startsearch $class_name]
# Loop through the class row by row
while {[class anymore $class_name $id]}{
set element [class nextelement $class_name $id]
log local0. "\[class nextelement $class_name $id\]: $element"
# Perform some operation against the current datagroup key and/or value
# Check if the element's key is greater than 2
if {[lindex $element 1] > 2}{
# Exit the loop if the logic check is true
log local0. "Found key greater than 2, breaking out of loop"
break
}
}
# Clean up the search
class donesearch $class_name $id
}
# This example extracts an base64 encoded image from a class to send in an HTTP response when load balancing failed:
# /config/img.txt:
# "img" := "R0lGODlhEgAeANUAABAREz9CSEBBQz0+QB8hJCIkJ5eZnGJlaXN2egQJDwUKEDo+Q0VJTgE
# DBQULEQUKDwMGCTo+Qk1RVUtPU0pOUk9TV1RYXFZaXlxgZFtfYy0vMRcYGTEzNR8gIW5xdG1
# wc2lsb2hrbklLTXh7fnV4e3R3enN2eXF0d4SHiqCipJeZmwQKDwULEDU6PktQVFtfYjI4PHN
# 2eAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAEgAeAEA
# G20CRcEgsDjFIZGa5fDmTSId0Sq2yroqsdsvVnr5fk9gUK8fAX4Z6zW6vu3Duak6v2+mIfH7
# E7/P1eSGsDjFIZGa5fDmTSId0Sq2yroqsdsvVnr5fk9gUK8fAX4Z6zW6vu3Duak6v2+CggMd
# IIWHHYOCsDjFIZGa5fDmTSId0Sq2yroqsdsvVnr5fk9gUK8fAX4Z6zW6vu3Duak6v2+FY2NG
# hsSkJIbjsDjFIZGa5fDmTSId0Sq2yroqsdsvVnr5fk9gUK8fAX4Z6zW6vu3Duak6v2+o0RmJ
# gEAC2bnQsDjFIZGa5fDmTSId0Sq2yroqsdsvVnr5fk9gUK8fAX4Z6zW6vu3Duak6v2+CZmFU
# uEA6kpqUsDjFIZGa5fDmTSId0Sq2yroqsdsvVnr5fk9gUK8fAX4Z6zW6vu3Duak6v2+OVyxc
# ExAKrrCvsDjFIZGa5fDmTSId0Sq2yroqsdsvVnr5fk9gUK8fAX4Z6zW6vu3Duak6v2+W3auK
# 7a2dSm7vL2+vCXBwSTExcTCwR/KygYCHs0eKgLLygfW19jZ1xfc3CgcFt/hHN3cFOfo6eroA
# e3tJwU7vL2+L8PIF7u0w+Pn6+/lV/lSruEBooGBgQYJxEio0yBChlgcQI0qcGPGORTsJMmrc
# yFFjEA7vL2+A7",
# class img {
# type string
# filename "/config/img.txt"
# }
rule LBFailedResponse {
when LB_FAILED {
HTTP::respond 200 content [b64decode [class element -value 0 img]] "Content-Type" "image/png"
}
}
# Using the -all flag added in v11.0 to return details on multiple matches (for class match or class search):
#
# Show the full contents of the string_dg datagroup retrieved as a TCL list:
log local0. "[class get string_dg] "
# Log output: {abc value1} {abcd value2} {abcde value3} {123 value4}
# Use -all with no other options to return a count of the number of matching names in the datagroup:
log local0. "[class search -all string_dg starts_with "abc"]"
# Log output: 3
# Use -all with the -index option to return the index of matching names in the datagroup:
log local0. "[class search -all -index string_dg starts_with "abc"]"
# Log output: 0 1 2
# Use -all with the -index option to return the index of matching names in the datagroup:
log local0. "[class search -all -index string_dg starts_with "abc"]"
# Log output: 0 1 2
# Use -all with the -element option to return the name and value of matching names in the datagroup:
log local0. "[class search -all -element string_dg starts_with "abc"]"
# Log output: {abc value1} {abcd value2} {abcde value3}
# Use -all with the -name option to return the name of matching names in the datagroup:
log local0. "[class search -all -name string_dg starts_with "abc"]"
# Log output: abc abcd abcde
# Use -all with the -value option to return the value of matching names in the datagroup:
log local0. "[class search -all -value string_dg starts_with "abc"]"
# Log output: value1 value2 value3
# Examples showing longest-match selection (v11.x syntax):
ltm data-group internal /Common/addr_list {
records {
10.0.0.0/8 {
data bignet
}
10.0.0.0/24 {
data littlenet
}
}
type ip
}
ltm data-group internal /Common/string_list {
records {
left {
data first
}
lefter {
data second
}
}
type string
}
log local0. "match of 10.0.0.128 is [class match -value 10.0.0.128 equals addr_list]"
log local0. "match of lefterest is [class match -value lefterest starts_with string_list]"
# will log:
# Rule /Common/classes : match of 10.0.0.128 is littlenet
# Rule /Common/classes : match of lefterest is second
# In each case, the longest match was used (10.0.0.0/24 had a longer match than 10.0.0.0/8, and "lefter" had a longer match than "left").
HINTS
SEE ALSO
https://devcentral.f5.com/wiki/iRules.GenericHostToUriMapping.ashx -
This iRule shows how to map a portion of the host header to a specified
Uri.
https://devcentral.f5.com/wiki/iRules.Google-Authenticator-iRule-For-Two-Factor-Auth-With-LDAP.ashx
- This iRule adds two-factor authentication to a virtual server by
combining an LDAP account with a Google Authenticator token
https://devcentral.f5.com/wiki/iRules.Google-Authenticator-Token-Verification-iRule-For-APM.ashx
- This iRule adds token authentication capabilities for Google
Authenticator to APM.
https://devcentral.f5.com/wiki/iRules.LTMImageHosting.ashx - Host
Images on LTM in External Class
https://devcentral.f5.com/wiki/iRules.MS-Exchange-Active-Sync-Multi-Device-Auth.ashx
- Utilizes the Exchange extended attributes to store multiple devices
per client, (i.e. iPhone, iPad, etc.) to validate the device as
approved for the assigned user.
https://devcentral.f5.com/wiki/iRules.ProxyPassV10.ashx - iRule (for
LTM v10/v11) to replace the functionality of Apache Webserver ProxyPass
and ProxyPassReverse functions allowing for a different server and
client view of your web application(s).
https://devcentral.f5.com/wiki/iRules.Route_Domain_Snat_and_Nat_Implementation.ashx
- This iRule Provides Snat and Nat capabilities across route domains
https://devcentral.f5.com/wiki/iRules.TLS-ServerNameIndication.ashx -
Server Name Indication (TLS SNI) allows dynamic selection of clientssl
profiles and pools
- This Solution will act as a Web Form Application protection layer
against malicious entities such as automated bots.
https://devcentral.f5.com/wiki/iRules.virtual_server_connection_rate_limit_with_tables.ashx
- Limit the rate of connections to a virtual server to prevent
overloading of pool members
For examples on v10 and v11 data group formats, see Jason Rahm's
articles:
https://devcentral.f5.com/Tutorials/TechTips/tabid/63/articleType/ArticleView/articleId/1086448/iRules-Data-Group-Formatting-Rules.aspx
https://devcentral.f5.com/Tutorials/TechTips/tabid/63/articleType/ArticleView/articleId/1086510/v11-iRules-Data-Group-Updates.aspx
Note that datagroups are not currently synced between GTMs, although if
synced between LTMs on GTM/LTM servers they will be accessible.
Note that if you wish to create datagroups on a standalone GTM, you
will need to contact support.
CHANGE LOG
@BIGIP-11.1.0 --First introduced to GTM. @BIGIP-10.0.0 --First
introduced the command.
BIG-IP 2019-05-10 iRule(1)