aboutsummaryrefslogtreecommitdiffstats
path: root/src/vnet/dpo
diff options
context:
space:
mode:
Diffstat (limited to 'src/vnet/dpo')
-rw-r--r--src/vnet/dpo/receive_dpo.c6
-rw-r--r--src/vnet/dpo/receive_dpo.h2
-rw-r--r--src/vnet/dpo/replicate_dpo.c88
-rw-r--r--src/vnet/dpo/replicate_dpo.h17
4 files changed, 113 insertions, 0 deletions
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 <vnet/ip/lookup.h>
#include <vnet/dpo/replicate_dpo.h>
#include <vnet/dpo/drop_dpo.h>
+#include <vnet/dpo/receive_dpo.h>
#include <vnet/adj/adj.h>
#include <vnet/mpls/mpls_types.h>
@@ -101,6 +102,23 @@ replicate_alloc_i (void)
}
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,
u32 indent,
@@ -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
@@ -47,6 +47,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
* - per-route counters
@@ -71,6 +80,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.
* Load-balance objects of via-entries are heavily shared by recursives,
@@ -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
*/