summaryrefslogtreecommitdiffstats
path: root/src/plugins/lb/node.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/lb/node.c')
-rw-r--r--src/plugins/lb/node.c246
1 files changed, 198 insertions, 48 deletions
diff --git a/src/plugins/lb/node.c b/src/plugins/lb/node.c
index b33ea22b5c1..8163e35a06e 100644
--- a/src/plugins/lb/node.c
+++ b/src/plugins/lb/node.c
@@ -173,14 +173,27 @@ lb_node_get_other_ports6 (ip6_header_t *ip60)
return 0;
}
-static_always_inline u32
-lb_node_get_hash (vlib_buffer_t *p, u8 is_input_v4)
+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)
{
- u32 hash;
+ vip_port_key_t key;
+ clib_bihash_kv_8_8_t kv, value;
+
+ /* For vip case, retrieve vip index for ip lookup */
+ *vip_idx = vnet_buffer (p)->ip.adj_index[VLIB_TX];
+
+ if (per_port_vip)
+ {
+ /* For per-port-vip case, ip lookup stores dummy index */
+ key.vip_prefix_index = *vip_idx;
+ }
+
if (is_input_v4)
{
ip4_header_t *ip40;
u64 ports;
+
ip40 = vlib_buffer_get_current (p);
if (PREDICT_TRUE(
ip40->protocol == IP_PROTOCOL_TCP
@@ -190,13 +203,20 @@ lb_node_get_hash (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);
+ *hash = lb_hash_hash (*((u64 *) &ip40->address_pair), ports, 0, 0, 0);
+
+ if (per_port_vip)
+ {
+ key.protocol = ip40->protocol;
+ key.port = (u16)(ports & 0xFFFF);
+ }
}
else
{
ip6_header_t *ip60;
ip60 = vlib_buffer_get_current (p);
u64 ports;
+
if (PREDICT_TRUE(
ip60->protocol == IP_PROTOCOL_TCP
|| ip60->protocol == IP_PROTOCOL_UDP))
@@ -205,18 +225,39 @@ lb_node_get_hash (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],
+ *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)
+ {
+ key.protocol = ip60->protocol;
+ key.port = (u16)(ports & 0xFFFF);
+ }
+ }
+
+ /* For per-port-vip case, retrieve vip index for vip_port_filter table */
+ if (per_port_vip)
+ {
+ kv.key = key.as_u64;
+ if (clib_bihash_search_8_8(&lbm->vip_index_per_port, &kv, &value) < 0)
+ {
+ /* return default vip */
+ *vip_idx = 0;
+ return;
+ }
+ *vip_idx = value.value;
}
- return hash;
}
static_always_inline uword
-lb_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame,
+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
+ 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
{
lb_main_t *lbm = &lb_main;
u32 n_left_from, *from, next_index, *to_next, n_left_to_next;
@@ -229,8 +270,13 @@ lb_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame,
next_index = node->cached_next_index;
u32 nexthash0 = 0;
+ u32 next_vip_idx0 = ~0;
if (PREDICT_TRUE(n_left_from > 0))
- nexthash0 = lb_node_get_hash (vlib_get_buffer (vm, from[0]), is_input_v4);
+ {
+ 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);
+ }
while (n_left_from > 0)
{
@@ -240,17 +286,21 @@ lb_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame,
u32 pi0;
vlib_buffer_t *p0;
lb_vip_t *vip0;
- u32 asindex0;
+ u32 asindex0 = 0;
u16 len0;
u32 available_index0;
u8 counter = 0;
u32 hash0 = nexthash0;
+ u32 vip_index0 = next_vip_idx0;
+ u32 next0;
if (PREDICT_TRUE(n_left_from > 1))
{
vlib_buffer_t *p1 = vlib_get_buffer (vm, from[1]);
//Compute next hash and prefetch bucket
- nexthash0 = lb_node_get_hash (p1, is_input_v4);
+ lb_node_get_hash (lbm, p1, is_input_v4,
+ &nexthash0, &next_vip_idx0,
+ per_port_vip);
lb_hash_prefetch_bucket (sticky_ht, nexthash0);
//Prefetch for encap, next
CLIB_PREFETCH(vlib_buffer_get_current (p1) - 64, 64, STORE);
@@ -272,8 +322,8 @@ lb_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame,
n_left_to_next -= 1;
p0 = vlib_get_buffer (vm, pi0);
- vip0 = pool_elt_at_index(lbm->vips,
- vnet_buffer (p0)->ip.adj_index[VLIB_TX]);
+
+ vip0 = pool_elt_at_index(lbm->vips, vip_index0);
if (is_input_v4)
{
@@ -290,7 +340,7 @@ lb_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame,
}
lb_hash_get (sticky_ht, hash0,
- vnet_buffer (p0)->ip.adj_index[VLIB_TX], lb_time,
+ vip_index0, lb_time,
&available_index0, &asindex0);
if (PREDICT_TRUE(asindex0 != ~0))
@@ -320,7 +370,7 @@ lb_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame,
//Note that when there is no AS configured, an entry is configured anyway.
//But no configured AS is not something that should happen
lb_hash_put (sticky_ht, hash0, asindex0,
- vnet_buffer (p0)->ip.adj_index[VLIB_TX],
+ vip_index0,
available_index0, lb_time);
}
else
@@ -333,7 +383,7 @@ lb_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame,
vlib_increment_simple_counter (
&lbm->vip_counters[counter], thread_index,
- vnet_buffer (p0)->ip.adj_index[VLIB_TX],
+ vip_index0,
1);
//Now let's encap
@@ -436,8 +486,7 @@ lb_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame,
csum, lbm->ass[asindex0].address.ip4.as_u32);
ip40->checksum = ip_csum_fold (csum);
- if ((ip40->protocol == IP_PROTOCOL_UDP)
- || (uh->dst_port == vip0->encap_args.port))
+ if (ip40->protocol == IP_PROTOCOL_UDP)
{
uh->dst_port = vip0->encap_args.target_port;
csum = uh->checksum;
@@ -448,7 +497,7 @@ lb_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame,
}
else
{
- next_index = LB_NEXT_DROP;
+ asindex0 = 0;
}
}
else if ((is_input_v4 == 0) && (encap_type == LB_ENCAP_TYPE_NAT6))
@@ -481,25 +530,25 @@ lb_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame,
}
else
{
- next_index = LB_NEXT_DROP;
+ asindex0 = 0;
}
}
}
+ next0 = lbm->ass[asindex0].dpo.dpoi_next_node;
+ //Note that this is going to error if asindex0 == 0
+ vnet_buffer (p0)->ip.adj_index[VLIB_TX] =
+ lbm->ass[asindex0].dpo.dpoi_index;
if (PREDICT_FALSE(p0->flags & VLIB_BUFFER_IS_TRACED))
{
lb_trace_t *tr = vlib_add_trace (vm, node, p0, sizeof(*tr));
tr->as_index = asindex0;
- tr->vip_index = vnet_buffer (p0)->ip.adj_index[VLIB_TX];
+ tr->vip_index = vip_index0;
}
//Enqueue to next
- //Note that this is going to error if asindex0 == 0
- vnet_buffer (p0)->ip.adj_index[VLIB_TX] =
- lbm->ass[asindex0].dpo.dpoi_index;
vlib_validate_buffer_enqueue_x1(
- vm, node, next_index, to_next, n_left_to_next, pi0,
- lbm->ass[asindex0].dpo.dpoi_next_node);
+ vm, node, next_index, to_next, n_left_to_next, pi0, next0);
}
vlib_put_next_frame (vm, node, next_index, n_left_to_next);
}
@@ -887,49 +936,84 @@ 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);
+ return lb_node_fn (vm, node, frame, 0, LB_ENCAP_TYPE_GRE6, 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);
+ return lb_node_fn (vm, node, frame, 0, LB_ENCAP_TYPE_GRE4, 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);
+ return lb_node_fn (vm, node, frame, 1, LB_ENCAP_TYPE_GRE6, 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);
+ return lb_node_fn (vm, node, frame, 1, LB_ENCAP_TYPE_GRE4, 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);
+}
+
+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);
+}
+
+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);
+}
+
+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);
}
static uword
lb4_l3dsr_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
- vlib_frame_t * frame)
+ vlib_frame_t * frame)
{
- return lb_node_fn (vm, node, frame, 1, LB_ENCAP_TYPE_L3DSR);
+ return lb_node_fn (vm, node, frame, 1, LB_ENCAP_TYPE_L3DSR, 0);
}
static uword
-lb6_nat6_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
- vlib_frame_t * frame)
+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, 0, LB_ENCAP_TYPE_NAT6);
+ return lb_node_fn (vm, node, frame, 1, LB_ENCAP_TYPE_L3DSR, 1);
}
static uword
-lb4_nat4_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
- vlib_frame_t * frame)
+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);
+}
+
+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);
+ return lb_node_fn (vm, node, frame, 1, LB_ENCAP_TYPE_NAT4, 1);
}
static uword
@@ -952,7 +1036,8 @@ VLIB_REGISTER_NODE (lb6_gre6_node) =
.name = "lb6-gre6",
.vector_size = sizeof(u32),
.format_trace = format_lb_trace,
- .n_errors = LB_N_ERROR, .error_strings = lb_error_strings,
+ .n_errors = LB_N_ERROR,
+ .error_strings = lb_error_strings,
.n_next_nodes = LB_N_NEXT,
.next_nodes =
{ [LB_NEXT_DROP] = "error-drop" },
@@ -992,7 +1077,72 @@ VLIB_REGISTER_NODE (lb4_gre4_node) =
.format_trace = format_lb_trace,
.n_errors = LB_N_ERROR,
.error_strings = lb_error_strings,
- .n_next_nodes = LB_N_NEXT,
+ .n_next_nodes = LB_N_NEXT,
+ .next_nodes =
+ { [LB_NEXT_DROP] = "error-drop" },
+ };
+
+VLIB_REGISTER_NODE (lb6_gre6_port_node) =
+ {
+ .function = lb6_gre6_port_node_fn,
+ .name = "lb6-gre6-port",
+ .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_node) =
+ {
+ .function = lb6_gre4_port_node_fn,
+ .name = "lb6-gre4-port",
+ .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_node) =
+ {
+ .function = lb4_gre6_port_node_fn,
+ .name = "lb4-gre6-port",
+ .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_node) =
+ {
+ .function = lb4_gre4_port_node_fn,
+ .name = "lb4-gre4-port",
+ .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_node) =
+ {
+ .function = lb4_l3dsr_port_node_fn,
+ .name = "lb4-l3dsr-port",
+ .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" },
};
@@ -1010,10 +1160,10 @@ VLIB_REGISTER_NODE (lb4_l3dsr_node) =
{ [LB_NEXT_DROP] = "error-drop" },
};
-VLIB_REGISTER_NODE (lb6_nat6_node) =
+VLIB_REGISTER_NODE (lb6_nat6_port_node) =
{
- .function = lb6_nat6_node_fn,
- .name = "lb6-nat6",
+ .function = lb6_nat6_port_node_fn,
+ .name = "lb6-nat6-port",
.vector_size = sizeof(u32),
.format_trace = format_lb_trace,
.n_errors = LB_N_ERROR,
@@ -1023,10 +1173,10 @@ VLIB_REGISTER_NODE (lb6_nat6_node) =
{ [LB_NEXT_DROP] = "error-drop" },
};
-VLIB_REGISTER_NODE (lb4_nat4_node) =
+VLIB_REGISTER_NODE (lb4_nat4_port_node) =
{
- .function = lb4_nat4_node_fn,
- .name = "lb4-nat4",
+ .function = lb4_nat4_port_node_fn,
+ .name = "lb4-nat4-port",
.vector_size = sizeof(u32),
.format_trace = format_lb_trace,
.n_errors = LB_N_ERROR,
@@ -1061,7 +1211,7 @@ VLIB_REGISTER_NODE (lb4_nodeport_node) =
.n_next_nodes = LB4_NODEPORT_N_NEXT,
.next_nodes =
{
- [LB4_NODEPORT_NEXT_IP4_NAT4] = "lb4-nat4",
+ [LB4_NODEPORT_NEXT_IP4_NAT4] = "lb4-nat4-port",
[LB4_NODEPORT_NEXT_DROP] = "error-drop",
},
};
@@ -1077,7 +1227,7 @@ VLIB_REGISTER_NODE (lb6_nodeport_node) =
.n_next_nodes = LB6_NODEPORT_N_NEXT,
.next_nodes =
{
- [LB6_NODEPORT_NEXT_IP6_NAT6] = "lb6-nat6",
+ [LB6_NODEPORT_NEXT_IP6_NAT6] = "lb6-nat6-port",
[LB6_NODEPORT_NEXT_DROP] = "error-drop",
},
};