1a78ecbc49f73cfc398c3c59449ad0eee0b7045f
[vpp.git] / vnet / vnet / adj / adj_nbr.c
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 #include <vnet/adj/adj_nbr.h>
17 #include <vnet/adj/adj_internal.h>
18 #include <vnet/ethernet/arp_packet.h>
19 #include <vnet/fib/fib_walk.h>
20
21 /*
22  * Vector Hash tables of neighbour (traditional) adjacencies
23  *  Key: interface(for the vector index), address (and its proto),
24  *       link-type/ether-type.
25  */
26 static BVT(clib_bihash) **adj_nbr_tables[FIB_PROTOCOL_MAX];
27
28 // FIXME SIZE APPROPRIATELY. ASK DAVEB.
29 #define ADJ_NBR_DEFAULT_HASH_NUM_BUCKETS (64 * 64)
30 #define ADJ_NBR_DEFAULT_HASH_MEMORY_SIZE (32<<20)
31
32
33 #define ADJ_NBR_SET_KEY(_key, _lt, _nh)         \
34 {                                               \
35     _key.key[0] = (_nh)->as_u64[0];             \
36     _key.key[1] = (_nh)->as_u64[1];             \
37     _key.key[2] = (_lt);                        \
38 }
39
40 #define ADJ_NBR_ITF_OK(_proto, _itf)                    \
41     (((_itf) < vec_len(adj_nbr_tables[_proto])) &&      \
42      (NULL != adj_nbr_tables[_proto][sw_if_index]))
43
44 static void
45 adj_nbr_insert (fib_protocol_t nh_proto,
46                 vnet_link_t link_type,
47                 const ip46_address_t *nh_addr,
48                 u32 sw_if_index,
49                 adj_index_t adj_index)
50 {
51     BVT(clib_bihash_kv) kv;
52
53     if (sw_if_index >= vec_len(adj_nbr_tables[nh_proto]))
54     {
55         vec_validate(adj_nbr_tables[nh_proto], sw_if_index);
56     }
57     if (NULL == adj_nbr_tables[nh_proto][sw_if_index])
58     {
59         adj_nbr_tables[nh_proto][sw_if_index] =
60             clib_mem_alloc_aligned(sizeof(BVT(clib_bihash)),
61                                    CLIB_CACHE_LINE_BYTES);
62         memset(adj_nbr_tables[nh_proto][sw_if_index],
63                0,
64                sizeof(BVT(clib_bihash)));
65
66         BV(clib_bihash_init) (adj_nbr_tables[nh_proto][sw_if_index],
67                               "Adjacency Neighbour table",
68                               ADJ_NBR_DEFAULT_HASH_NUM_BUCKETS,
69                               ADJ_NBR_DEFAULT_HASH_MEMORY_SIZE);
70     }
71
72     ADJ_NBR_SET_KEY(kv, link_type, nh_addr);
73     kv.value = adj_index;
74
75     BV(clib_bihash_add_del) (adj_nbr_tables[nh_proto][sw_if_index], &kv, 1);
76 }
77
78 void
79 adj_nbr_remove (fib_protocol_t nh_proto,
80                 vnet_link_t link_type,
81                 const ip46_address_t *nh_addr,
82                 u32 sw_if_index)
83 {
84     BVT(clib_bihash_kv) kv;
85
86     if (!ADJ_NBR_ITF_OK(nh_proto, sw_if_index))
87         return;
88
89     ADJ_NBR_SET_KEY(kv, link_type, nh_addr);
90
91     BV(clib_bihash_add_del) (adj_nbr_tables[nh_proto][sw_if_index], &kv, 0);
92 }
93
94 static adj_index_t
95 adj_nbr_find (fib_protocol_t nh_proto,
96               vnet_link_t link_type,
97               const ip46_address_t *nh_addr,
98               u32 sw_if_index)
99 {
100     BVT(clib_bihash_kv) kv;
101
102     ADJ_NBR_SET_KEY(kv, link_type, nh_addr);
103
104     if (!ADJ_NBR_ITF_OK(nh_proto, sw_if_index))
105         return (ADJ_INDEX_INVALID);
106
107     if (BV(clib_bihash_search)(adj_nbr_tables[nh_proto][sw_if_index],
108                                &kv, &kv) < 0)
109     {
110         return (ADJ_INDEX_INVALID);
111     }
112     else
113     {
114         return (kv.value);
115     }
116 }
117
118 static inline u32
119 adj_get_nd_node (fib_protocol_t proto)
120 {
121     switch (proto) {
122     case FIB_PROTOCOL_IP4:
123         return (ip4_arp_node.index);
124     case FIB_PROTOCOL_IP6:
125         return (ip6_discover_neighbor_node.index);
126     case FIB_PROTOCOL_MPLS:
127         break;
128     }
129     ASSERT(0);
130     return (ip4_arp_node.index);
131 }
132
133 static ip_adjacency_t*
134 adj_nbr_alloc (fib_protocol_t nh_proto,
135                vnet_link_t link_type,
136                const ip46_address_t *nh_addr,
137                u32 sw_if_index)
138 {
139     ip_adjacency_t *adj;
140
141     adj = adj_alloc(nh_proto);
142
143     adj_nbr_insert(nh_proto, link_type, nh_addr,
144                    sw_if_index,
145                    adj_get_index(adj));
146
147     /*
148      * since we just added the ADJ we have no rewrite string for it,
149      * so its for ARP
150      */
151     adj->lookup_next_index = IP_LOOKUP_NEXT_ARP;
152     adj->sub_type.nbr.next_hop = *nh_addr;
153     adj->ia_link = link_type;
154     adj->ia_nh_proto = nh_proto;
155     adj->rewrite_header.sw_if_index = sw_if_index;
156     memset(&adj->sub_type.midchain.next_dpo, 0,
157            sizeof(adj->sub_type.midchain.next_dpo));
158
159     return (adj);
160 }
161
162 /*
163  * adj_add_for_nbr
164  *
165  * Add an adjacency for the neighbour requested.
166  *
167  * The key for an adj is:
168  *   - the Next-hops protocol (i.e. v4 or v6)
169  *   - the address of the next-hop
170  *   - the interface the next-hop is reachable through
171  */
172 adj_index_t
173 adj_nbr_add_or_lock (fib_protocol_t nh_proto,
174                      vnet_link_t link_type,
175                      const ip46_address_t *nh_addr,
176                      u32 sw_if_index)
177 {
178     adj_index_t adj_index;
179     ip_adjacency_t *adj;
180
181     adj_index = adj_nbr_find(nh_proto, link_type, nh_addr, sw_if_index);
182
183     if (ADJ_INDEX_INVALID == adj_index)
184     {
185         vnet_main_t *vnm;
186
187         vnm = vnet_get_main();
188         adj = adj_nbr_alloc(nh_proto, link_type, nh_addr, sw_if_index);
189         adj_index = adj_get_index(adj);
190         adj_lock(adj_index);
191
192         vnet_rewrite_init(vnm, sw_if_index,
193                           adj_get_nd_node(nh_proto),
194                           vnet_tx_node_index_for_sw_interface(vnm, sw_if_index),
195                           &adj->rewrite_header);
196
197         /*
198          * we need a rewrite where the destination IP address is converted
199          * to the appropriate link-layer address. This is interface specific.
200          * So ask the interface to do it.
201          */
202         vnet_update_adjacency_for_sw_interface(vnm, sw_if_index, adj_index);
203     }
204     else
205     {
206         adj_lock(adj_index);
207     }
208
209     return (adj_index);
210 }
211
212 adj_index_t
213 adj_nbr_add_or_lock_w_rewrite (fib_protocol_t nh_proto,
214                                vnet_link_t link_type,
215                                const ip46_address_t *nh_addr,
216                                u32 sw_if_index,
217                                u8 *rewrite)
218 {
219     adj_index_t adj_index;
220     ip_adjacency_t *adj;
221
222     adj_index = adj_nbr_find(nh_proto, link_type, nh_addr, sw_if_index);
223
224     if (ADJ_INDEX_INVALID == adj_index)
225     {
226         adj = adj_nbr_alloc(nh_proto, link_type, nh_addr, sw_if_index);
227         adj->rewrite_header.sw_if_index = sw_if_index;
228     }
229     else
230     {
231         adj = adj_get(adj_index);
232     }
233
234     adj_lock(adj_get_index(adj));
235     adj_nbr_update_rewrite(adj_get_index(adj),
236                            ADJ_NBR_REWRITE_FLAG_COMPLETE,
237                            rewrite);
238
239     return (adj_get_index(adj));
240 }
241
242 /**
243  * adj_nbr_update_rewrite
244  *
245  * Update the adjacency's rewrite string. A NULL string implies the
246  * rewirte is reset (i.e. when ARP/ND etnry is gone).
247  * NB: the adj being updated may be handling traffic in the DP.
248  */
249 void
250 adj_nbr_update_rewrite (adj_index_t adj_index,
251                         adj_nbr_rewrite_flag_t flags,
252                         u8 *rewrite)
253 {
254     ip_adjacency_t *adj;
255
256     ASSERT(ADJ_INDEX_INVALID != adj_index);
257
258     adj = adj_get(adj_index);
259
260     if (flags & ADJ_NBR_REWRITE_FLAG_COMPLETE)
261     {
262         /*
263          * update the adj's rewrite string and build the arc
264          * from the rewrite node to the interface's TX node
265          */
266         adj_nbr_update_rewrite_internal(adj, IP_LOOKUP_NEXT_REWRITE,
267                                         adj_get_rewrite_node(adj->ia_link),
268                                         vnet_tx_node_index_for_sw_interface(
269                                             vnet_get_main(),
270                                             adj->rewrite_header.sw_if_index),
271                                         rewrite);
272     }
273     else
274     {
275         adj_nbr_update_rewrite_internal(adj, IP_LOOKUP_NEXT_ARP,
276                                         adj_get_nd_node(adj->ia_nh_proto),
277                                         vnet_tx_node_index_for_sw_interface(
278                                             vnet_get_main(),
279                                             adj->rewrite_header.sw_if_index),
280                                         rewrite);
281     }
282 }
283
284 /**
285  * adj_nbr_update_rewrite_internal
286  *
287  * Update the adjacency's rewrite string. A NULL string implies the
288  * rewirte is reset (i.e. when ARP/ND etnry is gone).
289  * NB: the adj being updated may be handling traffic in the DP.
290  */
291 void
292 adj_nbr_update_rewrite_internal (ip_adjacency_t *adj,
293                                  u32 adj_next_index,
294                                  u32 this_node,
295                                  u32 next_node,
296                                  u8 *rewrite)
297 {
298     adj_index_t walk_ai;
299     vlib_main_t * vm;
300     u32 old_next;
301
302     vm = vlib_get_main();
303     old_next = adj->lookup_next_index;
304
305     walk_ai = adj_get_index(adj);
306     if (VNET_LINK_MPLS == adj->ia_link)
307     {
308         /*
309          * The link type MPLS has no children in the control plane graph, it only
310          * has children in the data-palne graph. The backwalk is up the former.
311          * So we need to walk from its IP cousin.
312          */
313         walk_ai = adj_nbr_find(adj->ia_nh_proto,
314                                fib_proto_to_link(adj->ia_nh_proto),
315                                &adj->sub_type.nbr.next_hop,
316                                adj->rewrite_header.sw_if_index);
317     }
318
319     /*
320      * Updating a rewrite string is not atomic;
321      *  - the rewrite string is too long to write in one instruction
322      *  - when swapping from incomplete to complete, we also need to update
323      *    the VLIB graph next-index of the adj.
324      * ideally we would only want to suspend forwarding via this adj whilst we
325      * do this, but we do not have that level of granularity - it's suspend all
326      * worker threads or nothing.
327      * The other chioces are:
328      *  - to mark the adj down and back walk so child load-balances drop this adj
329      *    from the set.
330      *  - update the next_node index of this adj to point to error-drop
331      * both of which will mean for MAC change we will drop for this adj
332      * which is not acceptable. However, when the adj changes type (from
333      * complete to incomplete and vice-versa) the child DPOs, which have the
334      * VLIB graph next node index, will be sending packets to the wrong graph
335      * node. So from the options above, updating the next_node of the adj to
336      * be drop will work, but it relies on each graph node v4/v6/mpls, rewrite/
337      * arp/midchain always be valid w.r.t. a mis-match of adj type and node type
338      * (i.e. a rewrite adj in the arp node). This is not enforcable. Getting it
339      * wrong will lead to hard to find bugs since its a race condition. So we
340      * choose the more reliable method of updating the children to use the drop,
341      * then switching adj's type, then updating the children again. Did I mention
342      * that this doesn't happen often...
343      * So we need to distinguish between the two cases:
344      *  1 - mac change
345      *  2 - adj type change
346      */
347     if (old_next != adj_next_index &&
348         ADJ_INDEX_INVALID != walk_ai)
349     {
350         /*
351          * the adj is changing type. we need to fix all children so that they
352          * stack momentarily on a drop, while the adj changes. If we don't do
353          * this  the children will send packets to a VLIB graph node that does
354          * not correspond to the adj's type - and it goes downhill from there.
355          */
356         fib_node_back_walk_ctx_t bw_ctx = {
357             .fnbw_reason = FIB_NODE_BW_REASON_FLAG_ADJ_DOWN,
358             /*
359              * force this walk to be synchrous. if we don't and a node in the graph
360              * (a heavily shared path-list) chooses to back-ground the walk (make it
361              * async) then it will pause and we will do the adj update below, before
362              * all the children are updated. not good.
363              */
364             .fnbw_flags = FIB_NODE_BW_FLAG_FORCE_SYNC,
365         };
366
367         fib_walk_sync(FIB_NODE_TYPE_ADJ, walk_ai, &bw_ctx);
368     }
369
370     /*
371      * If we are just updating the MAC string of the adj (which we also can't
372      * do atomically), then we need to stop packets switching through the adj.
373      * We can't do that on a per-adj basis, so it's all the packets.
374      * If we are updating the type, and we walked back to the children above,
375      * then this barrier serves to flush the queues/frames.
376      */
377     vlib_worker_thread_barrier_sync(vm);
378
379     adj->lookup_next_index = adj_next_index;
380
381     if (NULL != rewrite)
382     {
383         /*
384          * new rewrite provided.
385          * fill in the adj's rewrite string, and build the VLIB graph arc.
386          */
387         vnet_rewrite_set_data_internal(&adj->rewrite_header,
388                                        sizeof(adj->rewrite_data),
389                                        rewrite,
390                                        vec_len(rewrite));
391         vec_free(rewrite);
392     }
393     else
394     {
395         vnet_rewrite_clear_data_internal(&adj->rewrite_header,
396                                          sizeof(adj->rewrite_data));
397     }
398     adj->rewrite_header.node_index = this_node;
399     adj->rewrite_header.next_index = vlib_node_add_next(vlib_get_main(),
400                                                         this_node,
401                                                         next_node);
402
403     /*
404      * done with the rewirte update - let the workers loose.
405      */
406     vlib_worker_thread_barrier_release(vm);
407
408     if (old_next != adj->lookup_next_index &&
409         ADJ_INDEX_INVALID != walk_ai)
410     {
411         /*
412          * backwalk to the children so they can stack on the now updated
413          * adjacency
414          */
415         fib_node_back_walk_ctx_t bw_ctx = {
416             .fnbw_reason = FIB_NODE_BW_REASON_FLAG_ADJ_UPDATE,
417         };
418
419         fib_walk_sync(FIB_NODE_TYPE_ADJ, walk_ai, &bw_ctx);
420     }
421 }
422
423 typedef struct adj_db_count_ctx_t_ {
424     u64 count;
425 } adj_db_count_ctx_t;
426
427 static void
428 adj_db_count (BVT(clib_bihash_kv) * kvp,
429               void *arg)
430 {
431     adj_db_count_ctx_t * ctx = arg;
432     ctx->count++;
433 }
434
435 u32
436 adj_nbr_db_size (void)
437 {
438     adj_db_count_ctx_t ctx = {
439         .count = 0,
440     };
441     fib_protocol_t proto;
442     u32 sw_if_index = 0;
443
444     for (proto = FIB_PROTOCOL_IP4; proto <= FIB_PROTOCOL_IP6; proto++)
445     {
446         vec_foreach_index(sw_if_index, adj_nbr_tables[proto])
447         {
448             if (NULL != adj_nbr_tables[proto][sw_if_index])
449             {
450                 BV(clib_bihash_foreach_key_value_pair) (
451                     adj_nbr_tables[proto][sw_if_index],
452                     adj_db_count,
453                     &ctx);
454             }
455         }
456     }
457     return (ctx.count);
458 }
459
460 /**
461  * @brief Context for a walk of the adjacency neighbour DB
462  */
463 typedef struct adj_walk_ctx_t_
464 {
465     adj_walk_cb_t awc_cb;
466     void *awc_ctx;
467 } adj_walk_ctx_t;
468
469 static void
470 adj_nbr_walk_cb (BVT(clib_bihash_kv) * kvp,
471                  void *arg)
472 {
473     adj_walk_ctx_t *ctx = arg;
474
475     // FIXME: can't stop early...
476     ctx->awc_cb(kvp->value, ctx->awc_ctx);
477 }
478
479 void
480 adj_nbr_walk (u32 sw_if_index,
481               fib_protocol_t adj_nh_proto,
482               adj_walk_cb_t cb,
483               void *ctx)
484 {
485     if (!ADJ_NBR_ITF_OK(adj_nh_proto, sw_if_index))
486         return;
487
488     adj_walk_ctx_t awc = {
489         .awc_ctx = ctx,
490         .awc_cb = cb,
491     };
492
493     BV(clib_bihash_foreach_key_value_pair) (
494         adj_nbr_tables[adj_nh_proto][sw_if_index],
495         adj_nbr_walk_cb,
496         &awc);
497 }
498
499 /**
500  * @brief Context for a walk of the adjacency neighbour DB
501  */
502 typedef struct adj_walk_nh_ctx_t_
503 {
504     adj_walk_cb_t awc_cb;
505     void *awc_ctx;
506     const ip46_address_t *awc_nh;
507 } adj_walk_nh_ctx_t;
508
509 static void
510 adj_nbr_walk_nh_cb (BVT(clib_bihash_kv) * kvp,
511                     void *arg)
512 {
513     ip_adjacency_t *adj;
514     adj_walk_nh_ctx_t *ctx = arg;
515
516     adj = adj_get(kvp->value);
517
518     if (!ip46_address_cmp(&adj->sub_type.nbr.next_hop, ctx->awc_nh)) 
519         ctx->awc_cb(kvp->value, ctx->awc_ctx);
520 }
521
522 /**
523  * @brief Walk adjacencies on a link with a given v4 next-hop.
524  * that is visit the adjacencies with different link types.
525  */
526 void
527 adj_nbr_walk_nh4 (u32 sw_if_index,
528                  const ip4_address_t *addr,
529                  adj_walk_cb_t cb,
530                  void *ctx)
531 {
532     if (!ADJ_NBR_ITF_OK(FIB_PROTOCOL_IP4, sw_if_index))
533         return;
534
535     ip46_address_t nh = {
536         .ip4 = *addr,
537     };
538
539     adj_walk_nh_ctx_t awc = {
540         .awc_ctx = ctx,
541         .awc_cb = cb,
542         .awc_nh = &nh,
543     };
544
545     BV(clib_bihash_foreach_key_value_pair) (
546         adj_nbr_tables[FIB_PROTOCOL_IP4][sw_if_index],
547         adj_nbr_walk_nh_cb,
548         &awc);
549 }
550
551 /**
552  * @brief Walk adjacencies on a link with a given v6 next-hop.
553  * that is visit the adjacencies with different link types.
554  */
555 void
556 adj_nbr_walk_nh6 (u32 sw_if_index,
557                  const ip6_address_t *addr,
558                  adj_walk_cb_t cb,
559                  void *ctx)
560 {
561     if (!ADJ_NBR_ITF_OK(FIB_PROTOCOL_IP6, sw_if_index))
562         return;
563
564     ip46_address_t nh = {
565         .ip6 = *addr,
566     };
567
568     adj_walk_nh_ctx_t awc = {
569         .awc_ctx = ctx,
570         .awc_cb = cb,
571         .awc_nh = &nh,
572     };
573
574     BV(clib_bihash_foreach_key_value_pair) (
575         adj_nbr_tables[FIB_PROTOCOL_IP6][sw_if_index],
576         adj_nbr_walk_nh_cb,
577         &awc);
578 }
579
580 /**
581  * @brief Walk adjacencies on a link with a given next-hop.
582  * that is visit the adjacencies with different link types.
583  */
584 void
585 adj_nbr_walk_nh (u32 sw_if_index,
586                  fib_protocol_t adj_nh_proto,
587                  const ip46_address_t *nh,
588                  adj_walk_cb_t cb,
589                  void *ctx)
590 {
591     if (!ADJ_NBR_ITF_OK(adj_nh_proto, sw_if_index))
592         return;
593
594     adj_walk_nh_ctx_t awc = {
595         .awc_ctx = ctx,
596         .awc_cb = cb,
597         .awc_nh = nh,
598     };
599
600     BV(clib_bihash_foreach_key_value_pair) (
601         adj_nbr_tables[adj_nh_proto][sw_if_index],
602         adj_nbr_walk_nh_cb,
603         &awc);
604 }
605
606 /**
607  * Flags associated with the interface state walks
608  */
609 typedef enum adj_nbr_interface_flags_t_
610 {
611     ADJ_NBR_INTERFACE_UP = (1 << 0),
612 } adj_nbr_interface_flags_t;
613
614 /**
615  * Context for the state change walk of the DB
616  */
617 typedef struct adj_nbr_interface_state_change_ctx_t_
618 {
619     /**
620      * Flags on the interface
621      */
622     adj_nbr_interface_flags_t flags;
623 } adj_nbr_interface_state_change_ctx_t;
624
625 static adj_walk_rc_t
626 adj_nbr_interface_state_change_one (adj_index_t ai,
627                                     void *arg)
628 {
629     /*
630      * Back walk the graph to inform the forwarding entries
631      * that this interface state has changed. Do this synchronously
632      * since this is the walk that provides convergence
633      */
634     adj_nbr_interface_state_change_ctx_t *ctx = arg;
635
636     fib_node_back_walk_ctx_t bw_ctx = {
637         .fnbw_reason = ((ctx->flags & ADJ_NBR_INTERFACE_UP) ?
638                         FIB_NODE_BW_REASON_FLAG_INTERFACE_UP :
639                         FIB_NODE_BW_REASON_FLAG_INTERFACE_DOWN),
640         /*
641          * the force sync applies only as far as the first fib_entry.
642          * And it's the fib_entry's we need to converge away from
643          * the adjacencies on the now down link
644          */
645         .fnbw_flags = (!(ctx->flags & ADJ_NBR_INTERFACE_UP) ?
646                        FIB_NODE_BW_FLAG_FORCE_SYNC :
647                        0),
648     };
649
650     fib_walk_sync(FIB_NODE_TYPE_ADJ, ai, &bw_ctx);
651
652     return (ADJ_WALK_RC_CONTINUE);
653 }
654
655 /**
656  * @brief Registered function for SW interface state changes
657  */
658 static clib_error_t *
659 adj_nbr_sw_interface_state_change (vnet_main_t * vnm,
660                                    u32 sw_if_index,
661                                    u32 flags)
662 {
663     fib_protocol_t proto;
664
665     /*
666      * walk each adj on the interface and trigger a walk from that adj
667      */
668     for (proto = FIB_PROTOCOL_IP4; proto <= FIB_PROTOCOL_IP6; proto++)
669     {
670         adj_nbr_interface_state_change_ctx_t ctx = {
671             .flags = ((flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) ?
672                       ADJ_NBR_INTERFACE_UP :
673                       0),
674         };
675
676         adj_nbr_walk(sw_if_index, proto,
677                      adj_nbr_interface_state_change_one,
678                      &ctx);
679     }
680
681     return (NULL);
682 }
683
684 VNET_SW_INTERFACE_ADMIN_UP_DOWN_FUNCTION_PRIO(
685     adj_nbr_sw_interface_state_change,
686     VNET_ITF_FUNC_PRIORITY_HIGH);
687
688 /**
689  * @brief Invoked on each SW interface of a HW interface when the
690  * HW interface state changes
691  */
692 static void
693 adj_nbr_hw_sw_interface_state_change (vnet_main_t * vnm,
694                                       u32 sw_if_index,
695                                       void *arg)
696 {
697     adj_nbr_interface_state_change_ctx_t *ctx = arg;
698     fib_protocol_t proto;
699
700     /*
701      * walk each adj on the interface and trigger a walk from that adj
702      */
703     for (proto = FIB_PROTOCOL_IP4; proto <= FIB_PROTOCOL_IP6; proto++)
704     {
705         adj_nbr_walk(sw_if_index, proto,
706                      adj_nbr_interface_state_change_one,
707                      ctx);
708     }
709 }
710
711 /**
712  * @brief Registered callback for HW interface state changes
713  */
714 static clib_error_t *
715 adj_nbr_hw_interface_state_change (vnet_main_t * vnm,
716                                    u32 hw_if_index,
717                                    u32 flags)
718 {
719     /*
720      * walk SW interface on the HW
721      */
722     adj_nbr_interface_state_change_ctx_t ctx = {
723         .flags = ((flags & VNET_HW_INTERFACE_FLAG_LINK_UP) ?
724                   ADJ_NBR_INTERFACE_UP :
725                   0),
726     };
727
728     vnet_hw_interface_walk_sw(vnm, hw_if_index,
729                               adj_nbr_hw_sw_interface_state_change,
730                               &ctx);
731
732     return (NULL);
733 }
734
735 VNET_HW_INTERFACE_LINK_UP_DOWN_FUNCTION_PRIO(
736     adj_nbr_hw_interface_state_change,
737     VNET_ITF_FUNC_PRIORITY_HIGH);
738
739 static adj_walk_rc_t
740 adj_nbr_interface_delete_one (adj_index_t ai,
741                               void *arg)
742 {
743     /*
744      * Back walk the graph to inform the forwarding entries
745      * that this interface has been deleted.
746      */
747     fib_node_back_walk_ctx_t bw_ctx = {
748         .fnbw_reason = FIB_NODE_BW_REASON_FLAG_INTERFACE_DELETE,
749     };
750
751     fib_walk_sync(FIB_NODE_TYPE_ADJ, ai, &bw_ctx);
752
753     return (ADJ_WALK_RC_CONTINUE);
754 }
755
756 /**
757  * adj_nbr_interface_add_del
758  *
759  * Registered to receive interface Add and delete notifications
760  */
761 static clib_error_t *
762 adj_nbr_interface_add_del (vnet_main_t * vnm,
763                            u32 sw_if_index,
764                            u32 is_add)
765 {
766     fib_protocol_t proto;
767
768     if (is_add)
769     {
770         /*
771          * not interested in interface additions. we will not back walk
772          * to resolve paths through newly added interfaces. Why? The control
773          * plane should have the brains to add interfaces first, then routes.
774          * So the case where there are paths with a interface that matches
775          * one just created is the case where the path resolved through an
776          * interface that was deleted, and still has not been removed. The
777          * new interface added, is NO GUARANTEE that the interface being
778          * added now, even though it may have the same sw_if_index, is the
779          * same interface that the path needs. So tough!
780          * If the control plane wants these routes to resolve it needs to
781          * remove and add them again.
782          */
783         return (NULL);
784     }
785
786     for (proto = FIB_PROTOCOL_IP4; proto <= FIB_PROTOCOL_IP6; proto++)
787     {
788         adj_nbr_walk(sw_if_index, proto,
789                      adj_nbr_interface_delete_one,
790                      NULL);
791     }
792
793     return (NULL);
794    
795 }
796
797 VNET_SW_INTERFACE_ADD_DEL_FUNCTION(adj_nbr_interface_add_del);
798
799
800 static adj_walk_rc_t
801 adj_nbr_show_one (adj_index_t ai,
802                   void *arg)
803 {
804     vlib_cli_output (arg, "[@%d]  %U",
805                      ai,
806                      format_ip_adjacency, ai,
807                      FORMAT_IP_ADJACENCY_NONE);
808
809     return (ADJ_WALK_RC_CONTINUE);
810 }
811
812 static clib_error_t *
813 adj_nbr_show (vlib_main_t * vm,
814               unformat_input_t * input,
815               vlib_cli_command_t * cmd)
816 {
817     adj_index_t ai = ADJ_INDEX_INVALID;
818     u32 sw_if_index = ~0;
819
820     while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
821     {
822         if (unformat (input, "%d", &ai))
823             ;
824         else if (unformat (input, "%U",
825                            unformat_vnet_sw_interface, vnet_get_main(),
826                            &sw_if_index))
827             ;
828         else
829             break;
830     }
831
832     if (ADJ_INDEX_INVALID != ai)
833     {
834         vlib_cli_output (vm, "[@%d] %U",
835                          ai,
836                          format_ip_adjacency, ai,
837                          FORMAT_IP_ADJACENCY_DETAIL);
838     }
839     else if (~0 != sw_if_index)
840     {
841         fib_protocol_t proto;
842
843         for (proto = FIB_PROTOCOL_IP4; proto <= FIB_PROTOCOL_IP6; proto++)
844         {
845             adj_nbr_walk(sw_if_index, proto,
846                          adj_nbr_show_one,
847                          vm);
848         }
849     }
850     else
851     {
852         fib_protocol_t proto;
853
854         for (proto = FIB_PROTOCOL_IP4; proto <= FIB_PROTOCOL_IP6; proto++)
855         {
856             vec_foreach_index(sw_if_index, adj_nbr_tables[proto])
857             {
858                 adj_nbr_walk(sw_if_index, proto,
859                              adj_nbr_show_one,
860                              vm);
861             }
862         }
863     }
864
865     return 0;
866 }
867
868 /*?
869  * Show all neighbour adjacencies.
870  * @cliexpar
871  * @cliexstart{sh adj nbr}
872  * [@2] ipv4 via 1.0.0.2 loop0: IP4: 00:00:22:aa:bb:cc -> 00:00:11:aa:bb:cc
873  * [@3] mpls via 1.0.0.2 loop0: MPLS_UNICAST: 00:00:22:aa:bb:cc -> 00:00:11:aa:bb:cc
874  * [@4] ipv4 via 1.0.0.3 loop0: IP4: 00:00:22:aa:bb:cc -> 00:00:11:aa:bb:cc
875  * [@5] mpls via 1.0.0.3 loop0: MPLS_UNICAST: 00:00:22:aa:bb:cc -> 00:00:11:aa:bb:cc
876  * @cliexend
877  ?*/
878 VLIB_CLI_COMMAND (ip4_show_fib_command, static) = {
879     .path = "show adj nbr",
880     .short_help = "show adj nbr [<adj_index>] [interface]",
881     .function = adj_nbr_show,
882 };
883
884 static ip46_type_t
885 adj_proto_to_46 (fib_protocol_t proto)
886 {
887     switch (proto)
888     {
889     case FIB_PROTOCOL_IP4:
890         return (IP46_TYPE_IP4);
891     case FIB_PROTOCOL_IP6:
892         return (IP46_TYPE_IP6);
893     default:
894         return (IP46_TYPE_IP4);
895     }
896     return (IP46_TYPE_IP4);
897 }
898
899 u8*
900 format_adj_nbr_incomplete (u8* s, va_list *ap)
901 {
902     index_t index = va_arg(*ap, index_t);
903     CLIB_UNUSED(u32 indent) = va_arg(*ap, u32);
904     vnet_main_t * vnm = vnet_get_main();
905     ip_adjacency_t * adj = adj_get(index);
906
907     s = format (s, "arp-%U", format_vnet_link, adj->ia_link);
908     s = format (s, ": via %U",
909                 format_ip46_address, &adj->sub_type.nbr.next_hop,
910                 adj_proto_to_46(adj->ia_nh_proto));
911     s = format (s, " %U",
912                 format_vnet_sw_interface_name,
913                 vnm,
914                 vnet_get_sw_interface(vnm,
915                                       adj->rewrite_header.sw_if_index));
916
917     return (s);
918 }
919
920 u8*
921 format_adj_nbr (u8* s, va_list *ap)
922 {
923     index_t index = va_arg(*ap, index_t);
924     CLIB_UNUSED(u32 indent) = va_arg(*ap, u32);
925     vnet_main_t * vnm = vnet_get_main();
926     ip_adjacency_t * adj = adj_get(index);
927
928     s = format (s, "%U", format_vnet_link, adj->ia_link);
929     s = format (s, " via %U ",
930                 format_ip46_address, &adj->sub_type.nbr.next_hop,
931                 adj_proto_to_46(adj->ia_nh_proto));
932     s = format (s, "%U",
933                 format_vnet_rewrite,
934                 vnm->vlib_main, &adj->rewrite_header, sizeof (adj->rewrite_data), 0);
935
936     return (s);
937 }
938
939 static void
940 adj_dpo_lock (dpo_id_t *dpo)
941 {
942     adj_lock(dpo->dpoi_index);
943 }
944 static void
945 adj_dpo_unlock (dpo_id_t *dpo)
946 {
947     adj_unlock(dpo->dpoi_index);
948 }
949
950 static void
951 adj_mem_show (void)
952 {
953     fib_show_memory_usage("Adjacency",
954                           pool_elts(adj_pool),
955                           pool_len(adj_pool),
956                           sizeof(ip_adjacency_t));
957 }
958
959 const static dpo_vft_t adj_nbr_dpo_vft = {
960     .dv_lock = adj_dpo_lock,
961     .dv_unlock = adj_dpo_unlock,
962     .dv_format = format_adj_nbr,
963     .dv_mem_show = adj_mem_show,
964 };
965 const static dpo_vft_t adj_nbr_incompl_dpo_vft = {
966     .dv_lock = adj_dpo_lock,
967     .dv_unlock = adj_dpo_unlock,
968     .dv_format = format_adj_nbr_incomplete,
969 };
970
971 /**
972  * @brief The per-protocol VLIB graph nodes that are assigned to an adjacency
973  *        object.
974  *
975  * this means that these graph nodes are ones from which a nbr is the
976  * parent object in the DPO-graph.
977  */
978 const static char* const nbr_ip4_nodes[] =
979 {
980     "ip4-rewrite-transit",
981     NULL,
982 };
983 const static char* const nbr_ip6_nodes[] =
984 {
985     "ip6-rewrite",
986     NULL,
987 };
988 const static char* const nbr_mpls_nodes[] =
989 {
990     "mpls-output",
991     NULL,
992 };
993 const static char* const nbr_ethernet_nodes[] =
994 {
995     "adj-l2-rewrite",
996     NULL,
997 };
998 const static char* const * const nbr_nodes[DPO_PROTO_NUM] =
999 {
1000     [DPO_PROTO_IP4]  = nbr_ip4_nodes,
1001     [DPO_PROTO_IP6]  = nbr_ip6_nodes,
1002     [DPO_PROTO_MPLS] = nbr_mpls_nodes,
1003     [DPO_PROTO_ETHERNET] = nbr_ethernet_nodes,
1004 };
1005
1006 const static char* const nbr_incomplete_ip4_nodes[] =
1007 {
1008     "ip4-arp",
1009     NULL,
1010 };
1011 const static char* const nbr_incomplete_ip6_nodes[] =
1012 {
1013     "ip6-discover-neighbor",
1014     NULL,
1015 };
1016 const static char* const nbr_incomplete_mpls_nodes[] =
1017 {
1018     "mpls-adj-incomplete",
1019     NULL,
1020 };
1021
1022 const static char* const * const nbr_incomplete_nodes[DPO_PROTO_NUM] =
1023 {
1024     [DPO_PROTO_IP4]  = nbr_incomplete_ip4_nodes,
1025     [DPO_PROTO_IP6]  = nbr_incomplete_ip6_nodes,
1026     [DPO_PROTO_MPLS] = nbr_incomplete_mpls_nodes,
1027 };
1028
1029 void
1030 adj_nbr_module_init (void)
1031 {
1032     dpo_register(DPO_ADJACENCY,
1033                  &adj_nbr_dpo_vft,
1034                  nbr_nodes);
1035     dpo_register(DPO_ADJACENCY_INCOMPLETE,
1036                  &adj_nbr_incompl_dpo_vft,
1037                  nbr_incomplete_nodes);
1038 }