OUR SITES NetworkRADIUS FreeRADIUS

Cache Module

The cache module is used to cache attributes. The idea is that you can look up information in a database, and then cache it. Repeated requests for the same information will then have the cached values added to the request.

The module can cache a fixed set of attributes per key. It can be listed in any recv or send section.

If you want to have different things cached for different sections, you will need to define multiple instances of the module, via cache <nameN> { …​ }.
Option Description

ok

if it found or created a cache entry.

updated

if it merged a cached entry.

noop

if it did nothing.

fail

on error.

Configuration Settings

driver

The current backend datastore used to store the cache entries are:

Driver Description

rbtree

An in memory, non persistent rbtree based datastore. Useful for caching data locally.

memcached

A non persistent "webscale" distributed datastore. Useful if the cached data need to be shared between a cluster of RADIUS servers.

redis

A persistent "webscale" clustered, sharded, data store. Extremely fast, and a good candidate for sharing data such as EAP session blobs, between a cluster of servers.

Some drivers accept specific options, to set them a config section with the the name as the driver should be added to the cache instance.

Driver specific options are:

Memcached cache driver

options

Memcached configuration options.

pool

Connection pool.

Redis cache driver

server

Redis Server name.

If using Redis cluster, multiple 'bootstrap' servers may be listed here (as separate config items). These will be contacted in turn until one provides us with a valid map for the cluster. Server strings may contain unique ports.

e.g.:

server = '127.0.0.1:30001'
server = '[::1]:30002'

Instantiation failure behaviour is controlled by pool.start as with every other module, but with clustering, the pool section determines limits for each node in the cluster, not the cluster as a whole.

port

Port to use for Redis server.

The default port is 6379.

password

For authenticating ourselves to the Redis server.

database

The database number to use.

pool

Connection pool.

key

The key used to index the cache. It is dynamically expanded at run time.

ttl

The TTL of cache entries, in seconds. Entries older than this will be expired.

This value should be between 10 and 86400.

You can flush the cache via radmin -e "set module config cache epoch 123456789" Where last value is a 32-bit Unix timestamp. Cache entries older than this are expired, as new entries added. You should never set the "epoch" configuration item in this file.
add_stats

If yes the following attributes will be added to the request:

  • &request.Cache-Entry-Hits - The number of times this entry has been retrieved.

Not supported by the rlm_cache_memcached module.
max_entries

Maximum entries allowed.

update { …​ }

The attributes to cache for a particular key.

Each key gets the same set of cached attributes.

The operation of the update section is a little different from normal update sections. This is because we need to both reference the attributes which we want to store in the cache, and also to describe where those attributes are written to when the cache entry is read.

The solution (albeit an imperfect one) is that the cache does not store attributes, it stores update sections. The update section given below is used as a template for the cache entry.

When the cache entry is created, the right-hand side of each attribute assignment line is expanded. The left-hand side of the attribute assignment is left alone.

Once all of the right-hand side values are expanded, the result is an update section with left-hand side assignments, and right-hand side values. That update section is then cached, indexed by the key

When the cache entry is read, it is looked up by the key, and the cached update section is found. This cache entry now has left-hand side assignments, and right-hand side values. It is then applied to the current request.

For example, if the cache module is configured with the block below:

update { &reply.Reply-Message := "Hello %{User-Name}" }

When the cache entry is created, the module will expand the right side of the entry, using the attributes from the packet. In this case, the string could expand to "Hello bob".

Once all of the right-hand values are expanded, the resulting cache entry will look like this:

update { &reply.Reply-Message := "Hello bob" }

When the cache module is read, this update section is applied just as if it had been specified in a configuration file.

Only request, reply, control and session-state lists are available for the left side of cache entries. Attempting to reference other lists will raise an error during config validation.
<list>.<attribute> <op> <value>

Cache all instances of Reply-Message in the reply list.

Add our own to show when the cache was last updated.

Add your own value for Class.

How to use

Configuration

This module supports a number of runtime configuration parameters represented by attributes in the &control. list.

&control.Cache-TTL

Sets the TTL of an entry to be created, or modifies the TTL of an existing entry.

Condition Description

Cache-TTL of > 0

Set the TTL of the entry to the new value (and reset the expiry timer).

Cache-TTL of < 0

Expire the existing entry and create a new one with TTL set to Cache-TTL * -1.

Cache-TTL of 0

Expire the existing entry and create a new one.

&control.Cache-Status-Only

If present and set to yes will prevent a new entry from being created, and existing entries from being merged. It will also alter the module’s return codes.

  • The module will return ok if a cache entry was found.

  • The module will return notfound if no cache entry was found.

If this is set to yes, no other cache control attributes will be honoured, but they will still be cleared.
&control.Cache-Allow-Insert

If present and set to no will prevent a new entry from being created. If not present or set to yes, and no entry exists, a new one will be created. This is evaluated after Cache-TTL, so expired entries may be recreated.

&control.Cache-Allow-Merge

If present and set to no will prevent existing entries from being merged. If not present or set to yes, and an entry exists (and is valid), it will be merged with the current request. This is evaluated before Cache-TTL, so entries being expired may first be merged.

&control.Cache-Merge-New

If present and set to yes will merge new cache entries into the current request. Useful if results of execs or expansions are stored directly in the cache.

All runtime configuration attributes will be removed from the &control. list after the cache module is called.

Methods

The cache module also allows handling the cache using the methods.

cache.status

Verify if an entry already exists without load the entries.

Return Description

ok

if a cache entry was found.

notfound

if no cache entry was found.

fail

if the cache was unavailable.

cache.load

Load an existing cache entry and merge it into the request.

Return Description

updated

if a cache entry was found and loaded.

notfound

if no cache entry was found.

fail

if the cache was unavailable.

cache.update

Perform an upsert against the data store, updating the entry TTL

Return Description

updated

if we added cache entry.

fail

if the cache was unavailable.

cache.store

Inserts data into the cache if, and only if, it is not already present Will not update the entry TTL.

Return Description

updated

we created or updated a cache entry.

noop

if a cache entry aready existed.

fail

if the cache was unavailable.

cache.clear

Delete cache entry from the data store without checking if the entry already exists.

Return Description

ok

if we found and removed a entry.

notfound

if no cache entry was found.

fail

if the cache was unavailable.

cache.ttl

Change the TTL on an existing entry.

Return Description

updated

if we found entry and updated the ttl.

notfound

if no cache entry was found.

fail

if the cache was unavailable.

Examples

# Add a cache entry
&control.Cache-TTL := 1h
cache.store
if (updated) {
  ..keys stored
}

# Get the cache status
cache.status
if (ok) {
  ..Exist a cache entry
}

# Load the cache entry
cache.load
if (updated) {
  ..loaded
}

# Change the entries TTL
&control.Cache-TTL := 30m
cache.ttl
if (updated) {
  ..ttl changed
}

# Clear the cache
cache.clear
if (ok) {
  ..cache is empty
}
  • This is evaluated before Cache-TTL, so entries being expired may first be merged.

  • All runtime configuration attributes will be removed from the &control: list after any cache method is called.

Default Configuration

cache {
#	driver = "rbtree"
#	memcached {
#		options = "--SERVER=localhost"
#		pool {
#			start = 0
#			min = 0
#			max =
#			spare = 1
#			uses = 0
#			lifetime = 0
#			idle_timeout = 60
#		}
#	}
#	redis {
#		server = 127.0.0.1
#		port = 6379
#		password = 'supersecret'
#		database = 0
#		pool {
			start = 0
			min = 0
#			max =
#			spare = 1
#			uses = 0
#			lifetime = 0
#			idle_timeout = 60
#		}
#	}
	key = &User-Name
	ttl = 10
	add_stats = no
#	max_entries = 0
	update {
		&reply.Reply-Message := &reply.Reply-Message
		&reply.Reply-Message += "Cache last updated at %t"
		&reply.Class := "%randstr(ssssssssssssssssssssssssssssssss)"
	}
}