aboutsummaryrefslogtreecommitdiffstats
path: root/src/plugins/lb/lb.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/lb.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/lb.c')
-rw-r--r--src/plugins/lb/lb.c129
1 files changed, 128 insertions, 1 deletions
diff --git a/src/plugins/lb/lb.c b/src/plugins/lb/lb.c
index dfdc5066a3d..782833495c1 100644
--- a/src/plugins/lb/lb.c
+++ b/src/plugins/lb/lb.c
@@ -93,6 +93,78 @@ const static char* const * const lb_dpo_nat6_port_nodes[DPO_PROTO_NUM] =
[DPO_PROTO_IP6] = lb_dpo_nat6_ip6_port,
};
+const static char *const lb_dpo_gre4_ip4_sticky[] = { "lb4-gre4-sticky",
+ NULL };
+const static char *const lb_dpo_gre4_ip6_sticky[] = { "lb6-gre4-sticky",
+ NULL };
+const static char *const *const lb_dpo_gre4_sticky_nodes[DPO_PROTO_NUM] = {
+ [DPO_PROTO_IP4] = lb_dpo_gre4_ip4_sticky,
+ [DPO_PROTO_IP6] = lb_dpo_gre4_ip6_sticky,
+};
+
+const static char *const lb_dpo_gre6_ip4_sticky[] = { "lb4-gre6-sticky",
+ NULL };
+const static char *const lb_dpo_gre6_ip6_sticky[] = { "lb6-gre6-sticky",
+ NULL };
+const static char *const *const lb_dpo_gre6_sticky_nodes[DPO_PROTO_NUM] = {
+ [DPO_PROTO_IP4] = lb_dpo_gre6_ip4_sticky,
+ [DPO_PROTO_IP6] = lb_dpo_gre6_ip6_sticky,
+};
+
+const static char *const lb_dpo_gre4_ip4_port_sticky[] = {
+ "lb4-gre4-port-sticky", NULL
+};
+const static char *const lb_dpo_gre4_ip6_port_sticky[] = {
+ "lb6-gre4-port-sticky", NULL
+};
+const static char *const
+ *const lb_dpo_gre4_port_sticky_nodes[DPO_PROTO_NUM] = {
+ [DPO_PROTO_IP4] = lb_dpo_gre4_ip4_port_sticky,
+ [DPO_PROTO_IP6] = lb_dpo_gre4_ip6_port_sticky,
+ };
+
+const static char *const lb_dpo_gre6_ip4_port_sticky[] = {
+ "lb4-gre6-port-sticky", NULL
+};
+const static char *const lb_dpo_gre6_ip6_port_sticky[] = {
+ "lb6-gre6-port-sticky", NULL
+};
+const static char *const
+ *const lb_dpo_gre6_port_sticky_nodes[DPO_PROTO_NUM] = {
+ [DPO_PROTO_IP4] = lb_dpo_gre6_ip4_port_sticky,
+ [DPO_PROTO_IP6] = lb_dpo_gre6_ip6_port_sticky,
+ };
+
+const static char *const lb_dpo_l3dsr_ip4_sticky[] = { "lb4-l3dsr-sticky",
+ NULL };
+const static char *const *const lb_dpo_l3dsr_sticky_nodes[DPO_PROTO_NUM] = {
+ [DPO_PROTO_IP4] = lb_dpo_l3dsr_ip4_sticky,
+};
+
+const static char *const lb_dpo_l3dsr_ip4_port_sticky[] = {
+ "lb4-l3dsr-port-sticky", NULL
+};
+const static char *const
+ *const lb_dpo_l3dsr_port_sticky_nodes[DPO_PROTO_NUM] = {
+ [DPO_PROTO_IP4] = lb_dpo_l3dsr_ip4_port_sticky,
+ };
+
+const static char *const lb_dpo_nat4_ip4_port_sticky[] = {
+ "lb4-nat4-port-sticky", NULL
+};
+const static char *const
+ *const lb_dpo_nat4_port_sticky_nodes[DPO_PROTO_NUM] = {
+ [DPO_PROTO_IP4] = lb_dpo_nat4_ip4_port_sticky,
+ };
+
+const static char *const lb_dpo_nat6_ip6_port_sticky[] = {
+ "lb6-nat6-port-sticky", NULL
+};
+const static char *const
+ *const lb_dpo_nat6_port_sticky_nodes[DPO_PROTO_NUM] = {
+ [DPO_PROTO_IP6] = lb_dpo_nat6_ip6_port_sticky,
+ };
+
u32 lb_hash_time_now(vlib_main_t * vm)
{
return (u32) (vlib_time_now(vm) + 10000);
@@ -198,15 +270,18 @@ u8 *format_lb_vip_detailed (u8 * s, va_list * args)
lb_vip_t *vip = va_arg (*args, lb_vip_t *);
u32 indent = format_get_indent (s);
- s = format(s, "%U %U [%lu] %U%s\n"
+ /* clang-format off */
+ s = format(s, "%U %U [%lu] %U%s%s\n"
"%U new_size:%u\n",
format_white_space, indent,
format_lb_vip_type, vip->type,
vip - lbm->vips,
format_ip46_prefix, &vip->prefix, (u32) vip->plen, IP46_TYPE_ANY,
+ lb_vip_is_src_ip_sticky (vip) ? " src_ip_sticky" : "",
(vip->flags & LB_VIP_FLAGS_USED)?"":" removed",
format_white_space, indent,
vip->new_flow_table_mask + 1);
+ /* clang-format on */
if (vip->port != 0)
{
@@ -949,6 +1024,22 @@ static void lb_vip_add_adjacency(lb_main_t *lbm, lb_vip_t *vip,
dpo_type = lbm->dpo_nat4_port_type;
else if (lb_vip_is_nat6_port(vip))
dpo_type = lbm->dpo_nat6_port_type;
+ else if (lb_vip_is_gre4_sticky (vip))
+ dpo_type = lbm->dpo_gre4_sticky_type;
+ else if (lb_vip_is_gre6_sticky (vip))
+ dpo_type = lbm->dpo_gre6_sticky_type;
+ else if (lb_vip_is_gre4_port_sticky (vip))
+ dpo_type = lbm->dpo_gre4_port_sticky_type;
+ else if (lb_vip_is_gre6_port_sticky (vip))
+ dpo_type = lbm->dpo_gre6_port_sticky_type;
+ else if (lb_vip_is_l3dsr_sticky (vip))
+ dpo_type = lbm->dpo_l3dsr_sticky_type;
+ else if (lb_vip_is_l3dsr_port_sticky (vip))
+ dpo_type = lbm->dpo_l3dsr_port_sticky_type;
+ else if (lb_vip_is_nat4_port_sticky (vip))
+ dpo_type = lbm->dpo_nat4_port_sticky_type;
+ else if (lb_vip_is_nat6_port_sticky (vip))
+ dpo_type = lbm->dpo_nat6_port_sticky_type;
dpo_set(&dpo, dpo_type, proto, *vip_prefix_index);
fib_table_entry_special_dpo_add(0,
@@ -1147,6 +1238,10 @@ int lb_vip_add(lb_vip_add_args_t args, u32 *vip_index)
}
vip->flags = LB_VIP_FLAGS_USED;
+ if (args.src_ip_sticky)
+ {
+ vip->flags |= LB_VIP_FLAGS_SRC_IP_STICKY;
+ }
vip->as_indexes = 0;
//Validate counters
@@ -1311,6 +1406,22 @@ lb_as_stack (lb_as_t *as)
dpo_type = lbm->dpo_nat4_port_type;
else if (lb_vip_is_nat6_port(vip))
dpo_type = lbm->dpo_nat6_port_type;
+ else if (lb_vip_is_gre4_sticky (vip))
+ dpo_type = lbm->dpo_gre4_sticky_type;
+ else if (lb_vip_is_gre6_sticky (vip))
+ dpo_type = lbm->dpo_gre6_sticky_type;
+ else if (lb_vip_is_gre4_port_sticky (vip))
+ dpo_type = lbm->dpo_gre4_port_sticky_type;
+ else if (lb_vip_is_gre6_port_sticky (vip))
+ dpo_type = lbm->dpo_gre6_port_sticky_type;
+ else if (lb_vip_is_l3dsr_sticky (vip))
+ dpo_type = lbm->dpo_l3dsr_sticky_type;
+ else if (lb_vip_is_l3dsr_port_sticky (vip))
+ dpo_type = lbm->dpo_l3dsr_port_sticky_type;
+ else if (lb_vip_is_nat4_port_sticky (vip))
+ dpo_type = lbm->dpo_nat4_port_sticky_type;
+ else if (lb_vip_is_nat6_port_sticky (vip))
+ dpo_type = lbm->dpo_nat6_port_sticky_type;
dpo_stack(dpo_type,
lb_vip_is_ip4(vip->type)?DPO_PROTO_IP4:DPO_PROTO_IP6,
@@ -1412,6 +1523,22 @@ lb_init (vlib_main_t * vm)
lb_dpo_nat4_port_nodes);
lbm->dpo_nat6_port_type = dpo_register_new_type(&lb_vft,
lb_dpo_nat6_port_nodes);
+ lbm->dpo_gre4_sticky_type =
+ dpo_register_new_type (&lb_vft, lb_dpo_gre4_sticky_nodes);
+ lbm->dpo_gre6_sticky_type =
+ dpo_register_new_type (&lb_vft, lb_dpo_gre6_sticky_nodes);
+ lbm->dpo_gre4_port_sticky_type =
+ dpo_register_new_type (&lb_vft, lb_dpo_gre4_port_sticky_nodes);
+ lbm->dpo_gre6_port_sticky_type =
+ dpo_register_new_type (&lb_vft, lb_dpo_gre6_port_sticky_nodes);
+ lbm->dpo_l3dsr_sticky_type =
+ dpo_register_new_type (&lb_vft, lb_dpo_l3dsr_sticky_nodes);
+ lbm->dpo_l3dsr_port_sticky_type =
+ dpo_register_new_type (&lb_vft, lb_dpo_l3dsr_port_sticky_nodes);
+ lbm->dpo_nat4_port_sticky_type =
+ dpo_register_new_type (&lb_vft, lb_dpo_nat4_port_sticky_nodes);
+ lbm->dpo_nat6_port_sticky_type =
+ dpo_register_new_type (&lb_vft, lb_dpo_nat6_port_sticky_nodes);
lbm->fib_node_type = fib_node_register_new_type ("lb", &lb_fib_node_vft);
//Init AS reference counters