diff options
author | Nobuhiro MIKI <nmiki@yahoo-corp.jp> | 2022-09-28 15:53:17 +0900 |
---|---|---|
committer | Beno�t Ganne <bganne@cisco.com> | 2023-01-18 10:53:23 +0000 |
commit | 613e6dc0bf928def5d337312d522e1a15df87b00 (patch) | |
tree | 04e592643029774fadcbfc8f8e82df778b867df9 /src/plugins/lb/node.c | |
parent | 893a0c3130e1d868c939db6dcde258da1277cf41 (diff) |
lb: add source ip based sticky load balancing
This patch adds source ip based sticky session, which is already
implemented in many hardware LBs and software LBs. Note that sticky
sessions may be reset if the hash is recalculated as ASs are added
or deleted.
Since this feature is unrelated to the other existing options, the
lb_add_del_vip API version has been upgraded to v2 and a new option
"src_ip_sticky" has been added.
Type: feature
Signed-off-by: Nobuhiro MIKI <nmiki@yahoo-corp.jp>
Change-Id: I3eb3680a28defbc701f28c873933ec2fb54544ab
Diffstat (limited to 'src/plugins/lb/node.c')
-rw-r--r-- | src/plugins/lb/node.c | 279 |
1 files changed, 257 insertions, 22 deletions
diff --git a/src/plugins/lb/node.c b/src/plugins/lb/node.c index b5e9da71376..f823ea9ce3c 100644 --- a/src/plugins/lb/node.c +++ b/src/plugins/lb/node.c @@ -174,8 +174,8 @@ lb_node_get_other_ports6 (ip6_header_t *ip60) } static_always_inline void -lb_node_get_hash (lb_main_t *lbm, vlib_buffer_t *p, u8 is_input_v4, - u32 *hash, u32 *vip_idx, u8 per_port_vip) +lb_node_get_hash (lb_main_t *lbm, vlib_buffer_t *p, u8 is_input_v4, u32 *hash, + u32 *vip_idx, u8 per_port_vip, u8 src_ip_sticky) { vip_port_key_t key; clib_bihash_kv_8_8_t kv, value; @@ -203,7 +203,15 @@ lb_node_get_hash (lb_main_t *lbm, vlib_buffer_t *p, u8 is_input_v4, else ports = lb_node_get_other_ports4 (ip40); - *hash = lb_hash_hash (*((u64 *) &ip40->address_pair), ports, 0, 0, 0); + if (src_ip_sticky) + { + *hash = lb_hash_hash (*((u64 *) &ip40->address_pair), 0, 0, 0, 0); + } + else + { + *hash = + lb_hash_hash (*((u64 *) &ip40->address_pair), ports, 0, 0, 0); + } if (per_port_vip) { @@ -225,10 +233,18 @@ lb_node_get_hash (lb_main_t *lbm, vlib_buffer_t *p, u8 is_input_v4, else ports = lb_node_get_other_ports6 (ip60); - *hash = lb_hash_hash (ip60->src_address.as_u64[0], - ip60->src_address.as_u64[1], - ip60->dst_address.as_u64[0], - ip60->dst_address.as_u64[1], ports); + if (src_ip_sticky) + { + *hash = lb_hash_hash ( + ip60->src_address.as_u64[0], ip60->src_address.as_u64[1], + ip60->dst_address.as_u64[0], ip60->dst_address.as_u64[1], 0); + } + else + { + *hash = lb_hash_hash ( + ip60->src_address.as_u64[0], ip60->src_address.as_u64[1], + ip60->dst_address.as_u64[0], ip60->dst_address.as_u64[1], ports); + } if (per_port_vip) { @@ -251,13 +267,15 @@ lb_node_get_hash (lb_main_t *lbm, vlib_buffer_t *p, u8 is_input_v4, } } +/* clang-format off */ static_always_inline uword lb_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame, u8 is_input_v4, //Compile-time parameter stating that is input is v4 (or v6) lb_encap_type_t encap_type, //Compile-time parameter is GRE4/GRE6/L3DSR/NAT4/NAT6 - u8 per_port_vip) //Compile-time parameter stating that is per_port_vip or not + u8 per_port_vip, //Compile-time parameter stating that is per_port_vip or not + u8 src_ip_sticky) //Compile-time parameter stating that is source ip based sticky or not { lb_main_t *lbm = &lb_main; u32 n_left_from, *from, next_index, *to_next, n_left_to_next; @@ -275,7 +293,7 @@ lb_node_fn (vlib_main_t * vm, { vlib_buffer_t *p0 = vlib_get_buffer (vm, from[0]); lb_node_get_hash (lbm, p0, is_input_v4, &nexthash0, - &next_vip_idx0, per_port_vip); + &next_vip_idx0, per_port_vip, src_ip_sticky); } while (n_left_from > 0) @@ -300,7 +318,7 @@ lb_node_fn (vlib_main_t * vm, //Compute next hash and prefetch bucket lb_node_get_hash (lbm, p1, is_input_v4, &nexthash0, &next_vip_idx0, - per_port_vip); + per_port_vip, src_ip_sticky); lb_hash_prefetch_bucket (sticky_ht, nexthash0); //Prefetch for encap, next CLIB_PREFETCH(vlib_buffer_get_current (p1) - 64, 64, STORE); @@ -565,6 +583,7 @@ lb_node_fn (vlib_main_t * vm, return frame->n_vectors; } +/* clang-format on */ u8 * format_nodeport_lb_trace (u8 * s, va_list * args) @@ -947,84 +966,168 @@ static uword lb6_gre6_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame) { - return lb_node_fn (vm, node, frame, 0, LB_ENCAP_TYPE_GRE6, 0); + return lb_node_fn (vm, node, frame, 0, LB_ENCAP_TYPE_GRE6, 0, 0); } static uword lb6_gre4_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame) { - return lb_node_fn (vm, node, frame, 0, LB_ENCAP_TYPE_GRE4, 0); + return lb_node_fn (vm, node, frame, 0, LB_ENCAP_TYPE_GRE4, 0, 0); } static uword lb4_gre6_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame) { - return lb_node_fn (vm, node, frame, 1, LB_ENCAP_TYPE_GRE6, 0); + return lb_node_fn (vm, node, frame, 1, LB_ENCAP_TYPE_GRE6, 0, 0); } static uword lb4_gre4_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame) { - return lb_node_fn (vm, node, frame, 1, LB_ENCAP_TYPE_GRE4, 0); + return lb_node_fn (vm, node, frame, 1, LB_ENCAP_TYPE_GRE4, 0, 0); } static uword lb6_gre6_port_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame) { - return lb_node_fn (vm, node, frame, 0, LB_ENCAP_TYPE_GRE6, 1); + return lb_node_fn (vm, node, frame, 0, LB_ENCAP_TYPE_GRE6, 1, 0); } static uword lb6_gre4_port_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame) { - return lb_node_fn (vm, node, frame, 0, LB_ENCAP_TYPE_GRE4, 1); + return lb_node_fn (vm, node, frame, 0, LB_ENCAP_TYPE_GRE4, 1, 0); } static uword lb4_gre6_port_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame) { - return lb_node_fn (vm, node, frame, 1, LB_ENCAP_TYPE_GRE6, 1); + return lb_node_fn (vm, node, frame, 1, LB_ENCAP_TYPE_GRE6, 1, 0); } static uword lb4_gre4_port_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame) { - return lb_node_fn (vm, node, frame, 1, LB_ENCAP_TYPE_GRE4, 1); + return lb_node_fn (vm, node, frame, 1, LB_ENCAP_TYPE_GRE4, 1, 0); } static uword lb4_l3dsr_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame) { - return lb_node_fn (vm, node, frame, 1, LB_ENCAP_TYPE_L3DSR, 0); + return lb_node_fn (vm, node, frame, 1, LB_ENCAP_TYPE_L3DSR, 0, 0); } static uword lb4_l3dsr_port_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame) { - return lb_node_fn (vm, node, frame, 1, LB_ENCAP_TYPE_L3DSR, 1); + return lb_node_fn (vm, node, frame, 1, LB_ENCAP_TYPE_L3DSR, 1, 0); } static uword lb6_nat6_port_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame) { - return lb_node_fn (vm, node, frame, 0, LB_ENCAP_TYPE_NAT6, 1); + return lb_node_fn (vm, node, frame, 0, LB_ENCAP_TYPE_NAT6, 1, 0); } static uword lb4_nat4_port_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame) { - return lb_node_fn (vm, node, frame, 1, LB_ENCAP_TYPE_NAT4, 1); + return lb_node_fn (vm, node, frame, 1, LB_ENCAP_TYPE_NAT4, 1, 0); +} + +static uword +lb6_gre6_sticky_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node, + vlib_frame_t *frame) +{ + return lb_node_fn (vm, node, frame, 0, LB_ENCAP_TYPE_GRE6, 0, 1); +} + +static uword +lb6_gre4_sticky_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node, + vlib_frame_t *frame) +{ + return lb_node_fn (vm, node, frame, 0, LB_ENCAP_TYPE_GRE4, 0, 1); +} + +static uword +lb4_gre6_sticky_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node, + vlib_frame_t *frame) +{ + return lb_node_fn (vm, node, frame, 1, LB_ENCAP_TYPE_GRE6, 0, 1); +} + +static uword +lb4_gre4_sticky_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node, + vlib_frame_t *frame) +{ + return lb_node_fn (vm, node, frame, 1, LB_ENCAP_TYPE_GRE4, 0, 1); +} + +static uword +lb6_gre6_port_sticky_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node, + vlib_frame_t *frame) +{ + return lb_node_fn (vm, node, frame, 0, LB_ENCAP_TYPE_GRE6, 1, 1); +} + +static uword +lb6_gre4_port_sticky_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node, + vlib_frame_t *frame) +{ + return lb_node_fn (vm, node, frame, 0, LB_ENCAP_TYPE_GRE4, 1, 1); +} + +static uword +lb4_gre6_port_sticky_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node, + vlib_frame_t *frame) +{ + return lb_node_fn (vm, node, frame, 1, LB_ENCAP_TYPE_GRE6, 1, 1); +} + +static uword +lb4_gre4_port_sticky_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node, + vlib_frame_t *frame) +{ + return lb_node_fn (vm, node, frame, 1, LB_ENCAP_TYPE_GRE4, 1, 1); +} + +static uword +lb4_l3dsr_sticky_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node, + vlib_frame_t *frame) +{ + return lb_node_fn (vm, node, frame, 1, LB_ENCAP_TYPE_L3DSR, 0, 1); +} + +static uword +lb4_l3dsr_port_sticky_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node, + vlib_frame_t *frame) +{ + return lb_node_fn (vm, node, frame, 1, LB_ENCAP_TYPE_L3DSR, 1, 1); +} + +static uword +lb6_nat6_port_sticky_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node, + vlib_frame_t *frame) +{ + return lb_node_fn (vm, node, frame, 0, LB_ENCAP_TYPE_NAT6, 1, 1); +} + +static uword +lb4_nat4_port_sticky_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node, + vlib_frame_t *frame) +{ + return lb_node_fn (vm, node, frame, 1, LB_ENCAP_TYPE_NAT4, 1, 1); } static uword @@ -1197,6 +1300,138 @@ VLIB_REGISTER_NODE (lb4_nat4_port_node) = { [LB_NEXT_DROP] = "error-drop" }, }; +VLIB_REGISTER_NODE (lb6_gre6_sticky_node) = { + .function = lb6_gre6_sticky_node_fn, + .name = "lb6-gre6-sticky", + .vector_size = sizeof (u32), + .format_trace = format_lb_trace, + .n_errors = LB_N_ERROR, + .error_strings = lb_error_strings, + .n_next_nodes = LB_N_NEXT, + .next_nodes = { [LB_NEXT_DROP] = "error-drop" }, +}; + +VLIB_REGISTER_NODE (lb6_gre4_sticky_node) = { + .function = lb6_gre4_sticky_node_fn, + .name = "lb6-gre4-sticky", + .vector_size = sizeof (u32), + .format_trace = format_lb_trace, + .n_errors = LB_N_ERROR, + .error_strings = lb_error_strings, + .n_next_nodes = LB_N_NEXT, + .next_nodes = { [LB_NEXT_DROP] = "error-drop" }, +}; + +VLIB_REGISTER_NODE (lb4_gre6_sticky_node) = { + .function = lb4_gre6_sticky_node_fn, + .name = "lb4-gre6-sticky", + .vector_size = sizeof (u32), + .format_trace = format_lb_trace, + .n_errors = LB_N_ERROR, + .error_strings = lb_error_strings, + .n_next_nodes = LB_N_NEXT, + .next_nodes = { [LB_NEXT_DROP] = "error-drop" }, +}; + +VLIB_REGISTER_NODE (lb4_gre4_sticky_node) = { + .function = lb4_gre4_sticky_node_fn, + .name = "lb4-gre4-sticky", + .vector_size = sizeof (u32), + .format_trace = format_lb_trace, + .n_errors = LB_N_ERROR, + .error_strings = lb_error_strings, + .n_next_nodes = LB_N_NEXT, + .next_nodes = { [LB_NEXT_DROP] = "error-drop" }, +}; + +VLIB_REGISTER_NODE (lb6_gre6_port_sticky_node) = { + .function = lb6_gre6_port_sticky_node_fn, + .name = "lb6-gre6-port-sticky", + .vector_size = sizeof (u32), + .format_trace = format_lb_trace, + .n_errors = LB_N_ERROR, + .error_strings = lb_error_strings, + .n_next_nodes = LB_N_NEXT, + .next_nodes = { [LB_NEXT_DROP] = "error-drop" }, +}; + +VLIB_REGISTER_NODE (lb6_gre4_port_sticky_node) = { + .function = lb6_gre4_port_sticky_node_fn, + .name = "lb6-gre4-port-sticky", + .vector_size = sizeof (u32), + .format_trace = format_lb_trace, + .n_errors = LB_N_ERROR, + .error_strings = lb_error_strings, + .n_next_nodes = LB_N_NEXT, + .next_nodes = { [LB_NEXT_DROP] = "error-drop" }, +}; + +VLIB_REGISTER_NODE (lb4_gre6_port_sticky_node) = { + .function = lb4_gre6_port_sticky_node_fn, + .name = "lb4-gre6-port-sticky", + .vector_size = sizeof (u32), + .format_trace = format_lb_trace, + .n_errors = LB_N_ERROR, + .error_strings = lb_error_strings, + .n_next_nodes = LB_N_NEXT, + .next_nodes = { [LB_NEXT_DROP] = "error-drop" }, +}; + +VLIB_REGISTER_NODE (lb4_gre4_port_sticky_node) = { + .function = lb4_gre4_port_sticky_node_fn, + .name = "lb4-gre4-port-sticky", + .vector_size = sizeof (u32), + .format_trace = format_lb_trace, + .n_errors = LB_N_ERROR, + .error_strings = lb_error_strings, + .n_next_nodes = LB_N_NEXT, + .next_nodes = { [LB_NEXT_DROP] = "error-drop" }, +}; + +VLIB_REGISTER_NODE (lb4_l3dsr_port_sticky_node) = { + .function = lb4_l3dsr_port_sticky_node_fn, + .name = "lb4-l3dsr-port-sticky", + .vector_size = sizeof (u32), + .format_trace = format_lb_trace, + .n_errors = LB_N_ERROR, + .error_strings = lb_error_strings, + .n_next_nodes = LB_N_NEXT, + .next_nodes = { [LB_NEXT_DROP] = "error-drop" }, +}; + +VLIB_REGISTER_NODE (lb4_l3dsr_sticky_node) = { + .function = lb4_l3dsr_sticky_node_fn, + .name = "lb4-l3dsr-sticky", + .vector_size = sizeof (u32), + .format_trace = format_lb_trace, + .n_errors = LB_N_ERROR, + .error_strings = lb_error_strings, + .n_next_nodes = LB_N_NEXT, + .next_nodes = { [LB_NEXT_DROP] = "error-drop" }, +}; + +VLIB_REGISTER_NODE (lb6_nat6_port_sticky_node) = { + .function = lb6_nat6_port_sticky_node_fn, + .name = "lb6-nat6-port-sticky", + .vector_size = sizeof (u32), + .format_trace = format_lb_trace, + .n_errors = LB_N_ERROR, + .error_strings = lb_error_strings, + .n_next_nodes = LB_N_NEXT, + .next_nodes = { [LB_NEXT_DROP] = "error-drop" }, +}; + +VLIB_REGISTER_NODE (lb4_nat4_port_sticky_node) = { + .function = lb4_nat4_port_sticky_node_fn, + .name = "lb4-nat4-port-sticky", + .vector_size = sizeof (u32), + .format_trace = format_lb_trace, + .n_errors = LB_N_ERROR, + .error_strings = lb_error_strings, + .n_next_nodes = LB_N_NEXT, + .next_nodes = { [LB_NEXT_DROP] = "error-drop" }, +}; + static uword lb4_nodeport_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame) |