diff options
author | Mauro Sardara <msardara@cisco.com> | 2020-03-24 17:34:14 +0000 |
---|---|---|
committer | Mauro Sardara <msardara@cisco.com> | 2020-09-14 17:31:15 +0000 |
commit | 88509fe353767cbde707c3e3b1f29392957819f3 (patch) | |
tree | cccd51bac7966cd3138c525e8075d90341184a66 /hicn-plugin/src/host_stack/route.c | |
parent | d875ae92a7fa1eaab3bc2616aeeedfc64a81fea4 (diff) |
[HICN-574] Host stack plugin for VPP.
Signed-off-by: Mauro Sardara <msardara@cisco.com>
Change-Id: I8d8fdffef31a7013265d6529c5f52f3d5ec70d18
Signed-off-by: Mauro Sardara <msardara@cisco.com>
Signed-off-by: Mauro <you@example.com>
Signed-off-by: Mauro Sardara <msardara@cisco.com>
Diffstat (limited to 'hicn-plugin/src/host_stack/route.c')
-rw-r--r-- | hicn-plugin/src/host_stack/route.c | 178 |
1 files changed, 178 insertions, 0 deletions
diff --git a/hicn-plugin/src/host_stack/route.c b/hicn-plugin/src/host_stack/route.c new file mode 100644 index 000000000..5b42bea26 --- /dev/null +++ b/hicn-plugin/src/host_stack/route.c @@ -0,0 +1,178 @@ +/* + * Copyright (c) 2020 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "host_stack.h" +#include "route.h" + +#include <vnet/fib/fib_entry.h> +#include <vnet/fib/fib_table.h> +#include <vnet/ip/ip6_packet.h> +#include <vnet/dpo/dpo.h> +#include <vnet/dpo/load_balance.h> +#include <vlib/global_funcs.h> +#include <vnet/dpo/drop_dpo.h> + +#define FIB_SOURCE_HICN_HS 0x04 //Right after the FIB_SOURCE_INTERFACE priority +#define HICN_HS_FIB_TABLE 0 + +fib_source_t hicn_hs_fib_src; + +void +hicn_hs_route_init () +{ + hicn_hs_fib_src = fib_source_allocate ("hicn_hs", FIB_SOURCE_HICN_HS, FIB_SOURCE_BH_API); +} + +always_inline int +hicn_route_get_dpo (const fib_prefix_t * prefix, + const dpo_id_t ** hicn_dpo, u32 * fib_index) +{ + //fib_prefix_t fib_pfx; + const dpo_id_t *load_balance_dpo_id; + const dpo_id_t *former_dpo_id; + int found = 0, ret = HICN_HS_ERROR_ROUTE_NOT_FOUND; + fib_node_index_t fib_entry_index; + + /* Check if the route already exist in the fib */ + /* + * ASSUMPTION: we use table 0 which is the default table and it is + * already existing and locked + */ + *fib_index = fib_table_find_or_create_and_lock (prefix->fp_proto, + HICN_HS_FIB_TABLE, + hicn_hs_fib_src); + fib_entry_index = fib_table_lookup_exact_match (*fib_index, prefix); + + if (fib_entry_index != FIB_NODE_INDEX_INVALID) + { + /* Route already existing. We need to update the dpo. */ + load_balance_dpo_id = + fib_entry_contribute_ip_forwarding (fib_entry_index); + + /* The dpo is not a load balance dpo as expected */ + if (load_balance_dpo_id->dpoi_type != DPO_LOAD_BALANCE) + ret = HICN_HS_ERROR_ROUTE_NO_LB_DPO; + else + { + /* former_dpo_id is a load_balance dpo */ + load_balance_t *lb = + load_balance_get (load_balance_dpo_id->dpoi_index); + + /* FIB entry exists but there is no hicn_hs dpo. */ + ret = HICN_HS_ERROR_ROUTE_DPO_NO_HICN; + for (int i = 0; i < lb->lb_n_buckets && !found; i++) + { + former_dpo_id = load_balance_get_bucket_i (lb, i); + + if (dpo_is_hicn_hs (former_dpo_id)) + { + *hicn_dpo = former_dpo_id; + ret = HICN_HS_ERROR_NONE; + found = 1; + } + } + } + } + /* + * Remove the lock from the table. We keep one lock per route, not + * per dpo + */ + fib_table_unlock (*fib_index, prefix->fp_proto, hicn_hs_fib_src); + + return ret; +} + +/* Add a new route for a name prefix */ +always_inline +int hicn_hs_route_add_flags (const fib_prefix_t * prefix, const dpo_id_t *dpo, fib_entry_flag_t flags) +{ + CLIB_UNUSED(vlib_main_t *vm) = vlib_get_main (); + int ret = HICN_HS_ERROR_NONE; + u32 fib_index; + const dpo_id_t *_dpo; + + ret = hicn_route_get_dpo (prefix, &_dpo, &fib_index); + + if (ret == HICN_HS_ERROR_ROUTE_NOT_FOUND) + { + /* Here is where we create the "via" like route */ + /* + * For the moment we use the global one the prefix you want + * to match Neale suggested -- FIB_SOURCE_HICN the client + * that is adding them -- no easy explanation at this timeā¦ + */ + fib_node_index_t new_fib_node_index = + fib_table_entry_special_dpo_add (fib_index, + prefix, + hicn_hs_fib_src, + flags, + dpo); + + /* We added a route, therefore add one lock to the table */ + fib_table_lock (fib_index, prefix->fp_proto, hicn_hs_fib_src); + + ret = + (new_fib_node_index != + FIB_NODE_INDEX_INVALID) ? HICN_HS_ERROR_NONE : + HICN_HS_ERROR_ROUTE_NO_INSERT; + } + + return ret; +} + +int +hicn_hs_route_add (const fib_prefix_t * prefix, const dpo_id_t *dpo) +{ + return hicn_hs_route_add_flags(prefix, dpo, (FIB_ENTRY_FLAG_EXCLUSIVE | + FIB_ENTRY_FLAG_LOOSE_URPF_EXEMPT)); +} + +clib_error_t * +hicn_hs_set_local_prefix(const fib_prefix_t * prefix) +{ + clib_error_t * ret = 0; + int rv; + const dpo_id_t *drop_dpo = drop_dpo_get(prefix->fp_proto == FIB_PROTOCOL_IP4 ? DPO_PROTO_IP4 : DPO_PROTO_IP6); + rv = hicn_hs_route_add_flags(prefix, drop_dpo, (FIB_ENTRY_FLAG_EXCLUSIVE | FIB_ENTRY_FLAG_LOCAL | FIB_ENTRY_FLAG_LOOSE_URPF_EXEMPT)); + + if (rv) + ret = clib_error_return (0, "Error: %s", hicn_hs_error_strings[rv]); + + return ret; +} + +int +hicn_route_del (fib_prefix_t * prefix) +{ + const dpo_id_t *hicn_dpo_id; + int ret = HICN_HS_ERROR_NONE; + u32 fib_index; + + /* Remove the fib entry only if the dpo is of type hicn */ + ret = hicn_route_get_dpo (prefix, &hicn_dpo_id, &fib_index); + + if (ret == HICN_HS_ERROR_NONE) + { + fib_table_entry_special_remove (HICN_HS_FIB_TABLE, prefix, hicn_hs_fib_src); + + /* + * Remove the lock from the table. We keep one lock per route + */ + fib_table_unlock (fib_index, prefix->fp_proto, hicn_hs_fib_src); + } + + // Remember to remove the lock from the table when removing the entry + return ret; +}
\ No newline at end of file |