#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>
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,
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++)
{
replicate_t *rep;
+ ASSERT (num_buckets <= REP_MAX_BUCKETS);
+
rep = replicate_alloc_i();
rep->rep_n_buckets = num_buckets;
rep->rep_proto = rep_proto;
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);
}
replicate_set_n_buckets (replicate_t *rep,
u32 n_buckets)
{
- rep->rep_n_buckets = n_buckets;
+ ASSERT (n_buckets <= REP_MAX_BUCKETS);
+ rep->rep_n_buckets = n_buckets;
}
void
rep->rep_proto);
n_buckets = vec_len(nhs);
+ if (n_buckets > REP_MAX_BUCKETS)
+ {
+ vlib_log_err (replicate_logger,
+ "Too many paths for replicate, truncating %d -> %d",
+ n_buckets, REP_MAX_BUCKETS);
+ for (int i = REP_MAX_BUCKETS; i < n_buckets; i++)
+ dpo_reset (&vec_elt (nhs, i).path_dpo);
+ vec_set_len (nhs, REP_MAX_BUCKETS);
+ n_buckets = REP_MAX_BUCKETS;
+ }
+
if (0 == rep->rep_n_buckets)
{
/*
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)
{
if (INDEX_INVALID != repi)
{
- vlib_cli_output (vm, "%U", format_replicate, repi,
+ if (pool_is_free_index (replicate_pool, repi))
+ vlib_cli_output (vm, "no such index %d", repi);
+ else
+ vlib_cli_output (vm, "%U", format_replicate, repi,
REPLICATE_FORMAT_DETAIL);
}
else
{
replicate_t *rep;
- pool_foreach(rep, replicate_pool,
- ({
+ pool_foreach (rep, replicate_pool)
+ {
vlib_cli_output (vm, "%U", format_replicate,
replicate_get_index(rep),
REPLICATE_FORMAT_NONE);
- }));
+ }
}
return 0;
{
replicate_trace_t *t;
- if (c0 != b0)
- {
- vlib_buffer_copy_trace_flag (vm, b0, ci0);
- VLIB_BUFFER_TRACE_TRAJECTORY_INIT (c0);
- }
t = vlib_add_trace (vm, node, c0, sizeof (*t));
t->rep_index = repi0;
t->dpo = *dpo0;