From 3c0d84c989e9928d5ca9ffe3aceb826864bd525a Mon Sep 17 00:00:00 2001 From: =?utf8?q?Beno=C3=AEt=20Ganne?= Date: Wed, 26 Jun 2019 14:05:51 +0200 Subject: [PATCH] gbp: add anonymous l3-out subnets MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit An anonymous l3-out subnet is a locally attached l3-out subnet, and differs from regular l3-out subnets in the way adjacencies are managed. It is required for the anonymous l3-out external interfaces to correctly classify locally attached l3-out hosts. Type: feature Change-Id: Ie7bc88b1f22abc4d0b46db5f3cfbf208bc53ba5f Signed-off-by: Benoît Ganne --- extras/vom/vom/gbp_subnet.cpp | 12 +++++-- extras/vom/vom/gbp_subnet.hpp | 14 +++++--- src/plugins/gbp/gbp.api | 1 + src/plugins/gbp/gbp_api.c | 6 ++++ src/plugins/gbp/gbp_subnet.c | 77 ++++++++++++++++++++++++++++++------------- src/plugins/gbp/gbp_subnet.h | 1 + 6 files changed, 83 insertions(+), 28 deletions(-) diff --git a/extras/vom/vom/gbp_subnet.cpp b/extras/vom/vom/gbp_subnet.cpp index 35422e2a6d4..bc897f125db 100644 --- a/extras/vom/vom/gbp_subnet.cpp +++ b/extras/vom/vom/gbp_subnet.cpp @@ -33,6 +33,7 @@ const gbp_subnet::type_t gbp_subnet::type_t::STITCHED_EXTERNAL( "stitched-external"); const gbp_subnet::type_t gbp_subnet::type_t::TRANSPORT(2, "transport"); const gbp_subnet::type_t gbp_subnet::type_t::L3_OUT(3, "l3-out"); +const gbp_subnet::type_t gbp_subnet::type_t::ANON_L3_OUT(4, "anon-l3-out"); singular_db gbp_subnet::m_db; @@ -67,11 +68,12 @@ gbp_subnet::gbp_subnet(const gbp_route_domain& rd, gbp_subnet::gbp_subnet(const gbp_route_domain& rd, const route::prefix_t& prefix, - sclass_t sclass) + sclass_t sclass, + const type_t& type) : m_hw(false) , m_rd(rd.singular()) , m_prefix(prefix) - , m_type(type_t::L3_OUT) + , m_type(type) , m_recirc(nullptr) , m_epg() , m_sclass(sclass) @@ -239,6 +241,12 @@ gbp_subnet::event_handler::handle_populate(const client_db::key_t& key) VOM_LOG(log_level_t::DEBUG) << "read: " << gs.to_string(); break; } + case GBP_API_SUBNET_ANON_L3_OUT: { + gbp_subnet gs(*rd, pfx, payload.subnet.sclass, type_t::ANON_L3_OUT); + OM::commit(key, gs); + VOM_LOG(log_level_t::DEBUG) << "read: " << gs.to_string(); + break; + } case GBP_API_SUBNET_STITCHED_EXTERNAL: { std::shared_ptr itf = interface::find(payload.subnet.sw_if_index); diff --git a/extras/vom/vom/gbp_subnet.hpp b/extras/vom/vom/gbp_subnet.hpp index bff32ffaf2f..3ae8439e83c 100644 --- a/extras/vom/vom/gbp_subnet.hpp +++ b/extras/vom/vom/gbp_subnet.hpp @@ -54,17 +54,22 @@ public: const static type_t TRANSPORT; /** - * A transport subnet, sent via the RD's UU-fwd interface + * A L3-out subnet */ const static type_t L3_OUT; + /** + * An anonymous L3-out subnet + */ + const static type_t ANON_L3_OUT; + private: type_t(int v, const std::string s); }; /** - * Construct an internal GBP subnet - */ + * Construct an internal GBP subnet + */ gbp_subnet(const gbp_route_domain& rd, const route::prefix_t& prefix, const type_t& type); @@ -82,7 +87,8 @@ public: */ gbp_subnet(const gbp_route_domain& rd, const route::prefix_t& prefix, - sclass_t sclass); + sclass_t sclass, + const type_t& type = type_t::L3_OUT); /** * Copy Construct diff --git a/src/plugins/gbp/gbp.api b/src/plugins/gbp/gbp.api index d1e483d5e5d..cf0564ccc9a 100644 --- a/src/plugins/gbp/gbp.api +++ b/src/plugins/gbp/gbp.api @@ -235,6 +235,7 @@ enum gbp_subnet_type GBP_API_SUBNET_STITCHED_INTERNAL, GBP_API_SUBNET_STITCHED_EXTERNAL, GBP_API_SUBNET_L3_OUT, + GBP_API_SUBNET_ANON_L3_OUT, }; typeonly define gbp_subnet diff --git a/src/plugins/gbp/gbp_api.c b/src/plugins/gbp/gbp_api.c index 010e3087eb3..3a3ce32c68d 100644 --- a/src/plugins/gbp/gbp_api.c +++ b/src/plugins/gbp/gbp_api.c @@ -404,6 +404,9 @@ gub_subnet_type_from_api (vl_api_gbp_subnet_type_t a, gbp_subnet_type_t * t) case GBP_API_SUBNET_L3_OUT: *t = GBP_SUBNET_L3_OUT; return (0); + case GBP_API_SUBNET_ANON_L3_OUT: + *t = GBP_SUBNET_ANON_L3_OUT; + return (0); case GBP_API_SUBNET_STITCHED_INTERNAL: *t = GBP_SUBNET_STITCHED_INTERNAL; return (0); @@ -461,6 +464,9 @@ gub_subnet_type_to_api (gbp_subnet_type_t t) case GBP_SUBNET_L3_OUT: a = GBP_API_SUBNET_L3_OUT; break; + case GBP_SUBNET_ANON_L3_OUT: + a = GBP_API_SUBNET_ANON_L3_OUT; + break; } a = clib_host_to_net_u32 (a); diff --git a/src/plugins/gbp/gbp_subnet.c b/src/plugins/gbp/gbp_subnet.c index e2dfd3799b0..bb069ffe892 100644 --- a/src/plugins/gbp/gbp_subnet.c +++ b/src/plugins/gbp/gbp_subnet.c @@ -180,8 +180,9 @@ gbp_subnet_external_add (gbp_subnet_t * gs, u32 sw_if_index, sclass_t sclass) } static int -gbp_subnet_l3_out_add (gbp_subnet_t * gs, sclass_t sclass) +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_sclass = sclass; @@ -190,11 +191,14 @@ gbp_subnet_l3_out_add (gbp_subnet_t * gs, sclass_t sclass) 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); @@ -208,10 +212,11 @@ gbp_subnet_del_i (index_t gsi) gs = pool_elt_at_index (gbp_subnet_pool, gsi); - if (GBP_SUBNET_L3_OUT == gs->gs_type) - fib_table_entry_delete_index (gs->gs_fei, FIB_SOURCE_SPECIAL); - else - fib_table_entry_delete_index (gs->gs_fei, FIB_SOURCE_PLUGIN_HI); + 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); @@ -255,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) @@ -291,7 +308,10 @@ gbp_subnet_add (u32 rd_id, rv = gbp_subnet_transport_add (gs); break; case GBP_SUBNET_L3_OUT: - rv = gbp_subnet_l3_out_add (gs, sclass); + 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; } @@ -302,6 +322,7 @@ 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; @@ -312,39 +333,47 @@ gbp_subnet_add_del_cli (vlib_main_t * vm, int is_add = 1; int rv; - while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + /* 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 (input, "del")) + if (unformat (line_input, "del")) is_add = 0; - else if (unformat (input, "rd %d", &rd_id)) + else if (unformat (line_input, "rd %d", &rd_id)) ; else if (unformat - (input, "prefix %U/%d", unformat_ip4_address, &pfx.fp_addr.ip4, - &length)) + (line_input, "prefix %U/%d", unformat_ip4_address, + &pfx.fp_addr.ip4, &length)) pfx.fp_proto = FIB_PROTOCOL_IP4; else if (unformat - (input, "prefix %U/%d", unformat_ip6_address, &pfx.fp_addr.ip6, - &length)) + (line_input, "prefix %U/%d", unformat_ip6_address, + &pfx.fp_addr.ip6, &length)) pfx.fp_proto = FIB_PROTOCOL_IP6; - else if (unformat (input, "type transport")) + else if (unformat (line_input, "type transport")) type = GBP_SUBNET_TRANSPORT; - else if (unformat (input, "type internal")) + else if (unformat (line_input, "type stitched-internal")) type = GBP_SUBNET_STITCHED_INTERNAL; - else if (unformat (input, "type external")) + else if (unformat (line_input, "type stitched-external")) type = GBP_SUBNET_STITCHED_EXTERNAL; - else if (unformat (input, "type l3out")) + 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 - (input, unformat_vnet_sw_interface, vnm, &sw_if_index)) + (line_input, unformat_vnet_sw_interface, vnm, &sw_if_index)) ; - else if (unformat (input, "sclass %u", &sclass)) + else if (unformat (line_input, "sclass %u", &sclass)) ; else - break; + return clib_error_return (0, "unknown input `%U'", + format_unformat_error, line_input); } + unformat_free (line_input); pfx.fp_len = length; @@ -408,6 +437,7 @@ gbp_subnet_walk (gbp_subnet_cb_t cb, void *ctx) sclass = gs->gs_stitched_external.gs_sclass; break; case GBP_SUBNET_L3_OUT: + case GBP_SUBNET_ANON_L3_OUT: sclass = gs->gs_l3_out.gs_sclass; break; } @@ -440,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")); @@ -473,6 +505,7 @@ format_gbp_subnet (u8 * s, va_list * args) vnet_get_main (), gs->gs_stitched_external.gs_sw_if_index); break; case GBP_SUBNET_L3_OUT: + case GBP_SUBNET_ANON_L3_OUT: s = format (s, " {sclass:%d}", gs->gs_l3_out.gs_sclass); break; } diff --git a/src/plugins/gbp/gbp_subnet.h b/src/plugins/gbp/gbp_subnet.h index b792a1bafcb..6fbef01ceba 100644 --- a/src/plugins/gbp/gbp_subnet.h +++ b/src/plugins/gbp/gbp_subnet.h @@ -24,6 +24,7 @@ typedef enum gbp_subnet_type_t_ GBP_SUBNET_STITCHED_INTERNAL, GBP_SUBNET_STITCHED_EXTERNAL, GBP_SUBNET_L3_OUT, + GBP_SUBNET_ANON_L3_OUT, } gbp_subnet_type_t; extern int gbp_subnet_add (u32 rd_id, -- 2.16.6