VPP-632 : InBand OAM Analyser

Refer to jira ticket for more details.

Change-Id: I6facb9ef8553a21464f9a2e612706f152badbb68
Signed-off-by: AkshayaNadahalli <anadahal@cisco.com>
This commit is contained in:
AkshayaNadahalli
2016-12-01 16:33:51 +05:30
committed by Neale Ranns
parent fed79e8391
commit fdd81af6af
33 changed files with 2797 additions and 336 deletions
+30 -6
View File
@@ -129,17 +129,39 @@ vxlan_gpe_ioam_export_test_plugin_la_SOURCES = \
vppapitestplugins_LTLIBRARIES += vxlan_gpe_ioam_export_test_plugin.la
########################################
# iOAM E2E plugin
# iOAM E2E
########################################
IOAM_E2E_SRC = \
ioam/encap/ip6_ioam_e2e.c \
ioam/encap/ip6_ioam_seqno.c \
ioam/encap/ip6_ioam_seqno_analyse.c
ioam/encap/ip6_ioam_seqno.c \
ioam/lib-e2e/ioam_seqno_lib.c
IOAM_E2E_NOINST_HDR = \
IOAM_E2E_NOINST_HDR = \
ioam/encap/ip6_ioam_e2e.h \
ioam/encap/ip6_ioam_seqno.h
ioam/encap/ip6_ioam_seqno.h \
ioam/lib-e2e/ioam_seqno_lib.h
########################################
# ipfix collector
########################################
IPFIX_COLLECTOR_SRC = \
ioam/ipfixcollector/ipfixcollector.c \
ioam/ipfixcollector/node.c \
ioam/ipfixcollector/ipfixcollector.h
########################################
# iOAM Analyse
########################################
IOAM_ANALYSE_SRC = \
ioam/analyse/ip6/ip6_ioam_analyse.c \
ioam/analyse/ip6/node.c \
ioam/analyse/ip6/ip6_ioam_analyse.h \
ioam/analyse/ioam_summary_export.c \
ioam/analyse/ioam_analyse.h \
ioam/analyse/ioam_summary_export.h
########################################
# iOAM plugins
@@ -150,7 +172,9 @@ ioam_plugin_la_SOURCES = \
$(IOAM_EXPORT_SRC) \
$(IOAM_TRACE_SRC) \
$(IOAM_VXLAN_GPE_SRC) \
$(IOAM_E2E_SRC)
$(IOAM_E2E_SRC) \
$(IPFIX_COLLECTOR_SRC) \
$(IOAM_ANALYSE_SRC)
API_FILES += \
$(IOAM_POT_API) \
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+86
View File
@@ -0,0 +1,86 @@
/*
* Copyright (c) 2017 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 __included_ip6_ioam_flow_report_h__
#define __included_ip6_ioam_flow_report_h__
#include <ioam/analyse/ioam_analyse.h>
#include <vnet/flow/flow_report.h>
#define foreach_ioam_ipfix_info_element \
_(ioamPacketSent, 5239, u32) \
_(ioamPacketCount, 5237, u32) \
_(ioamByteCount, 5238, u32) \
_(ioamPathMap, 5262, u32) \
_(ioamNumberOfPaths, 5264, u16) \
_(ioamSfcValidatedCount, 5278, u32) \
_(ioamSfcInValidatedCount, 5279, u32) \
_(ioamSeqnoRxCount, 5280, u32) \
_(ioamSeqnoLostCount, 5281, u32) \
_(ioamSeqnoReorderedCount, 5282, u32) \
_(ioamSeqnoDupCount, 5283, u32)
typedef enum
{
#define _(n,v,t) n = v,
foreach_ioam_ipfix_info_element
#undef _
} ioam_ipfix_info_element_id_t;
#define foreach_ioam_ipfix_field \
_(pkt_sent, 0xffffffff, ioamPacketSent, 4) \
_(pkt_counter, 0xffffffff, ioamPacketCount, 4) \
_(bytes_counter, 0xffffffff, ioamByteCount, 4) \
_(pot_data.sfc_validated_count, 0xffffffff, ioamSfcValidatedCount, 4) \
_(pot_data.sfc_invalidated_count, 0xffffffff, ioamSfcInValidatedCount, 4) \
_(seqno_data.rx_packets, 0xffffffff, ioamSeqnoRxCount, 4) \
_(seqno_data.lost_packets, 0xffffffff, ioamSeqnoLostCount, 4) \
_(seqno_data.reordered_packets, 0xffffffff, ioamSeqnoReorderedCount, 4) \
_(seqno_data.dup_packets, 0xffffffff, ioamSeqnoDupCount, 4)
clib_error_t *ioam_flow_report_init (vlib_main_t * vm);
typedef struct
{
u8 num_nodes;
u8 trace_type;
u16 reserve;
u32 mean_delay;
u32 pkt_counter;
u32 bytes_counter;
ioam_path_map_t path[IOAM_TRACE_MAX_NODES];
} ioam_path;
clib_error_t *ioam_flow_create (u8 del);
u8 *ioam_template_rewrite (flow_report_main_t * frm, flow_report_t * fr,
ip4_address_t * collector_address,
ip4_address_t * src_address, u16 collector_port);
u16 ioam_analyse_add_ipfix_record (flow_report_t * fr,
ioam_analyser_data_t * record,
vlib_buffer_t * b0, u16 offset,
ip6_address_t * src, ip6_address_t * dst,
u16 src_port, u16 dst_port);
#endif /* __included_ip6_ioam_flow_report_h__ */
/*
* fd.io coding-style-patch-verification: ON
*
* Local Variables:
* eval: (c-set-style "gnu")
* End:
*/
@@ -0,0 +1,162 @@
/*
* Copyright (c) 2017 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 <ioam/analyse/ioam_analyse.h>
#include <ioam/export-common/ioam_export.h>
#include <ioam/analyse/ip6/ip6_ioam_analyse.h>
#include <ioam/analyse/ioam_summary_export.h>
#include <vnet/ip/ip.h>
#include <ioam/ipfixcollector/ipfixcollector.h>
static clib_error_t *
ioam_analyse_enable_disable (vlib_main_t * vm,
int is_add, int is_export, int remote_listen)
{
ipfix_client_add_del_t ipfix_reg;
clib_error_t *rv = 0;
ipfix_reg.client_name = format (0, "ip6-hbh-analyse-remote");
ipfix_reg.client_node = analyse_node_remote.index;
ipfix_reg.ipfix_setid = IPFIX_IOAM_EXPORT_ID;
if (is_export)
{
rv = ioam_flow_create (!is_add);
if (rv)
goto ret;
}
if (is_add)
{
ip6_ioam_analyse_register_handlers ();
if (remote_listen)
{
ipfix_reg.del = 0;
ipfix_collector_reg_setid (vm, &ipfix_reg);
}
else
{
ioam_export_set_next_node (&ioam_export_main,
(u8 *) "ip6-hbh-analyse-local");
}
}
else
{
ip6_ioam_analyse_unregister_handlers ();
if (remote_listen)
{
ipfix_reg.del = 1;
ipfix_collector_reg_setid (vm, &ipfix_reg);
}
else
ioam_export_reset_next_node (&ioam_export_main);
}
ret:
vec_free (ipfix_reg.client_name);
return rv;
}
static clib_error_t *
set_ioam_analyse_command_fn (vlib_main_t * vm, unformat_input_t * input,
vlib_cli_command_t * cmd)
{
int is_export = 0;
int is_add = 1;
int remote_listen = 0;
while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
{
if (unformat (input, "export-ipfix-collector"))
is_export = 1;
else if (unformat (input, "disable"))
is_add = 0;
else if (unformat (input, "listen-ipfix"))
remote_listen = 1;
else
break;
}
return (ioam_analyse_enable_disable (vm, is_add, is_export, remote_listen));
}
/* *INDENT-OFF* */
VLIB_CLI_COMMAND (set_ioam_analyse_command, static) = {
.path = "set ioam analyse",
.short_help = "set ioam analyse [export-ipfix-collector] [disable] [listen-ipfix]",
.function = set_ioam_analyse_command_fn,
};
/* *INDENT-ON* */
static clib_error_t *
show_ioam_analyse_cmd_fn (vlib_main_t * vm, unformat_input_t * input,
vlib_cli_command_t * cmd)
{
ip6_ioam_analyser_main_t *am = &ioam_analyser_main;
ioam_analyser_data_t *record = NULL;
u8 i;
u8 *s = 0;
vec_reset_length (s);
s = format (0, "iOAM Analyse Information: \n");
vec_foreach_index (i, am->aggregated_data)
{
record = am->aggregated_data + i;
if (record->is_free)
continue;
s = format (s, "Flow Number: %u\n", i);
s = print_analyse_flow (s, record);
s = format (s, "\n");
}
vlib_cli_output (vm, "%v", s);
vec_free (s);
return 0;
}
/* *INDENT-OFF* */
VLIB_CLI_COMMAND (ip6_show_ioam_ipfix_cmd, static) = {
.path = "show ioam analyse ",
.short_help = "show ioam analyser information",
.function = show_ioam_analyse_cmd_fn,
};
/* *INDENT-ON* */
static clib_error_t *
ioam_analyse_init (vlib_main_t * vm)
{
ip6_ioam_analyser_main_t *am = &ioam_analyser_main;
u16 i;
vec_validate_aligned (am->aggregated_data, 50, CLIB_CACHE_LINE_BYTES);
vec_foreach_index (i, am->aggregated_data)
{
ioam_analyse_init_data (am->aggregated_data + i);
}
return 0;
}
VLIB_INIT_FUNCTION (ioam_analyse_init);
/*
* fd.io coding-style-patch-verification: ON
*
* Local Variables:
* eval: (c-set-style "gnu")
* End:
*/
@@ -0,0 +1,68 @@
/*
* Copyright (c) 2017 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_ANALYSE_IP6_IOAM_ANALYSE_NODE_H_
#define PLUGINS_IOAM_PLUGIN_IOAM_ANALYSE_IP6_IOAM_ANALYSE_NODE_H_
#include <ioam/analyse/ioam_analyse.h>
#include <vnet/ip/ip6_hop_by_hop.h>
/** @brief IP6-iOAM analyser main structure.
@note cache aligned.
*/
typedef struct
{
/** Array of function pointer to analyse each hop-by-hop option. */
int (*analyse_hbh_handler[MAX_IP6_HBH_OPTION]) (u32 flow_id,
ip6_hop_by_hop_option_t *
opt, u16 len);
/** This contains the aggregated data from the time VPP started analysing. */
ioam_analyser_data_t *aggregated_data;
} ip6_ioam_analyser_main_t;
extern ip6_ioam_analyser_main_t ioam_analyser_main;
extern vlib_node_registration_t analyse_node_local;
extern vlib_node_registration_t analyse_node_remote;
void ip6_ioam_analyse_register_handlers (void);
void ip6_ioam_analyse_unregister_handlers (void);
clib_error_t *ip6_ioam_analyse_init (vlib_main_t * vm);
inline static ioam_analyser_data_t *
ioam_analyse_get_data_from_flow_id (u32 flow_id)
{
if (flow_id >= vec_len (ioam_analyser_main.aggregated_data))
return NULL;
if (ioam_analyser_main.aggregated_data[flow_id].is_free)
ioam_analyser_main.aggregated_data[flow_id].is_free = 0;
return (ioam_analyser_main.aggregated_data + flow_id);
}
#endif /* PLUGINS_IOAM_PLUGIN_IOAM_ANALYSE_IP6_IOAM_ANALYSE_NODE_H_ */
/*
* fd.io coding-style-patch-verification: ON
*
* Local Variables:
* eval: (c-set-style "gnu")
* End:
*/
File diff suppressed because it is too large Load Diff
+2 -2
View File
@@ -37,7 +37,7 @@ static u8 * ioam_e2e_trace_handler (u8 * s,
if (e2e)
{
seqno = clib_net_to_host_u32 (e2e->e2e_data);
seqno = clib_net_to_host_u32 (e2e->e2e_hdr.e2e_data);
}
s = format (s, "SeqNo = 0x%Lx", seqno);
@@ -108,7 +108,7 @@ ioam_e2e_flow_handler (u32 ctx, u8 add)
{
pool_get(ioam_e2e_main.e2e_data, data);
data->flow_ctx = ctx;
ioam_seqno_init_bitmap(&data->seqno_data);
ioam_seqno_init_data(&data->seqno_data);
return ((u32) (data - ioam_e2e_main.e2e_data));
}
+17
View File
@@ -16,8 +16,16 @@
#ifndef __included_ip6_ioam_e2e_h__
#define __included_ip6_ioam_e2e_h__
#include "../lib-e2e/e2e_util.h"
#include "ip6_ioam_seqno.h"
/* *INDENT-OFF* */
typedef CLIB_PACKED(struct {
ip6_hop_by_hop_option_t hdr;
ioam_e2e_packet_t e2e_hdr;
}) ioam_e2e_option_t;
/* *INDENT-ON* */
typedef struct ioam_e2e_data_t_ {
u32 flow_ctx;
u32 pad;
@@ -44,4 +52,13 @@ ioam_e2ec_get_seqno_data_from_flow_ctx (u32 flow_ctx)
return &(data->seqno_data);
}
static inline u32
ioam_e2e_get_cur_seqno_from_flow_ctx (u32 flow_ctx)
{
ioam_seqno_data *data = NULL;
data = ioam_e2ec_get_seqno_data_from_flow_ctx(flow_ctx);
return data->seq_num;
}
#endif /* __included_ioam_e2e_h__ */
+5 -16
View File
@@ -16,26 +16,15 @@
#include <vnet/vnet.h>
#include <vnet/pg/pg.h>
#include <vppinfra/error.h>
#include <vnet/ip/ip6.h>
#include <vnet/ip/ip6_hop_by_hop.h>
#include <vnet/ip/ip6_hop_by_hop_packet.h>
#include <vppinfra/hash.h>
#include <vppinfra/error.h>
#include <vppinfra/elog.h>
#include <ioam/encap/ip6_ioam_pot.h>
#include <ioam/lib-pot/pot_util.h>
typedef CLIB_PACKED(struct {
ip6_hop_by_hop_option_t hdr;
u8 pot_type;
#define PROFILE_ID_MASK 0xF
u8 reserved_profile_id; /* 4 bits reserved, 4 bits to carry profile id */
u64 random;
u64 cumulative;
}) ioam_pot_option_t;
#define foreach_ip6_hop_by_hop_ioam_pot_stats \
_(PROCESSED, "Pkts with ip6 hop-by-hop pot options") \
_(PROFILE_MISS, "Pkts with ip6 hop-by-hop pot options but no profile set") \
@@ -180,19 +169,19 @@ ip6_hbh_ioam_proof_of_transit_pop_handler (vlib_buffer_t *b, ip6_header_t *ip,
int rv = 0;
pot_profile *pot_profile = 0;
u8 result = 0;
pot0 = (ioam_pot_option_t *) opt0;
random = clib_net_to_host_u64(pot0->random);
cumulative = clib_net_to_host_u64(pot0->cumulative);
pot_profile = pot_profile_get_active();
result = pot_validate (pot_profile,
cumulative, random);
if (result == 1)
if (result == 1)
{
ip6_ioam_stats_increment_counter (IP6_IOAM_POT_PASSED, 1);
}
else
else
{
ip6_ioam_stats_increment_counter (IP6_IOAM_POT_FAILED, 1);
}
+40
View File
@@ -0,0 +1,40 @@
/*
* Copyright (c) 2017 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_ENCAP_IP6_IOAM_POT_H_
#define PLUGINS_IOAM_PLUGIN_IOAM_ENCAP_IP6_IOAM_POT_H_
#include <vnet/ip/ip6_hop_by_hop_packet.h>
/* *INDENT-OFF* */
typedef CLIB_PACKED (struct {
ip6_hop_by_hop_option_t hdr;
u8 pot_type;
#define PROFILE_ID_MASK 0xF
u8 reserved_profile_id; /* 4 bits reserved, 4 bits to carry profile id */
u64 random;
u64 cumulative;
}) ioam_pot_option_t;
/* *INDENT-ON* */
#endif /* PLUGINS_IOAM_PLUGIN_IOAM_ENCAP_IP6_IOAM_POT_H_ */
/*
* fd.io coding-style-patch-verification: ON
*
* Local Variables:
* eval: (c-set-style "gnu")
* End:
*/
+3 -40
View File
@@ -28,20 +28,6 @@
#include "ip6_ioam_seqno.h"
#include "ip6_ioam_e2e.h"
ioam_seqno_data_main_t ioam_seqno_main;
void ioam_seqno_init_bitmap (ioam_seqno_data *data)
{
seqno_bitmap *bitmap = &data->seqno_rx.bitmap;
bitmap->window_size = SEQNO_WINDOW_SIZE;
bitmap->array_size = SEQNO_WINDOW_ARRAY_SIZE;
bitmap->mask = 32 * SEQNO_WINDOW_ARRAY_SIZE - 1;
bitmap->array[0] = 0x00000000;/* pretend we haven seen sequence numbers 0*/
bitmap->highest = 0;
data->seq_num = 0;
return ;
}
/*
* This Routine gets called from IPv6 hop-by-hop option handling.
@@ -60,7 +46,7 @@ ioam_seqno_encap_handler (vlib_buffer_t *b, ip6_header_t *ip,
data = ioam_e2ec_get_seqno_data_from_flow_ctx(opaque_index);
e2e = (ioam_e2e_option_t *) opt;
e2e->e2e_data = clib_host_to_net_u32(++data->seq_num);
e2e->e2e_hdr.e2e_data = clib_host_to_net_u32(++data->seq_num);
return (rv);
}
@@ -79,31 +65,8 @@ ioam_seqno_decap_handler (vlib_buffer_t *b, ip6_header_t *ip,
data = ioam_e2ec_get_seqno_data_from_flow_ctx(opaque_index);
e2e = (ioam_e2e_option_t *) opt;
ioam_analyze_seqno(&data->seqno_rx, (u64) clib_net_to_host_u32(e2e->e2e_data));
ioam_analyze_seqno(&data->seqno_rx,
(u64) clib_net_to_host_u32(e2e->e2e_hdr.e2e_data));
return (rv);
}
u8 *
show_ioam_seqno_cmd_fn (u8 *s, ioam_seqno_data *seqno_data, u8 enc)
{
seqno_rx_info *rx;
s = format(s, "SeqNo Data:\n");
if (enc)
{
s = format(s, " Current Seq. Number : %llu\n", seqno_data->seq_num);
}
else
{
rx = &seqno_data->seqno_rx;
s = format(s, " Highest Seq. Number : %llu\n", rx->bitmap.highest);
s = format(s, " Packets received : %llu\n", rx->rx_packets);
s = format(s, " Lost packets : %llu\n", rx->lost_packets);
s = format(s, " Reordered packets : %llu\n", rx->reordered_packets);
s = format(s, " Duplicate packets : %llu\n", rx->dup_packets);
}
format(s, "\n");
return s;
}
+1 -41
View File
@@ -18,42 +18,7 @@
#include <vnet/ip/ip6_packet.h>
#include <vnet/ip/ip6_hop_by_hop.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;
typedef struct ioam_seqno_data_main_t_ {
ioam_seqno_data *seqno_data;
} ioam_seqno_data_main_t;
void ioam_seqno_init_bitmap(ioam_seqno_data *data);
#include <ioam/lib-e2e/e2e_util.h>
int ioam_seqno_encap_handler(vlib_buffer_t *b, ip6_header_t *ip,
ip6_hop_by_hop_option_t *opt);
@@ -62,9 +27,4 @@ int
ioam_seqno_decap_handler(vlib_buffer_t *b, ip6_header_t *ip,
ip6_hop_by_hop_option_t *opt);
void ioam_analyze_seqno(seqno_rx_info *ppc_rx, u64 seqno);
u8 *
show_ioam_seqno_cmd_fn(u8 *s, ioam_seqno_data *seqno_data, u8 enc);
#endif
@@ -1,141 +0,0 @@
/*
* 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;
}
+22 -28
View File
@@ -27,7 +27,7 @@
#include <vppinfra/elog.h>
#include <vnet/plugin/plugin.h>
#include <ioam/lib-trace/trace_util.h>
#include <ioam/encap/ip6_ioam_trace.h>
/* Timestamp precision multipliers for seconds, milliseconds, microseconds
* and nanoseconds respectively.
@@ -40,15 +40,6 @@ typedef union
u32 as_u32[2];
} time_u64_t;
/* *INDENT-OFF* */
typedef CLIB_PACKED(struct {
ip6_hop_by_hop_option_t hdr;
u8 ioam_trace_type;
u8 data_list_elts_left;
u32 elts[0]; /* Variable type. So keep it generic */
}) ioam_trace_option_t;
/* *INDENT-ON* */
extern ip6_hop_by_hop_ioam_main_t ip6_hop_by_hop_ioam_main;
extern ip6_main_t ip6_main;
@@ -201,8 +192,9 @@ ip6_hop_by_hop_ioam_trace_rewrite_handler (u8 * rewrite_string,
HBH_OPTION_TYPE_DATA_CHANGE_ENROUTE;
trace_option->hdr.length = 2 /*ioam_trace_type,data_list_elts_left */ +
trace_option_elts * trace_data_size;
trace_option->ioam_trace_type = profile->trace_type & TRACE_TYPE_MASK;
trace_option->data_list_elts_left = trace_option_elts;
trace_option->trace_hdr.ioam_trace_type =
profile->trace_type & TRACE_TYPE_MASK;
trace_option->trace_hdr.data_list_elts_left = trace_option_elts;
*rewrite_size =
sizeof (ioam_trace_option_t) + (trace_option_elts * trace_data_size);
@@ -238,24 +230,24 @@ ip6_hbh_ioam_trace_data_list_handler (vlib_buffer_t * b, ip6_header_t * ip,
time_u64.as_u64 = 0;
if (PREDICT_TRUE (trace->data_list_elts_left))
if (PREDICT_TRUE (trace->trace_hdr.data_list_elts_left))
{
trace->data_list_elts_left--;
trace->trace_hdr.data_list_elts_left--;
/* fetch_trace_data_size returns in bytes. Convert it to 4-bytes
* to skip to this node's location.
*/
elt_index =
trace->data_list_elts_left *
fetch_trace_data_size (trace->ioam_trace_type) / 4;
elt = &trace->elts[elt_index];
if (trace->ioam_trace_type & BIT_TTL_NODEID)
trace->trace_hdr.data_list_elts_left *
fetch_trace_data_size (trace->trace_hdr.ioam_trace_type) / 4;
elt = &trace->trace_hdr.elts[elt_index];
if (trace->trace_hdr.ioam_trace_type & BIT_TTL_NODEID)
{
*elt =
clib_host_to_net_u32 ((ip->hop_limit << 24) | profile->node_id);
elt++;
}
if (trace->ioam_trace_type & BIT_ING_INTERFACE)
if (trace->trace_hdr.ioam_trace_type & BIT_ING_INTERFACE)
{
*elt =
(vnet_buffer (b)->sw_if_index[VLIB_RX] & 0xFFFF) << 16 |
@@ -264,7 +256,7 @@ ip6_hbh_ioam_trace_data_list_handler (vlib_buffer_t * b, ip6_header_t * ip,
elt++;
}
if (trace->ioam_trace_type & BIT_TIMESTAMP)
if (trace->trace_hdr.ioam_trace_type & BIT_TIMESTAMP)
{
/* Send least significant 32 bits */
f64 time_f64 =
@@ -276,7 +268,7 @@ ip6_hbh_ioam_trace_data_list_handler (vlib_buffer_t * b, ip6_header_t * ip,
elt++;
}
if (trace->ioam_trace_type & BIT_APPDATA)
if (trace->trace_hdr.ioam_trace_type & BIT_APPDATA)
{
/* $$$ set elt0->app_data */
*elt = clib_host_to_net_u32 (profile->app_data);
@@ -302,17 +294,19 @@ ip6_hbh_ioam_trace_data_list_trace_handler (u8 * s,
trace = (ioam_trace_option_t *) opt;
s =
format (s, " Trace Type 0x%x , %d elts left\n", trace->ioam_trace_type,
trace->data_list_elts_left);
format (s, " Trace Type 0x%x , %d elts left\n",
trace->trace_hdr.ioam_trace_type,
trace->trace_hdr.data_list_elts_left);
trace_data_size_in_words =
fetch_trace_data_size (trace->ioam_trace_type) / 4;
elt = &trace->elts[0];
while ((u8 *) elt < ((u8 *) (&trace->elts[0]) + trace->hdr.length - 2
/* -2 accounts for ioam_trace_type,elts_left */ ))
fetch_trace_data_size (trace->trace_hdr.ioam_trace_type) / 4;
elt = &trace->trace_hdr.elts[0];
while ((u8 *) elt <
((u8 *) (&trace->trace_hdr.elts[0]) + trace->hdr.length - 2
/* -2 accounts for ioam_trace_type,elts_left */ ))
{
s = format (s, " [%d] %U\n", elt_index,
format_ioam_data_list_element,
elt, &trace->ioam_trace_type);
elt, &trace->trace_hdr.ioam_trace_type);
elt_index++;
elt += trace_data_size_in_words;
}
+38
View File
@@ -0,0 +1,38 @@
/*
* Copyright (c) 2017 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_ENCAP_IP6_IOAM_TRACE_H_
#define PLUGINS_IOAM_PLUGIN_IOAM_ENCAP_IP6_IOAM_TRACE_H_
#include <vnet/ip/ip6_hop_by_hop_packet.h>
#include <ioam/lib-trace/trace_util.h>
/* *INDENT-OFF* */
typedef CLIB_PACKED(struct {
ip6_hop_by_hop_option_t hdr;
ioam_trace_hdr_t trace_hdr;
}) ioam_trace_option_t;
/* *INDENT-ON* */
#endif /* PLUGINS_IOAM_PLUGIN_IOAM_ENCAP_IP6_IOAM_TRACE_H_ */
/*
* fd.io coding-style-patch-verification: ON
*
* Local Variables:
* eval: (c-set-style "gnu")
* End:
*/
+39 -17
View File
@@ -20,6 +20,7 @@
#include <vnet/ip/ip_packet.h>
#include <vnet/ip/ip4_packet.h>
#include <vnet/ip/ip6_packet.h>
#include <vnet/ip/ip6_hop_by_hop.h>
#include <vnet/ip/udp.h>
#include <vnet/flow/ipfix_packet.h>
@@ -43,6 +44,7 @@ typedef struct
{
/* API message ID base */
u16 msg_id_base;
u16 set_id;
/* TODO: to support multiple collectors all this has to be grouped and create a vector here */
u8 *record_header;
@@ -67,14 +69,15 @@ typedef struct
/* convenience */
vlib_main_t *vlib_main;
vnet_main_t *vnet_main;
u32 ip4_lookup_node_index;
ethernet_main_t *ethernet_main;
u32 next_node_index;
uword my_hbh_slot;
u32 export_process_node_index;
} ioam_export_main_t;
ioam_export_main_t ioam_export_main;
ioam_export_main_t vxlan_gpe_ioam_export_main;
extern ioam_export_main_t ioam_export_main;
extern ioam_export_main_t vxlan_gpe_ioam_export_main;
extern vlib_node_registration_t export_node;
extern vlib_node_registration_t vxlan_export_node;
@@ -86,6 +89,24 @@ extern vlib_node_registration_t vxlan_export_node;
*/
#define DEFAULT_EXPORT_RECORDS 7
inline static void
ioam_export_set_next_node (ioam_export_main_t * em, u8 * next_node_name)
{
vlib_node_t *next_node;
next_node = vlib_get_node_by_name (em->vlib_main, next_node_name);
em->next_node_index = next_node->index;
}
inline static void
ioam_export_reset_next_node (ioam_export_main_t * em)
{
vlib_node_t *next_node;
next_node = vlib_get_node_by_name (em->vlib_main, (u8 *) "ip4-lookup");
em->next_node_index = next_node->index;
}
always_inline ioam_export_buffer_t *
ioam_export_get_my_buffer (ioam_export_main_t * em, u32 thread_id)
{
@@ -154,15 +175,13 @@ ioam_export_thread_buffer_init (ioam_export_main_t * em, vlib_main_t * vm)
int no_of_threads = vec_len (vlib_worker_threads);
int i;
ioam_export_buffer_t *eb = 0;
vlib_node_t *ip4_lookup_node;
pool_alloc_aligned (em->buffer_pool,
no_of_threads - 1, CLIB_CACHE_LINE_BYTES);
vec_validate_aligned (em->buffer_per_thread,
no_of_threads - 1, CLIB_CACHE_LINE_BYTES);
vec_validate_aligned (em->lockp, no_of_threads - 1, CLIB_CACHE_LINE_BYTES);
ip4_lookup_node = vlib_get_node_by_name (vm, (u8 *) "ip4-lookup");
em->ip4_lookup_node_index = ip4_lookup_node->index;
if (!em->buffer_per_thread || !em->buffer_pool || !em->lockp)
{
return (-1);
@@ -186,6 +205,7 @@ ioam_export_thread_buffer_init (ioam_export_main_t * em, vlib_main_t * vm)
}
#define IPFIX_IOAM_EXPORT_ID 272
#define IPFIX_VXLAN_IOAM_EXPORT_ID 273
/* Used to build the rewrite */
/* data set packet */
@@ -241,8 +261,8 @@ ioam_export_header_create (ioam_export_main_t * em,
ip->protocol = IP_PROTOCOL_UDP;
ip->src_address.as_u32 = src_address->as_u32;
ip->dst_address.as_u32 = collector_address->as_u32;
udp->src_port = clib_host_to_net_u16 (4939 /* $$FIXME */ );
udp->dst_port = clib_host_to_net_u16 (4939);
udp->src_port = clib_host_to_net_u16 (UDP_DST_PORT_ipfix);
udp->dst_port = clib_host_to_net_u16 (UDP_DST_PORT_ipfix);
/* FIXUP: UDP length */
udp->length = clib_host_to_net_u16 (vec_len (rewrite) +
(DEFAULT_EXPORT_RECORDS *
@@ -253,7 +273,7 @@ ioam_export_header_create (ioam_export_main_t * em,
h->domain_id = clib_host_to_net_u32 (em->domain_id);
/*FIXUP: Setid length in octets if records exported are not default */
s->set_id_length = ipfix_set_id_length (IPFIX_IOAM_EXPORT_ID,
s->set_id_length = ipfix_set_id_length (em->set_id,
(sizeof (*s) +
(DEFAULT_EXPORT_RECORDS *
DEFAULT_EXPORT_SIZE)));
@@ -309,11 +329,10 @@ ioam_export_send_buffer (ioam_export_main_t * em, vlib_main_t * vm,
/* FIXUP: lengths if different from default */
if (PREDICT_FALSE (eb->records_in_this_buffer != DEFAULT_EXPORT_RECORDS))
{
s->set_id_length =
ipfix_set_id_length (IPFIX_IOAM_EXPORT_ID /* set_id */ ,
b0->current_length - (sizeof (*ip) +
sizeof (*udp) +
sizeof (*h)));
s->set_id_length = ipfix_set_id_length (em->set_id /* set_id */ ,
b0->current_length -
(sizeof (*ip) + sizeof (*udp) +
sizeof (*h)));
h->version_length =
version_length (b0->current_length - (sizeof (*ip) + sizeof (*udp)));
sum0 = ip->checksum;
@@ -328,12 +347,12 @@ ioam_export_send_buffer (ioam_export_main_t * em, vlib_main_t * vm,
/* Enqueue pkts to ip4-lookup */
nf = vlib_get_frame_to_node (vm, em->ip4_lookup_node_index);
nf = vlib_get_frame_to_node (vm, em->next_node_index);
nf->n_vectors = 0;
to_next = vlib_frame_vector_args (nf);
nf->n_vectors = 1;
to_next[0] = eb->buffer_index;
vlib_put_frame_to_node (vm, em->ip4_lookup_node_index, nf);
vlib_put_frame_to_node (vm, em->next_node_index, nf);
return (1);
}
@@ -452,7 +471,7 @@ ioam_export_process_common (ioam_export_main_t * em, vlib_main_t * vm,
return 0; /* not so much */
}
#define ioam_export_node_common(EM, VM, N, F, HTYPE, L, V, NEXT) \
#define ioam_export_node_common(EM, VM, N, F, HTYPE, L, V, NEXT, FIXUP_FUNC) \
do { \
u32 n_left_from, *from, *to_next; \
export_next_t next_index; \
@@ -510,6 +529,7 @@ do { \
ip_len1 = \
ip_len1 > DEFAULT_EXPORT_SIZE ? DEFAULT_EXPORT_SIZE : ip_len1; \
copy3cachelines (eb0->data + eb0->current_length, ip0, ip_len0); \
FIXUP_FUNC(eb0, p0); \
eb0->current_length += DEFAULT_EXPORT_SIZE; \
my_buf->records_in_this_buffer++; \
if (my_buf->records_in_this_buffer >= DEFAULT_EXPORT_RECORDS) \
@@ -522,6 +542,7 @@ do { \
if (PREDICT_FALSE (eb0 == 0)) \
goto NO_BUFFER1; \
copy3cachelines (eb0->data + eb0->current_length, ip1, ip_len1); \
FIXUP_FUNC(eb0, p1); \
eb0->current_length += DEFAULT_EXPORT_SIZE; \
my_buf->records_in_this_buffer++; \
if (my_buf->records_in_this_buffer >= DEFAULT_EXPORT_RECORDS) \
@@ -578,6 +599,7 @@ do { \
ip_len0 = \
ip_len0 > DEFAULT_EXPORT_SIZE ? DEFAULT_EXPORT_SIZE : ip_len0; \
copy3cachelines (eb0->data + eb0->current_length, ip0, ip_len0); \
FIXUP_FUNC(eb0, p0); \
eb0->current_length += DEFAULT_EXPORT_SIZE; \
my_buf->records_in_this_buffer++; \
if (my_buf->records_in_this_buffer >= DEFAULT_EXPORT_RECORDS) \
@@ -83,6 +83,8 @@ do { \
#define foreach_vxlan_gpe_ioam_export_plugin_api_msg \
_(VXLAN_GPE_IOAM_EXPORT_ENABLE_DISABLE, vxlan_gpe_ioam_export_enable_disable)
ioam_export_main_t vxlan_gpe_ioam_export_main;
extern void vxlan_gpe_set_next_override (uword next);
/* Action function shared between message handler and debug CLI */
int
@@ -242,6 +244,8 @@ vxlan_gpe_ioam_export_init (vlib_main_t * vm)
clib_error_t *error = 0;
u8 *name;
em->set_id = IPFIX_VXLAN_IOAM_EXPORT_ID;
name = format (0, "vxlan_gpe_ioam_export_%08x%c", api_version, 0);
/* Ask for a correctly-sized block of API message decode slots */
@@ -254,6 +258,7 @@ vxlan_gpe_ioam_export_init (vlib_main_t * vm)
em->my_hbh_slot = ~0;
em->vlib_main = vm;
em->vnet_main = vnet_get_main ();
ioam_export_reset_next_node (em);
vec_free (name);
return error;
@@ -17,9 +17,9 @@
#include <vnet/pg/pg.h>
#include <vppinfra/error.h>
#include <vnet/ip/ip.h>
#include <ioam/export-common/ioam_export.h>
#include <vnet/vxlan-gpe/vxlan_gpe.h>
#include <vnet/vxlan-gpe/vxlan_gpe_packet.h>
#include <ioam/export-common/ioam_export.h>
typedef struct
{
@@ -121,6 +121,12 @@ copy3cachelines (void *dst, const void *src, size_t n)
#endif
}
static void
vxlan_gpe_export_fixup_func (vlib_buffer_t * export_buf,
vlib_buffer_t * pak_buf)
{
/* Todo: on implementing VXLAN GPE analyse */
}
static uword
vxlan_gpe_export_node_fn (vlib_main_t * vm,
@@ -129,7 +135,8 @@ vxlan_gpe_export_node_fn (vlib_main_t * vm,
ioam_export_main_t *em = &vxlan_gpe_ioam_export_main;
ioam_export_node_common (em, vm, node, frame, ip4_header_t, length,
ip_version_and_header_length,
EXPORT_NEXT_VXLAN_GPE_INPUT);
EXPORT_NEXT_VXLAN_GPE_INPUT,
vxlan_gpe_export_fixup_func);
return frame->n_vectors;
}
+6
View File
@@ -81,6 +81,10 @@ do { \
#define foreach_ioam_export_plugin_api_msg \
_(IOAM_EXPORT_IP6_ENABLE_DISABLE, ioam_export_ip6_enable_disable)
ioam_export_main_t ioam_export_main;
vlib_node_registration_t export_node;
/* Action function shared between message handler and debug CLI */
int
@@ -232,6 +236,8 @@ ioam_export_init (vlib_main_t * vm)
em->vlib_main = vm;
em->vnet_main = vnet_get_main ();
em->set_id = IPFIX_IOAM_EXPORT_ID;
ioam_export_reset_next_node (em);
name = format (0, "ioam_export_%08x%c", api_version, 0);
+17 -1
View File
@@ -17,8 +17,10 @@
#include <vnet/pg/pg.h>
#include <vppinfra/error.h>
#include <vnet/ip/ip.h>
#include <vnet/ip/ip6_hop_by_hop.h>
#include <ioam/export-common/ioam_export.h>
typedef struct
{
u32 next_index;
@@ -119,6 +121,20 @@ copy3cachelines (void *dst, const void *src, size_t n)
#endif
}
static void
ip6_export_fixup_func (vlib_buffer_t * export_buf, vlib_buffer_t * pak_buf)
{
ip6_header_t *ip6_temp =
(ip6_header_t *) (export_buf->data + export_buf->current_length);
u32 flow_label_temp =
clib_net_to_host_u32(ip6_temp->ip_version_traffic_class_and_flow_label)
& 0xFFF00000;
flow_label_temp |=
IOAM_MASK_DECAP_BIT((vnet_buffer(pak_buf)->l2_classify.opaque_index));
ip6_temp->ip_version_traffic_class_and_flow_label =
clib_host_to_net_u32(flow_label_temp);
}
static uword
ip6_export_node_fn (vlib_main_t * vm,
vlib_node_runtime_t * node, vlib_frame_t * frame)
@@ -126,7 +142,7 @@ ip6_export_node_fn (vlib_main_t * vm,
ioam_export_main_t *em = &ioam_export_main;
ioam_export_node_common(em, vm, node, frame, ip6_header_t, payload_length,
ip_version_traffic_class_and_flow_label,
EXPORT_NEXT_POP_HBYH);
EXPORT_NEXT_POP_HBYH, ip6_export_fixup_func);
return frame->n_vectors;
}
@@ -0,0 +1,105 @@
/*
* Copyright (c) 2017 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/ip/ip.h>
#include <vnet/plugin/plugin.h>
#include <vnet/ip/udp.h>
#include <ioam/ipfixcollector/ipfixcollector.h>
ipfix_collector_main_t ipfix_collector_main;
/**
* @brief IP-FIX SetID registration function.
*
* This function can be used by other VPP graph nodes to receive IP-FIX packets
* with a particular setid.
*
* @param vlib_main_t Vlib main of the graph node which is interseted in
* getting IP-Fix packet.
* @param ipfix_client_add_del_t Structure describing the client node which
* is interested in getting the IP-Fix packets for
* a SetID.
*
* @returns 0 on success.
* @returns Error codes(<0) otherwise.
*/
int
ipfix_collector_reg_setid (vlib_main_t * vm, ipfix_client_add_del_t * info)
{
ipfix_collector_main_t *cm = &ipfix_collector_main;
uword *p = NULL;
int i;
ipfix_client *client = 0;
if ((!info) || (!info->client_name))
return IPFIX_COLLECTOR_ERR_INVALID_PARAM;
p = hash_get (cm->client_reg_table, info->ipfix_setid);
client = p ? pool_elt_at_index (cm->client_reg_pool, (*p)) : NULL;
if (info->del)
{
if (!client)
return 0; //There is no registered handler, so send success
hash_unset (cm->client_reg_table, info->ipfix_setid);
vec_free (client->client_name);
pool_put (cm->client_reg_pool, client);
return 0;
}
if (client)
return IPFIX_COLLECTOR_ERR_REG_EXISTS;
pool_get (cm->client_reg_pool, client);
i = client - cm->client_reg_pool;
client->client_name = vec_dup (info->client_name);
client->client_node = info->client_node;
client->client_next_node = vlib_node_add_next (vm,
ipfix_collector_node.index,
client->client_node);
client->set_id = info->ipfix_setid;
hash_set (cm->client_reg_table, info->ipfix_setid, i);
return 0;
}
static clib_error_t *
ipfix_collector_init (vlib_main_t * vm)
{
clib_error_t *error = 0;
ipfix_collector_main_t *cm = &ipfix_collector_main;
cm->vlib_main = vm;
cm->vnet_main = vnet_get_main ();
cm->client_reg_pool = NULL;
cm->client_reg_table = hash_create (0, sizeof (uword));
udp_register_dst_port (vm,
UDP_DST_PORT_ipfix,
ipfix_collector_node.index, 1 /* is_ip4 */ );
return error;
}
VLIB_INIT_FUNCTION (ipfix_collector_init);
/*
* fd.io coding-style-patch-verification: ON
*
* Local Variables:
* eval: (c-set-style "gnu")
* End:
*/
@@ -0,0 +1,124 @@
/*
* Copyright (c) 2017 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_IPFIXCOLLECTOR_PLUGIN_IPFIXCOLLECTOR_IPFIXCOLLECTOR_H_
#define PLUGINS_IPFIXCOLLECTOR_PLUGIN_IPFIXCOLLECTOR_IPFIXCOLLECTOR_H_
#include <vppinfra/pool.h>
#include <vppinfra/hash.h>
#include <vppinfra/error.h>
#define IPFIX_COLLECTOR_CLIENT_NAME_MAX 64
#define IPFIX_COLLECTOR_ERR_INVALID_PARAM -1
#define IPFIX_COLLECTOR_ERR_REG_EXISTS -2
/** @brief Structure other nodes to use for registering with IP-FIX collector.
*/
typedef struct
{
/** String containing name of the client interested in getting
ip-fix packets. */
u8 *client_name;
/** Node index where packets have to be redirected. */
u32 client_node;
/** Setid of IPFix for which client is intereseted in getting packets. */
u16 ipfix_setid;
/** Add(0) or del(1) operation. */
u16 del;
} ipfix_client_add_del_t;
/** @brief IP-FIX collector internal client structure to store SetID to
client node ID.
*/
typedef struct
{
/** String containing name of the client interested in getting
ip-fix packets. */
u8 *client_name;
/** Node index where packets have to be redirected. */
u32 client_node;
/** ipfix-collector next index where packets have to be redirected. */
u32 client_next_node;
/** Setid of IPFix for which client is intereseted in getting packets. */
u16 set_id;
} ipfix_client;
/** @brief IP-FIX collector main structure to SetID to client node ID mapping.
@note cache aligned.
*/
typedef struct
{
/** Hash table to map IP-FIX setid to a client registration pool. SetId is
key to hash map. */
uword *client_reg_table;
/** Pool of Client node information for the IP-FIX SetID. */
ipfix_client *client_reg_pool;
/** Pointer to VLib main for the node - ipfix-collector. */
vlib_main_t *vlib_main;
/** Pointer to vnet main for convenience. */
vnet_main_t *vnet_main;
} ipfix_collector_main_t;
extern vlib_node_registration_t ipfix_collector_node;
extern ipfix_collector_main_t ipfix_collector_main;
/**
* @brief IP-FIX SetID registration function.
*
* This function can be used by other VPP graph nodes to receive IP-FIX packets
* with a particular setid.
*
* @param vlib_main_t Vlib main of the graph node which is interseted in
* getting IP-Fix packet.
* @param ipfix_client_add_del_t Structure describing the client node which
* is interested in getting the IP-Fix packets for
* a SetID.
*
* @returns 0 on success.
* @returns Error codes(<0) otherwise.
*/
int
ipfix_collector_reg_setid (vlib_main_t * vm, ipfix_client_add_del_t * info);
always_inline ipfix_client *
ipfix_collector_get_client (u16 set_id)
{
ipfix_collector_main_t *cm = &ipfix_collector_main;
uword *p;
p = hash_get (cm->client_reg_table, set_id);
return (p ? pool_elt_at_index (cm->client_reg_pool, (*p)) : NULL);
}
#endif /* PLUGINS_IPFIXCOLLECTOR_PLUGIN_IPFIXCOLLECTOR_IPFIXCOLLECTOR_H_ */
/*
* fd.io coding-style-patch-verification: ON
*
* Local Variables:
* eval: (c-set-style "gnu")
* End:
*/
File diff suppressed because it is too large Load Diff
+37
View File
@@ -0,0 +1,37 @@
/*
* Copyright (c) 2017 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_E2E_UTIL_H_
#define PLUGINS_IOAM_PLUGIN_IOAM_LIB_E2E_E2E_UTIL_H_
#include <ioam/lib-e2e/ioam_seqno_lib.h>
/* *INDENT-OFF* */
typedef CLIB_PACKED(struct {
u8 e2e_type;
u8 reserved;
u32 e2e_data;
}) ioam_e2e_packet_t;
/* *INDENT-ON* */
#endif /* PLUGINS_IOAM_PLUGIN_IOAM_LIB_E2E_E2E_UTIL_H_ */
/*
* fd.io coding-style-patch-verification: ON
*
* Local Variables:
* eval: (c-set-style "gnu")
* End:
*/
+84
View File
@@ -0,0 +1,84 @@
/*
* Copyright (c) 2017 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 <vlib/vlib.h>
#include <vnet/vnet.h>
#include <ioam/lib-e2e/ioam_seqno_lib.h>
u8 *
show_ioam_seqno_cmd_fn (u8 * s, ioam_seqno_data * seqno_data, u8 enc)
{
seqno_rx_info *rx;
s = format (s, "SeqNo Data:\n");
if (enc)
{
s = format (s, " Current Seq. Number : %llu\n", seqno_data->seq_num);
}
else
{
rx = &seqno_data->seqno_rx;
s = show_ioam_seqno_analyse_data_fn (s, rx);
}
format (s, "\n");
return s;
}
u8 *
show_ioam_seqno_analyse_data_fn (u8 * s, seqno_rx_info * rx)
{
s = format (s, " Highest Seq. Number : %llu\n", rx->bitmap.highest);
s = format (s, " Packets received : %llu\n", rx->rx_packets);
s = format (s, " Lost packets : %llu\n", rx->lost_packets);
s = format (s, " Reordered packets : %llu\n", rx->reordered_packets);
s = format (s, " Duplicate packets : %llu\n", rx->dup_packets);
format (s, "\n");
return s;
}
void
ioam_seqno_init_data (ioam_seqno_data * data)
{
data->seq_num = 0;
ioam_seqno_init_rx_info (&data->seqno_rx);
return;
}
void
ioam_seqno_init_rx_info (seqno_rx_info * data)
{
seqno_bitmap *bitmap = &data->bitmap;
bitmap->window_size = SEQNO_WINDOW_SIZE;
bitmap->array_size = SEQNO_WINDOW_ARRAY_SIZE;
bitmap->mask = 32 * SEQNO_WINDOW_ARRAY_SIZE - 1;
bitmap->array[0] = 0x00000000; /* pretend we haven seen sequence numbers 0 */
bitmap->highest = 0;
data->dup_packets = 0;
data->lost_packets = 0;
data->reordered_packets = 0;
data->rx_packets = 0;
return;
}
/*
* fd.io coding-style-patch-verification: ON
*
* Local Variables:
* eval: (c-set-style "gnu")
* End:
*/
+201
View File
@@ -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:
*/
+8 -1
View File
@@ -89,7 +89,14 @@ int trace_profile_create (trace_profile * profile, u8 trace_type, u8 num_elts,
void clear_trace_profiles (void);
/* *INDENT-OFF* */
typedef CLIB_PACKED (struct
{
u8 ioam_trace_type;
u8 data_list_elts_left;
u32 elts[0]; /* Variable type. So keep it generic */
}) ioam_trace_hdr_t;
/* *INDENT-ON* */
#define BIT_TTL_NODEID (1<<0)
#define BIT_ING_INTERFACE (1<<1)
-3
View File
@@ -492,9 +492,6 @@ int ip6_hbh_register_option (u8 option,
int ip6_hbh_unregister_option (u8 option);
void ip6_hbh_set_next_override (uword next);
/* Flag used by IOAM code. Classifier sets it pop-hop-by-hop checks it */
#define OI_DECAP 0x80000000
#endif /* included_ip_ip6_h */
/*
+3
View File
@@ -49,6 +49,9 @@
#include <vppinfra/bihash_template.c>
/* Flag used by IOAM code. Classifier sets it pop-hop-by-hop checks it */
#define OI_DECAP 0x80000000
/**
* @file
* @brief IPv6 Forwarding.

Some files were not shown because too many files have changed in this diff Show More