aboutsummaryrefslogtreecommitdiffstats
path: root/src/vnet/dpo/replicate_dpo.h
blob: d21f52a4833c9b22b53396d4a173f7561f349a54 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
/*
 * 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