summaryrefslogtreecommitdiffstats
path: root/src/vnet/fib/fib_entry.h
diff options
context:
space:
mode:
authorNeale Ranns <nranns@cisco.com>2017-11-25 15:20:26 -0800
committerDamjan Marion <dmarion.lists@gmail.com>2017-11-26 19:16:30 +0000
commit84517cfd1508f6da24937f310f7fffe752f22584 (patch)
treed26e98ec23ddf2cdcc573b39650a49c890ca2bd7 /src/vnet/fib/fib_entry.h
parent630b9741659b9a4b68c64ebbeb675761c6f26842 (diff)
FIB: optimise for src memory allocations
Most FIB entries will only ever have one source providing forwarding information. Currently the source infom is stored in a vector of sources on the FIB entry. Change this to a union of one source inline and a vector. This saves the need to alloc a vector of sources for each FIB entry. before: vpp# ip route add count 1500000 1.0.0.1/32 via 10.10.10.2 loop0 4.392857e5 routes/sec vpp# ip route del count 1500000 1.0.0.1/32 via 10.10.10.2 loop0 9.175464e5 routes/sec vpp# ip route add count 1500000 1.0.0.1/32 via 10.10.10.2 loop0 5.193375e5 routes/sec vpp# sh fib mem FIB memory Name Size in-use /allocated totals Entry 72 1500011/ 1500011 108000792/108000792 Entry Source 32 1500011/ 1500011 48000352/48000352 after: vpp# ip route add count 1500000 1.0.0.1/32 via 10.10.10.2 loop0 4.726560e5 routes/sec vpp# ip route del count 1500000 1.0.0.1/32 via 10.10.10.2 loop0 1.041629e6 routes/sec vpp# ip route add count 1500000 1.0.0.1/32 via 10.10.10.2 loop0 5.702895e5 routes/sec vpp# sh fib mem FIB memory Name Size in-use /allocated totals Entry 96 1500011/ 1500011 144001056/144001056 Entry Source 32 0 / 0 0/0 Change-Id: Ic71e413eaff1ec152656beda3b94186f7894ea49 Signed-off-by: Neale Ranns <nranns@cisco.com>
Diffstat (limited to 'src/vnet/fib/fib_entry.h')
-rw-r--r--src/vnet/fib/fib_entry.h44
1 files changed, 40 insertions, 4 deletions
diff --git a/src/vnet/fib/fib_entry.h b/src/vnet/fib/fib_entry.h
index cd2a685b765..cd954e3a15c 100644
--- a/src/vnet/fib/fib_entry.h
+++ b/src/vnet/fib/fib_entry.h
@@ -29,6 +29,10 @@
*/
typedef enum fib_source_t_ {
/**
+ * An invalid source of value 0
+ */
+ FIB_SOURCE_INVALID,
+ /**
* Marker. Add new values after this one.
*/
FIB_SOURCE_FIRST,
@@ -142,6 +146,7 @@ STATIC_ASSERT (sizeof(fib_source_t) == 1,
#define FIB_SOURCE_MAX (FIB_SOURCE_LAST+1)
#define FIB_SOURCES { \
+ [FIB_SOURCE_INVALID] = "invalid", \
[FIB_SOURCE_SPECIAL] = "special", \
[FIB_SOURCE_INTERFACE] = "interface", \
[FIB_SOURCE_PROXY] = "proxy", \
@@ -377,6 +382,29 @@ typedef struct fib_entry_src_t_ {
} fib_entry_src_t;
/**
+ * FIB entry flags.
+ * these are stored in the pad space within the fib_node_t
+ */
+typedef enum fib_entry_node_attribute_t_
+{
+ /**
+ * FIB entry has multiple sources, so the fe_srcs union
+ * uses the vector
+ */
+ FIB_ENTRY_NODE_ATTR_MULTIPLE_SRCS,
+} fib_entry_node_attribute_t;
+
+#define FIB_ENTRY_NODE_FLAG_NAMES { \
+ [FIB_ENTRY_NODE_ATTR_MULTIPLE_SRCS] = "multiple-srcs", \
+}
+
+typedef enum fib_entry_node_flags_t_
+{
+ FIB_ENTRY_NODE_FLAG_MULTIPLE_SRCS = (1 << FIB_ENTRY_NODE_ATTR_MULTIPLE_SRCS),
+} fib_entry_node_flags_t;
+
+
+/**
* An entry in a FIB table.
*
* This entry represents a route added to the FIB that is stored
@@ -409,12 +437,20 @@ typedef struct fib_entry_t_ {
* type to derive the EOS bit value.
*/
dpo_id_t fe_lb;
+
/**
- * Vector of source infos.
- * Most entries will only have 1 source. So we optimise for memory usage,
- * which is preferable since we have many entries.
+ * Source info.
+ * in the majority of cases a FIB entry will have only one source.
+ * so to save the extra memory allocation of the source's vector, we
+ * store space for one source inline. When two sources are present,
+ * we burn extra memory.
+ * The union is switched based on the FIB_ENTRY_NODE_FLAG_MULTIPLE_SRCS
*/
- fib_entry_src_t *fe_srcs;
+ union {
+ fib_entry_src_t *fe_srcs;
+ fib_entry_src_t fe_src;
+ } fe_u_src;
+
/**
* the path-list for which this entry is a child. This is also the path-list
* that is contributing forwarding for this entry.
>324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 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
/*
 * 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.
 */
/*
 * vnet/buffer.h: vnet buffer flags
 *
 * Copyright (c) 2008 Eliot Dresselhaus
 *
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

#ifndef included_vnet_buffer_h
#define included_vnet_buffer_h

#include <vlib/vlib.h>

/**
 * Flags that are set in the high order bits of ((vlib_buffer*)b)->flags
 */
#define foreach_vnet_buffer_field \
  _( 1, L4_CHECKSUM_COMPUTED, "l4-cksum-computed")	\
  _( 2, L4_CHECKSUM_CORRECT, "l4-cksum-correct")	\
  _( 3, VLAN_2_DEEP, "vlan-2-deep")			\
  _( 4, VLAN_1_DEEP, "vlan-1-deep")			\
  _( 8, SPAN_CLONE, "span-clone")			\
  _( 6, HANDOFF_NEXT_VALID, "handoff-next-valid")	\
  _( 7, LOCALLY_ORIGINATED, "local")			\
  _( 8, IS_IP4, "ip4")					\
  _( 9, IS_IP6, "ip6")					\
  _(10, OFFLOAD_IP_CKSUM, "offload-ip-cksum")		\
  _(11, OFFLOAD_TCP_CKSUM, "offload-tcp-cksum")		\
  _(12, OFFLOAD_UDP_CKSUM, "offload-udp-cksum")		\
  _(13, IS_NATED, "nated")				\
  _(14, L2_HDR_OFFSET_VALID, 0)				\
  _(15, L3_HDR_OFFSET_VALID, 0)				\
  _(16, L4_HDR_OFFSET_VALID, 0)

#define VNET_BUFFER_FLAGS_VLAN_BITS \
  (VNET_BUFFER_F_VLAN_1_DEEP | VNET_BUFFER_F_VLAN_2_DEEP)

enum
{
#define _(bit, name, v) VNET_BUFFER_F_##name  = (1 << LOG2_VLIB_BUFFER_FLAG_USER(bit)),
  foreach_vnet_buffer_field
#undef _
};

enum
{
#define _(bit, name, v) VNET_BUFFER_F_LOG2_##name  = LOG2_VLIB_BUFFER_FLAG_USER(bit),
  foreach_vnet_buffer_field
#undef _
};

/**
 * @brief Flags set in ((vnet_buffer(b)->flags
 */
#define foreach_vnet_opaque_flag \
  _( 1, IS_DVR, "DVR-processed")

enum
{
#define _(bit, name, v) VNET_OPAQUE_F_##name  = (1 << bit),
  foreach_vnet_opaque_flag
#undef _
};

enum
{
#define _(bit, name, v) VNET_OPAQUE_F_LOG2_##name  = bit,
  foreach_vnet_opaque_flag
#undef _
};


#define foreach_buffer_opaque_union_subtype     \
_(ip)                                           \
_(swt)                                          \
_(l2)                                           \
_(l2t)                                          \
_(gre)                                          \
_(l2_classify)                                  \
_(handoff)                                      \
_(policer)                                      \
_(ipsec)					\
_(map)						\
_(map_t)					\
_(ip_frag)					\
_(mpls)					        \
_(tcp)

/*
 * vnet stack buffer opaque array overlay structure.
 * The vnet_buffer_opaque_t *must* be the same size as the
 * vlib_buffer_t "opaque" structure member, 32 bytes.
 *
 * When adding a union type, please add a stanza to
 * foreach_buffer_opaque_union_subtype (directly above).
 * Code in vnet_interface_init(...) verifies the size
 * of the union, and will announce any deviations in an
 * impossible-to-miss manner.
 */
typedef struct
{
  u32 sw_if_index[VLIB_N_RX_TX];
  i16 l2_hdr_offset;
  i16 l3_hdr_offset;
  i16 l4_hdr_offset;
  u16 flags;

  union
  {
    /* IP4/6 buffer opaque. */
    struct
    {
      /* Adjacency from destination IP address lookup [VLIB_TX].
         Adjacency from source IP address lookup [VLIB_RX].
         This gets set to ~0 until source lookup is performed. */
      u32 adj_index[VLIB_N_RX_TX];

      union
      {
	struct
	{
	  /* Flow hash value for this packet computed from IP src/dst address
	     protocol and ports. */
	  u32 flow_hash;

	  union
	  {
	    /* next protocol */
	    u32 save_protocol;

	    /* Hint for transport protocols */
	    u32 fib_index;
	  };

	  /* Rewrite length */
	  u32 save_rewrite_length;

	  /* MFIB RPF ID */
	  u32 rpf_id;
	};

	/* ICMP */
	struct
	{
	  u8 type;
	  u8 code;
	  u32 data;
	} icmp;
      };

    } ip;

    /*
     * MPLS:
     * data copied from the MPLS header that was popped from the packet
     * during the look-up.
     */
    struct
    {
      u8 ttl;
      u8 exp;
      u8 first;
      /*
       * BIER - the nubmer of bytes in the header.
       *  the len field inthe header is not authoritative. It's the
       * value in the table that counts.
       */
      struct
      {
	u8 n_bytes;
      } bier;
    } mpls;

    /* ip4-in-ip6 softwire termination, only valid there */
    struct
    {
      u8 swt_disable;
      u32 mapping_index;
    } swt;

    /* l2 bridging path, only valid there */
    struct opaque_l2
    {
      u32 feature_bitmap;
      u16 bd_index;		/* bridge-domain index */
      u8 l2_len;		/* ethernet header length */
      u8 shg;			/* split-horizon group */
      u16 l2fib_sn;		/* l2fib bd/int seq_num */
      u8 bd_age;		/* aging enabled */
    } l2;

    /* l2tpv3 softwire encap, only valid there */
    struct
    {
      u32 pad[4];		/* do not overlay w/ ip.adj_index[0,1] */
      u8 next_index;
      u32 session_index;
    } l2t;

    struct
    {
      u32 src, dst;
    } gre;

    /* L2 classify */
    struct
    {
      struct opaque_l2 pad;
      union
      {
	u32 table_index;
	u32 opaque_index;
      };
      u64 hash;
    } l2_classify;

    /* IO - worker thread handoff */
    struct
    {
      u32 next_index;
    } handoff;

    /* vnet policer */
    struct
    {
      u32 pad[8 - VLIB_N_RX_TX - 1];	/* to end of opaque */
      u32 index;
    } policer;

    /* interface output features */
    struct
    {
      u32 flags;
      u32 sad_index;
    } ipsec;

    /* MAP */
    struct
    {
      u16 mtu;
    } map;

    /* MAP-T */
    struct
    {
      u32 map_domain_index;
      struct
      {
	u32 saddr, daddr;
	u16 frag_offset;	//Fragmentation header offset
	u16 l4_offset;		//L4 header overall offset
	u8 l4_protocol;		//The final protocol number
      } v6;			//Used by ip6_map_t only
      u16 checksum_offset;	//L4 checksum overall offset
      u16 mtu;			//Exit MTU
    } map_t;

    /* IP Fragmentation */
    struct
    {
      u32 pad[2];		/* do not overlay w/ ip.adj_index[0,1] */
      u16 header_offset;
      u16 mtu;
      u8 next_index;
      u8 flags;			//See ip_frag.h
    } ip_frag;

    /* COP - configurable junk filter(s) */
    struct
    {
      /* Current configuration index. */
      u32 current_config_index;
    } cop;

    /* LISP */
    struct
    {
      /* overlay address family */
      u16 overlay_afi;
    } lisp;

    /* Driver rx feature */
    struct
    {
      u32 saved_next_index;		/**< saved by drivers for short-cut */
      u16 buffer_advance;
    } device_input_feat;

    /* TCP */
    struct
    {
      u32 connection_index;
      u32 seq_number;
      u32 seq_end;
      u32 ack_number;
      u16 hdr_offset;		/**< offset relative to ip hdr */
      u16 data_offset;		/**< offset relative to ip hdr */
      u16 data_len;		/**< data len */
      u8 flags;
    } tcp;

    /* SCTP */
    struct
    {
      u32 connection_index;
      u16 sid; /**< Stream ID */
      u16 ssn; /**< Stream Sequence Number */
      u32 tsn; /**< Transmission Sequence Number */
      u16 hdr_offset;		/**< offset relative to ip hdr */
      u16 data_offset;		/**< offset relative to ip hdr */
      u16 data_len;		/**< data len */
      u8 flags;
    } sctp;

    /* SNAT */
    struct
    {
      u32 flags;
    } snat;

    u32 unused[6];
  };
} vnet_buffer_opaque_t;

/*
 * The opaque field of the vlib_buffer_t is intepreted as a
 * vnet_buffer_opaque_t. Hence it should be big enough to accommodate one.
 */
STATIC_ASSERT (sizeof (vnet_buffer_opaque_t) <=
	       STRUCT_SIZE_OF (vlib_buffer_t, opaque),
	       "VNET buffer meta-data too large for vlib_buffer");

#define vnet_buffer(b) ((vnet_buffer_opaque_t *) (b)->opaque)

/* Full cache line (64 bytes) of additional space */
typedef struct
{
  union
  {
#if VLIB_BUFFER_TRACE_TRAJECTORY > 0
    /* buffer trajectory tracing */
    struct
    {
      u16 *trajectory_trace;
    };
#endif
    u32 unused[12];
  };
} vnet_buffer_opaque2_t;

#define vnet_buffer2(b) ((vnet_buffer_opaque2_t *) (b)->opaque2)

/*
 * The opaque2 field of the vlib_buffer_t is intepreted as a
 * vnet_buffer_opaque2_t. Hence it should be big enough to accommodate one.
 */
STATIC_ASSERT (sizeof (vnet_buffer_opaque2_t) <=
	       STRUCT_SIZE_OF (vlib_buffer_t, opaque2),
	       "VNET buffer opaque2 meta-data too large for vlib_buffer");

format_function_t format_vnet_buffer;

#endif /* included_vnet_buffer_h */

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