summaryrefslogtreecommitdiffstats
path: root/src/vnet/mpls/mpls_tunnel.h
blob: 285817c33c47952339fbb54acff620a36e3257cb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
/*
 * 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.
 */

#ifndef __MPLS_TUNNEL_H__
#define __MPLS_TUNNEL_H__

#include <vnet/mpls/mpls.h>
#include <vnet/fib/fib_path_ext.h>

typedef enum mpls_tunnel_attribute_t_
{
    MPLS_TUNNEL_ATTRIBUTE_FIRST = 0,
    /**
     * @brief The tunnel is L2 only
     */
    MPLS_TUNNEL_ATTRIBUTE_L2 = MPLS_TUNNEL_ATTRIBUTE_FIRST,
    /**
     * @brief The tunnel has an underlying multicast LSP
     */
    MPLS_TUNNEL_ATTRIBUTE_MCAST,
    MPLS_TUNNEL_ATTRIBUTE_LAST = MPLS_TUNNEL_ATTRIBUTE_MCAST,
} mpls_tunnel_attribute_t;

#define MPLS_TUNNEL_ATTRIBUTES {		  \
    [MPLS_TUNNEL_ATTRIBUTE_MCAST]  = "multicast", \
    [MPLS_TUNNEL_ATTRIBUTE_L2]     = "L2",   \
}
#define FOR_EACH_MPLS_TUNNEL_ATTRIBUTE(_item)		\
    for (_item = MPLS_TUNNEL_ATTRIBUTE_FIRST;		\
	 _item <= MPLS_TUNNEL_ATTRIBUTE_LAST;		\
	 _item++)

typedef enum mpls_tunnel_flag_t_ {
    MPLS_TUNNEL_FLAG_NONE   = 0,
    MPLS_TUNNEL_FLAG_L2     = (1 << MPLS_TUNNEL_ATTRIBUTE_L2),
    MPLS_TUNNEL_FLAG_MCAST  = (1 << MPLS_TUNNEL_ATTRIBUTE_MCAST),
} __attribute__ ((packed)) mpls_tunnel_flags_t;


/**
 * @brief A uni-directional MPLS tunnel
 */
typedef struct mpls_tunnel_t_
{
    /**
     * @brief The tunnel hooks into the FIB control plane graph.
     */
    fib_node_t mt_node;

    /**
     * @brief Tunnel flags
     */
    mpls_tunnel_flags_t mt_flags;

    /**
     * @brief If the tunnel is an L2 tunnel, this is the link type ETHERNET
     * load-balance
     */
    dpo_id_t mt_l2_lb;

    /**
     * @brief The HW interface index of the tunnel interfaces
     */
    u32 mt_hw_if_index;

    /**
     * @brief The SW interface index of the tunnel interfaces
     */
    u32 mt_sw_if_index;

    /**
     * @brief The path-list over which the tunnel's destination is reachable
     */
    fib_node_index_t mt_path_list;

    /**
     * @brief sibling index on the path-list so notifications are received.
     */
    u32 mt_sibling_index;

    /**
     * A vector of path extensions o hold the label stack for each path
     */
    fib_path_ext_list_t mt_path_exts;
} mpls_tunnel_t;

/**
 * @brief Create a new MPLS tunnel
 * @return the SW Interface index of the newly created tuneel
 */
extern u32 vnet_mpls_tunnel_create (u8 l2_only,
                                    u8 is_multicast);

/**
 * @brief Add a path to an MPLS tunnel
 */
extern void vnet_mpls_tunnel_path_add (u32 sw_if_index,
                                       fib_route_path_t *rpath);

/**
 * @brief remove a path from a tunnel.
 * @return the number of remaining paths. 0 implies the tunnel can be deleted
 */
extern int vnet_mpls_tunnel_path_remove (u32 sw_if_index,
                                         fib_route_path_t *rpath);

/**
 * @brief Delete an MPLS tunnel
 */
extern void vnet_mpls_tunnel_del (u32 sw_if_index);

extern const mpls_tunnel_t *mpls_tunnel_get(u32 index);

/**
 * @brief Callback function invoked while walking MPLS tunnels
 */
typedef void (*mpls_tunnel_walk_cb_t)(u32 index, void *ctx);

/**
 * @brief Walk all the MPLS tunnels
 */
extern void mpls_tunnel_walk(mpls_tunnel_walk_cb_t cb,
			     void *ctx);

#endif
-weight: bold } /* Keyword.Type */ .highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */ .highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */ .highlight .na { color: #336699 } /* Name.Attribute */ .highlight .nb { color: #003388 } /* Name.Builtin */ .highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */ .highlight .no { color: #003366; font-weight: bold } /* Name.Constant */ .highlight .nd { color: #555555 } /* Name.Decorator */ .highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */ .highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */ .highlight .nl { color: #336699; font-style: italic } /* Name.Label */ .highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */ .highlight .py { color: #336699; font-weight: bold } /* Name.Property */ .highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */ .highlight .nv { color: #336699 } /* Name.Variable */ .highlight .ow { color: #008800 } /* Operator.Word */ .highlight .w { color: #bbbbbb } /* Text.Whitespace */ .highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */ .highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */ .highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */ .highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */ .highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */ .highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */ .highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */ .highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */ .highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */ .highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */ .highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */ .highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */ .highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */ .highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */ .highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */ .highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */ .highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */ .highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */ .highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */ .highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */ .highlight .vc { color: #336699 } /* Name.Variable.Class */ .highlight .vg { color: #dd7700 } /* Name.Variable.Global */ .highlight .vi { color: #3333bb } /* Name.Variable.Instance */ .highlight .vm { color: #336699 } /* Name.Variable.Magic */ .highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */ }
/*
 * 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 <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <pwd.h>
#include <grp.h>
#include <netinet/in.h>
#include <signal.h>
#include <pthread.h>
#include <unistd.h>
#include <time.h>
#include <fcntl.h>
#include <string.h>
#include <vppinfra/clib.h>
#include <vppinfra/vec.h>
#include <vppinfra/hash.h>
#include <vppinfra/bitmap.h>
#include <vppinfra/fifo.h>
#include <vppinfra/time.h>
#include <vppinfra/mheap.h>
#include <vppinfra/heap.h>
#include <vppinfra/pool.h>
#include <vppinfra/format.h>
#include <vppinfra/serialize.h>
#include "svmdb.h"

typedef struct
{
  svmdb_map_args_t map_args;
  int uid, gid;
  uword size;
} svmdbtool_main_t;

svmdbtool_main_t svmdbtool_main;

static inline svmdb_map_args_t *
map_arg_setup (char *chroot_path)
{
  svmdbtool_main_t *sm = &svmdbtool_main;
  svmdb_map_args_t *ma = &sm->map_args;

  memset (ma, 0, sizeof (*ma));
  ma->root_path = chroot_path;
  ma->size = sm->size;
  ma->uid = sm->uid;
  ma->gid = sm->gid;
  return ma;
}

static void
get_string (char *chroot_path, u8 * vbl)
{
  svmdb_client_t *c;
  char *rv;
  svmdb_map_args_t *ma;

  ma = map_arg_setup (chroot_path);

  c = svmdb_map (ma);

  rv = svmdb_local_get_string_variable (c, (char *) vbl);

  fformat (stdout, "%s\n", rv ? rv : "UNSET");
  vec_free (rv);
  svmdb_unmap (c);
}

static void
set_string (char *chroot_path, u8 * vbl, u8 * value)
{
  svmdb_client_t *c;
  svmdb_map_args_t *ma;

  ma = map_arg_setup (chroot_path);

  c = svmdb_map (ma);
  svmdb_local_set_string_variable (c, (char *) vbl, (char *) value);
  svmdb_unmap (c);
}

static void
unset_string (char *chroot_path, u8 * vbl)
{
  svmdb_client_t *c;
  svmdb_map_args_t *ma;

  ma = map_arg_setup (chroot_path);

  c = svmdb_map (ma);
  svmdb_local_unset_string_variable (c, (char *) vbl);
  svmdb_unmap (c);
}

static void
dump_strings (char *chroot_path)
{
  svmdb_client_t *c;
  svmdb_map_args_t *ma;

  ma = map_arg_setup (chroot_path);

  c = svmdb_map (ma);
  svmdb_local_dump_strings (c);
  svmdb_unmap (c);
}

static void
serialize_strings (char *chroot_path, char *filename)
{
  svmdb_client_t *c;
  svmdb_map_args_t *ma;

  ma = map_arg_setup (chroot_path);

  c = svmdb_map (ma);
  (void) svmdb_local_serialize_strings (c, filename);
  svmdb_unmap (c);
}

static void
unserialize_strings (char *chroot_path, char *filename)
{
  svmdb_client_t *c;
  svmdb_map_args_t *ma;

  ma = map_arg_setup (chroot_path);

  c = svmdb_map (ma);
  (void) svmdb_local_unserialize_strings (c, filename);
  svmdb_unmap (c);
}

static void
test_vlib_vec_rate (char *chroot_path, f64 vr)
{
  svmdb_client_t *c;
  f64 *tv = 0;
  svmdb_map_args_t *ma;

  ma = map_arg_setup (chroot_path);

  c = svmdb_map (ma);

  vec_add1 (tv, vr);

  svmdb_local_set_vec_variable (c, "vlib_vector_rate", (char *) tv,
				sizeof (*tv));
  svmdb_unmap (c);

  vec_free (tv);
}



static void
test_vec (char *chroot_path, u8 * vbl)
{
  svmdb_client_t *c;
  u64 *tv = 0;
  int i;
  svmdb_map_args_t *ma;

  ma = map_arg_setup (chroot_path);

  c = svmdb_map (ma);

  /* my amp goes to 11 */
  for (i = 0; i < 11; i++)
    {
      vec_add1 (tv, i);
    }

  svmdb_local_set_vec_variable (c, (char *) vbl, (char *) tv, sizeof (tv[0]));
  svmdb_unmap (c);

  vec_free (tv);
}

static void
fake_install (char *chroot_path, u8 * add_value)
{
  svmdb_client_t *c;
  u8 *v = 0;
  u8 **values = 0;
  u8 *oldvalue;
  u8 *value;
  int nitems = 0, i;
  serialize_main_t m;
  svmdb_map_args_t *ma;

  ma = map_arg_setup (chroot_path);

  c = svmdb_map (ma);

  oldvalue = svmdb_local_get_vec_variable (c, "installed_sw", 1);
  if (oldvalue)
    {
      unserialize_open_data (&m, oldvalue, vec_len (oldvalue));
      nitems = unserialize_likely_small_unsigned_integer (&m);
      for (i = 0; i < nitems; i++)
	{
	  unserialize_cstring (&m, (char **) &value);
	  vec_add1 (values, value);
	}
      vec_free (v);
    }
  nitems++;
  value = format (0, "%s%c", add_value, 0);

  vec_add1 (values, value);

  fformat (stdout, "Resulting installed_sw vector:\n");

  serialize_open_vector (&m, v);
  serialize_likely_small_unsigned_integer (&m, vec_len (values));
  for (i = 0; i < vec_len (values); i++)
    {
      fformat (stdout, "%s\n", values[i]);
      serialize_cstring (&m, (char *) values[i]);
    }

  v = serialize_close_vector (&m);

  svmdb_local_set_vec_variable (c, "installed_sw", v, sizeof (v[0]));
  svmdb_unmap (c);

  for (i = 0; i < vec_len (values); i++)
    vec_free (values[i]);
  vec_free (values);
}

static void
sigaction_handler (int signum, siginfo_t * i, void *notused)
{
  u32 action, opaque;

  action = (u32) (uword) i->si_ptr;
  action >>= 28;
  opaque = (u32) (uword) i->si_ptr;
  opaque &= ~(0xF0000000);

  clib_warning ("signal %d, action %d, opaque %x", signum, action, opaque);
}

static void
test_reg (char *chroot_path, u8 * vbl)
{
  svmdb_client_t *c;
  svmdb_notification_args_t args;
  svmdb_notification_args_t *a = &args;
  struct sigaction sa;
  svmdb_map_args_t *ma;

  ma = map_arg_setup (chroot_path);

  memset (&sa, 0, sizeof (sa));
  sa.sa_sigaction = sigaction_handler;
  sa.sa_flags = SA_SIGINFO;
  if (sigaction (SIGUSR2, &sa, 0) < 0)
    {
      clib_unix_warning ("sigaction");
      return;
    }

  memset (a, 0, sizeof (*a));

  c = svmdb_map (ma);

  a->add_del = 1 /* add */ ;
  a->nspace = SVMDB_NAMESPACE_STRING;
  a->var = (char *) vbl;
  a->elsize = 1;
  a->signum = SIGUSR2;
  a->action = SVMDB_ACTION_GET;
  a->opaque = 0x0eadbeef;

  svmdb_local_add_del_notification (c, a);

  (void) svmdb_local_get_string_variable (c, (char *) vbl);

  a->add_del = 0;		/* del */
  svmdb_local_add_del_notification (c, a);



  svmdb_unmap (c);
}

static void
unset_vec (char *chroot_path, u8 * vbl)
{
  svmdb_client_t *c;
  svmdb_map_args_t *ma;

  ma = map_arg_setup (chroot_path);

  c = svmdb_map (ma);

  svmdb_local_unset_vec_variable (c, (char *) vbl);
  svmdb_unmap (c);
}

static void
dump_vecs (char *chroot_path)
{
  svmdb_client_t *c;
  svmdb_map_args_t *ma;

  ma = map_arg_setup (chroot_path);

  c = svmdb_map (ma);

  svmdb_local_dump_vecs (c);
  svmdb_unmap (c);
}

static void
crash_test (char *chroot_path)
{
  svmdb_client_t *c;
  svmdb_map_args_t *ma;

  ma = map_arg_setup (chroot_path);

  c = svmdb_map (ma);

  clib_warning ("Grab region mutex and crash deliberately!");
  c->db_rp->mutex_owner_pid = getpid ();
  c->db_rp->mutex_owner_tag = -13;
  pthread_mutex_lock (&c->db_rp->mutex);

  abort ();
}

static void
map_with_size (char *chroot_path, uword size)
{
  svmdb_client_t *c;
  svmdb_map_args_t *ma;

  svmdbtool_main.size = size;
  ma = map_arg_setup (chroot_path);

  c = svmdb_map (ma);

  svmdb_unmap (c);
}

int
main (int argc, char **argv)
{
  unformat_input_t input;
  int parsed = 0;
  u8 *vbl = 0, *value = 0;
  char *chroot_path = 0;
  u8 *chroot_path_u8;
  u8 *filename;
  uword size;
  f64 vr;
  int uid, gid, rv;
  struct passwd _pw, *pw;
  struct group _grp, *grp;
  char *s, buf[128];

  svmdbtool_main.uid = geteuid ();
  svmdbtool_main.gid = getegid ();

  unformat_init_command_line (&input, argv);

  while (unformat_check_input (&input) != UNFORMAT_END_OF_INPUT)
    {
      if (unformat (&input, "get-string %s", &vbl))
	{
	  get_string (chroot_path, vbl);
	  vec_free (vbl);
	  parsed++;
	}
      else if (unformat (&input, "set-string %s %s", &vbl, &value))
	{
	  set_string (chroot_path, vbl, value);
	  vec_free (vbl);
	  vec_free (value);
	  parsed++;
	}
      else if (unformat (&input, "unset-string %s", &vbl))
	{
	  unset_string (chroot_path, vbl);
	  vec_free (vbl);
	  parsed++;
	}
      else if (unformat (&input, "dump-strings"))
	{
	  dump_strings (chroot_path);
	  parsed++;
	}
      else if (unformat (&input, "unset-vec %s", &vbl))
	{
	  unset_vec (chroot_path, vbl);
	  vec_free (vbl);
	  parsed++;
	}
      else if (unformat (&input, "dump-vecs"))
	{
	  dump_vecs (chroot_path);
	  parsed++;
	}
      else if (unformat (&input, "test-vec %s", &vbl))
	{
	  test_vec (chroot_path, vbl);
	  // vec_free(vbl);
	  parsed++;
	}
      else if (unformat (&input, "vlib-vec-rate %f", &vr))
	{
	  test_vlib_vec_rate (chroot_path, vr);
	  parsed++;
	}
      else if (unformat (&input, "test-reg %s", &vbl))
	{
	  test_reg (chroot_path, vbl);
	  parsed++;
	}
      else if (unformat (&input, "crash-test"))
	{
	  crash_test (chroot_path);
	}
      else if (unformat (&input, "chroot %s", &chroot_path_u8))
	{
	  chroot_path = (char *) chroot_path_u8;
	}
      else if (unformat (&input, "fake-install %s", &value))
	{
	  fake_install (chroot_path, value);
	  parsed++;
	}
      else if (unformat (&input, "size %d", &size))
	{
	  map_with_size (chroot_path, size);
	  parsed++;
	}
      else if (unformat (&input, "uid %d", &uid))
	svmdbtool_main.uid = uid;
      else if (unformat (&input, "gid %d", &gid))
	svmdbtool_main.gid = gid;
      else if (unformat (&input, "uid %s", &s))
	{
	  /* lookup the username */
	  pw = NULL;
	  rv = getpwnam_r (s, &_pw, buf, sizeof (buf), &pw);
	  if (rv < 0)
	    {
	      fformat (stderr, "cannot fetch username %s", s);
	      exit (1);
	    }
	  if (pw == NULL)
	    {
	      fformat (stderr, "username %s does not exist", s);
	      exit (1);
	    }
	  vec_free (s);
	  svmdbtool_main.uid = pw->pw_uid;
	}
      else if (unformat (&input, "gid %s", &s))
	{
	  /* lookup the group name */
	  grp = NULL;
	  rv = getgrnam_r (s, &_grp, buf, sizeof (buf), &grp);
	  if (rv != 0)
	    {
	      fformat (stderr, "cannot fetch group %s", s);
	      exit (1);
	    }
	  if (grp == NULL)
	    {
	      fformat (stderr, "group %s does not exist", s);
	      exit (1);
	    }
	  vec_free (s);
	  svmdbtool_main.gid = grp->gr_gid;
	}
      else if (unformat (&input, "serialize-strings %s", &filename))
	{
	  vec_add1 (filename, 0);
	  serialize_strings (chroot_path, (char *) filename);
	  parsed++;
	}
      else if (unformat (&input, "unserialize-strings %s", &filename))
	{
	  vec_add1 (filename, 0);
	  unserialize_strings (chroot_path, (char *) filename);
	  parsed++;
	}
      else
	{
	  break;
	}
    }

  unformat_free (&input);

  if (!parsed)
    {
      fformat (stdout, "%s: get-string <name> | set-string <name> <value>\n",
	       argv[0]);
      fformat (stdout, "      unset-string <name> | dump-strings\n");
      fformat (stdout, "      test-vec <name> |\n");
      fformat (stdout, "      unset-vec <name> | dump-vecs\n");
      fformat (stdout, "      chroot <prefix> [uid <nnn-or-userid>]\n");
      fformat (stdout, "      [gid <nnn-or-group-name>]\n");
    }

  exit (0);
}

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