Destination Cache Utility Functions

There are a few important utility functions associated with the destination cache. Several of these functions are called directly by users of the destination cache, and some of them are generic functions for manipulating entries that are initialized in the destination cache entry when it is created. The functions are defined in file linux/net/core/dst. c. Destination cache entries are allocated with dst_alloc.

In this function, we allocate an instance of a dst_entry structure. In most cases, the callers will have initialized an instance of a dst_ops structure at compile time. Then, we are called with a pointer to the dst_ops instance each time a new destination cache entry is requested.

struct dst entry * dst;

We check that entries in dst_ops is greater than the garbage collection threshold, gc_thresh. By checking the values in the destination operations, in effect we are checking the values specific to the destination cache user.

if (ops->gc && atomic read(&ops->entries) > ops->gc thresh) {

If the threshold is exceeded, it calls the cache garbage collection function through the gc field of dst_ops.

return NULL;

We allocate the entry from the slab cache pointed to by kmem_cachep in the dst_ops structure.

dst = kmem cache alloc(ops->kmem cachep, SLAB ATOMIC); if (!dst)

return NULL; memset(dst, 0, ops->entry size); atomic set(&dst-> refcnt, 0);

Then it sets the ops field to the dst_ops pointer passed in as a parameter. It sets lastuse to the current time, jiffies, and atomically increments entries. It sets input to dst_discard and output to dst_blackhole.

dst->ops = ops; dst->lastuse = jiffies; dst->path = dst; dst->input = dst discard; dst->output = dst blackhole; #if RT_CACHE_DEBUG >=_2

atomic inc(&dst total); #endif atomic inc(&ops->entries); return dst;

Destination cache entries are freed by calling dst free, an inline function defined in file ® dst.h.

static inline void dst free(struct dst entry * dst);

First, dst_free locks the entry. If_refcnt is zero, the entry is immediately destroyed. If not, it reinitializes dst_entry and places it on the garbage collection list, dst_garbage_list, to be destroyed when the garbage collection timer executes.

Dst_destroy immediately removes a cache entry.

void dst destroy(struct dst entry * dst);

The first thing we do in dst_destroy is check to see if there is an attached neighbor cache entry. If so, we free the neighbor. Then, we check for a hardware cache entry, and if there is one, we free it. Before calling kmem_cache_free to return dst to the slab cache, we call the higher-level destroy function by de-referencing the destroy function pointer referenced in the ops field of dst_entry.

The next two functions, dst_clone and dst_hold, both atomically increment the reference count in the_refcnt field. Both of these functions check that the argument dst is not NULL, but dst_hold assumes that the argument is valid.

static inline struct dst entry * dst clone(struct dst entry * dst); static inline void dst hold(struct dst entry * dst);

Dst_confirm calls neigh_confirm, passing it the value in the neighbour field. Neighbor confirmation verifies that the neighbor entry is reachable.

static inline void dst confirm(struct dst entry *dst);

The two functions, dst_link_failure and dst_negative_advice, call the higher-level negative_advice and link_failure functions through the respective pointers in the ops field of dst_entry.

static inline void dst link failure(struct sk buff *skb); static inline void dst negative advice(struct dst entry **dst p);

Continue reading here: Destination Cache Garbage Collection

Was this article helpful?

0 0