summaryrefslogtreecommitdiffstats
path: root/build-root/deb
AgeCommit message (Expand)AuthorFilesLines
2017-03-27Python API: Fixup of debian package after cFFI changes.Ole Troan4-15/+8
2017-02-24Fixed QAT device binding and device unbinding when vpp package is removedRadu Nicolau1-1/+1
2017-02-04dpdk: move to uio_pci_genericDamjan Marion2-4/+4
2017-01-20Add dpdk development packagingDamjan Marion3-23/+2
2017-01-04rename vpp python's api debian scriptsGabriel Ganne2-0/+0
2017-01-03deb: fix issues in debian/control, silence some warningsDamjan Marion2-7/+12
2017-01-03vpp-python-api deb packaging - use easy_install to install the python apiroot2-0/+13
2017-01-01Move java,lua api and remaining plugins to src/Damjan Marion2-2/+18
2016-12-20Remove RPATH from binaries before creating .deb and .rpm packagesDamjan Marion2-1/+2
2016-11-17remove reference to Intel with dpdk docsPadraig Connolly1-1/+1
2016-10-29Initial deb packaging of vpp-python-apiEd Warnicke3-1/+9
2016-10-11Rebind kernel drivers on VPP uninstallPeter Ginchev1-0/+21
2016-10-10platform: rewrote vppctl script to include historyPadraig1-1/+1
2016-09-10VPP-367: Peg vpp and vpp-plugins to depend on specific versionsEd Warnicke1-2/+2
2016-07-13Add plugins debian packagingDamjan Marion1-0/+7
2016-06-09VPP-127 Removed spurious use of sudoEd Warnicke1-1/+1
2016-06-08VPP-127: Make rpm/deb provide vpp group to access vpp-apiEd Warnicke1-0/+4
2016-05-04VPP-12: only remove vpp-related files from /dev/shmDave Barach2-4/+4
2016-04-20ubuntu 16.04 build support. Supporting systemd with vpp.service files.Srivatsa Sangli3-2/+16
2016-02-01Add a vpp-dpdk-dev package, enable plugins to use dpdk APIs directlyDave Barach2-8/+9
2016-01-20Rename vpe binary name to avoid collision with latexDamjan Marion3-6/+6
2015-12-16Add missing entries to .gitignoreEd Warnicke1-0/+2
2015-12-08Initial commit of vpp code.v1.0.0Ed Warnicke10-0/+243
#n456'>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
/*
 * ct6.c - skeleton vpp engine plug-in
 *
 * Copyright (c) <current-year> <your-organization>
 * 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 <vnet/plugin/plugin.h>
#include <ct6/ct6.h>

#include <vlibapi/api.h>
#include <vlibmemory/api.h>
#include <vpp/app/version.h>

/* define message IDs */
#include <ct6/ct6.api_enum.h>
#include <ct6/ct6.api_types.h>

#define REPLY_MSG_ID_BASE cmp->msg_id_base
#include <vlibapi/api_helper_macros.h>

ct6_main_t ct6_main;

/* Action function shared between message handler and debug CLI */

static void
ct6_feature_init (ct6_main_t * cmp)
{
  u32 nworkers = vlib_num_workers ();

  if (cmp->feature_initialized)
    return;

  clib_bihash_init_48_8 (&cmp->session_hash, "ct6 session table",
			 cmp->session_hash_buckets, cmp->session_hash_memory);
  cmp->feature_initialized = 1;
  vec_validate (cmp->sessions, nworkers);
  vec_validate_init_empty (cmp->first_index, nworkers, ~0);
  vec_validate_init_empty (cmp->last_index, nworkers, ~0);
}

int
ct6_in2out_enable_disable (ct6_main_t * cmp, u32 sw_if_index,
			   int enable_disable)
{
  vnet_sw_interface_t *sw;
  int rv = 0;

  ct6_feature_init (cmp);

  /* Utterly wrong? */
  if (pool_is_free_index (cmp->vnet_main->interface_main.sw_interfaces,
			  sw_if_index))
    return VNET_API_ERROR_INVALID_SW_IF_INDEX;

  /* Not a physical port? */
  sw = vnet_get_sw_interface (cmp->vnet_main, sw_if_index);
  if (sw->type != VNET_SW_INTERFACE_TYPE_HARDWARE)
    return VNET_API_ERROR_INVALID_SW_IF_INDEX;

  vnet_feature_enable_disable ("interface-output", "ct6-in2out",
			       sw_if_index, enable_disable, 0, 0);

  return rv;
}

int
ct6_out2in_enable_disable (ct6_main_t * cmp, u32 sw_if_index,
			   int enable_disable)
{
  vnet_sw_interface_t *sw;
  int rv = 0;

  ct6_feature_init (cmp);

  /* Utterly wrong? */
  if (pool_is_free_index (cmp->vnet_main->interface_main.sw_interfaces,
			  sw_if_index))
    return VNET_API_ERROR_INVALID_SW_IF_INDEX;

  /* Not a physical port? */
  sw = vnet_get_sw_interface (cmp->vnet_main, sw_if_index);
  if (sw->type != VNET_SW_INTERFACE_TYPE_HARDWARE)
    return VNET_API_ERROR_INVALID_SW_IF_INDEX;

  vnet_feature_enable_disable ("ip6-unicast", "ct6-out2in",
			       sw_if_index, enable_disable, 0, 0);

  return rv;
}

static clib_error_t *
set_ct6_enable_disable_command_fn (vlib_main_t * vm,
				   unformat_input_t * input,
				   vlib_cli_command_t * cmd)
{
  ct6_main_t *cmp = &ct6_main;
  u32 sw_if_index = ~0;
  int enable_disable = 1;
  u32 inside = ~0;
  int rv;

  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
    {
      if (unformat (input, "disable"))
	enable_disable = 0;
      else if (unformat (input, "%U", unformat_vnet_sw_interface,
			 cmp->vnet_main, &sw_if_index))
	;
      else if (unformat (input, "inside") || unformat (input, "in"))
	inside = 1;
      else if (unformat (input, "outside") || unformat (input, "out"))
	inside = 0;
      else
	break;
    }

  if (inside == ~0)
    return clib_error_return (0, "Please specify inside or outside");

  if (sw_if_index == ~0)
    return clib_error_return (0, "Please specify an interface...");

  if (inside == 1)
    rv = ct6_in2out_enable_disable (cmp, sw_if_index, enable_disable);
  else
    rv = ct6_out2in_enable_disable (cmp, sw_if_index, enable_disable);

  switch (rv)
    {
    case 0:
      break;

    case VNET_API_ERROR_INVALID_SW_IF_INDEX:
      return clib_error_return
	(0, "Invalid interface, only works on physical ports");
      break;

    default:
      return clib_error_return (0, "ct6_enable_disable returned %d", rv);
    }
  return 0;
}

/* *INDENT-OFF* */
VLIB_CLI_COMMAND (set_ct6_command, static) =
{
  .path = "set ct6",
  .short_help =
  "set ct6 [inside|outside] <interface-name> [disable]",
  .function = set_ct6_enable_disable_command_fn,
};
/* *INDENT-ON* */

/* API message handler */
static void vl_api_ct6_enable_disable_t_handler
  (vl_api_ct6_enable_disable_t * mp)
{
  vl_api_ct6_enable_disable_reply_t *rmp;
  ct6_main_t *cmp = &ct6_main;
  int rv;

  VALIDATE_SW_IF_INDEX (mp);

  if (mp->is_inside)
    rv = ct6_in2out_enable_disable (cmp, ntohl (mp->sw_if_index),
				    (int) (mp->enable_disable));
  else
    rv = ct6_out2in_enable_disable (cmp, ntohl (mp->sw_if_index),
				    (int) (mp->enable_disable));

  BAD_SW_IF_INDEX_LABEL;
  REPLY_MACRO (VL_API_CT6_ENABLE_DISABLE_REPLY);
}

#include <ct6/ct6.api.c>
static clib_error_t *
ct6_init (vlib_main_t * vm)
{
  ct6_main_t *cmp = &ct6_main;
  clib_error_t *error = 0;

  cmp->vlib_main = vm;
  cmp->vnet_main = vnet_get_main ();

  /* Ask for a correctly-sized block of API message decode slots */
  cmp->msg_id_base = setup_message_id_table ();

  /*
   * Set default parameters...
   * 256K sessions
   * 64K buckets
   * 2 minute inactivity timer
   * 10000 concurrent sessions
   */
  cmp->session_hash_memory = 16ULL << 20;
  cmp->session_hash_buckets = 64 << 10;
  cmp->session_timeout_interval = 120.0;
  cmp->max_sessions_per_worker = 10000;

  /* ... so the packet generator can feed the in2out node ... */
  ethernet_setup_node (vm, ct6_in2out_node.index);
  return error;
}

VLIB_INIT_FUNCTION (ct6_init);

/* *INDENT-OFF* */
VNET_FEATURE_INIT (ct6out2in, static) =
{
  .arc_name = "ip6-unicast",
  .node_name = "ct6-out2in",
  .runs_before = VNET_FEATURES ("ip6-lookup"),
};
/* *INDENT-ON */

/* *INDENT-OFF* */
VNET_FEATURE_INIT (ct6in2out, static) = {
  .arc_name = "interface-output",
  .node_name = "ct6-in2out",
  .runs_before = VNET_FEATURES ("interface-output-arc-end"),
};
/* *INDENT-ON */

/* *INDENT-OFF* */
VLIB_PLUGIN_REGISTER () =
{
  .version = VPP_BUILD_VER,
  .description = "IPv6 Connection Tracker",
};
/* *INDENT-ON* */

u8 *
format_ct6_session (u8 * s, va_list * args)
{
  ct6_main_t *cmp = va_arg (*args, ct6_main_t *);
  int i = va_arg (*args, int);
  ct6_session_t *s0 = va_arg (*args, ct6_session_t *);
  int verbose = va_arg (*args, int);
  clib_bihash_kv_48_8_t kvp0;

  if (s0 == 0)
    {
      s = format (s, "\n%6s%6s%40s%6s%40s%6s",
		  "Sess", "Prot", "Src", "Sport", "Dst", "Dport");
      return s;
    }

  s = format (s, "\n%6d%6d%40U%6u%40U%6u",
	      s0 - cmp->sessions[i], s0->key.proto,
	      format_ip6_address, &s0->key.src,
	      clib_net_to_host_u16 (s0->key.sport),
	      format_ip6_address, &s0->key.dst,
	      clib_net_to_host_u16 (s0->key.dport));

  clib_memcpy_fast (&kvp0, s0, sizeof (ct6_session_key_t));

  if (clib_bihash_search_48_8 (&cmp->session_hash, &kvp0, &kvp0) < 0)
    {
      s = format (s, " LOOKUP FAIL!");
    }
  else
    {
      if (kvp0.value == s0 - cmp->sessions[s0->thread_index])
	{
	  s = format (s, " OK");
	  if (verbose > 1)
	    {
	      s = format (s, " next %d prev %d", s0->next_index,
			  s0->prev_index);
	      s = format (s, " hits %d expires %.2f", s0->hits, s0->expires);
	    }
	}
      else
	s = format (s, " BOGUS LOOKUP RESULT!");
    }

  return s;
}

static clib_error_t *
show_ct6_command_fn_command_fn (vlib_main_t * vm,
				unformat_input_t * input,
				vlib_cli_command_t * cmd)
{
  ct6_main_t *cmp = &ct6_main;
  ct6_session_t *s0;
  int verbose = 0;
  u8 *s = 0;
  int i;

  if (!cmp->feature_initialized)
    return clib_error_return (0, "ip6 connection tracking not enabled...");

  if (unformat (input, "verbose %d", &verbose))
    ;
  else if (unformat (input, "verbose"))
    verbose = 1;

  for (i = 0; i < vec_len (cmp->sessions); i++)
    {
      s = format (s, "Thread %d: %d sessions\n", i,
		  pool_elts (cmp->sessions[i]));

      if (verbose == 0)
	continue;

      s =
	format (s, "%U", format_ct6_session, cmp,
		0 /* pool */ , 0 /* header */ , verbose);

      /* *INDENT-OFF* */
      pool_foreach (s0, cmp->sessions[i])
       {
        s = format (s, "%U", format_ct6_session, cmp, i, s0, verbose);
      }
      /* *INDENT-ON* */
    }
  vlib_cli_output (cmp->vlib_main, "%v", s);
  vec_free (s);
  return 0;
}

/* *INDENT-OFF* */
VLIB_CLI_COMMAND (show_ct6_command_fn_command, static) =
{
  .path = "show ip6 connection-tracker",
  .short_help = "show ip6 connection-tracker",
  .function = show_ct6_command_fn_command_fn,
};
/* *INDENT-ON* */

static void
increment_v6_address (ip6_address_t * a)
{
  u64 v0, v1;

  v0 = clib_net_to_host_u64 (a->as_u64[0]);
  v1 = clib_net_to_host_u64 (a->as_u64[1]);

  v1 += 1;
  if (v1 == 0)
    v0 += 1;
  a->as_u64[0] = clib_net_to_host_u64 (v0);
  a->as_u64[1] = clib_net_to_host_u64 (v1);
}


static clib_error_t *
test_ct6_command_fn_command_fn (vlib_main_t * vm,
				unformat_input_t * input,
				vlib_cli_command_t * cmd)
{
  ct6_main_t *cmp = &ct6_main;
  clib_bihash_kv_48_8_t kvp0;
  ct6_session_key_t *key0;
  ct6_session_t *s0;
  u8 src[16], dst[16];
  u32 recycled = 0, created = 0;
  int i, num_sessions = 5;
  u32 midpt_index;
  u8 *s = 0;

  cmp->max_sessions_per_worker = 4;

  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
    {
      if (unformat (input, "num-sessions %d", &num_sessions))
	;
      else
	if (unformat
	    (input, "max-sessions %d", &cmp->max_sessions_per_worker))
	;
      else
	break;
    }

  ct6_feature_init (cmp);

  /* Set up starting src/dst addresses */
  memset (src, 0, sizeof (src));
  memset (dst, 0, sizeof (dst));

  src[0] = 0xdb;
  dst[0] = 0xbe;

  src[15] = 1;
  dst[15] = 1;

  /*
   * See if we know about this flow.
   * Key set up for the out2in path, the performant case
   */
  key0 = (ct6_session_key_t *) & kvp0;
  memset (&kvp0, 0, sizeof (kvp0));

  for (i = 0; i < num_sessions; i++)
    {
      clib_memcpy_fast (&key0->src, src, sizeof (src));
      clib_memcpy_fast (&key0->dst, dst, sizeof (dst));
      key0->as_u64[4] = 0;
      key0->as_u64[5] = 0;
      key0->sport = clib_host_to_net_u16 (1234);
      key0->dport = clib_host_to_net_u16 (4321);
      key0->proto = 17;		/* udp, fwiw */

      s0 = ct6_create_or_recycle_session
	(cmp, &kvp0, 3.0 /* now */ , 0 /* thread index */ ,
	 &recycled, &created);

      s = format (s, "%U (%d, %d)", format_ct6_session, cmp,
		  0 /* thread index */ , s0, 1 /* verbose */ ,
		  recycled, created);
      vlib_cli_output (vm, "%v", s);
      vec_free (s);
      increment_v6_address ((ip6_address_t *) src);
      recycled = 0;
      created = 0;
    }

  /* *INDENT-OFF* */
  pool_foreach (s0, cmp->sessions[0])
   {
    s = format (s, "%U", format_ct6_session, cmp, 0, s0, 1 /* verbose */);
  }
  /* *INDENT-ON* */

  vlib_cli_output (vm, "\nEnd state: first index %d last index %d\n%v",
		   cmp->first_index[0], cmp->last_index[0], s);

  vec_free (s);

  midpt_index = cmp->max_sessions_per_worker / 3;

  s0 = pool_elt_at_index (cmp->sessions[0], midpt_index);
  vlib_cli_output (vm, "\nSimulate LRU hit on session %d",
		   s0 - cmp->sessions[0]);

  ct6_update_session_hit (cmp, s0, 234.0);

  /* *INDENT-OFF* */
  pool_foreach (s0, cmp->sessions[0])
   {
    s = format (s, "%U", format_ct6_session, cmp, 0, s0, 1 /* verbose */);
  }
  /* *INDENT-ON* */

  vlib_cli_output (vm, "\nEnd state: first index %d last index %d\n%v",
		   cmp->first_index[0], cmp->last_index[0], s);

  vec_free (s);

  return 0;
}

/* *INDENT-OFF* */
VLIB_CLI_COMMAND (test_ct6_command_fn_command, static) =
{
  .path = "test ip6 connection-tracker",
  .short_help = "test ip6 connection-tracker",
  .function = test_ct6_command_fn_command_fn,
};
/* *INDENT-ON* */

static clib_error_t *
ct6_config (vlib_main_t * vm, unformat_input_t * input)
{
  ct6_main_t *cmp = &ct6_main;

  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
    {
      if (unformat (input, "session-hash-buckets %u",
		    &cmp->session_hash_buckets))
	;
      else if (unformat (input, "session-hash-memory %U",
			 unformat_memory_size, &cmp->session_hash_memory))
	;
      else if (unformat (input, "session-timeout %f",
			 &cmp->session_timeout_interval))
	;
      else
	{
	  return clib_error_return (0, "unknown input '%U'",
				    format_unformat_error, input);
	}
    }
  return 0;
}

VLIB_CONFIG_FUNCTION (ct6_config, "ct6");

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