diff options
author | Neale Ranns <nranns@cisco.com> | 2019-02-07 07:26:12 -0800 |
---|---|---|
committer | Damjan Marion <dmarion@me.com> | 2019-06-18 13:54:35 +0000 |
commit | c87b66c86201458c0475d50c6e93f1497f9eec2e (patch) | |
tree | 57bf69c2adb85a93b26a86b5a1110e4290e7f391 /src/vnet/ipsec-gre | |
parent | 097fa66b986f06281f603767d321ab13ab6c88c3 (diff) |
ipsec: ipsec-tun protect
please consult the new tunnel proposal at:
https://wiki.fd.io/view/VPP/IPSec
Type: feature
Change-Id: I52857fc92ae068b85f59be08bdbea1bd5932e291
Signed-off-by: Neale Ranns <nranns@cisco.com>
Diffstat (limited to 'src/vnet/ipsec-gre')
-rw-r--r-- | src/vnet/ipsec-gre/dir.dox | 18 | ||||
-rw-r--r-- | src/vnet/ipsec-gre/error.def | 26 | ||||
-rw-r--r-- | src/vnet/ipsec-gre/interface.c | 301 | ||||
-rw-r--r-- | src/vnet/ipsec-gre/ipsec_gre.api | 88 | ||||
-rw-r--r-- | src/vnet/ipsec-gre/ipsec_gre.c | 394 | ||||
-rw-r--r-- | src/vnet/ipsec-gre/ipsec_gre.h | 105 | ||||
-rw-r--r-- | src/vnet/ipsec-gre/ipsec_gre_api.c | 190 | ||||
-rw-r--r-- | src/vnet/ipsec-gre/ipsec_gre_doc.md | 74 | ||||
-rw-r--r-- | src/vnet/ipsec-gre/node.c | 426 |
9 files changed, 0 insertions, 1622 deletions
diff --git a/src/vnet/ipsec-gre/dir.dox b/src/vnet/ipsec-gre/dir.dox deleted file mode 100644 index e6ffd10b01b..00000000000 --- a/src/vnet/ipsec-gre/dir.dox +++ /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. - */ -/** - @dir vnet/vnet/ipsec-gre - @brief L2-GRE over IPSec tunnel interface implementation -*/ diff --git a/src/vnet/ipsec-gre/error.def b/src/vnet/ipsec-gre/error.def deleted file mode 100644 index d84e8ed1759..00000000000 --- a/src/vnet/ipsec-gre/error.def +++ /dev/null @@ -1,26 +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-GRE over IPSec errors. - */ - - -ipsec_gre_error (NONE, "no error") -ipsec_gre_error (UNKNOWN_PROTOCOL, "unknown protocol") -ipsec_gre_error (UNSUPPORTED_VERSION, "unsupported version") -ipsec_gre_error (PKTS_DECAP, "GRE input packets decapsulated") -ipsec_gre_error (PKTS_ENCAP, "GRE output packets encapsulated") -ipsec_gre_error (NO_SUCH_TUNNEL, "GRE input packets dropped due to missing tunnel") diff --git a/src/vnet/ipsec-gre/interface.c b/src/vnet/ipsec-gre/interface.c deleted file mode 100644 index 6a8bb7d8f0b..00000000000 --- a/src/vnet/ipsec-gre/interface.c +++ /dev/null @@ -1,301 +0,0 @@ -/* - * gre_interface.c: gre interfaces - * - * 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-GRE over IPSec tunnel interface. - * - * Creates ipsec-gre tunnel interface. - * Provides a command line interface so humans can interact with VPP. - */ - -#include <vnet/vnet.h> -#include <vnet/pg/pg.h> -#include <vnet/ipsec-gre/ipsec_gre.h> -#include <vnet/ip/format.h> -#include <vnet/ipsec/ipsec.h> -#include <vnet/l2/l2_input.h> - -#include <vnet/ipsec/esp.h> - -u8 * -format_ipsec_gre_tunnel (u8 * s, va_list * args) -{ - ipsec_gre_tunnel_t *t = va_arg (*args, ipsec_gre_tunnel_t *); - ipsec_gre_main_t *gm = &ipsec_gre_main; - - s = format (s, - "[%d] %U (src) %U (dst) local-sa %d remote-sa %d", - t - gm->tunnels, - format_ip4_address, &t->tunnel_src, - format_ip4_address, &t->tunnel_dst, - t->local_sa_id, t->remote_sa_id); - return s; -} - -static clib_error_t * -show_ipsec_gre_tunnel_command_fn (vlib_main_t * vm, - unformat_input_t * input, - vlib_cli_command_t * cmd) -{ - ipsec_gre_main_t *igm = &ipsec_gre_main; - ipsec_gre_tunnel_t *t; - - if (pool_elts (igm->tunnels) == 0) - vlib_cli_output (vm, "No IPSec GRE tunnels configured..."); - - /* *INDENT-OFF* */ - pool_foreach (t, igm->tunnels, - ({ - vlib_cli_output (vm, "%U", format_ipsec_gre_tunnel, t); - })); - /* *INDENT-ON* */ - - return 0; -} - -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND (show_ipsec_gre_tunnel_command, static) = { - .path = "show ipsec gre tunnel", - .function = show_ipsec_gre_tunnel_command_fn, -}; -/* *INDENT-ON* */ - -/* force inclusion from application's main.c */ -clib_error_t * -ipsec_gre_interface_init (vlib_main_t * vm) -{ - return 0; -} - -VLIB_INIT_FUNCTION (ipsec_gre_interface_init); - -/** - * @brief Add or delete ipsec-gre tunnel interface. - * - * @param *a vnet_ipsec_gre_tunnel_add_del_args_t - tunnel interface parameters - * @param *sw_if_indexp u32 - software interface index - * @return int - 0 if success otherwise <code>VNET_API_ERROR_</code> - */ -int -vnet_ipsec_gre_tunnel_add_del (const ipsec_gre_tunnel_add_del_args_t * a, - u32 * sw_if_indexp) -{ - ipsec_gre_main_t *igm = &ipsec_gre_main; - vnet_main_t *vnm = igm->vnet_main; - ipsec_main_t *im = &ipsec_main; - ipsec_gre_tunnel_t *t; - vnet_hw_interface_t *hi; - u32 hw_if_index, sw_if_index; - u32 slot; - uword *p; - u64 key; - - key = (u64) a->src.as_u32 << 32 | (u64) a->dst.as_u32; - p = hash_get (igm->tunnel_by_key, key); - - if (a->is_add) - { - /* check if same src/dst pair exists */ - if (p) - return VNET_API_ERROR_INVALID_VALUE; - - pool_get_aligned (igm->tunnels, t, CLIB_CACHE_LINE_BYTES); - clib_memset (t, 0, sizeof (*t)); - - if (vec_len (igm->free_ipsec_gre_tunnel_hw_if_indices) > 0) - { - vnet_interface_main_t *im = &vnm->interface_main; - - hw_if_index = igm->free_ipsec_gre_tunnel_hw_if_indices - [vec_len (igm->free_ipsec_gre_tunnel_hw_if_indices) - 1]; - _vec_len (igm->free_ipsec_gre_tunnel_hw_if_indices) -= 1; - - hi = vnet_get_hw_interface (vnm, hw_if_index); - hi->dev_instance = t - igm->tunnels; - hi->hw_instance = hi->dev_instance; - - /* clear old stats of freed tunnel before reuse */ - sw_if_index = hi->sw_if_index; - vnet_interface_counter_lock (im); - vlib_zero_combined_counter - (&im->combined_sw_if_counters[VNET_INTERFACE_COUNTER_TX], - sw_if_index); - vlib_zero_combined_counter - (&im->combined_sw_if_counters[VNET_INTERFACE_COUNTER_RX], - sw_if_index); - vlib_zero_simple_counter - (&im->sw_if_counters[VNET_INTERFACE_COUNTER_DROP], sw_if_index); - vnet_interface_counter_unlock (im); - } - else - { - hw_if_index = vnet_register_interface - (vnm, ipsec_gre_device_class.index, t - igm->tunnels, - ipsec_gre_hw_interface_class.index, t - igm->tunnels); - hi = vnet_get_hw_interface (vnm, hw_if_index); - sw_if_index = hi->sw_if_index; - } - - t->hw_if_index = hw_if_index; - t->sw_if_index = sw_if_index; - t->local_sa_id = a->local_sa_id; - t->remote_sa_id = a->remote_sa_id; - t->local_sa = ipsec_get_sa_index_by_sa_id (t->local_sa_id); - t->remote_sa = ipsec_get_sa_index_by_sa_id (t->remote_sa_id); - - ip4_sw_interface_enable_disable (sw_if_index, 1); - - vec_validate_init_empty (igm->tunnel_index_by_sw_if_index, - sw_if_index, ~0); - igm->tunnel_index_by_sw_if_index[sw_if_index] = t - igm->tunnels; - - hi->min_packet_bytes = 64 + sizeof (gre_header_t) + - sizeof (ip4_header_t) + sizeof (esp_header_t) + sizeof (esp_footer_t); - - /* Standard default gre MTU. */ - /* TODO: Should take tunnel overhead into consideration */ - vnet_sw_interface_set_mtu (vnm, sw_if_index, 9000); - - clib_memcpy (&t->tunnel_src, &a->src, sizeof (t->tunnel_src)); - clib_memcpy (&t->tunnel_dst, &a->dst, sizeof (t->tunnel_dst)); - - hash_set (igm->tunnel_by_key, key, t - igm->tunnels); - - slot = vlib_node_add_next_with_slot - (vnm->vlib_main, hi->tx_node_index, im->esp4_encrypt_node_index, - IPSEC_GRE_OUTPUT_NEXT_ESP_ENCRYPT); - - ASSERT (slot == IPSEC_GRE_OUTPUT_NEXT_ESP_ENCRYPT); - } - else - { /* !is_add => delete */ - /* tunnel needs to exist */ - if (!p) - return VNET_API_ERROR_NO_SUCH_ENTRY; - - t = pool_elt_at_index (igm->tunnels, p[0]); - - sw_if_index = t->sw_if_index; - ip4_sw_interface_enable_disable (sw_if_index, 0); - vnet_sw_interface_set_flags (vnm, sw_if_index, 0 /* down */ ); - /* make sure tunnel is removed from l2 bd or xconnect */ - set_int_l2_mode (igm->vlib_main, vnm, MODE_L3, sw_if_index, 0, - L2_BD_PORT_TYPE_NORMAL, 0, 0); - vec_add1 (igm->free_ipsec_gre_tunnel_hw_if_indices, t->hw_if_index); - igm->tunnel_index_by_sw_if_index[sw_if_index] = ~0; - - hash_unset (igm->tunnel_by_key, key); - pool_put (igm->tunnels, t); - } - - if (sw_if_indexp) - *sw_if_indexp = sw_if_index; - - return ipsec_add_del_ipsec_gre_tunnel (vnm, a); -} - -static clib_error_t * -create_ipsec_gre_tunnel_command_fn (vlib_main_t * vm, - unformat_input_t * input, - vlib_cli_command_t * cmd) -{ - unformat_input_t _line_input, *line_input = &_line_input; - u32 num_m_args = 0; - ipsec_gre_tunnel_add_del_args_t _a, *a = &_a; - int rv; - u32 sw_if_index; - clib_error_t *error = NULL; - - clib_memset (a, 0, sizeof (*a)); - a->is_add = 1; - - /* 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")) - a->is_add = 0; - else if (unformat (line_input, "src %U", unformat_ip4_address, &a->src)) - num_m_args++; - else if (unformat (line_input, "dst %U", unformat_ip4_address, &a->dst)) - num_m_args++; - else if (unformat (line_input, "local-sa %d", &a->local_sa_id)) - num_m_args++; - else if (unformat (line_input, "remote-sa %d", &a->remote_sa_id)) - num_m_args++; - else - { - error = clib_error_return (0, "unknown input `%U'", - format_unformat_error, line_input); - goto done; - } - } - - if (num_m_args < 4) - { - error = clib_error_return (0, "mandatory argument(s) missing"); - goto done; - } - - if (memcmp (&a->src, &a->dst, sizeof (a->src)) == 0) - { - error = clib_error_return (0, "src and dst are identical"); - goto done; - } - - rv = vnet_ipsec_gre_tunnel_add_del (a, &sw_if_index); - - switch (rv) - { - case 0: - vlib_cli_output (vm, "%U\n", format_vnet_sw_if_index_name, - vnet_get_main (), sw_if_index); - break; - case VNET_API_ERROR_INVALID_VALUE: - error = clib_error_return (0, "GRE tunnel already exists..."); - goto done; - default: - error = clib_error_return (0, - "vnet_ipsec_gre_tunnel_add_del returned %d", - rv); - goto done; - } - -done: - unformat_free (line_input); - - return error; -} - -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND (create_ipsec_gre_tunnel_command, static) = { - .path = "create ipsec gre tunnel", - .short_help = "create ipsec gre tunnel src <addr> dst <addr> " - "local-sa <id> remote-sa <id> [del]", - .function = create_ipsec_gre_tunnel_command_fn, -}; -/* *INDENT-ON* */ - -/* -* fd.io coding-style-patch-verification: ON -* -* Local Variables: -* eval: (c-set-style "gnu") -* End: -*/ diff --git a/src/vnet/ipsec-gre/ipsec_gre.api b/src/vnet/ipsec-gre/ipsec_gre.api deleted file mode 100644 index b4950097f61..00000000000 --- a/src/vnet/ipsec-gre/ipsec_gre.api +++ /dev/null @@ -1,88 +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 = "1.1.0"; - -import "vnet/ip/ip_types.api"; - -/** \brief Add / del ipsec gre tunnel request - @param client_index - opaque cookie to identify the sender - @param context - sender context, to match reply w/ request - @param local_sa_id - local/output SA id - @param remote_sa_id - remote/input SA id - @param is_add - 1 if adding the tunnel, 0 if deleting - @param sw_if_index - software index of the ipsec gre tunnel - ignored on create. set in dump/details - @param src - tunnel source address - @param dst - tunnel destination address -*/ -typedef ipsec_gre_tunnel { - u32 client_index; - u32 context; - u32 local_sa_id; - u32 remote_sa_id; - u8 is_add; - u32 sw_if_index; - vl_api_ip4_address_t src; - vl_api_ip4_address_t dst; -}; - -define ipsec_gre_tunnel_add_del { - u32 client_index; - u32 context; - u8 is_add; - vl_api_ipsec_gre_tunnel_t tunnel; -}; - -/** \brief Reply for add / del ipsec gre tunnel request - @param context - returned sender context, to match reply w/ request - @param retval - return code - @param sw_if_index - software index of the new ipsec gre tunnel -*/ -define ipsec_gre_tunnel_add_del_reply { - u32 context; - i32 retval; - u32 sw_if_index; -}; - -/** \brief Dump ipsec gre tunnel table - @param client_index - opaque cookie to identify the sender - @param context - sender context, to match reply w/ request - @param tunnel_index - gre tunnel identifier or -1 in case of all tunnels -*/ -define ipsec_gre_tunnel_dump { - u32 client_index; - u32 context; - u32 sw_if_index; -}; - -/** \brief ipsec gre tunnel operational state response - @param context - returned sender context, to match reply w/ request - @param local_sa_id - local SA id - @param remote_sa_id - remote SA id - @param src_address - tunnel source address - @param dst_address - tunnel destination address -*/ -define ipsec_gre_tunnel_details { - u32 context; - vl_api_ipsec_gre_tunnel_t tunnel; -}; - -/* - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ - diff --git a/src/vnet/ipsec-gre/ipsec_gre.c b/src/vnet/ipsec-gre/ipsec_gre.c deleted file mode 100644 index cdb23dd9deb..00000000000 --- a/src/vnet/ipsec-gre/ipsec_gre.c +++ /dev/null @@ -1,394 +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-GRE over IPSec packet processing. - * - * Add GRE header to thr packet and send it to the esp-encrypt node. -*/ - -#include <vnet/vnet.h> -#include <vnet/ipsec-gre/ipsec_gre.h> - -extern ipsec_gre_main_t ipsec_gre_main; - -#ifndef CLIB_MARCH_VARIANT -ipsec_gre_main_t ipsec_gre_main; -#endif /* CLIB_MARCH_VARIANT */ - -/** - * @brief IPv4 and GRE header union. - * -*/ -typedef struct -{ - union - { - ip4_and_gre_header_t ip4_and_gre; - u64 as_u64[3]; - }; -} ip4_and_gre_union_t; - -/** - * @brief Packet trace. - * -*/ -typedef struct -{ - u32 tunnel_id; /**< Tunnel-id / index in tunnel vector */ - - u32 length; /**< pkt length */ - - ip4_address_t src; /**< tunnel src IPv4 address */ - ip4_address_t dst; /**< tunnel dst IPv4 address */ - - u32 sa_id; /**< tunnel IPSec SA id */ -} ipsec_gre_tx_trace_t; - -static u8 * -format_ipsec_gre_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 *); - ipsec_gre_tx_trace_t *t = va_arg (*args, ipsec_gre_tx_trace_t *); - - s = format (s, "GRE: tunnel %d len %d src %U dst %U sa-id %d", - t->tunnel_id, clib_net_to_host_u16 (t->length), - format_ip4_address, &t->src.as_u8, - format_ip4_address, &t->dst.as_u8, t->sa_id); - return s; -} - -/** - * @brief IPSec-GRE tunnel interface tx function. - * - * Add GRE header to the packet. - * - * @param vm vlib_main_t corresponding to the current thread. - * @param node vlib_node_runtime_t data for this node. - * @param frame vlib_frame_t whose contents should be dispatched. - * - * @par Graph mechanics: buffer metadata, next index usage - * - * <em>Uses:</em> - * - <code>node->runtime_data</code> - * - Match tunnel by <code>rd->dev_instance</code> in IPSec-GRE tunnels - * pool. - * - * <em>Sets:</em> - * - <code>vnet_buffer(b)->output_features.ipsec_sad_index</code> - * - Set IPSec Security Association for packet encryption. - * - <code>vnet_buffer(b)->sw_if_index[VLIB_TX]</code> - * - Reset output sw_if_index. - * - * <em>Next Index:</em> - * - Dispatches the packet to the esp-encrypt node. -*/ -VNET_DEVICE_CLASS_TX_FN (ipsec_gre_device_class) (vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_frame_t * frame) -{ - ipsec_gre_main_t *igm = &ipsec_gre_main; - u32 next_index; - u32 *from, *to_next, n_left_from, n_left_to_next; - vnet_interface_output_runtime_t *rd = (void *) node->runtime_data; - ipsec_gre_tunnel_t *t = pool_elt_at_index (igm->tunnels, rd->dev_instance); - - u16 l2_gre_protocol_ethertype = clib_net_to_host_u16 (GRE_PROTOCOL_teb); - - /* Vector of buffer / pkt indices we're supposed to process */ - from = vlib_frame_vector_args (frame); - - /* Number of buffers / pkts */ - n_left_from = frame->n_vectors; - - /* Speculatively send the first buffer to the last disposition we used */ - next_index = node->cached_next_index; - - while (n_left_from > 0) - { - /* set up to enqueue to our disposition with index = next_index */ - vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next); - - /* - * As long as we have enough pkts left to process two pkts - * and prefetch two pkts... - */ - while (n_left_from >= 4 && n_left_to_next >= 2) - { - vlib_buffer_t *b0, *b1; - ip4_header_t *ip0, *ip1; - ip4_and_gre_union_t *h0, *h1; - u32 bi0, next0, bi1, next1; - __attribute__ ((unused)) u8 error0, error1; - - /* Prefetch the 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); - - /* - * Prefetch packet data. We expect to overwrite - * the inbound L2 header with an ip header and a - * gre header. Might want to prefetch the last line - * of rewrite space as well; need profile data - */ - CLIB_PREFETCH (p2->data, CLIB_CACHE_LINE_BYTES, STORE); - CLIB_PREFETCH (p3->data, CLIB_CACHE_LINE_BYTES, STORE); - } - - /* Pick up the next two buffer indices */ - bi0 = from[0]; - bi1 = from[1]; - - /* Speculatively enqueue them where we sent the last buffer */ - 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); - - vlib_buffer_advance (b0, -sizeof (*h0)); - vlib_buffer_advance (b1, -sizeof (*h1)); - - h0 = vlib_buffer_get_current (b0); - h1 = vlib_buffer_get_current (b1); - h0->as_u64[0] = 0; - h0->as_u64[1] = 0; - h0->as_u64[2] = 0; - - h1->as_u64[0] = 0; - h1->as_u64[1] = 0; - h1->as_u64[2] = 0; - - ip0 = &h0->ip4_and_gre.ip4; - h0->ip4_and_gre.gre.protocol = l2_gre_protocol_ethertype; - ip0->ip_version_and_header_length = 0x45; - ip0->ttl = 254; - ip0->protocol = IP_PROTOCOL_GRE; - - ip1 = &h1->ip4_and_gre.ip4; - h1->ip4_and_gre.gre.protocol = l2_gre_protocol_ethertype; - ip1->ip_version_and_header_length = 0x45; - ip1->ttl = 254; - ip1->protocol = IP_PROTOCOL_GRE; - - ip0->length = - clib_host_to_net_u16 (vlib_buffer_length_in_chain (vm, b0)); - ip1->length = - clib_host_to_net_u16 (vlib_buffer_length_in_chain (vm, b1)); - ip0->src_address.as_u32 = t->tunnel_src.as_u32; - ip1->src_address.as_u32 = t->tunnel_src.as_u32; - ip0->dst_address.as_u32 = t->tunnel_dst.as_u32; - ip1->dst_address.as_u32 = t->tunnel_dst.as_u32; - ip0->checksum = ip4_header_checksum (ip0); - ip1->checksum = ip4_header_checksum (ip1); - - vnet_buffer (b0)->sw_if_index[VLIB_RX] = - vnet_buffer (b0)->sw_if_index[VLIB_TX]; - vnet_buffer (b1)->sw_if_index[VLIB_RX] = - vnet_buffer (b1)->sw_if_index[VLIB_TX]; - - vnet_buffer (b0)->ipsec.sad_index = t->local_sa; - vnet_buffer (b1)->ipsec.sad_index = t->local_sa; - - vnet_buffer (b0)->sw_if_index[VLIB_TX] = (u32) ~ 0; - vnet_buffer (b1)->sw_if_index[VLIB_TX] = (u32) ~ 0; - - next0 = IPSEC_GRE_OUTPUT_NEXT_ESP_ENCRYPT; - next1 = IPSEC_GRE_OUTPUT_NEXT_ESP_ENCRYPT; - error0 = IPSEC_GRE_ERROR_NONE; - error1 = IPSEC_GRE_ERROR_NONE; - - if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED)) - { - ipsec_gre_tx_trace_t *tr = vlib_add_trace (vm, node, - b0, sizeof (*tr)); - tr->tunnel_id = t - igm->tunnels; - tr->length = ip0->length; - tr->src.as_u32 = ip0->src_address.as_u32; - tr->dst.as_u32 = ip0->dst_address.as_u32; - tr->sa_id = t->local_sa_id; - } - - if (PREDICT_FALSE (b1->flags & VLIB_BUFFER_IS_TRACED)) - { - ipsec_gre_tx_trace_t *tr = vlib_add_trace (vm, node, - b1, sizeof (*tr)); - tr->tunnel_id = t - igm->tunnels; - tr->length = ip1->length; - tr->src.as_u32 = ip1->src_address.as_u32; - tr->dst.as_u32 = ip1->dst_address.as_u32; - tr->sa_id = t->local_sa_id; - } - - 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) - { - vlib_buffer_t *b0; - ip4_header_t *ip0; - ip4_and_gre_union_t *h0; - u32 bi0, next0; - __attribute__ ((unused)) u8 error0; - - bi0 = to_next[0] = from[0]; - from += 1; - n_left_from -= 1; - to_next += 1; - n_left_to_next -= 1; - - b0 = vlib_get_buffer (vm, bi0); - - vlib_buffer_advance (b0, -sizeof (*h0)); - - h0 = vlib_buffer_get_current (b0); - h0->as_u64[0] = 0; - h0->as_u64[1] = 0; - h0->as_u64[2] = 0; - - ip0 = &h0->ip4_and_gre.ip4; - h0->ip4_and_gre.gre.protocol = l2_gre_protocol_ethertype; - ip0->ip_version_and_header_length = 0x45; - ip0->ttl = 254; - ip0->protocol = IP_PROTOCOL_GRE; - ip0->length = - clib_host_to_net_u16 (vlib_buffer_length_in_chain (vm, b0)); - ip0->src_address.as_u32 = t->tunnel_src.as_u32; - ip0->dst_address.as_u32 = t->tunnel_dst.as_u32; - ip0->checksum = ip4_header_checksum (ip0); - - vnet_buffer (b0)->sw_if_index[VLIB_RX] = - vnet_buffer (b0)->sw_if_index[VLIB_TX]; - vnet_buffer (b0)->ipsec.sad_index = t->local_sa; - vnet_buffer (b0)->sw_if_index[VLIB_TX] = (u32) ~ 0; - - next0 = IPSEC_GRE_OUTPUT_NEXT_ESP_ENCRYPT; - error0 = IPSEC_GRE_ERROR_NONE; - - if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED)) - { - ipsec_gre_tx_trace_t *tr = vlib_add_trace (vm, node, - b0, sizeof (*tr)); - tr->tunnel_id = t - igm->tunnels; - tr->length = ip0->length; - tr->src.as_u32 = ip0->src_address.as_u32; - tr->dst.as_u32 = ip0->dst_address.as_u32; - tr->sa_id = t->local_sa_id; - } - - 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); - } - - vlib_node_increment_counter (vm, ipsec_gre_input_node.index, - IPSEC_GRE_ERROR_PKTS_ENCAP, frame->n_vectors); - - return frame->n_vectors; -} - -static clib_error_t * -ipsec_gre_interface_admin_up_down (vnet_main_t * vnm, u32 hw_if_index, - u32 flags) -{ - if (flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) - vnet_hw_interface_set_flags (vnm, hw_if_index, - VNET_HW_INTERFACE_FLAG_LINK_UP); - else - vnet_hw_interface_set_flags (vnm, hw_if_index, 0 /* down */ ); - - return /* no error */ 0; -} - -static u8 * -format_ipsec_gre_tunnel_name (u8 * s, va_list * args) -{ - u32 dev_instance = va_arg (*args, u32); - return format (s, "ipsec-gre%d", dev_instance); -} - -static u8 * -format_ipsec_gre_device (u8 * s, va_list * args) -{ - u32 dev_instance = va_arg (*args, u32); - CLIB_UNUSED (int verbose) = va_arg (*args, int); - - s = format (s, "IPSEC-GRE tunnel: id %d\n", dev_instance); - return s; -} - -/* *INDENT-OFF* */ -VNET_DEVICE_CLASS (ipsec_gre_device_class) = { - .name = "IPSec GRE tunnel device", - .format_device_name = format_ipsec_gre_tunnel_name, - .format_device = format_ipsec_gre_device, - .format_tx_trace = format_ipsec_gre_tx_trace, - .admin_up_down_function = ipsec_gre_interface_admin_up_down, -}; - - -#ifndef CLIB_MARCH_VARIANT -VNET_HW_INTERFACE_CLASS (ipsec_gre_hw_interface_class) = { - .name = "IPSEC-GRE", -}; -#endif /* CLIB_MARCH_VARIANT */ -/* *INDENT-ON* */ - -static clib_error_t * -ipsec_gre_init (vlib_main_t * vm) -{ - ipsec_gre_main_t *igm = &ipsec_gre_main; - clib_error_t *error; - - clib_memset (igm, 0, sizeof (igm[0])); - igm->vlib_main = vm; - igm->vnet_main = vnet_get_main (); - - if ((error = vlib_call_init_function (vm, ip_main_init))) - return error; - - if ((error = vlib_call_init_function (vm, ip4_lookup_init))) - return error; - - igm->tunnel_by_key = hash_create (0, sizeof (uword)); - - return vlib_call_init_function (vm, ipsec_gre_input_init); -} - -VLIB_INIT_FUNCTION (ipsec_gre_init); - -/* -* fd.io coding-style-patch-verification: ON -* -* Local Variables: -* eval: (c-set-style "gnu") -* End: -*/ diff --git a/src/vnet/ipsec-gre/ipsec_gre.h b/src/vnet/ipsec-gre/ipsec_gre.h deleted file mode 100644 index 730cd717795..00000000000 --- a/src/vnet/ipsec-gre/ipsec_gre.h +++ /dev/null @@ -1,105 +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-GRE over IPSec packet processing. -*/ - -#ifndef included_ipsec_gre_h -#define included_ipsec_gre_h - -#include <vnet/vnet.h> -#include <vnet/gre/packet.h> -#include <vnet/gre/gre.h> -#include <vnet/ip/ip.h> -#include <vnet/ip/ip4.h> -#include <vnet/ip/ip4_packet.h> -#include <vnet/pg/pg.h> -#include <vnet/ip/format.h> -#include <vnet/ipsec/ipsec.h> -#include <vnet/ipsec/ipsec_if.h> - -extern vnet_hw_interface_class_t ipsec_gre_hw_interface_class; - -/** - * @brief IPSec-GRE errors. - * -*/ -typedef enum -{ -#define ipsec_gre_error(n,s) IPSEC_GRE_ERROR_##n, -#include <vnet/ipsec-gre/error.def> -#undef ipsec_gre_error - IPSEC_GRE_N_ERROR, -} ipsec_gre_error_t; - -/** - * @brief IPSec-GRE tunnel parameters. - * -*/ -typedef struct -{ - /* Required for pool_get_aligned */ - CLIB_CACHE_LINE_ALIGN_MARK (cacheline0); - ip4_address_t tunnel_src; /**< tunnel IPv4 src address */ - ip4_address_t tunnel_dst; /**< tunnel IPv4 dst address */ - u32 local_sa; /**< local IPSec SA index */ - u32 remote_sa; /**< remote IPSec SA index */ - u32 local_sa_id; /**< local IPSec SA id */ - u32 remote_sa_id; /**< remote IPSec SA id */ - u32 hw_if_index;; /**< hardware interface index */ - u32 sw_if_index;; /**< software interface index */ -} ipsec_gre_tunnel_t; - -/** - * @brief IPSec-GRE state. - * -*/ -typedef struct -{ - ipsec_gre_tunnel_t *tunnels; /**< pool of tunnel instances */ - - uword *tunnel_by_key; /**< hash mapping src/dst addr pair to tunnel */ - - u32 *free_ipsec_gre_tunnel_hw_if_indices; /**< free vlib hw_if_indices */ - - u32 *tunnel_index_by_sw_if_index; /**< mapping from sw_if_index to tunnel - index */ - - vlib_main_t *vlib_main; /**< convenience */ - vnet_main_t *vnet_main; /**< convenience */ -} ipsec_gre_main_t; - -extern ipsec_gre_main_t ipsec_gre_main; - -extern vlib_node_registration_t ipsec_gre_input_node; -extern vnet_device_class_t ipsec_gre_device_class; - -/* manually added to the interface output node in ipsec_gre.c */ -#define IPSEC_GRE_OUTPUT_NEXT_ESP_ENCRYPT 0 - -extern int vnet_ipsec_gre_tunnel_add_del (const - ipsec_gre_tunnel_add_del_args_t * a, - u32 * sw_if_indexp); - -#endif /* included_ipsec_gre_h */ - -/* -* fd.io coding-style-patch-verification: ON -* -* Local Variables: -* eval: (c-set-style "gnu") -* End: -*/ diff --git a/src/vnet/ipsec-gre/ipsec_gre_api.c b/src/vnet/ipsec-gre/ipsec_gre_api.c deleted file mode 100644 index 9e5d615f977..00000000000 --- a/src/vnet/ipsec-gre/ipsec_gre_api.c +++ /dev/null @@ -1,190 +0,0 @@ -/* - *------------------------------------------------------------------ - * ipsec_gre_api.c - ipsec_gre 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/ipsec-gre/ipsec_gre.h> -#include <vnet/ip/ip_types_api.h> - -#include <vnet/vnet_msg_enum.h> - -#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 \ -_(IPSEC_GRE_TUNNEL_ADD_DEL, ipsec_gre_tunnel_add_del) \ -_(IPSEC_GRE_TUNNEL_DUMP, ipsec_gre_tunnel_dump) - -static void -vl_api_ipsec_gre_tunnel_add_del_t_handler (vl_api_ipsec_gre_tunnel_add_del_t * - mp) -{ - vl_api_ipsec_gre_tunnel_add_del_reply_t *rmp; - int rv = 0; - ipsec_gre_tunnel_add_del_args_t _a, *a = &_a; - u32 sw_if_index = ~0; - - clib_memset (a, 0, sizeof (*a)); - - ip4_address_decode (mp->tunnel.src, &a->src); - ip4_address_decode (mp->tunnel.dst, &a->dst); - - /* Check src & dst are different */ - if (a->src.as_u32 == a->dst.as_u32) - { - rv = VNET_API_ERROR_SAME_SRC_DST; - goto out; - } - - a->is_add = mp->is_add; - a->local_sa_id = ntohl (mp->tunnel.local_sa_id); - a->remote_sa_id = ntohl (mp->tunnel.remote_sa_id); - - rv = vnet_ipsec_gre_tunnel_add_del (a, &sw_if_index); - -out: - /* *INDENT-OFF* */ - REPLY_MACRO2(VL_API_IPSEC_GRE_TUNNEL_ADD_DEL_REPLY, - ({ - rmp->sw_if_index = ntohl (sw_if_index); - })); - /* *INDENT-ON* */ -} - -static void send_ipsec_gre_tunnel_details - (ipsec_gre_tunnel_t * t, vl_api_registration_t * reg, u32 context) -{ - vl_api_ipsec_gre_tunnel_details_t *rmp; - - rmp = vl_msg_api_alloc (sizeof (*rmp)); - clib_memset (rmp, 0, sizeof (*rmp)); - rmp->_vl_msg_id = ntohs (VL_API_IPSEC_GRE_TUNNEL_DETAILS); - - ip4_address_encode (&t->tunnel_src, rmp->tunnel.src); - ip4_address_encode (&t->tunnel_dst, rmp->tunnel.dst); - rmp->tunnel.sw_if_index = htonl (t->sw_if_index); - rmp->tunnel.local_sa_id = htonl (t->local_sa_id); - rmp->tunnel.remote_sa_id = htonl (t->remote_sa_id); - rmp->context = context; - - vl_api_send_msg (reg, (u8 *) rmp); -} - -static void vl_api_ipsec_gre_tunnel_dump_t_handler - (vl_api_ipsec_gre_tunnel_dump_t * mp) -{ - vl_api_registration_t *reg; - ipsec_gre_main_t *igm = &ipsec_gre_main; - ipsec_gre_tunnel_t *t; - u32 sw_if_index; - - reg = vl_api_client_index_to_registration (mp->client_index); - if (!reg) - return; - - sw_if_index = ntohl (mp->sw_if_index); - - if (~0 == sw_if_index) - { - /* *INDENT-OFF* */ - pool_foreach (t, igm->tunnels, - ({ - send_ipsec_gre_tunnel_details(t, reg, mp->context); - })); - /* *INDENT-ON* */ - } - else - { - if ((sw_if_index >= vec_len (igm->tunnel_index_by_sw_if_index)) || - (~0 == igm->tunnel_index_by_sw_if_index[sw_if_index])) - { - return; - } - t = &igm->tunnels[igm->tunnel_index_by_sw_if_index[sw_if_index]]; - send_ipsec_gre_tunnel_details (t, reg, mp->context); - } -} - -/* - * ipsec_gre_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_ipsec_gre; -#undef _ -} - -static clib_error_t * -ipsec_gre_api_hookup (vlib_main_t * vm) -{ - api_main_t *am = &api_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 (ipsec_gre_api_hookup); - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/vnet/ipsec-gre/ipsec_gre_doc.md b/src/vnet/ipsec-gre/ipsec_gre_doc.md deleted file mode 100644 index e1bb9cdab1a..00000000000 --- a/src/vnet/ipsec-gre/ipsec_gre_doc.md +++ /dev/null @@ -1,74 +0,0 @@ -# VPP L2-GRE over IPsec implementation {#ipsec_gre_doc} - -This is a memo intended to contain documentation of the VPP L2-GRE over IPsec implementation. -Everything that is not directly obvious should come here. - - -## L2-GRE over IPsec -GRE encapsulate layer 2 traffic and IPSec encrypt what is encapsulated by GRE. The whole point of L2-GRE over IPSec is to tunnel layer 2 over GRE and IPSec by bridging the physical interface with IPSec-GRE tunnel interface. - -There are 2 dedicated nodes for encapsulation: -* ipsec-gre<n>-tx - add GRE header -* esp-encrypt - encrypt GRE packet to ESP packet - -There are 3 dedicated nodes for decapsulation: -* ipsec-if-input - match IPSec SA by source IP address and SPI in ESP packet -* esp-decrypt - decrypt ESP packet -* ipsec-gre-input - remove GRE header - - -### Configuration - -L2-GRE over IPsec support the following CLI configuration command: - create ipsec gre tunnel src <addr> dst <addr> local-sa <id> remote-sa <id> [del] - -src: tunnel source IPv4 address -dst: tunnel destination IPv4 address -local-sa: tunnel local IPSec Security Association -remote-sa: tunnel remote IPSec Security Association -del: delete IPSec-GRE tunnel - -L2-GRE over IPsec support the following API configuration command: - ipsec_gre_add_del_tunnel src <addr> dst <addr> local_sa <sa-id> remote_sa <sa-id> [del] - -src: tunnel source IPv4 address -dst: tunnel destination IPv4 address -local_sa: tunnel local IPSec Security Association -remote_sa: tunnel remote IPSec Security Association -del: delete IPSec-GRE tunnel - - -### Configuration example - -Interface GigabitEthernet0/9/0 is in bridge with ipsec-gre0 tunnel interface, interface GigabitEthernet0/8/0 sending encapsulated and encrypted traffic. - -Configure IPv4 address on sending interface: -set int ip address GigabitEthernet0/8/0 192.168.1.1/24 - -Configure IPSec Security Associations: -ipsec sa add 10 spi 1001 esp crypto-key 4a506a794f574265564551694d653768 crypto-alg aes-cbc-128 integ-key 4339314b55523947594d6d3547666b45764e6a58 integ-alg sha1-96 -ipsec sa add 20 spi 1000 esp crypto-key 49517065716d6235726c734a4372466c crypto-alg aes-cbc-128 integ-key 307439636a5542735133595835546f68534e4f64 integ-alg sha1-96 - -Create IPSec-GRE tunnel: -create ipsec gre tunnel src 192.168.1.1 dst 192.168.1.2 local-sa 10 remote-sa 20 - -Set interfaces state: -set int state GigabitEthernet0/8/0 up -set int state GigabitEthernet0/9/0 up -set int state ipsec-gre0 up - -Bridge physical interface with IPSec-GRE tunnel interface: -set interface l2 bridge GigabitEthernet0/9/0 1 -set interface l2 bridge ipsec-gre0 1 - - -### Operational data - -L2-GRE over IPsec support the following CLI show command: - show ipsec gre tunnel - -L2-GRE over IPsec support the following API dump command: - ipsec_gre_tunnel_dump [sw_if_index <nn>] - -sw_if_index: software interface index of the IPSec-GRE tunnel interface - diff --git a/src/vnet/ipsec-gre/node.c b/src/vnet/ipsec-gre/node.c deleted file mode 100644 index 6a3aaa12e8c..00000000000 --- a/src/vnet/ipsec-gre/node.c +++ /dev/null @@ -1,426 +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-GRE over IPSec packet processing. - * - * Removes GRE header from the packet and sends it to the l2-input node. -*/ - -#include <vlib/vlib.h> -#include <vnet/pg/pg.h> -#include <vnet/ipsec-gre/ipsec_gre.h> -#include <vppinfra/sparse_vec.h> - -#define foreach_ipsec_gre_input_next \ -_(PUNT, "error-punt") \ -_(DROP, "error-drop") \ -_(L2_INPUT, "l2-input") - -typedef enum { -#define _(s,n) IPSEC_GRE_INPUT_NEXT_##s, - foreach_ipsec_gre_input_next -#undef _ - IPSEC_GRE_INPUT_N_NEXT, -} ipsec_gre_input_next_t; - -typedef struct { - u32 tunnel_id; - u32 length; - ip4_address_t src; - ip4_address_t dst; -} ipsec_gre_rx_trace_t; - -static u8 * format_ipsec_gre_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 *); - ipsec_gre_rx_trace_t * t = va_arg (*args, ipsec_gre_rx_trace_t *); - - s = format (s, "GRE: tunnel %d len %d src %U dst %U", - t->tunnel_id, clib_net_to_host_u16(t->length), - format_ip4_address, &t->src.as_u8, - format_ip4_address, &t->dst.as_u8); - return s; -} - -/** - * @brief L2-GRE over IPSec input node. - * @node ipsec-gre-input - * - * This node remove GRE header. - * - * @param vm vlib_main_t corresponding to the current thread. - * @param node vlib_node_runtime_t data for this node. - * @param from_frame vlib_frame_t whose contents should be dispatched. - * - * @par Graph mechanics: buffer metadata, next index usage - * - * <em>Uses:</em> - * - <code>ip->src_address</code> and <code>ip->dst_address</code> - * - Match tunnel by source and destination addresses in GRE IP header. - * - * <em>Sets:</em> - * - <code>vnet_buffer(b)->gre.src</code> - * - Save tunnel source IPv4 address. - * - <code>vnet_buffer(b)->gre.dst</code> - * - Save tunnel destination IPv4 address. - * - <code>vnet_buffer(b)->sw_if_index[VLIB_RX]</code> - * - Set input sw_if_index to IPSec-GRE tunnel for learning. - * - * <em>Next Index:</em> - * - Dispatches the packet to the l2-input node. -*/ -VLIB_NODE_FN (ipsec_gre_input_node) (vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_frame_t * from_frame) -{ - ipsec_gre_main_t * igm = &ipsec_gre_main; - u32 n_left_from, next_index, * from, * to_next; - u64 cached_tunnel_key = (u64) ~0; - u32 cached_tunnel_sw_if_index = 0, tunnel_sw_if_index; - u32 tun_src0, tun_dst0; - u32 tun_src1, tun_dst1; - - 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; - gre_header_t * h0, * h1; - u16 version0, version1, protocol0, protocol1; - int verr0, verr1; - u32 next0, next1; - ip4_header_t *ip0, *ip1; - - /* 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, sizeof (h0[0]), LOAD); - CLIB_PREFETCH (p3->data, sizeof (h1[0]), 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); - - /* ip4_local hands us the ip header, not the gre header */ - ip0 = vlib_buffer_get_current (b0); - ip1 = vlib_buffer_get_current (b1); - - /* Save src + dst ip4 address */ - tun_src0 = ip0->src_address.as_u32; - tun_dst0 = ip0->dst_address.as_u32; - tun_src1 = ip1->src_address.as_u32; - tun_dst1 = ip1->dst_address.as_u32; - - vlib_buffer_advance (b0, sizeof (*ip0)); - vlib_buffer_advance (b1, sizeof (*ip1)); - - h0 = vlib_buffer_get_current (b0); - h1 = vlib_buffer_get_current (b1); - - protocol0 = clib_net_to_host_u16 (h0->protocol); - protocol1 = clib_net_to_host_u16 (h1->protocol); - if (PREDICT_TRUE(protocol0 == GRE_PROTOCOL_teb)) - { - next0 = IPSEC_GRE_INPUT_NEXT_L2_INPUT; - b0->error = node->errors[IPSEC_GRE_ERROR_NONE]; - } - else - { - b0->error = node->errors[IPSEC_GRE_ERROR_UNKNOWN_PROTOCOL]; - next0 = IPSEC_GRE_INPUT_NEXT_DROP; - } - if (PREDICT_TRUE(protocol1 == GRE_PROTOCOL_teb)) - { - next1 = IPSEC_GRE_INPUT_NEXT_L2_INPUT; - b1->error = node->errors[IPSEC_GRE_ERROR_NONE]; - } - else - { - b1->error = node->errors[IPSEC_GRE_ERROR_UNKNOWN_PROTOCOL]; - next1 = IPSEC_GRE_INPUT_NEXT_DROP; - } - - version0 = clib_net_to_host_u16 (h0->flags_and_version); - verr0 = version0 & GRE_VERSION_MASK; - version1 = clib_net_to_host_u16 (h1->flags_and_version); - verr1 = version1 & GRE_VERSION_MASK; - - b0->error = verr0 ? node->errors[IPSEC_GRE_ERROR_UNSUPPORTED_VERSION] - : b0->error; - next0 = verr0 ? IPSEC_GRE_INPUT_NEXT_DROP : next0; - b1->error = verr1 ? node->errors[IPSEC_GRE_ERROR_UNSUPPORTED_VERSION] - : b1->error; - next1 = verr1 ? IPSEC_GRE_INPUT_NEXT_DROP : next1; - - /* For L2 payload set input sw_if_index to GRE tunnel for learning */ - if (PREDICT_TRUE(next0 == IPSEC_GRE_INPUT_NEXT_L2_INPUT)) - { - u64 key = ((u64)(tun_dst0) << 32) | (u64)(tun_src0); - - if (cached_tunnel_key != key) - { - vnet_hw_interface_t * hi; - ipsec_gre_tunnel_t * t; - uword * p; - - p = hash_get (igm->tunnel_by_key, key); - if (!p) - { - next0 = IPSEC_GRE_INPUT_NEXT_DROP; - b0->error = node->errors[IPSEC_GRE_ERROR_NO_SUCH_TUNNEL]; - goto drop0; - } - t = pool_elt_at_index (igm->tunnels, p[0]); - hi = vnet_get_hw_interface (igm->vnet_main, - t->hw_if_index); - tunnel_sw_if_index = hi->sw_if_index; - cached_tunnel_sw_if_index = tunnel_sw_if_index; - } - else - { - tunnel_sw_if_index = cached_tunnel_sw_if_index; - } - vnet_buffer(b0)->sw_if_index[VLIB_RX] = tunnel_sw_if_index; - } - -drop0: - /* For L2 payload set input sw_if_index to GRE tunnel for learning */ - if (PREDICT_TRUE(next1 == IPSEC_GRE_INPUT_NEXT_L2_INPUT)) - { - u64 key = ((u64)(tun_dst1) << 32) | (u64)(tun_src1); - - if (cached_tunnel_key != key) - { - vnet_hw_interface_t * hi; - ipsec_gre_tunnel_t * t; - uword * p; - - p = hash_get (igm->tunnel_by_key, key); - if (!p) - { - next1 = IPSEC_GRE_INPUT_NEXT_DROP; - b1->error = node->errors[IPSEC_GRE_ERROR_NO_SUCH_TUNNEL]; - goto drop1; - } - t = pool_elt_at_index (igm->tunnels, p[0]); - hi = vnet_get_hw_interface (igm->vnet_main, - t->hw_if_index); - tunnel_sw_if_index = hi->sw_if_index; - cached_tunnel_sw_if_index = tunnel_sw_if_index; - } - else - { - tunnel_sw_if_index = cached_tunnel_sw_if_index; - } - vnet_buffer(b1)->sw_if_index[VLIB_RX] = tunnel_sw_if_index; - } - -drop1: - if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED)) - { - ipsec_gre_rx_trace_t *tr = vlib_add_trace (vm, node, - b0, sizeof (*tr)); - tr->tunnel_id = ~0; - tr->length = ip0->length; - tr->src.as_u32 = ip0->src_address.as_u32; - tr->dst.as_u32 = ip0->dst_address.as_u32; - } - - if (PREDICT_FALSE(b1->flags & VLIB_BUFFER_IS_TRACED)) - { - ipsec_gre_rx_trace_t *tr = vlib_add_trace (vm, node, - b1, sizeof (*tr)); - tr->tunnel_id = ~0; - tr->length = ip1->length; - tr->src.as_u32 = ip1->src_address.as_u32; - tr->dst.as_u32 = ip1->dst_address.as_u32; - } - - vlib_buffer_advance (b0, sizeof (*h0)); - vlib_buffer_advance (b1, sizeof (*h1)); - - 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; - gre_header_t * h0; - ip4_header_t * ip0; - u16 version0, protocol0; - int verr0; - u32 next0; - u32 tun_src0, tun_dst0; - - 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); - ip0 = vlib_buffer_get_current (b0); - - tun_src0 = ip0->src_address.as_u32; - tun_dst0 = ip0->dst_address.as_u32; - - vlib_buffer_advance (b0, sizeof (*ip0)); - - h0 = vlib_buffer_get_current (b0); - - protocol0 = clib_net_to_host_u16 (h0->protocol); - if (PREDICT_TRUE(protocol0 == GRE_PROTOCOL_teb)) - { - next0 = IPSEC_GRE_INPUT_NEXT_L2_INPUT; - b0->error = node->errors[IPSEC_GRE_ERROR_NONE]; - } - else - { - b0->error = node->errors[IPSEC_GRE_ERROR_UNKNOWN_PROTOCOL]; - next0 = IPSEC_GRE_INPUT_NEXT_DROP; - } - - version0 = clib_net_to_host_u16 (h0->flags_and_version); - verr0 = version0 & GRE_VERSION_MASK; - b0->error = verr0 ? node->errors[IPSEC_GRE_ERROR_UNSUPPORTED_VERSION] - : b0->error; - next0 = verr0 ? IPSEC_GRE_INPUT_NEXT_DROP : next0; - - /* For L2 payload set input sw_if_index to GRE tunnel for learning */ - if (PREDICT_TRUE(next0 == IPSEC_GRE_INPUT_NEXT_L2_INPUT)) - { - u64 key = ((u64)(tun_dst0) << 32) | (u64)(tun_src0); - - if (cached_tunnel_key != key) - { - vnet_hw_interface_t * hi; - ipsec_gre_tunnel_t * t; - uword * p; - - p = hash_get (igm->tunnel_by_key, key); - if (!p) - { - next0 = IPSEC_GRE_INPUT_NEXT_DROP; - b0->error = node->errors[IPSEC_GRE_ERROR_NO_SUCH_TUNNEL]; - goto drop; - } - t = pool_elt_at_index (igm->tunnels, p[0]); - hi = vnet_get_hw_interface (igm->vnet_main, - t->hw_if_index); - tunnel_sw_if_index = hi->sw_if_index; - cached_tunnel_sw_if_index = tunnel_sw_if_index; - } - else - { - tunnel_sw_if_index = cached_tunnel_sw_if_index; - } - vnet_buffer(b0)->sw_if_index[VLIB_RX] = tunnel_sw_if_index; - } - -drop: - if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED)) - { - ipsec_gre_rx_trace_t *tr = vlib_add_trace (vm, node, - b0, sizeof (*tr)); - tr->tunnel_id = ~0; - tr->length = ip0->length; - tr->src.as_u32 = ip0->src_address.as_u32; - tr->dst.as_u32 = ip0->dst_address.as_u32; - } - - vlib_buffer_advance (b0, sizeof (*h0)); - - 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); - } - vlib_node_increment_counter (vm, ipsec_gre_input_node.index, - IPSEC_GRE_ERROR_PKTS_DECAP, from_frame->n_vectors); - return from_frame->n_vectors; -} - -static char * ipsec_gre_error_strings[] = { -#define ipsec_gre_error(n,s) s, -#include "error.def" -#undef ipsec_gre_error -}; - -VLIB_REGISTER_NODE (ipsec_gre_input_node) = { - .name = "ipsec-gre-input", - /* Takes a vector of packets. */ - .vector_size = sizeof (u32), - - .n_errors = IPSEC_GRE_N_ERROR, - .error_strings = ipsec_gre_error_strings, - - .n_next_nodes = IPSEC_GRE_INPUT_N_NEXT, - .next_nodes = { -#define _(s,n) [IPSEC_GRE_INPUT_NEXT_##s] = n, - foreach_ipsec_gre_input_next -#undef _ - }, - - .format_trace = format_ipsec_gre_rx_trace, -}; - -static clib_error_t * ipsec_gre_input_init (vlib_main_t * vm) -{ - { - clib_error_t * error; - error = vlib_call_init_function (vm, ipsec_gre_init); - if (error) - clib_error_report (error); - } - - return 0; -} - -VLIB_INIT_FUNCTION (ipsec_gre_input_init); |