summaryrefslogtreecommitdiffstats
path: root/hicn-plugin/src/faces/ip/face_ip.c
diff options
context:
space:
mode:
Diffstat (limited to 'hicn-plugin/src/faces/ip/face_ip.c')
-rwxr-xr-xhicn-plugin/src/faces/ip/face_ip.c326
1 files changed, 326 insertions, 0 deletions
diff --git a/hicn-plugin/src/faces/ip/face_ip.c b/hicn-plugin/src/faces/ip/face_ip.c
new file mode 100755
index 000000000..c7f6a1ba1
--- /dev/null
+++ b/hicn-plugin/src/faces/ip/face_ip.c
@@ -0,0 +1,326 @@
+/*
+ * Copyright (c) 2017-2019 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 "face_ip.h"
+#include "face_ip_node.h"
+#include "dpo_ip.h"
+#include "../../strategy_dpo_manager.h"
+#include "../face.h"
+#include "../../cache_policies/cs_lru.h"
+#include "../../infra.h"
+#include "../../hicn.h"
+#include "../app/face_prod.h"
+#include "../app/face_cons.h"
+
+#include "../../mapme.h" // HICN_MAPME_EVENT_*
+#include "../../mapme_eventmgr.h" // hicn_mapme_eventmgr_process_node
+
+extern vlib_node_registration_t hicn_mapme_eventmgr_process_node;
+
+u32 strategy_face_ip4_vlib_edge;
+u32 strategy_face_ip6_vlib_edge;
+
+void
+hicn_face_ip_init (vlib_main_t * vm)
+{
+ int strategy_nodes_n = hicn_strategy_get_all_available ();
+
+ /* Default Strategy has index 0 and it always exists */
+ strategy_face_ip4_vlib_edge = vlib_node_add_next (vm,
+ hicn_dpo_get_strategy_vft
+ (default_dpo.
+ hicn_dpo_get_type ())->
+ get_strategy_node_index
+ (),
+ hicn_face_ip4_output_node.
+ index);
+
+ strategy_face_ip6_vlib_edge = vlib_node_add_next (vm,
+ hicn_dpo_get_strategy_vft
+ (default_dpo.
+ hicn_dpo_get_type ())->
+ get_strategy_node_index
+ (),
+ hicn_face_ip6_output_node.
+ index);
+ /*
+ * Create and edge between al the other strategy nodes
+ * and the ip_encap nodes.
+ */
+ for (int i = 1; i < strategy_nodes_n; i++)
+ {
+ u32 temp_index4 = vlib_node_add_next (vm,
+ hicn_dpo_get_strategy_vft_from_id
+ (i)->get_strategy_node_index (),
+ hicn_face_ip4_output_node.index);
+ u32 temp_index6 = vlib_node_add_next (vm,
+ hicn_dpo_get_strategy_vft_from_id
+ (i)->get_strategy_node_index (),
+ hicn_face_ip6_output_node.index);
+ ASSERT (temp_index4 == strategy_face_ip4_vlib_edge);
+ ASSERT (temp_index6 == strategy_face_ip6_vlib_edge);
+ }
+
+ hicn_dpo_ip_module_init ();
+
+ register_face_type (hicn_face_ip_type, &ip_vft, "ip");
+}
+
+int
+hicn_face_ip_del (hicn_face_id_t face_id)
+{
+ hicn_face_t *face = hicn_dpoi_get_from_idx (face_id);
+ hicn_face_ip_t *face_ip = (hicn_face_ip_t *) face->data;
+ hicn_face_ip_key_t key;
+ hicn_face_ip_key_t old_key;
+
+ if (ip46_address_is_ip4 (&face_ip->local_addr))
+ {
+ hicn_face_ip4_get_key (&(face_ip->local_addr.ip4), face->shared.sw_if,
+ &key);
+ mhash_unset (&hicn_face_ip_local_hashtb, &key, (uword *) & old_key);
+ hicn_face_ip4_get_key (&(face_ip->remote_addr.ip4), face->shared.sw_if,
+ &key);
+ mhash_unset (&hicn_face_ip_remote_hashtb, &key, (uword *) & old_key);
+ }
+ else
+ {
+ hicn_face_ip6_get_key (&(face_ip->local_addr.ip6), face->shared.sw_if,
+ &key);
+ mhash_unset (&hicn_face_ip_local_hashtb, &key, (uword *) & old_key);
+ hicn_face_ip6_get_key (&(face_ip->remote_addr.ip6), face->shared.sw_if,
+ &key);
+ mhash_unset (&hicn_face_ip_remote_hashtb, &key, (uword *) & old_key);
+ }
+ return hicn_face_del (face_id);
+}
+
+
+/*
+ * Utility that adds a new face cache entry. For the moment we assume that the
+ * ip_adjacency has already been set up.
+ */
+int
+hicn_face_ip_add (const ip46_address_t * local_addr,
+ const ip46_address_t * remote_addr,
+ int sw_if, hicn_face_id_t * pfaceid)
+{
+ fib_protocol_t fib_type;
+ vnet_link_t link_type;
+ adj_index_t adj;
+ dpo_proto_t dpo_proto;
+
+ /* Check if we found at least one ip address */
+ if (ip46_address_is_zero (local_addr) || ip46_address_is_zero (remote_addr))
+ return HICN_ERROR_FACE_NO_GLOBAL_IP;
+
+ if (ip46_address_is_ip4 (local_addr) && ip46_address_is_ip4 (remote_addr))
+ {
+ link_type = VNET_LINK_IP4;
+ fib_type = FIB_PROTOCOL_IP4;
+ }
+ else
+ {
+ link_type = VNET_LINK_IP6;
+ fib_type = FIB_PROTOCOL_IP6;
+ }
+
+
+ adj = adj_nbr_add_or_lock (fib_type, link_type, remote_addr, sw_if);
+
+ hicn_face_flags_t flags = (hicn_face_flags_t) 0;
+ flags |= HICN_FACE_FLAGS_FACE;
+
+ hicn_face_t *face;
+ if (ip46_address_is_ip4 (local_addr))
+ {
+ face =
+ hicn_face_ip4_get (&(local_addr->ip4), sw_if,
+ &hicn_face_ip_local_hashtb);
+
+ if (face != NULL)
+ return HICN_ERROR_FACE_ALREADY_CREATED;
+
+ face =
+ hicn_face_ip4_get (&(remote_addr->ip4), sw_if,
+ &hicn_face_ip_remote_hashtb);
+
+ /* If remote matches the face is a iface */
+ if (face == NULL)
+ {
+ hicn_iface_ip_add (local_addr, remote_addr, sw_if, pfaceid);
+ face = hicn_dpoi_get_from_idx (*pfaceid);
+ }
+ else
+ {
+ *pfaceid = hicn_dpoi_get_index (face);
+ }
+
+ hicn_face_ip_key_t key;
+ hicn_face_ip4_get_key (&(local_addr->ip4), sw_if, &key);
+
+ mhash_set_mem (&hicn_face_ip_local_hashtb, &key, (uword *) pfaceid, 0);
+
+ hicn_face_ip_t *ip_face = (hicn_face_ip_t *) face->data;
+ clib_memcpy (&ip_face->local_addr, local_addr, sizeof (ip4_address_t));
+ clib_memcpy (&ip_face->remote_addr, remote_addr,
+ sizeof (ip4_address_t));
+ face->shared.sw_if = sw_if;
+ face->shared.flags = flags;
+ face->shared.adj = adj;
+
+ dpo_proto = DPO_PROTO_IP4;
+ }
+ else
+ {
+ face =
+ hicn_face_ip6_get (&(local_addr->ip6), sw_if,
+ &hicn_face_ip_local_hashtb);
+
+ if (face != NULL)
+ return HICN_ERROR_FACE_ALREADY_CREATED;
+
+ face =
+ hicn_face_ip6_get (&(remote_addr->ip6), sw_if,
+ &hicn_face_ip_remote_hashtb);
+
+ /* If remote matches the face is a iface */
+ if (face == NULL)
+ {
+ hicn_iface_ip_add (local_addr, remote_addr, sw_if, pfaceid);
+ face = hicn_dpoi_get_from_idx (*pfaceid);
+ }
+ else
+ {
+ *pfaceid = hicn_dpoi_get_index (face);
+ }
+
+ hicn_face_ip_key_t key;
+ hicn_face_ip6_get_key (&(local_addr->ip6), sw_if, &key);
+
+ mhash_set_mem (&hicn_face_ip_local_hashtb, &key, (uword *) pfaceid, 0);
+
+ hicn_face_ip_t *ip_face = (hicn_face_ip_t *) face->data;
+ clib_memcpy (&ip_face->local_addr, local_addr, sizeof (ip6_address_t));
+ clib_memcpy (&ip_face->remote_addr, remote_addr,
+ sizeof (ip6_address_t));
+ face->shared.sw_if = sw_if;
+ face->shared.flags = flags;
+ face->shared.adj = adj;
+
+ dpo_proto = DPO_PROTO_IP6;
+ }
+
+ retx_t *retx = vlib_process_signal_event_data (vlib_get_main (),
+ hicn_mapme_eventmgr_process_node.
+ index,
+ HICN_MAPME_EVENT_FACE_ADD, 1,
+ sizeof (retx_t));
+ *retx = (retx_t)
+ {
+ .prefix = 0,.dpo = (dpo_id_t)
+ {
+ .dpoi_type = hicn_face_ip_type,.dpoi_proto = dpo_proto,.dpoi_next_node =
+ 0,.dpoi_index = *pfaceid,}
+ };
+
+ return HICN_ERROR_NONE;
+}
+
+u8 *
+format_hicn_face_ip (u8 * s, va_list * args)
+{
+ index_t index = va_arg (*args, index_t);
+ CLIB_UNUSED (u32 indent) = va_arg (*args, u32);
+ hicn_face_t *face;
+ hicn_face_ip_t *ip_face;
+ ip_adjacency_t *adj;
+ vnet_main_t *vnm = vnet_get_main ();
+
+ face = hicn_dpoi_get_from_idx (index);
+ ip_face = (hicn_face_ip_t *) face->data;
+
+ if (face->shared.flags & HICN_FACE_FLAGS_FACE)
+ {
+ ASSERT (face->shared.adj != (adj_index_t) ~ 0);
+ adj = adj_get (face->shared.adj);
+
+ hicn_face_id_t face_id = hicn_dpoi_get_index (face);
+ s = format (s, "%U Face %d: ", format_white_space, indent, face_id);
+ s = format (s, "type IP local %U ",
+ format_ip46_address, &ip_face->local_addr, IP46_TYPE_ANY);
+ s =
+ format (s, "remote %U ", format_ip46_address, &ip_face->remote_addr,
+ IP46_TYPE_ANY);
+ s = format (s, "%U", format_vnet_link, adj->ia_link);
+ s = format (s, " dev %U", format_vnet_sw_interface_name, vnm,
+ vnet_get_sw_interface (vnm, face->shared.sw_if));
+
+ if ((face->shared.flags & HICN_FACE_FLAGS_APPFACE_PROD))
+ s = format (s, " %U", format_hicn_face_prod, face_id, 0);
+ else if ((face->shared.flags & HICN_FACE_FLAGS_APPFACE_CONS))
+ s = format (s, " %U", format_hicn_face_cons, face_id, 0);
+
+ if ((face->shared.flags & HICN_FACE_FLAGS_DELETED))
+ s = format (s, " (deleted)");
+ }
+ else
+ {
+ hicn_face_id_t face_id = hicn_dpoi_get_index (face);
+ s = format (s, "%U iFace %d: ", format_white_space, indent, face_id);
+ s = format (s, "type IP local %U remote %U",
+ format_ip46_address, &ip_face->local_addr, IP46_TYPE_ANY,
+ format_ip46_address, &ip_face->remote_addr, IP46_TYPE_ANY);
+ s =
+ format (s, " dev %U", format_vnet_sw_interface_name, vnm,
+ vnet_get_sw_interface (vnm, face->shared.sw_if));
+
+ if ((face->shared.flags & HICN_FACE_FLAGS_APPFACE_PROD))
+ s = format (s, " %U", format_hicn_face_prod, face_id, 0);
+ else if ((face->shared.flags & HICN_FACE_FLAGS_APPFACE_CONS))
+ s = format (s, " %U", format_hicn_face_cons, face_id, 0);
+
+ if ((face->shared.flags & HICN_FACE_FLAGS_DELETED))
+ s = format (s, " (deleted)");
+ }
+
+ return s;
+}
+
+void
+hicn_face_ip_get_dpo (hicn_face_t * face, dpo_id_t * dpo)
+{
+
+ hicn_face_ip_t *face_ip = (hicn_face_ip_t *) face->data;
+ return hicn_dpo_ip_create_from_face (face, dpo,
+ ip46_address_is_ip4 (&face_ip->
+ remote_addr) ?
+ strategy_face_ip4_vlib_edge :
+ strategy_face_ip6_vlib_edge);
+}
+
+hicn_face_vft_t ip_vft = {
+ .format_face = format_hicn_face_ip,
+ .hicn_face_del = hicn_face_ip_del,
+ .hicn_face_get_dpo = hicn_face_ip_get_dpo,
+};
+
+/*
+ * fd.io coding-style-patch-verification: ON
+ *
+ * Local Variables:
+ * eval: (c-set-style "gnu")
+ * End:
+ */