vpp/plugins/ioam-plugin/ioam/encap/ip6_ioam_seqno_analyse.c
AkshayaNadahalli ed4a2fdd4d Adding Sequence Number - Per Packet Counter(PPC) support for iOAM6.
- Added support in classifier session to identify a flow to be iOAM6 encap/decap
- Sequence number as part of iOAM6 E2E header is created as a plugin.

Change-Id: Ib7605de45aecff25d684d099b525f8dc96ee7038
Signed-off-by: AkshayaNadahalli <anadahal@cisco.com>
2016-11-03 11:44:21 +00:00

142 lines
3.7 KiB
C

/*
* 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.
*/
#include <vnet/vnet.h>
#include "ip6_ioam_seqno.h"
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
*/
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;
}