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:
committed by
Neale Ranns
parent
fed79e8391
commit
fdd81af6af
+30
-6
@@ -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
@@ -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
@@ -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));
|
||||
}
|
||||
|
||||
|
||||
@@ -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__ */
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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:
|
||||
*/
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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:
|
||||
*/
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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,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
@@ -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:
|
||||
*/
|
||||
@@ -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:
|
||||
*/
|
||||
@@ -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:
|
||||
*/
|
||||
@@ -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)
|
||||
|
||||
@@ -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 */
|
||||
|
||||
/*
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user