X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fplugins%2Fgbp%2Fgbp_subnet.c;h=bb069ffe892e715bf153ee93d6fd08ea7435539a;hb=3c0d84c98;hp=b0b6db8040eddc0a24c3dc2e0f6dfb0a34f8ea58;hpb=b6a47953973f7c94239c394b649100e91bdb2152;p=vpp.git diff --git a/src/plugins/gbp/gbp_subnet.c b/src/plugins/gbp/gbp_subnet.c index b0b6db8040e..bb069ffe892 100644 --- a/src/plugins/gbp/gbp_subnet.c +++ b/src/plugins/gbp/gbp_subnet.c @@ -43,12 +43,12 @@ typedef struct gbp_subnet_t_ { struct { - epg_id_t gs_epg; + sclass_t gs_sclass; u32 gs_sw_if_index; } gs_stitched_external; struct { - epg_id_t gs_epg; + sclass_t gs_sclass; } gs_l3_out; }; @@ -117,6 +117,9 @@ gbp_subnet_transport_add (gbp_subnet_t * gs) fproto = gs->gs_key->gsk_pfx.fp_proto; grd = gbp_route_domain_get (gs->gs_rd); + if (~0 == grd->grd_uu_sw_if_index[fproto]) + return (VNET_API_ERROR_INVALID_SW_IF_INDEX); + gs->gs_fei = fib_table_entry_update_one_path (gs->gs_key->gsk_fib_index, &gs->gs_key->gsk_pfx, FIB_SOURCE_PLUGIN_HI, @@ -152,15 +155,16 @@ gbp_subnet_internal_add (gbp_subnet_t * gs) } static int -gbp_subnet_external_add (gbp_subnet_t * gs, u32 sw_if_index, epg_id_t epg) +gbp_subnet_external_add (gbp_subnet_t * gs, u32 sw_if_index, sclass_t sclass) { dpo_id_t gpd = DPO_INVALID; - gs->gs_stitched_external.gs_epg = epg; + gs->gs_stitched_external.gs_sclass = sclass; gs->gs_stitched_external.gs_sw_if_index = sw_if_index; gbp_policy_dpo_add_or_lock (fib_proto_to_dpo (gs->gs_key->gsk_pfx.fp_proto), - gs->gs_stitched_external.gs_epg, + gbp_route_domain_get_scope (gs->gs_rd), + gs->gs_stitched_external.gs_sclass, gs->gs_stitched_external.gs_sw_if_index, &gpd); gs->gs_fei = fib_table_entry_special_dpo_update (gs->gs_key->gsk_fib_index, @@ -176,32 +180,55 @@ gbp_subnet_external_add (gbp_subnet_t * gs, u32 sw_if_index, epg_id_t epg) } static int -gbp_subnet_l3_out_add (gbp_subnet_t * gs, u32 sw_if_index, epg_id_t epg) +gbp_subnet_l3_out_add (gbp_subnet_t * gs, sclass_t sclass, int is_anon) { + fib_entry_flag_t flags; dpo_id_t gpd = DPO_INVALID; - gs->gs_l3_out.gs_epg = epg; + gs->gs_l3_out.gs_sclass = sclass; gbp_policy_dpo_add_or_lock (fib_proto_to_dpo (gs->gs_key->gsk_pfx.fp_proto), - gs->gs_l3_out.gs_epg, ~0, &gpd); + gbp_route_domain_get_scope (gs->gs_rd), + gs->gs_l3_out.gs_sclass, ~0, &gpd); + + flags = FIB_ENTRY_FLAG_INTERPOSE; + if (is_anon) + flags |= FIB_ENTRY_FLAG_COVERED_INHERIT; gs->gs_fei = fib_table_entry_special_dpo_add (gs->gs_key->gsk_fib_index, &gs->gs_key->gsk_pfx, FIB_SOURCE_SPECIAL, - FIB_ENTRY_FLAG_INTERPOSE, - &gpd); + flags, &gpd); dpo_reset (&gpd); return (0); } +static void +gbp_subnet_del_i (index_t gsi) +{ + gbp_subnet_t *gs; + + gs = pool_elt_at_index (gbp_subnet_pool, gsi); + + fib_table_entry_delete_index (gs->gs_fei, + (GBP_SUBNET_L3_OUT == gs->gs_type + || GBP_SUBNET_ANON_L3_OUT == + gs->gs_type) ? FIB_SOURCE_SPECIAL : + FIB_SOURCE_PLUGIN_HI); + + gbp_subnet_db_del (gs); + gbp_route_domain_unlock (gs->gs_rd); + + pool_put (gbp_subnet_pool, gs); +} + int gbp_subnet_del (u32 rd_id, const fib_prefix_t * pfx) { gbp_route_domain_t *grd; index_t gsi, grdi; - gbp_subnet_t *gs; u32 fib_index; grdi = gbp_route_domain_find (rd_id); @@ -217,17 +244,7 @@ gbp_subnet_del (u32 rd_id, const fib_prefix_t * pfx) if (INDEX_INVALID == gsi) return (VNET_API_ERROR_NO_SUCH_ENTRY); - gs = pool_elt_at_index (gbp_subnet_pool, gsi); - - if (GBP_SUBNET_L3_OUT == gs->gs_type) - fib_table_entry_delete (fib_index, pfx, FIB_SOURCE_SPECIAL); - else - fib_table_entry_delete (fib_index, pfx, FIB_SOURCE_PLUGIN_HI); - - gbp_subnet_db_del (gs); - gbp_route_domain_unlock (gs->gs_rd); - - pool_put (gbp_subnet_pool, gs); + gbp_subnet_del_i (gsi); return (0); } @@ -235,7 +252,7 @@ gbp_subnet_del (u32 rd_id, const fib_prefix_t * pfx) int gbp_subnet_add (u32 rd_id, const fib_prefix_t * pfx, - gbp_subnet_type_t type, u32 sw_if_index, epg_id_t epg) + gbp_subnet_type_t type, u32 sw_if_index, sclass_t sclass) { gbp_route_domain_t *grd; index_t grdi, gsi; @@ -243,6 +260,18 @@ gbp_subnet_add (u32 rd_id, u32 fib_index; int rv; + switch (type) + { + case GBP_SUBNET_TRANSPORT: + case GBP_SUBNET_STITCHED_INTERNAL: + case GBP_SUBNET_STITCHED_EXTERNAL: + case GBP_SUBNET_L3_OUT: + case GBP_SUBNET_ANON_L3_OUT: + break; + default: + return (VNET_API_ERROR_INCORRECT_ADJACENCY_TYPE); + } + grdi = gbp_route_domain_find_and_lock (rd_id); if (~0 == grdi) @@ -253,8 +282,11 @@ gbp_subnet_add (u32 rd_id, gsi = gbp_subnet_db_find (fib_index, pfx); + /* + * this is an update if the subnet already exists, so remove the old + */ if (INDEX_INVALID != gsi) - return (VNET_API_ERROR_ENTRY_ALREADY_EXISTS); + gbp_subnet_del_i (gsi); rv = -2; @@ -270,28 +302,123 @@ gbp_subnet_add (u32 rd_id, rv = gbp_subnet_internal_add (gs); break; case GBP_SUBNET_STITCHED_EXTERNAL: - rv = gbp_subnet_external_add (gs, sw_if_index, epg); + rv = gbp_subnet_external_add (gs, sw_if_index, sclass); break; case GBP_SUBNET_TRANSPORT: rv = gbp_subnet_transport_add (gs); break; case GBP_SUBNET_L3_OUT: - rv = gbp_subnet_l3_out_add (gs, sw_if_index, epg); + rv = gbp_subnet_l3_out_add (gs, sclass, 0 /* is_anon */ ); + break; + case GBP_SUBNET_ANON_L3_OUT: + rv = gbp_subnet_l3_out_add (gs, sclass, 1 /* is_anon */ ); break; } return (rv); } +static clib_error_t * +gbp_subnet_add_del_cli (vlib_main_t * vm, + unformat_input_t * input, vlib_cli_command_t * cmd) +{ + unformat_input_t _line_input, *line_input = &_line_input; + vnet_main_t *vnm = vnet_get_main (); + fib_prefix_t pfx = {.fp_addr = ip46_address_initializer }; + int length; + u32 rd_id = ~0; + u32 sw_if_index = ~0; + gbp_subnet_type_t type = ~0; + u32 sclass = ~0; + int is_add = 1; + int rv; + + /* Get a line of input. */ + if (!unformat_user (input, unformat_line_input, line_input)) + return 0; + + while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (line_input, "del")) + is_add = 0; + else if (unformat (line_input, "rd %d", &rd_id)) + ; + else + if (unformat + (line_input, "prefix %U/%d", unformat_ip4_address, + &pfx.fp_addr.ip4, &length)) + pfx.fp_proto = FIB_PROTOCOL_IP4; + else + if (unformat + (line_input, "prefix %U/%d", unformat_ip6_address, + &pfx.fp_addr.ip6, &length)) + pfx.fp_proto = FIB_PROTOCOL_IP6; + else if (unformat (line_input, "type transport")) + type = GBP_SUBNET_TRANSPORT; + else if (unformat (line_input, "type stitched-internal")) + type = GBP_SUBNET_STITCHED_INTERNAL; + else if (unformat (line_input, "type stitched-external")) + type = GBP_SUBNET_STITCHED_EXTERNAL; + else if (unformat (line_input, "type anon-l3-out")) + type = GBP_SUBNET_ANON_L3_OUT; + else if (unformat (line_input, "type l3-out")) + type = GBP_SUBNET_L3_OUT; + else + if (unformat_user + (line_input, unformat_vnet_sw_interface, vnm, &sw_if_index)) + ; + else if (unformat (line_input, "sclass %u", &sclass)) + ; + else + return clib_error_return (0, "unknown input `%U'", + format_unformat_error, line_input); + } + unformat_free (line_input); + + pfx.fp_len = length; + + if (is_add) + rv = gbp_subnet_add (rd_id, &pfx, type, sw_if_index, sclass); + else + rv = gbp_subnet_del (rd_id, &pfx); + + switch (rv) + { + case 0: + return 0; + case VNET_API_ERROR_NO_SUCH_FIB: + return clib_error_return (0, "no such FIB"); + } + + return clib_error_return (0, "unknown error %d", rv); +} + +/*? + * Add Group Based Policy Subnets + * + * @cliexpar + * @cliexstart{gbp subnet [del] rd prefix type [] [sclass ]} + * @cliexend + ?*/ +/* *INDENT-OFF* */ +VLIB_CLI_COMMAND (gbp_subnet_add_del, static) = { + .path = "gbp subnet", + .short_help = "gbp subnet [del] rd prefix type [] [sclass ]\n", + .function = gbp_subnet_add_del_cli, +}; +/* *INDENT-ON* */ + + + void gbp_subnet_walk (gbp_subnet_cb_t cb, void *ctx) { gbp_route_domain_t *grd; gbp_subnet_t *gs; u32 sw_if_index; - epg_id_t epg; + sclass_t sclass; - epg = EPG_INVALID; + sclass = SCLASS_INVALID; sw_if_index = ~0; /* *INDENT-OFF* */ @@ -307,15 +434,16 @@ gbp_subnet_walk (gbp_subnet_cb_t cb, void *ctx) break; case GBP_SUBNET_STITCHED_EXTERNAL: sw_if_index = gs->gs_stitched_external.gs_sw_if_index; - epg = gs->gs_stitched_external.gs_epg; + sclass = gs->gs_stitched_external.gs_sclass; break; case GBP_SUBNET_L3_OUT: - epg = gs->gs_l3_out.gs_epg; + case GBP_SUBNET_ANON_L3_OUT: + sclass = gs->gs_l3_out.gs_sclass; break; } if (WALK_STOP == cb (grd->grd_id, &gs->gs_key->gsk_pfx, - gs->gs_type, sw_if_index, epg, ctx)) + gs->gs_type, sw_if_index, sclass, ctx)) break; })); /* *INDENT-ON* */ @@ -342,6 +470,8 @@ format_gbp_subnet_type (u8 * s, va_list * args) return (format (s, "transport")); case GBP_SUBNET_L3_OUT: return (format (s, "l3-out")); + case GBP_SUBNET_ANON_L3_OUT: + return (format (s, "anon-l3-out")); } return (format (s, "unknown")); @@ -370,12 +500,13 @@ format_gbp_subnet (u8 * s, va_list * args) case GBP_SUBNET_TRANSPORT: break; case GBP_SUBNET_STITCHED_EXTERNAL: - s = format (s, " {epg:%d %U}", gs->gs_stitched_external.gs_epg, + s = format (s, " {sclass:%d %U}", gs->gs_stitched_external.gs_sclass, format_vnet_sw_if_index_name, vnet_get_main (), gs->gs_stitched_external.gs_sw_if_index); break; case GBP_SUBNET_L3_OUT: - s = format (s, " {epg:%d}", gs->gs_l3_out.gs_epg); + case GBP_SUBNET_ANON_L3_OUT: + s = format (s, " {sclass:%d}", gs->gs_l3_out.gs_sclass); break; }