NAT: counters (VPP-1484) 76/16476/2
authorMatus Fabian <matfabia@cisco.com>
Fri, 14 Dec 2018 09:55:16 +0000 (01:55 -0800)
committerOle Trøan <otroan@employees.org>
Fri, 14 Dec 2018 19:47:37 +0000 (19:47 +0000)
Change-Id: I5d1852a09712adfe7547c200d161539736aca6f5
Signed-off-by: Matus Fabian <matfabia@cisco.com>
src/plugins/nat/in2out.c
src/plugins/nat/in2out_ed.c
src/plugins/nat/nat44_classify.c
src/plugins/nat/nat44_handoff.c
src/plugins/nat/nat64_in2out.c
src/plugins/nat/nat64_out2in.c
src/plugins/nat/out2in.c
src/plugins/nat/out2in_ed.c
test/test_nat.py

index 786d821..15dae65 100755 (executable)
@@ -80,16 +80,23 @@ vlib_node_registration_t snat_in2out_output_slowpath_node;
 vlib_node_registration_t nat44_in2out_reass_node;
 
 #define foreach_snat_in2out_error                       \
-_(UNSUPPORTED_PROTOCOL, "Unsupported protocol")         \
-_(IN2OUT_PACKETS, "Good in2out packets processed")      \
-_(OUT_OF_PORTS, "Out of ports")                         \
-_(BAD_OUTSIDE_FIB, "Outside VRF ID not found")          \
+_(UNSUPPORTED_PROTOCOL, "unsupported protocol")         \
+_(IN2OUT_PACKETS, "good in2out packets processed")      \
+_(OUT_OF_PORTS, "out of ports")                         \
+_(BAD_OUTSIDE_FIB, "outside VRF ID not found")          \
 _(BAD_ICMP_TYPE, "unsupported ICMP type")               \
-_(NO_TRANSLATION, "No translation")                     \
-_(MAX_SESSIONS_EXCEEDED, "Maximum sessions exceeded")   \
-_(DROP_FRAGMENT, "Drop fragment")                       \
-_(MAX_REASS, "Maximum reassemblies exceeded")           \
-_(MAX_FRAG, "Maximum fragments per reassembly exceeded")
+_(NO_TRANSLATION, "no translation")                     \
+_(MAX_SESSIONS_EXCEEDED, "maximum sessions exceeded")   \
+_(DROP_FRAGMENT, "drop fragment")                       \
+_(MAX_REASS, "maximum reassemblies exceeded")           \
+_(MAX_FRAG, "maximum fragments per reassembly exceeded")\
+_(TCP_PACKETS, "TCP packets")                           \
+_(UDP_PACKETS, "UDP packets")                           \
+_(ICMP_PACKETS, "ICMP packets")                         \
+_(OTHER_PACKETS, "other protocol packets")              \
+_(FRAGMENTS, "fragments")                               \
+_(CACHED_FRAGMENTS, "cached fragments")                 \
+_(PROCESSED_FRAGMENTS, "processed fragments")
 
 typedef enum
 {
@@ -851,6 +858,8 @@ snat_in2out_node_fn_inline (vlib_main_t * vm,
   f64 now = vlib_time_now (vm);
   u32 stats_node_index;
   u32 thread_index = vm->thread_index;
+  u32 tcp_packets = 0, udp_packets = 0, icmp_packets = 0, other_packets =
+    0, fragments = 0;
 
   stats_node_index = is_slow_path ? snat_in2out_slowpath_node.index :
     snat_in2out_node.index;
@@ -950,6 +959,7 @@ snat_in2out_node_fn_inline (vlib_main_t * vm,
                      b0->error =
                        node->errors[SNAT_IN2OUT_ERROR_UNSUPPORTED_PROTOCOL];
                    }
+                 other_packets++;
                  goto trace00;
                }
 
@@ -958,6 +968,7 @@ snat_in2out_node_fn_inline (vlib_main_t * vm,
                  next0 = icmp_in2out_slow_path
                    (sm, b0, ip0, icmp0, sw_if_index0, rx_fib_index0,
                     node, next0, now, thread_index, &s0);
+                 icmp_packets++;
                  goto trace00;
                }
            }
@@ -972,6 +983,7 @@ snat_in2out_node_fn_inline (vlib_main_t * vm,
              if (ip4_is_fragment (ip0))
                {
                  next0 = SNAT_IN2OUT_NEXT_REASS;
+                 fragments++;
                  goto trace00;
                }
 
@@ -1064,12 +1076,14 @@ snat_in2out_node_fn_inline (vlib_main_t * vm,
                                     length /* changed member */ );
              mss_clamping (sm, tcp0, &sum0);
              tcp0->checksum = ip_csum_fold (sum0);
+             tcp_packets++;
            }
          else
            {
              old_port0 = udp0->src_port;
              udp0->src_port = s0->out2in.port;
              udp0->checksum = 0;
+             udp_packets++;
            }
 
          /* Accounting */
@@ -1094,7 +1108,7 @@ snat_in2out_node_fn_inline (vlib_main_t * vm,
                  s0 - sm->per_thread_data[thread_index].sessions;
            }
 
-         pkts_processed += next0 != SNAT_IN2OUT_NEXT_DROP;
+         pkts_processed += next0 == SNAT_IN2OUT_NEXT_LOOKUP;
 
          if (is_output_feature)
            iph_offset1 = vnet_buffer (b1)->ip.save_rewrite_length;
@@ -1134,6 +1148,7 @@ snat_in2out_node_fn_inline (vlib_main_t * vm,
                      b1->error =
                        node->errors[SNAT_IN2OUT_ERROR_UNSUPPORTED_PROTOCOL];
                    }
+                 other_packets++;
                  goto trace01;
                }
 
@@ -1142,6 +1157,7 @@ snat_in2out_node_fn_inline (vlib_main_t * vm,
                  next1 = icmp_in2out_slow_path
                    (sm, b1, ip1, icmp1, sw_if_index1, rx_fib_index1, node,
                     next1, now, thread_index, &s1);
+                 icmp_packets++;
                  goto trace01;
                }
            }
@@ -1156,6 +1172,7 @@ snat_in2out_node_fn_inline (vlib_main_t * vm,
              if (ip4_is_fragment (ip1))
                {
                  next1 = SNAT_IN2OUT_NEXT_REASS;
+                 fragments++;
                  goto trace01;
                }
 
@@ -1248,12 +1265,14 @@ snat_in2out_node_fn_inline (vlib_main_t * vm,
                                     length /* changed member */ );
              mss_clamping (sm, tcp1, &sum1);
              tcp1->checksum = ip_csum_fold (sum1);
+             tcp_packets++;
            }
          else
            {
              old_port1 = udp1->src_port;
              udp1->src_port = s1->out2in.port;
              udp1->checksum = 0;
+             udp_packets++;
            }
 
          /* Accounting */
@@ -1277,7 +1296,7 @@ snat_in2out_node_fn_inline (vlib_main_t * vm,
                  s1 - sm->per_thread_data[thread_index].sessions;
            }
 
-         pkts_processed += next1 != SNAT_IN2OUT_NEXT_DROP;
+         pkts_processed += next1 == SNAT_IN2OUT_NEXT_LOOKUP;
 
          /* verify speculative enqueues, maybe switch current next frame */
          vlib_validate_buffer_enqueue_x2 (vm, node, next_index,
@@ -1354,6 +1373,7 @@ snat_in2out_node_fn_inline (vlib_main_t * vm,
                      b0->error =
                        node->errors[SNAT_IN2OUT_ERROR_UNSUPPORTED_PROTOCOL];
                    }
+                 other_packets++;
                  goto trace0;
                }
 
@@ -1362,6 +1382,7 @@ snat_in2out_node_fn_inline (vlib_main_t * vm,
                  next0 = icmp_in2out_slow_path
                    (sm, b0, ip0, icmp0, sw_if_index0, rx_fib_index0, node,
                     next0, now, thread_index, &s0);
+                 icmp_packets++;
                  goto trace0;
                }
            }
@@ -1376,6 +1397,7 @@ snat_in2out_node_fn_inline (vlib_main_t * vm,
              if (ip4_is_fragment (ip0))
                {
                  next0 = SNAT_IN2OUT_NEXT_REASS;
+                 fragments++;
                  goto trace0;
                }
 
@@ -1467,12 +1489,14 @@ snat_in2out_node_fn_inline (vlib_main_t * vm,
                                     length /* changed member */ );
              mss_clamping (sm, tcp0, &sum0);
              tcp0->checksum = ip_csum_fold (sum0);
+             tcp_packets++;
            }
          else
            {
              old_port0 = udp0->src_port;
              udp0->src_port = s0->out2in.port;
              udp0->checksum = 0;
+             udp_packets++;
            }
 
          /* Accounting */
@@ -1497,7 +1521,7 @@ snat_in2out_node_fn_inline (vlib_main_t * vm,
                  s0 - sm->per_thread_data[thread_index].sessions;
            }
 
-         pkts_processed += next0 != SNAT_IN2OUT_NEXT_DROP;
+         pkts_processed += next0 == SNAT_IN2OUT_NEXT_LOOKUP;
 
          /* verify speculative enqueue, maybe switch current next frame */
          vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
@@ -1511,6 +1535,18 @@ snat_in2out_node_fn_inline (vlib_main_t * vm,
   vlib_node_increment_counter (vm, stats_node_index,
                               SNAT_IN2OUT_ERROR_IN2OUT_PACKETS,
                               pkts_processed);
+  vlib_node_increment_counter (vm, stats_node_index,
+                              SNAT_IN2OUT_ERROR_TCP_PACKETS, tcp_packets);
+  vlib_node_increment_counter (vm, stats_node_index,
+                              SNAT_IN2OUT_ERROR_UDP_PACKETS, tcp_packets);
+  vlib_node_increment_counter (vm, stats_node_index,
+                              SNAT_IN2OUT_ERROR_ICMP_PACKETS, icmp_packets);
+  vlib_node_increment_counter (vm, stats_node_index,
+                              SNAT_IN2OUT_ERROR_OTHER_PACKETS,
+                              other_packets);
+  vlib_node_increment_counter (vm, stats_node_index,
+                              SNAT_IN2OUT_ERROR_FRAGMENTS, fragments);
+
   return frame->n_vectors;
 }
 
@@ -1669,7 +1705,7 @@ nat44_in2out_reass_node_fn (vlib_main_t * vm,
 {
   u32 n_left_from, *from, *to_next;
   snat_in2out_next_t next_index;
-  u32 pkts_processed = 0;
+  u32 pkts_processed = 0, cached_fragments = 0;
   snat_main_t *sm = &snat_main;
   f64 now = vlib_time_now (vm);
   u32 thread_index = vm->thread_index;
@@ -1885,6 +1921,7 @@ nat44_in2out_reass_node_fn (vlib_main_t * vm,
            {
              n_left_to_next++;
              to_next--;
+             cached_fragments++;
            }
          else
            {
@@ -1922,8 +1959,11 @@ nat44_in2out_reass_node_fn (vlib_main_t * vm,
     }
 
   vlib_node_increment_counter (vm, nat44_in2out_reass_node.index,
-                              SNAT_IN2OUT_ERROR_IN2OUT_PACKETS,
+                              SNAT_IN2OUT_ERROR_PROCESSED_FRAGMENTS,
                               pkts_processed);
+  vlib_node_increment_counter (vm, nat44_in2out_reass_node.index,
+                              SNAT_IN2OUT_ERROR_CACHED_FRAGMENTS,
+                              cached_fragments);
 
   nat_send_all_to_node (vm, fragments_to_drop, node,
                        &node->errors[SNAT_IN2OUT_ERROR_DROP_FRAGMENT],
index ab253e8..9a61af9 100644 (file)
 #include <nat/nat_inlines.h>
 #include <nat/nat_syslog.h>
 
-#define foreach_nat_in2out_ed_error                       \
-_(UNSUPPORTED_PROTOCOL, "Unsupported protocol")         \
-_(IN2OUT_PACKETS, "Good in2out packets processed")      \
-_(OUT_OF_PORTS, "Out of ports")                         \
+#define foreach_nat_in2out_ed_error                     \
+_(UNSUPPORTED_PROTOCOL, "unsupported protocol")         \
+_(IN2OUT_PACKETS, "good in2out packets processed")      \
+_(OUT_OF_PORTS, "out of ports")                         \
 _(BAD_ICMP_TYPE, "unsupported ICMP type")               \
-_(MAX_SESSIONS_EXCEEDED, "Maximum sessions exceeded")   \
-_(DROP_FRAGMENT, "Drop fragment")                       \
-_(MAX_REASS, "Maximum reassemblies exceeded")           \
-_(MAX_FRAG, "Maximum fragments per reassembly exceeded")\
-_(NON_SYN, "non-SYN packet try to create session")
+_(MAX_SESSIONS_EXCEEDED, "maximum sessions exceeded")   \
+_(DROP_FRAGMENT, "drop fragment")                       \
+_(MAX_REASS, "maximum reassemblies exceeded")           \
+_(MAX_FRAG, "maximum fragments per reassembly exceeded")\
+_(NON_SYN, "non-SYN packet try to create session")      \
+_(TCP_PACKETS, "TCP packets")                           \
+_(UDP_PACKETS, "UDP packets")                           \
+_(ICMP_PACKETS, "ICMP packets")                         \
+_(OTHER_PACKETS, "other protocol packets")              \
+_(FRAGMENTS, "fragments")                               \
+_(CACHED_FRAGMENTS, "cached fragments")                 \
+_(PROCESSED_FRAGMENTS, "processed fragments")
+
 
 typedef enum
 {
@@ -899,6 +907,8 @@ nat44_ed_in2out_node_fn_inline (vlib_main_t * vm,
   f64 now = vlib_time_now (vm);
   u32 thread_index = vm->thread_index;
   snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
+  u32 tcp_packets = 0, udp_packets = 0, icmp_packets = 0, other_packets =
+    0, fragments = 0;
 
   stats_node_index = is_slow_path ? nat44_ed_in2out_slowpath_node.index :
     nat44_ed_in2out_node.index;
@@ -993,6 +1003,7 @@ nat44_ed_in2out_node_fn_inline (vlib_main_t * vm,
                                                      node);
                  if (!s0)
                    next0 = NAT_IN2OUT_ED_NEXT_DROP;
+                 other_packets++;
                  goto trace00;
                }
 
@@ -1001,6 +1012,7 @@ nat44_ed_in2out_node_fn_inline (vlib_main_t * vm,
                  next0 = icmp_in2out_ed_slow_path
                    (sm, b0, ip0, icmp0, sw_if_index0, rx_fib_index0, node,
                     next0, now, thread_index, &s0);
+                 icmp_packets++;
                  goto trace00;
                }
            }
@@ -1015,6 +1027,7 @@ nat44_ed_in2out_node_fn_inline (vlib_main_t * vm,
              if (ip4_is_fragment (ip0))
                {
                  next0 = NAT_IN2OUT_ED_NEXT_REASS;
+                 fragments++;
                  goto trace00;
                }
 
@@ -1120,6 +1133,7 @@ nat44_ed_in2out_node_fn_inline (vlib_main_t * vm,
                }
              mss_clamping (sm, tcp0, &sum0);
              tcp0->checksum = ip_csum_fold (sum0);
+             tcp_packets++;
              if (nat44_set_tcp_session_state_i2o
                  (sm, s0, tcp0, thread_index))
                goto trace00;
@@ -1133,6 +1147,7 @@ nat44_ed_in2out_node_fn_inline (vlib_main_t * vm,
                  udp0->dst_port = s0->ext_host_port;
                  ip0->dst_address.as_u32 = s0->ext_host_addr.as_u32;
                }
+             udp_packets++;
            }
 
          /* Accounting */
@@ -1156,7 +1171,7 @@ nat44_ed_in2out_node_fn_inline (vlib_main_t * vm,
                t->session_index = s0 - tsm->sessions;
            }
 
-         pkts_processed += next0 != NAT_IN2OUT_ED_NEXT_DROP;
+         pkts_processed += next0 == NAT_IN2OUT_ED_NEXT_LOOKUP;
 
 
          next1 = NAT_IN2OUT_ED_NEXT_LOOKUP;
@@ -1197,6 +1212,7 @@ nat44_ed_in2out_node_fn_inline (vlib_main_t * vm,
                                                      node);
                  if (!s1)
                    next1 = NAT_IN2OUT_ED_NEXT_DROP;
+                 other_packets++;
                  goto trace01;
                }
 
@@ -1205,6 +1221,7 @@ nat44_ed_in2out_node_fn_inline (vlib_main_t * vm,
                  next1 = icmp_in2out_ed_slow_path
                    (sm, b1, ip1, icmp1, sw_if_index1, rx_fib_index1, node,
                     next1, now, thread_index, &s1);
+                 icmp_packets++;
                  goto trace01;
                }
            }
@@ -1219,6 +1236,7 @@ nat44_ed_in2out_node_fn_inline (vlib_main_t * vm,
              if (ip4_is_fragment (ip1))
                {
                  next1 = NAT_IN2OUT_ED_NEXT_REASS;
+                 fragments++;
                  goto trace01;
                }
 
@@ -1324,6 +1342,7 @@ nat44_ed_in2out_node_fn_inline (vlib_main_t * vm,
                }
              tcp1->checksum = ip_csum_fold (sum1);
              mss_clamping (sm, tcp1, &sum1);
+             tcp_packets++;
              if (nat44_set_tcp_session_state_i2o
                  (sm, s1, tcp1, thread_index))
                goto trace01;
@@ -1337,6 +1356,7 @@ nat44_ed_in2out_node_fn_inline (vlib_main_t * vm,
                  udp1->dst_port = s1->ext_host_port;
                  ip1->dst_address.as_u32 = s1->ext_host_addr.as_u32;
                }
+             udp_packets++;
            }
 
          /* Accounting */
@@ -1360,7 +1380,7 @@ nat44_ed_in2out_node_fn_inline (vlib_main_t * vm,
                t->session_index = s1 - tsm->sessions;
            }
 
-         pkts_processed += next1 != NAT_IN2OUT_ED_NEXT_DROP;
+         pkts_processed += next1 == NAT_IN2OUT_ED_NEXT_LOOKUP;
 
          /* verify speculative enqueues, maybe switch current next frame */
          vlib_validate_buffer_enqueue_x2 (vm, node, next_index,
@@ -1430,6 +1450,7 @@ nat44_ed_in2out_node_fn_inline (vlib_main_t * vm,
                                                      node);
                  if (!s0)
                    next0 = NAT_IN2OUT_ED_NEXT_DROP;
+                 other_packets++;
                  goto trace0;
                }
 
@@ -1438,6 +1459,7 @@ nat44_ed_in2out_node_fn_inline (vlib_main_t * vm,
                  next0 = icmp_in2out_ed_slow_path
                    (sm, b0, ip0, icmp0, sw_if_index0, rx_fib_index0, node,
                     next0, now, thread_index, &s0);
+                 icmp_packets++;
                  goto trace0;
                }
            }
@@ -1452,6 +1474,7 @@ nat44_ed_in2out_node_fn_inline (vlib_main_t * vm,
              if (ip4_is_fragment (ip0))
                {
                  next0 = NAT_IN2OUT_ED_NEXT_REASS;
+                 fragments++;
                  goto trace0;
                }
 
@@ -1557,6 +1580,7 @@ nat44_ed_in2out_node_fn_inline (vlib_main_t * vm,
                }
              mss_clamping (sm, tcp0, &sum0);
              tcp0->checksum = ip_csum_fold (sum0);
+             tcp_packets++;
              if (nat44_set_tcp_session_state_i2o
                  (sm, s0, tcp0, thread_index))
                goto trace0;
@@ -1570,6 +1594,7 @@ nat44_ed_in2out_node_fn_inline (vlib_main_t * vm,
                  udp0->dst_port = s0->ext_host_port;
                  ip0->dst_address.as_u32 = s0->ext_host_addr.as_u32;
                }
+             udp_packets++;
            }
 
          /* Accounting */
@@ -1593,7 +1618,7 @@ nat44_ed_in2out_node_fn_inline (vlib_main_t * vm,
                t->session_index = s0 - tsm->sessions;
            }
 
-         pkts_processed += next0 != NAT_IN2OUT_ED_NEXT_DROP;
+         pkts_processed += next0 == NAT_IN2OUT_ED_NEXT_LOOKUP;
 
          /* verify speculative enqueue, maybe switch current next frame */
          vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
@@ -1607,6 +1632,19 @@ nat44_ed_in2out_node_fn_inline (vlib_main_t * vm,
   vlib_node_increment_counter (vm, stats_node_index,
                               NAT_IN2OUT_ED_ERROR_IN2OUT_PACKETS,
                               pkts_processed);
+  vlib_node_increment_counter (vm, stats_node_index,
+                              NAT_IN2OUT_ED_ERROR_TCP_PACKETS, tcp_packets);
+  vlib_node_increment_counter (vm, stats_node_index,
+                              NAT_IN2OUT_ED_ERROR_UDP_PACKETS, tcp_packets);
+  vlib_node_increment_counter (vm, stats_node_index,
+                              NAT_IN2OUT_ED_ERROR_ICMP_PACKETS,
+                              icmp_packets);
+  vlib_node_increment_counter (vm, stats_node_index,
+                              NAT_IN2OUT_ED_ERROR_OTHER_PACKETS,
+                              other_packets);
+  vlib_node_increment_counter (vm, stats_node_index,
+                              NAT_IN2OUT_ED_ERROR_FRAGMENTS, fragments);
+
   return frame->n_vectors;
 }
 
@@ -1746,7 +1784,7 @@ nat44_ed_in2out_reass_node_fn_inline (vlib_main_t * vm,
 {
   u32 n_left_from, *from, *to_next;
   nat_in2out_ed_next_t next_index;
-  u32 pkts_processed = 0;
+  u32 pkts_processed = 0, cached_fragments = 0;
   snat_main_t *sm = &snat_main;
   f64 now = vlib_time_now (vm);
   u32 thread_index = vm->thread_index;
@@ -2025,6 +2063,7 @@ nat44_ed_in2out_reass_node_fn_inline (vlib_main_t * vm,
            {
              n_left_to_next++;
              to_next--;
+             cached_fragments++;
            }
          else
            {
@@ -2062,8 +2101,11 @@ nat44_ed_in2out_reass_node_fn_inline (vlib_main_t * vm,
     }
 
   vlib_node_increment_counter (vm, nat44_ed_in2out_reass_node.index,
-                              NAT_IN2OUT_ED_ERROR_IN2OUT_PACKETS,
+                              NAT_IN2OUT_ED_ERROR_PROCESSED_FRAGMENTS,
                               pkts_processed);
+  vlib_node_increment_counter (vm, nat44_ed_in2out_reass_node.index,
+                              NAT_IN2OUT_ED_ERROR_CACHED_FRAGMENTS,
+                              cached_fragments);
 
   nat_send_all_to_node (vm, fragments_to_drop, node,
                        &node->errors[NAT_IN2OUT_ED_ERROR_DROP_FRAGMENT],
index 8608fc5..8a417dc 100644 (file)
@@ -31,7 +31,10 @@ vlib_node_registration_t nat44_handoff_classify_node;
 
 #define foreach_nat44_classify_error                      \
 _(MAX_REASS, "Maximum reassemblies exceeded")             \
-_(MAX_FRAG, "Maximum fragments per reassembly exceeded")
+_(MAX_FRAG, "Maximum fragments per reassembly exceeded")  \
+_(NEXT_IN2OUT, "next in2out")                             \
+_(NEXT_OUT2IN, "next out2in")                             \
+_(FRAG_CACHED, "fragment cached")
 
 typedef enum
 {
@@ -93,6 +96,7 @@ nat44_classify_node_fn_inline (vlib_main_t * vm,
   snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
   u32 *fragments_to_drop = 0;
   u32 *fragments_to_loopback = 0;
+  u32 next_in2out = 0, next_out2in = 0, frag_cached = 0;
 
   from = vlib_frame_vector_args (frame);
   n_left_from = frame->n_vectors;
@@ -361,12 +365,18 @@ nat44_classify_node_fn_inline (vlib_main_t * vm,
            {
              n_left_to_next++;
              to_next--;
+             frag_cached++;
            }
          else
-           /* verify speculative enqueue, maybe switch current next frame */
-           vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
-                                            to_next, n_left_to_next,
-                                            bi0, next0);
+           {
+             next_in2out += next0 == NAT44_CLASSIFY_NEXT_IN2OUT;
+             next_out2in += next0 == NAT44_CLASSIFY_NEXT_OUT2IN;
+
+             /* verify speculative enqueue, maybe switch current next frame */
+             vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
+                                              to_next, n_left_to_next,
+                                              bi0, next0);
+           }
 
          if (n_left_from == 0 && vec_len (fragments_to_loopback))
            {
@@ -398,6 +408,13 @@ nat44_classify_node_fn_inline (vlib_main_t * vm,
 
   vec_free (fragments_to_drop);
 
+  vlib_node_increment_counter (vm, node->node_index,
+                              NAT44_CLASSIFY_ERROR_NEXT_IN2OUT, next_in2out);
+  vlib_node_increment_counter (vm, node->node_index,
+                              NAT44_CLASSIFY_ERROR_NEXT_OUT2IN, next_out2in);
+  vlib_node_increment_counter (vm, node->node_index,
+                              NAT44_CLASSIFY_ERROR_FRAG_CACHED, frag_cached);
+
   return frame->n_vectors;
 }
 
index a49b8de..d7ab650 100644 (file)
@@ -31,7 +31,9 @@ typedef struct
 } nat44_handoff_trace_t;
 
 #define foreach_nat44_handoff_error                       \
-_(CONGESTION_DROP, "congestion drop")
+_(CONGESTION_DROP, "congestion drop")                     \
+_(SAME_WORKER, "same worker")                             \
+_(DO_HANDOFF, "do handoff")
 
 typedef enum
 {
@@ -79,6 +81,8 @@ nat44_worker_handoff_fn_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
   u16 thread_indices[VLIB_FRAME_SIZE], *ti;
   u32 fq_index;
   snat_get_worker_function_t *get_worker;
+  u32 thread_index = vm->thread_index;
+  u32 do_handoff = 0, same_worker = 0;
 
   from = vlib_frame_vector_args (frame);
   n_left_from = frame->n_vectors;
@@ -114,6 +118,11 @@ nat44_worker_handoff_fn_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
       ip0 = vlib_buffer_get_current (b[0]);
       ti[0] = get_worker (ip0, rx_fib_index0);
 
+      if (ti[0] != thread_index)
+       do_handoff++;
+      else
+       same_worker++;
+
       if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE)
                         && (b[0]->flags & VLIB_BUFFER_IS_TRACED)))
        {
@@ -136,6 +145,10 @@ nat44_worker_handoff_fn_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
     vlib_node_increment_counter (vm, node->node_index,
                                 NAT44_HANDOFF_ERROR_CONGESTION_DROP,
                                 frame->n_vectors - n_enq);
+  vlib_node_increment_counter (vm, node->node_index,
+                              NAT44_HANDOFF_ERROR_SAME_WORKER, same_worker);
+  vlib_node_increment_counter (vm, node->node_index,
+                              NAT44_HANDOFF_ERROR_DO_HANDOFF, do_handoff);
   return frame->n_vectors;
 }
 
index 0652f44..372931c 100644 (file)
@@ -80,9 +80,16 @@ _(UNSUPPORTED_PROTOCOL, "unsupported protocol")          \
 _(IN2OUT_PACKETS, "good in2out packets processed")       \
 _(NO_TRANSLATION, "no translation")                      \
 _(UNKNOWN, "unknown")                                    \
-_(DROP_FRAGMENT, "Drop fragment")                        \
-_(MAX_REASS, "Maximum reassemblies exceeded")            \
-_(MAX_FRAG, "Maximum fragments per reassembly exceeded")
+_(DROP_FRAGMENT, "drop fragment")                        \
+_(MAX_REASS, "maximum reassemblies exceeded")            \
+_(MAX_FRAG, "maximum fragments per reassembly exceeded") \
+_(TCP_PACKETS, "TCP packets")                            \
+_(UDP_PACKETS, "UDP packets")                            \
+_(ICMP_PACKETS, "ICMP packets")                          \
+_(OTHER_PACKETS, "other protocol packets")               \
+_(FRAGMENTS, "fragments")                                \
+_(CACHED_FRAGMENTS, "cached fragments")                  \
+_(PROCESSED_FRAGMENTS, "processed fragments")
 
 
 typedef enum
@@ -928,6 +935,8 @@ nat64_in2out_node_fn_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
   u32 pkts_processed = 0;
   u32 stats_node_index;
   u32 thread_index = vm->thread_index;
+  u32 tcp_packets = 0, udp_packets = 0, icmp_packets = 0, other_packets =
+    0, fragments = 0;
 
   stats_node_index =
     is_slow_path ? nat64_in2out_slowpath_node.index : nat64_in2out_node.index;
@@ -995,6 +1004,7 @@ nat64_in2out_node_fn_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
            {
              if (PREDICT_TRUE (proto0 == ~0))
                {
+                 other_packets++;
                  if (is_hairpinning (&ip60->dst_address))
                    {
                      next0 = NAT64_IN2OUT_NEXT_IP6_LOOKUP;
@@ -1031,11 +1041,13 @@ nat64_in2out_node_fn_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
              (ip60->protocol == IP_PROTOCOL_IPV6_FRAGMENTATION))
            {
              next0 = NAT64_IN2OUT_NEXT_REASS;
+             fragments++;
              goto trace0;
            }
 
          if (proto0 == SNAT_PROTOCOL_ICMP)
            {
+             icmp_packets++;
              if (is_hairpinning (&ip60->dst_address))
                {
                  next0 = NAT64_IN2OUT_NEXT_IP6_LOOKUP;
@@ -1060,6 +1072,11 @@ nat64_in2out_node_fn_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
            }
          else if (proto0 == SNAT_PROTOCOL_TCP || proto0 == SNAT_PROTOCOL_UDP)
            {
+             if (proto0 == SNAT_PROTOCOL_TCP)
+               tcp_packets++;
+             else
+               udp_packets++;
+
              if (is_hairpinning (&ip60->dst_address))
                {
                  next0 = NAT64_IN2OUT_NEXT_IP6_LOOKUP;
@@ -1093,7 +1110,7 @@ nat64_in2out_node_fn_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
              t->is_slow_path = is_slow_path;
            }
 
-         pkts_processed += next0 != NAT64_IN2OUT_NEXT_DROP;
+         pkts_processed += next0 == NAT64_IN2OUT_NEXT_IP4_LOOKUP;
 
          /* verify speculative enqueue, maybe switch current next frame */
          vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
@@ -1104,6 +1121,18 @@ nat64_in2out_node_fn_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
   vlib_node_increment_counter (vm, stats_node_index,
                               NAT64_IN2OUT_ERROR_IN2OUT_PACKETS,
                               pkts_processed);
+  vlib_node_increment_counter (vm, stats_node_index,
+                              NAT64_IN2OUT_ERROR_TCP_PACKETS, tcp_packets);
+  vlib_node_increment_counter (vm, stats_node_index,
+                              NAT64_IN2OUT_ERROR_UDP_PACKETS, tcp_packets);
+  vlib_node_increment_counter (vm, stats_node_index,
+                              NAT64_IN2OUT_ERROR_ICMP_PACKETS, icmp_packets);
+  vlib_node_increment_counter (vm, stats_node_index,
+                              NAT64_IN2OUT_ERROR_OTHER_PACKETS,
+                              other_packets);
+  vlib_node_increment_counter (vm, stats_node_index,
+                              NAT64_IN2OUT_ERROR_FRAGMENTS, fragments);
+
   return frame->n_vectors;
 }
 
@@ -1321,7 +1350,7 @@ nat64_in2out_reass_node_fn (vlib_main_t * vm,
 {
   u32 n_left_from, *from, *to_next;
   nat64_in2out_next_t next_index;
-  u32 pkts_processed = 0;
+  u32 pkts_processed = 0, cached_fragments = 0;
   u32 *fragments_to_drop = 0;
   u32 *fragments_to_loopback = 0;
   nat64_main_t *nm = &nat64_main;
@@ -1542,6 +1571,7 @@ nat64_in2out_reass_node_fn (vlib_main_t * vm,
            {
              n_left_to_next++;
              to_next--;
+             cached_fragments++;
            }
          else
            {
@@ -1579,8 +1609,11 @@ nat64_in2out_reass_node_fn (vlib_main_t * vm,
     }
 
   vlib_node_increment_counter (vm, nat64_in2out_reass_node.index,
-                              NAT64_IN2OUT_ERROR_IN2OUT_PACKETS,
+                              NAT64_IN2OUT_ERROR_PROCESSED_FRAGMENTS,
                               pkts_processed);
+  vlib_node_increment_counter (vm, nat64_in2out_reass_node.index,
+                              NAT64_IN2OUT_ERROR_CACHED_FRAGMENTS,
+                              cached_fragments);
 
   nat_send_all_to_node (vm, fragments_to_drop, node,
                        &node->errors[NAT64_IN2OUT_ERROR_DROP_FRAGMENT],
@@ -1616,7 +1649,9 @@ VLIB_NODE_FUNCTION_MULTIARCH (nat64_in2out_reass_node,
                              nat64_in2out_reass_node_fn);
 
 #define foreach_nat64_in2out_handoff_error                       \
-_(CONGESTION_DROP, "congestion drop")
+_(CONGESTION_DROP, "congestion drop")                            \
+_(SAME_WORKER, "same worker")                                    \
+_(DO_HANDOFF, "do handoff")
 
 typedef enum
 {
@@ -1660,6 +1695,8 @@ nat64_in2out_handoff_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
   u32 n_enq, n_left_from, *from;
   u16 thread_indices[VLIB_FRAME_SIZE], *ti;
   u32 fq_index;
+  u32 thread_index = vm->thread_index;
+  u32 do_handoff = 0, same_worker = 0;
 
   from = vlib_frame_vector_args (frame);
   n_left_from = frame->n_vectors;
@@ -1677,6 +1714,11 @@ nat64_in2out_handoff_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
       ip0 = vlib_buffer_get_current (b[0]);
       ti[0] = nat64_get_worker_in2out (&ip0->src_address);
 
+      if (ti[0] != thread_index)
+       do_handoff++;
+      else
+       same_worker++;
+
       if (PREDICT_FALSE
          ((node->flags & VLIB_NODE_FLAG_TRACE)
           && (b[0]->flags & VLIB_BUFFER_IS_TRACED)))
@@ -1699,6 +1741,13 @@ nat64_in2out_handoff_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
     vlib_node_increment_counter (vm, node->node_index,
                                 NAT64_IN2OUT_HANDOFF_ERROR_CONGESTION_DROP,
                                 frame->n_vectors - n_enq);
+  vlib_node_increment_counter (vm, node->node_index,
+                              NAT64_IN2OUT_HANDOFF_ERROR_SAME_WORKER,
+                              same_worker);
+  vlib_node_increment_counter (vm, node->node_index,
+                              NAT64_IN2OUT_HANDOFF_ERROR_DO_HANDOFF,
+                              do_handoff);
+
   return frame->n_vectors;
 }
 
index 1c8df8a..ba35de1 100644 (file)
@@ -72,13 +72,20 @@ vlib_node_registration_t nat64_out2in_reass_node;
 vlib_node_registration_t nat64_out2in_handoff_node;
 
 #define foreach_nat64_out2in_error                       \
-_(UNSUPPORTED_PROTOCOL, "Unsupported protocol")          \
-_(OUT2IN_PACKETS, "Good out2in packets processed")       \
-_(NO_TRANSLATION, "No translation")                      \
+_(UNSUPPORTED_PROTOCOL, "unsupported protocol")          \
+_(OUT2IN_PACKETS, "good out2in packets processed")       \
+_(NO_TRANSLATION, "no translation")                      \
 _(UNKNOWN, "unknown")                                    \
-_(DROP_FRAGMENT, "Drop fragment")                        \
-_(MAX_REASS, "Maximum reassemblies exceeded")            \
-_(MAX_FRAG, "Maximum fragments per reassembly exceeded")
+_(DROP_FRAGMENT, "drop fragment")                        \
+_(MAX_REASS, "maximum reassemblies exceeded")            \
+_(MAX_FRAG, "maximum fragments per reassembly exceeded") \
+_(TCP_PACKETS, "TCP packets")                            \
+_(UDP_PACKETS, "UDP packets")                            \
+_(ICMP_PACKETS, "ICMP packets")                          \
+_(OTHER_PACKETS, "other protocol packets")               \
+_(FRAGMENTS, "fragments")                                \
+_(CACHED_FRAGMENTS, "cached fragments")                  \
+_(PROCESSED_FRAGMENTS, "processed fragments")
 
 
 typedef enum
@@ -413,6 +420,8 @@ nat64_out2in_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
   nat64_out2in_next_t next_index;
   u32 pkts_processed = 0;
   u32 thread_index = vm->thread_index;
+  u32 tcp_packets = 0, udp_packets = 0, icmp_packets = 0, other_packets =
+    0, fragments = 0;
 
   from = vlib_frame_vector_args (frame);
   n_left_from = frame->n_vectors;
@@ -459,17 +468,20 @@ nat64_out2in_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
                  next0 = NAT64_OUT2IN_NEXT_DROP;
                  b0->error = node->errors[NAT64_OUT2IN_ERROR_NO_TRANSLATION];
                }
+             other_packets++;
              goto trace0;
            }
 
          if (PREDICT_FALSE (ip4_is_fragment (ip40)))
            {
              next0 = NAT64_OUT2IN_NEXT_REASS;
+             fragments++;
              goto trace0;
            }
 
          if (proto0 == SNAT_PROTOCOL_ICMP)
            {
+             icmp_packets++;
              if (icmp_to_icmp6
                  (b0, nat64_out2in_icmp_set_cb, &ctx0,
                   nat64_out2in_inner_icmp_set_cb, &ctx0))
@@ -481,6 +493,11 @@ nat64_out2in_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
            }
          else
            {
+             if (proto0 == SNAT_PROTOCOL_TCP)
+               tcp_packets++;
+             else
+               udp_packets++;
+
              if (ip4_to_ip6_tcp_udp (b0, nat64_out2in_tcp_udp_set_cb, &ctx0))
                {
                  udp0 = ip4_next_header (ip40);
@@ -511,7 +528,7 @@ nat64_out2in_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
              t->next_index = next0;
            }
 
-         pkts_processed += next0 != NAT64_OUT2IN_NEXT_DROP;
+         pkts_processed += next0 == NAT64_OUT2IN_NEXT_IP6_LOOKUP;
 
          /* verify speculative enqueue, maybe switch current next frame */
          vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
@@ -522,6 +539,18 @@ nat64_out2in_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
   vlib_node_increment_counter (vm, nat64_out2in_node.index,
                               NAT64_OUT2IN_ERROR_OUT2IN_PACKETS,
                               pkts_processed);
+  vlib_node_increment_counter (vm, nat64_out2in_node.index,
+                              NAT64_OUT2IN_ERROR_TCP_PACKETS, tcp_packets);
+  vlib_node_increment_counter (vm, nat64_out2in_node.index,
+                              NAT64_OUT2IN_ERROR_UDP_PACKETS, tcp_packets);
+  vlib_node_increment_counter (vm, nat64_out2in_node.index,
+                              NAT64_OUT2IN_ERROR_ICMP_PACKETS, icmp_packets);
+  vlib_node_increment_counter (vm, nat64_out2in_node.index,
+                              NAT64_OUT2IN_ERROR_OTHER_PACKETS,
+                              other_packets);
+  vlib_node_increment_counter (vm, nat64_out2in_node.index,
+                              NAT64_OUT2IN_ERROR_FRAGMENTS, fragments);
+
   return frame->n_vectors;
 }
 
@@ -651,7 +680,7 @@ nat64_out2in_reass_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
 {
   u32 n_left_from, *from, *to_next;
   nat64_out2in_next_t next_index;
-  u32 pkts_processed = 0;
+  u32 pkts_processed = 0, cached_fragments = 0;
   u32 *fragments_to_drop = 0;
   u32 *fragments_to_loopback = 0;
   nat64_main_t *nm = &nat64_main;
@@ -825,6 +854,7 @@ nat64_out2in_reass_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
            {
              n_left_to_next++;
              to_next--;
+             cached_fragments++;
            }
          else
            {
@@ -862,8 +892,11 @@ nat64_out2in_reass_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
     }
 
   vlib_node_increment_counter (vm, nat64_out2in_reass_node.index,
-                              NAT64_OUT2IN_ERROR_OUT2IN_PACKETS,
+                              NAT64_OUT2IN_ERROR_PROCESSED_FRAGMENTS,
                               pkts_processed);
+  vlib_node_increment_counter (vm, nat64_out2in_reass_node.index,
+                              NAT64_OUT2IN_ERROR_CACHED_FRAGMENTS,
+                              cached_fragments);
 
   nat_send_all_to_node (vm, fragments_to_drop, node,
                        &node->errors[NAT64_OUT2IN_ERROR_DROP_FRAGMENT],
@@ -898,7 +931,9 @@ VLIB_NODE_FUNCTION_MULTIARCH (nat64_out2in_reass_node,
                              nat64_out2in_reass_node_fn);
 
 #define foreach_nat64_out2in_handoff_error                       \
-_(CONGESTION_DROP, "congestion drop")
+_(CONGESTION_DROP, "congestion drop")                            \
+_(SAME_WORKER, "same worker")                                    \
+_(DO_HANDOFF, "do handoff")
 
 typedef enum
 {
@@ -942,6 +977,8 @@ nat64_out2in_handoff_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
   u32 n_enq, n_left_from, *from;
   u16 thread_indices[VLIB_FRAME_SIZE], *ti;
   u32 fq_index;
+  u32 thread_index = vm->thread_index;
+  u32 do_handoff = 0, same_worker = 0;
 
   from = vlib_frame_vector_args (frame);
   n_left_from = frame->n_vectors;
@@ -959,6 +996,11 @@ nat64_out2in_handoff_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
       ip0 = vlib_buffer_get_current (b[0]);
       ti[0] = nat64_get_worker_out2in (ip0);
 
+      if (ti[0] != thread_index)
+       do_handoff++;
+      else
+       same_worker++;
+
       if (PREDICT_FALSE
          ((node->flags & VLIB_NODE_FLAG_TRACE)
           && (b[0]->flags & VLIB_BUFFER_IS_TRACED)))
@@ -981,6 +1023,13 @@ nat64_out2in_handoff_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
     vlib_node_increment_counter (vm, node->node_index,
                                 NAT64_OUT2IN_HANDOFF_ERROR_CONGESTION_DROP,
                                 frame->n_vectors - n_enq);
+  vlib_node_increment_counter (vm, node->node_index,
+                              NAT64_OUT2IN_HANDOFF_ERROR_SAME_WORKER,
+                              same_worker);
+  vlib_node_increment_counter (vm, node->node_index,
+                              NAT64_OUT2IN_HANDOFF_ERROR_DO_HANDOFF,
+                              do_handoff);
+
   return frame->n_vectors;
 }
 
index 74d2088..18595e9 100755 (executable)
@@ -74,15 +74,22 @@ vlib_node_registration_t snat_out2in_fast_node;
 vlib_node_registration_t nat44_out2in_reass_node;
 
 #define foreach_snat_out2in_error                       \
-_(UNSUPPORTED_PROTOCOL, "Unsupported protocol")         \
-_(OUT2IN_PACKETS, "Good out2in packets processed")      \
-_(OUT_OF_PORTS, "Out of ports")                         \
+_(UNSUPPORTED_PROTOCOL, "unsupported protocol")         \
+_(OUT2IN_PACKETS, "good out2in packets processed")      \
+_(OUT_OF_PORTS, "out of ports")                         \
 _(BAD_ICMP_TYPE, "unsupported ICMP type")               \
-_(NO_TRANSLATION, "No translation")                     \
-_(MAX_SESSIONS_EXCEEDED, "Maximum sessions exceeded")   \
-_(DROP_FRAGMENT, "Drop fragment")                       \
-_(MAX_REASS, "Maximum reassemblies exceeded")           \
-_(MAX_FRAG, "Maximum fragments per reassembly exceeded")
+_(NO_TRANSLATION, "no translation")                     \
+_(MAX_SESSIONS_EXCEEDED, "maximum sessions exceeded")   \
+_(DROP_FRAGMENT, "drop fragment")                       \
+_(MAX_REASS, "maximum reassemblies exceeded")           \
+_(MAX_FRAG, "maximum fragments per reassembly exceeded")\
+_(TCP_PACKETS, "TCP packets")                           \
+_(UDP_PACKETS, "UDP packets")                           \
+_(ICMP_PACKETS, "ICMP packets")                         \
+_(OTHER_PACKETS, "other protocol packets")              \
+_(FRAGMENTS, "fragments")                               \
+_(CACHED_FRAGMENTS, "cached fragments")                 \
+_(PROCESSED_FRAGMENTS, "processed fragments")
 
 typedef enum
 {
@@ -689,6 +696,8 @@ snat_out2in_node_fn (vlib_main_t * vm,
   snat_main_t *sm = &snat_main;
   f64 now = vlib_time_now (vm);
   u32 thread_index = vm->thread_index;
+  u32 tcp_packets = 0, udp_packets = 0, icmp_packets = 0, other_packets =
+    0, fragments = 0;
 
   from = vlib_frame_vector_args (frame);
   n_left_from = frame->n_vectors;
@@ -783,12 +792,14 @@ snat_out2in_node_fn (vlib_main_t * vm,
                      next0 = SNAT_OUT2IN_NEXT_DROP;
                    }
                }
+             other_packets++;
              goto trace0;
            }
 
          if (PREDICT_FALSE (ip4_is_fragment (ip0)))
            {
              next0 = SNAT_OUT2IN_NEXT_REASS;
+             fragments++;
              goto trace0;
            }
 
@@ -797,6 +808,7 @@ snat_out2in_node_fn (vlib_main_t * vm,
              next0 = icmp_out2in_slow_path
                (sm, b0, ip0, icmp0, sw_if_index0, rx_fib_index0, node,
                 next0, now, thread_index, &s0);
+             icmp_packets++;
              goto trace0;
            }
 
@@ -880,12 +892,14 @@ snat_out2in_node_fn (vlib_main_t * vm,
                                     ip4_header_t /* cheat */ ,
                                     length /* changed member */ );
              tcp0->checksum = ip_csum_fold (sum0);
+             tcp_packets++;
            }
          else
            {
              old_port0 = udp0->dst_port;
              udp0->dst_port = s0->in2out.port;
              udp0->checksum = 0;
+             udp_packets++;
            }
 
          /* Accounting */
@@ -909,7 +923,7 @@ snat_out2in_node_fn (vlib_main_t * vm,
                  s0 - sm->per_thread_data[thread_index].sessions;
            }
 
-         pkts_processed += next0 != SNAT_OUT2IN_NEXT_DROP;
+         pkts_processed += next0 == SNAT_OUT2IN_NEXT_LOOKUP;
 
 
          ip1 = vlib_buffer_get_current (b1);
@@ -944,12 +958,14 @@ snat_out2in_node_fn (vlib_main_t * vm,
                      next1 = SNAT_OUT2IN_NEXT_DROP;
                    }
                }
+             other_packets++;
              goto trace1;
            }
 
          if (PREDICT_FALSE (ip4_is_fragment (ip1)))
            {
              next1 = SNAT_OUT2IN_NEXT_REASS;
+             fragments++;
              goto trace1;
            }
 
@@ -958,6 +974,7 @@ snat_out2in_node_fn (vlib_main_t * vm,
              next1 = icmp_out2in_slow_path
                (sm, b1, ip1, icmp1, sw_if_index1, rx_fib_index1, node,
                 next1, now, thread_index, &s1);
+             icmp_packets++;
              goto trace1;
            }
 
@@ -1041,12 +1058,14 @@ snat_out2in_node_fn (vlib_main_t * vm,
                                     ip4_header_t /* cheat */ ,
                                     length /* changed member */ );
              tcp1->checksum = ip_csum_fold (sum1);
+             tcp_packets++;
            }
          else
            {
              old_port1 = udp1->dst_port;
              udp1->dst_port = s1->in2out.port;
              udp1->checksum = 0;
+             udp_packets++;
            }
 
          /* Accounting */
@@ -1070,7 +1089,7 @@ snat_out2in_node_fn (vlib_main_t * vm,
                  s1 - sm->per_thread_data[thread_index].sessions;
            }
 
-         pkts_processed += next1 != SNAT_OUT2IN_NEXT_DROP;
+         pkts_processed += next1 == SNAT_OUT2IN_NEXT_LOOKUP;
 
          /* verify speculative enqueues, maybe switch current next frame */
          vlib_validate_buffer_enqueue_x2 (vm, node, next_index,
@@ -1132,6 +1151,7 @@ snat_out2in_node_fn (vlib_main_t * vm,
                      next0 = SNAT_OUT2IN_NEXT_DROP;
                    }
                }
+             other_packets++;
              goto trace00;
            }
 
@@ -1148,6 +1168,7 @@ snat_out2in_node_fn (vlib_main_t * vm,
          if (PREDICT_FALSE (ip4_is_fragment (ip0)))
            {
              next0 = SNAT_OUT2IN_NEXT_REASS;
+             fragments++;
              goto trace00;
            }
 
@@ -1156,6 +1177,7 @@ snat_out2in_node_fn (vlib_main_t * vm,
              next0 = icmp_out2in_slow_path
                (sm, b0, ip0, icmp0, sw_if_index0, rx_fib_index0, node,
                 next0, now, thread_index, &s0);
+             icmp_packets++;
              goto trace00;
            }
 
@@ -1239,12 +1261,14 @@ snat_out2in_node_fn (vlib_main_t * vm,
                                     ip4_header_t /* cheat */ ,
                                     length /* changed member */ );
              tcp0->checksum = ip_csum_fold (sum0);
+             tcp_packets++;
            }
          else
            {
              old_port0 = udp0->dst_port;
              udp0->dst_port = s0->in2out.port;
              udp0->checksum = 0;
+             udp_packets++;
            }
 
          /* Accounting */
@@ -1268,7 +1292,7 @@ snat_out2in_node_fn (vlib_main_t * vm,
                  s0 - sm->per_thread_data[thread_index].sessions;
            }
 
-         pkts_processed += next0 != SNAT_OUT2IN_NEXT_DROP;
+         pkts_processed += next0 == SNAT_OUT2IN_NEXT_LOOKUP;
 
          /* verify speculative enqueue, maybe switch current next frame */
          vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
@@ -1282,6 +1306,18 @@ snat_out2in_node_fn (vlib_main_t * vm,
   vlib_node_increment_counter (vm, snat_out2in_node.index,
                               SNAT_OUT2IN_ERROR_OUT2IN_PACKETS,
                               pkts_processed);
+  vlib_node_increment_counter (vm, snat_out2in_node.index,
+                              SNAT_OUT2IN_ERROR_TCP_PACKETS, tcp_packets);
+  vlib_node_increment_counter (vm, snat_out2in_node.index,
+                              SNAT_OUT2IN_ERROR_UDP_PACKETS, udp_packets);
+  vlib_node_increment_counter (vm, snat_out2in_node.index,
+                              SNAT_OUT2IN_ERROR_ICMP_PACKETS, icmp_packets);
+  vlib_node_increment_counter (vm, snat_out2in_node.index,
+                              SNAT_OUT2IN_ERROR_OTHER_PACKETS,
+                              other_packets);
+  vlib_node_increment_counter (vm, snat_out2in_node.index,
+                              SNAT_OUT2IN_ERROR_FRAGMENTS, fragments);
+
   return frame->n_vectors;
 }
 
@@ -1318,7 +1354,7 @@ nat44_out2in_reass_node_fn (vlib_main_t * vm,
 {
   u32 n_left_from, *from, *to_next;
   snat_out2in_next_t next_index;
-  u32 pkts_processed = 0;
+  u32 pkts_processed = 0, cached_fragments = 0;
   snat_main_t *sm = &snat_main;
   f64 now = vlib_time_now (vm);
   u32 thread_index = vm->thread_index;
@@ -1570,6 +1606,7 @@ nat44_out2in_reass_node_fn (vlib_main_t * vm,
            {
              n_left_to_next++;
              to_next--;
+             cached_fragments++;
            }
          else
            {
@@ -1607,8 +1644,11 @@ nat44_out2in_reass_node_fn (vlib_main_t * vm,
     }
 
   vlib_node_increment_counter (vm, nat44_out2in_reass_node.index,
-                              SNAT_OUT2IN_ERROR_OUT2IN_PACKETS,
+                              SNAT_OUT2IN_ERROR_PROCESSED_FRAGMENTS,
                               pkts_processed);
+  vlib_node_increment_counter (vm, nat44_out2in_reass_node.index,
+                              SNAT_OUT2IN_ERROR_CACHED_FRAGMENTS,
+                              cached_fragments);
 
   nat_send_all_to_node (vm, fragments_to_drop, node,
                        &node->errors[SNAT_OUT2IN_ERROR_DROP_FRAGMENT],
index f76fc60..c3f0559 100644 (file)
 #include <nat/nat_syslog.h>
 
 #define foreach_nat_out2in_ed_error                     \
-_(UNSUPPORTED_PROTOCOL, "Unsupported protocol")         \
-_(OUT2IN_PACKETS, "Good out2in packets processed")      \
-_(OUT_OF_PORTS, "Out of ports")                         \
+_(UNSUPPORTED_PROTOCOL, "unsupported protocol")         \
+_(OUT2IN_PACKETS, "good out2in packets processed")      \
+_(OUT_OF_PORTS, "out of ports")                         \
 _(BAD_ICMP_TYPE, "unsupported ICMP type")               \
-_(NO_TRANSLATION, "No translation")                     \
-_(MAX_SESSIONS_EXCEEDED, "Maximum sessions exceeded")   \
-_(DROP_FRAGMENT, "Drop fragment")                       \
-_(MAX_REASS, "Maximum reassemblies exceeded")           \
-_(MAX_FRAG, "Maximum fragments per reassembly exceeded")\
-_(NON_SYN, "non-SYN packet try to create session")
+_(NO_TRANSLATION, "no translation")                     \
+_(MAX_SESSIONS_EXCEEDED, "maximum sessions exceeded")   \
+_(DROP_FRAGMENT, "drop fragment")                       \
+_(MAX_REASS, "maximum reassemblies exceeded")           \
+_(MAX_FRAG, "maximum fragments per reassembly exceeded")\
+_(NON_SYN, "non-SYN packet try to create session")      \
+_(TCP_PACKETS, "TCP packets")                           \
+_(UDP_PACKETS, "UDP packets")                           \
+_(ICMP_PACKETS, "ICMP packets")                         \
+_(OTHER_PACKETS, "other protocol packets")              \
+_(FRAGMENTS, "fragments")                               \
+_(CACHED_FRAGMENTS, "cached fragments")                 \
+_(PROCESSED_FRAGMENTS, "processed fragments")
 
 typedef enum
 {
@@ -712,6 +719,8 @@ nat44_ed_out2in_node_fn_inline (vlib_main_t * vm,
   f64 now = vlib_time_now (vm);
   u32 thread_index = vm->thread_index;
   snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
+  u32 tcp_packets = 0, udp_packets = 0, icmp_packets = 0, other_packets =
+    0, fragments = 0;
 
   stats_node_index = is_slow_path ? nat44_ed_out2in_slowpath_node.index :
     nat44_ed_out2in_node.index;
@@ -804,6 +813,7 @@ nat44_ed_out2in_node_fn_inline (vlib_main_t * vm,
                    nat44_ed_out2in_unknown_proto (sm, b0, ip0, rx_fib_index0,
                                                   thread_index, now, vm,
                                                   node);
+                 other_packets++;
                  if (!sm->forwarding_enabled)
                    {
                      if (!s0)
@@ -817,6 +827,7 @@ nat44_ed_out2in_node_fn_inline (vlib_main_t * vm,
                  next0 = icmp_out2in_ed_slow_path
                    (sm, b0, ip0, icmp0, sw_if_index0, rx_fib_index0, node,
                     next0, now, thread_index, &s0);
+                 icmp_packets++;
                  goto trace00;
                }
            }
@@ -831,6 +842,7 @@ nat44_ed_out2in_node_fn_inline (vlib_main_t * vm,
              if (ip4_is_fragment (ip0))
                {
                  next0 = NAT44_ED_OUT2IN_NEXT_REASS;
+                 fragments++;
                  goto trace00;
                }
 
@@ -963,6 +975,7 @@ nat44_ed_out2in_node_fn_inline (vlib_main_t * vm,
                  ip0->src_address.as_u32 = s0->ext_host_nat_addr.as_u32;
                }
              tcp0->checksum = ip_csum_fold (sum0);
+             tcp_packets++;
              if (nat44_set_tcp_session_state_o2i
                  (sm, s0, tcp0, thread_index))
                goto trace00;
@@ -976,6 +989,7 @@ nat44_ed_out2in_node_fn_inline (vlib_main_t * vm,
                  ip0->src_address.as_u32 = s0->ext_host_nat_addr.as_u32;
                }
              udp0->checksum = 0;
+             udp_packets++;
            }
 
          /* Accounting */
@@ -999,7 +1013,7 @@ nat44_ed_out2in_node_fn_inline (vlib_main_t * vm,
                t->session_index = s0 - tsm->sessions;
            }
 
-         pkts_processed += next0 != NAT44_ED_OUT2IN_NEXT_DROP;
+         pkts_processed += next0 == NAT44_ED_OUT2IN_NEXT_LOOKUP;
 
          next1 = NAT44_ED_OUT2IN_NEXT_LOOKUP;
          vnet_buffer (b1)->snat.flags = 0;
@@ -1033,6 +1047,7 @@ nat44_ed_out2in_node_fn_inline (vlib_main_t * vm,
                    nat44_ed_out2in_unknown_proto (sm, b1, ip1, rx_fib_index1,
                                                   thread_index, now, vm,
                                                   node);
+                 other_packets++;
                  if (!sm->forwarding_enabled)
                    {
                      if (!s1)
@@ -1046,6 +1061,7 @@ nat44_ed_out2in_node_fn_inline (vlib_main_t * vm,
                  next1 = icmp_out2in_ed_slow_path
                    (sm, b1, ip1, icmp1, sw_if_index1, rx_fib_index1, node,
                     next1, now, thread_index, &s1);
+                 icmp_packets++;
                  goto trace01;
                }
            }
@@ -1060,6 +1076,7 @@ nat44_ed_out2in_node_fn_inline (vlib_main_t * vm,
              if (ip4_is_fragment (ip1))
                {
                  next1 = NAT44_ED_OUT2IN_NEXT_REASS;
+                 fragments++;
                  goto trace01;
                }
 
@@ -1192,6 +1209,7 @@ nat44_ed_out2in_node_fn_inline (vlib_main_t * vm,
                  ip1->src_address.as_u32 = s1->ext_host_nat_addr.as_u32;
                }
              tcp1->checksum = ip_csum_fold (sum1);
+             tcp_packets++;
              if (nat44_set_tcp_session_state_o2i
                  (sm, s1, tcp1, thread_index))
                goto trace01;
@@ -1205,6 +1223,7 @@ nat44_ed_out2in_node_fn_inline (vlib_main_t * vm,
                  ip1->src_address.as_u32 = s1->ext_host_nat_addr.as_u32;
                }
              udp1->checksum = 0;
+             udp_packets++;
            }
 
          /* Accounting */
@@ -1228,7 +1247,7 @@ nat44_ed_out2in_node_fn_inline (vlib_main_t * vm,
                t->session_index = s1 - tsm->sessions;
            }
 
-         pkts_processed += next1 != NAT44_ED_OUT2IN_NEXT_DROP;
+         pkts_processed += next1 == NAT44_ED_OUT2IN_NEXT_LOOKUP;
 
          /* verify speculative enqueues, maybe switch current next frame */
          vlib_validate_buffer_enqueue_x2 (vm, node, next_index,
@@ -1296,6 +1315,7 @@ nat44_ed_out2in_node_fn_inline (vlib_main_t * vm,
                    nat44_ed_out2in_unknown_proto (sm, b0, ip0, rx_fib_index0,
                                                   thread_index, now, vm,
                                                   node);
+                 other_packets++;
                  if (!sm->forwarding_enabled)
                    {
                      if (!s0)
@@ -1309,6 +1329,7 @@ nat44_ed_out2in_node_fn_inline (vlib_main_t * vm,
                  next0 = icmp_out2in_ed_slow_path
                    (sm, b0, ip0, icmp0, sw_if_index0, rx_fib_index0, node,
                     next0, now, thread_index, &s0);
+                 icmp_packets++;
                  goto trace0;
                }
            }
@@ -1323,6 +1344,7 @@ nat44_ed_out2in_node_fn_inline (vlib_main_t * vm,
              if (ip4_is_fragment (ip0))
                {
                  next0 = NAT44_ED_OUT2IN_NEXT_REASS;
+                 fragments++;
                  goto trace0;
                }
 
@@ -1455,6 +1477,7 @@ nat44_ed_out2in_node_fn_inline (vlib_main_t * vm,
                  ip0->src_address.as_u32 = s0->ext_host_nat_addr.as_u32;
                }
              tcp0->checksum = ip_csum_fold (sum0);
+             tcp_packets++;
              if (nat44_set_tcp_session_state_o2i
                  (sm, s0, tcp0, thread_index))
                goto trace0;
@@ -1468,6 +1491,7 @@ nat44_ed_out2in_node_fn_inline (vlib_main_t * vm,
                  ip0->src_address.as_u32 = s0->ext_host_nat_addr.as_u32;
                }
              udp0->checksum = 0;
+             udp_packets++;
            }
 
          /* Accounting */
@@ -1491,7 +1515,7 @@ nat44_ed_out2in_node_fn_inline (vlib_main_t * vm,
                t->session_index = s0 - tsm->sessions;
            }
 
-         pkts_processed += next0 != NAT44_ED_OUT2IN_NEXT_DROP;
+         pkts_processed += next0 == NAT44_ED_OUT2IN_NEXT_LOOKUP;
          /* verify speculative enqueue, maybe switch current next frame */
          vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
                                           to_next, n_left_to_next,
@@ -1504,6 +1528,18 @@ nat44_ed_out2in_node_fn_inline (vlib_main_t * vm,
   vlib_node_increment_counter (vm, stats_node_index,
                               NAT_OUT2IN_ED_ERROR_OUT2IN_PACKETS,
                               pkts_processed);
+  vlib_node_increment_counter (vm, stats_node_index,
+                              NAT_OUT2IN_ED_ERROR_TCP_PACKETS, tcp_packets);
+  vlib_node_increment_counter (vm, stats_node_index,
+                              NAT_OUT2IN_ED_ERROR_UDP_PACKETS, udp_packets);
+  vlib_node_increment_counter (vm, stats_node_index,
+                              NAT_OUT2IN_ED_ERROR_ICMP_PACKETS,
+                              icmp_packets);
+  vlib_node_increment_counter (vm, stats_node_index,
+                              NAT_OUT2IN_ED_ERROR_OTHER_PACKETS,
+                              other_packets);
+  vlib_node_increment_counter (vm, stats_node_index,
+                              NAT_OUT2IN_ED_ERROR_FRAGMENTS, fragments);
   return frame->n_vectors;
 }
 
index b873074..a7ca6d3 100644 (file)
@@ -1507,13 +1507,21 @@ class TestNAT44(MethodHolder):
 
     def test_dynamic(self):
         """ NAT44 dynamic translation test """
-
         self.nat44_add_address(self.nat_addr)
         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
                                                   is_inside=0)
 
         # in2out
+        tcpn = self.statistics.get_counter(
+            '/err/nat44-in2out-slowpath/TCP packets')
+        udpn = self.statistics.get_counter(
+            '/err/nat44-in2out-slowpath/UDP packets')
+        icmpn = self.statistics.get_counter(
+            '/err/nat44-in2out-slowpath/ICMP packets')
+        totaln = self.statistics.get_counter(
+            '/err/nat44-in2out-slowpath/good in2out packets processed')
+
         pkts = self.create_stream_in(self.pg0, self.pg1)
         self.pg0.add_stream(pkts)
         self.pg_enable_capture(self.pg_interfaces)
@@ -1521,7 +1529,26 @@ class TestNAT44(MethodHolder):
         capture = self.pg1.get_capture(len(pkts))
         self.verify_capture_out(capture)
 
+        err = self.statistics.get_counter(
+            '/err/nat44-in2out-slowpath/TCP packets')
+        self.assertEqual(err - tcpn, 1)
+        err = self.statistics.get_counter(
+            '/err/nat44-in2out-slowpath/UDP packets')
+        self.assertEqual(err - udpn, 1)
+        err = self.statistics.get_counter(
+            '/err/nat44-in2out-slowpath/ICMP packets')
+        self.assertEqual(err - icmpn, 1)
+        err = self.statistics.get_counter(
+            '/err/nat44-in2out-slowpath/good in2out packets processed')
+        self.assertEqual(err - totaln, 3)
+
         # out2in
+        tcpn = self.statistics.get_counter('/err/nat44-out2in/TCP packets')
+        udpn = self.statistics.get_counter('/err/nat44-out2in/UDP packets')
+        icmpn = self.statistics.get_counter('/err/nat44-out2in/ICMP packets')
+        totaln = self.statistics.get_counter(
+            '/err/nat44-out2in/good out2in packets processed')
+
         pkts = self.create_stream_out(self.pg1)
         self.pg1.add_stream(pkts)
         self.pg_enable_capture(self.pg_interfaces)
@@ -1529,6 +1556,16 @@ class TestNAT44(MethodHolder):
         capture = self.pg0.get_capture(len(pkts))
         self.verify_capture_in(capture, self.pg0)
 
+        err = self.statistics.get_counter('/err/nat44-out2in/TCP packets')
+        self.assertEqual(err - tcpn, 1)
+        err = self.statistics.get_counter('/err/nat44-out2in/UDP packets')
+        self.assertEqual(err - udpn, 1)
+        err = self.statistics.get_counter('/err/nat44-out2in/ICMP packets')
+        self.assertEqual(err - icmpn, 1)
+        err = self.statistics.get_counter(
+            '/err/nat44-out2in/good out2in packets processed')
+        self.assertEqual(err - totaln, 3)
+
     def test_dynamic_icmp_errors_in2out_ttl_1(self):
         """ NAT44 handling of client packets with TTL=1 """
 
@@ -3356,6 +3393,11 @@ class TestNAT44(MethodHolder):
             self.logger.error(ppp("Unexpected or invalid packet:", p))
             raise
 
+        err = self.statistics.get_counter('/err/nat44-classify/next in2out')
+        self.assertEqual(err, 1)
+        err = self.statistics.get_counter('/err/nat44-classify/next out2in')
+        self.assertEqual(err, 1)
+
     def test_del_session(self):
         """ Delete NAT44 session """
         self.nat44_add_address(self.nat_addr)
@@ -4008,6 +4050,15 @@ class TestNAT44EndpointDependent(MethodHolder):
         self.assertEqual(1, nat_config.endpoint_dependent)
 
         # in2out
+        tcpn = self.statistics.get_counter(
+            '/err/nat44-ed-in2out-slowpath/TCP packets')
+        udpn = self.statistics.get_counter(
+            '/err/nat44-ed-in2out-slowpath/UDP packets')
+        icmpn = self.statistics.get_counter(
+            '/err/nat44-ed-in2out-slowpath/ICMP packets')
+        totaln = self.statistics.get_counter(
+            '/err/nat44-ed-in2out-slowpath/good in2out packets processed')
+
         pkts = self.create_stream_in(self.pg0, self.pg1)
         self.pg0.add_stream(pkts)
         self.pg_enable_capture(self.pg_interfaces)
@@ -4015,7 +4066,27 @@ class TestNAT44EndpointDependent(MethodHolder):
         capture = self.pg1.get_capture(len(pkts))
         self.verify_capture_out(capture)
 
+        err = self.statistics.get_counter(
+            '/err/nat44-ed-in2out-slowpath/TCP packets')
+        self.assertEqual(err - tcpn, 1)
+        err = self.statistics.get_counter(
+            '/err/nat44-ed-in2out-slowpath/UDP packets')
+        self.assertEqual(err - udpn, 1)
+        err = self.statistics.get_counter(
+            '/err/nat44-ed-in2out-slowpath/ICMP packets')
+        self.assertEqual(err - icmpn, 1)
+        err = self.statistics.get_counter(
+            '/err/nat44-ed-in2out-slowpath/good in2out packets processed')
+        self.assertEqual(err - totaln, 3)
+
         # out2in
+        tcpn = self.statistics.get_counter('/err/nat44-ed-out2in/TCP packets')
+        udpn = self.statistics.get_counter('/err/nat44-ed-out2in/UDP packets')
+        icmpn = self.statistics.get_counter(
+            '/err/nat44-ed-out2in-slowpath/ICMP packets')
+        totaln = self.statistics.get_counter(
+            '/err/nat44-ed-out2in/good out2in packets processed')
+
         pkts = self.create_stream_out(self.pg1)
         self.pg1.add_stream(pkts)
         self.pg_enable_capture(self.pg_interfaces)
@@ -4023,6 +4094,17 @@ class TestNAT44EndpointDependent(MethodHolder):
         capture = self.pg0.get_capture(len(pkts))
         self.verify_capture_in(capture, self.pg0)
 
+        err = self.statistics.get_counter('/err/nat44-ed-out2in/TCP packets')
+        self.assertEqual(err - tcpn, 1)
+        err = self.statistics.get_counter('/err/nat44-ed-out2in/UDP packets')
+        self.assertEqual(err - udpn, 1)
+        err = self.statistics.get_counter(
+            '/err/nat44-ed-out2in-slowpath/ICMP packets')
+        self.assertEqual(err - icmpn, 1)
+        err = self.statistics.get_counter(
+            '/err/nat44-ed-out2in/good out2in packets processed')
+        self.assertEqual(err - totaln, 2)
+
     def test_forwarding(self):
         """ NAT44 forwarding test """
 
@@ -6840,6 +6922,12 @@ class TestNAT64(MethodHolder):
         self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
 
         # in2out
+        tcpn = self.statistics.get_counter('/err/nat64-in2out/TCP packets')
+        udpn = self.statistics.get_counter('/err/nat64-in2out/UDP packets')
+        icmpn = self.statistics.get_counter('/err/nat64-in2out/ICMP packets')
+        totaln = self.statistics.get_counter(
+            '/err/nat64-in2out/good in2out packets processed')
+
         pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
         self.pg0.add_stream(pkts)
         self.pg_enable_capture(self.pg_interfaces)
@@ -6848,7 +6936,23 @@ class TestNAT64(MethodHolder):
         self.verify_capture_out(capture, nat_ip=self.nat_addr,
                                 dst_ip=self.pg1.remote_ip4)
 
+        err = self.statistics.get_counter('/err/nat64-in2out/TCP packets')
+        self.assertEqual(err - tcpn, 1)
+        err = self.statistics.get_counter('/err/nat64-in2out/UDP packets')
+        self.assertEqual(err - udpn, 1)
+        err = self.statistics.get_counter('/err/nat64-in2out/ICMP packets')
+        self.assertEqual(err - icmpn, 1)
+        err = self.statistics.get_counter(
+            '/err/nat64-in2out/good in2out packets processed')
+        self.assertEqual(err - totaln, 3)
+
         # out2in
+        tcpn = self.statistics.get_counter('/err/nat64-out2in/TCP packets')
+        udpn = self.statistics.get_counter('/err/nat64-out2in/UDP packets')
+        icmpn = self.statistics.get_counter('/err/nat64-out2in/ICMP packets')
+        totaln = self.statistics.get_counter(
+            '/err/nat64-out2in/good out2in packets processed')
+
         pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
         self.pg1.add_stream(pkts)
         self.pg_enable_capture(self.pg_interfaces)
@@ -6857,6 +6961,16 @@ class TestNAT64(MethodHolder):
         ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
         self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
 
+        err = self.statistics.get_counter('/err/nat64-out2in/TCP packets')
+        self.assertEqual(err - tcpn, 1)
+        err = self.statistics.get_counter('/err/nat64-out2in/UDP packets')
+        self.assertEqual(err - udpn, 1)
+        err = self.statistics.get_counter('/err/nat64-out2in/ICMP packets')
+        self.assertEqual(err - icmpn, 1)
+        err = self.statistics.get_counter(
+            '/err/nat64-out2in/good out2in packets processed')
+        self.assertEqual(err - totaln, 3)
+
         # in2out
         pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
         self.pg0.add_stream(pkts)