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 2022-04-12 iRule(1)