aboutsummaryrefslogtreecommitdiffstats
path: root/requirements.txt
AgeCommit message (Expand)AuthorFilesLines
2017-02-23Add pypcap python requirementMatej Klotton1-1/+1
2016-07-01Add missing libraries to requirementsPavel Kotucek1-0/+3
2016-04-05Setup and check honeycomb on all DUTsselias1-0/+1
2016-03-17DropRateSearch libraryMiroslav Miklus1-1/+1
2016-02-08New version of RF tests.Stefan Kobza1-0/+9
'>303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344
/*
 * 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 <dns/dns.h>

#include <vlib/vlib.h>
#include <vnet/vnet.h>

vlib_node_registration_t dns46_request_node;

typedef struct
{
  u32 pool_index;
  u32 disposition;
} dns46_request_trace_t;

/* packet trace format function */
static u8 *
format_dns46_request_trace (u8 * s, va_list * args)
{
  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
  dns46_request_trace_t *t = va_arg (*args, dns46_request_trace_t *);

  s = format (s, "DNS46_REPLY: pool index %d, disposition  %d",
	      t->pool_index, t->disposition);
  return s;
}

vlib_node_registration_t dns46_request_node;

static char *dns46_request_error_strings[] = {
#define _(sym,string) string,
  foreach_dns46_request_error
#undef _
};

typedef enum
{
  DNS46_REQUEST_NEXT_DROP,
  DNS46_REQUEST_NEXT_IP_LOOKUP,
  DNS46_REQUEST_NEXT_PUNT,
  DNS46_REQUEST_N_NEXT,
} dns46_request_next_t;

static uword
dns46_request_inline (vlib_main_t * vm,
		      vlib_node_runtime_t * node, vlib_frame_t * frame,
		      int is_ip6)
{
  u32 n_left_from, *from, *to_next;
  dns46_request_next_t next_index;
  dns_main_t *dm = &dns_main;

  from = vlib_frame_vector_args (frame);
  n_left_from = frame->n_vectors;
  next_index = node->cached_next_index;

  while (n_left_from > 0)
    {
      u32 n_left_to_next;

      vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);

#if 0
      while (n_left_from >= 4 && n_left_to_next >= 2)
	{
	  u32 next0 = DNS46_REQUEST_NEXT_INTERFACE_OUTPUT;
	  u32 next1 = DNS46_REQUEST_NEXT_INTERFACE_OUTPUT;
	  u32 sw_if_index0, sw_if_index1;
	  u8 tmp0[6], tmp1[6];
	  ethernet_header_t *en0, *en1;
	  u32 bi0, bi1;
	  vlib_buffer_t *b0, *b1;

	  /* Prefetch next iteration. */
	  {
	    vlib_buffer_t *p2, *p3;

	    p2 = vlib_get_buffer (vm, from[2]);
	    p3 = vlib_get_buffer (vm, from[3]);

	    vlib_prefetch_buffer_header (p2, LOAD);
	    vlib_prefetch_buffer_header (p3, LOAD);

	    clib_prefetch_store (p2->data);
	    clib_prefetch_store (p3->data);
	  }

	  /* speculatively enqueue b0 and b1 to the current next frame */
	  to_next[0] = bi0 = from[0];
	  to_next[1] = bi1 = from[1];
	  from += 2;
	  to_next += 2;
	  n_left_from -= 2;
	  n_left_to_next -= 2;

	  b0 = vlib_get_buffer (vm, bi0);
	  b1 = vlib_get_buffer (vm, bi1);

	  /* $$$$$ End of processing 2 x packets $$$$$ */

	  if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE)))
	    {
	      if (b0->flags & VLIB_BUFFER_IS_TRACED)
		{
		  dns46_request_trace_t *t =
		    vlib_add_trace (vm, node, b0, sizeof (*t));
		  t->sw_if_index = sw_if_index0;
		  t->next_index = next0;
		}
	      if (b1->flags & VLIB_BUFFER_IS_TRACED)
		{
		  dns46_request_trace_t *t =
		    vlib_add_trace (vm, node, b1, sizeof (*t));
		  t->sw_if_index = sw_if_index1;
		  t->next_index = next1;
		}
	    }

	  /* verify speculative enqueues, maybe switch current next frame */
	  vlib_validate_buffer_enqueue_x2 (vm, node, next_index,
					   to_next, n_left_to_next,
					   bi0, bi1, next0, next1);
	}
#endif

      while (n_left_from > 0 && n_left_to_next > 0)
	{
	  u32 bi0;
	  vlib_buffer_t *b0;
	  u32 next0 = DNS46_REQUEST_NEXT_DROP;
	  u32 error0 = DNS46_REQUEST_ERROR_NONE;
	  udp_header_t *u0;
	  dns_header_t *d0;
	  dns_query_t *q0;
	  ip4_header_t *ip40 = 0;
	  ip6_header_t *ip60 = 0;
	  dns_cache_entry_t *ep0;
	  dns_pending_request_t _t0, *t0 = &_t0;
	  u16 flags0;
	  u32 pool_index0 = ~0;
	  u8 *name0;
	  u8 *label0;

	  /* speculatively enqueue b0 to the current next frame */
	  bi0 = from[0];
	  to_next[0] = bi0;
	  from += 1;
	  to_next += 1;
	  n_left_from -= 1;
	  n_left_to_next -= 1;

	  b0 = vlib_get_buffer (vm, bi0);
	  d0 = vlib_buffer_get_current (b0);
	  u0 = (udp_header_t *) ((u8 *) d0 - sizeof (*u0));

	  if (PREDICT_FALSE (dm->is_enabled == 0))
	    {
	      next0 = DNS46_REQUEST_NEXT_PUNT;
	      goto done0;
	    }

	  if (is_ip6)
	    {
	      ip60 = (ip6_header_t *) (((u8 *) u0) - sizeof (ip6_header_t));
	      next0 = DNS46_REQUEST_NEXT_DROP;
	      error0 = DNS46_REQUEST_ERROR_UNIMPLEMENTED;
	      goto done0;
	    }
	  else
	    {
	      ip40 = (ip4_header_t *) (((u8 *) u0) - sizeof (ip4_header_t));
	      if (ip40->ip_version_and_header_length != 0x45)
		{
		  error0 = DNS46_REQUEST_ERROR_IP_OPTIONS;
		  goto done0;
		}
	    }
	  /* Parse through the DNS request */
	  flags0 = clib_net_to_host_u16 (d0->flags);

	  /* Requests only */
	  if (flags0 & DNS_QR)
	    {
	      next0 = DNS46_REQUEST_NEXT_DROP;
	      error0 = DNS46_REQUEST_ERROR_BAD_REQUEST;
	      goto done0;
	    }
	  if (clib_net_to_host_u16 (d0->qdcount) != 1)
	    {
	      next0 = DNS46_REQUEST_NEXT_DROP;
	      error0 = DNS46_REQUEST_ERROR_TOO_MANY_REQUESTS;
	      goto done0;
	    }

	  label0 = (u8 *) (d0 + 1);

	  /*
	   * vnet_dns_labels_to_name produces a non NULL terminated vector
	   * vnet_dns_resolve_name expects a C-string.
	   */
	  name0 = vnet_dns_labels_to_name (label0, (u8 *) d0, (u8 **) & q0);
	  vec_add1 (name0, 0);
	  vec_dec_len (name0, 1);

	  t0->request_type = DNS_PEER_PENDING_NAME_TO_IP;

	  /*
	   * See if this is a reverse lookup. Both ip4 and ip6 reverse
	   * requests end with ".arpa"
	   */
	  if (PREDICT_TRUE (vec_len (name0) > 5))
	    {
	      u8 *aptr0 = name0 + vec_len (name0) - 5;

	      if (!memcmp (aptr0, ".arpa", 5))
		t0->request_type = DNS_PEER_PENDING_IP_TO_NAME;
	    }

	  t0->client_index = ~0;
	  t0->is_ip6 = is_ip6;
	  t0->dst_port = u0->src_port;
	  t0->id = d0->id;
	  t0->name = name0;
	  if (is_ip6)
	    clib_memcpy_fast (t0->dst_address, ip60->src_address.as_u8,
			      sizeof (ip6_address_t));
	  else
	    clib_memcpy_fast (t0->dst_address, ip40->src_address.as_u8,
			      sizeof (ip4_address_t));

	  vnet_dns_resolve_name (vm, dm, name0, t0, &ep0);

	  if (ep0)
	    {
	      if (is_ip6)
		vnet_send_dns6_reply (vm, dm, t0, ep0, b0);
	      else
		vnet_send_dns4_reply (vm, dm, t0, ep0, b0);
	      next0 = DNS46_REQUEST_NEXT_IP_LOOKUP;
	    }
	  else
	    {
	      error0 = DNS46_REQUEST_ERROR_RESOLUTION_REQUIRED;
	    }

	done0:
	  b0->error = node->errors[error0];

	  if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE)
			     && (b0->flags & VLIB_BUFFER_IS_TRACED)))
	    {
	      dns46_request_trace_t *t =
		vlib_add_trace (vm, node, b0, sizeof (*t));
	      t->disposition = error0;
	      t->pool_index = pool_index0;
	    }

	  /* verify speculative enqueue, maybe switch current next frame */
	  vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
					   to_next, n_left_to_next,
					   bi0, next0);
	}

      vlib_put_next_frame (vm, node, next_index, n_left_to_next);
    }

  return frame->n_vectors;
}

static uword
dns4_request_node_fn (vlib_main_t * vm,
		      vlib_node_runtime_t * node, vlib_frame_t * frame)
{

  return dns46_request_inline (vm, node, frame, 0 /* is_ip6 */ );
}

/* *INDENT-OFF* */
VLIB_REGISTER_NODE (dns4_request_node) =
{
  .function = dns4_request_node_fn,
  .name = "dns4-request",
  .vector_size = sizeof (u32),
  .format_trace = format_dns46_request_trace,
  .type = VLIB_NODE_TYPE_INTERNAL,
  .n_errors = ARRAY_LEN (dns46_request_error_strings),
  .error_strings = dns46_request_error_strings,
  .n_next_nodes = DNS46_REQUEST_N_NEXT,
  .next_nodes = {
    [DNS46_REQUEST_NEXT_DROP] = "error-drop",
    [DNS46_REQUEST_NEXT_PUNT] = "error-punt",
    [DNS46_REQUEST_NEXT_IP_LOOKUP] = "ip4-lookup",
  },
};
/* *INDENT-ON* */

static uword
dns6_request_node_fn (vlib_main_t * vm,
		      vlib_node_runtime_t * node, vlib_frame_t * frame)
{

  return dns46_request_inline (vm, node, frame, 1 /* is_ip6 */ );
}

/* *INDENT-OFF* */
VLIB_REGISTER_NODE (dns6_request_node) =
{
  .function = dns6_request_node_fn,
  .name = "dns6-request",
  .vector_size = sizeof (u32),
  .format_trace = format_dns46_request_trace,
  .type = VLIB_NODE_TYPE_INTERNAL,
  .n_errors = ARRAY_LEN (dns46_request_error_strings),
  .error_strings = dns46_request_error_strings,
  .n_next_nodes = DNS46_REQUEST_N_NEXT,
  .next_nodes = {
    [DNS46_REQUEST_NEXT_DROP] = "error-drop",
    [DNS46_REQUEST_NEXT_PUNT] = "error-punt",
    [DNS46_REQUEST_NEXT_IP_LOOKUP] = "ip6-lookup",
  },
};
/* *INDENT-ON* */

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