summaryrefslogtreecommitdiffstats
path: root/src/plugins/ioam/lib-e2e/ioam_seqno_lib.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/ioam/lib-e2e/ioam_seqno_lib.h')
-rw-r--r--src/plugins/ioam/lib-e2e/ioam_seqno_lib.h201
1 files changed, 201 insertions, 0 deletions
diff --git a/src/plugins/ioam/lib-e2e/ioam_seqno_lib.h b/src/plugins/ioam/lib-e2e/ioam_seqno_lib.h
new file mode 100644
index 00000000000..6bd38ff2968
--- /dev/null
+++ b/src/plugins/ioam/lib-e2e/ioam_seqno_lib.h
@@ -0,0 +1,201 @@
+/*
+ * Copyright (c) 2016 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef PLUGINS_IOAM_PLUGIN_IOAM_LIB_E2E_IOAM_SEQNO_LIB_H_
+#define PLUGINS_IOAM_PLUGIN_IOAM_LIB_E2E_IOAM_SEQNO_LIB_H_
+
+#include <vppinfra/types.h>
+
+#define SEQ_CHECK_VALUE 0x80000000 /* for seq number wraparound detection */
+
+#define SEQNO_WINDOW_SIZE 2048
+#define SEQNO_WINDOW_ARRAY_SIZE 64
+
+typedef struct seqno_bitmap_
+{
+ u32 window_size;
+ u32 array_size;
+ u32 mask;
+ u32 pad;
+ u64 highest;
+ u64 array[SEQNO_WINDOW_ARRAY_SIZE]; /* Will be alloc to array_size */
+} seqno_bitmap;
+
+typedef struct seqno_rx_info_
+{
+ u64 rx_packets;
+ u64 lost_packets;
+ u64 reordered_packets;
+ u64 dup_packets;
+ seqno_bitmap bitmap;
+} seqno_rx_info;
+
+/* This structure is 64-byte aligned */
+typedef struct ioam_seqno_data_
+{
+ union
+ {
+ u32 seq_num; /* Useful only for encap node */
+ seqno_rx_info seqno_rx;
+ };
+} ioam_seqno_data;
+
+static inline void
+BIT_SET (u64 * p, u32 n)
+{
+ p[n >> 5] |= (1 << (n & 31));
+}
+
+static inline int
+BIT_TEST (u64 * p, u32 n)
+{
+ return p[n >> 5] & (1 << (n & 31));
+}
+
+static void
+BIT_CLEAR (u64 * p, u64 start, int num_bits, u32 mask)
+{
+ int n, t;
+ int start_index = (start >> 5);
+ int mask_index = (mask >> 5);
+
+ start_index &= mask_index;
+ if (start & 0x1f)
+ {
+ int start_bit = (start & 0x1f);
+
+ n = (1 << start_bit) - 1;
+ t = start_bit + num_bits;
+ if (t < 32)
+ {
+ n |= ~((1 << t) - 1);
+ p[start_index] &= n;
+ return;
+ }
+ p[start_index] &= n;
+ start_index = (start_index + 1) & mask_index;
+ num_bits -= (32 - start_bit);
+ }
+ while (num_bits >= 32)
+ {
+ p[start_index] = 0;
+ start_index = (start_index + 1) & mask_index;
+ num_bits -= 32;
+ }
+ n = ~((1 << num_bits) - 1);
+ p[start_index] &= n;
+}
+
+static inline u8
+seqno_check_wraparound (u32 a, u32 b)
+{
+ if ((a != b) && (a > b) && ((a - b) > SEQ_CHECK_VALUE))
+ {
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ * Function to analyze the PPC value recevied.
+ * - Updates the bitmap with received sequence number
+ * - counts the received/lost/duplicate/reordered packets
+ */
+inline static void
+ioam_analyze_seqno (seqno_rx_info * seqno_rx, u64 seqno)
+{
+ int diff;
+ static int peer_dead_count;
+ seqno_bitmap *bitmap = &seqno_rx->bitmap;
+
+ seqno_rx->rx_packets++;
+
+ if (seqno > bitmap->highest)
+ { /* new larger sequence number */
+ peer_dead_count = 0;
+ diff = seqno - bitmap->highest;
+ if (diff < bitmap->window_size)
+ {
+ if (diff > 1)
+ { /* diff==1 is *such* a common case it's a win to optimize it */
+ BIT_CLEAR (bitmap->array, bitmap->highest + 1, diff - 1,
+ bitmap->mask);
+ seqno_rx->lost_packets += diff - 1;
+ }
+ }
+ else
+ {
+ seqno_rx->lost_packets += diff - 1;
+ memset (bitmap->array, 0, bitmap->array_size * sizeof (u64));
+ }
+ BIT_SET (bitmap->array, seqno & bitmap->mask);
+ bitmap->highest = seqno;
+ return;
+ }
+
+ /* we've seen a bigger seq number before */
+ diff = bitmap->highest - seqno;
+ if (diff >= bitmap->window_size)
+ {
+ if (seqno_check_wraparound (bitmap->highest, seqno))
+ {
+ memset (bitmap->array, 0, bitmap->array_size * sizeof (u64));
+ BIT_SET (bitmap->array, seqno & bitmap->mask);
+ bitmap->highest = seqno;
+ return;
+ }
+ else
+ {
+ peer_dead_count++;
+ if (peer_dead_count > 25)
+ {
+ peer_dead_count = 0;
+ memset (bitmap->array, 0, bitmap->array_size * sizeof (u64));
+ BIT_SET (bitmap->array, seqno & bitmap->mask);
+ bitmap->highest = seqno;
+ }
+ //ppc_rx->reordered_packets++;
+ }
+ return;
+ }
+
+ if (BIT_TEST (bitmap->array, seqno & bitmap->mask))
+ {
+ seqno_rx->dup_packets++;
+ return; /* Already seen */
+ }
+ seqno_rx->reordered_packets++;
+ seqno_rx->lost_packets--;
+ BIT_SET (bitmap->array, seqno & bitmap->mask);
+ return;
+}
+
+u8 *show_ioam_seqno_analyse_data_fn (u8 * s, seqno_rx_info * rx);
+
+u8 *show_ioam_seqno_cmd_fn (u8 * s, ioam_seqno_data * seqno_data, u8 enc);
+
+void ioam_seqno_init_data (ioam_seqno_data * data);
+
+void ioam_seqno_init_rx_info (seqno_rx_info * data);
+
+#endif /* PLUGINS_IOAM_PLUGIN_IOAM_LIB_E2E_IOAM_SEQNO_LIB_H_ */
+
+/*
+ * fd.io coding-style-patch-verification: ON
+ *
+ * Local Variables:
+ * eval: (c-set-style "gnu")
+ * End:
+ */