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 47 for(cpu_index = 0; cpu_index < tm->
n_vlib_mains; cpu_index++ ) {
50 s =
format(s,
"core %d\n", cpu_index);
72 return format(s, lb_vip_type_strings[i]);
73 return format(s,
"_WRONG_TYPE_");
81 if (
unformat(input, lb_vip_type_strings[i])) {
91 return format(s,
"%U %U new_size:%u #as:%u%s",
111 s =
format(s,
"%U %U [%u] %U%s\n" 121 s =
format(s,
"%U counters:\n",
125 s =
format(s,
"%U %s: %d\n",
131 s =
format(s,
"%U #as:%u\n",
145 as = &lbm->ass[*as_index];
146 s = format(s,
"%U %U %d buckets %d flows adj:%u %s\n",
147 format_white_space, indent,
148 format_ip46_address, &as->address, IP46_TYPE_ANY,
149 count[as - lbm->ass],
150 vlib_refcount_get(&lbm->as_refcount, as - lbm->ass),
152 (as->flags & LB_AS_FLAGS_USED)?
"used":
" removed");
196 as = &lbm->ass[*as_index];
197 if (!(as->flags & LB_AS_FLAGS_USED) &&
198 clib_u32_loop_gt(now, as->last_used + LB_CONCURRENCY_TIMEOUT) &&
199 (vlib_refcount_get(&lbm->as_refcount, as - lbm->ass) == 0)) {
200 pool_put(vip->as_indexes, as_index);
201 pool_put(lbm->ass, as);
211 u32 *to_be_removed_vips = 0, *
i;
213 lb_vip_garbage_collection(vip);
215 if (!(vip->flags & LB_VIP_FLAGS_USED) &&
216 (pool_elts(vip->as_indexes) == 0)) {
217 vec_add1(to_be_removed_vips, vip - lbm->vips);
222 vip = &lbm->vips[*
i];
246 as = &lbm->ass[*as_index];
247 if (as->flags & LB_AS_FLAGS_USED) {
258 new_flow_table[
i].as_index = 0;
269 as = &lbm->ass[*as_index];
270 if (!(as->flags & LB_AS_FLAGS_USED))
273 sort_arr[i].as_index = as - lbm->ass;
276 _vec_len(sort_arr) =
i;
282 lb_as_t *as = &lbm->ass[pr->as_index];
293 pr->skip = ((seed & 0xffffffff) | 1) & vip->new_flow_table_mask;
294 pr->last = (seed >> 32) & vip->new_flow_table_mask;
300 new_flow_table[
i].as_index = ~0;
307 pr->last = (pr->last + pr->skip) & vip->new_flow_table_mask;
308 if (new_flow_table[last].as_index == ~0) {
309 new_flow_table[
last].as_index = pr->as_index;
314 if (done ==
vec_len(new_flow_table))
326 if (vip->new_flow_table == 0 ||
327 new_flow_table[
i].as_index != vip->new_flow_table[
i].as_index)
330 old_table = vip->new_flow_table;
331 vip->new_flow_table = new_flow_table;
336 u32 per_cpu_sticky_buckets,
u32 flow_timeout)
340 if (!
is_pow2(per_cpu_sticky_buckets))
341 return VNET_API_ERROR_INVALID_MEMORY_SIZE;
360 if ((vip->flags & LB_AS_FLAGS_USED) &&
362 vip->prefix.as_u64[0] == prefix->as_u64[0] &&
363 vip->prefix.as_u64[1] == prefix->as_u64[1]) {
364 *vip_index = vip - lbm->vips;
368 return VNET_API_ERROR_NO_SUCH_ENTRY;
387 as = &lbm->ass[*asi];
388 if (as->vip_index == (vip - lbm->vips) &&
389 as->address.as_u64[0] == address->as_u64[0] &&
390 as->address.as_u64[1] == address->as_u64[1]) {
391 *as_index = as - lbm->ass;
405 return VNET_API_ERROR_NO_SUCH_ENTRY;
409 u32 *to_be_added = 0;
410 u32 *to_be_updated = 0;
422 return VNET_API_ERROR_VALUE_EXIST;
432 return VNET_API_ERROR_INVALID_ADDRESS_FAMILY;
438 if (addresses[n2].
as_u64[0] == addresses[n].
as_u64[0] &&
466 *as_index = as - lbm->
ass;
488 return VNET_API_ERROR_NO_SUCH_ENTRY;
496 return VNET_API_ERROR_NO_SUCH_ENTRY;
502 if (addresses[n2].
as_u64[0] == addresses[n].
as_u64[0] &&
516 if (indexes !=
NULL) {
549 return VNET_API_ERROR_NO_SUCH_ENTRY;
552 as = &lbm->
ass[as_index];
560 return VNET_API_ERROR_NO_SUCH_ENTRY;
567 return VNET_API_ERROR_INCORRECT_ADJACENCY_TYPE;
575 return VNET_API_ERROR_NO_SUCH_ENTRY;
582 return VNET_API_ERROR_INCORRECT_ADJACENCY_TYPE;
599 memset (&adj, 0,
sizeof (adj));
674 return VNET_API_ERROR_VALUE_EXIST;
679 return VNET_API_ERROR_INVALID_MEMORY_SIZE;
685 return VNET_API_ERROR_INVALID_ADDRESS_FAMILY;
717 *vip_index = vip - lbm->
vips;
730 return VNET_API_ERROR_NO_SUCH_ENTRY;
738 ip46_address_t *ass = 0;
742 as = &lbm->ass[*as_index];
743 vec_add1(ass, as->address);
792 default_as->
flags = 0;
795 default_as->
address.ip6.as_u64[0] = 0xffffffffffffffffL;
796 default_as->
address.ip6.as_u64[1] = 0xffffffffffffffffL;
798 #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) ...
u32 ip_lookup_next_index[LB_VIP_N_TYPES]
Node next index for IP adjacencies, for each of the traffic types.
u32 lb_hash_time_now(vlib_main_t *vm)
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
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)
ip_lookup_next_t lookup_next_index
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)
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)
#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)
ip_lookup_main_t lookup_main
u8 opaque[IP_ADJACENCY_OPAQUE_SZ]
u32 adj_index
Second ip lookup can be avoided by sending directly the packet to ip-rewrite with a configured adjace...
#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)
lb_hash_t * sticky_ht
Each CPU has its own sticky flow hash table.
#define pool_len(p)
Number of elements in pool vector.
#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)
#define LB_DEFAULT_PER_CPU_STICKY_BUCKETS
lb-plugin implements a MagLev-like load balancer.
u32 flow_timeout
Flow timeout in seconds.
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.
u32 table_index_or_table_id
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)
#define lb_vip_is_ip4(vip)
void ip6_add_del_route(ip6_main_t *im, ip6_add_del_route_args_t *args)
lb_vip_t * vips
Pool of all Virtual IPs.
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.
ip6_address_t dst_address
#define lb_vip_is_gre4(vip)
int lb_vip_del(u32 vip_index)
void * ip4_get_route(ip4_main_t *im, u32 fib_index_or_table_id, u32 flags, u8 *address, u32 address_length)
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
u32 ip6_get_route(ip6_main_t *im, u32 fib_index_or_table_id, u32 flags, ip6_address_t *address, u32 address_length)
#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 vip_index
Index of the VIP associated with that IP adjacency.
int lb_as_lookup_bypass(u32 vip_index, ip46_address_t *address, u8 is_disable)
Updates the adjacency index stored in the AS such that the second IP lookup (after encap) can be bypa...
#define IP6_ROUTE_FLAG_DEL
int lb_vip_del_ass(u32 vip_index, ip46_address_t *addresses, u32 n)
u32 last_garbage_collection
Last time garbage collection was run to free the ASs.
#define IP4_ROUTE_FLAG_DEL
lb_as_t * ass
Pool of ASs.
lb_vip_type_t type
The type of traffic for this.
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.
struct stored in adj->opaque data.
ip4_address_t dst_address
#define IP4_ROUTE_FLAG_ADD
ip_lookup_main_t lookup_main
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 uword is_pow2(uword x)
vlib_simple_counter_main_t vip_counters[LB_N_VIP_COUNTERS]
Per VIP counter.
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)
#define vec_sort_with_function(vec, f)
Sort a vector using the supplied element comparison function.
void lb_garbage_collection()
u32 table_index_or_table_id
static int lb_vip_find_index_with_lock(ip46_address_t *prefix, u8 plen, u32 *vip_index)
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.
static void * clib_mem_alloc_aligned(uword size, uword align)
ip4_main_t ip4_main
Global ip4 main structure.
This packet is to be rewritten and forwarded to the next processing node.
#define IP6_ROUTE_FLAG_ADD
#define vec_foreach(var, vec)
Vector iterator.
i16 explicit_fib_index
Force re-lookup in a different FIB.
u8 flags
Some per-AS flags.
lb_new_flow_entry_t * new_flow_table
Vector mapping (flow-hash & new_connect_table_mask) to AS index.
void ip4_add_del_route(ip4_main_t *im, ip4_add_del_route_args_t *args)
u8 flags
Flags related to this VIP.
#define CLIB_CACHE_LINE_BYTES
static char * lb_vip_type_strings[]
Load balancing service is provided per VIP.
u32 * as_indexes
Pool of AS indexes used for this VIP.
static ip_adjacency_t * ip_get_adjacency(ip_lookup_main_t *lm, u32 adj_index)
#define lb_put_writer_lock()
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.