ikev2: use new counters data model & add more counters 67/30767/4
authorFilip Tehlar <ftehlar@cisco.com>
Thu, 14 Jan 2021 13:32:01 +0000 (13:32 +0000)
committerBeno�t Ganne <bganne@cisco.com>
Wed, 20 Jan 2021 14:49:12 +0000 (14:49 +0000)
Type: feature
Ticket: VPP-1916

Change-Id: Ibe612d21f748a532d88b73b286dc4a1dd15d7420
Signed-off-by: Filip Tehlar <ftehlar@cisco.com>
src/plugins/ikev2/ikev2.api
src/plugins/ikev2/ikev2.c
src/plugins/ikev2/test/test_ikev2.py

index 9f44cba..f936e52 100644 (file)
@@ -496,6 +496,92 @@ autoreply define ikev2_profile_set_liveness
   option status="in_progress";
 };
 
+counters ikev2 {
+  processed {
+    severity info;
+    type counter64;
+    units "packets";
+    description "packets processed";
+  };
+  ike_sa_init_retransmit {
+    severity info;
+    type counter64;
+    units "packets";
+    description "IKE SA INIT retransmit";
+  };
+  ike_sa_init_ignore {
+    severity error;
+    type counter64;
+    units "packets";
+    description "IKE_SA_INIT ignore (IKE SA already auth)";
+  };
+  ike_req_retransmit {
+    severity error;
+    type counter64;
+    units "packets";
+    description "IKE request retransmit";
+  };
+  ike_req_ignore {
+    severity error;
+    type counter64;
+    units "packets";
+    description "IKE request ignore (old msgid)";
+  };
+  not_ikev2 {
+    severity error;
+    type counter64;
+    units "packets";
+    description "Non IKEv2 packets received";
+  };
+  bad_length {
+    severity error;
+    type counter64;
+    units "packets";
+    description "Bad packet length";
+  };
+  malformed_packet {
+    severity error;
+    type counter64;
+    units "packets";
+    description "Malformed packet";
+  };
+  no_buff_space {
+    severity error;
+    type counter64;
+    units "packets";
+    description "No buffer space";
+  };
+  keepalive {
+    severity info;
+    type counter64;
+    units "packets";
+    description "IKE keepalive messages received";
+  };
+  rekey_req {
+    severity info;
+    type counter64;
+    units "packets";
+    description "IKE rekey requests received";
+  };
+  exchange_sa_req {
+    severity info;
+    type counter64;
+    units "packets";
+    description "IKE EXCHANGE SA requests received";
+  };
+  ike_auth_req {
+    severity info;
+    type counter64;
+    units "packets";
+    description "IKE AUTH SA requests received";
+  };
+};
+paths {
+  "/err/ikev2-ip4" "ike";
+  "/err/ikev2-ip6" "ike";
+  "/err/ikev2-ip4-natt" "ike";
+};
+
 /*
  * Local Variables:
  * eval: (c-set-style "gnu")
index cfc3d9f..c9a8647 100644 (file)
@@ -28,6 +28,7 @@
 #include <plugins/ikev2/ikev2_priv.h>
 #include <openssl/sha.h>
 #include <vnet/ipsec/ipsec_punt.h>
+#include <plugins/ikev2/ikev2.api_enum.h>
 
 #define IKEV2_LIVENESS_RETRIES 3
 #define IKEV2_LIVENESS_PERIOD_CHECK 30
@@ -49,6 +50,14 @@ typedef struct
   u32 sw_if_index;
 } ikev2_trace_t;
 
+typedef struct
+{
+  u16 n_keepalives;
+  u16 n_rekey_req;
+  u16 n_exchange_sa_req;
+  u16 n_ike_auth_req;
+} ikev2_stats_t;
+
 static u8 *
 format_ikev2_trace (u8 * s, va_list * args)
 {
@@ -92,31 +101,6 @@ format_ikev2_gen_sa_error (u8 * s, va_list * args)
   return s;
 }
 
-#define foreach_ikev2_error \
-_(PROCESSED, "IKEv2 packets processed") \
-_(IKE_SA_INIT_RETRANSMIT, "IKE_SA_INIT retransmit ") \
-_(IKE_SA_INIT_IGNORE, "IKE_SA_INIT ignore (IKE SA already auth)") \
-_(IKE_REQ_RETRANSMIT, "IKE request retransmit") \
-_(IKE_REQ_IGNORE, "IKE request ignore (old msgid)") \
-_(NOT_IKEV2, "Non IKEv2 packets received") \
-_(BAD_LENGTH, "Bad packet length") \
-_(MALFORMED_PACKET, "Malformed packet") \
-_(NO_BUFF_SPACE, "No buffer space")
-
-typedef enum
-{
-#define _(sym,str) IKEV2_ERROR_##sym,
-  foreach_ikev2_error
-#undef _
-    IKEV2_N_ERROR,
-} ikev2_error_t;
-
-static char *ikev2_error_strings[] = {
-#define _(sym,string) string,
-  foreach_ikev2_error
-#undef _
-};
-
 typedef enum
 {
   IKEV2_NEXT_IP4_LOOKUP,
@@ -2264,8 +2248,8 @@ ikev2_delete_tunnel_interface (vnet_main_t * vnm, ikev2_sa_t * sa,
 }
 
 static u32
-ikev2_generate_message (vlib_buffer_t * b, ikev2_sa_t * sa,
-                       ike_header_t * ike, void *user, udp_header_t * udp)
+ikev2_generate_message (vlib_buffer_t *b, ikev2_sa_t *sa, ike_header_t *ike,
+                       void *user, udp_header_t *udp, ikev2_stats_t *stats)
 {
   ikev2_main_t *km = &ikev2_main;
   u16 buffer_data_size = vlib_buffer_get_default_data_size (km->vlib_main);
@@ -2448,7 +2432,15 @@ ikev2_generate_message (vlib_buffer_t * b, ikev2_sa_t * sa,
          vec_free (data);
          sa->unsupported_cp = 0;
        }
-      /* else send empty response */
+      else
+       /* else send empty response */
+       {
+         if (ike_hdr_is_response (ike))
+           {
+             ASSERT (stats != 0);
+             stats->n_keepalives++;
+           }
+       }
     }
   else if (ike->exchange == IKEV2_EXCHANGE_CREATE_CHILD_SA)
     {
@@ -2833,6 +2825,19 @@ ikev2_generate_sa_init_data_and_log (ikev2_sa_t * sa)
     ikev2_elog_error (IKEV2_GENERATE_SA_INIT_OK_ERR_UNSUPP_STR);
 }
 
+static void
+ikev2_update_stats (vlib_main_t *vm, u32 node_index, ikev2_stats_t *s)
+{
+  vlib_node_increment_counter (vm, node_index, IKEV2_ERROR_KEEPALIVE,
+                              s->n_keepalives);
+  vlib_node_increment_counter (vm, node_index, IKEV2_ERROR_REKEY_REQ,
+                              s->n_rekey_req);
+  vlib_node_increment_counter (vm, node_index, IKEV2_ERROR_EXCHANGE_SA_REQ,
+                              s->n_exchange_sa_req);
+  vlib_node_increment_counter (vm, node_index, IKEV2_ERROR_IKE_AUTH_REQ,
+                              s->n_ike_auth_req);
+}
+
 static_always_inline uword
 ikev2_node_internal (vlib_main_t *vm, vlib_node_runtime_t *node,
                     vlib_frame_t *frame, u8 is_ip4, u8 natt)
@@ -2842,8 +2847,10 @@ ikev2_node_internal (vlib_main_t *vm, vlib_node_runtime_t *node,
   vlib_buffer_t *bufs[VLIB_FRAME_SIZE], **b;
   u16 nexts[VLIB_FRAME_SIZE], *next = nexts;
   ikev2_main_per_thread_data_t *ptd = ikev2_get_per_thread_data ();
+  ikev2_stats_t _stats, *stats = &_stats;
   int res;
 
+  clib_memset_u16 (stats, 0, sizeof (stats[0]) / sizeof (u16));
   from = vlib_frame_vector_args (frame);
   vlib_get_buffers (vm, from, bufs, n_left);
   b = bufs;
@@ -2925,6 +2932,7 @@ ikev2_node_internal (vlib_main_t *vm, vlib_node_runtime_t *node,
 
          if (ike_hdr_is_initiator (ike0))
            {
+             stats->n_exchange_sa_req++;
              if (ike0->rspi == 0)
                {
                  if (is_ip4)
@@ -2972,7 +2980,8 @@ ikev2_node_internal (vlib_main_t *vm, vlib_node_runtime_t *node,
                      || sa0->state == IKEV2_STATE_NOTIFY_AND_DELETE)
                    {
                      ike0->flags = IKEV2_HDR_FLAG_RESPONSE;
-                     slen = ikev2_generate_message (b0, sa0, ike0, 0, udp0);
+                     slen =
+                       ikev2_generate_message (b0, sa0, ike0, 0, udp0, stats);
                      if (~0 == slen)
                        vlib_node_increment_counter (vm, node->node_index,
                                                     IKEV2_ERROR_NO_BUFF_SPACE,
@@ -3023,8 +3032,8 @@ ikev2_node_internal (vlib_main_t *vm, vlib_node_runtime_t *node,
                          ike0->msgid =
                            clib_net_to_host_u32 (sai->last_init_msg_id);
                          sa0->last_init_msg_id = sai->last_init_msg_id + 1;
-                         slen =
-                           ikev2_generate_message (b0, sa0, ike0, 0, udp0);
+                         slen = ikev2_generate_message (b0, sa0, ike0, 0,
+                                                        udp0, stats);
                          if (~0 == slen)
                            vlib_node_increment_counter (vm,
                                                         node->node_index,
@@ -3095,8 +3104,10 @@ ikev2_node_internal (vlib_main_t *vm, vlib_node_runtime_t *node,
                }
              else
                {
+                 stats->n_ike_auth_req++;
                  ike0->flags = IKEV2_HDR_FLAG_RESPONSE;
-                 slen = ikev2_generate_message (b0, sa0, ike0, 0, udp0);
+                 slen =
+                   ikev2_generate_message (b0, sa0, ike0, 0, udp0, stats);
                  if (~0 == slen)
                    vlib_node_increment_counter (vm, node->node_index,
                                                 IKEV2_ERROR_NO_BUFF_SPACE,
@@ -3168,7 +3179,8 @@ ikev2_node_internal (vlib_main_t *vm, vlib_node_runtime_t *node,
              if (ike_hdr_is_request (ike0))
                {
                  ike0->flags = IKEV2_HDR_FLAG_RESPONSE;
-                 slen = ikev2_generate_message (b0, sa0, ike0, 0, udp0);
+                 slen =
+                   ikev2_generate_message (b0, sa0, ike0, 0, udp0, stats);
                  if (~0 == slen)
                    vlib_node_increment_counter (vm, node->node_index,
                                                 IKEV2_ERROR_NO_BUFF_SPACE,
@@ -3228,8 +3240,10 @@ ikev2_node_internal (vlib_main_t *vm, vlib_node_runtime_t *node,
                    }
                  else
                    {
+                     stats->n_rekey_req++;
                      ike0->flags = IKEV2_HDR_FLAG_RESPONSE;
-                     slen = ikev2_generate_message (b0, sa0, ike0, 0, udp0);
+                     slen =
+                       ikev2_generate_message (b0, sa0, ike0, 0, udp0, stats);
                      if (~0 == slen)
                        vlib_node_increment_counter (vm, node->node_index,
                                                     IKEV2_ERROR_NO_BUFF_SPACE,
@@ -3318,6 +3332,7 @@ ikev2_node_internal (vlib_main_t *vm, vlib_node_runtime_t *node,
       b += 1;
     }
 
+  ikev2_update_stats (vm, node->node_index, stats);
   vlib_node_increment_counter (vm, node->node_index,
                               IKEV2_ERROR_PROCESSED, frame->n_vectors);
   vlib_buffer_enqueue_to_next (vm, node, from, nexts, frame->n_vectors);
@@ -3351,8 +3366,8 @@ VLIB_REGISTER_NODE (ikev2_node_ip4,static) = {
   .format_trace = format_ikev2_trace,
   .type = VLIB_NODE_TYPE_INTERNAL,
 
-  .n_errors = ARRAY_LEN(ikev2_error_strings),
-  .error_strings = ikev2_error_strings,
+  .n_errors = IKEV2_N_ERROR,
+  .error_counters = ikev2_error_counters,
 
   .n_next_nodes = IKEV2_IP4_N_NEXT,
   .next_nodes = {
@@ -3368,8 +3383,8 @@ VLIB_REGISTER_NODE (ikev2_node_ip4_natt,static) = {
   .format_trace = format_ikev2_trace,
   .type = VLIB_NODE_TYPE_INTERNAL,
 
-  .n_errors = ARRAY_LEN(ikev2_error_strings),
-  .error_strings = ikev2_error_strings,
+  .n_errors = IKEV2_N_ERROR,
+  .error_counters = ikev2_error_counters,
 
   .n_next_nodes = IKEV2_IP4_N_NEXT,
   .next_nodes = {
@@ -3385,8 +3400,8 @@ VLIB_REGISTER_NODE (ikev2_node_ip6,static) = {
   .format_trace = format_ikev2_trace,
   .type = VLIB_NODE_TYPE_INTERNAL,
 
-  .n_errors = ARRAY_LEN(ikev2_error_strings),
-  .error_strings = ikev2_error_strings,
+  .n_errors = IKEV2_N_ERROR,
+  .error_counters = ikev2_error_counters,
 
   .n_next_nodes = IKEV2_IP6_N_NEXT,
   .next_nodes = {
@@ -3722,7 +3737,7 @@ ikev2_initiate_delete_ike_sa_internal (vlib_main_t * vm,
       ike0->flags = 0;
       ike0->msgid = clib_host_to_net_u32 (sa->last_init_msg_id);
       sa->last_init_msg_id += 1;
-      len = ikev2_generate_message (b0, sa, ike0, 0, 0);
+      len = ikev2_generate_message (b0, sa, ike0, 0, 0, 0);
       if (~0 == len)
        return;
 
@@ -4392,7 +4407,7 @@ ikev2_delete_child_sa_internal (vlib_main_t * vm, ikev2_sa_t * sa,
   sa->del->spi = csa->i_proposals->spi;
   ike0->msgid = clib_host_to_net_u32 (sa->last_init_msg_id);
   sa->last_init_msg_id += 1;
-  len = ikev2_generate_message (b0, sa, ike0, 0, 0);
+  len = ikev2_generate_message (b0, sa, ike0, 0, 0, 0);
   if (~0 == len)
     return;
 
@@ -4518,7 +4533,7 @@ ikev2_rekey_child_sa_internal (vlib_main_t * vm, ikev2_sa_t * sa,
   RAND_bytes ((u8 *) & proposals[0].spi, sizeof (proposals[0].spi));
   rekey->spi = proposals[0].spi;
   rekey->ispi = csa->i_proposals->spi;
-  len = ikev2_generate_message (b0, sa, ike0, proposals, 0);
+  len = ikev2_generate_message (b0, sa, ike0, proposals, 0, 0);
   if (~0 == len)
     return;
 
@@ -4972,7 +4987,7 @@ ikev2_send_informational_request (ikev2_sa_t * sa)
   ike0->msgid = clib_host_to_net_u32 (sa->last_init_msg_id);
   ike0->flags = 0;
   sa->last_init_msg_id += 1;
-  len = ikev2_generate_message (b0, sa, ike0, 0, 0);
+  len = ikev2_generate_message (b0, sa, ike0, 0, 0, 0);
   if (~0 == len)
     return;
 
index 3db3a05..e6ccef7 100644 (file)
@@ -592,6 +592,10 @@ class IkePeer(VppTestCase):
         self.vapi.cli('ikev2 set logging level 4')
         self.vapi.cli('event-lo clear')
 
+    def assert_counter(self, count, name, version='ip4'):
+        node_name = '/err/ikev2-%s/' % version + name
+        self.assertEqual(count, self.statistics.get_err_counter(node_name))
+
     def create_rekey_request(self):
         sa, first_payload = self.generate_auth_payload(is_rekey=True)
         header = ikev2.IKEv2(
@@ -1317,11 +1321,19 @@ class TemplateResponder(IkePeer):
         self.sa.child_sas[0].rspi = prop.SPI
         self.sa.calc_child_keys()
 
+    IKE_NODE_SUFFIX = 'ip4'
+
+    def verify_counters(self):
+        self.assert_counter(2, 'processed', self.IKE_NODE_SUFFIX)
+        self.assert_counter(1, 'exchange_sa_req', self.IKE_NODE_SUFFIX)
+        self.assert_counter(1, 'ike_auth_req', self.IKE_NODE_SUFFIX)
+
     def test_responder(self):
         self.send_sa_init_req()
         self.send_sa_auth()
         self.verify_ipsec_sas()
         self.verify_ike_sas()
+        self.verify_counters()
 
 
 class Ikev2Params(object):
@@ -1624,6 +1636,8 @@ class TestApi(VppTestCase):
 class TestResponderBehindNAT(TemplateResponder, Ikev2Params):
     """ test responder - responder behind NAT """
 
+    IKE_NODE_SUFFIX = 'ip4-natt'
+
     def config_tc(self):
         self.config_params({'r_natt': True})
 
@@ -1782,6 +1796,9 @@ class TestInitiatorDelSAFromResponder(TemplateInitiator, Ikev2Params):
 
 class TestResponderInitBehindNATT(TemplateResponder, Ikev2Params):
     """ test ikev2 responder - initiator behind NAT """
+
+    IKE_NODE_SUFFIX = 'ip4-natt'
+
     def config_tc(self):
         self.config_params(
                 {'i_natt': True})
@@ -1875,6 +1892,7 @@ class Test_IKE_AES_CBC_128_SHA256_128_MODP2048_ESP_AES_CBC_192_SHA_384_192\
 
 class TestAES_CBC_128_SHA256_128_MODP3072_ESP_AES_GCM_16\
         (TemplateResponder, Ikev2Params):
+
     """
     IKE:AES_CBC_128_SHA256_128,DH=modp3072 ESP:AES_GCM_16
     """
@@ -1891,6 +1909,9 @@ class Test_IKE_AES_GCM_16_256(TemplateResponder, Ikev2Params):
     """
     IKE:AES_GCM_16_256
     """
+
+    IKE_NODE_SUFFIX = 'ip6'
+
     def config_tc(self):
         self.config_params({
             'del_sa_from_responder': True,
@@ -1920,6 +1941,7 @@ class TestInitiatorKeepaliveMsg(TestInitiatorPsk):
         self.assertEqual(ih.id, self.sa.msg_id)
         plain = self.sa.hmac_and_decrypt(ih)
         self.assertEqual(plain, b'')
+        self.assert_counter(1, 'keepalive', 'ip4')
 
     def test_initiator(self):
         super(TestInitiatorKeepaliveMsg, self).test_initiator()
@@ -1935,10 +1957,6 @@ class TestMalformedMessages(TemplateResponder, Ikev2Params):
     def config_tc(self):
         self.config_params()
 
-    def assert_counter(self, count, name, version='ip4'):
-        node_name = '/err/ikev2-%s/' % version + name
-        self.assertEqual(count, self.statistics.get_err_counter(node_name))
-
     def create_ike_init_msg(self, length=None, payload=None):
         msg = ikev2.IKEv2(length=length, init_SPI='\x11' * 8,
                           flags='Initiator', exch_type='IKE_SA_INIT')
@@ -1950,13 +1968,13 @@ class TestMalformedMessages(TemplateResponder, Ikev2Params):
     def verify_bad_packet_length(self):
         ike_msg = self.create_ike_init_msg(length=0xdead)
         self.send_and_assert_no_replies(self.pg0, ike_msg * self.pkt_count)
-        self.assert_counter(self.pkt_count, 'Bad packet length')
+        self.assert_counter(self.pkt_count, 'bad_length')
 
     def verify_bad_sa_payload_length(self):
         p = ikev2.IKEv2_payload_SA(length=0xdead)
         ike_msg = self.create_ike_init_msg(payload=p)
         self.send_and_assert_no_replies(self.pg0, ike_msg * self.pkt_count)
-        self.assert_counter(self.pkt_count, 'Malformed packet')
+        self.assert_counter(self.pkt_count, 'malformed_packet')
 
     def test_responder(self):
         self.pkt_count = 254