Coverage Report

Created: 2025-10-08 06:07

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/frr/bgpd/rfapi/vnc_export_bgp.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
/*
9
 * File:  vnc_export_bgp.c
10
 * Purpose: Export routes to BGP directly (not via zebra)
11
 */
12
13
#include "lib/zebra.h"
14
#include "lib/prefix.h"
15
#include "lib/agg_table.h"
16
#include "lib/vty.h"
17
#include "lib/log.h"
18
#include "lib/stream.h"
19
#include "lib/memory.h"
20
#include "lib/linklist.h"
21
#include "lib/plist.h"
22
#include "lib/routemap.h"
23
#include "lib/lib_errors.h"
24
25
#include "bgpd/bgpd.h"
26
#include "bgpd/bgp_ecommunity.h"
27
#include "bgpd/bgp_attr.h"
28
#include "bgpd/bgp_aspath.h"
29
30
#include "bgpd/rfapi/vnc_export_bgp.h"
31
#include "bgpd/rfapi/vnc_export_bgp_p.h"
32
#include "bgpd/rfapi/vnc_export_table.h"
33
#include "bgpd/rfapi/bgp_rfapi_cfg.h"
34
#include "bgpd/rfapi/rfapi.h"
35
#include "bgpd/rfapi/rfapi_import.h"
36
#include "bgpd/rfapi/rfapi_private.h"
37
#include "bgpd/rfapi/rfapi_backend.h"
38
#include "bgpd/rfapi/rfapi_vty.h"
39
#include "bgpd/rfapi/vnc_debug.h"
40
41
42
static void vnc_direct_add_rn_group_rd(struct bgp *bgp,
43
               struct rfapi_nve_group_cfg *rfg,
44
               struct agg_node *rn, struct attr *attr,
45
               afi_t afi,
46
               struct rfapi_descriptor *irfd);
47
48
/***********************************************************************
49
 * Export methods that set nexthop to CE (from 5226 roo EC) BEGIN
50
 ***********************************************************************/
51
52
/*
53
 * Memory allocation approach: make a ghost attr that
54
 * has non-interned parts for the modifications. ghost attr
55
 * memory is allocated by caller.
56
 *
57
 *  - extract ce (=5226) EC and use as new nexthop
58
 *  - strip Tunnel Encap attr
59
 *  - copy all ECs
60
 */
61
static void encap_attr_export_ce(struct attr *new, struct attr *orig,
62
         struct prefix *use_nexthop)
63
0
{
64
  /*
65
   * Make "new" a ghost attr copy of "orig"
66
   */
67
0
  memset(new, 0, sizeof(struct attr));
68
0
  *new = *orig;
69
70
  /*
71
   * Set nexthop
72
   */
73
0
  switch (use_nexthop->family) {
74
0
  case AF_INET:
75
0
    new->nexthop = use_nexthop->u.prefix4;
76
0
    new->mp_nexthop_len = BGP_ATTR_NHLEN_IPV4; /* bytes */
77
0
    new->flag |= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP);
78
0
    break;
79
80
0
  case AF_INET6:
81
0
    new->mp_nexthop_global = use_nexthop->u.prefix6;
82
0
    new->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL; /* bytes */
83
0
    break;
84
85
0
  default:
86
0
    assert(0);
87
0
    break;
88
0
  }
89
90
  /*
91
   * Set MED
92
   *
93
   * Note that it will be deleted when BGP sends to any eBGP
94
   * peer unless PEER_FLAG_MED_UNCHANGED is set:
95
   *
96
   *          neighbor NEIGHBOR attribute-unchanged med
97
   */
98
0
  if (!CHECK_FLAG(new->flag, BGP_ATTR_MULTI_EXIT_DISC)) {
99
0
    if (CHECK_FLAG(new->flag, BGP_ATTR_LOCAL_PREF)) {
100
0
      if (new->local_pref > 255)
101
0
        new->med = 0;
102
0
      else
103
0
        new->med = 255 - new->local_pref;
104
0
    } else {
105
0
      new->med = 255; /* shouldn't happen */
106
0
    }
107
0
    new->flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
108
0
  }
109
110
  /*
111
   * "new" is now a ghost attr:
112
   *  - it owns an "extra" struct
113
   *  - it owns any non-interned parts
114
   *  - any references to interned parts are not counted
115
   *
116
   * Caller should, after using the attr, call:
117
   *  - bgp_attr_flush() to free non-interned parts
118
   */
119
0
}
120
121
static int getce(struct bgp *bgp, struct attr *attr, struct prefix *pfx_ce)
122
0
{
123
0
  uint8_t *ecp;
124
0
  uint32_t i;
125
0
  uint16_t localadmin = bgp->rfapi_cfg->resolve_nve_roo_local_admin;
126
0
  struct ecommunity *ecomm = bgp_attr_get_ecommunity(attr);
127
128
0
  for (ecp = ecomm->val, i = 0; i < ecomm->size;
129
0
       ++i, ecp += ECOMMUNITY_SIZE) {
130
131
0
    if (VNC_DEBUG(EXPORT_BGP_GETCE)) {
132
0
      vnc_zlog_debug_any(
133
0
        "%s: %02x %02x %02x %02x %02x %02x %02x %02x",
134
0
        __func__, ecp[0], ecp[1], ecp[2], ecp[3],
135
0
        ecp[4], ecp[5], ecp[6], ecp[7]);
136
0
    }
137
138
    /*
139
     * is it ROO?
140
     */
141
0
    if (ecp[0] != 1 || ecp[1] != 3) {
142
0
      continue;
143
0
    }
144
145
    /*
146
     * Match local admin value?
147
     */
148
0
    if (ecp[6] != ((localadmin & 0xff00) >> 8)
149
0
        || ecp[7] != (localadmin & 0xff))
150
0
      continue;
151
152
0
    memset((uint8_t *)pfx_ce, 0, sizeof(*pfx_ce));
153
0
    memcpy(&pfx_ce->u.prefix4, ecp + 2, 4);
154
0
    pfx_ce->family = AF_INET;
155
0
    pfx_ce->prefixlen = IPV4_MAX_BITLEN;
156
157
0
    return 0;
158
0
  }
159
0
  return -1;
160
0
}
161
162
163
void vnc_direct_bgp_add_route_ce(struct bgp *bgp, struct agg_node *rn,
164
         struct bgp_path_info *bpi)
165
0
{
166
0
  struct attr *attr = bpi->attr;
167
0
  struct peer *peer = bpi->peer;
168
0
  const struct prefix *prefix = agg_node_get_prefix(rn);
169
0
  afi_t afi = family2afi(prefix->family);
170
0
  struct bgp_dest *udest;
171
0
  struct bgp_path_info *ubpi;
172
0
  struct attr hattr;
173
0
  struct attr *iattr;
174
0
  struct prefix ce_nexthop;
175
0
  struct prefix post_routemap_nexthop;
176
177
178
0
  if (!afi) {
179
0
    flog_err(EC_LIB_DEVELOPMENT, "%s: can't get afi of route node",
180
0
       __func__);
181
0
    return;
182
0
  }
183
184
0
  if ((bpi->type != ZEBRA_ROUTE_BGP)
185
0
      || (bpi->sub_type != BGP_ROUTE_NORMAL
186
0
    && bpi->sub_type != BGP_ROUTE_RFP
187
0
    && bpi->sub_type != BGP_ROUTE_STATIC)) {
188
189
0
    vnc_zlog_debug_verbose(
190
0
      "%s: wrong route type/sub_type for export, skipping",
191
0
      __func__);
192
0
    return;
193
0
  }
194
195
  /* check bgp redist flag for vnc direct ("vpn") routes */
196
0
  if (!bgp->redist[afi][ZEBRA_ROUTE_VNC_DIRECT]) {
197
0
    vnc_zlog_debug_verbose(
198
0
      "%s: bgp redistribution of VNC direct routes is off",
199
0
      __func__);
200
0
    return;
201
0
  }
202
203
0
  if (!bgp->rfapi_cfg) {
204
0
    vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
205
0
               __func__);
206
0
    return;
207
0
  }
208
209
0
  if (!VNC_EXPORT_BGP_CE_ENABLED(bgp->rfapi_cfg)) {
210
0
    vnc_zlog_debug_verbose(
211
0
      "%s: export-to-bgp ce mode not enabled, skipping",
212
0
      __func__);
213
0
    return;
214
0
  }
215
216
  /*
217
   * prefix list check
218
   */
219
0
  if (bgp->rfapi_cfg->plist_export_bgp[afi]) {
220
0
    if (prefix_list_apply(bgp->rfapi_cfg->plist_export_bgp[afi],
221
0
              prefix)
222
0
        == PREFIX_DENY) {
223
0
      vnc_zlog_debug_verbose(
224
0
        "%s: prefix list denied, skipping", __func__);
225
0
      return;
226
0
    }
227
0
  }
228
229
230
  /*
231
   * Extract CE
232
   * This works only for IPv4 because IPv6 addresses are too big
233
   * to fit in an extended community
234
   */
235
0
  if (getce(bgp, attr, &ce_nexthop)) {
236
0
    vnc_zlog_debug_verbose("%s: EC has no encoded CE, skipping",
237
0
               __func__);
238
0
    return;
239
0
  }
240
241
  /*
242
   * Is this route already represented in the unicast RIB?
243
   * (look up prefix; compare route type, sub_type, peer, nexthop)
244
   */
245
0
  udest = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi, SAFI_UNICAST,
246
0
         prefix, NULL);
247
0
  for (ubpi = bgp_dest_get_bgp_path_info(udest); ubpi;
248
0
       ubpi = ubpi->next) {
249
0
    struct prefix unicast_nexthop;
250
251
0
    if (CHECK_FLAG(ubpi->flags, BGP_PATH_REMOVED))
252
0
      continue;
253
254
0
    rfapiUnicastNexthop2Prefix(afi, ubpi->attr, &unicast_nexthop);
255
256
0
    if (ubpi->type == ZEBRA_ROUTE_VNC_DIRECT
257
0
        && ubpi->sub_type == BGP_ROUTE_REDISTRIBUTE
258
0
        && ubpi->peer == peer
259
0
        && prefix_same(&unicast_nexthop, &ce_nexthop)) {
260
261
0
      vnc_zlog_debug_verbose(
262
0
        "%s: already have matching exported unicast route, skipping",
263
0
        __func__);
264
0
      return;
265
0
    }
266
0
  }
267
268
  /*
269
   * Construct new attribute set with CE addr as
270
   * nexthop and without Tunnel Encap attr
271
   */
272
0
  encap_attr_export_ce(&hattr, attr, &ce_nexthop);
273
0
  if (bgp->rfapi_cfg->routemap_export_bgp) {
274
0
    struct bgp_path_info info;
275
0
    route_map_result_t ret;
276
277
0
    memset(&info, 0, sizeof(info));
278
0
    info.peer = peer;
279
0
    info.attr = &hattr;
280
0
    ret = route_map_apply(bgp->rfapi_cfg->routemap_export_bgp,
281
0
              prefix, &info);
282
0
    if (ret == RMAP_DENYMATCH) {
283
0
      bgp_attr_flush(&hattr);
284
0
      return;
285
0
    }
286
0
  }
287
288
0
  iattr = bgp_attr_intern(&hattr);
289
0
  bgp_attr_flush(&hattr);
290
291
  /*
292
   * Rule: disallow route-map alteration of next-hop, because it
293
   * would make it too difficult to keep track of the correspondence
294
   * between VPN routes and unicast routes.
295
   */
296
0
  rfapiUnicastNexthop2Prefix(afi, iattr, &post_routemap_nexthop);
297
298
0
  if (!prefix_same(&ce_nexthop, &post_routemap_nexthop)) {
299
0
    vnc_zlog_debug_verbose(
300
0
      "%s: route-map modification of nexthop not allowed, skipping",
301
0
      __func__);
302
0
    bgp_attr_unintern(&iattr);
303
0
    return;
304
0
  }
305
306
0
  bgp_update(peer, prefix, 0, /* addpath_id */
307
0
       iattr,    /* bgp_update copies this attr */
308
0
       afi, SAFI_UNICAST, ZEBRA_ROUTE_VNC_DIRECT,
309
0
       BGP_ROUTE_REDISTRIBUTE, NULL, /* RD not used for unicast */
310
0
       NULL, 0,       /* tag not used for unicast */
311
0
       0, NULL);       /* EVPN not used */
312
0
  bgp_attr_unintern(&iattr);
313
0
}
314
315
316
/*
317
 * "Withdrawing a Route" export process
318
 */
319
void vnc_direct_bgp_del_route_ce(struct bgp *bgp, struct agg_node *rn,
320
         struct bgp_path_info *bpi)
321
0
{
322
0
  const struct prefix *p = agg_node_get_prefix(rn);
323
0
  afi_t afi = family2afi(p->family);
324
0
  struct bgp_path_info *vbpi;
325
0
  struct prefix ce_nexthop;
326
327
0
  if (!afi) {
328
0
    flog_err(EC_LIB_DEVELOPMENT, "%s: bad afi", __func__);
329
0
    return;
330
0
  }
331
332
  /* check bgp redist flag for vnc direct ("vpn") routes */
333
0
  if (!bgp->redist[afi][ZEBRA_ROUTE_VNC_DIRECT]) {
334
0
    vnc_zlog_debug_verbose(
335
0
      "%s: bgp redistribution of VNC direct routes is off",
336
0
      __func__);
337
0
    return;
338
0
  }
339
340
0
  if (!bgp->rfapi_cfg) {
341
0
    vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
342
0
               __func__);
343
0
    return;
344
0
  }
345
0
  if (!VNC_EXPORT_BGP_CE_ENABLED(bgp->rfapi_cfg)) {
346
0
    vnc_zlog_debug_verbose(
347
0
      "%s: export-to-bgp ce mode not enabled, skipping",
348
0
      __func__);
349
0
    return;
350
0
  }
351
352
  /*
353
   * Extract CE
354
   * This works only for IPv4 because IPv6 addresses are too big
355
   * to fit in an extended community
356
   */
357
0
  if (getce(bgp, bpi->attr, &ce_nexthop)) {
358
0
    vnc_zlog_debug_verbose("%s: EC has no encoded CE, skipping",
359
0
               __func__);
360
0
    return;
361
0
  }
362
363
  /*
364
   * Look for other VPN routes with same prefix, same 5226 CE,
365
   * same peer. If at least one is present, don't remove the
366
   * route from the unicast RIB
367
   */
368
369
0
  for (vbpi = rn->info; vbpi; vbpi = vbpi->next) {
370
0
    struct prefix ce;
371
0
    if (bpi == vbpi)
372
0
      continue;
373
0
    if (bpi->peer != vbpi->peer)
374
0
      continue;
375
0
    if (getce(bgp, vbpi->attr, &ce))
376
0
      continue;
377
0
    if (prefix_same(&ce, &ce_nexthop)) {
378
0
      vnc_zlog_debug_verbose(
379
0
        "%s: still have a route via CE, not deleting unicast",
380
0
        __func__);
381
0
      return;
382
0
    }
383
0
  }
384
385
  /*
386
   * withdraw the route
387
   */
388
0
  bgp_withdraw(bpi->peer, p, 0, /* addpath_id */
389
0
         afi, SAFI_UNICAST, ZEBRA_ROUTE_VNC_DIRECT,
390
0
         BGP_ROUTE_REDISTRIBUTE, NULL, /* RD not used for unicast */
391
0
         NULL, 0, NULL); /* tag not used for unicast */
392
0
}
393
394
static void vnc_direct_bgp_vpn_enable_ce(struct bgp *bgp, afi_t afi)
395
0
{
396
0
  struct agg_node *rn;
397
0
  struct bgp_path_info *ri;
398
399
0
  vnc_zlog_debug_verbose("%s: entry, afi=%d", __func__, afi);
400
401
0
  if (!bgp)
402
0
    return;
403
404
0
  if (!(bgp->rfapi_cfg))
405
0
    return;
406
407
0
  if (!VNC_EXPORT_BGP_CE_ENABLED(bgp->rfapi_cfg)) {
408
0
    vnc_zlog_debug_verbose(
409
0
      "%s: export of CE routes not enabled, skipping",
410
0
      __func__);
411
0
    return;
412
0
  }
413
414
0
  if (afi != AFI_IP && afi != AFI_IP6) {
415
0
    vnc_zlog_debug_verbose("%s: bad afi: %d", __func__, afi);
416
0
    return;
417
0
  }
418
419
  /*
420
   * Go through entire ce import table and export to BGP unicast.
421
   */
422
0
  for (rn = agg_route_top(bgp->rfapi->it_ce->imported_vpn[afi]); rn;
423
0
       rn = agg_route_next(rn)) {
424
0
    if (!rn->info)
425
0
      continue;
426
427
0
    vnc_zlog_debug_verbose("%s: checking prefix %pRN", __func__,
428
0
               rn);
429
430
0
    for (ri = rn->info; ri; ri = ri->next) {
431
432
0
      vnc_zlog_debug_verbose("%s: ri->sub_type: %d", __func__,
433
0
                 ri->sub_type);
434
435
0
      if (ri->sub_type == BGP_ROUTE_NORMAL
436
0
          || ri->sub_type == BGP_ROUTE_RFP
437
0
          || ri->sub_type == BGP_ROUTE_STATIC) {
438
439
0
        vnc_direct_bgp_add_route_ce(bgp, rn, ri);
440
0
      }
441
0
    }
442
0
  }
443
0
}
444
445
static void vnc_direct_bgp_vpn_disable_ce(struct bgp *bgp, afi_t afi)
446
0
{
447
0
  struct bgp_dest *dest;
448
449
0
  vnc_zlog_debug_verbose("%s: entry, afi=%d", __func__, afi);
450
451
0
  if (!bgp)
452
0
    return;
453
454
0
  if (afi != AFI_IP && afi != AFI_IP6) {
455
0
    vnc_zlog_debug_verbose("%s: bad afi: %d", __func__, afi);
456
0
    return;
457
0
  }
458
459
  /*
460
   * Go through the entire BGP unicast table and remove routes that
461
   * originated from us
462
   */
463
0
  for (dest = bgp_table_top(bgp->rib[afi][SAFI_UNICAST]); dest;
464
0
       dest = bgp_route_next(dest)) {
465
466
0
    struct bgp_path_info *ri;
467
0
    struct bgp_path_info *next;
468
469
0
    for (ri = bgp_dest_get_bgp_path_info(dest), next = NULL; ri;
470
0
         ri = next) {
471
472
0
      next = ri->next;
473
474
0
      if (ri->type == ZEBRA_ROUTE_VNC_DIRECT
475
0
          && ri->sub_type == BGP_ROUTE_REDISTRIBUTE) {
476
477
0
        bgp_withdraw(
478
0
          ri->peer, bgp_dest_get_prefix(dest),
479
0
          0,    /* addpath_id */
480
0
          AFI_IP, SAFI_UNICAST,
481
0
          ZEBRA_ROUTE_VNC_DIRECT,
482
0
          BGP_ROUTE_REDISTRIBUTE,
483
0
          NULL, /* RD not used for unicast */
484
0
          NULL, 0,
485
0
          NULL); /* tag not used for unicast */
486
0
      }
487
0
    }
488
0
  }
489
0
}
490
491
/***********************************************************************
492
 * Export methods that set nexthop to CE (from 5226 roo EC) END
493
 ***********************************************************************/
494
495
/***********************************************************************
496
 * Export methods that proxy nexthop BEGIN
497
 ***********************************************************************/
498
499
static struct ecommunity *vnc_route_origin_ecom(struct agg_node *rn)
500
0
{
501
0
  struct ecommunity *new;
502
0
  struct bgp_path_info *bpi;
503
504
0
  if (!rn->info)
505
0
    return NULL;
506
507
0
  new = ecommunity_new();
508
509
0
  for (bpi = rn->info; bpi; bpi = bpi->next) {
510
511
0
    struct ecommunity_val roec;
512
513
0
    switch (BGP_MP_NEXTHOP_FAMILY(bpi->attr->mp_nexthop_len)) {
514
0
    case AF_INET:
515
0
      memset(&roec, 0, sizeof(roec));
516
0
      roec.val[0] = 0x01;
517
0
      roec.val[1] = 0x03;
518
0
      memcpy(roec.val + 2,
519
0
             &bpi->attr->mp_nexthop_global_in.s_addr, 4);
520
0
      roec.val[6] = 0;
521
0
      roec.val[7] = 0;
522
0
      ecommunity_add_val(new, &roec, false, false);
523
0
      break;
524
0
    case AF_INET6:
525
      /* No support for IPv6 addresses in extended communities
526
       */
527
0
      break;
528
0
    }
529
0
  }
530
531
0
  if (!new->size) {
532
0
    ecommunity_free(&new);
533
0
    new = NULL;
534
0
  }
535
536
0
  return new;
537
0
}
538
539
static struct ecommunity *vnc_route_origin_ecom_single(struct in_addr *origin)
540
0
{
541
0
  struct ecommunity *new;
542
0
  struct ecommunity_val roec;
543
544
0
  memset(&roec, 0, sizeof(roec));
545
0
  roec.val[0] = 0x01;
546
0
  roec.val[1] = 0x03;
547
0
  memcpy(roec.val + 2, &origin->s_addr, 4);
548
0
  roec.val[6] = 0;
549
0
  roec.val[7] = 0;
550
551
0
  new = ecommunity_new();
552
0
  ecommunity_add_val(new, &roec, false, false);
553
554
0
  if (!new->size) {
555
0
    ecommunity_free(&new);
556
0
    new = NULL;
557
0
  }
558
559
0
  return new;
560
0
}
561
562
563
/*
564
 * New memory allocation approach: make a ghost attr that
565
 * has non-interned parts for the modifications. ghost attr
566
 * memory is allocated by caller.
567
 */
568
static int
569
encap_attr_export(struct attr *new, struct attr *orig,
570
      struct prefix *new_nexthop,
571
      struct agg_node *rn) /* for VN addrs for ecom list */
572
               /* if rn is 0, use route's nexthop */
573
0
{
574
0
  struct prefix orig_nexthop;
575
0
  struct prefix *use_nexthop;
576
0
  static struct ecommunity *ecom_ro;
577
578
0
  if (new_nexthop) {
579
0
    use_nexthop = new_nexthop;
580
0
  } else {
581
0
    use_nexthop = &orig_nexthop;
582
0
    orig_nexthop.family =
583
0
      BGP_MP_NEXTHOP_FAMILY(orig->mp_nexthop_len);
584
0
    if (orig_nexthop.family == AF_INET) {
585
0
      orig_nexthop.prefixlen = IPV4_MAX_BITLEN;
586
0
      orig_nexthop.u.prefix4 = orig->mp_nexthop_global_in;
587
0
    } else if (orig_nexthop.family == AF_INET6) {
588
0
      orig_nexthop.prefixlen = IPV6_MAX_BITLEN;
589
0
      orig_nexthop.u.prefix6 = orig->mp_nexthop_global;
590
0
    } else {
591
0
      return -1; /* FAIL - can't compute nexthop */
592
0
    }
593
0
  }
594
595
596
  /*
597
   * Make "new" a ghost attr copy of "orig"
598
   */
599
0
  memset(new, 0, sizeof(struct attr));
600
0
  *new = *orig;
601
602
  /*
603
   * Set nexthop
604
   */
605
0
  switch (use_nexthop->family) {
606
0
  case AF_INET:
607
0
    new->nexthop = use_nexthop->u.prefix4;
608
0
    new->mp_nexthop_len = BGP_ATTR_NHLEN_IPV4; /* bytes */
609
0
    new->flag |= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP);
610
0
    break;
611
612
0
  case AF_INET6:
613
0
    new->mp_nexthop_global = use_nexthop->u.prefix6;
614
0
    new->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL; /* bytes */
615
0
    break;
616
617
0
  default:
618
0
    assert(0);
619
0
    break;
620
0
  }
621
622
0
  if (rn) {
623
0
    ecom_ro = vnc_route_origin_ecom(rn);
624
0
  } else {
625
    /* TBD  use lcom for IPv6 */
626
0
    ecom_ro = vnc_route_origin_ecom_single(&use_nexthop->u.prefix4);
627
0
  }
628
0
  if (bgp_attr_get_ecommunity(new)) {
629
0
    if (ecom_ro)
630
0
      bgp_attr_set_ecommunity(
631
0
        new,
632
0
        ecommunity_merge(ecom_ro,
633
0
             bgp_attr_get_ecommunity(new)));
634
0
  } else {
635
0
    bgp_attr_set_ecommunity(new, ecom_ro);
636
0
  }
637
638
  /*
639
   * Set MED
640
   *
641
   * Note that it will be deleted when BGP sends to any eBGP
642
   * peer unless PEER_FLAG_MED_UNCHANGED is set:
643
   *
644
   *          neighbor NEIGHBOR attribute-unchanged med
645
   */
646
0
  if (!CHECK_FLAG(new->flag, BGP_ATTR_MULTI_EXIT_DISC)) {
647
0
    if (CHECK_FLAG(new->flag, BGP_ATTR_LOCAL_PREF)) {
648
0
      if (new->local_pref > 255)
649
0
        new->med = 0;
650
0
      else
651
0
        new->med = 255 - new->local_pref;
652
0
    } else {
653
0
      new->med = 255; /* shouldn't happen */
654
0
    }
655
0
    new->flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
656
0
  }
657
658
  /*
659
   * "new" is now a ghost attr:
660
   *  - it owns an "extra" struct
661
   *  - it owns any non-interned parts
662
   *  - any references to interned parts are not counted
663
   *
664
   * Caller should, after using the attr, call:
665
   *  - bgp_attr_flush() to free non-interned parts
666
   */
667
668
0
  return 0;
669
0
}
670
671
/*
672
 * "Adding a Route" export process
673
 */
674
void vnc_direct_bgp_add_prefix(struct bgp *bgp,
675
             struct rfapi_import_table *import_table,
676
             struct agg_node *rn)
677
0
{
678
0
  struct attr attr = {0};
679
0
  struct listnode *node, *nnode;
680
0
  struct rfapi_rfg_name *rfgn;
681
0
  const struct prefix *p = agg_node_get_prefix(rn);
682
0
  afi_t afi = family2afi(p->family);
683
684
0
  if (!afi) {
685
0
    flog_err(EC_LIB_DEVELOPMENT, "%s: can't get afi of route node",
686
0
       __func__);
687
0
    return;
688
0
  }
689
690
  /* check bgp redist flag for vnc direct ("vpn") routes */
691
0
  if (!bgp->redist[afi][ZEBRA_ROUTE_VNC_DIRECT]) {
692
0
    vnc_zlog_debug_verbose(
693
0
      "%s: bgp redistribution of VNC direct routes is off",
694
0
      __func__);
695
0
    return;
696
0
  }
697
698
0
  if (!bgp->rfapi_cfg) {
699
0
    vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
700
0
               __func__);
701
0
    return;
702
0
  }
703
704
0
  if (!VNC_EXPORT_BGP_GRP_ENABLED(bgp->rfapi_cfg)) {
705
0
    vnc_zlog_debug_verbose(
706
0
      "%s: export-to-bgp group mode not enabled, skipping",
707
0
      __func__);
708
0
    return;
709
0
  }
710
711
0
  if (!listcount(bgp->rfapi_cfg->rfg_export_direct_bgp_l)) {
712
0
    vnc_zlog_debug_verbose(
713
0
      "%s: no bgp-direct export nve group, skipping",
714
0
      __func__);
715
0
    return;
716
0
  }
717
718
0
  bgp_attr_default_set(&attr, bgp, BGP_ORIGIN_INCOMPLETE);
719
  /* TBD set some configured med, see add_vnc_route() */
720
721
0
  vnc_zlog_debug_verbose(
722
0
    "%s: looping over nve-groups in direct-bgp export list",
723
0
    __func__);
724
725
0
  for (ALL_LIST_ELEMENTS(bgp->rfapi_cfg->rfg_export_direct_bgp_l, node,
726
0
             nnode, rfgn)) {
727
728
0
    struct listnode *ln;
729
730
    /*
731
     * If nve group is not defined yet, skip it
732
     */
733
0
    if (!rfgn->rfg)
734
0
      continue;
735
736
    /*
737
     * If the nve group uses a different import table, skip it
738
     */
739
0
    if (import_table != rfgn->rfg->rfapi_import_table)
740
0
      continue;
741
742
    /*
743
     * if no NVEs currently associated with this group, skip it
744
     */
745
0
    if (rfgn->rfg->type != RFAPI_GROUP_CFG_VRF && !rfgn->rfg->nves)
746
0
      continue;
747
748
    /*
749
     * per-nve-group prefix list check
750
     */
751
0
    if (rfgn->rfg->plist_export_bgp[afi]) {
752
0
      if (prefix_list_apply(rfgn->rfg->plist_export_bgp[afi],
753
0
                p)
754
0
          == PREFIX_DENY)
755
756
0
        continue;
757
0
    }
758
759
0
    if (rfgn->rfg->type == RFAPI_GROUP_CFG_VRF) {
760
0
      vnc_direct_add_rn_group_rd(bgp, rfgn->rfg, rn, &attr,
761
0
               afi, rfgn->rfg->rfd);
762
      /*
763
       * yuck!
764
       *  - but consistent with rest of function
765
       */
766
0
      continue;
767
0
    }
768
    /*
769
     * For each NVE that is assigned to the export nve group,
770
     * generate
771
     * a route with that NVE as its next hop
772
     */
773
0
    for (ln = listhead(rfgn->rfg->nves); ln;
774
0
         ln = listnextnode(ln)) {
775
0
      vnc_direct_add_rn_group_rd(bgp, rfgn->rfg, rn, &attr,
776
0
               afi, listgetdata(ln));
777
0
    }
778
0
  }
779
780
0
  aspath_unintern(&attr.aspath);
781
0
}
782
783
/*
784
 * "Withdrawing a Route" export process
785
 */
786
void vnc_direct_bgp_del_prefix(struct bgp *bgp,
787
             struct rfapi_import_table *import_table,
788
             struct agg_node *rn)
789
0
{
790
0
  struct listnode *node, *nnode;
791
0
  struct rfapi_rfg_name *rfgn;
792
0
  const struct prefix *p = agg_node_get_prefix(rn);
793
0
  afi_t afi = family2afi(p->family);
794
795
0
  if (!afi) {
796
0
    flog_err(EC_LIB_DEVELOPMENT, "%s: can't get afi route node",
797
0
       __func__);
798
0
    return;
799
0
  }
800
801
  /* check bgp redist flag for vnc direct ("vpn") routes */
802
0
  if (!bgp->redist[afi][ZEBRA_ROUTE_VNC_DIRECT]) {
803
0
    vnc_zlog_debug_verbose(
804
0
      "%s: bgp redistribution of VNC direct routes is off",
805
0
      __func__);
806
0
    return;
807
0
  }
808
809
0
  if (!bgp->rfapi_cfg) {
810
0
    vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
811
0
               __func__);
812
0
    return;
813
0
  }
814
815
0
  if (!VNC_EXPORT_BGP_GRP_ENABLED(bgp->rfapi_cfg)) {
816
0
    vnc_zlog_debug_verbose(
817
0
      "%s: export-to-bgp group mode not enabled, skipping",
818
0
      __func__);
819
0
    return;
820
0
  }
821
822
0
  if (!listcount(bgp->rfapi_cfg->rfg_export_direct_bgp_l)) {
823
0
    vnc_zlog_debug_verbose(
824
0
      "%s: no bgp-direct export nve group, skipping",
825
0
      __func__);
826
0
    return;
827
0
  }
828
829
0
  for (ALL_LIST_ELEMENTS(bgp->rfapi_cfg->rfg_export_direct_bgp_l, node,
830
0
             nnode, rfgn)) {
831
832
0
    struct listnode *ln;
833
834
    /*
835
     * If nve group is not defined yet, skip it
836
     */
837
0
    if (!rfgn->rfg)
838
0
      continue;
839
840
    /*
841
     * if no NVEs currently associated with this group, skip it
842
     */
843
0
    if (rfgn->rfg->type != RFAPI_GROUP_CFG_VRF && !rfgn->rfg->nves)
844
0
      continue;
845
846
    /*
847
     * If the nve group uses a different import table,
848
     * skip it
849
     */
850
0
    if (import_table != rfgn->rfg->rfapi_import_table)
851
0
      continue;
852
853
0
    if (rfgn->rfg->type == RFAPI_GROUP_CFG_VRF) {
854
0
      struct prefix nhp;
855
0
      struct rfapi_descriptor *irfd;
856
857
0
      irfd = rfgn->rfg->rfd;
858
859
0
      if (rfapiRaddr2Qprefix(&irfd->vn_addr, &nhp))
860
0
        continue;
861
862
0
      bgp_withdraw(irfd->peer, p, /* prefix */
863
0
             0,       /* addpath_id */
864
0
             afi, SAFI_UNICAST, ZEBRA_ROUTE_VNC_DIRECT,
865
0
             BGP_ROUTE_REDISTRIBUTE,
866
0
             NULL, /* RD not used for unicast */
867
0
             NULL, 0,
868
0
             NULL); /* tag not used for unicast */
869
      /*
870
       * yuck!
871
       *  - but consistent with rest of function
872
       */
873
0
      continue;
874
0
    }
875
    /*
876
     * For each NVE that is assigned to the export nve group,
877
     * generate
878
     * a route with that NVE as its next hop
879
     */
880
0
    for (ln = listhead(rfgn->rfg->nves); ln;
881
0
         ln = listnextnode(ln)) {
882
883
0
      struct prefix nhp;
884
0
      struct rfapi_descriptor *irfd;
885
886
0
      irfd = listgetdata(ln);
887
888
0
      if (rfapiRaddr2Qprefix(&irfd->vn_addr, &nhp))
889
0
        continue;
890
891
0
      bgp_withdraw(irfd->peer, p, /* prefix */
892
0
             0,       /* addpath_id */
893
0
             afi, SAFI_UNICAST, ZEBRA_ROUTE_VNC_DIRECT,
894
0
             BGP_ROUTE_REDISTRIBUTE,
895
0
             NULL, /* RD not used for unicast */
896
0
             NULL, 0,
897
0
             NULL); /* tag not used for unicast */
898
0
    }
899
0
  }
900
0
}
901
902
void vnc_direct_bgp_add_nve(struct bgp *bgp, struct rfapi_descriptor *rfd)
903
0
{
904
0
  struct listnode *node, *nnode;
905
0
  struct rfapi_rfg_name *rfgn;
906
0
  struct rfapi_nve_group_cfg *rfg = rfd->rfg;
907
0
  afi_t afi = family2afi(rfd->vn_addr.addr_family);
908
909
0
  if (!afi) {
910
0
    flog_err(EC_LIB_DEVELOPMENT, "%s: can't get afi of nve vn addr",
911
0
       __func__);
912
0
    return;
913
0
  }
914
915
0
  if (!bgp)
916
0
    return;
917
0
  if (!bgp->rfapi_cfg) {
918
0
    vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
919
0
               __func__);
920
0
    return;
921
0
  }
922
0
  if (!VNC_EXPORT_BGP_GRP_ENABLED(bgp->rfapi_cfg)) {
923
0
    vnc_zlog_debug_verbose(
924
0
      "%s: export-to-bgp group mode not enabled, skipping",
925
0
      __func__);
926
0
    return;
927
0
  }
928
929
0
  if (!bgp->redist[afi][ZEBRA_ROUTE_VNC_DIRECT]) {
930
0
    vnc_zlog_debug_verbose(
931
0
      "%s: bgp redistribution of VNC direct routes is off",
932
0
      __func__);
933
0
    return;
934
0
  }
935
936
  /*
937
   * Loop over the list of NVE-Groups configured for
938
   * exporting to direct-bgp and see if this new NVE's
939
   * group is among them.
940
   */
941
0
  for (ALL_LIST_ELEMENTS(bgp->rfapi_cfg->rfg_export_direct_bgp_l, node,
942
0
             nnode, rfgn)) {
943
944
    /*
945
     * Yes, this NVE's group is configured for export to direct-bgp
946
     */
947
0
    if (rfgn->rfg == rfg) {
948
949
0
      struct agg_table *rt = NULL;
950
0
      struct agg_node *rn;
951
0
      struct attr attr = {0};
952
0
      struct rfapi_import_table *import_table;
953
954
955
0
      import_table = rfg->rfapi_import_table;
956
957
0
      if (afi == AFI_IP || afi == AFI_IP6) {
958
0
        rt = import_table->imported_vpn[afi];
959
0
      } else {
960
0
        flog_err(EC_LIB_DEVELOPMENT, "%s: bad afi %d",
961
0
           __func__, afi);
962
0
        return;
963
0
      }
964
965
0
      bgp_attr_default_set(&attr, bgp, BGP_ORIGIN_INCOMPLETE);
966
      /* TBD set some configured med, see add_vnc_route() */
967
968
      /*
969
       * Walk the NVE-Group's VNC Import table
970
       */
971
0
      for (rn = agg_route_top(rt); rn;
972
0
           rn = agg_route_next(rn)) {
973
974
0
        if (rn->info) {
975
976
0
          struct prefix nhp;
977
0
          struct rfapi_descriptor *irfd = rfd;
978
0
          struct attr hattr;
979
0
          struct attr *iattr;
980
0
          struct bgp_path_info info;
981
0
          const struct prefix *p =
982
0
            agg_node_get_prefix(rn);
983
984
0
          if (rfapiRaddr2Qprefix(&irfd->vn_addr,
985
0
                     &nhp))
986
0
            continue;
987
988
          /*
989
           * per-nve-group prefix list check
990
           */
991
0
          if (rfgn->rfg->plist_export_bgp[afi]) {
992
0
            if (prefix_list_apply(
993
0
                  rfgn->rfg->plist_export_bgp
994
0
                    [afi],
995
0
                  p)
996
0
                == PREFIX_DENY)
997
998
0
              continue;
999
0
          }
1000
1001
1002
          /*
1003
           * Construct new attribute set with
1004
           * NVE's VN addr as
1005
           * nexthop and without Tunnel Encap attr
1006
           */
1007
0
          if (encap_attr_export(&hattr, &attr,
1008
0
                    &nhp, rn))
1009
0
            continue;
1010
1011
0
          if (rfgn->rfg->routemap_export_bgp) {
1012
0
            route_map_result_t ret;
1013
0
            info.peer = irfd->peer;
1014
0
            info.attr = &hattr;
1015
0
            ret = route_map_apply(
1016
0
              rfgn->rfg
1017
0
                ->routemap_export_bgp,
1018
0
              p, &info);
1019
0
            if (ret == RMAP_DENYMATCH) {
1020
0
              bgp_attr_flush(&hattr);
1021
0
              continue;
1022
0
            }
1023
0
          }
1024
1025
0
          iattr = bgp_attr_intern(&hattr);
1026
0
          bgp_attr_flush(&hattr);
1027
0
          bgp_update(
1028
0
            irfd->peer, p, /* prefix */
1029
0
            0,         /* addpath_id */
1030
0
            iattr, /* bgp_update copies
1031
                it */
1032
0
            afi, SAFI_UNICAST,
1033
0
            ZEBRA_ROUTE_VNC_DIRECT,
1034
0
            BGP_ROUTE_REDISTRIBUTE, NULL,
1035
            /* RD not used for unicast */
1036
0
            NULL,
1037
            /* tag not used for unicast */
1038
0
            0, 0, NULL); /* EVPN not used */
1039
1040
0
          bgp_attr_unintern(&iattr);
1041
0
        }
1042
0
      }
1043
1044
0
      aspath_unintern(&attr.aspath);
1045
0
    }
1046
0
  }
1047
0
}
1048
1049
1050
void vnc_direct_bgp_del_nve(struct bgp *bgp, struct rfapi_descriptor *rfd)
1051
0
{
1052
0
  struct listnode *node, *nnode;
1053
0
  struct rfapi_rfg_name *rfgn;
1054
0
  struct rfapi_nve_group_cfg *rfg = rfd->rfg;
1055
0
  afi_t afi = family2afi(rfd->vn_addr.addr_family);
1056
1057
0
  if (!afi) {
1058
0
    flog_err(EC_LIB_DEVELOPMENT, "%s: can't get afi of nve vn addr",
1059
0
       __func__);
1060
0
    return;
1061
0
  }
1062
1063
0
  if (!bgp)
1064
0
    return;
1065
0
  if (!bgp->rfapi_cfg) {
1066
0
    vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
1067
0
               __func__);
1068
0
    return;
1069
0
  }
1070
0
  if (!VNC_EXPORT_BGP_GRP_ENABLED(bgp->rfapi_cfg)) {
1071
0
    vnc_zlog_debug_verbose(
1072
0
      "%s: export-to-bgp group mode not enabled, skipping",
1073
0
      __func__);
1074
0
    return;
1075
0
  }
1076
1077
0
  if (!bgp->redist[afi][ZEBRA_ROUTE_VNC_DIRECT]) {
1078
0
    vnc_zlog_debug_verbose(
1079
0
      "%s: bgp redistribution of VNC direct routes is off",
1080
0
      __func__);
1081
0
    return;
1082
0
  }
1083
1084
  /*
1085
   * Loop over the list of NVE-Groups configured for
1086
   * exporting to direct-bgp and see if this new NVE's
1087
   * group is among them.
1088
   */
1089
0
  for (ALL_LIST_ELEMENTS(bgp->rfapi_cfg->rfg_export_direct_bgp_l, node,
1090
0
             nnode, rfgn)) {
1091
1092
    /*
1093
     * Yes, this NVE's group is configured for export to direct-bgp
1094
     */
1095
0
    if (rfg && rfgn->rfg == rfg) {
1096
1097
0
      struct agg_table *rt = NULL;
1098
0
      struct agg_node *rn;
1099
0
      struct rfapi_import_table *import_table;
1100
1101
0
      import_table = rfg->rfapi_import_table;
1102
1103
0
      if (afi == AFI_IP || afi == AFI_IP6) {
1104
0
        rt = import_table->imported_vpn[afi];
1105
0
      } else {
1106
0
        flog_err(EC_LIB_DEVELOPMENT, "%s: bad afi %d",
1107
0
           __func__, afi);
1108
0
        return;
1109
0
      }
1110
1111
      /*
1112
       * Walk the NVE-Group's VNC Import table
1113
       */
1114
0
      for (rn = agg_route_top(rt); rn;
1115
0
           rn = agg_route_next(rn)) {
1116
1117
0
        if (rn->info) {
1118
0
          const struct prefix *p =
1119
0
            agg_node_get_prefix(rn);
1120
0
          struct prefix nhp;
1121
0
          struct rfapi_descriptor *irfd = rfd;
1122
1123
0
          if (rfapiRaddr2Qprefix(&irfd->vn_addr,
1124
0
                     &nhp))
1125
0
            continue;
1126
1127
0
          bgp_withdraw(irfd->peer, p, /* prefix */
1128
0
                 0,    /* addpath_id */
1129
0
                 afi, SAFI_UNICAST,
1130
0
                 ZEBRA_ROUTE_VNC_DIRECT,
1131
0
                 BGP_ROUTE_REDISTRIBUTE,
1132
0
                 NULL, /* RD not used for
1133
                    unicast */
1134
0
                 NULL, 0, NULL); /* tag not
1135
                     used for
1136
                     unicast */
1137
0
        }
1138
0
      }
1139
0
    }
1140
0
  }
1141
0
}
1142
1143
static void vnc_direct_add_rn_group_rd(struct bgp *bgp,
1144
               struct rfapi_nve_group_cfg *rfg,
1145
               struct agg_node *rn, struct attr *attr,
1146
               afi_t afi, struct rfapi_descriptor *irfd)
1147
0
{
1148
0
  struct prefix nhp;
1149
0
  struct bgp_path_info info;
1150
0
  struct attr hattr;
1151
0
  struct attr *iattr;
1152
0
  const struct prefix *p = agg_node_get_prefix(rn);
1153
1154
0
  if (irfd == NULL && rfg->type != RFAPI_GROUP_CFG_VRF) {
1155
    /* need new rfapi_handle, for peer strcture
1156
     * -- based on vnc_add_vrf_prefi */
1157
0
    assert(rfg->rfd == NULL);
1158
1159
0
    if (!rfg->rt_export_list || !rfg->rfapi_import_table) {
1160
0
      vnc_zlog_debug_verbose(
1161
0
        "%s: VRF \"%s\" is missing RT import/export configuration.",
1162
0
        __func__, rfg->name);
1163
0
      return;
1164
0
    }
1165
0
    if (!rfg->rd.prefixlen) {
1166
0
      vnc_zlog_debug_verbose(
1167
0
        "%s: VRF \"%s\" is missing RD configuration.",
1168
0
        __func__, rfg->name);
1169
0
      return;
1170
0
    }
1171
0
    if (rfg->label > MPLS_LABEL_MAX) {
1172
0
      vnc_zlog_debug_verbose(
1173
0
        "%s: VRF \"%s\" is missing default label configuration.",
1174
0
        __func__, rfg->name);
1175
0
      return;
1176
0
    }
1177
1178
0
    irfd = XCALLOC(MTYPE_RFAPI_DESC,
1179
0
             sizeof(struct rfapi_descriptor));
1180
0
    irfd->bgp = bgp;
1181
0
    rfg->rfd = irfd;
1182
    /*
1183
     * leave most fields empty as will get from (dynamic) config
1184
     * when needed
1185
     */
1186
0
    irfd->default_tunneltype_option.type = BGP_ENCAP_TYPE_MPLS;
1187
0
    irfd->cookie = rfg;
1188
0
    if (rfg->vn_prefix.family
1189
0
        && !CHECK_FLAG(rfg->flags, RFAPI_RFG_VPN_NH_SELF)) {
1190
0
      rfapiQprefix2Raddr(&rfg->vn_prefix, &irfd->vn_addr);
1191
0
    } else {
1192
0
      memset(&irfd->vn_addr, 0, sizeof(struct rfapi_ip_addr));
1193
0
      irfd->vn_addr.addr_family = AF_INET;
1194
0
      irfd->vn_addr.addr.v4 = bgp->router_id;
1195
0
    }
1196
0
    irfd->un_addr = irfd->vn_addr; /* sigh, need something in UN for
1197
            lookups */
1198
0
    vnc_zlog_debug_verbose("%s: Opening RFD for VRF %s", __func__,
1199
0
               rfg->name);
1200
0
    rfapi_init_and_open(bgp, irfd, rfg);
1201
0
  }
1202
1203
0
  if (irfd == NULL || rfapiRaddr2Qprefix(&irfd->vn_addr, &nhp))
1204
0
    return;
1205
1206
  /*
1207
   * Construct new attribute set with NVE's VN
1208
   * addr as
1209
   * nexthop and without Tunnel Encap attr
1210
   */
1211
0
  if (encap_attr_export(&hattr, attr, &nhp, rn))
1212
0
    return;
1213
1214
0
  if (VNC_DEBUG(EXPORT_BGP_DIRECT_ADD)) {
1215
0
    vnc_zlog_debug_any("%s: attr follows", __func__);
1216
0
    rfapiPrintAttrPtrs(NULL, attr);
1217
0
    vnc_zlog_debug_any("%s: hattr follows", __func__);
1218
0
    rfapiPrintAttrPtrs(NULL, &hattr);
1219
0
  }
1220
1221
0
  if (rfg->routemap_export_bgp) {
1222
0
    route_map_result_t ret;
1223
1224
0
    info.peer = irfd->peer;
1225
0
    info.attr = &hattr;
1226
0
    ret = route_map_apply(rfg->routemap_export_bgp, p, &info);
1227
0
    if (ret == RMAP_DENYMATCH) {
1228
0
      bgp_attr_flush(&hattr);
1229
0
      vnc_zlog_debug_verbose(
1230
0
        "%s: route map says DENY, so not calling bgp_update",
1231
0
        __func__);
1232
0
      return;
1233
0
    }
1234
0
  }
1235
1236
0
  if (VNC_DEBUG(EXPORT_BGP_DIRECT_ADD)) {
1237
0
    vnc_zlog_debug_any("%s: hattr after route_map_apply:",
1238
0
           __func__);
1239
0
    rfapiPrintAttrPtrs(NULL, &hattr);
1240
0
  }
1241
0
  iattr = bgp_attr_intern(&hattr);
1242
0
  bgp_attr_flush(&hattr);
1243
1244
0
  bgp_update(irfd->peer, p, /* prefix */
1245
0
       0,     /* addpath_id */
1246
0
       iattr,   /* bgp_update copies it */
1247
0
       afi, SAFI_UNICAST, ZEBRA_ROUTE_VNC_DIRECT,
1248
0
       BGP_ROUTE_REDISTRIBUTE, NULL, /* RD not used for unicast */
1249
0
       NULL,      /* tag not used for unicast */
1250
0
       0, 0, NULL);       /* EVPN not used */
1251
1252
0
  bgp_attr_unintern(&iattr);
1253
1254
0
  return;
1255
0
}
1256
1257
/*
1258
 * Caller is responsible for ensuring that the specified nve-group
1259
 * is actually part of the list of exported nve groups.
1260
 */
1261
static void vnc_direct_bgp_add_group_afi(struct bgp *bgp,
1262
           struct rfapi_nve_group_cfg *rfg,
1263
           afi_t afi)
1264
0
{
1265
0
  struct agg_table *rt = NULL;
1266
0
  struct agg_node *rn;
1267
0
  struct attr attr = {0};
1268
0
  struct rfapi_import_table *import_table;
1269
1270
0
  vnc_zlog_debug_verbose("%s: entry", __func__);
1271
1272
0
  import_table = rfg->rfapi_import_table;
1273
0
  if (!import_table) {
1274
0
    vnc_zlog_debug_verbose(
1275
0
      "%s: import table not defined, returning", __func__);
1276
0
    return;
1277
0
  }
1278
1279
0
  if (afi == AFI_IP || afi == AFI_IP6) {
1280
0
    rt = import_table->imported_vpn[afi];
1281
0
  } else {
1282
0
    flog_err(EC_LIB_DEVELOPMENT, "%s: bad afi %d", __func__, afi);
1283
0
    return;
1284
0
  }
1285
1286
0
  if (!rfg->nves && rfg->type != RFAPI_GROUP_CFG_VRF) {
1287
0
    vnc_zlog_debug_verbose("%s: no NVEs in this group", __func__);
1288
0
    return;
1289
0
  }
1290
1291
0
  bgp_attr_default_set(&attr, bgp, BGP_ORIGIN_INCOMPLETE);
1292
  /* TBD set some configured med, see add_vnc_route() */
1293
1294
  /*
1295
   * Walk the NVE-Group's VNC Import table
1296
   */
1297
0
  for (rn = agg_route_top(rt); rn; rn = agg_route_next(rn)) {
1298
1299
0
    if (rn->info) {
1300
0
      const struct prefix *p = agg_node_get_prefix(rn);
1301
0
      struct listnode *ln;
1302
1303
      /*
1304
       * per-nve-group prefix list check
1305
       */
1306
0
      if (rfg->plist_export_bgp[afi]) {
1307
0
        if (prefix_list_apply(
1308
0
              rfg->plist_export_bgp[afi], p)
1309
0
            == PREFIX_DENY)
1310
1311
0
          continue;
1312
0
      }
1313
0
      if (rfg->type == RFAPI_GROUP_CFG_VRF) {
1314
0
        vnc_direct_add_rn_group_rd(bgp, rfg, rn, &attr,
1315
0
                 afi, rfg->rfd);
1316
        /*
1317
         * yuck!
1318
         *  - but consistent with rest of function
1319
         */
1320
0
        continue;
1321
0
      }
1322
      /*
1323
       * For each NVE that is assigned to the export nve
1324
       * group, generate
1325
       * a route with that NVE as its next hop
1326
       */
1327
0
      for (ln = listhead(rfg->nves); ln;
1328
0
           ln = listnextnode(ln)) {
1329
0
        vnc_direct_add_rn_group_rd(bgp, rfg, rn, &attr,
1330
0
                 afi,
1331
0
                 listgetdata(ln));
1332
0
      }
1333
0
    }
1334
0
  }
1335
1336
0
  aspath_unintern(&attr.aspath);
1337
0
}
1338
1339
1340
/*
1341
 * Caller is responsible for ensuring that the specified nve-group
1342
 * is actually part of the list of exported nve groups.
1343
 */
1344
void vnc_direct_bgp_add_group(struct bgp *bgp, struct rfapi_nve_group_cfg *rfg)
1345
0
{
1346
0
  vnc_direct_bgp_add_group_afi(bgp, rfg, AFI_IP);
1347
0
  vnc_direct_bgp_add_group_afi(bgp, rfg, AFI_IP6);
1348
0
}
1349
1350
static void vnc_direct_del_rn_group_rd(struct bgp *bgp,
1351
               struct rfapi_nve_group_cfg *rfg,
1352
               struct agg_node *rn, afi_t afi,
1353
               struct rfapi_descriptor *irfd)
1354
0
{
1355
0
  if (irfd == NULL)
1356
0
    return;
1357
1358
0
  bgp_withdraw(irfd->peer, agg_node_get_prefix(rn), /* prefix */
1359
0
         0,           /* addpath_id */
1360
0
         afi, SAFI_UNICAST, ZEBRA_ROUTE_VNC_DIRECT,
1361
0
         BGP_ROUTE_REDISTRIBUTE, NULL, /* RD not used for unicast */
1362
0
         NULL, 0, NULL); /* tag not used for unicast */
1363
0
  return;
1364
0
}
1365
1366
/*
1367
 * Caller is responsible for ensuring that the specified nve-group
1368
 * was actually part of the list of exported nve groups.
1369
 */
1370
static void vnc_direct_bgp_del_group_afi(struct bgp *bgp,
1371
           struct rfapi_nve_group_cfg *rfg,
1372
           afi_t afi)
1373
0
{
1374
0
  struct agg_table *rt = NULL;
1375
0
  struct agg_node *rn;
1376
0
  struct rfapi_import_table *import_table;
1377
1378
0
  vnc_zlog_debug_verbose("%s: entry", __func__);
1379
1380
0
  import_table = rfg->rfapi_import_table;
1381
0
  if (!import_table) {
1382
0
    vnc_zlog_debug_verbose(
1383
0
      "%s: import table not defined, returning", __func__);
1384
0
    return;
1385
0
  }
1386
1387
0
  rt = import_table->imported_vpn[afi];
1388
1389
0
  if (!rfg->nves && rfg->type != RFAPI_GROUP_CFG_VRF) {
1390
0
    vnc_zlog_debug_verbose("%s: no NVEs in this group", __func__);
1391
0
    return;
1392
0
  }
1393
1394
  /*
1395
   * Walk the NVE-Group's VNC Import table
1396
   */
1397
0
  for (rn = agg_route_top(rt); rn; rn = agg_route_next(rn))
1398
0
    if (rn->info) {
1399
0
      if (rfg->type == RFAPI_GROUP_CFG_VRF)
1400
0
        vnc_direct_del_rn_group_rd(bgp, rfg, rn, afi,
1401
0
                 rfg->rfd);
1402
0
      else {
1403
0
        struct listnode *ln;
1404
1405
        /*
1406
         * For each NVE that is assigned to the export
1407
         * nve
1408
         * group, generate
1409
         * a route with that NVE as its next hop
1410
         */
1411
0
        for (ln = listhead(rfg->nves); ln;
1412
0
             ln = listnextnode(ln))
1413
0
          vnc_direct_del_rn_group_rd(
1414
0
            bgp, rfg, rn, afi,
1415
0
            listgetdata(ln));
1416
0
      }
1417
0
    }
1418
0
}
1419
1420
/*
1421
 * Caller is responsible for ensuring that the specified nve-group
1422
 * was actually part of the list of exported nve groups.
1423
 */
1424
void vnc_direct_bgp_del_group(struct bgp *bgp, struct rfapi_nve_group_cfg *rfg)
1425
0
{
1426
0
  vnc_direct_bgp_del_group_afi(bgp, rfg, AFI_IP);
1427
0
  vnc_direct_bgp_del_group_afi(bgp, rfg, AFI_IP6);
1428
0
}
1429
1430
void vnc_direct_bgp_reexport_group_afi(struct bgp *bgp,
1431
               struct rfapi_nve_group_cfg *rfg,
1432
               afi_t afi)
1433
0
{
1434
0
  struct listnode *node;
1435
0
  struct rfapi_rfg_name *rfgn;
1436
1437
0
  if (VNC_EXPORT_BGP_GRP_ENABLED(bgp->rfapi_cfg)) {
1438
    /*
1439
     * look in the list of currently-exported groups
1440
     */
1441
0
    for (ALL_LIST_ELEMENTS_RO(
1442
0
           bgp->rfapi_cfg->rfg_export_direct_bgp_l, node,
1443
0
           rfgn)) {
1444
1445
0
      if (rfgn->rfg == rfg) {
1446
        /*
1447
         * If it matches, reexport it
1448
         */
1449
0
        vnc_direct_bgp_del_group_afi(bgp, rfg, afi);
1450
0
        vnc_direct_bgp_add_group_afi(bgp, rfg, afi);
1451
0
        break;
1452
0
      }
1453
0
    }
1454
0
  }
1455
0
}
1456
1457
1458
static void vnc_direct_bgp_unexport_table(afi_t afi, struct agg_table *rt,
1459
            struct list *nve_list)
1460
0
{
1461
0
  if (nve_list) {
1462
1463
0
    struct agg_node *rn;
1464
1465
0
    for (rn = agg_route_top(rt); rn; rn = agg_route_next(rn)) {
1466
1467
0
      if (rn->info) {
1468
1469
0
        struct listnode *hln;
1470
0
        struct rfapi_descriptor *irfd;
1471
1472
0
        for (ALL_LIST_ELEMENTS_RO(nve_list, hln,
1473
0
                irfd)) {
1474
1475
0
          bgp_withdraw(irfd->peer,
1476
0
                 agg_node_get_prefix(rn),
1477
0
                 0,    /* addpath_id */
1478
0
                 afi, SAFI_UNICAST,
1479
0
                 ZEBRA_ROUTE_VNC_DIRECT,
1480
0
                 BGP_ROUTE_REDISTRIBUTE,
1481
0
                 NULL, /* RD not used for
1482
                    unicast */
1483
0
                 NULL, 0, NULL); /* tag not
1484
                     used for
1485
                     unicast,
1486
                     EVPN
1487
                     neither */
1488
0
        }
1489
0
      }
1490
0
    }
1491
0
  }
1492
0
}
1493
1494
static void import_table_to_nve_list_direct_bgp(struct bgp *bgp,
1495
            struct rfapi_import_table *it,
1496
            struct list **nves,
1497
            uint8_t family)
1498
0
{
1499
0
  struct listnode *node;
1500
0
  struct rfapi_rfg_name *rfgn;
1501
1502
  /*
1503
   * Loop over the list of NVE-Groups configured for
1504
   * exporting to direct-bgp.
1505
   *
1506
   * Build a list of NVEs that use this import table
1507
   */
1508
0
  *nves = NULL;
1509
0
  for (ALL_LIST_ELEMENTS_RO(bgp->rfapi_cfg->rfg_export_direct_bgp_l, node,
1510
0
          rfgn)) {
1511
1512
    /*
1513
     * If this NVE-Group's import table matches the current one
1514
     */
1515
0
    if (rfgn->rfg && rfgn->rfg->rfapi_import_table == it) {
1516
0
      if (rfgn->rfg->nves)
1517
0
        nve_group_to_nve_list(rfgn->rfg, nves, family);
1518
0
      else if (rfgn->rfg->rfd
1519
0
         && rfgn->rfg->type == RFAPI_GROUP_CFG_VRF) {
1520
0
        if (!*nves)
1521
0
          *nves = list_new();
1522
0
        listnode_add(*nves, rfgn->rfg->rfd);
1523
0
      }
1524
0
    }
1525
0
  }
1526
0
}
1527
1528
void vnc_direct_bgp_vpn_enable(struct bgp *bgp, afi_t afi)
1529
0
{
1530
0
  struct listnode *rfgn;
1531
0
  struct rfapi_nve_group_cfg *rfg;
1532
1533
0
  if (!bgp)
1534
0
    return;
1535
1536
0
  if (!VNC_EXPORT_BGP_GRP_ENABLED(bgp->rfapi_cfg)) {
1537
0
    vnc_zlog_debug_verbose(
1538
0
      "%s: export-to-bgp group mode not enabled, skipping",
1539
0
      __func__);
1540
0
    return;
1541
0
  }
1542
1543
0
  if (afi != AFI_IP && afi != AFI_IP6) {
1544
0
    vnc_zlog_debug_verbose("%s: bad afi: %d", __func__, afi);
1545
0
    return;
1546
0
  }
1547
1548
  /*
1549
   * Policy is applied per-nve-group, so we need to iterate
1550
   * over the groups to add everything.
1551
   */
1552
0
  for (ALL_LIST_ELEMENTS_RO(bgp->rfapi_cfg->nve_groups_sequential, rfgn,
1553
0
          rfg)) {
1554
1555
    /*
1556
     * contains policy management
1557
     */
1558
0
    vnc_direct_bgp_add_group_afi(bgp, rfg, afi);
1559
0
  }
1560
0
}
1561
1562
1563
void vnc_direct_bgp_vpn_disable(struct bgp *bgp, afi_t afi)
1564
0
{
1565
0
  struct rfapi_import_table *it;
1566
0
  uint8_t family = afi2family(afi);
1567
1568
0
  vnc_zlog_debug_verbose("%s: entry, afi=%d", __func__, afi);
1569
1570
0
  if (!bgp)
1571
0
    return;
1572
1573
0
  if (!bgp->rfapi) {
1574
0
    vnc_zlog_debug_verbose("%s: rfapi not initialized", __func__);
1575
0
    return;
1576
0
  }
1577
1578
0
  if (!family || (afi != AFI_IP && afi != AFI_IP6)) {
1579
0
    vnc_zlog_debug_verbose("%s: bad afi: %d", __func__, afi);
1580
0
    return;
1581
0
  }
1582
1583
0
  for (it = bgp->rfapi->imports; it; it = it->next) {
1584
1585
0
    struct list *nve_list = NULL;
1586
1587
0
    import_table_to_nve_list_direct_bgp(bgp, it, &nve_list, family);
1588
1589
0
    if (nve_list) {
1590
0
      vnc_direct_bgp_unexport_table(
1591
0
        afi, it->imported_vpn[afi], nve_list);
1592
0
      list_delete(&nve_list);
1593
0
    }
1594
0
  }
1595
0
}
1596
1597
1598
/***********************************************************************
1599
 * Export methods that proxy nexthop END
1600
 ***********************************************************************/
1601
1602
1603
/***********************************************************************
1604
 * Export methods that preserve original nexthop BEGIN
1605
 * rh = "registering nve"
1606
 ***********************************************************************/
1607
1608
1609
/*
1610
 * "Adding a Route" export process
1611
 * TBD do we need to check bpi->type and bpi->sub_type here, or does
1612
 * caller do it?
1613
 */
1614
void vnc_direct_bgp_rh_add_route(struct bgp *bgp, afi_t afi,
1615
         const struct prefix *prefix, struct peer *peer,
1616
         struct attr *attr)
1617
0
{
1618
0
  struct vnc_export_info *eti;
1619
0
  struct attr hattr;
1620
0
  struct rfapi_cfg *hc;
1621
0
  struct attr *iattr;
1622
1623
0
  if (!afi) {
1624
0
    flog_err(EC_LIB_DEVELOPMENT, "%s: can't get afi of route node",
1625
0
       __func__);
1626
0
    return;
1627
0
  }
1628
1629
  /* check bgp redist flag for vnc direct ("vpn") routes */
1630
0
  if (!bgp->redist[afi][ZEBRA_ROUTE_VNC_DIRECT]) {
1631
0
    vnc_zlog_debug_verbose(
1632
0
      "%s: bgp redistribution of VNC direct routes is off",
1633
0
      __func__);
1634
0
    return;
1635
0
  }
1636
1637
0
  if (!(hc = bgp->rfapi_cfg)) {
1638
0
    vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
1639
0
               __func__);
1640
0
    return;
1641
0
  }
1642
1643
0
  if (!VNC_EXPORT_BGP_RH_ENABLED(bgp->rfapi_cfg)) {
1644
0
    vnc_zlog_debug_verbose(
1645
0
      "%s: export-to-bgp RH mode not enabled, skipping",
1646
0
      __func__);
1647
0
    return;
1648
0
  }
1649
1650
  /*
1651
   * prefix list check
1652
   */
1653
0
  if (hc->plist_export_bgp[afi]) {
1654
0
    if (prefix_list_apply(hc->plist_export_bgp[afi], prefix)
1655
0
        == PREFIX_DENY)
1656
0
      return;
1657
0
  }
1658
1659
  /*
1660
   * Construct new attribute set with NVE's VN addr as
1661
   * nexthop and without Tunnel Encap attr
1662
   */
1663
0
  if (encap_attr_export(&hattr, attr, NULL, NULL))
1664
0
    return;
1665
0
  if (hc->routemap_export_bgp) {
1666
0
    struct bgp_path_info info;
1667
0
    route_map_result_t ret;
1668
1669
0
    memset(&info, 0, sizeof(info));
1670
0
    info.peer = peer;
1671
0
    info.attr = &hattr;
1672
0
    ret = route_map_apply(hc->routemap_export_bgp, prefix, &info);
1673
0
    if (ret == RMAP_DENYMATCH) {
1674
0
      bgp_attr_flush(&hattr);
1675
0
      return;
1676
0
    }
1677
0
  }
1678
1679
0
  iattr = bgp_attr_intern(&hattr);
1680
0
  bgp_attr_flush(&hattr);
1681
1682
  /*
1683
   * record route information that we will need to expire
1684
   * this route
1685
   */
1686
0
  eti = vnc_eti_get(bgp, EXPORT_TYPE_BGP, prefix, peer,
1687
0
        ZEBRA_ROUTE_VNC_DIRECT_RH, BGP_ROUTE_REDISTRIBUTE);
1688
0
  rfapiGetVncLifetime(attr, &eti->lifetime);
1689
0
  eti->lifetime = rfapiGetHolddownFromLifetime(eti->lifetime);
1690
1691
  /*
1692
   * export expiration timer is already running on
1693
   * this route: cancel it
1694
   */
1695
0
  EVENT_OFF(eti->timer);
1696
1697
0
  bgp_update(peer, prefix, /* prefix */
1698
0
       0,    /* addpath_id */
1699
0
       iattr, /* bgp_update copies this attr */
1700
0
       afi, SAFI_UNICAST, ZEBRA_ROUTE_VNC_DIRECT_RH,
1701
0
       BGP_ROUTE_REDISTRIBUTE, NULL, /* RD not used for unicast */
1702
0
       NULL, /* tag not used for unicast, EVPN neither */
1703
0
       0, 0, NULL); /* EVPN not used */
1704
0
  bgp_attr_unintern(&iattr);
1705
0
}
1706
1707
static void vncExportWithdrawTimer(struct event *t)
1708
0
{
1709
0
  struct vnc_export_info *eti = EVENT_ARG(t);
1710
0
  const struct prefix *p = agg_node_get_prefix(eti->node);
1711
0
1712
0
  /*
1713
0
   * withdraw the route
1714
0
   */
1715
0
  bgp_withdraw(eti->peer, p, 0, /* addpath_id */
1716
0
         family2afi(p->family), SAFI_UNICAST, eti->type,
1717
0
         eti->subtype, NULL, /* RD not used for unicast */
1718
0
         NULL, 0,
1719
0
         NULL); /* tag not used for unicast, EVPN neither */
1720
0
1721
0
  /*
1722
0
   * Free the eti
1723
0
   */
1724
0
  vnc_eti_delete(eti);
1725
0
}
1726
1727
/*
1728
 * "Withdrawing a Route" export process
1729
 * TBD do we need to check bpi->type and bpi->sub_type here, or does
1730
 * caller do it?
1731
 */
1732
void vnc_direct_bgp_rh_del_route(struct bgp *bgp, afi_t afi,
1733
         const struct prefix *prefix, struct peer *peer)
1734
232
{
1735
232
  struct vnc_export_info *eti;
1736
1737
232
  if (!afi) {
1738
0
    flog_err(EC_LIB_DEVELOPMENT, "%s: can't get afi route node",
1739
0
       __func__);
1740
0
    return;
1741
0
  }
1742
1743
  /* check bgp redist flag for vnc direct ("vpn") routes */
1744
232
  if (!bgp->redist[afi][ZEBRA_ROUTE_VNC_DIRECT]) {
1745
232
    vnc_zlog_debug_verbose(
1746
232
      "%s: bgp redistribution of VNC direct routes is off",
1747
232
      __func__);
1748
232
    return;
1749
232
  }
1750
1751
0
  if (!bgp->rfapi_cfg) {
1752
0
    vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
1753
0
               __func__);
1754
0
    return;
1755
0
  }
1756
0
  if (!VNC_EXPORT_BGP_RH_ENABLED(bgp->rfapi_cfg)) {
1757
0
    vnc_zlog_debug_verbose(
1758
0
      "%s: export-to-bgp group mode not enabled, skipping",
1759
0
      __func__);
1760
0
    return;
1761
0
  }
1762
1763
0
  eti = vnc_eti_get(bgp, EXPORT_TYPE_BGP, prefix, peer,
1764
0
        ZEBRA_ROUTE_VNC_DIRECT_RH, BGP_ROUTE_REDISTRIBUTE);
1765
1766
0
  if (!eti->timer && eti->lifetime <= INT32_MAX) {
1767
0
    eti->timer = NULL;
1768
0
    event_add_timer(bm->master, vncExportWithdrawTimer, eti,
1769
0
        eti->lifetime, &eti->timer);
1770
0
    vnc_zlog_debug_verbose(
1771
0
      "%s: set expiration timer for %u seconds", __func__,
1772
0
      eti->lifetime);
1773
0
  }
1774
0
}
1775
1776
1777
void vnc_direct_bgp_rh_vpn_enable(struct bgp *bgp, afi_t afi)
1778
0
{
1779
0
  struct prefix_rd prd;
1780
0
  struct bgp_dest *pdest;
1781
0
  struct rfapi_cfg *hc;
1782
1783
0
  vnc_zlog_debug_verbose("%s: entry, afi=%d", __func__, afi);
1784
1785
0
  if (!bgp)
1786
0
    return;
1787
1788
0
  if (!(hc = bgp->rfapi_cfg))
1789
0
    return;
1790
1791
0
  if (!VNC_EXPORT_BGP_RH_ENABLED(bgp->rfapi_cfg)) {
1792
0
    vnc_zlog_debug_verbose(
1793
0
      "%s: export of RH routes not enabled, skipping",
1794
0
      __func__);
1795
0
    return;
1796
0
  }
1797
1798
0
  if (afi != AFI_IP && afi != AFI_IP6) {
1799
0
    vnc_zlog_debug_verbose("%s: bad afi: %d", __func__, afi);
1800
0
    return;
1801
0
  }
1802
1803
  /*
1804
   * Go through the entire BGP VPN table and export to BGP unicast.
1805
   */
1806
1807
0
  vnc_zlog_debug_verbose("%s: starting RD loop", __func__);
1808
1809
  /* Loop over all the RDs */
1810
0
  for (pdest = bgp_table_top(bgp->rib[afi][SAFI_MPLS_VPN]); pdest;
1811
0
       pdest = bgp_route_next(pdest)) {
1812
1813
0
    struct bgp_table *table;
1814
0
    struct bgp_dest *dest;
1815
0
    struct bgp_path_info *ri;
1816
0
    const struct prefix *pdest_p = bgp_dest_get_prefix(pdest);
1817
1818
0
    memset(&prd, 0, sizeof(prd));
1819
0
    prd.family = AF_UNSPEC;
1820
0
    prd.prefixlen = 64;
1821
0
    memcpy(prd.val, pdest_p->u.val, 8);
1822
1823
    /* This is the per-RD table of prefixes */
1824
0
    table = bgp_dest_get_bgp_table_info(pdest);
1825
1826
0
    if (!table)
1827
0
      continue;
1828
1829
0
    for (dest = bgp_table_top(table); dest;
1830
0
         dest = bgp_route_next(dest)) {
1831
0
      const struct prefix *dest_p;
1832
1833
      /*
1834
       * skip prefix list check if no routes here
1835
       */
1836
0
      if (!bgp_dest_has_bgp_path_info_data(dest))
1837
0
        continue;
1838
1839
0
      vnc_zlog_debug_verbose("%s: checking prefix %pBD",
1840
0
                 __func__, dest);
1841
1842
0
      dest_p = bgp_dest_get_prefix(dest);
1843
1844
      /*
1845
       * prefix list check
1846
       */
1847
0
      if (hc->plist_export_bgp[afi]) {
1848
0
        if (prefix_list_apply(hc->plist_export_bgp[afi],
1849
0
                  dest_p)
1850
0
            == PREFIX_DENY) {
1851
1852
0
          vnc_zlog_debug_verbose(
1853
0
            "%s:   prefix list says DENY",
1854
0
            __func__);
1855
0
          continue;
1856
0
        }
1857
0
      }
1858
1859
0
      for (ri = bgp_dest_get_bgp_path_info(dest); ri;
1860
0
           ri = ri->next) {
1861
1862
0
        vnc_zlog_debug_verbose("%s: ri->sub_type: %d",
1863
0
                   __func__, ri->sub_type);
1864
1865
0
        if (ri->sub_type == BGP_ROUTE_NORMAL
1866
0
            || ri->sub_type == BGP_ROUTE_RFP) {
1867
1868
0
          struct vnc_export_info *eti;
1869
0
          struct attr hattr;
1870
0
          struct attr *iattr;
1871
1872
          /*
1873
           * Construct new attribute set with
1874
           * NVE's VN addr as
1875
           * nexthop and without Tunnel Encap attr
1876
           */
1877
0
          if (encap_attr_export(&hattr, ri->attr,
1878
0
                    NULL, NULL)) {
1879
0
            vnc_zlog_debug_verbose(
1880
0
              "%s:   encap_attr_export failed",
1881
0
              __func__);
1882
0
            continue;
1883
0
          }
1884
1885
0
          if (hc->routemap_export_bgp) {
1886
0
            struct bgp_path_info info;
1887
0
            route_map_result_t ret;
1888
1889
0
            memset(&info, 0, sizeof(info));
1890
0
            info.peer = ri->peer;
1891
0
            info.attr = &hattr;
1892
0
            ret = route_map_apply(
1893
0
              hc->routemap_export_bgp,
1894
0
              dest_p, &info);
1895
0
            if (ret == RMAP_DENYMATCH) {
1896
0
              bgp_attr_flush(&hattr);
1897
0
              vnc_zlog_debug_verbose(
1898
0
                "%s:   route map says DENY",
1899
0
                __func__);
1900
0
              continue;
1901
0
            }
1902
0
          }
1903
1904
0
          iattr = bgp_attr_intern(&hattr);
1905
0
          bgp_attr_flush(&hattr);
1906
1907
          /*
1908
           * record route information that we will
1909
           * need to expire
1910
           * this route
1911
           */
1912
0
          eti = vnc_eti_get(
1913
0
            bgp, EXPORT_TYPE_BGP, dest_p,
1914
0
            ri->peer,
1915
0
            ZEBRA_ROUTE_VNC_DIRECT_RH,
1916
0
            BGP_ROUTE_REDISTRIBUTE);
1917
0
          rfapiGetVncLifetime(ri->attr,
1918
0
                  &eti->lifetime);
1919
1920
          /*
1921
           * export expiration timer is
1922
           * already running on
1923
           * this route: cancel it
1924
           */
1925
0
          EVENT_OFF(eti->timer);
1926
1927
0
          vnc_zlog_debug_verbose(
1928
0
            "%s: calling bgp_update",
1929
0
            __func__);
1930
1931
0
          bgp_update(
1932
0
            ri->peer, dest_p, /* prefix */
1933
0
            0,     /* addpath_id */
1934
0
            iattr, /* bgp_update copies
1935
                it */
1936
0
            AFI_IP, SAFI_UNICAST,
1937
0
            ZEBRA_ROUTE_VNC_DIRECT_RH,
1938
0
            BGP_ROUTE_REDISTRIBUTE, NULL,
1939
            /* RD not used for unicast */
1940
0
            NULL,
1941
            /* tag not used for unicast,
1942
               or EVPN */
1943
0
            0, 0, NULL); /* EVPN not used */
1944
1945
0
          bgp_attr_unintern(&iattr);
1946
0
        }
1947
0
      }
1948
0
    }
1949
0
  }
1950
0
}
1951
1952
void vnc_direct_bgp_rh_vpn_disable(struct bgp *bgp, afi_t afi)
1953
0
{
1954
0
  struct bgp_dest *dest;
1955
1956
0
  vnc_zlog_debug_verbose("%s: entry, afi=%d", __func__, afi);
1957
1958
0
  if (!bgp)
1959
0
    return;
1960
1961
0
  if (afi != AFI_IP && afi != AFI_IP6) {
1962
0
    vnc_zlog_debug_verbose("%s: bad afi: %d", __func__, afi);
1963
0
    return;
1964
0
  }
1965
1966
  /*
1967
   * Go through the entire BGP unicast table and remove routes that
1968
   * originated from us
1969
   */
1970
0
  for (dest = bgp_table_top(bgp->rib[afi][SAFI_UNICAST]); dest;
1971
0
       dest = bgp_route_next(dest)) {
1972
0
    const struct prefix *dest_p = bgp_dest_get_prefix(dest);
1973
0
    struct bgp_path_info *ri;
1974
0
    struct bgp_path_info *next;
1975
1976
0
    for (ri = bgp_dest_get_bgp_path_info(dest), next = NULL; ri;
1977
0
         ri = next) {
1978
1979
0
      next = ri->next;
1980
1981
0
      if (ri->type == ZEBRA_ROUTE_VNC_DIRECT_RH
1982
0
          && ri->sub_type == BGP_ROUTE_REDISTRIBUTE) {
1983
1984
0
        struct vnc_export_info *eti;
1985
1986
        /*
1987
         * Delete routes immediately (no timer)
1988
         */
1989
0
        eti = vnc_eti_checktimer(
1990
0
          bgp, EXPORT_TYPE_BGP, dest_p, ri->peer,
1991
0
          ZEBRA_ROUTE_VNC_DIRECT_RH,
1992
0
          BGP_ROUTE_REDISTRIBUTE);
1993
0
        if (eti) {
1994
0
          EVENT_OFF(eti->timer);
1995
0
          vnc_eti_delete(eti);
1996
0
        }
1997
1998
0
        bgp_withdraw(ri->peer, dest_p, /* prefix */
1999
0
               0,          /* addpath_id */
2000
0
               AFI_IP, SAFI_UNICAST,
2001
0
               ZEBRA_ROUTE_VNC_DIRECT_RH,
2002
0
               BGP_ROUTE_REDISTRIBUTE,
2003
0
               NULL, /* RD not used for unicast */
2004
0
               NULL, 0, NULL); /* tag not used for
2005
                   unicast, EVPN
2006
                   neither */
2007
0
      }
2008
0
    }
2009
0
  }
2010
0
}
2011
2012
void vnc_direct_bgp_rh_reexport(struct bgp *bgp, afi_t afi)
2013
0
{
2014
0
  if (VNC_EXPORT_BGP_RH_ENABLED(bgp->rfapi_cfg)) {
2015
0
    vnc_direct_bgp_rh_vpn_disable(bgp, afi);
2016
0
    vnc_direct_bgp_rh_vpn_enable(bgp, afi);
2017
0
  }
2018
0
}
2019
2020
/***********************************************************************
2021
 * Generic Export methods
2022
 ***********************************************************************/
2023
2024
/*
2025
 * Assumes the correct mode bits are already turned on. Thus it
2026
 * is OK to call this function from, e.g., bgp_redistribute_set()
2027
 * without caring if export is enabled or not
2028
 */
2029
void vnc_export_bgp_enable(struct bgp *bgp, afi_t afi)
2030
0
{
2031
0
  if (!bgp->rfapi_cfg)
2032
0
    return;
2033
2034
0
  switch (bgp->rfapi_cfg->flags & BGP_VNC_CONFIG_EXPORT_BGP_MODE_BITS) {
2035
0
  case BGP_VNC_CONFIG_EXPORT_BGP_MODE_NONE:
2036
0
    break;
2037
2038
0
  case BGP_VNC_CONFIG_EXPORT_BGP_MODE_GRP:
2039
0
    vnc_direct_bgp_vpn_enable(bgp, afi);
2040
0
    break;
2041
2042
0
  case BGP_VNC_CONFIG_EXPORT_BGP_MODE_RH:
2043
0
    vnc_direct_bgp_rh_vpn_enable(bgp, afi);
2044
0
    break;
2045
2046
0
  case BGP_VNC_CONFIG_EXPORT_BGP_MODE_CE:
2047
0
    vnc_direct_bgp_vpn_enable_ce(bgp, afi);
2048
0
    break;
2049
0
  }
2050
0
}
2051
2052
void vnc_export_bgp_disable(struct bgp *bgp, afi_t afi)
2053
0
{
2054
0
  if (!bgp->rfapi_cfg)
2055
0
    return;
2056
2057
0
  switch (bgp->rfapi_cfg->flags & BGP_VNC_CONFIG_EXPORT_BGP_MODE_BITS) {
2058
0
  case BGP_VNC_CONFIG_EXPORT_BGP_MODE_NONE:
2059
0
    break;
2060
2061
0
  case BGP_VNC_CONFIG_EXPORT_BGP_MODE_GRP:
2062
0
    vnc_direct_bgp_vpn_disable(bgp, afi);
2063
0
    break;
2064
2065
0
  case BGP_VNC_CONFIG_EXPORT_BGP_MODE_RH:
2066
0
    vnc_direct_bgp_rh_vpn_disable(bgp, afi);
2067
0
    break;
2068
2069
0
  case BGP_VNC_CONFIG_EXPORT_BGP_MODE_CE:
2070
0
    vnc_direct_bgp_vpn_disable_ce(bgp, afi);
2071
0
    break;
2072
0
  }
2073
0
}
2074
2075
void vnc_export_bgp_prechange(struct bgp *bgp)
2076
0
{
2077
0
  vnc_export_bgp_disable(bgp, AFI_IP);
2078
0
  vnc_export_bgp_disable(bgp, AFI_IP6);
2079
0
}
2080
2081
void vnc_export_bgp_postchange(struct bgp *bgp)
2082
0
{
2083
0
  vnc_export_bgp_enable(bgp, AFI_IP);
2084
0
  vnc_export_bgp_enable(bgp, AFI_IP6);
2085
0
}
2086
2087
void vnc_direct_bgp_reexport(struct bgp *bgp, afi_t afi)
2088
0
{
2089
0
  vnc_export_bgp_disable(bgp, afi);
2090
0
  vnc_export_bgp_enable(bgp, afi);
2091
0
}