/*
 * 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.
 */
/**
 * @brief
 *
 */

#ifndef __REPLICATE_DPO_H__
#define __REPLICATE_DPO_H__

#include <vlib/vlib.h>
#include <vnet/ip/lookup.h>
#include <vnet/dpo/dpo.h>
#include <vnet/dpo/load_balance.h>
#include <vnet/fib/fib_types.h>
#include <vnet/mpls/mpls_types.h>

/**
 * replicate main
 */
typedef struct replicate_main_t_
{
    vlib_combined_counter_main_t repm_counters;

    /* per-cpu vector of cloned packets */
    u32 **clones;
} replicate_main_t;

extern replicate_main_t replicate_main;

/**
 * The number of buckets that a replicate object can have
 * This must not overflow the rep_n_buckets field
 */
#define REP_MAX_BUCKETS 1024

/**
 * The number of buckets that a load-balance object can have and still
 * fit in one cache-line
 */
#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
 */
typedef struct replicate_t_ {
    /**
     * required for pool_get_aligned.
     *  memebers used in the switch path come first!
     */
    CLIB_CACHE_LINE_ALIGN_MARK(cacheline0);

    /**
     * number of buckets in the replicate.
     */
    u16 rep_n_buckets;

   /**
     * The protocol of packets that traverse this REP.
     * need in combination with the flow hash config to determine how to hash.
     * u8.
     */
    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,
     * so the lock count is a u32.
     */
    u32 rep_locks;

    /**
     * Vector of buckets containing the next DPOs, sized as repo_num
     */
    dpo_id_t *rep_buckets;

    /**
     * The rest of the cache line is used for buckets. In the common case
     * where there there are less than 4 buckets, then the buckets are
     * on the same cachlie and we save ourselves a pointer dereferance in 
     * the data-path.
     */
    dpo_id_t rep_buckets_inline[REP_NUM_INLINE_BUCKETS];
} replicate_t;

STATIC_ASSERT(sizeof(replicate_t) <= CLIB_CACHE_LINE_BYTES,
	      "A replicate object size exceeds one cacheline");
STATIC_ASSERT (REP_MAX_BUCKETS <= CLIB_U16_MAX,
	       "Too many buckets for replicate object");

/**
 * Flags controlling load-balance formatting/display
 */
typedef enum replicate_format_flags_t_ {
    REPLICATE_FORMAT_NONE,
    REPLICATE_FORMAT_DETAIL = (1 << 0),
} replicate_format_flags_t;

extern index_t replicate_create(u32 num_buckets,
                                dpo_proto_t rep_proto);
extern void replicate_multipath_update(
    const dpo_id_t *dpo,
    load_balance_path_t *next_hops);

extern void replicate_set_bucket(index_t repi,
                                 u32 bucket,
                                 const dpo_id_t *next);

extern u8* format_replicate(u8 * s, va_list * args);

extern const dpo_id_t *replicate_get_bucket(index_t repi,
                                            u32 bucket);
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
 */
extern replicate_t *replicate_pool;
static inline replicate_t*
replicate_get (index_t repi)
{
    repi &= ~MPLS_IS_REPLICATE;
    return (pool_elt_at_index(replicate_pool, repi));
}

#define REP_HAS_INLINE_BUCKETS(_rep)		\
    ((_rep)->rep_n_buckets <= REP_NUM_INLINE_BUCKETS)

static inline const dpo_id_t *
replicate_get_bucket_i (const replicate_t *rep,
			   u32 bucket)
{
    ASSERT(bucket < rep->rep_n_buckets);

    if (PREDICT_TRUE(REP_HAS_INLINE_BUCKETS(rep)))
    {
	return (&rep->rep_buckets_inline[bucket]);
    }
    else
    {
	return (&rep->rep_buckets[bucket]);
    }
}

extern void replicate_module_init(void);

#endif
