diff options
author | Damjan Marion <damarion@cisco.com> | 2016-12-19 23:05:39 +0100 |
---|---|---|
committer | Damjan Marion <damarion@cisco.com> | 2016-12-28 12:25:14 +0100 |
commit | 7cd468a3d7dee7d6c92f69a0bb7061ae208ec727 (patch) | |
tree | 5de62f8dbd3a752f5a676ca600e43d2652d1ff1a /vnet/vnet/ipsec-gre | |
parent | 696f1adec0df3b8f161862566dd9c86174302658 (diff) |
Reorganize source tree to use single autotools instance
Change-Id: I7b51f88292e057c6443b12224486f2d0c9f8ae23
Signed-off-by: Damjan Marion <damarion@cisco.com>
Diffstat (limited to 'vnet/vnet/ipsec-gre')
-rw-r--r-- | vnet/vnet/ipsec-gre/dir.dox | 18 | ||||
-rw-r--r-- | vnet/vnet/ipsec-gre/error.def | 26 | ||||
-rw-r--r-- | vnet/vnet/ipsec-gre/interface.c | 311 | ||||
-rw-r--r-- | vnet/vnet/ipsec-gre/ipsec_gre.api | 79 | ||||
-rw-r--r-- | vnet/vnet/ipsec-gre/ipsec_gre.c | 407 | ||||
-rw-r--r-- | vnet/vnet/ipsec-gre/ipsec_gre.h | 114 | ||||
-rw-r--r-- | vnet/vnet/ipsec-gre/ipsec_gre_api.c | 190 | ||||
-rw-r--r-- | vnet/vnet/ipsec-gre/ipsec_gre_doc.md | 74 | ||||
-rw-r--r-- | vnet/vnet/ipsec-gre/node.c | 433 |
9 files changed, 0 insertions, 1652 deletions
diff --git a/vnet/vnet/ipsec-gre/dir.dox b/vnet/vnet/ipsec-gre/dir.dox deleted file mode 100644 index e6ffd10b01b..00000000000 --- a/vnet/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/vnet/vnet/ipsec-gre/error.def b/vnet/vnet/ipsec-gre/error.def deleted file mode 100644 index d84e8ed1759..00000000000 --- a/vnet/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/vnet/vnet/ipsec-gre/interface.c b/vnet/vnet/ipsec-gre/interface.c deleted file mode 100644 index 56832ee1006..00000000000 --- a/vnet/vnet/ipsec-gre/interface.c +++ /dev/null @@ -1,311 +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> - -#if DPDK_CRYPTO==1 -#include <vnet/devices/dpdk/ipsec/esp.h> -#define ESP_NODE "dpdk-esp-encrypt" -#else -#include <vnet/ipsec/esp.h> -#define ESP_NODE "esp-encrypt" -#endif - -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_add_del_tunnel_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_add_del_tunnel (vnet_ipsec_gre_add_del_tunnel_args_t * a, - u32 * sw_if_indexp) -{ - ipsec_gre_main_t *igm = &ipsec_gre_main; - vnet_main_t *vnm = igm->vnet_main; - ip4_main_t *im = &ip4_main; - ipsec_gre_tunnel_t *t; - vnet_hw_interface_t *hi; - u32 hw_if_index, sw_if_index; - u32 slot; - uword *p; - u64 key; - ipsec_add_del_ipsec_gre_tunnel_args_t args; - - memset (&args, 0, sizeof (args)); - args.is_add = a->is_add; - args.local_sa_id = a->lsa; - args.remote_sa_id = a->rsa; - args.local_ip.as_u32 = a->src.as_u32; - args.remote_ip.as_u32 = a->dst.as_u32; - - 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); - 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->lsa; - t->remote_sa_id = a->rsa; - t->local_sa = ipsec_get_sa_index_by_sa_id (a->lsa); - t->remote_sa = ipsec_get_sa_index_by_sa_id (a->rsa); - - 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; - - vec_validate (im->fib_index_by_sw_if_index, sw_if_index); - - hi->min_packet_bytes = 64 + sizeof (gre_header_t) + - sizeof (ip4_header_t) + sizeof (esp_header_t) + sizeof (esp_footer_t); - hi->per_packet_overhead_bytes = - /* preamble */ 8 + /* inter frame gap */ 12; - - /* Standard default gre MTU. */ - hi->max_l3_packet_bytes[VLIB_RX] = hi->max_l3_packet_bytes[VLIB_TX] = - 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_named_next_with_slot - (vnm->vlib_main, hi->tx_node_index, ESP_NODE, - 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, 0, 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, &args); -} - -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; - u8 is_add = 1; - u32 num_m_args = 0; - ip4_address_t src, dst; - u32 lsa = 0, rsa = 0; - vnet_ipsec_gre_add_del_tunnel_args_t _a, *a = &_a; - int rv; - u32 sw_if_index; - - /* 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, "src %U", unformat_ip4_address, &src)) - num_m_args++; - else if (unformat (line_input, "dst %U", unformat_ip4_address, &dst)) - num_m_args++; - else if (unformat (line_input, "local-sa %d", &lsa)) - num_m_args++; - else if (unformat (line_input, "remote-sa %d", &rsa)) - num_m_args++; - else - return clib_error_return (0, "unknown input `%U'", - format_unformat_error, input); - } - unformat_free (line_input); - - if (num_m_args < 4) - return clib_error_return (0, "mandatory argument(s) missing"); - - if (memcmp (&src, &dst, sizeof (src)) == 0) - return clib_error_return (0, "src and dst are identical"); - - memset (a, 0, sizeof (*a)); - a->is_add = is_add; - a->lsa = lsa; - a->rsa = rsa; - clib_memcpy (&a->src, &src, sizeof (src)); - clib_memcpy (&a->dst, &dst, sizeof (dst)); - - rv = vnet_ipsec_gre_add_del_tunnel (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: - return clib_error_return (0, "GRE tunnel already exists..."); - default: - return clib_error_return (0, - "vnet_ipsec_gre_add_del_tunnel returned %d", - rv); - } - - return 0; -} - -/* *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/vnet/vnet/ipsec-gre/ipsec_gre.api b/vnet/vnet/ipsec-gre/ipsec_gre.api deleted file mode 100644 index 793bca0afcd..00000000000 --- a/vnet/vnet/ipsec-gre/ipsec_gre.api +++ /dev/null @@ -1,79 +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. - */ - -/** \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 SA id - @param remote_sa_id - remote SA id - @param is_add - 1 if adding the tunnel, 0 if deleting - @param src_address - tunnel source address - @param dst_address - tunnel destination address -*/ -define ipsec_gre_add_del_tunnel { - u32 client_index; - u32 context; - u32 local_sa_id; - u32 remote_sa_id; - u8 is_add; - u8 src_address[4]; - u8 dst_address[4]; -}; - -/** \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_add_del_tunnel_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 sw_if_index - software index of the ipsec gre tunnel - @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; - u32 sw_if_index; - u32 local_sa_id; - u32 remote_sa_id; - u8 src_address[4]; - u8 dst_address[4]; -}; - -/* - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ -
\ No newline at end of file diff --git a/vnet/vnet/ipsec-gre/ipsec_gre.c b/vnet/vnet/ipsec-gre/ipsec_gre.c deleted file mode 100644 index a0b065ac283..00000000000 --- a/vnet/vnet/ipsec-gre/ipsec_gre.c +++ /dev/null @@ -1,407 +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> - -ipsec_gre_main_t ipsec_gre_main; - -/** - * @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; - -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>Nexd Index:</em> - * - Dispatches the packet to the esp-encrypt node. -*/ -static uword -ipsec_gre_interface_tx (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); - - /* 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; - u16 gre_protocol0, gre_protocol1; - - /* 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); - - ip0 = vlib_buffer_get_current (b0); - gre_protocol0 = clib_net_to_host_u16 (0x01); - - ip1 = vlib_buffer_get_current (b1); - gre_protocol1 = clib_net_to_host_u16 (0x01); - - 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 = gre_protocol0; - 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 = gre_protocol1; - 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; - u16 gre_protocol0; - - 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); - - gre_protocol0 = clib_net_to_host_u16 (0x01); - - 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 = gre_protocol0; - 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, - .tx_function = ipsec_gre_interface_tx, - .admin_up_down_function = ipsec_gre_interface_admin_up_down, -}; - -VLIB_DEVICE_TX_FUNCTION_MULTIARCH (ipsec_gre_device_class, - ipsec_gre_interface_tx) - - -VNET_HW_INTERFACE_CLASS (ipsec_gre_hw_interface_class) = { - .name = "IPSEC-GRE", -}; -/* *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; - - 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); - -ipsec_gre_main_t * -ipsec_gre_get_main (vlib_main_t * vm) -{ - vlib_call_init_function (vm, ipsec_gre_init); - return &ipsec_gre_main; -} - -/* -* fd.io coding-style-patch-verification: ON -* -* Local Variables: -* eval: (c-set-style "gnu") -* End: -*/ diff --git a/vnet/vnet/ipsec-gre/ipsec_gre.h b/vnet/vnet/ipsec-gre/ipsec_gre.h deleted file mode 100644 index a2ca64b6f74..00000000000 --- a/vnet/vnet/ipsec-gre/ipsec_gre.h +++ /dev/null @@ -1,114 +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> - -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 -{ - 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; - -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 1 - -/** - * @brief IPSec-GRE tunnel add/del arguments. - * -*/ -typedef struct -{ - u8 is_add; /**< 1 - add, 0 - delete */ - - ip4_address_t src; /**< tunnel IPv4 src address */ - ip4_address_t dst; /**< tunnel IPv4 dst address */ - u32 lsa; /**< local IPSec SA id */ - u32 rsa; /**< remote IPSec SA id */ -} vnet_ipsec_gre_add_del_tunnel_args_t; - -int vnet_ipsec_gre_add_del_tunnel - (vnet_ipsec_gre_add_del_tunnel_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/vnet/vnet/ipsec-gre/ipsec_gre_api.c b/vnet/vnet/ipsec-gre/ipsec_gre_api.c deleted file mode 100644 index a7ea1490bae..00000000000 --- a/vnet/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/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_ADD_DEL_TUNNEL, ipsec_gre_add_del_tunnel) \ -_(IPSEC_GRE_TUNNEL_DUMP, ipsec_gre_tunnel_dump) - -static void -vl_api_ipsec_gre_add_del_tunnel_t_handler (vl_api_ipsec_gre_add_del_tunnel_t * - mp) -{ - vl_api_ipsec_gre_add_del_tunnel_reply_t *rmp; - int rv = 0; - vnet_ipsec_gre_add_del_tunnel_args_t _a, *a = &_a; - u32 sw_if_index = ~0; - - /* Check src & dst are different */ - if (memcmp (mp->src_address, mp->dst_address, 4) == 0) - { - rv = VNET_API_ERROR_SAME_SRC_DST; - goto out; - } - - memset (a, 0, sizeof (*a)); - - /* ip addresses sent in network byte order */ - clib_memcpy (&(a->src), mp->src_address, 4); - clib_memcpy (&(a->dst), mp->dst_address, 4); - a->is_add = mp->is_add; - a->lsa = ntohl (mp->local_sa_id); - a->rsa = ntohl (mp->remote_sa_id); - - rv = vnet_ipsec_gre_add_del_tunnel (a, &sw_if_index); - -out: - /* *INDENT-OFF* */ - REPLY_MACRO2(VL_API_GRE_ADD_DEL_TUNNEL_REPLY, - ({ - rmp->sw_if_index = ntohl (sw_if_index); - })); - /* *INDENT-ON* */ -} - -static void send_ipsec_gre_tunnel_details - (ipsec_gre_tunnel_t * t, unix_shared_memory_queue_t * q, u32 context) -{ - vl_api_ipsec_gre_tunnel_details_t *rmp; - - rmp = vl_msg_api_alloc (sizeof (*rmp)); - memset (rmp, 0, sizeof (*rmp)); - rmp->_vl_msg_id = ntohs (VL_API_IPSEC_GRE_TUNNEL_DETAILS); - clib_memcpy (rmp->src_address, &(t->tunnel_src), 4); - clib_memcpy (rmp->dst_address, &(t->tunnel_dst), 4); - rmp->sw_if_index = htonl (t->sw_if_index); - rmp->local_sa_id = htonl (t->local_sa_id); - rmp->remote_sa_id = htonl (t->remote_sa_id); - rmp->context = context; - - vl_msg_api_send_shmem (q, (u8 *) & rmp); -} - -static void vl_api_ipsec_gre_tunnel_dump_t_handler - (vl_api_ipsec_gre_tunnel_dump_t * mp) -{ - unix_shared_memory_queue_t *q; - ipsec_gre_main_t *igm = &ipsec_gre_main; - ipsec_gre_tunnel_t *t; - u32 sw_if_index; - - q = vl_api_client_index_to_input_queue (mp->client_index); - if (q == 0) - { - 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, q, 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, q, mp->context); - } -} - -/* - * ipsec_gre_api_hookup - * Add vpe's API message handlers to the table. - * vlib has alread 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/vnet/vnet/ipsec-gre/ipsec_gre_doc.md b/vnet/vnet/ipsec-gre/ipsec_gre_doc.md deleted file mode 100644 index e1bb9cdab1a..00000000000 --- a/vnet/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/vnet/vnet/ipsec-gre/node.c b/vnet/vnet/ipsec-gre/node.c deleted file mode 100644 index d20f248a6c8..00000000000 --- a/vnet/vnet/ipsec-gre/node.c +++ /dev/null @@ -1,433 +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; - -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. -*/ -static uword -ipsec_gre_input (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; - - 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 */ - vnet_buffer(b0)->gre.src = ip0->src_address.as_u32; - vnet_buffer(b0)->gre.dst = ip0->dst_address.as_u32; - vnet_buffer(b1)->gre.src = ip1->src_address.as_u32; - vnet_buffer(b1)->gre.dst = 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 == 0x0001)) - { - next0 = IPSEC_GRE_INPUT_NEXT_L2_INPUT; - b0->error = node->errors[IPSEC_GRE_ERROR_NONE]; - } - else - { - clib_warning("unknown GRE protocol: %d", protocol0); - b0->error = node->errors[IPSEC_GRE_ERROR_UNKNOWN_PROTOCOL]; - next0 = IPSEC_GRE_INPUT_NEXT_DROP; - } - if (PREDICT_TRUE(protocol1 == 0x0001)) - { - next1 = IPSEC_GRE_INPUT_NEXT_L2_INPUT; - b1->error = node->errors[IPSEC_GRE_ERROR_NONE]; - } - else - { - clib_warning("unknown GRE protocol: %d", protocol1); - 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)(vnet_buffer(b0)->gre.dst) << 32) | - (u64)(vnet_buffer(b0)->gre.src); - - 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)(vnet_buffer(b1)->gre.dst) << 32) | - (u64)(vnet_buffer(b1)->gre.src); - - 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; - - 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); - - vnet_buffer(b0)->gre.src = ip0->src_address.as_u32; - vnet_buffer(b0)->gre.dst = 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 == 0x0001)) - { - next0 = IPSEC_GRE_INPUT_NEXT_L2_INPUT; - b0->error = node->errors[IPSEC_GRE_ERROR_NONE]; - } - else - { - clib_warning("unknown GRE protocol: %d", protocol0); - 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_FALSE(next0 == IPSEC_GRE_INPUT_NEXT_L2_INPUT)) - { - u64 key = ((u64)(vnet_buffer(b0)->gre.dst) << 32) | - (u64)(vnet_buffer(b0)->gre.src); - - 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) = { - .function = ipsec_gre_input, - .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, -}; - -VLIB_NODE_FUNCTION_MULTIARCH (ipsec_gre_input_node, ipsec_gre_input) - -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); |