summaryrefslogtreecommitdiffstats
path: root/src/plugins/ioam/ip6/ioam_cache.h
AgeCommit message (Expand)AuthorFilesLines
2019-03-01ioam: migrate old MULTIARCH macros to VLIB_NODE_FNFilip Tehlar1-0/+3
2018-11-14Remove c-11 memcpy checks from perf-critical codeDave Barach1-9/+9
2018-10-23c11 safe string handling supportDave Barach1-6/+6
2018-05-04Harmonize vec/pool_get_aligned object sizes and alignment requestsDave Barach1-2/+5
2017-10-24Add extern to *_main global variable declarations in header files.Dave Wallace1-1/+1
2017-05-17ioam: configuration for SRv6 localsid (VPP-693)shwethab1-11/+7
2017-05-05First commit SR MPLSPablo Camarillo1-1/+1
2017-03-14ioam: ip6 hop by hop ext header and SR header co-existenceshwethab1-3/+3
2017-03-14IOAM Coverity fixAkshayaNadahalli1-7/+17
2017-03-06ioam: manycast using iOAM and SR (VPP-628)Shwetha Bhandari1-0/+897
a> 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304
/*
 *------------------------------------------------------------------
 * json_format.c
 *
 * Copyright (c) 2015 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 <inttypes.h>
#include <vat/json_format.h>
#include <vnet/ip/ip.h>
#include <vppinfra/vec.h>

#define VAT_TAB_WIDTH               2

typedef struct vat_print_ctx_s
{
  FILE *ofp;
  u32 indent;
} vat_print_ctx_t;

/* Format an IP4 address. */
static u8 *
vat_json_format_ip4_address (u8 * s, va_list * args)
{
  u8 *a = va_arg (*args, u8 *);
  return format (s, "%d.%d.%d.%d", a[0], a[1], a[2], a[3]);
}

/* Format an IP6 address. */
static u8 *
vat_json_format_ip6_address (u8 * s, va_list * args)
{
  ip6_address_t *a = va_arg (*args, ip6_address_t *);
  u32 i, i_max_n_zero, max_n_zeros, i_first_zero, n_zeros, last_double_colon;

  i_max_n_zero = ARRAY_LEN (a->as_u16);
  max_n_zeros = 0;
  i_first_zero = i_max_n_zero;
  n_zeros = 0;
  for (i = 0; i < ARRAY_LEN (a->as_u16); i++)
    {
      u32 is_zero = a->as_u16[i] == 0;
      if (is_zero && i_first_zero >= ARRAY_LEN (a->as_u16))
	{
	  i_first_zero = i;
	  n_zeros = 0;
	}
      n_zeros += is_zero;
      if ((!is_zero && n_zeros > max_n_zeros)
	  || (i + 1 >= ARRAY_LEN (a->as_u16) && n_zeros > max_n_zeros))
	{
	  i_max_n_zero = i_first_zero;
	  max_n_zeros = n_zeros;
	  i_first_zero = ARRAY_LEN (a->as_u16);
	  n_zeros = 0;
	}
    }

  last_double_colon = 0;
  for (i = 0; i < ARRAY_LEN (a->as_u16); i++)
    {
      if (i == i_max_n_zero && max_n_zeros > 1)
	{
	  s = format (s, "::");
	  i += max_n_zeros - 1;
	  last_double_colon = 1;
	}
      else
	{
	  s = format (s, "%s%x",
		      (last_double_colon || i == 0) ? "" : ":",
		      clib_net_to_host_u16 (a->as_u16[i]));
	  last_double_colon = 0;
	}
    }

  return s;
}

static void
vat_json_indent_print (vat_print_ctx_t * ctx)
{
  int i;
  for (i = 0; i < ctx->indent * VAT_TAB_WIDTH; i++)
    {
      fformat (ctx->ofp, " ");
    }
}

static void
vat_json_indent_line (vat_print_ctx_t * ctx, char *fmt, ...)
{
  va_list va;

  vat_json_indent_print (ctx);
  va_start (va, fmt);
  va_fformat (ctx->ofp, fmt, &va);
  va_end (va);
}

static u8
is_num_only (vat_json_node_t * p)
{
  vat_json_node_t *elem;
  vec_foreach (elem, p)
  {
    if (VAT_JSON_INT != elem->type && VAT_JSON_UINT != elem->type)
      {
	return 0;
      }
  }
  return 1;
}

static void
vat_json_print_internal (vat_print_ctx_t * ctx, vat_json_node_t * node)
{
#define P(fmt,...) fformat(ctx->ofp, fmt, ##__VA_ARGS__)
#define PL(fmt,...) fformat(ctx->ofp, fmt"\n", ##__VA_ARGS__)
#define PPL(fmt,...) vat_json_indent_line(ctx, fmt"\n", ##__VA_ARGS__)
#define PP(fmt,...) vat_json_indent_line(ctx, fmt, ##__VA_ARGS__)
#define INCR (ctx->indent++)
#define DECR (ctx->indent--)

  vat_json_pair_t *pair;
  u32 i, count;
  vat_json_node_t *elem;
  u8 num_only = 0;

  if (!node)
    {
      return;
    }

  switch (node->type)
    {
    case VAT_JSON_OBJECT:
      count = vec_len (node->pairs);
      if (count >= 1)
	{
	  PL ("{");
	  INCR;
	  for (i = 0; i < count; i++)
	    {
	      pair = &node->pairs[i];
	      PP ("\"%s\": ", pair->name);
	      vat_json_print_internal (ctx, &pair->value);
	      if (i < count - 1)
		{
		  P (",");
		}
	      PL ();
	    }
	  DECR;
	  PP ("}");
	}
      else
	{
	  P ("{}");
	}
      break;
    case VAT_JSON_ARRAY:
      num_only = is_num_only (node->array);
      count = vec_len (node->array);
      if (count >= 1)
	{
	  if (num_only)
	    P ("[");
	  else
	    PL ("[ ");
	  INCR;
	  for (i = 0; i < count; i++)
	    {
	      elem = &node->array[i];
	      if (!num_only)
		{
		  vat_json_indent_print (ctx);
		}
	      vat_json_print_internal (ctx, elem);
	      if (i < count - 1)
		{
		  if (num_only)
		    {
		      P (", ");
		    }
		  else
		    {
		      P (",");
		    }
		}
	      if (!num_only)
		PL ();
	    }
	  DECR;
	  if (!num_only)
	    PP ("]");
	  else
	    P ("]");
	}
      else
	{
	  P ("[]");
	}
      break;
    case VAT_JSON_INT:
      P ("%d", node->sint);
      break;
    case VAT_JSON_UINT:
      P ("%" PRIu64, node->uint);
      break;
    case VAT_JSON_REAL:
      P ("%f", node->real);
      break;
    case VAT_JSON_STRING:
      P ("\"%s\"", node->string);
      break;
    case VAT_JSON_IPV4:
      P ("\"%U\"", vat_json_format_ip4_address, &node->ip4);
      break;
    case VAT_JSON_IPV6:
      P ("\"%U\"", vat_json_format_ip6_address, &node->ip6);
      break;
    default:
      break;
    }
#undef PPL
#undef PP
#undef PL
#undef P
}

void
vat_json_print (FILE * ofp, vat_json_node_t * node)
{
  vat_print_ctx_t ctx;
  memset (&ctx, 0, sizeof ctx);
  ctx.indent = 0;
  ctx.ofp = ofp;
  fformat (ofp, "\n");
  vat_json_print_internal (&ctx, node);
  fformat (ofp, "\n");
}

void
vat_json_free (vat_json_node_t * node)
{
  int i = 0;

  if (NULL == node)
    {
      return;
    }
  switch (node->type)
    {
    case VAT_JSON_OBJECT:
      for (i = 0; i < vec_len (node->pairs); i++)
	{
	  vat_json_free (&node->pairs[i].value);
	}
      if (NULL != node->pairs)
	{
	  vec_free (node->pairs);
	}
      break;
    case VAT_JSON_ARRAY:
      for (i = 0; i < vec_len (node->array); i++)
	{
	  vat_json_free (&node->array[i]);
	}
      if (NULL != node->array)
	{
	  vec_free (node->array);
	}
      break;
    case VAT_JSON_STRING:
      if (NULL != node->string)
	{
	  vec_free (node->string);
	}
      break;
    default:
      break;
    }
}

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