ip: Path MTU
[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 neighbour 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 adjacency 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 adjacencies 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   /** Broadcast Adjacency. */
85   IP_LOOKUP_NEXT_BCAST,
86
87   /** Multicast Midchain Adjacency. An Adjacency for sending multicast packets
88    *  on a tunnel/virtual interface */
89   IP_LOOKUP_NEXT_MCAST_MIDCHAIN,
90
91   IP_LOOKUP_N_NEXT,
92 } __attribute__ ((packed)) ip_lookup_next_t;
93
94 typedef enum
95 {
96   IP4_LOOKUP_N_NEXT = IP_LOOKUP_N_NEXT,
97 } ip4_lookup_next_t;
98
99 typedef enum
100 {
101   /* Hop-by-hop header handling */
102   IP6_LOOKUP_NEXT_HOP_BY_HOP = IP_LOOKUP_N_NEXT,
103   IP6_LOOKUP_NEXT_ADD_HOP_BY_HOP,
104   IP6_LOOKUP_NEXT_POP_HOP_BY_HOP,
105   IP6_LOOKUP_N_NEXT,
106 } ip6_lookup_next_t;
107
108 #define IP4_LOOKUP_NEXT_NODES {                                 \
109     [IP_LOOKUP_NEXT_DROP] = "ip4-drop",                         \
110     [IP_LOOKUP_NEXT_PUNT] = "ip4-punt",                         \
111     [IP_LOOKUP_NEXT_LOCAL] = "ip4-local",                       \
112     [IP_LOOKUP_NEXT_ARP] = "ip4-arp",                           \
113     [IP_LOOKUP_NEXT_GLEAN] = "ip4-glean",                       \
114     [IP_LOOKUP_NEXT_REWRITE] = "ip4-rewrite",                   \
115     [IP_LOOKUP_NEXT_MCAST] = "ip4-rewrite-mcast",               \
116     [IP_LOOKUP_NEXT_BCAST] = "ip4-rewrite-bcast",               \
117     [IP_LOOKUP_NEXT_MIDCHAIN] = "ip4-midchain",                 \
118     [IP_LOOKUP_NEXT_MCAST_MIDCHAIN] = "ip4-mcast-midchain",     \
119     [IP_LOOKUP_NEXT_ICMP_ERROR] = "ip4-icmp-error",             \
120 }
121
122 #define IP6_LOOKUP_NEXT_NODES {                                 \
123     [IP_LOOKUP_NEXT_DROP] = "ip6-drop",                         \
124     [IP_LOOKUP_NEXT_PUNT] = "ip6-punt",                         \
125     [IP_LOOKUP_NEXT_LOCAL] = "ip6-local",                       \
126     [IP_LOOKUP_NEXT_ARP] = "ip6-discover-neighbor",             \
127     [IP_LOOKUP_NEXT_GLEAN] = "ip6-glean",                       \
128     [IP_LOOKUP_NEXT_REWRITE] = "ip6-rewrite",                   \
129     [IP_LOOKUP_NEXT_BCAST] = "ip6-rewrite-bcast",               \
130     [IP_LOOKUP_NEXT_MCAST] = "ip6-rewrite-mcast",               \
131     [IP_LOOKUP_NEXT_MIDCHAIN] = "ip6-midchain",                 \
132     [IP_LOOKUP_NEXT_MCAST_MIDCHAIN] = "ip6-mcast-midchain",     \
133     [IP_LOOKUP_NEXT_ICMP_ERROR] = "ip6-icmp-error",             \
134     [IP6_LOOKUP_NEXT_HOP_BY_HOP] = "ip6-hop-by-hop",            \
135     [IP6_LOOKUP_NEXT_ADD_HOP_BY_HOP] = "ip6-add-hop-by-hop",    \
136     [IP6_LOOKUP_NEXT_POP_HOP_BY_HOP] = "ip6-pop-hop-by-hop",    \
137 }
138
139 /**
140  * The special broadcast address (to construct a broadcast adjacency
141  */
142 extern const ip46_address_t ADJ_BCAST_ADDR;
143
144 /**
145  * Forward declaration
146  */
147 struct ip_adjacency_t_;
148
149 /**
150  * @brief A function type for post-rewrite fixups on midchain adjacency
151  */
152 typedef void (*adj_midchain_fixup_t) (vlib_main_t * vm,
153                                       const struct ip_adjacency_t_ * adj,
154                                       vlib_buffer_t * b0,
155                                       const void *data);
156
157 /**
158  * @brief Flags on an IP adjacency
159  */
160 typedef enum adj_attr_t_
161 {
162     /**
163      * Currently a sync walk is active. Used to prevent re-entrant walking
164      */
165     ADJ_ATTR_SYNC_WALK_ACTIVE = 0,
166
167     /**
168      * Packets TX through the midchain do not increment the interface
169      * counters. This should be used when the adj is associated with an L2
170      * interface and that L2 interface is in a bridge domain. In that case
171      * the packet will have traversed the interface's TX node, and hence have
172      * been counted, before it traverses ths midchain
173      */
174     ADJ_ATTR_MIDCHAIN_NO_COUNT,
175     /**
176      * When stacking midchains on a fib-entry extract the choice from the
177      * load-balance returned based on an IP hash of the adj's rewrite
178      */
179     ADJ_ATTR_MIDCHAIN_IP_STACK,
180     /**
181      * If the midchain were to stack on its FIB entry a loop would form.
182      */
183     ADJ_ATTR_MIDCHAIN_LOOPED,
184     /**
185      * the fixup function is standard IP4o4 header
186      */
187     ADJ_ATTR_MIDCHAIN_FIXUP_IP4O4_HDR,
188     /**
189      * the fixup function performs the flow hash
190      * this means the flow hash is performed on the inner
191      * header, where the entropy is higher.
192      */
193     ADJ_ATTR_MIDCHAIN_FIXUP_FLOW_HASH,
194 }  adj_attr_t;
195
196 #define ADJ_ATTR_NAMES {                                        \
197     [ADJ_ATTR_SYNC_WALK_ACTIVE] = "walk-active",                \
198     [ADJ_ATTR_MIDCHAIN_NO_COUNT] = "midchain-no-count",         \
199     [ADJ_ATTR_MIDCHAIN_IP_STACK] = "midchain-ip-stack",         \
200     [ADJ_ATTR_MIDCHAIN_LOOPED] = "midchain-looped",             \
201     [ADJ_ATTR_MIDCHAIN_FIXUP_IP4O4_HDR] = "midchain-ip4o4-hdr-fixup",   \
202     [ADJ_ATTR_MIDCHAIN_FIXUP_FLOW_HASH] = "midchain-flow-hash",   \
203 }
204
205 #define FOR_EACH_ADJ_ATTR(_attr)                        \
206     for (_attr = ADJ_ATTR_SYNC_WALK_ACTIVE;             \
207          _attr <= ADJ_ATTR_MIDCHAIN_FIXUP_FLOW_HASH;    \
208          _attr++)
209
210 /**
211  * @brief Flags on an IP adjacency
212  */
213 typedef enum adj_flags_t_
214 {
215     ADJ_FLAG_NONE = 0,
216     ADJ_FLAG_SYNC_WALK_ACTIVE = (1 << ADJ_ATTR_SYNC_WALK_ACTIVE),
217     ADJ_FLAG_MIDCHAIN_NO_COUNT = (1 << ADJ_ATTR_MIDCHAIN_NO_COUNT),
218     ADJ_FLAG_MIDCHAIN_IP_STACK = (1 << ADJ_ATTR_MIDCHAIN_IP_STACK),
219     ADJ_FLAG_MIDCHAIN_LOOPED = (1 << ADJ_ATTR_MIDCHAIN_LOOPED),
220     ADJ_FLAG_MIDCHAIN_FIXUP_IP4O4_HDR = (1 << ADJ_ATTR_MIDCHAIN_FIXUP_IP4O4_HDR),
221     ADJ_FLAG_MIDCHAIN_FIXUP_FLOW_HASH = (1 << ADJ_ATTR_MIDCHAIN_FIXUP_FLOW_HASH),
222 }  __attribute__ ((packed)) adj_flags_t;
223
224 /**
225  * @brief Format adjacency flags
226  */
227 extern u8* format_adj_flags(u8 * s, va_list * args);
228
229 /**
230  * @brief IP unicast adjacency.
231  *  @note cache aligned.
232  *
233  * An adjacency is a representation of a peer on a particular link.
234  */
235 typedef struct ip_adjacency_t_
236 {
237   CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
238
239   /**
240    * Linkage into the FIB node graph. First member since this type
241    * has 8 byte alignment requirements.
242    */
243   fib_node_t ia_node;
244   /**
245    * feature [arc] config index
246    */
247   u32 ia_cfg_index;
248
249   union
250   {
251     /**
252      * IP_LOOKUP_NEXT_ARP/IP_LOOKUP_NEXT_REWRITE
253      *
254      * neighbour adjacency sub-type;
255      */
256     struct
257     {
258       ip46_address_t next_hop;
259     } nbr;
260       /**
261        * IP_LOOKUP_NEXT_MIDCHAIN
262        *
263        * A nbr adj that is also recursive. Think tunnels.
264        * A nbr adj can transition to be of type MIDCHAIN
265        * so be sure to leave the two structs with the next_hop
266        * fields aligned.
267        */
268     struct
269     {
270       /**
271        * The recursive next-hop.
272        *  This field MUST be at the same memory location as
273        *   sub_type.nbr.next_hop
274        */
275       ip46_address_t next_hop;
276       /**
277        * The next DPO to use
278        */
279       dpo_id_t next_dpo;
280       /**
281        * A function to perform the post-rewrite fixup
282        */
283       adj_midchain_fixup_t fixup_func;
284       /**
285        * Fixup data passed back to the client in the fixup function
286        */
287       const void *fixup_data;
288       /**
289        * the FIB entry this midchain resolves through. required for recursive
290        * loop detection.
291        */
292       fib_node_index_t fei;
293
294       /** spare space */
295       u8 __ia_midchain_pad[4];
296
297     } midchain;
298     /**
299      * IP_LOOKUP_NEXT_GLEAN
300      *
301      * Glean the address to ARP for from the packet's destination.
302      * Technically these aren't adjacencies, i.e. they are not a
303      * representation of a peer. One day we might untangle this coupling
304      * and use a new Glean DPO.
305      */
306     struct
307     {
308       fib_prefix_t rx_pfx;
309     } glean;
310   } sub_type;
311
312   CLIB_CACHE_LINE_ALIGN_MARK (cacheline1);
313
314   /** Rewrite in second and third cache lines */
315   VNET_DECLARE_REWRITE;
316
317   /**
318    * more control plane members that do not fit on the first cacheline
319    */
320   CLIB_CACHE_LINE_ALIGN_MARK (cacheline3);
321
322   /**
323    * A sorted vector of delegates
324    */
325   struct adj_delegate_t_ *ia_delegates;
326
327   /**
328    * The VLIB node in which this adj is used to forward packets
329    */
330   u32 ia_node_index;
331
332   /**
333    * Next hop after ip4-lookup.
334    *  This is not accessed in the rewrite nodes.
335    * 1-bytes
336    */
337   ip_lookup_next_t lookup_next_index;
338
339   /**
340    * link/ether-type
341    * 1 bytes
342    */
343   vnet_link_t ia_link;
344
345   /**
346    * The protocol of the neighbor/peer. i.e. the protocol with
347    * which to interpret the 'next-hop' attributes of the sub-types.
348    * 1-bytes
349    */
350   fib_protocol_t ia_nh_proto;
351
352   /**
353    * Flags on the adjacency
354    * 1-bytes
355    */
356   adj_flags_t ia_flags;
357
358   /**
359    * Free space on the fourth cacheline (not used in the DP)
360    */
361   u8 __ia_pad[48];
362 } ip_adjacency_t;
363
364 STATIC_ASSERT ((STRUCT_OFFSET_OF (ip_adjacency_t, cacheline0) == 0),
365                "IP adjacency cacheline 0 is not offset");
366 STATIC_ASSERT ((STRUCT_OFFSET_OF (ip_adjacency_t, cacheline1) ==
367                 CLIB_CACHE_LINE_BYTES),
368                "IP adjacency cacheline 1 is more than one cacheline size offset");
369 #if defined __x86_64__
370 STATIC_ASSERT ((STRUCT_OFFSET_OF (ip_adjacency_t, cacheline3) ==
371                 3 * CLIB_CACHE_LINE_BYTES),
372                "IP adjacency cacheline 3 is more than one cacheline size offset");
373 /* An adj fits into 4 cachelines on your average machine */
374 STATIC_ASSERT_SIZEOF (ip_adjacency_t, 4 * 64);
375 #endif
376 STATIC_ASSERT ((STRUCT_OFFSET_OF (ip_adjacency_t, sub_type.nbr.next_hop) ==
377                 STRUCT_OFFSET_OF (ip_adjacency_t, sub_type.midchain.next_hop)),
378                "IP adjacency nbr and midchain offsets don't match");
379
380 /**
381  * @brief
382  *   Take a reference counting lock on the adjacency
383  */
384 extern void adj_lock(adj_index_t adj_index);
385 /**
386  * @brief
387  *   Release a reference counting lock on the adjacency
388  */
389 extern void adj_unlock(adj_index_t adj_index);
390
391 /**
392  * @brief
393  *  Add a child dependent to an adjacency. The child will
394  *  thus be informed via its registered back-walk function
395  *  when the adjacency state changes.
396  */
397 extern u32 adj_child_add(adj_index_t adj_index,
398                          fib_node_type_t type,
399                          fib_node_index_t child_index);
400 /**
401  * @brief
402  *  Remove a child dependent
403  */
404 extern void adj_child_remove(adj_index_t adj_index,
405                              u32 sibling_index);
406
407 /**
408  * @brief Walk the Adjacencies on a given interface
409  */
410 extern void adj_walk (u32 sw_if_index,
411                       adj_walk_cb_t cb,
412                       void *ctx);
413
414 /**
415  * @brief Return the link type of the adjacency
416  */
417 extern vnet_link_t adj_get_link_type (adj_index_t ai);
418
419 /**
420  * @brief Return the sw interface index of the adjacency.
421  */
422 extern u32 adj_get_sw_if_index (adj_index_t ai);
423
424 /**
425  * @brief Return true if the adjacency is 'UP', i.e. can be used for forwarding.
426  * 0 is down, !0 is up.
427  */
428 extern int adj_is_up (adj_index_t ai);
429
430 /**
431  * @brief Return the link type of the adjacency
432  */
433 extern const u8* adj_get_rewrite (adj_index_t ai);
434
435 /**
436  * @brief descend the FIB graph looking for loops
437  *
438  * @param ai
439  *  The adj index to traverse
440  *
441  * @param entry_indicies)
442  *  A pointer to a vector of FIB entries already visited.
443  */
444 extern int adj_recursive_loop_detect (adj_index_t ai,
445                                       fib_node_index_t **entry_indicies);
446
447 /**
448  * @brief
449  * The global adjacency pool. Exposed for fast/inline data-plane access
450  */
451 extern ip_adjacency_t *adj_pool;
452
453 /**
454  * @brief 
455  * Adjacency packet counters
456  */
457 extern vlib_combined_counter_main_t adjacency_counters;
458
459 /**
460  * @brief Global Config for enabling per-adjacency counters
461  * This is configurable because it comes with  a non-negligible
462  * performance cost. */
463 extern int adj_per_adj_counters;
464
465 /**
466  * @brief
467  * Get a pointer to an adjacency object from its index
468  */
469 static inline ip_adjacency_t *
470 adj_get (adj_index_t adj_index)
471 {
472     return (pool_elt_at_index(adj_pool, adj_index));
473 }
474
475 static inline int
476 adj_is_valid(adj_index_t adj_index)
477 {
478   return !(pool_is_free_index(adj_pool, adj_index));
479 }
480
481 /**
482  * @brief Get the global configuration option for enabling per-adj counters
483  */
484 static inline int 
485 adj_are_counters_enabled (void)
486 {
487     return (adj_per_adj_counters);
488 }
489
490 #endif