From b71fa75d48b16f45618ba3fe3aa847c331f837b0 Mon Sep 17 00:00:00 2001 From: Neale Ranns Date: Thu, 4 Apr 2019 12:43:36 +0000 Subject: [PATCH] IPSEC: punt reasons; SPI=0, no-tunnel Change-Id: If76992e283a27fa193a6865257ab3aa764066e48 Signed-off-by: Neale Ranns --- src/vnet/CMakeLists.txt | 1 + src/vnet/ipsec/ipsec_if_in.c | 68 +++++++++++++++++++++++++++++++++++--------- src/vnet/ipsec/ipsec_io.h | 1 + src/vnet/ipsec/ipsec_punt.c | 51 +++++++++++++++++++++++++++++++++ src/vnet/ipsec/ipsec_punt.h | 47 ++++++++++++++++++++++++++++++ test/test_punt.py | 12 ++++---- 6 files changed, 161 insertions(+), 19 deletions(-) create mode 100644 src/vnet/ipsec/ipsec_punt.c create mode 100644 src/vnet/ipsec/ipsec_punt.h diff --git a/src/vnet/CMakeLists.txt b/src/vnet/CMakeLists.txt index c96da2a6c57..89d46a14b82 100644 --- a/src/vnet/CMakeLists.txt +++ b/src/vnet/CMakeLists.txt @@ -556,6 +556,7 @@ list(APPEND VNET_SOURCES ipsec/ipsec_input.c ipsec/ipsec_if.c ipsec/ipsec_if_in.c + ipsec/ipsec_punt.c ipsec/ipsec_sa.c ipsec/ipsec_spd.c ipsec/ipsec_spd_policy.c diff --git a/src/vnet/ipsec/ipsec_if_in.c b/src/vnet/ipsec/ipsec_if_in.c index 9ba2c10bca6..b585c3d4dcf 100644 --- a/src/vnet/ipsec/ipsec_if_in.c +++ b/src/vnet/ipsec/ipsec_if_in.c @@ -22,12 +22,14 @@ #include #include #include +#include /* Statistics (not really errors) */ #define foreach_ipsec_if_input_error \ _(RX, "good packets received") \ _(DISABLED, "ipsec packets received on disabled interface") \ -_(NO_TUNNEL, "no matching tunnel") +_(NO_TUNNEL, "no matching tunnel") \ +_(SPI_0, "SPI 0") static char *ipsec_if_input_error_strings[] = { #define _(sym,string) string, @@ -61,6 +63,46 @@ format_ipsec_if_input_trace (u8 * s, va_list * args) return s; } +always_inline u16 +ipsec_ip4_if_no_tunnel (vlib_node_runtime_t * node, + vlib_buffer_t * b, + const esp_header_t * esp, + const ip4_header_t * ip4, u16 offset) +{ + if (PREDICT_FALSE (0 == esp->spi)) + { + b->error = node->errors[IPSEC_IF_INPUT_ERROR_SPI_0]; + b->punt_reason = + ipsec_punt_reason[(ip4->protocol == IP_PROTOCOL_UDP ? + IPSEC_PUNT_IP4_SPI_UDP_0 : IPSEC_PUNT_IP4_SPI_0)]; + } + else + { + b->error = node->errors[IPSEC_IF_INPUT_ERROR_NO_TUNNEL]; + b->punt_reason = ipsec_punt_reason[IPSEC_PUNT_IP4_NO_SUCH_TUNNEL]; + } + vlib_buffer_advance (b, -offset); + return IPSEC_INPUT_NEXT_PUNT; +} + +always_inline u16 +ipsec_ip6_if_no_tunnel (vlib_node_runtime_t * node, + vlib_buffer_t * b, + const esp_header_t * esp, u16 offset) +{ + if (PREDICT_FALSE (0 == esp->spi)) + { + b->error = node->errors[IPSEC_IF_INPUT_ERROR_NO_TUNNEL]; + b->punt_reason = ipsec_punt_reason[IPSEC_PUNT_IP6_SPI_0]; + } + else + { + b->error = node->errors[IPSEC_IF_INPUT_ERROR_NO_TUNNEL]; + b->punt_reason = ipsec_punt_reason[IPSEC_PUNT_IP6_NO_SUCH_TUNNEL]; + } + vlib_buffer_advance (b, -offset); + return (IPSEC_INPUT_NEXT_PUNT); +} always_inline uword ipsec_if_input_inline (vlib_main_t * vm, vlib_node_runtime_t * node, @@ -197,9 +239,9 @@ ipsec_if_input_inline (vlib_main_t * vm, vlib_node_runtime_t * node, } else { - b[0]->error = node->errors[IPSEC_IF_INPUT_ERROR_NO_TUNNEL]; + next[0] = + ipsec_ip6_if_no_tunnel (node, b[0], esp0, buf_adv0); n_no_tunnel++; - next[0] = IPSEC_INPUT_NEXT_DROP; goto pkt1; } } @@ -225,9 +267,9 @@ ipsec_if_input_inline (vlib_main_t * vm, vlib_node_runtime_t * node, } else { - b[0]->error = node->errors[IPSEC_IF_INPUT_ERROR_NO_TUNNEL]; + next[0] = + ipsec_ip4_if_no_tunnel (node, b[0], esp0, ip40, buf_adv0); n_no_tunnel++; - next[0] = IPSEC_INPUT_NEXT_DROP; goto pkt1; } } @@ -293,9 +335,9 @@ ipsec_if_input_inline (vlib_main_t * vm, vlib_node_runtime_t * node, } else { - b[1]->error = node->errors[IPSEC_IF_INPUT_ERROR_NO_TUNNEL]; + next[1] = + ipsec_ip6_if_no_tunnel (node, b[1], esp1, buf_adv1); n_no_tunnel++; - next[1] = IPSEC_INPUT_NEXT_DROP; goto trace1; } } @@ -321,9 +363,9 @@ ipsec_if_input_inline (vlib_main_t * vm, vlib_node_runtime_t * node, } else { - b[1]->error = node->errors[IPSEC_IF_INPUT_ERROR_NO_TUNNEL]; + next[1] = + ipsec_ip4_if_no_tunnel (node, b[1], esp1, ip41, buf_adv1); n_no_tunnel++; - next[1] = IPSEC_INPUT_NEXT_DROP; goto trace1; } } @@ -456,9 +498,9 @@ ipsec_if_input_inline (vlib_main_t * vm, vlib_node_runtime_t * node, } else { - b[0]->error = node->errors[IPSEC_IF_INPUT_ERROR_NO_TUNNEL]; + next[0] = + ipsec_ip6_if_no_tunnel (node, b[0], esp0, buf_adv0); n_no_tunnel++; - next[0] = IPSEC_INPUT_NEXT_DROP; goto trace00; } } @@ -484,9 +526,9 @@ ipsec_if_input_inline (vlib_main_t * vm, vlib_node_runtime_t * node, } else { - b[0]->error = node->errors[IPSEC_IF_INPUT_ERROR_NO_TUNNEL]; + next[0] = + ipsec_ip4_if_no_tunnel (node, b[0], esp0, ip40, buf_adv0); n_no_tunnel++; - next[0] = IPSEC_INPUT_NEXT_DROP; goto trace00; } } diff --git a/src/vnet/ipsec/ipsec_io.h b/src/vnet/ipsec/ipsec_io.h index f156b48360f..32668a0474f 100644 --- a/src/vnet/ipsec/ipsec_io.h +++ b/src/vnet/ipsec/ipsec_io.h @@ -27,6 +27,7 @@ typedef enum } ipsec_output_next_t; #define foreach_ipsec_input_next \ + _ (PUNT, "punt-dispatch") \ _ (DROP, "error-drop") #define _(v, s) IPSEC_INPUT_NEXT_##v, diff --git a/src/vnet/ipsec/ipsec_punt.c b/src/vnet/ipsec/ipsec_punt.c new file mode 100644 index 00000000000..357e9596cfc --- /dev/null +++ b/src/vnet/ipsec/ipsec_punt.c @@ -0,0 +1,51 @@ +/* + * esp_decrypt.c : IPSec ESP decrypt node + * + * Copyright (c) 2015 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 +#include + +static vlib_punt_hdl_t punt_hdl; + +vlib_punt_reason_t ipsec_punt_reason[IPSEC_PUNT_N_REASONS]; + +static clib_error_t * +ipsec_punt_init (vlib_main_t * vm) +{ + clib_error_t *error; + + if ((error = vlib_call_init_function (vm, punt_init))) + return (error); + + punt_hdl = vlib_punt_client_register ("ipsec"); + +#define _(s,v) vlib_punt_reason_alloc (punt_hdl, v, \ + &ipsec_punt_reason[IPSEC_PUNT_##s]); + foreach_ipsec_punt_reason +#undef _ + return (error); +} + +VLIB_INIT_FUNCTION (ipsec_punt_init); + + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ diff --git a/src/vnet/ipsec/ipsec_punt.h b/src/vnet/ipsec/ipsec_punt.h new file mode 100644 index 00000000000..19943273154 --- /dev/null +++ b/src/vnet/ipsec/ipsec_punt.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef __IPSEC_PUNT_H__ +#define __IPSEC_PUNT_H__ + +#include + +#define foreach_ipsec_punt_reason \ + _(IP4_SPI_0, "ip4-spi-0") \ + _(IP6_SPI_0, "ip6-spi-0") \ + _(IP4_SPI_UDP_0, "ip4-spi-o-udp-0") \ + _(IP4_NO_SUCH_TUNNEL, "ip4-no-such-tunnel") \ + _(IP6_NO_SUCH_TUNNEL, "ip6-no-such-tunnel") + +typedef enum ipsec_punt_reason_t_ +{ +#define _(s,v) IPSEC_PUNT_##s, + foreach_ipsec_punt_reason +#undef _ + IPSEC_PUNT_N_REASONS, +} ipsec_punt_reason_type_t; + +extern u8 *format_ipsec_punt_reason (u8 * s, va_list * args); + +extern vlib_punt_reason_t ipsec_punt_reason[IPSEC_PUNT_N_REASONS]; + +#endif /* __IPSEC_SPD_H__ */ + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ diff --git a/test/test_punt.py b/test/test_punt.py index b190101fe82..cb9d40de4c4 100644 --- a/test/test_punt.py +++ b/test/test_punt.py @@ -760,8 +760,8 @@ class TestPunt(VppTestCase): self.assertEqual(stats, 130) stats = self.statistics.get_counter("/net/punt") - self.assertEqual(stats[0][2]['packets'], 65) - self.assertEqual(stats[0][3]['packets'], 65) + self.assertEqual(stats[0][7]['packets'], 65) + self.assertEqual(stats[0][8]['packets'], 65) # # use the test CLI to test a client that punts exception @@ -788,8 +788,8 @@ class TestPunt(VppTestCase): self.assertEqual(p6[IPv6].hlim, rx[IPv6].hlim) stats = self.statistics.get_counter("/net/punt") - self.assertEqual(stats[0][2]['packets'], 2*65) - self.assertEqual(stats[0][3]['packets'], 2*65) + self.assertEqual(stats[0][7]['packets'], 2*65) + self.assertEqual(stats[0][8]['packets'], 2*65) # # add another registration for the same reason to send packets @@ -835,8 +835,8 @@ class TestPunt(VppTestCase): self.assertEqual(p6[IPv6].hlim, rx[IPv6].hlim) stats = self.statistics.get_counter("/net/punt") - self.assertEqual(stats[0][2]['packets'], 3*65) - self.assertEqual(stats[0][3]['packets'], 3*65) + self.assertEqual(stats[0][7]['packets'], 3*65) + self.assertEqual(stats[0][8]['packets'], 3*65) self.logger.info(self.vapi.cli("show vlib graph punt-dispatch")) self.logger.info(self.vapi.cli("show punt client")) -- 2.16.6