blob: bcf6c041209826a602419d91f3501a9e82522fc4 [file] [log] [blame]
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001/*
2 * Copyright (c) 2016 Cisco and/or its affiliates.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at:
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15/**
16 * An adjacency is a representation of an attached L3 peer.
17 *
18 * Adjacency Sub-types:
19 * - neighbour: a representation of an attached L3 peer.
20 * Key:{addr,interface,link/ether-type}
21 * SHARED
22 * - glean: used to drive ARP/ND for packets destined to a local sub-net.
23 * 'glean' mean use the packet's destination address as the target
24 * address in the ARP packet.
25 * UNSHARED. Only one per-interface.
26 * - midchain: a nighbour adj on a virtual/tunnel interface.
Neale Ranns0bfe5d82016-08-25 15:29:12 +010027 *
28 * The API to create and update the adjacency is very sub-type specific. This
29 * is intentional as it encourages the user to carefully consider which adjacency
30 * sub-type they are really using, and hence assign it data in the appropriate
31 * sub-type space in the union of sub-types. This prevents the adj becoming a
32 * disorganised dumping group for 'my features needs a u16 somewhere' data. It
33 * is important to enforce this approach as space in the adjacency is a premium,
34 * as we need it to fit in 1 cache line.
35 *
36 * the API is also based around an index to an ajdacency not a raw pointer. This
37 * is so the user doesn't suffer the same limp inducing firearm injuries that
38 * the author suffered as the adjacenices can realloc.
39 */
40
41#ifndef __ADJ_H__
42#define __ADJ_H__
43
Neale Ranns0bfe5d82016-08-25 15:29:12 +010044#include <vnet/adj/adj_types.h>
45#include <vnet/adj/adj_nbr.h>
Neale Ranns0bfe5d82016-08-25 15:29:12 +010046#include <vnet/adj/adj_glean.h>
Neale Rannsfa5d1982017-02-20 14:19:51 -080047#include <vnet/adj/rewrite.h>
48
49/** @brief Common (IP4/IP6) next index stored in adjacency. */
50typedef enum
51{
52 /** Adjacency to drop this packet. */
53 IP_LOOKUP_NEXT_DROP,
54 /** Adjacency to punt this packet. */
55 IP_LOOKUP_NEXT_PUNT,
56
57 /** This packet is for one of our own IP addresses. */
58 IP_LOOKUP_NEXT_LOCAL,
59
60 /** This packet matches an "incomplete adjacency" and packets
61 need to be passed to ARP to find rewrite string for
62 this destination. */
63 IP_LOOKUP_NEXT_ARP,
64
65 /** This packet matches an "interface route" and packets
66 need to be passed to ARP to find rewrite string for
67 this destination. */
68 IP_LOOKUP_NEXT_GLEAN,
69
70 /** This packet is to be rewritten and forwarded to the next
71 processing node. This is typically the output interface but
72 might be another node for further output processing. */
73 IP_LOOKUP_NEXT_REWRITE,
74
75 /** This packets follow a mid-chain adjacency */
76 IP_LOOKUP_NEXT_MIDCHAIN,
77
78 /** This packets needs to go to ICMP error */
79 IP_LOOKUP_NEXT_ICMP_ERROR,
80
81 /** Multicast Adjacency. */
82 IP_LOOKUP_NEXT_MCAST,
83
Neale Ranns0f26c5a2017-03-01 15:12:11 -080084 /** Multicast Midchain Adjacency. An Adjacency for sending macst packets
85 * on a tunnel/virtual interface */
86 IP_LOOKUP_NEXT_MCAST_MIDCHAIN,
87
Neale Rannsfa5d1982017-02-20 14:19:51 -080088 IP_LOOKUP_N_NEXT,
89} __attribute__ ((packed)) ip_lookup_next_t;
90
91typedef enum
92{
93 IP4_LOOKUP_N_NEXT = IP_LOOKUP_N_NEXT,
94} ip4_lookup_next_t;
95
96typedef enum
97{
98 /* Hop-by-hop header handling */
99 IP6_LOOKUP_NEXT_HOP_BY_HOP = IP_LOOKUP_N_NEXT,
100 IP6_LOOKUP_NEXT_ADD_HOP_BY_HOP,
101 IP6_LOOKUP_NEXT_POP_HOP_BY_HOP,
102 IP6_LOOKUP_N_NEXT,
103} ip6_lookup_next_t;
104
105#define IP4_LOOKUP_NEXT_NODES { \
106 [IP_LOOKUP_NEXT_DROP] = "ip4-drop", \
107 [IP_LOOKUP_NEXT_PUNT] = "ip4-punt", \
108 [IP_LOOKUP_NEXT_LOCAL] = "ip4-local", \
109 [IP_LOOKUP_NEXT_ARP] = "ip4-arp", \
110 [IP_LOOKUP_NEXT_GLEAN] = "ip4-glean", \
111 [IP_LOOKUP_NEXT_REWRITE] = "ip4-rewrite", \
112 [IP_LOOKUP_NEXT_MCAST] = "ip4-rewrite-mcast", \
113 [IP_LOOKUP_NEXT_MIDCHAIN] = "ip4-midchain", \
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800114 [IP_LOOKUP_NEXT_MCAST_MIDCHAIN] = "ip4-mcast-midchain", \
Neale Rannsfa5d1982017-02-20 14:19:51 -0800115 [IP_LOOKUP_NEXT_ICMP_ERROR] = "ip4-icmp-error", \
116}
117
118#define IP6_LOOKUP_NEXT_NODES { \
119 [IP_LOOKUP_NEXT_DROP] = "ip6-drop", \
120 [IP_LOOKUP_NEXT_PUNT] = "ip6-punt", \
121 [IP_LOOKUP_NEXT_LOCAL] = "ip6-local", \
122 [IP_LOOKUP_NEXT_ARP] = "ip6-discover-neighbor", \
123 [IP_LOOKUP_NEXT_GLEAN] = "ip6-glean", \
124 [IP_LOOKUP_NEXT_REWRITE] = "ip6-rewrite", \
125 [IP_LOOKUP_NEXT_MCAST] = "ip6-rewrite-mcast", \
126 [IP_LOOKUP_NEXT_MIDCHAIN] = "ip6-midchain", \
Neale Ranns0f26c5a2017-03-01 15:12:11 -0800127 [IP_LOOKUP_NEXT_MCAST_MIDCHAIN] = "ip6-mcast-midchain", \
Neale Rannsfa5d1982017-02-20 14:19:51 -0800128 [IP_LOOKUP_NEXT_ICMP_ERROR] = "ip6-icmp-error", \
129 [IP6_LOOKUP_NEXT_HOP_BY_HOP] = "ip6-hop-by-hop", \
130 [IP6_LOOKUP_NEXT_ADD_HOP_BY_HOP] = "ip6-add-hop-by-hop", \
131 [IP6_LOOKUP_NEXT_POP_HOP_BY_HOP] = "ip6-pop-hop-by-hop", \
132}
133
134/**
135 * Forward delcartion
136 */
137struct ip_adjacency_t_;
138
139/**
140 * @brief A function type for post-rewrite fixups on midchain adjacency
141 */
142typedef void (*adj_midchain_fixup_t) (vlib_main_t * vm,
143 struct ip_adjacency_t_ * adj,
Neale Rannsdb14f5a2018-01-29 10:43:33 -0800144 vlib_buffer_t * b0,
145 const void *data);
Neale Rannsfa5d1982017-02-20 14:19:51 -0800146
147/**
148 * @brief Flags on an IP adjacency
149 */
150typedef enum ip_adjacency_flags_t_
151{
152 ADJ_FLAG_NONE = 0,
153
154 /**
155 * Currently a sync walk is active. Used to prevent re-entrant walking
156 */
157 ADJ_FLAG_SYNC_WALK_ACTIVE = (1 << 0),
158
159 /**
160 * Packets TX through the midchain do not increment the interface
161 * counters. This should be used when the adj is associated with an L2
162 * interface and that L2 interface is in a bridege domain. In that case
163 * the packet will have traversed the interface's TX node, and hence have
164 * been counted, before it traverses ths midchain
165 */
166 ADJ_FLAG_MIDCHAIN_NO_COUNT = (1 << 1),
167} __attribute__ ((packed)) adj_flags_t;
168
169/**
170 * @brief IP unicast adjacency.
171 * @note cache aligned.
172 *
173 * An adjacency is a represenation of a peer on a particular link.
174 */
175typedef struct ip_adjacency_t_
176{
177 CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
178
179 /**
180 * Linkage into the FIB node grpah. First member since this type
181 * has 8 byte alignment requirements.
182 */
183 fib_node_t ia_node;
184
185 /**
186 * Next hop after ip4-lookup.
187 * This is not accessed in the rewrite nodes.
188 * 1-bytes
189 */
190 ip_lookup_next_t lookup_next_index;
191
192 /**
193 * link/ether-type
194 * 1 bytes
195 */
196 vnet_link_t ia_link;
197
198 /**
199 * The protocol of the neighbor/peer. i.e. the protocol with
200 * which to interpret the 'next-hop' attirbutes of the sub-types.
201 * 1-btyes
202 */
203 fib_protocol_t ia_nh_proto;
204
205 /**
206 * Flags on the adjacency
207 * 1-bytes
208 */
209 adj_flags_t ia_flags;
210
211 union
212 {
213 /**
214 * IP_LOOKUP_NEXT_ARP/IP_LOOKUP_NEXT_REWRITE
215 *
216 * neighbour adjacency sub-type;
217 */
218 struct
219 {
220 ip46_address_t next_hop;
221 } nbr;
222 /**
223 * IP_LOOKUP_NEXT_MIDCHAIN
224 *
225 * A nbr adj that is also recursive. Think tunnels.
226 * A nbr adj can transition to be of type MDICHAIN
227 * so be sure to leave the two structs with the next_hop
228 * fields aligned.
229 */
230 struct
231 {
232 /**
233 * The recursive next-hop.
234 * This field MUST be at the same memory location as
235 * sub_type.nbr.next_hop
236 */
237 ip46_address_t next_hop;
238 /**
239 * The next DPO to use
240 */
241 dpo_id_t next_dpo;
242 /**
243 * A function to perform the post-rewrite fixup
244 */
245 adj_midchain_fixup_t fixup_func;
Neale Rannsdb14f5a2018-01-29 10:43:33 -0800246 /**
247 * Fixup data passed back to the client in the fixup function
248 */
249 const void *fixup_data;
Neale Rannsfa5d1982017-02-20 14:19:51 -0800250 } midchain;
251 /**
252 * IP_LOOKUP_NEXT_GLEAN
253 *
254 * Glean the address to ARP for from the packet's destination.
255 * Technically these aren't adjacencies, i.e. they are not a
256 * representation of a peer. One day we might untangle this coupling
257 * and use a new Glean DPO.
258 */
259 struct
260 {
261 ip46_address_t receive_addr;
262 } glean;
263 } sub_type;
264
265 CLIB_CACHE_LINE_ALIGN_MARK (cacheline1);
266
267 /* Rewrite in second/third cache lines */
268 vnet_declare_rewrite (VLIB_BUFFER_PRE_DATA_SIZE);
Neale Ranns88fc83e2017-04-05 08:11:14 -0700269
270 /**
271 * more control plane members that do not fit on the first cacheline
272 */
273 /**
274 * A sorted vector of delegates
275 */
276 struct adj_delegate_t_ *ia_delegates;
277
Neale Rannsfa5d1982017-02-20 14:19:51 -0800278} ip_adjacency_t;
279
280STATIC_ASSERT ((STRUCT_OFFSET_OF (ip_adjacency_t, cacheline0) == 0),
281 "IP adjacency cachline 0 is not offset");
282STATIC_ASSERT ((STRUCT_OFFSET_OF (ip_adjacency_t, cacheline1) ==
283 CLIB_CACHE_LINE_BYTES),
284 "IP adjacency cachline 1 is more than one cachline size offset");
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100285
286/**
287 * @brief
288 * Take a reference counting lock on the adjacency
289 */
290extern void adj_lock(adj_index_t adj_index);
291/**
292 * @brief
293 * Release a reference counting lock on the adjacency
294 */
295extern void adj_unlock(adj_index_t adj_index);
296
297/**
298 * @brief
299 * Add a child dependent to an adjacency. The child will
300 * thus be informed via its registerd back-walk function
301 * when the adjacency state changes.
302 */
303extern u32 adj_child_add(adj_index_t adj_index,
304 fib_node_type_t type,
305 fib_node_index_t child_index);
306/**
307 * @brief
308 * Remove a child dependent
309 */
310extern void adj_child_remove(adj_index_t adj_index,
311 u32 sibling_index);
312
313/**
Neale Rannsb80c5362016-10-08 13:03:40 +0100314 * @brief Walk the Adjacencies on a given interface
315 */
316extern void adj_walk (u32 sw_if_index,
317 adj_walk_cb_t cb,
318 void *ctx);
319
320/**
321 * @brief Return the link type of the adjacency
322 */
323extern vnet_link_t adj_get_link_type (adj_index_t ai);
324
325/**
326 * @brief Return the sw interface index of the adjacency.
327 */
328extern u32 adj_get_sw_if_index (adj_index_t ai);
329
330/**
Neale Ranns88fc83e2017-04-05 08:11:14 -0700331 * @brief Return true if the adjacency is 'UP', i.e. can be used for forwarding.
332 * 0 is down, !0 is up.
333 */
334extern int adj_is_up (adj_index_t ai);
335
336/**
Neale Rannsb80c5362016-10-08 13:03:40 +0100337 * @brief Return the link type of the adjacency
338 */
339extern const u8* adj_get_rewrite (adj_index_t ai);
340
341/**
Neale Rannsb069a692017-03-15 12:34:25 -0400342 * @brief Notify the adjacency subsystem that the features settings for
343 * an interface have changed
344 */
345extern void adj_feature_update (u32 sw_if_index, u8 arc_index, u8 is_enable);
346
347/**
Neale Rannsffd78d12018-02-09 06:05:16 -0800348 * @brief Notify the adjacency subsystem that the MTU settings for
349 * an HW interface have changed
350 */
351extern void adj_mtu_update (u32 hw_if_index);
352
353/**
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100354 * @brief
Neale Ranns6c3ebcc2016-10-02 21:20:15 +0100355 * The global adjacnecy pool. Exposed for fast/inline data-plane access
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100356 */
Neale Ranns6c3ebcc2016-10-02 21:20:15 +0100357extern ip_adjacency_t *adj_pool;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100358
359/**
360 * @brief
361 * Adjacency packet counters
362 */
363extern vlib_combined_counter_main_t adjacency_counters;
364
365/**
Neale Ranns9c6a6132017-02-21 05:33:14 -0800366 * @brief Global Config for enabling per-adjacency counters
367 * This is configurable because it comes with a non-negligible
368 * performance cost. */
369extern int adj_per_adj_counters;
370
371/**
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100372 * @brief
373 * Get a pointer to an adjacency object from its index
374 */
375static inline ip_adjacency_t *
376adj_get (adj_index_t adj_index)
377{
Neale Ranns6c3ebcc2016-10-02 21:20:15 +0100378 return (vec_elt_at_index(adj_pool, adj_index));
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100379}
380
Neale Ranns9c6a6132017-02-21 05:33:14 -0800381/**
382 * @brief Get the global configuration option for enabling per-adj counters
383 */
384static inline int
385adj_are_counters_enabled (void)
386{
387 return (adj_per_adj_counters);
388}
389
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100390#endif