diff options
Diffstat (limited to 'src/vnet/lisp-gpe')
23 files changed, 0 insertions, 8257 deletions
diff --git a/src/vnet/lisp-gpe/FEATURE.yaml b/src/vnet/lisp-gpe/FEATURE.yaml deleted file mode 100644 index d2016e6120d..00000000000 --- a/src/vnet/lisp-gpe/FEATURE.yaml +++ /dev/null @@ -1,11 +0,0 @@ ---- -name: Locator ID Separation Protocol Generic Protocol Extension -maintainer: Florin Coras <fcoras@cisco.com> -features: - - ITR, ETR and RTR modes - - Support for Ethernet, IPv4, IPv6 and NSH EIDs (payloads) - - Source/dest forwarding - - IPv4 and IPv6 RLOCs -description: "Locator ID Separation Protocol Generic Protocol Extension (LISP-GPE) implementation" -state: production -properties: [API, CLI, STATS, MULTITHREAD] diff --git a/src/vnet/lisp-gpe/decap.c b/src/vnet/lisp-gpe/decap.c deleted file mode 100644 index ab35c7ea73d..00000000000 --- a/src/vnet/lisp-gpe/decap.c +++ /dev/null @@ -1,605 +0,0 @@ -/* - * Copyright (c) 2016 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. - */ -/** - * @file - * @brief L2 LISP-GPE decap code. - * - */ -#include <vlib/vlib.h> -#include <vnet/pg/pg.h> -#include <vnet/lisp-gpe/lisp_gpe.h> - -typedef struct -{ - u32 next_index; - u32 tunnel_index; - u32 error; - lisp_gpe_header_t h; -} lisp_gpe_rx_trace_t; - -static u8 * -format_lisp_gpe_rx_trace (u8 * s, va_list * args) -{ - CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *); - CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *); - lisp_gpe_rx_trace_t *t = va_arg (*args, lisp_gpe_rx_trace_t *); - - if (t->tunnel_index != ~0) - { - s = format (s, "LISP-GPE: tunnel %d next %d error %d", t->tunnel_index, - t->next_index, t->error); - } - else - { - s = format (s, "LISP-GPE: no tunnel next %d error %d\n", t->next_index, - t->error); - } - s = format (s, "\n %U", format_lisp_gpe_header_with_length, &t->h, - (u32) sizeof (t->h) /* max size */ ); - return s; -} - -static u32 next_proto_to_next_index[LISP_GPE_NEXT_PROTOS] = { - LISP_GPE_INPUT_NEXT_DROP, - LISP_GPE_INPUT_NEXT_IP4_INPUT, - LISP_GPE_INPUT_NEXT_IP6_INPUT, - LISP_GPE_INPUT_NEXT_L2_INPUT, - LISP_GPE_INPUT_NEXT_DROP -}; - -always_inline u32 -next_protocol_to_next_index (lisp_gpe_header_t * lgh, u8 * next_header) -{ - lisp_gpe_main_t *lgm = vnet_lisp_gpe_get_main (); - - /* lisp-gpe router */ - if (PREDICT_TRUE ((lgh->flags & LISP_GPE_FLAGS_P) - || GPE_ENCAP_VXLAN == lgm->encap_mode)) - { - if (PREDICT_FALSE (lgh->next_protocol >= LISP_GPE_NEXT_PROTOS)) - return LISP_GPE_INPUT_NEXT_DROP; - - return next_proto_to_next_index[lgh->next_protocol]; - } - /* legacy lisp router */ - else if ((lgh->flags & LISP_GPE_FLAGS_P) == 0) - { - ip4_header_t *iph = (ip4_header_t *) next_header; - if ((iph->ip_version_and_header_length & 0xF0) == 0x40) - return LISP_GPE_INPUT_NEXT_IP4_INPUT; - else if ((iph->ip_version_and_header_length & 0xF0) == 0x60) - return LISP_GPE_INPUT_NEXT_IP6_INPUT; - else - return LISP_GPE_INPUT_NEXT_DROP; - } - else - return LISP_GPE_INPUT_NEXT_DROP; -} - -always_inline tunnel_lookup_t * -next_index_to_iface (lisp_gpe_main_t * lgm, u32 next_index) -{ - if (LISP_GPE_INPUT_NEXT_IP4_INPUT == next_index - || LISP_GPE_INPUT_NEXT_IP6_INPUT == next_index) - return &lgm->l3_ifaces; - else if (LISP_GPE_INPUT_NEXT_L2_INPUT == next_index) - return &lgm->l2_ifaces; - else if (LISP_GPE_INPUT_NEXT_NSH_INPUT == next_index) - return &lgm->nsh_ifaces; - clib_warning ("next_index not associated to an interface!"); - return 0; -} - -static_always_inline void -incr_decap_stats (vnet_main_t * vnm, u32 thread_index, u32 length, - u32 sw_if_index, u32 * last_sw_if_index, u32 * n_packets, - u32 * n_bytes) -{ - vnet_interface_main_t *im; - - if (PREDICT_TRUE (sw_if_index == *last_sw_if_index)) - { - *n_packets += 1; - *n_bytes += length; - } - else - { - if (PREDICT_TRUE (*last_sw_if_index != ~0)) - { - im = &vnm->interface_main; - - vlib_increment_combined_counter (im->combined_sw_if_counters + - VNET_INTERFACE_COUNTER_RX, - thread_index, *last_sw_if_index, - *n_packets, *n_bytes); - } - *last_sw_if_index = sw_if_index; - *n_packets = 1; - *n_bytes = length; - } -} - -/** - * @brief LISP-GPE decap dispatcher. - * @node lisp_gpe_input_inline - * - * LISP-GPE decap dispatcher. - * - * Decaps IP-UDP-LISP-GPE header and based on the next protocol and in the - * GPE header and the vni decides the next node to forward the packet to. - * - * @param[in] vm vlib_main_t corresponding to current thread. - * @param[in] node vlib_node_runtime_t data for this node. - * @param[in] frame vlib_frame_t whose contents should be dispatched. - * - * @return number of vectors in frame. - */ -static uword -lisp_gpe_input_inline (vlib_main_t * vm, vlib_node_runtime_t * node, - vlib_frame_t * from_frame, u8 is_v4) -{ - u32 n_left_from, next_index, *from, *to_next, thread_index; - u32 n_bytes = 0, n_packets = 0, last_sw_if_index = ~0, drops = 0; - lisp_gpe_main_t *lgm = vnet_lisp_gpe_get_main (); - - thread_index = vm->thread_index; - from = vlib_frame_vector_args (from_frame); - n_left_from = from_frame->n_vectors; - - next_index = node->cached_next_index; - - while (n_left_from > 0) - { - u32 n_left_to_next; - - vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next); - - while (n_left_from >= 4 && n_left_to_next >= 2) - { - u32 bi0, bi1; - vlib_buffer_t *b0, *b1; - ip4_udp_lisp_gpe_header_t *iul4_0, *iul4_1; - ip6_udp_lisp_gpe_header_t *iul6_0, *iul6_1; - lisp_gpe_header_t *lh0, *lh1; - u32 next0, next1, error0, error1; - uword *si0, *si1; - tunnel_lookup_t *tl0, *tl1; - - /* Prefetch next iteration. */ - { - vlib_buffer_t *p2, *p3; - - p2 = vlib_get_buffer (vm, from[2]); - p3 = vlib_get_buffer (vm, from[3]); - - vlib_prefetch_buffer_header (p2, LOAD); - vlib_prefetch_buffer_header (p3, LOAD); - - CLIB_PREFETCH (p2->data, 2 * CLIB_CACHE_LINE_BYTES, LOAD); - CLIB_PREFETCH (p3->data, 2 * CLIB_CACHE_LINE_BYTES, LOAD); - } - - bi0 = from[0]; - bi1 = from[1]; - to_next[0] = bi0; - to_next[1] = bi1; - from += 2; - to_next += 2; - n_left_to_next -= 2; - n_left_from -= 2; - - b0 = vlib_get_buffer (vm, bi0); - b1 = vlib_get_buffer (vm, bi1); - - /* udp leaves current_data pointing at the lisp header */ - if (is_v4) - { - vlib_buffer_advance (b0, - -(word) (sizeof (udp_header_t) + - sizeof (ip4_header_t))); - vlib_buffer_advance (b1, - -(word) (sizeof (udp_header_t) + - sizeof (ip4_header_t))); - - iul4_0 = vlib_buffer_get_current (b0); - iul4_1 = vlib_buffer_get_current (b1); - - /* pop (ip, udp, lisp-gpe) */ - vlib_buffer_advance (b0, sizeof (*iul4_0)); - vlib_buffer_advance (b1, sizeof (*iul4_1)); - - lh0 = &iul4_0->lisp; - lh1 = &iul4_1->lisp; - } - else - { - vlib_buffer_advance (b0, - -(word) (sizeof (udp_header_t) + - sizeof (ip6_header_t))); - vlib_buffer_advance (b1, - -(word) (sizeof (udp_header_t) + - sizeof (ip6_header_t))); - - iul6_0 = vlib_buffer_get_current (b0); - iul6_1 = vlib_buffer_get_current (b1); - - /* pop (ip, udp, lisp-gpe) */ - vlib_buffer_advance (b0, sizeof (*iul6_0)); - vlib_buffer_advance (b1, sizeof (*iul6_1)); - - lh0 = &iul6_0->lisp; - lh1 = &iul6_1->lisp; - } - - /* determine next_index from lisp-gpe header */ - next0 = next_protocol_to_next_index (lh0, - vlib_buffer_get_current (b0)); - next1 = next_protocol_to_next_index (lh1, - vlib_buffer_get_current (b1)); - - /* determine if tunnel is l2 or l3 */ - tl0 = next_index_to_iface (lgm, next0); - tl1 = next_index_to_iface (lgm, next1); - - /* map iid/vni to lisp-gpe sw_if_index which is used by ipx_input to - * decide the rx vrf and the input features to be applied */ - si0 = hash_get (tl0->sw_if_index_by_vni, - clib_net_to_host_u32 (lh0->iid << 8)); - si1 = hash_get (tl1->sw_if_index_by_vni, - clib_net_to_host_u32 (lh1->iid << 8)); - - - /* Required to make the l2 tag push / pop code work on l2 subifs */ - vnet_update_l2_len (b0); - vnet_update_l2_len (b1); - - if (si0) - { - incr_decap_stats (lgm->vnet_main, thread_index, - vlib_buffer_length_in_chain (vm, b0), si0[0], - &last_sw_if_index, &n_packets, &n_bytes); - vnet_buffer (b0)->sw_if_index[VLIB_RX] = si0[0]; - error0 = 0; - } - else - { - next0 = LISP_GPE_INPUT_NEXT_DROP; - error0 = LISP_GPE_ERROR_NO_TUNNEL; - drops++; - } - - if (si1) - { - incr_decap_stats (lgm->vnet_main, thread_index, - vlib_buffer_length_in_chain (vm, b1), si1[0], - &last_sw_if_index, &n_packets, &n_bytes); - vnet_buffer (b1)->sw_if_index[VLIB_RX] = si1[0]; - error1 = 0; - } - else - { - next1 = LISP_GPE_INPUT_NEXT_DROP; - error1 = LISP_GPE_ERROR_NO_TUNNEL; - drops++; - } - - b0->error = error0 ? node->errors[error0] : 0; - b1->error = error1 ? node->errors[error1] : 0; - - if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED)) - { - lisp_gpe_rx_trace_t *tr = vlib_add_trace (vm, node, b0, - sizeof (*tr)); - tr->next_index = next0; - tr->error = error0; - tr->h = lh0[0]; - } - - if (PREDICT_FALSE (b1->flags & VLIB_BUFFER_IS_TRACED)) - { - lisp_gpe_rx_trace_t *tr = vlib_add_trace (vm, node, b1, - sizeof (*tr)); - tr->next_index = next1; - tr->error = error1; - tr->h = lh1[0]; - } - - vlib_validate_buffer_enqueue_x2 (vm, node, next_index, to_next, - n_left_to_next, bi0, bi1, next0, - next1); - } - - while (n_left_from > 0 && n_left_to_next > 0) - { - u32 bi0; - vlib_buffer_t *b0; - u32 next0; - ip4_udp_lisp_gpe_header_t *iul4_0; - ip6_udp_lisp_gpe_header_t *iul6_0; - lisp_gpe_header_t *lh0; - u32 error0; - uword *si0; - tunnel_lookup_t *tl0; - - bi0 = from[0]; - to_next[0] = bi0; - from += 1; - to_next += 1; - n_left_from -= 1; - n_left_to_next -= 1; - - b0 = vlib_get_buffer (vm, bi0); - - /* udp leaves current_data pointing at the lisp header - * TODO: there's no difference in processing between v4 and v6 - * encapsulated packets so the code should be simplified if ip header - * info is not going to be used for dp smrs/dpsec */ - if (is_v4) - { - vlib_buffer_advance (b0, - -(word) (sizeof (udp_header_t) + - sizeof (ip4_header_t))); - - iul4_0 = vlib_buffer_get_current (b0); - - /* pop (ip, udp, lisp-gpe) */ - vlib_buffer_advance (b0, sizeof (*iul4_0)); - - lh0 = &iul4_0->lisp; - } - else - { - vlib_buffer_advance (b0, - -(word) (sizeof (udp_header_t) + - sizeof (ip6_header_t))); - - iul6_0 = vlib_buffer_get_current (b0); - - /* pop (ip, udp, lisp-gpe) */ - vlib_buffer_advance (b0, sizeof (*iul6_0)); - - lh0 = &iul6_0->lisp; - } - - /* TODO if security is to be implemented, something similar to RPF, - * probably we'd like to check that the peer is allowed to send us - * packets. For this, we should use the tunnel table OR check that - * we have a mapping for the source eid and that the outer source of - * the packet is one of its locators */ - - /* determine next_index from lisp-gpe header */ - next0 = next_protocol_to_next_index (lh0, - vlib_buffer_get_current (b0)); - - /* determine if tunnel is l2 or l3 */ - tl0 = next_index_to_iface (lgm, next0); - - /* map iid/vni to lisp-gpe sw_if_index which is used by ipx_input to - * decide the rx vrf and the input features to be applied. - * NOTE: vni uses only the first 24 bits */ - si0 = hash_get (tl0->sw_if_index_by_vni, - clib_net_to_host_u32 (lh0->iid << 8)); - - /* Required to make the l2 tag push / pop code work on l2 subifs */ - vnet_update_l2_len (b0); - - if (si0) - { - incr_decap_stats (lgm->vnet_main, thread_index, - vlib_buffer_length_in_chain (vm, b0), si0[0], - &last_sw_if_index, &n_packets, &n_bytes); - vnet_buffer (b0)->sw_if_index[VLIB_RX] = si0[0]; - error0 = 0; - } - else - { - next0 = LISP_GPE_INPUT_NEXT_DROP; - error0 = LISP_GPE_ERROR_NO_TUNNEL; - drops++; - } - - /* TODO error handling if security is implemented */ - b0->error = error0 ? node->errors[error0] : 0; - - if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED)) - { - lisp_gpe_rx_trace_t *tr = vlib_add_trace (vm, node, b0, - sizeof (*tr)); - tr->next_index = next0; - tr->error = error0; - tr->h = lh0[0]; - } - - vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next, - n_left_to_next, bi0, next0); - } - - vlib_put_next_frame (vm, node, next_index, n_left_to_next); - } - - /* flush iface stats */ - incr_decap_stats (lgm->vnet_main, thread_index, 0, ~0, &last_sw_if_index, - &n_packets, &n_bytes); - vlib_node_increment_counter (vm, lisp_gpe_ip4_input_node.index, - LISP_GPE_ERROR_NO_TUNNEL, drops); - return from_frame->n_vectors; -} - -static uword -lisp_gpe_ip4_input (vlib_main_t * vm, vlib_node_runtime_t * node, - vlib_frame_t * from_frame) -{ - return lisp_gpe_input_inline (vm, node, from_frame, 1); -} - -static uword -lisp_gpe_ip6_input (vlib_main_t * vm, vlib_node_runtime_t * node, - vlib_frame_t * from_frame) -{ - return lisp_gpe_input_inline (vm, node, from_frame, 0); -} - -static char *lisp_gpe_ip4_input_error_strings[] = { -#define lisp_gpe_error(n,s) s, -#include <vnet/lisp-gpe/lisp_gpe_error.def> -#undef lisp_gpe_error -}; - -/* *INDENT-OFF* */ -VLIB_REGISTER_NODE (lisp_gpe_ip4_input_node) = { - .function = lisp_gpe_ip4_input, - .name = "lisp-gpe-ip4-input", - /* Takes a vector of packets. */ - .vector_size = sizeof (u32), - .n_next_nodes = LISP_GPE_INPUT_N_NEXT, - .next_nodes = { -#define _(s,n) [LISP_GPE_INPUT_NEXT_##s] = n, - foreach_lisp_gpe_ip_input_next -#undef _ - }, - - .n_errors = ARRAY_LEN (lisp_gpe_ip4_input_error_strings), - .error_strings = lisp_gpe_ip4_input_error_strings, - - .format_buffer = format_lisp_gpe_header_with_length, - .format_trace = format_lisp_gpe_rx_trace, - // $$$$ .unformat_buffer = unformat_lisp_gpe_header, -}; -/* *INDENT-ON* */ - -/* *INDENT-OFF* */ -VLIB_REGISTER_NODE (lisp_gpe_ip6_input_node) = { - .function = lisp_gpe_ip6_input, - .name = "lisp-gpe-ip6-input", - /* Takes a vector of packets. */ - .vector_size = sizeof (u32), - .n_next_nodes = LISP_GPE_INPUT_N_NEXT, - .next_nodes = { -#define _(s,n) [LISP_GPE_INPUT_NEXT_##s] = n, - foreach_lisp_gpe_ip_input_next -#undef _ - }, - - .n_errors = ARRAY_LEN (lisp_gpe_ip4_input_error_strings), - .error_strings = lisp_gpe_ip4_input_error_strings, - - .format_buffer = format_lisp_gpe_header_with_length, - .format_trace = format_lisp_gpe_rx_trace, - // $$$$ .unformat_buffer = unformat_lisp_gpe_header, -}; -/* *INDENT-ON* */ - -/** - * Adds arc from lisp-gpe-input to nsh-input if nsh-input is available - */ -static void -gpe_add_arc_from_input_to_nsh () -{ - lisp_gpe_main_t *lgm = vnet_lisp_gpe_get_main (); - vlib_main_t *vm = lgm->vlib_main; - vlib_node_t *nsh_input; - - /* Arc already exists */ - if (next_proto_to_next_index[LISP_GPE_NEXT_PROTO_NSH] - != LISP_GPE_INPUT_NEXT_DROP) - return; - - /* Check if nsh-input is available */ - if ((nsh_input = vlib_get_node_by_name (vm, (u8 *) "nsh-input"))) - { - u32 slot4, slot6; - slot4 = vlib_node_add_next_with_slot (vm, lisp_gpe_ip4_input_node.index, - nsh_input->index, - LISP_GPE_NEXT_PROTO_NSH); - slot6 = vlib_node_add_next_with_slot (vm, lisp_gpe_ip6_input_node.index, - nsh_input->index, - LISP_GPE_NEXT_PROTO_NSH); - ASSERT (slot4 == slot6 && slot4 == LISP_GPE_INPUT_NEXT_NSH_INPUT); - - next_proto_to_next_index[LISP_GPE_NEXT_PROTO_NSH] = slot4; - } -} - -/** GPE decap init function. */ -clib_error_t * -gpe_decap_init (vlib_main_t * vm) -{ - clib_error_t *error = 0; - - if ((error = vlib_call_init_function (vm, lisp_gpe_init))) - return error; - - gpe_add_arc_from_input_to_nsh (); - return 0; -} - -static uword -lisp_gpe_nsh_placeholder_input (vlib_main_t * vm, vlib_node_runtime_t * node, - vlib_frame_t * from_frame) -{ - vlib_node_increment_counter (vm, node->node_index, 0, 1); - return from_frame->n_vectors; -} - -static char *lisp_gpe_nsh_placeholder_error_strings[] = { - "lisp gpe placeholder nsh decap", -}; - -/* *INDENT-OFF* */ -VLIB_REGISTER_NODE (lisp_gpe_nsh_placeholder_input_node) = { - .function = lisp_gpe_nsh_placeholder_input, - .name = "lisp-gpe-nsh-placeholder-input", - .vector_size = sizeof (u32), - .type = VLIB_NODE_TYPE_INTERNAL, - .n_next_nodes = 1, - - .n_errors = 1, - .error_strings = lisp_gpe_nsh_placeholder_error_strings, - - .next_nodes = { - [0] = "error-drop", - }, -}; -/* *INDENT-ON* */ - -static clib_error_t * -lisp_add_placeholder_nsh_node_command_fn (vlib_main_t * vm, - unformat_input_t * input, - vlib_cli_command_t * cmd) -{ - lisp_gpe_main_t *lgm = vnet_lisp_gpe_get_main (); - vlib_node_add_next (lgm->vlib_main, lisp_gpe_ip4_input_node.index, - lisp_gpe_nsh_placeholder_input_node.index); - next_proto_to_next_index[LISP_GPE_NEXT_PROTO_NSH] = - LISP_GPE_INPUT_NEXT_NSH_INPUT; - return 0; -} - -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND (lisp_add_placeholder_nsh_node_command, static) = { - .path = "test one nsh add-placeholder-decap-node", - .function = lisp_add_placeholder_nsh_node_command_fn, -}; -/* *INDENT-ON* */ - -VLIB_INIT_FUNCTION (gpe_decap_init); - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/vnet/lisp-gpe/dir.dox b/src/vnet/lisp-gpe/dir.dox deleted file mode 100644 index afa6da9ab2c..00000000000 --- a/src/vnet/lisp-gpe/dir.dox +++ /dev/null @@ -1,26 +0,0 @@ -/* - * - * Copyright (c) 2013 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. - */ -/** - @dir - @brief LISP-GPE code. - - An implementation of LISP-GPE as per: - rfc-6830 - draft-lewis-lisp-gpe-02 - - See file: rfc.txt - -*/
\ No newline at end of file diff --git a/src/vnet/lisp-gpe/interface.c b/src/vnet/lisp-gpe/interface.c deleted file mode 100644 index 1ccb53dda72..00000000000 --- a/src/vnet/lisp-gpe/interface.c +++ /dev/null @@ -1,945 +0,0 @@ -/* - * Copyright (c) 2016 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. - */ - -/** - * @file - * @brief Common utility functions for LISP-GPE interfaces. - * - */ - -#include <vppinfra/error.h> -#include <vppinfra/hash.h> -#include <vnet/vnet.h> -#include <vnet/ip/ip.h> -#include <vnet/udp/udp.h> -#include <vnet/ethernet/ethernet.h> -#include <vnet/lisp-gpe/lisp_gpe.h> -#include <vnet/lisp-gpe/lisp_gpe_fwd_entry.h> -#include <vnet/lisp-gpe/lisp_gpe_tenant.h> -#include <vnet/lisp-gpe/lisp_gpe_adjacency.h> -#include <vnet/adj/adj.h> -#include <vnet/fib/fib_table.h> -#include <vnet/fib/ip4_fib.h> -#include <vnet/fib/ip6_fib.h> -#include <vnet/lisp-cp/lisp_cp_dpo.h> - -/** - * @brief The VLIB node arc/edge from the interface's TX node, to the L2 - * load-balanceing node. Which is where all packets go - */ -static uword l2_arc_to_lb; - -#define foreach_lisp_gpe_tx_next \ - _(DROP, "error-drop") \ - _(IP4_LOOKUP, "ip4-lookup") \ - _(IP6_LOOKUP, "ip6-lookup") - -typedef enum -{ -#define _(sym,str) LISP_GPE_TX_NEXT_##sym, - foreach_lisp_gpe_tx_next -#undef _ - LISP_GPE_TX_N_NEXT, -} lisp_gpe_tx_next_t; - -typedef struct -{ - u32 tunnel_index; -} lisp_gpe_tx_trace_t; - -u8 * -format_lisp_gpe_tx_trace (u8 * s, va_list * args) -{ - CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *); - CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *); - lisp_gpe_tx_trace_t *t = va_arg (*args, lisp_gpe_tx_trace_t *); - - s = format (s, "LISP-GPE-TX: tunnel %d", t->tunnel_index); - return s; -} - -#define is_v4_packet(_h) ((*(u8*) _h) & 0xF0) == 0x40 - -/** - * @brief LISP-GPE interface TX (encap) function. - * @node lisp_gpe_interface_tx - * - * The LISP-GPE interface TX (encap) function. - * - * Looks up the associated tunnel based on the adjacency hit in the SD FIB - * and if the tunnel is multihomed it uses the flow hash to determine - * sub-tunnel, and rewrite string, to be used to encapsulate the packet. - * - * @param[in] vm vlib_main_t corresponding to the current thread. - * @param[in] node vlib_node_runtime_t data for this node. - * @param[in] frame vlib_frame_t whose contents should be dispatched. - * - * @return number of vectors in frame. - */ -static uword -lisp_gpe_interface_tx (vlib_main_t * vm, vlib_node_runtime_t * node, - vlib_frame_t * from_frame) -{ - u32 n_left_from, next_index, *from, *to_next; - lisp_gpe_main_t *lgm = &lisp_gpe_main; - - from = vlib_frame_vector_args (from_frame); - n_left_from = from_frame->n_vectors; - - next_index = node->cached_next_index; - - while (n_left_from > 0) - { - u32 n_left_to_next; - - vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next); - - while (n_left_from > 0 && n_left_to_next > 0) - { - u32 bi0, adj_index0, next0; - const ip_adjacency_t *adj0; - const dpo_id_t *dpo0; - vlib_buffer_t *b0; - u8 is_v4_0; - - bi0 = from[0]; - to_next[0] = bi0; - from += 1; - to_next += 1; - n_left_from -= 1; - n_left_to_next -= 1; - - b0 = vlib_get_buffer (vm, bi0); - - /* Fixup the checksum and len fields in the LISP tunnel encap - * that was applied at the midchain node */ - is_v4_0 = is_v4_packet (vlib_buffer_get_current (b0)); - ip_udp_fixup_one (lgm->vlib_main, b0, is_v4_0); - - /* Follow the DPO on which the midchain is stacked */ - adj_index0 = vnet_buffer (b0)->ip.adj_index[VLIB_TX]; - adj0 = adj_get (adj_index0); - dpo0 = &adj0->sub_type.midchain.next_dpo; - next0 = dpo0->dpoi_next_node; - vnet_buffer (b0)->ip.adj_index[VLIB_TX] = dpo0->dpoi_index; - - if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED)) - { - lisp_gpe_tx_trace_t *tr = vlib_add_trace (vm, node, b0, - sizeof (*tr)); - tr->tunnel_index = adj_index0; - } - vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next, - n_left_to_next, bi0, next0); - } - - vlib_put_next_frame (vm, node, next_index, n_left_to_next); - } - - return from_frame->n_vectors; -} - -static u8 * -format_lisp_gpe_name (u8 * s, va_list * args) -{ - u32 dev_instance = va_arg (*args, u32); - return format (s, "lisp_gpe%d", dev_instance); -} - -/* *INDENT-OFF* */ -VNET_DEVICE_CLASS (lisp_gpe_device_class) = { - .name = "LISP_GPE", - .format_device_name = format_lisp_gpe_name, - .format_tx_trace = format_lisp_gpe_tx_trace, - .tx_function = lisp_gpe_interface_tx, -}; -/* *INDENT-ON* */ - -u8 * -format_lisp_gpe_header_with_length (u8 * s, va_list * args) -{ - lisp_gpe_header_t *h = va_arg (*args, lisp_gpe_header_t *); - u32 max_header_bytes = va_arg (*args, u32); - u32 header_bytes; - - header_bytes = sizeof (h[0]); - if (max_header_bytes != 0 && header_bytes > max_header_bytes) - return format (s, "lisp-gpe header truncated"); - - s = format (s, "flags: "); -#define _(n,v) if (h->flags & v) s = format (s, "%s ", #n); - foreach_lisp_gpe_flag_bit; -#undef _ - - s = format (s, "\n ver_res %d res %d next_protocol %d iid %d(%x)", - h->ver_res, h->res, h->next_protocol, - clib_net_to_host_u32 (h->iid << 8), - clib_net_to_host_u32 (h->iid << 8)); - return s; -} - -/* *INDENT-OFF* */ -VNET_HW_INTERFACE_CLASS (lisp_gpe_hw_class) = { - .name = "LISP_GPE", - .format_header = format_lisp_gpe_header_with_length, - .build_rewrite = lisp_gpe_build_rewrite, - .update_adjacency = lisp_gpe_update_adjacency, -}; -/* *INDENT-ON* */ - - -typedef struct -{ - u32 dpo_index; -} l2_lisp_gpe_tx_trace_t; - -static u8 * -format_l2_lisp_gpe_tx_trace (u8 * s, va_list * args) -{ - CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *); - CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *); - l2_lisp_gpe_tx_trace_t *t = va_arg (*args, l2_lisp_gpe_tx_trace_t *); - - s = format (s, "L2-LISP-GPE-TX: load-balance %d", t->dpo_index); - return s; -} - -/** - * @brief LISP-GPE interface TX (encap) function for L2 overlays. - * @node l2_lisp_gpe_interface_tx - * - * The L2 LISP-GPE interface TX (encap) function. - * - * Uses bridge domain index, source and destination ethernet addresses to - * lookup tunnel. If the tunnel is multihomed a flow has is used to determine - * the sub-tunnel and therefore the rewrite string to be used to encapsulate - * the packets. - * - * @param[in] vm vlib_main_t corresponding to the current thread. - * @param[in] node vlib_node_runtime_t data for this node. - * @param[in] frame vlib_frame_t whose contents should be dispatched. - * - * @return number of vectors in frame. - */ -static uword -l2_lisp_gpe_interface_tx (vlib_main_t * vm, vlib_node_runtime_t * node, - vlib_frame_t * from_frame) -{ - u32 n_left_from, next_index, *from, *to_next; - lisp_gpe_main_t *lgm = &lisp_gpe_main; - u32 thread_index = vm->thread_index; - vlib_combined_counter_main_t *cm = &load_balance_main.lbm_to_counters; - - from = vlib_frame_vector_args (from_frame); - n_left_from = from_frame->n_vectors; - - next_index = node->cached_next_index; - - while (n_left_from > 0) - { - u32 n_left_to_next; - - vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next); - - while (n_left_from > 0 && n_left_to_next > 0) - { - vlib_buffer_t *b0; - u32 bi0, lbi0; - ethernet_header_t *e0; - - bi0 = from[0]; - to_next[0] = bi0; - from += 1; - to_next += 1; - n_left_from -= 1; - n_left_to_next -= 1; - - b0 = vlib_get_buffer (vm, bi0); - e0 = vlib_buffer_get_current (b0); - - vnet_buffer (b0)->lisp.overlay_afi = LISP_AFI_MAC; - - /* lookup dst + src mac */ - lbi0 = lisp_l2_fib_lookup (lgm, vnet_buffer (b0)->l2.bd_index, - e0->src_address, e0->dst_address); - vnet_buffer (b0)->ip.adj_index[VLIB_TX] = lbi0; - - vlib_increment_combined_counter (cm, thread_index, lbi0, 1, - vlib_buffer_length_in_chain (vm, - b0)); - if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED)) - { - l2_lisp_gpe_tx_trace_t *tr = vlib_add_trace (vm, node, b0, - sizeof (*tr)); - tr->dpo_index = lbi0; - } - vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next, - n_left_to_next, bi0, l2_arc_to_lb); - } - - vlib_put_next_frame (vm, node, next_index, n_left_to_next); - } - - return from_frame->n_vectors; -} - -static u8 * -format_l2_lisp_gpe_name (u8 * s, va_list * args) -{ - u32 dev_instance = va_arg (*args, u32); - return format (s, "l2_lisp_gpe%d", dev_instance); -} - -/* *INDENT-OFF* */ -VNET_DEVICE_CLASS (l2_lisp_gpe_device_class,static) = { - .name = "L2_LISP_GPE", - .format_device_name = format_l2_lisp_gpe_name, - .format_tx_trace = format_l2_lisp_gpe_tx_trace, - .tx_function = l2_lisp_gpe_interface_tx, -}; -/* *INDENT-ON* */ - -typedef struct -{ - u32 dpo_index; -} nsh_lisp_gpe_tx_trace_t; - -u8 * -format_nsh_lisp_gpe_tx_trace (u8 * s, va_list * args) -{ - CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *); - CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *); - nsh_lisp_gpe_tx_trace_t *t = va_arg (*args, nsh_lisp_gpe_tx_trace_t *); - - s = format (s, "NSH-GPE-TX: tunnel %d", t->dpo_index); - return s; -} - -/** - * @brief LISP-GPE interface TX for NSH overlays. - * @node nsh_lisp_gpe_interface_tx - * - * The NSH LISP-GPE interface TX function. - * - * @param[in] vm vlib_main_t corresponding to the current thread. - * @param[in] node vlib_node_runtime_t data for this node. - * @param[in] frame vlib_frame_t whose contents should be dispatched. - * - * @return number of vectors in frame. - */ -static uword -nsh_lisp_gpe_interface_tx (vlib_main_t * vm, vlib_node_runtime_t * node, - vlib_frame_t * from_frame) -{ - u32 n_left_from, next_index, *from, *to_next; - lisp_gpe_main_t *lgm = &lisp_gpe_main; - - from = vlib_frame_vector_args (from_frame); - n_left_from = from_frame->n_vectors; - - next_index = node->cached_next_index; - - while (n_left_from > 0) - { - u32 n_left_to_next; - - vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next); - - while (n_left_from > 0 && n_left_to_next > 0) - { - vlib_buffer_t *b0; - u32 bi0; - u32 *nsh0, next0; - const dpo_id_t *dpo0; - - bi0 = from[0]; - to_next[0] = bi0; - from += 1; - to_next += 1; - n_left_from -= 1; - n_left_to_next -= 1; - - b0 = vlib_get_buffer (vm, bi0); - nsh0 = vlib_buffer_get_current (b0); - - vnet_buffer (b0)->lisp.overlay_afi = LISP_AFI_LCAF; - - /* lookup SPI + SI (second word of the NSH header). - * NB: Load balancing was done by the control plane */ - dpo0 = lisp_nsh_fib_lookup (lgm, nsh0[1]); - - next0 = dpo0->dpoi_next_node; - vnet_buffer (b0)->ip.adj_index[VLIB_TX] = dpo0->dpoi_index; - - if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED)) - { - nsh_lisp_gpe_tx_trace_t *tr = vlib_add_trace (vm, node, b0, - sizeof (*tr)); - tr->dpo_index = dpo0->dpoi_index; - } - vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next, - n_left_to_next, bi0, next0); - } - - vlib_put_next_frame (vm, node, next_index, n_left_to_next); - } - - return from_frame->n_vectors; -} - -static u8 * -format_nsh_lisp_gpe_name (u8 * s, va_list * args) -{ - u32 dev_instance = va_arg (*args, u32); - return format (s, "nsh_lisp_gpe%d", dev_instance); -} - -/* *INDENT-OFF* */ -VNET_DEVICE_CLASS (nsh_lisp_gpe_device_class,static) = { - .name = "NSH_LISP_GPE", - .format_device_name = format_nsh_lisp_gpe_name, - .format_tx_trace = format_nsh_lisp_gpe_tx_trace, - .tx_function = nsh_lisp_gpe_interface_tx, -}; -/* *INDENT-ON* */ - -static vnet_hw_interface_t * -lisp_gpe_create_iface (lisp_gpe_main_t * lgm, u32 vni, u32 dp_table, - vnet_device_class_t * dev_class, - tunnel_lookup_t * tuns) -{ - u32 flen; - u32 hw_if_index = ~0; - u8 *new_name; - vnet_hw_interface_t *hi; - vnet_main_t *vnm = lgm->vnet_main; - - /* create hw lisp_gpeX iface if needed, otherwise reuse existing */ - flen = vec_len (lgm->free_tunnel_hw_if_indices); - if (flen > 0) - { - hw_if_index = lgm->free_tunnel_hw_if_indices[flen - 1]; - _vec_len (lgm->free_tunnel_hw_if_indices) -= 1; - - hi = vnet_get_hw_interface (vnm, hw_if_index); - - /* rename interface */ - new_name = format (0, "%U", dev_class->format_device_name, vni); - - vec_add1 (new_name, 0); - vnet_rename_interface (vnm, hw_if_index, (char *) new_name); - vec_free (new_name); - - /* clear old stats of freed interface before reuse */ - vnet_interface_main_t *im = &vnm->interface_main; - vnet_interface_counter_lock (im); - vlib_zero_combined_counter (&im->combined_sw_if_counters - [VNET_INTERFACE_COUNTER_TX], - hi->sw_if_index); - vlib_zero_combined_counter (&im->combined_sw_if_counters - [VNET_INTERFACE_COUNTER_RX], - hi->sw_if_index); - vlib_zero_simple_counter (&im->sw_if_counters - [VNET_INTERFACE_COUNTER_DROP], - hi->sw_if_index); - vnet_interface_counter_unlock (im); - } - else - { - hw_if_index = vnet_register_interface (vnm, dev_class->index, vni, - lisp_gpe_hw_class.index, 0); - hi = vnet_get_hw_interface (vnm, hw_if_index); - } - - hash_set (tuns->hw_if_index_by_dp_table, dp_table, hw_if_index); - - /* set tunnel termination: post decap, packets are tagged as having been - * originated by lisp-gpe interface */ - hash_set (tuns->sw_if_index_by_vni, vni, hi->sw_if_index); - hash_set (tuns->vni_by_sw_if_index, hi->sw_if_index, vni); - - return hi; -} - -static void -lisp_gpe_remove_iface (lisp_gpe_main_t * lgm, u32 hi_index, u32 dp_table, - tunnel_lookup_t * tuns) -{ - vnet_main_t *vnm = lgm->vnet_main; - vnet_hw_interface_t *hi; - uword *vnip; - - hi = vnet_get_hw_interface (vnm, hi_index); - - /* disable interface */ - vnet_sw_interface_set_flags (vnm, hi->sw_if_index, 0 /* down */ ); - vnet_hw_interface_set_flags (vnm, hi->hw_if_index, 0 /* down */ ); - hash_unset (tuns->hw_if_index_by_dp_table, dp_table); - vec_add1 (lgm->free_tunnel_hw_if_indices, hi->hw_if_index); - - /* clean tunnel termination and vni to sw_if_index binding */ - vnip = hash_get (tuns->vni_by_sw_if_index, hi->sw_if_index); - if (0 == vnip) - { - clib_warning ("No vni associated to interface %d", hi->sw_if_index); - return; - } - hash_unset (tuns->sw_if_index_by_vni, vnip[0]); - hash_unset (tuns->vni_by_sw_if_index, hi->sw_if_index); -} - -static void -lisp_gpe_iface_set_table (u32 sw_if_index, u32 table_id) -{ - fib_node_index_t fib_index; - - fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4, table_id, - FIB_SOURCE_LISP); - vec_validate (ip4_main.fib_index_by_sw_if_index, sw_if_index); - ip4_main.fib_index_by_sw_if_index[sw_if_index] = fib_index; - ip4_sw_interface_enable_disable (sw_if_index, 1); - - fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP6, table_id, - FIB_SOURCE_LISP); - vec_validate (ip6_main.fib_index_by_sw_if_index, sw_if_index); - ip6_main.fib_index_by_sw_if_index[sw_if_index] = fib_index; - ip6_sw_interface_enable_disable (sw_if_index, 1); -} - -static void -lisp_gpe_tenant_del_default_routes (u32 table_id) -{ - fib_protocol_t proto; - - FOR_EACH_FIB_IP_PROTOCOL (proto) - { - fib_prefix_t prefix = { - .fp_proto = proto, - }; - u32 fib_index; - - fib_index = fib_table_find (prefix.fp_proto, table_id); - fib_table_entry_special_remove (fib_index, &prefix, FIB_SOURCE_LISP); - fib_table_unlock (fib_index, prefix.fp_proto, FIB_SOURCE_LISP); - } -} - -static void -lisp_gpe_tenant_add_default_routes (u32 table_id) -{ - fib_protocol_t proto; - - FOR_EACH_FIB_IP_PROTOCOL (proto) - { - fib_prefix_t prefix = { - .fp_proto = proto, - }; - u32 fib_index; - - /* - * Add a deafult route that results in a control plane punt DPO - */ - fib_index = fib_table_find_or_create_and_lock (prefix.fp_proto, table_id, - FIB_SOURCE_LISP); - fib_table_entry_special_dpo_add (fib_index, &prefix, FIB_SOURCE_LISP, - FIB_ENTRY_FLAG_EXCLUSIVE, - lisp_cp_dpo_get (fib_proto_to_dpo - (proto))); - } -} - - -/** - * @brief Add/del LISP-GPE L3 interface. - * - * Creates LISP-GPE interface, sets ingress arcs from lisp_gpeX_lookup, - * installs default routes that attract all traffic with no more specific - * routes to lgpe-ipx-lookup, set egress arcs to ipx-lookup, sets - * the interface in the right vrf and enables it. - * - * @param[in] lgm Reference to @ref lisp_gpe_main_t. - * @param[in] a Parameters to create interface. - * - * @return number of vectors in frame. - */ -u32 -lisp_gpe_add_l3_iface (lisp_gpe_main_t * lgm, u32 vni, u32 table_id, - u8 with_default_routes) -{ - vnet_main_t *vnm = lgm->vnet_main; - tunnel_lookup_t *l3_ifaces = &lgm->l3_ifaces; - vnet_hw_interface_t *hi; - uword *hip, *si; - - hip = hash_get (l3_ifaces->hw_if_index_by_dp_table, table_id); - - if (hip) - { - clib_warning ("vrf %d already mapped to a vni", table_id); - return ~0; - } - - si = hash_get (l3_ifaces->sw_if_index_by_vni, vni); - - if (si) - { - clib_warning ("Interface for vni %d already exists", vni); - } - - /* create lisp iface and populate tunnel tables */ - hi = lisp_gpe_create_iface (lgm, vni, table_id, - &lisp_gpe_device_class, l3_ifaces); - - /* insert default routes that point to lisp-cp lookup */ - lisp_gpe_iface_set_table (hi->sw_if_index, table_id); - if (with_default_routes) - lisp_gpe_tenant_add_default_routes (table_id); - - /* enable interface */ - vnet_sw_interface_set_flags (vnm, hi->sw_if_index, - VNET_SW_INTERFACE_FLAG_ADMIN_UP); - vnet_hw_interface_set_flags (vnm, hi->hw_if_index, - VNET_HW_INTERFACE_FLAG_LINK_UP); - - return (hi->sw_if_index); -} - -void -lisp_gpe_del_l3_iface (lisp_gpe_main_t * lgm, u32 vni, u32 table_id) -{ - vnet_main_t *vnm = lgm->vnet_main; - tunnel_lookup_t *l3_ifaces = &lgm->l3_ifaces; - vnet_hw_interface_t *hi; - uword *hip; - - hip = hash_get (l3_ifaces->hw_if_index_by_dp_table, table_id); - - if (hip == 0) - { - clib_warning ("The interface for vrf %d doesn't exist", table_id); - return; - } - - hi = vnet_get_hw_interface (vnm, hip[0]); - - lisp_gpe_remove_iface (lgm, hip[0], table_id, &lgm->l3_ifaces); - - /* unset default routes */ - ip4_sw_interface_enable_disable (hi->sw_if_index, 0); - ip6_sw_interface_enable_disable (hi->sw_if_index, 0); - lisp_gpe_tenant_del_default_routes (table_id); -} - -/** - * @brief Add/del LISP-GPE L2 interface. - * - * Creates LISP-GPE interface, sets it in L2 mode in the appropriate - * bridge domain, sets egress arcs and enables it. - * - * @param[in] lgm Reference to @ref lisp_gpe_main_t. - * @param[in] a Parameters to create interface. - * - * @return number of vectors in frame. - */ -u32 -lisp_gpe_add_l2_iface (lisp_gpe_main_t * lgm, u32 vni, u32 bd_id) -{ - vnet_main_t *vnm = lgm->vnet_main; - tunnel_lookup_t *l2_ifaces = &lgm->l2_ifaces; - vnet_hw_interface_t *hi; - uword *hip, *si; - u16 bd_index; - - if (bd_id > L2_BD_ID_MAX) - { - clib_warning ("bridge domain ID %d exceed 16M limit", bd_id); - return ~0; - } - - bd_index = bd_find_or_add_bd_index (&bd_main, bd_id); - hip = hash_get (l2_ifaces->hw_if_index_by_dp_table, bd_index); - - if (hip) - { - clib_warning ("bridge domain %d already mapped to a vni", bd_id); - return ~0; - } - - si = hash_get (l2_ifaces->sw_if_index_by_vni, vni); - if (si) - { - clib_warning ("Interface for vni %d already exists", vni); - return ~0; - } - - /* create lisp iface and populate tunnel tables */ - hi = lisp_gpe_create_iface (lgm, vni, bd_index, - &l2_lisp_gpe_device_class, &lgm->l2_ifaces); - - /* enable interface */ - vnet_sw_interface_set_flags (vnm, hi->sw_if_index, - VNET_SW_INTERFACE_FLAG_ADMIN_UP); - vnet_hw_interface_set_flags (vnm, hi->hw_if_index, - VNET_HW_INTERFACE_FLAG_LINK_UP); - - l2_arc_to_lb = vlib_node_add_named_next (vlib_get_main (), - hi->tx_node_index, - "l2-load-balance"); - - /* we're ready. add iface to l2 bridge domain */ - set_int_l2_mode (lgm->vlib_main, vnm, MODE_L2_BRIDGE, hi->sw_if_index, - bd_index, L2_BD_PORT_TYPE_NORMAL, 0, 0); - - return (hi->sw_if_index); -} - -/** - * @brief Add/del LISP-GPE L2 interface. - * - * Creates LISP-GPE interface, sets it in L2 mode in the appropriate - * bridge domain, sets egress arcs and enables it. - * - * @param[in] lgm Reference to @ref lisp_gpe_main_t. - * @param[in] a Parameters to create interface. - * - * @return number of vectors in frame. - */ -void -lisp_gpe_del_l2_iface (lisp_gpe_main_t * lgm, u32 vni, u32 bd_id) -{ - tunnel_lookup_t *l2_ifaces = &lgm->l2_ifaces; - vnet_hw_interface_t *hi; - - u32 bd_index = bd_find_index (&bd_main, bd_id); - ASSERT (bd_index != ~0); - uword *hip = hash_get (l2_ifaces->hw_if_index_by_dp_table, bd_index); - - if (hip == 0) - { - clib_warning ("The interface for bridge domain %d doesn't exist", - bd_id); - return; - } - - /* Remove interface from bridge .. by enabling L3 mode */ - hi = vnet_get_hw_interface (lgm->vnet_main, hip[0]); - set_int_l2_mode (lgm->vlib_main, lgm->vnet_main, MODE_L3, hi->sw_if_index, - 0, L2_BD_PORT_TYPE_NORMAL, 0, 0); - lisp_gpe_remove_iface (lgm, hip[0], bd_index, &lgm->l2_ifaces); -} - -/** - * @brief Add LISP-GPE NSH interface. - * - * Creates LISP-GPE interface, sets it in L3 mode. - * - * @param[in] lgm Reference to @ref lisp_gpe_main_t. - * @param[in] a Parameters to create interface. - * - * @return sw_if_index. - */ -u32 -vnet_lisp_gpe_add_nsh_iface (lisp_gpe_main_t * lgm) -{ - vnet_main_t *vnm = lgm->vnet_main; - tunnel_lookup_t *nsh_ifaces = &lgm->nsh_ifaces; - vnet_hw_interface_t *hi; - uword *hip, *si; - - hip = hash_get (nsh_ifaces->hw_if_index_by_dp_table, 0); - - if (hip) - { - clib_warning ("NSH interface 0 already exists"); - return ~0; - } - - si = hash_get (nsh_ifaces->sw_if_index_by_vni, 0); - if (si) - { - clib_warning ("NSH interface already exists"); - return ~0; - } - - /* create lisp iface and populate tunnel tables */ - hi = lisp_gpe_create_iface (lgm, 0, 0, - &nsh_lisp_gpe_device_class, &lgm->nsh_ifaces); - - /* enable interface */ - vnet_sw_interface_set_flags (vnm, hi->sw_if_index, - VNET_SW_INTERFACE_FLAG_ADMIN_UP); - vnet_hw_interface_set_flags (vnm, hi->hw_if_index, - VNET_HW_INTERFACE_FLAG_LINK_UP); - - return (hi->sw_if_index); -} - -/** - * @brief Del LISP-GPE NSH interface. - * - */ -void -vnet_lisp_gpe_del_nsh_iface (lisp_gpe_main_t * lgm) -{ - tunnel_lookup_t *nsh_ifaces = &lgm->nsh_ifaces; - uword *hip; - - hip = hash_get (nsh_ifaces->hw_if_index_by_dp_table, 0); - - if (hip == 0) - { - clib_warning ("The NSH 0 interface doesn't exist"); - return; - } - lisp_gpe_remove_iface (lgm, hip[0], 0, &lgm->nsh_ifaces); -} - -static clib_error_t * -lisp_gpe_add_del_iface_command_fn (vlib_main_t * vm, unformat_input_t * input, - vlib_cli_command_t * cmd) -{ - unformat_input_t _line_input, *line_input = &_line_input; - u8 is_add = 1; - u32 table_id, vni, bd_id; - u8 vni_is_set = 0, vrf_is_set = 0, bd_index_is_set = 0; - u8 nsh_iface = 0; - clib_error_t *error = NULL; - - if (vnet_lisp_gpe_enable_disable_status () == 0) - { - return clib_error_return (0, "LISP is disabled"); - } - - /* 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, "add")) - is_add = 1; - else if (unformat (line_input, "del")) - is_add = 0; - else if (unformat (line_input, "vrf %d", &table_id)) - { - vrf_is_set = 1; - } - else if (unformat (line_input, "vni %d", &vni)) - { - vni_is_set = 1; - } - else if (unformat (line_input, "bd %d", &bd_id)) - { - bd_index_is_set = 1; - } - else if (unformat (line_input, "nsh")) - { - nsh_iface = 1; - } - else - { - error = clib_error_return (0, "parse error: '%U'", - format_unformat_error, line_input); - goto done; - } - } - - if (nsh_iface) - { - if (is_add) - { - if (~0 == vnet_lisp_gpe_add_nsh_iface (&lisp_gpe_main)) - { - error = clib_error_return (0, "NSH interface not created"); - goto done; - } - } - else - { - vnet_lisp_gpe_del_nsh_iface (&lisp_gpe_main); - } - goto done; - } - - if (vrf_is_set && bd_index_is_set) - { - error = clib_error_return - (0, "Cannot set both vrf and brdige domain index!"); - goto done; - } - - if (!vni_is_set) - { - error = clib_error_return (0, "vni must be set!"); - goto done; - } - - if (!vrf_is_set && !bd_index_is_set) - { - error = - clib_error_return (0, "vrf or bridge domain index must be set!"); - goto done; - } - - if (bd_index_is_set) - { - if (is_add) - { - if (~0 == lisp_gpe_tenant_l2_iface_add_or_lock (vni, bd_id)) - { - error = clib_error_return (0, "L2 interface not created"); - goto done; - } - } - else - lisp_gpe_tenant_l2_iface_unlock (vni); - } - else - { - if (is_add) - { - if (~0 == lisp_gpe_tenant_l3_iface_add_or_lock (vni, table_id, 1 - /* with_default_route */ - )) - { - error = clib_error_return (0, "L3 interface not created"); - goto done; - } - } - else - lisp_gpe_tenant_l3_iface_unlock (vni); - } - -done: - unformat_free (line_input); - - return error; -} - -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND (add_del_lisp_gpe_iface_command, static) = { - .path = "gpe iface", - .short_help = "gpe iface add/del vni <vni> vrf <vrf>", - .function = lisp_gpe_add_del_iface_command_fn, -}; -/* *INDENT-ON* */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/vnet/lisp-gpe/lisp_gpe.api b/src/vnet/lisp-gpe/lisp_gpe.api deleted file mode 100644 index 6c751eabffb..00000000000 --- a/src/vnet/lisp-gpe/lisp_gpe.api +++ /dev/null @@ -1,237 +0,0 @@ -/* - * Copyright (c) 2015-2016 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. - */ - -option version = "2.0.0"; - -import "vnet/interface_types.api"; -import "vnet/lisp-cp/lisp_types.api"; - -/** \brief GPE locator structure - @param is_ip4 - whether addr is IPv4 or v6 - @param weight - locator weight - @param addr - IPv4/6 address -*/ -typedef gpe_locator -{ - u8 weight; - vl_api_address_t addr; -}; - -/** \brief add or delete GPE tunnel - @param client_index - opaque cookie to identify the sender - @param context - sender context, to match reply w/ request - @param is_add - add address if non-zero, else delete - @param rmt_eid - remote eid - @param lcl_eid - local eid - @param vni - virtual network identifier - @param dp_table - vrf/bridge domain id - @param action - negative action when 0 locators configured - @param loc_num - number of locators - @param locs - array of remote locators -*/ -manual_print manual_endian define gpe_add_del_fwd_entry -{ - u32 client_index; - u32 context; - bool is_add [default=true]; - vl_api_eid_t rmt_eid; - vl_api_eid_t lcl_eid; - u32 vni; - u32 dp_table; - u8 action; - u32 loc_num; - vl_api_gpe_locator_t locs[loc_num]; -}; - -define gpe_add_del_fwd_entry_reply -{ - u32 context; - i32 retval; - u32 fwd_entry_index; -}; - -/** \brief enable or disable gpe protocol - @param client_index - opaque cookie to identify the sender - @param context - sender context, to match reply w/ request - @param is_enable [default=true] - enable protocol if non-zero, else disable -*/ -autoreply define gpe_enable_disable -{ - u32 client_index; - u32 context; - bool is_enable [default=true]; -}; - -/** \brief add or delete gpe_iface - @param client_index - opaque cookie to identify the sender - @param context - sender context, to match reply w/ request - @param is_add - add address if non-zero, else delete -*/ -autoreply define gpe_add_del_iface -{ - u32 client_index; - u32 context; - bool is_add [default=true]; - bool is_l2; - u32 dp_table; - u32 vni; -}; - -define gpe_fwd_entry_vnis_get -{ - u32 client_index; - u32 context; -}; - -manual_print manual_endian define gpe_fwd_entry_vnis_get_reply -{ - u32 context; - i32 retval; - u32 count; - u32 vnis[count]; -}; - -define gpe_fwd_entries_get -{ - u32 client_index; - u32 context; - u32 vni; -}; - -typedef gpe_fwd_entry -{ - u32 fwd_entry_index; - u32 dp_table; - vl_api_eid_t leid; - vl_api_eid_t reid; - u32 vni; - u8 action; -}; - -manual_print manual_endian define gpe_fwd_entries_get_reply -{ - u32 context; - i32 retval; - u32 count; - vl_api_gpe_fwd_entry_t entries[count]; -}; - -define gpe_fwd_entry_path_dump -{ - u32 client_index; - u32 context; - u32 fwd_entry_index; -}; - -manual_endian manual_print define gpe_fwd_entry_path_details -{ - u32 context; - vl_api_gpe_locator_t lcl_loc; - vl_api_gpe_locator_t rmt_loc; -}; - -/** \brief Set GPE encapsulation mode - @param client_index - opaque cookie to identify the sender - @param context - sender context, to match reply w/ request - @param mode - LISP (value 0) or VXLAN (value 1) -*/ -autoreply define gpe_set_encap_mode -{ - u32 client_index; - u32 context; - bool is_vxlan; -}; - -/** \brief get GPE encapsulation mode - @param client_index - opaque cookie to identify the sender - @param context - sender context, to match reply w/ request - @param mode - LISP (value 0) or VXLAN (value 1) -*/ -define gpe_get_encap_mode -{ - u32 client_index; - u32 context; -}; - -/** \brief Reply for set_encap_mode - @param context - returned sender context, to match reply w/ request - @param retval - return code - @param encap_mode - GPE encapsulation mode -*/ -define gpe_get_encap_mode_reply -{ - u32 context; - i32 retval; - /* FIXME: gpe encap enum */ - u8 encap_mode; -}; - -/** \brief Add native fwd rpath - @param context - returned sender context, to match reply w/ request - @param retval - return code - @param is_add - flag to indicate add or del - @param table_id - table id for route path - @param nh_sw_if_index - next-hop sw_if_index (~0 if not set) - @param is_ip4 - flag to indicate if nh is ip4 - @param nh_addr - next hop ip address -*/ -autoreply define gpe_add_del_native_fwd_rpath -{ - u32 client_index; - u32 context; - bool is_add [default=true]; - u32 table_id; - vl_api_interface_index_t nh_sw_if_index; - vl_api_address_t nh_addr; -}; - -/** \brief get GPE native fwd rpath - @param client_index - opaque cookie to identify the sender - @param context - sender context, to match reply w/ request -*/ -define gpe_native_fwd_rpaths_get -{ - u32 client_index; - u32 context; - bool is_ip4; -}; - -/** \brief Reply for get native fwd rpath - @param context - returned sender context, to match reply w/ request - @param retval - return code - @param table_id - table id for route path - @param nh_sw_if_index - next-hop sw_if_index (~0 if not set) - @param nh_addr - next hop address -*/ -typedef gpe_native_fwd_rpath -{ - u32 fib_index; - vl_api_interface_index_t nh_sw_if_index; - vl_api_address_t nh_addr; -}; - -manual_print manual_endian define gpe_native_fwd_rpaths_get_reply -{ - u32 context; - i32 retval; - u32 count; - vl_api_gpe_native_fwd_rpath_t entries[count]; -}; - -/* - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/vnet/lisp-gpe/lisp_gpe.c b/src/vnet/lisp-gpe/lisp_gpe.c deleted file mode 100644 index c75ad6b87cd..00000000000 --- a/src/vnet/lisp-gpe/lisp_gpe.c +++ /dev/null @@ -1,728 +0,0 @@ -/* - * Copyright (c) 2016 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. - */ -/** - * @file - * @brief Common utility functions for IPv4, IPv6 and L2 LISP-GPE tunnels. - * - */ - -#include <vnet/lisp-gpe/lisp_gpe.h> -#include <vnet/lisp-gpe/lisp_gpe_fwd_entry.h> -#include <vnet/lisp-gpe/lisp_gpe_adjacency.h> -#include <vnet/lisp-gpe/lisp_gpe_tenant.h> -#include <vnet/fib/fib_path_list.h> -#include <vnet/fib/fib_table.h> -#include <vnet/fib/fib_internal.h> - -/** LISP-GPE global state */ -lisp_gpe_main_t lisp_gpe_main; - - -/** CLI command to add/del forwarding entry. */ -static clib_error_t * -lisp_gpe_add_del_fwd_entry_command_fn (vlib_main_t * vm, - unformat_input_t * input, - vlib_cli_command_t * cmd) -{ - unformat_input_t _line_input, *line_input = &_line_input; - u8 is_add = 1; - ip_address_t lloc, rloc; - clib_error_t *error = 0; - gid_address_t _reid, *reid = &_reid, _leid, *leid = &_leid; - u8 reid_set = 0, leid_set = 0, is_negative = 0, dp_table_set = 0, - vni_set = 0; - u32 vni = 0, dp_table = 0, action = ~0, w; - locator_pair_t pair, *pairs = 0; - int rv; - - clib_memset (leid, 0, sizeof (*leid)); - clib_memset (reid, 0, sizeof (*reid)); - - /* 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, "add")) - is_add = 1; - else if (unformat (line_input, "leid %U", unformat_gid_address, leid)) - { - leid_set = 1; - } - else if (unformat (line_input, "reid %U", unformat_gid_address, reid)) - { - reid_set = 1; - } - else if (unformat (line_input, "vni %u", &vni)) - { - gid_address_vni (leid) = vni; - gid_address_vni (reid) = vni; - vni_set = 1; - } - else if (unformat (line_input, "vrf %u", &dp_table)) - { - dp_table_set = 1; - } - else if (unformat (line_input, "bd %u", &dp_table)) - { - dp_table_set = 1; - } - else if (unformat (line_input, "negative action %U", - unformat_negative_mapping_action, &action)) - { - is_negative = 1; - } - else if (unformat (line_input, "loc-pair %U %U w %d", - unformat_ip_address, &lloc, - unformat_ip_address, &rloc, &w)) - { - ip_address_copy (&pair.lcl_loc, &lloc); - ip_address_copy (&pair.rmt_loc, &rloc); - pair.weight = w; - pair.priority = 0; - vec_add1 (pairs, pair); - } - else - { - error = unformat_parse_error (line_input); - vlib_cli_output (vm, "parse error: '%U'", - format_unformat_error, line_input); - goto done; - } - } - - if (!reid_set) - { - vlib_cli_output (vm, "remote eid must be set!"); - goto done; - } - - if (gid_address_type (reid) != GID_ADDR_NSH && (!vni_set || !dp_table_set)) - { - vlib_cli_output (vm, "vni and vrf/bd must be set!"); - goto done; - } - - if (is_negative) - { - if (~0 == action) - { - vlib_cli_output (vm, "no action set for negative tunnel!"); - goto done; - } - } - else - { - if (vec_len (pairs) == 0) - { - vlib_cli_output (vm, "expected ip4/ip6 locators"); - goto done; - } - } - - if (!leid_set) - { - /* if leid not set, make sure it's the same AFI like reid */ - gid_address_type (leid) = gid_address_type (reid); - if (GID_ADDR_IP_PREFIX == gid_address_type (reid)) - gid_address_ip_version (leid) = gid_address_ip_version (reid); - } - - /* add fwd entry */ - vnet_lisp_gpe_add_del_fwd_entry_args_t _a, *a = &_a; - clib_memset (a, 0, sizeof (a[0])); - - a->is_add = is_add; - a->is_negative = is_negative; - a->vni = vni; - a->table_id = dp_table; - gid_address_copy (&a->lcl_eid, leid); - gid_address_copy (&a->rmt_eid, reid); - a->locator_pairs = pairs; - a->action = action; - - rv = vnet_lisp_gpe_add_del_fwd_entry (a, 0); - if (0 != rv) - { - vlib_cli_output (vm, "failed to %s gpe tunnel!", - is_add ? "add" : "delete"); - } - -done: - unformat_free (line_input); - vec_free (pairs); - return error; -} - -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND (lisp_gpe_add_del_fwd_entry_command, static) = { - .path = "gpe entry", - .short_help = "gpe entry add/del vni <vni> vrf/bd <id> [leid <leid>]" - "reid <reid> [loc-pair <lloc> <rloc> w <weight>] " - "[negative action <action>]", - .function = lisp_gpe_add_del_fwd_entry_command_fn, -}; -/* *INDENT-ON* */ - -/** Check if LISP-GPE is enabled. */ -u8 -vnet_lisp_gpe_enable_disable_status (void) -{ - lisp_gpe_main_t *lgm = &lisp_gpe_main; - - return lgm->is_en; -} - -/** Enable/disable LISP-GPE. */ -clib_error_t * -vnet_lisp_gpe_enable_disable (vnet_lisp_gpe_enable_disable_args_t * a) -{ - lisp_gpe_main_t *lgm = &lisp_gpe_main; - vlib_main_t *vm = vlib_get_main (); - - if (a->is_en) - { - lgm->is_en = 1; - udp_register_dst_port (vm, UDP_DST_PORT_lisp_gpe, - lisp_gpe_ip4_input_node.index, 1 /* is_ip4 */ ); - udp_register_dst_port (vm, UDP_DST_PORT_lisp_gpe6, - lisp_gpe_ip6_input_node.index, 0 /* is_ip4 */ ); - } - else - { - /* remove all entries */ - vnet_lisp_gpe_fwd_entry_flush (); - - /* disable all l3 ifaces */ - lisp_gpe_tenant_flush (); - - udp_unregister_dst_port (vm, UDP_DST_PORT_lisp_gpe, 0 /* is_ip4 */ ); - udp_unregister_dst_port (vm, UDP_DST_PORT_lisp_gpe6, 1 /* is_ip4 */ ); - lgm->is_en = 0; - } - - return 0; -} - -/** Set GPE encapsulation mode. */ -int -vnet_gpe_set_encap_mode (gpe_encap_mode_t mode) -{ - lisp_gpe_main_t *lgm = &lisp_gpe_main; - - if (mode >= GPE_ENCAP_COUNT) - return VNET_API_ERROR_INVALID_GPE_MODE; - - if (pool_elts (lgm->lisp_fwd_entry_pool) != 0) - return VNET_API_ERROR_LISP_GPE_ENTRIES_PRESENT; - - lgm->encap_mode = mode; - return 0; -} - -/** CLI command to set GPE encap */ -static clib_error_t * -gpe_set_encap_mode_command_fn (vlib_main_t * vm, - unformat_input_t * input, - vlib_cli_command_t * cmd) -{ - unformat_input_t _line_input, *line_input = &_line_input; - gpe_encap_mode_t mode = GPE_ENCAP_COUNT; - vnet_api_error_t 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, "lisp")) - mode = GPE_ENCAP_LISP; - else if (unformat (line_input, "vxlan")) - mode = GPE_ENCAP_VXLAN; - else - { - return clib_error_return (0, "parse error: '%U'", - format_unformat_error, line_input); - } - } - rv = vnet_gpe_set_encap_mode (mode); - if (rv) - { - return clib_error_return (0, - "Error: invalid mode or GPE entries are present!"); - } - - return 0; -} - -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND (gpe_set_encap_mode_command, static) = { - .path = "gpe encap", - .short_help = "gpe encap [lisp|vxlan]", - .function = gpe_set_encap_mode_command_fn, -}; -/* *INDENT-ON* */ - -/** Format GPE encap mode. */ -u8 * -format_vnet_gpe_encap_mode (u8 * s, va_list * args) -{ - lisp_gpe_main_t *lgm = &lisp_gpe_main; - - switch (lgm->encap_mode) - { - case GPE_ENCAP_LISP: - return format (s, "lisp"); - case GPE_ENCAP_VXLAN: - return format (s, "vxlan"); - default: - return 0; - } - return 0; -} - -/** CLI command to show GPE encap */ -static clib_error_t * -gpe_show_encap_mode_command_fn (vlib_main_t * vm, - unformat_input_t * input, - vlib_cli_command_t * cmd) -{ - vlib_cli_output (vm, "encap mode: %U", format_vnet_gpe_encap_mode); - return 0; -} - -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND (gpe_show_encap_mode_command, static) = { - .path = "show gpe encap", - .short_help = "show GPE encapulation mode", - .function = gpe_show_encap_mode_command_fn, -}; -/* *INDENT-ON* */ - -/** CLI command to enable/disable LISP-GPE. */ -static clib_error_t * -lisp_gpe_enable_disable_command_fn (vlib_main_t * vm, - unformat_input_t * input, - vlib_cli_command_t * cmd) -{ - unformat_input_t _line_input, *line_input = &_line_input; - u8 is_en = 1; - vnet_lisp_gpe_enable_disable_args_t _a, *a = &_a; - clib_error_t *error = NULL; - - /* Get a line of input. */ - if (!unformat_user (input, unformat_line_input, line_input)) - return clib_error_return (0, "expected enable | disable"); - - while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) - { - if (unformat (line_input, "enable")) - is_en = 1; - else if (unformat (line_input, "disable")) - is_en = 0; - else - { - error = clib_error_return (0, "parse error: '%U'", - format_unformat_error, line_input); - goto done; - } - } - a->is_en = is_en; - error = vnet_lisp_gpe_enable_disable (a); - -done: - unformat_free (line_input); - - return error; -} - -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND (enable_disable_lisp_gpe_command, static) = { - .path = "gpe", - .short_help = "gpe [enable|disable]", - .function = lisp_gpe_enable_disable_command_fn, -}; -/* *INDENT-ON* */ - -/** CLI command to show LISP-GPE interfaces. */ -static clib_error_t * -lisp_show_iface_command_fn (vlib_main_t * vm, - unformat_input_t * input, - vlib_cli_command_t * cmd) -{ - lisp_gpe_main_t *lgm = &lisp_gpe_main; - hash_pair_t *p; - - vlib_cli_output (vm, "%=10s%=12s", "vrf", "hw_if_index"); - - /* *INDENT-OFF* */ - hash_foreach_pair (p, lgm->l3_ifaces.hw_if_index_by_dp_table, ({ - vlib_cli_output (vm, "%=10d%=10d", p->key, p->value[0]); - })); - /* *INDENT-ON* */ - - if (0 != lgm->l2_ifaces.hw_if_index_by_dp_table) - { - vlib_cli_output (vm, "%=10s%=12s", "bd_id", "hw_if_index"); - /* *INDENT-OFF* */ - hash_foreach_pair (p, lgm->l2_ifaces.hw_if_index_by_dp_table, ({ - vlib_cli_output (vm, "%=10d%=10d", p->key, p->value[0]); - })); - /* *INDENT-ON* */ - } - return 0; -} - -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND (lisp_show_iface_command) = { - .path = "show gpe interface", - .short_help = "show gpe interface", - .function = lisp_show_iface_command_fn, -}; -/* *INDENT-ON* */ - -/** CLI command to show GPE fwd native route path. */ -static clib_error_t * -gpe_show_native_fwd_rpath_command_fn (vlib_main_t * vm, - unformat_input_t * input, - vlib_cli_command_t * cmd) -{ - lisp_gpe_main_t *lgm = &lisp_gpe_main; - fib_route_path_t *rpath; - - if (vec_len (lgm->native_fwd_rpath[AF_IP4])) - { - vec_foreach (rpath, lgm->native_fwd_rpath[AF_IP4]) - { - vlib_cli_output (vm, "nh: %U fib_index %u sw_if_index %u", - format_ip46_address, &rpath->frp_addr, - IP46_TYPE_IP4, rpath->frp_fib_index, - rpath->frp_sw_if_index); - } - } - if (vec_len (lgm->native_fwd_rpath[AF_IP6])) - { - vec_foreach (rpath, lgm->native_fwd_rpath[AF_IP6]) - { - vlib_cli_output (vm, "nh: %U fib_index %u sw_if_index %u", - format_ip46_address, &rpath->frp_addr, IP46_TYPE_IP6, - rpath->frp_fib_index, rpath->frp_sw_if_index); - } - } - return 0; -} - -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND (gpe_show_native_fwd_rpath_command) = { - .path = "show gpe native-forward", - .short_help = "show gpe native-forward", - .function = gpe_show_native_fwd_rpath_command_fn, -}; -/* *INDENT-ON* */ - -void -gpe_update_native_fwd_path (u8 ip_version) -{ - lisp_gpe_main_t *lgm = vnet_lisp_gpe_get_main (); - lisp_gpe_fwd_entry_t *lfe; - fib_prefix_t fib_prefix; - u32 *lfei; - - vec_foreach (lfei, lgm->native_fwd_lfes[ip_version]) - { - lfe = pool_elt_at_index (lgm->lisp_fwd_entry_pool, lfei[0]); - ip_prefix_to_fib_prefix (&lfe->key->rmt.ippref, &fib_prefix); - fib_table_entry_update (lfe->eid_fib_index, &fib_prefix, FIB_SOURCE_LISP, - FIB_ENTRY_FLAG_NONE, - lgm->native_fwd_rpath[ip_version]); - } -} - -int -vnet_gpe_add_del_native_fwd_rpath (vnet_gpe_native_fwd_rpath_args_t * a) -{ - lisp_gpe_main_t *lgm = vnet_lisp_gpe_get_main (); - fib_route_path_t *rpath; - u8 ip_version; - - ip_version = a->rpath.frp_proto == DPO_PROTO_IP4 ? AF_IP4 : AF_IP6; - - if (a->is_add) - { - vec_add1 (lgm->native_fwd_rpath[ip_version], a->rpath); - } - else - { - vec_foreach (rpath, lgm->native_fwd_rpath[ip_version]) - { - if (!fib_route_path_cmp (rpath, &a->rpath)) - { - vec_del1 (lgm->native_fwd_rpath[ip_version], - rpath - lgm->native_fwd_rpath[ip_version]); - break; - } - } - } - gpe_update_native_fwd_path (ip_version); - return 0; -} - -/** - * CLI command to add action for native forward. - */ -static clib_error_t * -gpe_native_forward_command_fn (vlib_main_t * vm, unformat_input_t * input, - vlib_cli_command_t * cmd) -{ - vnet_main_t *vnm = vnet_get_main (); - unformat_input_t _line_input, *line_input = &_line_input; - vnet_api_error_t rv; - fib_route_path_t rpath; - u32 table_id = ~0; - vnet_gpe_native_fwd_rpath_args_t _a, *a = &_a; - u8 is_add = 1; - clib_error_t *error = 0; - - /* Get a line of input. */ - if (!unformat_user (input, unformat_line_input, line_input)) - return 0; - - clib_memset (&rpath, 0, sizeof (rpath)); - - while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) - { - if (unformat (line_input, "table %d", &table_id)) - ; - else if (unformat (line_input, "del")) - is_add = 0; - else if (unformat (line_input, "via %U %U", - unformat_ip4_address, - &rpath.frp_addr.ip4, - unformat_vnet_sw_interface, vnm, - &rpath.frp_sw_if_index)) - { - rpath.frp_weight = 1; - rpath.frp_proto = DPO_PROTO_IP4; - } - else if (unformat (line_input, "via %U %U", - unformat_ip6_address, - &rpath.frp_addr.ip6, - unformat_vnet_sw_interface, vnm, - &rpath.frp_sw_if_index)) - { - rpath.frp_weight = 1; - rpath.frp_proto = DPO_PROTO_IP6; - } - else if (unformat (line_input, "via %U", - unformat_ip4_address, &rpath.frp_addr.ip4)) - { - rpath.frp_weight = 1; - rpath.frp_sw_if_index = ~0; - rpath.frp_proto = DPO_PROTO_IP4; - } - else if (unformat (line_input, "via %U", - unformat_ip6_address, &rpath.frp_addr.ip6)) - { - rpath.frp_weight = 1; - rpath.frp_sw_if_index = ~0; - rpath.frp_proto = DPO_PROTO_IP6; - } - else - { - return clib_error_return (0, "parse error: '%U'", - format_unformat_error, line_input); - } - } - - if ((u32) ~ 0 == table_id) - { - rpath.frp_fib_index = 0; - } - else - { - rpath.frp_fib_index = - fib_table_find (dpo_proto_to_fib (rpath.frp_proto), table_id); - if ((u32) ~ 0 == rpath.frp_fib_index) - { - error = clib_error_return (0, "Nonexistent table id %d", table_id); - goto done; - } - } - - a->rpath = rpath; - a->is_add = is_add; - - rv = vnet_gpe_add_del_native_fwd_rpath (a); - if (rv) - { - return clib_error_return (0, "Error: couldn't add path!"); - } - -done: - return error; -} - -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND (gpe_native_forward_command) = { - .path = "gpe native-forward", - .short_help = "gpe native-forward [del] via <nh-ip-addr> [iface] " - "[table <table>]", - .function = gpe_native_forward_command_fn, -}; -/* *INDENT-ON* */ - -/** Format LISP-GPE status. */ -u8 * -format_vnet_lisp_gpe_status (u8 * s, va_list * args) -{ - lisp_gpe_main_t *lgm = &lisp_gpe_main; - return format (s, "%s", lgm->is_en ? "enabled" : "disabled"); -} - -/** LISP-GPE init function. */ -clib_error_t * -lisp_gpe_init (vlib_main_t * vm) -{ - lisp_gpe_main_t *lgm = &lisp_gpe_main; - clib_error_t *error = 0; - - if ((error = vlib_call_init_function (vm, ip_main_init))) - return error; - - if ((error = vlib_call_init_function (vm, ip4_lookup_init))) - return error; - - lgm->vnet_main = vnet_get_main (); - lgm->vlib_main = vm; - lgm->im4 = &ip4_main; - lgm->im6 = &ip6_main; - lgm->lm4 = &ip4_main.lookup_main; - lgm->lm6 = &ip6_main.lookup_main; - lgm->encap_mode = GPE_ENCAP_LISP; - - lgm->lisp_gpe_fwd_entries = - hash_create_mem (0, sizeof (lisp_gpe_fwd_entry_key_t), sizeof (uword)); - - lgm->lisp_stats_index_by_key = - hash_create_mem (0, sizeof (lisp_stats_key_t), sizeof (uword)); - clib_memset (&lgm->counters, 0, sizeof (lgm->counters)); - lgm->counters.name = "LISP counters"; - - return 0; -} - -gpe_encap_mode_t -vnet_gpe_get_encap_mode (void) -{ - lisp_gpe_main_t *lgm = &lisp_gpe_main; - return lgm->encap_mode; -} - -static clib_error_t * -lisp_gpe_test_send_nsh_packet (u8 * file_name) -{ - vlib_frame_t *f; - vlib_buffer_t *b; - lisp_gpe_main_t *lgm = vnet_lisp_gpe_get_main (); - pcap_main_t pm; - clib_error_t *error = 0; - - if (!file_name) - return clib_error_create ("no pcap file specified!"); - - clib_memset (&pm, 0, sizeof (pm)); - pm.file_name = (char *) file_name; - error = pcap_read (&pm); - if (error) - return error; - - u32 bi; - if (vlib_buffer_alloc (lgm->vlib_main, &bi, 1) != 1) - return clib_error_create ("cannot allocate memory!"); - - b = vlib_get_buffer (lgm->vlib_main, bi); - tunnel_lookup_t *nsh_ifaces = &lgm->nsh_ifaces; - uword *hip; - vnet_hw_interface_t *hi; - - hip = hash_get (nsh_ifaces->hw_if_index_by_dp_table, 0); - if (hip == 0) - return clib_error_create ("The NSH 0 interface doesn't exist"); - - hi = vnet_get_hw_interface (lgm->vnet_main, hip[0]); - - vnet_buffer (b)->sw_if_index[VLIB_TX] = hi->sw_if_index; - u8 *p = vlib_buffer_put_uninit (b, vec_len (pm.packets_read[0])); - clib_memcpy_fast (p, pm.packets_read[0], vec_len (pm.packets_read[0])); - vlib_buffer_pull (b, sizeof (ethernet_header_t)); - - vlib_node_t *n = vlib_get_node_by_name (lgm->vlib_main, - (u8 *) "interface-tx"); - f = vlib_get_frame_to_node (lgm->vlib_main, n->index); - u32 *to_next = vlib_frame_vector_args (f); - to_next[0] = bi; - f->n_vectors = 1; - vlib_put_frame_to_node (lgm->vlib_main, n->index, f); - - return error; -} - -static clib_error_t * -lisp_test_nsh_command_fn (vlib_main_t * vm, unformat_input_t * input, - vlib_cli_command_t * cmd) -{ - clib_error_t *error = 0; - u8 *file_name = 0; - - while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) - { - if (unformat (input, "pcap %v", &file_name)) - { - error = lisp_gpe_test_send_nsh_packet (file_name); - goto done; - } - else - { - error = clib_error_create ("unknown input `%U'", - format_unformat_error, input); - goto done; - } - } - -done: - return error; -} - -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND (lisp_test_nsh_command, static) = { - .path = "test one nsh", - .short_help = "test gpe nsh pcap <path-to-pcap-file>", - .function = lisp_test_nsh_command_fn, -}; -/* *INDENT-ON* */ - -VLIB_INIT_FUNCTION (lisp_gpe_init); - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/vnet/lisp-gpe/lisp_gpe.h b/src/vnet/lisp-gpe/lisp_gpe.h deleted file mode 100644 index 3a3d0e9f4da..00000000000 --- a/src/vnet/lisp-gpe/lisp_gpe.h +++ /dev/null @@ -1,339 +0,0 @@ -/* - * Copyright (c) 2016 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. - */ -/** - * @file - * @brief LISP-GPE definitions. - */ - -#ifndef included_vnet_lisp_gpe_h -#define included_vnet_lisp_gpe_h - -#include <vppinfra/error.h> -#include <vppinfra/mhash.h> -#include <vnet/vnet.h> -#include <vnet/ip/ip.h> -#include <vnet/l2/l2_input.h> -#include <vnet/ethernet/ethernet.h> -#include <vnet/ip/ip4_packet.h> -#include <vnet/udp/udp.h> -#include <vnet/lisp-cp/lisp_types.h> -#include <vnet/lisp-gpe/lisp_gpe_packet.h> -#include <vnet/adj/adj_types.h> -#include <vppinfra/bihash_24_8.h> -#include <vppinfra/bihash_template.h> - -/** IP4-UDP-LISP encap header */ -/* *INDENT-OFF* */ -typedef CLIB_PACKED (struct { - ip4_header_t ip4; /* 20 bytes */ - udp_header_t udp; /* 8 bytes */ - lisp_gpe_header_t lisp; /* 8 bytes */ -}) ip4_udp_lisp_gpe_header_t; -/* *INDENT-ON* */ - -/** IP6-UDP-LISP encap header */ -/* *INDENT-OFF* */ -typedef CLIB_PACKED (struct { - ip6_header_t ip6; /* 40 bytes */ - udp_header_t udp; /* 8 bytes */ - lisp_gpe_header_t lisp; /* 8 bytes */ -}) ip6_udp_lisp_gpe_header_t; -/* *INDENT-ON* */ - -#define foreach_lisp_gpe_ip_input_next \ -_(DROP, "error-drop") \ -_(IP4_INPUT, "ip4-input") \ -_(IP6_INPUT, "ip6-input") \ -_(L2_INPUT, "l2-input") - -/** Enum of possible next nodes post LISP-GPE decap */ -typedef enum -{ -#define _(s,n) LISP_GPE_INPUT_NEXT_##s, - foreach_lisp_gpe_ip_input_next -#undef _ - LISP_GPE_INPUT_N_NEXT, -} lisp_gpe_input_next_t; - -/* Arc to nsh-input added only if nsh-input exists */ -#define LISP_GPE_INPUT_NEXT_NSH_INPUT 4 - -typedef enum -{ -#define lisp_gpe_error(n,s) LISP_GPE_ERROR_##n, -#include <vnet/lisp-gpe/lisp_gpe_error.def> -#undef lisp_gpe_error - LISP_GPE_N_ERROR, -} lisp_gpe_error_t; - -typedef struct tunnel_lookup -{ - /** Lookup lisp-gpe interfaces by dp table (eg. vrf/bridge index) */ - uword *hw_if_index_by_dp_table; - - /** lookup decap tunnel termination sw_if_index by vni and vice versa */ - uword *sw_if_index_by_vni; - - // FIXME - Need this? - uword *vni_by_sw_if_index; -} tunnel_lookup_t; - -typedef struct -{ - u32 fwd_entry_index; - u32 tunnel_index; -} lisp_stats_key_t; - -typedef struct -{ - u32 vni; - dp_address_t deid; - dp_address_t seid; - ip_address_t loc_rloc; - ip_address_t rmt_rloc; - - vlib_counter_t counters; -} lisp_api_stats_t; - -typedef enum gpe_encap_mode_e -{ - GPE_ENCAP_LISP, - GPE_ENCAP_VXLAN, - GPE_ENCAP_COUNT -} gpe_encap_mode_t; - -/** LISP-GPE global state*/ -typedef struct lisp_gpe_main -{ - /** - * @brief DB of all forwarding entries. The Key is:{l-EID,r-EID,vni} - * where the EID encodes L2 or L3 - */ - uword *lisp_gpe_fwd_entries; - - /** - * @brief A Pool of all LISP forwarding entries - */ - struct lisp_gpe_fwd_entry_t_ *lisp_fwd_entry_pool; - - /** Free vlib hw_if_indices */ - u32 *free_tunnel_hw_if_indices; - - u8 is_en; - - /* L3 data structures - * ================== */ - tunnel_lookup_t l3_ifaces; - - /* L2 data structures - * ================== */ - - /** L2 LISP FIB */ - BVT (clib_bihash) l2_fib; - - tunnel_lookup_t l2_ifaces; - - /** Load-balance for a miss in the table */ - dpo_id_t l2_lb_cp_lkup; - - /* NSH data structures - * ================== */ - - BVT (clib_bihash) nsh_fib; - - tunnel_lookup_t nsh_ifaces; - - const dpo_id_t *nsh_cp_lkup; - - gpe_encap_mode_t encap_mode; - - u8 *placeholder_stats_pool; - uword *lisp_stats_index_by_key; - vlib_combined_counter_main_t counters; - - /** Native fwd data structures */ - fib_route_path_t *native_fwd_rpath[2]; - u32 *native_fwd_lfes[2]; - - /** convenience */ - vlib_main_t *vlib_main; - vnet_main_t *vnet_main; - ip4_main_t *im4; - ip6_main_t *im6; - ip_lookup_main_t *lm4; - ip_lookup_main_t *lm6; -} lisp_gpe_main_t; - -/** LISP-GPE global state*/ -extern lisp_gpe_main_t lisp_gpe_main; - -always_inline lisp_gpe_main_t * -vnet_lisp_gpe_get_main () -{ - return &lisp_gpe_main; -} - - -extern vlib_node_registration_t lisp_gpe_ip4_input_node; -extern vlib_node_registration_t lisp_gpe_ip6_input_node; -extern vnet_hw_interface_class_t lisp_gpe_hw_class; - -u8 *format_lisp_gpe_header_with_length (u8 * s, va_list * args); - -/** Read LISP-GPE status */ -u8 vnet_lisp_gpe_enable_disable_status (void); - -u32 -lisp_gpe_l3_iface_find_or_create (lisp_gpe_main_t * lgm, - u32 overlay_table_id, u32 vni); - -/** Add/del LISP-GPE interface. */ -extern void lisp_gpe_del_l2_iface (lisp_gpe_main_t * lgm, u32 vni, u32 bd_id); -extern u32 lisp_gpe_add_l2_iface (lisp_gpe_main_t * lgm, u32 vni, u32 bd_id); -extern void lisp_gpe_del_l3_iface (lisp_gpe_main_t * lgm, u32 vni, u32 bd_id); -extern u32 lisp_gpe_add_l3_iface (lisp_gpe_main_t * lgm, u32 vni, u32 bd_id, - u8 with_default_route); - - -typedef struct -{ - u8 is_en; -} vnet_lisp_gpe_enable_disable_args_t; - -clib_error_t - * vnet_lisp_gpe_enable_disable (vnet_lisp_gpe_enable_disable_args_t * a); - -typedef enum -{ - NO_ACTION, - FORWARD_NATIVE, - SEND_MAP_REQUEST, - DROP -} negative_fwd_actions_e; - -/** */ -typedef struct -{ - /** forwarding entry index of */ - u32 fwd_entry_index; - - u8 is_src_dst; - - u8 is_add; - - /** type of mapping */ - u8 is_negative; - - /** action for negative mappings */ - negative_fwd_actions_e action; - - /** local eid */ - gid_address_t lcl_eid; - - /** remote eid */ - gid_address_t rmt_eid; - - /** vector of locator pairs */ - locator_pair_t *locator_pairs; - - /** FIB index to lookup remote locator at encap */ - u32 encap_fib_index; - - /** FIB index to lookup inner IP at decap */ - u32 decap_fib_index; - - /* TODO remove */ - u32 decap_next_index; - - /** VNI/tenant id in HOST byte order */ - u32 vni; - - /** vrf or bd where fwd entry should be inserted */ - union - { - /** table (vrf) id */ - u32 table_id; - - /** bridge domain id */ - u32 bd_id; - - /** generic access */ - u32 dp_table; - }; -} vnet_lisp_gpe_add_del_fwd_entry_args_t; - -typedef struct -{ - fib_route_path_t rpath; - u8 is_add; -} vnet_gpe_native_fwd_rpath_args_t; - -typedef struct -{ - u32 fwd_entry_index; - u32 dp_table; - u32 vni; - u8 action; - dp_address_t leid; - dp_address_t reid; -} lisp_api_gpe_fwd_entry_t; - -#define foreach_lgpe_ip4_lookup_next \ - _(DROP, "error-drop") \ - _(LISP_CP_LOOKUP, "lisp-cp-lookup") - -typedef enum lgpe_ip4_lookup_next -{ -#define _(sym,str) LGPE_IP4_LOOKUP_NEXT_##sym, - foreach_lgpe_ip4_lookup_next -#undef _ - LGPE_IP4_LOOKUP_N_NEXT, -} lgpe_ip4_lookup_next_t; - -#define foreach_lgpe_ip6_lookup_next \ - _(DROP, "error-drop") \ - _(LISP_CP_LOOKUP, "lisp-cp-lookup") - -typedef enum lgpe_ip6_lookup_next -{ -#define _(sym,str) LGPE_IP6_LOOKUP_NEXT_##sym, - foreach_lgpe_ip6_lookup_next -#undef _ - LGPE_IP6_LOOKUP_N_NEXT, -} lgpe_ip6_lookup_next_t; - -u8 *format_vnet_lisp_gpe_status (u8 * s, va_list * args); - -lisp_api_gpe_fwd_entry_t *vnet_lisp_gpe_fwd_entries_get_by_vni (u32 vni); -gpe_encap_mode_t vnet_gpe_get_encap_mode (void); -int vnet_gpe_set_encap_mode (gpe_encap_mode_t mode); - -u8 vnet_lisp_stats_enable_disable_state (void); -vnet_api_error_t vnet_lisp_stats_enable_disable (u8 enable); -lisp_api_stats_t *vnet_lisp_get_stats (void); -int vnet_lisp_flush_stats (void); -int vnet_gpe_add_del_native_fwd_rpath (vnet_gpe_native_fwd_rpath_args_t * a); -u32 vnet_lisp_gpe_add_nsh_iface (lisp_gpe_main_t * lgm); -void vnet_lisp_gpe_del_nsh_iface (lisp_gpe_main_t * lgm); - -#endif /* included_vnet_lisp_gpe_h */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/vnet/lisp-gpe/lisp_gpe_adjacency.c b/src/vnet/lisp-gpe/lisp_gpe_adjacency.c deleted file mode 100644 index cd0b33857f5..00000000000 --- a/src/vnet/lisp-gpe/lisp_gpe_adjacency.c +++ /dev/null @@ -1,604 +0,0 @@ -/* - * Copyright (c) 2016 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. - */ -/** - * @file - * @brief Common utility functions for IPv4, IPv6 and L2 LISP-GPE adjacencys. - * - */ - -#include <vnet/dpo/load_balance.h> -#include <vnet/lisp-cp/control.h> -#include <vnet/lisp-cp/lisp_types.h> -#include <vnet/lisp-gpe/lisp_gpe_sub_interface.h> -#include <vnet/lisp-gpe/lisp_gpe_adjacency.h> -#include <vnet/lisp-gpe/lisp_gpe_tunnel.h> -#include <vnet/fib/fib_entry.h> -#include <vnet/adj/adj_midchain.h> -#include <vppinfra/bihash_24_8.h> -#include <vppinfra/bihash_template.h> - -/** - * Memory pool of all adjacencies - */ -static lisp_gpe_adjacency_t *lisp_adj_pool; - -/** - * Hash table of all adjacencies. key:{nh, itf} - * We never have an all zeros address since the interfaces are multi-access, - * therefore there is no ambiguity between a v4 and v6 next-hop, so we don't - * need to add the protocol to the key. - */ -static -BVT (clib_bihash) - lisp_adj_db; - -#define LISP_ADJ_SET_KEY(_key, _itf, _nh) \ -{ \ - _key.key[0] = ip_addr_v6((_nh)).as_u64[0]; \ - _key.key[1] = ip_addr_v6((_nh)).as_u64[1]; \ - _key.key[2] = (_itf); \ -} - - static index_t lisp_adj_find (const ip_address_t * addr, u32 sw_if_index) -{ - BVT (clib_bihash_kv) kv; - - LISP_ADJ_SET_KEY (kv, sw_if_index, addr); - - if (BV (clib_bihash_search) (&lisp_adj_db, &kv, &kv) < 0) - { - return (INDEX_INVALID); - } - else - { - return (kv.value); - } -} - -static void -lisp_adj_insert (const ip_address_t * addr, u32 sw_if_index, index_t ai) -{ - BVT (clib_bihash_kv) kv; - - LISP_ADJ_SET_KEY (kv, sw_if_index, addr); - kv.value = ai; - - BV (clib_bihash_add_del) (&lisp_adj_db, &kv, 1); -} - -static void -lisp_adj_remove (const ip_address_t * addr, u32 sw_if_index) -{ - BVT (clib_bihash_kv) kv; - - LISP_ADJ_SET_KEY (kv, sw_if_index, addr); - - BV (clib_bihash_add_del) (&lisp_adj_db, &kv, 0); -} - -static lisp_gpe_adjacency_t * -lisp_gpe_adjacency_get_i (index_t lai) -{ - return (pool_elt_at_index (lisp_adj_pool, lai)); -} - -fib_forward_chain_type_t -lisp_gpe_adj_get_fib_chain_type (const lisp_gpe_adjacency_t * ladj) -{ - switch (ip_addr_version (&ladj->remote_rloc)) - { - case AF_IP4: - return (FIB_FORW_CHAIN_TYPE_UNICAST_IP4); - case AF_IP6: - return (FIB_FORW_CHAIN_TYPE_UNICAST_IP6); - default: - ASSERT (0); - break; - } - return (FIB_FORW_CHAIN_TYPE_UNICAST_IP4); -} - -static void -ip46_address_to_ip_address (const ip46_address_t * a, ip_address_t * b) -{ - if (ip46_address_is_ip4 (a)) - { - clib_memset (b, 0, sizeof (*b)); - ip_address_set (b, &a->ip4, AF_IP4); - } - else - { - ip_address_set (b, &a->ip6, AF_IP6); - } -} - -/** - * @brief Stack the tunnel's midchain on the IP forwarding chain of the via - */ -static void -lisp_gpe_adj_stack_one (lisp_gpe_adjacency_t * ladj, adj_index_t ai) -{ - const lisp_gpe_tunnel_t *lgt; - - lgt = lisp_gpe_tunnel_get (ladj->tunnel_index); - - adj_nbr_midchain_stack_on_fib_entry (ai, - lgt->fib_entry_index, - lisp_gpe_adj_get_fib_chain_type - (ladj)); -} - -/** - * @brief Call back when restacking all adjacencies on a GRE interface - */ -static adj_walk_rc_t -lisp_gpe_adj_walk_cb (adj_index_t ai, void *ctx) -{ - lisp_gpe_adjacency_t *ladj = ctx; - - lisp_gpe_adj_stack_one (ladj, ai); - - return (ADJ_WALK_RC_CONTINUE); -} - -static void -lisp_gpe_adj_stack (lisp_gpe_adjacency_t * ladj) -{ - fib_protocol_t nh_proto; - ip46_address_t nh; - - nh_proto = ip_address_to_46 (&ladj->remote_rloc, &nh); - - /* - * walk all the adjacencies on th lisp interface and restack them - */ - adj_nbr_walk_nh (ladj->sw_if_index, - nh_proto, &nh, lisp_gpe_adj_walk_cb, ladj); -} - -static lisp_gpe_next_protocol_e -lisp_gpe_adj_proto_from_vnet_link_type (vnet_link_t linkt) -{ - switch (linkt) - { - case VNET_LINK_IP4: - return (LISP_GPE_NEXT_PROTO_IP4); - case VNET_LINK_IP6: - return (LISP_GPE_NEXT_PROTO_IP6); - case VNET_LINK_ETHERNET: - return (LISP_GPE_NEXT_PROTO_ETHERNET); - case VNET_LINK_NSH: - return (LISP_GPE_NEXT_PROTO_NSH); - default: - ASSERT (0); - } - return (LISP_GPE_NEXT_PROTO_IP4); -} - -#define is_v4_packet(_h) ((*(u8*) _h) & 0xF0) == 0x40 - -static lisp_afi_e -lisp_afi_from_vnet_link_type (vnet_link_t link) -{ - switch (link) - { - case VNET_LINK_IP4: - return LISP_AFI_IP; - case VNET_LINK_IP6: - return LISP_AFI_IP6; - case VNET_LINK_ETHERNET: - return LISP_AFI_MAC; - default: - return LISP_AFI_NO_ADDR; - } -} - -static void -lisp_gpe_increment_stats_counters (lisp_cp_main_t * lcm, - const ip_adjacency_t * adj, - vlib_buffer_t * b) -{ - lisp_gpe_main_t *lgm = vnet_lisp_gpe_get_main (); - lisp_gpe_adjacency_t *ladj; - ip_address_t rloc; - index_t lai; - u32 si, di; - gid_address_t src, dst; - uword *feip; - - ip46_address_to_ip_address (&adj->sub_type.nbr.next_hop, &rloc); - si = vnet_buffer (b)->sw_if_index[VLIB_TX]; - lai = lisp_adj_find (&rloc, si); - ASSERT (INDEX_INVALID != lai); - - ladj = pool_elt_at_index (lisp_adj_pool, lai); - - u8 *lisp_data = (u8 *) vlib_buffer_get_current (b); - - /* skip IP header */ - if (is_v4_packet (lisp_data)) - lisp_data += sizeof (ip4_header_t); - else - lisp_data += sizeof (ip6_header_t); - - /* skip UDP header */ - lisp_data += sizeof (udp_header_t); - // TODO: skip TCP? - - /* skip LISP GPE header */ - lisp_data += sizeof (lisp_gpe_header_t); - - i16 saved_current_data = b->current_data; - b->current_data = lisp_data - b->data; - - lisp_afi_e afi = lisp_afi_from_vnet_link_type (adj->ia_link); - get_src_and_dst_eids_from_buffer (lcm, b, &src, &dst, afi); - b->current_data = saved_current_data; - di = gid_dictionary_sd_lookup (&lcm->mapping_index_by_gid, &dst, &src); - if (PREDICT_FALSE (~0 == di)) - { - clib_warning ("dst mapping not found (%U, %U)", format_gid_address, - &src, format_gid_address, &dst); - return; - } - - feip = hash_get (lcm->fwd_entry_by_mapping_index, di); - if (PREDICT_FALSE (!feip)) - return; - - lisp_stats_key_t key; - clib_memset (&key, 0, sizeof (key)); - key.fwd_entry_index = feip[0]; - key.tunnel_index = ladj->tunnel_index; - - uword *p = hash_get_mem (lgm->lisp_stats_index_by_key, &key); - ALWAYS_ASSERT (p); - - /* compute payload length starting after GPE */ - u32 bytes = b->current_length - (lisp_data - b->data - b->current_data); - vlib_increment_combined_counter (&lgm->counters, vlib_get_thread_index (), - p[0], 1, bytes); -} - -static void -lisp_gpe_fixup (vlib_main_t * vm, - const ip_adjacency_t * adj, - vlib_buffer_t * b, const void *data) -{ - lisp_cp_main_t *lcm = vnet_lisp_cp_get_main (); - - if (lcm->flags & LISP_FLAG_STATS_ENABLED) - lisp_gpe_increment_stats_counters (lcm, adj, b); - - /* Fixup the checksum and len fields in the LISP tunnel encap - * that was applied at the midchain node */ - ip_udp_fixup_one (vm, b, is_v4_packet (vlib_buffer_get_current (b))); -} - -/** - * @brief The LISP-GPE interface registered function to update, i.e. - * provide an rewrite string for, an adjacency. - */ -void -lisp_gpe_update_adjacency (vnet_main_t * vnm, u32 sw_if_index, adj_index_t ai) -{ - const lisp_gpe_tunnel_t *lgt; - lisp_gpe_adjacency_t *ladj; - ip_adjacency_t *adj; - ip_address_t rloc; - vnet_link_t linkt; - adj_flags_t af; - index_t lai; - - adj = adj_get (ai); - ip46_address_to_ip_address (&adj->sub_type.nbr.next_hop, &rloc); - - /* - * find an existing or create a new adj - */ - lai = lisp_adj_find (&rloc, sw_if_index); - - ASSERT (INDEX_INVALID != lai); - - ladj = pool_elt_at_index (lisp_adj_pool, lai); - lgt = lisp_gpe_tunnel_get (ladj->tunnel_index); - linkt = adj_get_link_type (ai); - af = ADJ_FLAG_MIDCHAIN_IP_STACK; - if (VNET_LINK_ETHERNET == linkt) - af |= ADJ_FLAG_MIDCHAIN_NO_COUNT; - - adj_nbr_midchain_update_rewrite - (ai, lisp_gpe_fixup, NULL, af, - lisp_gpe_tunnel_build_rewrite (lgt, ladj, - lisp_gpe_adj_proto_from_vnet_link_type - (linkt))); - - lisp_gpe_adj_stack_one (ladj, ai); -} - -u8 * -lisp_gpe_build_rewrite (vnet_main_t * vnm, - u32 sw_if_index, - vnet_link_t link_type, const void *dst_address) -{ - ASSERT (0); - return (NULL); -} - -index_t -lisp_gpe_adjacency_find_or_create_and_lock (const locator_pair_t * pair, - u32 overlay_table_id, u32 vni) -{ - const lisp_gpe_sub_interface_t *l3s; - const lisp_gpe_tunnel_t *lgt; - lisp_gpe_adjacency_t *ladj; - index_t lai, l3si; - - /* - * first find the L3 sub-interface that corresponds to the loacl-rloc and vni - */ - l3si = lisp_gpe_sub_interface_find_or_create_and_lock (&pair->lcl_loc, - overlay_table_id, - vni); - l3s = lisp_gpe_sub_interface_get (l3si); - - /* - * find an existing or create a new adj - */ - lai = lisp_adj_find (&pair->rmt_loc, l3s->sw_if_index); - - if (INDEX_INVALID == lai) - { - - pool_get (lisp_adj_pool, ladj); - clib_memset (ladj, 0, sizeof (*ladj)); - lai = (ladj - lisp_adj_pool); - - ip_address_copy (&ladj->remote_rloc, &pair->rmt_loc); - ladj->vni = vni; - /* transfer the lock to the adj */ - ladj->lisp_l3_sub_index = l3si; - ladj->sw_if_index = l3s->sw_if_index; - - /* if vni is non-default */ - if (ladj->vni) - ladj->flags = LISP_GPE_FLAGS_I; - - /* work in lisp-gpe not legacy mode */ - ladj->flags |= LISP_GPE_FLAGS_P; - - /* - * find the tunnel that will provide the underlying transport - * and hence the rewrite. - * The RLOC FIB index is default table - always. - */ - ladj->tunnel_index = lisp_gpe_tunnel_find_or_create_and_lock (pair, 0); - - lgt = lisp_gpe_tunnel_get (ladj->tunnel_index); - - /* - * become of child of the RLOC FIB entry so we are updated when - * its reachability changes, allowing us to re-stack the midcahins - */ - ladj->fib_entry_child_index = fib_entry_child_add (lgt->fib_entry_index, - FIB_NODE_TYPE_LISP_ADJ, - lai); - - lisp_adj_insert (&ladj->remote_rloc, ladj->sw_if_index, lai); - } - else - { - /* unlock the interface from the find. */ - lisp_gpe_sub_interface_unlock (l3si); - ladj = lisp_gpe_adjacency_get_i (lai); - } - - ladj->locks++; - - return (lai); -} - -/** - * @brief Get a pointer to a tunnel from a pointer to a FIB node - */ -static lisp_gpe_adjacency_t * -lisp_gpe_adjacency_from_fib_node (const fib_node_t * node) -{ - return ((lisp_gpe_adjacency_t *) - ((char *) node - - STRUCT_OFFSET_OF (lisp_gpe_adjacency_t, fib_node))); -} - -static void -lisp_gpe_adjacency_last_lock_gone (lisp_gpe_adjacency_t * ladj) -{ - const lisp_gpe_tunnel_t *lgt; - - /* - * no children so we are not counting locks. no-op. - * at least not counting - */ - lisp_adj_remove (&ladj->remote_rloc, ladj->sw_if_index); - - /* - * unlock the resources this adj holds - */ - lgt = lisp_gpe_tunnel_get (ladj->tunnel_index); - - fib_entry_child_remove (lgt->fib_entry_index, ladj->fib_entry_child_index); - - lisp_gpe_tunnel_unlock (ladj->tunnel_index); - lisp_gpe_sub_interface_unlock (ladj->lisp_l3_sub_index); - - pool_put (lisp_adj_pool, ladj); -} - -void -lisp_gpe_adjacency_unlock (index_t lai) -{ - lisp_gpe_adjacency_t *ladj; - - ladj = lisp_gpe_adjacency_get_i (lai); - - ladj->locks--; - - if (0 == ladj->locks) - { - lisp_gpe_adjacency_last_lock_gone (ladj); - } -} - -const lisp_gpe_adjacency_t * -lisp_gpe_adjacency_get (index_t lai) -{ - return (lisp_gpe_adjacency_get_i (lai)); -} - - -/** - * @brief LISP GPE tunnel back walk - * - * The FIB entry through which this tunnel resolves has been updated. - * re-stack the midchain on the new forwarding. - */ -static fib_node_back_walk_rc_t -lisp_gpe_adjacency_back_walk (fib_node_t * node, - fib_node_back_walk_ctx_t * ctx) -{ - lisp_gpe_adj_stack (lisp_gpe_adjacency_from_fib_node (node)); - - return (FIB_NODE_BACK_WALK_CONTINUE); -} - -static fib_node_t * -lisp_gpe_adjacency_get_fib_node (fib_node_index_t index) -{ - lisp_gpe_adjacency_t *ladj; - - ladj = pool_elt_at_index (lisp_adj_pool, index); - return (&ladj->fib_node); -} - -static void -lisp_gpe_adjacency_last_fib_lock_gone (fib_node_t * node) -{ - lisp_gpe_adjacency_last_lock_gone (lisp_gpe_adjacency_from_fib_node (node)); -} - -const static fib_node_vft_t lisp_gpe_tuennel_vft = { - .fnv_get = lisp_gpe_adjacency_get_fib_node, - .fnv_back_walk = lisp_gpe_adjacency_back_walk, - .fnv_last_lock = lisp_gpe_adjacency_last_fib_lock_gone, -}; - -u8 * -format_lisp_gpe_adjacency (u8 * s, va_list * args) -{ - lisp_gpe_adjacency_t *ladj = va_arg (*args, lisp_gpe_adjacency_t *); - lisp_gpe_adjacency_format_flags_t flags = - va_arg (*args, lisp_gpe_adjacency_format_flags_t); - - if (flags & LISP_GPE_ADJ_FORMAT_FLAG_DETAIL) - { - s = - format (s, "index %d locks:%d\n", ladj - lisp_adj_pool, ladj->locks); - } - - s = format (s, " vni: %d,", ladj->vni); - s = format (s, " remote-RLOC: %U,", format_ip_address, &ladj->remote_rloc); - - if (flags & LISP_GPE_ADJ_FORMAT_FLAG_DETAIL) - { - s = format (s, " %U\n", - format_lisp_gpe_sub_interface, - lisp_gpe_sub_interface_get (ladj->lisp_l3_sub_index)); - s = format (s, " %U\n", - format_lisp_gpe_tunnel, - lisp_gpe_tunnel_get (ladj->tunnel_index)); - } - else - { - s = format (s, " LISP L3 sub-interface index: %d,", - ladj->lisp_l3_sub_index); - s = format (s, " LISP tunnel index: %d", ladj->tunnel_index); - } - - - return (s); -} - -static clib_error_t * -lisp_gpe_adjacency_show (vlib_main_t * vm, - unformat_input_t * input, vlib_cli_command_t * cmd) -{ - lisp_gpe_adjacency_t *ladj; - index_t index; - - if (pool_elts (lisp_adj_pool) == 0) - vlib_cli_output (vm, "No lisp-gpe Adjacencies"); - - if (unformat (input, "%d", &index)) - { - ladj = lisp_gpe_adjacency_get_i (index); - vlib_cli_output (vm, "%U", format_lisp_gpe_adjacency, ladj, - LISP_GPE_ADJ_FORMAT_FLAG_DETAIL); - } - else - { - /* *INDENT-OFF* */ - pool_foreach (ladj, lisp_adj_pool, - ({ - vlib_cli_output (vm, "[%d] %U\n", - ladj - lisp_adj_pool, - format_lisp_gpe_adjacency, ladj, - LISP_GPE_ADJ_FORMAT_FLAG_NONE); - })); - /* *INDENT-ON* */ - } - - return 0; -} - -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND (show_lisp_gpe_tunnel_command, static) = -{ - .path = "show gpe adjacency", - .function = lisp_gpe_adjacency_show, -}; -/* *INDENT-ON* */ - -#define LISP_ADJ_NBR_DEFAULT_HASH_NUM_BUCKETS (256) -#define LISP_ADJ_NBR_DEFAULT_HASH_MEMORY_SIZE (1<<20) - -static clib_error_t * -lisp_gpe_adj_module_init (vlib_main_t * vm) -{ - BV (clib_bihash_init) (&lisp_adj_db, - "Adjacency Neighbour table", - LISP_ADJ_NBR_DEFAULT_HASH_NUM_BUCKETS, - LISP_ADJ_NBR_DEFAULT_HASH_MEMORY_SIZE); - - fib_node_register_type (FIB_NODE_TYPE_LISP_ADJ, &lisp_gpe_tuennel_vft); - return (NULL); -} - -VLIB_INIT_FUNCTION (lisp_gpe_adj_module_init); -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/vnet/lisp-gpe/lisp_gpe_adjacency.h b/src/vnet/lisp-gpe/lisp_gpe_adjacency.h deleted file mode 100644 index adc3acaee3c..00000000000 --- a/src/vnet/lisp-gpe/lisp_gpe_adjacency.h +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Copyright (c) 2016 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. - */ -/** - * @file - * @brief Common utility functions for IPv4, IPv6 and L2 LISP-GPE adjacencys. - * - */ - -#ifndef LISP_GPE_ADJACENCY_H__ -#define LISP_GPE_ADJACENCY_H__ - -#include <vnet/fib/fib_node.h> -#include <vnet/lisp-gpe/lisp_gpe.h> - -/** - * @brief A LISP GPE Adjacency. - * - * A adjacency represents peer on an L3 sub-interface to which to send traffic. - * adjacencies are thus present in the EID space. - * The peer is identified by the key:{remote-rloc, sub-interface}, which is - * equivalent to the usal adjacency key {next-hop, interface}. So curiously - * the rloc address from the underlay is used as a next hop address in the overlay - * This is OK because: - * 1 - the RLOC is unique in the underlay AND there is only one underlay VRF per - * overlay - * 2 - the RLOC may overlap with an address in the overlay, but we do not create - * an adj-fib (i.e. a route in the overlay FIB for the rloc) - * - * - */ -typedef struct lisp_gpe_adjacency_t_ -{ - /** - * The LISP adj is a part of the FIB control plane graph. - */ - fib_node_t fib_node; - - /** - * remote RLOC. The adjacency's next-hop - */ - ip_address_t remote_rloc; - - /** - * The VNI. Used in combination with the local-rloc to get the sub-interface - */ - u32 vni; - - /** - * The number of locks/reference counts on the adjacency. - */ - u32 locks; - - /** - * The index of the LISP L3 subinterface - */ - u32 lisp_l3_sub_index; - - /** - * The SW IF index of the sub-interface this adjacency uses. - * Cached for convenience from the LISP L3 sub-interface - */ - u32 sw_if_index; - - /** - * The index of the LISP GPE tunnel that provides the transport - * in the underlay. - */ - u32 tunnel_index; - - /** - * This adjacency is a child of the FIB entry to reach the RLOC. - * This is so when the reachability of that RLOC changes, we can restack - * the FIB adjacnecies. - */ - u32 fib_entry_child_index; - - /** - * LISP header fields in HOST byte order - */ - u8 flags; - u8 ver_res; - u8 res; - u8 next_protocol; - -} lisp_gpe_adjacency_t; - -extern index_t lisp_gpe_adjacency_find_or_create_and_lock (const - locator_pair_t * - pair, - u32 rloc_fib_index, - u32 vni); - -extern void lisp_gpe_adjacency_unlock (index_t l3si); - -extern const lisp_gpe_adjacency_t *lisp_gpe_adjacency_get (index_t l3si); - -extern void lisp_gpe_update_adjacency (vnet_main_t * vnm, - u32 sw_if_index, adj_index_t ai); -extern u8 *lisp_gpe_build_rewrite (vnet_main_t * vnm, - u32 sw_if_index, - vnet_link_t link_type, - const void *dst_address); - - -/** - * @brief Flags for displaying the adjacency - */ -typedef enum lisp_gpe_adjacency_format_flags_t_ -{ - LISP_GPE_ADJ_FORMAT_FLAG_NONE, - LISP_GPE_ADJ_FORMAT_FLAG_DETAIL, -} lisp_gpe_adjacency_format_flags_t; - -extern u8 *format_lisp_gpe_adjacency (u8 * s, va_list * args); - -#endif - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/vnet/lisp-gpe/lisp_gpe_api.c b/src/vnet/lisp-gpe/lisp_gpe_api.c deleted file mode 100644 index e20347a46f6..00000000000 --- a/src/vnet/lisp-gpe/lisp_gpe_api.c +++ /dev/null @@ -1,549 +0,0 @@ -/* - *------------------------------------------------------------------ - * lisp_gpe_api.c - lisp_gpe api - * - * Copyright (c) 2016 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 <vnet/vnet.h> -#include <vlibmemory/api.h> - -#include <vnet/interface.h> -#include <vnet/api_errno.h> -#include <vnet/lisp-gpe/lisp_gpe.h> -#include <vnet/lisp-gpe/lisp_gpe_adjacency.h> -#include <vnet/lisp-gpe/lisp_gpe_tunnel.h> -#include <vnet/lisp-gpe/lisp_gpe_fwd_entry.h> -#include <vnet/lisp-gpe/lisp_gpe_tenant.h> -#include <vnet/fib/fib_table.h> -#include <vnet/vnet_msg_enum.h> -#include <vnet/ip/ip_types_api.h> -#include <vnet/ethernet/ethernet_types_api.h> -#include <vnet/lisp-gpe/lisp_types_api.h> - -#define vl_api_gpe_locator_pair_t_endian vl_noop_handler -#define vl_api_gpe_locator_pair_t_print vl_noop_handler -#define vl_api_gpe_add_del_fwd_entry_t_endian vl_noop_handler -#define vl_api_gpe_add_del_fwd_entry_t_print vl_noop_handler - -#define vl_typedefs /* define message structures */ -#include <vnet/vnet_all_api_h.h> -#undef vl_typedefs - -#define vl_endianfun /* define message structures */ -#include <vnet/vnet_all_api_h.h> -#undef vl_endianfun - -/* instantiate all the print functions we know about */ -#define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__) -#define vl_printfun -#include <vnet/vnet_all_api_h.h> -#undef vl_printfun - -#include <vlibapi/api_helper_macros.h> - -#define foreach_vpe_api_msg \ -_(GPE_ADD_DEL_FWD_ENTRY, gpe_add_del_fwd_entry) \ -_(GPE_FWD_ENTRIES_GET, gpe_fwd_entries_get) \ -_(GPE_FWD_ENTRY_PATH_DUMP, gpe_fwd_entry_path_dump) \ -_(GPE_ENABLE_DISABLE, gpe_enable_disable) \ -_(GPE_ADD_DEL_IFACE, gpe_add_del_iface) \ -_(GPE_FWD_ENTRY_VNIS_GET, gpe_fwd_entry_vnis_get) \ -_(GPE_SET_ENCAP_MODE, gpe_set_encap_mode) \ -_(GPE_GET_ENCAP_MODE, gpe_get_encap_mode) \ -_(GPE_ADD_DEL_NATIVE_FWD_RPATH, gpe_add_del_native_fwd_rpath) \ -_(GPE_NATIVE_FWD_RPATHS_GET, gpe_native_fwd_rpaths_get) - -static locator_pair_t * -unformat_gpe_loc_pairs (void *locs, u32 rloc_num) -{ - u32 i; - locator_pair_t *pairs = 0, pair, *p; - vl_api_gpe_locator_t *r; - - for (i = 0; i < rloc_num; i++) - { - /* local locator */ - r = &((vl_api_gpe_locator_t *) locs)[i]; - clib_memset (&pair, 0, sizeof (pair)); - ip_address_decode2 (&r->addr, &pair.lcl_loc); - - pair.weight = r->weight; - vec_add1 (pairs, pair); - } - - for (i = rloc_num; i < rloc_num * 2; i++) - { - /* remote locators */ - r = &((vl_api_gpe_locator_t *) locs)[i]; - p = &pairs[i - rloc_num]; - ip_address_decode2 (&r->addr, &p->rmt_loc); - } - return pairs; -} - -static void - gpe_fwd_entry_path_dump_t_net_to_host - (vl_api_gpe_fwd_entry_path_dump_t * mp) -{ - mp->fwd_entry_index = clib_net_to_host_u32 (mp->fwd_entry_index); -} - -static void -lisp_api_set_locator (vl_api_gpe_locator_t * loc, - const ip_address_t * addr, u8 weight) -{ - loc->weight = weight; - ip_address_encode2 (addr, &loc->addr); -} - -static void - vl_api_gpe_fwd_entry_path_dump_t_handler - (vl_api_gpe_fwd_entry_path_dump_t * mp) -{ - lisp_fwd_path_t *path; - vl_api_gpe_fwd_entry_path_details_t *rmp = NULL; - lisp_gpe_main_t *lgm = &lisp_gpe_main; - vl_api_registration_t *reg; - lisp_gpe_fwd_entry_t *lfe; - - gpe_fwd_entry_path_dump_t_net_to_host (mp); - - reg = vl_api_client_index_to_registration (mp->client_index); - if (!reg) - return; - - if (pool_is_free_index (lgm->lisp_fwd_entry_pool, mp->fwd_entry_index)) - return; - - lfe = pool_elt_at_index (lgm->lisp_fwd_entry_pool, mp->fwd_entry_index); - - if (LISP_GPE_FWD_ENTRY_TYPE_NEGATIVE == lfe->type) - return; - - vec_foreach (path, lfe->paths) - { - rmp = vl_msg_api_alloc (sizeof (*rmp)); - clib_memset (rmp, 0, sizeof (*rmp)); - const lisp_gpe_tunnel_t *lgt; - - rmp->_vl_msg_id = - clib_host_to_net_u16 (VL_API_GPE_FWD_ENTRY_PATH_DETAILS); - - const lisp_gpe_adjacency_t *ladj = - lisp_gpe_adjacency_get (path->lisp_adj); - lisp_api_set_locator (&rmp->rmt_loc, &ladj->remote_rloc, path->weight); - lgt = lisp_gpe_tunnel_get (ladj->tunnel_index); - lisp_api_set_locator (&rmp->lcl_loc, &lgt->key->lcl, path->weight); - - rmp->context = mp->context; - vl_api_send_msg (reg, (u8 *) rmp); - } -} - -static void -gpe_fwd_entries_copy (vl_api_gpe_fwd_entry_t * dst, - lisp_api_gpe_fwd_entry_t * src) -{ - lisp_api_gpe_fwd_entry_t *e; - u32 i = 0; - - vec_foreach (e, src) - { - clib_memset (&dst[i], 0, sizeof (*dst)); - dst[i].dp_table = e->dp_table; - dst[i].fwd_entry_index = e->fwd_entry_index; - dst[i].vni = e->vni; - dst[i].action = e->action; - switch (fid_addr_type (&e->leid)) - { - case FID_ADDR_IP_PREF: - dst[i].leid.type = EID_TYPE_API_PREFIX; - dst[i].reid.type = EID_TYPE_API_PREFIX; - ip_prefix_encode2 (&fid_addr_ippref (&e->leid), - &dst[i].leid.address.prefix); - ip_prefix_encode2 (&fid_addr_ippref (&e->reid), - &dst[i].reid.address.prefix); - break; - case FID_ADDR_MAC: - mac_address_encode ((mac_address_t *) fid_addr_mac (&e->leid), - dst[i].leid.address.mac); - mac_address_encode ((mac_address_t *) fid_addr_mac (&e->reid), - dst[i].reid.address.mac); - dst[i].leid.type = EID_TYPE_API_MAC; - dst[i].reid.type = EID_TYPE_API_MAC; - break; - default: - clib_warning ("unknown fid type %d!", fid_addr_type (&e->leid)); - break; - } - i++; - } -} - -static void -gpe_fwd_entries_get_t_net_to_host (vl_api_gpe_fwd_entries_get_t * mp) -{ - mp->vni = clib_net_to_host_u32 (mp->vni); -} - -static void -gpe_entry_t_host_to_net (vl_api_gpe_fwd_entry_t * e) -{ - e->fwd_entry_index = clib_host_to_net_u32 (e->fwd_entry_index); - e->dp_table = clib_host_to_net_u32 (e->dp_table); - e->vni = clib_host_to_net_u32 (e->vni); -} - -static void - gpe_fwd_entries_get_reply_t_host_to_net - (vl_api_gpe_fwd_entries_get_reply_t * mp) -{ - u32 i; - vl_api_gpe_fwd_entry_t *e; - - for (i = 0; i < mp->count; i++) - { - e = &mp->entries[i]; - gpe_entry_t_host_to_net (e); - } - mp->count = clib_host_to_net_u32 (mp->count); -} - -static void -vl_api_gpe_fwd_entry_vnis_get_t_handler (vl_api_gpe_fwd_entry_vnis_get_t * mp) -{ - vl_api_gpe_fwd_entry_vnis_get_reply_t *rmp = 0; - hash_pair_t *p; - u32 i = 0; - int rv = 0; - - u32 *vnis = vnet_lisp_gpe_get_fwd_entry_vnis (); - u32 size = hash_elts (vnis) * sizeof (u32); - - /* *INDENT-OFF* */ - REPLY_MACRO4 (VL_API_GPE_FWD_ENTRY_VNIS_GET_REPLY, size, - { - rmp->count = clib_host_to_net_u32 (hash_elts (vnis)); - hash_foreach_pair (p, vnis, - ({ - rmp->vnis[i++] = clib_host_to_net_u32 (p->key); - })); - }); - /* *INDENT-ON* */ - - hash_free (vnis); -} - -static void -vl_api_gpe_fwd_entries_get_t_handler (vl_api_gpe_fwd_entries_get_t * mp) -{ - lisp_api_gpe_fwd_entry_t *e; - vl_api_gpe_fwd_entries_get_reply_t *rmp = 0; - u32 size = 0; - int rv = 0; - - gpe_fwd_entries_get_t_net_to_host (mp); - - e = vnet_lisp_gpe_fwd_entries_get_by_vni (mp->vni); - size = vec_len (e) * sizeof (vl_api_gpe_fwd_entry_t); - - /* *INDENT-OFF* */ - REPLY_MACRO4 (VL_API_GPE_FWD_ENTRIES_GET_REPLY, size, - { - rmp->count = vec_len (e); - gpe_fwd_entries_copy (rmp->entries, e); - gpe_fwd_entries_get_reply_t_host_to_net (rmp); - }); - /* *INDENT-ON* */ - - vec_free (e); -} - -static void -gpe_add_del_fwd_entry_t_net_to_host (vl_api_gpe_add_del_fwd_entry_t * mp) -{ - mp->vni = clib_net_to_host_u32 (mp->vni); - mp->dp_table = clib_net_to_host_u32 (mp->dp_table); - mp->loc_num = clib_net_to_host_u32 (mp->loc_num); -} - -static void -vl_api_gpe_add_del_fwd_entry_t_handler (vl_api_gpe_add_del_fwd_entry_t * mp) -{ - vl_api_gpe_add_del_fwd_entry_reply_t *rmp; - vnet_lisp_gpe_add_del_fwd_entry_args_t _a, *a = &_a; - locator_pair_t *pairs = 0; - int rv = 0; - - gpe_add_del_fwd_entry_t_net_to_host (mp); - clib_memset (a, 0, sizeof (a[0])); - - rv = unformat_lisp_eid_api (&a->rmt_eid, mp->vni, &mp->rmt_eid); - rv |= unformat_lisp_eid_api (&a->lcl_eid, mp->vni, &mp->lcl_eid); - - if (mp->loc_num % 2 != 0) - { - rv = -1; - goto send_reply; - } - pairs = unformat_gpe_loc_pairs (mp->locs, mp->loc_num / 2); - - if (rv) - goto send_reply; - - a->is_add = mp->is_add; - a->locator_pairs = pairs; - a->dp_table = mp->dp_table; - a->vni = mp->vni; - a->action = mp->action; - if (mp->loc_num == 0) - a->is_negative = 1; - - rv = vnet_lisp_gpe_add_del_fwd_entry (a, 0); - vec_free (pairs); -send_reply: - /* *INDENT-OFF* */ - REPLY_MACRO2 (VL_API_GPE_ADD_DEL_FWD_ENTRY_REPLY, - { - rmp->fwd_entry_index = clib_host_to_net_u32 (a->fwd_entry_index); - }); - /* *INDENT-ON* */ -} - -static void -vl_api_gpe_enable_disable_t_handler (vl_api_gpe_enable_disable_t * mp) -{ - vl_api_gpe_enable_disable_reply_t *rmp; - int rv = 0; - vnet_lisp_gpe_enable_disable_args_t _a, *a = &_a; - - a->is_en = mp->is_enable; - vnet_lisp_gpe_enable_disable (a); - - REPLY_MACRO (VL_API_GPE_ENABLE_DISABLE_REPLY); -} - -static void -vl_api_gpe_add_del_iface_t_handler (vl_api_gpe_add_del_iface_t * mp) -{ - vl_api_gpe_add_del_iface_reply_t *rmp; - int rv = 0; - u32 vni, dp_table; - - vni = clib_net_to_host_u32 (mp->vni); - dp_table = clib_net_to_host_u32 (mp->dp_table); - - if (mp->is_l2) - { - if (mp->is_add) - { - if (~0 == lisp_gpe_tenant_l2_iface_add_or_lock (vni, dp_table)) - rv = 1; - } - else - lisp_gpe_tenant_l2_iface_unlock (vni); - } - else - { - if (mp->is_add) - { - if (~0 == lisp_gpe_tenant_l3_iface_add_or_lock (vni, dp_table, 1)) - rv = 1; - } - else - lisp_gpe_tenant_l3_iface_unlock (vni); - } - - REPLY_MACRO (VL_API_GPE_ADD_DEL_IFACE_REPLY); -} - -static void -vl_api_gpe_set_encap_mode_t_handler (vl_api_gpe_set_encap_mode_t * mp) -{ - vl_api_gpe_set_encap_mode_reply_t *rmp; - int rv = 0; - - rv = vnet_gpe_set_encap_mode (mp->is_vxlan); - REPLY_MACRO (VL_API_GPE_SET_ENCAP_MODE_REPLY); -} - -static void -vl_api_gpe_get_encap_mode_t_handler (vl_api_gpe_get_encap_mode_t * mp) -{ - vl_api_gpe_get_encap_mode_reply_t *rmp; - int rv = 0; - - /* *INDENT-OFF* */ - REPLY_MACRO2 (VL_API_GPE_GET_ENCAP_MODE_REPLY, - ({ - rmp->encap_mode = vnet_gpe_get_encap_mode (); - })); - /* *INDENT-ON* */ -} - -static void - vl_api_gpe_add_del_native_fwd_rpath_t_handler - (vl_api_gpe_add_del_native_fwd_rpath_t * mp) -{ - vl_api_gpe_add_del_native_fwd_rpath_reply_t *rmp; - vnet_gpe_native_fwd_rpath_args_t _a, *a = &_a; - int rv = 0; - - clib_memset (a, 0, sizeof (a[0])); - - if (mp->nh_addr.af) - clib_memcpy (&a->rpath.frp_addr.ip6, mp->nh_addr.un.ip6, - sizeof (ip6_address_t)); - else - clib_memcpy (&a->rpath.frp_addr.ip4, mp->nh_addr.un.ip4, - sizeof (ip4_address_t)); - - a->is_add = mp->is_add; - a->rpath.frp_proto = mp->nh_addr.af ? DPO_PROTO_IP6 : DPO_PROTO_IP4; - a->rpath.frp_fib_index = - fib_table_find (dpo_proto_to_fib (a->rpath.frp_proto), - clib_net_to_host_u32 (mp->table_id)); - if (~0 == a->rpath.frp_fib_index) - { - rv = VNET_API_ERROR_INVALID_VALUE; - goto done; - } - - a->rpath.frp_sw_if_index = clib_net_to_host_u32 (mp->nh_sw_if_index); - a->rpath.frp_weight = 1; - - rv = vnet_gpe_add_del_native_fwd_rpath (a); -done: - REPLY_MACRO (VL_API_GPE_ADD_DEL_NATIVE_FWD_RPATH_REPLY); -} - -static void -gpe_native_fwd_rpaths_copy (vl_api_gpe_native_fwd_rpath_t * dst, - fib_route_path_t * src) -{ - fib_route_path_t *e; - fib_table_t *table; - u32 i = 0; - - vec_foreach (e, src) - { - clib_memset (&dst[i], 0, sizeof (*dst)); - table = fib_table_get (e->frp_fib_index, dpo_proto_to_fib (e->frp_proto)); - dst[i].fib_index = table->ft_table_id; - dst[i].nh_sw_if_index = e->frp_sw_if_index; - ip_address_encode (&e->frp_addr, IP46_TYPE_ANY, &dst[i].nh_addr); - i++; - } -} - -static void -gpe_native_fwd_rpath_t_host_to_net (vl_api_gpe_native_fwd_rpath_t * e) -{ - e->fib_index = clib_host_to_net_u32 (e->fib_index); - e->nh_sw_if_index = clib_host_to_net_u32 (e->nh_sw_if_index); -} - -static void - gpe_native_fwd_rpaths_get_reply_t_host_to_net - (vl_api_gpe_native_fwd_rpaths_get_reply_t * mp) -{ - u32 i; - vl_api_gpe_native_fwd_rpath_t *e; - - for (i = 0; i < mp->count; i++) - { - e = &mp->entries[i]; - gpe_native_fwd_rpath_t_host_to_net (e); - } - mp->count = clib_host_to_net_u32 (mp->count); -} - -static void -vl_api_gpe_native_fwd_rpaths_get_t_handler (vl_api_gpe_native_fwd_rpaths_get_t - * mp) -{ - lisp_gpe_main_t *lgm = vnet_lisp_gpe_get_main (); - vl_api_gpe_native_fwd_rpaths_get_reply_t *rmp; - u32 size = 0; - int rv = 0; - - u8 rpath_index = mp->is_ip4 ? 1 : 0; - - size = vec_len (lgm->native_fwd_rpath[rpath_index]) - * sizeof (vl_api_gpe_native_fwd_rpath_t); - - /* *INDENT-OFF* */ - REPLY_MACRO4 (VL_API_GPE_NATIVE_FWD_RPATHS_GET_REPLY, size, - { - rmp->count = vec_len (lgm->native_fwd_rpath[rpath_index]); - gpe_native_fwd_rpaths_copy (rmp->entries, - lgm->native_fwd_rpath[rpath_index]); - gpe_native_fwd_rpaths_get_reply_t_host_to_net (rmp); - }); - /* *INDENT-ON* */ -} - -/* - * gpe_api_hookup - * Add vpe's API message handlers to the table. - * vlib has already mapped shared memory and - * added the client registration handlers. - * See .../vlib-api/vlibmemory/memclnt_vlib.c:memclnt_process() - */ -#define vl_msg_name_crc_list -#include <vnet/vnet_all_api_h.h> -#undef vl_msg_name_crc_list - -static void -setup_message_id_table (api_main_t * am) -{ -#define _(id,n,crc) vl_msg_api_add_msg_name_crc (am, #n "_" #crc, id); - foreach_vl_msg_name_crc_lisp_gpe; -#undef _ -} - -static clib_error_t * -gpe_api_hookup (vlib_main_t * vm) -{ - api_main_t *am = vlibapi_get_main (); - -#define _(N,n) \ - vl_msg_api_set_handlers(VL_API_##N, #n, \ - vl_api_##n##_t_handler, \ - vl_noop_handler, \ - vl_api_##n##_t_endian, \ - vl_api_##n##_t_print, \ - sizeof(vl_api_##n##_t), 1); - foreach_vpe_api_msg; -#undef _ - - /* - * Set up the (msg_name, crc, message-id) table - */ - setup_message_id_table (am); - - return 0; -} - -VLIB_API_INIT_FUNCTION (gpe_api_hookup); - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/vnet/lisp-gpe/lisp_gpe_error.def b/src/vnet/lisp-gpe/lisp_gpe_error.def deleted file mode 100644 index 415fada73d2..00000000000 --- a/src/vnet/lisp-gpe/lisp_gpe_error.def +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright (c) 2016 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. - */ - -lisp_gpe_error (ENCAPSULATED, "good packets encapsulated") -lisp_gpe_error (DECAPSULATED, "good packets decapsulated") -lisp_gpe_error (NO_TUNNEL, "tunnel does not exist") diff --git a/src/vnet/lisp-gpe/lisp_gpe_fwd_entry.c b/src/vnet/lisp-gpe/lisp_gpe_fwd_entry.c deleted file mode 100644 index 487ba246b4d..00000000000 --- a/src/vnet/lisp-gpe/lisp_gpe_fwd_entry.c +++ /dev/null @@ -1,1595 +0,0 @@ -/* - * Copyright (c) 2016 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 <vnet/lisp-gpe/lisp_gpe_fwd_entry.h> -#include <vnet/lisp-gpe/lisp_gpe_adjacency.h> -#include <vnet/lisp-gpe/lisp_gpe_tenant.h> -#include <vnet/lisp-cp/lisp_cp_dpo.h> -#include <vnet/fib/fib_table.h> -#include <vnet/fib/fib_entry.h> -#include <vnet/fib/fib_path_list.h> -#include <vnet/fib/ip6_fib.h> -#include <vnet/fib/ip4_fib.h> -#include <vnet/dpo/drop_dpo.h> -#include <vnet/dpo/lookup_dpo.h> -#include <vnet/dpo/load_balance.h> -#include <vnet/adj/adj_midchain.h> - -/** - * @brief Add route to IP4 or IP6 Destination FIB. - * - * Add a route to the destination FIB that results in the lookup - * in the SRC FIB. The SRC FIB is created is it does not yet exist. - * - * @param[in] dst_table_id Destination FIB Table-ID - * @param[in] dst_prefix Destination IP prefix. - * - * @return src_fib_index The index/ID of the SRC FIB created. - */ -static u32 -ip_dst_fib_add_route (u32 dst_fib_index, const ip_prefix_t * dst_prefix) -{ - fib_node_index_t src_fib_index; - fib_prefix_t dst_fib_prefix; - fib_node_index_t dst_fei; - - ASSERT (NULL != dst_prefix); - - ip_prefix_to_fib_prefix (dst_prefix, &dst_fib_prefix); - - /* - * lookup the destination prefix in the VRF table and retrieve the - * LISP associated data - */ - dst_fei = fib_table_lookup_exact_match (dst_fib_index, &dst_fib_prefix); - - /* - * If the FIB entry is not present, or not LISP sourced, add it - */ - if (dst_fei == FIB_NODE_INDEX_INVALID || - NULL == fib_entry_get_source_data (dst_fei, FIB_SOURCE_LISP)) - { - dpo_id_t src_lkup_dpo = DPO_INVALID; - - /* create a new src FIB. */ - src_fib_index = - fib_table_create_and_lock (dst_fib_prefix.fp_proto, - FIB_SOURCE_LISP, - "LISP-src for [%d,%U]", - dst_fib_index, - format_fib_prefix, &dst_fib_prefix); - /* - * add src fib default route - */ - fib_prefix_t prefix = { - .fp_proto = dst_fib_prefix.fp_proto, - }; - fib_table_entry_special_dpo_add (src_fib_index, &prefix, - FIB_SOURCE_LISP, - FIB_ENTRY_FLAG_EXCLUSIVE, - lisp_cp_dpo_get (fib_proto_to_dpo - (dst_fib_prefix.fp_proto))); - /* - * create a data-path object to perform the source address lookup - * in the SRC FIB - */ - lookup_dpo_add_or_lock_w_fib_index (src_fib_index, - (ip_prefix_version (dst_prefix) == - AF_IP6 ? DPO_PROTO_IP6 : - DPO_PROTO_IP4), - LOOKUP_UNICAST, - LOOKUP_INPUT_SRC_ADDR, - LOOKUP_TABLE_FROM_CONFIG, - &src_lkup_dpo); - - /* - * add the entry to the destination FIB that uses the lookup DPO - */ - dst_fei = fib_table_entry_special_dpo_add (dst_fib_index, - &dst_fib_prefix, - FIB_SOURCE_LISP, - FIB_ENTRY_FLAG_EXCLUSIVE, - &src_lkup_dpo); - - /* - * the DPO is locked by the FIB entry, and we have no further - * need for it. - */ - dpo_unlock (&src_lkup_dpo); - - /* - * save the SRC FIB index on the entry so we can retrieve it for - * subsequent routes. - */ - fib_entry_set_source_data (dst_fei, FIB_SOURCE_LISP, &src_fib_index); - } - else - { - /* - * destination FIB entry already present - */ - src_fib_index = *(u32 *) fib_entry_get_source_data (dst_fei, - FIB_SOURCE_LISP); - } - - return (src_fib_index); -} - -/** - * @brief Del route to IP4 or IP6 SD FIB. - * - * Remove routes from both destination and source FIBs. - * - * @param[in] src_fib_index The index/ID of the SRC FIB - * @param[in] src_prefix Source IP prefix. - * @param[in] dst_fib_index The index/ID of the DST FIB - * @param[in] dst_prefix Destination IP prefix. - */ -static void -ip_src_dst_fib_del_route (u32 src_fib_index, - const ip_prefix_t * src_prefix, - u32 dst_fib_index, const ip_prefix_t * dst_prefix) -{ - fib_prefix_t dst_fib_prefix, src_fib_prefix; - u8 have_default = 0; - u32 n_entries; - - ASSERT (NULL != dst_prefix); - ASSERT (NULL != src_prefix); - - ip_prefix_to_fib_prefix (dst_prefix, &dst_fib_prefix); - ip_prefix_to_fib_prefix (src_prefix, &src_fib_prefix); - - fib_table_entry_delete (src_fib_index, &src_fib_prefix, FIB_SOURCE_LISP); - - /* check if only default left or empty */ - fib_prefix_t default_pref = { - .fp_proto = dst_fib_prefix.fp_proto - }; - - if (fib_table_lookup_exact_match (src_fib_index, - &default_pref) != FIB_NODE_INDEX_INVALID) - have_default = 1; - - n_entries = fib_table_get_num_entries (src_fib_index, - src_fib_prefix.fp_proto, - FIB_SOURCE_LISP); - if (n_entries == 0 || (have_default && n_entries == 1)) - { - /* - * remove src FIB default route - */ - if (have_default) - fib_table_entry_special_remove (src_fib_index, &default_pref, - FIB_SOURCE_LISP); - - /* - * there's nothing left now, unlock the source FIB and the - * destination route - */ - fib_table_entry_special_remove (dst_fib_index, - &dst_fib_prefix, FIB_SOURCE_LISP); - fib_table_unlock (src_fib_index, src_fib_prefix.fp_proto, - FIB_SOURCE_LISP); - } -} - -/** - * @brief Add route to IP4 or IP6 SRC FIB. - * - * Adds a route to in the LISP SRC FIB with the result of the route - * being the DPO passed. - * - * @param[in] src_fib_index The index/ID of the SRC FIB - * @param[in] src_prefix Source IP prefix. - * @param[in] src_dpo The DPO the route will link to. - * - * @return fib index of the inserted prefix - */ -static fib_node_index_t -ip_src_fib_add_route_w_dpo (u32 src_fib_index, - const ip_prefix_t * src_prefix, - const dpo_id_t * src_dpo) -{ - fib_node_index_t fei = ~0; - fib_prefix_t src_fib_prefix; - - ip_prefix_to_fib_prefix (src_prefix, &src_fib_prefix); - - /* - * add the entry into the source fib. - */ - fib_node_index_t src_fei; - - src_fei = fib_table_lookup_exact_match (src_fib_index, &src_fib_prefix); - - if (FIB_NODE_INDEX_INVALID == src_fei || - !fib_entry_is_sourced (src_fei, FIB_SOURCE_LISP)) - { - fei = fib_table_entry_special_dpo_add (src_fib_index, - &src_fib_prefix, - FIB_SOURCE_LISP, - FIB_ENTRY_FLAG_EXCLUSIVE, - src_dpo); - } - return fei; -} - -static fib_route_path_t * -lisp_gpe_mk_fib_paths (const lisp_fwd_path_t * paths) -{ - const lisp_gpe_adjacency_t *ladj; - fib_route_path_t *rpaths = NULL; - fib_protocol_t fp; - u8 best_priority; - u32 ii; - - vec_validate (rpaths, vec_len (paths) - 1); - - best_priority = paths[0].priority; - - vec_foreach_index (ii, paths) - { - if (paths[0].priority != best_priority) - break; - - ladj = lisp_gpe_adjacency_get (paths[ii].lisp_adj); - - fp = ip_address_to_46 (&ladj->remote_rloc, &rpaths[ii].frp_addr); - - rpaths[ii].frp_proto = fib_proto_to_dpo (fp); - rpaths[ii].frp_sw_if_index = ladj->sw_if_index; - rpaths[ii].frp_weight = (paths[ii].weight ? paths[ii].weight : 1); - } - - ASSERT (0 != vec_len (rpaths)); - - return (rpaths); -} - -/** - * @brief Add route to IP4 or IP6 SRC FIB. - * - * Adds a route to in the LISP SRC FIB for the tunnel. - * - * @param[in] src_fib_index The index/ID of the SRC FIB - * @param[in] src_prefix Source IP prefix. - * @param[in] paths The paths from which to construct the - * load balance - */ -static fib_node_index_t -ip_src_fib_add_route (u32 src_fib_index, - const ip_prefix_t * src_prefix, - const lisp_fwd_path_t * paths) -{ - fib_prefix_t src_fib_prefix; - fib_route_path_t *rpaths; - - ip_prefix_to_fib_prefix (src_prefix, &src_fib_prefix); - - rpaths = lisp_gpe_mk_fib_paths (paths); - - fib_node_index_t fib_entry_index = - fib_table_entry_update (src_fib_index, &src_fib_prefix, FIB_SOURCE_LISP, - FIB_ENTRY_FLAG_NONE, rpaths); - vec_free (rpaths); - return fib_entry_index; -} - -static void -gpe_native_fwd_add_del_lfe (lisp_gpe_fwd_entry_t * lfe, u8 is_add) -{ - lisp_gpe_main_t *lgm = vnet_lisp_gpe_get_main (); - u8 found = 0, ip_version; - u32 *lfei, new_lfei; - ip_version = ip_prefix_version (&lfe->key->rmt.ippref); - - new_lfei = lfe - lgm->lisp_fwd_entry_pool; - vec_foreach (lfei, lgm->native_fwd_lfes[ip_version]) - { - lfe = pool_elt_at_index (lgm->lisp_fwd_entry_pool, lfei[0]); - if (lfei[0] == new_lfei) - { - found = 1; - break; - } - } - - if (is_add) - { - if (!found) - vec_add1 (lgm->native_fwd_lfes[ip_version], new_lfei); - } - else - { - if (found) - vec_del1 (lgm->native_fwd_lfes[ip_version], lfei[0]); - } -} - -static index_t -create_fib_entries (lisp_gpe_fwd_entry_t * lfe) -{ - fib_node_index_t fi; - fib_entry_t *fe; - lisp_gpe_main_t *lgm = vnet_lisp_gpe_get_main (); - dpo_proto_t dproto; - ip_prefix_t ippref; - fib_prefix_t fib_prefix; - u8 ip_version = ip_prefix_version (&lfe->key->rmt.ippref); - dproto = (ip_version == AF_IP4 ? DPO_PROTO_IP4 : DPO_PROTO_IP6); - - if (lfe->is_src_dst) - { - lfe->src_fib_index = ip_dst_fib_add_route (lfe->eid_fib_index, - &lfe->key->rmt.ippref); - memcpy (&ippref, &lfe->key->lcl.ippref, sizeof (ippref)); - } - else - { - lfe->src_fib_index = lfe->eid_fib_index; - memcpy (&ippref, &lfe->key->rmt.ippref, sizeof (ippref)); - } - - if (LISP_GPE_FWD_ENTRY_TYPE_NEGATIVE == lfe->type) - { - dpo_id_t dpo = DPO_INVALID; - - switch (lfe->action) - { - case LISP_FORWARD_NATIVE: - /* TODO handle route overlaps with fib and default route */ - if (vec_len (lgm->native_fwd_rpath[ip_version])) - { - ip_prefix_to_fib_prefix (&lfe->key->rmt.ippref, &fib_prefix); - fi = fib_table_entry_update (lfe->eid_fib_index, &fib_prefix, - FIB_SOURCE_LISP, - FIB_ENTRY_FLAG_NONE, - lgm->native_fwd_rpath[ip_version]); - gpe_native_fwd_add_del_lfe (lfe, 1); - goto done; - } - case LISP_NO_ACTION: - /* TODO update timers? */ - case LISP_SEND_MAP_REQUEST: - /* insert tunnel that always sends map-request */ - dpo_copy (&dpo, lisp_cp_dpo_get (dproto)); - break; - case LISP_DROP: - /* for drop fwd entries, just add route, no need to add encap tunnel */ - dpo_copy (&dpo, drop_dpo_get (dproto)); - break; - } - fi = ip_src_fib_add_route_w_dpo (lfe->src_fib_index, &ippref, &dpo); - dpo_reset (&dpo); - } - else - { - fi = ip_src_fib_add_route (lfe->src_fib_index, &ippref, lfe->paths); - } -done: - fe = fib_entry_get (fi); - return fe->fe_lb.dpoi_index; -} - -static void -delete_fib_entries (lisp_gpe_fwd_entry_t * lfe) -{ - fib_prefix_t dst_fib_prefix; - - if (lfe->is_src_dst) - ip_src_dst_fib_del_route (lfe->src_fib_index, - &lfe->key->lcl.ippref, - lfe->eid_fib_index, &lfe->key->rmt.ippref); - else - { - ip_prefix_to_fib_prefix (&lfe->key->rmt.ippref, &dst_fib_prefix); - fib_table_entry_delete (lfe->src_fib_index, &dst_fib_prefix, - FIB_SOURCE_LISP); - gpe_native_fwd_add_del_lfe (lfe, 0); - } -} - -static lisp_gpe_fwd_entry_t * -find_fwd_entry (lisp_gpe_main_t * lgm, - vnet_lisp_gpe_add_del_fwd_entry_args_t * a, - lisp_gpe_fwd_entry_key_t * key) -{ - uword *p; - - clib_memset (key, 0, sizeof (*key)); - - if (GID_ADDR_IP_PREFIX == gid_address_type (&a->rmt_eid)) - { - /* - * the ip version of the source is not set to ip6 when the - * source is all zeros. force it. - */ - ip_prefix_version (&gid_address_ippref (&a->lcl_eid)) = - ip_prefix_version (&gid_address_ippref (&a->rmt_eid)); - } - - gid_to_dp_address (&a->rmt_eid, &key->rmt); - gid_to_dp_address (&a->lcl_eid, &key->lcl); - key->vni = a->vni; - - p = hash_get_mem (lgm->lisp_gpe_fwd_entries, key); - - if (NULL != p) - { - return (pool_elt_at_index (lgm->lisp_fwd_entry_pool, p[0])); - } - return (NULL); -} - -static int -lisp_gpe_fwd_entry_path_sort (void *a1, void *a2) -{ - lisp_fwd_path_t *p1 = a1, *p2 = a2; - - return (p1->priority - p2->priority); -} - -static void -lisp_gpe_fwd_entry_mk_paths (lisp_gpe_fwd_entry_t * lfe, - vnet_lisp_gpe_add_del_fwd_entry_args_t * a) -{ - lisp_fwd_path_t *path; - u32 index; - - vec_validate (lfe->paths, vec_len (a->locator_pairs) - 1); - - vec_foreach_index (index, a->locator_pairs) - { - path = &lfe->paths[index]; - - path->priority = a->locator_pairs[index].priority; - path->weight = a->locator_pairs[index].weight; - - path->lisp_adj = - lisp_gpe_adjacency_find_or_create_and_lock (&a->locator_pairs - [index], - a->dp_table, lfe->key->vni); - } - vec_sort_with_function (lfe->paths, lisp_gpe_fwd_entry_path_sort); -} - -void -vnet_lisp_gpe_add_fwd_counters (vnet_lisp_gpe_add_del_fwd_entry_args_t * a, - u32 fwd_entry_index) -{ - const lisp_gpe_adjacency_t *ladj; - lisp_fwd_path_t *path; - lisp_gpe_main_t *lgm = vnet_lisp_gpe_get_main (); - u8 *placeholder_elt; - lisp_gpe_fwd_entry_t *lfe; - lisp_gpe_fwd_entry_key_t fe_key; - lisp_stats_key_t key; - - lfe = find_fwd_entry (lgm, a, &fe_key); - - if (!lfe) - return; - - if (LISP_GPE_FWD_ENTRY_TYPE_NORMAL != lfe->type) - return; - - clib_memset (&key, 0, sizeof (key)); - key.fwd_entry_index = fwd_entry_index; - - vec_foreach (path, lfe->paths) - { - ladj = lisp_gpe_adjacency_get (path->lisp_adj); - key.tunnel_index = ladj->tunnel_index; - lisp_stats_key_t *key_copy = clib_mem_alloc (sizeof (*key_copy)); - memcpy (key_copy, &key, sizeof (*key_copy)); - pool_get (lgm->placeholder_stats_pool, placeholder_elt); - hash_set_mem (lgm->lisp_stats_index_by_key, key_copy, - placeholder_elt - lgm->placeholder_stats_pool); - - vlib_validate_combined_counter (&lgm->counters, - placeholder_elt - - lgm->placeholder_stats_pool); - vlib_zero_combined_counter (&lgm->counters, - placeholder_elt - - lgm->placeholder_stats_pool); - } -} - -/** - * @brief Add/Delete LISP IP forwarding entry. - * - * creation of forwarding entries for IP LISP overlay: - * - * @param[in] lgm Reference to @ref lisp_gpe_main_t. - * @param[in] a Parameters for building the forwarding entry. - * - * @return 0 on success. - */ -static int -add_ip_fwd_entry (lisp_gpe_main_t * lgm, - vnet_lisp_gpe_add_del_fwd_entry_args_t * a) -{ - lisp_gpe_fwd_entry_key_t key; - lisp_gpe_fwd_entry_t *lfe; - fib_protocol_t fproto; - - lfe = find_fwd_entry (lgm, a, &key); - - if (NULL != lfe) - /* don't support updates */ - return VNET_API_ERROR_INVALID_VALUE; - - pool_get (lgm->lisp_fwd_entry_pool, lfe); - clib_memset (lfe, 0, sizeof (*lfe)); - lfe->key = clib_mem_alloc (sizeof (key)); - memcpy (lfe->key, &key, sizeof (key)); - - hash_set_mem (lgm->lisp_gpe_fwd_entries, lfe->key, - lfe - lgm->lisp_fwd_entry_pool); - a->fwd_entry_index = lfe - lgm->lisp_fwd_entry_pool; - - fproto = (AF_IP4 == ip_prefix_version (&fid_addr_ippref (&lfe->key->rmt)) ? - FIB_PROTOCOL_IP4 : FIB_PROTOCOL_IP6); - - lfe->type = (a->is_negative ? - LISP_GPE_FWD_ENTRY_TYPE_NEGATIVE : - LISP_GPE_FWD_ENTRY_TYPE_NORMAL); - lfe->tenant = lisp_gpe_tenant_find_or_create (lfe->key->vni); - lfe->eid_table_id = a->table_id; - lfe->eid_fib_index = fib_table_find_or_create_and_lock (fproto, - lfe->eid_table_id, - FIB_SOURCE_LISP); - lfe->is_src_dst = a->is_src_dst; - - if (LISP_GPE_FWD_ENTRY_TYPE_NEGATIVE != lfe->type) - { - lisp_gpe_fwd_entry_mk_paths (lfe, a); - } - else - { - lfe->action = a->action; - } - - lfe->dpoi_index = create_fib_entries (lfe); - return (0); -} - -static void -del_ip_fwd_entry_i (lisp_gpe_main_t * lgm, lisp_gpe_fwd_entry_t * lfe) -{ - lisp_fwd_path_t *path; - fib_protocol_t fproto; - - if (LISP_GPE_FWD_ENTRY_TYPE_NEGATIVE != lfe->type) - { - vec_foreach (path, lfe->paths) - { - lisp_gpe_adjacency_unlock (path->lisp_adj); - } - } - - delete_fib_entries (lfe); - - fproto = (AF_IP4 == ip_prefix_version (&fid_addr_ippref (&lfe->key->rmt)) ? - FIB_PROTOCOL_IP4 : FIB_PROTOCOL_IP6); - fib_table_unlock (lfe->eid_fib_index, fproto, FIB_SOURCE_LISP); - - hash_unset_mem (lgm->lisp_gpe_fwd_entries, lfe->key); - clib_mem_free (lfe->key); - pool_put (lgm->lisp_fwd_entry_pool, lfe); -} - -/** - * @brief Add/Delete LISP IP forwarding entry. - * - * removal of forwarding entries for IP LISP overlay: - * - * @param[in] lgm Reference to @ref lisp_gpe_main_t. - * @param[in] a Parameters for building the forwarding entry. - * - * @return 0 on success. - */ -static int -del_ip_fwd_entry (lisp_gpe_main_t * lgm, - vnet_lisp_gpe_add_del_fwd_entry_args_t * a) -{ - lisp_gpe_fwd_entry_key_t key; - lisp_gpe_fwd_entry_t *lfe; - - lfe = find_fwd_entry (lgm, a, &key); - - if (NULL == lfe) - /* no such entry */ - return VNET_API_ERROR_INVALID_VALUE; - - del_ip_fwd_entry_i (lgm, lfe); - - return (0); -} - -static void -make_mac_fib_key (BVT (clib_bihash_kv) * kv, u16 bd_index, u8 src_mac[6], - u8 dst_mac[6]) -{ - kv->key[0] = (((u64) bd_index) << 48) | mac_to_u64 (dst_mac); - kv->key[1] = mac_to_u64 (src_mac); - kv->key[2] = 0; -} - -/** - * @brief Lookup L2 SD FIB entry - * - * Does a vni + dest + source lookup in the L2 LISP FIB. If the lookup fails - * it tries a second time with source set to 0 (i.e., a simple dest lookup). - * - * @param[in] lgm Reference to @ref lisp_gpe_main_t. - * @param[in] bd_index Bridge domain index. - * @param[in] src_mac Source mac address. - * @param[in] dst_mac Destination mac address. - * - * @return index of mapping matching the lookup key. - */ -index_t -lisp_l2_fib_lookup (lisp_gpe_main_t * lgm, u16 bd_index, u8 src_mac[6], - u8 dst_mac[6]) -{ - int rv; - BVT (clib_bihash_kv) kv, value; - - make_mac_fib_key (&kv, bd_index, src_mac, dst_mac); - rv = BV (clib_bihash_search_inline_2) (&lgm->l2_fib, &kv, &value); - - /* no match, try with src 0, catch all for dst */ - if (rv != 0) - { - kv.key[1] = 0; - rv = BV (clib_bihash_search_inline_2) (&lgm->l2_fib, &kv, &value); - if (rv == 0) - return value.value; - } - else - return value.value; - - return lisp_gpe_main.l2_lb_cp_lkup.dpoi_index; -} - -/** - * @brief Add/del L2 SD FIB entry - * - * Inserts value in L2 FIB keyed by vni + dest + source. If entry is - * overwritten the associated value is returned. - * - * @param[in] lgm Reference to @ref lisp_gpe_main_t. - * @param[in] bd_index Bridge domain index. - * @param[in] src_mac Source mac address. - * @param[in] dst_mac Destination mac address. - * @param[in] val Value to add. - * @param[in] is_add Add/del flag. - * - * @return ~0 or value of overwritten entry. - */ -static u32 -lisp_l2_fib_add_del_entry (u16 bd_index, u8 src_mac[6], - u8 dst_mac[6], const dpo_id_t * dpo, u8 is_add) -{ - lisp_gpe_main_t *lgm = &lisp_gpe_main; - BVT (clib_bihash_kv) kv, value; - u32 old_val = ~0; - - make_mac_fib_key (&kv, bd_index, src_mac, dst_mac); - - if (BV (clib_bihash_search) (&lgm->l2_fib, &kv, &value) == 0) - old_val = value.value; - - if (!is_add) - BV (clib_bihash_add_del) (&lgm->l2_fib, &kv, 0 /* is_add */ ); - else - { - kv.value = dpo->dpoi_index; - BV (clib_bihash_add_del) (&lgm->l2_fib, &kv, 1 /* is_add */ ); - } - return old_val; -} - -#define L2_FIB_DEFAULT_HASH_NUM_BUCKETS (64 * 1024) -#define L2_FIB_DEFAULT_HASH_MEMORY_SIZE (32<<20) - -static void -l2_fib_init (lisp_gpe_main_t * lgm) -{ - index_t lbi; - - BV (clib_bihash_init) (&lgm->l2_fib, "l2 fib", - 1 << max_log2 (L2_FIB_DEFAULT_HASH_NUM_BUCKETS), - L2_FIB_DEFAULT_HASH_MEMORY_SIZE); - - /* - * the result from a 'miss' in a L2 Table - */ - lbi = load_balance_create (1, DPO_PROTO_ETHERNET, 0); - load_balance_set_bucket (lbi, 0, lisp_cp_dpo_get (DPO_PROTO_ETHERNET)); - - dpo_set (&lgm->l2_lb_cp_lkup, DPO_LOAD_BALANCE, DPO_PROTO_ETHERNET, lbi); -} - -static void -del_l2_fwd_entry_i (lisp_gpe_main_t * lgm, lisp_gpe_fwd_entry_t * lfe) -{ - lisp_fwd_path_t *path; - - if (LISP_GPE_FWD_ENTRY_TYPE_NEGATIVE != lfe->type) - { - vec_foreach (path, lfe->paths) - { - lisp_gpe_adjacency_unlock (path->lisp_adj); - } - fib_path_list_child_remove (lfe->l2.path_list_index, - lfe->l2.child_index); - } - - lisp_l2_fib_add_del_entry (lfe->l2.eid_bd_index, - fid_addr_mac (&lfe->key->lcl), - fid_addr_mac (&lfe->key->rmt), NULL, 0); - - hash_unset_mem (lgm->lisp_gpe_fwd_entries, lfe->key); - clib_mem_free (lfe->key); - pool_put (lgm->lisp_fwd_entry_pool, lfe); -} - -/** - * @brief Delete LISP L2 forwarding entry. - * - * Coordinates the removal of forwarding entries for L2 LISP overlay: - * - * @param[in] lgm Reference to @ref lisp_gpe_main_t. - * @param[in] a Parameters for building the forwarding entry. - * - * @return 0 on success. - */ -static int -del_l2_fwd_entry (lisp_gpe_main_t * lgm, - vnet_lisp_gpe_add_del_fwd_entry_args_t * a) -{ - lisp_gpe_fwd_entry_key_t key; - lisp_gpe_fwd_entry_t *lfe; - - lfe = find_fwd_entry (lgm, a, &key); - - if (NULL == lfe) - return VNET_API_ERROR_INVALID_VALUE; - - del_l2_fwd_entry_i (lgm, lfe); - - return (0); -} - -/** - * @brief Construct and insert the forwarding information used by an L2 entry - */ -static void -lisp_gpe_l2_update_fwding (lisp_gpe_fwd_entry_t * lfe) -{ - lisp_gpe_main_t *lgm = &lisp_gpe_main; - dpo_id_t dpo = DPO_INVALID; - - if (LISP_GPE_FWD_ENTRY_TYPE_NEGATIVE != lfe->type) - { - fib_path_list_contribute_forwarding (lfe->l2.path_list_index, - FIB_FORW_CHAIN_TYPE_ETHERNET, - FIB_PATH_LIST_FWD_FLAG_NONE, - &lfe->l2.dpo); - dpo_copy (&dpo, &lfe->l2.dpo); - } - else - { - switch (lfe->action) - { - case SEND_MAP_REQUEST: - dpo_copy (&dpo, &lgm->l2_lb_cp_lkup); - break; - case NO_ACTION: - case FORWARD_NATIVE: - case DROP: - dpo_copy (&dpo, drop_dpo_get (DPO_PROTO_ETHERNET)); - } - } - - /* add entry to l2 lisp fib */ - lisp_l2_fib_add_del_entry (lfe->l2.eid_bd_index, - fid_addr_mac (&lfe->key->lcl), - fid_addr_mac (&lfe->key->rmt), &dpo, 1); - lfe->dpoi_index = dpo.dpoi_index; - - dpo_reset (&dpo); -} - -/** - * @brief Add LISP L2 forwarding entry. - * - * Coordinates the creation of forwarding entries for L2 LISP overlay: - * creates lisp-gpe tunnel and injects new entry in Source/Dest L2 FIB. - * - * @param[in] lgm Reference to @ref lisp_gpe_main_t. - * @param[in] a Parameters for building the forwarding entry. - * - * @return 0 on success. - */ -static int -add_l2_fwd_entry (lisp_gpe_main_t * lgm, - vnet_lisp_gpe_add_del_fwd_entry_args_t * a) -{ - lisp_gpe_fwd_entry_key_t key; - bd_main_t *bdm = &bd_main; - lisp_gpe_fwd_entry_t *lfe; - uword *bd_indexp; - - bd_indexp = hash_get (bdm->bd_index_by_bd_id, a->bd_id); - if (!bd_indexp) - { - clib_warning ("bridge domain %d doesn't exist", a->bd_id); - return -1; - } - - lfe = find_fwd_entry (lgm, a, &key); - - if (NULL != lfe) - /* don't support updates */ - return VNET_API_ERROR_INVALID_VALUE; - - pool_get (lgm->lisp_fwd_entry_pool, lfe); - clib_memset (lfe, 0, sizeof (*lfe)); - lfe->key = clib_mem_alloc (sizeof (key)); - memcpy (lfe->key, &key, sizeof (key)); - - hash_set_mem (lgm->lisp_gpe_fwd_entries, lfe->key, - lfe - lgm->lisp_fwd_entry_pool); - a->fwd_entry_index = lfe - lgm->lisp_fwd_entry_pool; - - lfe->type = (a->is_negative ? - LISP_GPE_FWD_ENTRY_TYPE_NEGATIVE : - LISP_GPE_FWD_ENTRY_TYPE_NORMAL); - lfe->l2.eid_bd_id = a->bd_id; - lfe->l2.eid_bd_index = bd_indexp[0]; - lfe->tenant = lisp_gpe_tenant_find_or_create (lfe->key->vni); - - if (LISP_GPE_FWD_ENTRY_TYPE_NEGATIVE != lfe->type) - { - fib_route_path_t *rpaths; - - /* - * Make the sorted array of LISP paths with their resp. adjacency - */ - lisp_gpe_fwd_entry_mk_paths (lfe, a); - - /* - * From the LISP paths, construct a FIB path list that will - * contribute a load-balance. - */ - rpaths = lisp_gpe_mk_fib_paths (lfe->paths); - - lfe->l2.path_list_index = - fib_path_list_create (FIB_PATH_LIST_FLAG_NONE, rpaths); - - /* - * become a child of the path-list so we receive updates when - * its forwarding state changes. this includes an implicit lock. - */ - lfe->l2.child_index = - fib_path_list_child_add (lfe->l2.path_list_index, - FIB_NODE_TYPE_LISP_GPE_FWD_ENTRY, - lfe - lgm->lisp_fwd_entry_pool); - } - else - { - lfe->action = a->action; - } - - lisp_gpe_l2_update_fwding (lfe); - - return 0; -} - -/** - * @brief Lookup NSH SD FIB entry - * - * Does an SPI+SI lookup in the NSH LISP FIB. - * - * @param[in] lgm Reference to @ref lisp_gpe_main_t. - * @param[in] spi_si SPI + SI. - * - * @return next node index. - */ -const dpo_id_t * -lisp_nsh_fib_lookup (lisp_gpe_main_t * lgm, u32 spi_si_net_order) -{ - int rv; - BVT (clib_bihash_kv) kv, value; - - clib_memset (&kv, 0, sizeof (kv)); - kv.key[0] = spi_si_net_order; - rv = BV (clib_bihash_search_inline_2) (&lgm->nsh_fib, &kv, &value); - - if (rv != 0) - { - return lgm->nsh_cp_lkup; - } - else - { - lisp_gpe_fwd_entry_t *lfe; - lfe = pool_elt_at_index (lgm->lisp_fwd_entry_pool, value.value); - return &lfe->nsh.choice; - } -} - -/** - * @brief Add/del NSH FIB entry - * - * Inserts value in NSH FIB keyed by SPI+SI. If entry is - * overwritten the associated value is returned. - * - * @param[in] lgm Reference to @ref lisp_gpe_main_t. - * @param[in] spi_si SPI + SI. - * @param[in] dpo Load balanced mapped to SPI + SI - * - * @return ~0 or value of overwritten entry. - */ -static u32 -lisp_nsh_fib_add_del_entry (u32 spi_si_host_order, u32 lfei, u8 is_add) -{ - lisp_gpe_main_t *lgm = &lisp_gpe_main; - BVT (clib_bihash_kv) kv, value; - u32 old_val = ~0; - - clib_memset (&kv, 0, sizeof (kv)); - kv.key[0] = clib_host_to_net_u32 (spi_si_host_order); - kv.value = 0ULL; - - if (BV (clib_bihash_search) (&lgm->nsh_fib, &kv, &value) == 0) - old_val = value.value; - - if (!is_add) - BV (clib_bihash_add_del) (&lgm->nsh_fib, &kv, 0 /* is_add */ ); - else - { - kv.value = lfei; - BV (clib_bihash_add_del) (&lgm->nsh_fib, &kv, 1 /* is_add */ ); - } - return old_val; -} - -#define NSH_FIB_DEFAULT_HASH_NUM_BUCKETS (64 * 1024) -#define NSH_FIB_DEFAULT_HASH_MEMORY_SIZE (32<<20) - -static void -nsh_fib_init (lisp_gpe_main_t * lgm) -{ - BV (clib_bihash_init) (&lgm->nsh_fib, "nsh fib", - 1 << max_log2 (NSH_FIB_DEFAULT_HASH_NUM_BUCKETS), - NSH_FIB_DEFAULT_HASH_MEMORY_SIZE); - - /* - * the result from a 'miss' in a NSH Table - */ - lgm->nsh_cp_lkup = lisp_cp_dpo_get (DPO_PROTO_NSH); -} - -static void -del_nsh_fwd_entry_i (lisp_gpe_main_t * lgm, lisp_gpe_fwd_entry_t * lfe) -{ - lisp_fwd_path_t *path; - - if (LISP_GPE_FWD_ENTRY_TYPE_NEGATIVE != lfe->type) - { - vec_foreach (path, lfe->paths) - { - lisp_gpe_adjacency_unlock (path->lisp_adj); - } - fib_path_list_child_remove (lfe->nsh.path_list_index, - lfe->nsh.child_index); - dpo_reset (&lfe->nsh.choice); - } - - lisp_nsh_fib_add_del_entry (fid_addr_nsh (&lfe->key->rmt), (u32) ~ 0, 0); - - hash_unset_mem (lgm->lisp_gpe_fwd_entries, lfe->key); - clib_mem_free (lfe->key); - pool_put (lgm->lisp_fwd_entry_pool, lfe); -} - -/** - * @brief Delete LISP NSH forwarding entry. - * - * Coordinates the removal of forwarding entries for NSH LISP overlay: - * - * @param[in] lgm Reference to @ref lisp_gpe_main_t. - * @param[in] a Parameters for building the forwarding entry. - * - * @return 0 on success. - */ -static int -del_nsh_fwd_entry (lisp_gpe_main_t * lgm, - vnet_lisp_gpe_add_del_fwd_entry_args_t * a) -{ - lisp_gpe_fwd_entry_key_t key; - lisp_gpe_fwd_entry_t *lfe; - - lfe = find_fwd_entry (lgm, a, &key); - - if (NULL == lfe) - return VNET_API_ERROR_INVALID_VALUE; - - del_nsh_fwd_entry_i (lgm, lfe); - - return (0); -} - -/** - * @brief Construct and insert the forwarding information used by an NSH entry - */ -static void -lisp_gpe_nsh_update_fwding (lisp_gpe_fwd_entry_t * lfe) -{ - lisp_gpe_main_t *lgm = vnet_lisp_gpe_get_main (); - dpo_id_t dpo = DPO_INVALID; - vnet_hw_interface_t *hi; - uword *hip; - - if (LISP_GPE_FWD_ENTRY_TYPE_NEGATIVE != lfe->type) - { - fib_path_list_contribute_forwarding (lfe->nsh.path_list_index, - FIB_FORW_CHAIN_TYPE_NSH, - FIB_PATH_LIST_FWD_FLAG_NONE, - &lfe->nsh.dpo); - - /* - * LISP encap is always the same for this SPI+SI so we do that hash now - * and stack on the choice. - */ - if (DPO_LOAD_BALANCE == lfe->nsh.dpo.dpoi_type) - { - const dpo_id_t *tmp; - const load_balance_t *lb; - int hash; - - lb = load_balance_get (lfe->nsh.dpo.dpoi_index); - hash = fid_addr_nsh (&lfe->key->rmt) % lb->lb_n_buckets; - tmp = - load_balance_get_bucket_i (lb, hash & lb->lb_n_buckets_minus_1); - - dpo_copy (&dpo, tmp); - } - } - else - { - switch (lfe->action) - { - case SEND_MAP_REQUEST: - dpo_copy (&dpo, lgm->nsh_cp_lkup); - break; - case NO_ACTION: - case FORWARD_NATIVE: - case DROP: - dpo_copy (&dpo, drop_dpo_get (DPO_PROTO_NSH)); - } - } - - /* We have only one nsh-lisp interface (no NSH virtualization) */ - hip = hash_get (lgm->nsh_ifaces.hw_if_index_by_dp_table, 0); - if (hip) - { - hi = vnet_get_hw_interface (lgm->vnet_main, hip[0]); - dpo_stack_from_node (hi->tx_node_index, &lfe->nsh.choice, &dpo); - } - /* add entry to nsh lisp fib */ - lisp_nsh_fib_add_del_entry (fid_addr_nsh (&lfe->key->rmt), - lfe - lgm->lisp_fwd_entry_pool, 1); - dpo_reset (&dpo); - -} - -/** - * @brief Add LISP NSH forwarding entry. - * - * Coordinates the creation of forwarding entries for L2 LISP overlay: - * creates lisp-gpe tunnel and injects new entry in Source/Dest L2 FIB. - * - * @param[in] lgm Reference to @ref lisp_gpe_main_t. - * @param[in] a Parameters for building the forwarding entry. - * - * @return 0 on success. - */ -static int -add_nsh_fwd_entry (lisp_gpe_main_t * lgm, - vnet_lisp_gpe_add_del_fwd_entry_args_t * a) -{ - lisp_gpe_fwd_entry_key_t key; - lisp_gpe_fwd_entry_t *lfe; - - lfe = find_fwd_entry (lgm, a, &key); - - if (NULL != lfe) - /* don't support updates */ - return VNET_API_ERROR_INVALID_VALUE; - - pool_get (lgm->lisp_fwd_entry_pool, lfe); - clib_memset (lfe, 0, sizeof (*lfe)); - lfe->key = clib_mem_alloc (sizeof (key)); - memcpy (lfe->key, &key, sizeof (key)); - - hash_set_mem (lgm->lisp_gpe_fwd_entries, lfe->key, - lfe - lgm->lisp_fwd_entry_pool); - a->fwd_entry_index = lfe - lgm->lisp_fwd_entry_pool; - - lfe->type = (a->is_negative ? - LISP_GPE_FWD_ENTRY_TYPE_NEGATIVE : - LISP_GPE_FWD_ENTRY_TYPE_NORMAL); - lfe->tenant = 0; - - if (LISP_GPE_FWD_ENTRY_TYPE_NEGATIVE != lfe->type) - { - fib_route_path_t *rpaths; - - /* - * Make the sorted array of LISP paths with their resp. adjacency - */ - lisp_gpe_fwd_entry_mk_paths (lfe, a); - - /* - * From the LISP paths, construct a FIB path list that will - * contribute a load-balance. - */ - rpaths = lisp_gpe_mk_fib_paths (lfe->paths); - - lfe->nsh.path_list_index = - fib_path_list_create (FIB_PATH_LIST_FLAG_NONE, rpaths); - - /* - * become a child of the path-list so we receive updates when - * its forwarding state changes. this includes an implicit lock. - */ - lfe->nsh.child_index = - fib_path_list_child_add (lfe->nsh.path_list_index, - FIB_NODE_TYPE_LISP_GPE_FWD_ENTRY, - lfe - lgm->lisp_fwd_entry_pool); - } - else - { - lfe->action = a->action; - } - - lisp_gpe_nsh_update_fwding (lfe); - - return 0; -} - -/** - * @brief conver from the embedded fib_node_t struct to the LSIP entry - */ -static lisp_gpe_fwd_entry_t * -lisp_gpe_fwd_entry_from_fib_node (fib_node_t * node) -{ - return ((lisp_gpe_fwd_entry_t *) (((char *) node) - - STRUCT_OFFSET_OF (lisp_gpe_fwd_entry_t, - node))); -} - -/** - * @brief Function invoked during a backwalk of the FIB graph - */ -static fib_node_back_walk_rc_t -lisp_gpe_fib_node_back_walk (fib_node_t * node, - fib_node_back_walk_ctx_t * ctx) -{ - lisp_gpe_fwd_entry_t *lfe = lisp_gpe_fwd_entry_from_fib_node (node); - - if (fid_addr_type (&lfe->key->rmt) == FID_ADDR_MAC) - lisp_gpe_l2_update_fwding (lfe); - else if (fid_addr_type (&lfe->key->rmt) == FID_ADDR_NSH) - lisp_gpe_nsh_update_fwding (lfe); - - return (FIB_NODE_BACK_WALK_CONTINUE); -} - -/** - * @brief Get a fib_node_t struct from the index of a LISP fwd entry - */ -static fib_node_t * -lisp_gpe_fwd_entry_get_fib_node (fib_node_index_t index) -{ - lisp_gpe_main_t *lgm = &lisp_gpe_main; - lisp_gpe_fwd_entry_t *lfe; - - lfe = pool_elt_at_index (lgm->lisp_fwd_entry_pool, index); - - return (&(lfe->node)); -} - -/** - * @brief An indication from the graph that the last lock has gone - */ -static void -lisp_gpe_fwd_entry_fib_node_last_lock_gone (fib_node_t * node) -{ - /* We don't manage the locks of the LISP objects via the graph, since - * this object has no children. so this is a no-op. */ -} - -/** - * @brief Virtual function table to register with FIB for the LISP type - */ -const static fib_node_vft_t lisp_fwd_vft = { - .fnv_get = lisp_gpe_fwd_entry_get_fib_node, - .fnv_last_lock = lisp_gpe_fwd_entry_fib_node_last_lock_gone, - .fnv_back_walk = lisp_gpe_fib_node_back_walk, -}; - -/** - * @brief Forwarding entry create/remove dispatcher. - * - * Calls l2 or l3 forwarding entry add/del function based on input data. - * - * @param[in] a Forwarding entry parameters. - * @param[out] hw_if_indexp NOT USED - * - * @return 0 on success. - */ -int -vnet_lisp_gpe_add_del_fwd_entry (vnet_lisp_gpe_add_del_fwd_entry_args_t * a, - u32 * hw_if_indexp) -{ - lisp_gpe_main_t *lgm = &lisp_gpe_main; - u8 type; - - if (vnet_lisp_gpe_enable_disable_status () == 0) - { - clib_warning ("LISP is disabled!"); - return VNET_API_ERROR_LISP_DISABLED; - } - - type = gid_address_type (&a->rmt_eid); - switch (type) - { - case GID_ADDR_IP_PREFIX: - if (a->is_add) - return add_ip_fwd_entry (lgm, a); - else - return del_ip_fwd_entry (lgm, a); - break; - case GID_ADDR_MAC: - if (a->is_add) - return add_l2_fwd_entry (lgm, a); - else - return del_l2_fwd_entry (lgm, a); - case GID_ADDR_NSH: - if (a->is_add) - return add_nsh_fwd_entry (lgm, a); - else - return del_nsh_fwd_entry (lgm, a); - default: - clib_warning ("Forwarding entries for type %d not supported!", type); - return -1; - } -} - -int -vnet_lisp_flush_stats (void) -{ - lisp_gpe_main_t *lgm = vnet_lisp_gpe_get_main (); - vlib_combined_counter_main_t *cm = &lgm->counters; - u32 i; - - if (cm->counters == NULL) - return 0; - - for (i = 0; i < vlib_combined_counter_n_counters (cm); i++) - vlib_zero_combined_counter (cm, i); - - return 0; -} - -static void -lisp_del_adj_stats (lisp_gpe_main_t * lgm, u32 fwd_entry_index, u32 ti) -{ - hash_pair_t *hp; - lisp_stats_key_t key; - void *key_copy; - uword *p; - u8 *s; - - clib_memset (&key, 0, sizeof (key)); - key.fwd_entry_index = fwd_entry_index; - key.tunnel_index = ti; - - p = hash_get_mem (lgm->lisp_stats_index_by_key, &key); - if (p) - { - s = pool_elt_at_index (lgm->placeholder_stats_pool, p[0]); - hp = hash_get_pair (lgm->lisp_stats_index_by_key, &key); - key_copy = (void *) (hp->key); - hash_unset_mem (lgm->lisp_stats_index_by_key, &key); - clib_mem_free (key_copy); - pool_put (lgm->placeholder_stats_pool, s); - } -} - -void -vnet_lisp_gpe_del_fwd_counters (vnet_lisp_gpe_add_del_fwd_entry_args_t * a, - u32 fwd_entry_index) -{ - lisp_gpe_main_t *lgm = &lisp_gpe_main; - lisp_gpe_fwd_entry_key_t fe_key; - lisp_gpe_fwd_entry_t *lfe; - lisp_fwd_path_t *path; - const lisp_gpe_adjacency_t *ladj; - - lfe = find_fwd_entry (lgm, a, &fe_key); - if (!lfe) - return; - - if (LISP_GPE_FWD_ENTRY_TYPE_NORMAL != lfe->type) - return; - - vec_foreach (path, lfe->paths) - { - ladj = lisp_gpe_adjacency_get (path->lisp_adj); - lisp_del_adj_stats (lgm, fwd_entry_index, ladj->tunnel_index); - } -} - -/** - * @brief Flush all the forwrding entries - */ -void -vnet_lisp_gpe_fwd_entry_flush (void) -{ - lisp_gpe_main_t *lgm = &lisp_gpe_main; - lisp_gpe_fwd_entry_t *lfe; - - /* *INDENT-OFF* */ - pool_foreach (lfe, lgm->lisp_fwd_entry_pool, - ({ - switch (fid_addr_type(&lfe->key->rmt)) - { - case FID_ADDR_MAC: - del_l2_fwd_entry_i (lgm, lfe); - break; - case FID_ADDR_IP_PREF: - del_ip_fwd_entry_i (lgm, lfe); - break; - case FID_ADDR_NSH: - del_nsh_fwd_entry_i (lgm, lfe); - break; - } - })); - /* *INDENT-ON* */ -} - -static u8 * -format_lisp_fwd_path (u8 * s, va_list * ap) -{ - lisp_fwd_path_t *lfp = va_arg (*ap, lisp_fwd_path_t *); - - s = format (s, "weight:%d ", lfp->weight); - s = format (s, "adj:[%U]\n", - format_lisp_gpe_adjacency, - lisp_gpe_adjacency_get (lfp->lisp_adj), - LISP_GPE_ADJ_FORMAT_FLAG_NONE); - - return (s); -} - -typedef enum lisp_gpe_fwd_entry_format_flag_t_ -{ - LISP_GPE_FWD_ENTRY_FORMAT_NONE = (0 << 0), - LISP_GPE_FWD_ENTRY_FORMAT_DETAIL = (1 << 1), -} lisp_gpe_fwd_entry_format_flag_t; - - -static u8 * -format_lisp_gpe_fwd_entry (u8 * s, va_list * ap) -{ - lisp_gpe_main_t *lgm = &lisp_gpe_main; - lisp_gpe_fwd_entry_t *lfe = va_arg (*ap, lisp_gpe_fwd_entry_t *); - lisp_gpe_fwd_entry_format_flag_t flags = - va_arg (*ap, lisp_gpe_fwd_entry_format_flag_t); - - s = format (s, "VNI:%d VRF:%d EID: %U -> %U [index:%d]", - lfe->key->vni, lfe->eid_table_id, - format_fid_address, &lfe->key->lcl, - format_fid_address, &lfe->key->rmt, - lfe - lgm->lisp_fwd_entry_pool); - - if (LISP_GPE_FWD_ENTRY_TYPE_NEGATIVE == lfe->type) - { - s = format (s, "\n Negative - action:%U", - format_negative_mapping_action, lfe->action); - } - else - { - lisp_fwd_path_t *path; - - s = format (s, "\n via:"); - vec_foreach (path, lfe->paths) - { - s = format (s, "\n %U", format_lisp_fwd_path, path); - } - } - - if (flags & LISP_GPE_FWD_ENTRY_FORMAT_DETAIL) - { - switch (fid_addr_type (&lfe->key->rmt)) - { - case FID_ADDR_MAC: - s = format (s, " fib-path-list:%d\n", lfe->l2.path_list_index); - s = format (s, " dpo:%U\n", format_dpo_id, &lfe->l2.dpo, 0); - break; - case FID_ADDR_NSH: - s = format (s, " fib-path-list:%d\n", lfe->nsh.path_list_index); - s = format (s, " dpo:%U\n", format_dpo_id, &lfe->nsh.dpo, 0); - break; - case FID_ADDR_IP_PREF: - break; - } - } - - return (s); -} - -static clib_error_t * -lisp_gpe_fwd_entry_show (vlib_main_t * vm, - unformat_input_t * input, vlib_cli_command_t * cmd) -{ - lisp_gpe_main_t *lgm = &lisp_gpe_main; - lisp_gpe_fwd_entry_t *lfe; - index_t index; - u32 vni = ~0; - - if (unformat (input, "vni %d", &vni)) - ; - else if (unformat (input, "%d", &index)) - { - if (!pool_is_free_index (lgm->lisp_fwd_entry_pool, index)) - { - lfe = pool_elt_at_index (lgm->lisp_fwd_entry_pool, index); - - vlib_cli_output (vm, "[%d@] %U", - index, - format_lisp_gpe_fwd_entry, lfe, - LISP_GPE_FWD_ENTRY_FORMAT_DETAIL); - } - else - { - vlib_cli_output (vm, "entry %d invalid", index); - } - - return (NULL); - } - - /* *INDENT-OFF* */ - pool_foreach (lfe, lgm->lisp_fwd_entry_pool, - ({ - if ((vni == ~0) || - (lfe->key->vni == vni)) - vlib_cli_output (vm, "%U", format_lisp_gpe_fwd_entry, lfe, - LISP_GPE_FWD_ENTRY_FORMAT_NONE); - })); - /* *INDENT-ON* */ - - return (NULL); -} - -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND (lisp_gpe_fwd_entry_show_command, static) = { - .path = "show gpe entry", - .short_help = "show gpe entry vni <vni> vrf <vrf> [leid <leid>] reid <reid>", - .function = lisp_gpe_fwd_entry_show, -}; -/* *INDENT-ON* */ - -clib_error_t * -lisp_gpe_fwd_entry_init (vlib_main_t * vm) -{ - lisp_gpe_main_t *lgm = &lisp_gpe_main; - clib_error_t *error = NULL; - - if ((error = vlib_call_init_function (vm, lisp_cp_dpo_module_init))) - return (error); - - l2_fib_init (lgm); - nsh_fib_init (lgm); - - fib_node_register_type (FIB_NODE_TYPE_LISP_GPE_FWD_ENTRY, &lisp_fwd_vft); - - return (error); -} - -u32 * -vnet_lisp_gpe_get_fwd_entry_vnis (void) -{ - lisp_gpe_main_t *lgm = vnet_lisp_gpe_get_main (); - lisp_gpe_fwd_entry_t *lfe; - u32 *vnis = 0; - - /* *INDENT-OFF* */ - pool_foreach (lfe, lgm->lisp_fwd_entry_pool, - ({ - hash_set (vnis, lfe->key->vni, 0); - })); - /* *INDENT-ON* */ - - return vnis; -} - -lisp_api_gpe_fwd_entry_t * -vnet_lisp_gpe_fwd_entries_get_by_vni (u32 vni) -{ - lisp_gpe_main_t *lgm = &lisp_gpe_main; - lisp_gpe_fwd_entry_t *lfe; - lisp_api_gpe_fwd_entry_t *entries = 0, e; - - /* *INDENT-OFF* */ - pool_foreach (lfe, lgm->lisp_fwd_entry_pool, - ({ - if (lfe->key->vni == vni) - { - clib_memset (&e, 0, sizeof (e)); - e.dp_table = lfe->eid_table_id; - e.vni = lfe->key->vni; - if (lfe->type == LISP_GPE_FWD_ENTRY_TYPE_NEGATIVE) - e.action = lfe->action; - e.fwd_entry_index = lfe - lgm->lisp_fwd_entry_pool; - memcpy (&e.reid, &lfe->key->rmt, sizeof (e.reid)); - memcpy (&e.leid, &lfe->key->lcl, sizeof (e.leid)); - vec_add1 (entries, e); - } - })); - /* *INDENT-ON* */ - - return entries; -} - -int -vnet_lisp_gpe_get_fwd_stats (vnet_lisp_gpe_add_del_fwd_entry_args_t * a, - vlib_counter_t * c) -{ - lisp_gpe_main_t *lgm = vnet_lisp_gpe_get_main (); - lisp_gpe_fwd_entry_t *lfe; - lisp_gpe_fwd_entry_key_t unused; - - lfe = find_fwd_entry (lgm, a, &unused); - if (NULL == lfe) - return -1; - - if (LISP_GPE_FWD_ENTRY_TYPE_NEGATIVE == lfe->type) - return -1; - - if (~0 == lfe->dpoi_index) - return -1; - - vlib_get_combined_counter (&load_balance_main.lbm_to_counters, - lfe->dpoi_index, c); - return 0; -} - -VLIB_INIT_FUNCTION (lisp_gpe_fwd_entry_init); - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/vnet/lisp-gpe/lisp_gpe_fwd_entry.h b/src/vnet/lisp-gpe/lisp_gpe_fwd_entry.h deleted file mode 100644 index dfdb8b911ae..00000000000 --- a/src/vnet/lisp-gpe/lisp_gpe_fwd_entry.h +++ /dev/null @@ -1,240 +0,0 @@ -/* - * Copyright (c) 2016 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. - */ -/** - * @file - * @brief LISP-GPE definitions. - */ - -#ifndef __LISP_GPE_FWD_ENTRY_H__ -#define __LISP_GPE_FWD_ENTRY_H__ - -#include <vnet/lisp-gpe/lisp_gpe.h> - -/** - * @brief A path on which to forward lisp traffic - */ -typedef struct lisp_fwd_path_t_ -{ - /** - * The adjacency constructed for the locator pair - */ - index_t lisp_adj; - - /** - * Priority. Only the paths with the best priority will be installed in FIB - */ - u8 priority; - - /** - * [UE]CMP weigt for the path - */ - u8 weight; - -} lisp_fwd_path_t; - -/** - * @brief A Forwarding entry can be 'normal' or 'negative' - * Negative implies we deliberately want to add a FIB entry for an EID - * that results in 'special' behaviour determined by an 'action'. - * @normal means send it down some tunnels. - */ -typedef enum lisp_gpe_fwd_entry_type_t_ -{ - LISP_GPE_FWD_ENTRY_TYPE_NORMAL, - LISP_GPE_FWD_ENTRY_TYPE_NEGATIVE, -} lisp_gpe_fwd_entry_type_t; - - -/** - * LISP-GPE fwd entry key - */ -typedef struct lisp_gpe_fwd_entry_key_t_ -{ - dp_address_t rmt; - dp_address_t lcl; - u32 vni; -} lisp_gpe_fwd_entry_key_t; - -/** - * @brief A LISP Forwarding Entry - * - * A forwarding entry is from a locai EID to a remote EID over a set of rloc pairs - */ -typedef struct lisp_gpe_fwd_entry_t_ -{ - /** - * Follows src/dst or dst only forwarding policy - */ - u8 is_src_dst; - - /** - * This object joins the FIB control plane graph to receive updates to - * for changes to the graph. - */ - fib_node_t node; - - /** - * The Entry's key: {lEID,rEID,vni} - */ - lisp_gpe_fwd_entry_key_t *key; - - /** - * The forwarding entry type - */ - lisp_gpe_fwd_entry_type_t type; - - /** - * The tenant the entry belongs to - */ - u32 tenant; - - /** - * The VRF (in the case of L3) or Bridge-Domain (for L2) index - */ - union - { - /** - * Fields relevant to an L2 entry - */ - struct - { - /** - * The VRF ID - */ - u32 eid_table_id; - - /** - * The FIB index for the overlay, i.e. the FIB in which the EIDs - * are present - */ - u32 eid_fib_index; - /** - * The SRC-FIB index for created for anding source-route entries - */ - u32 src_fib_index; - }; - /** - * Fields relevant to an L2 entry - */ - struct - { - /** - * The Bridge-Domain (for L2) index - */ - u32 eid_bd_id; - - /** - * The Bridge-domain index for the overlay EIDs - */ - u32 eid_bd_index; - - /** - * The path-list created for the forwarding - */ - fib_node_index_t path_list_index; - - /** - * Child index of this entry on the path-list - */ - u32 child_index; - - /** - * The DPO used to forward - */ - dpo_id_t dpo; - } l2; - - /** - * Fields relevant to an NSH entry - */ - struct - { - /** - * The path-list created for the forwarding - */ - fib_node_index_t path_list_index; - - /** - * Child index of this entry on the path-list - */ - u32 child_index; - - /** - * The DPO contributed by NSH - */ - dpo_id_t dpo; - - /** - * The DPO used for forwarding. Obtained after stacking tx node - * onto lb choice - */ - dpo_id_t choice; - } nsh; - }; - - union - { - /** - * @brief When the type is 'normal' - * The RLOC pair that form the route's paths. i.e. where to send - * packets for this route. - */ - lisp_fwd_path_t *paths; - - /** - * @brief When the type is negative. The action to take. - */ - negative_fwd_actions_e action; - }; - - /** - * used for getting load balance statistics - */ - index_t dpoi_index; - -} lisp_gpe_fwd_entry_t; - -extern int -vnet_lisp_gpe_add_del_fwd_entry (vnet_lisp_gpe_add_del_fwd_entry_args_t * a, - u32 * hw_if_indexp); - -extern void vnet_lisp_gpe_fwd_entry_flush (void); - -extern u32 lisp_l2_fib_lookup (lisp_gpe_main_t * lgm, - u16 bd_index, u8 src_mac[8], u8 dst_mac[8]); - -extern const dpo_id_t *lisp_nsh_fib_lookup (lisp_gpe_main_t * lgm, - u32 spi_si); -extern void -vnet_lisp_gpe_del_fwd_counters (vnet_lisp_gpe_add_del_fwd_entry_args_t * a, - u32 fwd_entry_index); -extern void -vnet_lisp_gpe_add_fwd_counters (vnet_lisp_gpe_add_del_fwd_entry_args_t * a, - u32 fwd_entry_index); -extern u32 *vnet_lisp_gpe_get_fwd_entry_vnis (void); - -int -vnet_lisp_gpe_get_fwd_stats (vnet_lisp_gpe_add_del_fwd_entry_args_t * a, - vlib_counter_t * c); - -#endif - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/vnet/lisp-gpe/lisp_gpe_packet.h b/src/vnet/lisp-gpe/lisp_gpe_packet.h deleted file mode 100644 index 62ac9bd7015..00000000000 --- a/src/vnet/lisp-gpe/lisp_gpe_packet.h +++ /dev/null @@ -1,149 +0,0 @@ -/* - * Copyright (c) 2016 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. - */ -/** - * @file - * @brief LISP-GPE packet header structure - * - */ - -#ifndef included_lisp_gpe_packet_h -#define included_lisp_gpe_packet_h - -/* - * From draft-lewis-lisp-gpe-02.txt - * - * 0 1 2 3 - * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * |N|L|E|V|I|P|R|O|Ver| Reserved | Next Protocol | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | Instance ID/Locator-Status-Bits | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * - * N: The N-bit is the nonce-present bit. When this bit is set to 1, - * the low-order 24 bits of the first 32 bits of the LISP header - * contain a Nonce. See Section 6.3.1 for details. Both N- and - * V-bits MUST NOT be set in the same packet. If they are, a - * decapsulating ETR MUST treat the 'Nonce/Map-Version' field as - * having a Nonce value present. - * - * L: The L-bit is the 'Locator-Status-Bits' field enabled bit. When - * this bit is set to 1, the Locator-Status-Bits in the second - * 32 bits of the LISP header are in use. - * - * E: The E-bit is the echo-nonce-request bit. This bit MUST be ignored - * and has no meaning when the N-bit is set to 0. When the N-bit is - * set to 1 and this bit is set to 1, an ITR is requesting that the - * nonce value in the 'Nonce' field be echoed back in LISP- - * encapsulated packets when the ITR is also an ETR. See - * Section 6.3.1 for details. - * - * V: The V-bit is the Map-Version present bit. When this bit is set to - * 1, the N-bit MUST be 0. Refer to Section 6.6.3 for more details. - * - * I: The I-bit is the Instance ID bit. See Section 5.5 for more - * details. When this bit is set to 1, the 'Locator-Status-Bits' - * field is reduced to 8 bits and the high-order 24 bits are used as - * an Instance ID. If the L-bit is set to 0, then the low-order - * 8 bits are transmitted as zero and ignored on receipt. - * - * P Bit: Flag bit 5 is defined as the Next Protocol bit. The P bit - * MUST be set to 1 to indicate the presence of the 8 bit next - * protocol field. - * - * P = 0 indicates that the payload MUST conform to LISP as defined - * in [RFC6830]. - * - * Flag bit 5 was chosen as the P bit because this flag bit is - * currently unallocated in LISP [RFC6830]. - * - * O: Flag bit 7 is defined as the O bit. When the O bit is set to 1, the - * packet is an OAM packet and OAM processing MUST occur. The OAM - * protocol details are out of scope for this document. As with the - * P-bit, bit 7 is currently a reserved flag in [RFC6830]. - * - * Next Protocol Field: The lower 8 bits of the first word are used to - * carry a next protocol. This next protocol field contains the - * protocol of the encapsulated payload packet. - * - * LISP [RFC6830] uses the lower 16 bits of the first word for either - * a nonce, an echo-nonce ([RFC6830]) or to support map-versioning - * ([RFC6834]). These are all optional capabilities that are - * indicated by setting the N, E, and the V bit respectively. - * - * To maintain the desired data plane compatibility, when the P bit - * is set, the N, E, and V bits MUST be set to zero. - * - * A new protocol registry will be requested from IANA for the Next - * Protocol field. This draft defines the following Next Protocol - * values: - * - * 0x1 : IPv4 - * 0x2 : IPv6 - * 0x3 : Ethernet - * 0x4: Network Service Header - */ - -/** LISP-GPE header */ -typedef struct -{ - u8 flags; - u8 ver_res; - u8 res; - u8 next_protocol; - u32 iid; -} lisp_gpe_header_t; - -#define foreach_lisp_gpe_flag_bit \ -_(N, 0x80) \ -_(L, 0x40) \ -_(E, 0x20) \ -_(V, 0x10) \ -_(I, 0x08) \ -_(P, 0x04) \ -_(O, 0x01) - -typedef enum -{ -#define _(n,v) LISP_GPE_FLAGS_##n = v, - foreach_lisp_gpe_flag_bit -#undef _ -} vnet_lisp_gpe_flag_bit_t; - -#define LISP_GPE_VERSION 0x0 - -#define LISP_GPE_NEXT_PROTOCOL_IP4 0x1 -#define LISP_GPE_NEXT_PROTOCOL_IP6 0x2 -#define LISP_GPE_NEXT_PROTOCOL_ETHERNET 0x3 -#define LISP_GPE_NEXT_PROTOCOL_NSH 0x4 - -typedef enum -{ - LISP_GPE_NEXT_PROTO_IP4 = 1, - LISP_GPE_NEXT_PROTO_IP6, - LISP_GPE_NEXT_PROTO_ETHERNET, - LISP_GPE_NEXT_PROTO_NSH, - LISP_GPE_NEXT_PROTOS -} lisp_gpe_next_protocol_e; - -#endif /* included_lisp_gpe_packet_h */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/vnet/lisp-gpe/lisp_gpe_sub_interface.c b/src/vnet/lisp-gpe/lisp_gpe_sub_interface.c deleted file mode 100644 index 1ccd5817d7f..00000000000 --- a/src/vnet/lisp-gpe/lisp_gpe_sub_interface.c +++ /dev/null @@ -1,286 +0,0 @@ -/* - * Copyright (c) 2016 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. - */ -/** - * @file - * @brief LISP sub-interfaces. - * - */ -#include <vnet/lisp-gpe/lisp_gpe_tenant.h> -#include <vnet/lisp-gpe/lisp_gpe_sub_interface.h> -#include <vnet/fib/fib_table.h> -#include <vnet/interface.h> - -/** - * @brief Pool of all l3-sub-interfaces - */ -static lisp_gpe_sub_interface_t *lisp_gpe_sub_interface_pool; - -/** - * A DB of all LISP L3 sub-interfaces. The key is:{VNI,l-RLOC} - */ -static uword *lisp_gpe_sub_interfaces; - -/** - * A DB of all VNET L3 sub-interfaces. The key is:{VNI,l-RLOC} - * Used in the data-plane for interface lookup on decap. - */ -uword *lisp_gpe_sub_interfaces_sw_if_index; - -/** - * The next available sub-interface ID. FIXME - */ -static u32 lisp_gpe_sub_interface_id; - - -static index_t -lisp_gpe_sub_interface_db_find (const ip_address_t * lrloc, u32 vni) -{ - uword *p; - - lisp_gpe_sub_interface_key_t key; - - clib_memset (&key, 0, sizeof (key)); - ip_address_copy (&key.local_rloc, lrloc); - key.vni = vni; - p = hash_get_mem (lisp_gpe_sub_interfaces, &key); - - if (NULL == p) - return (INDEX_INVALID); - else - return (p[0]); -} - -static void -lisp_gpe_sub_interface_db_insert (const lisp_gpe_sub_interface_t * l3s) -{ - hash_set_mem (lisp_gpe_sub_interfaces, - l3s->key, l3s - lisp_gpe_sub_interface_pool); - hash_set_mem (lisp_gpe_sub_interfaces_sw_if_index, - l3s->key, l3s->sw_if_index); -} - -static void -lisp_gpe_sub_interface_db_remove (const lisp_gpe_sub_interface_t * l3s) -{ - hash_unset_mem (lisp_gpe_sub_interfaces, l3s->key); - hash_unset_mem (lisp_gpe_sub_interfaces_sw_if_index, l3s->key); -} - -lisp_gpe_sub_interface_t * -lisp_gpe_sub_interface_get_i (index_t l3si) -{ - return (pool_elt_at_index (lisp_gpe_sub_interface_pool, l3si)); -} - -static void -lisp_gpe_sub_interface_set_table (u32 sw_if_index, u32 table_id) -{ - fib_node_index_t fib_index; - - fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4, table_id, - FIB_SOURCE_LISP); - ASSERT (FIB_NODE_INDEX_INVALID != fib_index); - - vec_validate (ip4_main.fib_index_by_sw_if_index, sw_if_index); - ip4_main.fib_index_by_sw_if_index[sw_if_index] = fib_index; - - fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP6, table_id, - FIB_SOURCE_LISP); - ASSERT (FIB_NODE_INDEX_INVALID != fib_index); - - vec_validate (ip6_main.fib_index_by_sw_if_index, sw_if_index); - ip6_main.fib_index_by_sw_if_index[sw_if_index] = fib_index; -} - -static void -lisp_gpe_sub_interface_unset_table (u32 sw_if_index, u32 table_id) -{ - fib_table_unlock (ip4_main.fib_index_by_sw_if_index[sw_if_index], - FIB_PROTOCOL_IP4, FIB_SOURCE_LISP); - ip4_main.fib_index_by_sw_if_index[sw_if_index] = 0; - ip4_sw_interface_enable_disable (sw_if_index, 0); - - fib_table_unlock (ip6_main.fib_index_by_sw_if_index[sw_if_index], - FIB_PROTOCOL_IP6, FIB_SOURCE_LISP); - ip6_main.fib_index_by_sw_if_index[sw_if_index] = 0; - ip6_sw_interface_enable_disable (sw_if_index, 0); -} - -index_t -lisp_gpe_sub_interface_find_or_create_and_lock (const ip_address_t * lrloc, - u32 overlay_table_id, u32 vni) -{ - lisp_gpe_sub_interface_t *l3s; - index_t l3si; - - l3si = lisp_gpe_sub_interface_db_find (lrloc, vni); - - if (INDEX_INVALID == l3si) - { - u32 main_sw_if_index, sub_sw_if_index; - - /* - * find the main interface from the VNI - */ - main_sw_if_index = - lisp_gpe_tenant_l3_iface_add_or_lock (vni, overlay_table_id, - 1 /* with_default_route */ ); - - vnet_sw_interface_t sub_itf_template = { - .type = VNET_SW_INTERFACE_TYPE_SUB, - .flood_class = VNET_FLOOD_CLASS_NORMAL, - .sup_sw_if_index = main_sw_if_index, - .sub.id = lisp_gpe_sub_interface_id++, - }; - - if (NULL != vnet_create_sw_interface (vnet_get_main (), - &sub_itf_template, - &sub_sw_if_index)) - return (INDEX_INVALID); - - pool_get (lisp_gpe_sub_interface_pool, l3s); - clib_memset (l3s, 0, sizeof (*l3s)); - l3s->key = clib_mem_alloc (sizeof (*l3s->key)); - clib_memset (l3s->key, 0, sizeof (*l3s->key)); - - ip_address_copy (&l3s->key->local_rloc, lrloc); - l3s->key->vni = vni; - l3s->main_sw_if_index = main_sw_if_index; - l3s->sw_if_index = sub_sw_if_index; - l3s->eid_table_id = overlay_table_id; - - l3si = (l3s - lisp_gpe_sub_interface_pool); - - // FIXME. enable When we get an adj - ip6_sw_interface_enable_disable (l3s->sw_if_index, 1); - ip4_sw_interface_enable_disable (l3s->sw_if_index, 1); - - vnet_sw_interface_set_flags (vnet_get_main (), - l3s->sw_if_index, - VNET_SW_INTERFACE_FLAG_ADMIN_UP); - - lisp_gpe_sub_interface_db_insert (l3s); - } - else - { - l3s = lisp_gpe_sub_interface_get_i (l3si); - l3s->eid_table_id = overlay_table_id; - } - - lisp_gpe_sub_interface_set_table (l3s->sw_if_index, l3s->eid_table_id); - l3s->locks++; - - return (l3si); -} - -void -lisp_gpe_sub_interface_unlock (index_t l3si) -{ - lisp_gpe_sub_interface_t *l3s; - - l3s = lisp_gpe_sub_interface_get_i (l3si); - - ASSERT (0 != l3s->locks); - l3s->locks--; - - if (0 == l3s->locks) - { - lisp_gpe_sub_interface_unset_table (l3s->sw_if_index, - l3s->eid_table_id); - - lisp_gpe_tenant_l3_iface_unlock (l3s->key->vni); - vnet_sw_interface_set_flags (vnet_get_main (), l3s->sw_if_index, 0); - vnet_delete_sub_interface (l3s->sw_if_index); - - lisp_gpe_sub_interface_db_remove (l3s); - - clib_mem_free (l3s->key); - pool_put (lisp_gpe_sub_interface_pool, l3s); - } -} - -const lisp_gpe_sub_interface_t * -lisp_gpe_sub_interface_get (index_t l3si) -{ - return (lisp_gpe_sub_interface_get_i (l3si)); -} - -u8 * -format_lisp_gpe_sub_interface (u8 * s, va_list * ap) -{ - lisp_gpe_sub_interface_t *l3s = va_arg (*ap, lisp_gpe_sub_interface_t *); - vnet_main_t *vnm = vnet_get_main (); - - s = format (s, "%-16U", - format_vnet_sw_interface_name, - vnm, vnet_get_sw_interface (vnm, l3s->sw_if_index)); - s = format (s, "%=8d", l3s->key->vni); - s = format (s, "%=15d", l3s->sw_if_index); - s = format (s, "%U", format_ip_address, &l3s->key->local_rloc); - - return (s); -} - -/** CLI command to show LISP-GPE interfaces. */ -static clib_error_t * -lisp_gpe_sub_interface_show (vlib_main_t * vm, - unformat_input_t * input, - vlib_cli_command_t * cmd) -{ - lisp_gpe_sub_interface_t *l3s; - - vlib_cli_output (vm, "%-16s%=8s%=15s%s", "Name", "VNI", "sw_if_index", - "local RLOC"); - - /* *INDENT-OFF* */ - pool_foreach (l3s, lisp_gpe_sub_interface_pool, - ({ - vlib_cli_output (vm, "%U", format_lisp_gpe_sub_interface, l3s); - })); - /* *INDENT-ON* */ - - return 0; -} - -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND (lisp_gpe_sub_interface_command) = { - .path = "show gpe sub-interface", - .short_help = "show gpe sub-interface", - .function = lisp_gpe_sub_interface_show, -}; -/* *INDENT-ON* */ - -static clib_error_t * -lisp_gpe_sub_interface_module_init (vlib_main_t * vm) -{ - lisp_gpe_sub_interfaces = - hash_create_mem (0, - sizeof (lisp_gpe_sub_interface_key_t), sizeof (uword)); - lisp_gpe_sub_interfaces_sw_if_index = - hash_create_mem (0, - sizeof (lisp_gpe_sub_interface_key_t), sizeof (uword)); - - return (NULL); -} - -VLIB_INIT_FUNCTION (lisp_gpe_sub_interface_module_init); - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/vnet/lisp-gpe/lisp_gpe_sub_interface.h b/src/vnet/lisp-gpe/lisp_gpe_sub_interface.h deleted file mode 100644 index 7375bf00ccc..00000000000 --- a/src/vnet/lisp-gpe/lisp_gpe_sub_interface.h +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Copyright (c) 2016 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. - */ -/** - * @file - * @brief LISP sub-interfaces. - * - */ - -#ifndef __LISP_GPE_SUB_INTERFACE_H__ -#define __LISP_GPE_SUB_INTERFACE_H__ - -#include <vnet/lisp-gpe/lisp_gpe.h> - -/** - * A Key for lookup in the L£ sub-interface DB - */ -typedef struct lisp_gpe_sub_interface_key_t_ -{ - /** - * The local-RLOC. This is the interface's 'source' address. - */ - ip_address_t local_rloc; - - /** - * The VNI. In network byte order! - */ - u32 vni; -} lisp_gpe_sub_interface_key_t; - -/** - * @brief A LISP L3 sub-interface - * - * A LISP sub-interface is a multi-access interface, whose local address is a - * single local-RLOC. Adjacencies that form on this sub-interface, represent - * remote RLOCs. - * This is analogous to an ethernet interface. - * As with all interface types it can only be present in one VRF, hence a - * LISP sub-interface is per-local-rloc and per-VNI. - */ -typedef struct lisp_gpe_sub_interface_t_ -{ - /** - * The interface's key inthe DB; rloc & vni; - * The key is allocated from the heap so it can be used in the hash-table. - * if it's part of the object, then it is subjet to realloc, which no-worky. - */ - lisp_gpe_sub_interface_key_t *key; - - /** - * The Table-ID in the overlay that this interface is bound to. - */ - u32 eid_table_id; - - /** - * A reference counting lock on the number of users of this interface. - * When this count drops to 0 the interface is deleted. - */ - u32 locks; - - /** - * The SW if index assigned to this sub-interface - */ - u32 sw_if_index; - - /** - * The SW IF index assigned to the main interface of which this is a sub. - */ - u32 main_sw_if_index; -} lisp_gpe_sub_interface_t; - -extern index_t lisp_gpe_sub_interface_find_or_create_and_lock (const - ip_address_t * - lrloc, - u32 - eid_table_id, - u32 vni); - -extern u8 *format_lisp_gpe_sub_interface (u8 * s, va_list * ap); - -extern void lisp_gpe_sub_interface_unlock (index_t itf); - -extern const lisp_gpe_sub_interface_t *lisp_gpe_sub_interface_get (index_t - itf); - -/** - * A DB of all L3 sub-interfaces. The key is:{VNI,l-RLOC} - */ -extern uword *lisp_gpe_sub_interfaces_sw_if_index; - -/** - * @brief - * Get a VNET L3 interface matching the local-RLOC and VNI - * Called from the data-plane - */ -always_inline u32 -lisp_gpe_sub_interface_find_ip6 (const ip6_address_t * addr, u32 vni) -{ - lisp_gpe_sub_interface_key_t key; - const uword *p; - - ip_addr_v6 (&key.local_rloc).as_u64[0] = addr->as_u64[0]; - ip_addr_v6 (&key.local_rloc).as_u64[1] = addr->as_u64[1]; - ip_addr_version (&key.local_rloc) = AF_IP6; - key.vni = vni; - - p = hash_get_mem (&lisp_gpe_sub_interfaces_sw_if_index, &key); - - if (NULL != p) - return p[0]; - - return (INDEX_INVALID); -} - -/** - * @brief - * Get a VNET L3 interface matching the local-RLOC and VNI - * Called from the data-plane - */ -always_inline index_t -lisp_gpe_sub_interface_find_ip4 (const ip4_address_t * addr, u32 vni) -{ - lisp_gpe_sub_interface_key_t key; - const uword *p; - - ip_addr_v4 (&key.local_rloc).as_u32 = addr->as_u32; - key.local_rloc.version = AF_IP4; - key.vni = vni; - - p = hash_get_mem (&lisp_gpe_sub_interfaces_sw_if_index, &key); - - if (NULL != p) - return p[0]; - - return (INDEX_INVALID); -} - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ - -#endif diff --git a/src/vnet/lisp-gpe/lisp_gpe_tenant.c b/src/vnet/lisp-gpe/lisp_gpe_tenant.c deleted file mode 100644 index e2a310c043c..00000000000 --- a/src/vnet/lisp-gpe/lisp_gpe_tenant.c +++ /dev/null @@ -1,333 +0,0 @@ -/* - * Copyright (c) 2016 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 <vnet/lisp-gpe/lisp_gpe_tenant.h> - -/** - * The pool of all tenants - */ -static lisp_gpe_tenant_t *lisp_gpe_tenant_pool; - -/** - * The hash table of all tenants: key:{VNI}. - */ -uword *lisp_gpe_tenant_db; - -static lisp_gpe_tenant_t * -lisp_gpe_tenant_find (u32 vni) -{ - uword *p; - - p = hash_get (lisp_gpe_tenant_db, vni); - - if (NULL == p) - return (NULL); - - return (pool_elt_at_index (lisp_gpe_tenant_pool, p[0])); -} - -static lisp_gpe_tenant_t * -lisp_gpe_tenant_find_or_create_i (u32 vni) -{ - lisp_gpe_tenant_t *lt; - - lt = lisp_gpe_tenant_find (vni); - - if (NULL == lt) - { - pool_get (lisp_gpe_tenant_pool, lt); - clib_memset (lt, 0, sizeof (*lt)); - - lt->lt_vni = vni; - lt->lt_table_id = ~0; - lt->lt_bd_id = ~0; - - hash_set (lisp_gpe_tenant_db, vni, lt - lisp_gpe_tenant_pool); - } - - return (lt); -} - -/** - * @brief Find or create a tenant for the given VNI - */ -u32 -lisp_gpe_tenant_find_or_create (u32 vni) -{ - lisp_gpe_tenant_t *lt; - - lt = lisp_gpe_tenant_find (vni); - - if (NULL == lt) - { - lt = lisp_gpe_tenant_find_or_create_i (vni); - } - - return (lt - lisp_gpe_tenant_pool); -} - -/** - * @brief If there are no more locks/users of te tenant, then delete it - */ -static void -lisp_gpe_tenant_delete_if_empty (lisp_gpe_tenant_t * lt) -{ - int i; - - for (i = 0; i < LISP_GPE_TENANT_LOCK_NUM; i++) - { - if (lt->lt_locks[i]) - return; - } - - hash_unset (lisp_gpe_tenant_db, lt->lt_vni); - pool_put (lisp_gpe_tenant_pool, lt); -} - -/** - * @brief Add/create and lock a new or find and lock the existing L3 - * interface for the tenant - * - * @paran vni The tenant's VNI - * @param table_id the Tenant's L3 table ID. - * @param with_default_route Install default route for the interface - * - * @return the SW IF index of the L3 interface - */ -u32 -lisp_gpe_tenant_l3_iface_add_or_lock (u32 vni, u32 table_id, - u8 with_default_route) -{ - lisp_gpe_tenant_t *lt; - - lt = lisp_gpe_tenant_find_or_create_i (vni); - - if (~0 == lt->lt_table_id) - lt->lt_table_id = table_id; - - ASSERT (lt->lt_table_id == table_id); - - if (0 == lt->lt_locks[LISP_GPE_TENANT_LOCK_L3_IFACE]) - { - /* create the l3 interface since there are currently no users of it */ - lt->lt_l3_sw_if_index = - lisp_gpe_add_l3_iface (&lisp_gpe_main, vni, table_id, - with_default_route); - } - - lt->lt_locks[LISP_GPE_TENANT_LOCK_L3_IFACE]++; - - return (lt->lt_l3_sw_if_index); -} - -/** - * @brief Release the lock held on the tenant's L3 interface - */ -void -lisp_gpe_tenant_l3_iface_unlock (u32 vni) -{ - lisp_gpe_tenant_t *lt; - - lt = lisp_gpe_tenant_find (vni); - - if (NULL == lt) - { - clib_warning ("No tenant for VNI %d", vni); - return; - } - - if (0 == lt->lt_locks[LISP_GPE_TENANT_LOCK_L3_IFACE]) - { - clib_warning ("No L3 interface for tenant VNI %d", vni); - return; - } - - lt->lt_locks[LISP_GPE_TENANT_LOCK_L3_IFACE]--; - - if (0 == lt->lt_locks[LISP_GPE_TENANT_LOCK_L3_IFACE]) - { - /* the last user has gone, so delete the l3 interface */ - lisp_gpe_del_l3_iface (&lisp_gpe_main, vni, lt->lt_table_id); - } - - /* - * If there are no more locks on any tenant managed resource, then - * this tenant is toast. - */ - lisp_gpe_tenant_delete_if_empty (lt); -} - -/** - * @brief Add/create and lock a new or find and lock the existing L2 - * interface for the tenant - * - * @paran vni The tenant's VNI - * @param table_id the Tenant's L2 Bridge Domain ID. - * - * @return the SW IF index of the L2 interface - */ -u32 -lisp_gpe_tenant_l2_iface_add_or_lock (u32 vni, u32 bd_id) -{ - lisp_gpe_tenant_t *lt; - - lt = lisp_gpe_tenant_find_or_create_i (vni); - - if (NULL == lt) - { - clib_warning ("No tenant for VNI %d", vni); - return ~0; - } - - if (~0 == lt->lt_bd_id) - lt->lt_bd_id = bd_id; - - ASSERT (lt->lt_bd_id == bd_id); - - if (0 == lt->lt_locks[LISP_GPE_TENANT_LOCK_L2_IFACE]) - { - /* create the l2 interface since there are currently no users of it */ - lt->lt_l2_sw_if_index = - lisp_gpe_add_l2_iface (&lisp_gpe_main, vni, bd_id); - } - - lt->lt_locks[LISP_GPE_TENANT_LOCK_L2_IFACE]++; - - return (lt->lt_l2_sw_if_index); -} - -/** - * @brief Release the lock held on the tenant's L3 interface - */ -void -lisp_gpe_tenant_l2_iface_unlock (u32 vni) -{ - lisp_gpe_tenant_t *lt; - - lt = lisp_gpe_tenant_find (vni); - - if (NULL == lt) - { - clib_warning ("No tenant for VNI %d", vni); - return; - } - - if (0 == lt->lt_locks[LISP_GPE_TENANT_LOCK_L2_IFACE]) - { - clib_warning ("No L2 interface for tenant VNI %d", vni); - return; - } - - lt->lt_locks[LISP_GPE_TENANT_LOCK_L2_IFACE]--; - - if (0 == lt->lt_locks[LISP_GPE_TENANT_LOCK_L2_IFACE]) - { - /* the last user has gone, so delete the l2 interface */ - lisp_gpe_del_l2_iface (&lisp_gpe_main, vni, lt->lt_bd_id); - } - - /* - * If there are no more locks on any tenant managed resource, then - * this tenant is toast. - */ - lisp_gpe_tenant_delete_if_empty (lt); -} - -/** - * @brief get a const pointer to the tenant object - */ -const lisp_gpe_tenant_t * -lisp_gpe_tenant_get (u32 index) -{ - return (pool_elt_at_index (lisp_gpe_tenant_pool, index)); -} - -/** - * @brief Flush/delete ALL the tenants - */ -void -lisp_gpe_tenant_flush (void) -{ - lisp_gpe_tenant_t *lt; - - /* *INDENT-OFF* */ - pool_foreach(lt, lisp_gpe_tenant_pool, - ({ - lisp_gpe_tenant_l2_iface_unlock(lt->lt_vni); - lisp_gpe_tenant_l3_iface_unlock(lt->lt_vni); - })); - /* *INDENT-ON* */ -} - -/** - * @brief Show/display one tenant - */ -static u8 * -format_lisp_gpe_tenant (u8 * s, va_list * ap) -{ - const lisp_gpe_tenant_t *lt = va_arg (*ap, lisp_gpe_tenant_t *); - - s = format (s, "VNI:%d ", lt->lt_vni); - - if (lt->lt_table_id != ~0) - { - s = format (s, "VRF:%d ", lt->lt_table_id); - s = format (s, "L3-SW-IF:%d ", lt->lt_l3_sw_if_index); - } - - if (lt->lt_bd_id != ~0) - { - s = format (s, "BD-ID:%d ", lt->lt_bd_id); - s = format (s, "L2-SW-IF:%d ", lt->lt_l2_sw_if_index); - } - - return (s); -} - -/** - * @brief CLI command to show LISP-GPE tenant. - */ -static clib_error_t * -lisp_gpe_tenant_show (vlib_main_t * vm, - unformat_input_t * input, vlib_cli_command_t * cmd) -{ - lisp_gpe_tenant_t *lt; - - /* *INDENT-OFF* */ - pool_foreach (lt, lisp_gpe_tenant_pool, - ({ - vlib_cli_output (vm, "%U", format_lisp_gpe_tenant, lt); - })); - /* *INDENT-ON* */ - - return 0; -} - -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND (lisp_gpe_tenant_command) = { - .path = "show gpe tenant", - .short_help = "show gpe tenant", - .function = lisp_gpe_tenant_show, -}; -/* *INDENT-ON* */ - - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/vnet/lisp-gpe/lisp_gpe_tenant.h b/src/vnet/lisp-gpe/lisp_gpe_tenant.h deleted file mode 100644 index a9271da91f5..00000000000 --- a/src/vnet/lisp-gpe/lisp_gpe_tenant.h +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (c) 2016 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. - */ - -#ifndef __LISP_GPE_TENANT_H__ -#define __LISP_GPE_TENANT_H__ - -#include <vnet/lisp-gpe/lisp_gpe.h> - -/** - * Refernece counting lock types on the tenant. - * When all of these counters drop to zero, we no longer need the tenant. - */ -typedef enum lisp_gpe_tenant_lock_t_ -{ - LISP_GPE_TENANT_LOCK_L2_IFACE, - LISP_GPE_TENANT_LOCK_L3_IFACE, - LISP_GPE_TENANT_LOCK_NUM, -} lisp_gpe_tenant_lock_t; - -/** - * @brief Representation of the data associated with a LISP overlay tenant - * - * This object exists to manage the shared resources of the L2 and L3 interface - * of a given tenant. - */ -typedef struct lisp_gpe_tenant_t_ -{ - /** - * The VNI is the identifier of the tenant - */ - u32 lt_vni; - - /** - * The tenant can have both L2 and L3 services enabled. - */ - u32 lt_table_id; - u32 lt_bd_id; - - /** - * The number of locks on the tenant's L3 interface. - */ - u32 lt_locks[LISP_GPE_TENANT_LOCK_NUM]; - - /** - * The L3 SW interface index - */ - u32 lt_l3_sw_if_index; - - /** - * The L2 SW interface index - */ - u32 lt_l2_sw_if_index; - -} lisp_gpe_tenant_t; - -extern u32 lisp_gpe_tenant_find_or_create (u32 vni); - -extern u32 lisp_gpe_tenant_l3_iface_add_or_lock (u32 vni, u32 vrf, - u8 with_default_route); -extern void lisp_gpe_tenant_l3_iface_unlock (u32 vni); - -extern u32 lisp_gpe_tenant_l2_iface_add_or_lock (u32 vni, u32 vrf); -extern void lisp_gpe_tenant_l2_iface_unlock (u32 vni); - -extern const lisp_gpe_tenant_t *lisp_gpe_tenant_get (u32 index); - -extern void lisp_gpe_tenant_flush (void); - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ - -#endif diff --git a/src/vnet/lisp-gpe/lisp_gpe_tunnel.c b/src/vnet/lisp-gpe/lisp_gpe_tunnel.c deleted file mode 100644 index 0373542ba34..00000000000 --- a/src/vnet/lisp-gpe/lisp_gpe_tunnel.c +++ /dev/null @@ -1,293 +0,0 @@ -/* - * Copyright (c) 2016 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. - */ -/** - * @file - * @brief Common utility functions for IPv4, IPv6 and L2 LISP-GPE tunnels. - * - */ -#include <vnet/lisp-gpe/lisp_gpe.h> -#include <vnet/lisp-gpe/lisp_gpe_tunnel.h> -#include <vnet/lisp-gpe/lisp_gpe_adjacency.h> - -#include <vnet/fib/fib_table.h> - -/** - * @brief Pool of all LISP tunnels - */ -static lisp_gpe_tunnel_t *lisp_gpe_tunnel_pool; - -/** - * @brief a DB of all tunnels - */ -static uword *lisp_gpe_tunnel_db; - -/** - * @brief Compute IP-UDP-GPE sub-tunnel encap/rewrite header. - * - * @param[in] t Parent of the sub-tunnel. - * @param[in] st Sub-tunnel. - * @param[in] lp Local and remote locators used in the encap header. - * - * @return 0 on success. - */ -u8 * -lisp_gpe_tunnel_build_rewrite (const lisp_gpe_tunnel_t * lgt, - const lisp_gpe_adjacency_t * ladj, - lisp_gpe_next_protocol_e payload_proto) -{ - lisp_gpe_header_t *lisp0; - u8 *rw = 0; - int len; - gpe_encap_mode_t encap_mode = vnet_gpe_get_encap_mode (); - - if (AF_IP4 == ip_addr_version (&lgt->key->lcl)) - { - ip4_udp_lisp_gpe_header_t *h0; - ip4_header_t *ip0; - - len = sizeof (*h0); - - vec_validate_aligned (rw, len - 1, CLIB_CACHE_LINE_BYTES); - - h0 = (ip4_udp_lisp_gpe_header_t *) rw; - - /* Fixed portion of the (outer) ip4 header */ - ip0 = &h0->ip4; - ip0->ip_version_and_header_length = 0x45; - ip0->ttl = 254; - ip0->protocol = IP_PROTOCOL_UDP; - - /* we fix up the ip4 header length and checksum after-the-fact */ - ip_address_copy_addr (&ip0->src_address, &lgt->key->lcl); - ip_address_copy_addr (&ip0->dst_address, &lgt->key->rmt); - ip0->checksum = ip4_header_checksum (ip0); - - /* UDP header, randomize src port on something, maybe? */ - h0->udp.src_port = clib_host_to_net_u16 (4341); - h0->udp.dst_port = clib_host_to_net_u16 (UDP_DST_PORT_lisp_gpe); - - /* LISP-gpe header */ - lisp0 = &h0->lisp; - } - else - { - ip6_udp_lisp_gpe_header_t *h0; - ip6_header_t *ip0; - - len = sizeof (*h0); - - vec_validate_aligned (rw, len - 1, CLIB_CACHE_LINE_BYTES); - - h0 = (ip6_udp_lisp_gpe_header_t *) rw; - - /* Fixed portion of the (outer) ip6 header */ - ip0 = &h0->ip6; - ip0->ip_version_traffic_class_and_flow_label = - clib_host_to_net_u32 (0x6 << 28); - ip0->hop_limit = 254; - ip0->protocol = IP_PROTOCOL_UDP; - - /* we fix up the ip6 header length after-the-fact */ - ip_address_copy_addr (&ip0->src_address, &lgt->key->lcl); - ip_address_copy_addr (&ip0->dst_address, &lgt->key->rmt); - - /* UDP header, randomize src port on something, maybe? */ - h0->udp.src_port = clib_host_to_net_u16 (4341); - h0->udp.dst_port = clib_host_to_net_u16 (UDP_DST_PORT_lisp_gpe); - - /* LISP-gpe header */ - lisp0 = &h0->lisp; - } - - lisp0->flags = ladj->flags; - if (GPE_ENCAP_VXLAN == encap_mode) - /* unset P flag */ - lisp0->flags &= ~LISP_GPE_FLAGS_P; - - lisp0->ver_res = 0; - lisp0->res = 0; - lisp0->next_protocol = payload_proto; - lisp0->iid = clib_host_to_net_u32 (ladj->vni) >> 8; /* first 24 bits only */ - - return (rw); -} - -static lisp_gpe_tunnel_t * -lisp_gpe_tunnel_db_find (const lisp_gpe_tunnel_key_t * key) -{ - uword *p; - - p = hash_get_mem (lisp_gpe_tunnel_db, (void *) key); - - if (NULL != p) - { - return (pool_elt_at_index (lisp_gpe_tunnel_pool, p[0])); - } - return (NULL); -} - -lisp_gpe_tunnel_t * -lisp_gpe_tunnel_get_i (index_t lgti) -{ - return (pool_elt_at_index (lisp_gpe_tunnel_pool, lgti)); -} - -index_t -lisp_gpe_tunnel_find_or_create_and_lock (const locator_pair_t * pair, - u32 rloc_fib_index) -{ - lisp_gpe_tunnel_key_t key = { - .lcl = pair->lcl_loc, - .rmt = pair->rmt_loc, - .fib_index = rloc_fib_index, - }; - lisp_gpe_tunnel_t *lgt; - fib_prefix_t pfx; - - lgt = lisp_gpe_tunnel_db_find (&key); - - if (NULL == lgt) - { - pool_get (lisp_gpe_tunnel_pool, lgt); - clib_memset (lgt, 0, sizeof (*lgt)); - - lgt->key = clib_mem_alloc (sizeof (*lgt->key)); - clib_memset (lgt->key, 0, sizeof (*lgt->key)); - - lgt->key->rmt = pair->rmt_loc; - lgt->key->lcl = pair->lcl_loc; - lgt->key->fib_index = rloc_fib_index; - - /* - * source the FIB entry for the RLOC so we can track its forwarding - * chain - */ - ip_address_to_fib_prefix (&lgt->key->rmt, &pfx); - - lgt->fib_entry_index = fib_table_entry_special_add (rloc_fib_index, - &pfx, - FIB_SOURCE_RR, - FIB_ENTRY_FLAG_NONE); - - hash_set_mem (lisp_gpe_tunnel_db, lgt->key, - (lgt - lisp_gpe_tunnel_pool)); - } - - lgt->locks++; - - return (lgt - lisp_gpe_tunnel_pool); -} - -void -lisp_gpe_tunnel_unlock (index_t lgti) -{ - lisp_gpe_tunnel_t *lgt; - - lgt = lisp_gpe_tunnel_get_i (lgti); - lgt->locks--; - - if (0 == lgt->locks) - { - hash_unset_mem (lisp_gpe_tunnel_db, lgt->key); - clib_mem_free (lgt->key); - pool_put (lisp_gpe_tunnel_pool, lgt); - } -} - -const lisp_gpe_tunnel_t * -lisp_gpe_tunnel_get (index_t lgti) -{ - return (lisp_gpe_tunnel_get_i (lgti)); -} - -/** Format LISP-GPE tunnel. */ -u8 * -format_lisp_gpe_tunnel (u8 * s, va_list * args) -{ - lisp_gpe_tunnel_t *lgt = va_arg (*args, lisp_gpe_tunnel_t *); - - s = format (s, "tunnel %d\n", lgt - lisp_gpe_tunnel_pool); - s = format (s, " fib-index: %d, locks:%d \n", - lgt->key->fib_index, lgt->locks); - s = format (s, " lisp ver 0\n"); - - s = format (s, " locator-pair:\n"); - s = format (s, " local: %U remote: %U\n", - format_ip_address, &lgt->key->lcl, - format_ip_address, &lgt->key->rmt); - s = format (s, " RLOC FIB entry: %d\n", lgt->fib_entry_index); - - return s; -} - -/** - * CLI command to show LISP-GPE tunnels. - */ -static clib_error_t * -show_lisp_gpe_tunnel_command_fn (vlib_main_t * vm, - unformat_input_t * input, - vlib_cli_command_t * cmd) -{ - lisp_gpe_tunnel_t *lgt; - index_t index; - - if (pool_elts (lisp_gpe_tunnel_pool) == 0) - vlib_cli_output (vm, "No lisp-gpe tunnels configured..."); - - if (unformat (input, "%d", &index)) - { - lgt = lisp_gpe_tunnel_get_i (index); - vlib_cli_output (vm, "%U", format_lisp_gpe_tunnel, lgt); - } - else - { - /* *INDENT-OFF* */ - pool_foreach (lgt, lisp_gpe_tunnel_pool, - ({ - vlib_cli_output (vm, "%U", format_lisp_gpe_tunnel, lgt); - })); - /* *INDENT-ON* */ - } - - return 0; -} - -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND (show_lisp_gpe_tunnel_command, static) = -{ - .path = "show gpe tunnel", - .function = show_lisp_gpe_tunnel_command_fn, -}; -/* *INDENT-ON* */ - -static clib_error_t * -lisp_gpe_tunnel_module_init (vlib_main_t * vm) -{ - lisp_gpe_tunnel_db = hash_create_mem (0, - sizeof (lisp_gpe_tunnel_key_t), - sizeof (uword)); - - return (NULL); -} - -VLIB_INIT_FUNCTION (lisp_gpe_tunnel_module_init); - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/vnet/lisp-gpe/lisp_gpe_tunnel.h b/src/vnet/lisp-gpe/lisp_gpe_tunnel.h deleted file mode 100644 index 333d2882883..00000000000 --- a/src/vnet/lisp-gpe/lisp_gpe_tunnel.h +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (c) 2016 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. - */ -/** - * @file - * @brief Common utility functions for IPv4, IPv6 and L2 LISP-GPE tunnels. - * - */ - -#ifndef LISP_GPE_TUNNEL_H__ -#define LISP_GPE_TUNNEL_H__ - -#include <vnet/lisp-gpe/lisp_gpe.h> -#include <vnet/lisp-gpe/lisp_gpe_packet.h> - -/** - * Forward declaration - */ -struct lisp_gpe_adjacency_t_; - -/** - * A Key for a tunnel - */ -typedef struct lisp_gpe_tunnel_key_t_ -{ - ip_address_t rmt; - ip_address_t lcl; - u32 fib_index; -} lisp_gpe_tunnel_key_t; - -/** - * @brief A LISP GPE Tunnel. - * - * A tunnel represents an associatation between a local and remote RLOC. - * As such it represents a unique LISP rewrite. - */ -typedef struct lisp_gpe_tunnel_t_ -{ - /** - * RLOC pair and rloc fib_index. This is the tunnel's key. - */ - lisp_gpe_tunnel_key_t *key; - - /** - * number of reference counting locks - */ - u32 locks; - - /** - * the FIB entry through which the remote rloc is reachable - s */ - fib_node_index_t fib_entry_index; -} lisp_gpe_tunnel_t; - -extern index_t lisp_gpe_tunnel_find_or_create_and_lock (const locator_pair_t * - pair, - u32 rloc_fib_index); - -extern void lisp_gpe_tunnel_unlock (index_t lgti); - -extern const lisp_gpe_tunnel_t *lisp_gpe_tunnel_get (index_t lgti); - -extern u8 *lisp_gpe_tunnel_build_rewrite (const lisp_gpe_tunnel_t * lgt, - const struct lisp_gpe_adjacency_t_ - *ladj, - lisp_gpe_next_protocol_e - payload_proto); -extern u8 *format_lisp_gpe_tunnel (u8 * s, va_list * args); - -#endif - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/vnet/lisp-gpe/lisp_types_api.c b/src/vnet/lisp-gpe/lisp_types_api.c deleted file mode 120000 index 84e06c41264..00000000000 --- a/src/vnet/lisp-gpe/lisp_types_api.c +++ /dev/null @@ -1 +0,0 @@ -../lisp-cp/lisp_types_api.c
\ No newline at end of file diff --git a/src/vnet/lisp-gpe/lisp_types_api.h b/src/vnet/lisp-gpe/lisp_types_api.h deleted file mode 120000 index f895123c6b0..00000000000 --- a/src/vnet/lisp-gpe/lisp_types_api.h +++ /dev/null @@ -1 +0,0 @@ -../lisp-cp/lisp_types_api.h
\ No newline at end of file diff --git a/src/vnet/lisp-gpe/rfc.txt b/src/vnet/lisp-gpe/rfc.txt deleted file mode 100644 index 5e3da150c70..00000000000 --- a/src/vnet/lisp-gpe/rfc.txt +++ /dev/null @@ -1,826 +0,0 @@ -Network Working Group D. Lewis -Internet-Draft Cisco Systems, Inc. -Intended status: Informational P. Agarwal -Expires: January 5, 2015 Broadcom - L. Kreeger - F. Maino - P. Quinn - M. Smith - N. Yadav - Cisco Systems, Inc. - July 4, 2014 - - - LISP Generic Protocol Extension - draft-lewis-lisp-gpe-02.txt - -Abstract - - This draft describes extending the Locator/ID Separation Protocol - (LISP) [RFC6830], via changes to the LISP header, with three new - capabilities: support for multi-protocol encapsulation, operations, - administration and management (OAM) signaling, and explicit - versioning. - -Status of this Memo - - This Internet-Draft is submitted in full conformance with the - provisions of BCP 78 and BCP 79. - - Internet-Drafts are working documents of the Internet Engineering - Task Force (IETF). Note that other groups may also distribute - working documents as Internet-Drafts. The list of current Internet- - Drafts is at http://datatracker.ietf.org/drafts/current/. - - Internet-Drafts are draft documents valid for a maximum of six months - and may be updated, replaced, or obsoleted by other documents at any - time. It is inappropriate to use Internet-Drafts as reference - material or to cite them other than as "work in progress." - - This Internet-Draft will expire on January 5, 2015. - -Copyright Notice - - Copyright (c) 2014 IETF Trust and the persons identified as the - document authors. All rights reserved. - - This document is subject to BCP 78 and the IETF Trust's Legal - Provisions Relating to IETF Documents - - - -Lewis, et al. Expires January 5, 2015 [Page 1] - -Internet-Draft LISP Generic Protocol Extension July 2014 - - - (http://trustee.ietf.org/license-info) in effect on the date of - publication of this document. Please review these documents - carefully, as they describe your rights and restrictions with respect - to this document. Code Components extracted from this document must - include Simplified BSD License text as described in Section 4.e of - the Trust Legal Provisions and are provided without warranty as - described in the Simplified BSD License. - - -Table of Contents - - 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . . 3 - 2. LISP Header Without Protocol Extensions . . . . . . . . . . . 4 - 3. Generic Protocol Extension for LISP (LISP-gpe) . . . . . . . . 5 - 3.1. Multi Protocol Support . . . . . . . . . . . . . . . . . . 5 - 3.2. OAM Support . . . . . . . . . . . . . . . . . . . . . . . 6 - 3.3. Version Bits . . . . . . . . . . . . . . . . . . . . . . . 6 - 4. Backward Compatibility . . . . . . . . . . . . . . . . . . . . 8 - 4.1. LISP-gpe Routers to (legacy) LISP Routers . . . . . . . . 8 - 4.2. (legacy) LISP Routers to LISP-gpe Routers . . . . . . . . 8 - 4.3. Type of Service . . . . . . . . . . . . . . . . . . . . . 8 - 4.4. VLAN Identifier (VID) . . . . . . . . . . . . . . . . . . 8 - 5. LISP-gpe Examples . . . . . . . . . . . . . . . . . . . . . . 9 - 6. Security Considerations . . . . . . . . . . . . . . . . . . . 11 - 7. Acknowledgments . . . . . . . . . . . . . . . . . . . . . . . 12 - 8. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 13 - 9. References . . . . . . . . . . . . . . . . . . . . . . . . . . 14 - 9.1. Normative References . . . . . . . . . . . . . . . . . . . 14 - 9.2. Informative References . . . . . . . . . . . . . . . . . . 14 - Authors' Addresses . . . . . . . . . . . . . . . . . . . . . . . . 15 - - - - - - - - - - - - - - - - - - - - - -Lewis, et al. Expires January 5, 2015 [Page 2] - -Internet-Draft LISP Generic Protocol Extension July 2014 - - -1. Introduction - - LISP [RFC6830] defines an encapsulation format that carries IPv4 or - IPv6 (henceforth referred to as IP) packets in a LISP header and - outer UDP/IP transport. - - The LISP header does not specify the protocol being encapsulated and - therefore is currently limited to encapsulating only IP packet - payloads. Other protocols, most notably VXLAN [VXLAN] (which defines - a similar header format to LISP), are used to encapsulate L2 - protocols such as Ethernet. LISP [RFC6830] can be extended to - indicate the inner protocol, enabling the encapsulation of Ethernet, - IP or any other desired protocol all the while ensuring compatibility - with existing LISP [RFC6830] deployments. - - As LISP is deployed, there's also the need to provide increased - visibility and diagnostic capabilities within the overlay. - - This document describes extending LISP ([RFC6830]) via the following - changes: - - Next Protocol Bit (P bit): A reserved flag bit is allocated, and set - in the LISP-gpe header to indicate that a next protocol field is - present. - - OAM Flag Bit (O bit): A reserved flag bit is allocated, and set in - the LISP-gpe header, to indicate that the packet is an OAM packet. - - Version: Two reserved bits are allocated, and set in the LISP-gpe - header, to indicate LISP-gpe protocol version. - - Next protocol: An 8 bit next protocol field is present in the LISP- - gpe header. - - - - - - - - - - - - - - - - - - -Lewis, et al. Expires January 5, 2015 [Page 3] - -Internet-Draft LISP Generic Protocol Extension July 2014 - - -2. LISP Header Without Protocol Extensions - - As described in the introduction, the LISP header has no protocol - identifier that indicates the type of payload being carried by LISP. - Because of this, LISP is limited to an IP payload. Furthermore, the - LISP header has no mechanism to signal OAM packets. - - The LISP header contains flags (some defined, some reserved), a - Nonce/Map-version field and an instance ID/Locator-status-bit field. - The flags provide flexibility to define how the reserved bits can be - used to change the definition of the LISP header. - - - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - |N|L|E|V|I|flags| Nonce/Map-Version | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Instance ID/Locator-Status-Bits | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - - - Figure 1: LISP Header - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Lewis, et al. Expires January 5, 2015 [Page 4] - -Internet-Draft LISP Generic Protocol Extension July 2014 - - -3. Generic Protocol Extension for LISP (LISP-gpe) - -3.1. Multi Protocol Support - - This draft defines the following changes to the LISP header in order - to support multi-protocol encapsulation. - - P Bit: Flag bit 5 is defined as the Next Protocol bit. The P bit - MUST be set to 1 to indicate the presence of the 8 bit next - protocol field. - - P = 0 indicates that the payload MUST conform to LISP as defined - in [RFC6830]. - - Flag bit 5 was chosen as the P bit because this flag bit is - currently unallocated in LISP [RFC6830]. - - Next Protocol Field: The lower 8 bits of the first word are used to - carry a next protocol. This next protocol field contains the - protocol of the encapsulated payload packet. - - LISP [RFC6830] uses the lower 16 bits of the first word for either - a nonce, an echo-nonce ([RFC6830]) or to support map-versioning - ([RFC6834]). These are all optional capabilities that are - indicated by setting the N, E, and the V bit respectively. - - To maintain the desired data plane compatibility, when the P bit - is set, the N, E, and V bits MUST be set to zero. - - A new protocol registry will be requested from IANA for the Next - Protocol field. This draft defines the following Next Protocol - values: - - 0x1 : IPv4 - - 0x2 : IPv6 - - 0x3 : Ethernet - - 0x4: Network Service Header - - - - - - - - - - - -Lewis, et al. Expires January 5, 2015 [Page 5] - -Internet-Draft LISP Generic Protocol Extension July 2014 - - - 0 1 2 3 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - |N|L|E|V|I|P|R|R| Reserved | Next Protocol | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Instance ID/Locator-Status-Bits | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - - - - Figure 2: LISP-gpe Next Protocol (P=1) - -3.2. OAM Support - - Flag bit 7 is defined as the O bit. When the O bit is set to 1, the - packet is an OAM packet and OAM processing MUST occur. The OAM - protocol details are out of scope for this document. As with the - P-bit, bit 7 is currently a reserved flag in [RFC6830]. - - - - - 0 1 2 3 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - |N|L|E|V|I|P|R|O| Reserved | Next Protocol | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Instance ID/Locator-Status-Bits | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - - - - Figure 3: LISP-gpe OAM bit (P=1) - -3.3. Version Bits - - LISP-gpe bits8 and 9 are defined as version bits. The version field - is used to ensure backward compatibility going forward with future - LISP-gpe updates. - - The initial version for LISP-gpe is 0. - - - - - - - - - - -Lewis, et al. Expires January 5, 2015 [Page 6] - -Internet-Draft LISP Generic Protocol Extension July 2014 - - - 0 1 2 3 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - |N|L|E|V|I|P|R|O|Ver| Reserved | Next Protocol | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Instance ID/Locator-Status-Bits | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - - - - Figure 4: LISP-gpe Version bits (P=1) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Lewis, et al. Expires January 5, 2015 [Page 7] - -Internet-Draft LISP Generic Protocol Extension July 2014 - - -4. Backward Compatibility - - Undefined (in RFC6830) flag bits 5 and 7, LISP-gpe P and O bits, were - selected to ensure compatibility with existing LISP [RFC6830] - deployments. - - Similarly, using P = 0 to indicate that the format of the header and - payload conforms to [RFC6830] ensures compatibility with existing - LISP hardware forwarding platforms. - -4.1. LISP-gpe Routers to (legacy) LISP Routers - - A LISP-gpe router MUST not encapsulate non-IP packet nor OAM packets - to a LISP router. A method for determining the capabilities of a - LISP router (gpe or "legacy") is out of the scope of this draft. - - When encapsulating IP packets to a LISP router the P bit SHOULD be - set to 1 and the UDP port MUST be set to 4341. OAM bit MUST be set - to 0. The Next Protocol field SHOULD be 0x1 (IPv4) or 0x2 (IPv6). - The (legacy) LISP router will ignore the P bit and the protocol type - field. The (legacy) LISP router will treat the packet as a LISP - packet and inspect the first nibble of the payload to determine the - IP version. - - When the P bit is set, the N, E, and V bits MUST be set to zero. The - receiving (legacy) LISP router will ignore N, E and V bits, when the - P bit is set. - -4.2. (legacy) LISP Routers to LISP-gpe Routers - - When a LISP-gpe router receives a packet from a (legacy) LISP router, - the P bit MUST not be set and the UDP port MUST be 4341. The payload - MUST be IP, and the LISP-gpe router will inspect the first nibble of - the payload to determine IP version. - -4.3. Type of Service - - When a LISP-gpe router performs Ethernet encapsulation, the inner - 802.1Q [IEEE8021Q] priority code point (PCP) field MAY be mapped from - the encapsulated frame to the Type of Service field in the outer IPv4 - header, or in the case of IPv6 the 'Traffic Class' field. - -4.4. VLAN Identifier (VID) - - When a LISP-gpe router performs Ethernet encapsulation, the inner - header 802.1Q [IEEE8021Q] VLAN Identifier (VID) MAY be mapped to, or - used to determine the LISP Instance ID field. - - - - -Lewis, et al. Expires January 5, 2015 [Page 8] - -Internet-Draft LISP Generic Protocol Extension July 2014 - - -5. LISP-gpe Examples - - This section provides two examples of IP protocols, and one example - of Ethernet encapsulated LISP-gpe using the generic extension - described in this document. - - - - 0 1 2 3 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - |N|L|E|V|I|1|0|0|0| Reserved | NP = IPv4 | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Instance ID/Locator-Status-Bits | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Original IPv4 Packet | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - - - - Figure 5: IPv4 and LISP-gpe - - - - - 0 1 2 3 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - |N|L|E|V|I|1|0|0|0| Reserved | NP = IPv6 | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Instance ID/Locator-Status-Bits | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Original IPv6 Packet | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - - - - Figure 6: IPv6 and LISP-gpe - - - - - - - - - - - - - -Lewis, et al. Expires January 5, 2015 [Page 9] - -Internet-Draft LISP Generic Protocol Extension July 2014 - - - 0 1 2 3 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - |N|L|E|V|I|1|0|0|0| Reserved | NP = Ethernet | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Instance ID/Locator-Status-Bits | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Original Ethernet Frame | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - - - - Figure 7: Ethernet and LISP-gpe - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Lewis, et al. Expires January 5, 2015 [Page 10] - -Internet-Draft LISP Generic Protocol Extension July 2014 - - -6. Security Considerations - - LISP-gpe security considerations are similar to the LISP security - considerations documented at length in LISP [RFC6830]. With LISP- - gpe, issues such as dataplane spoofing, flooding, and traffic - redirection are dependent on the particular protocol payload - encapsulated. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Lewis, et al. Expires January 5, 2015 [Page 11] - -Internet-Draft LISP Generic Protocol Extension July 2014 - - -7. Acknowledgments - - A special thank you goes to Dino Farinacci for his guidance and - detailed review. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Lewis, et al. Expires January 5, 2015 [Page 12] - -Internet-Draft LISP Generic Protocol Extension July 2014 - - -8. IANA Considerations - - IANA is requested to set up a registry of "Next Protocol". These are - 8-bit values. Next Protocol values 0, 1, 2, 3 and 4 are defined in - this draft. New values are assigned via Standards Action [RFC5226]. - - +---------------+-------------+---------------+ - | Next Protocol | Description | Reference | - +---------------+-------------+---------------+ - | 0 | Reserved | This document | - | | | | - | 1 | IPv4 | This document | - | | | | - | 2 | IPv6 | This document | - | | | | - | 3 | Ethernet | This document | - | | | | - | 4 | NSH | This document | - | | | | - | 5..253 | Unassigned | | - +---------------+-------------+---------------+ - - Table 1 - - There are ten bits at the beginning of the LISP-gpe header. New - bits are assigned via Standards Action [RFC5226]. - - Bits 0-3 - Assigned by LISP [RFC6830] - Bit 4 - Instance ID (I bit) - Bit 5 - Next Protocol (P bit) - Bit 6 - Reserved - Bit 7 - OAM (O bit) - Bits 8-9 - Version - - - - - - - - - - - - - - - - - - -Lewis, et al. Expires January 5, 2015 [Page 13] - -Internet-Draft LISP Generic Protocol Extension July 2014 - - -9. References - -9.1. Normative References - - [RFC0768] Postel, J., "User Datagram Protocol", STD 6, RFC 768, - August 1980. - - [RFC0791] Postel, J., "Internet Protocol", STD 5, RFC 791, - September 1981. - - [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate - Requirement Levels", BCP 14, RFC 2119, March 1997. - - [RFC5226] Narten, T. and H. Alvestrand, "Guidelines for Writing an - IANA Considerations Section in RFCs", BCP 26, RFC 5226, - May 2008. - -9.2. Informative References - - [ETYPES] The IEEE Registration Authority, "IEEE 802 Numbers", 2012, - <http://www.iana.org/assignments/ieee-802-numbers/ - ieee-802-numbers.xml>. - - [IEEE8021Q] - The IEEE Computer Society, "Media Access Control (MAC) - Bridges and Virtual Bridge Local Area Networks", August - 2012, <http://standards.ieee.org/getieee802/download/ - 802.1Q-2011.pdf>. - - [RFC1700] Reynolds, J. and J. Postel, "Assigned Numbers", RFC 1700, - October 1994. - - [RFC6830] Farinacci, D., Fuller, V., Meyer, D., and D. Lewis, "The - Locator/ID Separation Protocol (LISP)", RFC 6830, - January 2013. - - [RFC6834] Iannone, L., Saucez, D., and O. Bonaventure, "Locator/ID - Separation Protocol (LISP) Map-Versioning", RFC 6834, - January 2013. - - [VXLAN] Dutt, D., Mahalingam, M., Duda, K., Agarwal, P., Kreeger, - L., Sridhar, T., Bursell, M., and C. Wright, "VXLAN: A - Framework for Overlaying Virtualized Layer 2 Networks over - Layer 3 Networks", 2013. - - - - - - - -Lewis, et al. Expires January 5, 2015 [Page 14] - -Internet-Draft LISP Generic Protocol Extension July 2014 - - -Authors' Addresses - - Darrel Lewis - Cisco Systems, Inc. - - Email: darlewis@cisco.com - - - Puneet Agarwal - Broadcom - - Email: pagarwal@broadcom.com - - - Larry Kreeger - Cisco Systems, Inc. - - Email: kreeger@cisco.com - - - Fabio Maino - Cisco Systems, Inc. - - Email: fmaino@cisco.com - - - Paul Quinn - Cisco Systems, Inc. - - Email: paulq@cisco.com - - - Michael Smith - Cisco Systems, Inc. - - Email: michsmit@cisco.com - - - Navindra Yadav - Cisco Systems, Inc. - - Email: nyadav@cisco.com |