af7730f70866a7ca2a69731157f811b6c8c6976e
[vpp.git] / src / vnet / adj / adj.h
1 /*
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.
27  *
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
44 #include <vnet/adj/adj_types.h>
45 #include <vnet/adj/adj_nbr.h>
46 #include <vnet/adj/adj_glean.h>
47 #include <vnet/adj/rewrite.h>
48
49 /** @brief Common (IP4/IP6) next index stored in adjacency. */
50 typedef 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
84   IP_LOOKUP_N_NEXT,
85 } __attribute__ ((packed)) ip_lookup_next_t;
86
87 typedef enum
88 {
89   IP4_LOOKUP_N_NEXT = IP_LOOKUP_N_NEXT,
90 } ip4_lookup_next_t;
91
92 typedef enum
93 {
94   /* Hop-by-hop header handling */
95   IP6_LOOKUP_NEXT_HOP_BY_HOP = IP_LOOKUP_N_NEXT,
96   IP6_LOOKUP_NEXT_ADD_HOP_BY_HOP,
97   IP6_LOOKUP_NEXT_POP_HOP_BY_HOP,
98   IP6_LOOKUP_N_NEXT,
99 } ip6_lookup_next_t;
100
101 #define IP4_LOOKUP_NEXT_NODES {                                 \
102     [IP_LOOKUP_NEXT_DROP] = "ip4-drop",                         \
103     [IP_LOOKUP_NEXT_PUNT] = "ip4-punt",                         \
104     [IP_LOOKUP_NEXT_LOCAL] = "ip4-local",                       \
105     [IP_LOOKUP_NEXT_ARP] = "ip4-arp",                           \
106     [IP_LOOKUP_NEXT_GLEAN] = "ip4-glean",                       \
107     [IP_LOOKUP_NEXT_REWRITE] = "ip4-rewrite",                   \
108     [IP_LOOKUP_NEXT_MCAST] = "ip4-rewrite-mcast",               \
109     [IP_LOOKUP_NEXT_MIDCHAIN] = "ip4-midchain",                 \
110     [IP_LOOKUP_NEXT_ICMP_ERROR] = "ip4-icmp-error",             \
111 }
112
113 #define IP6_LOOKUP_NEXT_NODES {                                 \
114     [IP_LOOKUP_NEXT_DROP] = "ip6-drop",                         \
115     [IP_LOOKUP_NEXT_PUNT] = "ip6-punt",                         \
116     [IP_LOOKUP_NEXT_LOCAL] = "ip6-local",                       \
117     [IP_LOOKUP_NEXT_ARP] = "ip6-discover-neighbor",             \
118     [IP_LOOKUP_NEXT_GLEAN] = "ip6-glean",                       \
119     [IP_LOOKUP_NEXT_REWRITE] = "ip6-rewrite",                   \
120     [IP_LOOKUP_NEXT_MCAST] = "ip6-rewrite-mcast",               \
121     [IP_LOOKUP_NEXT_MIDCHAIN] = "ip6-midchain",                 \
122     [IP_LOOKUP_NEXT_ICMP_ERROR] = "ip6-icmp-error",             \
123     [IP6_LOOKUP_NEXT_HOP_BY_HOP] = "ip6-hop-by-hop",            \
124     [IP6_LOOKUP_NEXT_ADD_HOP_BY_HOP] = "ip6-add-hop-by-hop",    \
125     [IP6_LOOKUP_NEXT_POP_HOP_BY_HOP] = "ip6-pop-hop-by-hop",    \
126 }
127
128 /**
129  * Forward delcartion
130  */
131 struct ip_adjacency_t_;
132
133 /**
134  * @brief A function type for post-rewrite fixups on midchain adjacency
135  */
136 typedef void (*adj_midchain_fixup_t) (vlib_main_t * vm,
137                                       struct ip_adjacency_t_ * adj,
138                                       vlib_buffer_t * b0);
139
140 /**
141  * @brief Flags on an IP adjacency
142  */
143 typedef enum ip_adjacency_flags_t_
144 {
145     ADJ_FLAG_NONE = 0,
146
147     /**
148      * Currently a sync walk is active. Used to prevent re-entrant walking
149      */
150     ADJ_FLAG_SYNC_WALK_ACTIVE = (1 << 0),
151
152     /**
153      * Packets TX through the midchain do not increment the interface
154      * counters. This should be used when the adj is associated with an L2
155      * interface and that L2 interface is in a bridege domain. In that case
156      * the packet will have traversed the interface's TX node, and hence have
157      * been counted, before it traverses ths midchain
158      */
159     ADJ_FLAG_MIDCHAIN_NO_COUNT = (1 << 1),
160 }  __attribute__ ((packed)) adj_flags_t;
161
162 /**
163  * @brief IP unicast adjacency.
164  *  @note cache aligned.
165  *
166  * An adjacency is a represenation of a peer on a particular link.
167  */
168 typedef struct ip_adjacency_t_
169 {
170   CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
171
172   /**
173    * Linkage into the FIB node grpah. First member since this type
174    * has 8 byte alignment requirements.
175    */
176   fib_node_t ia_node;
177
178   /**
179    * Next hop after ip4-lookup.
180    *  This is not accessed in the rewrite nodes.
181    * 1-bytes
182    */
183   ip_lookup_next_t lookup_next_index;
184
185   /**
186    * link/ether-type
187    * 1 bytes
188    */
189   vnet_link_t ia_link;
190
191   /**
192    * The protocol of the neighbor/peer. i.e. the protocol with
193    * which to interpret the 'next-hop' attirbutes of the sub-types.
194    * 1-btyes
195    */
196   fib_protocol_t ia_nh_proto;
197
198   /**
199    * Flags on the adjacency
200    * 1-bytes
201    */
202   adj_flags_t ia_flags;
203
204   union
205   {
206     /**
207      * IP_LOOKUP_NEXT_ARP/IP_LOOKUP_NEXT_REWRITE
208      *
209      * neighbour adjacency sub-type;
210      */
211     struct
212     {
213       ip46_address_t next_hop;
214     } nbr;
215       /**
216        * IP_LOOKUP_NEXT_MIDCHAIN
217        *
218        * A nbr adj that is also recursive. Think tunnels.
219        * A nbr adj can transition to be of type MDICHAIN
220        * so be sure to leave the two structs with the next_hop
221        * fields aligned.
222        */
223     struct
224     {
225       /**
226        * The recursive next-hop.
227        *  This field MUST be at the same memory location as
228        *   sub_type.nbr.next_hop
229        */
230       ip46_address_t next_hop;
231       /**
232        * The next DPO to use
233        */
234       dpo_id_t next_dpo;
235       /**
236        * A function to perform the post-rewrite fixup
237        */
238       adj_midchain_fixup_t fixup_func;
239     } midchain;
240     /**
241      * IP_LOOKUP_NEXT_GLEAN
242      *
243      * Glean the address to ARP for from the packet's destination.
244      * Technically these aren't adjacencies, i.e. they are not a
245      * representation of a peer. One day we might untangle this coupling
246      * and use a new Glean DPO.
247      */
248     struct
249     {
250       ip46_address_t receive_addr;
251     } glean;
252   } sub_type;
253
254   CLIB_CACHE_LINE_ALIGN_MARK (cacheline1);
255
256   /* Rewrite in second/third cache lines */
257   vnet_declare_rewrite (VLIB_BUFFER_PRE_DATA_SIZE);
258 } ip_adjacency_t;
259
260 STATIC_ASSERT ((STRUCT_OFFSET_OF (ip_adjacency_t, cacheline0) == 0),
261                "IP adjacency cachline 0 is not offset");
262 STATIC_ASSERT ((STRUCT_OFFSET_OF (ip_adjacency_t, cacheline1) ==
263                 CLIB_CACHE_LINE_BYTES),
264                "IP adjacency cachline 1 is more than one cachline size offset");
265
266 /**
267  * @brief
268  *   Take a reference counting lock on the adjacency
269  */
270 extern void adj_lock(adj_index_t adj_index);
271 /**
272  * @brief
273  *   Release a reference counting lock on the adjacency
274  */
275 extern void adj_unlock(adj_index_t adj_index);
276
277 /**
278  * @brief
279  *  Add a child dependent to an adjacency. The child will
280  *  thus be informed via its registerd back-walk function
281  *  when the adjacency state changes.
282  */
283 extern u32 adj_child_add(adj_index_t adj_index,
284                          fib_node_type_t type,
285                          fib_node_index_t child_index);
286 /**
287  * @brief
288  *  Remove a child dependent
289  */
290 extern void adj_child_remove(adj_index_t adj_index,
291                              u32 sibling_index);
292
293 /**
294  * @brief Walk the Adjacencies on a given interface
295  */
296 extern void adj_walk (u32 sw_if_index,
297                       adj_walk_cb_t cb,
298                       void *ctx);
299
300 /**
301  * @brief Return the link type of the adjacency
302  */
303 extern vnet_link_t adj_get_link_type (adj_index_t ai);
304
305 /**
306  * @brief Return the sw interface index of the adjacency.
307  */
308 extern u32 adj_get_sw_if_index (adj_index_t ai);
309
310 /**
311  * @brief Return the link type of the adjacency
312  */
313 extern const u8* adj_get_rewrite (adj_index_t ai);
314
315 /**
316  * @brief Notify the adjacency subsystem that the features settings for
317  * an interface have changed
318  */
319 extern void adj_feature_update (u32 sw_if_index, u8 arc_index, u8 is_enable);
320
321 /**
322  * @brief
323  * The global adjacnecy pool. Exposed for fast/inline data-plane access
324  */
325 extern ip_adjacency_t *adj_pool;
326
327 /**
328  * @brief 
329  * Adjacency packet counters
330  */
331 extern vlib_combined_counter_main_t adjacency_counters;
332
333 /**
334  * @brief Global Config for enabling per-adjacency counters
335  * This is configurable because it comes with  a non-negligible
336  * performance cost. */
337 extern int adj_per_adj_counters;
338
339 /**
340  * @brief
341  * Get a pointer to an adjacency object from its index
342  */
343 static inline ip_adjacency_t *
344 adj_get (adj_index_t adj_index)
345 {
346     return (vec_elt_at_index(adj_pool, adj_index));
347 }
348
349 /**
350  * @brief Get the global configuration option for enabling per-adj counters
351  */
352 static inline int 
353 adj_are_counters_enabled (void)
354 {
355     return (adj_per_adj_counters);
356 }
357
358 #endif