diff options
-rw-r--r-- | plugins/lb-plugin/lb/cli.c | 41 | ||||
-rw-r--r-- | plugins/lb-plugin/lb/lb.c | 60 | ||||
-rw-r--r-- | plugins/lb-plugin/lb/lb.h | 13 | ||||
-rw-r--r-- | plugins/lb-plugin/lb/node.c | 16 |
4 files changed, 125 insertions, 5 deletions
diff --git a/plugins/lb-plugin/lb/cli.c b/plugins/lb-plugin/lb/cli.c index b59c6426241..398572ce396 100644 --- a/plugins/lb-plugin/lb/cli.c +++ b/plugins/lb-plugin/lb/cli.c @@ -17,6 +17,47 @@ #include <lb/util.h> static clib_error_t * +lb_bypass_command_fn (vlib_main_t * vm, + unformat_input_t * input, vlib_cli_command_t * cmd) +{ + unformat_input_t _line_input, *line_input = &_line_input; + ip46_address_t vip_prefix, as_addr; + u8 vip_plen; + u32 vip_index; + u8 disable = 0; + int ret; + + if (!unformat_user (input, unformat_line_input, line_input)) + return 0; + + if (!unformat(line_input, "%U", unformat_ip46_prefix, &vip_prefix, &vip_plen, IP46_TYPE_ANY)) + return clib_error_return (0, "invalid vip prefix: '%U'", + format_unformat_error, line_input); + + if ((ret = lb_vip_find_index(&vip_prefix, vip_plen, &vip_index))) + return clib_error_return (0, "lb_vip_find_index error %d", ret); + + if (!unformat(line_input, "%U", unformat_ip46_address, &as_addr, IP46_TYPE_ANY)) + return clib_error_return (0, "invalid as address: '%U'", + format_unformat_error, line_input); + + if (unformat(line_input, "disable")) + disable = 1; + + if ((ret = lb_as_lookup_bypass(vip_index, &as_addr, disable))) + return clib_error_return (0, "lb_as_lookup_bypass error %d", ret); + + return 0; +} + +VLIB_CLI_COMMAND (lb_bypass_command, static) = +{ + .path = "lb bypass", + .short_help = "lb bypass <prefix> <address> [disable]", + .function = lb_bypass_command_fn, +}; + +static clib_error_t * lb_vip_command_fn (vlib_main_t * vm, unformat_input_t * input, vlib_cli_command_t * cmd) { diff --git a/plugins/lb-plugin/lb/lb.c b/plugins/lb-plugin/lb/lb.c index 5eeeac5cfb7..e91bdf0bc10 100644 --- a/plugins/lb-plugin/lb/lb.c +++ b/plugins/lb-plugin/lb/lb.c @@ -143,10 +143,12 @@ u8 *format_lb_vip_detailed (u8 * s, va_list * args) u32 *as_index; pool_foreach(as_index, vip->as_indexes, { as = &lbm->ass[*as_index]; - s = format(s, "%U %U %d buckets %d flows %s\n", format_white_space, indent, + s = format(s, "%U %U %d buckets %d flows adj:%u %s\n", + format_white_space, indent, format_ip46_address, &as->address, IP46_TYPE_ANY, count[as - lbm->ass], vlib_refcount_get(&lbm->as_refcount, as - lbm->ass), + as->adj_index, (as->flags & LB_AS_FLAGS_USED)?"used":" removed"); }); @@ -447,6 +449,7 @@ next: //Update reused ASs vec_foreach(ip, to_be_updated) { lbm->ass[*ip].flags = LB_AS_FLAGS_USED; + lbm->ass[*ip].adj_index = ~0; } vec_free(to_be_updated); @@ -458,6 +461,7 @@ next: as->address = addresses[*ip]; as->flags = LB_AS_FLAGS_USED; as->vip_index = vip_index; + as->adj_index = ~0; pool_get(vip->as_indexes, as_index); *as_index = as - lbm->ass; } @@ -531,6 +535,59 @@ int lb_vip_del_ass(u32 vip_index, ip46_address_t *addresses, u32 n) return ret; } +int lb_as_lookup_bypass(u32 vip_index, ip46_address_t *address, u8 is_disable) +{ + lb_get_writer_lock(); + lb_main_t *lbm = &lb_main; + u32 as_index; + lb_as_t *as; + lb_vip_t *vip; + + if (!(vip = lb_vip_get_by_index(vip_index)) || + lb_as_find_index_vip(vip, address, &as_index)) { + lb_put_writer_lock(); + return VNET_API_ERROR_NO_SUCH_ENTRY; + } + + as = &lbm->ass[as_index]; + + if (is_disable) { + as->adj_index = ~0; + } else if (lb_vip_is_gre4(vip)) { + uword *p = ip4_get_route (&ip4_main, 0, 0, as->address.ip4.as_u8, 32); + if (p == 0) { + lb_put_writer_lock(); + return VNET_API_ERROR_NO_SUCH_ENTRY; + } + u32 ai = (u32)p[0]; + ip_lookup_main_t *lm4 = &ip4_main.lookup_main; + ip_adjacency_t *adj4 = ip_get_adjacency (lm4, ai); + if (adj4->lookup_next_index != IP_LOOKUP_NEXT_REWRITE) { + lb_put_writer_lock(); + return VNET_API_ERROR_INCORRECT_ADJACENCY_TYPE; + } + + as->adj_index = ai; + } else { + u32 ai = ip6_get_route (&ip6_main, 0, 0, &as->address.ip6, 128); + if (ai == 0) { + lb_put_writer_lock(); + return VNET_API_ERROR_NO_SUCH_ENTRY; + } + + ip_lookup_main_t *lm6 = &ip6_main.lookup_main; + ip_adjacency_t *adj6 = ip_get_adjacency (lm6, ai); + if (adj6->lookup_next_index != IP_LOOKUP_NEXT_REWRITE) { + lb_put_writer_lock(); + return VNET_API_ERROR_INCORRECT_ADJACENCY_TYPE; + } + + as->adj_index = ai; + } + lb_put_writer_lock(); + return 0; +} + /** * Add the VIP adjacency to the ip4 or ip6 fib @@ -733,6 +790,7 @@ lb_init (vlib_main_t * vm) lbm->ass = 0; pool_get(lbm->ass, default_as); default_as->flags = 0; + default_as->adj_index = ~0; default_as->vip_index = ~0; default_as->address.ip6.as_u64[0] = 0xffffffffffffffffL; default_as->address.ip6.as_u64[1] = 0xffffffffffffffffL; diff --git a/plugins/lb-plugin/lb/lb.h b/plugins/lb-plugin/lb/lb.h index 3d250319422..14a4d8a39e7 100644 --- a/plugins/lb-plugin/lb/lb.h +++ b/plugins/lb-plugin/lb/lb.h @@ -55,6 +55,13 @@ typedef struct { ip46_address_t address; /** + * Second ip lookup can be avoided by sending directly the packet + * to ip-rewrite with a configured adjacency. + * When set to ~0, the packets are sent to ip6-lookup. + */ + u32 adj_index; + + /** * ASs are indexed by address and VIP Index. * Which means there will be duplicated if the same server * address is used for multiple VIPs. @@ -295,6 +302,12 @@ int lb_vip_find_index(ip46_address_t *prefix, u8 plen, u32 *vip_index); int lb_vip_add_ass(u32 vip_index, ip46_address_t *addresses, u32 n); int lb_vip_del_ass(u32 vip_index, ip46_address_t *addresses, u32 n); +/** + * Updates the adjacency index stored in the AS such that the second + * IP lookup (after encap) can be bypassed. + */ +int lb_as_lookup_bypass(u32 vip_index, ip46_address_t *address, u8 is_disable); + u32 lb_hash_time_now(vlib_main_t * vm); void lb_garbage_collection(); diff --git a/plugins/lb-plugin/lb/node.c b/plugins/lb-plugin/lb/node.c index 4d598104944..8df462c0853 100644 --- a/plugins/lb-plugin/lb/node.c +++ b/plugins/lb-plugin/lb/node.c @@ -38,6 +38,7 @@ static char *lb_error_strings[] = { typedef enum { LB_NEXT_LOOKUP, + LB_NEXT_REWRITE, LB_NEXT_DROP, LB_N_NEXT, } lb_next_t; @@ -47,14 +48,14 @@ typedef struct { u32 as_index; } lb_trace_t; -u8 *lb_format_adjacency(u8 * s, - struct ip_lookup_main_t * lm, - ip_adjacency_t *adj) +u8 *lb_format_adjacency(u8 * s, va_list * va) { lb_main_t *lbm = &lb_main; + __attribute((unused)) ip_lookup_main_t *lm = va_arg (*va, ip_lookup_main_t *); + ip_adjacency_t *adj = va_arg (*va, ip_adjacency_t *); lb_adj_data_t *ad = (lb_adj_data_t *) &adj->opaque; __attribute__((unused)) lb_vip_t *vip = pool_elt_at_index (lbm->vips, ad->vip_index); - return format(s, "idx:%d", ad->vip_index); + return format(s, "vip idx:%d", ad->vip_index); } u8 * @@ -251,6 +252,9 @@ lb_node_fn (vlib_main_t * vm, clib_host_to_net_u16(0x0800): clib_host_to_net_u16(0x86DD); + vnet_buffer(p0)->ip.adj_index[VLIB_TX] = as0->adj_index; + next0 = (as0->adj_index != ~0)?LB_NEXT_REWRITE:next0; + if (PREDICT_FALSE (p0->flags & VLIB_BUFFER_IS_TRACED)) { lb_trace_t *tr = vlib_add_trace (vm, node, p0, sizeof (*tr)); @@ -310,6 +314,7 @@ VLIB_REGISTER_NODE (lb6_gre6_node) = .next_nodes = { [LB_NEXT_LOOKUP] = "ip6-lookup", + [LB_NEXT_REWRITE] = "ip6-rewrite", [LB_NEXT_DROP] = "error-drop" }, }; @@ -334,6 +339,7 @@ VLIB_REGISTER_NODE (lb6_gre4_node) = .next_nodes = { [LB_NEXT_LOOKUP] = "ip4-lookup", + [LB_NEXT_REWRITE]= "ip4-rewrite-transit", [LB_NEXT_DROP] = "error-drop" }, }; @@ -358,6 +364,7 @@ VLIB_REGISTER_NODE (lb4_gre6_node) = .next_nodes = { [LB_NEXT_LOOKUP] = "ip6-lookup", + [LB_NEXT_REWRITE] = "ip6-rewrite", [LB_NEXT_DROP] = "error-drop" }, }; @@ -382,6 +389,7 @@ VLIB_REGISTER_NODE (lb4_gre4_node) = .next_nodes = { [LB_NEXT_LOOKUP] = "ip4-lookup", + [LB_NEXT_REWRITE]= "ip4-rewrite-transit", [LB_NEXT_DROP] = "error-drop" }, }; |