aboutsummaryrefslogtreecommitdiffstats
path: root/src/vnet/fib
diff options
context:
space:
mode:
authorNeale Ranns <nranns@cisco.com>2017-03-01 15:12:11 -0800
committerNeale Ranns <nranns@cisco.com>2017-04-07 09:12:12 +0000
commit0f26c5a0138ac86d7ebd197c31a09d8d624c35fe (patch)
tree5cee4659885432c439e44d7346fd5e482df5f0e6 /src/vnet/fib
parentc14f31c2c62fb66d98aef4402a6f1bda09683fd3 (diff)
MPLS Mcast
1 - interface-DPO Used in the Data-plane to change a packet's input interface 2 - MPLS multicast FIB entry Same as a unicast entry but it links to a replicate not a load-balance DPO 3 - Multicast MPLS tunnel Update MPLS tunnels to use a FIB path-list to describe the endpoint[s]. Use the path-list to generate the forwarding chain (DPOs) to link to . 4 - Resolve a path via a local label (of an mLDP LSP) For IP multicast entries to use an LSP in the replication list, we need to decribe the 'resolve-via-label' where the label is that of a multicast LSP. 5 - MPLS disposition path sets RPF-ID For a interface-less LSP (i.e. mLDP not RSVP-TE) at the tail of the LSP we still need to perform an RPF check. An MPLS disposition DPO performs the MPLS pop validation checks and sets the RPF-ID in the packet. 6 - RPF check with per-entry RPF-ID An RPF-ID is used instead of a real interface SW if index in the case the IP traffic arrives from an LSP that does not have an associated interface. Change-Id: Ib92e177be919147bafeb599729abf3d1abc2f4b3 Signed-off-by: Neale Ranns <nranns@cisco.com>
Diffstat (limited to 'src/vnet/fib')
-rw-r--r--src/vnet/fib/fib_api.h4
-rw-r--r--src/vnet/fib/fib_entry.c47
-rw-r--r--src/vnet/fib/fib_entry.h13
-rw-r--r--src/vnet/fib/fib_entry_src.c154
-rw-r--r--src/vnet/fib/fib_internal.h1
-rw-r--r--src/vnet/fib/fib_path.c222
-rw-r--r--src/vnet/fib/fib_path.h17
-rw-r--r--src/vnet/fib/fib_path_ext.c4
-rw-r--r--src/vnet/fib/fib_path_ext.h3
-rw-r--r--src/vnet/fib/fib_path_list.c270
-rw-r--r--src/vnet/fib/fib_path_list.h22
-rw-r--r--src/vnet/fib/fib_table.c47
-rw-r--r--src/vnet/fib/fib_test.c345
-rw-r--r--src/vnet/fib/fib_test.h111
-rw-r--r--src/vnet/fib/fib_types.c15
-rw-r--r--src/vnet/fib/fib_types.h60
-rw-r--r--src/vnet/fib/mpls_fib.c15
17 files changed, 1039 insertions, 311 deletions
diff --git a/src/vnet/fib/fib_api.h b/src/vnet/fib/fib_api.h
index f82753170db..10d0cb58a95 100644
--- a/src/vnet/fib/fib_api.h
+++ b/src/vnet/fib/fib_api.h
@@ -24,6 +24,7 @@ add_del_route_check (fib_protocol_t table_proto,
fib_protocol_t next_hop_table_proto,
u32 next_hop_table_id,
u8 create_missing_tables,
+ u8 is_rpf_id,
u32 * fib_index, u32 * next_hop_fib_index);
int
@@ -33,10 +34,13 @@ add_del_route_t_handler (u8 is_multipath,
u8 is_unreach,
u8 is_prohibit,
u8 is_local,
+ u8 is_multicast,
u8 is_classify,
u32 classify_table_index,
u8 is_resolve_host,
u8 is_resolve_attached,
+ u8 is_interface_rx,
+ u8 is_rpf_id,
u32 fib_index,
const fib_prefix_t * prefix,
u8 next_hop_proto_is_ip4,
diff --git a/src/vnet/fib/fib_entry.c b/src/vnet/fib/fib_entry.c
index dac1fce995f..6f811aa1414 100644
--- a/src/vnet/fib/fib_entry.c
+++ b/src/vnet/fib/fib_entry.c
@@ -75,13 +75,7 @@ fib_entry_get_default_chain_type (const fib_entry_t *fib_entry)
return (FIB_FORW_CHAIN_TYPE_UNICAST_IP6);
case FIB_PROTOCOL_MPLS:
if (MPLS_EOS == fib_entry->fe_prefix.fp_eos)
- /*
- * If the entry being asked is a eos-MPLS label entry,
- * then use the payload-protocol field, that we stashed there
- * for just this purpose
- */
- return (fib_forw_chain_type_from_dpo_proto(
- fib_entry->fe_prefix.fp_payload_proto));
+ return (FIB_FORW_CHAIN_TYPE_MPLS_EOS);
else
return (FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS);
}
@@ -371,6 +365,35 @@ fib_entry_contribute_urpf (fib_node_index_t entry_index,
}
/*
+ * If the client is request a chain for multicast forwarding then swap
+ * the chain type to one that can provide such transport.
+ */
+static fib_forward_chain_type_t
+fib_entry_chain_type_mcast_to_ucast (fib_forward_chain_type_t fct)
+{
+ switch (fct)
+ {
+ case FIB_FORW_CHAIN_TYPE_MCAST_IP4:
+ case FIB_FORW_CHAIN_TYPE_MCAST_IP6:
+ /*
+ * we can only transport IP multicast packets if there is an
+ * LSP.
+ */
+ fct = FIB_FORW_CHAIN_TYPE_MPLS_EOS;
+ break;
+ case FIB_FORW_CHAIN_TYPE_MPLS_EOS:
+ case FIB_FORW_CHAIN_TYPE_UNICAST_IP4:
+ case FIB_FORW_CHAIN_TYPE_UNICAST_IP6:
+ case FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS:
+ case FIB_FORW_CHAIN_TYPE_ETHERNET:
+ case FIB_FORW_CHAIN_TYPE_NSH:
+ break;
+ }
+
+ return (fct);
+}
+
+/*
* fib_entry_contribute_forwarding
*
* Get an lock the forwarding information (DPO) contributed by the FIB entry.
@@ -385,6 +408,11 @@ fib_entry_contribute_forwarding (fib_node_index_t fib_entry_index,
fib_entry = fib_entry_get(fib_entry_index);
+ /*
+ * mfib children ask for mcast chains. fix these to the appropriate ucast types.
+ */
+ fct = fib_entry_chain_type_mcast_to_ucast(fct);
+
if (fct == fib_entry_get_default_chain_type(fib_entry))
{
dpo_copy(dpo, &fib_entry->fe_lb);
@@ -414,6 +442,11 @@ fib_entry_contribute_forwarding (fib_node_index_t fib_entry_index,
dpo_copy(dpo, &fed->fd_dpo);
}
+ /*
+ * don't allow the special index indicating replicate.vs.load-balance
+ * to escape to the clients
+ */
+ dpo->dpoi_index &= ~MPLS_IS_REPLICATE;
}
const dpo_id_t *
diff --git a/src/vnet/fib/fib_entry.h b/src/vnet/fib/fib_entry.h
index a3f75e6084a..b17a0b6444c 100644
--- a/src/vnet/fib/fib_entry.h
+++ b/src/vnet/fib/fib_entry.h
@@ -193,6 +193,11 @@ typedef enum fib_entry_attribute_t_ {
*/
FIB_ENTRY_ATTRIBUTE_LOCAL,
/**
+ * The prefix/address is a multicast prefix.
+ * this aplies only to MPLS. IP multicast is handled by mfib
+ */
+ FIB_ENTRY_ATTRIBUTE_MULTICAST,
+ /**
* The prefix/address exempted from loose uRPF check
* To be used with caution
*/
@@ -200,7 +205,7 @@ typedef enum fib_entry_attribute_t_ {
/**
* Marker. add new entries before this one.
*/
- FIB_ENTRY_ATTRIBUTE_LAST = FIB_ENTRY_ATTRIBUTE_URPF_EXEMPT,
+ FIB_ENTRY_ATTRIBUTE_LAST = FIB_ENTRY_ATTRIBUTE_MULTICAST,
} fib_entry_attribute_t;
/**
@@ -215,7 +220,8 @@ typedef enum fib_entry_attribute_t_ {
[FIB_ENTRY_ATTRIBUTE_DROP] = "drop", \
[FIB_ENTRY_ATTRIBUTE_EXCLUSIVE] = "exclusive", \
[FIB_ENTRY_ATTRIBUTE_LOCAL] = "local", \
- [FIB_ENTRY_ATTRIBUTE_URPF_EXEMPT] = "uRPF-exempt" \
+ [FIB_ENTRY_ATTRIBUTE_URPF_EXEMPT] = "uRPF-exempt", \
+ [FIB_ENTRY_ATTRIBUTE_MULTICAST] = "multicast", \
}
#define FOR_EACH_FIB_ATTRIBUTE(_item) \
@@ -232,6 +238,7 @@ typedef enum fib_entry_flag_t_ {
FIB_ENTRY_FLAG_LOCAL = (1 << FIB_ENTRY_ATTRIBUTE_LOCAL),
FIB_ENTRY_FLAG_IMPORT = (1 << FIB_ENTRY_ATTRIBUTE_IMPORT),
FIB_ENTRY_FLAG_LOOSE_URPF_EXEMPT = (1 << FIB_ENTRY_ATTRIBUTE_URPF_EXEMPT),
+ FIB_ENTRY_FLAG_MULTICAST = (1 << FIB_ENTRY_ATTRIBUTE_MULTICAST),
} __attribute__((packed)) fib_entry_flag_t;
/**
@@ -396,7 +403,7 @@ typedef struct fib_entry_t_ {
* paint the header straight on without the need to check the packet
* type to derive the EOS bit value.
*/
- dpo_id_t fe_lb; // [FIB_FORW_CHAIN_MPLS_NUM];
+ dpo_id_t fe_lb;
/**
* Vector of source infos.
* Most entries will only have 1 source. So we optimise for memory usage,
diff --git a/src/vnet/fib/fib_entry_src.c b/src/vnet/fib/fib_entry_src.c
index aa1d5a24a0f..a700282ee9b 100644
--- a/src/vnet/fib/fib_entry_src.c
+++ b/src/vnet/fib/fib_entry_src.c
@@ -17,6 +17,7 @@
#include <vnet/dpo/load_balance.h>
#include <vnet/dpo/mpls_label_dpo.h>
#include <vnet/dpo/drop_dpo.h>
+#include <vnet/dpo/replicate_dpo.h>
#include <vnet/fib/fib_entry_src.h>
#include <vnet/fib/fib_table.h>
@@ -229,8 +230,6 @@ fib_forward_chain_type_t
fib_entry_chain_type_fixup (const fib_entry_t *entry,
fib_forward_chain_type_t fct)
{
- ASSERT(FIB_FORW_CHAIN_TYPE_MPLS_EOS == fct);
-
/*
* The EOS chain is a tricky since one cannot know the adjacency
* to link to without knowing what the packets payload protocol
@@ -238,6 +237,11 @@ fib_entry_chain_type_fixup (const fib_entry_t *entry,
*/
fib_forward_chain_type_t dfct;
+ if (FIB_FORW_CHAIN_TYPE_MPLS_EOS != fct)
+ {
+ return (fct);
+ }
+
dfct = fib_entry_get_default_chain_type(entry);
if (FIB_FORW_CHAIN_TYPE_MPLS_EOS == dfct)
@@ -303,7 +307,12 @@ fib_entry_src_collect_forwarding (fib_node_index_t pl_index,
* found a matching extension. stack it to obtain the forwarding
* info for this path.
*/
- ctx->next_hops = fib_path_ext_stack(path_ext, ctx->fib_entry, ctx->fct, ctx->next_hops);
+ ctx->next_hops =
+ fib_path_ext_stack(path_ext,
+ ctx->fct,
+ fib_entry_chain_type_fixup(ctx->fib_entry,
+ ctx->fct),
+ ctx->next_hops);
}
else
{
@@ -355,6 +364,9 @@ fib_entry_src_collect_forwarding (fib_node_index_t pl_index,
fib_entry_chain_type_fixup(ctx->fib_entry,
ctx->fct),
&nh->path_dpo);
+ fib_path_stack_mpls_disp(path_index,
+ ctx->fib_entry->fe_prefix.fp_payload_proto,
+ &nh->path_dpo);
break;
}
@@ -424,50 +436,70 @@ fib_entry_src_mk_lb (fib_entry_t *fib_entry,
/*
* first time create
*/
- flow_hash_config_t fhc;
-
- fhc = fib_table_get_flow_hash_config(fib_entry->fe_fib_index,
- dpo_proto_to_fib(lb_proto));
- dpo_set(dpo_lb,
- DPO_LOAD_BALANCE,
- lb_proto,
- load_balance_create(0, lb_proto, fhc));
+ if (esrc->fes_entry_flags & FIB_ENTRY_FLAG_MULTICAST)
+ {
+ dpo_set(dpo_lb,
+ DPO_REPLICATE,
+ lb_proto,
+ MPLS_IS_REPLICATE | replicate_create(0, lb_proto));
+ }
+ else
+ {
+ flow_hash_config_t fhc;
+
+ fhc = fib_table_get_flow_hash_config(fib_entry->fe_fib_index,
+ dpo_proto_to_fib(lb_proto));
+ dpo_set(dpo_lb,
+ DPO_LOAD_BALANCE,
+ lb_proto,
+ load_balance_create(0, lb_proto, fhc));
+ }
}
- load_balance_multipath_update(dpo_lb,
- ctx.next_hops,
- fib_entry_calc_lb_flags(&ctx));
- vec_free(ctx.next_hops);
-
- /*
- * if this entry is sourced by the uRPF-exempt source then we
- * append the always present local0 interface (index 0) to the
- * uRPF list so it is not empty. that way packets pass the loose check.
- */
- index_t ui = fib_path_list_get_urpf(esrc->fes_pl);
-
- if ((fib_entry_is_sourced(fib_entry_get_index(fib_entry),
- FIB_SOURCE_URPF_EXEMPT) ||
- (esrc->fes_entry_flags & FIB_ENTRY_FLAG_LOOSE_URPF_EXEMPT))&&
- (0 == fib_urpf_check_size(ui)))
+ if (esrc->fes_entry_flags & FIB_ENTRY_FLAG_MULTICAST)
{
- /*
- * The uRPF list we get from the path-list is shared by all
- * other users of the list, but the uRPF exemption applies
- * only to this prefix. So we need our own list.
- */
- ui = fib_urpf_list_alloc_and_lock();
- fib_urpf_list_append(ui, 0);
- fib_urpf_list_bake(ui);
- load_balance_set_urpf(dpo_lb->dpoi_index, ui);
- fib_urpf_list_unlock(ui);
+ /*
+ * MPLS multicast
+ */
+ replicate_multipath_update(dpo_lb, ctx.next_hops);
}
else
{
- load_balance_set_urpf(dpo_lb->dpoi_index, ui);
+ load_balance_multipath_update(dpo_lb,
+ ctx.next_hops,
+ fib_entry_calc_lb_flags(&ctx));
+ vec_free(ctx.next_hops);
+
+ /*
+ * if this entry is sourced by the uRPF-exempt source then we
+ * append the always present local0 interface (index 0) to the
+ * uRPF list so it is not empty. that way packets pass the loose check.
+ */
+ index_t ui = fib_path_list_get_urpf(esrc->fes_pl);
+
+ if ((fib_entry_is_sourced(fib_entry_get_index(fib_entry),
+ FIB_SOURCE_URPF_EXEMPT) ||
+ (esrc->fes_entry_flags & FIB_ENTRY_FLAG_LOOSE_URPF_EXEMPT))&&
+ (0 == fib_urpf_check_size(ui)))
+ {
+ /*
+ * The uRPF list we get from the path-list is shared by all
+ * other users of the list, but the uRPF exemption applies
+ * only to this prefix. So we need our own list.
+ */
+ ui = fib_urpf_list_alloc_and_lock();
+ fib_urpf_list_append(ui, 0);
+ fib_urpf_list_bake(ui);
+ load_balance_set_urpf(dpo_lb->dpoi_index, ui);
+ fib_urpf_list_unlock(ui);
+ }
+ else
+ {
+ load_balance_set_urpf(dpo_lb->dpoi_index, ui);
+ }
+ load_balance_set_fib_entry_flags(dpo_lb->dpoi_index,
+ fib_entry_get_flags_i(fib_entry));
}
- load_balance_set_fib_entry_flags(dpo_lb->dpoi_index,
- fib_entry_get_flags_i(fib_entry));
}
void
@@ -887,21 +919,6 @@ fib_entry_src_action_remove (fib_entry_t *fib_entry,
return (sflags);
}
-static inline int
-fib_route_recurses_via_self (const fib_prefix_t *prefix,
- const fib_route_path_t *rpath)
-{
- /*
- * not all zeros next hop &&
- * is recursive path &&
- * nexthop is same as the route's address
- */
- return ((!ip46_address_is_zero(&rpath->frp_addr)) &&
- (~0 == rpath->frp_sw_if_index) &&
- (0 == ip46_address_cmp(&rpath->frp_addr, &prefix->fp_addr)));
-
-}
-
/*
* fib_route_attached_cross_table
*
@@ -962,14 +979,14 @@ fib_entry_src_flags_2_path_list_flags (fib_entry_flag_t eflags)
{
plf |= FIB_PATH_LIST_FLAG_DROP;
}
- if (eflags & FIB_ENTRY_FLAG_LOCAL)
- {
- plf |= FIB_PATH_LIST_FLAG_LOCAL;
- }
if (eflags & FIB_ENTRY_FLAG_EXCLUSIVE)
{
plf |= FIB_PATH_LIST_FLAG_EXCLUSIVE;
}
+ if (eflags & FIB_ENTRY_FLAG_LOCAL)
+ {
+ plf |= FIB_PATH_LIST_FLAG_LOCAL;
+ }
return (plf);
}
@@ -980,25 +997,6 @@ fib_entry_flags_update (const fib_entry_t *fib_entry,
fib_path_list_flags_t *pl_flags,
fib_entry_src_t *esrc)
{
- /*
- * don't allow the addition of a recursive looped path for prefix
- * via itself.
- */
- if (fib_route_recurses_via_self(&fib_entry->fe_prefix, rpath))
- {
- /*
- * force the install of a drop path-list.
- * we want the entry to have some path-list, mainly so
- * the dodgy path can be rmeoved when the source stops playing
- * silly buggers.
- */
- *pl_flags |= FIB_PATH_LIST_FLAG_DROP;
- }
- else
- {
- *pl_flags &= ~FIB_PATH_LIST_FLAG_DROP;
- }
-
if ((esrc->fes_src == FIB_SOURCE_API) ||
(esrc->fes_src == FIB_SOURCE_CLI))
{
diff --git a/src/vnet/fib/fib_internal.h b/src/vnet/fib/fib_internal.h
index 2d980bcce0a..8abc0e07313 100644
--- a/src/vnet/fib/fib_internal.h
+++ b/src/vnet/fib/fib_internal.h
@@ -25,6 +25,7 @@
#undef FIB_DEBUG
extern void fib_prefix_from_mpls_label(mpls_label_t label,
+ mpls_eos_bit_t eos,
fib_prefix_t *prf);
extern int fib_route_path_cmp(const fib_route_path_t *rpath1,
diff --git a/src/vnet/fib/fib_path.c b/src/vnet/fib/fib_path.c
index 6b202a97824..f81f41706c5 100644
--- a/src/vnet/fib/fib_path.c
+++ b/src/vnet/fib/fib_path.c
@@ -21,6 +21,8 @@
#include <vnet/dpo/receive_dpo.h>
#include <vnet/dpo/load_balance_map.h>
#include <vnet/dpo/lookup_dpo.h>
+#include <vnet/dpo/interface_dpo.h>
+#include <vnet/dpo/mpls_disposition.h>
#include <vnet/adj/adj.h>
#include <vnet/adj/adj_mcast.h>
@@ -67,6 +69,10 @@ typedef enum fib_path_type_t_ {
*/
FIB_PATH_TYPE_DEAG,
/**
+ * interface receive.
+ */
+ FIB_PATH_TYPE_INTF_RX,
+ /**
* receive. it's for-us.
*/
FIB_PATH_TYPE_RECEIVE,
@@ -88,6 +94,7 @@ typedef enum fib_path_type_t_ {
[FIB_PATH_TYPE_SPECIAL] = "special", \
[FIB_PATH_TYPE_EXCLUSIVE] = "exclusive", \
[FIB_PATH_TYPE_DEAG] = "deag", \
+ [FIB_PATH_TYPE_INTF_RX] = "intf-rx", \
[FIB_PATH_TYPE_RECEIVE] = "receive", \
}
@@ -220,10 +227,16 @@ typedef struct fib_path_t_ {
* The next-hop
*/
ip46_address_t fp_ip;
- /**
- * The local label to resolve through.
- */
- mpls_label_t fp_local_label;
+ struct {
+ /**
+ * The local label to resolve through.
+ */
+ mpls_label_t fp_local_label;
+ /**
+ * The EOS bit of the resolving label
+ */
+ mpls_eos_bit_t fp_eos;
+ };
} fp_nh;
/**
* The FIB table index in which to find the next-hop.
@@ -254,6 +267,10 @@ typedef struct fib_path_t_ {
* The FIB index in which to perfom the next lookup
*/
fib_node_index_t fp_tbl_id;
+ /**
+ * The RPF-ID to tag the packets with
+ */
+ fib_rpf_id_t fp_rpf_id;
} deag;
struct {
} special;
@@ -273,6 +290,12 @@ typedef struct fib_path_t_ {
*/
ip46_address_t fp_addr;
} receive;
+ struct {
+ /**
+ * The interface on which the packets will be input.
+ */
+ u32 fp_interface;
+ } intf_rx;
};
STRUCT_MARK(path_hash_end);
@@ -444,9 +467,11 @@ format_fib_path (u8 * s, va_list * args)
case FIB_PATH_TYPE_RECURSIVE:
if (FIB_PROTOCOL_MPLS == path->fp_nh_proto)
{
- s = format (s, "via %U",
+ s = format (s, "via %U %U",
format_mpls_unicast_label,
- path->recursive.fp_nh.fp_local_label);
+ path->recursive.fp_nh.fp_local_label,
+ format_mpls_eos_bit,
+ path->recursive.fp_nh.fp_eos);
}
else
{
@@ -465,6 +490,7 @@ format_fib_path (u8 * s, va_list * args)
break;
case FIB_PATH_TYPE_RECEIVE:
+ case FIB_PATH_TYPE_INTF_RX:
case FIB_PATH_TYPE_SPECIAL:
case FIB_PATH_TYPE_DEAG:
case FIB_PATH_TYPE_EXCLUSIVE:
@@ -736,6 +762,7 @@ fib_path_unresolve (fib_path_t *path)
break;
case FIB_PATH_TYPE_SPECIAL:
case FIB_PATH_TYPE_RECEIVE:
+ case FIB_PATH_TYPE_INTF_RX:
case FIB_PATH_TYPE_DEAG:
/*
* these hold only the path's DPO, which is reset below.
@@ -754,16 +781,24 @@ fib_path_unresolve (fib_path_t *path)
}
static fib_forward_chain_type_t
-fib_path_proto_to_chain_type (fib_protocol_t proto)
+fib_path_to_chain_type (const fib_path_t *path)
{
- switch (proto)
+ switch (path->fp_nh_proto)
{
case FIB_PROTOCOL_IP4:
return (FIB_FORW_CHAIN_TYPE_UNICAST_IP4);
case FIB_PROTOCOL_IP6:
return (FIB_FORW_CHAIN_TYPE_UNICAST_IP6);
case FIB_PROTOCOL_MPLS:
- return (FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS);
+ if (FIB_PATH_TYPE_RECURSIVE == path->fp_type &&
+ MPLS_EOS == path->recursive.fp_nh.fp_eos)
+ {
+ return (FIB_FORW_CHAIN_TYPE_MPLS_EOS);
+ }
+ else
+ {
+ return (FIB_FORW_CHAIN_TYPE_MPLS_EOS);
+ }
}
return (FIB_FORW_CHAIN_TYPE_UNICAST_IP4);
}
@@ -793,7 +828,7 @@ fib_path_back_walk_notify (fib_node_t *node,
*/
fib_path_recursive_adj_update(
path,
- fib_path_proto_to_chain_type(path->fp_nh_proto),
+ fib_path_to_chain_type(path),
&path->fp_dpo);
}
if ((FIB_NODE_BW_REASON_FLAG_ADJ_UPDATE & ctx->fnbw_reason) ||
@@ -931,6 +966,8 @@ FIXME comment
path->fp_oper_flags |= FIB_PATH_OPER_FLAG_DROP;
}
break;
+ case FIB_PATH_TYPE_INTF_RX:
+ ASSERT(0);
case FIB_PATH_TYPE_DEAG:
/*
* FIXME When VRF delete is allowed this will need a poke.
@@ -986,6 +1023,14 @@ fib_path_route_flags_to_cfg_flags (const fib_route_path_t *rpath)
cfg_flags |= FIB_PATH_CFG_FLAG_LOCAL;
if (rpath->frp_flags & FIB_ROUTE_PATH_ATTACHED)
cfg_flags |= FIB_PATH_CFG_FLAG_ATTACHED;
+ if (rpath->frp_flags & FIB_ROUTE_PATH_INTF_RX)
+ cfg_flags |= FIB_PATH_CFG_FLAG_INTF_RX;
+ if (rpath->frp_flags & FIB_ROUTE_PATH_RPF_ID)
+ cfg_flags |= FIB_PATH_CFG_FLAG_RPF_ID;
+ if (rpath->frp_flags & FIB_ROUTE_PATH_EXCLUSIVE)
+ cfg_flags |= FIB_PATH_CFG_FLAG_EXCLUSIVE;
+ if (rpath->frp_flags & FIB_ROUTE_PATH_DROP)
+ cfg_flags |= FIB_PATH_CFG_FLAG_DROP;
return (cfg_flags);
}
@@ -998,8 +1043,6 @@ fib_path_route_flags_to_cfg_flags (const fib_route_path_t *rpath)
*/
fib_node_index_t
fib_path_create (fib_node_index_t pl_index,
- fib_protocol_t nh_proto,
- fib_path_cfg_flags_t flags,
const fib_route_path_t *rpath)
{
fib_path_t *path;
@@ -1012,7 +1055,7 @@ fib_path_create (fib_node_index_t pl_index,
dpo_reset(&path->fp_dpo);
path->fp_pl_index = pl_index;
- path->fp_nh_proto = nh_proto;
+ path->fp_nh_proto = rpath->frp_proto;
path->fp_via_fib = FIB_NODE_INDEX_INVALID;
path->fp_weight = rpath->frp_weight;
if (0 == path->fp_weight)
@@ -1023,8 +1066,7 @@ fib_path_create (fib_node_index_t pl_index,
*/
path->fp_weight = 1;
}
- path->fp_cfg_flags = flags;
- path->fp_cfg_flags |= fib_path_route_flags_to_cfg_flags(rpath);
+ path->fp_cfg_flags = fib_path_route_flags_to_cfg_flags(rpath);
/*
* deduce the path's tpye from the parementers and save what is needed.
@@ -1035,6 +1077,17 @@ fib_path_create (fib_node_index_t pl_index,
path->receive.fp_interface = rpath->frp_sw_if_index;
path->receive.fp_addr = rpath->frp_addr;
}
+ else if (path->fp_cfg_flags & FIB_PATH_CFG_FLAG_INTF_RX)
+ {
+ path->fp_type = FIB_PATH_TYPE_INTF_RX;
+ path->intf_rx.fp_interface = rpath->frp_sw_if_index;
+ }
+ else if (path->fp_cfg_flags & FIB_PATH_CFG_FLAG_RPF_ID)
+ {
+ path->fp_type = FIB_PATH_TYPE_DEAG;
+ path->deag.fp_tbl_id = rpath->frp_fib_index;
+ path->deag.fp_rpf_id = rpath->frp_rpf_id;
+ }
else if (~0 != rpath->frp_sw_if_index)
{
if (ip46_address_is_zero(&rpath->frp_addr))
@@ -1069,6 +1122,7 @@ fib_path_create (fib_node_index_t pl_index,
if (FIB_PROTOCOL_MPLS == path->fp_nh_proto)
{
path->recursive.fp_nh.fp_local_label = rpath->frp_local_label;
+ path->recursive.fp_nh.fp_eos = rpath->frp_eos;
}
else
{
@@ -1238,17 +1292,13 @@ fib_path_cmp_i (const fib_path_t *path1,
res = ip46_address_cmp(&path1->attached_next_hop.fp_nh,
&path2->attached_next_hop.fp_nh);
if (0 == res) {
- res = vnet_sw_interface_compare(
- vnet_get_main(),
- path1->attached_next_hop.fp_interface,
- path2->attached_next_hop.fp_interface);
+ res = (path1->attached_next_hop.fp_interface -
+ path2->attached_next_hop.fp_interface);
}
break;
case FIB_PATH_TYPE_ATTACHED:
- res = vnet_sw_interface_compare(
- vnet_get_main(),
- path1->attached.fp_interface,
- path2->attached.fp_interface);
+ res = (path1->attached.fp_interface -
+ path2->attached.fp_interface);
break;
case FIB_PATH_TYPE_RECURSIVE:
res = ip46_address_cmp(&path1->recursive.fp_nh,
@@ -1261,6 +1311,13 @@ fib_path_cmp_i (const fib_path_t *path1,
break;
case FIB_PATH_TYPE_DEAG:
res = (path1->deag.fp_tbl_id - path2->deag.fp_tbl_id);
+ if (0 == res)
+ {
+ res = (path1->deag.fp_rpf_id - path2->deag.fp_rpf_id);
+ }
+ break;
+ case FIB_PATH_TYPE_INTF_RX:
+ res = (path1->intf_rx.fp_interface - path2->intf_rx.fp_interface);
break;
case FIB_PATH_TYPE_SPECIAL:
case FIB_PATH_TYPE_RECEIVE:
@@ -1336,22 +1393,22 @@ fib_path_cmp_w_route_path (fib_node_index_t path_index,
&rpath->frp_addr);
if (0 == res)
{
- res = vnet_sw_interface_compare(
- vnet_get_main(),
- path->attached_next_hop.fp_interface,
- rpath->frp_sw_if_index);
+ res = (path->attached_next_hop.fp_interface -
+ rpath->frp_sw_if_index);
}
break;
case FIB_PATH_TYPE_ATTACHED:
- res = vnet_sw_interface_compare(
- vnet_get_main(),
- path->attached.fp_interface,
- rpath->frp_sw_if_index);
+ res = (path->attached.fp_interface - rpath->frp_sw_if_index);
break;
case FIB_PATH_TYPE_RECURSIVE:
if (FIB_PROTOCOL_MPLS == path->fp_nh_proto)
{
res = path->recursive.fp_nh.fp_local_label - rpath->frp_local_label;
+
+ if (res == 0)
+ {
+ res = path->recursive.fp_nh.fp_eos - rpath->frp_eos;
+ }
}
else
{
@@ -1364,9 +1421,16 @@ fib_path_cmp_w_route_path (fib_node_index_t path_index,
res = (path->recursive.fp_tbl_id - rpath->frp_fib_index);
}
break;
+ case FIB_PATH_TYPE_INTF_RX:
+ res = (path->intf_rx.fp_interface - rpath->frp_sw_if_index);
+ break;
case FIB_PATH_TYPE_DEAG:
res = (path->deag.fp_tbl_id - rpath->frp_fib_index);
- break;
+ if (0 == res)
+ {
+ res = (path->deag.fp_rpf_id - rpath->frp_rpf_id);
+ }
+ break;
case FIB_PATH_TYPE_SPECIAL:
case FIB_PATH_TYPE_RECEIVE:
case FIB_PATH_TYPE_EXCLUSIVE:
@@ -1465,6 +1529,7 @@ fib_path_recursive_loop_detect (fib_node_index_t path_index,
case FIB_PATH_TYPE_SPECIAL:
case FIB_PATH_TYPE_DEAG:
case FIB_PATH_TYPE_RECEIVE:
+ case FIB_PATH_TYPE_INTF_RX:
case FIB_PATH_TYPE_EXCLUSIVE:
/*
* these path types cannot be part of a loop, since they are the leaves
@@ -1563,7 +1628,9 @@ fib_path_resolve (fib_node_index_t path_index)
if (FIB_PROTOCOL_MPLS == path->fp_nh_proto)
{
- fib_prefix_from_mpls_label(path->recursive.fp_nh.fp_local_label, &pfx);
+ fib_prefix_from_mpls_label(path->recursive.fp_nh.fp_local_label,
+ path->recursive.fp_nh.fp_eos,
+ &pfx);
}
else
{
@@ -1592,7 +1659,7 @@ fib_path_resolve (fib_node_index_t path_index)
*/
fib_path_recursive_adj_update(
path,
- fib_path_proto_to_chain_type(path->fp_nh_proto),
+ fib_path_to_chain_type(path),
&path->fp_dpo);
break;
@@ -1605,16 +1672,25 @@ fib_path_resolve (fib_node_index_t path_index)
drop_dpo_get(fib_proto_to_dpo(path->fp_nh_proto)));
break;
case FIB_PATH_TYPE_DEAG:
+ {
/*
* Resolve via a lookup DPO.
* FIXME. control plane should add routes with a table ID
*/
- lookup_dpo_add_or_lock_w_fib_index(path->deag.fp_tbl_id,
- fib_proto_to_dpo(path->fp_nh_proto),
- LOOKUP_INPUT_DST_ADDR,
- LOOKUP_TABLE_FROM_CONFIG,
- &path->fp_dpo);
+ lookup_cast_t cast;
+
+ cast = (path->fp_cfg_flags & FIB_PATH_CFG_FLAG_RPF_ID ?
+ LOOKUP_MULTICAST :
+ LOOKUP_UNICAST);
+
+ lookup_dpo_add_or_lock_w_fib_index(path->deag.fp_tbl_id,
+ fib_proto_to_dpo(path->fp_nh_proto),
+ cast,
+ LOOKUP_INPUT_DST_ADDR,
+ LOOKUP_TABLE_FROM_CONFIG,
+ &path->fp_dpo);
break;
+ }
case FIB_PATH_TYPE_RECEIVE:
/*
* Resolve via a receive DPO.
@@ -1624,6 +1700,15 @@ fib_path_resolve (fib_node_index_t path_index)
&path->receive.fp_addr,
&path->fp_dpo);
break;
+ case FIB_PATH_TYPE_INTF_RX: {
+ /*
+ * Resolve via a receive DPO.
+ */
+ interface_dpo_add_or_lock(fib_proto_to_dpo(path->fp_nh_proto),
+ path->intf_rx.fp_interface,
+ &path->fp_dpo);
+ break;
+ }
case FIB_PATH_TYPE_EXCLUSIVE:
/*
* Resolve via the user provided DPO
@@ -1652,6 +1737,7 @@ fib_path_get_resolving_interface (fib_node_index_t path_index)
return (path->receive.fp_interface);
case FIB_PATH_TYPE_RECURSIVE:
return (fib_entry_get_resolving_interface(path->fp_via_fib));
+ case FIB_PATH_TYPE_INTF_RX:
case FIB_PATH_TYPE_SPECIAL:
case FIB_PATH_TYPE_DEAG:
case FIB_PATH_TYPE_EXCLUSIVE:
@@ -1743,6 +1829,7 @@ fib_path_contribute_urpf (fib_node_index_t path_index,
case FIB_PATH_TYPE_DEAG:
case FIB_PATH_TYPE_RECEIVE:
+ case FIB_PATH_TYPE_INTF_RX:
/*
* these path types don't link to an adj
*/
@@ -1751,6 +1838,44 @@ fib_path_contribute_urpf (fib_node_index_t path_index,
}
void
+fib_path_stack_mpls_disp (fib_node_index_t path_index,
+ dpo_proto_t payload_proto,
+ dpo_id_t *dpo)
+{
+ fib_path_t *path;
+
+ path = fib_path_get(path_index);
+
+ ASSERT(path);
+
+ switch (path->fp_type)
+ {
+ case FIB_PATH_TYPE_DEAG:
+ {
+ dpo_id_t tmp = DPO_INVALID;
+
+ dpo_copy(&tmp, dpo);
+ dpo_set(dpo,
+ DPO_MPLS_DISPOSITION,
+ payload_proto,
+ mpls_disp_dpo_create(payload_proto,
+ path->deag.fp_rpf_id,
+ &tmp));
+ dpo_reset(&tmp);
+ break;
+ }
+ case FIB_PATH_TYPE_RECEIVE:
+ case FIB_PATH_TYPE_ATTACHED:
+ case FIB_PATH_TYPE_ATTACHED_NEXT_HOP:
+ case FIB_PATH_TYPE_RECURSIVE:
+ case FIB_PATH_TYPE_INTF_RX:
+ case FIB_PATH_TYPE_EXCLUSIVE:
+ case FIB_PATH_TYPE_SPECIAL:
+ break;
+ }
+}
+
+void
fib_path_contribute_forwarding (fib_node_index_t path_index,
fib_forward_chain_type_t fct,
dpo_id_t *dpo)
@@ -1769,7 +1894,7 @@ fib_path_contribute_forwarding (fib_node_index_t path_index,
* This then represents the path's 'native' protocol; IP.
* For all others will need to go find something else.
*/
- if (fib_path_proto_to_chain_type(path->fp_nh_proto) == fct)
+ if (fib_path_to_chain_type(path) == fct)
{
dpo_copy(dpo, &path->fp_dpo);
}
@@ -1813,10 +1938,10 @@ fib_path_contribute_forwarding (fib_node_index_t path_index,
case FIB_FORW_CHAIN_TYPE_UNICAST_IP4:
case FIB_FORW_CHAIN_TYPE_UNICAST_IP6:
case FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS:
- fib_path_recursive_adj_update(path, fct, dpo);
- break;
case FIB_FORW_CHAIN_TYPE_MCAST_IP4:
case FIB_FORW_CHAIN_TYPE_MCAST_IP6:
+ fib_path_recursive_adj_update(path, fct, dpo);
+ break;
case FIB_FORW_CHAIN_TYPE_ETHERNET:
case FIB_FORW_CHAIN_TYPE_NSH:
ASSERT(0);
@@ -1829,13 +1954,14 @@ fib_path_contribute_forwarding (fib_node_index_t path_index,
case FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS:
lookup_dpo_add_or_lock_w_table_id(MPLS_FIB_DEFAULT_TABLE_ID,
DPO_PROTO_MPLS,
+ LOOKUP_UNICAST,
LOOKUP_INPUT_DST_ADDR,
LOOKUP_TABLE_FROM_CONFIG,
dpo);
break;
+ case FIB_FORW_CHAIN_TYPE_MPLS_EOS:
case FIB_FORW_CHAIN_TYPE_UNICAST_IP4:
case FIB_FORW_CHAIN_TYPE_UNICAST_IP6:
- case FIB_FORW_CHAIN_TYPE_MPLS_EOS:
dpo_copy(dpo, &path->fp_dpo);
break;
case FIB_FORW_CHAIN_TYPE_MCAST_IP4:
@@ -1870,7 +1996,7 @@ fib_path_contribute_forwarding (fib_node_index_t path_index,
ai = adj_mcast_add_or_lock(path->fp_nh_proto,
fib_forw_chain_type_to_link_type(fct),
path->attached.fp_interface);
- dpo_set(dpo, DPO_ADJACENCY_MCAST,
+ dpo_set(dpo, DPO_ADJACENCY,
fib_forw_chain_type_to_dpo_proto(fct),
ai);
adj_unlock(ai);
@@ -1878,6 +2004,14 @@ fib_path_contribute_forwarding (fib_node_index_t path_index,
break;
}
break;
+ case FIB_PATH_TYPE_INTF_RX:
+ /*
+ * Create the adj needed for sending IP multicast traffic
+ */
+ interface_dpo_add_or_lock(fib_forw_chain_type_to_dpo_proto(fct),
+ path->attached.fp_interface,
+ dpo);
+ break;
case FIB_PATH_TYPE_RECEIVE:
case FIB_PATH_TYPE_SPECIAL:
dpo_copy(dpo, &path->fp_dpo);
diff --git a/src/vnet/fib/fib_path.h b/src/vnet/fib/fib_path.h
index 14efc1ab842..334be6f56e6 100644
--- a/src/vnet/fib/fib_path.h
+++ b/src/vnet/fib/fib_path.h
@@ -69,6 +69,14 @@ typedef enum fib_path_cfg_attribute_t_ {
/**
* The path is a for-us path
*/
+ FIB_PATH_CFG_ATTRIBUTE_INTF_RX,
+ /**
+ * The path is a deag with rpf-id
+ */
+ FIB_PATH_CFG_ATTRIBUTE_RPF_ID,
+ /**
+ * The path is an interface recieve
+ */
FIB_PATH_CFG_ATTRIBUTE_LOCAL,
/**
* Marker. Add new types before this one, then update it.
@@ -88,6 +96,8 @@ typedef enum fib_path_cfg_attribute_t_ {
[FIB_PATH_CFG_ATTRIBUTE_RESOLVE_ATTACHED] = "resolve-attached", \
[FIB_PATH_CFG_ATTRIBUTE_LOCAL] = "local", \
[FIB_PATH_CFG_ATTRIBUTE_ATTACHED] = "attached", \
+ [FIB_PATH_CFG_ATTRIBUTE_INTF_RX] = "interface-rx", \
+ [FIB_PATH_CFG_ATTRIBUTE_RPF_ID] = "rpf-id", \
}
#define FOR_EACH_FIB_PATH_CFG_ATTRIBUTE(_item) \
@@ -106,6 +116,8 @@ typedef enum fib_path_cfg_flags_t_ {
FIB_PATH_CFG_FLAG_RESOLVE_ATTACHED = (1 << FIB_PATH_CFG_ATTRIBUTE_RESOLVE_ATTACHED),
FIB_PATH_CFG_FLAG_LOCAL = (1 << FIB_PATH_CFG_ATTRIBUTE_LOCAL),
FIB_PATH_CFG_FLAG_ATTACHED = (1 << FIB_PATH_CFG_ATTRIBUTE_ATTACHED),
+ FIB_PATH_CFG_FLAG_INTF_RX = (1 << FIB_PATH_CFG_ATTRIBUTE_INTF_RX),
+ FIB_PATH_CFG_FLAG_RPF_ID = (1 << FIB_PATH_CFG_ATTRIBUTE_RPF_ID),
} __attribute__ ((packed)) fib_path_cfg_flags_t;
@@ -117,8 +129,6 @@ extern u8 *fib_path_adj_format(fib_node_index_t pi,
extern u8 * format_fib_path(u8 * s, va_list * args);
extern fib_node_index_t fib_path_create(fib_node_index_t pl_index,
- fib_protocol_t nh_proto,
- fib_path_cfg_flags_t flags,
const fib_route_path_t *path);
extern fib_node_index_t fib_path_create_special(fib_node_index_t pl_index,
fib_protocol_t nh_proto,
@@ -145,6 +155,9 @@ extern load_balance_path_t * fib_path_append_nh_for_multipath_hash(
fib_node_index_t path_index,
fib_forward_chain_type_t fct,
load_balance_path_t *hash_key);
+extern void fib_path_stack_mpls_disp(fib_node_index_t path_index,
+ dpo_proto_t payload_proto,
+ dpo_id_t *dpo);
extern void fib_path_contribute_forwarding(fib_node_index_t path_index,
fib_forward_chain_type_t type,
dpo_id_t *dpo);
diff --git a/src/vnet/fib/fib_path_ext.c b/src/vnet/fib/fib_path_ext.c
index f75b5626c04..08293bcf175 100644
--- a/src/vnet/fib/fib_path_ext.c
+++ b/src/vnet/fib/fib_path_ext.c
@@ -103,8 +103,8 @@ fib_path_ext_is_imp_null (fib_path_ext_t *path_ext)
load_balance_path_t *
fib_path_ext_stack (fib_path_ext_t *path_ext,
- const fib_entry_t *entry,
fib_forward_chain_type_t child_fct,
+ fib_forward_chain_type_t imp_null_fct,
load_balance_path_t *nhs)
{
fib_forward_chain_type_t parent_fct;
@@ -129,7 +129,7 @@ fib_path_ext_stack (fib_path_ext_t *path_ext,
*/
if (fib_path_ext_is_imp_null(path_ext))
{
- parent_fct = fib_entry_chain_type_fixup(entry, child_fct);
+ parent_fct = imp_null_fct;
}
else
{
diff --git a/src/vnet/fib/fib_path_ext.h b/src/vnet/fib/fib_path_ext.h
index cf8f8df00c6..d617700d026 100644
--- a/src/vnet/fib/fib_path_ext.h
+++ b/src/vnet/fib/fib_path_ext.h
@@ -18,6 +18,7 @@
#include <vnet/mpls/mpls.h>
#include <vnet/fib/fib_types.h>
+#include <vnet/dpo/load_balance.h>
/**
* A path extension is a per-entry addition to the forwarding information
@@ -61,8 +62,8 @@ extern void fib_path_ext_resolve(fib_path_ext_t *path_ext,
fib_node_index_t path_list_index);
extern load_balance_path_t *fib_path_ext_stack(fib_path_ext_t *path_ext,
- const struct fib_entry_t_ *entry,
fib_forward_chain_type_t fct,
+ fib_forward_chain_type_t imp_null_fct,
load_balance_path_t *nhs);
#endif
diff --git a/src/vnet/fib/fib_path_list.c b/src/vnet/fib/fib_path_list.c
index b9a391b33f5..ea6565dd19b 100644
--- a/src/vnet/fib/fib_path_list.c
+++ b/src/vnet/fib/fib_path_list.c
@@ -41,13 +41,6 @@ typedef struct fib_path_list_t_ {
fib_path_list_flags_t fpl_flags;
/**
- * The next-hop protocol for the paths in this path list.
- * Note that fixing the proto here means we don't support a mix of
- * v4 and v6 paths. ho hum.
- */
- fib_protocol_t fpl_nh_proto;
-
- /**
* Vector of paths indicies for all configured paths.
* For shareable path-lists this list MUST not change.
*/
@@ -57,6 +50,11 @@ typedef struct fib_path_list_t_ {
* the RPF list calculated for this path list
*/
fib_node_index_t fpl_urpf;
+
+ /**
+ * Hash table of paths. valid only with INDEXED flag
+ */
+ uword *fpl_db;
} fib_path_list_t;
/*
@@ -131,7 +129,6 @@ format_fib_path_list (u8 * s, va_list * args)
s = format (s, " index:%u", fib_path_list_get_index(path_list));
s = format (s, " locks:%u", path_list->fpl_node.fn_locks);
- s = format (s, " proto:%U", format_fib_protocol, path_list->fpl_nh_proto);
if (FIB_PATH_LIST_FLAG_NONE != path_list->fpl_flags)
{
@@ -156,26 +153,6 @@ format_fib_path_list (u8 * s, va_list * args)
}
u8 *
-fib_path_list_adjs_format (fib_node_index_t path_list_index,
- u32 indent,
- u8 * s)
-{
- fib_path_list_t *path_list;
- u32 i;
-
- path_list = fib_path_list_get(path_list_index);
-
- vec_foreach_index (i, path_list->fpl_paths)
- {
- s = fib_path_adj_format(path_list->fpl_paths[i],
- indent, s);
- }
-
- return (s);
-}
-
-
-u8 *
fib_path_list_format (fib_node_index_t path_list_index,
u8 * s)
{
@@ -648,27 +625,6 @@ fib_path_list_is_looped (fib_node_index_t path_list_index)
return (path_list->fpl_flags & FIB_PATH_LIST_FLAG_LOOPED);
}
-static fib_path_cfg_flags_t
-fib_path_list_flags_2_path_flags (fib_path_list_flags_t plf)
-{
- fib_path_cfg_flags_t pf = FIB_PATH_CFG_FLAG_NONE;
-
- if (plf & FIB_PATH_LIST_FLAG_LOCAL)
- {
- pf |= FIB_PATH_CFG_FLAG_LOCAL;
- }
- if (plf & FIB_PATH_LIST_FLAG_DROP)
- {
- pf |= FIB_PATH_CFG_FLAG_DROP;
- }
- if (plf & FIB_PATH_LIST_FLAG_EXCLUSIVE)
- {
- pf |= FIB_PATH_CFG_FLAG_EXCLUSIVE;
- }
-
- return (pf);
-}
-
static fib_path_list_flags_t
fib_path_list_flags_fixup (fib_path_list_flags_t flags)
{
@@ -695,18 +651,15 @@ fib_path_list_create (fib_path_list_flags_t flags,
flags = fib_path_list_flags_fixup(flags);
path_list = fib_path_list_alloc(&path_list_index);
path_list->fpl_flags = flags;
- /*
- * we'll assume for now all paths are the same next-hop protocol
- */
- path_list->fpl_nh_proto = rpaths[0].frp_proto;
- vec_foreach_index(i, rpaths)
+ if (NULL != rpaths)
{
- vec_add1(path_list->fpl_paths,
- fib_path_create(path_list_index,
- path_list->fpl_nh_proto,
- fib_path_list_flags_2_path_flags(flags),
- &rpaths[i]));
+ vec_foreach_index(i, rpaths)
+ {
+ vec_add1(path_list->fpl_paths,
+ fib_path_create(path_list_index,
+ &rpaths[i]));
+ }
}
/*
@@ -748,6 +701,27 @@ fib_path_list_create (fib_path_list_flags_t flags,
return (path_list_index);
}
+static fib_path_cfg_flags_t
+fib_path_list_flags_2_path_flags (fib_path_list_flags_t plf)
+{
+ fib_path_cfg_flags_t pf = FIB_PATH_CFG_FLAG_NONE;
+
+ if (plf & FIB_PATH_LIST_FLAG_DROP)
+ {
+ pf |= FIB_PATH_CFG_FLAG_DROP;
+ }
+ if (plf & FIB_PATH_LIST_FLAG_EXCLUSIVE)
+ {
+ pf |= FIB_PATH_CFG_FLAG_EXCLUSIVE;
+ }
+ if (plf & FIB_PATH_LIST_FLAG_LOCAL)
+ {
+ pf |= FIB_PATH_CFG_FLAG_LOCAL;
+ }
+
+ return (pf);
+}
+
fib_node_index_t
fib_path_list_create_special (fib_protocol_t nh_proto,
fib_path_list_flags_t flags,
@@ -758,11 +732,10 @@ fib_path_list_create_special (fib_protocol_t nh_proto,
path_list = fib_path_list_alloc(&path_list_index);
path_list->fpl_flags = flags;
- path_list->fpl_nh_proto = nh_proto;
path_index =
fib_path_create_special(path_list_index,
- path_list->fpl_nh_proto,
+ nh_proto,
fib_path_list_flags_2_path_flags(flags),
dpo);
vec_add1(path_list->fpl_paths, path_index);
@@ -776,6 +749,30 @@ fib_path_list_create_special (fib_protocol_t nh_proto,
}
/*
+ * return the index info the path-lists's vector of paths, of the matching path.
+ * ~0 if not found
+ */
+u32
+fib_path_list_find_rpath (fib_node_index_t path_list_index,
+ const fib_route_path_t *rpath)
+{
+ fib_path_list_t *path_list;
+ u32 ii;
+
+ path_list = fib_path_list_get(path_list_index);
+
+ vec_foreach_index (ii, path_list->fpl_paths)
+ {
+ if (!fib_path_cmp_w_route_path(path_list->fpl_paths[ii], rpath))
+ {
+ return (ii);
+ }
+ }
+ return (~0);
+}
+
+
+/*
* fib_path_list_copy_and_path_add
*
* Create a copy of a path-list and append one more path to it.
@@ -783,12 +780,61 @@ fib_path_list_create_special (fib_protocol_t nh_proto,
* can be a shared path-list from the data-base.
*/
fib_node_index_t
+fib_path_list_path_add (fib_node_index_t path_list_index,
+ const fib_route_path_t *rpaths)
+{
+ fib_node_index_t new_path_index, *orig_path_index;
+ fib_path_list_t *path_list;
+
+ /*
+ * alloc the new list before we retrieve the old one, lest
+ * the alloc result in a realloc
+ */
+ path_list = fib_path_list_get(path_list_index);
+
+ ASSERT(1 == vec_len(rpaths));
+ ASSERT(!(path_list->fpl_flags & FIB_PATH_LIST_FLAG_SHARED));
+
+ FIB_PATH_LIST_DBG(orig_path_list, "path-add");
+
+ new_path_index = fib_path_create(path_list_index,
+ rpaths);
+
+ vec_foreach (orig_path_index, path_list->fpl_paths)
+ {
+ /*
+ * don't add duplicate paths
+ */
+ if (0 == fib_path_cmp(new_path_index, *orig_path_index))
+ {
+ return (*orig_path_index);
+ }
+ }
+
+ /*
+ * Add the new path - no sort, no sharing, no key..
+ */
+ vec_add1(path_list->fpl_paths, new_path_index);
+
+ FIB_PATH_LIST_DBG(path_list, "path-added");
+
+ /*
+ * no shared path list requested. resolve and use the one
+ * just created.
+ */
+ fib_path_resolve(new_path_index);
+
+ return (new_path_index);
+}
+
+fib_node_index_t
fib_path_list_copy_and_path_add (fib_node_index_t orig_path_list_index,
- fib_path_list_flags_t flags,
- const fib_route_path_t *rpaths)
+ fib_path_list_flags_t flags,
+ const fib_route_path_t *rpaths)
{
fib_node_index_t path_index, new_path_index, *orig_path_index;
fib_path_list_t *path_list, *orig_path_list;
+ fib_node_index_t exist_path_list_index;
fib_node_index_t path_list_index;
fib_node_index_t pi;
@@ -806,13 +852,11 @@ fib_path_list_copy_and_path_add (fib_node_index_t orig_path_list_index,
flags = fib_path_list_flags_fixup(flags);
path_list->fpl_flags = flags;
- path_list->fpl_nh_proto = orig_path_list->fpl_nh_proto;
+
vec_validate(path_list->fpl_paths, vec_len(orig_path_list->fpl_paths));
pi = 0;
new_path_index = fib_path_create(path_list_index,
- path_list->fpl_nh_proto,
- fib_path_list_flags_2_path_flags(flags),
rpaths);
vec_foreach (orig_path_index, orig_path_list->fpl_paths)
@@ -845,47 +889,80 @@ fib_path_list_copy_and_path_add (fib_node_index_t orig_path_list_index,
FIB_PATH_LIST_DBG(path_list, "path-added");
/*
- * If a shared path list is requested, consult the DB for a match
+ * check for a matching path-list in the DB.
+ * If we find one then we can return the existing one and destroy the
+ * new one just created.
*/
- if (path_list->fpl_flags & FIB_PATH_LIST_FLAG_SHARED)
+ exist_path_list_index = fib_path_list_db_find(path_list);
+ if (FIB_NODE_INDEX_INVALID != exist_path_list_index)
{
- fib_node_index_t exist_path_list_index;
- /*
- * check for a matching path-list in the DB.
- * If we find one then we can return the existing one and destroy the
- * new one just created.
- */
- exist_path_list_index = fib_path_list_db_find(path_list);
- if (FIB_NODE_INDEX_INVALID != exist_path_list_index)
- {
- fib_path_list_destroy(path_list);
+ fib_path_list_destroy(path_list);
- path_list_index = exist_path_list_index;
- }
- else
- {
- /*
- * if there was not a matching path-list, then this
- * new one will need inserting into the DB and resolving.
- */
- fib_path_list_db_insert(path_list_index);
-
- path_list = fib_path_list_resolve(path_list);
- }
+ path_list_index = exist_path_list_index;
}
else
{
- /*
- * no shared path list requested. resolve and use the one
- * just created.
- */
- path_list = fib_path_list_resolve(path_list);
+ /*
+ * if there was not a matching path-list, then this
+ * new one will need inserting into the DB and resolving.
+ */
+ fib_path_list_db_insert(path_list_index);
+
+ path_list = fib_path_list_resolve(path_list);
}
return (path_list_index);
}
/*
+ * fib_path_list_path_remove
+ */
+fib_node_index_t
+fib_path_list_path_remove (fib_node_index_t path_list_index,
+ const fib_route_path_t *rpaths)
+{
+ fib_node_index_t match_path_index, tmp_path_index;
+ fib_path_list_t *path_list;
+ fib_node_index_t pi;
+
+ path_list = fib_path_list_get(path_list_index);
+
+ ASSERT(1 == vec_len(rpaths));
+ ASSERT(!(path_list->fpl_flags & FIB_PATH_LIST_FLAG_SHARED));
+
+ FIB_PATH_LIST_DBG(orig_path_list, "path-remove");
+
+ /*
+ * create a representation of the path to be removed, so it
+ * can be used as a comparison object during the copy.
+ */
+ tmp_path_index = fib_path_create(path_list_index,
+ rpaths);
+ match_path_index = FIB_NODE_INDEX_INVALID;
+
+ vec_foreach_index (pi, path_list->fpl_paths)
+ {
+ if (0 == fib_path_cmp(tmp_path_index,
+ path_list->fpl_paths[pi]))
+ {
+ /*
+ * match - remove it
+ */
+ match_path_index = path_list->fpl_paths[pi];
+ fib_path_destroy(match_path_index);
+ vec_del1(path_list->fpl_paths, pi);
+ }
+ }
+
+ /*
+ * done with the temporary now
+ */
+ fib_path_destroy(tmp_path_index);
+
+ return (match_path_index);
+}
+
+/*
* fib_path_list_copy_and_path_remove
*
* Copy the path-list excluding the path passed.
@@ -911,7 +988,6 @@ fib_path_list_copy_and_path_remove (fib_node_index_t orig_path_list_index,
FIB_PATH_LIST_DBG(orig_path_list, "copy-remove");
path_list->fpl_flags = flags;
- path_list->fpl_nh_proto = orig_path_list->fpl_nh_proto;
/*
* allocate as many paths as we might need in one go, rather than
* using vec_add to do a few at a time.
@@ -927,8 +1003,6 @@ fib_path_list_copy_and_path_remove (fib_node_index_t orig_path_list_index,
* can be used as a comparison object during the copy.
*/
tmp_path_index = fib_path_create(path_list_index,
- path_list->fpl_nh_proto,
- fib_path_list_flags_2_path_flags(flags),
rpaths);
vec_foreach (orig_path_index, orig_path_list->fpl_paths)
diff --git a/src/vnet/fib/fib_path_list.h b/src/vnet/fib/fib_path_list.h
index b4971addfba..9d2462119fb 100644
--- a/src/vnet/fib/fib_path_list.h
+++ b/src/vnet/fib/fib_path_list.h
@@ -39,6 +39,11 @@ typedef enum fib_path_list_attribute_t_ {
*/
FIB_PATH_LIST_ATTRIBUTE_SHARED = FIB_PATH_LIST_ATTRIBUTE_FIRST,
/**
+ * Indexed means the path-list keeps a hash table of all paths for
+ * fast lookup. The lookup result is the fib_node_index of the path.
+ */
+ FIB_PATH_LIST_ATTRIBUTE_INDEXED,
+ /**
* explicit drop path-list. Used when the entry source needs to
* force a drop, despite the fact the path info is present.
*/
@@ -73,6 +78,7 @@ typedef enum fib_path_list_attribute_t_ {
typedef enum fib_path_list_flags_t_ {
FIB_PATH_LIST_FLAG_NONE = 0,
FIB_PATH_LIST_FLAG_SHARED = (1 << FIB_PATH_LIST_ATTRIBUTE_SHARED),
+ FIB_PATH_LIST_FLAG_INDEXED = (1 << FIB_PATH_LIST_ATTRIBUTE_INDEXED),
FIB_PATH_LIST_FLAG_DROP = (1 << FIB_PATH_LIST_ATTRIBUTE_DROP),
FIB_PATH_LIST_FLAG_LOCAL = (1 << FIB_PATH_LIST_ATTRIBUTE_LOCAL),
FIB_PATH_LIST_FLAG_EXCLUSIVE = (1 << FIB_PATH_LIST_ATTRIBUTE_EXCLUSIVE),
@@ -83,10 +89,11 @@ typedef enum fib_path_list_flags_t_ {
#define FIB_PATH_LIST_ATTRIBUTES { \
[FIB_PATH_LIST_ATTRIBUTE_SHARED] = "shared", \
+ [FIB_PATH_LIST_ATTRIBUTE_INDEXED] = "indexed", \
[FIB_PATH_LIST_ATTRIBUTE_RESOLVED] = "resolved", \
[FIB_PATH_LIST_ATTRIBUTE_DROP] = "drop", \
[FIB_PATH_LIST_ATTRIBUTE_EXCLUSIVE] = "exclusive", \
- [FIB_PATH_LIST_ATTRIBUTE_LOCAL] = "local", \
+ [FIB_PATH_LIST_ATTRIBUTE_LOCAL] = "local", \
[FIB_PATH_LIST_ATTRIBUTE_LOOPED] = "looped", \
[FIB_PATH_LIST_ATTRIBUTE_NO_URPF] = "no-uRPF", \
}
@@ -110,6 +117,13 @@ extern fib_node_index_t fib_path_list_copy_and_path_remove(
fib_node_index_t pl_index,
fib_path_list_flags_t flags,
const fib_route_path_t *path);
+extern fib_node_index_t fib_path_list_path_add (
+ fib_node_index_t path_list_index,
+ const fib_route_path_t *rpaths);
+extern fib_node_index_t fib_path_list_path_remove (
+ fib_node_index_t path_list_index,
+ const fib_route_path_t *rpaths);
+
extern u32 fib_path_list_get_n_paths(fib_node_index_t pl_index);
extern void fib_path_list_contribute_forwarding(fib_node_index_t path_list_index,
@@ -137,11 +151,11 @@ extern int fib_path_list_is_looped(fib_node_index_t path_list_index);
extern fib_protocol_t fib_path_list_get_proto(fib_node_index_t path_list_index);
extern u8 * fib_path_list_format(fib_node_index_t pl_index,
u8 * s);
-extern u8 * fib_path_list_adjs_format(fib_node_index_t pl_index,
- u32 indent,
- u8 * s);
extern index_t fib_path_list_lb_map_add_or_lock(fib_node_index_t pl_index,
const fib_node_index_t *pis);
+extern u32 fib_path_list_find_rpath (fib_node_index_t path_list_index,
+ const fib_route_path_t *rpath);
+
/**
* A callback function type for walking a path-list's paths
*/
diff --git a/src/vnet/fib/fib_table.c b/src/vnet/fib/fib_table.c
index 6c3162e7489..b31f35e3520 100644
--- a/src/vnet/fib/fib_table.c
+++ b/src/vnet/fib/fib_table.c
@@ -475,8 +475,21 @@ fib_table_entry_special_remove (u32 fib_index,
*/
static void
fib_table_route_path_fixup (const fib_prefix_t *prefix,
+ fib_entry_flag_t eflags,
fib_route_path_t *path)
{
+ /*
+ * not all zeros next hop &&
+ * is recursive path &&
+ * nexthop is same as the route's address
+ */
+ if ((!ip46_address_is_zero(&path->frp_addr)) &&
+ (~0 == path->frp_sw_if_index) &&
+ (0 == ip46_address_cmp(&path->frp_addr, &prefix->fp_addr)))
+ {
+ /* Prefix recurses via itse;f */
+ path->frp_flags |= FIB_ROUTE_PATH_DROP;
+ }
if (fib_prefix_is_host(prefix) &&
ip46_address_is_zero(&path->frp_addr) &&
path->frp_sw_if_index != ~0)
@@ -484,7 +497,19 @@ fib_table_route_path_fixup (const fib_prefix_t *prefix,
path->frp_addr = prefix->fp_addr;
path->frp_flags |= FIB_ROUTE_PATH_ATTACHED;
}
-}
+ if (eflags & FIB_ENTRY_FLAG_DROP)
+ {
+ path->frp_flags |= FIB_ROUTE_PATH_DROP;
+ }
+ if (eflags & FIB_ENTRY_FLAG_LOCAL)
+ {
+ path->frp_flags |= FIB_ROUTE_PATH_LOCAL;
+ }
+ if (eflags & FIB_ENTRY_FLAG_EXCLUSIVE)
+ {
+ path->frp_flags |= FIB_ROUTE_PATH_EXCLUSIVE;
+ }
+}
fib_node_index_t
fib_table_entry_path_add (u32 fib_index,
@@ -536,7 +561,7 @@ fib_table_entry_path_add2 (u32 fib_index,
for (ii = 0; ii < vec_len(rpath); ii++)
{
- fib_table_route_path_fixup(prefix, &rpath[ii]);
+ fib_table_route_path_fixup(prefix, flags, &rpath[ii]);
}
if (FIB_NODE_INDEX_INVALID == fib_entry_index)
@@ -583,11 +608,6 @@ fib_table_entry_path_remove2 (u32 fib_index,
fib_table = fib_table_get(fib_index, prefix->fp_proto);
fib_entry_index = fib_table_lookup_exact_match_i(fib_table, prefix);
- for (ii = 0; ii < vec_len(rpath); ii++)
- {
- fib_table_route_path_fixup(prefix, &rpath[ii]);
- }
-
if (FIB_NODE_INDEX_INVALID == fib_entry_index)
{
/*
@@ -605,6 +625,15 @@ fib_table_entry_path_remove2 (u32 fib_index,
fib_entry_lock(fib_entry_index);
was_sourced = fib_entry_is_sourced(fib_entry_index, source);
+ for (ii = 0; ii < vec_len(rpath); ii++)
+ {
+ fib_table_route_path_fixup(
+ prefix,
+ fib_entry_get_flags_for_source(fib_entry_index,
+ source),
+ &rpath[ii]);
+ }
+
src_flag = fib_entry_path_remove(fib_entry_index, source, rpath);
if (!(FIB_ENTRY_SRC_FLAG_ADDED & src_flag))
@@ -661,7 +690,6 @@ fib_table_entry_path_remove (u32 fib_index,
};
fib_route_path_t *paths = NULL;
- fib_table_route_path_fixup(prefix, &path);
vec_add1(paths, path);
fib_table_entry_path_remove2(fib_index, prefix, source, paths);
@@ -692,7 +720,7 @@ fib_table_entry_update (u32 fib_index,
for (ii = 0; ii < vec_len(paths); ii++)
{
- fib_table_route_path_fixup(prefix, &paths[ii]);
+ fib_table_route_path_fixup(prefix, flags, &paths[ii]);
}
/*
* sort the paths provided by the control plane. this means
@@ -750,7 +778,6 @@ fib_table_entry_update_one_path (u32 fib_index,
};
fib_route_path_t *paths = NULL;
- fib_table_route_path_fixup(prefix, &path);
vec_add1(paths, path);
fib_entry_index =
diff --git a/src/vnet/fib/fib_test.c b/src/vnet/fib/fib_test.c
index 3c9b8a38fe1..e4a8a70e0d0 100644
--- a/src/vnet/fib/fib_test.c
+++ b/src/vnet/fib/fib_test.c
@@ -25,6 +25,8 @@
#include <vnet/dpo/receive_dpo.h>
#include <vnet/dpo/ip_null_dpo.h>
#include <vnet/bfd/bfd_main.h>
+#include <vnet/dpo/interface_dpo.h>
+#include <vnet/dpo/replicate_dpo.h>
#include <vnet/mpls/mpls.h>
@@ -271,6 +273,7 @@ typedef enum fib_test_lb_bucket_type_t_ {
FT_LB_O_LB,
FT_LB_SPECIAL,
FT_LB_ADJ,
+ FT_LB_INTF,
} fib_test_lb_bucket_type_t;
typedef struct fib_test_lb_bucket_t_ {
@@ -315,6 +318,31 @@ typedef struct fib_test_lb_bucket_t_ {
};
} fib_test_lb_bucket_t;
+typedef enum fib_test_rep_bucket_type_t_ {
+ FT_REP_LABEL_O_ADJ,
+ FT_REP_DISP_MFIB_LOOKUP,
+ FT_REP_INTF,
+} fib_test_rep_bucket_type_t;
+
+typedef struct fib_test_rep_bucket_t_ {
+ fib_test_rep_bucket_type_t type;
+
+ union
+ {
+ struct
+ {
+ mpls_eos_bit_t eos;
+ mpls_label_t label;
+ u8 ttl;
+ adj_index_t adj;
+ } label_o_adj;
+ struct
+ {
+ adj_index_t adj;
+ } adj;
+ };
+} fib_test_rep_bucket_t;
+
#define FIB_TEST_LB(_cond, _comment, _args...) \
{ \
if (!FIB_TEST_I(_cond, _comment, ##_args)) { \
@@ -322,7 +350,83 @@ typedef struct fib_test_lb_bucket_t_ {
} \
}
-static int
+int
+fib_test_validate_rep_v (const replicate_t *rep,
+ u16 n_buckets,
+ va_list ap)
+{
+ const fib_test_rep_bucket_t *exp;
+ const dpo_id_t *dpo;
+ int bucket;
+
+ FIB_TEST_LB((n_buckets == rep->rep_n_buckets),
+ "n_buckets = %d", rep->rep_n_buckets);
+
+ for (bucket = 0; bucket < n_buckets; bucket++)
+ {
+ exp = va_arg(ap, fib_test_rep_bucket_t*);
+
+ dpo = replicate_get_bucket_i(rep, bucket);
+
+ switch (exp->type)
+ {
+ case FT_REP_LABEL_O_ADJ:
+ {
+ const mpls_label_dpo_t *mld;
+ mpls_label_t hdr;
+ FIB_TEST_LB((DPO_MPLS_LABEL == dpo->dpoi_type),
+ "bucket %d stacks on %U",
+ bucket,
+ format_dpo_type, dpo->dpoi_type);
+
+ mld = mpls_label_dpo_get(dpo->dpoi_index);
+ hdr = clib_net_to_host_u32(mld->mld_hdr[0].label_exp_s_ttl);
+
+ FIB_TEST_LB((vnet_mpls_uc_get_label(hdr) ==
+ exp->label_o_adj.label),
+ "bucket %d stacks on label %d",
+ bucket,
+ exp->label_o_adj.label);
+
+ FIB_TEST_LB((vnet_mpls_uc_get_s(hdr) ==
+ exp->label_o_adj.eos),
+ "bucket %d stacks on label %d %U",
+ bucket,
+ exp->label_o_adj.label,
+ format_mpls_eos_bit, exp->label_o_adj.eos);
+
+ FIB_TEST_LB((DPO_ADJACENCY_INCOMPLETE == mld->mld_dpo.dpoi_type),
+ "bucket %d label stacks on %U",
+ bucket,
+ format_dpo_type, mld->mld_dpo.dpoi_type);
+
+ FIB_TEST_LB((exp->label_o_adj.adj == mld->mld_dpo.dpoi_index),
+ "bucket %d label stacks on adj %d",
+ bucket,
+ exp->label_o_adj.adj);
+ }
+ break;
+ case FT_REP_INTF:
+ FIB_TEST_LB((DPO_INTERFACE == dpo->dpoi_type),
+ "bucket %d stacks on %U",
+ bucket,
+ format_dpo_type, dpo->dpoi_type);
+
+ FIB_TEST_LB((exp->adj.adj == dpo->dpoi_index),
+ "bucket %d stacks on adj %d",
+ bucket,
+ exp->adj.adj);
+ break;
+ case FT_REP_DISP_MFIB_LOOKUP:
+// ASSERT(0);
+ break;
+ }
+ }
+
+ return (!0);
+}
+
+int
fib_test_validate_lb_v (const load_balance_t *lb,
u16 n_buckets,
va_list ap)
@@ -484,6 +588,16 @@ fib_test_validate_lb_v (const load_balance_t *lb,
bucket,
exp->adj.adj);
break;
+ case FT_LB_INTF:
+ FIB_TEST_I((DPO_INTERFACE == dpo->dpoi_type),
+ "bucket %d stacks on %U",
+ bucket,
+ format_dpo_type, dpo->dpoi_type);
+ FIB_TEST_LB((exp->adj.adj == dpo->dpoi_index),
+ "bucket %d stacks on adj %d",
+ bucket,
+ exp->adj.adj);
+ break;
case FT_LB_O_LB:
FIB_TEST_I((DPO_LOAD_BALANCE == dpo->dpoi_type),
"bucket %d stacks on %U",
@@ -509,14 +623,13 @@ fib_test_validate_lb_v (const load_balance_t *lb,
return (!0);
}
-static int
+int
fib_test_validate_entry (fib_node_index_t fei,
fib_forward_chain_type_t fct,
u16 n_buckets,
...)
{
dpo_id_t dpo = DPO_INVALID;
- const load_balance_t *lb;
fib_prefix_t pfx;
index_t fw_lbi;
u32 fib_index;
@@ -529,47 +642,59 @@ fib_test_validate_entry (fib_node_index_t fei,
fib_index = fib_entry_get_fib_index(fei);
fib_entry_contribute_forwarding(fei, fct, &dpo);
- FIB_TEST_LB((DPO_LOAD_BALANCE == dpo.dpoi_type),
- "Entry links to %U",
- format_dpo_type, dpo.dpoi_type);
- lb = load_balance_get(dpo.dpoi_index);
-
- res = fib_test_validate_lb_v(lb, n_buckets, ap);
+ if (DPO_REPLICATE == dpo.dpoi_type)
+ {
+ const replicate_t *rep;
- /*
- * ensure that the LB contributed by the entry is the
- * same as the LB in the forwarding tables
- */
- if (fct == fib_entry_get_default_chain_type(fib_entry_get(fei)))
+ rep = replicate_get(dpo.dpoi_index);
+ res = fib_test_validate_rep_v(rep, n_buckets, ap);
+ }
+ else
{
- switch (pfx.fp_proto)
- {
- case FIB_PROTOCOL_IP4:
- fw_lbi = ip4_fib_forwarding_lookup(fib_index, &pfx.fp_addr.ip4);
- break;
- case FIB_PROTOCOL_IP6:
- fw_lbi = ip6_fib_table_fwding_lookup(&ip6_main, fib_index, &pfx.fp_addr.ip6);
- break;
- case FIB_PROTOCOL_MPLS:
- {
- mpls_unicast_header_t hdr = {
- .label_exp_s_ttl = 0,
- };
+ const load_balance_t *lb;
+
+ FIB_TEST_LB((DPO_LOAD_BALANCE == dpo.dpoi_type),
+ "Entry links to %U",
+ format_dpo_type, dpo.dpoi_type);
- vnet_mpls_uc_set_label(&hdr.label_exp_s_ttl, pfx.fp_label);
- vnet_mpls_uc_set_s(&hdr.label_exp_s_ttl, pfx.fp_eos);
- hdr.label_exp_s_ttl = clib_host_to_net_u32(hdr.label_exp_s_ttl);
+ lb = load_balance_get(dpo.dpoi_index);
+ res = fib_test_validate_lb_v(lb, n_buckets, ap);
- fw_lbi = mpls_fib_table_forwarding_lookup(fib_index, &hdr);
+ /*
+ * ensure that the LB contributed by the entry is the
+ * same as the LB in the forwarding tables
+ */
+ if (fct == fib_entry_get_default_chain_type(fib_entry_get(fei)))
+ {
+ switch (pfx.fp_proto)
+ {
+ case FIB_PROTOCOL_IP4:
+ fw_lbi = ip4_fib_forwarding_lookup(fib_index, &pfx.fp_addr.ip4);
+ break;
+ case FIB_PROTOCOL_IP6:
+ fw_lbi = ip6_fib_table_fwding_lookup(&ip6_main, fib_index, &pfx.fp_addr.ip6);
break;
+ case FIB_PROTOCOL_MPLS:
+ {
+ mpls_unicast_header_t hdr = {
+ .label_exp_s_ttl = 0,
+ };
+
+ vnet_mpls_uc_set_label(&hdr.label_exp_s_ttl, pfx.fp_label);
+ vnet_mpls_uc_set_s(&hdr.label_exp_s_ttl, pfx.fp_eos);
+ hdr.label_exp_s_ttl = clib_host_to_net_u32(hdr.label_exp_s_ttl);
+
+ fw_lbi = mpls_fib_table_forwarding_lookup(fib_index, &hdr);
+ break;
+ }
+ default:
+ fw_lbi = 0;
}
- default:
- fw_lbi = 0;
+ FIB_TEST_LB((fw_lbi == dpo.dpoi_index),
+ "Contributed LB = FW LB: %U\n %U",
+ format_load_balance, fw_lbi, 0,
+ format_load_balance, dpo.dpoi_index, 0);
}
- FIB_TEST_LB((fw_lbi == dpo.dpoi_index),
- "Contributed LB = FW LB: %U\n %U",
- format_load_balance, fw_lbi, 0,
- format_load_balance, dpo.dpoi_index, 0);
}
dpo_reset(&dpo);
@@ -1289,6 +1414,7 @@ fib_test_v4 (void)
lookup_dpo_add_or_lock_w_fib_index(fib_index,
DPO_PROTO_IP4,
+ LOOKUP_UNICAST,
LOOKUP_INPUT_DST_ADDR,
LOOKUP_TABLE_FROM_CONFIG,
&ex_dpo);
@@ -2605,7 +2731,6 @@ fib_test_v4 (void)
NULL,
FIB_ROUTE_PATH_FLAG_NONE);
-
fei = fib_table_lookup(fib_index, &pfx_5_5_5_6_s_32);
dpo1 = fib_entry_contribute_ip_forwarding(fei);
@@ -7493,6 +7618,7 @@ lfib_test (void)
fib_route_path_t *rpaths = NULL, rpath = {
.frp_proto = FIB_PROTOCOL_MPLS,
.frp_local_label = 1200,
+ .frp_eos = MPLS_NON_EOS,
.frp_sw_if_index = ~0, // recurive
.frp_fib_index = 0, // Default MPLS fib
.frp_weight = 1,
@@ -7608,6 +7734,146 @@ lfib_test (void)
dpo_reset(&ip_1200);
/*
+ * An rx-interface route.
+ * like the tail of an mcast LSP
+ */
+ dpo_id_t idpo = DPO_INVALID;
+
+ interface_dpo_add_or_lock(DPO_PROTO_IP4,
+ tm->hw[0]->sw_if_index,
+ &idpo);
+
+ fib_prefix_t pfx_2500 = {
+ .fp_len = 21,
+ .fp_proto = FIB_PROTOCOL_MPLS,
+ .fp_label = 2500,
+ .fp_eos = MPLS_EOS,
+ .fp_payload_proto = DPO_PROTO_IP4,
+ };
+ fib_test_lb_bucket_t rx_intf_0 = {
+ .type = FT_LB_INTF,
+ .adj = {
+ .adj = idpo.dpoi_index,
+ },
+ };
+
+ lfe = fib_table_entry_update_one_path(fib_index,
+ &pfx_2500,
+ FIB_SOURCE_API,
+ FIB_ENTRY_FLAG_NONE,
+ FIB_PROTOCOL_IP4,
+ NULL,
+ tm->hw[0]->sw_if_index,
+ ~0, // invalid fib index
+ 0,
+ NULL,
+ FIB_ROUTE_PATH_INTF_RX);
+ FIB_TEST(fib_test_validate_entry(lfe,
+ FIB_FORW_CHAIN_TYPE_MPLS_EOS,
+ 1,
+ &rx_intf_0),
+ "2500 rx-interface 0");
+ fib_table_entry_delete(fib_index, &pfx_2500, FIB_SOURCE_API);
+
+ /*
+ * An MPLS mulicast entry
+ */
+ fib_prefix_t pfx_3500 = {
+ .fp_len = 21,
+ .fp_proto = FIB_PROTOCOL_MPLS,
+ .fp_label = 3500,
+ .fp_eos = MPLS_EOS,
+ .fp_payload_proto = DPO_PROTO_IP4,
+ };
+ fib_test_rep_bucket_t mc_0 = {
+ .type = FT_REP_LABEL_O_ADJ,
+ .label_o_adj = {
+ .adj = ai_mpls_10_10_10_1,
+ .label = 3300,
+ .eos = MPLS_EOS,
+ },
+ };
+ fib_test_rep_bucket_t mc_intf_0 = {
+ .type = FT_REP_INTF,
+ .adj = {
+ .adj = idpo.dpoi_index,
+ },
+ };
+ mpls_label_t *l3300 = NULL;
+ vec_add1(l3300, 3300);
+
+ lfe = fib_table_entry_update_one_path(lfib_index,
+ &pfx_3500,
+ FIB_SOURCE_API,
+ FIB_ENTRY_FLAG_MULTICAST,
+ FIB_PROTOCOL_IP4,
+ &nh_10_10_10_1,
+ tm->hw[0]->sw_if_index,
+ ~0, // invalid fib index
+ 1,
+ l3300,
+ FIB_ROUTE_PATH_FLAG_NONE);
+ FIB_TEST(fib_test_validate_entry(lfe,
+ FIB_FORW_CHAIN_TYPE_MPLS_EOS,
+ 1,
+ &mc_0),
+ "3500 via replicate over 10.10.10.1");
+
+ /*
+ * MPLS Bud-node. Add a replication via an interface-receieve path
+ */
+ lfe = fib_table_entry_path_add(lfib_index,
+ &pfx_3500,
+ FIB_SOURCE_API,
+ FIB_ENTRY_FLAG_MULTICAST,
+ FIB_PROTOCOL_IP4,
+ NULL,
+ tm->hw[0]->sw_if_index,
+ ~0, // invalid fib index
+ 0,
+ NULL,
+ FIB_ROUTE_PATH_INTF_RX);
+ FIB_TEST(fib_test_validate_entry(lfe,
+ FIB_FORW_CHAIN_TYPE_MPLS_EOS,
+ 2,
+ &mc_0,
+ &mc_intf_0),
+ "3500 via replicate over 10.10.10.1 and interface-rx");
+
+ /*
+ * Add a replication via an interface-free for-us path
+ */
+ fib_test_rep_bucket_t mc_disp = {
+ .type = FT_REP_DISP_MFIB_LOOKUP,
+ .adj = {
+ .adj = idpo.dpoi_index,
+ },
+ };
+ lfe = fib_table_entry_path_add(lfib_index,
+ &pfx_3500,
+ FIB_SOURCE_API,
+ FIB_ENTRY_FLAG_MULTICAST,
+ FIB_PROTOCOL_IP4,
+ NULL,
+ 5, // rpf-id
+ 0, // default table
+ 0,
+ NULL,
+ FIB_ROUTE_PATH_RPF_ID);
+ FIB_TEST(fib_test_validate_entry(lfe,
+ FIB_FORW_CHAIN_TYPE_MPLS_EOS,
+ 3,
+ &mc_0,
+ &mc_disp,
+ &mc_intf_0),
+ "3500 via replicate over 10.10.10.1 and interface-rx");
+
+
+
+ fib_table_entry_delete(fib_index, &pfx_3500, FIB_SOURCE_API);
+ dpo_reset(&idpo);
+
+ /*
* cleanup
*/
mpls_sw_interface_enable_disable(&mpls_main,
@@ -7617,6 +7883,9 @@ lfib_test (void)
FIB_TEST(lb_count == pool_elts(load_balance_pool),
"Load-balance resources freed %d of %d",
lb_count, pool_elts(load_balance_pool));
+ FIB_TEST(0 == pool_elts(interface_dpo_pool),
+ "interface_dpo resources freed %d of %d",
+ 0, pool_elts(interface_dpo_pool));
return (0);
}
diff --git a/src/vnet/fib/fib_test.h b/src/vnet/fib/fib_test.h
new file mode 100644
index 00000000000..b98680bf683
--- /dev/null
+++ b/src/vnet/fib/fib_test.h
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2016 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 __FIB_TEST_H__
+#define __FIB_TEST_H__
+
+#include <vnet/fib/fib_types.h>
+
+typedef enum fib_test_lb_bucket_type_t_ {
+ FT_LB_LABEL_O_ADJ,
+ FT_LB_LABEL_STACK_O_ADJ,
+ FT_LB_LABEL_O_LB,
+ FT_LB_O_LB,
+ FT_LB_SPECIAL,
+ FT_LB_ADJ,
+ FT_LB_INTF,
+} fib_test_lb_bucket_type_t;
+
+typedef struct fib_test_lb_bucket_t_ {
+ fib_test_lb_bucket_type_t type;
+
+ union
+ {
+ struct
+ {
+ mpls_eos_bit_t eos;
+ mpls_label_t label;
+ u8 ttl;
+ adj_index_t adj;
+ } label_o_adj;
+ struct
+ {
+ mpls_eos_bit_t eos;
+ mpls_label_t label_stack[8];
+ u8 label_stack_size;
+ u8 ttl;
+ adj_index_t adj;
+ } label_stack_o_adj;
+ struct
+ {
+ mpls_eos_bit_t eos;
+ mpls_label_t label;
+ u8 ttl;
+ index_t lb;
+ } label_o_lb;
+ struct
+ {
+ index_t adj;
+ } adj;
+ struct
+ {
+ index_t lb;
+ } lb;
+ struct
+ {
+ index_t adj;
+ } special;
+ };
+} fib_test_lb_bucket_t;
+
+typedef enum fib_test_rep_bucket_type_t_ {
+ FT_REP_LABEL_O_ADJ,
+ FT_REP_INTF,
+} fib_test_rep_bucket_type_t;
+
+typedef struct fib_test_rep_bucket_t_ {
+ fib_test_rep_bucket_type_t type;
+
+ union
+ {
+ struct
+ {
+ mpls_eos_bit_t eos;
+ mpls_label_t label;
+ u8 ttl;
+ adj_index_t adj;
+ } label_o_adj;
+ struct
+ {
+ adj_index_t adj;
+ } adj;
+ };
+} fib_test_rep_bucket_t;
+
+
+extern int fib_test_validate_rep_v(const replicate_t *rep,
+ u16 n_buckets,
+ va_list ap);
+
+extern int fib_test_validate_lb_v(const load_balance_t *lb,
+ u16 n_buckets,
+ va_list ap);
+
+extern int fib_test_validate_entry(fib_node_index_t fei,
+ fib_forward_chain_type_t fct,
+ u16 n_buckets,
+ ...);
+
+#endif
diff --git a/src/vnet/fib/fib_types.c b/src/vnet/fib/fib_types.c
index 2837a59db01..8165f3eb313 100644
--- a/src/vnet/fib/fib_types.c
+++ b/src/vnet/fib/fib_types.c
@@ -66,12 +66,13 @@ fib_prefix_from_ip46_addr (const ip46_address_t *addr,
void
fib_prefix_from_mpls_label (mpls_label_t label,
+ mpls_eos_bit_t eos,
fib_prefix_t *pfx)
{
pfx->fp_proto = FIB_PROTOCOL_MPLS;
pfx->fp_len = 21;
pfx->fp_label = label;
- pfx->fp_eos = MPLS_NON_EOS;
+ pfx->fp_eos = eos;
}
int
@@ -194,17 +195,7 @@ fib_route_path_cmp (const fib_route_path_t *rpath1,
if (0 != res) return (res);
- if (~0 != rpath1->frp_sw_if_index &&
- ~0 != rpath2->frp_sw_if_index)
- {
- res = vnet_sw_interface_compare(vnet_get_main(),
- rpath1->frp_sw_if_index,
- rpath2->frp_sw_if_index);
- }
- else
- {
- res = rpath1->frp_sw_if_index - rpath2->frp_sw_if_index;
- }
+ res = (rpath1->frp_sw_if_index - rpath2->frp_sw_if_index);
if (0 != res) return (res);
diff --git a/src/vnet/fib/fib_types.h b/src/vnet/fib/fib_types.h
index 1c5299a9214..4cb73e8a7a6 100644
--- a/src/vnet/fib/fib_types.h
+++ b/src/vnet/fib/fib_types.h
@@ -286,9 +286,37 @@ typedef enum fib_route_path_flags_t_
* Attached path
*/
FIB_ROUTE_PATH_ATTACHED = (1 << 3),
+ /**
+ * A Drop path - resolve the path on the drop DPO
+ */
+ FIB_ROUTE_PATH_DROP = (1 << 4),
+ /**
+ * Don't resolve the path, use the DPO the client provides
+ */
+ FIB_ROUTE_PATH_EXCLUSIVE = (1 << 5),
+ /**
+ * A path that result in received traffic being recieved/recirculated
+ * so that it appears to have arrived on the new interface
+ */
+ FIB_ROUTE_PATH_INTF_RX = (1 << 6),
+ /**
+ * A local path with a RPF-ID => multicast traffic
+ */
+ FIB_ROUTE_PATH_RPF_ID = (1 << 7),
} fib_route_path_flags_t;
/**
+ * An RPF-ID is numerical value that is used RPF validate. An entry
+ * has-a RPF-ID, when a packet egress from (e.g. an LSP) it gains an
+ * RPF-ID, these two are compared for the RPF check.
+ * This replaces the interfce based chack (since the LSP has no associated
+ * interface.
+ */
+typedef u32 fib_rpf_id_t;
+
+#define MFIB_RPF_ID_NONE (0)
+
+/**
* @brief
* A representation of a path as described by a route producer.
* These paramenters will determine the path 'type', of which there are:
@@ -321,17 +349,29 @@ typedef struct fib_route_path_t_ {
*/
ip46_address_t frp_addr;
- /**
- * The MPLS local Label to reursively resolve through.
- * This is valid when the path type is MPLS.
- */
- mpls_label_t frp_local_label;
+ struct {
+ /**
+ * The MPLS local Label to reursively resolve through.
+ * This is valid when the path type is MPLS.
+ */
+ mpls_label_t frp_local_label;
+ /**
+ * EOS bit for the resolving label
+ */
+ mpls_eos_bit_t frp_eos;
+ };
+ };
+ union {
+ /**
+ * The interface.
+ * Will be invalid for recursive paths.
+ */
+ u32 frp_sw_if_index;
+ /**
+ * The RPF-ID
+ */
+ fib_rpf_id_t frp_rpf_id;
};
- /**
- * The interface.
- * Will be invalid for recursive paths.
- */
- u32 frp_sw_if_index;
/**
* The FIB index to lookup the nexthop
* Only valid for recursive paths.
diff --git a/src/vnet/fib/mpls_fib.c b/src/vnet/fib/mpls_fib.c
index 4b2b76ea154..19f9f3c1432 100644
--- a/src/vnet/fib/mpls_fib.c
+++ b/src/vnet/fib/mpls_fib.c
@@ -165,6 +165,7 @@ mpls_fib_create_with_table_id (u32 table_id)
lookup_dpo_add_or_lock_w_fib_index(0, // unused
DPO_PROTO_IP4,
+ LOOKUP_UNICAST,
LOOKUP_INPUT_DST_ADDR,
LOOKUP_TABLE_FROM_INPUT_INTERFACE,
&dpo);
@@ -179,6 +180,7 @@ mpls_fib_create_with_table_id (u32 table_id)
lookup_dpo_add_or_lock_w_fib_index(0, //unsued
DPO_PROTO_MPLS,
+ LOOKUP_UNICAST,
LOOKUP_INPUT_DST_ADDR,
LOOKUP_TABLE_FROM_INPUT_INTERFACE,
&dpo);
@@ -197,6 +199,7 @@ mpls_fib_create_with_table_id (u32 table_id)
lookup_dpo_add_or_lock_w_fib_index(0, //unused
DPO_PROTO_IP6,
+ LOOKUP_UNICAST,
LOOKUP_INPUT_DST_ADDR,
LOOKUP_TABLE_FROM_INPUT_INTERFACE,
&dpo);
@@ -210,6 +213,7 @@ mpls_fib_create_with_table_id (u32 table_id)
prefix.fp_eos = MPLS_NON_EOS;
lookup_dpo_add_or_lock_w_fib_index(0, // unsued
DPO_PROTO_MPLS,
+ LOOKUP_UNICAST,
LOOKUP_INPUT_DST_ADDR,
LOOKUP_TABLE_FROM_INPUT_INTERFACE,
&dpo);
@@ -320,8 +324,15 @@ mpls_fib_forwarding_table_update (mpls_fib_t *mf,
{
mpls_label_t key;
- ASSERT(DPO_LOAD_BALANCE == dpo->dpoi_type);
-
+ ASSERT((DPO_LOAD_BALANCE == dpo->dpoi_type) ||
+ (DPO_REPLICATE == dpo->dpoi_type));
+ if (CLIB_DEBUG > 0)
+ {
+ if (DPO_REPLICATE == dpo->dpoi_type)
+ ASSERT(dpo->dpoi_index & MPLS_IS_REPLICATE);
+ if (DPO_LOAD_BALANCE == dpo->dpoi_type)
+ ASSERT(!(dpo->dpoi_index & MPLS_IS_REPLICATE));
+ }
key = mpls_fib_entry_mk_key(label, eos);
mf->mf_lbs[key] = dpo->dpoi_index;