diff options
Diffstat (limited to 'src/plugins/lb/node.c')
-rw-r--r-- | src/plugins/lb/node.c | 246 |
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", }, }; |