X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fplugins%2Flb%2Flb.c;h=4dbf134cc4f0e4d774e0bdf1a379efa260321755;hb=2da39718f560478678caacccd198ee4c0c9673c3;hp=041c65c13264787ee60d185bdf3cc4b6f4ebbb10;hpb=004869d0d4947a6e56b2d1bd481bbb6916d7a2e0;p=vpp.git diff --git a/src/plugins/lb/lb.c b/src/plugins/lb/lb.c index 041c65c1326..4dbf134cc4f 100644 --- a/src/plugins/lb/lb.c +++ b/src/plugins/lb/lb.c @@ -18,6 +18,7 @@ #include #include #include +#include //GC runs at most once every so many seconds #define LB_GARBAGE_RUN 60 @@ -25,10 +26,13 @@ //After so many seconds. It is assumed that inter-core race condition will not occur. #define LB_CONCURRENCY_TIMEOUT 10 +// FIB source for adding routes +static fib_source_t lb_fib_src; + lb_main_t lb_main; -#define lb_get_writer_lock() do {} while(__sync_lock_test_and_set (lb_main.writer_lock, 1)) -#define lb_put_writer_lock() lb_main.writer_lock[0] = 0 +#define lb_get_writer_lock() clib_spinlock_lock (&lb_main.writer_lock) +#define lb_put_writer_lock() clib_spinlock_unlock (&lb_main.writer_lock) static void lb_as_stack (lb_as_t *as); @@ -289,7 +293,7 @@ static void lb_vip_garbage_collection(lb_vip_t *vip) lb_snat6_key_t m_key6; clib_bihash_kv_24_8_t kv6, value6; lb_snat_mapping_t *m = 0; - ASSERT (lbm->writer_lock[0]); + CLIB_SPINLOCK_ASSERT_LOCKED (&lbm->writer_lock); u32 now = (u32) vlib_time_now(vlib_get_main()); if (!clib_u32_loop_gt(now, vip->last_garbage_collection + LB_GARBAGE_RUN)) @@ -383,9 +387,8 @@ static void lb_vip_update_new_flow_table(lb_vip_t *vip) lb_new_flow_entry_t *new_flow_table = 0; lb_as_t *as; lb_pseudorand_t *pr, *sort_arr = 0; - u32 count; - ASSERT (lbm->writer_lock[0]); //We must have the lock + CLIB_SPINLOCK_ASSERT_LOCKED (&lbm->writer_lock); // We must have the lock //Check if some AS is configured or not i = 0; @@ -408,7 +411,6 @@ out: } //First, let's sort the ASs - sort_arr = 0; vec_alloc(sort_arr, pool_elts(vip->as_indexes)); i = 0; @@ -444,7 +446,7 @@ out: //Let's create a new flow table vec_validate(new_flow_table, vip->new_flow_table_mask); for (i=0; ilast; pr->last = (pr->last + pr->skip) & vip->new_flow_table_mask; - if (new_flow_table[last].as_index == ~0) { + if (new_flow_table[last].as_index == 0) { new_flow_table[last].as_index = pr->as_index; break; } @@ -463,16 +465,8 @@ out: } } - vec_free(sort_arr); - finished: - -//Count number of changed entries - count = 0; - for (i=0; inew_flow_table == 0 || - new_flow_table[i].as_index != vip->new_flow_table[i].as_index) - count++; + vec_free(sort_arr); old_table = vip->new_flow_table; vip->new_flow_table = new_flow_table; @@ -506,7 +500,8 @@ int lb_vip_port_find_index(ip46_address_t *prefix, u8 plen, { lb_main_t *lbm = &lb_main; lb_vip_t *vip; - ASSERT (lbm->writer_lock[0]); //This must be called with the lock owned + /* This must be called with the lock owned */ + CLIB_SPINLOCK_ASSERT_LOCKED (&lbm->writer_lock); ip46_prefix_normalize(prefix, plen); pool_foreach(vip, lbm->vips, { if ((vip->flags & LB_AS_FLAGS_USED) && @@ -570,7 +565,8 @@ int lb_vip_find_index(ip46_address_t *prefix, u8 plen, u8 protocol, static int lb_as_find_index_vip(lb_vip_t *vip, ip46_address_t *address, u32 *as_index) { lb_main_t *lbm = &lb_main; - ASSERT (lbm->writer_lock[0]); //This must be called with the lock owned + /* This must be called with the lock owned */ + CLIB_SPINLOCK_ASSERT_LOCKED (&lbm->writer_lock); lb_as_t *as; u32 *asi; pool_foreach(asi, vip->as_indexes, { @@ -686,7 +682,7 @@ next: { /* Add SNAT static mapping */ pool_get (lbm->snat_mappings, m); - memset (m, 0, sizeof (*m)); + clib_memset (m, 0, sizeof (*m)); if (lb_vip_is_nat4_port(vip)) { lb_snat4_key_t m_key4; clib_bihash_kv_8_8_t kv4; @@ -762,7 +758,43 @@ next: return 0; } -int lb_vip_del_ass_withlock(u32 vip_index, ip46_address_t *addresses, u32 n) +int +lb_flush_vip_as (u32 vip_index, u32 as_index) +{ + u32 thread_index; + vlib_thread_main_t *tm = vlib_get_thread_main(); + lb_main_t *lbm = &lb_main; + + for(thread_index = 0; thread_index < tm->n_vlib_mains; thread_index++ ) { + lb_hash_t *h = lbm->per_cpu[thread_index].sticky_ht; + if (h != NULL) { + u32 i; + lb_hash_bucket_t *b; + + lb_hash_foreach_entry(h, b, i) { + if ((vip_index == ~0) + || ((b->vip[i] == vip_index) && (as_index == ~0)) + || ((b->vip[i] == vip_index) && (b->value[i] == as_index))) + { + vlib_refcount_add(&lbm->as_refcount, thread_index, b->value[i], -1); + vlib_refcount_add(&lbm->as_refcount, thread_index, 0, 1); + b->vip[i] = ~0; + b->value[i] = 0; + } + } + if (vip_index == ~0) + { + lb_hash_free(h); + lbm->per_cpu[thread_index].sticky_ht = 0; + } + } + } + + return 0; +} + +int lb_vip_del_ass_withlock(u32 vip_index, ip46_address_t *addresses, u32 n, + u8 flush) { lb_main_t *lbm = &lb_main; u32 now = (u32) vlib_time_now(vlib_get_main()); @@ -802,6 +834,12 @@ next: vec_foreach(ip, indexes) { lbm->ass[*ip].flags &= ~LB_AS_FLAGS_USED; lbm->ass[*ip].last_used = now; + + if(flush) + { + /* flush flow table for deleted ASs*/ + lb_flush_vip_as(vip_index, *ip); + } } //Recompute flows @@ -812,10 +850,10 @@ next: return 0; } -int lb_vip_del_ass(u32 vip_index, ip46_address_t *addresses, u32 n) +int lb_vip_del_ass(u32 vip_index, ip46_address_t *addresses, u32 n, u8 flush) { lb_get_writer_lock(); - int ret = lb_vip_del_ass_withlock(vip_index, addresses, n); + int ret = lb_vip_del_ass_withlock(vip_index, addresses, n, flush); lb_put_writer_lock(); return ret; @@ -825,7 +863,7 @@ static int lb_vip_prefix_index_alloc (lb_main_t *lbm) { /* - * Check for dynamically allocaetd instance number. + * Check for dynamically allocated instance number. */ u32 bit; @@ -913,7 +951,7 @@ static void lb_vip_add_adjacency(lb_main_t *lbm, lb_vip_t *vip, dpo_set(&dpo, dpo_type, proto, *vip_prefix_index); fib_table_entry_special_dpo_add(0, &pfx, - FIB_SOURCE_PLUGIN_HI, + lb_fib_src, FIB_ENTRY_FLAG_EXCLUSIVE, &dpo); dpo_reset(&dpo); @@ -952,10 +990,15 @@ static int lb_vip_del_port_filter(lb_main_t *lbm, lb_vip_t *vip) key.vip_prefix_index = vip->vip_prefix_index; key.protocol = vip->protocol; key.port = clib_host_to_net_u16(vip->port); + key.rsv = 0; kv.key = key.as_u64; - if(clib_bihash_search_8_8(&lbm->vip_index_per_port, &kv, &value) == 0) - m = pool_elt_at_index (lbm->vips, value.value); + if(clib_bihash_search_8_8(&lbm->vip_index_per_port, &kv, &value) != 0) + { + clib_warning("looking up vip_index_per_port failed."); + return VNET_API_ERROR_NO_SUCH_ENTRY; + } + m = pool_elt_at_index (lbm->vips, value.value); ASSERT (m); kv.value = m - lbm->vips; @@ -997,7 +1040,7 @@ static void lb_vip_del_adjacency(lb_main_t *lbm, lb_vip_t *vip) pfx.fp_len = vip->plen; pfx.fp_proto = FIB_PROTOCOL_IP6; } - fib_table_entry_special_remove(0, &pfx, FIB_SOURCE_PLUGIN_HI); + fib_table_entry_special_remove(0, &pfx, lb_fib_src); } int lb_vip_add(lb_vip_add_args_t args, u32 *vip_index) @@ -1158,10 +1201,11 @@ int lb_vip_del(u32 vip_index) { lb_main_t *lbm = &lb_main; lb_vip_t *vip; + int rv = 0; /* Does not remove default vip, i.e. vip_index = 0 */ if (vip_index == 0) - return 0; + return VNET_API_ERROR_INVALID_VALUE; lb_get_writer_lock(); if (!(vip = lb_vip_get_by_index(vip_index))) { @@ -1177,12 +1221,13 @@ int lb_vip_del(u32 vip_index) ip46_address_t *ass = 0; lb_as_t *as; u32 *as_index; + pool_foreach(as_index, vip->as_indexes, { as = &lbm->ass[*as_index]; vec_add1(ass, as->address); }); if (vec_len(ass)) - lb_vip_del_ass_withlock(vip_index, ass, vec_len(ass)); + lb_vip_del_ass_withlock(vip_index, ass, vec_len(ass), 0); vec_free(ass); } @@ -1192,20 +1237,20 @@ int lb_vip_del(u32 vip_index) //Delete per-port vip filtering entry if (vip->port != 0) { - lb_vip_del_port_filter(lbm, vip); + rv = lb_vip_del_port_filter(lbm, vip); } //Set the VIP as unused vip->flags &= ~LB_VIP_FLAGS_USED; lb_put_writer_lock(); - return 0; + return rv; } /* *INDENT-OFF* */ VLIB_PLUGIN_REGISTER () = { .version = VPP_BUILD_VER, - .description = "Load Balancer", + .description = "Load Balancer (LB)", }; /* *INDENT-ON* */ @@ -1336,6 +1381,7 @@ lb_init (vlib_main_t * vm) //Allocate and init default VIP. lbm->vips = 0; pool_get(lbm->vips, default_vip); + default_vip->new_flow_table_mask = 0; default_vip->prefix.ip6.as_u64[0] = 0xffffffffffffffffL; default_vip->prefix.ip6.as_u64[1] = 0xffffffffffffffffL; default_vip->protocol = ~0; @@ -1344,8 +1390,7 @@ lb_init (vlib_main_t * vm) lbm->per_cpu = 0; vec_validate(lbm->per_cpu, tm->n_vlib_mains - 1); - lbm->writer_lock = clib_mem_alloc_aligned (CLIB_CACHE_LINE_BYTES, CLIB_CACHE_LINE_BYTES); - lbm->writer_lock[0] = 0; + clib_spinlock_init (&lbm->writer_lock); lbm->per_cpu_sticky_buckets = LB_DEFAULT_PER_CPU_STICKY_BUCKETS; lbm->flow_timeout = LB_DEFAULT_FLOW_TIMEOUT; lbm->ip4_src_address.as_u32 = 0xffffffff; @@ -1379,6 +1424,12 @@ lb_init (vlib_main_t * vm) default_as->address.ip6.as_u64[0] = 0xffffffffffffffffL; default_as->address.ip6.as_u64[1] = 0xffffffffffffffffL; + /* Generate a valid flow table for default VIP */ + default_vip->as_indexes = NULL; + lb_get_writer_lock(); + lb_vip_update_new_flow_table(default_vip); + lb_put_writer_lock(); + lbm->vip_index_by_nodeport = hash_create_mem (0, sizeof(u16), sizeof (uword)); @@ -1397,6 +1448,11 @@ lb_init (vlib_main_t * vm) #define _(a,b,c) lbm->vip_counters[c].name = b; lb_foreach_vip_counter #undef _ + + lb_fib_src = fib_source_allocate("lb", + FIB_SOURCE_PRIORITY_HI, + FIB_SOURCE_BH_SIMPLE); + return NULL; }