return s;
}
-lb_hash_t *lb_get_sticky_table(u32 cpu_index)
+lb_hash_t *lb_get_sticky_table(u32 thread_index)
{
lb_main_t *lbm = &lb_main;
- lb_hash_t *sticky_ht = lbm->per_cpu[cpu_index].sticky_ht;
+ lb_hash_t *sticky_ht = lbm->per_cpu[thread_index].sticky_ht;
//Check if size changed
if (PREDICT_FALSE(sticky_ht && (lbm->per_cpu_sticky_buckets != lb_hash_nbuckets(sticky_ht))))
{
lb_hash_bucket_t *b;
u32 i;
lb_hash_foreach_entry(sticky_ht, b, i) {
- vlib_refcount_add(&lbm->as_refcount, cpu_index, b->value[i], -1);
- vlib_refcount_add(&lbm->as_refcount, cpu_index, 0, 1);
+ 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(sticky_ht);
//Create if necessary
if (PREDICT_FALSE(sticky_ht == NULL)) {
- lbm->per_cpu[cpu_index].sticky_ht = lb_hash_alloc(lbm->per_cpu_sticky_buckets, lbm->flow_timeout);
- sticky_ht = lbm->per_cpu[cpu_index].sticky_ht;
+ lbm->per_cpu[thread_index].sticky_ht = lb_hash_alloc(lbm->per_cpu_sticky_buckets, lbm->flow_timeout);
+ sticky_ht = lbm->per_cpu[thread_index].sticky_ht;
clib_warning("Regenerated sticky table %p", sticky_ht);
}
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)
- u8 is_encap_v4) //Compile-time parameter stating that is GRE encap is v4 (or v6)
+ lb_encap_type_t encap_type) //Compile-time parameter stating that is GRE4 or GRE6 or L3DSR
{
lb_main_t *lbm = &lb_main;
u32 n_left_from, *from, next_index, *to_next, n_left_to_next;
- u32 cpu_index = os_get_cpu_number();
+ u32 thread_index = vlib_get_thread_index();
u32 lb_time = lb_hash_time_now(vm);
- lb_hash_t *sticky_ht = lb_get_sticky_table(cpu_index);
+ lb_hash_t *sticky_ht = lb_get_sticky_table(thread_index);
from = vlib_frame_vector_args (frame);
n_left_from = frame->n_vectors;
next_index = node->cached_next_index;
//Configuration may be changed, vectors resized, etc...
//Dereference previously used
- vlib_refcount_add(&lbm->as_refcount, cpu_index,
+ vlib_refcount_add(&lbm->as_refcount, thread_index,
lb_hash_available_value(sticky_ht, hash0, available_index0), -1);
- vlib_refcount_add(&lbm->as_refcount, cpu_index,
+ vlib_refcount_add(&lbm->as_refcount, thread_index,
asindex0, 1);
//Add sticky entry
}
vlib_increment_simple_counter(&lbm->vip_counters[counter],
- cpu_index,
+ thread_index,
vnet_buffer (p0)->ip.adj_index[VLIB_TX],
1);
//Now let's encap
- {
- gre_header_t *gre0;
- if (is_encap_v4)
- {
- ip4_header_t *ip40;
- vlib_buffer_advance(p0, - sizeof(ip4_header_t) - sizeof(gre_header_t));
- ip40 = vlib_buffer_get_current(p0);
- gre0 = (gre_header_t *)(ip40 + 1);
- ip40->src_address = lbm->ip4_src_address;
- ip40->dst_address = lbm->ass[asindex0].address.ip4;
- ip40->ip_version_and_header_length = 0x45;
- ip40->ttl = 128;
- ip40->length = clib_host_to_net_u16(len0 + sizeof(gre_header_t) + sizeof(ip4_header_t));
- ip40->protocol = IP_PROTOCOL_GRE;
- ip40->checksum = ip4_header_checksum (ip40);
- }
- else
- {
- ip6_header_t *ip60;
- vlib_buffer_advance(p0, - sizeof(ip6_header_t) - sizeof(gre_header_t));
- ip60 = vlib_buffer_get_current(p0);
- gre0 = (gre_header_t *)(ip60 + 1);
- ip60->dst_address = lbm->ass[asindex0].address.ip6;
- ip60->src_address = lbm->ip6_src_address;
- ip60->hop_limit = 128;
- ip60->ip_version_traffic_class_and_flow_label = clib_host_to_net_u32 (0x6<<28);
- ip60->payload_length = clib_host_to_net_u16(len0 + sizeof(gre_header_t));
- ip60->protocol = IP_PROTOCOL_GRE;
- }
-
- gre0->flags_and_version = 0;
- gre0->protocol = (is_input_v4)?
- clib_host_to_net_u16(0x0800):
- clib_host_to_net_u16(0x86DD);
- }
+ if ( (encap_type == LB_ENCAP_TYPE_GRE4)
+ || (encap_type == LB_ENCAP_TYPE_GRE6) )
+ {
+ gre_header_t *gre0;
+ if (encap_type == LB_ENCAP_TYPE_GRE4) /* encap GRE4*/
+ {
+ ip4_header_t *ip40;
+ vlib_buffer_advance(p0, - sizeof(ip4_header_t) - sizeof(gre_header_t));
+ ip40 = vlib_buffer_get_current(p0);
+ gre0 = (gre_header_t *)(ip40 + 1);
+ ip40->src_address = lbm->ip4_src_address;
+ ip40->dst_address = lbm->ass[asindex0].address.ip4;
+ ip40->ip_version_and_header_length = 0x45;
+ ip40->ttl = 128;
+ ip40->fragment_id = 0;
+ ip40->flags_and_fragment_offset = 0;
+ ip40->length = clib_host_to_net_u16(len0 + sizeof(gre_header_t) + sizeof(ip4_header_t));
+ ip40->protocol = IP_PROTOCOL_GRE;
+ ip40->checksum = ip4_header_checksum (ip40);
+ }
+ else /* encap GRE6*/
+ {
+ ip6_header_t *ip60;
+ vlib_buffer_advance(p0, - sizeof(ip6_header_t) - sizeof(gre_header_t));
+ ip60 = vlib_buffer_get_current(p0);
+ gre0 = (gre_header_t *)(ip60 + 1);
+ ip60->dst_address = lbm->ass[asindex0].address.ip6;
+ ip60->src_address = lbm->ip6_src_address;
+ ip60->hop_limit = 128;
+ ip60->ip_version_traffic_class_and_flow_label = clib_host_to_net_u32 (0x6<<28);
+ ip60->payload_length = clib_host_to_net_u16(len0 + sizeof(gre_header_t));
+ ip60->protocol = IP_PROTOCOL_GRE;
+ }
+
+ gre0->flags_and_version = 0;
+ gre0->protocol = (is_input_v4)?
+ clib_host_to_net_u16(0x0800):
+ clib_host_to_net_u16(0x86DD);
+ } else if (encap_type == LB_ENCAP_TYPE_L3DSR) /* encap L3DSR*/
+ {
+ ip4_header_t *ip40;
+ tcp_header_t *th0;
+
+ ip40 = vlib_buffer_get_current(p0);
+ ip40->dst_address = lbm->ass[asindex0].address.ip4;
+ /* Get and rewrite DSCP bit */
+ ip40->tos = (u8)((vip0->dscp & 0x3F)<<2);
+ ip40->checksum = ip4_header_checksum (ip40);
+ /* Recomputing L4 checksum after dst-IP modifying */
+ th0 = ip4_next_header(ip40);
+ th0->checksum = 0;
+ th0->checksum = ip4_tcp_udp_compute_checksum(vm, p0, ip40);
+ }
if (PREDICT_FALSE (p0->flags & VLIB_BUFFER_IS_TRACED))
{
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, 0);
+ return lb_node_fn(vm, node, frame, 0, LB_ENCAP_TYPE_GRE6);
}
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, 1);
+ return lb_node_fn(vm, node, frame, 0, LB_ENCAP_TYPE_GRE4);
}
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, 0);
+ return lb_node_fn(vm, node, frame, 1, LB_ENCAP_TYPE_GRE6);
}
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, 1);
+ return lb_node_fn(vm, node, frame, 1, LB_ENCAP_TYPE_GRE4);
+}
+
+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);
}
VLIB_REGISTER_NODE (lb6_gre6_node) =
},
};
+VLIB_REGISTER_NODE (lb4_l3dsr_node) =
+{
+ .function = lb4_l3dsr_node_fn,
+ .name = "lb4-l3dsr",
+ .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"
+ },
+};