ip: Protocol Independent IP Neighbors
[vpp.git] / src / vnet / adj / adj.h
index 0434d7c..1a841ed 100644 (file)
@@ -81,6 +81,9 @@ typedef enum
   /** Multicast Adjacency. */
   IP_LOOKUP_NEXT_MCAST,
 
+  /** Broadcasr Adjacency. */
+  IP_LOOKUP_NEXT_BCAST,
+
   /** Multicast Midchain Adjacency. An Adjacency for sending macst packets
    *  on a tunnel/virtual interface */
   IP_LOOKUP_NEXT_MCAST_MIDCHAIN,
@@ -110,6 +113,7 @@ typedef enum
     [IP_LOOKUP_NEXT_GLEAN] = "ip4-glean",                      \
     [IP_LOOKUP_NEXT_REWRITE] = "ip4-rewrite",                  \
     [IP_LOOKUP_NEXT_MCAST] = "ip4-rewrite-mcast",              \
+    [IP_LOOKUP_NEXT_BCAST] = "ip4-rewrite-bcast",               \
     [IP_LOOKUP_NEXT_MIDCHAIN] = "ip4-midchain",                        \
     [IP_LOOKUP_NEXT_MCAST_MIDCHAIN] = "ip4-mcast-midchain",     \
     [IP_LOOKUP_NEXT_ICMP_ERROR] = "ip4-icmp-error",            \
@@ -122,6 +126,7 @@ typedef enum
     [IP_LOOKUP_NEXT_ARP] = "ip6-discover-neighbor",            \
     [IP_LOOKUP_NEXT_GLEAN] = "ip6-glean",                      \
     [IP_LOOKUP_NEXT_REWRITE] = "ip6-rewrite",                  \
+    [IP_LOOKUP_NEXT_BCAST] = "ip6-rewrite-bcast",              \
     [IP_LOOKUP_NEXT_MCAST] = "ip6-rewrite-mcast",              \
     [IP_LOOKUP_NEXT_MIDCHAIN] = "ip6-midchain",                        \
     [IP_LOOKUP_NEXT_MCAST_MIDCHAIN] = "ip6-mcast-midchain",     \
@@ -131,6 +136,11 @@ typedef enum
     [IP6_LOOKUP_NEXT_POP_HOP_BY_HOP] = "ip6-pop-hop-by-hop",   \
 }
 
+/**
+ * The special broadcast address (to construct a broadcast adjacency
+ */
+extern const ip46_address_t ADJ_BCAST_ADDR;
+
 /**
  * Forward delcartion
  */
@@ -140,21 +150,19 @@ struct ip_adjacency_t_;
  * @brief A function type for post-rewrite fixups on midchain adjacency
  */
 typedef void (*adj_midchain_fixup_t) (vlib_main_t * vm,
-                                     struct ip_adjacency_t_ * adj,
+                                     const struct ip_adjacency_t_ * adj,
                                      vlib_buffer_t * b0,
                                       const void *data);
 
 /**
  * @brief Flags on an IP adjacency
  */
-typedef enum ip_adjacency_flags_t_
+typedef enum adj_attr_t_
 {
-    ADJ_FLAG_NONE = 0,
-
     /**
      * Currently a sync walk is active. Used to prevent re-entrant walking
      */
-    ADJ_FLAG_SYNC_WALK_ACTIVE = (1 << 0),
+    ADJ_ATTR_SYNC_WALK_ACTIVE = 0,
 
     /**
      * Packets TX through the midchain do not increment the interface
@@ -163,21 +171,59 @@ typedef enum ip_adjacency_flags_t_
      * the packet will have traversed the interface's TX node, and hence have
      * been counted, before it traverses ths midchain
      */
-    ADJ_FLAG_MIDCHAIN_NO_COUNT = (1 << 1),
+    ADJ_ATTR_MIDCHAIN_NO_COUNT,
+    /**
+     * When stacking midchains on a fib-entry extract the choice from the
+     * load-balance returned based on an IP hash of the adj's rewrite
+     */
+    ADJ_ATTR_MIDCHAIN_IP_STACK,
+    /**
+     * If the midchain were to stack on its FIB entry a loop would form.
+     */
+    ADJ_ATTR_MIDCHAIN_LOOPED,
+}  adj_attr_t;
+
+#define ADJ_ATTR_NAMES {                                        \
+    [ADJ_ATTR_SYNC_WALK_ACTIVE] = "walk-active",                \
+    [ADJ_ATTR_MIDCHAIN_NO_COUNT] = "midchain-no-count",         \
+    [ADJ_ATTR_MIDCHAIN_IP_STACK] = "midchain-ip-stack",         \
+    [ADJ_ATTR_MIDCHAIN_LOOPED] = "midchain-looped",             \
+}
+
+#define FOR_EACH_ADJ_ATTR(_attr)                 \
+    for (_attr = ADJ_ATTR_SYNC_WALK_ACTIVE;      \
+        _attr <= ADJ_ATTR_MIDCHAIN_LOOPED;      \
+        _attr++)
+
+/**
+ * @brief Flags on an IP adjacency
+ */
+typedef enum adj_flags_t_
+{
+    ADJ_FLAG_NONE = 0,
+    ADJ_FLAG_SYNC_WALK_ACTIVE = (1 << ADJ_ATTR_SYNC_WALK_ACTIVE),
+    ADJ_FLAG_MIDCHAIN_NO_COUNT = (1 << ADJ_ATTR_MIDCHAIN_NO_COUNT),
+    ADJ_FLAG_MIDCHAIN_IP_STACK = (1 << ADJ_ATTR_MIDCHAIN_IP_STACK),
+    ADJ_FLAG_MIDCHAIN_LOOPED = (1 << ADJ_ATTR_MIDCHAIN_LOOPED),
 }  __attribute__ ((packed)) adj_flags_t;
 
+/**
+ * @brief Format adjacency flags
+ */
+extern u8* format_adj_flags(u8 * s, va_list * args);
+
 /**
  * @brief IP unicast adjacency.
  *  @note cache aligned.
  *
- * An adjacency is a represenation of a peer on a particular link.
+ * An adjacency is a representation of a peer on a particular link.
  */
 typedef struct ip_adjacency_t_
 {
   CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
 
   /**
-   * Linkage into the FIB node grpah. First member since this type
+   * Linkage into the FIB node graph. First member since this type
    * has 8 byte alignment requirements.
    */
   fib_node_t ia_node;
@@ -197,7 +243,7 @@ typedef struct ip_adjacency_t_
 
   /**
    * The protocol of the neighbor/peer. i.e. the protocol with
-   * which to interpret the 'next-hop' attirbutes of the sub-types.
+   * which to interpret the 'next-hop' attributes of the sub-types.
    * 1-btyes
    */
   fib_protocol_t ia_nh_proto;
@@ -247,6 +293,11 @@ typedef struct ip_adjacency_t_
        * Fixup data passed back to the client in the fixup function
        */
       const void *fixup_data;
+      /**
+       * the FIB entry this midchain resolves through. required for recursive
+       * loop detection.
+       */
+      fib_node_index_t fei;
     } midchain;
     /**
      * IP_LOOKUP_NEXT_GLEAN
@@ -265,7 +316,7 @@ typedef struct ip_adjacency_t_
   CLIB_CACHE_LINE_ALIGN_MARK (cacheline1);
 
   /* Rewrite in second/third cache lines */
-  vnet_declare_rewrite (VLIB_BUFFER_PRE_DATA_SIZE);
+  VNET_DECLARE_REWRITE;
 
   /**
    * more control plane members that do not fit on the first cacheline
@@ -273,15 +324,19 @@ typedef struct ip_adjacency_t_
   /**
    * A sorted vector of delegates
    */
-  struct adj_delegate_t_ **ia_delegates;
+  struct adj_delegate_t_ *ia_delegates;
 
+  /**
+   * The VLIB node in which this adj is used to forward packets
+   */
+  u32 ia_node_index;
 } ip_adjacency_t;
 
 STATIC_ASSERT ((STRUCT_OFFSET_OF (ip_adjacency_t, cacheline0) == 0),
-              "IP adjacency cachline 0 is not offset");
+              "IP adjacency cacheline 0 is not offset");
 STATIC_ASSERT ((STRUCT_OFFSET_OF (ip_adjacency_t, cacheline1) ==
                CLIB_CACHE_LINE_BYTES),
-              "IP adjacency cachline 1 is more than one cachline size offset");
+              "IP adjacency cacheline 1 is more than one cacheline size offset");
 
 /**
  * @brief
@@ -339,20 +394,20 @@ extern int adj_is_up (adj_index_t ai);
 extern const u8* adj_get_rewrite (adj_index_t ai);
 
 /**
- * @brief Notify the adjacency subsystem that the features settings for
- * an interface have changed
- */
-extern void adj_feature_update (u32 sw_if_index, u8 arc_index, u8 is_enable);
-
-/**
- * @brief Notify the adjacency subsystem that the MTU settings for
- * an HW interface have changed
+ * @brief descend the FIB graph looking for loops
+ *
+ * @param ai
+ *  The adj index to traverse
+ *
+ * @param entry_indicies)
+ *  A pointer to a vector of FIB entries already visited.
  */
-extern void adj_mtu_update (u32 hw_if_index);
+extern int adj_recursive_loop_detect (adj_index_t ai,
+                                      fib_node_index_t **entry_indicies);
 
 /**
  * @brief
- * The global adjacnecy pool. Exposed for fast/inline data-plane access
+ * The global adjacency pool. Exposed for fast/inline data-plane access
  */
 extern ip_adjacency_t *adj_pool;
 
@@ -375,7 +430,13 @@ extern int adj_per_adj_counters;
 static inline ip_adjacency_t *
 adj_get (adj_index_t adj_index)
 {
-    return (vec_elt_at_index(adj_pool, adj_index));
+    return (pool_elt_at_index(adj_pool, adj_index));
+}
+
+static inline int
+adj_is_valid(adj_index_t adj_index)
+{
+  return !(pool_is_free_index(adj_pool, adj_index));
 }
 
 /**