aboutsummaryrefslogtreecommitdiffstats
path: root/src/plugins/lb/node.c
diff options
context:
space:
mode:
authorNobuhiro MIKI <nmiki@yahoo-corp.jp>2022-09-28 15:53:17 +0900
committerBeno�t Ganne <bganne@cisco.com>2023-01-18 10:53:23 +0000
commit613e6dc0bf928def5d337312d522e1a15df87b00 (patch)
tree04e592643029774fadcbfc8f8e82df778b867df9 /src/plugins/lb/node.c
parent893a0c3130e1d868c939db6dcde258da1277cf41 (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.c279
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)