diff options
-rw-r--r-- | src/plugins/lb/api.c | 2 | ||||
-rw-r--r-- | src/plugins/lb/cli.c | 124 | ||||
-rw-r--r-- | src/plugins/lb/lb.api | 2 | ||||
-rw-r--r-- | src/plugins/lb/lb.c | 50 | ||||
-rw-r--r-- | src/plugins/lb/lb.h | 2 |
5 files changed, 164 insertions, 16 deletions
diff --git a/src/plugins/lb/api.c b/src/plugins/lb/api.c index 18aae43b11d..5194c2e88ec 100644 --- a/src/plugins/lb/api.c +++ b/src/plugins/lb/api.c @@ -218,7 +218,7 @@ vl_api_lb_add_del_as_t_handler goto done; if (mp->is_del) - rv = lb_vip_del_ass(vip_index, &as_address, 1); + rv = lb_vip_del_ass(vip_index, &as_address, 1, mp->is_flush); else rv = lb_vip_add_ass(vip_index, &as_address, 1); diff --git a/src/plugins/lb/cli.c b/src/plugins/lb/cli.c index cfe8f381b13..6e1b7c1b1ee 100644 --- a/src/plugins/lb/cli.c +++ b/src/plugins/lb/cli.c @@ -201,6 +201,7 @@ lb_as_command_fn (vlib_main_t * vm, u32 port = 0; u8 protocol = 0; u8 del = 0; + u8 flush = 0; int ret; clib_error_t *error = 0; @@ -219,11 +220,17 @@ lb_as_command_fn (vlib_main_t * vm, { if (unformat(line_input, "%U", unformat_ip46_address, &as_addr, IP46_TYPE_ANY)) - { - vec_add1(as_array, as_addr); - } else if (unformat(line_input, "del")) { - del = 1; - } + { + vec_add1(as_array, as_addr); + } + else if (unformat(line_input, "del")) + { + del = 1; + } + else if (unformat(line_input, "flush")) + { + flush = 1; + } else if (unformat(line_input, "protocol tcp")) { protocol = (u8)IP_PROTOCOL_TCP; @@ -262,7 +269,7 @@ lb_as_command_fn (vlib_main_t * vm, clib_warning("vip index is %d", vip_index); if (del) { - if ((ret = lb_vip_del_ass(vip_index, as_array, vec_len(as_array)))) + if ((ret = lb_vip_del_ass(vip_index, as_array, vec_len(as_array), flush))) { error = clib_error_return (0, "lb_vip_del_ass error %d", ret); goto done; @@ -286,7 +293,7 @@ VLIB_CLI_COMMAND (lb_as_command, static) = { .path = "lb as", .short_help = "lb as <vip-prefix> [protocol (tcp|udp) port <n>]" - " [<address> [<address> [...]]] [del]", + " [<address> [<address> [...]]] [del] [flush]", .function = lb_as_command_fn, }; @@ -490,6 +497,109 @@ VLIB_CLI_COMMAND (lb_set_interface_nat6_command, static) = { .short_help = "lb set interface nat6 in <intfc> [del]", }; +int +lb_flush_vip (u32 vip_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 (b->vip[i] == vip_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; + } + } + } + } + + return 0; +} + +static clib_error_t * +lb_flush_vip_command_fn (vlib_main_t * vm, + unformat_input_t * input, + vlib_cli_command_t * cmd) +{ + unformat_input_t _line_input, *line_input = &_line_input; + int ret; + ip46_address_t vip_prefix; + u8 vip_plen; + u32 vip_index; + u8 protocol = 0; + u32 port = 0; + clib_error_t *error = 0; + + if (!unformat_user (input, unformat_line_input, line_input)) + return 0; + + if (!unformat(line_input, "%U", unformat_ip46_prefix, &vip_prefix, + &vip_plen, IP46_TYPE_ANY, &vip_plen)) { + error = clib_error_return (0, "invalid vip prefix: '%U'", + format_unformat_error, line_input); + goto done; + } + + while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) + { + if (unformat(line_input, "protocol tcp")) + { + protocol = (u8)IP_PROTOCOL_TCP; + } + else if (unformat(line_input, "protocol udp")) + { + protocol = (u8)IP_PROTOCOL_UDP; + } + else if (unformat(line_input, "port %d", &port)) + ; + } + + if (port == 0) + { + protocol = ~0; + } + + if ((ret = lb_vip_find_index(&vip_prefix, vip_plen, protocol, + (u16)port, &vip_index))){ + error = clib_error_return (0, "lb_vip_find_index error %d", ret); + goto done; + } + + if ((ret = lb_flush_vip(vip_index))) + { + error = clib_error_return (0, "lb_flush_vip error %d", ret); + } + else + { + vlib_cli_output(vm, "lb_flush_vip ok %d", vip_index); + } + +done: + unformat_free (line_input); + + return error; +} + +/* + * flush lb flowtable as per vip + */ +VLIB_CLI_COMMAND (lb_flush_vip_command, static) = +{ + .path = "lb flush vip", + .short_help = "lb flush vip <prefix> " + "[protocol (tcp|udp) port <n>] exec []", + .function = lb_flush_vip_command_fn, +}; + static clib_error_t * lb_flowtable_flush_command_fn (vlib_main_t * vm, unformat_input_t * input, vlib_cli_command_t * cmd) diff --git a/src/plugins/lb/lb.api b/src/plugins/lb/lb.api index de3d0c1e5e7..545d6b18c3e 100644 --- a/src/plugins/lb/lb.api +++ b/src/plugins/lb/lb.api @@ -61,6 +61,7 @@ autoreply define lb_add_del_vip { @param port - destination port. @param as_address - The application server address (IPv4 in lower order 32 bits). @param is_del - The AS should be removed. + @param is_flush - The sessions related to this AS should be flushed. */ autoreply define lb_add_del_as { u32 client_index; @@ -71,5 +72,6 @@ autoreply define lb_add_del_as { u16 port; u8 as_address[16]; u8 is_del; + u8 is_flush; }; diff --git a/src/plugins/lb/lb.c b/src/plugins/lb/lb.c index 041c65c1326..42103eeef2a 100644 --- a/src/plugins/lb/lb.c +++ b/src/plugins/lb/lb.c @@ -762,12 +762,41 @@ 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 ((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; + } + } + } + } + + return 0; +} + +int lb_vip_del_ass_withlock(u32 vip_index, ip46_address_t *addresses, u32 n, + u32 *as_index) { lb_main_t *lbm = &lb_main; u32 now = (u32) vlib_time_now(vlib_get_main()); u32 *ip = 0; - u32 as_index = 0; lb_vip_t *vip; if (!(vip = lb_vip_get_by_index(vip_index))) { @@ -776,7 +805,7 @@ int lb_vip_del_ass_withlock(u32 vip_index, ip46_address_t *addresses, u32 n) u32 *indexes = NULL; while (n--) { - if (lb_as_find_index_vip(vip, &addresses[n], &as_index)) { + if (lb_as_find_index_vip(vip, &addresses[n], as_index)) { vec_free(indexes); return VNET_API_ERROR_NO_SUCH_ENTRY; } @@ -790,7 +819,7 @@ int lb_vip_del_ass_withlock(u32 vip_index, ip46_address_t *addresses, u32 n) } } - vec_add1(indexes, as_index); + vec_add1(indexes, *as_index); next: continue; } @@ -812,12 +841,19 @@ 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) { + u32 as_index = 0; 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, &as_index); lb_put_writer_lock(); + if(flush) + { + /* flush flow table per as of per-port-vip */ + ret = lb_flush_vip_as(vip_index, as_index); + } + return ret; } @@ -1182,7 +1218,7 @@ int lb_vip_del(u32 vip_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), as_index); vec_free(ass); } diff --git a/src/plugins/lb/lb.h b/src/plugins/lb/lb.h index 3177f892ae5..c77a1b6e294 100644 --- a/src/plugins/lb/lb.h +++ b/src/plugins/lb/lb.h @@ -606,7 +606,7 @@ int lb_vip_find_index(ip46_address_t *prefix, u8 plen, u8 protocol, #define lb_vip_get_by_index(index) (pool_is_free_index(lb_main.vips, index)?NULL:pool_elt_at_index(lb_main.vips, index)) int lb_vip_add_ass(u32 vip_index, ip46_address_t *addresses, u32 n); -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); u32 lb_hash_time_now(vlib_main_t * vm); |