diff options
author | Neale Ranns <nranns@cisco.com> | 2020-09-21 08:17:51 +0000 |
---|---|---|
committer | Damjan Marion <dmarion@me.com> | 2020-09-22 16:01:29 +0000 |
commit | 2b202bc4b2d870d76bfe6fb1906ae62e253cec72 (patch) | |
tree | b05011f96b8d9d080647323e4609af0fac90b612 /src/plugins/lisp/lisp-gpe/lisp_gpe_tunnel.c | |
parent | b468773aa4164bf52e0751fdf780f67248037cc0 (diff) |
lisp: Move to plugin
Type: refactor
Change-Id: I54df533a8f863c4e49742903cf2457f18b4fc506
Signed-off-by: Neale Ranns <nranns@cisco.com>
Diffstat (limited to 'src/plugins/lisp/lisp-gpe/lisp_gpe_tunnel.c')
-rw-r--r-- | src/plugins/lisp/lisp-gpe/lisp_gpe_tunnel.c | 293 |
1 files changed, 293 insertions, 0 deletions
diff --git a/src/plugins/lisp/lisp-gpe/lisp_gpe_tunnel.c b/src/plugins/lisp/lisp-gpe/lisp_gpe_tunnel.c new file mode 100644 index 00000000000..b2426429322 --- /dev/null +++ b/src/plugins/lisp/lisp-gpe/lisp_gpe_tunnel.c @@ -0,0 +1,293 @@ +/* + * 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 <lisp/lisp-gpe/lisp_gpe.h> +#include <lisp/lisp-gpe/lisp_gpe_tunnel.h> +#include <lisp/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: + */ |