Coverage Report

Created: 2026-01-13 06:56

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/frr/bgpd/rfapi/rfapi.c
Line
Count
Source
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
/*
3
 *
4
 * Copyright 2009-2016, LabN Consulting, L.L.C.
5
 *
6
 */
7
8
#include "lib/zebra.h"
9
#include "lib/prefix.h"
10
#include "lib/agg_table.h"
11
#include "lib/vty.h"
12
#include "lib/memory.h"
13
#include "lib/routemap.h"
14
#include "lib/log.h"
15
#include "lib/linklist.h"
16
#include "lib/command.h"
17
#include "lib/stream.h"
18
#include "lib/ringbuf.h"
19
#include "lib/lib_errors.h"
20
21
#include "bgpd/bgpd.h"
22
#include "bgpd/bgp_ecommunity.h"
23
#include "bgpd/bgp_attr.h"
24
25
#include "bgpd/rfapi/bgp_rfapi_cfg.h"
26
#include "bgpd/rfapi/rfapi.h"
27
#include "bgpd/rfapi/rfapi_backend.h"
28
29
#include "bgpd/bgp_route.h"
30
#include "bgpd/bgp_mplsvpn.h"
31
#include "bgpd/bgp_aspath.h"
32
#include "bgpd/bgp_advertise.h"
33
#include "bgpd/bgp_vnc_types.h"
34
#include "bgpd/bgp_zebra.h"
35
36
#include "bgpd/rfapi/rfapi_import.h"
37
#include "bgpd/rfapi/rfapi_private.h"
38
#include "bgpd/rfapi/rfapi_monitor.h"
39
#include "bgpd/rfapi/rfapi_vty.h"
40
#include "bgpd/rfapi/vnc_export_bgp.h"
41
#include "bgpd/rfapi/vnc_export_bgp_p.h"
42
#include "bgpd/rfapi/vnc_zebra.h"
43
#include "bgpd/rfapi/vnc_import_bgp.h"
44
#include "bgpd/rfapi/rfapi_rib.h"
45
#include "bgpd/rfapi/rfapi_ap.h"
46
#include "bgpd/rfapi/rfapi_encap_tlv.h"
47
#include "bgpd/rfapi/vnc_debug.h"
48
49
#ifdef HAVE_GLIBC_BACKTRACE
50
/* for backtrace and friends */
51
#include <execinfo.h>
52
#endif /* HAVE_GLIBC_BACKTRACE */
53
54
#define DEBUG_CLEANUP 0
55
56
struct ethaddr rfapi_ethaddr0 = {{0}};
57
58
#define DEBUG_RFAPI_STR "RF API debugging/testing command\n"
59
60
const char *rfapi_error_str(int code)
61
0
{
62
0
  switch (code) {
63
0
  case 0:
64
0
    return "Success";
65
0
  case ENXIO:
66
0
    return "BGP or VNC not configured";
67
0
  case ENOENT:
68
0
    return "No match";
69
0
  case EEXIST:
70
0
    return "Handle already open";
71
0
  case ENOMSG:
72
0
    return "Incomplete configuration";
73
0
  case EAFNOSUPPORT:
74
0
    return "Invalid address family";
75
0
  case EDEADLK:
76
0
    return "Called from within a callback procedure";
77
0
  case EBADF:
78
0
    return "Invalid handle";
79
0
  case EINVAL:
80
0
    return "Invalid argument";
81
0
  case ESTALE:
82
0
    return "Stale descriptor";
83
0
  default:
84
0
    return "Unknown error";
85
0
  }
86
0
}
87
88
/*------------------------------------------
89
 * rfapi_get_response_lifetime_default
90
 *
91
 * Returns the default lifetime for a response.
92
 *    rfp_start_val     value returned by rfp_start or
93
 *                      NULL (=use default instance)
94
 *
95
 * input:
96
 *    None
97
 *
98
 * output:
99
 *
100
 * return value: The bgp instance default lifetime for a response.
101
 --------------------------------------------*/
102
int rfapi_get_response_lifetime_default(void *rfp_start_val)
103
0
{
104
0
  struct bgp *bgp = rfapi_bgp_lookup_by_rfp(rfp_start_val);
105
0
  if (bgp)
106
0
    return bgp->rfapi_cfg->default_response_lifetime;
107
0
  return BGP_VNC_DEFAULT_RESPONSE_LIFETIME_DEFAULT;
108
0
}
109
110
/*------------------------------------------
111
 * rfapi_is_vnc_configured
112
 *
113
 * Returns if VNC is configured
114
 *
115
 * input:
116
 *    rfp_start_val     value returned by rfp_start or
117
 *                      NULL (=use default instance)
118
 *
119
 * output:
120
 *
121
 * return value: If VNC is configured for the bgpd instance
122
 *  0   Success
123
 *  ENXIO   VNC not configured
124
 --------------------------------------------*/
125
int rfapi_is_vnc_configured(void *rfp_start_val)
126
0
{
127
0
  struct bgp *bgp = rfapi_bgp_lookup_by_rfp(rfp_start_val);
128
0
  if (bgp_rfapi_is_vnc_configured(bgp) == 0)
129
0
    return 0;
130
0
  return ENXIO;
131
0
}
132
133
134
/*------------------------------------------
135
 * rfapi_get_vn_addr
136
 *
137
 * Get the virtual network address used by an NVE based on it's RFD
138
 *
139
 * input:
140
 *    rfd: rfapi descriptor returned by rfapi_open or rfapi_create_generic
141
 *
142
 * output:
143
 *
144
 * return value:
145
 *  vn    NVE virtual network address
146
 *------------------------------------------*/
147
struct rfapi_ip_addr *rfapi_get_vn_addr(void *rfd)
148
0
{
149
0
  struct rfapi_descriptor *rrfd = (struct rfapi_descriptor *)rfd;
150
0
  return &rrfd->vn_addr;
151
0
}
152
153
/*------------------------------------------
154
 * rfapi_get_un_addr
155
 *
156
 * Get the underlay network address used by an NVE based on it's RFD
157
 *
158
 * input:
159
 *    rfd: rfapi descriptor returned by rfapi_open or rfapi_create_generic
160
 *
161
 * output:
162
 *
163
 * return value:
164
 *  un    NVE underlay network address
165
 *------------------------------------------*/
166
struct rfapi_ip_addr *rfapi_get_un_addr(void *rfd)
167
0
{
168
0
  struct rfapi_descriptor *rrfd = (struct rfapi_descriptor *)rfd;
169
0
  return &rrfd->un_addr;
170
0
}
171
172
int rfapi_ip_addr_cmp(struct rfapi_ip_addr *a1, struct rfapi_ip_addr *a2)
173
0
{
174
0
  if (a1->addr_family != a2->addr_family)
175
0
    return a1->addr_family - a2->addr_family;
176
177
0
  if (a1->addr_family == AF_INET) {
178
0
    return IPV4_ADDR_CMP(&a1->addr.v4, &a2->addr.v4);
179
0
  }
180
181
0
  if (a1->addr_family == AF_INET6) {
182
0
    return IPV6_ADDR_CMP(&a1->addr.v6, &a2->addr.v6);
183
0
  }
184
185
0
  assert(1);
186
  /* NOTREACHED */
187
0
  return 1;
188
0
}
189
190
static int rfapi_find_node(struct bgp *bgp, struct rfapi_ip_addr *vn_addr,
191
         struct rfapi_ip_addr *un_addr,
192
         struct agg_node **node)
193
0
{
194
0
  struct rfapi *h;
195
0
  struct prefix p;
196
0
  struct agg_node *rn;
197
0
  int rc;
198
0
  afi_t afi;
199
200
0
  if (!bgp) {
201
0
    return ENXIO;
202
0
  }
203
204
0
  h = bgp->rfapi;
205
0
  if (!h) {
206
0
    return ENXIO;
207
0
  }
208
209
0
  afi = family2afi(un_addr->addr_family);
210
0
  if (!afi) {
211
0
    return EAFNOSUPPORT;
212
0
  }
213
214
0
  if ((rc = rfapiRaddr2Qprefix(un_addr, &p)))
215
0
    return rc;
216
217
0
  rn = agg_node_lookup(h->un[afi], &p);
218
219
0
  if (!rn)
220
0
    return ENOENT;
221
222
0
  agg_unlock_node(rn);
223
224
0
  *node = rn;
225
226
0
  return 0;
227
0
}
228
229
230
int rfapi_find_rfd(struct bgp *bgp, struct rfapi_ip_addr *vn_addr,
231
       struct rfapi_ip_addr *un_addr, struct rfapi_descriptor **rfd)
232
0
{
233
0
  struct agg_node *rn;
234
0
  int rc;
235
236
0
  rc = rfapi_find_node(bgp, vn_addr, un_addr, &rn);
237
238
0
  if (rc)
239
0
    return rc;
240
241
0
  for (*rfd = (struct rfapi_descriptor *)(rn->info); *rfd;
242
0
       *rfd = (*rfd)->next) {
243
0
    if (!rfapi_ip_addr_cmp(&(*rfd)->vn_addr, vn_addr))
244
0
      break;
245
0
  }
246
247
0
  if (!*rfd)
248
0
    return ENOENT;
249
250
0
  return 0;
251
0
}
252
253
/*------------------------------------------
254
 * rfapi_find_handle
255
 *
256
 * input:
257
 *  un    underlay network address
258
 *  vn    virtual network address
259
 *
260
 * output:
261
 *  pHandle   pointer to location to store handle
262
 *
263
 * return value:
264
 *  0   Success
265
 *  ENOENT    no matching handle
266
 *  ENXIO   BGP or VNC not configured
267
 *------------------------------------------*/
268
static int rfapi_find_handle(struct bgp *bgp, struct rfapi_ip_addr *vn_addr,
269
           struct rfapi_ip_addr *un_addr,
270
           rfapi_handle *handle)
271
0
{
272
0
  struct rfapi_descriptor **rfd;
273
274
0
  rfd = (struct rfapi_descriptor **)handle;
275
276
0
  return rfapi_find_rfd(bgp, vn_addr, un_addr, rfd);
277
0
}
278
279
static int rfapi_find_handle_vty(struct vty *vty, struct rfapi_ip_addr *vn_addr,
280
         struct rfapi_ip_addr *un_addr,
281
         rfapi_handle *handle)
282
0
{
283
0
  struct bgp *bgp;
284
0
  struct rfapi_descriptor **rfd;
285
286
0
  bgp = bgp_get_default(); /* assume 1 instance for now */
287
288
0
  rfd = (struct rfapi_descriptor **)handle;
289
290
0
  return rfapi_find_rfd(bgp, vn_addr, un_addr, rfd);
291
0
}
292
293
static int is_valid_rfd(struct rfapi_descriptor *rfd)
294
0
{
295
0
  rfapi_handle hh;
296
297
0
  if (!rfd || rfd->bgp == NULL)
298
0
    return 0;
299
300
0
  if (CHECK_FLAG(
301
0
        rfd->flags,
302
0
        RFAPI_HD_FLAG_IS_VRF)) /* assume VRF/internal are valid */
303
0
    return 1;
304
305
0
  if (rfapi_find_handle(rfd->bgp, &rfd->vn_addr, &rfd->un_addr, &hh))
306
0
    return 0;
307
308
0
  if (rfd != hh)
309
0
    return 0;
310
311
0
  return 1;
312
0
}
313
314
/*
315
 * check status of descriptor
316
 */
317
int rfapi_check(void *handle)
318
0
{
319
0
  struct rfapi_descriptor *rfd = (struct rfapi_descriptor *)handle;
320
0
  rfapi_handle hh;
321
0
  int rc;
322
323
0
  if (!rfd || rfd->bgp == NULL)
324
0
    return EINVAL;
325
326
0
  if (CHECK_FLAG(
327
0
        rfd->flags,
328
0
        RFAPI_HD_FLAG_IS_VRF)) /* assume VRF/internal are valid */
329
0
    return 0;
330
331
0
  if ((rc = rfapi_find_handle(rfd->bgp, &rfd->vn_addr, &rfd->un_addr,
332
0
            &hh)))
333
0
    return rc;
334
335
0
  if (rfd != hh)
336
0
    return ENOENT;
337
338
0
  if (!rfd->rfg)
339
0
    return ESTALE;
340
341
0
  return 0;
342
0
}
343
344
345
void del_vnc_route(struct rfapi_descriptor *rfd,
346
       struct peer *peer, /* rfd->peer for RFP regs */
347
       struct bgp *bgp, safi_t safi, const struct prefix *p,
348
       struct prefix_rd *prd, uint8_t type, uint8_t sub_type,
349
       struct rfapi_nexthop *lnh, int kill)
350
0
{
351
0
  afi_t afi; /* of the VN address */
352
0
  struct bgp_dest *bn;
353
0
  struct bgp_path_info *bpi;
354
0
  struct prefix_rd prd0;
355
356
0
  afi = family2afi(p->family);
357
0
  assert(afi == AFI_IP || afi == AFI_IP6);
358
359
0
  if (safi == SAFI_ENCAP) {
360
0
    memset(&prd0, 0, sizeof(prd0));
361
0
    prd0.family = AF_UNSPEC;
362
0
    prd0.prefixlen = 64;
363
0
    prd = &prd0;
364
0
  }
365
0
  bn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
366
367
0
  vnc_zlog_debug_verbose(
368
0
    "%s: peer=%p, prefix=%pFX, prd=%pRDP afi=%d, safi=%d bn=%p, bn->info=%p",
369
0
    __func__, peer, p, prd, afi, safi, bn,
370
0
    (bn ? bgp_dest_get_bgp_path_info(bn) : NULL));
371
372
0
  for (bpi = (bn ? bgp_dest_get_bgp_path_info(bn) : NULL); bpi;
373
0
       bpi = bpi->next) {
374
375
0
    vnc_zlog_debug_verbose(
376
0
      "%s: trying bpi=%p, bpi->peer=%p, bpi->type=%d, bpi->sub_type=%d, bpi->extra->vnc.export.rfapi_handle=%p, local_pref=%" PRIu64,
377
0
      __func__, bpi, bpi->peer, bpi->type, bpi->sub_type,
378
0
      (bpi->extra ? bpi->extra->vnc.export.rfapi_handle
379
0
            : NULL),
380
0
      CHECK_FLAG(bpi->attr->flag,
381
0
           ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)
382
0
           ? bpi->attr->local_pref : 0));
383
384
0
    if (bpi->peer == peer && bpi->type == type
385
0
        && bpi->sub_type == sub_type && bpi->extra
386
0
        && bpi->extra->vnc.export.rfapi_handle == (void *)rfd) {
387
388
0
      vnc_zlog_debug_verbose("%s: matched it", __func__);
389
390
0
      break;
391
0
    }
392
0
  }
393
394
0
  if (lnh) {
395
    /*
396
     * lnh set means to JUST delete the local nexthop from this
397
     * route. Leave the route itself in place.
398
     * TBD add return code reporting of success/failure
399
     */
400
0
    if (!bpi || !bpi->extra
401
0
        || !bpi->extra->vnc.export.local_nexthops) {
402
      /*
403
       * no local nexthops
404
       */
405
0
      vnc_zlog_debug_verbose(
406
0
        "%s: lnh list already empty at prefix %pFX",
407
0
        __func__, p);
408
0
      goto done;
409
0
    }
410
411
    /*
412
     * look for it
413
     */
414
0
    struct listnode *node;
415
0
    struct rfapi_nexthop *pLnh = NULL;
416
417
0
    for (ALL_LIST_ELEMENTS_RO(bpi->extra->vnc.export.local_nexthops,
418
0
            node, pLnh)) {
419
420
0
      if (prefix_same(&pLnh->addr, &lnh->addr)) {
421
0
        break;
422
0
      }
423
0
    }
424
425
0
    if (pLnh) {
426
0
      listnode_delete(bpi->extra->vnc.export.local_nexthops,
427
0
          pLnh);
428
429
      /* silly rabbit, listnode_delete doesn't invoke
430
       * list->del on data */
431
0
      rfapi_nexthop_free(pLnh);
432
0
    } else {
433
0
      vnc_zlog_debug_verbose("%s: desired lnh not found %pFX",
434
0
                 __func__, p);
435
0
    }
436
0
    goto done;
437
0
  }
438
439
  /*
440
   * loop back to import tables
441
   * Do this before removing from BGP RIB because rfapiProcessWithdraw
442
   * might refer to it
443
   */
444
0
  rfapiProcessWithdraw(peer, rfd, p, prd, NULL, afi, safi, type, kill);
445
446
0
  if (bpi) {
447
0
    vnc_zlog_debug_verbose(
448
0
      "%s: Found route (safi=%d) to delete at prefix %pFX",
449
0
      __func__, safi, p);
450
451
0
    if (safi == SAFI_MPLS_VPN) {
452
0
      struct bgp_dest *pdest = NULL;
453
0
      struct bgp_table *table = NULL;
454
455
0
      pdest = bgp_node_get(bgp->rib[afi][safi],
456
0
               (struct prefix *)prd);
457
0
      table = bgp_dest_get_bgp_table_info(pdest);
458
0
      if (table)
459
0
        vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
460
0
          bgp, prd, table, p, bpi);
461
0
      bgp_dest_unlock_node(pdest);
462
0
    }
463
464
    /*
465
     * Delete local_nexthops list
466
     */
467
0
    if (bpi->extra && bpi->extra->vnc.export.local_nexthops)
468
0
      list_delete(&bpi->extra->vnc.export.local_nexthops);
469
470
0
    bgp_aggregate_decrement(bgp, p, bpi, afi, safi);
471
0
    bgp_path_info_delete(bn, bpi);
472
0
    bgp_process(bgp, bn, afi, safi);
473
0
  } else {
474
0
    vnc_zlog_debug_verbose(
475
0
      "%s: Couldn't find route (safi=%d) at prefix %pFX",
476
0
      __func__, safi, p);
477
0
  }
478
0
done:
479
0
  bgp_dest_unlock_node(bn);
480
0
}
481
482
struct rfapi_nexthop *rfapi_nexthop_new(struct rfapi_nexthop *copyme)
483
0
{
484
0
  struct rfapi_nexthop *new =
485
0
    XCALLOC(MTYPE_RFAPI_NEXTHOP, sizeof(struct rfapi_nexthop));
486
0
  if (copyme)
487
0
    *new = *copyme;
488
0
  return new;
489
0
}
490
491
void rfapi_nexthop_free(void *p)
492
0
{
493
0
  struct rfapi_nexthop *goner = p;
494
0
  XFREE(MTYPE_RFAPI_NEXTHOP, goner);
495
0
}
496
497
struct rfapi_vn_option *rfapi_vn_options_dup(struct rfapi_vn_option *existing)
498
0
{
499
0
  struct rfapi_vn_option *p;
500
0
  struct rfapi_vn_option *head = NULL;
501
0
  struct rfapi_vn_option *tail = NULL;
502
503
0
  for (p = existing; p; p = p->next) {
504
0
    struct rfapi_vn_option *new;
505
506
0
    new = XCALLOC(MTYPE_RFAPI_VN_OPTION,
507
0
            sizeof(struct rfapi_vn_option));
508
0
    *new = *p;
509
0
    new->next = NULL;
510
0
    if (tail)
511
0
      (tail)->next = new;
512
0
    tail = new;
513
0
    if (!head) {
514
0
      head = new;
515
0
    }
516
0
  }
517
0
  return head;
518
0
}
519
520
void rfapi_un_options_free(struct rfapi_un_option *p)
521
0
{
522
0
  struct rfapi_un_option *next;
523
524
0
  while (p) {
525
0
    next = p->next;
526
0
    XFREE(MTYPE_RFAPI_UN_OPTION, p);
527
0
    p = next;
528
0
  }
529
0
}
530
531
void rfapi_vn_options_free(struct rfapi_vn_option *p)
532
0
{
533
0
  struct rfapi_vn_option *next;
534
535
0
  while (p) {
536
0
    next = p->next;
537
0
    XFREE(MTYPE_RFAPI_VN_OPTION, p);
538
0
    p = next;
539
0
  }
540
0
}
541
542
/* Based on bgp_redistribute_add() */
543
void add_vnc_route(struct rfapi_descriptor *rfd, /* cookie, VPN UN addr, peer */
544
       struct bgp *bgp, int safi, const struct prefix *p,
545
       struct prefix_rd *prd, struct rfapi_ip_addr *nexthop,
546
       uint32_t *local_pref,
547
       uint32_t *lifetime, /* NULL => dont send lifetime */
548
       struct bgp_tea_options *rfp_options,
549
       struct rfapi_un_option *options_un,
550
       struct rfapi_vn_option *options_vn,
551
       struct ecommunity *rt_export_list, /* Copied, not consumed */
552
       uint32_t *med,      /* NULL => don't set med */
553
       uint32_t *label,      /* low order 3 bytes */
554
       uint8_t type, uint8_t sub_type, /* RFP, NORMAL or REDIST */
555
       int flags)
556
0
{
557
0
  afi_t afi; /* of the VN address */
558
0
  struct bgp_path_info *new;
559
0
  struct bgp_path_info *bpi;
560
0
  struct bgp_dest *bn;
561
562
0
  struct attr attr = {0};
563
0
  struct attr *new_attr;
564
0
  uint32_t label_val;
565
566
0
  struct bgp_attr_encap_subtlv *encaptlv;
567
0
  char buf[PREFIX_STRLEN];
568
569
0
  struct rfapi_nexthop *lnh = NULL; /* local nexthop */
570
0
  struct rfapi_vn_option *vo;
571
0
  struct rfapi_l2address_option *l2o = NULL;
572
0
  struct rfapi_ip_addr *un_addr = &rfd->un_addr;
573
574
0
  bgp_encap_types TunnelType = BGP_ENCAP_TYPE_RESERVED;
575
0
  struct bgp_redist *red;
576
577
0
  if (safi == SAFI_ENCAP
578
0
      && !(bgp->rfapi_cfg->flags & BGP_VNC_CONFIG_ADV_UN_METHOD_ENCAP)) {
579
580
    /*
581
     * Encap mode not enabled. UN addresses will be communicated
582
     * via VNC Tunnel subtlv instead.
583
     */
584
0
    vnc_zlog_debug_verbose(
585
0
      "%s: encap mode not enabled, not adding SAFI_ENCAP route",
586
0
      __func__);
587
0
    return;
588
0
  }
589
590
0
  for (vo = options_vn; vo; vo = vo->next) {
591
0
    if (RFAPI_VN_OPTION_TYPE_L2ADDR == vo->type) {
592
0
      l2o = &vo->v.l2addr;
593
0
      if (RFAPI_0_ETHERADDR(&l2o->macaddr))
594
0
        l2o = NULL; /* not MAC resolution */
595
0
    }
596
0
    if (RFAPI_VN_OPTION_TYPE_LOCAL_NEXTHOP == vo->type) {
597
0
      lnh = &vo->v.local_nexthop;
598
0
    }
599
0
  }
600
601
0
  if (label)
602
0
    label_val = *label;
603
0
  else
604
0
    label_val = MPLS_LABEL_IMPLICIT_NULL;
605
606
0
  afi = family2afi(p->family);
607
0
  assert(afi == AFI_IP || afi == AFI_IP6);
608
609
0
  vnc_zlog_debug_verbose("%s: afi=%s, safi=%s", __func__, afi2str(afi),
610
0
             safi2str(safi));
611
612
  /* Make default attribute. Produces already-interned attr.aspath */
613
  /* Cripes, the memory management of attributes is byzantine */
614
615
0
  bgp_attr_default_set(&attr, bgp, BGP_ORIGIN_INCOMPLETE);
616
617
  /*
618
   * At this point:
619
   * attr: static
620
   *  extra: dynamically allocated, owned by attr
621
   *  aspath: points to interned hash from aspath hash table
622
   */
623
624
625
  /*
626
   * Route-specific un_options get added to the VPN SAFI
627
   * advertisement tunnel encap attribute.  (the per-NVE
628
   * "default" un_options are put into the 1-per-NVE ENCAP
629
   * SAFI advertisement). The VPN SAFI also gets the
630
   * default un_options if there are no route-specific options.
631
   */
632
0
  if (options_un) {
633
0
    struct rfapi_un_option *uo;
634
635
0
    for (uo = options_un; uo; uo = uo->next) {
636
0
      if (RFAPI_UN_OPTION_TYPE_TUNNELTYPE == uo->type) {
637
0
        TunnelType = rfapi_tunneltype_option_to_tlv(
638
0
          bgp, un_addr, &uo->v.tunnel, &attr,
639
0
          l2o != NULL);
640
0
      }
641
0
    }
642
0
  } else {
643
    /*
644
     * Add encap attr
645
     * These are the NVE-specific "default" un_options which are
646
     * put into the 1-per-NVE ENCAP advertisement.
647
     */
648
0
    if (rfd->default_tunneltype_option.type) {
649
0
      TunnelType = rfapi_tunneltype_option_to_tlv(
650
0
        bgp, un_addr, &rfd->default_tunneltype_option,
651
0
        &attr, l2o != NULL);
652
0
    } else /* create default for local addse  */
653
0
      if (type == ZEBRA_ROUTE_BGP
654
0
          && sub_type == BGP_ROUTE_RFP)
655
0
      TunnelType = rfapi_tunneltype_option_to_tlv(
656
0
        bgp, un_addr, NULL, &attr, l2o != NULL);
657
0
  }
658
659
0
  if (TunnelType == BGP_ENCAP_TYPE_MPLS) {
660
0
    if (safi == SAFI_ENCAP) {
661
      /* Encap SAFI not used with MPLS  */
662
0
      vnc_zlog_debug_verbose(
663
0
        "%s: mpls tunnel type, encap safi omitted",
664
0
        __func__);
665
0
      aspath_unintern(&attr.aspath); /* Unintern original. */
666
0
      return;
667
0
    }
668
0
  }
669
670
0
  if (local_pref) {
671
0
    attr.local_pref = *local_pref;
672
0
    attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
673
0
  }
674
675
0
  if (med) {
676
0
    attr.med = *med;
677
0
    attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
678
0
  }
679
680
  /* override default weight assigned by bgp_attr_default_set() */
681
0
  attr.weight = rfd->peer ? rfd->peer->weight[afi][safi] : 0;
682
683
  /*
684
   * NB: ticket 81: do not reset attr.aspath here because it would
685
   * cause iBGP peers to drop route
686
   */
687
688
  /*
689
   * Set originator ID for routes imported from BGP directly.
690
   * These routes could be synthetic, and therefore could
691
   * reuse the peer pointers of the routes they are derived
692
   * from. Setting the originator ID to "us" prevents the
693
   * wrong originator ID from being sent when this route is
694
   * sent from a route reflector.
695
   */
696
0
  if (type == ZEBRA_ROUTE_BGP_DIRECT
697
0
      || type == ZEBRA_ROUTE_BGP_DIRECT_EXT) {
698
0
    attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID);
699
0
    attr.originator_id = bgp->router_id;
700
0
  }
701
702
703
  /* Set up vnc attribute (sub-tlv for Prefix Lifetime) */
704
0
  if (lifetime && *lifetime != RFAPI_INFINITE_LIFETIME) {
705
0
    uint32_t lt;
706
707
0
    encaptlv = XCALLOC(MTYPE_ENCAP_TLV,
708
0
           sizeof(struct bgp_attr_encap_subtlv) + 4);
709
0
    encaptlv->type =
710
0
      BGP_VNC_SUBTLV_TYPE_LIFETIME; /* prefix lifetime */
711
0
    encaptlv->length = 4;
712
0
    lt = htonl(*lifetime);
713
0
    memcpy(encaptlv->value, &lt, 4);
714
0
    bgp_attr_set_vnc_subtlvs(&attr, encaptlv);
715
0
    vnc_zlog_debug_verbose(
716
0
      "%s: set Encap Attr Prefix Lifetime to %d", __func__,
717
0
      *lifetime);
718
0
  }
719
720
  /* add rfp options to vnc attr */
721
0
  if (rfp_options) {
722
723
0
    if (flags & RFAPI_AHR_RFPOPT_IS_VNCTLV) {
724
0
      struct bgp_attr_encap_subtlv *vnc_subtlvs =
725
0
        bgp_attr_get_vnc_subtlvs(&attr);
726
      /*
727
       * this flag means we're passing a pointer to an
728
       * existing encap tlv chain which we should copy.
729
       * It's a hack to avoid adding yet another argument
730
       * to add_vnc_route()
731
       */
732
0
      encaptlv = encap_tlv_dup(
733
0
        (struct bgp_attr_encap_subtlv *)rfp_options);
734
0
      if (vnc_subtlvs)
735
0
        vnc_subtlvs->next = encaptlv;
736
0
      else
737
0
        bgp_attr_set_vnc_subtlvs(&attr, encaptlv);
738
0
    } else {
739
0
      struct bgp_tea_options *hop;
740
      /* XXX max of one tlv present so far from above code */
741
0
      struct bgp_attr_encap_subtlv *tail =
742
0
        bgp_attr_get_vnc_subtlvs(&attr);
743
744
0
      for (hop = rfp_options; hop; hop = hop->next) {
745
746
        /*
747
         * Construct subtlv
748
         */
749
0
        encaptlv = XCALLOC(
750
0
          MTYPE_ENCAP_TLV,
751
0
          sizeof(struct bgp_attr_encap_subtlv) + 2
752
0
            + hop->length);
753
0
        encaptlv->type =
754
0
          BGP_VNC_SUBTLV_TYPE_RFPOPTION; /* RFP
755
                    option
756
                    */
757
0
        encaptlv->length = 2 + hop->length;
758
0
        *((uint8_t *)(encaptlv->value) + 0) = hop->type;
759
0
        *((uint8_t *)(encaptlv->value) + 1) =
760
0
          hop->length;
761
0
        memcpy(((uint8_t *)encaptlv->value) + 2,
762
0
               hop->value, hop->length);
763
764
        /*
765
         * add to end of subtlv chain
766
         */
767
0
        if (tail)
768
0
          tail->next = encaptlv;
769
0
        else
770
0
          bgp_attr_set_vnc_subtlvs(&attr,
771
0
                 encaptlv);
772
0
        tail = encaptlv;
773
0
      }
774
0
    }
775
0
  }
776
777
  /*
778
   * At this point:
779
   * attr: static
780
   *  extra: dynamically allocated, owned by attr
781
   *      vnc_subtlvs: dynamic chain, length 1
782
   *  aspath: points to interned hash from aspath hash table
783
   */
784
785
786
0
  bgp_attr_set_ecommunity(&attr, ecommunity_new());
787
0
  assert(bgp_attr_get_ecommunity(&attr));
788
789
0
  if (TunnelType != BGP_ENCAP_TYPE_MPLS
790
0
      && TunnelType != BGP_ENCAP_TYPE_RESERVED) {
791
    /*
792
     * Add BGP Encapsulation Extended Community. Format described in
793
     * section 4.5 of RFC 5512.
794
     * Always include when not MPLS type, to disambiguate this case.
795
     */
796
0
    struct ecommunity_val beec;
797
798
0
    memset(&beec, 0, sizeof(beec));
799
0
    beec.val[0] = ECOMMUNITY_ENCODE_OPAQUE;
800
0
    beec.val[1] = ECOMMUNITY_OPAQUE_SUBTYPE_ENCAP;
801
0
    beec.val[6] = ((TunnelType) >> 8) & 0xff;
802
0
    beec.val[7] = (TunnelType)&0xff;
803
0
    ecommunity_add_val(bgp_attr_get_ecommunity(&attr), &beec, false,
804
0
           false);
805
0
  }
806
807
  /*
808
   * Add extended community attributes to match rt export list
809
   */
810
0
  if (rt_export_list) {
811
0
    bgp_attr_set_ecommunity(
812
0
      &attr, ecommunity_merge(bgp_attr_get_ecommunity(&attr),
813
0
            rt_export_list));
814
0
  }
815
816
0
  struct ecommunity *ecomm = bgp_attr_get_ecommunity(&attr);
817
818
0
  if (!ecomm->size) {
819
0
    ecommunity_free(&ecomm);
820
0
    bgp_attr_set_ecommunity(&attr, NULL);
821
0
  }
822
0
  vnc_zlog_debug_verbose("%s: attr.ecommunity=%p", __func__, ecomm);
823
824
825
  /*
826
   * At this point:
827
   * attr: static
828
   *  extra: dynamically allocated, owned by attr
829
   *      vnc_subtlvs: dynamic chain, length 1
830
   *      ecommunity: dynamic 2-part
831
   *  aspath: points to interned hash from aspath hash table
832
   */
833
834
  /* stuff nexthop in attr_extra; which field depends on IPv4 or IPv6 */
835
0
  switch (nexthop->addr_family) {
836
0
  case AF_INET:
837
    /*
838
     * set this field to prevent bgp_route.c code from setting
839
     * mp_nexthop_global_in to self
840
     */
841
0
    attr.nexthop.s_addr = nexthop->addr.v4.s_addr;
842
843
0
    attr.mp_nexthop_global_in = nexthop->addr.v4;
844
0
    attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
845
0
    break;
846
847
0
  case AF_INET6:
848
0
    attr.mp_nexthop_global = nexthop->addr.v6;
849
0
    attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
850
0
    break;
851
852
0
  default:
853
0
    assert(0);
854
0
  }
855
856
857
0
  prefix2str(p, buf, sizeof(buf));
858
859
  /*
860
   * At this point:
861
   *
862
   * attr: static
863
   *  extra: dynamically allocated, owned by attr
864
   *      vnc_subtlvs: dynamic chain, length 1
865
   *      ecommunity: dynamic 2-part
866
   *  aspath: points to interned hash from aspath hash table
867
   */
868
869
0
  red = bgp_redist_lookup(bgp, afi, type, 0);
870
871
0
  if (red && red->redist_metric_flag) {
872
0
    attr.med = red->redist_metric;
873
0
    attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
874
0
  }
875
876
0
  bn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
877
878
  /*
879
   * bgp_attr_intern creates a new reference to a cached
880
   * attribute, but leaves the following bits of trash:
881
   * - old attr
882
   * - old attr->extra (free via bgp_attr_extra_free(attr))
883
   *
884
   * Note that it frees the original attr->extra->ecommunity
885
   * but leaves the new attribute pointing to the ORIGINAL
886
   * vnc options (which therefore we needn't free from the
887
   * static attr)
888
   */
889
0
  new_attr = bgp_attr_intern(&attr);
890
891
0
  aspath_unintern(&attr.aspath); /* Unintern original. */
892
893
  /*
894
   * At this point:
895
   *
896
   * attr: static
897
   *  extra: dynamically allocated, owned by attr
898
   *      vnc_subtlvs: dynamic chain, length 1
899
   *      ecommunity: POINTS TO INTERNED ecom, THIS REF NOT COUNTED
900
   *
901
   * new_attr: an attr that is part of the hash table, distinct
902
   *           from attr which is static.
903
   *  extra: dynamically allocated, owned by new_attr (in hash table)
904
   *      vnc_subtlvs: POINTS TO SAME dynamic chain AS attr
905
   *      ecommunity: POINTS TO interned/refcounted dynamic 2-part AS attr
906
   *  aspath: POINTS TO interned/refcounted hashed block
907
   */
908
0
  for (bpi = bgp_dest_get_bgp_path_info(bn); bpi; bpi = bpi->next) {
909
    /* probably only need to check
910
     * bpi->extra->vnc.export.rfapi_handle */
911
0
    if (bpi->peer == rfd->peer && bpi->type == type
912
0
        && bpi->sub_type == sub_type && bpi->extra
913
0
        && bpi->extra->vnc.export.rfapi_handle == (void *)rfd) {
914
915
0
      break;
916
0
    }
917
0
  }
918
919
0
  if (bpi) {
920
921
    /*
922
     * Adding new local_nexthop, which does not by itself change
923
     * what is advertised via BGP
924
     */
925
0
    if (lnh) {
926
0
      if (!bpi->extra->vnc.export.local_nexthops) {
927
        /* TBD make arrangements to free when needed */
928
0
        bpi->extra->vnc.export.local_nexthops =
929
0
          list_new();
930
0
        bpi->extra->vnc.export.local_nexthops->del =
931
0
          rfapi_nexthop_free;
932
0
      }
933
934
      /*
935
       * already present?
936
       */
937
0
      struct listnode *node;
938
0
      struct rfapi_nexthop *pLnh = NULL;
939
940
0
      for (ALL_LIST_ELEMENTS_RO(
941
0
             bpi->extra->vnc.export.local_nexthops,
942
0
             node, pLnh)) {
943
944
0
        if (prefix_same(&pLnh->addr, &lnh->addr)) {
945
0
          break;
946
0
        }
947
0
      }
948
949
      /*
950
       * Not present, add new one
951
       */
952
0
      if (!pLnh) {
953
0
        pLnh = rfapi_nexthop_new(lnh);
954
0
        listnode_add(
955
0
          bpi->extra->vnc.export.local_nexthops,
956
0
          pLnh);
957
0
      }
958
0
    }
959
960
0
    if (attrhash_cmp(bpi->attr, new_attr)
961
0
        && !CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) {
962
0
      bgp_attr_unintern(&new_attr);
963
0
      bgp_dest_unlock_node(bn);
964
965
0
      vnc_zlog_debug_any(
966
0
        "%s: Found route (safi=%d) at prefix %s, no change",
967
0
        __func__, safi, buf);
968
969
0
      goto done;
970
0
    } else {
971
      /* The attribute is changed. */
972
0
      bgp_path_info_set_flag(bn, bpi, BGP_PATH_ATTR_CHANGED);
973
974
0
      if (safi == SAFI_MPLS_VPN) {
975
0
        struct bgp_dest *pdest = NULL;
976
0
        struct bgp_table *table = NULL;
977
978
0
        pdest = bgp_node_get(bgp->rib[afi][safi],
979
0
                 (struct prefix *)prd);
980
0
        table = bgp_dest_get_bgp_table_info(pdest);
981
0
        if (table)
982
0
          vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
983
0
            bgp, prd, table, p, bpi);
984
0
        bgp_dest_unlock_node(pdest);
985
0
      }
986
987
      /* Rewrite BGP route information. */
988
0
      if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED))
989
0
        bgp_path_info_restore(bn, bpi);
990
0
      else
991
0
        bgp_aggregate_decrement(bgp, p, bpi, afi, safi);
992
0
      bgp_attr_unintern(&bpi->attr);
993
0
      bpi->attr = new_attr;
994
0
      bpi->uptime = monotime(NULL);
995
996
997
0
      if (safi == SAFI_MPLS_VPN) {
998
0
        struct bgp_dest *pdest = NULL;
999
0
        struct bgp_table *table = NULL;
1000
1001
0
        pdest = bgp_node_get(bgp->rib[afi][safi],
1002
0
                 (struct prefix *)prd);
1003
0
        table = bgp_dest_get_bgp_table_info(pdest);
1004
0
        if (table)
1005
0
          vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
1006
0
            bgp, prd, table, p, bpi);
1007
0
        bgp_dest_unlock_node(pdest);
1008
0
      }
1009
1010
      /* Process change. */
1011
0
      bgp_aggregate_increment(bgp, p, bpi, afi, safi);
1012
0
      bgp_process(bgp, bn, afi, safi);
1013
0
      bgp_dest_unlock_node(bn);
1014
1015
0
      vnc_zlog_debug_any(
1016
0
        "%s: Found route (safi=%d) at prefix %s, changed attr",
1017
0
        __func__, safi, buf);
1018
1019
0
      goto done;
1020
0
    }
1021
0
  }
1022
1023
0
  new = info_make(type, sub_type, 0, rfd->peer, new_attr, NULL);
1024
0
  SET_FLAG(new->flags, BGP_PATH_VALID);
1025
1026
  /* save backref to rfapi handle */
1027
0
  bgp_path_info_extra_get(new);
1028
0
  new->extra->vnc.export.rfapi_handle = (void *)rfd;
1029
0
  encode_label(label_val, &new->extra->label[0]);
1030
1031
  /* debug */
1032
1033
0
  if (VNC_DEBUG(VERBOSE)) {
1034
0
    vnc_zlog_debug_verbose("%s: printing BPI", __func__);
1035
0
    rfapiPrintBi(NULL, new);
1036
0
  }
1037
1038
0
  bgp_aggregate_increment(bgp, p, new, afi, safi);
1039
0
  bgp_path_info_add(bn, new);
1040
1041
0
  if (safi == SAFI_MPLS_VPN) {
1042
0
    struct bgp_dest *pdest = NULL;
1043
0
    struct bgp_table *table = NULL;
1044
1045
0
    pdest = bgp_node_get(bgp->rib[afi][safi], (struct prefix *)prd);
1046
0
    table = bgp_dest_get_bgp_table_info(pdest);
1047
0
    if (table)
1048
0
      vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
1049
0
        bgp, prd, table, p, new);
1050
0
    bgp_dest_unlock_node(pdest);
1051
0
    encode_label(label_val, &bn->local_label);
1052
0
  }
1053
1054
0
  bgp_dest_unlock_node(bn);
1055
0
  bgp_process(bgp, bn, afi, safi);
1056
1057
0
  vnc_zlog_debug_any(
1058
0
    "%s: Added route (safi=%s) at prefix %s (bn=%p, prd=%pRDP)",
1059
0
    __func__, safi2str(safi), buf, bn, prd);
1060
1061
0
done:
1062
  /* Loop back to import tables */
1063
0
  rfapiProcessUpdate(rfd->peer, rfd, p, prd, new_attr, afi, safi, type,
1064
0
         sub_type, &label_val);
1065
0
  vnc_zlog_debug_verbose("%s: looped back import route (safi=%d)",
1066
0
             __func__, safi);
1067
0
}
1068
1069
uint32_t rfp_cost_to_localpref(uint8_t cost)
1070
0
{
1071
0
  return 255 - cost;
1072
0
}
1073
1074
static void rfapiTunnelRouteAnnounce(struct bgp *bgp,
1075
             struct rfapi_descriptor *rfd,
1076
             uint32_t *pLifetime)
1077
0
{
1078
0
  struct prefix_rd prd;
1079
0
  struct prefix pfx_vn;
1080
0
  int rc;
1081
0
  uint32_t local_pref = rfp_cost_to_localpref(0);
1082
1083
0
  rc = rfapiRaddr2Qprefix(&(rfd->vn_addr), &pfx_vn);
1084
0
  assert(!rc);
1085
1086
  /*
1087
   * Construct route distinguisher = 0
1088
   */
1089
0
  memset(&prd, 0, sizeof(prd));
1090
0
  prd.family = AF_UNSPEC;
1091
0
  prd.prefixlen = 64;
1092
1093
0
  add_vnc_route(rfd,  /* rfapi descr, for export list  & backref */
1094
0
          bgp,  /* which bgp instance */
1095
0
          SAFI_ENCAP, /* which SAFI */
1096
0
          &pfx_vn,    /* prefix to advertise */
1097
0
          &prd,       /* route distinguisher to use */
1098
0
          &rfd->un_addr, /* nexthop */
1099
0
          &local_pref,
1100
0
          pLifetime, /* max lifetime of child VPN routes */
1101
0
          NULL,      /* no rfp options  for ENCAP safi */
1102
0
          NULL,      /* rfp un options */
1103
0
          NULL,      /* rfp vn options */
1104
0
          rfd->rt_export_list, NULL, /* med */
1105
0
          NULL,      /* label: default */
1106
0
          ZEBRA_ROUTE_BGP, BGP_ROUTE_RFP, 0);
1107
0
}
1108
1109
1110
/***********************************************************************
1111
 *      RFP processing behavior configuration
1112
 ***********************************************************************/
1113
1114
/*------------------------------------------
1115
 * rfapi_rfp_set_configuration
1116
 *
1117
 * This is used to change rfapi's processing behavior based on
1118
 * RFP requirements.
1119
 *
1120
 * input:
1121
 *    rfp_start_val     value returned by rfp_start
1122
 *    rfapi_rfp_cfg     Pointer to configuration structure
1123
 *
1124
 * output:
1125
 *    none
1126
 *
1127
 * return value:
1128
 *  0   Success
1129
 *  ENXIO   Unabled to locate configured BGP/VNC
1130
--------------------------------------------*/
1131
int rfapi_rfp_set_configuration(void *rfp_start_val, struct rfapi_rfp_cfg *new)
1132
0
{
1133
0
  struct rfapi_rfp_cfg *rcfg;
1134
0
  struct bgp *bgp;
1135
1136
0
  bgp = rfapi_bgp_lookup_by_rfp(rfp_start_val);
1137
1138
0
  if (!new || !bgp || !bgp->rfapi_cfg)
1139
0
    return ENXIO;
1140
1141
0
  rcfg = &bgp->rfapi_cfg->rfp_cfg;
1142
0
  rcfg->download_type = new->download_type;
1143
0
  rcfg->ftd_advertisement_interval = new->ftd_advertisement_interval;
1144
0
  rcfg->holddown_factor = new->holddown_factor;
1145
1146
0
  if (rcfg->use_updated_response != new->use_updated_response) {
1147
0
    rcfg->use_updated_response = new->use_updated_response;
1148
0
    if (rcfg->use_updated_response)
1149
0
      rfapiMonitorCallbacksOn(bgp);
1150
0
    else
1151
0
      rfapiMonitorCallbacksOff(bgp);
1152
0
  }
1153
0
  if (rcfg->use_removes != new->use_removes) {
1154
0
    rcfg->use_removes = new->use_removes;
1155
0
    if (rcfg->use_removes)
1156
0
      rfapiMonitorResponseRemovalOn(bgp);
1157
0
    else
1158
0
      rfapiMonitorResponseRemovalOff(bgp);
1159
0
  }
1160
0
  return 0;
1161
0
}
1162
1163
/*------------------------------------------
1164
 * rfapi_rfp_set_cb_methods
1165
 *
1166
 * Change registered callback functions for asynchronous notifications
1167
 * from RFAPI to the RFP client.
1168
 *
1169
 * input:
1170
 *    rfp_start_val     value returned by rfp_start
1171
 *    methods   Pointer to struct rfapi_rfp_cb_methods containing
1172
 *      pointers to callback methods as described above
1173
 *
1174
 * return value:
1175
 *  0   Success
1176
 *  ENXIO   BGP or VNC not configured
1177
 *------------------------------------------*/
1178
int rfapi_rfp_set_cb_methods(void *rfp_start_val,
1179
           struct rfapi_rfp_cb_methods *methods)
1180
0
{
1181
0
  struct rfapi *h;
1182
0
  struct bgp *bgp;
1183
1184
0
  bgp = rfapi_bgp_lookup_by_rfp(rfp_start_val);
1185
0
  if (!bgp)
1186
0
    return ENXIO;
1187
1188
0
  h = bgp->rfapi;
1189
0
  if (!h)
1190
0
    return ENXIO;
1191
1192
0
  h->rfp_methods = *methods;
1193
1194
0
  return 0;
1195
0
}
1196
1197
/***********************************************************************
1198
 *      NVE Sessions
1199
 ***********************************************************************/
1200
/*
1201
 * Caller must supply an already-allocated rfd with the "caller"
1202
 * fields already set (vn_addr, un_addr, callback, cookie)
1203
 * The advertised_prefixes[] array elements should be NULL to
1204
 * have this function set them to newly-allocated radix trees.
1205
 */
1206
static int rfapi_open_inner(struct rfapi_descriptor *rfd, struct bgp *bgp,
1207
          struct rfapi *h, struct rfapi_nve_group_cfg *rfg)
1208
0
{
1209
0
  int ret;
1210
1211
0
  if (h->flags & RFAPI_INCALLBACK)
1212
0
    return EDEADLK;
1213
1214
  /*
1215
   * Fill in configured fields
1216
   */
1217
1218
  /*
1219
   * If group's RD is specified as "auto", then fill in based
1220
   * on NVE's VN address
1221
   */
1222
0
  rfd->rd = rfg->rd;
1223
1224
0
  if (rfd->rd.family == AF_UNIX) {
1225
0
    ret = rfapi_set_autord_from_vn(&rfd->rd, &rfd->vn_addr);
1226
0
    if (ret != 0)
1227
0
      return ret;
1228
0
  }
1229
0
  rfd->rt_export_list = (rfg->rt_export_list)
1230
0
              ? ecommunity_dup(rfg->rt_export_list)
1231
0
              : NULL;
1232
0
  rfd->response_lifetime = rfg->response_lifetime;
1233
0
  rfd->rfg = rfg;
1234
1235
  /*
1236
   * Fill in BGP peer structure
1237
   */
1238
0
  rfd->peer = peer_new(bgp);
1239
0
  rfd->peer->status = Established; /* keep bgp core happy */
1240
1241
  /*
1242
   * since this peer is not on the I/O thread, this lock is not strictly
1243
   * necessary, but serves as a reminder to those who may meddle...
1244
   */
1245
0
  frr_with_mutex (&rfd->peer->io_mtx) {
1246
    // we don't need any I/O related facilities
1247
0
    if (rfd->peer->ibuf)
1248
0
      stream_fifo_free(rfd->peer->ibuf);
1249
0
    if (rfd->peer->obuf)
1250
0
      stream_fifo_free(rfd->peer->obuf);
1251
1252
0
    if (rfd->peer->ibuf_work)
1253
0
      ringbuf_del(rfd->peer->ibuf_work);
1254
1255
0
    rfd->peer->ibuf = NULL;
1256
0
    rfd->peer->obuf = NULL;
1257
0
    rfd->peer->ibuf_work = NULL;
1258
0
  }
1259
1260
0
  { /* base code assumes have valid host pointer */
1261
0
    char buf[INET6_ADDRSTRLEN];
1262
0
    buf[0] = 0;
1263
1264
0
    if (rfd->vn_addr.addr_family == AF_INET) {
1265
0
      inet_ntop(AF_INET, &rfd->vn_addr.addr.v4, buf,
1266
0
          sizeof(buf));
1267
0
    } else if (rfd->vn_addr.addr_family == AF_INET6) {
1268
0
      inet_ntop(AF_INET6, &rfd->vn_addr.addr.v6, buf,
1269
0
          sizeof(buf));
1270
0
    }
1271
0
    rfd->peer->host = XSTRDUP(MTYPE_BGP_PEER_HOST, buf);
1272
0
  }
1273
  /* Mark peer as belonging to HD */
1274
0
  SET_FLAG(rfd->peer->flags, PEER_FLAG_IS_RFAPI_HD);
1275
1276
  /*
1277
   * Set min prefix lifetime to max value so it will get set
1278
   * upon first rfapi_register()
1279
   */
1280
0
  rfd->min_prefix_lifetime = UINT32_MAX;
1281
1282
/*
1283
 * Allocate response tables if needed
1284
 */
1285
0
#define RFD_RTINIT_AFI(rh, ary, afi)                                           \
1286
0
  do {                                                                   \
1287
0
    if (!ary[afi]) {                                               \
1288
0
      ary[afi] = agg_table_init();                           \
1289
0
      agg_set_table_info(ary[afi], rh);                      \
1290
0
    }                                                              \
1291
0
  } while (0)
1292
1293
0
#define RFD_RTINIT(rh, ary)                                                    \
1294
0
  do {                                                                   \
1295
0
    RFD_RTINIT_AFI(rh, ary, AFI_IP);                               \
1296
0
    RFD_RTINIT_AFI(rh, ary, AFI_IP6);                              \
1297
0
    RFD_RTINIT_AFI(rh, ary, AFI_L2VPN);                            \
1298
0
  } while (0)
1299
1300
0
  RFD_RTINIT(rfd, rfd->rib);
1301
0
  RFD_RTINIT(rfd, rfd->rib_pending);
1302
0
  RFD_RTINIT(rfd, rfd->rsp_times);
1303
1304
  /*
1305
   * Link to Import Table
1306
   */
1307
0
  rfd->import_table = rfg->rfapi_import_table;
1308
0
  rfd->import_table->refcount += 1;
1309
1310
0
  rfapiApInit(&rfd->advertised);
1311
1312
  /*
1313
   * add this NVE descriptor to the list of NVEs in the NVE group
1314
   */
1315
0
  if (!rfg->nves) {
1316
0
    rfg->nves = list_new();
1317
0
  }
1318
0
  listnode_add(rfg->nves, rfd);
1319
1320
0
  vnc_direct_bgp_add_nve(bgp, rfd);
1321
0
  vnc_zebra_add_nve(bgp, rfd);
1322
1323
0
  return 0;
1324
0
}
1325
1326
/* moved from rfapi_register */
1327
int rfapi_init_and_open(struct bgp *bgp, struct rfapi_descriptor *rfd,
1328
      struct rfapi_nve_group_cfg *rfg)
1329
0
{
1330
0
  struct rfapi *h = bgp->rfapi;
1331
0
  char buf_vn[BUFSIZ];
1332
0
  char buf_un[BUFSIZ];
1333
0
  afi_t afi_vn, afi_un;
1334
0
  struct prefix pfx_un;
1335
0
  struct agg_node *rn;
1336
1337
0
  rfd->open_time = monotime(NULL);
1338
1339
0
  if (rfg->type == RFAPI_GROUP_CFG_VRF)
1340
0
    SET_FLAG(rfd->flags, RFAPI_HD_FLAG_IS_VRF);
1341
1342
0
  rfapiRfapiIpAddr2Str(&rfd->vn_addr, buf_vn, BUFSIZ);
1343
0
  rfapiRfapiIpAddr2Str(&rfd->un_addr, buf_un, BUFSIZ);
1344
1345
0
  vnc_zlog_debug_verbose("%s: new RFD with VN=%s UN=%s cookie=%p",
1346
0
             __func__, buf_vn, buf_un, rfd->cookie);
1347
1348
0
  if (rfg->type != RFAPI_GROUP_CFG_VRF) /* unclear if needed for VRF */
1349
0
  {
1350
0
    listnode_add(&h->descriptors, rfd);
1351
0
    if (h->descriptors.count > h->stat.max_descriptors) {
1352
0
      h->stat.max_descriptors = h->descriptors.count;
1353
0
    }
1354
1355
    /*
1356
     * attach to UN radix tree
1357
     */
1358
0
    afi_vn = family2afi(rfd->vn_addr.addr_family);
1359
0
    afi_un = family2afi(rfd->un_addr.addr_family);
1360
0
    assert(afi_vn && afi_un);
1361
0
    assert(!rfapiRaddr2Qprefix(&rfd->un_addr, &pfx_un));
1362
1363
0
    rn = agg_node_get(h->un[afi_un], &pfx_un);
1364
0
    assert(rn);
1365
0
    rfd->next = rn->info;
1366
0
    rn->info = rfd;
1367
0
    rfd->un_node = rn;
1368
0
  }
1369
0
  return rfapi_open_inner(rfd, bgp, h, rfg);
1370
0
}
1371
1372
struct rfapi_vn_option *rfapiVnOptionsDup(struct rfapi_vn_option *orig)
1373
0
{
1374
0
  struct rfapi_vn_option *head = NULL;
1375
0
  struct rfapi_vn_option *tail = NULL;
1376
0
  struct rfapi_vn_option *vo = NULL;
1377
1378
0
  for (vo = orig; vo; vo = vo->next) {
1379
0
    struct rfapi_vn_option *new;
1380
1381
0
    new = XCALLOC(MTYPE_RFAPI_VN_OPTION,
1382
0
            sizeof(struct rfapi_vn_option));
1383
0
    memcpy(new, vo, sizeof(struct rfapi_vn_option));
1384
0
    new->next = NULL;
1385
1386
0
    if (tail) {
1387
0
      tail->next = new;
1388
0
    } else {
1389
0
      head = tail = new;
1390
0
    }
1391
0
  }
1392
0
  return head;
1393
0
}
1394
1395
struct rfapi_un_option *rfapiUnOptionsDup(struct rfapi_un_option *orig)
1396
0
{
1397
0
  struct rfapi_un_option *head = NULL;
1398
0
  struct rfapi_un_option *tail = NULL;
1399
0
  struct rfapi_un_option *uo = NULL;
1400
1401
0
  for (uo = orig; uo; uo = uo->next) {
1402
0
    struct rfapi_un_option *new;
1403
1404
0
    new = XCALLOC(MTYPE_RFAPI_UN_OPTION,
1405
0
            sizeof(struct rfapi_un_option));
1406
0
    memcpy(new, uo, sizeof(struct rfapi_un_option));
1407
0
    new->next = NULL;
1408
1409
0
    if (tail) {
1410
0
      tail->next = new;
1411
0
    } else {
1412
0
      head = tail = new;
1413
0
    }
1414
0
  }
1415
0
  return head;
1416
0
}
1417
1418
struct bgp_tea_options *rfapiOptionsDup(struct bgp_tea_options *orig)
1419
0
{
1420
0
  struct bgp_tea_options *head = NULL;
1421
0
  struct bgp_tea_options *tail = NULL;
1422
0
  struct bgp_tea_options *hop = NULL;
1423
1424
0
  for (hop = orig; hop; hop = hop->next) {
1425
0
    struct bgp_tea_options *new;
1426
1427
0
    new = XCALLOC(MTYPE_BGP_TEA_OPTIONS,
1428
0
            sizeof(struct bgp_tea_options));
1429
0
    memcpy(new, hop, sizeof(struct bgp_tea_options));
1430
0
    new->next = NULL;
1431
0
    if (hop->value) {
1432
0
      new->value = XCALLOC(MTYPE_BGP_TEA_OPTIONS_VALUE,
1433
0
               hop->length);
1434
0
      memcpy(new->value, hop->value, hop->length);
1435
0
    }
1436
0
    if (tail) {
1437
0
      tail->next = new;
1438
0
    } else {
1439
0
      head = tail = new;
1440
0
    }
1441
0
  }
1442
0
  return head;
1443
0
}
1444
1445
void rfapiFreeBgpTeaOptionChain(struct bgp_tea_options *p)
1446
0
{
1447
0
  struct bgp_tea_options *next;
1448
1449
0
  while (p) {
1450
0
    next = p->next;
1451
1452
0
    XFREE(MTYPE_BGP_TEA_OPTIONS_VALUE, p->value);
1453
0
    XFREE(MTYPE_BGP_TEA_OPTIONS, p);
1454
1455
0
    p = next;
1456
0
  }
1457
0
}
1458
1459
void rfapiAdbFree(struct rfapi_adb *adb)
1460
0
{
1461
0
  XFREE(MTYPE_RFAPI_ADB, adb);
1462
0
}
1463
1464
static int
1465
rfapi_query_inner(void *handle, struct rfapi_ip_addr *target,
1466
      struct rfapi_l2address_option *l2o, /* may be NULL */
1467
      struct rfapi_next_hop_entry **ppNextHopEntry)
1468
0
{
1469
0
  afi_t afi;
1470
0
  struct prefix p;
1471
0
  struct prefix p_original;
1472
0
  struct agg_node *rn;
1473
0
  struct rfapi_descriptor *rfd = (struct rfapi_descriptor *)handle;
1474
0
  struct bgp *bgp = rfd->bgp;
1475
0
  struct rfapi_next_hop_entry *pNHE = NULL;
1476
0
  struct rfapi_ip_addr *self_vn_addr = NULL;
1477
0
  int eth_is_0 = 0;
1478
0
  int use_eth_resolution = 0;
1479
0
  struct rfapi_next_hop_entry *i_nhe;
1480
1481
  /* preemptive */
1482
0
  if (!bgp) {
1483
0
    vnc_zlog_debug_verbose("%s: No BGP instance, returning ENXIO",
1484
0
               __func__);
1485
0
    return ENXIO;
1486
0
  }
1487
0
  if (!bgp->rfapi) {
1488
0
    vnc_zlog_debug_verbose("%s: No RFAPI instance, returning ENXIO",
1489
0
               __func__);
1490
0
    return ENXIO;
1491
0
  }
1492
0
  if (bgp->rfapi->flags & RFAPI_INCALLBACK) {
1493
0
    vnc_zlog_debug_verbose(
1494
0
      "%s: Called during calback, returning EDEADLK",
1495
0
      __func__);
1496
0
    return EDEADLK;
1497
0
  }
1498
1499
0
  if (!is_valid_rfd(rfd)) {
1500
0
    vnc_zlog_debug_verbose("%s: invalid handle, returning EBADF",
1501
0
               __func__);
1502
0
    return EBADF;
1503
0
  }
1504
1505
0
  rfd->rsp_counter++;     /* dedup: identify this generation */
1506
0
  rfd->rsp_time = monotime(NULL);    /* response content dedup */
1507
0
  rfd->ftd_last_allowed_time =
1508
0
    monotime(NULL) -
1509
0
    bgp->rfapi_cfg->rfp_cfg.ftd_advertisement_interval;
1510
1511
0
  if (l2o) {
1512
0
    if (!memcmp(l2o->macaddr.octet, rfapi_ethaddr0.octet,
1513
0
          ETH_ALEN)) {
1514
0
      eth_is_0 = 1;
1515
0
    }
1516
    /* per t/c Paul/Lou 151022 */
1517
0
    if (!eth_is_0 || l2o->logical_net_id) {
1518
0
      use_eth_resolution = 1;
1519
0
    }
1520
0
  }
1521
1522
0
  if (ppNextHopEntry)
1523
0
    *ppNextHopEntry = NULL;
1524
1525
  /*
1526
   * Save original target in prefix form. In case of L2-based queries,
1527
   * p_original will be modified to reflect the L2 target
1528
   */
1529
0
  assert(!rfapiRaddr2Qprefix(target, &p_original));
1530
1531
0
  if (bgp->rfapi_cfg->rfp_cfg.download_type == RFAPI_RFP_DOWNLOAD_FULL) {
1532
    /* convert query to 0/0 when full-table download is enabled */
1533
0
    memset((char *)&p, 0, sizeof(p));
1534
0
    p.family = target->addr_family;
1535
0
  } else {
1536
0
    p = p_original;
1537
0
  }
1538
1539
0
  {
1540
0
    char *s;
1541
1542
0
    vnc_zlog_debug_verbose("%s(rfd=%p, target=%pFX, ppNextHop=%p)",
1543
0
               __func__, rfd, &p, ppNextHopEntry);
1544
1545
0
    s = ecommunity_ecom2str(rfd->import_table->rt_import_list,
1546
0
          ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
1547
0
    vnc_zlog_debug_verbose(
1548
0
      "%s rfd->import_table=%p, rfd->import_table->rt_import_list: %s",
1549
0
      __func__, rfd->import_table, s);
1550
0
    XFREE(MTYPE_ECOMMUNITY_STR, s);
1551
0
  }
1552
1553
0
  afi = family2afi(p.family);
1554
0
  assert(afi);
1555
1556
0
  if (CHECK_FLAG(bgp->rfapi_cfg->flags,
1557
0
           BGP_VNC_CONFIG_FILTER_SELF_FROM_RSP)) {
1558
0
    self_vn_addr = &rfd->vn_addr;
1559
0
  }
1560
1561
0
  if (use_eth_resolution) {
1562
0
    uint32_t logical_net_id = l2o->logical_net_id;
1563
0
    struct ecommunity *l2com;
1564
1565
    /*
1566
     * fix up p_original to contain L2 address
1567
     */
1568
0
    rfapiL2o2Qprefix(l2o, &p_original);
1569
1570
0
    l2com = bgp_rfapi_get_ecommunity_by_lni_label(
1571
0
      bgp, 1, logical_net_id, l2o->label);
1572
0
    if (l2com) {
1573
0
      uint8_t *v = l2com->val;
1574
0
      logical_net_id = (v[5] << 16) + (v[6] << 8) + (v[7]);
1575
0
    }
1576
    /*
1577
     * Ethernet/L2-based lookup
1578
     *
1579
     * Always returns IT node corresponding to route
1580
     */
1581
1582
0
    if (RFAPI_RFP_DOWNLOAD_FULL
1583
0
        == bgp->rfapi_cfg->rfp_cfg.download_type) {
1584
0
      eth_is_0 = 1;
1585
0
    }
1586
1587
0
    rn = rfapiMonitorEthAdd(
1588
0
      bgp, rfd, (eth_is_0 ? &rfapi_ethaddr0 : &l2o->macaddr),
1589
0
      logical_net_id);
1590
1591
0
    if (eth_is_0) {
1592
0
      struct rfapi_ip_prefix rprefix;
1593
1594
0
      memset(&rprefix, 0, sizeof(rprefix));
1595
0
      rprefix.prefix.addr_family = target->addr_family;
1596
0
      if (target->addr_family == AF_INET) {
1597
0
        rprefix.length = IPV4_MAX_BITLEN;
1598
0
      } else {
1599
0
        rprefix.length = IPV6_MAX_BITLEN;
1600
0
      }
1601
1602
0
      pNHE = rfapiEthRouteTable2NextHopList(
1603
0
        logical_net_id, &rprefix,
1604
0
        rfd->response_lifetime, self_vn_addr,
1605
0
        rfd->rib[afi], &p_original);
1606
0
      goto done;
1607
0
    }
1608
1609
0
  } else {
1610
1611
    /*
1612
     * IP-based lookup
1613
     */
1614
1615
0
    rn = rfapiMonitorAdd(bgp, rfd, &p);
1616
1617
    /*
1618
     * If target address is 0, this request is special: means to
1619
     * return ALL routes in the table
1620
     *
1621
     * Monitors for All-Routes queries get put on a special list,
1622
     * not in the VPN tree
1623
     */
1624
0
    if (RFAPI_0_PREFIX(&p)) {
1625
1626
0
      vnc_zlog_debug_verbose("%s: 0-prefix", __func__);
1627
1628
      /*
1629
       * Generate nexthop list for caller
1630
       */
1631
0
      pNHE = rfapiRouteTable2NextHopList(
1632
0
        rfd->import_table->imported_vpn[afi],
1633
0
        rfd->response_lifetime, self_vn_addr,
1634
0
        rfd->rib[afi], &p_original);
1635
0
      goto done;
1636
0
    }
1637
1638
0
    if (rn) {
1639
0
      agg_lock_node(rn); /* so we can unlock below */
1640
0
    } else {
1641
      /*
1642
       * returns locked node. Don't unlock yet because the
1643
       * unlock
1644
       * might free it before we're done with it. This
1645
       * situation
1646
       * could occur when rfapiMonitorGetAttachNode() returns
1647
       * a
1648
       * newly-created default node.
1649
       */
1650
0
      rn = rfapiMonitorGetAttachNode(rfd, &p);
1651
0
    }
1652
0
  }
1653
1654
0
  assert(rn);
1655
0
  if (!rn->info) {
1656
0
    agg_unlock_node(rn);
1657
0
    vnc_zlog_debug_verbose(
1658
0
      "%s: VPN route not found, returning ENOENT", __func__);
1659
0
    return ENOENT;
1660
0
  }
1661
1662
0
  if (VNC_DEBUG(RFAPI_QUERY)) {
1663
0
    rfapiShowImportTable(NULL, "query",
1664
0
             rfd->import_table->imported_vpn[afi], 1);
1665
0
  }
1666
1667
0
  if (use_eth_resolution) {
1668
1669
0
    struct rfapi_ip_prefix rprefix;
1670
1671
0
    memset(&rprefix, 0, sizeof(rprefix));
1672
0
    rprefix.prefix.addr_family = target->addr_family;
1673
0
    if (target->addr_family == AF_INET) {
1674
0
      rprefix.length = IPV4_MAX_BITLEN;
1675
0
    } else {
1676
0
      rprefix.length = IPV6_MAX_BITLEN;
1677
0
    }
1678
1679
0
    pNHE = rfapiEthRouteNode2NextHopList(
1680
0
      rn, &rprefix, rfd->response_lifetime, self_vn_addr,
1681
0
      rfd->rib[afi], &p_original);
1682
1683
1684
0
  } else {
1685
    /*
1686
     * Generate answer to query
1687
     */
1688
0
    pNHE = rfapiRouteNode2NextHopList(rn, rfd->response_lifetime,
1689
0
              self_vn_addr, rfd->rib[afi],
1690
0
              &p_original);
1691
0
  }
1692
1693
0
  agg_unlock_node(rn);
1694
1695
0
done:
1696
0
  if (ppNextHopEntry) {
1697
    /* only count if caller gets it */
1698
0
    ++bgp->rfapi->response_immediate_count;
1699
0
  }
1700
1701
0
  if (!pNHE) {
1702
0
    vnc_zlog_debug_verbose("%s: NO NHEs, returning ENOENT",
1703
0
               __func__);
1704
0
    return ENOENT;
1705
0
  }
1706
1707
  /*
1708
   * count nexthops for statistics
1709
   */
1710
0
  for (i_nhe = pNHE; i_nhe; i_nhe = i_nhe->next) {
1711
0
    ++rfd->stat_count_nh_reachable;
1712
0
  }
1713
1714
0
  if (ppNextHopEntry) {
1715
0
    *ppNextHopEntry = pNHE;
1716
0
  } else {
1717
0
    rfapi_free_next_hop_list(pNHE);
1718
0
  }
1719
1720
0
  vnc_zlog_debug_verbose("%s: success", __func__);
1721
0
  return 0;
1722
0
}
1723
1724
/*
1725
 * support on-the-fly reassignment of an already-open nve to a new
1726
 * nve-group in the event that its original nve-group is
1727
 * administratively deleted.
1728
 */
1729
static int rfapi_open_rfd(struct rfapi_descriptor *rfd, struct bgp *bgp)
1730
0
{
1731
0
  struct prefix pfx_vn;
1732
0
  struct prefix pfx_un;
1733
0
  struct rfapi_nve_group_cfg *rfg;
1734
0
  struct rfapi *h;
1735
0
  struct rfapi_cfg *hc;
1736
0
  int rc;
1737
1738
0
  h = bgp->rfapi;
1739
0
  if (!h)
1740
0
    return ENXIO;
1741
1742
0
  hc = bgp->rfapi_cfg;
1743
0
  if (!hc)
1744
0
    return ENXIO;
1745
1746
0
  rc = rfapiRaddr2Qprefix(&rfd->vn_addr, &pfx_vn);
1747
0
  assert(!rc);
1748
1749
0
  rc = rfapiRaddr2Qprefix(&rfd->un_addr, &pfx_un);
1750
0
  assert(!rc);
1751
1752
  /*
1753
   * Find the matching nve group config block
1754
   */
1755
0
  rfg = bgp_rfapi_cfg_match_group(hc, &pfx_vn, &pfx_un);
1756
0
  if (!rfg) {
1757
0
    return ENOENT;
1758
0
  }
1759
1760
  /*
1761
   * check nve group config block for required values
1762
   */
1763
0
  if (!rfg->rt_export_list || !rfg->rfapi_import_table) {
1764
1765
0
    return ENOMSG;
1766
0
  }
1767
1768
0
  rc = rfapi_open_inner(rfd, bgp, h, rfg);
1769
0
  if (rc) {
1770
0
    return rc;
1771
0
  }
1772
1773
  /*
1774
   * re-advertise registered routes, this time as part of new NVE-group
1775
   */
1776
0
  rfapiApReadvertiseAll(bgp, rfd);
1777
1778
  /*
1779
   * re-attach callbacks to import table
1780
   */
1781
0
  if (!(bgp->rfapi_cfg->flags & BGP_VNC_CONFIG_CALLBACK_DISABLE)) {
1782
0
    rfapiMonitorAttachImportHd(rfd);
1783
0
  }
1784
1785
0
  return 0;
1786
0
}
1787
1788
/*------------------------------------------
1789
 * rfapi_open
1790
 *
1791
 * This function initializes a NVE record and associates it with
1792
 * the specified VN and underlay network addresses
1793
 *
1794
 * input:
1795
 *      rfp_start_val   value returned by rfp_start
1796
 *  vn    NVE virtual network address
1797
 *
1798
 *  un    NVE underlay network address
1799
 *
1800
 *  default_options Default options to use on registrations.
1801
 *      For now only tunnel type is supported.
1802
 *      May be overridden per-prefix in rfapi_register().
1803
 *      Caller owns (rfapi_open() does not free)
1804
 *
1805
 *  response_cb Pointer to next hop list update callback function or
1806
 *      NULL when no callbacks are desired.
1807
 *
1808
 *  userdata  Passed to subsequent response_cb invocations.
1809
 *
1810
 * output:
1811
 *  response_lifetime The length of time that responses sent to this
1812
 *      NVE are valid.
1813
 *
1814
 *  pHandle   pointer to location to store rfapi handle. The
1815
 *      handle must be passed on subsequent rfapi_ calls.
1816
 *
1817
 *
1818
 * return value:
1819
 *  0   Success
1820
 *  EEXIST    NVE with this {vn,un} already open
1821
 *  ENOENT    No matching nve group config
1822
 *  ENOMSG    Matched nve group config was incomplete
1823
 *  ENXIO   BGP or VNC not configured
1824
 *  EAFNOSUPPORT  Matched nve group specifies auto-assignment of RD,
1825
 *      but underlay network address is not IPv4
1826
 *  EDEADLK   Called from within a callback procedure
1827
 *------------------------------------------*/
1828
int rfapi_open(void *rfp_start_val, struct rfapi_ip_addr *vn,
1829
         struct rfapi_ip_addr *un,
1830
         struct rfapi_un_option *default_options,
1831
         uint32_t *response_lifetime,
1832
         void *userdata, /* callback cookie */
1833
         rfapi_handle *pHandle)
1834
0
{
1835
0
  struct bgp *bgp;
1836
0
  struct rfapi *h;
1837
0
  struct rfapi_descriptor *rfd;
1838
0
  struct rfapi_cfg *hc;
1839
0
  struct rfapi_nve_group_cfg *rfg;
1840
1841
0
  struct prefix pfx_vn;
1842
0
  struct prefix pfx_un;
1843
1844
0
  int rc;
1845
0
  rfapi_handle hh = NULL;
1846
0
  int reusing_provisional = 0;
1847
1848
0
  {
1849
0
    char buf[2][INET_ADDRSTRLEN];
1850
0
    vnc_zlog_debug_verbose(
1851
0
      "%s: VN=%s UN=%s", __func__,
1852
0
      rfapiRfapiIpAddr2Str(vn, buf[0], INET_ADDRSTRLEN),
1853
0
      rfapiRfapiIpAddr2Str(un, buf[1], INET_ADDRSTRLEN));
1854
0
  }
1855
1856
0
  assert(pHandle);
1857
0
  *pHandle = NULL;
1858
1859
0
  bgp = rfapi_bgp_lookup_by_rfp(rfp_start_val);
1860
0
  if (!bgp)
1861
0
    return ENXIO;
1862
1863
0
  h = bgp->rfapi;
1864
0
  if (!h)
1865
0
    return ENXIO;
1866
1867
0
  hc = bgp->rfapi_cfg;
1868
0
  if (!hc)
1869
0
    return ENXIO;
1870
1871
0
  if (h->flags & RFAPI_INCALLBACK)
1872
0
    return EDEADLK;
1873
1874
0
  rc = rfapiRaddr2Qprefix(vn, &pfx_vn);
1875
0
  assert(!rc);
1876
1877
0
  rc = rfapiRaddr2Qprefix(un, &pfx_un);
1878
0
  assert(!rc);
1879
1880
  /*
1881
   * already have a descriptor with VN and UN?
1882
   */
1883
0
  if (!rfapi_find_handle(bgp, vn, un, &hh)) {
1884
    /*
1885
     * we might have set up a handle for static routes before
1886
     * this NVE was opened. In that case, reuse the handle
1887
     */
1888
0
    rfd = hh;
1889
0
    if (!CHECK_FLAG(rfd->flags, RFAPI_HD_FLAG_PROVISIONAL)) {
1890
0
      return EEXIST;
1891
0
    }
1892
1893
    /*
1894
     * reuse provisional descriptor
1895
     * hh is not NULL
1896
     */
1897
0
    reusing_provisional = 1;
1898
0
  }
1899
1900
  /*
1901
   * Find the matching nve group config block
1902
   */
1903
0
  rfg = bgp_rfapi_cfg_match_group(hc, &pfx_vn, &pfx_un);
1904
0
  if (!rfg) {
1905
0
    ++h->stat.count_unknown_nves;
1906
0
    {
1907
0
      char buf[2][INET_ADDRSTRLEN];
1908
0
      zlog_notice("%s: no matching group VN=%s UN=%s",
1909
0
            __func__,
1910
0
            rfapiRfapiIpAddr2Str(vn, buf[0],
1911
0
               INET_ADDRSTRLEN),
1912
0
            rfapiRfapiIpAddr2Str(un, buf[1],
1913
0
               INET_ADDRSTRLEN));
1914
0
    }
1915
0
    return ENOENT;
1916
0
  }
1917
1918
  /*
1919
   * check nve group config block for required values
1920
   */
1921
0
  if (!rfg->rt_export_list || !rfg->rfapi_import_table) {
1922
1923
0
    ++h->stat.count_unknown_nves;
1924
0
    return ENOMSG;
1925
0
  }
1926
1927
  /*
1928
   * If group config specifies auto-rd assignment, check that
1929
   * VN address is IPv4|v6 so we don't fail in rfapi_open_inner().
1930
   * Check here so we don't need to unwind memory allocations, &c.
1931
   */
1932
0
  if ((rfg->rd.family == AF_UNIX) && (vn->addr_family != AF_INET)
1933
0
      && (vn->addr_family != AF_INET6)) {
1934
0
    return EAFNOSUPPORT;
1935
0
  }
1936
1937
0
  if (hh) {
1938
    /*
1939
     * reusing provisional rfd
1940
     */
1941
0
    rfd = hh;
1942
0
  } else {
1943
0
    rfd = XCALLOC(MTYPE_RFAPI_DESC,
1944
0
            sizeof(struct rfapi_descriptor));
1945
0
  }
1946
1947
0
  rfd->bgp = bgp;
1948
0
  if (default_options) {
1949
0
    struct rfapi_un_option *p;
1950
1951
0
    for (p = default_options; p; p = p->next) {
1952
0
      if ((RFAPI_UN_OPTION_TYPE_PROVISIONAL == p->type)) {
1953
0
        rfd->flags |= RFAPI_HD_FLAG_PROVISIONAL;
1954
0
      }
1955
0
      if ((RFAPI_UN_OPTION_TYPE_TUNNELTYPE == p->type)) {
1956
0
        rfd->default_tunneltype_option = p->v.tunnel;
1957
0
      }
1958
0
    }
1959
0
  }
1960
1961
  /*
1962
   * Fill in caller fields
1963
   */
1964
0
  rfd->vn_addr = *vn;
1965
0
  rfd->un_addr = *un;
1966
0
  rfd->cookie = userdata;
1967
1968
0
  if (!reusing_provisional) {
1969
0
    rc = rfapi_init_and_open(bgp, rfd, rfg);
1970
    /*
1971
     * This can fail only if the VN address is IPv6 and the group
1972
     * specified auto-assignment of RDs, which only works for v4,
1973
     * and the check above should catch it.
1974
     *
1975
     * Another failure possibility is that we were called
1976
     * during an rfapi callback. Also checked above.
1977
     */
1978
0
    assert(!rc);
1979
0
  }
1980
1981
0
  if (response_lifetime)
1982
0
    *response_lifetime = rfd->response_lifetime;
1983
0
  *pHandle = rfd;
1984
0
  return 0;
1985
0
}
1986
1987
/*
1988
 * For use with debug functions
1989
 */
1990
static int rfapi_set_response_cb(struct rfapi_descriptor *rfd,
1991
         rfapi_response_cb_t *response_cb)
1992
0
{
1993
0
  if (!is_valid_rfd(rfd))
1994
0
    return EBADF;
1995
0
  rfd->response_cb = response_cb;
1996
0
  return 0;
1997
0
}
1998
1999
/*
2000
 * rfapi_close_inner
2001
 *
2002
 * Does almost all the work of rfapi_close, except:
2003
 *  1. preserves the descriptor (doesn't free it)
2004
 *  2. preserves the prefix query list (i.e., rfd->mon list)
2005
 *  3. preserves the advertised prefix list (rfd->advertised)
2006
 *  4. preserves the rib and rib_pending tables
2007
 *
2008
 * The purpose of organizing it this way is to support on-the-fly
2009
 * reassignment of an already-open nve to a new nve-group in the
2010
 * event that its original nve-group is administratively deleted.
2011
 */
2012
static int rfapi_close_inner(struct rfapi_descriptor *rfd, struct bgp *bgp)
2013
0
{
2014
0
  int rc;
2015
0
  struct prefix pfx_vn;
2016
0
  struct prefix_rd prd; /* currently always 0 for VN->UN */
2017
2018
0
  if (!is_valid_rfd(rfd))
2019
0
    return EBADF;
2020
2021
0
  rc = rfapiRaddr2Qprefix(&rfd->vn_addr, &pfx_vn);
2022
0
  assert(!rc); /* should never have bad AF in stored vn address */
2023
2024
  /*
2025
   * update exported routes to reflect disappearance of this NVE as
2026
   * nexthop
2027
   */
2028
0
  vnc_direct_bgp_del_nve(bgp, rfd);
2029
0
  vnc_zebra_del_nve(bgp, rfd);
2030
2031
  /*
2032
   * unlink this HD's monitors from import table
2033
   */
2034
0
  rfapiMonitorDetachImportHd(rfd);
2035
2036
  /*
2037
   * Unlink from Import Table
2038
   * NB rfd->import_table will be NULL if we are closing a stale
2039
   * descriptor
2040
   */
2041
0
  if (rfd->import_table)
2042
0
    rfapiImportTableRefDelByIt(bgp, rfd->import_table);
2043
0
  rfd->import_table = NULL;
2044
2045
  /*
2046
   * Construct route distinguisher
2047
   */
2048
0
  memset(&prd, 0, sizeof(prd));
2049
0
  prd = rfd->rd;
2050
0
  prd.family = AF_UNSPEC;
2051
0
  prd.prefixlen = 64;
2052
2053
  /*
2054
   * withdraw tunnel
2055
   */
2056
0
  del_vnc_route(rfd, rfd->peer, bgp, SAFI_ENCAP,
2057
0
          &pfx_vn, /* prefix being advertised */
2058
0
          &prd,    /* route distinguisher to use (0 for ENCAP) */
2059
0
          ZEBRA_ROUTE_BGP, BGP_ROUTE_RFP, NULL, 0); /* no kill */
2060
2061
  /*
2062
   * Construct route distinguisher for VPN routes
2063
   */
2064
0
  prd = rfd->rd;
2065
0
  prd.family = AF_UNSPEC;
2066
0
  prd.prefixlen = 64;
2067
2068
  /*
2069
   * find all VPN routes associated with this rfd and delete them, too
2070
   */
2071
0
  rfapiApWithdrawAll(bgp, rfd);
2072
2073
  /*
2074
   * remove this nve descriptor from the list of nves
2075
   * associated with the nve group
2076
   */
2077
0
  if (rfd->rfg) {
2078
0
    listnode_delete(rfd->rfg->nves, rfd);
2079
0
    rfd->rfg = NULL; /* XXX mark as orphaned/stale */
2080
0
  }
2081
2082
0
  if (rfd->rt_export_list)
2083
0
    ecommunity_free(&rfd->rt_export_list);
2084
0
  rfd->rt_export_list = NULL;
2085
2086
  /*
2087
   * free peer structure (possibly delayed until its
2088
   * refcount reaches zero)
2089
   */
2090
0
  if (rfd->peer) {
2091
0
    vnc_zlog_debug_verbose("%s: calling peer_delete(%p), #%d",
2092
0
               __func__, rfd->peer, rfd->peer->lock);
2093
0
    peer_delete(rfd->peer);
2094
0
  }
2095
0
  rfd->peer = NULL;
2096
2097
0
  return 0;
2098
0
}
2099
2100
int rfapi_close(void *handle)
2101
0
{
2102
0
  struct rfapi_descriptor *rfd = (struct rfapi_descriptor *)handle;
2103
0
  int rc;
2104
0
  struct agg_node *node;
2105
0
  struct bgp *bgp;
2106
0
  struct rfapi *h;
2107
2108
0
  vnc_zlog_debug_verbose("%s: rfd=%p", __func__, rfd);
2109
2110
#ifdef RFAPI_WHO_IS_CALLING_ME
2111
#ifdef HAVE_GLIBC_BACKTRACE
2112
#define RFAPI_DEBUG_BACKTRACE_NENTRIES 5
2113
  {
2114
    void *buf[RFAPI_DEBUG_BACKTRACE_NENTRIES];
2115
    char **syms;
2116
    int i;
2117
    size_t size;
2118
2119
    size = backtrace(buf, RFAPI_DEBUG_BACKTRACE_NENTRIES);
2120
    syms = backtrace_symbols(buf, size);
2121
    for (i = 0; i < size && i < RFAPI_DEBUG_BACKTRACE_NENTRIES;
2122
         ++i) {
2123
      vnc_zlog_debug_verbose("backtrace[%2d]: %s", i,
2124
                 syms[i]);
2125
    }
2126
    free(syms);
2127
  }
2128
#endif
2129
#endif
2130
2131
0
  bgp = rfd->bgp;
2132
0
  if (!bgp)
2133
0
    return ENXIO;
2134
2135
0
  h = bgp->rfapi;
2136
0
  if (!h)
2137
0
    return ENXIO;
2138
2139
0
  if (!is_valid_rfd(rfd))
2140
0
    return EBADF;
2141
2142
0
  if (h->flags & RFAPI_INCALLBACK) {
2143
    /*
2144
     * Queue these close requests for processing after callback
2145
     * is finished
2146
     */
2147
0
    if (!CHECK_FLAG(rfd->flags,
2148
0
        RFAPI_HD_FLAG_CLOSING_ADMINISTRATIVELY)) {
2149
0
      work_queue_add(h->deferred_close_q, handle);
2150
0
      vnc_zlog_debug_verbose(
2151
0
        "%s: added handle %p to deferred close queue",
2152
0
        __func__, handle);
2153
0
    }
2154
0
    return 0;
2155
0
  }
2156
2157
0
  if (CHECK_FLAG(rfd->flags, RFAPI_HD_FLAG_CLOSING_ADMINISTRATIVELY)) {
2158
2159
0
    vnc_zlog_debug_verbose("%s administrative close rfd=%p",
2160
0
               __func__, rfd);
2161
2162
0
    if (h->rfp_methods.close_cb) {
2163
0
      vnc_zlog_debug_verbose(
2164
0
        "%s calling close callback rfd=%p", __func__,
2165
0
        rfd);
2166
2167
      /*
2168
       * call the callback fairly early so that it can still
2169
       * lookup un/vn
2170
       * from handle, etc.
2171
       *
2172
       * NB RFAPI_INCALLBACK is tested above, so if we reach
2173
       * this point
2174
       * we are not already in the context of a callback.
2175
       */
2176
0
      h->flags |= RFAPI_INCALLBACK;
2177
0
      (*h->rfp_methods.close_cb)(handle, EIDRM);
2178
0
      h->flags &= ~RFAPI_INCALLBACK;
2179
0
    }
2180
0
  }
2181
2182
0
  if (rfd->rfg) {
2183
    /*
2184
     * Orphaned descriptors have already done this part, so do
2185
     * only for non-orphaned descriptors.
2186
     */
2187
0
    if ((rc = rfapi_close_inner(rfd, bgp)))
2188
0
      return rc;
2189
0
  }
2190
2191
  /*
2192
   * Remove descriptor from UN index
2193
   * (remove from chain at node)
2194
   */
2195
0
  rc = rfapi_find_node(bgp, &rfd->vn_addr, &rfd->un_addr, &node);
2196
0
  if (!rc) {
2197
0
    struct rfapi_descriptor *hh;
2198
2199
0
    if (node->info == rfd) {
2200
0
      node->info = rfd->next;
2201
0
    } else {
2202
2203
0
      for (hh = node->info; hh; hh = hh->next) {
2204
0
        if (hh->next == rfd) {
2205
0
          hh->next = rfd->next;
2206
0
          break;
2207
0
        }
2208
0
      }
2209
0
    }
2210
0
    agg_unlock_node(node);
2211
0
  }
2212
2213
  /*
2214
   * remove from descriptor list
2215
   */
2216
0
  listnode_delete(&h->descriptors, rfd);
2217
2218
  /*
2219
   * Delete monitor list items and free monitor structures
2220
   */
2221
0
  (void)rfapiMonitorDelHd(rfd);
2222
2223
  /*
2224
   * release advertised prefix data
2225
   */
2226
0
  rfapiApRelease(&rfd->advertised);
2227
2228
  /*
2229
   * Release RFP callback RIB
2230
   */
2231
0
  rfapiRibFree(rfd);
2232
2233
  /*
2234
   * free descriptor
2235
   */
2236
0
  memset(rfd, 0, sizeof(struct rfapi_descriptor));
2237
0
  XFREE(MTYPE_RFAPI_DESC, rfd);
2238
2239
0
  return 0;
2240
0
}
2241
2242
/*
2243
 * Reopen a nve descriptor. If the descriptor's NVE-group
2244
 * does not exist (e.g., if it has been administratively removed),
2245
 * reassignment to a new NVE-group is attempted.
2246
 *
2247
 * If NVE-group reassignment fails, the descriptor becomes "stale"
2248
 * (rfd->rfg == NULL implies "stale:). The only permissible API operation
2249
 * on a stale descriptor is rfapi_close(). Any other rfapi_* API operation
2250
 * on the descriptor will return ESTALE.
2251
 *
2252
 * Reopening a descriptor is a potentially expensive operation, because
2253
 * it involves withdrawing any routes advertised by the NVE, withdrawing
2254
 * the NVE's route queries, and then re-adding them all after a new
2255
 * NVE-group is assigned. There are also possible route-export affects
2256
 * caused by deleting and then adding the NVE: advertised prefixes
2257
 * and nexthop lists for exported routes can turn over.
2258
 */
2259
int rfapi_reopen(struct rfapi_descriptor *rfd, struct bgp *bgp)
2260
0
{
2261
0
  struct rfapi *h;
2262
0
  int rc;
2263
2264
0
  if ((rc = rfapi_close_inner(rfd, bgp))) {
2265
0
    return rc;
2266
0
  }
2267
0
  if ((rc = rfapi_open_rfd(rfd, bgp))) {
2268
2269
0
    h = bgp->rfapi;
2270
2271
0
    assert(h != NULL && !CHECK_FLAG(h->flags, RFAPI_INCALLBACK));
2272
2273
0
    if (CHECK_FLAG(rfd->flags,
2274
0
             RFAPI_HD_FLAG_CLOSING_ADMINISTRATIVELY)
2275
0
        && h && h->rfp_methods.close_cb) {
2276
2277
      /*
2278
       * NB RFAPI_INCALLBACK is tested above, so if we reach
2279
       * this point
2280
       * we are not already in the context of a callback.
2281
       */
2282
0
      h->flags |= RFAPI_INCALLBACK;
2283
0
      (*h->rfp_methods.close_cb)((rfapi_handle)rfd, ESTALE);
2284
0
      h->flags &= ~RFAPI_INCALLBACK;
2285
0
    }
2286
0
    return rc;
2287
0
  }
2288
0
  return 0;
2289
0
}
2290
2291
/***********************************************************************
2292
 *      NVE Routes
2293
 ***********************************************************************/
2294
/*
2295
 * Announce reachability to this prefix via the NVE
2296
 */
2297
int rfapi_register(void *handle, struct rfapi_ip_prefix *prefix,
2298
       uint32_t lifetime, /* host byte order */
2299
       struct rfapi_un_option *options_un,
2300
       struct rfapi_vn_option *options_vn,
2301
       rfapi_register_action action)
2302
0
{
2303
0
  struct rfapi_descriptor *rfd = (struct rfapi_descriptor *)handle;
2304
0
  struct bgp *bgp;
2305
0
  struct prefix p;
2306
0
  struct prefix *pfx_ip = NULL;
2307
0
  struct prefix_rd prd;
2308
0
  afi_t afi;
2309
0
  struct prefix pfx_mac_buf;
2310
0
  struct prefix *pfx_mac = NULL;
2311
0
  struct prefix pfx_vn_buf;
2312
0
  const char *action_str = NULL;
2313
0
  uint32_t *label = NULL;
2314
0
  struct rfapi_vn_option *vo;
2315
0
  struct rfapi_l2address_option *l2o = NULL;
2316
0
  struct prefix_rd *prd_override = NULL;
2317
2318
0
  switch (action) {
2319
0
  case RFAPI_REGISTER_ADD:
2320
0
    action_str = "add";
2321
0
    break;
2322
0
  case RFAPI_REGISTER_WITHDRAW:
2323
0
    action_str = "withdraw";
2324
0
    break;
2325
0
  case RFAPI_REGISTER_KILL:
2326
0
    action_str = "kill";
2327
0
    break;
2328
0
  default:
2329
0
    assert(0);
2330
0
    break;
2331
0
  }
2332
2333
  /*
2334
   * Inspect VN options
2335
   */
2336
0
  for (vo = options_vn; vo; vo = vo->next) {
2337
0
    if (RFAPI_VN_OPTION_TYPE_L2ADDR == vo->type) {
2338
0
      l2o = &vo->v.l2addr;
2339
0
    }
2340
0
    if (RFAPI_VN_OPTION_TYPE_INTERNAL_RD == vo->type) {
2341
0
      prd_override = &vo->v.internal_rd;
2342
0
    }
2343
0
  }
2344
2345
  /*********************************************************************
2346
   *      advertise prefix
2347
   *********************************************************************/
2348
2349
  /*
2350
   * set <p> based on <prefix>
2351
   */
2352
0
  assert(!rfapiRprefix2Qprefix(prefix, &p));
2353
2354
0
  afi = family2afi(prefix->prefix.addr_family);
2355
0
  assert(afi);
2356
2357
0
  vnc_zlog_debug_verbose(
2358
0
    "%s(rfd=%p, pfx=%pFX, lifetime=%d, opts_un=%p, opts_vn=%p, action=%s)",
2359
0
    __func__, rfd, &p, lifetime, options_un, options_vn,
2360
0
    action_str);
2361
2362
  /*
2363
   * These tests come after the prefix conversion so that we can
2364
   * print the prefix in a debug message before failing
2365
   */
2366
2367
0
  bgp = rfd->bgp;
2368
0
  if (!bgp) {
2369
0
    vnc_zlog_debug_verbose("%s: no BGP instance: returning ENXIO",
2370
0
               __func__);
2371
0
    return ENXIO;
2372
0
  }
2373
0
  if (!bgp->rfapi) {
2374
0
    vnc_zlog_debug_verbose("%s: no RFAPI instance: returning ENXIO",
2375
0
               __func__);
2376
0
    return ENXIO;
2377
0
  }
2378
0
  if (!rfd->rfg) {
2379
0
    if (RFAPI_REGISTER_ADD == action) {
2380
0
      ++bgp->rfapi->stat.count_registrations_failed;
2381
0
    }
2382
0
    vnc_zlog_debug_verbose(
2383
0
      "%s: rfd=%p, no RF GRP instance: returning ESTALE",
2384
0
      __func__, rfd);
2385
0
    return ESTALE;
2386
0
  }
2387
2388
0
  if (bgp->rfapi->flags & RFAPI_INCALLBACK) {
2389
0
    if (RFAPI_REGISTER_ADD == action) {
2390
0
      ++bgp->rfapi->stat.count_registrations_failed;
2391
0
    }
2392
0
    vnc_zlog_debug_verbose("%s: in callback: returning EDEADLK",
2393
0
               __func__);
2394
0
    return EDEADLK;
2395
0
  }
2396
2397
0
  if (!is_valid_rfd(rfd)) {
2398
0
    if (RFAPI_REGISTER_ADD == action) {
2399
0
      ++bgp->rfapi->stat.count_registrations_failed;
2400
0
    }
2401
0
    vnc_zlog_debug_verbose("%s: invalid handle: returning EBADF",
2402
0
               __func__);
2403
0
    return EBADF;
2404
0
  }
2405
2406
  /*
2407
   * Is there a MAC address in this registration?
2408
   */
2409
0
  if (l2o && !RFAPI_0_ETHERADDR(&l2o->macaddr)) {
2410
0
    rfapiL2o2Qprefix(l2o, &pfx_mac_buf);
2411
0
    pfx_mac = &pfx_mac_buf;
2412
0
  }
2413
2414
  /*
2415
   * Is there an IP prefix in this registration?
2416
   */
2417
0
  if (!(RFAPI_0_PREFIX(&p) && RFAPI_HOST_PREFIX(&p))) {
2418
0
    pfx_ip = &p;
2419
0
  } else {
2420
0
    if (!pfx_mac) {
2421
0
      vnc_zlog_debug_verbose(
2422
0
        "%s: missing mac addr that is required for host 0 pfx",
2423
0
        __func__);
2424
0
      if (RFAPI_REGISTER_ADD == action) {
2425
0
        ++bgp->rfapi->stat.count_registrations_failed;
2426
0
      }
2427
0
      return EINVAL;
2428
0
    }
2429
0
    if (rfapiRaddr2Qprefix(&rfd->vn_addr, &pfx_vn_buf)) {
2430
0
      vnc_zlog_debug_verbose(
2431
0
        "%s: handle has bad vn_addr: returning EBADF",
2432
0
        __func__);
2433
0
      if (RFAPI_REGISTER_ADD == action) {
2434
0
        ++bgp->rfapi->stat.count_registrations_failed;
2435
0
      }
2436
0
      return EBADF;
2437
0
    }
2438
0
  }
2439
2440
0
  if (RFAPI_REGISTER_ADD == action) {
2441
0
    ++bgp->rfapi->stat.count_registrations;
2442
0
  }
2443
2444
  /*
2445
   * Figure out if this registration is missing an IP address
2446
   *
2447
   * MAC-addr based:
2448
   *
2449
   *  In RFAPI, we use prefixes in family AF_LINK to store
2450
   *  the MAC addresses. These prefixes are used for the
2451
   *  list of advertised prefixes and in the RFAPI import
2452
   *  tables.
2453
   *
2454
   *  In BGP proper, we use the prefix matching the NVE's
2455
   *  VN address with a host prefix-length (i.e., 32 or 128).
2456
   *
2457
   */
2458
0
  if (l2o && l2o->logical_net_id && RFAPI_0_PREFIX(&p)
2459
0
      && RFAPI_HOST_PREFIX(&p)) {
2460
2461
0
    rfapiL2o2Qprefix(l2o, &pfx_mac_buf);
2462
0
    pfx_mac = &pfx_mac_buf;
2463
0
  }
2464
2465
  /*
2466
   * Construct route distinguisher
2467
   */
2468
0
  if (prd_override) {
2469
0
    prd = *prd_override;
2470
0
  } else {
2471
0
    memset(&prd, 0, sizeof(prd));
2472
0
    if (pfx_mac) {
2473
0
      prd.family = AF_UNSPEC;
2474
0
      prd.prefixlen = 64;
2475
0
      encode_rd_type(RD_TYPE_VNC_ETH, prd.val);
2476
0
      if (l2o->local_nve_id
2477
0
          || !(rfd->rfg->flags & RFAPI_RFG_L2RD)) {
2478
        /*
2479
         * If Local NVE ID is specified in message, use
2480
         * it.
2481
         * (if no local default configured, also use it
2482
         * even if 0)
2483
         */
2484
0
        prd.val[1] = l2o->local_nve_id;
2485
0
      } else {
2486
0
        if (rfd->rfg->l2rd) {
2487
          /*
2488
           * locally-configured literal value
2489
           */
2490
0
          prd.val[1] = rfd->rfg->l2rd;
2491
0
        } else {
2492
          /*
2493
           * 0 means auto:vn, which means use LSB
2494
           * of VN addr
2495
           */
2496
0
          if (rfd->vn_addr.addr_family
2497
0
              == AF_INET) {
2498
0
            prd.val[1] =
2499
0
              *(((char *)&rfd->vn_addr
2500
0
                   .addr.v4
2501
0
                   .s_addr)
2502
0
                + 3);
2503
0
          } else {
2504
0
            prd.val[1] =
2505
0
              *(((char *)&rfd->vn_addr
2506
0
                   .addr.v6
2507
0
                   .s6_addr)
2508
0
                + 15);
2509
0
          }
2510
0
        }
2511
0
      }
2512
0
      memcpy(prd.val + 2, pfx_mac->u.prefix_eth.octet, 6);
2513
0
    } else {
2514
0
      prd = rfd->rd;
2515
0
      prd.family = AF_UNSPEC;
2516
0
      prd.prefixlen = 64;
2517
0
    }
2518
0
  }
2519
2520
2521
0
  if (action == RFAPI_REGISTER_WITHDRAW
2522
0
      || action == RFAPI_REGISTER_KILL) {
2523
2524
0
    int adv_tunnel = 0;
2525
2526
    /*
2527
     * withdraw previous advertisement
2528
     */
2529
0
    del_vnc_route(
2530
0
      rfd, rfd->peer, bgp, SAFI_MPLS_VPN,
2531
0
      pfx_ip ? pfx_ip
2532
0
             : &pfx_vn_buf, /* prefix being advertised */
2533
0
      &prd, /* route distinguisher (0 for ENCAP) */
2534
0
      ZEBRA_ROUTE_BGP, BGP_ROUTE_RFP, NULL,
2535
0
      action == RFAPI_REGISTER_KILL);
2536
2537
0
    if (0 == rfapiApDelete(bgp, rfd, &p, pfx_mac, &prd,
2538
0
               &adv_tunnel)) {
2539
0
      if (adv_tunnel)
2540
0
        rfapiTunnelRouteAnnounce(
2541
0
          bgp, rfd, &rfd->max_prefix_lifetime);
2542
0
    }
2543
2544
0
  } else {
2545
2546
0
    int adv_tunnel = 0;
2547
0
    uint32_t local_pref;
2548
0
    struct ecommunity *rtlist = NULL;
2549
0
    struct ecommunity_val ecom_value;
2550
2551
0
    if (!rfapiApCount(rfd)) {
2552
      /*
2553
       * make sure we advertise tunnel route upon adding the
2554
       * first VPN route
2555
       */
2556
0
      adv_tunnel = 1;
2557
0
    }
2558
2559
0
    if (rfapiApAdd(bgp, rfd, &p, pfx_mac, &prd, lifetime,
2560
0
             prefix->cost, l2o)) {
2561
0
      adv_tunnel = 1;
2562
0
    }
2563
2564
0
    vnc_zlog_debug_verbose("%s: adv_tunnel = %d", __func__,
2565
0
               adv_tunnel);
2566
0
    if (adv_tunnel) {
2567
0
      vnc_zlog_debug_verbose("%s: announcing tunnel route",
2568
0
                 __func__);
2569
0
      rfapiTunnelRouteAnnounce(bgp, rfd,
2570
0
             &rfd->max_prefix_lifetime);
2571
0
    }
2572
2573
0
    vnc_zlog_debug_verbose("%s: calling add_vnc_route", __func__);
2574
2575
0
    local_pref = rfp_cost_to_localpref(prefix->cost);
2576
2577
0
    if (l2o && l2o->label)
2578
0
      label = &l2o->label;
2579
2580
0
    if (pfx_mac) {
2581
0
      struct ecommunity *l2com = NULL;
2582
2583
0
      if (label) {
2584
0
        l2com = bgp_rfapi_get_ecommunity_by_lni_label(
2585
0
          bgp, 1, l2o->logical_net_id, *label);
2586
0
      }
2587
0
      if (l2com) {
2588
0
        rtlist = ecommunity_dup(l2com);
2589
0
      } else {
2590
        /*
2591
         * If mac address is set, add an RT based on the
2592
         * registered LNI
2593
         */
2594
0
        memset((char *)&ecom_value, 0,
2595
0
               sizeof(ecom_value));
2596
0
        ecom_value.val[1] = ECOMMUNITY_ROUTE_TARGET;
2597
0
        ecom_value.val[5] =
2598
0
          (l2o->logical_net_id >> 16) & 0xff;
2599
0
        ecom_value.val[6] =
2600
0
          (l2o->logical_net_id >> 8) & 0xff;
2601
0
        ecom_value.val[7] =
2602
0
          (l2o->logical_net_id >> 0) & 0xff;
2603
0
        rtlist = ecommunity_new();
2604
0
        ecommunity_add_val(rtlist, &ecom_value,
2605
0
               false, false);
2606
0
      }
2607
0
      if (l2o->tag_id) {
2608
0
        as_t as = bgp->as;
2609
0
        uint16_t val = l2o->tag_id;
2610
0
        memset((char *)&ecom_value, 0,
2611
0
               sizeof(ecom_value));
2612
0
        ecom_value.val[1] = ECOMMUNITY_ROUTE_TARGET;
2613
0
        if (as > BGP_AS_MAX) {
2614
0
          ecom_value.val[0] =
2615
0
            ECOMMUNITY_ENCODE_AS4;
2616
0
          ecom_value.val[2] = (as >> 24) & 0xff;
2617
0
          ecom_value.val[3] = (as >> 16) & 0xff;
2618
0
          ecom_value.val[4] = (as >> 8) & 0xff;
2619
0
          ecom_value.val[5] = as & 0xff;
2620
0
        } else {
2621
0
          ecom_value.val[0] =
2622
0
            ECOMMUNITY_ENCODE_AS;
2623
0
          ecom_value.val[2] = (as >> 8) & 0xff;
2624
0
          ecom_value.val[3] = as & 0xff;
2625
0
        }
2626
0
        ecom_value.val[6] = (val >> 8) & 0xff;
2627
0
        ecom_value.val[7] = val & 0xff;
2628
0
        if (rtlist == NULL)
2629
0
          rtlist = ecommunity_new();
2630
0
        ecommunity_add_val(rtlist, &ecom_value,
2631
0
               false, false);
2632
0
      }
2633
0
    }
2634
2635
    /*
2636
     * advertise prefix via tunnel endpoint
2637
     */
2638
0
    add_vnc_route(
2639
0
      rfd, /* rfapi descr, for export list & backref */
2640
0
      bgp, /* which bgp instance */
2641
0
      SAFI_MPLS_VPN, /* which SAFI */
2642
0
      (pfx_ip ? pfx_ip
2643
0
        : &pfx_vn_buf), /* prefix being advertised */
2644
0
      &prd, /* route distinguisher to use (0 for ENCAP) */
2645
0
      &rfd->vn_addr, /* nexthop */
2646
0
      &local_pref,
2647
0
      &lifetime, /* prefix lifetime -> Tunnel Encap attr */
2648
0
      NULL, options_un, /* rfapi un options */
2649
0
      options_vn,       /* rfapi vn options */
2650
0
      (rtlist ? rtlist : rfd->rt_export_list), NULL, /* med */
2651
0
      label, /* label: default */
2652
0
      ZEBRA_ROUTE_BGP, BGP_ROUTE_RFP, 0);
2653
2654
0
    if (rtlist)
2655
0
      ecommunity_free(&rtlist); /* sets rtlist = NULL */
2656
0
  }
2657
2658
0
  vnc_zlog_debug_verbose("%s: success", __func__);
2659
0
  return 0;
2660
0
}
2661
2662
int rfapi_query(void *handle, struct rfapi_ip_addr *target,
2663
    struct rfapi_l2address_option *l2o, /* may be NULL */
2664
    struct rfapi_next_hop_entry **ppNextHopEntry)
2665
0
{
2666
0
  struct rfapi_descriptor *rfd = (struct rfapi_descriptor *)handle;
2667
0
  struct bgp *bgp = rfd->bgp;
2668
0
  int rc;
2669
2670
0
  assert(ppNextHopEntry);
2671
0
  *ppNextHopEntry = NULL;
2672
2673
0
  if (bgp && bgp->rfapi) {
2674
0
    bgp->rfapi->stat.count_queries++;
2675
0
  }
2676
2677
0
  if (!rfd->rfg) {
2678
0
    if (bgp && bgp->rfapi)
2679
0
      ++bgp->rfapi->stat.count_queries_failed;
2680
0
    return ESTALE;
2681
0
  }
2682
2683
0
  if ((rc = rfapi_query_inner(handle, target, l2o, ppNextHopEntry))) {
2684
0
    if (bgp && bgp->rfapi)
2685
0
      ++bgp->rfapi->stat.count_queries_failed;
2686
0
  }
2687
0
  return rc;
2688
0
}
2689
2690
int rfapi_query_done(rfapi_handle handle, struct rfapi_ip_addr *target)
2691
0
{
2692
0
  struct prefix p;
2693
0
  int rc;
2694
0
  struct rfapi_descriptor *rfd = (struct rfapi_descriptor *)handle;
2695
0
  struct bgp *bgp = rfd->bgp;
2696
2697
0
  if (!rfd->rfg)
2698
0
    return ESTALE;
2699
2700
0
  assert(target);
2701
0
  rc = rfapiRaddr2Qprefix(target, &p);
2702
0
  assert(!rc);
2703
2704
0
  if (!is_valid_rfd(rfd))
2705
0
    return EBADF;
2706
2707
  /* preemptive */
2708
0
  if (!bgp || !bgp->rfapi)
2709
0
    return ENXIO;
2710
2711
0
  if (bgp->rfapi->flags & RFAPI_INCALLBACK)
2712
0
    return EDEADLK;
2713
2714
0
  rfapiMonitorDel(bgp, rfd, &p);
2715
2716
0
  return 0;
2717
0
}
2718
2719
int rfapi_query_done_all(rfapi_handle handle, int *count)
2720
0
{
2721
0
  struct rfapi_descriptor *rfd = (struct rfapi_descriptor *)handle;
2722
0
  struct bgp *bgp = rfd->bgp;
2723
0
  ;
2724
0
  int num;
2725
2726
0
  if (!rfd->rfg)
2727
0
    return ESTALE;
2728
2729
0
  if (!is_valid_rfd(rfd))
2730
0
    return EBADF;
2731
2732
  /* preemptive */
2733
0
  if (!bgp || !bgp->rfapi)
2734
0
    return ENXIO;
2735
2736
0
  if (bgp->rfapi->flags & RFAPI_INCALLBACK)
2737
0
    return EDEADLK;
2738
2739
0
  num = rfapiMonitorDelHd(rfd);
2740
2741
0
  if (count)
2742
0
    *count = num;
2743
2744
0
  return 0;
2745
0
}
2746
2747
void rfapi_free_next_hop_list(struct rfapi_next_hop_entry *list)
2748
0
{
2749
0
  struct rfapi_next_hop_entry *nh;
2750
0
  struct rfapi_next_hop_entry *next;
2751
2752
0
  for (nh = list; nh; nh = next) {
2753
0
    next = nh->next;
2754
0
    rfapi_un_options_free(nh->un_options);
2755
0
    nh->un_options = NULL;
2756
0
    rfapi_vn_options_free(nh->vn_options);
2757
0
    nh->vn_options = NULL;
2758
0
    XFREE(MTYPE_RFAPI_NEXTHOP, nh);
2759
0
  }
2760
0
}
2761
2762
/*
2763
 * NULL handle => return total count across all nves
2764
 */
2765
uint32_t rfapi_monitor_count(void *handle)
2766
0
{
2767
0
  struct bgp *bgp = bgp_get_default();
2768
0
  uint32_t count;
2769
2770
0
  if (handle) {
2771
0
    struct rfapi_descriptor *rfd =
2772
0
      (struct rfapi_descriptor *)handle;
2773
0
    count = rfd->monitor_count;
2774
0
  } else {
2775
2776
0
    if (!bgp || !bgp->rfapi)
2777
0
      return 0;
2778
2779
0
    count = bgp->rfapi->monitor_count;
2780
0
  }
2781
2782
0
  return count;
2783
0
}
2784
2785
/***********************************************************************
2786
 *      CLI/CONFIG
2787
 ***********************************************************************/
2788
2789
DEFUN (debug_rfapi_show_nves,
2790
       debug_rfapi_show_nves_cmd,
2791
       "debug rfapi-dev show nves",
2792
       DEBUG_STR
2793
       DEBUG_RFAPI_STR
2794
       SHOW_STR
2795
       "NVE Information\n")
2796
0
{
2797
0
  rfapiPrintMatchingDescriptors(vty, NULL, NULL);
2798
0
  return CMD_SUCCESS;
2799
0
}
2800
2801
DEFUN (
2802
  debug_rfapi_show_nves_vn_un,
2803
  debug_rfapi_show_nves_vn_un_cmd,
2804
  "debug rfapi-dev show nves <vn|un> <A.B.C.D|X:X::X:X>", /* prefix also ok */
2805
  DEBUG_STR
2806
  DEBUG_RFAPI_STR
2807
  SHOW_STR
2808
  "NVE Information\n"
2809
  "Specify virtual network\n"
2810
  "Specify underlay network interface\n"
2811
  "IPv4 address\n"
2812
  "IPv6 address\n")
2813
0
{
2814
0
  struct prefix pfx;
2815
2816
0
  if (!str2prefix(argv[5]->arg, &pfx)) {
2817
0
    vty_out(vty, "Malformed address \"%s\"\n", argv[5]->arg);
2818
0
    return CMD_WARNING_CONFIG_FAILED;
2819
0
  }
2820
0
  if (pfx.family != AF_INET && pfx.family != AF_INET6) {
2821
0
    vty_out(vty, "Invalid address \"%s\"\n", argv[5]->arg);
2822
0
    return CMD_WARNING_CONFIG_FAILED;
2823
0
  }
2824
2825
0
  if (argv[4]->arg[0] == 'u') {
2826
0
    rfapiPrintMatchingDescriptors(vty, NULL, &pfx);
2827
0
  } else {
2828
0
    rfapiPrintMatchingDescriptors(vty, &pfx, NULL);
2829
0
  }
2830
0
  return CMD_SUCCESS;
2831
0
}
2832
2833
/*
2834
 * Note: this function does not flush vty output, so if it is called
2835
 * with a stream pointing to a vty, the user will have to type something
2836
 * before the callback output shows up
2837
 */
2838
static void test_nexthops_callback(
2839
  //    struct rfapi_ip_addr        *target,
2840
  struct rfapi_next_hop_entry *next_hops, void *userdata)
2841
0
{
2842
0
  void *stream = userdata;
2843
2844
0
  int (*fp)(void *, const char *, ...);
2845
0
  struct vty *vty;
2846
0
  void *out;
2847
0
  const char *vty_newline;
2848
2849
0
  if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
2850
0
    return;
2851
2852
0
  fp(out, "Nexthops Callback, Target=(");
2853
  // rfapiPrintRfapiIpAddr(stream, target);
2854
0
  fp(out, ")\n");
2855
2856
0
  rfapiPrintNhl(stream, next_hops);
2857
2858
0
  fp(out, "\n");
2859
2860
0
  rfapi_free_next_hop_list(next_hops);
2861
0
}
2862
2863
DEFUN (debug_rfapi_open,
2864
       debug_rfapi_open_cmd,
2865
       "debug rfapi-dev open vn <A.B.C.D|X:X::X:X> un <A.B.C.D|X:X::X:X>",
2866
       DEBUG_STR
2867
       DEBUG_RFAPI_STR
2868
       "rfapi_open\n"
2869
       "indicate vn addr follows\n"
2870
       "virtual network interface IPv4 address\n"
2871
       "virtual network interface IPv6 address\n"
2872
       "indicate xt addr follows\n"
2873
       "underlay network interface IPv4 address\n"
2874
       "underlay network interface IPv6 address\n")
2875
0
{
2876
0
  struct rfapi_ip_addr vn;
2877
0
  struct rfapi_ip_addr un;
2878
0
  uint32_t lifetime = 0;
2879
0
  int rc;
2880
0
  rfapi_handle handle;
2881
2882
  /*
2883
   * Get VN addr
2884
   */
2885
0
  if ((rc = rfapiCliGetRfapiIpAddr(vty, argv[4]->arg, &vn)))
2886
0
    return rc;
2887
2888
  /*
2889
   * Get UN addr
2890
   */
2891
0
  if ((rc = rfapiCliGetRfapiIpAddr(vty, argv[6]->arg, &un)))
2892
0
    return rc;
2893
2894
0
  rc = rfapi_open(rfapi_get_rfp_start_val_by_bgp(bgp_get_default()), &vn,
2895
0
      &un, /*&uo */ NULL, &lifetime, NULL, &handle);
2896
2897
0
  vty_out(vty, "rfapi_open: status %d, handle %p, lifetime %d\n", rc,
2898
0
    handle, lifetime);
2899
2900
0
  rc = rfapi_set_response_cb(handle, test_nexthops_callback);
2901
2902
0
  vty_out(vty, "rfapi_set_response_cb: status %d\n", rc);
2903
2904
0
  return CMD_SUCCESS;
2905
0
}
2906
2907
2908
DEFUN (debug_rfapi_close_vn_un,
2909
       debug_rfapi_close_vn_un_cmd,
2910
       "debug rfapi-dev close vn <A.B.C.D|X:X::X:X> un <A.B.C.D|X:X::X:X>",
2911
       DEBUG_STR
2912
       DEBUG_RFAPI_STR
2913
       "rfapi_close\n"
2914
       "indicate vn addr follows\n"
2915
       "virtual network interface IPv4 address\n"
2916
       "virtual network interface IPv6 address\n"
2917
       "indicate xt addr follows\n"
2918
       "underlay network interface IPv4 address\n"
2919
       "underlay network interface IPv6 address\n")
2920
0
{
2921
0
  struct rfapi_ip_addr vn;
2922
0
  struct rfapi_ip_addr un;
2923
0
  rfapi_handle handle;
2924
0
  int rc;
2925
2926
  /*
2927
   * Get VN addr
2928
   */
2929
0
  if ((rc = rfapiCliGetRfapiIpAddr(vty, argv[4]->arg, &vn)))
2930
0
    return rc;
2931
2932
2933
  /*
2934
   * Get UN addr
2935
   */
2936
0
  if ((rc = rfapiCliGetRfapiIpAddr(vty, argv[6]->arg, &un)))
2937
0
    return rc;
2938
2939
2940
0
  if (rfapi_find_handle_vty(vty, &vn, &un, &handle)) {
2941
0
    vty_out(vty, "can't locate handle matching vn=%s, un=%s\n",
2942
0
      argv[4]->arg, argv[6]->arg);
2943
0
    return CMD_WARNING_CONFIG_FAILED;
2944
0
  }
2945
2946
0
  rc = rfapi_close(handle);
2947
2948
0
  vty_out(vty, "rfapi_close(handle=%p): status %d\n", handle, rc);
2949
2950
0
  return CMD_SUCCESS;
2951
0
}
2952
2953
DEFUN (debug_rfapi_close_rfd,
2954
       debug_rfapi_close_rfd_cmd,
2955
       "debug rfapi-dev close rfd HANDLE",
2956
       DEBUG_STR
2957
       DEBUG_RFAPI_STR
2958
       "rfapi_close\n"
2959
       "indicate handle follows\n" "rfapi handle in hexadecimal\n")
2960
0
{
2961
0
  rfapi_handle handle;
2962
0
  int rc;
2963
0
  char *endptr = NULL;
2964
2965
0
  handle = (rfapi_handle)(uintptr_t)(strtoull(argv[4]->arg, &endptr, 16));
2966
2967
0
  if (*endptr != '\0' || (uintptr_t)handle == UINTPTR_MAX) {
2968
0
    vty_out(vty, "Invalid value: %s\n", argv[4]->arg);
2969
0
    return CMD_WARNING_CONFIG_FAILED;
2970
0
  }
2971
2972
0
  rc = rfapi_close(handle);
2973
2974
0
  vty_out(vty, "rfapi_close(handle=%p): status %d\n", handle, rc);
2975
2976
0
  return CMD_SUCCESS;
2977
0
}
2978
2979
DEFUN (debug_rfapi_register_vn_un,
2980
       debug_rfapi_register_vn_un_cmd,
2981
       "debug rfapi-dev register vn <A.B.C.D|X:X::X:X> un <A.B.C.D|X:X::X:X> prefix <A.B.C.D/M|X:X::X:X/M> lifetime SECONDS [cost (0-255)]",
2982
       DEBUG_STR
2983
       DEBUG_RFAPI_STR
2984
       "rfapi_register\n"
2985
       "indicate vn addr follows\n"
2986
       "virtual network IPv4 interface address\n"
2987
       "virtual network IPv6 interface address\n"
2988
       "indicate un addr follows\n"
2989
       "underlay network IPv4 interface address\n"
2990
       "underlay network IPv6 interface address\n"
2991
       "indicate prefix follows\n"
2992
       "IPv4 prefix\n"
2993
       "IPv6 prefix\n"
2994
       "indicate lifetime follows\n"
2995
       "lifetime\n"
2996
       "Cost (localpref = 255-cost)\n"
2997
       "0-255\n")
2998
0
{
2999
0
  struct rfapi_ip_addr vn;
3000
0
  struct rfapi_ip_addr un;
3001
0
  rfapi_handle handle;
3002
0
  struct prefix pfx;
3003
0
  uint32_t lifetime;
3004
0
  struct rfapi_ip_prefix hpfx;
3005
0
  int rc;
3006
0
  uint8_t cost = 100;
3007
3008
  /*
3009
   * Get VN addr
3010
   */
3011
0
  if ((rc = rfapiCliGetRfapiIpAddr(vty, argv[4]->arg, &vn)))
3012
0
    return rc;
3013
3014
3015
  /*
3016
   * Get UN addr
3017
   */
3018
0
  if ((rc = rfapiCliGetRfapiIpAddr(vty, argv[6]->arg, &un)))
3019
0
    return rc;
3020
3021
3022
0
  if (rfapi_find_handle_vty(vty, &vn, &un, &handle)) {
3023
0
    vty_out(vty, "can't locate handle matching vn=%s, un=%s\n",
3024
0
      argv[4]->arg, argv[6]->arg);
3025
0
    return CMD_WARNING_CONFIG_FAILED;
3026
0
  }
3027
3028
  /*
3029
   * Get prefix to advertise
3030
   */
3031
0
  if (!str2prefix(argv[8]->arg, &pfx)) {
3032
0
    vty_out(vty, "Malformed prefix \"%s\"\n", argv[8]->arg);
3033
0
    return CMD_WARNING_CONFIG_FAILED;
3034
0
  }
3035
0
  if (pfx.family != AF_INET && pfx.family != AF_INET6) {
3036
0
    vty_out(vty, "Bad family for prefix \"%s\"\n", argv[8]->arg);
3037
0
    return CMD_WARNING_CONFIG_FAILED;
3038
0
  }
3039
0
  rfapiQprefix2Rprefix(&pfx, &hpfx);
3040
3041
0
  if (strmatch(argv[10]->text, "infinite")) {
3042
0
    lifetime = RFAPI_INFINITE_LIFETIME;
3043
0
  } else {
3044
0
    lifetime = strtoul(argv[10]->arg, NULL, 10);
3045
0
  }
3046
3047
0
  if (argc >= 13)
3048
0
    cost = (uint8_t) strtoul(argv[12]->arg, NULL, 10);
3049
0
  hpfx.cost = cost;
3050
3051
0
  rc = rfapi_register(handle, &hpfx, lifetime, NULL, NULL,
3052
0
          RFAPI_REGISTER_ADD);
3053
0
  if (rc) {
3054
0
    vty_out(vty, "rfapi_register failed with rc=%d (%s)\n", rc,
3055
0
      strerror(rc));
3056
0
  }
3057
3058
0
  return CMD_SUCCESS;
3059
0
}
3060
3061
DEFUN (debug_rfapi_register_vn_un_l2o,
3062
       debug_rfapi_register_vn_un_l2o_cmd,
3063
       "debug rfapi-dev register vn <A.B.C.D|X:X::X:X> un <A.B.C.D|X:X::X:X> prefix <A.B.C.D/M|X:X::X:X/M> lifetime SECONDS macaddr X:X:X:X:X:X lni (0-16777215)",
3064
       DEBUG_STR
3065
       DEBUG_RFAPI_STR
3066
       "rfapi_register\n"
3067
       "indicate vn addr follows\n"
3068
       "virtual network IPv4 interface address\n"
3069
       "virtual network IPv6 interface address\n"
3070
       "indicate un addr follows\n"
3071
       "underlay network IPv4 interface address\n"
3072
       "underlay network IPv6 interface address\n"
3073
       "indicate prefix follows\n"
3074
       "IPv4 prefix\n"
3075
       "IPv6 prefix\n"
3076
       "indicate lifetime follows\n"
3077
       "Seconds of lifetime\n"
3078
       "indicate MAC address follows\n"
3079
       "MAC address\n"
3080
       "indicate lni follows\n"
3081
       "lni value range\n")
3082
0
{
3083
0
  struct rfapi_ip_addr vn;
3084
0
  struct rfapi_ip_addr un;
3085
0
  rfapi_handle handle;
3086
0
  struct prefix pfx;
3087
0
  uint32_t lifetime;
3088
0
  struct rfapi_ip_prefix hpfx;
3089
0
  int rc;
3090
0
  struct rfapi_vn_option optary[10]; /* XXX must be big enough */
3091
0
  struct rfapi_vn_option *opt = NULL;
3092
0
  int opt_next = 0;
3093
3094
  /*
3095
   * Get VN addr
3096
   */
3097
0
  if ((rc = rfapiCliGetRfapiIpAddr(vty, argv[4]->arg, &vn)))
3098
0
    return rc;
3099
3100
3101
  /*
3102
   * Get UN addr
3103
   */
3104
0
  if ((rc = rfapiCliGetRfapiIpAddr(vty, argv[6]->arg, &un)))
3105
0
    return rc;
3106
3107
3108
0
  if (rfapi_find_handle_vty(vty, &vn, &un, &handle)) {
3109
0
    vty_out(vty, "can't locate handle matching vn=%s, un=%s\n",
3110
0
      argv[4]->arg, argv[6]->arg);
3111
0
    return CMD_WARNING_CONFIG_FAILED;
3112
0
  }
3113
3114
  /*
3115
   * Get prefix to advertise
3116
   */
3117
0
  if (!str2prefix(argv[8]->arg, &pfx)) {
3118
0
    vty_out(vty, "Malformed prefix \"%s\"\n", argv[8]->arg);
3119
0
    return CMD_WARNING_CONFIG_FAILED;
3120
0
  }
3121
0
  if (pfx.family != AF_INET && pfx.family != AF_INET6) {
3122
0
    vty_out(vty, "Bad family for prefix \"%s\"\n", argv[8]->arg);
3123
0
    return CMD_WARNING_CONFIG_FAILED;
3124
0
  }
3125
0
  rfapiQprefix2Rprefix(&pfx, &hpfx);
3126
3127
0
  if (strmatch(argv[10]->text, "infinite")) {
3128
0
    lifetime = RFAPI_INFINITE_LIFETIME;
3129
0
  } else {
3130
0
    lifetime = strtoul(argv[10]->arg, NULL, 10);
3131
0
  }
3132
3133
  /* L2 option parsing START */
3134
0
  memset(optary, 0, sizeof(optary));
3135
0
  optary[opt_next].v.l2addr.logical_net_id =
3136
0
    strtoul(argv[14]->arg, NULL, 10);
3137
0
  if (rfapiStr2EthAddr(argv[12]->arg,
3138
0
           &optary[opt_next].v.l2addr.macaddr)) {
3139
0
    vty_out(vty, "Bad mac address \"%s\"\n", argv[12]->arg);
3140
0
    return CMD_WARNING_CONFIG_FAILED;
3141
0
  }
3142
0
  optary[opt_next].type = RFAPI_VN_OPTION_TYPE_L2ADDR;
3143
0
  opt = optary;
3144
3145
  /* L2 option parsing END */
3146
3147
  /* TBD fixme */
3148
0
  rc = rfapi_register(handle, &hpfx, lifetime, NULL /* &uo */, opt,
3149
0
          RFAPI_REGISTER_ADD);
3150
0
  if (rc) {
3151
0
    vty_out(vty, "rfapi_register failed with rc=%d (%s)\n", rc,
3152
0
      strerror(rc));
3153
0
  }
3154
3155
0
  return CMD_SUCCESS;
3156
0
}
3157
3158
3159
DEFUN (debug_rfapi_unregister_vn_un,
3160
       debug_rfapi_unregister_vn_un_cmd,
3161
       "debug rfapi-dev unregister vn <A.B.C.D|X:X::X:X> un <A.B.C.D|X:X::X:X> prefix <A.B.C.D/M|X:X::X:X/M> [kill]",
3162
       DEBUG_STR
3163
       DEBUG_RFAPI_STR
3164
       "rfapi_unregister\n"
3165
       "indicate vn addr follows\n"
3166
       "virtual network interface address\n"
3167
       "virtual network interface address\n"
3168
       "indicate xt addr follows\n"
3169
       "underlay network interface address\n"
3170
       "underlay network interface address\n"
3171
       "prefix to remove\n"
3172
       "prefix to remove\n"
3173
       "prefix to remove\n"
3174
       "Remove without holddown\n")
3175
0
{
3176
0
  struct rfapi_ip_addr vn;
3177
0
  struct rfapi_ip_addr un;
3178
0
  rfapi_handle handle;
3179
0
  struct prefix pfx;
3180
0
  struct rfapi_ip_prefix hpfx;
3181
0
  int rc;
3182
3183
  /*
3184
   * Get VN addr
3185
   */
3186
0
  if ((rc = rfapiCliGetRfapiIpAddr(vty, argv[4]->arg, &vn)))
3187
0
    return rc;
3188
3189
  /*
3190
   * Get UN addr
3191
   */
3192
0
  if ((rc = rfapiCliGetRfapiIpAddr(vty, argv[6]->arg, &un)))
3193
0
    return rc;
3194
3195
3196
0
  if (rfapi_find_handle_vty(vty, &vn, &un, &handle)) {
3197
0
    vty_out(vty, "can't locate handle matching vn=%s, un=%s\n",
3198
0
      argv[4]->arg, argv[6]->arg);
3199
0
    return CMD_WARNING_CONFIG_FAILED;
3200
0
  }
3201
3202
  /*
3203
   * Get prefix to advertise
3204
   */
3205
0
  if (!str2prefix(argv[8]->arg, &pfx)) {
3206
0
    vty_out(vty, "Malformed prefix \"%s\"\n", argv[8]->arg);
3207
0
    return CMD_WARNING_CONFIG_FAILED;
3208
0
  }
3209
0
  if (pfx.family != AF_INET && pfx.family != AF_INET6) {
3210
0
    vty_out(vty, "Bad family for prefix \"%s\"\n", argv[8]->arg);
3211
0
    return CMD_WARNING_CONFIG_FAILED;
3212
0
  }
3213
0
  rfapiQprefix2Rprefix(&pfx, &hpfx);
3214
3215
0
  rfapi_register(handle, &hpfx, 0, NULL, NULL,
3216
0
           (argc == 10 ?
3217
0
      RFAPI_REGISTER_KILL : RFAPI_REGISTER_WITHDRAW));
3218
3219
0
  return CMD_SUCCESS;
3220
0
}
3221
3222
DEFUN (debug_rfapi_query_vn_un,
3223
       debug_rfapi_query_vn_un_cmd,
3224
       "debug rfapi-dev query vn <A.B.C.D|X:X::X:X> un <A.B.C.D|X:X::X:X> target <A.B.C.D|X:X::X:X>",
3225
       DEBUG_STR
3226
       DEBUG_RFAPI_STR
3227
       "rfapi_query\n"
3228
       "indicate vn addr follows\n"
3229
       "virtual network interface IPv4 address\n"
3230
       "virtual network interface IPv6 address\n"
3231
       "indicate un addr follows\n"
3232
       "IPv4 un address\n"
3233
       "IPv6 un address\n"
3234
       "indicate target follows\n"
3235
       "target IPv4 address\n"
3236
       "target IPv6 address\n")
3237
0
{
3238
0
  struct rfapi_ip_addr vn;
3239
0
  struct rfapi_ip_addr un;
3240
0
  struct rfapi_ip_addr target;
3241
0
  rfapi_handle handle;
3242
0
  int rc;
3243
0
  struct rfapi_next_hop_entry *pNextHopEntry;
3244
3245
  /*
3246
   * Get VN addr
3247
   */
3248
0
  if ((rc = rfapiCliGetRfapiIpAddr(vty, argv[4]->arg, &vn)))
3249
0
    return rc;
3250
3251
3252
  /*
3253
   * Get UN addr
3254
   */
3255
0
  if ((rc = rfapiCliGetRfapiIpAddr(vty, argv[6]->arg, &un)))
3256
0
    return rc;
3257
3258
3259
  /*
3260
   * Get target addr
3261
   */
3262
0
  if ((rc = rfapiCliGetRfapiIpAddr(vty, argv[8]->arg, &target)))
3263
0
    return rc;
3264
3265
3266
0
  if (rfapi_find_handle_vty(vty, &vn, &un, &handle)) {
3267
0
    vty_out(vty, "can't locate handle matching vn=%s, un=%s\n",
3268
0
      argv[4]->arg, argv[6]->arg);
3269
0
    return CMD_WARNING_CONFIG_FAILED;
3270
0
  }
3271
3272
  /*
3273
   * options parameter not used? Set to NULL for now
3274
   */
3275
0
  rc = rfapi_query(handle, &target, NULL, &pNextHopEntry);
3276
3277
0
  if (rc) {
3278
0
    vty_out(vty, "rfapi_query failed with rc=%d (%s)\n", rc,
3279
0
      strerror(rc));
3280
0
  } else {
3281
    /*
3282
     * print nexthop list
3283
     */
3284
0
    test_nexthops_callback(/*&target, */ pNextHopEntry,
3285
0
               vty); /* frees nh list! */
3286
0
  }
3287
3288
0
  return CMD_SUCCESS;
3289
0
}
3290
3291
3292
DEFUN (debug_rfapi_query_vn_un_l2o,
3293
       debug_rfapi_query_vn_un_l2o_cmd,
3294
       "debug rfapi-dev query vn <A.B.C.D|X:X::X:X> un <A.B.C.D|X:X::X:X> lni LNI target X:X:X:X:X:X",
3295
       DEBUG_STR
3296
       DEBUG_RFAPI_STR
3297
       "rfapi_query\n"
3298
       "indicate vn addr follows\n"
3299
       "virtual network interface IPv4 address\n"
3300
       "virtual network interface IPv6 address\n"
3301
       "indicate xt addr follows\n"
3302
       "underlay network interface IPv4 address\n"
3303
       "underlay network interface IPv6 address\n"
3304
       "logical network ID follows\n"
3305
       "logical network ID\n"
3306
       "indicate target MAC addr follows\n"
3307
       "target MAC addr\n")
3308
0
{
3309
0
  struct rfapi_ip_addr vn;
3310
0
  struct rfapi_ip_addr un;
3311
0
  int rc;
3312
3313
  /*
3314
   * Get VN addr
3315
   */
3316
0
  if ((rc = rfapiCliGetRfapiIpAddr(vty, argv[4]->arg, &vn)))
3317
0
    return rc;
3318
3319
3320
  /*
3321
   * Get UN addr
3322
   */
3323
0
  if ((rc = rfapiCliGetRfapiIpAddr(vty, argv[6]->arg, &un)))
3324
0
    return rc;
3325
3326
0
  vty_out(vty, "%% This command is broken.\n");
3327
0
  return CMD_WARNING_CONFIG_FAILED;
3328
0
}
3329
3330
3331
DEFUN (debug_rfapi_query_done_vn_un,
3332
       debug_rfapi_query_vn_un_done_cmd,
3333
       "debug rfapi-dev query done vn <A.B.C.D|X:X::X:X> un <A.B.C.D|X:X::X:X> target <A.B.C.D|X:X::X:X>",
3334
       DEBUG_STR
3335
       DEBUG_RFAPI_STR
3336
       "rfapi_query_done\n"
3337
       "rfapi_query_done\n"
3338
       "indicate vn addr follows\n"
3339
       "virtual network interface IPv4 address\n"
3340
       "virtual network interface IPv6 address\n"
3341
       "indicate xt addr follows\n"
3342
       "underlay network interface IPv4 address\n"
3343
       "underlay network interface IPv6 address\n"
3344
       "indicate target follows\n"
3345
       "Target IPv4 address\n"
3346
       "Target IPv6 address\n")
3347
0
{
3348
0
  struct rfapi_ip_addr vn;
3349
0
  struct rfapi_ip_addr un;
3350
0
  struct rfapi_ip_addr target;
3351
0
  rfapi_handle handle;
3352
0
  int rc;
3353
3354
  /*
3355
   * Get VN addr
3356
   */
3357
0
  if ((rc = rfapiCliGetRfapiIpAddr(vty, argv[5]->arg, &vn)))
3358
0
    return rc;
3359
3360
3361
  /*
3362
   * Get UN addr
3363
   */
3364
0
  if ((rc = rfapiCliGetRfapiIpAddr(vty, argv[7]->arg, &un)))
3365
0
    return rc;
3366
3367
3368
  /*
3369
   * Get target addr
3370
   */
3371
0
  if ((rc = rfapiCliGetRfapiIpAddr(vty, argv[9]->arg, &target)))
3372
0
    return rc;
3373
3374
3375
0
  if (rfapi_find_handle_vty(vty, &vn, &un, &handle)) {
3376
0
    vty_out(vty, "can't locate handle matching vn=%s, un=%s\n",
3377
0
      argv[5]->arg, argv[7]->arg);
3378
0
    return CMD_WARNING_CONFIG_FAILED;
3379
0
  }
3380
3381
  /*
3382
   * options parameter not used? Set to NULL for now
3383
   */
3384
0
  rc = rfapi_query_done(handle, &target);
3385
3386
0
  vty_out(vty, "rfapi_query_done returned %d\n", rc);
3387
3388
0
  return CMD_SUCCESS;
3389
0
}
3390
3391
DEFUN (debug_rfapi_show_import,
3392
       debug_rfapi_show_import_cmd,
3393
       "debug rfapi-dev show import",
3394
       DEBUG_STR
3395
       DEBUG_RFAPI_STR
3396
       SHOW_STR
3397
       "import\n")
3398
0
{
3399
0
  struct bgp *bgp;
3400
0
  struct rfapi *h;
3401
0
  struct rfapi_import_table *it;
3402
0
  char *s;
3403
0
  int first_l2 = 1;
3404
3405
  /*
3406
   * Show all import tables
3407
   */
3408
3409
0
  bgp = bgp_get_default(); /* assume 1 instance for now */
3410
0
  if (!bgp) {
3411
0
    vty_out(vty, "No BGP instance\n");
3412
0
    return CMD_WARNING_CONFIG_FAILED;
3413
0
  }
3414
3415
0
  h = bgp->rfapi;
3416
0
  if (!h) {
3417
0
    vty_out(vty, "No RFAPI instance\n");
3418
0
    return CMD_WARNING_CONFIG_FAILED;
3419
0
  }
3420
3421
  /*
3422
   * Iterate over all import tables; do a filtered import
3423
   * for the afi/safi combination
3424
   */
3425
3426
3427
0
  for (it = h->imports; it; it = it->next) {
3428
0
    s = ecommunity_ecom2str(it->rt_import_list,
3429
0
          ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
3430
0
    vty_out(vty, "Import Table %p, RTs: %s\n", it, s);
3431
0
    XFREE(MTYPE_ECOMMUNITY_STR, s);
3432
3433
0
    rfapiShowImportTable(vty, "IP VPN", it->imported_vpn[AFI_IP],
3434
0
             1);
3435
0
    rfapiShowImportTable(vty, "IP ENCAP",
3436
0
             it->imported_encap[AFI_IP], 0);
3437
0
    rfapiShowImportTable(vty, "IP6 VPN", it->imported_vpn[AFI_IP6],
3438
0
             1);
3439
0
    rfapiShowImportTable(vty, "IP6 ENCAP",
3440
0
             it->imported_encap[AFI_IP6], 0);
3441
0
  }
3442
3443
0
  if (h->import_mac) {
3444
0
    void *cursor = NULL;
3445
0
    uint32_t lni;
3446
0
    uintptr_t lni_as_ptr;
3447
0
    int rc;
3448
0
    char buf[BUFSIZ];
3449
3450
0
    for (rc = skiplist_next(h->import_mac, (void **)&lni_as_ptr,
3451
0
          (void **)&it, &cursor);
3452
0
         !rc;
3453
0
         rc = skiplist_next(h->import_mac, (void **)&lni_as_ptr,
3454
0
          (void **)&it, &cursor)) {
3455
3456
0
      if (it->imported_vpn[AFI_L2VPN]) {
3457
0
        lni = lni_as_ptr;
3458
0
        if (first_l2) {
3459
0
          vty_out(vty,
3460
0
            "\nLNI-based Ethernet Tables:\n");
3461
0
          first_l2 = 0;
3462
0
        }
3463
0
        snprintf(buf, sizeof(buf), "L2VPN LNI=%u", lni);
3464
0
        rfapiShowImportTable(
3465
0
          vty, buf, it->imported_vpn[AFI_L2VPN],
3466
0
          1);
3467
0
      }
3468
0
    }
3469
0
  }
3470
3471
0
  rfapiShowImportTable(vty, "CE IT - IP VPN",
3472
0
           h->it_ce->imported_vpn[AFI_IP], 1);
3473
3474
0
  return CMD_SUCCESS;
3475
0
}
3476
3477
DEFUN (debug_rfapi_show_import_vn_un,
3478
       debug_rfapi_show_import_vn_un_cmd,
3479
       "debug rfapi-dev show import vn <A.B.C.D|X:X::X:X> un <A.B.C.D|X:X::X:X>",
3480
       DEBUG_STR
3481
       DEBUG_RFAPI_STR
3482
       SHOW_STR
3483
       "import\n"
3484
       "indicate vn addr follows\n"
3485
       "virtual network interface IPv4 address\n"
3486
       "virtual network interface IPv6 address\n"
3487
       "indicate xt addr follows\n"
3488
       "underlay network interface IPv4 address\n"
3489
       "underlay network interface IPv6 address\n")
3490
0
{
3491
0
  struct rfapi_ip_addr vn;
3492
0
  struct rfapi_ip_addr un;
3493
0
  rfapi_handle handle;
3494
0
  int rc;
3495
0
  struct rfapi_descriptor *rfd;
3496
3497
  /*
3498
   * Get VN addr
3499
   */
3500
0
  if ((rc = rfapiCliGetRfapiIpAddr(vty, argv[5]->arg, &vn)))
3501
0
    return rc;
3502
3503
3504
  /*
3505
   * Get UN addr
3506
   */
3507
0
  if ((rc = rfapiCliGetRfapiIpAddr(vty, argv[7]->arg, &un)))
3508
0
    return rc;
3509
3510
3511
0
  if (rfapi_find_handle_vty(vty, &vn, &un, &handle)) {
3512
0
    vty_out(vty, "can't locate handle matching vn=%s, un=%s\n",
3513
0
      argv[5]->arg, argv[7]->arg);
3514
0
    return CMD_WARNING_CONFIG_FAILED;
3515
0
  }
3516
3517
0
  rfd = (struct rfapi_descriptor *)handle;
3518
3519
0
  rfapiShowImportTable(vty, "IP VPN",
3520
0
           rfd->import_table->imported_vpn[AFI_IP], 1);
3521
0
  rfapiShowImportTable(vty, "IP ENCAP",
3522
0
           rfd->import_table->imported_encap[AFI_IP], 0);
3523
0
  rfapiShowImportTable(vty, "IP6 VPN",
3524
0
           rfd->import_table->imported_vpn[AFI_IP6], 1);
3525
0
  rfapiShowImportTable(vty, "IP6 ENCAP",
3526
0
           rfd->import_table->imported_encap[AFI_IP6], 0);
3527
3528
0
  return CMD_SUCCESS;
3529
0
}
3530
3531
DEFUN (debug_rfapi_response_omit_self,
3532
       debug_rfapi_response_omit_self_cmd,
3533
       "debug rfapi-dev response-omit-self <on|off>",
3534
       DEBUG_STR
3535
       DEBUG_RFAPI_STR
3536
       "Omit self in RFP responses\n"
3537
       "filter out self from responses\n" "leave self in responses\n")
3538
0
{
3539
0
  struct bgp *bgp = bgp_get_default();
3540
3541
0
  if (!bgp) {
3542
0
    vty_out(vty, "No BGP process is configured\n");
3543
0
    return CMD_WARNING_CONFIG_FAILED;
3544
0
  }
3545
0
  if (!bgp->rfapi_cfg) {
3546
0
    vty_out(vty, "VNC not configured\n");
3547
0
    return CMD_WARNING_CONFIG_FAILED;
3548
0
  }
3549
3550
0
  if (strmatch(argv[3]->text, "on"))
3551
0
    SET_FLAG(bgp->rfapi_cfg->flags,
3552
0
       BGP_VNC_CONFIG_FILTER_SELF_FROM_RSP);
3553
0
  else
3554
0
    UNSET_FLAG(bgp->rfapi_cfg->flags,
3555
0
         BGP_VNC_CONFIG_FILTER_SELF_FROM_RSP);
3556
3557
0
  return CMD_SUCCESS;
3558
0
}
3559
3560
3561
#ifdef RFAPI_DEBUG_SKIPLIST_CLI
3562
3563
#include "lib/skiplist.h"
3564
DEFUN (skiplist_test_cli,
3565
       skiplist_test_cli_cmd,
3566
       "skiplist test",
3567
       "skiplist command\n"
3568
       "test\n")
3569
{
3570
  skiplist_test(vty);
3571
3572
  return CMD_SUCCESS;
3573
}
3574
3575
DEFUN (skiplist_debug_cli,
3576
       skiplist_debug_cli_cmd,
3577
       "skiplist debug",
3578
       "skiplist command\n"
3579
       "debug\n")
3580
{
3581
  skiplist_debug(vty, NULL);
3582
  return CMD_SUCCESS;
3583
}
3584
3585
#endif /* RFAPI_DEBUG_SKIPLIST_CLI */
3586
3587
void rfapi_init(void)
3588
0
{
3589
0
  bgp_rfapi_cfg_init();
3590
0
  vnc_debug_init();
3591
3592
0
  install_element(ENABLE_NODE, &debug_rfapi_show_import_cmd);
3593
0
  install_element(ENABLE_NODE, &debug_rfapi_show_import_vn_un_cmd);
3594
3595
0
  install_element(ENABLE_NODE, &debug_rfapi_open_cmd);
3596
0
  install_element(ENABLE_NODE, &debug_rfapi_close_vn_un_cmd);
3597
0
  install_element(ENABLE_NODE, &debug_rfapi_close_rfd_cmd);
3598
0
  install_element(ENABLE_NODE, &debug_rfapi_register_vn_un_cmd);
3599
0
  install_element(ENABLE_NODE, &debug_rfapi_unregister_vn_un_cmd);
3600
0
  install_element(ENABLE_NODE, &debug_rfapi_query_vn_un_cmd);
3601
0
  install_element(ENABLE_NODE, &debug_rfapi_query_vn_un_done_cmd);
3602
0
  install_element(ENABLE_NODE, &debug_rfapi_query_vn_un_l2o_cmd);
3603
3604
0
  install_element(ENABLE_NODE, &debug_rfapi_response_omit_self_cmd);
3605
3606
  /* Need the following show commands for gpz test scripts */
3607
0
  install_element(ENABLE_NODE, &debug_rfapi_show_nves_cmd);
3608
0
  install_element(ENABLE_NODE, &debug_rfapi_show_nves_vn_un_cmd);
3609
0
  install_element(ENABLE_NODE, &debug_rfapi_register_vn_un_l2o_cmd);
3610
3611
#ifdef RFAPI_DEBUG_SKIPLIST_CLI
3612
  install_element(ENABLE_NODE, &skiplist_test_cli_cmd);
3613
  install_element(ENABLE_NODE, &skiplist_debug_cli_cmd);
3614
#endif
3615
3616
0
  rfapi_vty_init();
3617
0
}
3618
3619
#ifdef DEBUG_RFAPI
3620
static void rfapi_print_exported(struct bgp *bgp)
3621
{
3622
  struct bgp_dest *destn;
3623
  struct bgp_dest *dest;
3624
  struct bgp_path_info *bpi;
3625
3626
  if (!bgp)
3627
    return;
3628
3629
  for (destn = bgp_table_top(bgp->rib[AFI_IP][SAFI_MPLS_VPN]); destn;
3630
       destn = bgp_route_next(destn)) {
3631
    struct bgp_table *table;
3632
3633
    table = bgp_dest_get_bgp_table_info(destn);
3634
    if (!table)
3635
      continue;
3636
    fprintf(stderr, "%s: vpn destn=%p\n", __func__, destn);
3637
    for (dest = bgp_table_top(table); dest;
3638
         dest = bgp_route_next(dest)) {
3639
      bpi = bgp_dest_get_bgp_path_info(dest);
3640
3641
      if (!bpi)
3642
        continue;
3643
      fprintf(stderr, "%s: dest=%p\n", __func__, dest);
3644
      for (; bpi; bpi = bpi->next) {
3645
        rfapiPrintBi((void *)2, bpi); /* 2 => stderr */
3646
      }
3647
    }
3648
  }
3649
  for (destn = bgp_table_top(bgp->rib[AFI_IP][SAFI_ENCAP]); destn;
3650
       destn = bgp_route_next(destn)) {
3651
    struct bgp_table *table;
3652
3653
    table = bgp_dest_get_bgp_table_info(destn);
3654
    if (!table)
3655
      continue;
3656
    fprintf(stderr, "%s: encap destn=%p\n", __func__, destn);
3657
    for (dest = bgp_table_top(table); dest;
3658
         dest = bgp_route_next(dest)) {
3659
      bpi = bgp_dest_get_bgp_path_info(dest);
3660
      if (!bpi)
3661
        continue;
3662
      fprintf(stderr, "%s: dest=%p\n", __func__, dest);
3663
      for (; bpi; bpi = bpi->next) {
3664
        rfapiPrintBi((void *)2, bpi); /* 2 => stderr */
3665
      }
3666
    }
3667
  }
3668
}
3669
#endif /* defined(DEBUG_RFAPI) */
3670
3671
/*
3672
 * Free all memory to prepare for clean exit as seen by valgrind memcheck
3673
 */
3674
void rfapi_delete(struct bgp *bgp)
3675
0
{
3676
0
  extern void rfp_clear_vnc_nve_all(void); /* can't fix correctly yet */
3677
3678
#if DEBUG_CLEANUP
3679
  zlog_debug("%s: bgp %p", __func__, bgp);
3680
#endif
3681
3682
  /*
3683
   * This clears queries and registered routes, and closes nves
3684
   */
3685
0
  if (bgp->rfapi)
3686
0
    rfp_clear_vnc_nve_all();
3687
3688
  /*
3689
   * close any remaining descriptors
3690
   */
3691
0
  struct rfapi *h = bgp->rfapi;
3692
3693
0
  if (h && h->descriptors.count) {
3694
0
    struct listnode *node, *nnode;
3695
0
    struct rfapi_descriptor *rfd;
3696
#if DEBUG_CLEANUP
3697
    zlog_debug("%s: descriptor count %u", __func__,
3698
         h->descriptors.count);
3699
#endif
3700
0
    for (ALL_LIST_ELEMENTS(&h->descriptors, node, nnode, rfd)) {
3701
#if DEBUG_CLEANUP
3702
      zlog_debug("%s: closing rfd %p", __func__, rfd);
3703
#endif
3704
0
      (void)rfapi_close(rfd);
3705
0
    }
3706
0
  }
3707
3708
0
  bgp_rfapi_cfg_destroy(bgp, bgp->rfapi_cfg);
3709
0
  bgp->rfapi_cfg = NULL;
3710
0
  bgp_rfapi_destroy(bgp, bgp->rfapi);
3711
0
  bgp->rfapi = NULL;
3712
#ifdef DEBUG_RFAPI
3713
  /*
3714
   * show what's left in the BGP MPLSVPN RIB
3715
   */
3716
  rfapi_print_exported(bgp);
3717
#endif
3718
0
}
3719
3720
int rfapi_set_autord_from_vn(struct prefix_rd *rd, struct rfapi_ip_addr *vn)
3721
0
{
3722
0
  vnc_zlog_debug_verbose("%s: auto-assigning RD", __func__);
3723
0
  if (vn->addr_family != AF_INET && vn->addr_family != AF_INET6) {
3724
0
    vnc_zlog_debug_verbose(
3725
0
      "%s: can't auto-assign RD, VN addr family is not IPv4|v6",
3726
0
      __func__);
3727
0
    return EAFNOSUPPORT;
3728
0
  }
3729
0
  rd->family = AF_UNSPEC;
3730
0
  rd->prefixlen = 64;
3731
0
  rd->val[1] = RD_TYPE_IP;
3732
0
  if (vn->addr_family == AF_INET) {
3733
0
    memcpy(rd->val + 2, &vn->addr.v4.s_addr, 4);
3734
0
  } else { /* is v6 */
3735
0
    memcpy(rd->val + 2, &vn->addr.v6.s6_addr32[3],
3736
0
           4); /* low order 4 bytes */
3737
0
  }
3738
0
  vnc_zlog_debug_verbose("%s: auto-RD is set to %pRDP", __func__, rd);
3739
0
  return 0;
3740
0
}
3741
3742
/*------------------------------------------
3743
 * rfapi_bgp_lookup_by_rfp
3744
 *
3745
 * Find bgp instance pointer based on value returned by rfp_start
3746
 *
3747
 * input:
3748
 *      rfp_start_val     value returned by rfp_startor
3749
 *                        NULL (=get default instance)
3750
 *
3751
 * output:
3752
 *  none
3753
 *
3754
 * return value:
3755
 *  bgp             bgp instance pointer
3756
 *      NULL = not found
3757
 *
3758
 --------------------------------------------*/
3759
struct bgp *rfapi_bgp_lookup_by_rfp(void *rfp_start_val)
3760
0
{
3761
0
  struct bgp *bgp = NULL;
3762
0
  struct listnode *node, *nnode;
3763
3764
0
  if (rfp_start_val == NULL)
3765
0
    bgp = bgp_get_default();
3766
0
  else
3767
0
    for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
3768
0
      if (bgp->rfapi != NULL
3769
0
          && bgp->rfapi->rfp == rfp_start_val)
3770
0
        return bgp;
3771
0
  return bgp;
3772
0
}
3773
3774
/*------------------------------------------
3775
 * rfapi_get_rfp_start_val_by_bgp
3776
 *
3777
 * Find bgp instance pointer based on value returned by rfp_start
3778
 *
3779
 * input:
3780
 *  bgp             bgp instance pointer
3781
 *
3782
 * output:
3783
 *  none
3784
 *
3785
 * return value:
3786
 *  rfp_start_val
3787
 *      NULL = not found
3788
 *
3789
 --------------------------------------------*/
3790
void *rfapi_get_rfp_start_val_by_bgp(struct bgp *bgp)
3791
0
{
3792
0
  if (!bgp || !bgp->rfapi)
3793
0
    return NULL;
3794
0
  return bgp->rfapi->rfp;
3795
0
}
3796
3797
/***********************************************************************
3798
 *     RFP group specific configuration
3799
 ***********************************************************************/
3800
static void *rfapi_rfp_get_or_init_group_config_default(struct rfapi_cfg *rfc,
3801
              struct vty *vty,
3802
              uint32_t size)
3803
0
{
3804
0
  if (rfc->default_rfp_cfg == NULL && size > 0) {
3805
0
    rfc->default_rfp_cfg = XCALLOC(MTYPE_RFAPI_RFP_GROUP_CFG, size);
3806
0
    vnc_zlog_debug_verbose("%s: allocated, size=%d", __func__,
3807
0
               size);
3808
0
  }
3809
0
  return rfc->default_rfp_cfg;
3810
0
}
3811
3812
static void *rfapi_rfp_get_or_init_group_config_nve(struct rfapi_cfg *rfc,
3813
                struct vty *vty,
3814
                uint32_t size)
3815
0
{
3816
0
  struct rfapi_nve_group_cfg *rfg =
3817
0
    VTY_GET_CONTEXT_SUB(rfapi_nve_group_cfg);
3818
3819
  /* make sure group is still in list */
3820
0
  if (!rfg || !listnode_lookup(rfc->nve_groups_sequential, rfg)) {
3821
    /* Not in list anymore */
3822
0
    vty_out(vty, "Current NVE group no longer exists\n");
3823
0
    return NULL;
3824
0
  }
3825
3826
0
  if (rfg->rfp_cfg == NULL && size > 0) {
3827
0
    rfg->rfp_cfg = XCALLOC(MTYPE_RFAPI_RFP_GROUP_CFG, size);
3828
0
    vnc_zlog_debug_verbose("%s: allocated, size=%d", __func__,
3829
0
               size);
3830
0
  }
3831
0
  return rfg->rfp_cfg;
3832
0
}
3833
3834
static void *rfapi_rfp_get_or_init_group_config_l2(struct rfapi_cfg *rfc,
3835
               struct vty *vty,
3836
               uint32_t size)
3837
0
{
3838
0
  struct rfapi_l2_group_cfg *rfg =
3839
0
    VTY_GET_CONTEXT_SUB(rfapi_l2_group_cfg);
3840
3841
  /* make sure group is still in list */
3842
0
  if (!rfg || !listnode_lookup(rfc->l2_groups, rfg)) {
3843
    /* Not in list anymore */
3844
0
    vty_out(vty, "Current L2 group no longer exists\n");
3845
0
    return NULL;
3846
0
  }
3847
0
  if (rfg->rfp_cfg == NULL && size > 0) {
3848
0
    rfg->rfp_cfg = XCALLOC(MTYPE_RFAPI_RFP_GROUP_CFG, size);
3849
0
    vnc_zlog_debug_verbose("%s: allocated, size=%d", __func__,
3850
0
               size);
3851
0
  }
3852
0
  return rfg->rfp_cfg;
3853
0
}
3854
3855
/*------------------------------------------
3856
 * rfapi_rfp_init_group_config_ptr_vty
3857
 *
3858
 * This is used to init or return a previously init'ed group specific
3859
 * configuration pointer. Group is identified by vty context.
3860
 * NOTE: size is ignored when a previously init'ed value is returned.
3861
 * RFAPI frees rfp_cfg_group when group is deleted during reconfig,
3862
 * bgp restart or shutdown.
3863
 *
3864
 * input:
3865
 *    rfp_start_val     value returned by rfp_start
3866
 *    type              group type
3867
 *    vty               quagga vty context
3868
 *    size              number of bytes to allocation
3869
 *
3870
 * output:
3871
 *    none
3872
 *
3873
 * return value:
3874
 *    rfp_cfg_group     NULL or Pointer to configuration structure
3875
--------------------------------------------*/
3876
void *rfapi_rfp_init_group_config_ptr_vty(void *rfp_start_val,
3877
            rfapi_rfp_cfg_group_type type,
3878
            struct vty *vty, uint32_t size)
3879
0
{
3880
0
  struct bgp *bgp;
3881
0
  void *ret = NULL;
3882
3883
0
  if (rfp_start_val == NULL || vty == NULL)
3884
0
    return NULL;
3885
3886
0
  bgp = rfapi_bgp_lookup_by_rfp(rfp_start_val);
3887
0
  if (!bgp || !bgp->rfapi_cfg)
3888
0
    return NULL;
3889
3890
0
  switch (type) {
3891
0
  case RFAPI_RFP_CFG_GROUP_DEFAULT:
3892
0
    ret = rfapi_rfp_get_or_init_group_config_default(bgp->rfapi_cfg,
3893
0
                 vty, size);
3894
0
    break;
3895
0
  case RFAPI_RFP_CFG_GROUP_NVE:
3896
0
    ret = rfapi_rfp_get_or_init_group_config_nve(bgp->rfapi_cfg,
3897
0
                   vty, size);
3898
0
    break;
3899
0
  case RFAPI_RFP_CFG_GROUP_L2:
3900
0
    ret = rfapi_rfp_get_or_init_group_config_l2(bgp->rfapi_cfg, vty,
3901
0
                  size);
3902
0
    break;
3903
0
  default:
3904
0
    flog_err(EC_LIB_DEVELOPMENT, "%s: Unknown group type=%d",
3905
0
       __func__, type);
3906
    /* should never happen */
3907
0
    assert("Unknown type" == NULL);
3908
0
    break;
3909
0
  }
3910
0
  return ret;
3911
0
}
3912
3913
/*------------------------------------------
3914
 * rfapi_rfp_get_group_config_ptr_vty
3915
 *
3916
 * This is used to get group specific configuration pointer.
3917
 * Group is identified by type and vty context.
3918
 * RFAPI frees rfp_cfg_group when group is deleted during reconfig,
3919
 * bgp restart or shutdown.
3920
 *
3921
 * input:
3922
 *    rfp_start_val     value returned by rfp_start
3923
 *    type              group type
3924
 *    vty               quagga vty context
3925
 *
3926
 * output:
3927
 *    none
3928
 *
3929
 * return value:
3930
 *    rfp_cfg_group     Pointer to configuration structure
3931
--------------------------------------------*/
3932
void *rfapi_rfp_get_group_config_ptr_vty(void *rfp_start_val,
3933
           rfapi_rfp_cfg_group_type type,
3934
           struct vty *vty)
3935
0
{
3936
0
  return rfapi_rfp_init_group_config_ptr_vty(rfp_start_val, type, vty, 0);
3937
0
}
3938
3939
static void *
3940
rfapi_rfp_get_group_config_name_nve(struct rfapi_cfg *rfc, const char *name,
3941
            void *criteria,
3942
            rfp_group_config_search_cb_t *search_cb)
3943
0
{
3944
0
  struct rfapi_nve_group_cfg *rfg;
3945
0
  struct listnode *node;
3946
3947
0
  for (ALL_LIST_ELEMENTS_RO(rfc->nve_groups_sequential, node, rfg)) {
3948
0
    if (!strcmp(rfg->name, name) && /* name match */
3949
0
        (search_cb == NULL || !search_cb(criteria, rfg->rfp_cfg)))
3950
0
      return rfg->rfp_cfg;
3951
0
  }
3952
0
  return NULL;
3953
0
}
3954
3955
static void *
3956
rfapi_rfp_get_group_config_name_l2(struct rfapi_cfg *rfc, const char *name,
3957
           void *criteria,
3958
           rfp_group_config_search_cb_t *search_cb)
3959
0
{
3960
0
  struct rfapi_l2_group_cfg *rfg;
3961
0
  struct listnode *node;
3962
3963
0
  for (ALL_LIST_ELEMENTS_RO(rfc->l2_groups, node, rfg)) {
3964
0
    if (!strcmp(rfg->name, name) && /* name match */
3965
0
        (search_cb == NULL || !search_cb(criteria, rfg->rfp_cfg)))
3966
0
      return rfg->rfp_cfg;
3967
0
  }
3968
0
  return NULL;
3969
0
}
3970
3971
/*------------------------------------------
3972
 * rfapi_rfp_get_group_config_ptr_name
3973
 *
3974
 * This is used to get group specific configuration pointer.
3975
 * Group is identified by type and name context.
3976
 * RFAPI frees rfp_cfg_group when group is deleted during reconfig,
3977
 * bgp restart or shutdown.
3978
 *
3979
 * input:
3980
 *    rfp_start_val     value returned by rfp_start
3981
 *    type              group type
3982
 *    name              group name
3983
 *    criteria          RFAPI caller provided search criteria
3984
 *    search_cb         optional rfp_group_config_search_cb_t
3985
 *
3986
 * output:
3987
 *    none
3988
 *
3989
 * return value:
3990
 *    rfp_cfg_group     Pointer to configuration structure
3991
--------------------------------------------*/
3992
void *rfapi_rfp_get_group_config_ptr_name(
3993
  void *rfp_start_val, rfapi_rfp_cfg_group_type type, const char *name,
3994
  void *criteria, rfp_group_config_search_cb_t *search_cb)
3995
0
{
3996
0
  struct bgp *bgp;
3997
0
  void *ret = NULL;
3998
3999
0
  if (rfp_start_val == NULL || name == NULL)
4000
0
    return NULL;
4001
4002
0
  bgp = rfapi_bgp_lookup_by_rfp(rfp_start_val);
4003
0
  if (!bgp || !bgp->rfapi_cfg)
4004
0
    return NULL;
4005
4006
0
  switch (type) {
4007
0
  case RFAPI_RFP_CFG_GROUP_DEFAULT:
4008
0
    ret = bgp->rfapi_cfg->default_rfp_cfg;
4009
0
    break;
4010
0
  case RFAPI_RFP_CFG_GROUP_NVE:
4011
0
    ret = rfapi_rfp_get_group_config_name_nve(bgp->rfapi_cfg, name,
4012
0
                criteria, search_cb);
4013
0
    break;
4014
0
  case RFAPI_RFP_CFG_GROUP_L2:
4015
0
    ret = rfapi_rfp_get_group_config_name_l2(bgp->rfapi_cfg, name,
4016
0
               criteria, search_cb);
4017
0
    break;
4018
0
  default:
4019
0
    flog_err(EC_LIB_DEVELOPMENT, "%s: Unknown group type=%d",
4020
0
       __func__, type);
4021
    /* should never happen */
4022
0
    assert("Unknown type" == NULL);
4023
0
    break;
4024
0
  }
4025
0
  return ret;
4026
0
}
4027
4028
/*------------------------------------------
4029
 * rfapi_rfp_get_l2_group_config_ptr_lni
4030
 *
4031
 * This is used to get group specific configuration pointer.
4032
 * Group is identified by type and logical network identifier.
4033
 * RFAPI frees rfp_cfg_group when group is deleted during reconfig,
4034
 * bgp restart or shutdown.
4035
 *
4036
 * input:
4037
 *    rfp_start_val     value returned by rfp_start
4038
 *    type              group type
4039
 *    logical_net_id    group logical network identifier
4040
 *    criteria          RFAPI caller provided search criteria
4041
 *    search_cb         optional rfp_group_config_search_cb_t
4042
 *
4043
 * output:
4044
 *    none
4045
 *
4046
 * return value:
4047
 *    rfp_cfg_group     Pointer to configuration structure
4048
--------------------------------------------*/
4049
void *
4050
rfapi_rfp_get_l2_group_config_ptr_lni(void *rfp_start_val,
4051
              uint32_t logical_net_id, void *criteria,
4052
              rfp_group_config_search_cb_t *search_cb)
4053
0
{
4054
0
  struct bgp *bgp;
4055
0
  struct rfapi_l2_group_cfg *rfg;
4056
0
  struct listnode *node;
4057
4058
0
  if (rfp_start_val == NULL)
4059
0
    return NULL;
4060
4061
0
  bgp = rfapi_bgp_lookup_by_rfp(rfp_start_val);
4062
0
  if (!bgp || !bgp->rfapi_cfg)
4063
0
    return NULL;
4064
4065
0
  for (ALL_LIST_ELEMENTS_RO(bgp->rfapi_cfg->l2_groups, node, rfg)) {
4066
0
    if (rfg->logical_net_id == logical_net_id
4067
0
        && (search_cb == NULL
4068
0
      || !search_cb(criteria, rfg->rfp_cfg))) {
4069
0
      if (rfg->rfp_cfg == NULL)
4070
0
        vnc_zlog_debug_verbose(
4071
0
          "%s: returning rfp group config for lni=0",
4072
0
          __func__);
4073
0
      return rfg->rfp_cfg;
4074
0
    }
4075
0
  }
4076
0
  return NULL;
4077
0
}