Line data Source code
1 : /* 2 : * Copyright (c) 2016 Cisco and/or its affiliates. 3 : * Licensed under the Apache License, Version 2.0 (the "License"); 4 : * you may not use this file except in compliance with the License. 5 : * You may obtain a copy of the License at: 6 : * 7 : * http://www.apache.org/licenses/LICENSE-2.0 8 : * 9 : * Unless required by applicable law or agreed to in writing, software 10 : * distributed under the License is distributed on an "AS IS" BASIS, 11 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 : * See the License for the specific language governing permissions and 13 : * limitations under the License. 14 : */ 15 : 16 : #ifndef PLUGINS_IOAM_PLUGIN_IOAM_LIB_E2E_IOAM_SEQNO_LIB_H_ 17 : #define PLUGINS_IOAM_PLUGIN_IOAM_LIB_E2E_IOAM_SEQNO_LIB_H_ 18 : 19 : #include <vppinfra/types.h> 20 : 21 : #define SEQ_CHECK_VALUE 0x80000000 /* for seq number wraparound detection */ 22 : 23 : #define SEQNO_WINDOW_SIZE 2048 24 : #define SEQNO_WINDOW_ARRAY_SIZE 64 25 : 26 : typedef struct seqno_bitmap_ 27 : { 28 : u32 window_size; 29 : u32 array_size; 30 : u32 mask; 31 : u32 pad; 32 : u64 highest; 33 : u64 array[SEQNO_WINDOW_ARRAY_SIZE]; /* Will be alloc to array_size */ 34 : } seqno_bitmap; 35 : 36 : typedef struct seqno_rx_info_ 37 : { 38 : u64 rx_packets; 39 : u64 lost_packets; 40 : u64 reordered_packets; 41 : u64 dup_packets; 42 : seqno_bitmap bitmap; 43 : } seqno_rx_info; 44 : 45 : /* This structure is 64-byte aligned */ 46 : typedef struct ioam_seqno_data_ 47 : { 48 : union 49 : { 50 : u32 seq_num; /* Useful only for encap node */ 51 : seqno_rx_info seqno_rx; 52 : }; 53 : } ioam_seqno_data; 54 : 55 : static inline void 56 0 : BIT_SET (u64 * p, u32 n) 57 : { 58 0 : p[n >> 5] |= (1 << (n & 31)); 59 0 : } 60 : 61 : static inline int 62 0 : BIT_TEST (u64 * p, u32 n) 63 : { 64 0 : return p[n >> 5] & (1 << (n & 31)); 65 : } 66 : 67 : static void 68 0 : BIT_CLEAR (u64 * p, u64 start, int num_bits, u32 mask) 69 : { 70 : int n, t; 71 0 : int start_index = (start >> 5); 72 0 : int mask_index = (mask >> 5); 73 : 74 0 : start_index &= mask_index; 75 0 : if (start & 0x1f) 76 : { 77 0 : int start_bit = (start & 0x1f); 78 : 79 0 : n = (1 << start_bit) - 1; 80 0 : t = start_bit + num_bits; 81 0 : if (t < 32) 82 : { 83 0 : n |= ~((1 << t) - 1); 84 0 : p[start_index] &= n; 85 0 : return; 86 : } 87 0 : p[start_index] &= n; 88 0 : start_index = (start_index + 1) & mask_index; 89 0 : num_bits -= (32 - start_bit); 90 : } 91 0 : while (num_bits >= 32) 92 : { 93 0 : p[start_index] = 0; 94 0 : start_index = (start_index + 1) & mask_index; 95 0 : num_bits -= 32; 96 : } 97 0 : n = ~((1 << num_bits) - 1); 98 0 : p[start_index] &= n; 99 : } 100 : 101 : static inline u8 102 0 : seqno_check_wraparound (u32 a, u32 b) 103 : { 104 0 : if ((a != b) && (a > b) && ((a - b) > SEQ_CHECK_VALUE)) 105 : { 106 0 : return 1; 107 : } 108 0 : return 0; 109 : } 110 : 111 : /* 112 : * Function to analyze the PPC value recevied. 113 : * - Updates the bitmap with received sequence number 114 : * - counts the received/lost/duplicate/reordered packets 115 : */ 116 : inline static void 117 0 : ioam_analyze_seqno (seqno_rx_info * seqno_rx, u64 seqno) 118 : { 119 : int diff; 120 : static int peer_dead_count; 121 0 : seqno_bitmap *bitmap = &seqno_rx->bitmap; 122 : 123 0 : seqno_rx->rx_packets++; 124 : 125 0 : if (seqno > bitmap->highest) 126 : { /* new larger sequence number */ 127 0 : peer_dead_count = 0; 128 0 : diff = seqno - bitmap->highest; 129 0 : if (diff < bitmap->window_size) 130 : { 131 0 : if (diff > 1) 132 : { /* diff==1 is *such* a common case it's a win to optimize it */ 133 0 : BIT_CLEAR (bitmap->array, bitmap->highest + 1, diff - 1, 134 : bitmap->mask); 135 0 : seqno_rx->lost_packets += diff - 1; 136 : } 137 : } 138 : else 139 : { 140 0 : seqno_rx->lost_packets += diff - 1; 141 0 : clib_memset (bitmap->array, 0, bitmap->array_size * sizeof (u64)); 142 : } 143 0 : BIT_SET (bitmap->array, seqno & bitmap->mask); 144 0 : bitmap->highest = seqno; 145 0 : return; 146 : } 147 : 148 : /* we've seen a bigger seq number before */ 149 0 : diff = bitmap->highest - seqno; 150 0 : if (diff >= bitmap->window_size) 151 : { 152 0 : if (seqno_check_wraparound (bitmap->highest, seqno)) 153 : { 154 0 : clib_memset (bitmap->array, 0, bitmap->array_size * sizeof (u64)); 155 0 : BIT_SET (bitmap->array, seqno & bitmap->mask); 156 0 : bitmap->highest = seqno; 157 0 : return; 158 : } 159 : else 160 : { 161 0 : peer_dead_count++; 162 0 : if (peer_dead_count > 25) 163 : { 164 0 : peer_dead_count = 0; 165 0 : clib_memset (bitmap->array, 0, 166 : bitmap->array_size * sizeof (u64)); 167 0 : BIT_SET (bitmap->array, seqno & bitmap->mask); 168 0 : bitmap->highest = seqno; 169 : } 170 : //ppc_rx->reordered_packets++; 171 : } 172 0 : return; 173 : } 174 : 175 0 : if (BIT_TEST (bitmap->array, seqno & bitmap->mask)) 176 : { 177 0 : seqno_rx->dup_packets++; 178 0 : return; /* Already seen */ 179 : } 180 0 : seqno_rx->reordered_packets++; 181 0 : seqno_rx->lost_packets--; 182 0 : BIT_SET (bitmap->array, seqno & bitmap->mask); 183 0 : return; 184 : } 185 : 186 : u8 *show_ioam_seqno_analyse_data_fn (u8 * s, seqno_rx_info * rx); 187 : 188 : u8 *show_ioam_seqno_cmd_fn (u8 * s, ioam_seqno_data * seqno_data, u8 enc); 189 : 190 : void ioam_seqno_init_data (ioam_seqno_data * data); 191 : 192 : void ioam_seqno_init_rx_info (seqno_rx_info * data); 193 : 194 : #endif /* PLUGINS_IOAM_PLUGIN_IOAM_LIB_E2E_IOAM_SEQNO_LIB_H_ */ 195 : 196 : /* 197 : * fd.io coding-style-patch-verification: ON 198 : * 199 : * Local Variables: 200 : * eval: (c-set-style "gnu") 201 : * End: 202 : */