Coverage Report

Created: 2025-08-03 06:36

/src/frr/bgpd/rfapi/rfapi_rib.c
Line
Count
Source (jump to first uncovered line)
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
/*
3
 *
4
 * Copyright 2009-2016, LabN Consulting, L.L.C.
5
 *
6
 */
7
8
/*
9
 * File:  rfapi_rib.c
10
 * Purpose: maintain per-nve ribs and generate change lists
11
 */
12
13
#include "lib/zebra.h"
14
#include "lib/prefix.h"
15
#include "lib/agg_table.h"
16
#include "lib/vty.h"
17
#include "lib/memory.h"
18
#include "lib/log.h"
19
#include "lib/skiplist.h"
20
#include "lib/workqueue.h"
21
22
#include "bgpd/bgpd.h"
23
#include "bgpd/bgp_route.h"
24
#include "bgpd/bgp_ecommunity.h"
25
#include "bgpd/bgp_mplsvpn.h"
26
#include "bgpd/bgp_vnc_types.h"
27
28
#include "bgpd/rfapi/rfapi.h"
29
#include "bgpd/rfapi/bgp_rfapi_cfg.h"
30
#include "bgpd/rfapi/rfapi_import.h"
31
#include "bgpd/rfapi/rfapi_private.h"
32
#include "bgpd/rfapi/rfapi_vty.h"
33
#include "bgpd/rfapi/vnc_import_bgp.h"
34
#include "bgpd/rfapi/rfapi_rib.h"
35
#include "bgpd/rfapi/rfapi_monitor.h"
36
#include "bgpd/rfapi/rfapi_encap_tlv.h"
37
#include "bgpd/rfapi/vnc_debug.h"
38
39
#define DEBUG_PROCESS_PENDING_NODE  0
40
#define DEBUG_PENDING_DELETE_ROUTE  0
41
#define DEBUG_NHL     0
42
#define DEBUG_RIB_SL_RD                 0
43
#define DEBUG_CLEANUP 0
44
45
/* forward decl */
46
#if DEBUG_NHL
47
static void rfapiRibShowRibSl(void *stream, struct prefix *pfx,
48
            struct skiplist *sl);
49
#endif
50
51
/*
52
 * RIB
53
 * ---
54
 * Model of the set of routes currently in the NVE's RIB.
55
 *
56
 * node->info   ptr to "struct skiplist".
57
 *      MUST be NULL if there are no routes.
58
 *      key = ptr to struct prefix {vn}
59
 *      val = ptr to struct rfapi_info
60
 *      skiplist.del = NULL
61
 *      skiplist.cmp = vnc_prefix_cmp
62
 *
63
 * node->aggregate  ptr to "struct skiplist".
64
 *      key = ptr to struct prefix {vn}
65
 *      val = ptr to struct rfapi_info
66
 *      skiplist.del = rfapi_info_free
67
 *      skiplist.cmp = vnc_prefix_cmp
68
 *
69
 *      This skiplist at "aggregate"
70
 *      contains the routes recently
71
 *      deleted
72
 *
73
 *
74
 * Pending RIB
75
 * -----------
76
 * Sparse list of prefixes that need to be updated. Each node
77
 * will have the complete set of routes for the prefix.
78
 *
79
 * node->info   ptr to "struct list" (lib/linklist.h)
80
 *      "Cost List"
81
 *      List of routes sorted lowest cost first.
82
 *      This list is how the new complete set
83
 *      of routes should look.
84
 *      Set if there are updates to the prefix;
85
 *      MUST be NULL if there are no updates.
86
 *
87
 *      .data = ptr to struct rfapi_info
88
 *      list.cmp = NULL (sorted manually)
89
 *      list.del = rfapi_info_free
90
 *
91
 *      Special case: if node->info is 1, it means
92
 *      "delete all routes at this prefix".
93
 *
94
 * node->aggregate  ptr to struct skiplist
95
 *      key = ptr to struct prefix {vn} (part of ri)
96
 *      val =  struct rfapi_info
97
 *      skiplist.cmp = vnc_prefix_cmp
98
 *      skiplist.del = NULL
99
 *
100
 *      ptlist is rewritten anew each time
101
 *      rfapiRibUpdatePendingNode() is called
102
 *
103
 *      THE ptlist VALUES ARE REFERENCES TO THE
104
 *      rfapi_info STRUCTS IN THE node->info LIST.
105
 */
106
107
/*
108
 * iterate over RIB to count responses, compare with running counters
109
 */
110
void rfapiRibCheckCounts(
111
  int checkstats,      /* validate rfd & global counts */
112
  unsigned int offset) /* number of ri's held separately */
113
0
{
114
0
  struct rfapi_descriptor *rfd;
115
0
  struct listnode *node;
116
117
0
  struct bgp *bgp = bgp_get_default();
118
119
0
  uint32_t t_pfx_active = 0;
120
121
0
  uint32_t t_ri_active = 0;
122
0
  uint32_t t_ri_deleted = 0;
123
0
  uint32_t t_ri_pend = 0;
124
125
0
  unsigned int alloc_count;
126
127
  /*
128
   * loop over NVEs
129
   */
130
0
  for (ALL_LIST_ELEMENTS_RO(&bgp->rfapi->descriptors, node, rfd)) {
131
132
0
    afi_t afi;
133
0
    uint32_t pfx_active = 0;
134
135
0
    for (afi = AFI_IP; afi < AFI_MAX; ++afi) {
136
137
0
      struct agg_node *rn;
138
139
0
      for (rn = agg_route_top(rfd->rib[afi]); rn;
140
0
           rn = agg_route_next(rn)) {
141
142
0
        struct skiplist *sl = rn->info;
143
0
        struct skiplist *dsl = rn->aggregate;
144
0
        uint32_t ri_active = 0;
145
0
        uint32_t ri_deleted = 0;
146
147
0
        if (sl) {
148
0
          ri_active = skiplist_count(sl);
149
0
          assert(ri_active);
150
0
          t_ri_active += ri_active;
151
0
          ++pfx_active;
152
0
          ++t_pfx_active;
153
0
        }
154
155
0
        if (dsl) {
156
0
          ri_deleted = skiplist_count(dsl);
157
0
          t_ri_deleted += ri_deleted;
158
0
        }
159
0
      }
160
0
      for (rn = agg_route_top(rfd->rib_pending[afi]); rn;
161
0
           rn = agg_route_next(rn)) {
162
163
0
        struct list *l = rn->info; /* sorted by cost */
164
0
        struct skiplist *sl = rn->aggregate;
165
0
        uint32_t ri_pend_cost = 0;
166
0
        uint32_t ri_pend_uniq = 0;
167
168
0
        if (sl) {
169
0
          ri_pend_uniq = skiplist_count(sl);
170
0
        }
171
172
0
        if (l && (l != (void *)1)) {
173
0
          ri_pend_cost = l->count;
174
0
          t_ri_pend += l->count;
175
0
        }
176
177
0
        assert(ri_pend_uniq == ri_pend_cost);
178
0
      }
179
0
    }
180
181
0
    if (checkstats) {
182
0
      if (pfx_active != rfd->rib_prefix_count) {
183
0
        vnc_zlog_debug_verbose(
184
0
          "%s: rfd %p actual pfx count %u != running %u",
185
0
          __func__, rfd, pfx_active,
186
0
          rfd->rib_prefix_count);
187
0
        assert(0);
188
0
      }
189
0
    }
190
0
  }
191
192
0
  if (checkstats && bgp->rfapi) {
193
0
    if (t_pfx_active != bgp->rfapi->rib_prefix_count_total) {
194
0
      vnc_zlog_debug_verbose(
195
0
        "%s: actual total pfx count %u != running %u",
196
0
        __func__, t_pfx_active,
197
0
        bgp->rfapi->rib_prefix_count_total);
198
0
      assert(0);
199
0
    }
200
0
  }
201
202
  /*
203
   * Check against memory allocation count
204
   */
205
0
  alloc_count = mtype_stats_alloc(MTYPE_RFAPI_INFO);
206
0
  assert(t_ri_active + t_ri_deleted + t_ri_pend + offset == alloc_count);
207
0
}
208
209
static struct rfapi_info *rfapi_info_new(void)
210
0
{
211
0
  return XCALLOC(MTYPE_RFAPI_INFO, sizeof(struct rfapi_info));
212
0
}
213
214
void rfapiFreeRfapiUnOptionChain(struct rfapi_un_option *p)
215
0
{
216
0
  while (p) {
217
0
    struct rfapi_un_option *next;
218
219
0
    next = p->next;
220
0
    XFREE(MTYPE_RFAPI_UN_OPTION, p);
221
0
    p = next;
222
0
  }
223
0
}
224
225
void rfapiFreeRfapiVnOptionChain(struct rfapi_vn_option *p)
226
0
{
227
0
  while (p) {
228
0
    struct rfapi_vn_option *next;
229
230
0
    next = p->next;
231
0
    XFREE(MTYPE_RFAPI_VN_OPTION, p);
232
0
    p = next;
233
0
  }
234
0
}
235
236
237
static void rfapi_info_free(struct rfapi_info *goner)
238
0
{
239
0
  if (goner) {
240
0
    if (goner->tea_options) {
241
0
      rfapiFreeBgpTeaOptionChain(goner->tea_options);
242
0
      goner->tea_options = NULL;
243
0
    }
244
0
    if (goner->un_options) {
245
0
      rfapiFreeRfapiUnOptionChain(goner->un_options);
246
0
      goner->un_options = NULL;
247
0
    }
248
0
    if (goner->vn_options) {
249
0
      rfapiFreeRfapiVnOptionChain(goner->vn_options);
250
0
      goner->vn_options = NULL;
251
0
    }
252
0
    if (goner->timer) {
253
0
      struct rfapi_rib_tcb *tcb;
254
255
0
      tcb = EVENT_ARG(goner->timer);
256
0
      EVENT_OFF(goner->timer);
257
0
      XFREE(MTYPE_RFAPI_RECENT_DELETE, tcb);
258
0
    }
259
0
    XFREE(MTYPE_RFAPI_INFO, goner);
260
0
  }
261
0
}
262
263
/*
264
 * Timer control block for recently-deleted and expired routes
265
 */
266
struct rfapi_rib_tcb {
267
  struct rfapi_descriptor *rfd;
268
  struct skiplist *sl;
269
  struct rfapi_info *ri;
270
  struct agg_node *rn;
271
  int flags;
272
#define RFAPI_RIB_TCB_FLAG_DELETED  0x00000001
273
};
274
275
/*
276
 * remove route from rib
277
 */
278
static void rfapiRibExpireTimer(struct event *t)
279
0
{
280
0
  struct rfapi_rib_tcb *tcb = EVENT_ARG(t);
281
0
282
0
  RFAPI_RIB_CHECK_COUNTS(1, 0);
283
0
284
0
  /*
285
0
   * Forget reference to thread. Otherwise rfapi_info_free() will
286
0
   * attempt to free thread pointer as an option chain
287
0
   */
288
0
  tcb->ri->timer = NULL;
289
0
290
0
  /* "deleted" skiplist frees ri, "active" doesn't */
291
0
  assert(!skiplist_delete(tcb->sl, &tcb->ri->rk, NULL));
292
0
  if (!tcb->sl->del) {
293
0
    /*
294
0
     * XXX in this case, skiplist has no delete function: we must
295
0
     * therefore delete rfapi_info explicitly.
296
0
     */
297
0
    rfapi_info_free(tcb->ri);
298
0
  }
299
0
300
0
  if (skiplist_empty(tcb->sl)) {
301
0
    if (CHECK_FLAG(tcb->flags, RFAPI_RIB_TCB_FLAG_DELETED))
302
0
      tcb->rn->aggregate = NULL;
303
0
    else {
304
0
      struct bgp *bgp = bgp_get_default();
305
0
      tcb->rn->info = NULL;
306
0
      RFAPI_RIB_PREFIX_COUNT_DECR(tcb->rfd, bgp->rfapi);
307
0
    }
308
0
    skiplist_free(tcb->sl);
309
0
    agg_unlock_node(tcb->rn);
310
0
  }
311
0
312
0
  XFREE(MTYPE_RFAPI_RECENT_DELETE, tcb);
313
0
314
0
  RFAPI_RIB_CHECK_COUNTS(1, 0);
315
0
}
316
317
static void rfapiRibStartTimer(struct rfapi_descriptor *rfd,
318
             struct rfapi_info *ri,
319
             struct agg_node *rn, /* route node attached to */
320
             int deleted)
321
0
{
322
0
  struct rfapi_rib_tcb *tcb = NULL;
323
324
0
  if (ri->timer) {
325
0
    tcb = EVENT_ARG(ri->timer);
326
0
    EVENT_OFF(ri->timer);
327
0
  } else {
328
0
    tcb = XCALLOC(MTYPE_RFAPI_RECENT_DELETE,
329
0
            sizeof(struct rfapi_rib_tcb));
330
0
  }
331
#if DEBUG_CLEANUP
332
  zlog_debug("%s: rfd %p, rn %p, ri %p, tcb %p", __func__, rfd, rn, ri,
333
       tcb);
334
#endif
335
336
0
  tcb->rfd = rfd;
337
0
  tcb->ri = ri;
338
0
  tcb->rn = rn;
339
0
  if (deleted) {
340
0
    tcb->sl = (struct skiplist *)rn->aggregate;
341
0
    SET_FLAG(tcb->flags, RFAPI_RIB_TCB_FLAG_DELETED);
342
0
  } else {
343
0
    tcb->sl = (struct skiplist *)rn->info;
344
0
    UNSET_FLAG(tcb->flags, RFAPI_RIB_TCB_FLAG_DELETED);
345
0
  }
346
347
0
  vnc_zlog_debug_verbose("%s: rfd %p pfx %pRN life %u", __func__, rfd, rn,
348
0
             ri->lifetime);
349
350
0
  event_add_timer(bm->master, rfapiRibExpireTimer, tcb, ri->lifetime,
351
0
      &ri->timer);
352
0
}
353
354
extern void rfapi_rib_key_init(struct prefix *prefix, /* may be NULL */
355
             struct prefix_rd *rd,  /* may be NULL */
356
             struct prefix *aux,    /* may be NULL */
357
             struct rfapi_rib_key *rk)
358
359
0
{
360
0
  memset((void *)rk, 0, sizeof(struct rfapi_rib_key));
361
0
  if (prefix)
362
0
    rk->vn = *prefix;
363
0
  if (rd)
364
0
    rk->rd = *rd;
365
0
  if (aux)
366
0
    rk->aux_prefix = *aux;
367
0
}
368
369
/*
370
 * Compares two <struct rfapi_rib_key>s
371
 */
372
int rfapi_rib_key_cmp(const void *k1, const void *k2)
373
0
{
374
0
  const struct rfapi_rib_key *a = (struct rfapi_rib_key *)k1;
375
0
  const struct rfapi_rib_key *b = (struct rfapi_rib_key *)k2;
376
0
  int ret;
377
378
0
  if (!a || !b)
379
0
    return (a - b);
380
381
0
  ret = vnc_prefix_cmp(&a->vn, &b->vn);
382
0
  if (ret)
383
0
    return ret;
384
385
0
  ret = vnc_prefix_cmp(&a->rd, &b->rd);
386
0
  if (ret)
387
0
    return ret;
388
389
0
  ret = vnc_prefix_cmp(&a->aux_prefix, &b->aux_prefix);
390
391
0
  return ret;
392
0
}
393
394
395
/*
396
 * Note: this function will claim that two option chains are
397
 * different unless their option items are in identical order.
398
 * The consequence is that RFP updated responses can be sent
399
 * unnecessarily, or that they might contain nexthop items
400
 * that are not strictly needed.
401
 *
402
 * This function could be modified to compare option chains more
403
 * thoroughly, but it's not clear that the extra compuation would
404
 * be worth it.
405
 */
406
static int bgp_tea_options_cmp(struct bgp_tea_options *a,
407
             struct bgp_tea_options *b)
408
0
{
409
0
  int rc;
410
411
0
  if (!a || !b) {
412
0
    return (a - b);
413
0
  }
414
415
0
  if (a->type != b->type)
416
0
    return (a->type - b->type);
417
0
  if (a->length != b->length)
418
0
    return (a->length = b->length);
419
0
  if ((rc = memcmp(a->value, b->value, a->length)))
420
0
    return rc;
421
0
  if (!a->next != !b->next) { /* logical xor */
422
0
    return (a->next - b->next);
423
0
  }
424
0
  if (a->next)
425
0
    return bgp_tea_options_cmp(a->next, b->next);
426
0
  return 0;
427
0
}
428
429
static int rfapi_info_cmp(struct rfapi_info *a, struct rfapi_info *b)
430
0
{
431
0
  int rc;
432
433
0
  if (!a || !b)
434
0
    return (a - b);
435
436
0
  if ((rc = rfapi_rib_key_cmp(&a->rk, &b->rk)))
437
0
    return rc;
438
439
0
  if ((rc = vnc_prefix_cmp(&a->un, &b->un)))
440
0
    return rc;
441
442
0
  if (a->cost != b->cost)
443
0
    return (a->cost - b->cost);
444
445
0
  if (a->lifetime != b->lifetime)
446
0
    return (a->lifetime - b->lifetime);
447
448
0
  if ((rc = bgp_tea_options_cmp(a->tea_options, b->tea_options)))
449
0
    return rc;
450
451
0
  return 0;
452
0
}
453
454
void rfapiRibClear(struct rfapi_descriptor *rfd)
455
0
{
456
0
  struct bgp *bgp;
457
0
  afi_t afi;
458
459
0
  if (rfd->bgp)
460
0
    bgp = rfd->bgp;
461
0
  else
462
0
    bgp = bgp_get_default();
463
#ifdef DEBUG_L2_EXTRA
464
  vnc_zlog_debug_verbose("%s: rfd=%p", __func__, rfd);
465
#endif
466
467
0
  for (afi = AFI_IP; afi < AFI_MAX; ++afi) {
468
0
    struct agg_node *pn;
469
0
    struct agg_node *rn;
470
471
0
    if (rfd->rib_pending[afi]) {
472
0
      for (pn = agg_route_top(rfd->rib_pending[afi]); pn;
473
0
           pn = agg_route_next(pn)) {
474
0
        if (pn->aggregate) {
475
          /*
476
           * free references into the rfapi_info
477
           * structures before
478
           * freeing the structures themselves
479
           */
480
0
          skiplist_free(
481
0
            (struct skiplist
482
0
               *)(pn->aggregate));
483
0
          pn->aggregate = NULL;
484
0
          agg_unlock_node(
485
0
            pn); /* skiplist deleted */
486
0
        }
487
        /*
488
         * free the rfapi_info structures
489
         */
490
0
        if (pn->info) {
491
0
          if (pn->info != (void *)1) {
492
0
            list_delete(
493
0
              (struct list *
494
0
                 *)(&pn->info));
495
0
          }
496
0
          pn->info = NULL;
497
          /* linklist or 1 deleted */
498
0
          agg_unlock_node(pn);
499
0
        }
500
0
      }
501
0
    }
502
0
    if (rfd->rib[afi]) {
503
0
      for (rn = agg_route_top(rfd->rib[afi]); rn;
504
0
           rn = agg_route_next(rn)) {
505
0
        if (rn->info) {
506
507
0
          struct rfapi_info *ri;
508
509
0
          while (0 == skiplist_first(
510
0
                  (struct skiplist *)
511
0
                    rn->info,
512
0
                  NULL,
513
0
                  (void **)&ri)) {
514
515
0
            if (ri->timer) {
516
0
              struct rfapi_rib_tcb
517
0
                *tcb;
518
519
0
              tcb = EVENT_ARG(
520
0
                ri->timer);
521
0
              EVENT_OFF(ri->timer);
522
0
              XFREE(MTYPE_RFAPI_RECENT_DELETE,
523
0
                    tcb);
524
0
            }
525
0
            rfapi_info_free(ri);
526
0
            skiplist_delete_first(
527
0
              (struct skiplist *)
528
0
                rn->info);
529
0
          }
530
0
          skiplist_free(
531
0
            (struct skiplist *)rn->info);
532
0
          rn->info = NULL;
533
0
          agg_unlock_node(rn);
534
0
          RFAPI_RIB_PREFIX_COUNT_DECR(rfd,
535
0
                    bgp->rfapi);
536
0
        }
537
0
        if (rn->aggregate) {
538
539
0
          struct rfapi_info *ri_del;
540
541
          /* delete skiplist & contents */
542
0
          while (!skiplist_first(
543
0
            (struct skiplist
544
0
               *)(rn->aggregate),
545
0
            NULL, (void **)&ri_del)) {
546
547
            /* sl->del takes care of ri_del
548
             */
549
0
            skiplist_delete_first((
550
0
              struct skiplist
551
0
                *)(rn->aggregate));
552
0
          }
553
0
          skiplist_free(
554
0
            (struct skiplist
555
0
               *)(rn->aggregate));
556
557
0
          rn->aggregate = NULL;
558
0
          agg_unlock_node(rn);
559
0
        }
560
0
      }
561
0
    }
562
0
  }
563
0
  if (rfd->updated_responses_queue)
564
0
    work_queue_free_and_null(&rfd->updated_responses_queue);
565
0
}
566
567
/*
568
 * Release all dynamically-allocated memory that is part of an HD's RIB
569
 */
570
void rfapiRibFree(struct rfapi_descriptor *rfd)
571
0
{
572
0
  afi_t afi;
573
574
#if DEBUG_CLEANUP
575
  zlog_debug("%s: rfd %p", __func__, rfd);
576
#endif
577
578
  /*
579
   * NB rfd is typically detached from master list, so is not included
580
   * in the count performed by RFAPI_RIB_CHECK_COUNTS
581
   */
582
583
  /*
584
   * Free routes attached to radix trees
585
   */
586
0
  rfapiRibClear(rfd);
587
588
  /* Now the uncounted rfapi_info's are freed, so the check should succeed
589
   */
590
0
  RFAPI_RIB_CHECK_COUNTS(1, 0);
591
592
  /*
593
   * Free radix trees
594
   */
595
0
  for (afi = AFI_IP; afi < AFI_MAX; ++afi) {
596
0
    if (rfd->rib_pending[afi])
597
0
      agg_table_finish(rfd->rib_pending[afi]);
598
0
    rfd->rib_pending[afi] = NULL;
599
600
0
    if (rfd->rib[afi])
601
0
      agg_table_finish(rfd->rib[afi]);
602
0
    rfd->rib[afi] = NULL;
603
604
    /* NB agg_table_finish frees only prefix nodes, not chained
605
     * info */
606
0
    if (rfd->rsp_times[afi])
607
0
      agg_table_finish(rfd->rsp_times[afi]);
608
0
    rfd->rib[afi] = NULL;
609
0
  }
610
0
}
611
612
/*
613
 * Copies struct bgp_path_info to struct rfapi_info, except for rk fields and un
614
 */
615
static void rfapiRibBi2Ri(struct bgp_path_info *bpi, struct rfapi_info *ri,
616
        uint32_t lifetime)
617
0
{
618
0
  struct bgp_attr_encap_subtlv *pEncap;
619
620
0
  ri->cost = rfapiRfpCost(bpi->attr);
621
0
  ri->lifetime = lifetime;
622
623
  /* This loop based on rfapiRouteInfo2NextHopEntry() */
624
0
  for (pEncap = bgp_attr_get_vnc_subtlvs(bpi->attr); pEncap;
625
0
       pEncap = pEncap->next) {
626
0
    struct bgp_tea_options *hop;
627
628
0
    switch (pEncap->type) {
629
0
    case BGP_VNC_SUBTLV_TYPE_LIFETIME:
630
      /* use configured lifetime, not attr lifetime */
631
0
      break;
632
633
0
    case BGP_VNC_SUBTLV_TYPE_RFPOPTION:
634
0
      hop = XCALLOC(MTYPE_BGP_TEA_OPTIONS,
635
0
              sizeof(struct bgp_tea_options));
636
0
      assert(hop);
637
0
      hop->type = pEncap->value[0];
638
0
      hop->length = pEncap->value[1];
639
0
      hop->value = XCALLOC(MTYPE_BGP_TEA_OPTIONS_VALUE,
640
0
               pEncap->length - 2);
641
0
      assert(hop->value);
642
0
      memcpy(hop->value, pEncap->value + 2,
643
0
             pEncap->length - 2);
644
0
      if (hop->length > pEncap->length - 2) {
645
0
        zlog_warn(
646
0
          "%s: VNC subtlv length mismatch: RFP option says %d, attr says %d (shrinking)",
647
0
          __func__, hop->length,
648
0
          pEncap->length - 2);
649
0
        hop->length = pEncap->length - 2;
650
0
      }
651
0
      hop->next = ri->tea_options;
652
0
      ri->tea_options = hop;
653
0
      break;
654
655
0
    default:
656
0
      break;
657
0
    }
658
0
  }
659
660
0
  rfapi_un_options_free(ri->un_options); /* maybe free old version */
661
0
  ri->un_options = rfapi_encap_tlv_to_un_option(bpi->attr);
662
663
  /*
664
   * VN options
665
   */
666
0
  if (bpi->extra
667
0
      && decode_rd_type(bpi->extra->vnc.import.rd.val)
668
0
           == RD_TYPE_VNC_ETH) {
669
    /* ethernet route */
670
671
0
    struct rfapi_vn_option *vo;
672
673
0
    vo = XCALLOC(MTYPE_RFAPI_VN_OPTION,
674
0
           sizeof(struct rfapi_vn_option));
675
0
    assert(vo);
676
677
0
    vo->type = RFAPI_VN_OPTION_TYPE_L2ADDR;
678
679
    /* copy from RD already stored in bpi, so we don't need it_node
680
     */
681
0
    memcpy(&vo->v.l2addr.macaddr, bpi->extra->vnc.import.rd.val + 2,
682
0
           ETH_ALEN);
683
684
0
    (void)rfapiEcommunityGetLNI(bgp_attr_get_ecommunity(bpi->attr),
685
0
              &vo->v.l2addr.logical_net_id);
686
0
    (void)rfapiEcommunityGetEthernetTag(
687
0
      bgp_attr_get_ecommunity(bpi->attr),
688
0
      &vo->v.l2addr.tag_id);
689
690
    /* local_nve_id comes from RD */
691
0
    vo->v.l2addr.local_nve_id = bpi->extra->vnc.import.rd.val[1];
692
693
    /* label comes from MP_REACH_NLRI label */
694
0
    vo->v.l2addr.label = decode_label(&bpi->extra->label[0]);
695
696
0
    rfapi_vn_options_free(
697
0
      ri->vn_options); /* maybe free old version */
698
0
    ri->vn_options = vo;
699
0
  }
700
701
  /*
702
   * If there is an auxiliary IP address (L2 can have it), copy it
703
   */
704
0
  if (bpi->extra && bpi->extra->vnc.import.aux_prefix.family) {
705
0
    ri->rk.aux_prefix = bpi->extra->vnc.import.aux_prefix;
706
0
  }
707
0
}
708
709
/*
710
 * rfapiRibPreloadBi
711
 *
712
 *  Install route into NVE RIB model so as to be consistent with
713
 *  caller's response to rfapi_query().
714
 *
715
 *  Also: return indication to caller whether this specific route
716
 *  should be included in the response to the NVE according to
717
 *  the following tests:
718
 *
719
 *  1. If there were prior duplicates of this route in this same
720
 *     query response, don't include the route.
721
 *
722
 * RETURN VALUE:
723
 *
724
 *  0 OK to include route in response
725
 *  !0  do not include route in response
726
 */
727
int rfapiRibPreloadBi(
728
  struct agg_node *rfd_rib_node, /* NULL = don't preload or filter */
729
  struct prefix *pfx_vn, struct prefix *pfx_un, uint32_t lifetime,
730
  struct bgp_path_info *bpi)
731
0
{
732
0
  struct rfapi_descriptor *rfd;
733
0
  struct skiplist *slRibPt = NULL;
734
0
  struct rfapi_info *ori = NULL;
735
0
  struct rfapi_rib_key rk;
736
0
  struct agg_node *trn;
737
0
  afi_t afi;
738
0
  const struct prefix *p = agg_node_get_prefix(rfd_rib_node);
739
740
0
  if (!rfd_rib_node)
741
0
    return 0;
742
743
0
  afi = family2afi(p->family);
744
745
0
  rfd = agg_get_table_info(agg_get_table(rfd_rib_node));
746
747
0
  memset((void *)&rk, 0, sizeof(rk));
748
0
  rk.vn = *pfx_vn;
749
0
  rk.rd = bpi->extra->vnc.import.rd;
750
751
  /*
752
   * If there is an auxiliary IP address (L2 can have it), copy it
753
   */
754
0
  if (bpi->extra->vnc.import.aux_prefix.family) {
755
0
    rk.aux_prefix = bpi->extra->vnc.import.aux_prefix;
756
0
  }
757
758
  /*
759
   * is this route already in NVE's RIB?
760
   */
761
0
  slRibPt = (struct skiplist *)rfd_rib_node->info;
762
763
0
  if (slRibPt && !skiplist_search(slRibPt, &rk, (void **)&ori)) {
764
765
0
    if ((ori->rsp_counter == rfd->rsp_counter)
766
0
        && (ori->last_sent_time == rfd->rsp_time)) {
767
0
      return -1; /* duplicate in this response */
768
0
    }
769
770
    /* found: update contents of existing route in RIB */
771
0
    ori->un = *pfx_un;
772
0
    rfapiRibBi2Ri(bpi, ori, lifetime);
773
0
  } else {
774
    /* not found: add new route to RIB */
775
0
    ori = rfapi_info_new();
776
0
    ori->rk = rk;
777
0
    ori->un = *pfx_un;
778
0
    rfapiRibBi2Ri(bpi, ori, lifetime);
779
780
0
    if (!slRibPt) {
781
0
      slRibPt = skiplist_new(0, rfapi_rib_key_cmp, NULL);
782
0
      rfd_rib_node->info = slRibPt;
783
0
      agg_lock_node(rfd_rib_node);
784
0
      RFAPI_RIB_PREFIX_COUNT_INCR(rfd, rfd->bgp->rfapi);
785
0
    }
786
0
    skiplist_insert(slRibPt, &ori->rk, ori);
787
0
  }
788
789
0
  ori->last_sent_time = monotime(NULL);
790
791
  /*
792
   * poke timer
793
   */
794
0
  RFAPI_RIB_CHECK_COUNTS(0, 0);
795
0
  rfapiRibStartTimer(rfd, ori, rfd_rib_node, 0);
796
0
  RFAPI_RIB_CHECK_COUNTS(0, 0);
797
798
  /*
799
   * Update last sent time for prefix
800
   */
801
0
  trn = agg_node_get(rfd->rsp_times[afi], p); /* locks trn */
802
0
  trn->info = (void *)(uintptr_t)monotime(NULL);
803
0
  if (agg_node_get_lock_count(trn) > 1)
804
0
    agg_unlock_node(trn);
805
806
0
  return 0;
807
0
}
808
809
/*
810
 * Frees rfapi_info items at node
811
 *
812
 * Adjust 'rib' and 'rib_pending' as follows:
813
 *
814
 * If rib_pending node->info is 1 (magic value):
815
 *  callback: NHL = RIB NHL with lifetime = withdraw_lifetime_value
816
 *  RIB = remove all routes at the node
817
 *  DONE
818
 *
819
 * For each item at rib node:
820
 *  if not present in pending node, move RIB item to "delete list"
821
 *
822
 * For each item at pending rib node:
823
 *  if present (same vn/un) in rib node with same lifetime & options, drop
824
 *  matching item from pending node
825
 *
826
 * For each remaining item at pending rib node, add or replace item
827
 * at rib node.
828
 *
829
 * Construct NHL as concatenation of pending list + delete list
830
 *
831
 * Clear pending node
832
 */
833
static void process_pending_node(struct bgp *bgp, struct rfapi_descriptor *rfd,
834
         afi_t afi,
835
         struct agg_node *pn, /* pending node */
836
         struct rfapi_next_hop_entry **head,
837
         struct rfapi_next_hop_entry **tail)
838
0
{
839
0
  struct listnode *node = NULL;
840
0
  struct listnode *nnode = NULL;
841
0
  struct rfapi_info *ri = NULL;    /* happy valgrind */
842
0
  struct rfapi_ip_prefix hp = {0}; /* pfx to put in NHE */
843
0
  struct agg_node *rn = NULL;
844
0
  struct skiplist *slRibPt = NULL; /* rib list */
845
0
  struct skiplist *slPendPt = NULL;
846
0
  struct list *lPendCost = NULL;
847
0
  struct list *delete_list = NULL;
848
0
  int printedprefix = 0;
849
0
  int rib_node_started_nonempty = 0;
850
0
  int sendingsomeroutes = 0;
851
0
  const struct prefix *p;
852
#if DEBUG_PROCESS_PENDING_NODE
853
  unsigned int count_rib_initial = 0;
854
  unsigned int count_pend_vn_initial = 0;
855
  unsigned int count_pend_cost_initial = 0;
856
#endif
857
858
0
  assert(pn);
859
0
  p = agg_node_get_prefix(pn);
860
0
  vnc_zlog_debug_verbose("%s: afi=%d, %pRN pn->info=%p", __func__, afi,
861
0
             pn, pn->info);
862
863
0
  if (AFI_L2VPN != afi) {
864
0
    rfapiQprefix2Rprefix(p, &hp);
865
0
  }
866
867
0
  RFAPI_RIB_CHECK_COUNTS(1, 0);
868
869
  /*
870
   * Find corresponding RIB node
871
   */
872
0
  rn = agg_node_get(rfd->rib[afi], p); /* locks rn */
873
874
  /*
875
   * RIB skiplist has key=rfapi_addr={vn,un}, val = rfapi_info,
876
   * skiplist.del = NULL
877
   */
878
0
  slRibPt = (struct skiplist *)rn->info;
879
0
  if (slRibPt)
880
0
    rib_node_started_nonempty = 1;
881
882
0
  slPendPt = (struct skiplist *)(pn->aggregate);
883
0
  lPendCost = (struct list *)(pn->info);
884
885
#if DEBUG_PROCESS_PENDING_NODE
886
  /* debugging */
887
  if (slRibPt)
888
    count_rib_initial = skiplist_count(slRibPt);
889
890
  if (slPendPt)
891
    count_pend_vn_initial = skiplist_count(slPendPt);
892
893
  if (lPendCost && lPendCost != (struct list *)1)
894
    count_pend_cost_initial = lPendCost->count;
895
#endif
896
897
898
  /*
899
   * Handle special case: delete all routes at prefix
900
   */
901
0
  if (lPendCost == (struct list *)1) {
902
0
    vnc_zlog_debug_verbose("%s: lPendCost=1 => delete all",
903
0
               __func__);
904
0
    if (slRibPt && !skiplist_empty(slRibPt)) {
905
0
      delete_list = list_new();
906
0
      while (0
907
0
             == skiplist_first(slRibPt, NULL, (void **)&ri)) {
908
0
        listnode_add(delete_list, ri);
909
0
        vnc_zlog_debug_verbose(
910
0
          "%s: after listnode_add, delete_list->count=%d",
911
0
          __func__, delete_list->count);
912
0
        rfapiFreeBgpTeaOptionChain(ri->tea_options);
913
0
        ri->tea_options = NULL;
914
915
0
        if (ri->timer) {
916
0
          struct rfapi_rib_tcb *tcb;
917
918
0
          tcb = EVENT_ARG(ri->timer);
919
0
          EVENT_OFF(ri->timer);
920
0
          XFREE(MTYPE_RFAPI_RECENT_DELETE, tcb);
921
0
        }
922
923
0
        vnc_zlog_debug_verbose(
924
0
          "%s:   put dl pfx=%pRN vn=%pFX un=%pFX cost=%d life=%d vn_options=%p",
925
0
          __func__, pn, &ri->rk.vn, &ri->un,
926
0
          ri->cost, ri->lifetime, ri->vn_options);
927
928
0
        skiplist_delete_first(slRibPt);
929
0
      }
930
931
0
      assert(skiplist_empty(slRibPt));
932
933
0
      skiplist_free(slRibPt);
934
0
      rn->info = slRibPt = NULL;
935
0
      agg_unlock_node(rn);
936
937
0
      lPendCost = pn->info = NULL;
938
0
      agg_unlock_node(pn);
939
940
0
      goto callback;
941
0
    }
942
0
    if (slRibPt) {
943
0
      skiplist_free(slRibPt);
944
0
      rn->info = NULL;
945
0
      agg_unlock_node(rn);
946
0
    }
947
948
0
    assert(!slPendPt);
949
0
    if (slPendPt) { /* TBD I think we can toss this block */
950
0
      skiplist_free(slPendPt);
951
0
      pn->aggregate = NULL;
952
0
      agg_unlock_node(pn);
953
0
    }
954
955
0
    pn->info = NULL;
956
0
    agg_unlock_node(pn);
957
958
0
    agg_unlock_node(rn); /* agg_node_get() */
959
960
0
    if (rib_node_started_nonempty) {
961
0
      RFAPI_RIB_PREFIX_COUNT_DECR(rfd, bgp->rfapi);
962
0
    }
963
964
0
    RFAPI_RIB_CHECK_COUNTS(1, 0);
965
966
0
    return;
967
0
  }
968
969
0
  vnc_zlog_debug_verbose("%s:   lPendCost->count=%d, slRibPt->count=%d",
970
0
             __func__,
971
0
             (lPendCost ? (int)lPendCost->count : -1),
972
0
             (slRibPt ? (int)slRibPt->count : -1));
973
974
  /*
975
   * Iterate over routes at RIB Node.
976
   * If not found at Pending Node, delete from RIB Node and add to
977
   * deletelist
978
   * If found at Pending Node
979
   *      If identical rfapi_info, delete from Pending Node
980
   */
981
0
  if (slRibPt) {
982
0
    void *cursor = NULL;
983
0
    struct rfapi_info *ori;
984
985
    /*
986
     * Iterate over RIB List
987
     *
988
     */
989
0
    while (!skiplist_next(slRibPt, NULL, (void **)&ori, &cursor)) {
990
991
0
      if (skiplist_search(slPendPt, &ori->rk, (void **)&ri)) {
992
        /*
993
         * Not in Pending list, so it should be deleted
994
         */
995
0
        if (!delete_list)
996
0
          delete_list = list_new();
997
0
        listnode_add(delete_list, ori);
998
0
        rfapiFreeBgpTeaOptionChain(ori->tea_options);
999
0
        ori->tea_options = NULL;
1000
0
        if (ori->timer) {
1001
0
          struct rfapi_rib_tcb *tcb;
1002
1003
0
          tcb = EVENT_ARG(ori->timer);
1004
0
          EVENT_OFF(ori->timer);
1005
0
          XFREE(MTYPE_RFAPI_RECENT_DELETE, tcb);
1006
0
        }
1007
1008
#if DEBUG_PROCESS_PENDING_NODE
1009
        /* deleted from slRibPt below, after we're done
1010
         * iterating */
1011
        vnc_zlog_debug_verbose(
1012
          "%s:   slRibPt ri %p not matched in pending list, delete",
1013
          __func__, ori);
1014
#endif
1015
1016
0
      } else {
1017
        /*
1018
         * Found in pending list. If same lifetime,
1019
         * cost, options,
1020
         * then remove from pending list because the
1021
         * route
1022
         * hasn't changed.
1023
         */
1024
0
        if (!rfapi_info_cmp(ori, ri)) {
1025
0
          skiplist_delete(slPendPt, &ri->rk,
1026
0
              NULL);
1027
0
          assert(lPendCost);
1028
0
          if (lPendCost) {
1029
            /* linear walk: might need
1030
             * optimization */
1031
0
            listnode_delete(lPendCost,
1032
0
                ri); /* XXX
1033
                  doesn't
1034
                  free
1035
                  data!
1036
                  bug? */
1037
0
            rfapi_info_free(
1038
0
              ri); /* grr... */
1039
0
          }
1040
0
        }
1041
#if DEBUG_PROCESS_PENDING_NODE
1042
        vnc_zlog_debug_verbose(
1043
          "%s:   slRibPt ri %p matched in pending list, %s",
1044
          __func__, ori,
1045
          (same ? "same info"
1046
                : "different info"));
1047
#endif
1048
0
      }
1049
0
    }
1050
    /*
1051
     * Go back and delete items from RIB
1052
     */
1053
0
    if (delete_list) {
1054
0
      for (ALL_LIST_ELEMENTS_RO(delete_list, node, ri)) {
1055
0
        vnc_zlog_debug_verbose(
1056
0
          "%s:   deleting ri %p from slRibPt",
1057
0
          __func__, ri);
1058
0
        assert(!skiplist_delete(slRibPt, &ri->rk,
1059
0
              NULL));
1060
0
      }
1061
0
      if (skiplist_empty(slRibPt)) {
1062
0
        skiplist_free(slRibPt);
1063
0
        slRibPt = rn->info = NULL;
1064
0
        agg_unlock_node(rn);
1065
0
      }
1066
0
    }
1067
0
  }
1068
1069
0
  RFAPI_RIB_CHECK_COUNTS(0, (delete_list ? delete_list->count : 0));
1070
1071
  /*
1072
   * Iterate over routes at Pending Node
1073
   *
1074
   * If {vn} found at RIB Node, update RIB Node route contents to match PN
1075
   * If {vn} NOT found at RIB Node, add copy to RIB Node
1076
   */
1077
0
  if (lPendCost) {
1078
0
    for (ALL_LIST_ELEMENTS_RO(lPendCost, node, ri)) {
1079
1080
0
      struct rfapi_info *ori;
1081
1082
0
      if (slRibPt
1083
0
          && !skiplist_search(slRibPt, &ri->rk,
1084
0
            (void **)&ori)) {
1085
1086
        /* found: update contents of existing route in
1087
         * RIB */
1088
0
        ori->un = ri->un;
1089
0
        ori->cost = ri->cost;
1090
0
        ori->lifetime = ri->lifetime;
1091
0
        rfapiFreeBgpTeaOptionChain(ori->tea_options);
1092
0
        ori->tea_options =
1093
0
          rfapiOptionsDup(ri->tea_options);
1094
0
        ori->last_sent_time = monotime(NULL);
1095
1096
0
        rfapiFreeRfapiVnOptionChain(ori->vn_options);
1097
0
        ori->vn_options =
1098
0
          rfapiVnOptionsDup(ri->vn_options);
1099
1100
0
        rfapiFreeRfapiUnOptionChain(ori->un_options);
1101
0
        ori->un_options =
1102
0
          rfapiUnOptionsDup(ri->un_options);
1103
1104
0
        vnc_zlog_debug_verbose(
1105
0
          "%s:   matched lPendCost item %p in slRibPt, rewrote",
1106
0
          __func__, ri);
1107
1108
0
      } else {
1109
        /* not found: add new route to RIB */
1110
0
        ori = rfapi_info_new();
1111
0
        ori->rk = ri->rk;
1112
0
        ori->un = ri->un;
1113
0
        ori->cost = ri->cost;
1114
0
        ori->lifetime = ri->lifetime;
1115
0
        ori->tea_options =
1116
0
          rfapiOptionsDup(ri->tea_options);
1117
0
        ori->last_sent_time = monotime(NULL);
1118
0
        ori->vn_options =
1119
0
          rfapiVnOptionsDup(ri->vn_options);
1120
0
        ori->un_options =
1121
0
          rfapiUnOptionsDup(ri->un_options);
1122
1123
0
        if (!slRibPt) {
1124
0
          slRibPt = skiplist_new(
1125
0
            0, rfapi_rib_key_cmp, NULL);
1126
0
          rn->info = slRibPt;
1127
0
          agg_lock_node(rn);
1128
0
        }
1129
0
        skiplist_insert(slRibPt, &ori->rk, ori);
1130
1131
0
        vnc_zlog_debug_verbose(
1132
0
          "%s:   nomatch lPendCost item %p in slRibPt, added (rd=%pRDP)",
1133
0
          __func__, ri, &ori->rk.rd);
1134
0
      }
1135
1136
      /*
1137
       * poke timer
1138
       */
1139
0
      RFAPI_RIB_CHECK_COUNTS(
1140
0
        0, (delete_list ? delete_list->count : 0));
1141
0
      rfapiRibStartTimer(rfd, ori, rn, 0);
1142
0
      RFAPI_RIB_CHECK_COUNTS(
1143
0
        0, (delete_list ? delete_list->count : 0));
1144
0
    }
1145
0
  }
1146
1147
1148
0
callback:
1149
  /*
1150
   * Construct NHL as concatenation of pending list + delete list
1151
   */
1152
1153
1154
0
  RFAPI_RIB_CHECK_COUNTS(0, (delete_list ? delete_list->count : 0));
1155
1156
0
  if (lPendCost) {
1157
1158
0
    char buf[BUFSIZ];
1159
0
    char buf2[BUFSIZ];
1160
1161
0
    vnc_zlog_debug_verbose("%s: lPendCost->count now %d", __func__,
1162
0
               lPendCost->count);
1163
0
    vnc_zlog_debug_verbose("%s: For prefix %pRN (a)", __func__, pn);
1164
0
    printedprefix = 1;
1165
1166
0
    for (ALL_LIST_ELEMENTS(lPendCost, node, nnode, ri)) {
1167
1168
0
      struct rfapi_next_hop_entry *new;
1169
0
      struct agg_node *trn;
1170
1171
0
      new = XCALLOC(MTYPE_RFAPI_NEXTHOP,
1172
0
              sizeof(struct rfapi_next_hop_entry));
1173
1174
0
      if (ri->rk.aux_prefix.family) {
1175
0
        rfapiQprefix2Rprefix(&ri->rk.aux_prefix,
1176
0
                 &new->prefix);
1177
0
      } else {
1178
0
        new->prefix = hp;
1179
0
        if (AFI_L2VPN == afi) {
1180
          /* hp is 0; need to set length to match
1181
           * AF of vn */
1182
0
          new->prefix.length =
1183
0
            (ri->rk.vn.family == AF_INET)
1184
0
              ? 32
1185
0
              : 128;
1186
0
        }
1187
0
      }
1188
0
      new->prefix.cost = ri->cost;
1189
0
      new->lifetime = ri->lifetime;
1190
0
      rfapiQprefix2Raddr(&ri->rk.vn, &new->vn_address);
1191
0
      rfapiQprefix2Raddr(&ri->un, &new->un_address);
1192
      /* free option chain from ri */
1193
0
      rfapiFreeBgpTeaOptionChain(ri->tea_options);
1194
1195
0
      ri->tea_options =
1196
0
        NULL; /* option chain was transferred to NHL */
1197
1198
0
      new->vn_options = ri->vn_options;
1199
0
      ri->vn_options =
1200
0
        NULL; /* option chain was transferred to NHL */
1201
1202
0
      new->un_options = ri->un_options;
1203
0
      ri->un_options =
1204
0
        NULL; /* option chain was transferred to NHL */
1205
1206
0
      if (*tail)
1207
0
        (*tail)->next = new;
1208
0
      *tail = new;
1209
0
      if (!*head) {
1210
0
        *head = new;
1211
0
      }
1212
0
      sendingsomeroutes = 1;
1213
1214
0
      ++rfd->stat_count_nh_reachable;
1215
0
      ++bgp->rfapi->stat.count_updated_response_updates;
1216
1217
      /*
1218
       * update this NVE's timestamp for this prefix
1219
       */
1220
0
      trn = agg_node_get(rfd->rsp_times[afi],
1221
0
             p); /* locks trn */
1222
0
      trn->info = (void *)(uintptr_t)monotime(NULL);
1223
0
      if (agg_node_get_lock_count(trn) > 1)
1224
0
        agg_unlock_node(trn);
1225
1226
0
      rfapiRfapiIpAddr2Str(&new->vn_address, buf, BUFSIZ);
1227
0
      rfapiRfapiIpAddr2Str(&new->un_address, buf2, BUFSIZ);
1228
0
      vnc_zlog_debug_verbose(
1229
0
        "%s:   add vn=%s un=%s cost=%d life=%d",
1230
0
        __func__, buf, buf2, new->prefix.cost,
1231
0
        new->lifetime);
1232
0
    }
1233
0
  }
1234
1235
0
  RFAPI_RIB_CHECK_COUNTS(0, (delete_list ? delete_list->count : 0));
1236
1237
0
  if (delete_list) {
1238
1239
0
    char buf[BUFSIZ];
1240
0
    char buf2[BUFSIZ];
1241
1242
0
    if (!printedprefix) {
1243
0
      vnc_zlog_debug_verbose("%s: For prefix %pRN (d)",
1244
0
                 __func__, pn);
1245
0
    }
1246
0
    vnc_zlog_debug_verbose("%s: delete_list has %d elements",
1247
0
               __func__, delete_list->count);
1248
1249
0
    RFAPI_RIB_CHECK_COUNTS(0, delete_list->count);
1250
0
    if (!CHECK_FLAG(bgp->rfapi_cfg->flags,
1251
0
        BGP_VNC_CONFIG_RESPONSE_REMOVAL_DISABLE)) {
1252
1253
0
      for (ALL_LIST_ELEMENTS(delete_list, node, nnode, ri)) {
1254
1255
0
        struct rfapi_next_hop_entry *new;
1256
0
        struct rfapi_info *ri_del;
1257
1258
0
        RFAPI_RIB_CHECK_COUNTS(0, delete_list->count);
1259
0
        new = XCALLOC(
1260
0
          MTYPE_RFAPI_NEXTHOP,
1261
0
          sizeof(struct rfapi_next_hop_entry));
1262
1263
0
        if (ri->rk.aux_prefix.family) {
1264
0
          rfapiQprefix2Rprefix(&ri->rk.aux_prefix,
1265
0
                   &new->prefix);
1266
0
        } else {
1267
0
          new->prefix = hp;
1268
0
          if (AFI_L2VPN == afi) {
1269
            /* hp is 0; need to set length
1270
             * to match AF of vn */
1271
0
            new->prefix.length =
1272
0
              (ri->rk.vn.family
1273
0
               == AF_INET)
1274
0
                ? 32
1275
0
                : 128;
1276
0
          }
1277
0
        }
1278
1279
0
        new->prefix.cost = ri->cost;
1280
0
        new->lifetime = RFAPI_REMOVE_RESPONSE_LIFETIME;
1281
0
        rfapiQprefix2Raddr(&ri->rk.vn,
1282
0
               &new->vn_address);
1283
0
        rfapiQprefix2Raddr(&ri->un, &new->un_address);
1284
1285
0
        new->vn_options = ri->vn_options;
1286
0
        ri->vn_options = NULL; /* option chain was
1287
                transferred to NHL */
1288
1289
0
        new->un_options = ri->un_options;
1290
0
        ri->un_options = NULL; /* option chain was
1291
                transferred to NHL */
1292
1293
0
        if (*tail)
1294
0
          (*tail)->next = new;
1295
0
        *tail = new;
1296
0
        if (!*head) {
1297
0
          *head = new;
1298
0
        }
1299
0
        ++rfd->stat_count_nh_removal;
1300
0
        ++bgp->rfapi->stat
1301
0
            .count_updated_response_deletes;
1302
1303
0
        rfapiRfapiIpAddr2Str(&new->vn_address, buf,
1304
0
                 BUFSIZ);
1305
0
        rfapiRfapiIpAddr2Str(&new->un_address, buf2,
1306
0
                 BUFSIZ);
1307
0
        vnc_zlog_debug_verbose(
1308
0
          "%s:   DEL vn=%s un=%s cost=%d life=%d",
1309
0
          __func__, buf, buf2, new->prefix.cost,
1310
0
          new->lifetime);
1311
1312
0
        RFAPI_RIB_CHECK_COUNTS(0, delete_list->count);
1313
        /*
1314
         * Update/add to list of recent deletions at
1315
         * this prefix
1316
         */
1317
0
        if (!rn->aggregate) {
1318
0
          rn->aggregate = skiplist_new(
1319
0
            0, rfapi_rib_key_cmp,
1320
0
            (void (*)(void *))
1321
0
              rfapi_info_free);
1322
0
          agg_lock_node(rn);
1323
0
        }
1324
0
        RFAPI_RIB_CHECK_COUNTS(0, delete_list->count);
1325
1326
        /* sanity check lifetime */
1327
0
        if (ri->lifetime
1328
0
            > RFAPI_LIFETIME_INFINITE_WITHDRAW_DELAY)
1329
0
          ri->lifetime =
1330
0
            RFAPI_LIFETIME_INFINITE_WITHDRAW_DELAY;
1331
1332
0
        RFAPI_RIB_CHECK_COUNTS(0, delete_list->count);
1333
        /* cancel normal expire timer */
1334
0
        if (ri->timer) {
1335
0
          struct rfapi_rib_tcb *tcb;
1336
1337
0
          tcb = EVENT_ARG(ri->timer);
1338
0
          EVENT_OFF(ri->timer);
1339
0
          XFREE(MTYPE_RFAPI_RECENT_DELETE, tcb);
1340
0
        }
1341
0
        RFAPI_RIB_CHECK_COUNTS(0, delete_list->count);
1342
1343
        /*
1344
         * Look in "recently-deleted" list
1345
         */
1346
0
        if (skiplist_search(
1347
0
              (struct skiplist *)(rn->aggregate),
1348
0
              &ri->rk, (void **)&ri_del)) {
1349
1350
0
          int rc;
1351
1352
0
          RFAPI_RIB_CHECK_COUNTS(
1353
0
            0, delete_list->count);
1354
          /*
1355
           * NOT in "recently-deleted" list
1356
           */
1357
0
          list_delete_node(
1358
0
            delete_list,
1359
0
            node); /* does not free ri */
1360
0
          rc = skiplist_insert(
1361
0
            (struct skiplist
1362
0
               *)(rn->aggregate),
1363
0
            &ri->rk, ri);
1364
0
          assert(!rc);
1365
1366
0
          RFAPI_RIB_CHECK_COUNTS(
1367
0
            0, delete_list->count);
1368
0
          rfapiRibStartTimer(rfd, ri, rn, 1);
1369
0
          RFAPI_RIB_CHECK_COUNTS(
1370
0
            0, delete_list->count);
1371
0
          ri->last_sent_time = monotime(NULL);
1372
#if DEBUG_RIB_SL_RD
1373
          vnc_zlog_debug_verbose(
1374
            "%s: move route to recently deleted list, rd=%pRDP",
1375
            __func__, &ri->rk.rd);
1376
#endif
1377
1378
0
        } else {
1379
          /*
1380
           * IN "recently-deleted" list
1381
           */
1382
0
          RFAPI_RIB_CHECK_COUNTS(
1383
0
            0, delete_list->count);
1384
0
          rfapiRibStartTimer(rfd, ri_del, rn, 1);
1385
0
          RFAPI_RIB_CHECK_COUNTS(
1386
0
            0, delete_list->count);
1387
0
          ri->last_sent_time = monotime(NULL);
1388
0
        }
1389
0
      }
1390
0
    } else {
1391
0
      vnc_zlog_debug_verbose(
1392
0
        "%s: response removal disabled, omitting removals",
1393
0
        __func__);
1394
0
    }
1395
1396
0
    delete_list->del = (void (*)(void *))rfapi_info_free;
1397
0
    list_delete(&delete_list);
1398
0
  }
1399
1400
0
  RFAPI_RIB_CHECK_COUNTS(0, 0);
1401
1402
  /*
1403
   * Reset pending lists. The final agg_unlock_node() will probably
1404
   * cause the pending node to be released.
1405
   */
1406
0
  if (slPendPt) {
1407
0
    skiplist_free(slPendPt);
1408
0
    pn->aggregate = NULL;
1409
0
    agg_unlock_node(pn);
1410
0
  }
1411
0
  if (lPendCost) {
1412
0
    list_delete(&lPendCost);
1413
0
    pn->info = NULL;
1414
0
    agg_unlock_node(pn);
1415
0
  }
1416
0
  RFAPI_RIB_CHECK_COUNTS(0, 0);
1417
1418
0
  if (rib_node_started_nonempty) {
1419
0
    if (!rn->info) {
1420
0
      RFAPI_RIB_PREFIX_COUNT_DECR(rfd, bgp->rfapi);
1421
0
    }
1422
0
  } else {
1423
0
    if (rn->info) {
1424
0
      RFAPI_RIB_PREFIX_COUNT_INCR(rfd, bgp->rfapi);
1425
0
    }
1426
0
  }
1427
1428
0
  if (sendingsomeroutes)
1429
0
    rfapiMonitorTimersRestart(rfd, p);
1430
1431
0
  agg_unlock_node(rn); /* agg_node_get() */
1432
1433
0
  RFAPI_RIB_CHECK_COUNTS(1, 0);
1434
0
}
1435
1436
/*
1437
 * regardless of targets, construct a single callback by doing
1438
 * only one traversal of the pending RIB
1439
 *
1440
 *
1441
 * Do callback
1442
 *
1443
 */
1444
static void rib_do_callback_onepass(struct rfapi_descriptor *rfd, afi_t afi)
1445
0
{
1446
0
  struct bgp *bgp = bgp_get_default();
1447
0
  struct rfapi_next_hop_entry *head = NULL;
1448
0
  struct rfapi_next_hop_entry *tail = NULL;
1449
0
  struct agg_node *rn;
1450
1451
#ifdef DEBUG_L2_EXTRA
1452
  vnc_zlog_debug_verbose("%s: rfd=%p, afi=%d", __func__, rfd, afi);
1453
#endif
1454
1455
0
  if (!rfd->rib_pending[afi])
1456
0
    return;
1457
1458
0
  assert(bgp->rfapi);
1459
1460
0
  for (rn = agg_route_top(rfd->rib_pending[afi]); rn;
1461
0
       rn = agg_route_next(rn)) {
1462
0
    process_pending_node(bgp, rfd, afi, rn, &head, &tail);
1463
0
  }
1464
1465
0
  if (head) {
1466
0
    rfapi_response_cb_t *f;
1467
1468
#if DEBUG_NHL
1469
    vnc_zlog_debug_verbose("%s: response callback NHL follows:",
1470
               __func__);
1471
    rfapiPrintNhl(NULL, head);
1472
#endif
1473
1474
0
    if (rfd->response_cb)
1475
0
      f = rfd->response_cb;
1476
0
    else
1477
0
      f = bgp->rfapi->rfp_methods.response_cb;
1478
1479
0
    bgp->rfapi->flags |= RFAPI_INCALLBACK;
1480
0
    vnc_zlog_debug_verbose("%s: invoking updated response callback",
1481
0
               __func__);
1482
0
    (*f)(head, rfd->cookie);
1483
0
    bgp->rfapi->flags &= ~RFAPI_INCALLBACK;
1484
0
    ++bgp->rfapi->response_updated_count;
1485
0
  }
1486
0
}
1487
1488
static wq_item_status rfapiRibDoQueuedCallback(struct work_queue *wq,
1489
                 void *data)
1490
0
{
1491
0
  struct rfapi_descriptor *rfd;
1492
0
  afi_t afi;
1493
0
  uint32_t queued_flag;
1494
1495
0
  RFAPI_RIB_CHECK_COUNTS(1, 0);
1496
1497
0
  rfd = ((struct rfapi_updated_responses_queue *)data)->rfd;
1498
0
  afi = ((struct rfapi_updated_responses_queue *)data)->afi;
1499
1500
  /* Make sure the HD wasn't closed after the work item was scheduled */
1501
0
  if (rfapi_check(rfd))
1502
0
    return WQ_SUCCESS;
1503
1504
0
  rib_do_callback_onepass(rfd, afi);
1505
1506
0
  queued_flag = RFAPI_QUEUED_FLAG(afi);
1507
1508
0
  UNSET_FLAG(rfd->flags, queued_flag);
1509
1510
0
  RFAPI_RIB_CHECK_COUNTS(1, 0);
1511
1512
0
  return WQ_SUCCESS;
1513
0
}
1514
1515
static void rfapiRibQueueItemDelete(struct work_queue *wq, void *data)
1516
0
{
1517
0
  XFREE(MTYPE_RFAPI_UPDATED_RESPONSE_QUEUE, data);
1518
0
}
1519
1520
static void updated_responses_queue_init(struct rfapi_descriptor *rfd)
1521
0
{
1522
0
  if (rfd->updated_responses_queue)
1523
0
    return;
1524
1525
0
  rfd->updated_responses_queue =
1526
0
    work_queue_new(bm->master, "rfapi updated responses");
1527
0
  assert(rfd->updated_responses_queue);
1528
1529
0
  rfd->updated_responses_queue->spec.workfunc = rfapiRibDoQueuedCallback;
1530
0
  rfd->updated_responses_queue->spec.del_item_data =
1531
0
    rfapiRibQueueItemDelete;
1532
0
  rfd->updated_responses_queue->spec.max_retries = 0;
1533
0
  rfd->updated_responses_queue->spec.hold = 1;
1534
0
}
1535
1536
/*
1537
 * Called when an import table node is modified. Construct a
1538
 * new complete nexthop list, sorted by cost (lowest first),
1539
 * based on the import table node.
1540
 *
1541
 * Filter out duplicate nexthops (vn address). There should be
1542
 * only one UN address per VN address from the point of view of
1543
 * a given import table, so we can probably ignore UN addresses
1544
 * while filtering.
1545
 *
1546
 * Based on rfapiNhlAddNodeRoutes()
1547
 */
1548
void rfapiRibUpdatePendingNode(
1549
  struct bgp *bgp, struct rfapi_descriptor *rfd,
1550
  struct rfapi_import_table *it, /* needed for L2 */
1551
  struct agg_node *it_node, uint32_t lifetime)
1552
0
{
1553
0
  const struct prefix *prefix;
1554
0
  struct bgp_path_info *bpi;
1555
0
  struct agg_node *pn;
1556
0
  afi_t afi;
1557
0
  uint32_t queued_flag;
1558
0
  int count = 0;
1559
1560
0
  vnc_zlog_debug_verbose("%s: entry", __func__);
1561
1562
0
  if (CHECK_FLAG(bgp->rfapi_cfg->flags, BGP_VNC_CONFIG_CALLBACK_DISABLE))
1563
0
    return;
1564
1565
0
  vnc_zlog_debug_verbose("%s: callbacks are not disabled", __func__);
1566
1567
0
  RFAPI_RIB_CHECK_COUNTS(1, 0);
1568
1569
0
  prefix = agg_node_get_prefix(it_node);
1570
0
  afi = family2afi(prefix->family);
1571
0
  vnc_zlog_debug_verbose("%s: prefix=%pFX", __func__, prefix);
1572
1573
0
  pn = agg_node_get(rfd->rib_pending[afi], prefix);
1574
0
  assert(pn);
1575
1576
0
  vnc_zlog_debug_verbose("%s: pn->info=%p, pn->aggregate=%p", __func__,
1577
0
             pn->info, pn->aggregate);
1578
1579
0
  if (pn->aggregate) {
1580
    /*
1581
     * free references into the rfapi_info structures before
1582
     * freeing the structures themselves
1583
     */
1584
0
    skiplist_free((struct skiplist *)(pn->aggregate));
1585
0
    pn->aggregate = NULL;
1586
0
    agg_unlock_node(pn); /* skiplist deleted */
1587
0
  }
1588
1589
1590
  /*
1591
   * free the rfapi_info structures
1592
   */
1593
0
  if (pn->info) {
1594
0
    if (pn->info != (void *)1) {
1595
0
      list_delete((struct list **)(&pn->info));
1596
0
    }
1597
0
    pn->info = NULL;
1598
0
    agg_unlock_node(pn); /* linklist or 1 deleted */
1599
0
  }
1600
1601
  /*
1602
   * The BPIs in the import table are already sorted by cost
1603
   */
1604
0
  for (bpi = it_node->info; bpi; bpi = bpi->next) {
1605
1606
0
    struct rfapi_info *ri;
1607
0
    struct prefix pfx_nh;
1608
1609
0
    if (!bpi->extra) {
1610
      /* shouldn't happen */
1611
      /* TBD increment error stats counter */
1612
0
      continue;
1613
0
    }
1614
1615
0
    rfapiNexthop2Prefix(bpi->attr, &pfx_nh);
1616
1617
    /*
1618
     * Omit route if nexthop is self
1619
     */
1620
0
    if (CHECK_FLAG(bgp->rfapi_cfg->flags,
1621
0
             BGP_VNC_CONFIG_FILTER_SELF_FROM_RSP)) {
1622
1623
0
      struct prefix pfx_vn;
1624
1625
0
      assert(!rfapiRaddr2Qprefix(&rfd->vn_addr, &pfx_vn));
1626
0
      if (prefix_same(&pfx_vn, &pfx_nh))
1627
0
        continue;
1628
0
    }
1629
1630
0
    ri = rfapi_info_new();
1631
0
    ri->rk.vn = pfx_nh;
1632
0
    ri->rk.rd = bpi->extra->vnc.import.rd;
1633
    /*
1634
     * If there is an auxiliary IP address (L2 can have it), copy it
1635
     */
1636
0
    if (bpi->extra->vnc.import.aux_prefix.family) {
1637
0
      ri->rk.aux_prefix = bpi->extra->vnc.import.aux_prefix;
1638
0
    }
1639
1640
0
    if (rfapiGetUnAddrOfVpnBi(bpi, &ri->un)) {
1641
0
      rfapi_info_free(ri);
1642
0
      continue;
1643
0
    }
1644
1645
0
    if (!pn->aggregate) {
1646
0
      pn->aggregate =
1647
0
        skiplist_new(0, rfapi_rib_key_cmp, NULL);
1648
0
      agg_lock_node(pn);
1649
0
    }
1650
1651
    /*
1652
     * If we have already added this nexthop, the insert will fail.
1653
     * Note that the skiplist key is a pointer INTO the rfapi_info
1654
     * structure which will be added to the "info" list.
1655
     * The skiplist entry VALUE is not used for anything but
1656
     * might be useful during debugging.
1657
     */
1658
0
    if (skiplist_insert((struct skiplist *)pn->aggregate, &ri->rk,
1659
0
            ri)) {
1660
1661
      /*
1662
       * duplicate
1663
       */
1664
0
      rfapi_info_free(ri);
1665
0
      continue;
1666
0
    }
1667
1668
0
    rfapiRibBi2Ri(bpi, ri, lifetime);
1669
1670
0
    if (!pn->info) {
1671
0
      pn->info = list_new();
1672
0
      ((struct list *)(pn->info))->del =
1673
0
        (void (*)(void *))rfapi_info_free;
1674
0
      agg_lock_node(pn);
1675
0
    }
1676
1677
0
    listnode_add((struct list *)(pn->info), ri);
1678
0
  }
1679
1680
0
  if (pn->info) {
1681
0
    count = ((struct list *)(pn->info))->count;
1682
0
  }
1683
1684
0
  if (!count) {
1685
0
    assert(!pn->info);
1686
0
    assert(!pn->aggregate);
1687
0
    pn->info = (void *)1; /* magic value means this node has no
1688
           routes */
1689
0
    agg_lock_node(pn);
1690
0
  }
1691
1692
0
  agg_unlock_node(pn); /* agg_node_get */
1693
1694
0
  queued_flag = RFAPI_QUEUED_FLAG(afi);
1695
1696
0
  if (!CHECK_FLAG(rfd->flags, queued_flag)) {
1697
1698
0
    struct rfapi_updated_responses_queue *urq;
1699
1700
0
    urq = XCALLOC(MTYPE_RFAPI_UPDATED_RESPONSE_QUEUE,
1701
0
            sizeof(struct rfapi_updated_responses_queue));
1702
0
    if (!rfd->updated_responses_queue)
1703
0
      updated_responses_queue_init(rfd);
1704
1705
0
    SET_FLAG(rfd->flags, queued_flag);
1706
0
    urq->rfd = rfd;
1707
0
    urq->afi = afi;
1708
0
    work_queue_add(rfd->updated_responses_queue, urq);
1709
0
  }
1710
0
  RFAPI_RIB_CHECK_COUNTS(1, 0);
1711
0
}
1712
1713
void rfapiRibUpdatePendingNodeSubtree(
1714
  struct bgp *bgp, struct rfapi_descriptor *rfd,
1715
  struct rfapi_import_table *it, struct agg_node *it_node,
1716
  struct agg_node *omit_subtree, /* may be NULL */
1717
  uint32_t lifetime)
1718
0
{
1719
  /* FIXME: need to find a better way here to work without sticking our
1720
   * hands in node->link */
1721
0
  if (agg_node_left(it_node)
1722
0
      && (agg_node_left(it_node) != omit_subtree)) {
1723
0
    if (agg_node_left(it_node)->info)
1724
0
      rfapiRibUpdatePendingNode(
1725
0
        bgp, rfd, it, agg_node_left(it_node), lifetime);
1726
0
    rfapiRibUpdatePendingNodeSubtree(bgp, rfd, it,
1727
0
             agg_node_left(it_node),
1728
0
             omit_subtree, lifetime);
1729
0
  }
1730
1731
0
  if (agg_node_right(it_node)
1732
0
      && (agg_node_right(it_node) != omit_subtree)) {
1733
0
    if (agg_node_right(it_node)->info)
1734
0
      rfapiRibUpdatePendingNode(bgp, rfd, it,
1735
0
              agg_node_right(it_node),
1736
0
              lifetime);
1737
0
    rfapiRibUpdatePendingNodeSubtree(bgp, rfd, it,
1738
0
             agg_node_right(it_node),
1739
0
             omit_subtree, lifetime);
1740
0
  }
1741
0
}
1742
1743
/*
1744
 * RETURN VALUE
1745
 *
1746
 *  0 allow prefix to be included in response
1747
 *  !0  don't allow prefix to be included in response
1748
 */
1749
int rfapiRibFTDFilterRecentPrefix(
1750
  struct rfapi_descriptor *rfd,
1751
  struct agg_node *it_rn,       /* import table node */
1752
  struct prefix *pfx_target_original) /* query target */
1753
0
{
1754
0
  struct bgp *bgp = rfd->bgp;
1755
0
  const struct prefix *p = agg_node_get_prefix(it_rn);
1756
0
  afi_t afi = family2afi(p->family);
1757
0
  time_t prefix_time;
1758
0
  struct agg_node *trn;
1759
1760
  /*
1761
   * Not in FTD mode, so allow prefix
1762
   */
1763
0
  if (bgp->rfapi_cfg->rfp_cfg.download_type != RFAPI_RFP_DOWNLOAD_FULL)
1764
0
    return 0;
1765
1766
  /*
1767
   * TBD
1768
   * This matches behavior of now-obsolete rfapiRibFTDFilterRecent(),
1769
   * but we need to decide if that is correct.
1770
   */
1771
0
  if (p->family == AF_ETHERNET)
1772
0
    return 0;
1773
1774
#ifdef DEBUG_FTD_FILTER_RECENT
1775
  {
1776
    vnc_zlog_debug_verbose("%s: prefix %pFX", __func__,
1777
               agg_node_get_prefix(it_rn));
1778
  }
1779
#endif
1780
1781
  /*
1782
   * prefix covers target address, so allow prefix
1783
   */
1784
0
  if (prefix_match(p, pfx_target_original)) {
1785
#ifdef DEBUG_FTD_FILTER_RECENT
1786
    vnc_zlog_debug_verbose("%s: prefix covers target, allowed",
1787
               __func__);
1788
#endif
1789
0
    return 0;
1790
0
  }
1791
1792
  /*
1793
   * check this NVE's timestamp for this prefix
1794
   */
1795
0
  trn = agg_node_get(rfd->rsp_times[afi], p); /* locks trn */
1796
0
  prefix_time = (time_t)trn->info;
1797
0
  if (agg_node_get_lock_count(trn) > 1)
1798
0
    agg_unlock_node(trn);
1799
1800
#ifdef DEBUG_FTD_FILTER_RECENT
1801
  vnc_zlog_debug_verbose("%s: last sent time %lu, last allowed time %lu",
1802
             __func__, prefix_time,
1803
             rfd->ftd_last_allowed_time);
1804
#endif
1805
1806
  /*
1807
   * haven't sent this prefix, which doesn't cover target address,
1808
   * to NVE since ftd_advertisement_interval, so OK to send now.
1809
   */
1810
0
  if (prefix_time <= rfd->ftd_last_allowed_time)
1811
0
    return 0;
1812
1813
0
  return 1;
1814
0
}
1815
1816
/*
1817
 * Call when rfapi returns from rfapi_query() so the RIB reflects
1818
 * the routes sent to the NVE before the first updated response
1819
 *
1820
 * Also: remove duplicates from response. Caller should use returned
1821
 * value of nexthop chain.
1822
 */
1823
struct rfapi_next_hop_entry *
1824
rfapiRibPreload(struct bgp *bgp, struct rfapi_descriptor *rfd,
1825
    struct rfapi_next_hop_entry *response, int use_eth_resolution)
1826
0
{
1827
0
  struct rfapi_next_hop_entry *nhp;
1828
0
  struct rfapi_next_hop_entry *nhp_next;
1829
0
  struct rfapi_next_hop_entry *head = NULL;
1830
0
  struct rfapi_next_hop_entry *tail = NULL;
1831
0
  time_t new_last_sent_time;
1832
1833
0
  vnc_zlog_debug_verbose("%s: loading response=%p, use_eth_resolution=%d",
1834
0
             __func__, response, use_eth_resolution);
1835
1836
0
  new_last_sent_time = monotime(NULL);
1837
1838
0
  for (nhp = response; nhp; nhp = nhp_next) {
1839
1840
0
    struct prefix pfx;
1841
0
    struct rfapi_rib_key rk;
1842
0
    afi_t afi;
1843
0
    struct rfapi_info *ri;
1844
0
    int need_insert;
1845
0
    struct agg_node *rn;
1846
0
    int rib_node_started_nonempty = 0;
1847
0
    struct agg_node *trn;
1848
0
    int allowed = 0;
1849
1850
    /* save in case we delete nhp */
1851
0
    nhp_next = nhp->next;
1852
1853
0
    if (nhp->lifetime == RFAPI_REMOVE_RESPONSE_LIFETIME) {
1854
      /*
1855
       * weird, shouldn't happen
1856
       */
1857
0
      vnc_zlog_debug_verbose(
1858
0
        "%s: got nhp->lifetime == RFAPI_REMOVE_RESPONSE_LIFETIME",
1859
0
        __func__);
1860
0
      continue;
1861
0
    }
1862
1863
1864
0
    if (use_eth_resolution) {
1865
      /* get the prefix of the ethernet address in the L2
1866
       * option */
1867
0
      struct rfapi_l2address_option *pL2o;
1868
0
      struct rfapi_vn_option *vo;
1869
1870
      /*
1871
       * Look for VN option of type
1872
       * RFAPI_VN_OPTION_TYPE_L2ADDR
1873
       */
1874
0
      for (pL2o = NULL, vo = nhp->vn_options; vo;
1875
0
           vo = vo->next) {
1876
0
        if (RFAPI_VN_OPTION_TYPE_L2ADDR == vo->type) {
1877
0
          pL2o = &vo->v.l2addr;
1878
0
          break;
1879
0
        }
1880
0
      }
1881
1882
0
      if (!pL2o) {
1883
        /*
1884
         * not supposed to happen
1885
         */
1886
0
        vnc_zlog_debug_verbose("%s: missing L2 info",
1887
0
                   __func__);
1888
0
        continue;
1889
0
      }
1890
1891
0
      afi = AFI_L2VPN;
1892
0
      rfapiL2o2Qprefix(pL2o, &pfx);
1893
0
    } else {
1894
0
      rfapiRprefix2Qprefix(&nhp->prefix, &pfx);
1895
0
      afi = family2afi(pfx.family);
1896
0
    }
1897
1898
    /*
1899
     * TBD for ethernet, rib must know the right way to distinguish
1900
     * duplicate routes
1901
     *
1902
     * Current approach: prefix is key to radix tree; then
1903
     * each prefix has a set of routes with unique VN addrs
1904
     */
1905
1906
    /*
1907
     * Look up prefix in RIB
1908
     */
1909
0
    rn = agg_node_get(rfd->rib[afi], &pfx); /* locks rn */
1910
1911
0
    if (rn->info) {
1912
0
      rib_node_started_nonempty = 1;
1913
0
    } else {
1914
0
      rn->info = skiplist_new(0, rfapi_rib_key_cmp, NULL);
1915
0
      agg_lock_node(rn);
1916
0
    }
1917
1918
    /*
1919
     * Look up route at prefix
1920
     */
1921
0
    need_insert = 0;
1922
0
    memset((void *)&rk, 0, sizeof(rk));
1923
0
    assert(!rfapiRaddr2Qprefix(&nhp->vn_address, &rk.vn));
1924
1925
0
    if (use_eth_resolution) {
1926
      /* copy what came from aux_prefix to rk.aux_prefix */
1927
0
      rfapiRprefix2Qprefix(&nhp->prefix, &rk.aux_prefix);
1928
0
      if (RFAPI_0_PREFIX(&rk.aux_prefix)
1929
0
          && RFAPI_HOST_PREFIX(&rk.aux_prefix)) {
1930
        /* mark as "none" if nhp->prefix is 0/32 or
1931
         * 0/128 */
1932
0
        rk.aux_prefix.family = AF_UNSPEC;
1933
0
      }
1934
0
    }
1935
1936
#if DEBUG_NHL
1937
    {
1938
      char str_aux_prefix[PREFIX_STRLEN];
1939
1940
      str_aux_prefix[0] = 0;
1941
1942
      prefix2str(&rk.aux_prefix, str_aux_prefix,
1943
           sizeof(str_aux_prefix));
1944
1945
      if (!rk.aux_prefix.family) {
1946
      }
1947
      vnc_zlog_debug_verbose(
1948
        "%s:   rk.vn=%pFX rk.aux_prefix=%s", __func__,
1949
        &rk.vn,
1950
        (rk.aux_prefix.family ? str_aux_prefix : "-"));
1951
    }
1952
    vnc_zlog_debug_verbose(
1953
      "%s: RIB skiplist for this prefix follows", __func__);
1954
    rfapiRibShowRibSl(NULL, agg_node_get_prefix(rn),
1955
          (struct skiplist *)rn->info);
1956
#endif
1957
1958
1959
0
    if (!skiplist_search((struct skiplist *)rn->info, &rk,
1960
0
             (void **)&ri)) {
1961
      /*
1962
       * Already have this route; make values match
1963
       */
1964
0
      rfapiFreeRfapiUnOptionChain(ri->un_options);
1965
0
      ri->un_options = NULL;
1966
0
      rfapiFreeRfapiVnOptionChain(ri->vn_options);
1967
0
      ri->vn_options = NULL;
1968
1969
#if DEBUG_NHL
1970
      vnc_zlog_debug_verbose("%s: found in RIB", __func__);
1971
#endif
1972
1973
      /*
1974
       * Filter duplicate routes from initial response.
1975
       * Check timestamps to avoid wraparound problems
1976
       */
1977
0
      if ((ri->rsp_counter != rfd->rsp_counter)
1978
0
          || (ri->last_sent_time != new_last_sent_time)) {
1979
1980
#if DEBUG_NHL
1981
        vnc_zlog_debug_verbose(
1982
          "%s: allowed due to counter/timestamp diff",
1983
          __func__);
1984
#endif
1985
0
        allowed = 1;
1986
0
      }
1987
1988
0
    } else {
1989
1990
#if DEBUG_NHL
1991
      vnc_zlog_debug_verbose(
1992
        "%s: allowed due to not yet in RIB", __func__);
1993
#endif
1994
      /* not found: add new route to RIB */
1995
0
      ri = rfapi_info_new();
1996
0
      need_insert = 1;
1997
0
      allowed = 1;
1998
0
    }
1999
2000
0
    ri->rk = rk;
2001
0
    assert(!rfapiRaddr2Qprefix(&nhp->un_address, &ri->un));
2002
0
    ri->cost = nhp->prefix.cost;
2003
0
    ri->lifetime = nhp->lifetime;
2004
0
    ri->vn_options = rfapiVnOptionsDup(nhp->vn_options);
2005
0
    ri->rsp_counter = rfd->rsp_counter;
2006
0
    ri->last_sent_time = monotime(NULL);
2007
2008
0
    if (need_insert) {
2009
0
      int rc;
2010
0
      rc = skiplist_insert((struct skiplist *)rn->info,
2011
0
               &ri->rk, ri);
2012
0
      assert(!rc);
2013
0
    }
2014
2015
0
    if (!rib_node_started_nonempty) {
2016
0
      RFAPI_RIB_PREFIX_COUNT_INCR(rfd, bgp->rfapi);
2017
0
    }
2018
2019
0
    RFAPI_RIB_CHECK_COUNTS(0, 0);
2020
0
    rfapiRibStartTimer(rfd, ri, rn, 0);
2021
0
    RFAPI_RIB_CHECK_COUNTS(0, 0);
2022
2023
0
    agg_unlock_node(rn);
2024
2025
    /*
2026
     * update this NVE's timestamp for this prefix
2027
     */
2028
0
    trn = agg_node_get(rfd->rsp_times[afi], &pfx); /* locks trn */
2029
0
    trn->info = (void *)(uintptr_t)monotime(NULL);
2030
0
    if (agg_node_get_lock_count(trn) > 1)
2031
0
      agg_unlock_node(trn);
2032
2033
0
    vnc_zlog_debug_verbose(
2034
0
      "%s:   added pfx=%pFX nh[vn]=%pFX, cost=%u, lifetime=%u, allowed=%d",
2035
0
      __func__, &pfx, &rk.vn, nhp->prefix.cost, nhp->lifetime,
2036
0
      allowed);
2037
2038
0
    if (allowed) {
2039
0
      if (tail)
2040
0
        (tail)->next = nhp;
2041
0
      tail = nhp;
2042
0
      if (!head) {
2043
0
        head = nhp;
2044
0
      }
2045
0
    } else {
2046
0
      rfapi_un_options_free(nhp->un_options);
2047
0
      nhp->un_options = NULL;
2048
0
      rfapi_vn_options_free(nhp->vn_options);
2049
0
      nhp->vn_options = NULL;
2050
2051
0
      XFREE(MTYPE_RFAPI_NEXTHOP, nhp);
2052
0
    }
2053
0
  }
2054
2055
0
  if (tail)
2056
0
    tail->next = NULL;
2057
0
  return head;
2058
0
}
2059
2060
void rfapiRibPendingDeleteRoute(struct bgp *bgp, struct rfapi_import_table *it,
2061
        afi_t afi, struct agg_node *it_node)
2062
0
{
2063
0
  struct rfapi_descriptor *rfd;
2064
0
  struct listnode *node;
2065
0
  const struct prefix *p = agg_node_get_prefix(it_node);
2066
2067
0
  vnc_zlog_debug_verbose("%s: entry, it=%p, afi=%d, it_node=%p, pfx=%pRN",
2068
0
             __func__, it, afi, it_node, it_node);
2069
2070
0
  if (AFI_L2VPN == afi) {
2071
    /*
2072
     * ethernet import tables are per-LNI and each ethernet monitor
2073
     * identifies the rfd that owns it.
2074
     */
2075
0
    struct rfapi_monitor_eth *m;
2076
0
    struct agg_node *rn;
2077
0
    struct skiplist *sl;
2078
0
    void *cursor;
2079
0
    int rc;
2080
2081
    /*
2082
     * route-specific monitors
2083
     */
2084
0
    if ((sl = RFAPI_MONITOR_ETH(it_node))) {
2085
2086
0
      vnc_zlog_debug_verbose(
2087
0
        "%s: route-specific skiplist: %p", __func__,
2088
0
        sl);
2089
2090
0
      for (cursor = NULL,
2091
0
          rc = skiplist_next(sl, NULL, (void **)&m, &cursor);
2092
0
           !rc; rc = skiplist_next(sl, NULL, (void **)&m,
2093
0
                 &cursor)) {
2094
2095
#if DEBUG_PENDING_DELETE_ROUTE
2096
        vnc_zlog_debug_verbose("%s: eth monitor rfd=%p",
2097
                   __func__, m->rfd);
2098
#endif
2099
        /*
2100
         * If we have already sent a route with this
2101
         * prefix to this
2102
         * NVE, it's OK to send an update with the
2103
         * delete
2104
         */
2105
0
        if ((rn = agg_node_lookup(m->rfd->rib[afi],
2106
0
                p))) {
2107
0
          rfapiRibUpdatePendingNode(
2108
0
            bgp, m->rfd, it, it_node,
2109
0
            m->rfd->response_lifetime);
2110
0
          agg_unlock_node(rn);
2111
0
        }
2112
0
      }
2113
0
    }
2114
2115
    /*
2116
     * all-routes/FTD monitors
2117
     */
2118
0
    for (m = it->eth0_queries; m; m = m->next) {
2119
#if DEBUG_PENDING_DELETE_ROUTE
2120
      vnc_zlog_debug_verbose("%s: eth0 monitor rfd=%p",
2121
                 __func__, m->rfd);
2122
#endif
2123
      /*
2124
       * If we have already sent a route with this prefix to
2125
       * this
2126
       * NVE, it's OK to send an update with the delete
2127
       */
2128
0
      if ((rn = agg_node_lookup(m->rfd->rib[afi], p))) {
2129
0
        rfapiRibUpdatePendingNode(
2130
0
          bgp, m->rfd, it, it_node,
2131
0
          m->rfd->response_lifetime);
2132
0
        agg_unlock_node(rn);
2133
0
      }
2134
0
    }
2135
2136
0
  } else {
2137
    /*
2138
     * Find RFDs that reference this import table
2139
     */
2140
0
    for (ALL_LIST_ELEMENTS_RO(&bgp->rfapi->descriptors, node,
2141
0
            rfd)) {
2142
2143
0
      struct agg_node *rn;
2144
2145
0
      vnc_zlog_debug_verbose(
2146
0
        "%s: comparing rfd(%p)->import_table=%p to it=%p",
2147
0
        __func__, rfd, rfd->import_table, it);
2148
2149
0
      if (rfd->import_table != it)
2150
0
        continue;
2151
2152
0
      vnc_zlog_debug_verbose("%s: matched rfd %p", __func__,
2153
0
                 rfd);
2154
2155
      /*
2156
       * If we have sent a response to this NVE with this
2157
       * prefix
2158
       * previously, we should send an updated response.
2159
       */
2160
0
      if ((rn = agg_node_lookup(rfd->rib[afi], p))) {
2161
0
        rfapiRibUpdatePendingNode(
2162
0
          bgp, rfd, it, it_node,
2163
0
          rfd->response_lifetime);
2164
0
        agg_unlock_node(rn);
2165
0
      }
2166
0
    }
2167
0
  }
2168
0
}
2169
2170
void rfapiRibShowResponsesSummary(void *stream)
2171
0
{
2172
0
  int (*fp)(void *, const char *, ...);
2173
0
  struct vty *vty;
2174
0
  void *out;
2175
0
  const char *vty_newline;
2176
0
  struct bgp *bgp = bgp_get_default();
2177
2178
0
  int nves = 0;
2179
0
  int nves_with_nonempty_ribs = 0;
2180
0
  struct rfapi_descriptor *rfd;
2181
0
  struct listnode *node;
2182
2183
0
  if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
2184
0
    return;
2185
0
  if (!bgp) {
2186
0
    fp(out, "Unable to find default BGP instance\n");
2187
0
    return;
2188
0
  }
2189
2190
0
  fp(out, "%-24s ", "Responses: (Prefixes)");
2191
0
  fp(out, "%-8s %-8u ", "Active:", bgp->rfapi->rib_prefix_count_total);
2192
0
  fp(out, "%-8s %-8u",
2193
0
     "Maximum:", bgp->rfapi->rib_prefix_count_total_max);
2194
0
  fp(out, "\n");
2195
2196
0
  fp(out, "%-24s ", "           (Updated)");
2197
0
  fp(out, "%-8s %-8u ",
2198
0
     "Update:", bgp->rfapi->stat.count_updated_response_updates);
2199
0
  fp(out, "%-8s %-8u",
2200
0
     "Remove:", bgp->rfapi->stat.count_updated_response_deletes);
2201
0
  fp(out, "%-8s %-8u", "Total:",
2202
0
     bgp->rfapi->stat.count_updated_response_updates
2203
0
       + bgp->rfapi->stat.count_updated_response_deletes);
2204
0
  fp(out, "\n");
2205
2206
0
  fp(out, "%-24s ", "           (NVEs)");
2207
0
  for (ALL_LIST_ELEMENTS_RO(&bgp->rfapi->descriptors, node, rfd)) {
2208
0
    ++nves;
2209
0
    if (rfd->rib_prefix_count)
2210
0
      ++nves_with_nonempty_ribs;
2211
0
  }
2212
0
  fp(out, "%-8s %-8u ", "Active:", nves_with_nonempty_ribs);
2213
0
  fp(out, "%-8s %-8u", "Total:", nves);
2214
0
  fp(out, "\n");
2215
0
}
2216
2217
void rfapiRibShowResponsesSummaryClear(void)
2218
0
{
2219
0
  struct bgp *bgp = bgp_get_default();
2220
2221
0
  bgp->rfapi->rib_prefix_count_total_max =
2222
0
    bgp->rfapi->rib_prefix_count_total;
2223
0
}
2224
2225
static int print_rib_sl(int (*fp)(void *, const char *, ...), struct vty *vty,
2226
      void *out, struct skiplist *sl, int deleted,
2227
      char *str_pfx, int *printedprefix)
2228
0
{
2229
0
  struct rfapi_info *ri;
2230
0
  int rc;
2231
0
  void *cursor;
2232
0
  int routes_displayed = 0;
2233
2234
0
  cursor = NULL;
2235
0
  for (rc = skiplist_next(sl, NULL, (void **)&ri, &cursor); !rc;
2236
0
       rc = skiplist_next(sl, NULL, (void **)&ri, &cursor)) {
2237
2238
0
    char str_vn[PREFIX_STRLEN];
2239
0
    char str_un[PREFIX_STRLEN];
2240
0
    char str_lifetime[BUFSIZ];
2241
0
    char str_age[BUFSIZ];
2242
0
    char *p;
2243
2244
0
    ++routes_displayed;
2245
2246
0
    prefix2str(&ri->rk.vn, str_vn, sizeof(str_vn));
2247
0
    p = index(str_vn, '/');
2248
0
    if (p)
2249
0
      *p = 0;
2250
2251
0
    prefix2str(&ri->un, str_un, sizeof(str_un));
2252
0
    p = index(str_un, '/');
2253
0
    if (p)
2254
0
      *p = 0;
2255
2256
0
    rfapiFormatSeconds(ri->lifetime, str_lifetime, BUFSIZ);
2257
#ifdef RFAPI_REGISTRATIONS_REPORT_AGE
2258
    rfapiFormatAge(ri->last_sent_time, str_age, BUFSIZ);
2259
#else
2260
0
    {
2261
0
      time_t now = monotime(NULL);
2262
0
      time_t expire =
2263
0
        ri->last_sent_time + (time_t)ri->lifetime;
2264
      /* allow for delayed/async removal */
2265
0
      rfapiFormatSeconds((expire > now ? expire - now : 1),
2266
0
             str_age, BUFSIZ);
2267
0
    }
2268
0
#endif
2269
2270
0
    fp(out, " %c %-20s %-15s %-15s %-4u %-8s %-8s %pRDP\n",
2271
0
       deleted ? 'r' : ' ', *printedprefix ? "" : str_pfx, str_vn,
2272
0
       str_un, ri->cost, str_lifetime, str_age, &ri->rk.rd);
2273
2274
0
    if (!*printedprefix)
2275
0
      *printedprefix = 1;
2276
0
  }
2277
0
  return routes_displayed;
2278
0
}
2279
2280
#if DEBUG_NHL
2281
/*
2282
 * This one is for debugging (set stream to NULL to send output to log)
2283
 */
2284
static void rfapiRibShowRibSl(void *stream, struct prefix *pfx,
2285
            struct skiplist *sl)
2286
{
2287
  int (*fp)(void *, const char *, ...);
2288
  struct vty *vty;
2289
  void *out;
2290
  const char *vty_newline;
2291
2292
  int nhs_displayed = 0;
2293
  char str_pfx[PREFIX_STRLEN];
2294
  int printedprefix = 0;
2295
2296
  if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
2297
    return;
2298
2299
  prefix2str(pfx, str_pfx, sizeof(str_pfx));
2300
2301
  nhs_displayed +=
2302
    print_rib_sl(fp, vty, out, sl, 0, str_pfx, &printedprefix);
2303
}
2304
#endif
2305
2306
void rfapiRibShowResponses(void *stream, struct prefix *pfx_match,
2307
         int show_removed)
2308
0
{
2309
0
  int (*fp)(void *, const char *, ...);
2310
0
  struct vty *vty;
2311
0
  void *out;
2312
0
  const char *vty_newline;
2313
2314
0
  struct rfapi_descriptor *rfd;
2315
0
  struct listnode *node;
2316
2317
0
  struct bgp *bgp = bgp_get_default();
2318
0
  int printedheader = 0;
2319
0
  int routes_total = 0;
2320
0
  int nhs_total = 0;
2321
0
  int nves_displayed = 0;
2322
0
  int routes_displayed = 0;
2323
0
  int nhs_displayed = 0;
2324
2325
0
  if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
2326
0
    return;
2327
0
  if (!bgp) {
2328
0
    fp(out, "Unable to find default BGP instance\n");
2329
0
    return;
2330
0
  }
2331
2332
  /*
2333
   * loop over NVEs
2334
   */
2335
0
  for (ALL_LIST_ELEMENTS_RO(&bgp->rfapi->descriptors, node, rfd)) {
2336
2337
0
    int printednve = 0;
2338
0
    afi_t afi;
2339
2340
0
    for (afi = AFI_IP; afi < AFI_MAX; ++afi) {
2341
2342
0
      struct agg_node *rn;
2343
2344
0
      if (!rfd->rib[afi])
2345
0
        continue;
2346
2347
0
      for (rn = agg_route_top(rfd->rib[afi]); rn;
2348
0
           rn = agg_route_next(rn)) {
2349
0
        const struct prefix *p =
2350
0
          agg_node_get_prefix(rn);
2351
0
        struct skiplist *sl;
2352
0
        char str_pfx[PREFIX_STRLEN];
2353
0
        int printedprefix = 0;
2354
2355
0
        if (!show_removed)
2356
0
          sl = rn->info;
2357
0
        else
2358
0
          sl = rn->aggregate;
2359
2360
0
        if (!sl)
2361
0
          continue;
2362
2363
0
        routes_total++;
2364
0
        nhs_total += skiplist_count(sl);
2365
2366
0
        if (pfx_match && !prefix_match(pfx_match, p)
2367
0
            && !prefix_match(p, pfx_match))
2368
0
          continue;
2369
2370
0
        if (!printedheader) {
2371
0
          ++printedheader;
2372
2373
0
          fp(out, "\n[%s]\n",
2374
0
             show_removed ? "Removed" : "Active");
2375
0
          fp(out, "%-15s %-15s\n", "Querying VN",
2376
0
             "Querying UN");
2377
0
          fp(out,
2378
0
             "   %-20s %-15s %-15s %4s %-8s %-8s\n",
2379
0
             "Prefix", "Registered VN",
2380
0
             "Registered UN", "Cost", "Lifetime",
2381
#ifdef RFAPI_REGISTRATIONS_REPORT_AGE
2382
             "Age"
2383
#else
2384
0
             "Remaining"
2385
0
#endif
2386
0
          );
2387
0
        }
2388
0
        if (!printednve) {
2389
0
          char str_vn[BUFSIZ];
2390
0
          char str_un[BUFSIZ];
2391
2392
0
          ++printednve;
2393
0
          ++nves_displayed;
2394
2395
0
          fp(out, "%-15s %-15s\n",
2396
0
             rfapiRfapiIpAddr2Str(&rfd->vn_addr,
2397
0
                str_vn, BUFSIZ),
2398
0
             rfapiRfapiIpAddr2Str(&rfd->un_addr,
2399
0
                str_un,
2400
0
                BUFSIZ));
2401
0
        }
2402
0
        prefix2str(p, str_pfx, sizeof(str_pfx));
2403
        // fp(out, "  %s\n", buf);  /* prefix */
2404
2405
0
        routes_displayed++;
2406
0
        nhs_displayed += print_rib_sl(
2407
0
          fp, vty, out, sl, show_removed, str_pfx,
2408
0
          &printedprefix);
2409
0
      }
2410
0
    }
2411
0
  }
2412
2413
0
  if (routes_total) {
2414
0
    fp(out, "\n");
2415
0
    fp(out, "Displayed %u NVEs, and %u out of %u %s prefixes",
2416
0
       nves_displayed, routes_displayed, routes_total,
2417
0
       show_removed ? "removed" : "active");
2418
0
    if (nhs_displayed != routes_displayed
2419
0
        || nhs_total != routes_total)
2420
0
      fp(out, " with %u out of %u next hops", nhs_displayed,
2421
0
         nhs_total);
2422
0
    fp(out, "\n");
2423
0
  }
2424
0
}