* @brief
* A Data-Path Object is an object that represents actions that are
* applied to packets are they are switched through VPP's data-path.
- *
+ *
* The DPO can be considered to be like is a base class that is specialised
* by other objects to provide concreate actions
*
* instances.
*/
+// clang-format off
+
#ifndef __DPO_H__
#define __DPO_H__
*/
typedef enum dpo_proto_t_
{
-#if CLIB_DEBUG > 0
- DPO_PROTO_IP4 = 1,
-#else
DPO_PROTO_IP4 = 0,
-#endif
DPO_PROTO_IP6,
- DPO_PROTO_ETHERNET,
DPO_PROTO_MPLS,
+ DPO_PROTO_ETHERNET,
+ DPO_PROTO_BIER,
DPO_PROTO_NSH,
} __attribute__((packed)) dpo_proto_t;
[DPO_PROTO_ETHERNET] = "ethernet", \
[DPO_PROTO_MPLS] = "mpls", \
[DPO_PROTO_NSH] = "nsh", \
+ [DPO_PROTO_BIER] = "bier", \
}
#define FOR_EACH_DPO_PROTO(_proto) \
DPO_LOOKUP,
DPO_LISP_CP,
DPO_CLASSIFY,
- DPO_MPLS_LABEL,
- DPO_MPLS_DISPOSITION,
+ DPO_MPLS_DISPOSITION_PIPE,
+ DPO_MPLS_DISPOSITION_UNIFORM,
DPO_MFIB_ENTRY,
- DPO_INTERFACE,
+ DPO_INTERFACE_RX,
+ DPO_INTERFACE_TX,
+ DPO_DVR,
+ DPO_L3_PROXY,
+ DPO_BIER_TABLE,
+ DPO_BIER_FMASK,
+ DPO_BIER_IMP,
+ DPO_BIER_DISP_TABLE,
+ DPO_BIER_DISP_ENTRY,
+ DPO_IP6_LL,
+ DPO_PW_CW,
DPO_LAST,
} __attribute__((packed)) dpo_type_t;
[DPO_REPLICATE] = "dpo-replicate", \
[DPO_LISP_CP] = "dpo-lisp-cp", \
[DPO_CLASSIFY] = "dpo-classify", \
- [DPO_MPLS_LABEL] = "dpo-mpls-label", \
- [DPO_MPLS_DISPOSITION] = "dpo-mpls-diposition", \
- [DPO_MFIB_ENTRY] = "dpo-mfib_entry", \
- [DPO_INTERFACE] = "dpo-interface" \
+ [DPO_MPLS_DISPOSITION_PIPE] = "dpo-mpls-diposition-pipe", \
+ [DPO_MPLS_DISPOSITION_UNIFORM] = "dpo-mpls-diposition-uniform", \
+ [DPO_MFIB_ENTRY] = "dpo-mfib-entry", \
+ [DPO_INTERFACE_RX] = "dpo-interface-rx", \
+ [DPO_INTERFACE_TX] = "dpo-interface-tx", \
+ [DPO_DVR] = "dpo-dvr", \
+ [DPO_L3_PROXY] = "dpo-l3-proxy", \
+ [DPO_BIER_TABLE] = "bier-table", \
+ [DPO_BIER_FMASK] = "bier-fmask", \
+ [DPO_BIER_IMP] = "bier-imposition", \
+ [DPO_BIER_DISP_ENTRY] = "bier-disp-entry", \
+ [DPO_BIER_DISP_TABLE] = "bier-disp-table", \
+ [DPO_IP6_LL] = "ip6-link-local", \
+ [DPO_PW_CW] = "PW-CW", \
}
/**
* instance number/index of objects of that type
*/
typedef struct dpo_id_t_ {
- /**
- * the type
- */
- dpo_type_t dpoi_type;
- /**
- * the data-path protocol of the type.
- */
- dpo_proto_t dpoi_proto;
- /**
- * The next VLIB node to follow.
- */
- u16 dpoi_next_node;
- /**
- * the index of objects of that type
- */
- index_t dpoi_index;
-} __attribute__ ((aligned(sizeof(u64)))) dpo_id_t;
+ union {
+ struct {
+ /**
+ * the type
+ */
+ dpo_type_t dpoi_type;
+ /**
+ * the data-path protocol of the type.
+ */
+ dpo_proto_t dpoi_proto;
+ /**
+ * The next VLIB node to follow.
+ */
+ u16 dpoi_next_node;
+ /**
+ * the index of objects of that type
+ */
+ index_t dpoi_index;
+ };
+ u64 as_u64;
+ };
+} dpo_id_t;
STATIC_ASSERT(sizeof(dpo_id_t) <= sizeof(u64),
"DPO ID is greater than sizeof u64 "
*/
extern void dpo_unlock(dpo_id_t *dpo);
+/**
+ * @brief
+ * Make an interpose DPO from an original
+ */
+extern void dpo_mk_interpose(const dpo_id_t *original,
+ const dpo_id_t *parent,
+ dpo_id_t *clone);
+
/**
* @brief Set/create a DPO ID
* The DPO will be locked.
extern int dpo_is_adj(const dpo_id_t *dpo);
/**
- * @biref Format a DPO_id_t oject
+ * @brief Format a DPO_id_t oject
*/
extern u8 *format_dpo_id(u8 * s, va_list * args);
/**
- * @biref format a DPO type
+ * @brief format a DPO type
*/
extern u8 *format_dpo_type(u8 * s, va_list * args);
*/
extern u8 *format_dpo_proto(u8 * s, va_list * args);
+/**
+ * @brief format a DPO protocol
+ */
+extern vnet_link_t dpo_proto_to_link(dpo_proto_t dp);
+
/**
* @brief
* Set and stack a DPO.
const dpo_id_t *parent_dpo);
/**
- * @brief
+ * @brief
* Set and stack a DPO.
* The DPO passed is set to the parent DPO and the necessary
* VLIB graph arcs are created, from the child_node passed.
*
* @param child_node
- * The VLIB grpah node index to create an arc from to the parent
+ * The VLIB graph node index to create an arc from to the parent
*
- * @parem dpo
+ * @param dpo
* This is the DPO to stack and set.
*
- * @paren parent_dpo
+ * @param parent_dpo
* The parent DPO to stack onto.
- */
+ */
extern void dpo_stack_from_node(u32 child_node,
dpo_id_t *dpo,
const dpo_id_t *parent);
+/**
+ * Get a uRPF interface for the DPO
+ *
+ * @param dpo
+ * The DPO from which to get the uRPF interface
+ *
+ * @return valid SW interface index or ~0
+ */
+extern u32 dpo_get_urpf(const dpo_id_t *dpo);
+
+/**
+ * Get the MTU DPO
+ *
+ * @param dpo
+ * The DPO from which to get the MTU
+ *
+ * @return MTU (0xffff if something more usefull was unavailable)
+ */
+extern u16 dpo_get_mtu(const dpo_id_t *dpo);
+
/**
* @brief A lock function registered for a DPO type
*/
*/
typedef void (*dpo_mem_show_t)(void);
+/**
+ * @brief Given a DPO instance return a vector of node indices that
+ * the type/instance will use.
+ */
+typedef u32* (*dpo_get_next_node_t)(const dpo_id_t *dpo);
+
+/**
+ * @brief Given a DPO instance return an interface that can
+ * be used in an uRPF check
+ */
+typedef u32 (*dpo_get_urpf_t)(const dpo_id_t *dpo);
+
+/**
+ * @brief Given a DPO instance return the MTU
+ */
+typedef u16 (*dpo_get_mtu_t)(const dpo_id_t *dpo);
+
+/**
+ * @brief Called during FIB interposition when the originally
+ * registered DPO is used to 'clone' an instance for interposition
+ * at a particular location in the FIB graph.
+ * The parent is the next DPO in the chain that the clone will
+ * be used instead of. The clone may then choose to stack itself
+ * on the parent.
+ */
+typedef void (*dpo_mk_interpose_t)(const dpo_id_t *original,
+ const dpo_id_t *parent,
+ dpo_id_t *clone);
+
/**
* @brief A virtual function table regisitered for a DPO type
*/
* A show memory usage function
*/
dpo_mem_show_t dv_mem_show;
+ /**
+ * A function to get the next VLIB node given an instance
+ * of the DPO. If this is null, then the node's name MUST be
+ * retreiveable from the nodes names array passed in the register
+ * function
+ */
+ dpo_get_next_node_t dv_get_next_node;
+ /**
+ * Get uRPF interface
+ */
+ dpo_get_urpf_t dv_get_urpf;
+ /**
+ * Get MTU
+ */
+ dpo_get_mtu_t dv_get_mtu;
+ /**
+ * Signal on an interposed child that the parent has changed
+ */
+ dpo_mk_interpose_t dv_mk_interpose;
} dpo_vft_t;
* (see above).
*
* @param type
- * The type being registered.
+ * The type being registered.
*
* @param vft
* The virtual function table to register for the type.
extern dpo_type_t dpo_register_new_type(const dpo_vft_t *vft,
const char * const * const * nodes);
+/**
+ * @brief Return already stacked up next node index for a given
+ * child_type/child_proto and parent_type/patent_proto.
+ * The VLIB graph arc used is taken from the parent and child types
+ * passed.
+ *
+ * @param child_type
+ * Child DPO type.
+ *
+ * @param child_proto
+ * Child DPO proto
+ *
+ * @param parent_type
+ * Parent DPO type.
+ *
+ * @param parent_proto
+ * Parent DPO proto
+ *
+ * @return The VLIB Graph node index
+ */
+extern u32
+dpo_get_next_node_by_type_and_proto (dpo_type_t child_type,
+ dpo_proto_t child_proto,
+ dpo_type_t parent_type,
+ dpo_proto_t parent_proto);
+
+
+/**
+ * @brief Barrier sync if a dpo pool is about to expand
+ *
+ * @param VM (output)
+ * vlib_main_t *, invariably &vlib_global_main
+ *
+ * @param P
+ * pool pointer
+ *
+ * @param YESNO (output)
+ * typically a u8, 1 => expand will occur, worker barrier held
+ * 0 => no expand, barrier not held
+ *
+ * @return YESNO set
+ */
+
+#define dpo_pool_barrier_sync(VM,P,YESNO) \
+do { \
+ pool_get_aligned_will_expand ((P), YESNO, CLIB_CACHE_LINE_BYTES); \
+ \
+ if (YESNO) \
+ { \
+ VM = vlib_get_main(); \
+ ASSERT ((VM)->thread_index == 0); \
+ vlib_worker_thread_barrier_sync((VM)); \
+ } \
+} while(0);
+
+/**
+ * @brief Release barrier sync after dpo pool expansion
+ *
+ * @param VM
+ * vlib_main_t pointer, must be &vlib_global_main
+ *
+ * @param YESNO
+ * typically a u8, 1 => release required
+ * 0 => no release required
+ * @return none
+ */
+
+#define dpo_pool_barrier_release(VM,YESNO) \
+ if ((YESNO)) vlib_worker_thread_barrier_release((VM));
+
#endif
+
+// clang-format on