From 6a4375e02d8dd4ebcc2f79ee9f6abbafdd2f674c Mon Sep 17 00:00:00 2001 From: Hongjun Ni Date: Tue, 18 Sep 2018 23:25:02 +0800 Subject: [PATCH] LB: fix flush flow table issue Change-Id: Ib0a06ab71aed42eb5bb2ab2edf4844b2167e0610 Signed-off-by: Hongjun Ni --- src/plugins/lb/api.c | 45 +++++++++++++++++++++++++++++++++++++- src/plugins/lb/cli.c | 60 ++++++--------------------------------------------- src/plugins/lb/lb.api | 16 ++++++++++++++ src/plugins/lb/lb.c | 37 ++++++++++++++++++------------- src/plugins/lb/lb.h | 1 + 5 files changed, 90 insertions(+), 69 deletions(-) diff --git a/src/plugins/lb/api.c b/src/plugins/lb/api.c index 5194c2e88ec..c392123c792 100644 --- a/src/plugins/lb/api.c +++ b/src/plugins/lb/api.c @@ -239,11 +239,54 @@ static void *vl_api_lb_add_del_as_t_print FINISH; } +static void +vl_api_lb_flush_vip_t_handler +(vl_api_lb_flush_vip_t * mp) +{ + lb_main_t *lbm = &lb_main; + int rv = 0; + ip46_address_t vip_prefix; + u8 vip_plen; + u32 vip_index; + vl_api_lb_flush_vip_reply_t * rmp; + + if (mp->port == 0) + { + mp->protocol = ~0; + } + + memcpy (&(vip_prefix.ip6), mp->ip_prefix, sizeof(vip_prefix.ip6)); + + vip_plen = mp->prefix_length; + + rv = lb_vip_find_index(&vip_prefix, vip_plen, mp->protocol, + (u16)mp->port, &vip_index); + + rv = lb_flush_vip_as(vip_index, ~0); + + REPLY_MACRO (VL_API_LB_FLUSH_VIP_REPLY); +} + +static void *vl_api_lb_flush_vip_t_print +(vl_api_lb_flush_vip_t *mp, void * handle) +{ + u8 * s; + s = format (0, "SCRIPT: lb_add_del_vip "); + s = format (s, "%U ", format_ip46_prefix, + (ip46_address_t *)mp->ip_prefix, mp->prefix_length, IP46_TYPE_ANY); + + s = format (s, "protocol %u ", mp->protocol); + s = format (s, "port %u ", mp->port); + + FINISH; +} + /* List of message types that this plugin understands */ #define foreach_lb_plugin_api_msg \ _(LB_CONF, lb_conf) \ _(LB_ADD_DEL_VIP, lb_add_del_vip) \ -_(LB_ADD_DEL_AS, lb_add_del_as) +_(LB_ADD_DEL_AS, lb_add_del_as) \ +_(LB_FLUSH_VIP, lb_flush_vip) static clib_error_t * lb_api_init (vlib_main_t * vm) { diff --git a/src/plugins/lb/cli.c b/src/plugins/lb/cli.c index 6e1b7c1b1ee..a12a63354cc 100644 --- a/src/plugins/lb/cli.c +++ b/src/plugins/lb/cli.c @@ -497,32 +497,13 @@ VLIB_CLI_COMMAND (lb_set_interface_nat6_command, static) = { .short_help = "lb set interface nat6 in [del]", }; -int -lb_flush_vip (u32 vip_index) +static clib_error_t * +lb_flowtable_flush_command_fn (vlib_main_t * vm, + unformat_input_t * input, vlib_cli_command_t * cmd) { - 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; - } - } - } - } + lb_flush_vip_as(~0, 0); - return 0; + return NULL; } static clib_error_t * @@ -574,7 +555,7 @@ lb_flush_vip_command_fn (vlib_main_t * vm, goto done; } - if ((ret = lb_flush_vip(vip_index))) + if ((ret = lb_flush_vip_as(vip_index, ~0))) { error = clib_error_return (0, "lb_flush_vip error %d", ret); } @@ -596,37 +577,10 @@ VLIB_CLI_COMMAND (lb_flush_vip_command, static) = { .path = "lb flush vip", .short_help = "lb flush vip " - "[protocol (tcp|udp) port ] exec []", + "[protocol (tcp|udp) port ]", .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) -{ - 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) { - vlib_refcount_add(&lbm->as_refcount, thread_index, b->value[i], -1); - vlib_refcount_add(&lbm->as_refcount, thread_index, 0, 1); - } - - lb_hash_free(h); - lbm->per_cpu[thread_index].sticky_ht = 0; - } - } - - return NULL; -} - /* * flush all lb flowtables * This is indented for debug and unit-tests purposes only diff --git a/src/plugins/lb/lb.api b/src/plugins/lb/lb.api index 545d6b18c3e..d36f857f5de 100644 --- a/src/plugins/lb/lb.api +++ b/src/plugins/lb/lb.api @@ -75,3 +75,19 @@ autoreply define lb_add_del_as { u8 is_flush; }; +/** \brief Flush a given vip + @param client_index - opaque cookie to identify the sender + @param context - sender context, to match reply w/ request + @param ip_prefix - IP address (IPv4 in lower order 32 bits). + @param prefix_length - IP prefix length (96 + 'IPv4 prefix length' for IPv4). + @param protocol - tcp or udp. + @param port - destination port. +*/ +autoreply define lb_flush_vip { + u32 client_index; + u32 context; + u8 ip_prefix[16]; + u8 prefix_length; + u8 protocol; + u16 port; +}; diff --git a/src/plugins/lb/lb.c b/src/plugins/lb/lb.c index 601b297ffe8..1936c1983ee 100644 --- a/src/plugins/lb/lb.c +++ b/src/plugins/lb/lb.c @@ -766,8 +766,9 @@ lb_flush_vip_as (u32 vip_index, u32 as_index) lb_hash_bucket_t *b; lb_hash_foreach_entry(h, b, i) { - if ((b->vip[i] == vip_index) - || (b->value[i] == as_index)) + 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); @@ -775,18 +776,24 @@ lb_flush_vip_as (u32 vip_index, u32 as_index) 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, - u32 *as_index) + u8 flush) { 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))) { @@ -795,7 +802,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; } @@ -809,7 +816,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; } @@ -821,6 +828,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 @@ -833,17 +846,10 @@ next: 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, &as_index); + int ret = lb_vip_del_ass_withlock(vip_index, addresses, n, flush); 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; } @@ -1203,12 +1209,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), as_index); + lb_vip_del_ass_withlock(vip_index, ass, vec_len(ass), 0); vec_free(ass); } diff --git a/src/plugins/lb/lb.h b/src/plugins/lb/lb.h index c77a1b6e294..d09ac632be6 100644 --- a/src/plugins/lb/lb.h +++ b/src/plugins/lb/lb.h @@ -607,6 +607,7 @@ int lb_vip_find_index(ip46_address_t *prefix, u8 plen, u8 protocol, 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, u8 flush); +int lb_flush_vip_as (u32 vip_index, u32 as_index); u32 lb_hash_time_now(vlib_main_t * vm); -- 2.16.6