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:
7 * http://www.apache.org/licenses/LICENSE-2.0
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.
16 #include <vnet/vnet.h>
17 #include "ip6_ioam_seqno.h"
19 static inline void BIT_SET (u64 *p, u32 n)
21 p[ n>>5 ] |= (1 << (n&31));
24 static inline int BIT_TEST (u64 *p, u32 n)
26 return p[ n>>5 ] & (1 << (n&31));
29 static void BIT_CLEAR (u64 *p, u64 start, int num_bits, u32 mask)
32 int start_index = (start >> 5);
33 int mask_index = (mask >> 5);
35 start_index &= mask_index;
38 int start_bit = (start & 0x1f);
40 n = (1 << start_bit)-1;
41 t = start_bit + num_bits;
45 p[ start_index ] &= n;
48 p[ start_index ] &= n;
49 start_index = (start_index + 1) & mask_index;
50 num_bits -= (32 - start_bit);
52 while (num_bits >= 32)
55 start_index = (start_index + 1) & mask_index;
58 n = ~((1 << num_bits) - 1);
59 p[ start_index ] &= n;
62 static inline u8 seqno_check_wraparound(u32 a, u32 b)
64 if ((a != b) && (a > b) && ((a - b) > SEQ_CHECK_VALUE))
72 * Function to analyze the PPC value recevied.
73 * - Updates the bitmap with received sequence number
74 * - counts the received/lost/duplicate/reordered packets
76 void ioam_analyze_seqno (seqno_rx_info *seqno_rx, u64 seqno)
79 static int peer_dead_count;
80 seqno_bitmap *bitmap = &seqno_rx->bitmap;
82 seqno_rx->rx_packets++;
84 if (seqno > bitmap->highest)
85 { /* new larger sequence number */
87 diff = seqno - bitmap->highest;
88 if (diff < bitmap->window_size)
91 { /* diff==1 is *such* a common case it's a win to optimize it */
92 BIT_CLEAR(bitmap->array, bitmap->highest+1, diff-1, bitmap->mask);
93 seqno_rx->lost_packets += diff -1;
98 seqno_rx->lost_packets += diff -1;
99 memset( bitmap->array, 0, bitmap->array_size * sizeof(u64) );
101 BIT_SET(bitmap->array, seqno & bitmap->mask);
102 bitmap->highest = seqno;
106 /* we've seen a bigger seq number before */
107 diff = bitmap->highest - seqno;
108 if (diff >= bitmap->window_size)
110 if (seqno_check_wraparound(bitmap->highest, seqno))
112 memset( bitmap->array, 0, bitmap->array_size * sizeof(u64));
113 BIT_SET(bitmap->array, seqno & bitmap->mask);
114 bitmap->highest = seqno;
120 if (peer_dead_count > 25)
123 memset( bitmap->array, 0, bitmap->array_size * sizeof(u64) );
124 BIT_SET(bitmap->array, seqno & bitmap->mask);
125 bitmap->highest = seqno;
127 //ppc_rx->reordered_packets++;
132 if (BIT_TEST(bitmap->array, seqno & bitmap->mask))
134 seqno_rx->dup_packets++;
135 return; /* Already seen */
137 seqno_rx->reordered_packets++;
138 seqno_rx->lost_packets--;
139 BIT_SET(bitmap->array, seqno & bitmap->mask);