aboutsummaryrefslogtreecommitdiffstats
path: root/GPL/traffic_profiles/trex/trex-sl-3n-ethip4-ip4dst10000-4cnf.py
diff options
context:
space:
mode:
authorpmikus <pmikus@cisco.com>2020-08-18 09:57:26 +0000
committerPeter Mikus <pmikus@cisco.com>2020-08-18 10:18:00 +0000
commit42d1016e92cf2b8ba4e493d878c475de325a447a (patch)
tree5359bc5fee023773c74d7a9e8e0148ba9202ea1a /GPL/traffic_profiles/trex/trex-sl-3n-ethip4-ip4dst10000-4cnf.py
parent5c43c46d08dbc9e73422e947420096d075b269cf (diff)
Framework: Qemu alignments
Signed-off-by: pmikus <pmikus@cisco.com> Change-Id: I20098fca8fb513accef3edc9a72bfd3c56bf9be2
Diffstat (limited to 'GPL/traffic_profiles/trex/trex-sl-3n-ethip4-ip4dst10000-4cnf.py')
0 files changed, 0 insertions, 0 deletions
#n357'>357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524
/*
 * 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_IOAM_ANALYSE_H_
#define PLUGINS_IOAM_PLUGIN_IOAM_ANALYSE_IOAM_ANALYSE_H_

#include <vlib/vlib.h>
#include <vnet/vnet.h>
#include <vppinfra/types.h>
#include <ioam/lib-e2e/e2e_util.h>
#include <ioam/lib-trace/trace_util.h>
#include <ioam/lib-trace/trace_config.h>
#include <vppinfra/lock.h>

#define IOAM_FLOW_TEMPLATE_ID    260
#define IOAM_TRACE_MAX_NODES      10
#define IOAM_MAX_PATHS_PER_FLOW   10

typedef struct
{
  u16 ingress_if;
  u16 egress_if;
  u32 node_id;
  u32 state_up;
} ioam_path_map_t;

/** @brief Analysed iOAM trace data.
    @note cache aligned.
*/
typedef struct
{
  /** No of nodes in path. */
  u8 num_nodes;

  /** Data contained in trace - NodeId, TTL, Ingress & Egress Link, Timestamp. */
  u8 trace_type;

  /** Flag to indicate whether node is allocated. */
  u8 is_free;

  u8 pad[5];

  /** Actual PATH flow has taken. */
  ioam_path_map_t path[IOAM_TRACE_MAX_NODES];

  /** Num of pkts in the flow going over path. */
  u32 pkt_counter;

  /** Num of bytes in the flow going over path. */
  u32 bytes_counter;

  /** Minumum Dealay for the flow. */
  u32 min_delay;

  /** Maximum Dealay for the flow. */
  u32 max_delay;

  /** Average Dealay for the flow. */
  u32 mean_delay;

  u32 reserve;
} ioam_analyse_trace_record;

typedef struct
{
  ioam_analyse_trace_record path_data[IOAM_MAX_PATHS_PER_FLOW];
} ioam_analyse_trace_data;

/** @brief Analysed iOAM pot data.
    @note cache aligned.
*/
typedef struct
{
  /** Number of packets validated (passes through the service chain)
      within the timestamps. */
  u32 sfc_validated_count;

  /** Number of packets invalidated (failed through the service chain)
      within the timestamps. */
  u32 sfc_invalidated_count;
} ioam_analyse_pot_data;

/** @brief Analysed iOAM data.
    @note cache aligned.
*/
typedef struct ioam_analyser_data_t_
{
  CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);

  u8 is_free;
  u8 pad[3];

  /** Num of pkts sent for this flow. */
  u32 pkt_sent;

  /** Num of pkts matching this flow. */
  u32 pkt_counter;

  /** Num of bytes matching this flow. */
  u32 bytes_counter;

  /** Analysed iOAM trace data. */
  ioam_analyse_trace_data trace_data;

  /** Analysed iOAM pot data. */
  ioam_analyse_pot_data pot_data;

  /** Analysed iOAM seqno data. */
  seqno_rx_info seqno_data;

  /** Cache of previously analysed data, useful for export. */
  struct ioam_analyser_data_t_ *chached_data_list;

  /** Lock to since we use this to export the data in other thread. */
  clib_spinlock_t writer_lock;
} ioam_analyser_data_t;

always_inline f64
ip6_ioam_analyse_calc_delay (ioam_trace_hdr_t * trace, u16 trace_len,
			     u8 oneway)
{
  u16 size_of_all_traceopts;
  u8 size_of_traceopt_per_node;
  u8 num_nodes;
  u32 *start_elt, *end_elt, *uturn_elt;;
  u32 start_time, end_time;
  u8 done = 0;

  size_of_traceopt_per_node = fetch_trace_data_size (trace->ioam_trace_type);
  // Unknown trace type
  if (size_of_traceopt_per_node == 0)
    return 0;
  size_of_all_traceopts = trace_len;	/*ioam_trace_type,data_list_elts_left */

  num_nodes = (u8) (size_of_all_traceopts / size_of_traceopt_per_node);
  if ((num_nodes == 0) || (num_nodes <= trace->data_list_elts_left))
    return 0;

  num_nodes -= trace->data_list_elts_left;

  start_elt = trace->elts;
  end_elt =
    trace->elts +
    (u32) ((size_of_traceopt_per_node / sizeof (u32)) * (num_nodes - 1));

  if (oneway && (trace->ioam_trace_type & BIT_TTL_NODEID))
    {
      done = 0;
      do
	{
	  uturn_elt = start_elt - size_of_traceopt_per_node / sizeof (u32);

	  if ((clib_net_to_host_u32 (*start_elt) >> 24) <=
	      (clib_net_to_host_u32 (*uturn_elt) >> 24))
	    done = 1;
	}
      while (!done && (start_elt = uturn_elt) != end_elt);
    }
  if (trace->ioam_trace_type & BIT_TTL_NODEID)
    {
      start_elt++;
      end_elt++;
    }
  if (trace->ioam_trace_type & BIT_ING_INTERFACE)
    {
      start_elt++;
      end_elt++;
    }
  start_time = clib_net_to_host_u32 (*start_elt);
  end_time = clib_net_to_host_u32 (*end_elt);

  return (f64) (end_time - start_time);
}

always_inline void
ip6_ioam_analyse_set_paths_down (ioam_analyser_data_t * data)
{
  ioam_analyse_trace_data *trace_data;
  ioam_analyse_trace_record *trace_record;
  ioam_path_map_t *path;
  u8 k, i;

  clib_spinlock_lock (&data->writer_lock);

  trace_data = &data->trace_data;

  for (i = 0; i < IOAM_MAX_PATHS_PER_FLOW; i++)
    {
      trace_record = trace_data->path_data + i;

      if (trace_record->is_free)
	continue;

      path = trace_record->path;

      for (k = 0; k < trace_record->num_nodes; k++)
	path[k].state_up = 0;
    }
  clib_spinlock_unlock (&data->writer_lock);
}

always_inline void
ip6_ioam_analyse_hbh_trace_loopback (ioam_analyser_data_t * data,
				     ioam_trace_hdr_t * trace, u16 trace_len)
{
  ioam_analyse_trace_data *trace_data;
  ioam_analyse_trace_record *trace_record;
  ioam_path_map_t *path;
  u8 i, j, k, num_nodes, max_nodes;
  u8 *ptr;
  u32 nodeid;
  u16 ingress_if, egress_if;
  u16 size_of_traceopt_per_node;
  u16 size_of_all_traceopts;

  clib_spinlock_lock (&data->writer_lock);

  trace_data = &data->trace_data;

  size_of_traceopt_per_node = fetch_trace_data_size (trace->ioam_trace_type);
  if (0 == size_of_traceopt_per_node)
    goto end;

  size_of_all_traceopts = trace_len;

  ptr = (u8 *) trace->elts;
  max_nodes = (u8) (size_of_all_traceopts / size_of_traceopt_per_node);
  num_nodes = max_nodes - trace->data_list_elts_left;

  for (i = 0; i < IOAM_MAX_PATHS_PER_FLOW; i++)
    {
      trace_record = trace_data->path_data + i;
      path = trace_record->path;

      if (trace_record->is_free)
	continue;

      for (j = max_nodes, k = 0; k < num_nodes; j--, k++)
	{
	  ptr =
	    (u8 *) ((u8 *) trace->elts +
		    (size_of_traceopt_per_node * (j - 1)));

	  nodeid = clib_net_to_host_u32 (*((u32 *) ptr)) & 0x00ffffff;
	  ptr += 4;

	  if (nodeid != path[k].node_id)
	    goto end;

	  if ((trace->ioam_trace_type == TRACE_TYPE_IF_TS_APP) ||
	      (trace->ioam_trace_type == TRACE_TYPE_IF))
	    {
	      ingress_if = clib_net_to_host_u16 (*((u16 *) ptr));
	      ptr += 2;
	      egress_if = clib_net_to_host_u16 (*((u16 *) ptr));
	      if ((ingress_if != path[k].ingress_if) ||
		  (egress_if != path[k].egress_if))
		{
		  goto end;
		}
	    }
	  /* Found Match - set path hop state to up */
	  path[k].state_up = 1;
	}
    }
end:
  clib_spinlock_unlock (&data->writer_lock);
}

always_inline int
ip6_ioam_analyse_hbh_trace (ioam_analyser_data_t * data,
			    ioam_trace_hdr_t * trace, u16 pak_len,
			    u16 trace_len)
{
  ioam_analyse_trace_data *trace_data;
  u16 size_of_traceopt_per_node;
  u16 size_of_all_traceopts;
  u8 i, j, k, num_nodes, max_nodes;
  u8 *ptr;
  u32 nodeid;
  u16 ingress_if, egress_if;
  ioam_path_map_t *path = NULL;
  ioam_analyse_trace_record *trace_record;

  clib_spinlock_lock (&data->writer_lock);

  trace_data = &data->trace_data;

  size_of_traceopt_per_node = fetch_trace_data_size (trace->ioam_trace_type);
  // Unknown trace type
  if (size_of_traceopt_per_node == 0)
    goto DONE;
  size_of_all_traceopts = trace_len;

  ptr = (u8 *) trace->elts;
  max_nodes = (u8) (size_of_all_traceopts / size_of_traceopt_per_node);
  num_nodes = max_nodes - trace->data_list_elts_left;

  for (i = 0; i < IOAM_MAX_PATHS_PER_FLOW; i++)
    {
      trace_record = trace_data->path_data + i;

      if (trace_record->is_free ||
	  (num_nodes != trace_record->num_nodes) ||
	  (trace->ioam_trace_type != trace_record->trace_type))
	continue;

      path = trace_record->path;

      for (j = max_nodes, k = 0; k < num_nodes; j--, k++)
	{
	  ptr =
	    (u8 *) ((u8 *) trace->elts +
		    (size_of_traceopt_per_node * (j - 1)));

	  nodeid = clib_net_to_host_u32 (*((u32 *) ptr)) & 0x00ffffff;
	  ptr += 4;

	  if (nodeid != path[k].node_id)
	    break;

	  if ((trace->ioam_trace_type == TRACE_TYPE_IF_TS_APP) ||
	      (trace->ioam_trace_type == TRACE_TYPE_IF))
	    {
	      ingress_if = clib_net_to_host_u16 (*((u16 *) ptr));
	      ptr += 2;
	      egress_if = clib_net_to_host_u16 (*((u16 *) ptr));
	      if ((ingress_if != path[k].ingress_if) ||
		  (egress_if != path[k].egress_if))
		{
		  break;
		}
	    }
	}

      if (k == num_nodes)
	{
	  goto found_match;
	}
    }

  for (i = 0; i < IOAM_MAX_PATHS_PER_FLOW; i++)
    {
      trace_record = trace_data->path_data + i;
      if (trace_record->is_free)
	{
	  trace_record->is_free = 0;
	  trace_record->num_nodes = num_nodes;
	  trace_record->trace_type = trace->ioam_trace_type;
	  path = trace_data->path_data[i].path;
	  trace_record->pkt_counter = 0;
	  trace_record->bytes_counter = 0;
	  trace_record->min_delay = 0xFFFFFFFF;
	  trace_record->max_delay = 0;
	  trace_record->mean_delay = 0;
	  break;
	}
    }

  for (j = max_nodes, k = 0; k < num_nodes; j--, k++)
    {
      ptr =
	(u8 *) ((u8 *) trace->elts + (size_of_traceopt_per_node * (j - 1)));

      path[k].node_id = clib_net_to_host_u32 (*((u32 *) ptr)) & 0x00ffffff;
      ptr += 4;

      if ((trace->ioam_trace_type == TRACE_TYPE_IF_TS_APP) ||
	  (trace->ioam_trace_type == TRACE_TYPE_IF))
	{
	  path[k].ingress_if = clib_net_to_host_u16 (*((u16 *) ptr));
	  ptr += 2;
	  path[k].egress_if = clib_net_to_host_u16 (*((u16 *) ptr));
	}
    }

found_match:
  /* Set path state to UP */
  for (k = 0; k < num_nodes; k++)
    path[k].state_up = 1;

  trace_record->pkt_counter++;
  trace_record->bytes_counter += pak_len;
  if (trace->ioam_trace_type & BIT_TIMESTAMP)
    {
      /* Calculate time delay */
      u32 delay = (u32) ip6_ioam_analyse_calc_delay (trace, trace_len, 0);
      if (delay < trace_record->min_delay)
	trace_record->min_delay = delay;
      else if (delay > trace_record->max_delay)
	trace_record->max_delay = delay;

      u64 sum = (trace_record->mean_delay * data->seqno_data.rx_packets);
      trace_record->mean_delay =
	(u32) ((sum + delay) / (data->seqno_data.rx_packets + 1));
    }
DONE:
  clib_spinlock_unlock (&data->writer_lock);
  return 0;
}

always_inline int
ip6_ioam_analyse_hbh_e2e (ioam_analyser_data_t * data,
			  ioam_e2e_packet_t * e2e, u16 len)
{
  clib_spinlock_lock (&data->writer_lock);

  ioam_analyze_seqno (&data->seqno_data,
		      (u64) clib_net_to_host_u32 (e2e->e2e_data));

  clib_spinlock_unlock (&data->writer_lock);

  return 0;
}

always_inline u8 *
format_path_map (u8 * s, va_list * args)
{
  ioam_path_map_t *pm = va_arg (*args, ioam_path_map_t *);
  u32 num_of_elts = va_arg (*args, u32);
  u32 i;

  for (i = 0; i < num_of_elts; i++)
    {
      s =
	format (s,
		"node_id: 0x%x, ingress_if: 0x%x, egress_if:0x%x, state:%s\n",
		pm->node_id, pm->ingress_if, pm->egress_if,
		pm->state_up ? "UP" : "DOWN");
      pm++;
    }

  return (s);
}

always_inline u8 *
print_analyse_flow (u8 * s, ioam_analyser_data_t * record)
{
  int j;
  ioam_analyse_trace_record *trace_record;

  s = format (s, "pkt_sent : %u\n", record->pkt_sent);
  s = format (s, "pkt_counter : %u\n", record->pkt_counter);
  s = format (s, "bytes_counter : %u\n", record->bytes_counter);

  s = format (s, "Trace data: \n");

  for (j = 0; j < IOAM_MAX_PATHS_PER_FLOW; j++)
    {
      trace_record = record->trace_data.path_data + j;
      if (trace_record->is_free)
	continue;

      s = format (s, "path_map:\n%U", format_path_map,
		  trace_record->path, trace_record->num_nodes);
      s = format (s, "pkt_counter: %u\n", trace_record->pkt_counter);
      s = format (s, "bytes_counter: %u\n", trace_record->bytes_counter);

      s = format (s, "min_delay: %u\n", trace_record->min_delay);
      s = format (s, "max_delay: %u\n", trace_record->max_delay);
      s = format (s, "mean_delay: %u\n", trace_record->mean_delay);
    }

  s = format (s, "\nPOT data: \n");
  s = format (s, "sfc_validated_count : %u\n",
	      record->pot_data.sfc_validated_count);
  s = format (s, "sfc_invalidated_count : %u\n",
	      record->pot_data.sfc_invalidated_count);

  s = format (s, "\nSeqno Data:\n");
  s = format (s,
	      "RX Packets        : %lu\n"
	      "Lost Packets      : %lu\n"
	      "Duplicate Packets : %lu\n"
	      "Reordered Packets : %lu\n",
	      record->seqno_data.rx_packets,
	      record->seqno_data.lost_packets,
	      record->seqno_data.dup_packets,
	      record->seqno_data.reordered_packets);

  s = format (s, "\n");
  return s;
}

always_inline void
ioam_analyse_init_data (ioam_analyser_data_t * data)
{
  u16 j;
  ioam_analyse_trace_data *trace_data;

  data->is_free = 1;

  /* We maintain data corresponding to last IP-Fix export, this may
   * get extended in future to maintain history of data */
  vec_validate_aligned (data->chached_data_list, 0, CLIB_CACHE_LINE_BYTES);

  clib_spinlock_init (&data->writer_lock);

  trace_data = &(data->trace_data);
  for (j = 0; j < IOAM_MAX_PATHS_PER_FLOW; j++)
    trace_data->path_data[j].is_free = 1;
}

#endif /* PLUGINS_IOAM_PLUGIN_IOAM_ANALYSE_IOAM_ANALYSE_H_ */

/*
 * fd.io coding-style-patch-verification: ON
 *
 * Local Variables:
 * eval: (c-set-style "gnu")
 * End:
 */