21 #define LB_GARBAGE_RUN 60    24 #define LB_CONCURRENCY_TIMEOUT 10    28 #define lb_get_writer_lock() do {} while(__sync_lock_test_and_set (lb_main.writer_lock, 1))    29 #define lb_put_writer_lock() lb_main.writer_lock[0] = 0    66   for(cpu_index = 0; cpu_index < tm->
n_vlib_mains; cpu_index++ ) {
    69       s = 
format(s, 
"core %d\n", cpu_index);
    91       return format(s, lb_vip_type_strings[i]);
    92   return format(s, 
"_WRONG_TYPE_");
   100     if (
unformat(input, lb_vip_type_strings[i])) {
   110   return format(s, 
"%U %U new_size:%u #as:%u%s",
   132   s = 
format(s, 
"%U %U [%u] %U%s\n"   142   s = 
format(s, 
"%U  counters:\n",
   146     s = 
format(s, 
"%U    %s: %d\n",
   152   s = 
format(s, 
"%U  #as:%u\n",
   166       as = &lbm->ass[*as_index];
   167       s = format(s, 
"%U    %U %d buckets   %d flows  dpo:%u %s\n",
   168                    format_white_space, indent,
   169                    format_ip46_address, &as->address, IP46_TYPE_ANY,
   170                    count[as - lbm->ass],
   171                    vlib_refcount_get(&lbm->as_refcount, as - lbm->ass),
   173                    (as->flags & LB_AS_FLAGS_USED)?
"used":
" removed");
   216       as = &lbm->ass[*as_index];
   217       if (!(as->flags & LB_AS_FLAGS_USED) && 
   218           clib_u32_loop_gt(now, as->last_used + LB_CONCURRENCY_TIMEOUT) && 
   219           (vlib_refcount_get(&lbm->as_refcount, as - lbm->ass) == 0))
   221           fib_entry_child_remove(as->next_hop_fib_entry_index,
   222                                  as->next_hop_child_index);
   223           fib_table_entry_delete_index(as->next_hop_fib_entry_index,
   225           as->next_hop_fib_entry_index = FIB_NODE_INDEX_INVALID;
   227           pool_put(vip->as_indexes, as_index);
   228           pool_put(lbm->ass, as);
   238   u32 *to_be_removed_vips = 0, *
i;
   240       lb_vip_garbage_collection(vip);
   242       if (!(vip->flags & LB_VIP_FLAGS_USED) &&
   243           (pool_elts(vip->as_indexes) == 0)) {
   244         vec_add1(to_be_removed_vips, vip - lbm->vips);
   249     vip = &lbm->vips[*
i];
   273       as = &lbm->ass[*as_index];
   274       if (as->flags & LB_AS_FLAGS_USED) { 
   285       new_flow_table[
i].as_index = 0;
   296       as = &lbm->ass[*as_index];
   297       if (!(as->flags & LB_AS_FLAGS_USED)) 
   300       sort_arr[i].as_index = as - lbm->ass;
   303   _vec_len(sort_arr) = 
i;
   309     lb_as_t *as = &lbm->ass[pr->as_index];
   320     pr->skip = ((seed & 0xffffffff) | 1) & vip->new_flow_table_mask;
   321     pr->last = (seed >> 32) & vip->new_flow_table_mask;
   327     new_flow_table[
i].as_index = ~0;
   334         pr->last = (pr->last + pr->skip) & vip->new_flow_table_mask;
   335         if (new_flow_table[last].as_index == ~0) {
   336           new_flow_table[
last].as_index = pr->as_index;
   341       if (done == 
vec_len(new_flow_table))
   353     if (vip->new_flow_table == 0 ||
   354         new_flow_table[
i].as_index != vip->new_flow_table[
i].as_index)
   357   old_table = vip->new_flow_table;
   358   vip->new_flow_table = new_flow_table;
   363            u32 per_cpu_sticky_buckets, 
u32 flow_timeout)
   367   if (!
is_pow2(per_cpu_sticky_buckets))
   368     return VNET_API_ERROR_INVALID_MEMORY_SIZE;
   387       if ((vip->flags & LB_AS_FLAGS_USED) &&
   389           vip->prefix.as_u64[0] == prefix->as_u64[0] &&
   390           vip->prefix.as_u64[1] == prefix->as_u64[1]) {
   391         *vip_index = vip - lbm->vips;
   395   return VNET_API_ERROR_NO_SUCH_ENTRY;
   414       as = &lbm->ass[*asi];
   415       if (as->vip_index == (vip - lbm->vips) &&
   416           as->address.as_u64[0] == address->as_u64[0] &&
   417           as->address.as_u64[1] == address->as_u64[1]) {
   418         *as_index = as - lbm->ass;
   432     return VNET_API_ERROR_NO_SUCH_ENTRY;
   436   u32 *to_be_added = 0;
   437   u32 *to_be_updated = 0;
   449         return VNET_API_ERROR_VALUE_EXIST;
   459       return VNET_API_ERROR_INVALID_ADDRESS_FAMILY;
   465         if (addresses[n2].
as_u64[0] == addresses[n].
as_u64[0] &&
   491     *as_index = as - lbm->
ass;
   541     return VNET_API_ERROR_NO_SUCH_ENTRY;
   549       return VNET_API_ERROR_NO_SUCH_ENTRY;
   555         if (addresses[n2].
as_u64[0] == addresses[n].
as_u64[0] &&
   569   if (indexes != 
NULL) {
   611       proto, vip - lbm->
vips);
   647     return VNET_API_ERROR_VALUE_EXIST;
   652     return VNET_API_ERROR_INVALID_MEMORY_SIZE;
   658     return VNET_API_ERROR_INVALID_ADDRESS_FAMILY;
   690   *vip_index = vip - lbm->
vips;
   703     return VNET_API_ERROR_NO_SUCH_ENTRY;
   711     ip46_address_t *ass = 0;
   715         as = &lbm->ass[*as_index];
   716         vec_add1(ass, as->address);
   771   return ((
lb_as_t*)(((
char*)node) -
   832   default_as->
flags = 0;
   835   default_as->
address.ip6.as_u64[0] = 0xffffffffffffffffL;
   836   default_as->
address.ip6.as_u64[1] = 0xffffffffffffffffL;
   838 #define _(a,b,c) lbm->vip_counters[c].name = b; 
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
fib_protocol_t fp_proto
protocol type 
dpo_lock_fn_t dv_lock
A reference counting lock function. 
u32 lb_hash_time_now(vlib_main_t *vm)
Recursive resolution source. 
static int lb_pseudorand_compare(void *a, void *b)
Each VIP is configured with a set of application server. 
sll srl srl sll sra u16x4 i
A virtual function table regisitered for a DPO type. 
void ip46_prefix_normalize(ip46_address_t *prefix, u8 plen)
static vlib_main_t * vlib_get_main(void)
bad routing header type(not 4)") sr_error (NO_MORE_SEGMENTS
u32 per_cpu_sticky_buckets
Number of buckets in the per-cpu sticky hash table. 
clib_error_t * lb_init(vlib_main_t *vm)
clib_error_t * vlib_plugin_register(vlib_main_t *vm, vnet_plugin_handoff_t *h, int from_early_init)
u32 fib_entry_child_add(fib_node_index_t fib_entry_index, fib_node_type_t child_type, fib_node_index_t child_index)
static void lb_fib_node_last_lock_gone(fib_node_t *node)
static void lb_vip_update_new_flow_table(lb_vip_t *vip)
static int lb_as_find_index_vip(lb_vip_t *vip, ip46_address_t *address, u32 *as_index)
static f64 vlib_time_now(vlib_main_t *vm)
enum fib_node_back_walk_rc_t_ fib_node_back_walk_rc_t
Return code from a back walk function. 
const dpo_id_t * fib_entry_contribute_ip_forwarding(fib_node_index_t fib_entry_index)
u8 * format_ip46_prefix(u8 *s, va_list *args)
static void lb_vip_del_adjacency(lb_main_t *lbm, lb_vip_t *vip)
Deletes the adjacency associated with the VIP. 
int lb_conf(ip4_address_t *ip4_address, ip6_address_t *ip6_address, u32 per_cpu_sticky_buckets, u32 flow_timeout)
Fix global load-balancer parameters. 
#define lb_get_writer_lock()
int lb_vip_add_ass(u32 vip_index, ip46_address_t *addresses, u32 n)
u32 index_t
A Data-Path Object is an object that represents actions that are applied to packets are they are swit...
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment). 
ip46_address_t prefix
A Virtual IP represents a given service delivered by a set of application servers. 
#define clib_u32_loop_gt(a, b)
32 bits integer comparison for running values. 
static u64 clib_xxhash(u64 key)
static heap_elt_t * last(heap_header_t *h)
static_always_inline void vlib_refcount_init(vlib_refcount_t *r)
static void lb_dpo_lock(dpo_id_t *dpo)
#define STRUCT_OFFSET_OF(t, f)
static void lb_as_stack(lb_as_t *as)
#define lb_vip_get_by_index(index)
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment). 
u32 vip_index
ASs are indexed by address and VIP Index. 
#define vec_alloc(V, N)
Allocate space for N more elements (no header, unspecified alignment) 
static const char *const *const lb_dpo_gre6_nodes[DPO_PROTO_NUM]
lb_hash_t * sticky_ht
Each CPU has its own sticky flow hash table. 
#define pool_len(p)
Number of elements in pool vector. 
fib_node_type_t fib_node_register_new_type(const fib_node_vft_t *vft)
Create a new FIB node type and Register the function table for it. 
#define LB_VIP_FLAGS_USED
#define ip46_address_type(ip46)
ip46_address_t address
Destination address used to tunnel traffic towards that application server. 
int lb_vip_del_ass_withlock(u32 vip_index, ip46_address_t *addresses, u32 n)
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool. 
#define VLIB_INIT_FUNCTION(x)
static lb_as_t * lb_as_from_fib_node(fib_node_t *node)
void fib_table_entry_special_remove(u32 fib_index, const fib_prefix_t *prefix, fib_source_t source)
Remove a 'special' entry from the FIB. 
#define LB_DEFAULT_PER_CPU_STICKY_BUCKETS
lb-plugin implements a MagLev-like load balancer. 
static const char *const lb_dpo_gre4_ip4[]
u32 flow_timeout
Flow timeout in seconds. 
A high priority source a plugin can use. 
fib_node_type_t fib_node_type
Node type for registering to fib changes. 
dpo_type_t dpo_gre4_type
DPO used to send packet from IP4/6 lookup to LB node. 
Aggregrate type for a prefix. 
static void lb_vip_add_adjacency(lb_main_t *lbm, lb_vip_t *vip)
Add the VIP adjacency to the ip4 or ip6 fib. 
vlib_refcount_t as_refcount
Each AS has an associated reference counter. 
static void lb_vip_garbage_collection(lb_vip_t *vip)
u8 * format_lb_main(u8 *s, va_list *args)
u8 * format_lb_vip(u8 *s, va_list *args)
enum dpo_proto_t_ dpo_proto_t
Data path protocol. 
u16 fp_len
The mask length. 
#define lb_vip_is_ip4(vip)
lb_vip_t * vips
Pool of all Virtual IPs. 
dpo_type_t dpo_register_new_type(const dpo_vft_t *vft, const char *const *const *nodes)
Create and register a new DPO type. 
u32 last_used
Rotating timestamp of when LB_AS_FLAGS_USED flag was last set. 
ip4_address_t ip4_src_address
Source address used for IPv4 encapsulated traffic. 
char * name
The counter collection's name. 
u8 plen
The VIP prefix length. 
The identity of a DPO is a combination of its type and its instance number/index of objects of that t...
#define lb_vip_is_gre4(vip)
static const char *const lb_dpo_gre6_ip4[]
#define ADJ_INDEX_INVALID
Invalid ADJ index - used when no adj is known likewise blazoned capitals INVALID speak volumes where ...
#define pool_elt_at_index(p, i)
Returns pointer to element at given index. 
fib_node_index_t fib_table_entry_special_add(u32 fib_index, const fib_prefix_t *prefix, fib_source_t source, fib_entry_flag_t flags, adj_index_t adj_index)
Add a 'special' entry to the FIB that links to the adj passed A special entry is an entry that the FI...
ip46_address_t fp_addr
The address type is not deriveable from the fp_addr member. 
int lb_vip_del(u32 vip_index)
u8 * format_lb_vip_type(u8 *s, va_list *args)
#define pool_put(P, E)
Free an object E in pool P. 
uword unformat_lb_vip_type(unformat_input_t *input, va_list *args)
#define LB_DEFAULT_FLOW_TIMEOUT
static const char *const *const lb_dpo_gre4_nodes[DPO_PROTO_NUM]
An node in the FIB graph. 
fib_node_t fib_node
Registration to FIB event. 
static const char *const lb_dpo_gre6_ip6[]
static const dpo_vft_t lb_vft
#define ip46_prefix_is_ip4(ip46, len)
#define pool_free(p)
Free a pool. 
int lb_vip_add(ip46_address_t *prefix, u8 plen, lb_vip_type_t type, u32 new_length, u32 *vip_index)
#define vec_free(V)
Free vector's memory (no header). 
static vlib_thread_main_t * vlib_get_thread_main()
volatile u32 * writer_lock
#define lb_foreach_vip_counter
u32 fib_node_index_t
A typedef of a node index. 
static fib_node_back_walk_rc_t lb_fib_node_back_walk_notify(fib_node_t *node, fib_node_back_walk_ctx_t *ctx)
int lb_vip_del_ass(u32 vip_index, ip46_address_t *addresses, u32 n)
void dpo_set(dpo_id_t *dpo, dpo_type_t type, dpo_proto_t proto, index_t index)
Set/create a DPO ID The DPO will be locked. 
u32 last_garbage_collection
Last time garbage collection was run to free the ASs. 
lb_as_t * ass
Pool of ASs. 
lb_vip_type_t type
The type of traffic for this. 
Context passed between object during a back walk. 
fib_node_index_t fib_table_entry_special_dpo_add(u32 fib_index, const fib_prefix_t *prefix, fib_source_t source, fib_entry_flag_t flags, const dpo_id_t *dpo)
Add a 'special' entry to the FIB that links to the DPO passed A special entry is an entry that the FI...
void vlib_validate_simple_counter(vlib_simple_counter_main_t *cm, u32 index)
validate a simple counter 
lb_vip_type_t
The load balancer supports IPv4 and IPv6 traffic and GRE4 and GRE6 encap. 
int lb_vip_find_index(ip46_address_t *prefix, u8 plen, u32 *vip_index)
u8 * format_lb_as(u8 *s, va_list *args)
u32 new_flow_table_mask
New flows table length - 1 (length MUST be a power of 2) 
static void vlib_zero_simple_counter(vlib_simple_counter_main_t *cm, u32 index)
Clear a simple counter Clears the set of per-thread u16 counters, and the u64 counter. 
lb_per_cpu_t * per_cpu
Some global data is per-cpu. 
static void lb_dpo_unlock(dpo_id_t *dpo)
static uword is_pow2(uword x)
vlib_simple_counter_main_t vip_counters[LB_N_VIP_COUNTERS]
Per VIP counter. 
static const char *const lb_dpo_gre4_ip6[]
ip6_address_t ip6_src_address
Source address used in IPv6 encapsulated traffic. 
u8 * format_lb_vip_detailed(u8 *s, va_list *args)
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant) 
static fib_node_t * lb_fib_node_get_node(fib_node_index_t index)
#define vec_sort_with_function(vec, f)
Sort a vector using the supplied element comparison function. 
#define DPO_INVALID
An initialiser for DPOs declared on the stack. 
void lb_garbage_collection()
static int lb_vip_find_index_with_lock(ip46_address_t *prefix, u8 plen, u32 *vip_index)
u32 next_hop_child_index
The child index on the FIB entry. 
static u64 vlib_get_simple_counter(vlib_simple_counter_main_t *cm, u32 index)
Get the value of a simple counter Scrapes the entire set of mini counters. 
A FIB graph nodes virtual function table. 
static void * clib_mem_alloc_aligned(uword size, uword align)
void dpo_reset(dpo_id_t *dpo)
reset a DPO ID The DPO will be unlocked. 
#define vec_foreach(var, vec)
Vector iterator. 
dpo_id_t dpo
The next DPO in the graph to follow. 
u8 flags
Some per-AS flags. 
u16 dpoi_next_node
The next VLIB node to follow. 
lb_new_flow_entry_t * new_flow_table
Vector mapping (flow-hash & new_connect_table_mask) to AS index. 
u8 flags
Flags related to this VIP. 
#define CLIB_CACHE_LINE_BYTES
static char * lb_vip_type_strings[]
u8 * format_lb_dpo(u8 *s, va_list *va)
Load balancing service is provided per VIP. 
u32 * as_indexes
Pool of AS indexes used for this VIP. 
void dpo_stack(dpo_type_t child_type, dpo_proto_t child_proto, dpo_id_t *dpo, const dpo_id_t *parent)
Stack one DPO object on another, and thus establish a child-parent relationship. 
#define lb_put_writer_lock()
fib_node_index_t next_hop_fib_entry_index
The FIB entry index for the next-hop. 
static_always_inline u32 lb_hash_elts(lb_hash_t *h, u32 time_now)
static uword pool_elts(void *v)
Number of active elements in a pool.