From 9e829a856fdf88b3ea5770048ea20dcd50d1b4eb Mon Sep 17 00:00:00 2001 From: Neale Ranns Date: Mon, 17 Dec 2018 05:50:32 -0800 Subject: MFIB: recurse resolution through an MFIB entry Change-Id: I8dc261e40b8398c5c8ab6bb69ecebbd0176055d9 Signed-off-by: Neale Ranns --- src/vnet/dpo/receive_dpo.c | 6 +++ src/vnet/dpo/receive_dpo.h | 2 + src/vnet/dpo/replicate_dpo.c | 88 ++++++++++++++++++++++++++++++++++++++++++++ src/vnet/dpo/replicate_dpo.h | 17 +++++++++ 4 files changed, 113 insertions(+) (limited to 'src/vnet/dpo') diff --git a/src/vnet/dpo/receive_dpo.c b/src/vnet/dpo/receive_dpo.c index 30ddceeb23e..949dbfa6587 100644 --- a/src/vnet/dpo/receive_dpo.c +++ b/src/vnet/dpo/receive_dpo.c @@ -25,6 +25,12 @@ */ receive_dpo_t *receive_dpo_pool; +int +dpo_is_receive (const dpo_id_t *dpo) +{ + return (dpo->dpoi_type == DPO_RECEIVE); +} + static receive_dpo_t * receive_dpo_alloc (void) { diff --git a/src/vnet/dpo/receive_dpo.h b/src/vnet/dpo/receive_dpo.h index 9ab86a824c6..ee3c7836aff 100644 --- a/src/vnet/dpo/receive_dpo.h +++ b/src/vnet/dpo/receive_dpo.h @@ -47,6 +47,8 @@ typedef struct receive_dpo_t_ u16 rd_locks; } receive_dpo_t; +extern int dpo_is_receive(const dpo_id_t *dpo); + extern void receive_dpo_add_or_lock (dpo_proto_t proto, u32 sw_if_index, const ip46_address_t *nh_addr, diff --git a/src/vnet/dpo/replicate_dpo.c b/src/vnet/dpo/replicate_dpo.c index 39b17f103c9..69e367aa368 100644 --- a/src/vnet/dpo/replicate_dpo.c +++ b/src/vnet/dpo/replicate_dpo.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -100,6 +101,23 @@ replicate_alloc_i (void) return (rep); } +static u8* +format_replicate_flags (u8 *s, va_list *args) +{ + int flags = va_arg (*args, int); + + if (flags == REPLICATE_FLAGS_NONE) + { + s = format (s, "none"); + } + else if (flags & REPLICATE_FLAGS_HAS_LOCAL) + { + s = format (s, "has-local "); + } + + return (s); +} + static u8* replicate_format (index_t repi, replicate_format_flags_t flags, @@ -118,6 +136,7 @@ replicate_format (index_t repi, s = format(s, "%U: ", format_dpo_type, DPO_REPLICATE); s = format(s, "[index:%d buckets:%d ", repi, rep->rep_n_buckets); + s = format(s, "flags:[%U] ", format_replicate_flags, rep->rep_flags); s = format(s, "to:[%Ld:%Ld]]", to.packets, to.bytes); for (i = 0; i < rep->rep_n_buckets; i++) @@ -182,6 +201,14 @@ replicate_set_bucket_i (replicate_t *rep, dpo_id_t *buckets, const dpo_id_t *next) { + if (dpo_is_receive(&buckets[bucket])) + { + rep->rep_flags &= ~REPLICATE_FLAGS_HAS_LOCAL; + } + if (dpo_is_receive(next)) + { + rep->rep_flags |= REPLICATE_FLAGS_HAS_LOCAL; + } dpo_stack(DPO_REPLICATE, rep->rep_proto, &buckets[bucket], next); } @@ -492,6 +519,67 @@ replicate_lock (dpo_id_t *dpo) rep->rep_locks++; } +index_t +replicate_dup (replicate_flags_t flags, + index_t repi) +{ + replicate_t *rep, *copy; + + rep = replicate_get(repi); + + if (rep->rep_flags == flags || + flags & REPLICATE_FLAGS_HAS_LOCAL) + { + /* + * we can include all the buckets from the original in the copy + */ + return (repi); + } + else + { + /* + * caller doesn't want the local paths that the original has + */ + if (rep->rep_n_buckets == 1) + { + /* + * original has only one bucket that is the local, so create + * a new one with only the drop + */ + copy = replicate_create_i (1, rep->rep_proto); + + replicate_set_bucket_i(copy, 0, + replicate_get_buckets(copy), + drop_dpo_get(rep->rep_proto)); + } + else + { + dpo_id_t *old_buckets, *copy_buckets; + u16 bucket, pos; + + copy = replicate_create_i(rep->rep_n_buckets - 1, + rep->rep_proto); + + rep = replicate_get(repi); + old_buckets = replicate_get_buckets(rep); + copy_buckets = replicate_get_buckets(copy); + pos = 0; + + for (bucket = 0; bucket < rep->rep_n_buckets; bucket++) + { + if (!dpo_is_receive(&old_buckets[bucket])) + { + replicate_set_bucket_i(copy, pos, copy_buckets, + (&old_buckets[bucket])); + pos++; + } + } + } + } + + return (replicate_get_index(copy)); +} + static void replicate_destroy (replicate_t *rep) { diff --git a/src/vnet/dpo/replicate_dpo.h b/src/vnet/dpo/replicate_dpo.h index 7b075394bc3..70faef3e28f 100644 --- a/src/vnet/dpo/replicate_dpo.h +++ b/src/vnet/dpo/replicate_dpo.h @@ -46,6 +46,15 @@ extern replicate_main_t replicate_main; */ #define REP_NUM_INLINE_BUCKETS 4 +/** + * Flags on the replicate DPO + */ +typedef enum replicate_flags_t_ +{ + REPLICATE_FLAGS_NONE, + REPLICATE_FLAGS_HAS_LOCAL, +} __clib_packed replicate_flags_t; + /** * The FIB DPO provieds; * - load-balancing over the next DPOs in the chain/graph @@ -70,6 +79,11 @@ typedef struct replicate_t_ { */ dpo_proto_t rep_proto; + /** + * Flags specifying the replicate properties/behaviour + */ + replicate_flags_t rep_flags; + /** * The number of locks, which is approximately the number of users, * of this load-balance. @@ -121,6 +135,9 @@ extern int replicate_is_drop(const dpo_id_t *dpo); extern u16 replicate_n_buckets(index_t repi); +extern index_t replicate_dup(replicate_flags_t flags, + index_t repi); + /** * The encapsulation breakages are for fast DP access */ -- cgit 1.2.3-korg