Coverage Report

Created: 2025-12-05 06:31

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/frr/bgpd/bgp_routemap.c
Line
Count
Source
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
/* Route map function of bgpd.
3
 * Copyright (C) 1998, 1999 Kunihiro Ishiguro
4
 */
5
6
#include <zebra.h>
7
8
#include "prefix.h"
9
#include "filter.h"
10
#include "routemap.h"
11
#include "command.h"
12
#include "linklist.h"
13
#include "plist.h"
14
#include "memory.h"
15
#include "log.h"
16
#include "frrlua.h"
17
#include "frrscript.h"
18
#ifdef HAVE_LIBPCRE2_POSIX
19
#ifndef _FRR_PCRE2_POSIX
20
#define _FRR_PCRE2_POSIX
21
#include <pcre2posix.h>
22
#endif /* _FRR_PCRE2_POSIX */
23
#elif defined(HAVE_LIBPCREPOSIX)
24
#include <pcreposix.h>
25
#else
26
#include <regex.h>
27
#endif /* HAVE_LIBPCRE2_POSIX */
28
#include "buffer.h"
29
#include "sockunion.h"
30
#include "hash.h"
31
#include "queue.h"
32
#include "frrstr.h"
33
#include "network.h"
34
#include "lib/northbound_cli.h"
35
36
#include "bgpd/bgpd.h"
37
#include "bgpd/bgp_table.h"
38
#include "bgpd/bgp_attr.h"
39
#include "bgpd/bgp_aspath.h"
40
#include "bgpd/bgp_packet.h"
41
#include "bgpd/bgp_route.h"
42
#include "bgpd/bgp_zebra.h"
43
#include "bgpd/bgp_regex.h"
44
#include "bgpd/bgp_community.h"
45
#include "bgpd/bgp_community_alias.h"
46
#include "bgpd/bgp_clist.h"
47
#include "bgpd/bgp_filter.h"
48
#include "bgpd/bgp_mplsvpn.h"
49
#include "bgpd/bgp_ecommunity.h"
50
#include "bgpd/bgp_lcommunity.h"
51
#include "bgpd/bgp_vty.h"
52
#include "bgpd/bgp_debug.h"
53
#include "bgpd/bgp_evpn.h"
54
#include "bgpd/bgp_evpn_private.h"
55
#include "bgpd/bgp_evpn_vty.h"
56
#include "bgpd/bgp_mplsvpn.h"
57
#include "bgpd/bgp_pbr.h"
58
#include "bgpd/bgp_flowspec_util.h"
59
#include "bgpd/bgp_encap_types.h"
60
#include "bgpd/bgp_mpath.h"
61
#include "bgpd/bgp_script.h"
62
63
#ifdef ENABLE_BGP_VNC
64
#include "bgpd/rfapi/bgp_rfapi_cfg.h"
65
#endif
66
67
#include "bgpd/bgp_routemap_clippy.c"
68
69
/* Memo of route-map commands.
70
71
o Cisco route-map
72
73
 match as-path          :  Done
74
       community        :  Done
75
       interface        :  Done
76
       ip address       :  Done
77
       ip next-hop      :  Done
78
       ip route-source  :  Done
79
       ip prefix-list   :  Done
80
       ipv6 address     :  Done
81
       ipv6 next-hop    :  Done
82
       ipv6 route-source:  (This will not be implemented by bgpd)
83
       ipv6 prefix-list :  Done
84
       length           :  (This will not be implemented by bgpd)
85
       metric           :  Done
86
       route-type       :  (This will not be implemented by bgpd)
87
       tag              :  Done
88
       local-preference :  Done
89
90
 set  as-path prepend   :  Done
91
      as-path tag       :  Not yet
92
      automatic-tag     :  (This will not be implemented by bgpd)
93
      community         :  Done
94
      large-community   :  Done
95
      large-comm-list   :  Done
96
      comm-list         :  Not yet
97
      dampning          :  Not yet
98
      default           :  (This will not be implemented by bgpd)
99
      interface         :  (This will not be implemented by bgpd)
100
      ip default        :  (This will not be implemented by bgpd)
101
      ip next-hop       :  Done
102
      ip precedence     :  (This will not be implemented by bgpd)
103
      ip tos            :  (This will not be implemented by bgpd)
104
      level             :  (This will not be implemented by bgpd)
105
      local-preference  :  Done
106
      metric            :  Done
107
      metric-type       :  Not yet
108
      origin            :  Done
109
      tag               :  Done
110
      weight            :  Done
111
      table             :  Done
112
113
o Local extensions
114
115
  set ipv6 next-hop global: Done
116
  set ipv6 next-hop prefer-global: Done
117
  set ipv6 next-hop local : Done
118
  set as-path exclude     : Done
119
120
*/
121
122
/* generic value manipulation to be shared in multiple rules */
123
124
0
#define RMAP_VALUE_SET 0
125
0
#define RMAP_VALUE_ADD 1
126
0
#define RMAP_VALUE_SUB 2
127
128
struct rmap_value {
129
  uint8_t action;
130
  uint8_t variable;
131
  uint32_t value;
132
};
133
134
static int route_value_match(struct rmap_value *rv, uint32_t value)
135
0
{
136
0
  if (rv->variable == 0 && value == rv->value)
137
0
    return RMAP_MATCH;
138
139
0
  return RMAP_NOMATCH;
140
0
}
141
142
static uint32_t route_value_adjust(struct rmap_value *rv, uint32_t current,
143
           struct peer *peer)
144
0
{
145
0
  uint32_t value;
146
147
0
  switch (rv->variable) {
148
0
  case 1:
149
0
    value = peer->rtt;
150
0
    break;
151
0
  default:
152
0
    value = rv->value;
153
0
    break;
154
0
  }
155
156
0
  switch (rv->action) {
157
0
  case RMAP_VALUE_ADD:
158
0
    if (current > UINT32_MAX - value)
159
0
      return UINT32_MAX;
160
0
    return current + value;
161
0
  case RMAP_VALUE_SUB:
162
0
    if (current <= value)
163
0
      return 0;
164
0
    return current - value;
165
0
  default:
166
0
    return value;
167
0
  }
168
0
}
169
170
static void *route_value_compile(const char *arg)
171
0
{
172
0
  uint8_t action = RMAP_VALUE_SET, var = 0;
173
0
  unsigned long larg = 0;
174
0
  char *endptr = NULL;
175
0
  struct rmap_value *rv;
176
177
0
  if (arg[0] == '+') {
178
0
    action = RMAP_VALUE_ADD;
179
0
    arg++;
180
0
  } else if (arg[0] == '-') {
181
0
    action = RMAP_VALUE_SUB;
182
0
    arg++;
183
0
  }
184
185
0
  if (all_digit(arg)) {
186
0
    errno = 0;
187
0
    larg = strtoul(arg, &endptr, 10);
188
0
    if (*arg == 0 || *endptr != 0 || errno || larg > UINT32_MAX)
189
0
      return NULL;
190
0
  } else {
191
0
    if (strcmp(arg, "rtt") == 0)
192
0
      var = 1;
193
0
    else
194
0
      return NULL;
195
0
  }
196
197
0
  rv = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_value));
198
199
0
  rv->action = action;
200
0
  rv->variable = var;
201
0
  rv->value = larg;
202
0
  return rv;
203
0
}
204
205
static void route_value_free(void *rule)
206
0
{
207
0
  XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
208
0
}
209
210
/* generic as path object to be shared in multiple rules */
211
212
static void *route_aspath_compile(const char *arg)
213
0
{
214
0
  struct aspath *aspath;
215
216
0
  aspath = aspath_str2aspath(arg, bgp_get_asnotation(NULL));
217
0
  if (!aspath)
218
0
    return NULL;
219
0
  return aspath;
220
0
}
221
222
static void route_aspath_free(void *rule)
223
0
{
224
0
  struct aspath *aspath = rule;
225
0
  aspath_free(aspath);
226
0
}
227
228
struct bgp_match_peer_compiled {
229
  char *interface;
230
  union sockunion su;
231
};
232
233
/* 'match peer (A.B.C.D|X:X::X:X|WORD)' */
234
235
/* Compares the peer specified in the 'match peer' clause with the peer
236
    received in bgp_path_info->peer. If it is the same, or if the peer structure
237
    received is a peer_group containing it, returns RMAP_MATCH. */
238
static enum route_map_cmd_result_t
239
route_match_peer(void *rule, const struct prefix *prefix, void *object)
240
0
{
241
0
  struct bgp_match_peer_compiled *pc;
242
0
  union sockunion *su;
243
0
  union sockunion su_def = {
244
0
    .sin = {.sin_family = AF_INET, .sin_addr.s_addr = INADDR_ANY}};
245
0
  struct peer_group *group;
246
0
  struct peer *peer;
247
0
  struct listnode *node, *nnode;
248
249
0
  pc = rule;
250
0
  su = &pc->su;
251
0
  peer = ((struct bgp_path_info *)object)->peer;
252
253
0
  if (pc->interface) {
254
0
    if (!peer->conf_if || !peer->group)
255
0
      return RMAP_NOMATCH;
256
257
0
    if (peer->conf_if && strcmp(peer->conf_if, pc->interface) == 0)
258
0
      return RMAP_MATCH;
259
260
0
    if (peer->group &&
261
0
        strcmp(peer->group->name, pc->interface) == 0)
262
0
      return RMAP_MATCH;
263
264
0
    return RMAP_NOMATCH;
265
0
  }
266
267
  /* If su='0.0.0.0' (command 'match peer local'), and it's a
268
     NETWORK,
269
     REDISTRIBUTE, AGGREGATE-ADDRESS or DEFAULT_GENERATED route
270
     => return RMAP_MATCH
271
  */
272
0
  if (sockunion_same(su, &su_def)) {
273
0
    int ret;
274
0
    if (CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_NETWORK)
275
0
        || CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_REDISTRIBUTE)
276
0
        || CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_AGGREGATE)
277
0
        || CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_DEFAULT))
278
0
      ret = RMAP_MATCH;
279
0
    else
280
0
      ret = RMAP_NOMATCH;
281
0
    return ret;
282
0
  }
283
284
0
  if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
285
0
    if (sockunion_same(su, &peer->su))
286
0
      return RMAP_MATCH;
287
288
0
    return RMAP_NOMATCH;
289
0
  } else {
290
0
    group = peer->group;
291
0
    for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
292
0
      if (sockunion_same(su, &peer->su))
293
0
        return RMAP_MATCH;
294
0
    }
295
0
    return RMAP_NOMATCH;
296
0
  }
297
298
0
  return RMAP_NOMATCH;
299
0
}
300
301
static void *route_match_peer_compile(const char *arg)
302
0
{
303
0
  struct bgp_match_peer_compiled *pc;
304
0
  int ret;
305
306
0
  pc = XCALLOC(MTYPE_ROUTE_MAP_COMPILED,
307
0
         sizeof(struct bgp_match_peer_compiled));
308
309
0
  ret = str2sockunion(strcmp(arg, "local") ? arg : "0.0.0.0", &pc->su);
310
0
  if (ret < 0) {
311
0
    pc->interface = XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
312
0
    return pc;
313
0
  }
314
315
0
  return pc;
316
0
}
317
318
/* Free route map's compiled `ip address' value. */
319
static void route_match_peer_free(void *rule)
320
0
{
321
0
  struct bgp_match_peer_compiled *pc = rule;
322
323
0
  XFREE(MTYPE_ROUTE_MAP_COMPILED, pc->interface);
324
325
0
  XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
326
0
}
327
328
/* Route map commands for ip address matching. */
329
static const struct route_map_rule_cmd route_match_peer_cmd = {
330
  "peer",
331
  route_match_peer,
332
  route_match_peer_compile,
333
  route_match_peer_free
334
};
335
336
#ifdef HAVE_SCRIPTING
337
338
enum frrlua_rm_status {
339
  /*
340
   * Script function run failure.  This will translate into a deny
341
   */
342
  LUA_RM_FAILURE = 0,
343
  /*
344
   * No Match was found for the route map function
345
   */
346
  LUA_RM_NOMATCH,
347
  /*
348
   * Match was found but no changes were made to the incoming data.
349
   */
350
  LUA_RM_MATCH,
351
  /*
352
   * Match was found and data was modified, so figure out what changed
353
   */
354
  LUA_RM_MATCH_AND_CHANGE,
355
};
356
357
static enum route_map_cmd_result_t
358
route_match_script(void *rule, const struct prefix *prefix, void *object)
359
{
360
  const char *scriptname = rule;
361
  const char *routematch_function = "route_match";
362
  struct bgp_path_info *path = (struct bgp_path_info *)object;
363
364
  struct frrscript *fs = frrscript_new(scriptname);
365
366
  if (frrscript_load(fs, routematch_function, NULL)) {
367
    zlog_err(
368
      "Issue loading script or function; defaulting to no match");
369
    return RMAP_NOMATCH;
370
  }
371
372
  struct attr newattr = *path->attr;
373
374
  int result = frrscript_call(
375
    fs, routematch_function, ("prefix", prefix),
376
    ("attributes", &newattr), ("peer", path->peer),
377
    ("RM_FAILURE", LUA_RM_FAILURE), ("RM_NOMATCH", LUA_RM_NOMATCH),
378
    ("RM_MATCH", LUA_RM_MATCH),
379
    ("RM_MATCH_AND_CHANGE", LUA_RM_MATCH_AND_CHANGE));
380
381
  if (result) {
382
    zlog_err("Issue running script rule; defaulting to no match");
383
    return RMAP_NOMATCH;
384
  }
385
386
  long long *action = frrscript_get_result(fs, routematch_function,
387
             "action", lua_tointegerp);
388
389
  int status = RMAP_NOMATCH;
390
391
  switch (*action) {
392
  case LUA_RM_FAILURE:
393
    zlog_err(
394
      "Executing route-map match script '%s' failed; defaulting to no match",
395
      scriptname);
396
    status = RMAP_NOMATCH;
397
    break;
398
  case LUA_RM_NOMATCH:
399
    status = RMAP_NOMATCH;
400
    break;
401
  case LUA_RM_MATCH_AND_CHANGE:
402
    status = RMAP_MATCH;
403
    zlog_debug("Updating attribute based on script's values");
404
405
    uint32_t locpref = 0;
406
407
    path->attr->med = newattr.med;
408
409
    if (path->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
410
      locpref = path->attr->local_pref;
411
    if (locpref != newattr.local_pref) {
412
      SET_FLAG(path->attr->flag,
413
         ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF));
414
      path->attr->local_pref = newattr.local_pref;
415
    }
416
    break;
417
  case LUA_RM_MATCH:
418
    status = RMAP_MATCH;
419
    break;
420
  }
421
422
  XFREE(MTYPE_SCRIPT_RES, action);
423
424
  frrscript_delete(fs);
425
426
  return status;
427
}
428
429
static void *route_match_script_compile(const char *arg)
430
{
431
  char *scriptname;
432
433
  scriptname = XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
434
435
  return scriptname;
436
}
437
438
static void route_match_script_free(void *rule)
439
{
440
  XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
441
}
442
443
static const struct route_map_rule_cmd route_match_script_cmd = {
444
  "script",
445
  route_match_script,
446
  route_match_script_compile,
447
  route_match_script_free
448
};
449
450
#endif /* HAVE_SCRIPTING */
451
452
/* `match ip address IP_ACCESS_LIST' */
453
454
/* Match function should return 1 if match is success else return
455
   zero. */
456
static enum route_map_cmd_result_t
457
route_match_ip_address(void *rule, const struct prefix *prefix, void *object)
458
0
{
459
0
  struct access_list *alist;
460
461
0
  if (prefix->family == AF_INET) {
462
0
    alist = access_list_lookup(AFI_IP, (char *)rule);
463
0
    if (alist == NULL) {
464
0
      if (unlikely(CHECK_FLAG(rmap_debug,
465
0
            DEBUG_ROUTEMAP_DETAIL)))
466
0
        zlog_debug(
467
0
          "%s: Access-List Specified: %s does not exist defaulting to NO_MATCH",
468
0
          __func__, (char *)rule);
469
0
      return RMAP_NOMATCH;
470
0
    }
471
472
0
    return (access_list_apply(alist, prefix) == FILTER_DENY
473
0
        ? RMAP_NOMATCH
474
0
        : RMAP_MATCH);
475
0
  }
476
0
  return RMAP_NOMATCH;
477
0
}
478
479
/* Route map `ip address' match statement.  `arg' should be
480
   access-list name. */
481
static void *route_match_ip_address_compile(const char *arg)
482
0
{
483
0
  struct access_list *alist;
484
485
0
  alist = access_list_lookup(AFI_IP, arg);
486
0
  if (!alist)
487
0
    zlog_warn(
488
0
      "Access List specified %s does not exist yet, default will be NO_MATCH until it is created",
489
0
      arg);
490
0
  return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
491
0
}
492
493
/* Free route map's compiled `ip address' value. */
494
static void route_match_ip_address_free(void *rule)
495
0
{
496
0
  XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
497
0
}
498
499
/* Route map commands for ip address matching. */
500
static const struct route_map_rule_cmd route_match_ip_address_cmd = {
501
  "ip address",
502
  route_match_ip_address,
503
  route_match_ip_address_compile,
504
  route_match_ip_address_free
505
};
506
507
/* `match ip next-hop <IP_ADDRESS_ACCESS_LIST_NAME>' */
508
509
/* Match function return 1 if match is success else return zero. */
510
static enum route_map_cmd_result_t
511
route_match_ip_next_hop(void *rule, const struct prefix *prefix, void *object)
512
0
{
513
0
  struct access_list *alist;
514
0
  struct bgp_path_info *path;
515
0
  struct prefix_ipv4 p;
516
517
0
  if (prefix->family == AF_INET) {
518
0
    path = object;
519
0
    p.family = AF_INET;
520
0
    p.prefix = path->attr->nexthop;
521
0
    p.prefixlen = IPV4_MAX_BITLEN;
522
523
0
    alist = access_list_lookup(AFI_IP, (char *)rule);
524
0
    if (alist == NULL) {
525
0
      if (unlikely(CHECK_FLAG(rmap_debug,
526
0
            DEBUG_ROUTEMAP_DETAIL)))
527
0
        zlog_debug(
528
0
          "%s: Access-List Specified: %s does not exist defaulting to NO_MATCH",
529
0
          __func__, (char *)rule);
530
531
0
      return RMAP_NOMATCH;
532
0
    }
533
534
0
    return (access_list_apply(alist, &p) == FILTER_DENY
535
0
        ? RMAP_NOMATCH
536
0
        : RMAP_MATCH);
537
0
  }
538
0
  return RMAP_NOMATCH;
539
0
}
540
541
/* Route map `ip next-hop' match statement. `arg' is
542
   access-list name. */
543
static void *route_match_ip_next_hop_compile(const char *arg)
544
0
{
545
0
  return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
546
0
}
547
548
/* Free route map's compiled `ip address' value. */
549
static void route_match_ip_next_hop_free(void *rule)
550
0
{
551
0
  XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
552
0
}
553
554
/* Route map commands for ip next-hop matching. */
555
static const struct route_map_rule_cmd route_match_ip_next_hop_cmd = {
556
  "ip next-hop",
557
  route_match_ip_next_hop,
558
  route_match_ip_next_hop_compile,
559
  route_match_ip_next_hop_free
560
};
561
562
/* `match ip route-source ACCESS-LIST' */
563
564
/* Match function return 1 if match is success else return zero. */
565
static enum route_map_cmd_result_t
566
route_match_ip_route_source(void *rule, const struct prefix *pfx, void *object)
567
0
{
568
0
  struct access_list *alist;
569
0
  struct bgp_path_info *path;
570
0
  struct peer *peer;
571
0
  struct prefix_ipv4 p;
572
573
0
  if (pfx->family == AF_INET) {
574
0
    path = object;
575
0
    peer = path->peer;
576
577
0
    if (!peer || sockunion_family(&peer->su) != AF_INET)
578
0
      return RMAP_NOMATCH;
579
580
0
    p.family = AF_INET;
581
0
    p.prefix = peer->su.sin.sin_addr;
582
0
    p.prefixlen = IPV4_MAX_BITLEN;
583
584
0
    alist = access_list_lookup(AFI_IP, (char *)rule);
585
0
    if (alist == NULL) {
586
0
      if (unlikely(CHECK_FLAG(rmap_debug,
587
0
            DEBUG_ROUTEMAP_DETAIL)))
588
0
        zlog_debug(
589
0
          "%s: Access-List Specified: %s does not exist defaulting to NO_MATCH",
590
0
          __func__, (char *)rule);
591
592
0
      return RMAP_NOMATCH;
593
0
    }
594
595
0
    return (access_list_apply(alist, &p) == FILTER_DENY
596
0
        ? RMAP_NOMATCH
597
0
        : RMAP_MATCH);
598
0
  }
599
0
  return RMAP_NOMATCH;
600
0
}
601
602
/* Route map `ip route-source' match statement. `arg' is
603
   access-list name. */
604
static void *route_match_ip_route_source_compile(const char *arg)
605
0
{
606
0
  return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
607
0
}
608
609
/* Free route map's compiled `ip address' value. */
610
static void route_match_ip_route_source_free(void *rule)
611
0
{
612
0
  XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
613
0
}
614
615
/* Route map commands for ip route-source matching. */
616
static const struct route_map_rule_cmd route_match_ip_route_source_cmd = {
617
  "ip route-source",
618
  route_match_ip_route_source,
619
  route_match_ip_route_source_compile,
620
  route_match_ip_route_source_free
621
};
622
623
static enum route_map_cmd_result_t
624
route_match_prefix_list_flowspec(afi_t afi, struct prefix_list *plist,
625
         const struct prefix *p)
626
0
{
627
0
  int ret;
628
0
  struct bgp_pbr_entry_main api;
629
630
0
  memset(&api, 0, sizeof(api));
631
632
0
  if (family2afi(p->u.prefix_flowspec.family) != afi)
633
0
    return RMAP_NOMATCH;
634
635
  /* extract match from flowspec entries */
636
0
  ret = bgp_flowspec_match_rules_fill(
637
0
              (uint8_t *)p->u.prefix_flowspec.ptr,
638
0
              p->u.prefix_flowspec.prefixlen, &api,
639
0
              afi);
640
0
  if (ret < 0)
641
0
    return RMAP_NOMATCH;
642
0
  if (api.match_bitmask & PREFIX_DST_PRESENT ||
643
0
      api.match_bitmask_iprule & PREFIX_DST_PRESENT) {
644
0
    if (family2afi((&api.dst_prefix)->family) != afi)
645
0
      return RMAP_NOMATCH;
646
0
    return prefix_list_apply(plist, &api.dst_prefix) == PREFIX_DENY
647
0
      ? RMAP_NOMATCH
648
0
      : RMAP_MATCH;
649
0
  } else if (api.match_bitmask & PREFIX_SRC_PRESENT ||
650
0
       api.match_bitmask_iprule & PREFIX_SRC_PRESENT) {
651
0
    if (family2afi((&api.src_prefix)->family) != afi)
652
0
      return RMAP_NOMATCH;
653
0
    return (prefix_list_apply(plist, &api.src_prefix) == PREFIX_DENY
654
0
      ? RMAP_NOMATCH
655
0
      : RMAP_MATCH);
656
0
  }
657
0
  return RMAP_NOMATCH;
658
0
}
659
660
static enum route_map_cmd_result_t
661
route_match_prefix_list_evpn(afi_t afi, struct prefix_list *plist,
662
           const struct prefix *p)
663
0
{
664
  /* Convert to match a general plist */
665
0
  struct prefix new;
666
667
0
  if (evpn_prefix2prefix(p, &new))
668
0
    return RMAP_NOMATCH;
669
670
0
  return (prefix_list_apply(plist, &new) == PREFIX_DENY ? RMAP_NOMATCH
671
0
                    : RMAP_MATCH);
672
0
}
673
674
static enum route_map_cmd_result_t
675
route_match_address_prefix_list(void *rule, afi_t afi,
676
        const struct prefix *prefix, void *object)
677
0
{
678
0
  struct prefix_list *plist;
679
680
0
  plist = prefix_list_lookup(afi, (char *)rule);
681
0
  if (plist == NULL) {
682
0
    if (unlikely(CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP_DETAIL)))
683
0
      zlog_debug(
684
0
        "%s: Prefix List %s specified does not exist defaulting to NO_MATCH",
685
0
        __func__, (char *)rule);
686
0
    return RMAP_NOMATCH;
687
0
  }
688
689
0
  if (prefix->family == AF_FLOWSPEC)
690
0
    return route_match_prefix_list_flowspec(afi, plist,
691
0
              prefix);
692
693
0
  else if (prefix->family == AF_EVPN)
694
0
    return route_match_prefix_list_evpn(afi, plist, prefix);
695
696
0
  return (prefix_list_apply(plist, prefix) == PREFIX_DENY ? RMAP_NOMATCH
697
0
                : RMAP_MATCH);
698
0
}
699
700
static enum route_map_cmd_result_t
701
route_match_ip_address_prefix_list(void *rule, const struct prefix *prefix,
702
           void *object)
703
0
{
704
0
  return route_match_address_prefix_list(rule, AFI_IP, prefix, object);
705
0
}
706
707
static void *route_match_ip_address_prefix_list_compile(const char *arg)
708
0
{
709
0
  return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
710
0
}
711
712
static void route_match_ip_address_prefix_list_free(void *rule)
713
0
{
714
0
  XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
715
0
}
716
717
static const struct route_map_rule_cmd
718
    route_match_ip_address_prefix_list_cmd = {
719
  "ip address prefix-list",
720
  route_match_ip_address_prefix_list,
721
  route_match_ip_address_prefix_list_compile,
722
  route_match_ip_address_prefix_list_free
723
};
724
725
/* `match ip next-hop prefix-list PREFIX_LIST' */
726
727
static enum route_map_cmd_result_t
728
route_match_ip_next_hop_prefix_list(void *rule, const struct prefix *prefix,
729
            void *object)
730
0
{
731
0
  struct prefix_list *plist;
732
0
  struct bgp_path_info *path;
733
0
  struct prefix_ipv4 p;
734
735
0
  if (prefix->family == AF_INET) {
736
0
    path = object;
737
0
    p.family = AF_INET;
738
0
    p.prefix = path->attr->nexthop;
739
0
    p.prefixlen = IPV4_MAX_BITLEN;
740
741
0
    plist = prefix_list_lookup(AFI_IP, (char *)rule);
742
0
    if (plist == NULL) {
743
0
      if (unlikely(CHECK_FLAG(rmap_debug,
744
0
            DEBUG_ROUTEMAP_DETAIL)))
745
0
        zlog_debug(
746
0
          "%s: Prefix List %s specified does not exist defaulting to NO_MATCH",
747
0
          __func__, (char *)rule);
748
0
      return RMAP_NOMATCH;
749
0
    }
750
751
0
    return (prefix_list_apply(plist, &p) == PREFIX_DENY
752
0
        ? RMAP_NOMATCH
753
0
        : RMAP_MATCH);
754
0
  }
755
0
  return RMAP_NOMATCH;
756
0
}
757
758
static void *route_match_ip_next_hop_prefix_list_compile(const char *arg)
759
0
{
760
0
  return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
761
0
}
762
763
static void route_match_ip_next_hop_prefix_list_free(void *rule)
764
0
{
765
0
  XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
766
0
}
767
768
static const struct route_map_rule_cmd
769
    route_match_ip_next_hop_prefix_list_cmd = {
770
  "ip next-hop prefix-list",
771
  route_match_ip_next_hop_prefix_list,
772
  route_match_ip_next_hop_prefix_list_compile,
773
  route_match_ip_next_hop_prefix_list_free
774
};
775
776
/* `match ipv6 next-hop prefix-list PREFIXLIST_NAME' */
777
static enum route_map_cmd_result_t
778
route_match_ipv6_next_hop_prefix_list(void *rule, const struct prefix *prefix,
779
              void *object)
780
0
{
781
0
  struct prefix_list *plist;
782
0
  struct bgp_path_info *path;
783
0
  struct prefix_ipv6 p;
784
785
0
  if (prefix->family == AF_INET6) {
786
0
    path = object;
787
0
    p.family = AF_INET6;
788
0
    p.prefix = path->attr->mp_nexthop_global;
789
0
    p.prefixlen = IPV6_MAX_BITLEN;
790
791
0
    plist = prefix_list_lookup(AFI_IP6, (char *)rule);
792
0
    if (!plist) {
793
0
      if (unlikely(CHECK_FLAG(rmap_debug,
794
0
            DEBUG_ROUTEMAP_DETAIL)))
795
0
        zlog_debug(
796
0
          "%s: Prefix List %s specified does not exist defaulting to NO_MATCH",
797
0
          __func__, (char *)rule);
798
0
      return RMAP_NOMATCH;
799
0
    }
800
801
0
    if (prefix_list_apply(plist, &p) == PREFIX_PERMIT)
802
0
      return RMAP_MATCH;
803
804
0
    if (path->attr->mp_nexthop_len
805
0
        == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
806
0
      p.prefix = path->attr->mp_nexthop_local;
807
0
      if (prefix_list_apply(plist, &p) == PREFIX_PERMIT)
808
0
        return RMAP_MATCH;
809
0
    }
810
0
  }
811
812
0
  return RMAP_NOMATCH;
813
0
}
814
815
static void *route_match_ipv6_next_hop_prefix_list_compile(const char *arg)
816
0
{
817
0
  return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
818
0
}
819
820
static void route_match_ipv6_next_hop_prefix_list_free(void *rule)
821
0
{
822
0
  XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
823
0
}
824
825
static const struct route_map_rule_cmd
826
    route_match_ipv6_next_hop_prefix_list_cmd = {
827
  "ipv6 next-hop prefix-list",
828
  route_match_ipv6_next_hop_prefix_list,
829
  route_match_ipv6_next_hop_prefix_list_compile,
830
  route_match_ipv6_next_hop_prefix_list_free
831
};
832
833
/* `match ip next-hop type <blackhole>' */
834
835
static enum route_map_cmd_result_t
836
route_match_ip_next_hop_type(void *rule, const struct prefix *prefix,
837
           void *object)
838
0
{
839
0
  struct bgp_path_info *path;
840
841
0
  if (prefix->family == AF_INET) {
842
0
    path = (struct bgp_path_info *)object;
843
0
    if (!path)
844
0
      return RMAP_NOMATCH;
845
846
    /* If nexthop interface's index can't be resolved and nexthop is
847
       set to any address then mark it as type `blackhole`.
848
       This logic works for matching kernel/static routes like:
849
       `ip route add blackhole 10.0.0.1`. */
850
0
    if (path->attr->nexthop.s_addr == INADDR_ANY
851
0
        && !path->attr->nh_ifindex)
852
0
      return RMAP_MATCH;
853
0
  }
854
0
  return RMAP_NOMATCH;
855
0
}
856
857
static void *route_match_ip_next_hop_type_compile(const char *arg)
858
0
{
859
0
  return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
860
0
}
861
862
static void route_match_ip_next_hop_type_free(void *rule)
863
0
{
864
0
  XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
865
0
}
866
867
static const struct route_map_rule_cmd
868
    route_match_ip_next_hop_type_cmd = {
869
  "ip next-hop type",
870
  route_match_ip_next_hop_type,
871
  route_match_ip_next_hop_type_compile,
872
  route_match_ip_next_hop_type_free
873
};
874
875
/* `match source-protocol` */
876
static enum route_map_cmd_result_t
877
route_match_source_protocol(void *rule, const struct prefix *prefix,
878
          void *object)
879
0
{
880
0
  struct bgp_path_info *path = object;
881
0
  int *protocol = rule;
882
883
0
  if (!path)
884
0
    return RMAP_NOMATCH;
885
886
0
  if (path->type == *protocol)
887
0
    return RMAP_MATCH;
888
889
0
  return RMAP_NOMATCH;
890
0
}
891
892
static void *route_match_source_protocol_compile(const char *arg)
893
0
{
894
0
  int *protocol;
895
896
0
  protocol = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(*protocol));
897
0
  *protocol = proto_name2num(arg);
898
899
0
  return protocol;
900
0
}
901
902
static void route_match_source_protocol_free(void *rule)
903
0
{
904
0
  XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
905
0
}
906
907
static const struct route_map_rule_cmd route_match_source_protocol_cmd = {
908
  "source-protocol",
909
  route_match_source_protocol,
910
  route_match_source_protocol_compile,
911
  route_match_source_protocol_free
912
};
913
914
915
/* `match ip route-source prefix-list PREFIX_LIST' */
916
917
static enum route_map_cmd_result_t
918
route_match_ip_route_source_prefix_list(void *rule, const struct prefix *prefix,
919
          void *object)
920
0
{
921
0
  struct prefix_list *plist;
922
0
  struct bgp_path_info *path;
923
0
  struct peer *peer;
924
0
  struct prefix_ipv4 p;
925
926
0
  if (prefix->family == AF_INET) {
927
0
    path = object;
928
0
    peer = path->peer;
929
930
0
    if (!peer || sockunion_family(&peer->su) != AF_INET)
931
0
      return RMAP_NOMATCH;
932
933
0
    p.family = AF_INET;
934
0
    p.prefix = peer->su.sin.sin_addr;
935
0
    p.prefixlen = IPV4_MAX_BITLEN;
936
937
0
    plist = prefix_list_lookup(AFI_IP, (char *)rule);
938
0
    if (plist == NULL) {
939
0
      if (unlikely(CHECK_FLAG(rmap_debug,
940
0
            DEBUG_ROUTEMAP_DETAIL)))
941
0
        zlog_debug(
942
0
          "%s: Prefix List %s specified does not exist defaulting to NO_MATCH",
943
0
          __func__, (char *)rule);
944
0
      return RMAP_NOMATCH;
945
0
    }
946
947
0
    return (prefix_list_apply(plist, &p) == PREFIX_DENY
948
0
        ? RMAP_NOMATCH
949
0
        : RMAP_MATCH);
950
0
  }
951
0
  return RMAP_NOMATCH;
952
0
}
953
954
static void *route_match_ip_route_source_prefix_list_compile(const char *arg)
955
0
{
956
0
  return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
957
0
}
958
959
static void route_match_ip_route_source_prefix_list_free(void *rule)
960
0
{
961
0
  XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
962
0
}
963
964
static const struct route_map_rule_cmd
965
    route_match_ip_route_source_prefix_list_cmd = {
966
  "ip route-source prefix-list",
967
  route_match_ip_route_source_prefix_list,
968
  route_match_ip_route_source_prefix_list_compile,
969
  route_match_ip_route_source_prefix_list_free
970
};
971
972
/* `match evpn default-route' */
973
974
/* Match function should return 1 if match is success else 0 */
975
static enum route_map_cmd_result_t
976
route_match_evpn_default_route(void *rule, const struct prefix *p, void *object)
977
0
{
978
0
  if (is_evpn_prefix_default(p))
979
0
    return RMAP_MATCH;
980
981
0
  return RMAP_NOMATCH;
982
0
}
983
984
/* Route map commands for default-route matching. */
985
static const struct route_map_rule_cmd
986
    route_match_evpn_default_route_cmd = {
987
  "evpn default-route",
988
  route_match_evpn_default_route,
989
  NULL,
990
  NULL
991
};
992
993
/* `match mac address MAC_ACCESS_LIST' */
994
995
/* Match function should return 1 if match is success else return
996
   zero. */
997
static enum route_map_cmd_result_t
998
route_match_mac_address(void *rule, const struct prefix *prefix, void *object)
999
0
{
1000
0
  struct access_list *alist;
1001
0
  struct prefix p;
1002
1003
0
  alist = access_list_lookup(AFI_L2VPN, (char *)rule);
1004
0
  if (alist == NULL) {
1005
0
    if (unlikely(CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP_DETAIL)))
1006
0
      zlog_debug(
1007
0
        "%s: Access-List Specified: %s does not exist defaulting to NO_MATCH",
1008
0
        __func__, (char *)rule);
1009
1010
0
    return RMAP_NOMATCH;
1011
0
  }
1012
0
  if (prefix->u.prefix_evpn.route_type != BGP_EVPN_MAC_IP_ROUTE) {
1013
0
    if (unlikely(CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP_DETAIL)))
1014
0
      zlog_debug(
1015
0
        "%s: Prefix %pFX is not a EVPN MAC IP ROUTE defaulting to NO_MATCH",
1016
0
        __func__, prefix);
1017
0
    return RMAP_NOMATCH;
1018
0
  }
1019
1020
0
  p.family = AF_ETHERNET;
1021
0
  p.prefixlen = ETH_ALEN * 8;
1022
0
  p.u.prefix_eth = prefix->u.prefix_evpn.macip_addr.mac;
1023
1024
0
  return (access_list_apply(alist, &p) == FILTER_DENY ? RMAP_NOMATCH
1025
0
                  : RMAP_MATCH);
1026
0
}
1027
1028
/* Route map `mac address' match statement.  `arg' should be
1029
   access-list name. */
1030
static void *route_match_mac_address_compile(const char *arg)
1031
0
{
1032
0
  return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
1033
0
}
1034
1035
/* Free route map's compiled `ip address' value. */
1036
static void route_match_mac_address_free(void *rule)
1037
0
{
1038
0
  XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
1039
0
}
1040
1041
/* Route map commands for mac address matching. */
1042
static const struct route_map_rule_cmd route_match_mac_address_cmd = {
1043
  "mac address",
1044
  route_match_mac_address,
1045
  route_match_mac_address_compile,
1046
  route_match_mac_address_free
1047
};
1048
1049
/*
1050
 * Match function returns:
1051
 * ...RMAP_MATCH if match is found.
1052
 * ...RMAP_NOMATCH if match is not found.
1053
 * ...RMAP_NOOP to ignore this match check.
1054
 */
1055
static enum route_map_cmd_result_t
1056
route_match_vni(void *rule, const struct prefix *prefix, void *object)
1057
0
{
1058
0
  vni_t vni = 0;
1059
0
  unsigned int label_cnt = 0;
1060
0
  struct bgp_path_info *path = NULL;
1061
0
  struct prefix_evpn *evp = (struct prefix_evpn *) prefix;
1062
1063
0
  vni = *((vni_t *)rule);
1064
0
  path = (struct bgp_path_info *)object;
1065
1066
  /*
1067
   * This rmap filter is valid for vxlan tunnel type only.
1068
   * For any other tunnel type, return noop to ignore
1069
   * this check.
1070
   */
1071
0
  if (path->attr->encap_tunneltype != BGP_ENCAP_TYPE_VXLAN)
1072
0
    return RMAP_NOOP;
1073
1074
  /*
1075
   * Apply filter to type 1, 2, 5 routes only.
1076
   * Other route types do not have vni label.
1077
   */
1078
0
  if (evp
1079
0
      && (evp->prefix.route_type != BGP_EVPN_AD_ROUTE
1080
0
    && evp->prefix.route_type != BGP_EVPN_MAC_IP_ROUTE
1081
0
    && evp->prefix.route_type != BGP_EVPN_IP_PREFIX_ROUTE))
1082
0
    return RMAP_NOOP;
1083
1084
0
  if (path->extra == NULL)
1085
0
    return RMAP_NOMATCH;
1086
1087
0
  for (;
1088
0
       label_cnt < BGP_MAX_LABELS && label_cnt < path->extra->num_labels;
1089
0
       label_cnt++) {
1090
0
    if (vni == label2vni(&path->extra->label[label_cnt]))
1091
0
      return RMAP_MATCH;
1092
0
  }
1093
1094
0
  return RMAP_NOMATCH;
1095
0
}
1096
1097
/* Route map `vni' match statement. */
1098
static void *route_match_vni_compile(const char *arg)
1099
0
{
1100
0
  vni_t *vni = NULL;
1101
0
  char *end = NULL;
1102
1103
0
  vni = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(vni_t));
1104
1105
0
  *vni = strtoul(arg, &end, 10);
1106
0
  if (*end != '\0') {
1107
0
    XFREE(MTYPE_ROUTE_MAP_COMPILED, vni);
1108
0
    return NULL;
1109
0
  }
1110
1111
0
  return vni;
1112
0
}
1113
1114
/* Free route map's compiled `vni' value. */
1115
static void route_match_vni_free(void *rule)
1116
0
{
1117
0
  XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
1118
0
}
1119
1120
/* Route map commands for vni matching. */
1121
static const struct route_map_rule_cmd route_match_evpn_vni_cmd = {
1122
  "evpn vni",
1123
  route_match_vni,
1124
  route_match_vni_compile,
1125
  route_match_vni_free
1126
};
1127
1128
/* `match evpn route-type' */
1129
1130
/* Match function should return 1 if match is success else return
1131
   zero. */
1132
static enum route_map_cmd_result_t
1133
route_match_evpn_route_type(void *rule, const struct prefix *pfx, void *object)
1134
0
{
1135
0
  uint8_t route_type = 0;
1136
1137
0
  route_type = *((uint8_t *)rule);
1138
1139
0
  if (route_type == pfx->u.prefix_evpn.route_type)
1140
0
    return RMAP_MATCH;
1141
1142
0
  return RMAP_NOMATCH;
1143
0
}
1144
1145
/* Route map `route-type' match statement. */
1146
static void *route_match_evpn_route_type_compile(const char *arg)
1147
0
{
1148
0
  uint8_t *route_type = NULL;
1149
1150
0
  route_type = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(uint8_t));
1151
1152
0
  if (strncmp(arg, "ea", 2) == 0)
1153
0
    *route_type = BGP_EVPN_AD_ROUTE;
1154
0
  else if (strncmp(arg, "ma", 2) == 0)
1155
0
    *route_type = BGP_EVPN_MAC_IP_ROUTE;
1156
0
  else if (strncmp(arg, "mu", 2) == 0)
1157
0
    *route_type = BGP_EVPN_IMET_ROUTE;
1158
0
  else if (strncmp(arg, "es", 2) == 0)
1159
0
    *route_type = BGP_EVPN_ES_ROUTE;
1160
0
  else
1161
0
    *route_type = BGP_EVPN_IP_PREFIX_ROUTE;
1162
1163
0
  return route_type;
1164
0
}
1165
1166
/* Free route map's compiled `route-type' value. */
1167
static void route_match_evpn_route_type_free(void *rule)
1168
0
{
1169
0
  XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
1170
0
}
1171
1172
/* Route map commands for evpn route-type  matching. */
1173
static const struct route_map_rule_cmd route_match_evpn_route_type_cmd = {
1174
  "evpn route-type",
1175
  route_match_evpn_route_type,
1176
  route_match_evpn_route_type_compile,
1177
  route_match_evpn_route_type_free
1178
};
1179
1180
/* `match rd' */
1181
1182
/* Match function should return 1 if match is success else return zero. */
1183
static enum route_map_cmd_result_t
1184
route_match_rd(void *rule, const struct prefix *prefix, void *object)
1185
0
{
1186
0
  struct prefix_rd *prd_rule = NULL;
1187
0
  const struct prefix_rd *prd_route = NULL;
1188
0
  struct bgp_path_info *path = NULL;
1189
1190
0
  if (prefix->family != AF_EVPN)
1191
0
    return RMAP_NOMATCH;
1192
1193
0
  prd_rule = (struct prefix_rd *)rule;
1194
0
  path = (struct bgp_path_info *)object;
1195
1196
0
  if (path->net == NULL || path->net->pdest == NULL)
1197
0
    return RMAP_NOMATCH;
1198
1199
0
  prd_route = (struct prefix_rd *)bgp_dest_get_prefix(path->net->pdest);
1200
0
  if (memcmp(prd_route->val, prd_rule->val, ECOMMUNITY_SIZE) == 0)
1201
0
    return RMAP_MATCH;
1202
1203
0
  return RMAP_NOMATCH;
1204
0
}
1205
1206
/* Route map `rd' match statement. */
1207
static void *route_match_rd_compile(const char *arg)
1208
0
{
1209
0
  struct prefix_rd *prd;
1210
0
  int ret;
1211
1212
0
  prd = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct prefix_rd));
1213
1214
0
  ret = str2prefix_rd(arg, prd);
1215
0
  if (!ret) {
1216
0
    XFREE(MTYPE_ROUTE_MAP_COMPILED, prd);
1217
0
    return NULL;
1218
0
  }
1219
1220
0
  return prd;
1221
0
}
1222
1223
/* Free route map's compiled `rd' value. */
1224
static void route_match_rd_free(void *rule)
1225
0
{
1226
0
  XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
1227
0
}
1228
1229
/* Route map commands for rd matching. */
1230
static const struct route_map_rule_cmd route_match_evpn_rd_cmd = {
1231
  "evpn rd",
1232
  route_match_rd,
1233
  route_match_rd_compile,
1234
  route_match_rd_free
1235
};
1236
1237
static enum route_map_cmd_result_t
1238
route_set_evpn_gateway_ip(void *rule, const struct prefix *prefix, void *object)
1239
0
{
1240
0
  struct ipaddr *gw_ip = rule;
1241
0
  struct bgp_path_info *path;
1242
0
  struct prefix_evpn *evp;
1243
1244
0
  if (prefix->family != AF_EVPN)
1245
0
    return RMAP_OKAY;
1246
1247
0
  evp = (struct prefix_evpn *)prefix;
1248
0
  if (evp->prefix.route_type != BGP_EVPN_IP_PREFIX_ROUTE)
1249
0
    return RMAP_OKAY;
1250
1251
0
  if ((is_evpn_prefix_ipaddr_v4(evp) && IPADDRSZ(gw_ip) != 4)
1252
0
      || (is_evpn_prefix_ipaddr_v6(evp) && IPADDRSZ(gw_ip) != 16))
1253
0
    return RMAP_OKAY;
1254
1255
0
  path = object;
1256
1257
  /* Set gateway-ip value. */
1258
0
  path->attr->evpn_overlay.type = OVERLAY_INDEX_GATEWAY_IP;
1259
0
  memcpy(&path->attr->evpn_overlay.gw_ip, &gw_ip->ip.addr,
1260
0
         IPADDRSZ(gw_ip));
1261
1262
0
  return RMAP_OKAY;
1263
0
}
1264
1265
/*
1266
 * Route map `evpn gateway-ip' compile function.
1267
 * Given string is converted to struct ipaddr structure
1268
 */
1269
static void *route_set_evpn_gateway_ip_compile(const char *arg)
1270
0
{
1271
0
  struct ipaddr *gw_ip = NULL;
1272
0
  int ret;
1273
1274
0
  gw_ip = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct ipaddr));
1275
1276
0
  ret = str2ipaddr(arg, gw_ip);
1277
0
  if (ret < 0) {
1278
0
    XFREE(MTYPE_ROUTE_MAP_COMPILED, gw_ip);
1279
0
    return NULL;
1280
0
  }
1281
0
  return gw_ip;
1282
0
}
1283
1284
/* Free route map's compiled `evpn gateway_ip' value. */
1285
static void route_set_evpn_gateway_ip_free(void *rule)
1286
0
{
1287
0
  struct ipaddr *gw_ip = rule;
1288
1289
0
  XFREE(MTYPE_ROUTE_MAP_COMPILED, gw_ip);
1290
0
}
1291
1292
/* Route map commands for set evpn gateway-ip ipv4. */
1293
struct route_map_rule_cmd route_set_evpn_gateway_ip_ipv4_cmd = {
1294
  "evpn gateway-ip ipv4", route_set_evpn_gateway_ip,
1295
  route_set_evpn_gateway_ip_compile, route_set_evpn_gateway_ip_free};
1296
1297
/* Route map commands for set evpn gateway-ip ipv6. */
1298
struct route_map_rule_cmd route_set_evpn_gateway_ip_ipv6_cmd = {
1299
  "evpn gateway-ip ipv6", route_set_evpn_gateway_ip,
1300
  route_set_evpn_gateway_ip_compile, route_set_evpn_gateway_ip_free};
1301
1302
/* Route map commands for VRF route leak with source vrf matching */
1303
static enum route_map_cmd_result_t
1304
route_match_vrl_source_vrf(void *rule, const struct prefix *prefix,
1305
         void *object)
1306
0
{
1307
0
  struct bgp_path_info *path;
1308
0
  char *vrf_name;
1309
1310
0
  vrf_name = rule;
1311
0
  path = (struct bgp_path_info *)object;
1312
1313
0
  if (strncmp(vrf_name, "n/a", VRF_NAMSIZ) == 0)
1314
0
    return RMAP_NOMATCH;
1315
1316
0
  if (path->extra == NULL || path->extra->bgp_orig == NULL)
1317
0
    return RMAP_NOMATCH;
1318
1319
0
  if (strncmp(vrf_name, vrf_id_to_name(path->extra->bgp_orig->vrf_id),
1320
0
        VRF_NAMSIZ)
1321
0
      == 0)
1322
0
    return RMAP_MATCH;
1323
1324
0
  return RMAP_NOMATCH;
1325
0
}
1326
1327
static void *route_match_vrl_source_vrf_compile(const char *arg)
1328
0
{
1329
0
  uint8_t *vrf_name = NULL;
1330
1331
0
  vrf_name = XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
1332
1333
0
  return vrf_name;
1334
0
}
1335
1336
/* Free route map's compiled `route-type' value. */
1337
static void route_match_vrl_source_vrf_free(void *rule)
1338
0
{
1339
0
  XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
1340
0
}
1341
1342
static const struct route_map_rule_cmd route_match_vrl_source_vrf_cmd = {
1343
  "source-vrf",
1344
  route_match_vrl_source_vrf,
1345
  route_match_vrl_source_vrf_compile,
1346
  route_match_vrl_source_vrf_free
1347
};
1348
1349
/* `match alias` */
1350
static enum route_map_cmd_result_t
1351
route_match_alias(void *rule, const struct prefix *prefix, void *object)
1352
0
{
1353
0
  char *alias = rule;
1354
0
  struct bgp_path_info *path = object;
1355
0
  char **communities;
1356
0
  int num;
1357
0
  bool found;
1358
1359
0
  if (bgp_attr_get_community(path->attr)) {
1360
0
    found = false;
1361
0
    frrstr_split(bgp_attr_get_community(path->attr)->str, " ",
1362
0
           &communities, &num);
1363
0
    for (int i = 0; i < num; i++) {
1364
0
      const char *com2alias =
1365
0
        bgp_community2alias(communities[i]);
1366
0
      if (!found && strcmp(alias, com2alias) == 0)
1367
0
        found = true;
1368
0
      XFREE(MTYPE_TMP, communities[i]);
1369
0
    }
1370
0
    XFREE(MTYPE_TMP, communities);
1371
0
    if (found)
1372
0
      return RMAP_MATCH;
1373
0
  }
1374
1375
0
  if (bgp_attr_get_lcommunity(path->attr)) {
1376
0
    found = false;
1377
0
    frrstr_split(bgp_attr_get_lcommunity(path->attr)->str, " ",
1378
0
           &communities, &num);
1379
0
    for (int i = 0; i < num; i++) {
1380
0
      const char *com2alias =
1381
0
        bgp_community2alias(communities[i]);
1382
0
      if (!found && strcmp(alias, com2alias) == 0)
1383
0
        found = true;
1384
0
      XFREE(MTYPE_TMP, communities[i]);
1385
0
    }
1386
0
    XFREE(MTYPE_TMP, communities);
1387
0
    if (found)
1388
0
      return RMAP_MATCH;
1389
0
  }
1390
1391
0
  return RMAP_NOMATCH;
1392
0
}
1393
1394
static void *route_match_alias_compile(const char *arg)
1395
0
{
1396
1397
0
  return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
1398
0
}
1399
1400
static void route_match_alias_free(void *rule)
1401
0
{
1402
0
  XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
1403
0
}
1404
1405
static const struct route_map_rule_cmd route_match_alias_cmd = {
1406
  "alias", route_match_alias, route_match_alias_compile,
1407
  route_match_alias_free};
1408
1409
/* `match local-preference LOCAL-PREF' */
1410
1411
/* Match function return 1 if match is success else return zero. */
1412
static enum route_map_cmd_result_t
1413
route_match_local_pref(void *rule, const struct prefix *prefix, void *object)
1414
0
{
1415
0
  uint32_t *local_pref;
1416
0
  struct bgp_path_info *path;
1417
1418
0
  local_pref = rule;
1419
0
  path = object;
1420
1421
0
  if (path->attr->local_pref == *local_pref)
1422
0
    return RMAP_MATCH;
1423
0
  else
1424
0
    return RMAP_NOMATCH;
1425
0
}
1426
1427
/*
1428
 * Route map `match local-preference' match statement.
1429
 * `arg' is local-pref value
1430
 */
1431
static void *route_match_local_pref_compile(const char *arg)
1432
0
{
1433
0
  uint32_t *local_pref;
1434
0
  char *endptr = NULL;
1435
0
  unsigned long tmpval;
1436
1437
0
  errno = 0;
1438
0
  tmpval = strtoul(arg, &endptr, 10);
1439
0
  if (*endptr != '\0' || errno || tmpval > UINT32_MAX)
1440
0
    return NULL;
1441
1442
0
  local_pref = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(uint32_t));
1443
1444
0
  *local_pref = tmpval;
1445
0
  return local_pref;
1446
0
}
1447
1448
/* Free route map's compiled `match local-preference' value. */
1449
static void route_match_local_pref_free(void *rule)
1450
0
{
1451
0
  XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
1452
0
}
1453
1454
/* Route map commands for metric matching. */
1455
static const struct route_map_rule_cmd route_match_local_pref_cmd = {
1456
  "local-preference",
1457
  route_match_local_pref,
1458
  route_match_local_pref_compile,
1459
  route_match_local_pref_free
1460
};
1461
1462
/* `match metric METRIC' */
1463
1464
/* Match function return 1 if match is success else return zero. */
1465
static enum route_map_cmd_result_t
1466
route_match_metric(void *rule, const struct prefix *prefix, void *object)
1467
0
{
1468
0
  struct rmap_value *rv;
1469
0
  struct bgp_path_info *path;
1470
1471
0
  rv = rule;
1472
0
  path = object;
1473
0
  return route_value_match(rv, path->attr->med);
1474
0
}
1475
1476
/* Route map commands for metric matching. */
1477
static const struct route_map_rule_cmd route_match_metric_cmd = {
1478
  "metric",
1479
  route_match_metric,
1480
  route_value_compile,
1481
  route_value_free,
1482
};
1483
1484
/* `match as-path ASPATH' */
1485
1486
/* Match function for as-path match.  I assume given object is */
1487
static enum route_map_cmd_result_t
1488
route_match_aspath(void *rule, const struct prefix *prefix, void *object)
1489
0
{
1490
1491
0
  struct as_list *as_list;
1492
0
  struct bgp_path_info *path;
1493
1494
0
  as_list = as_list_lookup((char *)rule);
1495
0
  if (as_list == NULL)
1496
0
    return RMAP_NOMATCH;
1497
1498
0
  path = object;
1499
1500
  /* Perform match. */
1501
0
  return ((as_list_apply(as_list, path->attr->aspath) == AS_FILTER_DENY)
1502
0
      ? RMAP_NOMATCH
1503
0
      : RMAP_MATCH);
1504
0
}
1505
1506
/* Compile function for as-path match. */
1507
static void *route_match_aspath_compile(const char *arg)
1508
0
{
1509
0
  return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
1510
0
}
1511
1512
/* Compile function for as-path match. */
1513
static void route_match_aspath_free(void *rule)
1514
0
{
1515
0
  XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
1516
0
}
1517
1518
/* Route map commands for aspath matching. */
1519
static const struct route_map_rule_cmd route_match_aspath_cmd = {
1520
  "as-path",
1521
  route_match_aspath,
1522
  route_match_aspath_compile,
1523
  route_match_aspath_free
1524
};
1525
1526
/* `match community COMMUNIY' */
1527
struct rmap_community {
1528
  char *name;
1529
  uint32_t name_hash;
1530
  int exact;
1531
};
1532
1533
/* Match function for community match. */
1534
static enum route_map_cmd_result_t
1535
route_match_community(void *rule, const struct prefix *prefix, void *object)
1536
0
{
1537
0
  struct community_list *list;
1538
0
  struct bgp_path_info *path;
1539
0
  struct rmap_community *rcom = rule;
1540
1541
0
  path = object;
1542
0
  rcom = rule;
1543
1544
0
  list = community_list_lookup(bgp_clist, rcom->name, rcom->name_hash,
1545
0
             COMMUNITY_LIST_MASTER);
1546
0
  if (!list)
1547
0
    return RMAP_NOMATCH;
1548
1549
0
  if (rcom->exact) {
1550
0
    if (community_list_exact_match(
1551
0
          bgp_attr_get_community(path->attr), list))
1552
0
      return RMAP_MATCH;
1553
0
  } else {
1554
0
    if (community_list_match(bgp_attr_get_community(path->attr),
1555
0
           list))
1556
0
      return RMAP_MATCH;
1557
0
  }
1558
1559
0
  return RMAP_NOMATCH;
1560
0
}
1561
1562
/* Compile function for community match. */
1563
static void *route_match_community_compile(const char *arg)
1564
0
{
1565
0
  struct rmap_community *rcom;
1566
0
  int len;
1567
0
  char *p;
1568
1569
0
  rcom = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_community));
1570
1571
0
  p = strchr(arg, ' ');
1572
0
  if (p) {
1573
0
    len = p - arg;
1574
0
    rcom->name = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, len + 1);
1575
0
    memcpy(rcom->name, arg, len);
1576
0
    rcom->exact = 1;
1577
0
  } else {
1578
0
    rcom->name = XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
1579
0
    rcom->exact = 0;
1580
0
  }
1581
1582
0
  rcom->name_hash = bgp_clist_hash_key(rcom->name);
1583
0
  return rcom;
1584
0
}
1585
1586
/* Compile function for community match. */
1587
static void route_match_community_free(void *rule)
1588
0
{
1589
0
  struct rmap_community *rcom = rule;
1590
1591
0
  XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom->name);
1592
0
  XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom);
1593
0
}
1594
1595
/*
1596
 * In routemap processing there is a need to add the
1597
 * name as a rule_key in the dependency table. Routemap
1598
 * lib is unaware of rule_key when exact-match clause
1599
 * is in use. routemap lib uses the compiled output to
1600
 * get the rule_key value.
1601
 */
1602
static void *route_match_get_community_key(void *rule)
1603
0
{
1604
0
  struct rmap_community *rcom;
1605
1606
0
  rcom = rule;
1607
0
  return rcom->name;
1608
0
}
1609
1610
1611
/* Route map commands for community matching. */
1612
static const struct route_map_rule_cmd route_match_community_cmd = {
1613
  "community",
1614
  route_match_community,
1615
  route_match_community_compile,
1616
  route_match_community_free,
1617
  route_match_get_community_key
1618
};
1619
1620
/* Match function for lcommunity match. */
1621
static enum route_map_cmd_result_t
1622
route_match_lcommunity(void *rule, const struct prefix *prefix, void *object)
1623
0
{
1624
0
  struct community_list *list;
1625
0
  struct bgp_path_info *path;
1626
0
  struct rmap_community *rcom = rule;
1627
1628
0
  path = object;
1629
1630
0
  list = community_list_lookup(bgp_clist, rcom->name, rcom->name_hash,
1631
0
             LARGE_COMMUNITY_LIST_MASTER);
1632
0
  if (!list)
1633
0
    return RMAP_NOMATCH;
1634
1635
0
  if (rcom->exact) {
1636
0
    if (lcommunity_list_exact_match(
1637
0
          bgp_attr_get_lcommunity(path->attr), list))
1638
0
      return RMAP_MATCH;
1639
0
  } else {
1640
0
    if (lcommunity_list_match(bgp_attr_get_lcommunity(path->attr),
1641
0
            list))
1642
0
      return RMAP_MATCH;
1643
0
  }
1644
1645
0
  return RMAP_NOMATCH;
1646
0
}
1647
1648
/* Compile function for community match. */
1649
static void *route_match_lcommunity_compile(const char *arg)
1650
0
{
1651
0
  struct rmap_community *rcom;
1652
0
  int len;
1653
0
  char *p;
1654
1655
0
  rcom = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_community));
1656
1657
0
  p = strchr(arg, ' ');
1658
0
  if (p) {
1659
0
    len = p - arg;
1660
0
    rcom->name = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, len + 1);
1661
0
    memcpy(rcom->name, arg, len);
1662
0
    rcom->exact = 1;
1663
0
  } else {
1664
0
    rcom->name = XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
1665
0
    rcom->exact = 0;
1666
0
  }
1667
1668
0
  rcom->name_hash = bgp_clist_hash_key(rcom->name);
1669
0
  return rcom;
1670
0
}
1671
1672
/* Compile function for community match. */
1673
static void route_match_lcommunity_free(void *rule)
1674
0
{
1675
0
  struct rmap_community *rcom = rule;
1676
1677
0
  XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom->name);
1678
0
  XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom);
1679
0
}
1680
1681
/* Route map commands for community matching. */
1682
static const struct route_map_rule_cmd route_match_lcommunity_cmd = {
1683
  "large-community",
1684
  route_match_lcommunity,
1685
  route_match_lcommunity_compile,
1686
  route_match_lcommunity_free,
1687
  route_match_get_community_key
1688
};
1689
1690
1691
/* Match function for extcommunity match. */
1692
static enum route_map_cmd_result_t
1693
route_match_ecommunity(void *rule, const struct prefix *prefix, void *object)
1694
0
{
1695
0
  struct community_list *list;
1696
0
  struct bgp_path_info *path;
1697
0
  struct rmap_community *rcom = rule;
1698
1699
0
  path = object;
1700
1701
0
  list = community_list_lookup(bgp_clist, rcom->name, rcom->name_hash,
1702
0
             EXTCOMMUNITY_LIST_MASTER);
1703
0
  if (!list)
1704
0
    return RMAP_NOMATCH;
1705
1706
0
  if (ecommunity_list_match(bgp_attr_get_ecommunity(path->attr), list))
1707
0
    return RMAP_MATCH;
1708
1709
0
  return RMAP_NOMATCH;
1710
0
}
1711
1712
/* Compile function for extcommunity match. */
1713
static void *route_match_ecommunity_compile(const char *arg)
1714
0
{
1715
0
  struct rmap_community *rcom;
1716
1717
0
  rcom = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_community));
1718
0
  rcom->name = XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
1719
0
  rcom->name_hash = bgp_clist_hash_key(rcom->name);
1720
1721
0
  return rcom;
1722
0
}
1723
1724
/* Compile function for extcommunity match. */
1725
static void route_match_ecommunity_free(void *rule)
1726
0
{
1727
0
  struct rmap_community *rcom = rule;
1728
1729
0
  XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom->name);
1730
0
  XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom);
1731
0
}
1732
1733
/* Route map commands for community matching. */
1734
static const struct route_map_rule_cmd route_match_ecommunity_cmd = {
1735
  "extcommunity",
1736
  route_match_ecommunity,
1737
  route_match_ecommunity_compile,
1738
  route_match_ecommunity_free
1739
};
1740
1741
/* `match nlri` and `set nlri` are replaced by `address-family ipv4`
1742
   and `address-family vpnv4'.  */
1743
1744
/* `match origin' */
1745
static enum route_map_cmd_result_t
1746
route_match_origin(void *rule, const struct prefix *prefix, void *object)
1747
0
{
1748
0
  uint8_t *origin;
1749
0
  struct bgp_path_info *path;
1750
1751
0
  origin = rule;
1752
0
  path = object;
1753
1754
0
  if (path->attr->origin == *origin)
1755
0
    return RMAP_MATCH;
1756
1757
0
  return RMAP_NOMATCH;
1758
0
}
1759
1760
static void *route_match_origin_compile(const char *arg)
1761
0
{
1762
0
  uint8_t *origin;
1763
1764
0
  origin = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(uint8_t));
1765
1766
0
  if (strcmp(arg, "igp") == 0)
1767
0
    *origin = 0;
1768
0
  else if (strcmp(arg, "egp") == 0)
1769
0
    *origin = 1;
1770
0
  else
1771
0
    *origin = 2;
1772
1773
0
  return origin;
1774
0
}
1775
1776
/* Free route map's compiled `ip address' value. */
1777
static void route_match_origin_free(void *rule)
1778
0
{
1779
0
  XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
1780
0
}
1781
1782
/* Route map commands for origin matching. */
1783
static const struct route_map_rule_cmd route_match_origin_cmd = {
1784
  "origin",
1785
  route_match_origin,
1786
  route_match_origin_compile,
1787
  route_match_origin_free
1788
};
1789
1790
/* match probability  { */
1791
1792
static enum route_map_cmd_result_t
1793
route_match_probability(void *rule, const struct prefix *prefix, void *object)
1794
0
{
1795
0
  long r = frr_weak_random();
1796
1797
0
  switch (*(long *)rule) {
1798
0
  case 0:
1799
0
    break;
1800
0
  case RAND_MAX:
1801
0
    return RMAP_MATCH;
1802
0
  default:
1803
0
    if (r < *(long *)rule) {
1804
0
      return RMAP_MATCH;
1805
0
    }
1806
0
  }
1807
1808
0
  return RMAP_NOMATCH;
1809
0
}
1810
1811
static void *route_match_probability_compile(const char *arg)
1812
0
{
1813
0
  long *lobule;
1814
0
  unsigned perc;
1815
1816
0
  perc = atoi(arg);
1817
0
  lobule = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(long));
1818
1819
0
  switch (perc) {
1820
0
  case 0:
1821
0
    *lobule = 0;
1822
0
    break;
1823
0
  case 100:
1824
0
    *lobule = RAND_MAX;
1825
0
    break;
1826
0
  default:
1827
0
    *lobule = RAND_MAX / 100 * perc;
1828
0
  }
1829
1830
0
  return lobule;
1831
0
}
1832
1833
static void route_match_probability_free(void *rule)
1834
0
{
1835
0
  XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
1836
0
}
1837
1838
static const struct route_map_rule_cmd route_match_probability_cmd = {
1839
  "probability",
1840
  route_match_probability,
1841
  route_match_probability_compile,
1842
  route_match_probability_free
1843
};
1844
1845
/* `match interface IFNAME' */
1846
/* Match function should return 1 if match is success else return
1847
   zero. */
1848
static enum route_map_cmd_result_t
1849
route_match_interface(void *rule, const struct prefix *prefix, void *object)
1850
0
{
1851
0
  struct interface *ifp;
1852
0
  struct bgp_path_info *path;
1853
1854
0
  path = object;
1855
1856
0
  if (!path || !path->peer || !path->peer->bgp)
1857
0
    return RMAP_NOMATCH;
1858
1859
0
  ifp = if_lookup_by_name((char *)rule, path->peer->bgp->vrf_id);
1860
1861
0
  if (ifp == NULL || ifp->ifindex != path->attr->nh_ifindex)
1862
0
    return RMAP_NOMATCH;
1863
1864
0
  return RMAP_MATCH;
1865
0
}
1866
1867
/* Route map `interface' match statement.  `arg' should be
1868
   interface name. */
1869
static void *route_match_interface_compile(const char *arg)
1870
0
{
1871
0
  return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
1872
0
}
1873
1874
/* Free route map's compiled `interface' value. */
1875
static void route_match_interface_free(void *rule)
1876
0
{
1877
0
  XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
1878
0
}
1879
1880
/* Route map commands for ip address matching. */
1881
static const struct route_map_rule_cmd route_match_interface_cmd = {
1882
  "interface",
1883
  route_match_interface,
1884
  route_match_interface_compile,
1885
  route_match_interface_free
1886
};
1887
1888
/* } */
1889
1890
/* `set ip next-hop IP_ADDRESS' */
1891
1892
/* Match function return 1 if match is success else return zero. */
1893
static enum route_map_cmd_result_t
1894
route_match_tag(void *rule, const struct prefix *prefix, void *object)
1895
0
{
1896
0
  route_tag_t *tag;
1897
0
  struct bgp_path_info *path;
1898
1899
0
  tag = rule;
1900
0
  path = object;
1901
1902
0
  return ((path->attr->tag == *tag) ? RMAP_MATCH : RMAP_NOMATCH);
1903
0
}
1904
1905
1906
/* Route map commands for tag matching. */
1907
static const struct route_map_rule_cmd route_match_tag_cmd = {
1908
  "tag",
1909
  route_match_tag,
1910
  route_map_rule_tag_compile,
1911
  route_map_rule_tag_free,
1912
};
1913
1914
static enum route_map_cmd_result_t
1915
route_set_srte_color(void *rule, const struct prefix *prefix, void *object)
1916
0
{
1917
0
  uint32_t *srte_color = rule;
1918
0
  struct bgp_path_info *path;
1919
1920
0
  path = object;
1921
1922
0
  path->attr->srte_color = *srte_color;
1923
0
  path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_SRTE_COLOR);
1924
1925
0
  return RMAP_OKAY;
1926
0
}
1927
1928
/* Route map `sr-te color' compile function */
1929
static void *route_set_srte_color_compile(const char *arg)
1930
0
{
1931
0
  uint32_t *color;
1932
1933
0
  color = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(uint32_t));
1934
0
  *color = atoi(arg);
1935
1936
0
  return color;
1937
0
}
1938
1939
/* Free route map's compiled `sr-te color' value. */
1940
static void route_set_srte_color_free(void *rule)
1941
0
{
1942
0
  XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
1943
0
}
1944
1945
/* Route map commands for sr-te color set. */
1946
struct route_map_rule_cmd route_set_srte_color_cmd = {
1947
  "sr-te color", route_set_srte_color, route_set_srte_color_compile,
1948
  route_set_srte_color_free};
1949
1950
/* Set nexthop to object.  object must be pointer to struct attr. */
1951
struct rmap_ip_nexthop_set {
1952
  struct in_addr *address;
1953
  int peer_address;
1954
  int unchanged;
1955
};
1956
1957
static enum route_map_cmd_result_t
1958
route_set_ip_nexthop(void *rule, const struct prefix *prefix, void *object)
1959
0
{
1960
0
  struct rmap_ip_nexthop_set *rins = rule;
1961
0
  struct bgp_path_info *path;
1962
0
  struct peer *peer;
1963
1964
0
  if (prefix->family == AF_INET6)
1965
0
    return RMAP_OKAY;
1966
1967
0
  path = object;
1968
0
  peer = path->peer;
1969
1970
0
  if (rins->unchanged) {
1971
0
    SET_FLAG(path->attr->rmap_change_flags,
1972
0
       BATTR_RMAP_NEXTHOP_UNCHANGED);
1973
0
  } else if (rins->peer_address) {
1974
0
    if ((CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN)
1975
0
         || CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IMPORT))
1976
0
        && peer->su_remote
1977
0
        && sockunion_family(peer->su_remote) == AF_INET) {
1978
0
      path->attr->nexthop.s_addr =
1979
0
        sockunion2ip(peer->su_remote);
1980
0
      path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP);
1981
0
    } else if (CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT)) {
1982
      /* The next hop value will be set as part of
1983
       * packet rewrite.  Set the flags here to indicate
1984
       * that rewrite needs to be done.
1985
       * Also, clear the value.
1986
       */
1987
0
      SET_FLAG(path->attr->rmap_change_flags,
1988
0
         BATTR_RMAP_NEXTHOP_PEER_ADDRESS);
1989
0
      path->attr->nexthop.s_addr = INADDR_ANY;
1990
0
    }
1991
0
  } else {
1992
    /* Set next hop value. */
1993
0
    path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP);
1994
0
    path->attr->nexthop = *rins->address;
1995
0
    SET_FLAG(path->attr->rmap_change_flags,
1996
0
       BATTR_RMAP_IPV4_NHOP_CHANGED);
1997
    /* case for MP-BGP : MPLS VPN */
1998
0
    path->attr->mp_nexthop_global_in = *rins->address;
1999
0
    path->attr->mp_nexthop_len = sizeof(*rins->address);
2000
0
  }
2001
2002
0
  return RMAP_OKAY;
2003
0
}
2004
2005
/* Route map `ip nexthop' compile function.  Given string is converted
2006
   to struct in_addr structure. */
2007
static void *route_set_ip_nexthop_compile(const char *arg)
2008
0
{
2009
0
  struct rmap_ip_nexthop_set *rins;
2010
0
  struct in_addr *address = NULL;
2011
0
  int peer_address = 0;
2012
0
  int unchanged = 0;
2013
0
  int ret;
2014
2015
0
  if (strcmp(arg, "peer-address") == 0)
2016
0
    peer_address = 1;
2017
0
  else if (strcmp(arg, "unchanged") == 0)
2018
0
    unchanged = 1;
2019
0
  else {
2020
0
    address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED,
2021
0
          sizeof(struct in_addr));
2022
0
    ret = inet_aton(arg, address);
2023
2024
0
    if (ret == 0) {
2025
0
      XFREE(MTYPE_ROUTE_MAP_COMPILED, address);
2026
0
      return NULL;
2027
0
    }
2028
0
  }
2029
2030
0
  rins = XCALLOC(MTYPE_ROUTE_MAP_COMPILED,
2031
0
           sizeof(struct rmap_ip_nexthop_set));
2032
2033
0
  rins->address = address;
2034
0
  rins->peer_address = peer_address;
2035
0
  rins->unchanged = unchanged;
2036
2037
0
  return rins;
2038
0
}
2039
2040
/* Free route map's compiled `ip nexthop' value. */
2041
static void route_set_ip_nexthop_free(void *rule)
2042
0
{
2043
0
  struct rmap_ip_nexthop_set *rins = rule;
2044
2045
0
  XFREE(MTYPE_ROUTE_MAP_COMPILED, rins->address);
2046
2047
0
  XFREE(MTYPE_ROUTE_MAP_COMPILED, rins);
2048
0
}
2049
2050
/* Route map commands for ip nexthop set. */
2051
static const struct route_map_rule_cmd route_set_ip_nexthop_cmd = {
2052
  "ip next-hop",
2053
  route_set_ip_nexthop,
2054
  route_set_ip_nexthop_compile,
2055
  route_set_ip_nexthop_free
2056
};
2057
2058
/* `set l3vpn next-hop encapsulation l3vpn gre' */
2059
2060
/* Set nexthop to object */
2061
struct rmap_l3vpn_nexthop_encapsulation_set {
2062
  uint8_t protocol;
2063
};
2064
2065
static enum route_map_cmd_result_t
2066
route_set_l3vpn_nexthop_encapsulation(void *rule, const struct prefix *prefix,
2067
              void *object)
2068
0
{
2069
0
  struct rmap_l3vpn_nexthop_encapsulation_set *rins = rule;
2070
0
  struct bgp_path_info *path;
2071
2072
0
  path = object;
2073
2074
0
  if (rins->protocol != IPPROTO_GRE)
2075
0
    return RMAP_OKAY;
2076
2077
0
  SET_FLAG(path->attr->rmap_change_flags, BATTR_RMAP_L3VPN_ACCEPT_GRE);
2078
0
  return RMAP_OKAY;
2079
0
}
2080
2081
/* Route map `l3vpn nexthop encapsulation' compile function. */
2082
static void *route_set_l3vpn_nexthop_encapsulation_compile(const char *arg)
2083
0
{
2084
0
  struct rmap_l3vpn_nexthop_encapsulation_set *rins;
2085
2086
0
  rins = XCALLOC(MTYPE_ROUTE_MAP_COMPILED,
2087
0
           sizeof(struct rmap_l3vpn_nexthop_encapsulation_set));
2088
2089
  /* XXX ALL GRE modes are accepted for now: gre or ip6gre */
2090
0
  rins->protocol = IPPROTO_GRE;
2091
2092
0
  return rins;
2093
0
}
2094
2095
/* Free route map's compiled `ip nexthop' value. */
2096
static void route_set_l3vpn_nexthop_encapsulation_free(void *rule)
2097
0
{
2098
0
  XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
2099
0
}
2100
2101
/* Route map commands for l3vpn next-hop encapsulation set. */
2102
static const struct route_map_rule_cmd
2103
  route_set_l3vpn_nexthop_encapsulation_cmd = {
2104
    "l3vpn next-hop encapsulation",
2105
    route_set_l3vpn_nexthop_encapsulation,
2106
    route_set_l3vpn_nexthop_encapsulation_compile,
2107
    route_set_l3vpn_nexthop_encapsulation_free};
2108
2109
/* `set local-preference LOCAL_PREF' */
2110
2111
/* Set local preference. */
2112
static enum route_map_cmd_result_t
2113
route_set_local_pref(void *rule, const struct prefix *prefix, void *object)
2114
0
{
2115
0
  struct rmap_value *rv;
2116
0
  struct bgp_path_info *path;
2117
0
  uint32_t locpref = 0;
2118
2119
  /* Fetch routemap's rule information. */
2120
0
  rv = rule;
2121
0
  path = object;
2122
2123
  /* Set local preference value. */
2124
0
  if (path->attr->local_pref)
2125
0
    locpref = path->attr->local_pref;
2126
2127
0
  path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
2128
0
  path->attr->local_pref = route_value_adjust(rv, locpref, path->peer);
2129
2130
0
  return RMAP_OKAY;
2131
0
}
2132
2133
/* Set local preference rule structure. */
2134
static const struct route_map_rule_cmd route_set_local_pref_cmd = {
2135
  "local-preference",
2136
  route_set_local_pref,
2137
  route_value_compile,
2138
  route_value_free,
2139
};
2140
2141
/* `set weight WEIGHT' */
2142
2143
/* Set weight. */
2144
static enum route_map_cmd_result_t
2145
route_set_weight(void *rule, const struct prefix *prefix, void *object)
2146
0
{
2147
0
  struct rmap_value *rv;
2148
0
  struct bgp_path_info *path;
2149
2150
  /* Fetch routemap's rule information. */
2151
0
  rv = rule;
2152
0
  path = object;
2153
2154
  /* Set weight value. */
2155
0
  path->attr->weight = route_value_adjust(rv, 0, path->peer);
2156
2157
0
  return RMAP_OKAY;
2158
0
}
2159
2160
/* Set local preference rule structure. */
2161
static const struct route_map_rule_cmd route_set_weight_cmd = {
2162
  "weight",
2163
  route_set_weight,
2164
  route_value_compile,
2165
  route_value_free,
2166
};
2167
2168
/* `set distance DISTANCE */
2169
static enum route_map_cmd_result_t
2170
route_set_distance(void *rule, const struct prefix *prefix, void *object)
2171
0
{
2172
0
  struct bgp_path_info *path = object;
2173
0
  struct rmap_value *rv = rule;
2174
2175
0
  path->attr->distance = rv->value;
2176
2177
0
  return RMAP_OKAY;
2178
0
}
2179
2180
/* set distance rule structure */
2181
static const struct route_map_rule_cmd route_set_distance_cmd = {
2182
  "distance",
2183
  route_set_distance,
2184
  route_value_compile,
2185
  route_value_free,
2186
};
2187
2188
/* `set metric METRIC' */
2189
2190
/* Set metric to attribute. */
2191
static enum route_map_cmd_result_t
2192
route_set_metric(void *rule, const struct prefix *prefix, void *object)
2193
0
{
2194
0
  struct rmap_value *rv;
2195
0
  struct bgp_path_info *path;
2196
0
  uint32_t med = 0;
2197
2198
  /* Fetch routemap's rule information. */
2199
0
  rv = rule;
2200
0
  path = object;
2201
2202
0
  if (path->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
2203
0
    med = path->attr->med;
2204
2205
0
  path->attr->med = route_value_adjust(rv, med, path->peer);
2206
0
  path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
2207
2208
0
  return RMAP_OKAY;
2209
0
}
2210
2211
/* Set metric rule structure. */
2212
static const struct route_map_rule_cmd route_set_metric_cmd = {
2213
  "metric",
2214
  route_set_metric,
2215
  route_value_compile,
2216
  route_value_free,
2217
};
2218
2219
/* `set table (1-4294967295)' */
2220
2221
static enum route_map_cmd_result_t
2222
route_set_table_id(void *rule, const struct prefix *prefix,
2223
2224
       void *object)
2225
0
{
2226
0
  struct rmap_value *rv;
2227
0
  struct bgp_path_info *path;
2228
2229
  /* Fetch routemap's rule information. */
2230
0
  rv = rule;
2231
0
  path = object;
2232
2233
0
  path->attr->rmap_table_id = rv->value;
2234
2235
0
  return RMAP_OKAY;
2236
0
}
2237
2238
/* Set table_id rule structure. */
2239
static const struct route_map_rule_cmd route_set_table_id_cmd = {
2240
  "table",
2241
  route_set_table_id,
2242
  route_value_compile,
2243
  route_value_free
2244
};
2245
2246
/* `set as-path prepend ASPATH' */
2247
2248
/* For AS path prepend mechanism. */
2249
static enum route_map_cmd_result_t
2250
route_set_aspath_prepend(void *rule, const struct prefix *prefix, void *object)
2251
0
{
2252
0
  struct aspath *aspath;
2253
0
  struct aspath *new;
2254
0
  struct bgp_path_info *path;
2255
2256
0
  path = object;
2257
2258
0
  if (path->attr->aspath->refcnt)
2259
0
    new = aspath_dup(path->attr->aspath);
2260
0
  else
2261
0
    new = path->attr->aspath;
2262
2263
0
  if ((uintptr_t)rule > 10) {
2264
0
    aspath = rule;
2265
0
    aspath_prepend(aspath, new);
2266
0
  } else {
2267
0
    as_t as = aspath_leftmost(new);
2268
0
    if (as)
2269
0
      new = aspath_add_seq_n(new, as, (uintptr_t)rule);
2270
0
  }
2271
2272
0
  path->attr->aspath = new;
2273
2274
0
  return RMAP_OKAY;
2275
0
}
2276
2277
static void *route_set_aspath_prepend_compile(const char *arg)
2278
0
{
2279
0
  unsigned int num;
2280
2281
0
  if (sscanf(arg, "last-as %u", &num) == 1 && num > 0 && num <= 10)
2282
0
    return (void *)(uintptr_t)num;
2283
2284
0
  return route_aspath_compile(arg);
2285
0
}
2286
2287
static void route_set_aspath_prepend_free(void *rule)
2288
0
{
2289
0
  if ((uintptr_t)rule > 10)
2290
0
    route_aspath_free(rule);
2291
0
}
2292
2293
2294
/* Set as-path prepend rule structure. */
2295
static const struct route_map_rule_cmd route_set_aspath_prepend_cmd = {
2296
  "as-path prepend",
2297
  route_set_aspath_prepend,
2298
  route_set_aspath_prepend_compile,
2299
  route_set_aspath_prepend_free,
2300
};
2301
2302
/* `set as-path exclude ASn' */
2303
2304
/* For ASN exclude mechanism.
2305
 * Iterate over ASns requested and filter them from the given AS_PATH one by
2306
 * one.
2307
 * Make a deep copy of existing AS_PATH, but for the first ASn only.
2308
 */
2309
static enum route_map_cmd_result_t
2310
route_set_aspath_exclude(void *rule, const struct prefix *dummy, void *object)
2311
0
{
2312
0
  struct aspath *new_path, *exclude_path;
2313
0
  struct bgp_path_info *path;
2314
2315
0
  exclude_path = rule;
2316
0
  path = object;
2317
0
  if (path->attr->aspath->refcnt)
2318
0
    new_path = aspath_dup(path->attr->aspath);
2319
0
  else
2320
0
    new_path = path->attr->aspath;
2321
0
  path->attr->aspath = aspath_filter_exclude(new_path, exclude_path);
2322
2323
0
  return RMAP_OKAY;
2324
0
}
2325
2326
/* Set ASn exlude rule structure. */
2327
static const struct route_map_rule_cmd route_set_aspath_exclude_cmd = {
2328
  "as-path exclude",
2329
  route_set_aspath_exclude,
2330
  route_aspath_compile,
2331
  route_aspath_free,
2332
};
2333
2334
/* `set as-path replace AS-PATH` */
2335
static void *route_aspath_replace_compile(const char *arg)
2336
0
{
2337
0
  return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
2338
0
}
2339
2340
static void route_aspath_replace_free(void *rule)
2341
0
{
2342
0
  XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
2343
0
}
2344
2345
static enum route_map_cmd_result_t
2346
route_set_aspath_replace(void *rule, const struct prefix *dummy, void *object)
2347
0
{
2348
0
  struct aspath *aspath_new;
2349
0
  const char *replace = rule;
2350
0
  struct bgp_path_info *path = object;
2351
0
  as_t own_asn = path->peer->change_local_as ? path->peer->change_local_as
2352
0
               : path->peer->local_as;
2353
2354
0
  if (path->peer->sort != BGP_PEER_EBGP) {
2355
0
    zlog_warn(
2356
0
      "`set as-path replace` is supported only for EBGP peers");
2357
0
    return RMAP_NOOP;
2358
0
  }
2359
2360
0
  if (path->attr->aspath->refcnt)
2361
0
    aspath_new = aspath_dup(path->attr->aspath);
2362
0
  else
2363
0
    aspath_new = path->attr->aspath;
2364
2365
0
  if (strmatch(replace, "any")) {
2366
0
    path->attr->aspath =
2367
0
      aspath_replace_all_asn(aspath_new, own_asn);
2368
0
  } else {
2369
0
    as_t replace_asn = strtoul(replace, NULL, 10);
2370
2371
0
    path->attr->aspath = aspath_replace_specific_asn(
2372
0
      aspath_new, replace_asn, own_asn);
2373
0
  }
2374
2375
0
  aspath_free(aspath_new);
2376
2377
0
  return RMAP_OKAY;
2378
0
}
2379
2380
static const struct route_map_rule_cmd route_set_aspath_replace_cmd = {
2381
  "as-path replace",
2382
  route_set_aspath_replace,
2383
  route_aspath_replace_compile,
2384
  route_aspath_replace_free,
2385
};
2386
2387
/* `set community COMMUNITY' */
2388
struct rmap_com_set {
2389
  struct community *com;
2390
  int additive;
2391
  int none;
2392
};
2393
2394
/* For community set mechanism. */
2395
static enum route_map_cmd_result_t
2396
route_set_community(void *rule, const struct prefix *prefix, void *object)
2397
0
{
2398
0
  struct rmap_com_set *rcs;
2399
0
  struct bgp_path_info *path;
2400
0
  struct attr *attr;
2401
0
  struct community *new = NULL;
2402
0
  struct community *old;
2403
0
  struct community *merge;
2404
2405
0
  rcs = rule;
2406
0
  path = object;
2407
0
  attr = path->attr;
2408
0
  old = bgp_attr_get_community(attr);
2409
2410
  /* "none" case.  */
2411
0
  if (rcs->none) {
2412
0
    bgp_attr_set_community(attr, NULL);
2413
    /* See the longer comment down below. */
2414
0
    if (old && old->refcnt == 0)
2415
0
      community_free(&old);
2416
0
    return RMAP_OKAY;
2417
0
  }
2418
2419
  /* "additive" case.  */
2420
0
  if (rcs->additive && old) {
2421
0
    merge = community_merge(community_dup(old), rcs->com);
2422
2423
0
    new = community_uniq_sort(merge);
2424
0
    community_free(&merge);
2425
0
  } else
2426
0
    new = community_dup(rcs->com);
2427
2428
  /* HACK: if the old community is not intern'd,
2429
   * we should free it here, or all reference to it may be
2430
   * lost.
2431
   * Really need to cleanup attribute caching sometime.
2432
   */
2433
0
  if (old && old->refcnt == 0)
2434
0
    community_free(&old);
2435
2436
  /* will be interned by caller if required */
2437
0
  bgp_attr_set_community(attr, new);
2438
2439
0
  return RMAP_OKAY;
2440
0
}
2441
2442
/* Compile function for set community. */
2443
static void *route_set_community_compile(const char *arg)
2444
0
{
2445
0
  struct rmap_com_set *rcs;
2446
0
  struct community *com = NULL;
2447
0
  char *sp;
2448
0
  int additive = 0;
2449
0
  int none = 0;
2450
2451
0
  if (strcmp(arg, "none") == 0)
2452
0
    none = 1;
2453
0
  else {
2454
0
    sp = strstr(arg, "additive");
2455
2456
0
    if (sp && sp > arg) {
2457
      /* "additive" keyword is included.  */
2458
0
      additive = 1;
2459
0
      *(sp - 1) = '\0';
2460
0
    }
2461
2462
0
    com = community_str2com(arg);
2463
2464
0
    if (additive)
2465
0
      *(sp - 1) = ' ';
2466
2467
0
    if (!com)
2468
0
      return NULL;
2469
0
  }
2470
2471
0
  rcs = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_com_set));
2472
0
  rcs->com = com;
2473
0
  rcs->additive = additive;
2474
0
  rcs->none = none;
2475
2476
0
  return rcs;
2477
0
}
2478
2479
/* Free function for set community. */
2480
static void route_set_community_free(void *rule)
2481
0
{
2482
0
  struct rmap_com_set *rcs = rule;
2483
2484
0
  if (rcs->com)
2485
0
    community_free(&rcs->com);
2486
0
  XFREE(MTYPE_ROUTE_MAP_COMPILED, rcs);
2487
0
}
2488
2489
/* Set community rule structure. */
2490
static const struct route_map_rule_cmd route_set_community_cmd = {
2491
  "community",
2492
  route_set_community,
2493
  route_set_community_compile,
2494
  route_set_community_free,
2495
};
2496
2497
/* `set community COMMUNITY' */
2498
struct rmap_lcom_set {
2499
  struct lcommunity *lcom;
2500
  int additive;
2501
  int none;
2502
};
2503
2504
2505
/* For lcommunity set mechanism. */
2506
static enum route_map_cmd_result_t
2507
route_set_lcommunity(void *rule, const struct prefix *prefix, void *object)
2508
0
{
2509
0
  struct rmap_lcom_set *rcs;
2510
0
  struct bgp_path_info *path;
2511
0
  struct attr *attr;
2512
0
  struct lcommunity *new = NULL;
2513
0
  struct lcommunity *old;
2514
0
  struct lcommunity *merge;
2515
2516
0
  rcs = rule;
2517
0
  path = object;
2518
0
  attr = path->attr;
2519
0
  old = bgp_attr_get_lcommunity(attr);
2520
2521
  /* "none" case.  */
2522
0
  if (rcs->none) {
2523
0
    bgp_attr_set_lcommunity(attr, NULL);
2524
2525
    /* See the longer comment down below. */
2526
0
    if (old && old->refcnt == 0)
2527
0
      lcommunity_free(&old);
2528
0
    return RMAP_OKAY;
2529
0
  }
2530
2531
0
  if (rcs->additive && old) {
2532
0
    merge = lcommunity_merge(lcommunity_dup(old), rcs->lcom);
2533
2534
0
    new = lcommunity_uniq_sort(merge);
2535
0
    lcommunity_free(&merge);
2536
0
  } else
2537
0
    new = lcommunity_dup(rcs->lcom);
2538
2539
  /* HACK: if the old large-community is not intern'd,
2540
   * we should free it here, or all reference to it may be
2541
   * lost.
2542
   * Really need to cleanup attribute caching sometime.
2543
   */
2544
0
  if (old && old->refcnt == 0)
2545
0
    lcommunity_free(&old);
2546
2547
  /* will be intern()'d or attr_flush()'d by bgp_update_main() */
2548
0
  bgp_attr_set_lcommunity(attr, new);
2549
2550
0
  return RMAP_OKAY;
2551
0
}
2552
2553
/* Compile function for set community. */
2554
static void *route_set_lcommunity_compile(const char *arg)
2555
0
{
2556
0
  struct rmap_lcom_set *rcs;
2557
0
  struct lcommunity *lcom = NULL;
2558
0
  char *sp;
2559
0
  int additive = 0;
2560
0
  int none = 0;
2561
2562
0
  if (strcmp(arg, "none") == 0)
2563
0
    none = 1;
2564
0
  else {
2565
0
    sp = strstr(arg, "additive");
2566
2567
0
    if (sp && sp > arg) {
2568
      /* "additive" keyworkd is included.  */
2569
0
      additive = 1;
2570
0
      *(sp - 1) = '\0';
2571
0
    }
2572
2573
0
    lcom = lcommunity_str2com(arg);
2574
2575
0
    if (additive)
2576
0
      *(sp - 1) = ' ';
2577
2578
0
    if (!lcom)
2579
0
      return NULL;
2580
0
  }
2581
2582
0
  rcs = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_com_set));
2583
0
  rcs->lcom = lcom;
2584
0
  rcs->additive = additive;
2585
0
  rcs->none = none;
2586
2587
0
  return rcs;
2588
0
}
2589
2590
/* Free function for set lcommunity. */
2591
static void route_set_lcommunity_free(void *rule)
2592
0
{
2593
0
  struct rmap_lcom_set *rcs = rule;
2594
2595
0
  if (rcs->lcom) {
2596
0
    lcommunity_free(&rcs->lcom);
2597
0
  }
2598
0
  XFREE(MTYPE_ROUTE_MAP_COMPILED, rcs);
2599
0
}
2600
2601
/* Set community rule structure. */
2602
static const struct route_map_rule_cmd route_set_lcommunity_cmd = {
2603
  "large-community",
2604
  route_set_lcommunity,
2605
  route_set_lcommunity_compile,
2606
  route_set_lcommunity_free,
2607
};
2608
2609
/* `set large-comm-list (<1-99>|<100-500>|WORD) delete' */
2610
2611
/* For large community set mechanism. */
2612
static enum route_map_cmd_result_t
2613
route_set_lcommunity_delete(void *rule, const struct prefix *pfx, void *object)
2614
0
{
2615
0
  struct community_list *list;
2616
0
  struct lcommunity *merge;
2617
0
  struct lcommunity *new;
2618
0
  struct lcommunity *old;
2619
0
  struct bgp_path_info *path;
2620
0
  struct rmap_community *rcom = rule;
2621
2622
0
  if (!rcom)
2623
0
    return RMAP_OKAY;
2624
2625
0
  path = object;
2626
0
  list = community_list_lookup(bgp_clist, rcom->name, rcom->name_hash,
2627
0
             LARGE_COMMUNITY_LIST_MASTER);
2628
0
  old = bgp_attr_get_lcommunity(path->attr);
2629
2630
0
  if (list && old) {
2631
0
    merge = lcommunity_list_match_delete(lcommunity_dup(old), list);
2632
0
    new = lcommunity_uniq_sort(merge);
2633
0
    lcommunity_free(&merge);
2634
2635
    /* HACK: if the old community is not intern'd,
2636
     * we should free it here, or all reference to it may be
2637
     * lost.
2638
     * Really need to cleanup attribute caching sometime.
2639
     */
2640
0
    if (old->refcnt == 0)
2641
0
      lcommunity_free(&old);
2642
2643
0
    if (new->size == 0) {
2644
0
      bgp_attr_set_lcommunity(path->attr, NULL);
2645
0
      lcommunity_free(&new);
2646
0
    } else {
2647
0
      bgp_attr_set_lcommunity(path->attr, new);
2648
0
    }
2649
0
  }
2650
2651
0
  return RMAP_OKAY;
2652
0
}
2653
2654
/* Compile function for set lcommunity. */
2655
static void *route_set_lcommunity_delete_compile(const char *arg)
2656
0
{
2657
0
  struct rmap_community *rcom;
2658
0
  char **splits;
2659
0
  int num;
2660
2661
0
  frrstr_split(arg, " ", &splits, &num);
2662
2663
0
  rcom = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_community));
2664
0
  rcom->name = XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, splits[0]);
2665
0
  rcom->name_hash = bgp_clist_hash_key(rcom->name);
2666
2667
0
  for (int i = 0; i < num; i++)
2668
0
    XFREE(MTYPE_TMP, splits[i]);
2669
0
  XFREE(MTYPE_TMP, splits);
2670
2671
0
  return rcom;
2672
0
}
2673
2674
/* Free function for set lcommunity. */
2675
static void route_set_lcommunity_delete_free(void *rule)
2676
0
{
2677
0
  struct rmap_community *rcom = rule;
2678
2679
0
  XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom->name);
2680
0
  XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom);
2681
0
}
2682
2683
/* Set lcommunity rule structure. */
2684
static const struct route_map_rule_cmd route_set_lcommunity_delete_cmd = {
2685
  "large-comm-list",
2686
  route_set_lcommunity_delete,
2687
  route_set_lcommunity_delete_compile,
2688
  route_set_lcommunity_delete_free,
2689
};
2690
2691
2692
/* `set comm-list (<1-99>|<100-500>|WORD) delete' */
2693
2694
/* For community set mechanism. */
2695
static enum route_map_cmd_result_t
2696
route_set_community_delete(void *rule, const struct prefix *prefix,
2697
         void *object)
2698
0
{
2699
0
  struct community_list *list;
2700
0
  struct community *merge;
2701
0
  struct community *new;
2702
0
  struct community *old;
2703
0
  struct bgp_path_info *path;
2704
0
  struct rmap_community *rcom = rule;
2705
2706
0
  if (!rcom)
2707
0
    return RMAP_OKAY;
2708
2709
0
  path = object;
2710
0
  list = community_list_lookup(bgp_clist, rcom->name, rcom->name_hash,
2711
0
             COMMUNITY_LIST_MASTER);
2712
0
  old = bgp_attr_get_community(path->attr);
2713
2714
0
  if (list && old) {
2715
0
    merge = community_list_match_delete(community_dup(old), list);
2716
0
    new = community_uniq_sort(merge);
2717
0
    community_free(&merge);
2718
2719
    /* HACK: if the old community is not intern'd,
2720
     * we should free it here, or all reference to it may be
2721
     * lost.
2722
     * Really need to cleanup attribute caching sometime.
2723
     */
2724
0
    if (old->refcnt == 0)
2725
0
      community_free(&old);
2726
2727
0
    if (new->size == 0) {
2728
0
      bgp_attr_set_community(path->attr, NULL);
2729
0
      community_free(&new);
2730
0
    } else {
2731
0
      bgp_attr_set_community(path->attr, new);
2732
0
    }
2733
0
  }
2734
2735
0
  return RMAP_OKAY;
2736
0
}
2737
2738
/* Compile function for set community. */
2739
static void *route_set_community_delete_compile(const char *arg)
2740
0
{
2741
0
  struct rmap_community *rcom;
2742
0
  char **splits;
2743
0
  int num;
2744
2745
0
  frrstr_split(arg, " ", &splits, &num);
2746
2747
0
  rcom = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_community));
2748
0
  rcom->name = XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, splits[0]);
2749
0
  rcom->name_hash = bgp_clist_hash_key(rcom->name);
2750
2751
0
  for (int i = 0; i < num; i++)
2752
0
    XFREE(MTYPE_TMP, splits[i]);
2753
0
  XFREE(MTYPE_TMP, splits);
2754
2755
0
  return rcom;
2756
0
}
2757
2758
/* Free function for set community. */
2759
static void route_set_community_delete_free(void *rule)
2760
0
{
2761
0
  struct rmap_community *rcom = rule;
2762
2763
0
  XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom->name);
2764
0
  XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom);
2765
0
}
2766
2767
/* Set community rule structure. */
2768
static const struct route_map_rule_cmd route_set_community_delete_cmd = {
2769
  "comm-list",
2770
  route_set_community_delete,
2771
  route_set_community_delete_compile,
2772
  route_set_community_delete_free,
2773
};
2774
2775
/* `set extcommunity rt COMMUNITY' */
2776
2777
struct rmap_ecom_set {
2778
  struct ecommunity *ecom;
2779
  bool none;
2780
};
2781
2782
/* For community set mechanism.  Used by _rt and _soo. */
2783
static enum route_map_cmd_result_t
2784
route_set_ecommunity(void *rule, const struct prefix *prefix, void *object)
2785
0
{
2786
0
  struct rmap_ecom_set *rcs;
2787
0
  struct ecommunity *new_ecom;
2788
0
  struct ecommunity *old_ecom;
2789
0
  struct bgp_path_info *path;
2790
0
  struct attr *attr;
2791
2792
0
  rcs = rule;
2793
0
  path = object;
2794
0
  attr = path->attr;
2795
2796
0
  if (rcs->none) {
2797
0
    bgp_attr_set_ecommunity(attr, NULL);
2798
0
    return RMAP_OKAY;
2799
0
  }
2800
2801
0
  if (!rcs->ecom)
2802
0
    return RMAP_OKAY;
2803
2804
  /* We assume additive for Extended Community. */
2805
0
  old_ecom = bgp_attr_get_ecommunity(path->attr);
2806
2807
0
  if (old_ecom) {
2808
0
    new_ecom =
2809
0
      ecommunity_merge(ecommunity_dup(old_ecom), rcs->ecom);
2810
2811
    /* old_ecom->refcnt = 1 => owned elsewhere, e.g.
2812
     * bgp_update_receive()
2813
     *         ->refcnt = 0 => set by a previous route-map
2814
     * statement */
2815
0
    if (!old_ecom->refcnt)
2816
0
      ecommunity_free(&old_ecom);
2817
0
  } else
2818
0
    new_ecom = ecommunity_dup(rcs->ecom);
2819
2820
  /* will be intern()'d or attr_flush()'d by bgp_update_main() */
2821
0
  bgp_attr_set_ecommunity(path->attr, new_ecom);
2822
2823
0
  return RMAP_OKAY;
2824
0
}
2825
2826
static void *route_set_ecommunity_none_compile(const char *arg)
2827
0
{
2828
0
  struct rmap_ecom_set *rcs;
2829
0
  bool none = false;
2830
2831
0
  if (strncmp(arg, "none", 4) == 0)
2832
0
    none = true;
2833
2834
0
  rcs = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_ecom_set));
2835
0
  rcs->ecom = NULL;
2836
0
  rcs->none = none;
2837
2838
0
  return rcs;
2839
0
}
2840
2841
static void *route_set_ecommunity_rt_compile(const char *arg)
2842
0
{
2843
0
  struct rmap_ecom_set *rcs;
2844
0
  struct ecommunity *ecom;
2845
2846
0
  ecom = ecommunity_str2com(arg, ECOMMUNITY_ROUTE_TARGET, 0);
2847
0
  if (!ecom)
2848
0
    return NULL;
2849
2850
0
  rcs = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_ecom_set));
2851
0
  rcs->ecom = ecommunity_intern(ecom);
2852
0
  rcs->none = false;
2853
2854
0
  return rcs;
2855
0
}
2856
2857
/* Free function for set community.  Used by _rt and _soo */
2858
static void route_set_ecommunity_free(void *rule)
2859
0
{
2860
0
  struct rmap_ecom_set *rcs = rule;
2861
2862
0
  if (rcs->ecom)
2863
0
    ecommunity_unintern(&rcs->ecom);
2864
2865
0
  XFREE(MTYPE_ROUTE_MAP_COMPILED, rcs);
2866
0
}
2867
2868
static const struct route_map_rule_cmd route_set_ecommunity_none_cmd = {
2869
  "extcommunity",
2870
  route_set_ecommunity,
2871
  route_set_ecommunity_none_compile,
2872
  route_set_ecommunity_free,
2873
};
2874
2875
/* Set community rule structure. */
2876
static const struct route_map_rule_cmd route_set_ecommunity_rt_cmd = {
2877
  "extcommunity rt",
2878
  route_set_ecommunity,
2879
  route_set_ecommunity_rt_compile,
2880
  route_set_ecommunity_free,
2881
};
2882
2883
/* `set extcommunity soo COMMUNITY' */
2884
2885
/* Compile function for set community. */
2886
static void *route_set_ecommunity_soo_compile(const char *arg)
2887
0
{
2888
0
  struct rmap_ecom_set *rcs;
2889
0
  struct ecommunity *ecom;
2890
2891
0
  ecom = ecommunity_str2com(arg, ECOMMUNITY_SITE_ORIGIN, 0);
2892
0
  if (!ecom)
2893
0
    return NULL;
2894
2895
0
  rcs = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_ecom_set));
2896
0
  rcs->ecom = ecommunity_intern(ecom);
2897
0
  rcs->none = false;
2898
2899
0
  return rcs;
2900
0
}
2901
2902
/* Set community rule structure. */
2903
static const struct route_map_rule_cmd route_set_ecommunity_soo_cmd = {
2904
  "extcommunity soo",
2905
  route_set_ecommunity,
2906
  route_set_ecommunity_soo_compile,
2907
  route_set_ecommunity_free,
2908
};
2909
2910
static void *route_set_ecommunity_nt_compile(const char *arg)
2911
0
{
2912
0
  struct rmap_ecom_set *rcs;
2913
0
  struct ecommunity *ecom;
2914
2915
0
  ecom = ecommunity_str2com(arg, ECOMMUNITY_NODE_TARGET, 0);
2916
0
  if (!ecom)
2917
0
    return NULL;
2918
2919
0
  rcs = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_ecom_set));
2920
0
  rcs->ecom = ecommunity_intern(ecom);
2921
0
  rcs->none = false;
2922
2923
0
  return rcs;
2924
0
}
2925
2926
static const struct route_map_rule_cmd route_set_ecommunity_nt_cmd = {
2927
  "extcommunity nt",
2928
  route_set_ecommunity,
2929
  route_set_ecommunity_nt_compile,
2930
  route_set_ecommunity_free,
2931
};
2932
2933
/* `set extcommunity bandwidth' */
2934
2935
struct rmap_ecomm_lb_set {
2936
  uint8_t lb_type;
2937
0
#define RMAP_ECOMM_LB_SET_VALUE 1
2938
0
#define RMAP_ECOMM_LB_SET_CUMUL 2
2939
0
#define RMAP_ECOMM_LB_SET_NUM_MPATH 3
2940
  bool non_trans;
2941
  uint32_t bw;
2942
};
2943
2944
static enum route_map_cmd_result_t
2945
route_set_ecommunity_lb(void *rule, const struct prefix *prefix, void *object)
2946
0
{
2947
0
  struct rmap_ecomm_lb_set *rels = rule;
2948
0
  struct bgp_path_info *path;
2949
0
  struct peer *peer;
2950
0
  struct ecommunity ecom_lb = {0};
2951
0
  struct ecommunity_val lb_eval;
2952
0
  uint32_t bw_bytes = 0;
2953
0
  uint16_t mpath_count = 0;
2954
0
  struct ecommunity *new_ecom;
2955
0
  struct ecommunity *old_ecom;
2956
0
  as_t as;
2957
2958
0
  path = object;
2959
0
  peer = path->peer;
2960
0
  if (!peer || !peer->bgp)
2961
0
    return RMAP_ERROR;
2962
2963
  /* Build link bandwidth extended community */
2964
0
  as = (peer->bgp->as > BGP_AS_MAX) ? BGP_AS_TRANS : peer->bgp->as;
2965
0
  if (rels->lb_type == RMAP_ECOMM_LB_SET_VALUE) {
2966
0
    bw_bytes = ((uint64_t)rels->bw * 1000 * 1000) / 8;
2967
0
  } else if (rels->lb_type == RMAP_ECOMM_LB_SET_CUMUL) {
2968
    /* process this only for the best path. */
2969
0
    if (!CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
2970
0
      return RMAP_OKAY;
2971
2972
0
    bw_bytes = (uint32_t)bgp_path_info_mpath_cumbw(path);
2973
0
    if (!bw_bytes)
2974
0
      return RMAP_OKAY;
2975
2976
0
  } else if (rels->lb_type == RMAP_ECOMM_LB_SET_NUM_MPATH) {
2977
2978
    /* process this only for the best path. */
2979
0
    if (!CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
2980
0
      return RMAP_OKAY;
2981
2982
0
    bw_bytes = ((uint64_t)peer->bgp->lb_ref_bw * 1000 * 1000) / 8;
2983
0
    mpath_count = bgp_path_info_mpath_count(path) + 1;
2984
0
    bw_bytes *= mpath_count;
2985
0
  }
2986
2987
0
  encode_lb_extcomm(as, bw_bytes, rels->non_trans, &lb_eval,
2988
0
        CHECK_FLAG(peer->flags,
2989
0
             PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE));
2990
2991
  /* add to route or merge with existing */
2992
0
  old_ecom = bgp_attr_get_ecommunity(path->attr);
2993
0
  if (old_ecom) {
2994
0
    new_ecom = ecommunity_dup(old_ecom);
2995
0
    ecommunity_add_val(new_ecom, &lb_eval, true, true);
2996
0
    if (!old_ecom->refcnt)
2997
0
      ecommunity_free(&old_ecom);
2998
0
  } else {
2999
0
    ecom_lb.size = 1;
3000
0
    ecom_lb.unit_size = ECOMMUNITY_SIZE;
3001
0
    ecom_lb.val = (uint8_t *)lb_eval.val;
3002
0
    new_ecom = ecommunity_dup(&ecom_lb);
3003
0
  }
3004
3005
  /* new_ecom will be intern()'d or attr_flush()'d in call stack */
3006
0
  bgp_attr_set_ecommunity(path->attr, new_ecom);
3007
3008
  /* Mark that route-map has set link bandwidth; used in attribute
3009
   * setting decisions.
3010
   */
3011
0
  SET_FLAG(path->attr->rmap_change_flags, BATTR_RMAP_LINK_BW_SET);
3012
3013
0
  return RMAP_OKAY;
3014
0
}
3015
3016
static void *route_set_ecommunity_lb_compile(const char *arg)
3017
0
{
3018
0
  struct rmap_ecomm_lb_set *rels;
3019
0
  uint8_t lb_type;
3020
0
  uint32_t bw = 0;
3021
0
  char bw_str[40] = {0};
3022
0
  char *p, *str;
3023
0
  bool non_trans = false;
3024
3025
0
  str = (char *)arg;
3026
0
  p = strchr(arg, ' ');
3027
0
  if (p) {
3028
0
    int len;
3029
3030
0
    len = p - arg;
3031
0
    memcpy(bw_str, arg, len);
3032
0
    non_trans = true;
3033
0
    str = bw_str;
3034
0
  }
3035
3036
0
  if (strcmp(str, "cumulative") == 0)
3037
0
    lb_type = RMAP_ECOMM_LB_SET_CUMUL;
3038
0
  else if (strcmp(str, "num-multipaths") == 0)
3039
0
    lb_type = RMAP_ECOMM_LB_SET_NUM_MPATH;
3040
0
  else {
3041
0
    char *end = NULL;
3042
3043
0
    bw = strtoul(str, &end, 10);
3044
0
    if (*end != '\0')
3045
0
      return NULL;
3046
0
    lb_type = RMAP_ECOMM_LB_SET_VALUE;
3047
0
  }
3048
3049
0
  rels = XCALLOC(MTYPE_ROUTE_MAP_COMPILED,
3050
0
           sizeof(struct rmap_ecomm_lb_set));
3051
0
  rels->lb_type = lb_type;
3052
0
  rels->bw = bw;
3053
0
  rels->non_trans = non_trans;
3054
3055
0
  return rels;
3056
0
}
3057
3058
static void route_set_ecommunity_lb_free(void *rule)
3059
0
{
3060
0
  XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
3061
0
}
3062
3063
/* Set community rule structure. */
3064
struct route_map_rule_cmd route_set_ecommunity_lb_cmd = {
3065
  "extcommunity bandwidth",
3066
  route_set_ecommunity_lb,
3067
  route_set_ecommunity_lb_compile,
3068
  route_set_ecommunity_lb_free,
3069
};
3070
3071
/* `set origin ORIGIN' */
3072
3073
/* For origin set. */
3074
static enum route_map_cmd_result_t
3075
route_set_origin(void *rule, const struct prefix *prefix, void *object)
3076
0
{
3077
0
  uint8_t *origin;
3078
0
  struct bgp_path_info *path;
3079
3080
0
  origin = rule;
3081
0
  path = object;
3082
3083
0
  path->attr->origin = *origin;
3084
3085
0
  return RMAP_OKAY;
3086
0
}
3087
3088
/* Compile function for origin set. */
3089
static void *route_set_origin_compile(const char *arg)
3090
0
{
3091
0
  uint8_t *origin;
3092
3093
0
  origin = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(uint8_t));
3094
3095
0
  if (strcmp(arg, "igp") == 0)
3096
0
    *origin = BGP_ORIGIN_IGP;
3097
0
  else if (strcmp(arg, "egp") == 0)
3098
0
    *origin = BGP_ORIGIN_EGP;
3099
0
  else
3100
0
    *origin = BGP_ORIGIN_INCOMPLETE;
3101
3102
0
  return origin;
3103
0
}
3104
3105
/* Compile function for origin set. */
3106
static void route_set_origin_free(void *rule)
3107
0
{
3108
0
  XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
3109
0
}
3110
3111
/* Set origin rule structure. */
3112
static const struct route_map_rule_cmd route_set_origin_cmd = {
3113
  "origin",
3114
  route_set_origin,
3115
  route_set_origin_compile,
3116
  route_set_origin_free,
3117
};
3118
3119
/* `set atomic-aggregate' */
3120
3121
/* For atomic aggregate set. */
3122
static enum route_map_cmd_result_t
3123
route_set_atomic_aggregate(void *rule, const struct prefix *pfx, void *object)
3124
0
{
3125
0
  struct bgp_path_info *path;
3126
3127
0
  path = object;
3128
0
  path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE);
3129
3130
0
  return RMAP_OKAY;
3131
0
}
3132
3133
/* Compile function for atomic aggregate. */
3134
static void *route_set_atomic_aggregate_compile(const char *arg)
3135
0
{
3136
0
  return (void *)1;
3137
0
}
3138
3139
/* Compile function for atomic aggregate. */
3140
static void route_set_atomic_aggregate_free(void *rule)
3141
0
{
3142
0
  return;
3143
0
}
3144
3145
/* Set atomic aggregate rule structure. */
3146
static const struct route_map_rule_cmd route_set_atomic_aggregate_cmd = {
3147
  "atomic-aggregate",
3148
  route_set_atomic_aggregate,
3149
  route_set_atomic_aggregate_compile,
3150
  route_set_atomic_aggregate_free,
3151
};
3152
3153
/* AIGP TLV Metric */
3154
static enum route_map_cmd_result_t
3155
route_set_aigp_metric(void *rule, const struct prefix *pfx, void *object)
3156
0
{
3157
0
  const char *aigp_metric = rule;
3158
0
  struct bgp_path_info *path = object;
3159
0
  uint32_t aigp = 0;
3160
3161
0
  if (strmatch(aigp_metric, "igp-metric")) {
3162
0
    if (!path->nexthop)
3163
0
      return RMAP_NOMATCH;
3164
3165
0
    bgp_attr_set_aigp_metric(path->attr, path->nexthop->metric);
3166
0
  } else {
3167
0
    aigp = atoi(aigp_metric);
3168
0
    bgp_attr_set_aigp_metric(path->attr, aigp);
3169
0
  }
3170
3171
0
  path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_AIGP);
3172
3173
0
  return RMAP_OKAY;
3174
0
}
3175
3176
static void *route_set_aigp_metric_compile(const char *arg)
3177
0
{
3178
0
  return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
3179
0
}
3180
3181
static void route_set_aigp_metric_free(void *rule)
3182
0
{
3183
0
  XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
3184
0
}
3185
3186
static const struct route_map_rule_cmd route_set_aigp_metric_cmd = {
3187
  "aigp-metric",
3188
  route_set_aigp_metric,
3189
  route_set_aigp_metric_compile,
3190
  route_set_aigp_metric_free,
3191
};
3192
3193
/* `set aggregator as AS A.B.C.D' */
3194
struct aggregator {
3195
  as_t as;
3196
  struct in_addr address;
3197
};
3198
3199
static enum route_map_cmd_result_t
3200
route_set_aggregator_as(void *rule, const struct prefix *prefix, void *object)
3201
0
{
3202
0
  struct bgp_path_info *path;
3203
0
  struct aggregator *aggregator;
3204
3205
0
  path = object;
3206
0
  aggregator = rule;
3207
3208
0
  path->attr->aggregator_as = aggregator->as;
3209
0
  path->attr->aggregator_addr = aggregator->address;
3210
0
  path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR);
3211
3212
0
  return RMAP_OKAY;
3213
0
}
3214
3215
static void *route_set_aggregator_as_compile(const char *arg)
3216
0
{
3217
0
  struct aggregator *aggregator;
3218
0
  char as[10];
3219
0
  char address[20];
3220
0
  int ret;
3221
3222
0
  aggregator =
3223
0
    XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct aggregator));
3224
0
  if (sscanf(arg, "%s %s", as, address) != 2) {
3225
0
    XFREE(MTYPE_ROUTE_MAP_COMPILED, aggregator);
3226
0
    return NULL;
3227
0
  }
3228
3229
0
  aggregator->as = strtoul(as, NULL, 10);
3230
0
  ret = inet_aton(address, &aggregator->address);
3231
0
  if (ret == 0) {
3232
0
    XFREE(MTYPE_ROUTE_MAP_COMPILED, aggregator);
3233
0
    return NULL;
3234
0
  }
3235
0
  return aggregator;
3236
0
}
3237
3238
static void route_set_aggregator_as_free(void *rule)
3239
0
{
3240
0
  XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
3241
0
}
3242
3243
static const struct route_map_rule_cmd route_set_aggregator_as_cmd = {
3244
  "aggregator as",
3245
  route_set_aggregator_as,
3246
  route_set_aggregator_as_compile,
3247
  route_set_aggregator_as_free,
3248
};
3249
3250
/* Set tag to object. object must be pointer to struct bgp_path_info */
3251
static enum route_map_cmd_result_t
3252
route_set_tag(void *rule, const struct prefix *prefix, void *object)
3253
0
{
3254
0
  route_tag_t *tag;
3255
0
  struct bgp_path_info *path;
3256
3257
0
  tag = rule;
3258
0
  path = object;
3259
3260
  /* Set tag value */
3261
0
  path->attr->tag = *tag;
3262
3263
0
  return RMAP_OKAY;
3264
0
}
3265
3266
/* Route map commands for tag set. */
3267
static const struct route_map_rule_cmd route_set_tag_cmd = {
3268
  "tag",
3269
  route_set_tag,
3270
  route_map_rule_tag_compile,
3271
  route_map_rule_tag_free,
3272
};
3273
3274
/* Set label-index to object. object must be pointer to struct bgp_path_info */
3275
static enum route_map_cmd_result_t
3276
route_set_label_index(void *rule, const struct prefix *prefix, void *object)
3277
0
{
3278
0
  struct rmap_value *rv;
3279
0
  struct bgp_path_info *path;
3280
0
  uint32_t label_index;
3281
3282
  /* Fetch routemap's rule information. */
3283
0
  rv = rule;
3284
0
  path = object;
3285
3286
  /* Set label-index value. */
3287
0
  label_index = rv->value;
3288
0
  if (label_index) {
3289
0
    path->attr->label_index = label_index;
3290
0
    path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID);
3291
0
  }
3292
3293
0
  return RMAP_OKAY;
3294
0
}
3295
3296
/* Route map commands for label-index set. */
3297
static const struct route_map_rule_cmd route_set_label_index_cmd = {
3298
  "label-index",
3299
  route_set_label_index,
3300
  route_value_compile,
3301
  route_value_free,
3302
};
3303
3304
/* `match ipv6 address IP_ACCESS_LIST' */
3305
3306
static enum route_map_cmd_result_t
3307
route_match_ipv6_address(void *rule, const struct prefix *prefix, void *object)
3308
0
{
3309
0
  struct access_list *alist;
3310
3311
0
  if (prefix->family == AF_INET6) {
3312
0
    alist = access_list_lookup(AFI_IP6, (char *)rule);
3313
0
    if (alist == NULL) {
3314
0
      if (unlikely(CHECK_FLAG(rmap_debug,
3315
0
            DEBUG_ROUTEMAP_DETAIL)))
3316
0
        zlog_debug(
3317
0
          "%s: Access-List Specified: %s does not exist defaulting to NO_MATCH",
3318
0
          __func__, (char *)rule);
3319
3320
0
      return RMAP_NOMATCH;
3321
0
    }
3322
3323
0
    return (access_list_apply(alist, prefix) == FILTER_DENY
3324
0
        ? RMAP_NOMATCH
3325
0
        : RMAP_MATCH);
3326
0
  }
3327
0
  return RMAP_NOMATCH;
3328
0
}
3329
3330
static void *route_match_ipv6_address_compile(const char *arg)
3331
0
{
3332
0
  struct access_list *alist;
3333
3334
0
  alist = access_list_lookup(AFI_IP6, arg);
3335
0
  if (!alist)
3336
0
    zlog_warn(
3337
0
      "Access List specified %s does not exist yet, default will be NO_MATCH until it is created",
3338
0
      arg);
3339
3340
0
  return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
3341
0
}
3342
3343
static void route_match_ipv6_address_free(void *rule)
3344
0
{
3345
0
  XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
3346
0
}
3347
3348
/* Route map commands for ip address matching. */
3349
static const struct route_map_rule_cmd route_match_ipv6_address_cmd = {
3350
  "ipv6 address",
3351
  route_match_ipv6_address,
3352
  route_match_ipv6_address_compile,
3353
  route_match_ipv6_address_free
3354
};
3355
3356
/* `match ipv6 next-hop ACCESSLIST6_NAME' */
3357
static enum route_map_cmd_result_t
3358
route_match_ipv6_next_hop(void *rule, const struct prefix *prefix, void *object)
3359
0
{
3360
0
  struct bgp_path_info *path;
3361
0
  struct access_list *alist;
3362
0
  struct prefix_ipv6 p;
3363
3364
0
  if (prefix->family == AF_INET6) {
3365
0
    path = object;
3366
0
    p.family = AF_INET6;
3367
0
    p.prefix = path->attr->mp_nexthop_global;
3368
0
    p.prefixlen = IPV6_MAX_BITLEN;
3369
3370
0
    alist = access_list_lookup(AFI_IP6, (char *)rule);
3371
0
    if (!alist) {
3372
0
      if (unlikely(CHECK_FLAG(rmap_debug,
3373
0
            DEBUG_ROUTEMAP_DETAIL)))
3374
0
        zlog_debug(
3375
0
          "%s: Access-List Specified: %s does not exist defaulting to NO_MATCH",
3376
0
          __func__, (char *)rule);
3377
3378
0
      return RMAP_NOMATCH;
3379
0
    }
3380
3381
0
    if (access_list_apply(alist, &p) == FILTER_PERMIT)
3382
0
      return RMAP_MATCH;
3383
3384
0
    if (path->attr->mp_nexthop_len
3385
0
        == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
3386
0
      p.prefix = path->attr->mp_nexthop_local;
3387
0
      if (access_list_apply(alist, &p) == FILTER_PERMIT)
3388
0
        return RMAP_MATCH;
3389
0
    }
3390
0
  }
3391
3392
0
  return RMAP_NOMATCH;
3393
0
}
3394
3395
static void *route_match_ipv6_next_hop_compile(const char *arg)
3396
0
{
3397
0
  return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
3398
0
}
3399
3400
static void route_match_ipv6_next_hop_free(void *rule)
3401
0
{
3402
0
  XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
3403
0
}
3404
3405
static const struct route_map_rule_cmd route_match_ipv6_next_hop_cmd = {
3406
  "ipv6 next-hop",
3407
  route_match_ipv6_next_hop,
3408
  route_match_ipv6_next_hop_compile,
3409
  route_match_ipv6_next_hop_free
3410
};
3411
3412
/* `match ipv6 next-hop IP_ADDRESS' */
3413
3414
static enum route_map_cmd_result_t
3415
route_match_ipv6_next_hop_address(void *rule, const struct prefix *prefix,
3416
          void *object)
3417
0
{
3418
0
  struct in6_addr *addr = rule;
3419
0
  struct bgp_path_info *path;
3420
3421
0
  path = object;
3422
3423
0
  if (IPV6_ADDR_SAME(&path->attr->mp_nexthop_global, addr))
3424
0
    return RMAP_MATCH;
3425
3426
0
  if (path->attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
3427
0
      && IPV6_ADDR_SAME(&path->attr->mp_nexthop_local, rule))
3428
0
    return RMAP_MATCH;
3429
3430
0
  return RMAP_NOMATCH;
3431
0
}
3432
3433
static void *route_match_ipv6_next_hop_address_compile(const char *arg)
3434
0
{
3435
0
  struct in6_addr *address;
3436
0
  int ret;
3437
3438
0
  address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct in6_addr));
3439
3440
0
  ret = inet_pton(AF_INET6, arg, address);
3441
0
  if (!ret) {
3442
0
    XFREE(MTYPE_ROUTE_MAP_COMPILED, address);
3443
0
    return NULL;
3444
0
  }
3445
3446
0
  return address;
3447
0
}
3448
3449
static void route_match_ipv6_next_hop_address_free(void *rule)
3450
0
{
3451
0
  XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
3452
0
}
3453
3454
static const struct route_map_rule_cmd route_match_ipv6_next_hop_address_cmd = {
3455
  "ipv6 next-hop address",
3456
  route_match_ipv6_next_hop_address,
3457
  route_match_ipv6_next_hop_address_compile,
3458
  route_match_ipv6_next_hop_address_free
3459
};
3460
3461
/* `match ip next-hop address IP_ADDRESS' */
3462
3463
static enum route_map_cmd_result_t
3464
route_match_ipv4_next_hop(void *rule, const struct prefix *prefix, void *object)
3465
0
{
3466
0
  struct in_addr *addr = rule;
3467
0
  struct bgp_path_info *path;
3468
3469
0
  path = object;
3470
3471
0
  if (path->attr->nexthop.s_addr == addr->s_addr
3472
0
      || (path->attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV4
3473
0
    && IPV4_ADDR_SAME(&path->attr->mp_nexthop_global_in, addr)))
3474
0
    return RMAP_MATCH;
3475
3476
0
  return RMAP_NOMATCH;
3477
0
}
3478
3479
static void *route_match_ipv4_next_hop_compile(const char *arg)
3480
0
{
3481
0
  struct in_addr *address;
3482
0
  int ret;
3483
3484
0
  address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct in_addr));
3485
3486
0
  ret = inet_pton(AF_INET, arg, address);
3487
0
  if (!ret) {
3488
0
    XFREE(MTYPE_ROUTE_MAP_COMPILED, address);
3489
0
    return NULL;
3490
0
  }
3491
3492
0
  return address;
3493
0
}
3494
3495
static void route_match_ipv4_next_hop_free(void *rule)
3496
0
{
3497
0
  XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
3498
0
}
3499
3500
static const struct route_map_rule_cmd route_match_ipv4_next_hop_cmd = {
3501
  "ip next-hop address",
3502
  route_match_ipv4_next_hop,
3503
  route_match_ipv4_next_hop_compile,
3504
  route_match_ipv4_next_hop_free
3505
};
3506
3507
/* `match ipv6 address prefix-list PREFIX_LIST' */
3508
3509
static enum route_map_cmd_result_t
3510
route_match_ipv6_address_prefix_list(void *rule, const struct prefix *prefix,
3511
             void *object)
3512
0
{
3513
0
  return route_match_address_prefix_list(rule, AFI_IP6, prefix, object);
3514
0
}
3515
3516
static void *route_match_ipv6_address_prefix_list_compile(const char *arg)
3517
0
{
3518
0
  return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
3519
0
}
3520
3521
static void route_match_ipv6_address_prefix_list_free(void *rule)
3522
0
{
3523
0
  XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
3524
0
}
3525
3526
static const struct route_map_rule_cmd
3527
    route_match_ipv6_address_prefix_list_cmd = {
3528
  "ipv6 address prefix-list",
3529
  route_match_ipv6_address_prefix_list,
3530
  route_match_ipv6_address_prefix_list_compile,
3531
  route_match_ipv6_address_prefix_list_free
3532
};
3533
3534
/* `match ipv6 next-hop type <TYPE>' */
3535
3536
static enum route_map_cmd_result_t
3537
route_match_ipv6_next_hop_type(void *rule, const struct prefix *prefix,
3538
             void *object)
3539
0
{
3540
0
  struct bgp_path_info *path;
3541
0
  struct in6_addr *addr = rule;
3542
3543
0
  if (prefix->family == AF_INET6) {
3544
0
    path = (struct bgp_path_info *)object;
3545
0
    if (!path)
3546
0
      return RMAP_NOMATCH;
3547
3548
0
    if (IPV6_ADDR_SAME(&path->attr->mp_nexthop_global, addr)
3549
0
        && !path->attr->nh_ifindex)
3550
0
      return RMAP_MATCH;
3551
0
  }
3552
3553
0
  return RMAP_NOMATCH;
3554
0
}
3555
3556
static void *route_match_ipv6_next_hop_type_compile(const char *arg)
3557
0
{
3558
0
  struct in6_addr *address;
3559
0
  int ret;
3560
3561
0
  address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct in6_addr));
3562
3563
0
  ret = inet_pton(AF_INET6, "::0", address);
3564
0
  if (!ret) {
3565
0
    XFREE(MTYPE_ROUTE_MAP_COMPILED, address);
3566
0
    return NULL;
3567
0
  }
3568
3569
0
  return address;
3570
0
}
3571
3572
static void route_match_ipv6_next_hop_type_free(void *rule)
3573
0
{
3574
0
  XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
3575
0
}
3576
3577
static const struct route_map_rule_cmd
3578
    route_match_ipv6_next_hop_type_cmd = {
3579
  "ipv6 next-hop type",
3580
  route_match_ipv6_next_hop_type,
3581
  route_match_ipv6_next_hop_type_compile,
3582
  route_match_ipv6_next_hop_type_free
3583
};
3584
3585
/* `set ipv6 nexthop global IP_ADDRESS' */
3586
3587
/* Set nexthop to object.  object must be pointer to struct attr. */
3588
static enum route_map_cmd_result_t
3589
route_set_ipv6_nexthop_global(void *rule, const struct prefix *p, void *object)
3590
0
{
3591
0
  struct in6_addr *address;
3592
0
  struct bgp_path_info *path;
3593
3594
  /* Fetch routemap's rule information. */
3595
0
  address = rule;
3596
0
  path = object;
3597
3598
  /* Set next hop value. */
3599
0
  path->attr->mp_nexthop_global = *address;
3600
3601
  /* Set nexthop length. */
3602
0
  if (path->attr->mp_nexthop_len == 0)
3603
0
    path->attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
3604
3605
0
  SET_FLAG(path->attr->rmap_change_flags,
3606
0
     BATTR_RMAP_IPV6_GLOBAL_NHOP_CHANGED);
3607
3608
0
  return RMAP_OKAY;
3609
0
}
3610
3611
/* Route map `ip next-hop' compile function.  Given string is converted
3612
   to struct in_addr structure. */
3613
static void *route_set_ipv6_nexthop_global_compile(const char *arg)
3614
0
{
3615
0
  int ret;
3616
0
  struct in6_addr *address;
3617
3618
0
  address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct in6_addr));
3619
3620
0
  ret = inet_pton(AF_INET6, arg, address);
3621
3622
0
  if (ret == 0) {
3623
0
    XFREE(MTYPE_ROUTE_MAP_COMPILED, address);
3624
0
    return NULL;
3625
0
  }
3626
3627
0
  return address;
3628
0
}
3629
3630
/* Free route map's compiled `ip next-hop' value. */
3631
static void route_set_ipv6_nexthop_global_free(void *rule)
3632
0
{
3633
0
  XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
3634
0
}
3635
3636
/* Route map commands for ip nexthop set. */
3637
static const struct route_map_rule_cmd
3638
    route_set_ipv6_nexthop_global_cmd = {
3639
  "ipv6 next-hop global",
3640
  route_set_ipv6_nexthop_global,
3641
  route_set_ipv6_nexthop_global_compile,
3642
  route_set_ipv6_nexthop_global_free
3643
};
3644
3645
/* Set next-hop preference value. */
3646
static enum route_map_cmd_result_t
3647
route_set_ipv6_nexthop_prefer_global(void *rule, const struct prefix *prefix,
3648
             void *object)
3649
0
{
3650
0
  struct bgp_path_info *path;
3651
0
  struct peer *peer;
3652
3653
  /* Fetch routemap's rule information. */
3654
0
  path = object;
3655
0
  peer = path->peer;
3656
3657
0
  if (CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN)
3658
0
      || CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IMPORT)) {
3659
    /* Set next hop preference to global */
3660
0
    path->attr->mp_nexthop_prefer_global = true;
3661
0
    SET_FLAG(path->attr->rmap_change_flags,
3662
0
       BATTR_RMAP_IPV6_PREFER_GLOBAL_CHANGED);
3663
0
  } else {
3664
0
    path->attr->mp_nexthop_prefer_global = false;
3665
0
    SET_FLAG(path->attr->rmap_change_flags,
3666
0
       BATTR_RMAP_IPV6_PREFER_GLOBAL_CHANGED);
3667
0
  }
3668
3669
0
  return RMAP_OKAY;
3670
0
}
3671
3672
static void *route_set_ipv6_nexthop_prefer_global_compile(const char *arg)
3673
0
{
3674
0
  int *rins = NULL;
3675
3676
0
  rins = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(int));
3677
0
  *rins = 1;
3678
3679
0
  return rins;
3680
0
}
3681
3682
/* Free route map's compiled `ip next-hop' value. */
3683
static void route_set_ipv6_nexthop_prefer_global_free(void *rule)
3684
0
{
3685
0
  XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
3686
0
}
3687
3688
/* Route map commands for ip nexthop set preferred. */
3689
static const struct route_map_rule_cmd
3690
    route_set_ipv6_nexthop_prefer_global_cmd = {
3691
  "ipv6 next-hop prefer-global",
3692
  route_set_ipv6_nexthop_prefer_global,
3693
  route_set_ipv6_nexthop_prefer_global_compile,
3694
  route_set_ipv6_nexthop_prefer_global_free
3695
};
3696
3697
/* `set ipv6 nexthop local IP_ADDRESS' */
3698
3699
/* Set nexthop to object.  object must be pointer to struct attr. */
3700
static enum route_map_cmd_result_t
3701
route_set_ipv6_nexthop_local(void *rule, const struct prefix *p, void *object)
3702
0
{
3703
0
  struct in6_addr *address;
3704
0
  struct bgp_path_info *path;
3705
0
  struct bgp_dest *dest;
3706
0
  struct bgp_table *table = NULL;
3707
3708
  /* Fetch routemap's rule information. */
3709
0
  address = rule;
3710
0
  path = object;
3711
0
  dest = path->net;
3712
3713
0
  if (!dest)
3714
0
    return RMAP_OKAY;
3715
3716
0
  table = bgp_dest_table(dest);
3717
0
  if (!table)
3718
0
    return RMAP_OKAY;
3719
3720
  /* Set next hop value. */
3721
0
  path->attr->mp_nexthop_local = *address;
3722
3723
  /* Set nexthop length. */
3724
0
  if (table->safi == SAFI_MPLS_VPN || table->safi == SAFI_ENCAP ||
3725
0
      table->safi == SAFI_EVPN)
3726
0
    path->attr->mp_nexthop_len = BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL;
3727
0
  else
3728
0
    path->attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
3729
3730
0
  SET_FLAG(path->attr->rmap_change_flags,
3731
0
     BATTR_RMAP_IPV6_LL_NHOP_CHANGED);
3732
3733
0
  return RMAP_OKAY;
3734
0
}
3735
3736
/* Route map `ip nexthop' compile function.  Given string is converted
3737
   to struct in_addr structure. */
3738
static void *route_set_ipv6_nexthop_local_compile(const char *arg)
3739
0
{
3740
0
  int ret;
3741
0
  struct in6_addr *address;
3742
3743
0
  address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct in6_addr));
3744
3745
0
  ret = inet_pton(AF_INET6, arg, address);
3746
3747
0
  if (ret == 0) {
3748
0
    XFREE(MTYPE_ROUTE_MAP_COMPILED, address);
3749
0
    return NULL;
3750
0
  }
3751
3752
0
  return address;
3753
0
}
3754
3755
/* Free route map's compiled `ip nexthop' value. */
3756
static void route_set_ipv6_nexthop_local_free(void *rule)
3757
0
{
3758
0
  XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
3759
0
}
3760
3761
/* Route map commands for ip nexthop set. */
3762
static const struct route_map_rule_cmd
3763
    route_set_ipv6_nexthop_local_cmd = {
3764
  "ipv6 next-hop local",
3765
  route_set_ipv6_nexthop_local,
3766
  route_set_ipv6_nexthop_local_compile,
3767
  route_set_ipv6_nexthop_local_free
3768
};
3769
3770
/* `set ipv6 nexthop peer-address' */
3771
3772
/* Set nexthop to object.  object must be pointer to struct attr. */
3773
static enum route_map_cmd_result_t
3774
route_set_ipv6_nexthop_peer(void *rule, const struct prefix *pfx, void *object)
3775
0
{
3776
0
  struct in6_addr peer_address;
3777
0
  struct bgp_path_info *path;
3778
0
  struct peer *peer;
3779
3780
  /* Fetch routemap's rule information. */
3781
0
  path = object;
3782
0
  peer = path->peer;
3783
3784
0
  if ((CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN)
3785
0
       || CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IMPORT))
3786
0
      && peer->su_remote
3787
0
      && sockunion_family(peer->su_remote) == AF_INET6) {
3788
0
    peer_address = peer->su_remote->sin6.sin6_addr;
3789
    /* Set next hop value and length in attribute. */
3790
0
    if (IN6_IS_ADDR_LINKLOCAL(&peer_address)) {
3791
0
      path->attr->mp_nexthop_local = peer_address;
3792
0
      if (path->attr->mp_nexthop_len
3793
0
          != BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
3794
0
        path->attr->mp_nexthop_len =
3795
0
          BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
3796
0
    } else {
3797
0
      path->attr->mp_nexthop_global = peer_address;
3798
0
      if (path->attr->mp_nexthop_len == 0)
3799
0
        path->attr->mp_nexthop_len =
3800
0
          BGP_ATTR_NHLEN_IPV6_GLOBAL;
3801
0
    }
3802
3803
0
  } else if (CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT)) {
3804
    /* The next hop value will be set as part of packet
3805
     * rewrite.
3806
     * Set the flags here to indicate that rewrite needs to
3807
     * be done.
3808
     * Also, clear the value - we clear both global and
3809
     * link-local
3810
     * nexthops, whether we send one or both is determined
3811
     * elsewhere.
3812
     */
3813
0
    SET_FLAG(path->attr->rmap_change_flags,
3814
0
       BATTR_RMAP_NEXTHOP_PEER_ADDRESS);
3815
    /* clear next hop value. */
3816
0
    memset(&(path->attr->mp_nexthop_global), 0,
3817
0
           sizeof(struct in6_addr));
3818
0
    memset(&(path->attr->mp_nexthop_local), 0,
3819
0
           sizeof(struct in6_addr));
3820
0
  }
3821
3822
0
  return RMAP_OKAY;
3823
0
}
3824
3825
/* Route map `ip next-hop' compile function.  Given string is converted
3826
   to struct in_addr structure. */
3827
static void *route_set_ipv6_nexthop_peer_compile(const char *arg)
3828
0
{
3829
0
  int *rins = NULL;
3830
3831
0
  rins = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(int));
3832
0
  *rins = 1;
3833
3834
0
  return rins;
3835
0
}
3836
3837
/* Free route map's compiled `ip next-hop' value. */
3838
static void route_set_ipv6_nexthop_peer_free(void *rule)
3839
0
{
3840
0
  XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
3841
0
}
3842
3843
/* Route map commands for ip nexthop set. */
3844
static const struct route_map_rule_cmd route_set_ipv6_nexthop_peer_cmd = {
3845
  "ipv6 next-hop peer-address",
3846
  route_set_ipv6_nexthop_peer,
3847
  route_set_ipv6_nexthop_peer_compile,
3848
  route_set_ipv6_nexthop_peer_free
3849
};
3850
3851
/* `set ipv4 vpn next-hop A.B.C.D' */
3852
3853
static enum route_map_cmd_result_t
3854
route_set_vpnv4_nexthop(void *rule, const struct prefix *prefix, void *object)
3855
0
{
3856
0
  struct in_addr *address;
3857
0
  struct bgp_path_info *path;
3858
3859
  /* Fetch routemap's rule information. */
3860
0
  address = rule;
3861
0
  path = object;
3862
3863
  /* Set next hop value. */
3864
0
  path->attr->mp_nexthop_global_in = *address;
3865
0
  path->attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
3866
3867
0
  SET_FLAG(path->attr->rmap_change_flags, BATTR_RMAP_VPNV4_NHOP_CHANGED);
3868
3869
0
  return RMAP_OKAY;
3870
0
}
3871
3872
static void *route_set_vpnv4_nexthop_compile(const char *arg)
3873
0
{
3874
0
  int ret;
3875
0
  struct in_addr *address;
3876
3877
0
  address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct in_addr));
3878
3879
0
  ret = inet_aton(arg, address);
3880
3881
0
  if (ret == 0) {
3882
0
    XFREE(MTYPE_ROUTE_MAP_COMPILED, address);
3883
0
    return NULL;
3884
0
  }
3885
3886
0
  return address;
3887
0
}
3888
3889
/* `set ipv6 vpn next-hop A.B.C.D' */
3890
3891
static enum route_map_cmd_result_t
3892
route_set_vpnv6_nexthop(void *rule, const struct prefix *prefix, void *object)
3893
0
{
3894
0
  struct in6_addr *address;
3895
0
  struct bgp_path_info *path;
3896
3897
  /* Fetch routemap's rule information. */
3898
0
  address = rule;
3899
0
  path = object;
3900
3901
  /* Set next hop value. */
3902
0
  memcpy(&path->attr->mp_nexthop_global, address,
3903
0
         sizeof(struct in6_addr));
3904
0
  path->attr->mp_nexthop_len = BGP_ATTR_NHLEN_VPNV6_GLOBAL;
3905
3906
0
  SET_FLAG(path->attr->rmap_change_flags,
3907
0
     BATTR_RMAP_VPNV6_GLOBAL_NHOP_CHANGED);
3908
3909
0
  return RMAP_OKAY;
3910
0
}
3911
3912
static void *route_set_vpnv6_nexthop_compile(const char *arg)
3913
0
{
3914
0
  int ret;
3915
0
  struct in6_addr *address;
3916
3917
0
  address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct in6_addr));
3918
0
  ret = inet_pton(AF_INET6, arg, address);
3919
3920
0
  if (ret == 0) {
3921
0
    XFREE(MTYPE_ROUTE_MAP_COMPILED, address);
3922
0
    return NULL;
3923
0
  }
3924
3925
0
  return address;
3926
0
}
3927
3928
static void route_set_vpn_nexthop_free(void *rule)
3929
0
{
3930
0
  XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
3931
0
}
3932
3933
/* Route map commands for ipv4 next-hop set. */
3934
static const struct route_map_rule_cmd route_set_vpnv4_nexthop_cmd = {
3935
  "ipv4 vpn next-hop",
3936
  route_set_vpnv4_nexthop,
3937
  route_set_vpnv4_nexthop_compile,
3938
  route_set_vpn_nexthop_free
3939
};
3940
3941
/* Route map commands for ipv6 next-hop set. */
3942
static const struct route_map_rule_cmd route_set_vpnv6_nexthop_cmd = {
3943
  "ipv6 vpn next-hop",
3944
  route_set_vpnv6_nexthop,
3945
  route_set_vpnv6_nexthop_compile,
3946
  route_set_vpn_nexthop_free
3947
};
3948
3949
/* `set originator-id' */
3950
3951
/* For origin set. */
3952
static enum route_map_cmd_result_t
3953
route_set_originator_id(void *rule, const struct prefix *prefix, void *object)
3954
0
{
3955
0
  struct in_addr *address;
3956
0
  struct bgp_path_info *path;
3957
3958
0
  address = rule;
3959
0
  path = object;
3960
3961
0
  path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID);
3962
0
  path->attr->originator_id = *address;
3963
3964
0
  return RMAP_OKAY;
3965
0
}
3966
3967
/* Compile function for originator-id set. */
3968
static void *route_set_originator_id_compile(const char *arg)
3969
0
{
3970
0
  int ret;
3971
0
  struct in_addr *address;
3972
3973
0
  address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct in_addr));
3974
3975
0
  ret = inet_aton(arg, address);
3976
3977
0
  if (ret == 0) {
3978
0
    XFREE(MTYPE_ROUTE_MAP_COMPILED, address);
3979
0
    return NULL;
3980
0
  }
3981
3982
0
  return address;
3983
0
}
3984
3985
/* Compile function for originator_id set. */
3986
static void route_set_originator_id_free(void *rule)
3987
0
{
3988
0
  XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
3989
0
}
3990
3991
/* Set originator-id rule structure. */
3992
static const struct route_map_rule_cmd route_set_originator_id_cmd = {
3993
  "originator-id",
3994
  route_set_originator_id,
3995
  route_set_originator_id_compile,
3996
  route_set_originator_id_free,
3997
};
3998
3999
static enum route_map_cmd_result_t
4000
route_match_rpki_extcommunity(void *rule, const struct prefix *prefix,
4001
            void *object)
4002
0
{
4003
0
  struct bgp_path_info *path;
4004
0
  struct ecommunity *ecomm;
4005
0
  struct ecommunity_val *ecomm_val;
4006
0
  enum rpki_states *rpki_status = rule;
4007
0
  enum rpki_states ecomm_rpki_status = RPKI_NOT_BEING_USED;
4008
4009
0
  path = object;
4010
4011
0
  ecomm = bgp_attr_get_ecommunity(path->attr);
4012
0
  if (!ecomm)
4013
0
    return RMAP_NOMATCH;
4014
4015
0
  ecomm_val = ecommunity_lookup(ecomm, ECOMMUNITY_ENCODE_OPAQUE_NON_TRANS,
4016
0
              ECOMMUNITY_ORIGIN_VALIDATION_STATE);
4017
0
  if (!ecomm_val)
4018
0
    return RMAP_NOMATCH;
4019
4020
  /* The Origin Validation State is encoded in the last octet of
4021
   * the extended community.
4022
   */
4023
0
  switch (ecomm_val->val[7]) {
4024
0
  case ECOMMUNITY_ORIGIN_VALIDATION_STATE_VALID:
4025
0
    ecomm_rpki_status = RPKI_VALID;
4026
0
    break;
4027
0
  case ECOMMUNITY_ORIGIN_VALIDATION_STATE_NOTFOUND:
4028
0
    ecomm_rpki_status = RPKI_NOTFOUND;
4029
0
    break;
4030
0
  case ECOMMUNITY_ORIGIN_VALIDATION_STATE_INVALID:
4031
0
    ecomm_rpki_status = RPKI_INVALID;
4032
0
    break;
4033
0
  case ECOMMUNITY_ORIGIN_VALIDATION_STATE_NOTUSED:
4034
0
    break;
4035
0
  }
4036
4037
0
  if (ecomm_rpki_status == *rpki_status)
4038
0
    return RMAP_MATCH;
4039
4040
0
  return RMAP_NOMATCH;
4041
0
}
4042
4043
static void *route_match_extcommunity_compile(const char *arg)
4044
0
{
4045
0
  int *rpki_status;
4046
4047
0
  rpki_status = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(int));
4048
4049
0
  if (strcmp(arg, "valid") == 0)
4050
0
    *rpki_status = RPKI_VALID;
4051
0
  else if (strcmp(arg, "invalid") == 0)
4052
0
    *rpki_status = RPKI_INVALID;
4053
0
  else
4054
0
    *rpki_status = RPKI_NOTFOUND;
4055
4056
0
  return rpki_status;
4057
0
}
4058
4059
static const struct route_map_rule_cmd route_match_rpki_extcommunity_cmd = {
4060
  "rpki-extcommunity",
4061
  route_match_rpki_extcommunity,
4062
  route_match_extcommunity_compile,
4063
  route_value_free
4064
};
4065
4066
/*
4067
 * This is the workhorse routine for processing in/out routemap
4068
 * modifications.
4069
 */
4070
static void bgp_route_map_process_peer(const char *rmap_name,
4071
               struct route_map *map, struct peer *peer,
4072
               int afi, int safi, int route_update)
4073
0
{
4074
0
  struct bgp_filter *filter;
4075
4076
0
  if (!peer || !rmap_name)
4077
0
    return;
4078
4079
0
  filter = &peer->filter[afi][safi];
4080
  /*
4081
   * in is for non-route-server clients,
4082
   * out is for all peers
4083
   */
4084
0
  if (filter->map[RMAP_IN].name
4085
0
      && (strcmp(rmap_name, filter->map[RMAP_IN].name) == 0)) {
4086
0
    filter->map[RMAP_IN].map = map;
4087
4088
0
    if (route_update && peer_established(peer)) {
4089
0
      if (CHECK_FLAG(peer->af_flags[afi][safi],
4090
0
               PEER_FLAG_SOFT_RECONFIG)) {
4091
0
        if (bgp_debug_update(peer, NULL, NULL, 1))
4092
0
          zlog_debug(
4093
0
            "Processing route_map %s(%s:%s) update on peer %s (inbound, soft-reconfig)",
4094
0
            rmap_name, afi2str(afi),
4095
0
            safi2str(safi), peer->host);
4096
4097
0
        bgp_soft_reconfig_in(peer, afi, safi);
4098
0
      } else if (CHECK_FLAG(peer->cap,
4099
0
                PEER_CAP_REFRESH_OLD_RCV)
4100
0
           || CHECK_FLAG(peer->cap,
4101
0
             PEER_CAP_REFRESH_NEW_RCV)) {
4102
0
        if (bgp_debug_update(peer, NULL, NULL, 1))
4103
0
          zlog_debug(
4104
0
            "Processing route_map %s(%s:%s) update on peer %s (inbound, route-refresh)",
4105
0
            rmap_name, afi2str(afi),
4106
0
            safi2str(safi), peer->host);
4107
0
        bgp_route_refresh_send(
4108
0
          peer, afi, safi, 0, 0, 0,
4109
0
          BGP_ROUTE_REFRESH_NORMAL);
4110
0
      }
4111
0
    }
4112
0
  }
4113
4114
  /*
4115
   * For outbound, unsuppress and default-originate map change (content or
4116
   * map created), merely update the "config" here, the actual route
4117
   * announcement happens at the group level.
4118
   */
4119
0
  if (filter->map[RMAP_OUT].name
4120
0
      && (strcmp(rmap_name, filter->map[RMAP_OUT].name) == 0))
4121
0
    filter->map[RMAP_OUT].map = map;
4122
4123
0
  if (filter->usmap.name && (strcmp(rmap_name, filter->usmap.name) == 0))
4124
0
    filter->usmap.map = map;
4125
4126
0
  if (filter->advmap.aname
4127
0
      && (strcmp(rmap_name, filter->advmap.aname) == 0)) {
4128
0
    filter->advmap.amap = map;
4129
0
  }
4130
4131
0
  if (filter->advmap.cname
4132
0
      && (strcmp(rmap_name, filter->advmap.cname) == 0)) {
4133
0
    filter->advmap.cmap = map;
4134
0
  }
4135
4136
0
  if (peer->default_rmap[afi][safi].name
4137
0
      && (strcmp(rmap_name, peer->default_rmap[afi][safi].name) == 0))
4138
0
    peer->default_rmap[afi][safi].map = map;
4139
4140
  /* Notify BGP conditional advertisement scanner percess */
4141
0
  peer->advmap_config_change[afi][safi] = true;
4142
0
}
4143
4144
static void bgp_route_map_update_peer_group(const char *rmap_name,
4145
              struct route_map *map,
4146
              struct bgp *bgp)
4147
0
{
4148
0
  struct peer_group *group;
4149
0
  struct listnode *node, *nnode;
4150
0
  struct bgp_filter *filter;
4151
0
  int afi, safi;
4152
0
  int direct;
4153
4154
0
  if (!bgp)
4155
0
    return;
4156
4157
  /* All the peers have been updated correctly already. This is
4158
   * just updating the placeholder data. No real update required.
4159
   */
4160
0
  for (ALL_LIST_ELEMENTS(bgp->group, node, nnode, group)) {
4161
0
    FOREACH_AFI_SAFI (afi, safi) {
4162
0
      filter = &group->conf->filter[afi][safi];
4163
4164
0
      for (direct = RMAP_IN; direct < RMAP_MAX; direct++) {
4165
0
        if ((filter->map[direct].name)
4166
0
            && (strcmp(rmap_name,
4167
0
                 filter->map[direct].name)
4168
0
          == 0))
4169
0
          filter->map[direct].map = map;
4170
0
      }
4171
4172
0
      if (filter->usmap.name
4173
0
          && (strcmp(rmap_name, filter->usmap.name) == 0))
4174
0
        filter->usmap.map = map;
4175
4176
0
      if (filter->advmap.aname &&
4177
0
          (strcmp(rmap_name, filter->advmap.aname) == 0))
4178
0
        filter->advmap.amap = map;
4179
4180
0
      if (filter->advmap.cname &&
4181
0
          (strcmp(rmap_name, filter->advmap.cname) == 0))
4182
0
        filter->advmap.cmap = map;
4183
0
    }
4184
0
  }
4185
0
}
4186
4187
/*
4188
 * Note that if an extreme number (tens of thousands) of route-maps are in use
4189
 * and if bgp has an extreme number of peers, network statements, etc then this
4190
 * function can consume a lot of cycles. This is due to this function being
4191
 * called for each route-map and within this function we walk the list of peers,
4192
 * network statements, etc looking to see if they use this route-map.
4193
 */
4194
static void bgp_route_map_process_update(struct bgp *bgp, const char *rmap_name,
4195
           bool route_update)
4196
0
{
4197
0
  int i;
4198
0
  bool matched;
4199
0
  afi_t afi;
4200
0
  safi_t safi;
4201
0
  struct peer *peer;
4202
0
  struct bgp_dest *bn;
4203
0
  struct bgp_static *bgp_static;
4204
0
  struct bgp_aggregate *aggregate;
4205
0
  struct listnode *node, *nnode;
4206
0
  struct route_map *map;
4207
0
  char buf[INET6_ADDRSTRLEN];
4208
4209
0
  map = route_map_lookup_by_name(rmap_name);
4210
4211
0
  for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
4212
4213
    /* Ignore dummy peer-group structure */
4214
0
    if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
4215
0
      continue;
4216
4217
0
    FOREACH_AFI_SAFI (afi, safi) {
4218
      /* process in/out/import/export/default-orig
4219
       * route-maps */
4220
0
      bgp_route_map_process_peer(rmap_name, map, peer, afi,
4221
0
               safi, route_update);
4222
0
    }
4223
0
  }
4224
4225
  /* for outbound/default-orig route-maps, process for groups */
4226
0
  update_group_policy_update(bgp, BGP_POLICY_ROUTE_MAP, rmap_name,
4227
0
           route_update, 0);
4228
4229
  /* update peer-group config (template) */
4230
0
  bgp_route_map_update_peer_group(rmap_name, map, bgp);
4231
4232
0
  FOREACH_AFI_SAFI (afi, safi) {
4233
    /* For table route-map updates. */
4234
0
    if (!bgp_fibupd_safi(safi))
4235
0
      continue;
4236
4237
0
    if (bgp->table_map[afi][safi].name
4238
0
        && (strcmp(rmap_name, bgp->table_map[afi][safi].name)
4239
0
      == 0)) {
4240
4241
      /* bgp->table_map[afi][safi].map  is NULL.
4242
       * i.e Route map creation event.
4243
       * So update applied_counter.
4244
       * If it is not NULL, i.e It may be routemap updation or
4245
       * deletion. so no need to update the counter.
4246
       */
4247
0
      if (!bgp->table_map[afi][safi].map)
4248
0
        route_map_counter_increment(map);
4249
0
      bgp->table_map[afi][safi].map = map;
4250
4251
0
      if (BGP_DEBUG(zebra, ZEBRA))
4252
0
        zlog_debug(
4253
0
          "Processing route_map %s(%s:%s) update on table map",
4254
0
          rmap_name, afi2str(afi),
4255
0
          safi2str(safi));
4256
0
      if (route_update)
4257
0
        bgp_zebra_announce_table(bgp, afi, safi);
4258
0
    }
4259
4260
    /* For network route-map updates. */
4261
0
    for (bn = bgp_table_top(bgp->route[afi][safi]); bn;
4262
0
         bn = bgp_route_next(bn)) {
4263
0
      bgp_static = bgp_dest_get_bgp_static_info(bn);
4264
0
      if (!bgp_static)
4265
0
        continue;
4266
4267
0
      if (!bgp_static->rmap.name
4268
0
          || (strcmp(rmap_name, bgp_static->rmap.name) != 0))
4269
0
        continue;
4270
4271
0
      if (!bgp_static->rmap.map)
4272
0
        route_map_counter_increment(map);
4273
4274
0
      bgp_static->rmap.map = map;
4275
4276
0
      if (route_update && !bgp_static->backdoor) {
4277
0
        const struct prefix *bn_p =
4278
0
          bgp_dest_get_prefix(bn);
4279
4280
0
        if (bgp_debug_zebra(bn_p))
4281
0
          zlog_debug(
4282
0
            "Processing route_map %s(%s:%s) update on static route %s",
4283
0
            rmap_name, afi2str(afi),
4284
0
            safi2str(safi),
4285
0
            inet_ntop(bn_p->family,
4286
0
                &bn_p->u.prefix, buf,
4287
0
                sizeof(buf)));
4288
0
        bgp_static_update(bgp, bn_p, bgp_static, afi,
4289
0
              safi);
4290
0
      }
4291
0
    }
4292
4293
    /* For aggregate-address route-map updates. */
4294
0
    for (bn = bgp_table_top(bgp->aggregate[afi][safi]); bn;
4295
0
         bn = bgp_route_next(bn)) {
4296
0
      aggregate = bgp_dest_get_bgp_aggregate_info(bn);
4297
0
      if (!aggregate)
4298
0
        continue;
4299
4300
0
      matched = false;
4301
4302
      /* Update suppress map pointer. */
4303
0
      if (aggregate->suppress_map_name
4304
0
          && strmatch(aggregate->suppress_map_name,
4305
0
          rmap_name)) {
4306
0
        if (aggregate->rmap.map == NULL)
4307
0
          route_map_counter_increment(map);
4308
4309
0
        aggregate->suppress_map = map;
4310
4311
0
        bgp_aggregate_toggle_suppressed(
4312
0
          aggregate, bgp, bgp_dest_get_prefix(bn),
4313
0
          afi, safi, false);
4314
4315
0
        matched = true;
4316
0
      }
4317
4318
0
      if (aggregate->rmap.name
4319
0
          && strmatch(rmap_name, aggregate->rmap.name)) {
4320
0
        if (aggregate->rmap.map == NULL)
4321
0
          route_map_counter_increment(map);
4322
4323
0
        aggregate->rmap.map = map;
4324
4325
0
        matched = true;
4326
0
      }
4327
4328
0
      if (matched && route_update) {
4329
0
        const struct prefix *bn_p =
4330
0
          bgp_dest_get_prefix(bn);
4331
4332
0
        if (bgp_debug_zebra(bn_p))
4333
0
          zlog_debug(
4334
0
            "Processing route_map %s(%s:%s) update on aggregate-address route %s",
4335
0
            rmap_name, afi2str(afi),
4336
0
            safi2str(safi),
4337
0
            inet_ntop(bn_p->family,
4338
0
                &bn_p->u.prefix, buf,
4339
0
                sizeof(buf)));
4340
0
        (void)bgp_aggregate_route(bgp, bn_p, afi, safi,
4341
0
                aggregate);
4342
0
      }
4343
0
    }
4344
0
  }
4345
4346
  /* For redistribute route-map updates. */
4347
0
  for (afi = AFI_IP; afi < AFI_MAX; afi++)
4348
0
    for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
4349
0
      struct list *red_list;
4350
0
      struct bgp_redist *red;
4351
4352
0
      red_list = bgp->redist[afi][i];
4353
0
      if (!red_list)
4354
0
        continue;
4355
4356
0
      for (ALL_LIST_ELEMENTS_RO(red_list, node, red)) {
4357
0
        if (!red->rmap.name
4358
0
            || (strcmp(rmap_name, red->rmap.name) != 0))
4359
0
          continue;
4360
4361
0
        if (!red->rmap.map)
4362
0
          route_map_counter_increment(map);
4363
4364
0
        red->rmap.map = map;
4365
4366
0
        if (!route_update)
4367
0
          continue;
4368
4369
0
        if (BGP_DEBUG(zebra, ZEBRA))
4370
0
          zlog_debug(
4371
0
            "Processing route_map %s(%s:%s) update on redistributed routes",
4372
0
            rmap_name, afi2str(afi),
4373
0
            safi2str(safi));
4374
4375
0
        bgp_redistribute_resend(bgp, afi, i,
4376
0
              red->instance);
4377
0
      }
4378
0
    }
4379
4380
  /* for type5 command route-maps */
4381
0
  FOREACH_AFI_SAFI (afi, safi) {
4382
0
    if (!bgp->adv_cmd_rmap[afi][safi].name
4383
0
        || strcmp(rmap_name, bgp->adv_cmd_rmap[afi][safi].name)
4384
0
             != 0)
4385
0
      continue;
4386
4387
    /* Make sure the route-map is populated here if not already done */
4388
0
    bgp->adv_cmd_rmap[afi][safi].map = map;
4389
4390
0
    if (BGP_DEBUG(zebra, ZEBRA))
4391
0
      zlog_debug(
4392
0
        "Processing route_map %s(%s:%s) update on advertise type5 route command",
4393
0
        rmap_name, afi2str(afi), safi2str(safi));
4394
4395
0
    if (route_update && advertise_type5_routes(bgp, afi)) {
4396
0
      bgp_evpn_withdraw_type5_routes(bgp, afi, safi);
4397
0
      bgp_evpn_advertise_type5_routes(bgp, afi, safi);
4398
0
    }
4399
0
  }
4400
0
}
4401
4402
static void bgp_route_map_process_update_cb(char *rmap_name)
4403
0
{
4404
0
  struct listnode *node, *nnode;
4405
0
  struct bgp *bgp;
4406
4407
0
  for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
4408
0
    bgp_route_map_process_update(bgp, rmap_name, true);
4409
4410
0
#ifdef ENABLE_BGP_VNC
4411
0
    vnc_routemap_update(bgp, __func__);
4412
0
#endif
4413
0
  }
4414
4415
0
  vpn_policy_routemap_event(rmap_name);
4416
0
}
4417
4418
void bgp_route_map_update_timer(struct event *thread)
4419
0
{
4420
0
  route_map_walk_update_list(bgp_route_map_process_update_cb);
4421
0
}
4422
4423
static void bgp_route_map_mark_update(const char *rmap_name)
4424
0
{
4425
0
  struct listnode *node, *nnode;
4426
0
  struct bgp *bgp;
4427
4428
  /* If new update is received before the current timer timed out,
4429
   * turn it off and start a new timer.
4430
   */
4431
0
  EVENT_OFF(bm->t_rmap_update);
4432
4433
  /* rmap_update_timer of 0 means don't do route updates */
4434
0
  if (bm->rmap_update_timer) {
4435
0
    event_add_timer(bm->master, bgp_route_map_update_timer, NULL,
4436
0
        bm->rmap_update_timer, &bm->t_rmap_update);
4437
4438
    /* Signal the groups that a route-map update event has
4439
     * started */
4440
0
    for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
4441
0
      update_group_policy_update(bgp, BGP_POLICY_ROUTE_MAP,
4442
0
               rmap_name, true, 1);
4443
0
  } else {
4444
0
    for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
4445
0
      bgp_route_map_process_update(bgp, rmap_name, false);
4446
0
#ifdef ENABLE_BGP_VNC
4447
0
      vnc_routemap_update(bgp, __func__);
4448
0
#endif
4449
0
    }
4450
4451
0
    vpn_policy_routemap_event(rmap_name);
4452
0
  }
4453
0
}
4454
4455
static void bgp_route_map_add(const char *rmap_name)
4456
0
{
4457
0
  if (route_map_mark_updated(rmap_name) == 0)
4458
0
    bgp_route_map_mark_update(rmap_name);
4459
4460
0
  route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_ADDED);
4461
0
}
4462
4463
static void bgp_route_map_delete(const char *rmap_name)
4464
0
{
4465
0
  if (route_map_mark_updated(rmap_name) == 0)
4466
0
    bgp_route_map_mark_update(rmap_name);
4467
4468
0
  route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_DELETED);
4469
0
}
4470
4471
static void bgp_route_map_event(const char *rmap_name)
4472
0
{
4473
0
  if (route_map_mark_updated(rmap_name) == 0)
4474
0
    bgp_route_map_mark_update(rmap_name);
4475
4476
0
  route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_ADDED);
4477
0
}
4478
4479
DEFUN_YANG (match_mac_address,
4480
      match_mac_address_cmd,
4481
      "match mac address ACCESSLIST_MAC_NAME",
4482
      MATCH_STR
4483
      "mac address\n"
4484
      "Match address of route\n"
4485
      "MAC Access-list name\n")
4486
0
{
4487
0
  const char *xpath =
4488
0
    "./match-condition[condition='frr-bgp-route-map:mac-address-list']";
4489
0
  char xpath_value[XPATH_MAXLEN];
4490
4491
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
4492
0
  snprintf(xpath_value, sizeof(xpath_value),
4493
0
     "%s/rmap-match-condition/frr-bgp-route-map:list-name", xpath);
4494
0
  nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, argv[3]->arg);
4495
4496
0
  return nb_cli_apply_changes(vty, NULL);
4497
0
}
4498
4499
DEFUN_YANG (no_match_mac_address,
4500
      no_match_mac_address_cmd,
4501
      "no match mac address ACCESSLIST_MAC_NAME",
4502
      NO_STR
4503
      MATCH_STR
4504
      "mac\n"
4505
      "Match address of route\n"
4506
      "MAC acess-list name\n")
4507
0
{
4508
0
  const char *xpath =
4509
0
    "./match-condition[condition='frr-bgp-route-map:mac-address-list']";
4510
4511
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
4512
0
  return nb_cli_apply_changes(vty, NULL);
4513
0
}
4514
4515
/*
4516
 * Helper to handle the case of the user passing in a number or type string
4517
 */
4518
static const char *parse_evpn_rt_type(const char *num_rt_type)
4519
0
{
4520
0
  switch (num_rt_type[0]) {
4521
0
  case '1':
4522
0
    return "ead";
4523
0
  case '2':
4524
0
    return "macip";
4525
0
  case '3':
4526
0
    return "multicast";
4527
0
  case '4':
4528
0
    return "es";
4529
0
  case '5':
4530
0
    return "prefix";
4531
0
  default:
4532
0
    break;
4533
0
  }
4534
4535
  /* Was already full type string */
4536
0
  return num_rt_type;
4537
0
}
4538
4539
DEFUN_YANG (match_evpn_route_type,
4540
      match_evpn_route_type_cmd,
4541
      "match evpn route-type <ead|1|macip|2|multicast|3|es|4|prefix|5>",
4542
      MATCH_STR
4543
      EVPN_HELP_STR
4544
      EVPN_TYPE_HELP_STR
4545
      EVPN_TYPE_1_HELP_STR
4546
      EVPN_TYPE_1_HELP_STR
4547
      EVPN_TYPE_2_HELP_STR
4548
      EVPN_TYPE_2_HELP_STR
4549
      EVPN_TYPE_3_HELP_STR
4550
      EVPN_TYPE_3_HELP_STR
4551
      EVPN_TYPE_4_HELP_STR
4552
      EVPN_TYPE_4_HELP_STR
4553
      EVPN_TYPE_5_HELP_STR
4554
      EVPN_TYPE_5_HELP_STR)
4555
0
{
4556
0
  const char *xpath =
4557
0
    "./match-condition[condition='frr-bgp-route-map:evpn-route-type']";
4558
0
  char xpath_value[XPATH_MAXLEN];
4559
4560
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
4561
0
  snprintf(xpath_value, sizeof(xpath_value),
4562
0
     "%s/rmap-match-condition/frr-bgp-route-map:evpn-route-type",
4563
0
     xpath);
4564
0
  nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
4565
0
            parse_evpn_rt_type(argv[3]->arg));
4566
4567
0
  return nb_cli_apply_changes(vty, NULL);
4568
0
}
4569
4570
DEFUN_YANG (no_match_evpn_route_type,
4571
      no_match_evpn_route_type_cmd,
4572
      "no match evpn route-type <ead|1|macip|2|multicast|3|es|4|prefix|5>",
4573
      NO_STR
4574
      MATCH_STR
4575
      EVPN_HELP_STR
4576
      EVPN_TYPE_HELP_STR
4577
      EVPN_TYPE_1_HELP_STR
4578
      EVPN_TYPE_1_HELP_STR
4579
      EVPN_TYPE_2_HELP_STR
4580
      EVPN_TYPE_2_HELP_STR
4581
      EVPN_TYPE_3_HELP_STR
4582
      EVPN_TYPE_3_HELP_STR
4583
      EVPN_TYPE_4_HELP_STR
4584
      EVPN_TYPE_4_HELP_STR
4585
      EVPN_TYPE_5_HELP_STR
4586
      EVPN_TYPE_5_HELP_STR)
4587
0
{
4588
0
  const char *xpath =
4589
0
    "./match-condition[condition='frr-bgp-route-map:evpn-route-type']";
4590
4591
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
4592
4593
0
  return nb_cli_apply_changes(vty, NULL);
4594
0
}
4595
4596
4597
DEFUN_YANG (match_evpn_vni,
4598
      match_evpn_vni_cmd,
4599
      "match evpn vni " CMD_VNI_RANGE,
4600
      MATCH_STR
4601
      EVPN_HELP_STR
4602
      "Match VNI\n"
4603
      "VNI ID\n")
4604
0
{
4605
0
  const char *xpath =
4606
0
    "./match-condition[condition='frr-bgp-route-map:evpn-vni']";
4607
0
  char xpath_value[XPATH_MAXLEN];
4608
4609
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
4610
0
  snprintf(xpath_value, sizeof(xpath_value),
4611
0
     "%s/rmap-match-condition/frr-bgp-route-map:evpn-vni", xpath);
4612
0
  nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, argv[3]->arg);
4613
4614
0
  return nb_cli_apply_changes(vty, NULL);
4615
0
}
4616
4617
DEFUN_YANG (no_match_evpn_vni,
4618
      no_match_evpn_vni_cmd,
4619
      "no match evpn vni " CMD_VNI_RANGE,
4620
      NO_STR
4621
      MATCH_STR
4622
      EVPN_HELP_STR
4623
      "Match VNI\n"
4624
      "VNI ID\n")
4625
0
{
4626
0
  const char *xpath =
4627
0
    "./match-condition[condition='frr-bgp-route-map:evpn-vni']";
4628
0
  char xpath_value[XPATH_MAXLEN];
4629
4630
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
4631
0
  snprintf(xpath_value, sizeof(xpath_value),
4632
0
     "%s/rmap-match-condition/frr-bgp-route-map:evpn-vni", xpath);
4633
0
  nb_cli_enqueue_change(vty, xpath_value, NB_OP_DESTROY, argv[3]->arg);
4634
4635
0
  return nb_cli_apply_changes(vty, NULL);
4636
0
}
4637
4638
DEFUN_YANG (match_evpn_default_route,
4639
      match_evpn_default_route_cmd,
4640
      "match evpn default-route",
4641
      MATCH_STR
4642
      EVPN_HELP_STR
4643
      "default EVPN type-5 route\n")
4644
0
{
4645
0
  const char *xpath =
4646
0
    "./match-condition[condition='frr-bgp-route-map:evpn-default-route']";
4647
0
  char xpath_value[XPATH_MAXLEN];
4648
4649
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
4650
4651
0
  snprintf(xpath_value, sizeof(xpath_value),
4652
0
     "%s/rmap-match-condition/frr-bgp-route-map:evpn-default-route",
4653
0
     xpath);
4654
0
  nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, NULL);
4655
4656
0
  return nb_cli_apply_changes(vty, NULL);
4657
0
}
4658
4659
DEFUN_YANG (no_match_evpn_default_route,
4660
      no_match_evpn_default_route_cmd,
4661
      "no match evpn default-route",
4662
      NO_STR
4663
      MATCH_STR
4664
      EVPN_HELP_STR
4665
      "default EVPN type-5 route\n")
4666
0
{
4667
0
  const char *xpath =
4668
0
    "./match-condition[condition='frr-bgp-route-map:evpn-default-route']";
4669
4670
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
4671
4672
0
  return nb_cli_apply_changes(vty, NULL);
4673
0
}
4674
4675
DEFUN_YANG (match_evpn_rd,
4676
      match_evpn_rd_cmd,
4677
      "match evpn rd ASN:NN_OR_IP-ADDRESS:NN",
4678
      MATCH_STR
4679
      EVPN_HELP_STR
4680
      "Route Distinguisher\n"
4681
      "ASN:XX or A.B.C.D:XX\n")
4682
0
{
4683
0
  const char *xpath =
4684
0
    "./match-condition[condition='frr-bgp-route-map:evpn-rd']";
4685
0
  char xpath_value[XPATH_MAXLEN];
4686
4687
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
4688
0
  snprintf(
4689
0
    xpath_value, sizeof(xpath_value),
4690
0
    "%s/rmap-match-condition/frr-bgp-route-map:route-distinguisher",
4691
0
    xpath);
4692
0
  nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, argv[3]->arg);
4693
4694
0
  return nb_cli_apply_changes(vty, NULL);
4695
0
}
4696
4697
DEFUN_YANG (no_match_evpn_rd,
4698
      no_match_evpn_rd_cmd,
4699
      "no match evpn rd ASN:NN_OR_IP-ADDRESS:NN",
4700
      NO_STR
4701
      MATCH_STR
4702
      EVPN_HELP_STR
4703
      "Route Distinguisher\n"
4704
      "ASN:XX or A.B.C.D:XX\n")
4705
0
{
4706
0
  const char *xpath =
4707
0
    "./match-condition[condition='frr-bgp-route-map:evpn-rd']";
4708
4709
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
4710
0
  return nb_cli_apply_changes(vty, NULL);
4711
0
}
4712
4713
DEFUN_YANG (set_evpn_gw_ip_ipv4,
4714
      set_evpn_gw_ip_ipv4_cmd,
4715
      "set evpn gateway-ip ipv4 A.B.C.D",
4716
      SET_STR
4717
      EVPN_HELP_STR
4718
      "Set gateway IP for prefix advertisement route\n"
4719
      "IPv4 address\n"
4720
      "Gateway IP address in IPv4 format\n")
4721
0
{
4722
0
  int ret;
4723
0
  union sockunion su;
4724
0
  const char *xpath =
4725
0
    "./set-action[action='frr-bgp-route-map:set-evpn-gateway-ip-ipv4']";
4726
0
  char xpath_value[XPATH_MAXLEN];
4727
4728
0
  ret = str2sockunion(argv[4]->arg, &su);
4729
0
  if (ret < 0) {
4730
0
    vty_out(vty, "%% Malformed gateway IP\n");
4731
0
    return CMD_WARNING_CONFIG_FAILED;
4732
0
  }
4733
4734
0
  if (su.sin.sin_addr.s_addr == 0 ||
4735
0
      !ipv4_unicast_valid(&su.sin.sin_addr)) {
4736
0
    vty_out(vty,
4737
0
      "%% Gateway IP cannot be 0.0.0.0, multicast or reserved\n");
4738
0
    return CMD_WARNING_CONFIG_FAILED;
4739
0
  }
4740
4741
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
4742
4743
0
  snprintf(xpath_value, sizeof(xpath_value),
4744
0
     "%s/rmap-set-action/frr-bgp-route-map:evpn-gateway-ip-ipv4",
4745
0
     xpath);
4746
4747
0
  nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, argv[4]->arg);
4748
0
  return nb_cli_apply_changes(vty, NULL);
4749
0
}
4750
4751
DEFUN_YANG (no_set_evpn_gw_ip_ipv4,
4752
      no_set_evpn_gw_ip_ipv4_cmd,
4753
      "no set evpn gateway-ip ipv4 A.B.C.D",
4754
      NO_STR
4755
      SET_STR
4756
      EVPN_HELP_STR
4757
      "Set gateway IP for prefix advertisement route\n"
4758
      "IPv4 address\n"
4759
      "Gateway IP address in IPv4 format\n")
4760
0
{
4761
0
  int ret;
4762
0
  union sockunion su;
4763
0
  const char *xpath =
4764
0
    "./set-action[action='frr-bgp-route-map:set-evpn-gateway-ip-ipv4']";
4765
4766
0
  ret = str2sockunion(argv[5]->arg, &su);
4767
0
  if (ret < 0) {
4768
0
    vty_out(vty, "%% Malformed gateway IP\n");
4769
0
    return CMD_WARNING_CONFIG_FAILED;
4770
0
  }
4771
4772
0
  if (su.sin.sin_addr.s_addr == 0 ||
4773
0
      !ipv4_unicast_valid(&su.sin.sin_addr)) {
4774
0
    vty_out(vty,
4775
0
      "%% Gateway IP cannot be 0.0.0.0, multicast or reserved\n");
4776
0
    return CMD_WARNING_CONFIG_FAILED;
4777
0
  }
4778
4779
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
4780
4781
0
  return nb_cli_apply_changes(vty, NULL);
4782
0
}
4783
4784
DEFUN_YANG (set_evpn_gw_ip_ipv6,
4785
      set_evpn_gw_ip_ipv6_cmd,
4786
      "set evpn gateway-ip ipv6 X:X::X:X",
4787
      SET_STR
4788
      EVPN_HELP_STR
4789
      "Set gateway IP for prefix advertisement route\n"
4790
      "IPv6 address\n"
4791
      "Gateway IP address in IPv6 format\n")
4792
0
{
4793
0
  int ret;
4794
0
  union sockunion su;
4795
0
  const char *xpath =
4796
0
    "./set-action[action='frr-bgp-route-map:set-evpn-gateway-ip-ipv6']";
4797
0
  char xpath_value[XPATH_MAXLEN];
4798
4799
0
  ret = str2sockunion(argv[4]->arg, &su);
4800
0
  if (ret < 0) {
4801
0
    vty_out(vty, "%% Malformed gateway IP\n");
4802
0
    return CMD_WARNING_CONFIG_FAILED;
4803
0
  }
4804
4805
0
  if (IN6_IS_ADDR_LINKLOCAL(&su.sin6.sin6_addr)
4806
0
      || IN6_IS_ADDR_MULTICAST(&su.sin6.sin6_addr)) {
4807
0
    vty_out(vty,
4808
0
      "%% Gateway IP cannot be a linklocal or multicast address\n");
4809
0
    return CMD_WARNING_CONFIG_FAILED;
4810
0
  }
4811
4812
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
4813
4814
0
  snprintf(xpath_value, sizeof(xpath_value),
4815
0
     "%s/rmap-set-action/frr-bgp-route-map:evpn-gateway-ip-ipv6",
4816
0
     xpath);
4817
4818
0
  nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, argv[4]->arg);
4819
0
  return nb_cli_apply_changes(vty, NULL);
4820
0
}
4821
4822
DEFUN_YANG (no_set_evpn_gw_ip_ipv6,
4823
      no_set_evpn_gw_ip_ipv6_cmd,
4824
      "no set evpn gateway-ip ipv6 X:X::X:X",
4825
      NO_STR
4826
      SET_STR
4827
      EVPN_HELP_STR
4828
      "Set gateway IP for prefix advertisement route\n"
4829
      "IPv4 address\n"
4830
      "Gateway IP address in IPv4 format\n")
4831
0
{
4832
0
  int ret;
4833
0
  union sockunion su;
4834
0
  const char *xpath =
4835
0
    "./set-action[action='frr-bgp-route-map:set-evpn-gateway-ip-ipv6']";
4836
4837
0
  ret = str2sockunion(argv[5]->arg, &su);
4838
0
  if (ret < 0) {
4839
0
    vty_out(vty, "%% Malformed gateway IP\n");
4840
0
    return CMD_WARNING_CONFIG_FAILED;
4841
0
  }
4842
4843
0
  if (IN6_IS_ADDR_LINKLOCAL(&su.sin6.sin6_addr)
4844
0
      || IN6_IS_ADDR_MULTICAST(&su.sin6.sin6_addr)) {
4845
0
    vty_out(vty,
4846
0
      "%% Gateway IP cannot be a linklocal or multicast address\n");
4847
0
    return CMD_WARNING_CONFIG_FAILED;
4848
0
  }
4849
4850
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
4851
4852
0
  return nb_cli_apply_changes(vty, NULL);
4853
0
}
4854
4855
DEFPY_YANG(match_vrl_source_vrf,
4856
      match_vrl_source_vrf_cmd,
4857
      "match source-vrf NAME$vrf_name",
4858
      MATCH_STR
4859
      "source vrf\n"
4860
      "The VRF name\n")
4861
0
{
4862
0
  const char *xpath =
4863
0
    "./match-condition[condition='frr-bgp-route-map:source-vrf']";
4864
0
  char xpath_value[XPATH_MAXLEN];
4865
4866
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
4867
0
  snprintf(xpath_value, sizeof(xpath_value),
4868
0
     "%s/rmap-match-condition/frr-bgp-route-map:source-vrf", xpath);
4869
0
  nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, vrf_name);
4870
4871
0
  return nb_cli_apply_changes(vty, NULL);
4872
0
}
4873
4874
DEFPY_YANG(no_match_vrl_source_vrf,
4875
      no_match_vrl_source_vrf_cmd,
4876
      "no match source-vrf NAME$vrf_name",
4877
      NO_STR MATCH_STR
4878
      "source vrf\n"
4879
      "The VRF name\n")
4880
0
{
4881
0
  const char *xpath =
4882
0
    "./match-condition[condition='frr-bgp-route-map:source-vrf']";
4883
4884
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
4885
0
  return nb_cli_apply_changes(vty, NULL);
4886
0
}
4887
4888
DEFPY_YANG (match_peer,
4889
       match_peer_cmd,
4890
       "match peer <A.B.C.D$addrv4|X:X::X:X$addrv6|WORD$intf>",
4891
       MATCH_STR
4892
       "Match peer address\n"
4893
       "IP address of peer\n"
4894
       "IPv6 address of peer\n"
4895
       "Interface name of peer or peer group name\n")
4896
0
{
4897
0
  const char *xpath =
4898
0
    "./match-condition[condition='frr-bgp-route-map:peer']";
4899
0
  char xpath_value[XPATH_MAXLEN];
4900
4901
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
4902
4903
0
  if (addrv4_str) {
4904
0
    snprintf(
4905
0
      xpath_value, sizeof(xpath_value),
4906
0
      "%s/rmap-match-condition/frr-bgp-route-map:peer-ipv4-address",
4907
0
      xpath);
4908
0
    nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
4909
0
              addrv4_str);
4910
0
  } else if (addrv6_str) {
4911
0
    snprintf(
4912
0
      xpath_value, sizeof(xpath_value),
4913
0
      "%s/rmap-match-condition/frr-bgp-route-map:peer-ipv6-address",
4914
0
      xpath);
4915
0
    nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
4916
0
              addrv6_str);
4917
0
  } else {
4918
0
    snprintf(
4919
0
      xpath_value, sizeof(xpath_value),
4920
0
      "%s/rmap-match-condition/frr-bgp-route-map:peer-interface",
4921
0
      xpath);
4922
0
    nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, intf);
4923
0
  }
4924
4925
0
  return nb_cli_apply_changes(vty, NULL);
4926
0
}
4927
4928
DEFUN_YANG (match_peer_local,
4929
      match_peer_local_cmd,
4930
      "match peer local",
4931
      MATCH_STR
4932
      "Match peer address\n"
4933
      "Static or Redistributed routes\n")
4934
0
{
4935
0
  const char *xpath =
4936
0
    "./match-condition[condition='frr-bgp-route-map:peer']";
4937
0
  char xpath_value[XPATH_MAXLEN];
4938
4939
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
4940
4941
0
  snprintf(xpath_value, sizeof(xpath_value),
4942
0
     "%s/rmap-match-condition/frr-bgp-route-map:peer-local", xpath);
4943
0
  nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, "true");
4944
4945
0
  return nb_cli_apply_changes(vty, NULL);
4946
0
}
4947
4948
DEFUN_YANG (no_match_peer,
4949
      no_match_peer_cmd,
4950
      "no match peer [<local|A.B.C.D|X:X::X:X|WORD>]",
4951
      NO_STR
4952
      MATCH_STR
4953
      "Match peer address\n"
4954
      "Static or Redistributed routes\n"
4955
      "IP address of peer\n"
4956
      "IPv6 address of peer\n"
4957
      "Interface name of peer\n")
4958
0
{
4959
0
  const char *xpath =
4960
0
    "./match-condition[condition='frr-bgp-route-map:peer']";
4961
4962
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
4963
4964
0
  return nb_cli_apply_changes(vty, NULL);
4965
0
}
4966
4967
#ifdef HAVE_SCRIPTING
4968
DEFUN_YANG (match_script,
4969
      match_script_cmd,
4970
      "[no] match script WORD",
4971
      NO_STR
4972
      MATCH_STR
4973
      "Execute script to determine match\n"
4974
      "The script name to run, without .lua; e.g. 'myroutemap' to run myroutemap.lua\n")
4975
{
4976
  bool no = strmatch(argv[0]->text, "no");
4977
  int i = 0;
4978
  argv_find(argv, argc, "WORD", &i);
4979
  const char *script = argv[i]->arg;
4980
  const char *xpath =
4981
    "./match-condition[condition='frr-bgp-route-map:match-script']";
4982
  char xpath_value[XPATH_MAXLEN];
4983
4984
  if (no) {
4985
    nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
4986
    snprintf(xpath_value, sizeof(xpath_value),
4987
       "%s/rmap-match-condition/frr-bgp-route-map:script",
4988
       xpath);
4989
    nb_cli_enqueue_change(vty, xpath_value, NB_OP_DESTROY,
4990
              script);
4991
4992
    return nb_cli_apply_changes(vty, NULL);
4993
  }
4994
4995
  nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
4996
  snprintf(xpath_value, sizeof(xpath_value),
4997
      "%s/rmap-match-condition/frr-bgp-route-map:script",
4998
      xpath);
4999
  nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
5000
      script);
5001
5002
  return nb_cli_apply_changes(vty, NULL);
5003
}
5004
#endif /* HAVE_SCRIPTING */
5005
5006
/* match probability */
5007
DEFUN_YANG (match_probability,
5008
      match_probability_cmd,
5009
      "match probability (0-100)",
5010
      MATCH_STR
5011
      "Match portion of routes defined by percentage value\n"
5012
      "Percentage of routes\n")
5013
0
{
5014
0
  int idx_number = 2;
5015
5016
0
  const char *xpath =
5017
0
    "./match-condition[condition='frr-bgp-route-map:probability']";
5018
0
  char xpath_value[XPATH_MAXLEN];
5019
5020
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5021
0
  snprintf(xpath_value, sizeof(xpath_value),
5022
0
     "%s/rmap-match-condition/frr-bgp-route-map:probability",
5023
0
     xpath);
5024
0
  nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
5025
0
            argv[idx_number]->arg);
5026
5027
0
  return nb_cli_apply_changes(vty, NULL);
5028
0
}
5029
5030
5031
DEFUN_YANG (no_match_probability,
5032
      no_match_probability_cmd,
5033
      "no match probability [(1-99)]",
5034
      NO_STR
5035
      MATCH_STR
5036
      "Match portion of routes defined by percentage value\n"
5037
      "Percentage of routes\n")
5038
0
{
5039
0
  int idx_number = 3;
5040
0
  const char *xpath =
5041
0
    "./match-condition[condition='frr-bgp-route-map:probability']";
5042
0
  char xpath_value[XPATH_MAXLEN];
5043
5044
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5045
5046
0
  if (argc <= idx_number)
5047
0
    return nb_cli_apply_changes(vty, NULL);
5048
5049
0
  snprintf(xpath_value, sizeof(xpath_value),
5050
0
     "%s/rmap-match-condition/frr-bgp-route-map:probability",
5051
0
     xpath);
5052
0
  nb_cli_enqueue_change(vty, xpath_value, NB_OP_DESTROY,
5053
0
            argv[idx_number]->arg);
5054
5055
0
  return nb_cli_apply_changes(vty, NULL);
5056
0
}
5057
5058
5059
DEFPY_YANG (match_ip_route_source,
5060
       match_ip_route_source_cmd,
5061
       "match ip route-source ACCESSLIST4_NAME",
5062
       MATCH_STR
5063
       IP_STR
5064
       "Match advertising source address of route\n"
5065
       "IP Access-list name\n")
5066
0
{
5067
0
  const char *xpath =
5068
0
    "./match-condition[condition='frr-bgp-route-map:ip-route-source']";
5069
0
  char xpath_value[XPATH_MAXLEN + 32];
5070
0
  int idx_acl = 3;
5071
5072
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5073
0
  snprintf(xpath_value, sizeof(xpath_value),
5074
0
      "%s/rmap-match-condition/frr-bgp-route-map:list-name",
5075
0
      xpath);
5076
0
  nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
5077
0
            argv[idx_acl]->arg);
5078
5079
0
  return nb_cli_apply_changes(vty, NULL);
5080
0
}
5081
5082
5083
DEFUN_YANG (no_match_ip_route_source,
5084
      no_match_ip_route_source_cmd,
5085
      "no match ip route-source [ACCESSLIST4_NAME]",
5086
      NO_STR
5087
      MATCH_STR
5088
      IP_STR
5089
      "Match advertising source address of route\n"
5090
      "IP Access-list name\n")
5091
0
{
5092
0
  const char *xpath =
5093
0
    "./match-condition[condition='frr-bgp-route-map:ip-route-source']";
5094
5095
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5096
0
  return nb_cli_apply_changes(vty, NULL);
5097
0
}
5098
5099
DEFUN_YANG (match_ip_route_source_prefix_list,
5100
      match_ip_route_source_prefix_list_cmd,
5101
      "match ip route-source prefix-list PREFIXLIST_NAME",
5102
      MATCH_STR
5103
      IP_STR
5104
      "Match advertising source address of route\n"
5105
      "Match entries of prefix-lists\n"
5106
      "IP prefix-list name\n")
5107
0
{
5108
0
  int idx_word = 4;
5109
0
  const char *xpath =
5110
0
    "./match-condition[condition='frr-bgp-route-map:ip-route-source-prefix-list']";
5111
0
  char xpath_value[XPATH_MAXLEN + 32];
5112
5113
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5114
0
  snprintf(xpath_value, sizeof(xpath_value),
5115
0
     "%s/rmap-match-condition/frr-bgp-route-map:list-name", xpath);
5116
0
  nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
5117
0
            argv[idx_word]->arg);
5118
5119
0
  return nb_cli_apply_changes(vty, NULL);
5120
0
}
5121
5122
5123
DEFUN_YANG (no_match_ip_route_source_prefix_list,
5124
      no_match_ip_route_source_prefix_list_cmd,
5125
      "no match ip route-source prefix-list [PREFIXLIST_NAME]",
5126
      NO_STR
5127
      MATCH_STR
5128
      IP_STR
5129
      "Match advertising source address of route\n"
5130
      "Match entries of prefix-lists\n"
5131
      "IP prefix-list name\n")
5132
0
{
5133
0
  const char *xpath =
5134
0
    "./match-condition[condition='frr-bgp-route-map:ip-route-source-prefix-list']";
5135
5136
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5137
0
  return nb_cli_apply_changes(vty, NULL);
5138
0
}
5139
5140
DEFUN_YANG (match_local_pref,
5141
      match_local_pref_cmd,
5142
      "match local-preference (0-4294967295)",
5143
      MATCH_STR
5144
      "Match local-preference of route\n"
5145
      "Metric value\n")
5146
0
{
5147
0
  int idx_number = 2;
5148
5149
0
  const char *xpath =
5150
0
    "./match-condition[condition='frr-bgp-route-map:match-local-preference']";
5151
0
  char xpath_value[XPATH_MAXLEN];
5152
5153
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5154
0
  snprintf(xpath_value, sizeof(xpath_value),
5155
0
     "%s/rmap-match-condition/frr-bgp-route-map:local-preference",
5156
0
     xpath);
5157
0
  nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
5158
0
            argv[idx_number]->arg);
5159
5160
0
  return nb_cli_apply_changes(vty, NULL);
5161
0
}
5162
5163
5164
DEFUN_YANG (no_match_local_pref,
5165
      no_match_local_pref_cmd,
5166
      "no match local-preference [(0-4294967295)]",
5167
      NO_STR
5168
      MATCH_STR
5169
      "Match local preference of route\n"
5170
      "Local preference value\n")
5171
0
{
5172
0
  int idx_localpref = 3;
5173
0
  const char *xpath =
5174
0
    "./match-condition[condition='frr-bgp-route-map:match-local-preference']";
5175
0
  char xpath_value[XPATH_MAXLEN];
5176
5177
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5178
5179
0
  if (argc <= idx_localpref)
5180
0
    return nb_cli_apply_changes(vty, NULL);
5181
5182
0
  snprintf(xpath_value, sizeof(xpath_value),
5183
0
     "%s/rmap-match-condition/frr-bgp-route-map:local-preference",
5184
0
     xpath);
5185
0
  nb_cli_enqueue_change(vty, xpath_value, NB_OP_DESTROY,
5186
0
            argv[idx_localpref]->arg);
5187
5188
0
  return nb_cli_apply_changes(vty, NULL);
5189
0
}
5190
5191
DEFUN_YANG(match_alias, match_alias_cmd, "match alias ALIAS_NAME",
5192
     MATCH_STR
5193
     "Match BGP community alias name\n"
5194
     "BGP community alias name\n")
5195
0
{
5196
0
  const char *alias = argv[2]->arg;
5197
0
  struct community_alias ca1;
5198
0
  struct community_alias *lookup_alias;
5199
5200
0
  const char *xpath =
5201
0
    "./match-condition[condition='frr-bgp-route-map:match-alias']";
5202
0
  char xpath_value[XPATH_MAXLEN];
5203
5204
0
  memset(&ca1, 0, sizeof(ca1));
5205
0
  strlcpy(ca1.alias, alias, sizeof(ca1.alias));
5206
0
  lookup_alias = bgp_ca_alias_lookup(&ca1);
5207
0
  if (!lookup_alias) {
5208
0
    vty_out(vty, "%% BGP alias name '%s' does not exist\n", alias);
5209
0
    return CMD_WARNING_CONFIG_FAILED;
5210
0
  }
5211
5212
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5213
0
  snprintf(xpath_value, sizeof(xpath_value),
5214
0
     "%s/rmap-match-condition/frr-bgp-route-map:alias", xpath);
5215
0
  nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, alias);
5216
5217
0
  return nb_cli_apply_changes(vty, NULL);
5218
0
}
5219
5220
5221
DEFUN_YANG(no_match_alias, no_match_alias_cmd, "no match alias [ALIAS_NAME]",
5222
     NO_STR MATCH_STR
5223
     "Match BGP community alias name\n"
5224
     "BGP community alias name\n")
5225
0
{
5226
0
  int idx_alias = 3;
5227
0
  const char *xpath =
5228
0
    "./match-condition[condition='frr-bgp-route-map:match-alias']";
5229
0
  char xpath_value[XPATH_MAXLEN];
5230
5231
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5232
5233
0
  if (argc <= idx_alias)
5234
0
    return nb_cli_apply_changes(vty, NULL);
5235
5236
0
  snprintf(xpath_value, sizeof(xpath_value),
5237
0
     "%s/rmap-match-condition/frr-bgp-route-map:alias", xpath);
5238
0
  nb_cli_enqueue_change(vty, xpath_value, NB_OP_DESTROY,
5239
0
            argv[idx_alias]->arg);
5240
5241
0
  return nb_cli_apply_changes(vty, NULL);
5242
0
}
5243
5244
DEFPY_YANG (match_community,
5245
       match_community_cmd,
5246
       "match community <(1-99)|(100-500)|COMMUNITY_LIST_NAME> [exact-match]",
5247
       MATCH_STR
5248
       "Match BGP community list\n"
5249
       "Community-list number (standard)\n"
5250
       "Community-list number (expanded)\n"
5251
       "Community-list name\n"
5252
       "Do exact matching of communities\n")
5253
0
{
5254
0
  const char *xpath =
5255
0
    "./match-condition[condition='frr-bgp-route-map:match-community']";
5256
0
  char xpath_value[XPATH_MAXLEN];
5257
0
  char xpath_match[XPATH_MAXLEN];
5258
0
  int idx_comm_list = 2;
5259
5260
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5261
5262
0
  snprintf(
5263
0
    xpath_value, sizeof(xpath_value),
5264
0
    "%s/rmap-match-condition/frr-bgp-route-map:comm-list/comm-list-name",
5265
0
    xpath);
5266
0
  nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, argv[idx_comm_list]->arg);
5267
5268
0
  if (argc == 4) {
5269
0
    snprintf(
5270
0
      xpath_match, sizeof(xpath_match),
5271
0
      "%s/rmap-match-condition/frr-bgp-route-map:comm-list/comm-list-name-exact-match",
5272
0
      xpath);
5273
0
    nb_cli_enqueue_change(vty, xpath_match, NB_OP_MODIFY,
5274
0
        "true");
5275
0
  } else {
5276
0
    snprintf(
5277
0
      xpath_match, sizeof(xpath_match),
5278
0
      "%s/rmap-match-condition/frr-bgp-route-map:comm-list/comm-list-name-exact-match",
5279
0
      xpath);
5280
0
    nb_cli_enqueue_change(vty, xpath_match, NB_OP_MODIFY,
5281
0
        "false");
5282
0
  }
5283
5284
0
  return nb_cli_apply_changes(vty, NULL);
5285
0
}
5286
5287
DEFUN_YANG (no_match_community,
5288
      no_match_community_cmd,
5289
      "no match community [<(1-99)|(100-500)|COMMUNITY_LIST_NAME> [exact-match]]",
5290
      NO_STR
5291
      MATCH_STR
5292
      "Match BGP community list\n"
5293
      "Community-list number (standard)\n"
5294
      "Community-list number (expanded)\n"
5295
      "Community-list name\n"
5296
      "Do exact matching of communities\n")
5297
0
{
5298
0
  const char *xpath =
5299
0
    "./match-condition[condition='frr-bgp-route-map:match-community']";
5300
5301
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5302
0
  return nb_cli_apply_changes(vty, NULL);
5303
0
}
5304
5305
DEFPY_YANG (match_lcommunity,
5306
      match_lcommunity_cmd,
5307
      "match large-community <(1-99)|(100-500)|LCOMMUNITY_LIST_NAME> [exact-match]",
5308
      MATCH_STR
5309
      "Match BGP large community list\n"
5310
      "Large Community-list number (standard)\n"
5311
      "Large Community-list number (expanded)\n"
5312
      "Large Community-list name\n"
5313
      "Do exact matching of communities\n")
5314
0
{
5315
0
  const char *xpath =
5316
0
    "./match-condition[condition='frr-bgp-route-map:match-large-community']";
5317
0
  char xpath_value[XPATH_MAXLEN];
5318
0
  char xpath_match[XPATH_MAXLEN];
5319
0
  int idx_lcomm_list = 2;
5320
5321
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5322
5323
0
  snprintf(
5324
0
    xpath_value, sizeof(xpath_value),
5325
0
    "%s/rmap-match-condition/frr-bgp-route-map:comm-list/comm-list-name",
5326
0
    xpath);
5327
0
  nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, argv[idx_lcomm_list]->arg);
5328
5329
0
  if (argc == 4) {
5330
0
    snprintf(
5331
0
      xpath_match, sizeof(xpath_match),
5332
0
      "%s/rmap-match-condition/frr-bgp-route-map:comm-list/comm-list-name-exact-match",
5333
0
      xpath);
5334
0
    nb_cli_enqueue_change(vty, xpath_match, NB_OP_MODIFY,
5335
0
        "true");
5336
0
  } else {
5337
0
    snprintf(
5338
0
      xpath_match, sizeof(xpath_match),
5339
0
      "%s/rmap-match-condition/frr-bgp-route-map:comm-list/comm-list-name-exact-match",
5340
0
      xpath);
5341
0
    nb_cli_enqueue_change(vty, xpath_match, NB_OP_MODIFY,
5342
0
        "false");
5343
0
  }
5344
5345
0
  return nb_cli_apply_changes(vty, NULL);
5346
0
}
5347
5348
DEFUN_YANG (no_match_lcommunity,
5349
      no_match_lcommunity_cmd,
5350
      "no match large-community [<(1-99)|(100-500)|LCOMMUNITY_LIST_NAME> [exact-match]]",
5351
      NO_STR
5352
      MATCH_STR
5353
      "Match BGP large community list\n"
5354
      "Large Community-list number (standard)\n"
5355
      "Large Community-list number (expanded)\n"
5356
      "Large Community-list name\n"
5357
      "Do exact matching of communities\n")
5358
0
{
5359
0
  const char *xpath =
5360
0
    "./match-condition[condition='frr-bgp-route-map:match-large-community']";
5361
5362
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5363
0
  return nb_cli_apply_changes(vty, NULL);
5364
0
}
5365
5366
DEFPY_YANG (match_ecommunity,
5367
      match_ecommunity_cmd,
5368
            "match extcommunity <(1-99)|(100-500)|EXTCOMMUNITY_LIST_NAME>",
5369
      MATCH_STR
5370
      "Match BGP/VPN extended community list\n"
5371
      "Extended community-list number (standard)\n"
5372
      "Extended community-list number (expanded)\n"
5373
      "Extended community-list name\n")
5374
0
{
5375
0
  const char *xpath =
5376
0
    "./match-condition[condition='frr-bgp-route-map:match-extcommunity']";
5377
0
  char xpath_value[XPATH_MAXLEN];
5378
0
  int idx_comm_list = 2;
5379
5380
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5381
5382
0
  snprintf(
5383
0
    xpath_value, sizeof(xpath_value),
5384
0
    "%s/rmap-match-condition/frr-bgp-route-map:comm-list/comm-list-name",
5385
0
    xpath);
5386
0
  nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, argv[idx_comm_list]->arg);
5387
5388
0
  return nb_cli_apply_changes(vty, NULL);
5389
0
}
5390
5391
5392
DEFUN_YANG (no_match_ecommunity,
5393
      no_match_ecommunity_cmd,
5394
      "no match extcommunity [<(1-99)|(100-500)|EXTCOMMUNITY_LIST_NAME>]",
5395
      NO_STR
5396
      MATCH_STR
5397
      "Match BGP/VPN extended community list\n"
5398
      "Extended community-list number (standard)\n"
5399
      "Extended community-list number (expanded)\n"
5400
      "Extended community-list name\n")
5401
0
{
5402
0
  const char *xpath =
5403
0
    "./match-condition[condition='frr-bgp-route-map:match-extcommunity']";
5404
5405
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5406
0
  return nb_cli_apply_changes(vty, NULL);
5407
0
}
5408
5409
5410
DEFUN_YANG (match_aspath,
5411
      match_aspath_cmd,
5412
      "match as-path AS_PATH_FILTER_NAME",
5413
      MATCH_STR
5414
      "Match BGP AS path list\n"
5415
      "AS path access-list name\n")
5416
0
{
5417
0
  int idx_word = 2;
5418
5419
0
  const char *xpath =
5420
0
    "./match-condition[condition='frr-bgp-route-map:as-path-list']";
5421
0
  char xpath_value[XPATH_MAXLEN];
5422
5423
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5424
0
  snprintf(xpath_value, sizeof(xpath_value),
5425
0
     "%s/rmap-match-condition/frr-bgp-route-map:list-name", xpath);
5426
0
  nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
5427
0
            argv[idx_word]->arg);
5428
5429
0
  return nb_cli_apply_changes(vty, NULL);
5430
0
}
5431
5432
5433
DEFUN_YANG (no_match_aspath,
5434
      no_match_aspath_cmd,
5435
      "no match as-path [AS_PATH_FILTER_NAME]",
5436
      NO_STR
5437
      MATCH_STR
5438
      "Match BGP AS path list\n"
5439
      "AS path access-list name\n")
5440
0
{
5441
0
  const char *xpath =
5442
0
    "./match-condition[condition='frr-bgp-route-map:as-path-list']";
5443
5444
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5445
5446
0
  return nb_cli_apply_changes(vty, NULL);
5447
0
}
5448
5449
DEFUN_YANG (match_origin,
5450
      match_origin_cmd,
5451
      "match origin <egp|igp|incomplete>",
5452
      MATCH_STR
5453
      "BGP origin code\n"
5454
      "remote EGP\n"
5455
      "local IGP\n"
5456
       "unknown heritage\n")
5457
0
{
5458
0
  int idx_origin = 2;
5459
0
  const char *origin_type;
5460
0
  const char *xpath =
5461
0
    "./match-condition[condition='frr-bgp-route-map:match-origin']";
5462
0
  char xpath_value[XPATH_MAXLEN];
5463
5464
0
  if (strncmp(argv[idx_origin]->arg, "igp", 2) == 0)
5465
0
    origin_type = "igp";
5466
0
  else if (strncmp(argv[idx_origin]->arg, "egp", 1) == 0)
5467
0
    origin_type = "egp";
5468
0
  else if (strncmp(argv[idx_origin]->arg, "incomplete", 2) == 0)
5469
0
    origin_type = "incomplete";
5470
0
  else {
5471
0
    vty_out(vty, "%% Invalid match origin type\n");
5472
0
    return CMD_WARNING_CONFIG_FAILED;
5473
0
  }
5474
5475
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5476
0
  snprintf(xpath_value, sizeof(xpath_value),
5477
0
     "%s/rmap-match-condition/frr-bgp-route-map:origin", xpath);
5478
0
  nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, origin_type);
5479
5480
0
  return nb_cli_apply_changes(vty, NULL);
5481
0
}
5482
5483
5484
DEFUN_YANG (no_match_origin,
5485
      no_match_origin_cmd,
5486
      "no match origin [<egp|igp|incomplete>]",
5487
      NO_STR
5488
      MATCH_STR
5489
      "BGP origin code\n"
5490
      "remote EGP\n"
5491
      "local IGP\n"
5492
      "unknown heritage\n")
5493
0
{
5494
0
  const char *xpath =
5495
0
    "./match-condition[condition='frr-bgp-route-map:match-origin']";
5496
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5497
0
  return nb_cli_apply_changes(vty, NULL);
5498
0
}
5499
5500
DEFUN_YANG (set_table_id,
5501
      set_table_id_cmd,
5502
      "set table (1-4294967295)",
5503
      SET_STR
5504
      "export route to non-main kernel table\n"
5505
      "Kernel routing table id\n")
5506
0
{
5507
0
  int idx_number = 2;
5508
0
  const char *xpath = "./set-action[action='frr-bgp-route-map:table']";
5509
0
  char xpath_value[XPATH_MAXLEN];
5510
5511
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5512
0
  snprintf(xpath_value, sizeof(xpath_value),
5513
0
     "%s/rmap-set-action/frr-bgp-route-map:table", xpath);
5514
0
  nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
5515
0
            argv[idx_number]->arg);
5516
0
  return nb_cli_apply_changes(vty, NULL);
5517
0
}
5518
5519
DEFUN_YANG (no_set_table_id,
5520
      no_set_table_id_cmd,
5521
      "no set table",
5522
      NO_STR
5523
      SET_STR
5524
      "export route to non-main kernel table\n")
5525
0
{
5526
0
  const char *xpath = "./set-action[action='frr-bgp-route-map:table']";
5527
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5528
0
  return nb_cli_apply_changes(vty, NULL);
5529
0
}
5530
5531
DEFUN_YANG (set_ip_nexthop_peer,
5532
      set_ip_nexthop_peer_cmd,
5533
      "[no] set ip next-hop peer-address",
5534
      NO_STR
5535
      SET_STR
5536
      IP_STR
5537
      "Next hop address\n"
5538
      "Use peer address (for BGP only)\n")
5539
0
{
5540
0
  char xpath_value[XPATH_MAXLEN];
5541
0
  const char *xpath =
5542
0
    "./set-action[action='frr-bgp-route-map:set-ipv4-nexthop']";
5543
5544
0
  if (strmatch(argv[0]->text, "no"))
5545
0
    nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5546
0
  else {
5547
0
    nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5548
0
    snprintf(xpath_value, sizeof(xpath_value),
5549
0
       "%s/rmap-set-action/frr-bgp-route-map:ipv4-nexthop",
5550
0
       xpath);
5551
0
    nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
5552
0
              "peer-address");
5553
0
  }
5554
0
  return nb_cli_apply_changes(vty, NULL);
5555
0
}
5556
5557
DEFUN_YANG (set_ip_nexthop_unchanged,
5558
      set_ip_nexthop_unchanged_cmd,
5559
      "[no] set ip next-hop unchanged",
5560
      NO_STR
5561
      SET_STR
5562
      IP_STR
5563
      "Next hop address\n"
5564
      "Don't modify existing Next hop address\n")
5565
0
{
5566
0
  char xpath_value[XPATH_MAXLEN];
5567
0
  const char *xpath =
5568
0
    "./set-action[action='frr-bgp-route-map:set-ipv4-nexthop']";
5569
5570
0
  if (strmatch(argv[0]->text, "no"))
5571
0
    nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5572
0
  else {
5573
0
    nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5574
0
    snprintf(xpath_value, sizeof(xpath_value),
5575
0
       "%s/rmap-set-action/frr-bgp-route-map:ipv4-nexthop",
5576
0
       xpath);
5577
0
    nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
5578
0
              "unchanged");
5579
0
  }
5580
0
  return nb_cli_apply_changes(vty, NULL);
5581
0
}
5582
5583
DEFUN_YANG (set_distance,
5584
      set_distance_cmd,
5585
      "set distance (1-255)",
5586
      SET_STR
5587
      "BGP Administrative Distance to use\n"
5588
      "Distance value\n")
5589
0
{
5590
0
  int idx_number = 2;
5591
0
  const char *xpath = "./set-action[action='frr-bgp-route-map:distance']";
5592
0
  char xpath_value[XPATH_MAXLEN];
5593
5594
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5595
0
  snprintf(xpath_value, sizeof(xpath_value),
5596
0
     "%s/rmap-set-action/frr-bgp-route-map:distance", xpath);
5597
0
  nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
5598
0
            argv[idx_number]->arg);
5599
0
  return nb_cli_apply_changes(vty, NULL);
5600
0
}
5601
5602
DEFUN_YANG (no_set_distance,
5603
      no_set_distance_cmd,
5604
      "no set distance [(1-255)]",
5605
      NO_STR SET_STR
5606
      "BGP Administrative Distance to use\n"
5607
      "Distance value\n")
5608
0
{
5609
0
  const char *xpath = "./set-action[action='frr-bgp-route-map:distance']";
5610
5611
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5612
0
  return nb_cli_apply_changes(vty, NULL);
5613
0
}
5614
5615
DEFPY_YANG(set_l3vpn_nexthop_encapsulation, set_l3vpn_nexthop_encapsulation_cmd,
5616
     "[no] set l3vpn next-hop encapsulation gre",
5617
     NO_STR SET_STR
5618
     "L3VPN operations\n"
5619
     "Next hop Information\n"
5620
     "Encapsulation options (for BGP only)\n"
5621
     "Accept L3VPN traffic over GRE encapsulation\n")
5622
0
{
5623
0
  const char *xpath =
5624
0
    "./set-action[action='frr-bgp-route-map:set-l3vpn-nexthop-encapsulation']";
5625
0
  const char *xpath_value =
5626
0
    "./set-action[action='frr-bgp-route-map:set-l3vpn-nexthop-encapsulation']/rmap-set-action/frr-bgp-route-map:l3vpn-nexthop-encapsulation";
5627
0
  enum nb_operation operation;
5628
5629
0
  if (no)
5630
0
    operation = NB_OP_DESTROY;
5631
0
  else
5632
0
    operation = NB_OP_CREATE;
5633
5634
0
  nb_cli_enqueue_change(vty, xpath, operation, NULL);
5635
0
  if (operation == NB_OP_DESTROY)
5636
0
    return nb_cli_apply_changes(vty, NULL);
5637
5638
0
  nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, "gre");
5639
5640
0
  return nb_cli_apply_changes(vty, NULL);
5641
0
}
5642
5643
DEFUN_YANG (set_local_pref,
5644
      set_local_pref_cmd,
5645
      "set local-preference WORD",
5646
      SET_STR
5647
      "BGP local preference path attribute\n"
5648
      "Preference value (0-4294967295)\n")
5649
0
{
5650
0
  int idx_number = 2;
5651
0
  const char *xpath =
5652
0
    "./set-action[action='frr-bgp-route-map:set-local-preference']";
5653
0
  char xpath_value[XPATH_MAXLEN];
5654
5655
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5656
0
  snprintf(xpath_value, sizeof(xpath_value),
5657
0
     "%s/rmap-set-action/frr-bgp-route-map:local-pref", xpath);
5658
0
  nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
5659
0
            argv[idx_number]->arg);
5660
0
  return nb_cli_apply_changes(vty, NULL);
5661
0
}
5662
5663
DEFUN_YANG (no_set_local_pref,
5664
      no_set_local_pref_cmd,
5665
      "no set local-preference [WORD]",
5666
      NO_STR
5667
      SET_STR
5668
      "BGP local preference path attribute\n"
5669
      "Preference value (0-4294967295)\n")
5670
0
{
5671
0
  const char *xpath =
5672
0
    "./set-action[action='frr-bgp-route-map:set-local-preference']";
5673
5674
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5675
0
  return nb_cli_apply_changes(vty, NULL);
5676
0
}
5677
5678
DEFUN_YANG (set_weight,
5679
      set_weight_cmd,
5680
      "set weight (0-4294967295)",
5681
      SET_STR
5682
      "BGP weight for routing table\n"
5683
      "Weight value\n")
5684
0
{
5685
0
  int idx_number = 2;
5686
0
  const char *xpath = "./set-action[action='frr-bgp-route-map:weight']";
5687
0
  char xpath_value[XPATH_MAXLEN];
5688
5689
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5690
0
  snprintf(xpath_value, sizeof(xpath_value),
5691
0
     "%s/rmap-set-action/frr-bgp-route-map:weight", xpath);
5692
0
  nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
5693
0
            argv[idx_number]->arg);
5694
0
  return nb_cli_apply_changes(vty, NULL);
5695
0
}
5696
5697
DEFUN_YANG (no_set_weight,
5698
      no_set_weight_cmd,
5699
      "no set weight [(0-4294967295)]",
5700
      NO_STR
5701
      SET_STR
5702
      "BGP weight for routing table\n"
5703
      "Weight value\n")
5704
0
{
5705
0
  const char *xpath = "./set-action[action='frr-bgp-route-map:weight']";
5706
5707
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5708
0
  return nb_cli_apply_changes(vty, NULL);
5709
0
}
5710
5711
DEFUN_YANG (set_label_index,
5712
      set_label_index_cmd,
5713
      "set label-index (0-1048560)",
5714
      SET_STR
5715
      "Label index to associate with the prefix\n"
5716
      "Label index value\n")
5717
0
{
5718
0
  int idx_number = 2;
5719
0
  const char *xpath =
5720
0
    "./set-action[action='frr-bgp-route-map:label-index']";
5721
0
  char xpath_value[XPATH_MAXLEN];
5722
5723
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5724
0
  snprintf(xpath_value, sizeof(xpath_value),
5725
0
     "%s/rmap-set-action/frr-bgp-route-map:label-index", xpath);
5726
0
  nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
5727
0
            argv[idx_number]->arg);
5728
0
  return nb_cli_apply_changes(vty, NULL);
5729
0
}
5730
5731
DEFUN_YANG (no_set_label_index,
5732
      no_set_label_index_cmd,
5733
      "no set label-index [(0-1048560)]",
5734
      NO_STR
5735
      SET_STR
5736
      "Label index to associate with the prefix\n"
5737
      "Label index value\n")
5738
0
{
5739
0
  const char *xpath =
5740
0
    "./set-action[action='frr-bgp-route-map:label-index']";
5741
5742
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5743
0
  return nb_cli_apply_changes(vty, NULL);
5744
0
}
5745
5746
DEFUN_YANG (set_aspath_prepend_asn,
5747
      set_aspath_prepend_asn_cmd,
5748
      "set as-path prepend ASNUM...",
5749
      SET_STR
5750
      "Transform BGP AS_PATH attribute\n"
5751
      "Prepend to the as-path\n"
5752
      AS_STR)
5753
0
{
5754
0
  int idx_asn = 3;
5755
0
  int ret;
5756
0
  char *str;
5757
0
  struct aspath *aspath;
5758
5759
0
  str = argv_concat(argv, argc, idx_asn);
5760
5761
0
  const char *xpath =
5762
0
    "./set-action[action='frr-bgp-route-map:as-path-prepend']";
5763
0
  char xpath_value[XPATH_MAXLEN];
5764
5765
0
  aspath = route_aspath_compile(str);
5766
0
  if (!aspath) {
5767
0
    vty_out(vty, "%% Invalid AS path value %s\n", str);
5768
0
    return CMD_WARNING_CONFIG_FAILED;
5769
0
  }
5770
0
  route_aspath_free(aspath);
5771
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5772
0
  snprintf(xpath_value, sizeof(xpath_value),
5773
0
     "%s/rmap-set-action/frr-bgp-route-map:prepend-as-path", xpath);
5774
0
  nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, str);
5775
0
  ret = nb_cli_apply_changes(vty, NULL);
5776
0
  XFREE(MTYPE_TMP, str);
5777
0
  return ret;
5778
0
}
5779
5780
DEFUN_YANG (set_aspath_prepend_lastas,
5781
      set_aspath_prepend_lastas_cmd,
5782
      "set as-path prepend last-as (1-10)",
5783
      SET_STR
5784
      "Transform BGP AS_PATH attribute\n"
5785
      "Prepend to the as-path\n"
5786
      "Use the last AS-number in the as-path\n"
5787
      "Number of times to insert\n")
5788
0
{
5789
0
  int idx_num = 4;
5790
5791
0
  const char *xpath =
5792
0
    "./set-action[action='frr-bgp-route-map:as-path-prepend']";
5793
0
  char xpath_value[XPATH_MAXLEN];
5794
5795
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5796
0
  snprintf(xpath_value, sizeof(xpath_value),
5797
0
     "%s/rmap-set-action/frr-bgp-route-map:last-as", xpath);
5798
0
  nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
5799
0
            argv[idx_num]->arg);
5800
0
  return nb_cli_apply_changes(vty, NULL);
5801
0
}
5802
5803
DEFPY_YANG (set_aspath_replace_asn,
5804
      set_aspath_replace_asn_cmd,
5805
      "set as-path replace <any|ASNUM>$replace",
5806
      SET_STR
5807
      "Transform BGP AS_PATH attribute\n"
5808
      "Replace AS number to local AS number\n"
5809
      "Replace any AS number to local AS number\n"
5810
      "Replace a specific AS number in plain or dotted format to local AS number\n")
5811
0
{
5812
0
  const char *xpath =
5813
0
    "./set-action[action='frr-bgp-route-map:as-path-replace']";
5814
0
  char xpath_value[XPATH_MAXLEN];
5815
0
  as_t as_value;
5816
5817
0
  if (!strmatch(replace, "any") && !asn_str2asn(replace, &as_value)) {
5818
0
    vty_out(vty, "%% Invalid AS value %s\n", replace);
5819
0
    return CMD_WARNING_CONFIG_FAILED;
5820
0
  }
5821
5822
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5823
0
  snprintf(xpath_value, sizeof(xpath_value),
5824
0
     "%s/rmap-set-action/frr-bgp-route-map:replace-as-path", xpath);
5825
0
  nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, replace);
5826
0
  return nb_cli_apply_changes(vty, NULL);
5827
0
}
5828
5829
DEFPY_YANG (no_set_aspath_replace_asn,
5830
      no_set_aspath_replace_asn_cmd,
5831
      "no set as-path replace [<any|ASNUM>]",
5832
      NO_STR
5833
      SET_STR
5834
      "Transform BGP AS_PATH attribute\n"
5835
      "Replace AS number to local AS number\n"
5836
      "Replace any AS number to local AS number\n"
5837
      "Replace a specific AS number in plain or dotted format to local AS number\n")
5838
0
{
5839
0
  const char *xpath =
5840
0
    "./set-action[action='frr-bgp-route-map:as-path-replace']";
5841
5842
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5843
0
  return nb_cli_apply_changes(vty, NULL);
5844
0
}
5845
5846
DEFUN_YANG (no_set_aspath_prepend,
5847
      no_set_aspath_prepend_cmd,
5848
      "no set as-path prepend [ASNUM]",
5849
      NO_STR
5850
      SET_STR
5851
      "Transform BGP AS_PATH attribute\n"
5852
      "Prepend to the as-path\n"
5853
      AS_STR)
5854
0
{
5855
0
  const char *xpath =
5856
0
    "./set-action[action='frr-bgp-route-map:as-path-prepend']";
5857
5858
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5859
0
  return nb_cli_apply_changes(vty, NULL);
5860
0
}
5861
5862
DEFUN_YANG (no_set_aspath_prepend_lastas,
5863
      no_set_aspath_prepend_lastas_cmd,
5864
      "no set as-path prepend last-as [(1-10)]",
5865
      NO_STR
5866
      SET_STR
5867
      "Transform BGP AS_PATH attribute\n"
5868
      "Prepend to the as-path\n"
5869
      "Use the peers AS-number\n"
5870
      "Number of times to insert\n")
5871
0
{
5872
0
  const char *xpath =
5873
0
    "./set-action[action='frr-bgp-route-map:as-path-prepend']";
5874
5875
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5876
0
  return nb_cli_apply_changes(vty, NULL);
5877
0
}
5878
5879
DEFUN_YANG (set_aspath_exclude,
5880
      set_aspath_exclude_cmd,
5881
      "set as-path exclude ASNUM...",
5882
      SET_STR
5883
      "Transform BGP AS-path attribute\n"
5884
      "Exclude from the as-path\n"
5885
      AS_STR)
5886
0
{
5887
0
  int idx_asn = 3;
5888
0
  int ret;
5889
0
  char *str;
5890
0
  struct aspath *aspath;
5891
5892
0
  str = argv_concat(argv, argc, idx_asn);
5893
5894
0
  const char *xpath =
5895
0
    "./set-action[action='frr-bgp-route-map:as-path-exclude']";
5896
0
  char xpath_value[XPATH_MAXLEN];
5897
5898
0
  aspath = route_aspath_compile(str);
5899
0
  if (!aspath) {
5900
0
    vty_out(vty, "%% Invalid AS path value %s\n", str);
5901
0
    return CMD_WARNING_CONFIG_FAILED;
5902
0
  }
5903
0
  route_aspath_free(aspath);
5904
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5905
0
  snprintf(xpath_value, sizeof(xpath_value),
5906
0
     "%s/rmap-set-action/frr-bgp-route-map:exclude-as-path", xpath);
5907
0
  nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, str);
5908
0
  ret = nb_cli_apply_changes(vty, NULL);
5909
0
  XFREE(MTYPE_TMP, str);
5910
0
  return ret;
5911
0
}
5912
5913
DEFUN_YANG (no_set_aspath_exclude,
5914
      no_set_aspath_exclude_cmd,
5915
      "no set as-path exclude ASNUM...",
5916
      NO_STR
5917
      SET_STR
5918
      "Transform BGP AS_PATH attribute\n"
5919
      "Exclude from the as-path\n"
5920
      "AS number\n")
5921
0
{
5922
0
  const char *xpath =
5923
0
    "./set-action[action='frr-bgp-route-map:as-path-exclude']";
5924
5925
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
5926
0
  return nb_cli_apply_changes(vty, NULL);
5927
0
}
5928
5929
ALIAS_YANG (no_set_aspath_exclude, no_set_aspath_exclude_all_cmd,
5930
            "no set as-path exclude",
5931
            NO_STR SET_STR
5932
            "Transform BGP AS_PATH attribute\n"
5933
            "Exclude from the as-path\n")
5934
5935
DEFUN_YANG (set_community,
5936
      set_community_cmd,
5937
      "set community AA:NN...",
5938
      SET_STR
5939
      "BGP community attribute\n"
5940
      COMMUNITY_VAL_STR)
5941
0
{
5942
0
  int idx_aa_nn = 2;
5943
0
  int i;
5944
0
  int first = 0;
5945
0
  int additive = 0;
5946
0
  struct buffer *b;
5947
0
  struct community *com = NULL;
5948
0
  char *str;
5949
0
  char *argstr = NULL;
5950
0
  int ret;
5951
5952
0
  const char *xpath =
5953
0
    "./set-action[action='frr-bgp-route-map:set-community']";
5954
0
  char xpath_value[XPATH_MAXLEN];
5955
5956
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
5957
0
  snprintf(xpath_value, sizeof(xpath_value),
5958
0
     "%s/rmap-set-action/frr-bgp-route-map:community-string",
5959
0
     xpath);
5960
5961
0
  b = buffer_new(1024);
5962
5963
0
  for (i = idx_aa_nn; i < argc; i++) {
5964
0
    if (strncmp(argv[i]->arg, "additive", strlen(argv[i]->arg))
5965
0
        == 0) {
5966
0
      additive = 1;
5967
0
      continue;
5968
0
    }
5969
5970
0
    if (first)
5971
0
      buffer_putc(b, ' ');
5972
0
    else
5973
0
      first = 1;
5974
5975
#if CONFDATE > 20230801
5976
CPP_NOTICE("Deprecate COMMUNITY_INTERNET BGP community")
5977
#endif
5978
0
    if (strncmp(argv[i]->arg, "internet", strlen(argv[i]->arg))
5979
0
        == 0) {
5980
0
      buffer_putstr(b, "internet");
5981
0
      vty_out(vty, "%% `internet` community is deprecated\n");
5982
0
      zlog_warn("`internet` community is deprecated");
5983
0
      continue;
5984
0
    }
5985
0
    if (strncmp(argv[i]->arg, "local-AS", strlen(argv[i]->arg))
5986
0
        == 0) {
5987
0
      buffer_putstr(b, "local-AS");
5988
0
      continue;
5989
0
    }
5990
0
    if (strncmp(argv[i]->arg, "no-a", strlen("no-a")) == 0
5991
0
        && strncmp(argv[i]->arg, "no-advertise",
5992
0
             strlen(argv[i]->arg))
5993
0
             == 0) {
5994
0
      buffer_putstr(b, "no-advertise");
5995
0
      continue;
5996
0
    }
5997
0
    if (strncmp(argv[i]->arg, "no-e", strlen("no-e")) == 0
5998
0
        && strncmp(argv[i]->arg, "no-export", strlen(argv[i]->arg))
5999
0
             == 0) {
6000
0
      buffer_putstr(b, "no-export");
6001
0
      continue;
6002
0
    }
6003
0
    if (strncmp(argv[i]->arg, "blackhole", strlen(argv[i]->arg))
6004
0
        == 0) {
6005
0
      buffer_putstr(b, "blackhole");
6006
0
      continue;
6007
0
    }
6008
0
    if (strncmp(argv[i]->arg, "graceful-shutdown",
6009
0
          strlen(argv[i]->arg))
6010
0
        == 0) {
6011
0
      buffer_putstr(b, "graceful-shutdown");
6012
0
      continue;
6013
0
    }
6014
0
    buffer_putstr(b, argv[i]->arg);
6015
0
  }
6016
0
  buffer_putc(b, '\0');
6017
6018
  /* Fetch result string then compile it to communities attribute.  */
6019
0
  str = buffer_getstr(b);
6020
0
  buffer_free(b);
6021
6022
0
  if (str)
6023
0
    com = community_str2com(str);
6024
6025
  /* Can't compile user input into communities attribute.  */
6026
0
  if (!com) {
6027
0
    vty_out(vty, "%% Malformed communities attribute '%s'\n", str);
6028
0
    XFREE(MTYPE_TMP, str);
6029
0
    return CMD_WARNING_CONFIG_FAILED;
6030
0
  }
6031
0
  XFREE(MTYPE_TMP, str);
6032
6033
  /* Set communites attribute string.  */
6034
0
  str = community_str(com, false, false);
6035
6036
0
  if (additive) {
6037
0
    size_t argstr_sz = strlen(str) + strlen(" additive") + 1;
6038
0
    argstr = XCALLOC(MTYPE_TMP, argstr_sz);
6039
0
    strlcpy(argstr, str, argstr_sz);
6040
0
    strlcat(argstr, " additive", argstr_sz);
6041
0
    nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, argstr);
6042
0
  } else
6043
0
    nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, str);
6044
6045
0
  ret = nb_cli_apply_changes(vty, NULL);
6046
6047
0
  if (argstr)
6048
0
    XFREE(MTYPE_TMP, argstr);
6049
0
  community_free(&com);
6050
6051
0
  return ret;
6052
0
}
6053
6054
DEFUN_YANG (set_community_none,
6055
      set_community_none_cmd,
6056
      "set community none",
6057
      SET_STR
6058
      "BGP community attribute\n"
6059
      "No community attribute\n")
6060
0
{
6061
0
  const char *xpath =
6062
0
    "./set-action[action='frr-bgp-route-map:set-community']";
6063
0
  char xpath_value[XPATH_MAXLEN];
6064
6065
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6066
6067
0
  snprintf(xpath_value, sizeof(xpath_value),
6068
0
     "%s/rmap-set-action/frr-bgp-route-map:community-none", xpath);
6069
0
  nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, "true");
6070
0
  return nb_cli_apply_changes(vty, NULL);
6071
0
}
6072
6073
DEFUN_YANG (no_set_community,
6074
      no_set_community_cmd,
6075
      "no set community AA:NN...",
6076
      NO_STR
6077
      SET_STR
6078
      "BGP community attribute\n"
6079
      COMMUNITY_VAL_STR)
6080
0
{
6081
0
  const char *xpath =
6082
0
    "./set-action[action='frr-bgp-route-map:set-community']";
6083
6084
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6085
0
  return nb_cli_apply_changes(vty, NULL);
6086
0
}
6087
6088
ALIAS_YANG (no_set_community,
6089
            no_set_community_short_cmd,
6090
            "no set community",
6091
            NO_STR
6092
            SET_STR
6093
            "BGP community attribute\n")
6094
6095
DEFPY_YANG (set_community_delete,
6096
       set_community_delete_cmd,
6097
       "set comm-list <(1-99)|(100-500)|COMMUNITY_LIST_NAME> delete",
6098
       SET_STR
6099
       "set BGP community list (for deletion)\n"
6100
       "Community-list number (standard)\n"
6101
       "Community-list number (expanded)\n"
6102
       "Community-list name\n"
6103
       "Delete matching communities\n")
6104
0
{
6105
0
  const char *xpath =
6106
0
    "./set-action[action='frr-bgp-route-map:comm-list-delete']";
6107
0
  char xpath_value[XPATH_MAXLEN];
6108
0
  int idx_comm_list = 2;
6109
6110
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6111
6112
0
  snprintf(xpath_value, sizeof(xpath_value),
6113
0
     "%s/rmap-set-action/frr-bgp-route-map:comm-list-name",
6114
0
     xpath);
6115
0
  nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
6116
0
      argv[idx_comm_list]->arg);
6117
6118
0
  return nb_cli_apply_changes(vty, NULL);
6119
6120
0
}
6121
6122
DEFUN_YANG (no_set_community_delete,
6123
      no_set_community_delete_cmd,
6124
      "no set comm-list [<(1-99)|(100-500)|COMMUNITY_LIST_NAME> delete]",
6125
      NO_STR
6126
      SET_STR
6127
      "set BGP community list (for deletion)\n"
6128
      "Community-list number (standard)\n"
6129
      "Community-list number (expanded)\n"
6130
      "Community-list name\n"
6131
      "Delete matching communities\n")
6132
0
{
6133
0
  const char *xpath =
6134
0
    "./set-action[action='frr-bgp-route-map:comm-list-delete']";
6135
6136
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6137
0
  return nb_cli_apply_changes(vty, NULL);
6138
0
}
6139
6140
DEFUN_YANG (set_lcommunity,
6141
      set_lcommunity_cmd,
6142
      "set large-community AA:BB:CC...",
6143
      SET_STR
6144
      "BGP large community attribute\n"
6145
      "Large Community number in aa:bb:cc format or additive\n")
6146
0
{
6147
0
  char *str;
6148
0
  int ret;
6149
0
  const char *xpath =
6150
0
    "./set-action[action='frr-bgp-route-map:set-large-community']";
6151
0
  char xpath_value[XPATH_MAXLEN];
6152
6153
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6154
6155
0
  snprintf(xpath_value, sizeof(xpath_value),
6156
0
     "%s/rmap-set-action/frr-bgp-route-map:large-community-string",
6157
0
     xpath);
6158
0
  str = argv_concat(argv, argc, 2);
6159
0
  nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, str);
6160
0
  ret = nb_cli_apply_changes(vty, NULL);
6161
0
  XFREE(MTYPE_TMP, str);
6162
0
  return ret;
6163
0
}
6164
6165
DEFUN_YANG (set_lcommunity_none,
6166
      set_lcommunity_none_cmd,
6167
      "set large-community none",
6168
      SET_STR
6169
      "BGP large community attribute\n"
6170
      "No large community attribute\n")
6171
0
{
6172
0
  const char *xpath =
6173
0
    "./set-action[action='frr-bgp-route-map:set-large-community']";
6174
0
  char xpath_value[XPATH_MAXLEN];
6175
6176
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6177
6178
0
  snprintf(xpath_value, sizeof(xpath_value),
6179
0
     "%s/rmap-set-action/frr-bgp-route-map:large-community-none",
6180
0
     xpath);
6181
0
  nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, "true");
6182
0
  return nb_cli_apply_changes(vty, NULL);
6183
0
}
6184
6185
DEFUN_YANG (no_set_lcommunity,
6186
      no_set_lcommunity_cmd,
6187
      "no set large-community none",
6188
      NO_STR
6189
      SET_STR
6190
      "BGP large community attribute\n"
6191
      "No community attribute\n")
6192
0
{
6193
0
  const char *xpath =
6194
0
    "./set-action[action='frr-bgp-route-map:set-large-community']";
6195
6196
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6197
0
  return nb_cli_apply_changes(vty, NULL);
6198
0
}
6199
6200
DEFUN_YANG (no_set_lcommunity1,
6201
      no_set_lcommunity1_cmd,
6202
      "no set large-community AA:BB:CC...",
6203
      NO_STR
6204
      SET_STR
6205
      "BGP large community attribute\n"
6206
      "Large community in AA:BB:CC... format or additive\n")
6207
0
{
6208
0
  const char *xpath =
6209
0
    "./set-action[action='frr-bgp-route-map:set-large-community']";
6210
6211
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6212
0
  return nb_cli_apply_changes(vty, NULL);
6213
0
}
6214
6215
ALIAS_YANG (no_set_lcommunity1,
6216
            no_set_lcommunity1_short_cmd,
6217
            "no set large-community",
6218
            NO_STR
6219
            SET_STR
6220
            "BGP large community attribute\n")
6221
6222
DEFPY_YANG (set_lcommunity_delete,
6223
       set_lcommunity_delete_cmd,
6224
       "set large-comm-list <(1-99)|(100-500)|LCOMMUNITY_LIST_NAME> delete",
6225
       SET_STR
6226
       "set BGP large community list (for deletion)\n"
6227
       "Large Community-list number (standard)\n"
6228
       "Large Communitly-list number (expanded)\n"
6229
       "Large Community-list name\n"
6230
       "Delete matching large communities\n")
6231
0
{
6232
0
  const char *xpath =
6233
0
    "./set-action[action='frr-bgp-route-map:large-comm-list-delete']";
6234
0
  char xpath_value[XPATH_MAXLEN];
6235
0
  int idx_lcomm_list = 2;
6236
6237
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6238
6239
0
  snprintf(xpath_value, sizeof(xpath_value),
6240
0
      "%s/rmap-set-action/frr-bgp-route-map:comm-list-name",
6241
0
      xpath);
6242
0
  nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
6243
0
      argv[idx_lcomm_list]->arg);
6244
6245
0
  return nb_cli_apply_changes(vty, NULL);
6246
0
}
6247
6248
DEFUN_YANG (no_set_lcommunity_delete,
6249
      no_set_lcommunity_delete_cmd,
6250
      "no set large-comm-list <(1-99)|(100-500)|LCOMMUNITY_LIST_NAME> [delete]",
6251
      NO_STR
6252
      SET_STR
6253
      "set BGP large community list (for deletion)\n"
6254
      "Large Community-list number (standard)\n"
6255
      "Large Communitly-list number (expanded)\n"
6256
      "Large Community-list name\n"
6257
      "Delete matching large communities\n")
6258
0
{
6259
0
  const char *xpath =
6260
0
    "./set-action[action='frr-bgp-route-map:large-comm-list-delete']";
6261
6262
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6263
0
  return nb_cli_apply_changes(vty, NULL);
6264
0
}
6265
6266
ALIAS_YANG (no_set_lcommunity_delete,
6267
            no_set_lcommunity_delete_short_cmd,
6268
            "no set large-comm-list",
6269
            NO_STR
6270
            SET_STR
6271
            "set BGP large community list (for deletion)\n")
6272
6273
DEFUN_YANG (set_ecommunity_rt,
6274
      set_ecommunity_rt_cmd,
6275
      "set extcommunity rt ASN:NN_OR_IP-ADDRESS:NN...",
6276
      SET_STR
6277
      "BGP extended community attribute\n"
6278
      "Route Target extended community\n"
6279
      "VPN extended community\n")
6280
0
{
6281
0
  int idx_asn_nn = 3;
6282
0
  char *str;
6283
0
  int ret;
6284
0
  const char *xpath =
6285
0
    "./set-action[action='frr-bgp-route-map:set-extcommunity-rt']";
6286
0
  char xpath_value[XPATH_MAXLEN];
6287
6288
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6289
6290
0
  snprintf(xpath_value, sizeof(xpath_value),
6291
0
     "%s/rmap-set-action/frr-bgp-route-map:extcommunity-rt", xpath);
6292
0
  str = argv_concat(argv, argc, idx_asn_nn);
6293
0
  nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, str);
6294
0
  ret = nb_cli_apply_changes(vty, NULL);
6295
0
  XFREE(MTYPE_TMP, str);
6296
0
  return ret;
6297
0
}
6298
6299
DEFUN_YANG (no_set_ecommunity_rt,
6300
      no_set_ecommunity_rt_cmd,
6301
      "no set extcommunity rt ASN:NN_OR_IP-ADDRESS:NN...",
6302
      NO_STR
6303
      SET_STR
6304
      "BGP extended community attribute\n"
6305
      "Route Target extended community\n"
6306
      "VPN extended community\n")
6307
0
{
6308
0
  const char *xpath =
6309
0
    "./set-action[action='frr-bgp-route-map:set-extcommunity-rt']";
6310
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6311
0
  return nb_cli_apply_changes(vty, NULL);
6312
0
}
6313
6314
ALIAS_YANG (no_set_ecommunity_rt,
6315
            no_set_ecommunity_rt_short_cmd,
6316
            "no set extcommunity rt",
6317
            NO_STR
6318
            SET_STR
6319
            "BGP extended community attribute\n"
6320
            "Route Target extended community\n")
6321
6322
DEFUN_YANG (set_ecommunity_soo,
6323
      set_ecommunity_soo_cmd,
6324
      "set extcommunity soo ASN:NN_OR_IP-ADDRESS:NN...",
6325
      SET_STR
6326
     "BGP extended community attribute\n"
6327
     "Site-of-Origin extended community\n"
6328
     "VPN extended community\n")
6329
0
{
6330
0
  int idx_asn_nn = 3;
6331
0
  char *str;
6332
0
  int ret;
6333
0
  const char *xpath =
6334
0
    "./set-action[action='frr-bgp-route-map:set-extcommunity-soo']";
6335
0
  char xpath_value[XPATH_MAXLEN];
6336
6337
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6338
6339
0
  snprintf(xpath_value, sizeof(xpath_value),
6340
0
     "%s/rmap-set-action/frr-bgp-route-map:extcommunity-soo",
6341
0
     xpath);
6342
0
  str = argv_concat(argv, argc, idx_asn_nn);
6343
0
  nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, str);
6344
0
  ret = nb_cli_apply_changes(vty, NULL);
6345
0
  XFREE(MTYPE_TMP, str);
6346
0
  return ret;
6347
0
}
6348
6349
DEFUN_YANG (no_set_ecommunity_soo,
6350
      no_set_ecommunity_soo_cmd,
6351
      "no set extcommunity soo ASN:NN_OR_IP-ADDRESS:NN...",
6352
      NO_STR
6353
      SET_STR
6354
      "BGP extended community attribute\n"
6355
      "Site-of-Origin extended community\n"
6356
      "VPN extended community\n")
6357
0
{
6358
0
  const char *xpath =
6359
0
    "./set-action[action='frr-bgp-route-map:set-extcommunity-soo']";
6360
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6361
0
  return nb_cli_apply_changes(vty, NULL);
6362
0
}
6363
6364
ALIAS_YANG (no_set_ecommunity_soo,
6365
            no_set_ecommunity_soo_short_cmd,
6366
            "no set extcommunity soo",
6367
            NO_STR
6368
            SET_STR
6369
            "GP extended community attribute\n"
6370
            "Site-of-Origin extended community\n")
6371
6372
DEFUN_YANG(set_ecommunity_none, set_ecommunity_none_cmd,
6373
     "set extcommunity none",
6374
     SET_STR
6375
     "BGP extended community attribute\n"
6376
     "No extended community attribute\n")
6377
0
{
6378
0
  const char *xpath =
6379
0
    "./set-action[action='frr-bgp-route-map:set-extcommunity-none']";
6380
0
  char xpath_value[XPATH_MAXLEN];
6381
6382
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6383
6384
0
  snprintf(xpath_value, sizeof(xpath_value),
6385
0
     "%s/rmap-set-action/frr-bgp-route-map:extcommunity-none",
6386
0
     xpath);
6387
0
  nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, "true");
6388
0
  return nb_cli_apply_changes(vty, NULL);
6389
0
}
6390
6391
DEFUN_YANG(no_set_ecommunity_none, no_set_ecommunity_none_cmd,
6392
     "no set extcommunity none",
6393
     NO_STR SET_STR
6394
     "BGP extended community attribute\n"
6395
     "No extended community attribute\n")
6396
0
{
6397
0
  const char *xpath =
6398
0
    "./set-action[action='frr-bgp-route-map:set-extcommunity-none']";
6399
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6400
0
  return nb_cli_apply_changes(vty, NULL);
6401
0
}
6402
6403
DEFUN_YANG (set_ecommunity_lb,
6404
      set_ecommunity_lb_cmd,
6405
      "set extcommunity bandwidth <(1-25600)|cumulative|num-multipaths> [non-transitive]",
6406
      SET_STR
6407
      "BGP extended community attribute\n"
6408
      "Link bandwidth extended community\n"
6409
      "Bandwidth value in Mbps\n"
6410
      "Cumulative bandwidth of all multipaths (outbound-only)\n"
6411
      "Internally computed bandwidth based on number of multipaths (outbound-only)\n"
6412
      "Attribute is set as non-transitive\n")
6413
0
{
6414
0
  int idx_lb = 3;
6415
0
  int idx_non_transitive = 0;
6416
0
  const char *xpath =
6417
0
    "./set-action[action='frr-bgp-route-map:set-extcommunity-lb']";
6418
0
  char xpath_lb_type[XPATH_MAXLEN];
6419
0
  char xpath_bandwidth[XPATH_MAXLEN];
6420
0
  char xpath_non_transitive[XPATH_MAXLEN];
6421
6422
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6423
6424
0
  snprintf(xpath_lb_type, sizeof(xpath_lb_type),
6425
0
     "%s/rmap-set-action/frr-bgp-route-map:extcommunity-lb/lb-type",
6426
0
     xpath);
6427
0
  snprintf(xpath_bandwidth, sizeof(xpath_bandwidth),
6428
0
     "%s/rmap-set-action/frr-bgp-route-map:extcommunity-lb/bandwidth",
6429
0
     xpath);
6430
0
  snprintf(xpath_non_transitive, sizeof(xpath_non_transitive),
6431
0
     "%s/rmap-set-action/frr-bgp-route-map:extcommunity-lb/two-octet-as-specific",
6432
0
     xpath);
6433
6434
0
  if ((strcmp(argv[idx_lb]->arg, "cumulative")) == 0)
6435
0
    nb_cli_enqueue_change(vty, xpath_lb_type, NB_OP_MODIFY,
6436
0
              "cumulative-bandwidth");
6437
0
  else if ((strcmp(argv[idx_lb]->arg, "num-multipaths")) == 0)
6438
0
    nb_cli_enqueue_change(vty, xpath_lb_type, NB_OP_MODIFY,
6439
0
              "computed-bandwidth");
6440
0
  else {
6441
0
    nb_cli_enqueue_change(vty, xpath_lb_type, NB_OP_MODIFY,
6442
0
              "explicit-bandwidth");
6443
0
    nb_cli_enqueue_change(vty, xpath_bandwidth, NB_OP_MODIFY,
6444
0
              argv[idx_lb]->arg);
6445
0
  }
6446
6447
0
  if (argv_find(argv, argc, "non-transitive", &idx_non_transitive))
6448
0
    nb_cli_enqueue_change(vty, xpath_non_transitive, NB_OP_MODIFY,
6449
0
              "true");
6450
0
  else
6451
0
    nb_cli_enqueue_change(vty, xpath_non_transitive, NB_OP_MODIFY,
6452
0
              "false");
6453
6454
0
  return nb_cli_apply_changes(vty, NULL);
6455
0
}
6456
6457
DEFUN_YANG (no_set_ecommunity_lb,
6458
      no_set_ecommunity_lb_cmd,
6459
      "no set extcommunity bandwidth <(1-25600)|cumulative|num-multipaths> [non-transitive]",
6460
      NO_STR
6461
      SET_STR
6462
      "BGP extended community attribute\n"
6463
      "Link bandwidth extended community\n"
6464
      "Bandwidth value in Mbps\n"
6465
      "Cumulative bandwidth of all multipaths (outbound-only)\n"
6466
      "Internally computed bandwidth based on number of multipaths (outbound-only)\n"
6467
      "Attribute is set as non-transitive\n")
6468
0
{
6469
0
  const char *xpath =
6470
0
    "./set-action[action='frr-bgp-route-map:set-extcommunity-lb']";
6471
6472
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6473
0
  return nb_cli_apply_changes(vty, NULL);
6474
0
}
6475
6476
ALIAS_YANG (no_set_ecommunity_lb,
6477
            no_set_ecommunity_lb_short_cmd,
6478
            "no set extcommunity bandwidth",
6479
            NO_STR
6480
            SET_STR
6481
            "BGP extended community attribute\n"
6482
            "Link bandwidth extended community\n")
6483
6484
DEFPY_YANG (set_ecommunity_nt,
6485
      set_ecommunity_nt_cmd,
6486
      "set extcommunity nt RTLIST...",
6487
      SET_STR
6488
      "BGP extended community attribute\n"
6489
      "Node Target extended community\n"
6490
      "Node Target ID\n")
6491
0
{
6492
0
  int idx_nt = 3;
6493
0
  char *str;
6494
0
  int ret;
6495
0
  const char *xpath =
6496
0
    "./set-action[action='frr-bgp-route-map:set-extcommunity-nt']";
6497
0
  char xpath_value[XPATH_MAXLEN];
6498
6499
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6500
6501
0
  snprintf(xpath_value, sizeof(xpath_value),
6502
0
     "%s/rmap-set-action/frr-bgp-route-map:extcommunity-nt", xpath);
6503
0
  str = argv_concat(argv, argc, idx_nt);
6504
0
  nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, str);
6505
0
  ret = nb_cli_apply_changes(vty, NULL);
6506
0
  XFREE(MTYPE_TMP, str);
6507
0
  return ret;
6508
0
}
6509
6510
DEFPY_YANG (no_set_ecommunity_nt,
6511
      no_set_ecommunity_nt_cmd,
6512
      "no set extcommunity nt RTLIST...",
6513
      NO_STR
6514
      SET_STR
6515
      "BGP extended community attribute\n"
6516
      "Node Target extended community\n"
6517
      "Node Target ID\n")
6518
0
{
6519
0
  const char *xpath =
6520
0
    "./set-action[action='frr-bgp-route-map:set-extcommunity-nt']";
6521
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6522
0
  return nb_cli_apply_changes(vty, NULL);
6523
0
}
6524
6525
ALIAS_YANG (no_set_ecommunity_nt,
6526
            no_set_ecommunity_nt_short_cmd,
6527
            "no set extcommunity nt",
6528
            NO_STR
6529
            SET_STR
6530
            "BGP extended community attribute\n"
6531
            "Node Target extended community\n")
6532
6533
DEFUN_YANG (set_origin,
6534
      set_origin_cmd,
6535
      "set origin <egp|igp|incomplete>",
6536
      SET_STR
6537
      "BGP origin code\n"
6538
      "remote EGP\n"
6539
      "local IGP\n"
6540
      "unknown heritage\n")
6541
0
{
6542
0
  int idx_origin = 2;
6543
0
  const char *origin_type;
6544
0
  const char *xpath =
6545
0
    "./set-action[action='frr-bgp-route-map:set-origin']";
6546
0
  char xpath_value[XPATH_MAXLEN];
6547
6548
0
  if (strncmp(argv[idx_origin]->arg, "igp", 2) == 0)
6549
0
    origin_type = "igp";
6550
0
  else if (strncmp(argv[idx_origin]->arg, "egp", 1) == 0)
6551
0
    origin_type = "egp";
6552
0
  else if (strncmp(argv[idx_origin]->arg, "incomplete", 2) == 0)
6553
0
    origin_type = "incomplete";
6554
0
  else {
6555
0
    vty_out(vty, "%% Invalid match origin type\n");
6556
0
    return CMD_WARNING_CONFIG_FAILED;
6557
0
  }
6558
6559
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6560
0
  snprintf(xpath_value, sizeof(xpath_value),
6561
0
     "%s/rmap-set-action/frr-bgp-route-map:origin", xpath);
6562
0
  nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, origin_type);
6563
6564
0
  return nb_cli_apply_changes(vty, NULL);
6565
0
}
6566
6567
DEFUN_YANG (no_set_origin,
6568
      no_set_origin_cmd,
6569
      "no set origin [<egp|igp|incomplete>]",
6570
      NO_STR
6571
      SET_STR
6572
      "BGP origin code\n"
6573
      "remote EGP\n"
6574
      "local IGP\n"
6575
      "unknown heritage\n")
6576
0
{
6577
0
  const char *xpath =
6578
0
    "./set-action[action='frr-bgp-route-map:set-origin']";
6579
6580
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6581
0
  return nb_cli_apply_changes(vty, NULL);
6582
0
}
6583
6584
DEFUN_YANG (set_atomic_aggregate,
6585
      set_atomic_aggregate_cmd,
6586
      "set atomic-aggregate",
6587
      SET_STR
6588
      "BGP atomic aggregate attribute\n" )
6589
0
{
6590
0
  const char *xpath =
6591
0
    "./set-action[action='frr-bgp-route-map:atomic-aggregate']";
6592
0
  char xpath_value[XPATH_MAXLEN];
6593
6594
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6595
0
  snprintf(xpath_value, sizeof(xpath_value),
6596
0
     "%s/rmap-set-action/frr-bgp-route-map:atomic-aggregate",
6597
0
     xpath);
6598
0
  nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, NULL);
6599
6600
0
  return nb_cli_apply_changes(vty, NULL);
6601
0
}
6602
6603
DEFUN_YANG (no_set_atomic_aggregate,
6604
      no_set_atomic_aggregate_cmd,
6605
      "no set atomic-aggregate",
6606
      NO_STR
6607
      SET_STR
6608
      "BGP atomic aggregate attribute\n" )
6609
0
{
6610
0
  const char *xpath =
6611
0
    "./set-action[action='frr-bgp-route-map:atomic-aggregate']";
6612
6613
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6614
0
  return nb_cli_apply_changes(vty, NULL);
6615
0
}
6616
6617
DEFPY_YANG (set_aigp_metric,
6618
      set_aigp_metric_cmd,
6619
      "set aigp-metric <igp-metric|(1-4294967295)>$aigp_metric",
6620
      SET_STR
6621
      "BGP AIGP attribute (AIGP Metric TLV)\n"
6622
      "AIGP Metric value from IGP protocol\n"
6623
      "Manual AIGP Metric value\n")
6624
0
{
6625
0
  const char *xpath =
6626
0
    "./set-action[action='frr-bgp-route-map:aigp-metric']";
6627
0
  char xpath_value[XPATH_MAXLEN];
6628
6629
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6630
0
  snprintf(xpath_value, sizeof(xpath_value),
6631
0
     "%s/rmap-set-action/frr-bgp-route-map:aigp-metric", xpath);
6632
0
  nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, aigp_metric);
6633
6634
0
  return nb_cli_apply_changes(vty, NULL);
6635
0
}
6636
6637
DEFPY_YANG (no_set_aigp_metric,
6638
      no_set_aigp_metric_cmd,
6639
      "no set aigp-metric [<igp-metric|(1-4294967295)>]",
6640
      NO_STR
6641
      SET_STR
6642
      "BGP AIGP attribute (AIGP Metric TLV)\n"
6643
      "AIGP Metric value from IGP protocol\n"
6644
      "Manual AIGP Metric value\n")
6645
0
{
6646
0
  const char *xpath =
6647
0
    "./set-action[action='frr-bgp-route-map:aigp-metric']";
6648
6649
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6650
0
  return nb_cli_apply_changes(vty, NULL);
6651
0
}
6652
6653
DEFUN_YANG (set_aggregator_as,
6654
      set_aggregator_as_cmd,
6655
      "set aggregator as ASNUM A.B.C.D",
6656
      SET_STR
6657
      "BGP aggregator attribute\n"
6658
      "AS number of aggregator\n"
6659
      AS_STR
6660
      "IP address of aggregator\n")
6661
0
{
6662
0
  int idx_number = 3;
6663
0
  int idx_ipv4 = 4;
6664
0
  char xpath_asn[XPATH_MAXLEN];
6665
0
  char xpath_addr[XPATH_MAXLEN];
6666
0
  const char *xpath =
6667
0
    "./set-action[action='frr-bgp-route-map:aggregator']";
6668
0
  as_t as_value;
6669
6670
0
  if (!asn_str2asn(argv[idx_number]->arg, &as_value)) {
6671
0
    vty_out(vty, "%% Invalid AS value %s\n", argv[idx_number]->arg);
6672
0
    return CMD_WARNING_CONFIG_FAILED;
6673
0
  }
6674
6675
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6676
6677
0
  snprintf(
6678
0
    xpath_asn, sizeof(xpath_asn),
6679
0
    "%s/rmap-set-action/frr-bgp-route-map:aggregator/aggregator-asn",
6680
0
    xpath);
6681
0
  nb_cli_enqueue_change(vty, xpath_asn, NB_OP_MODIFY,
6682
0
            argv[idx_number]->arg);
6683
6684
0
  snprintf(
6685
0
    xpath_addr, sizeof(xpath_addr),
6686
0
    "%s/rmap-set-action/frr-bgp-route-map:aggregator/aggregator-address",
6687
0
    xpath);
6688
0
  nb_cli_enqueue_change(vty, xpath_addr, NB_OP_MODIFY,
6689
0
            argv[idx_ipv4]->arg);
6690
6691
0
  return nb_cli_apply_changes(vty, NULL);
6692
0
}
6693
6694
DEFUN_YANG (no_set_aggregator_as,
6695
      no_set_aggregator_as_cmd,
6696
      "no set aggregator as [ASNUM A.B.C.D]",
6697
      NO_STR
6698
      SET_STR
6699
      "BGP aggregator attribute\n"
6700
      "AS number of aggregator\n"
6701
      AS_STR
6702
      "IP address of aggregator\n")
6703
0
{
6704
0
  const char *xpath =
6705
0
    "./set-action[action='frr-bgp-route-map:aggregator']";
6706
6707
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6708
0
  return nb_cli_apply_changes(vty, NULL);
6709
0
}
6710
6711
DEFUN_YANG (match_ipv6_next_hop,
6712
      match_ipv6_next_hop_cmd,
6713
      "match ipv6 next-hop ACCESSLIST6_NAME",
6714
      MATCH_STR
6715
      IPV6_STR
6716
      "Match IPv6 next-hop address of route\n"
6717
      "IPv6 access-list name\n")
6718
0
{
6719
0
  const char *xpath =
6720
0
    "./match-condition[condition='frr-route-map:ipv6-next-hop-list']";
6721
0
  char xpath_value[XPATH_MAXLEN];
6722
6723
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6724
0
  snprintf(xpath_value, sizeof(xpath_value),
6725
0
     "%s/rmap-match-condition/list-name", xpath);
6726
0
  nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
6727
0
            argv[argc - 1]->arg);
6728
6729
0
  return nb_cli_apply_changes(vty, NULL);
6730
0
}
6731
6732
DEFUN_YANG (no_match_ipv6_next_hop,
6733
      no_match_ipv6_next_hop_cmd,
6734
      "no match ipv6 next-hop [ACCESSLIST6_NAME]",
6735
      NO_STR
6736
      MATCH_STR
6737
      IPV6_STR
6738
      "Match IPv6 next-hop address of route\n"
6739
      "IPv6 access-list name\n")
6740
0
{
6741
0
  const char *xpath =
6742
0
    "./match-condition[condition='frr-route-map:ipv6-next-hop-list']";
6743
6744
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6745
0
  return nb_cli_apply_changes(vty, NULL);
6746
0
}
6747
6748
DEFUN_YANG (match_ipv6_next_hop_address,
6749
      match_ipv6_next_hop_address_cmd,
6750
      "match ipv6 next-hop address X:X::X:X",
6751
      MATCH_STR
6752
      IPV6_STR
6753
      "Match IPv6 next-hop address of route\n"
6754
      "IPv6 address\n"
6755
      "IPv6 address of next hop\n")
6756
0
{
6757
0
  const char *xpath =
6758
0
    "./match-condition[condition='frr-bgp-route-map:ipv6-nexthop']";
6759
0
  char xpath_value[XPATH_MAXLEN];
6760
6761
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6762
0
  snprintf(xpath_value, sizeof(xpath_value),
6763
0
     "%s/rmap-match-condition/frr-bgp-route-map:ipv6-address",
6764
0
     xpath);
6765
0
  nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
6766
0
            argv[argc - 1]->arg);
6767
6768
0
  return nb_cli_apply_changes(vty, NULL);
6769
0
}
6770
6771
DEFUN_YANG (no_match_ipv6_next_hop_address,
6772
      no_match_ipv6_next_hop_address_cmd,
6773
      "no match ipv6 next-hop address X:X::X:X",
6774
      NO_STR
6775
      MATCH_STR
6776
      IPV6_STR
6777
      "Match IPv6 next-hop address of route\n"
6778
      "IPv6 address\n"
6779
      "IPv6 address of next hop\n")
6780
0
{
6781
0
  const char *xpath =
6782
0
    "./match-condition[condition='frr-bgp-route-map:ipv6-nexthop']";
6783
6784
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6785
0
  return nb_cli_apply_changes(vty, NULL);
6786
0
}
6787
6788
ALIAS_HIDDEN (match_ipv6_next_hop_address,
6789
        match_ipv6_next_hop_old_cmd,
6790
        "match ipv6 next-hop X:X::X:X",
6791
        MATCH_STR
6792
        IPV6_STR
6793
        "Match IPv6 next-hop address of route\n"
6794
        "IPv6 address of next hop\n")
6795
6796
ALIAS_HIDDEN (no_match_ipv6_next_hop_address,
6797
        no_match_ipv6_next_hop_old_cmd,
6798
        "no match ipv6 next-hop X:X::X:X",
6799
        NO_STR
6800
        MATCH_STR
6801
        IPV6_STR
6802
        "Match IPv6 next-hop address of route\n"
6803
        "IPv6 address of next hop\n")
6804
6805
DEFUN_YANG (match_ipv6_next_hop_prefix_list,
6806
      match_ipv6_next_hop_prefix_list_cmd,
6807
      "match ipv6 next-hop prefix-list PREFIXLIST_NAME",
6808
      MATCH_STR
6809
      IPV6_STR
6810
      "Match IPv6 next-hop address of route\n"
6811
      "Match entries by prefix-list\n"
6812
      "IPv6 prefix-list name\n")
6813
0
{
6814
0
  const char *xpath =
6815
0
    "./match-condition[condition='frr-route-map:ipv6-next-hop-prefix-list']";
6816
0
  char xpath_value[XPATH_MAXLEN];
6817
6818
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6819
0
  snprintf(xpath_value, sizeof(xpath_value),
6820
0
     "%s/rmap-match-condition/list-name", xpath);
6821
0
  nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
6822
0
            argv[argc - 1]->arg);
6823
6824
0
  return nb_cli_apply_changes(vty, NULL);
6825
0
}
6826
6827
DEFUN_YANG (no_match_ipv6_next_hop_prefix_list,
6828
      no_match_ipv6_next_hop_prefix_list_cmd,
6829
      "no match ipv6 next-hop prefix-list [PREFIXLIST_NAME]",
6830
      NO_STR
6831
      MATCH_STR
6832
      IPV6_STR
6833
      "Match IPv6 next-hop address of route\n"
6834
      "Match entries by prefix-list\n"
6835
      "IPv6 prefix-list name\n")
6836
0
{
6837
0
  const char *xpath =
6838
0
    "./match-condition[condition='frr-route-map:ipv6-next-hop-prefix-list']";
6839
6840
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6841
0
  return nb_cli_apply_changes(vty, NULL);
6842
0
}
6843
6844
DEFPY_YANG (match_ipv4_next_hop,
6845
       match_ipv4_next_hop_cmd,
6846
       "match ip next-hop address A.B.C.D",
6847
       MATCH_STR
6848
       IP_STR
6849
       "Match IP next-hop address of route\n"
6850
       "IP address\n"
6851
       "IP address of next-hop\n")
6852
0
{
6853
0
  const char *xpath =
6854
0
    "./match-condition[condition='frr-bgp-route-map:ipv4-nexthop']";
6855
0
  char xpath_value[XPATH_MAXLEN];
6856
6857
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6858
0
  snprintf(xpath_value, sizeof(xpath_value),
6859
0
     "%s/rmap-match-condition/frr-bgp-route-map:ipv4-address",
6860
0
     xpath);
6861
0
  nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, argv[4]->arg);
6862
6863
0
  return nb_cli_apply_changes(vty, NULL);
6864
0
}
6865
6866
DEFPY_YANG (no_match_ipv4_next_hop,
6867
       no_match_ipv4_next_hop_cmd,
6868
       "no match ip next-hop address [A.B.C.D]",
6869
       NO_STR
6870
       MATCH_STR
6871
       IP_STR
6872
       "Match IP next-hop address of route\n"
6873
       "IP address\n"
6874
       "IP address of next-hop\n")
6875
0
{
6876
0
  const char *xpath =
6877
0
    "./match-condition[condition='frr-bgp-route-map:ipv4-nexthop']";
6878
6879
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6880
0
  return nb_cli_apply_changes(vty, NULL);
6881
0
}
6882
6883
DEFUN_YANG (set_ipv6_nexthop_peer,
6884
      set_ipv6_nexthop_peer_cmd,
6885
      "set ipv6 next-hop peer-address",
6886
      SET_STR
6887
      IPV6_STR
6888
      "Next hop address\n"
6889
      "Use peer address (for BGP only)\n")
6890
0
{
6891
0
  const char *xpath =
6892
0
    "./set-action[action='frr-bgp-route-map:ipv6-peer-address']";
6893
0
  char xpath_value[XPATH_MAXLEN];
6894
6895
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6896
0
  snprintf(xpath_value, sizeof(xpath_value),
6897
0
     "%s/rmap-set-action/frr-bgp-route-map:preference", xpath);
6898
0
  nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, "true");
6899
6900
0
  return nb_cli_apply_changes(vty, NULL);
6901
0
}
6902
6903
DEFUN_YANG (no_set_ipv6_nexthop_peer,
6904
      no_set_ipv6_nexthop_peer_cmd,
6905
      "no set ipv6 next-hop peer-address",
6906
      NO_STR
6907
      SET_STR
6908
      IPV6_STR
6909
      "IPv6 next-hop address\n"
6910
      "Use peer address (for BGP only)\n")
6911
0
{
6912
0
  const char *xpath =
6913
0
    "./set-action[action='frr-bgp-route-map:ipv6-peer-address']";
6914
6915
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6916
0
  return nb_cli_apply_changes(vty, NULL);
6917
0
}
6918
6919
DEFUN_YANG (set_ipv6_nexthop_prefer_global,
6920
      set_ipv6_nexthop_prefer_global_cmd,
6921
      "set ipv6 next-hop prefer-global",
6922
      SET_STR
6923
      IPV6_STR
6924
      "IPv6 next-hop address\n"
6925
      "Prefer global over link-local if both exist\n")
6926
0
{
6927
0
  const char *xpath =
6928
0
    "./set-action[action='frr-bgp-route-map:ipv6-prefer-global']";
6929
0
  char xpath_value[XPATH_MAXLEN];
6930
6931
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6932
0
  snprintf(xpath_value, sizeof(xpath_value),
6933
0
     "%s/rmap-set-action/frr-bgp-route-map:preference", xpath);
6934
0
  nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, "true");
6935
6936
0
  return nb_cli_apply_changes(vty, NULL);
6937
0
}
6938
6939
DEFUN_YANG (no_set_ipv6_nexthop_prefer_global,
6940
      no_set_ipv6_nexthop_prefer_global_cmd,
6941
      "no set ipv6 next-hop prefer-global",
6942
      NO_STR
6943
      SET_STR
6944
      IPV6_STR
6945
      "IPv6 next-hop address\n"
6946
      "Prefer global over link-local if both exist\n")
6947
0
{
6948
0
  const char *xpath =
6949
0
    "./set-action[action='frr-bgp-route-map:ipv6-prefer-global']";
6950
6951
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6952
0
  return nb_cli_apply_changes(vty, NULL);
6953
0
}
6954
6955
DEFUN_YANG (set_ipv6_nexthop_global,
6956
      set_ipv6_nexthop_global_cmd,
6957
      "set ipv6 next-hop global X:X::X:X",
6958
      SET_STR
6959
      IPV6_STR
6960
      "IPv6 next-hop address\n"
6961
      "IPv6 global address\n"
6962
      "IPv6 address of next hop\n")
6963
0
{
6964
0
  int idx_ipv6 = 4;
6965
0
  const char *xpath =
6966
0
    "./set-action[action='frr-bgp-route-map:ipv6-nexthop-global']";
6967
0
  char xpath_value[XPATH_MAXLEN];
6968
6969
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
6970
0
  snprintf(xpath_value, sizeof(xpath_value),
6971
0
     "%s/rmap-set-action/frr-bgp-route-map:ipv6-address", xpath);
6972
0
  nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
6973
0
            argv[idx_ipv6]->arg);
6974
6975
0
  return nb_cli_apply_changes(vty, NULL);
6976
0
}
6977
6978
DEFUN_YANG (no_set_ipv6_nexthop_global,
6979
      no_set_ipv6_nexthop_global_cmd,
6980
      "no set ipv6 next-hop global X:X::X:X",
6981
      NO_STR
6982
      SET_STR
6983
      IPV6_STR
6984
      "IPv6 next-hop address\n"
6985
      "IPv6 global address\n"
6986
      "IPv6 address of next hop\n")
6987
0
{
6988
0
  const char *xpath =
6989
0
    "./set-action[action='frr-bgp-route-map:ipv6-nexthop-global']";
6990
6991
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
6992
0
  return nb_cli_apply_changes(vty, NULL);
6993
0
}
6994
6995
#ifdef KEEP_OLD_VPN_COMMANDS
6996
DEFUN_YANG (set_vpn_nexthop,
6997
      set_vpn_nexthop_cmd,
6998
      "set <vpnv4 next-hop A.B.C.D|vpnv6 next-hop X:X::X:X>",
6999
      SET_STR
7000
      "VPNv4 information\n"
7001
      "VPN next-hop address\n"
7002
      "IP address of next hop\n"
7003
      "VPNv6 information\n"
7004
      "VPN next-hop address\n"
7005
      "IPv6 address of next hop\n")
7006
{
7007
  int idx_ip = 3;
7008
  afi_t afi;
7009
  int idx = 0;
7010
  char xpath_value[XPATH_MAXLEN];
7011
7012
  if (argv_find_and_parse_vpnvx(argv, argc, &idx, &afi)) {
7013
    if (afi == AFI_IP) {
7014
      const char *xpath =
7015
        "./set-action[action='frr-bgp-route-map:ipv4-vpn-address']";
7016
7017
      nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
7018
      snprintf(
7019
        xpath_value, sizeof(xpath_value),
7020
        "%s/rmap-set-action/frr-bgp-route-map:ipv4-address",
7021
        xpath);
7022
    } else {
7023
      const char *xpath =
7024
        "./set-action[action='frr-bgp-route-map:ipv6-vpn-address']";
7025
7026
      nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
7027
      snprintf(
7028
        xpath_value, sizeof(xpath_value),
7029
        "%s/rmap-set-action/frr-bgp-route-map:ipv6-address",
7030
        xpath);
7031
    }
7032
7033
    nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
7034
        argv[idx_ip]->arg);
7035
7036
    return nb_cli_apply_changes(vty, NULL);
7037
  }
7038
7039
  return CMD_SUCCESS;
7040
}
7041
7042
DEFUN_YANG (no_set_vpn_nexthop,
7043
     no_set_vpn_nexthop_cmd,
7044
     "no set <vpnv4 next-hop A.B.C.D|vpnv6 next-hop X:X::X:X>",
7045
     NO_STR
7046
     SET_STR
7047
     "VPNv4 information\n"
7048
     "VPN next-hop address\n"
7049
     "IP address of next hop\n"
7050
     "VPNv6 information\n"
7051
     "VPN next-hop address\n"
7052
     "IPv6 address of next hop\n")
7053
{
7054
  afi_t afi;
7055
  int idx = 0;
7056
7057
  if (argv_find_and_parse_vpnvx(argv, argc, &idx, &afi)) {
7058
    if (afi == AFI_IP) {
7059
      const char *xpath =
7060
        "./set-action[action='frr-bgp-route-map:ipv4-vpn-address']";
7061
      nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
7062
    } else {
7063
      const char *xpath =
7064
        "./set-action[action='frr-bgp-route-map:ipv6-vpn-address']";
7065
      nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
7066
    }
7067
    return nb_cli_apply_changes(vty, NULL);
7068
  }
7069
  return CMD_SUCCESS;
7070
}
7071
#endif /* KEEP_OLD_VPN_COMMANDS */
7072
7073
DEFPY_YANG (set_ipx_vpn_nexthop,
7074
      set_ipx_vpn_nexthop_cmd,
7075
      "set <ipv4|ipv6> vpn next-hop <A.B.C.D$addrv4|X:X::X:X$addrv6>",
7076
      SET_STR
7077
      "IPv4 information\n"
7078
      "IPv6 information\n"
7079
      "VPN information\n"
7080
      "VPN next-hop address\n"
7081
      "IP address of next hop\n"
7082
      "IPv6 address of next hop\n")
7083
0
{
7084
0
  int idx_ip = 4;
7085
0
  afi_t afi;
7086
0
  int idx = 0;
7087
0
  char xpath_value[XPATH_MAXLEN];
7088
7089
0
  if (argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
7090
0
    if (afi == AFI_IP) {
7091
0
      if (addrv6_str) {
7092
0
        vty_out(vty, "%% IPv4 next-hop expected\n");
7093
0
        return CMD_WARNING_CONFIG_FAILED;
7094
0
      }
7095
7096
0
      const char *xpath =
7097
0
        "./set-action[action='frr-bgp-route-map:ipv4-vpn-address']";
7098
7099
0
      nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
7100
0
      snprintf(
7101
0
        xpath_value, sizeof(xpath_value),
7102
0
        "%s/rmap-set-action/frr-bgp-route-map:ipv4-address",
7103
0
        xpath);
7104
0
    } else {
7105
0
      if (addrv4_str) {
7106
0
        vty_out(vty, "%% IPv6 next-hop expected\n");
7107
0
        return CMD_WARNING_CONFIG_FAILED;
7108
0
      }
7109
7110
0
      const char *xpath =
7111
0
        "./set-action[action='frr-bgp-route-map:ipv6-vpn-address']";
7112
7113
0
      nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
7114
0
      snprintf(
7115
0
        xpath_value, sizeof(xpath_value),
7116
0
        "%s/rmap-set-action/frr-bgp-route-map:ipv6-address",
7117
0
        xpath);
7118
0
    }
7119
0
    nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
7120
0
              argv[idx_ip]->arg);
7121
0
    return nb_cli_apply_changes(vty, NULL);
7122
0
  }
7123
0
  return CMD_SUCCESS;
7124
0
}
7125
7126
DEFUN_YANG (no_set_ipx_vpn_nexthop,
7127
      no_set_ipx_vpn_nexthop_cmd,
7128
      "no set <ipv4|ipv6> vpn next-hop [<A.B.C.D|X:X::X:X>]",
7129
      NO_STR
7130
      SET_STR
7131
      "IPv4 information\n"
7132
      "IPv6 information\n"
7133
      "VPN information\n"
7134
      "VPN next-hop address\n"
7135
      "IP address of next hop\n"
7136
      "IPv6 address of next hop\n")
7137
0
{
7138
0
  afi_t afi;
7139
0
  int idx = 0;
7140
7141
0
  if (argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
7142
0
    if (afi == AFI_IP) {
7143
0
      const char *xpath =
7144
0
        "./set-action[action='frr-bgp-route-map:ipv4-vpn-address']";
7145
0
      nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
7146
0
    } else {
7147
0
      const char *xpath =
7148
0
        "./set-action[action='frr-bgp-route-map:ipv6-vpn-address']";
7149
0
      nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
7150
0
    }
7151
0
    return nb_cli_apply_changes(vty, NULL);
7152
0
  }
7153
0
  return CMD_SUCCESS;
7154
0
}
7155
7156
DEFUN_YANG (set_originator_id,
7157
      set_originator_id_cmd,
7158
      "set originator-id A.B.C.D",
7159
      SET_STR
7160
     "BGP originator ID attribute\n"
7161
     "IP address of originator\n")
7162
0
{
7163
0
  int idx_ipv4 = 2;
7164
0
  const char *xpath =
7165
0
    "./set-action[action='frr-bgp-route-map:originator-id']";
7166
0
  char xpath_value[XPATH_MAXLEN];
7167
7168
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
7169
0
  snprintf(xpath_value, sizeof(xpath_value),
7170
0
     "%s/rmap-set-action/frr-bgp-route-map:originator-id", xpath);
7171
0
  nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
7172
0
            argv[idx_ipv4]->arg);
7173
7174
0
  return nb_cli_apply_changes(vty, NULL);
7175
0
}
7176
7177
DEFUN_YANG (no_set_originator_id,
7178
      no_set_originator_id_cmd,
7179
      "no set originator-id [A.B.C.D]",
7180
      NO_STR
7181
      SET_STR
7182
      "BGP originator ID attribute\n"
7183
      "IP address of originator\n")
7184
0
{
7185
0
  const char *xpath =
7186
0
    "./set-action[action='frr-bgp-route-map:originator-id']";
7187
7188
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
7189
0
  return nb_cli_apply_changes(vty, NULL);
7190
0
}
7191
7192
DEFPY_YANG (match_rpki_extcommunity,
7193
       match_rpki_extcommunity_cmd,
7194
       "[no$no] match rpki-extcommunity <valid|invalid|notfound>",
7195
       NO_STR
7196
       MATCH_STR
7197
       "BGP RPKI (Origin Validation State) extended community attribute\n"
7198
       "Valid prefix\n"
7199
       "Invalid prefix\n"
7200
       "Prefix not found\n")
7201
0
{
7202
0
  const char *xpath =
7203
0
    "./match-condition[condition='frr-bgp-route-map:rpki-extcommunity']";
7204
0
  char xpath_value[XPATH_MAXLEN];
7205
7206
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
7207
7208
0
  if (!no) {
7209
0
    snprintf(
7210
0
      xpath_value, sizeof(xpath_value),
7211
0
      "%s/rmap-match-condition/frr-bgp-route-map:rpki-extcommunity",
7212
0
      xpath);
7213
0
    nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
7214
0
              argv[2]->arg);
7215
0
  }
7216
7217
0
  return nb_cli_apply_changes(vty, NULL);
7218
0
}
7219
7220
DEFPY_YANG (match_source_protocol,
7221
            match_source_protocol_cmd,
7222
      "match source-protocol " FRR_REDIST_STR_ZEBRA "$proto",
7223
      MATCH_STR
7224
      "Match protocol via which the route was learnt\n"
7225
      FRR_REDIST_HELP_STR_ZEBRA)
7226
0
{
7227
0
  const char *xpath =
7228
0
    "./match-condition[condition='frr-bgp-route-map:source-protocol']";
7229
0
  char xpath_value[XPATH_MAXLEN];
7230
7231
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
7232
0
  snprintf(xpath_value, sizeof(xpath_value),
7233
0
     "%s/rmap-match-condition/frr-bgp-route-map:source-protocol",
7234
0
     xpath);
7235
0
  nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, proto);
7236
7237
0
  return nb_cli_apply_changes(vty, NULL);
7238
0
}
7239
7240
DEFPY_YANG (no_match_source_protocol,
7241
            no_match_source_protocol_cmd,
7242
      "no match source-protocol [" FRR_REDIST_STR_ZEBRA "]",
7243
      NO_STR
7244
      MATCH_STR
7245
      "Match protocol via which the route was learnt\n"
7246
      FRR_REDIST_HELP_STR_ZEBRA)
7247
0
{
7248
0
  const char *xpath =
7249
0
    "./match-condition[condition='frr-bgp-route-map:source-protocol']";
7250
7251
0
  nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
7252
7253
0
  return nb_cli_apply_changes(vty, NULL);
7254
0
}
7255
7256
/* Initialization of route map. */
7257
void bgp_route_map_init(void)
7258
1
{
7259
1
  route_map_init();
7260
7261
1
  route_map_add_hook(bgp_route_map_add);
7262
1
  route_map_delete_hook(bgp_route_map_delete);
7263
1
  route_map_event_hook(bgp_route_map_event);
7264
7265
1
  route_map_match_interface_hook(generic_match_add);
7266
1
  route_map_no_match_interface_hook(generic_match_delete);
7267
7268
1
  route_map_match_ip_address_hook(generic_match_add);
7269
1
  route_map_no_match_ip_address_hook(generic_match_delete);
7270
7271
1
  route_map_match_ip_address_prefix_list_hook(generic_match_add);
7272
1
  route_map_no_match_ip_address_prefix_list_hook(generic_match_delete);
7273
7274
1
  route_map_match_ip_next_hop_hook(generic_match_add);
7275
1
  route_map_no_match_ip_next_hop_hook(generic_match_delete);
7276
7277
1
  route_map_match_ipv6_next_hop_hook(generic_match_add);
7278
1
  route_map_no_match_ipv6_next_hop_hook(generic_match_delete);
7279
7280
1
  route_map_match_ip_next_hop_prefix_list_hook(generic_match_add);
7281
1
  route_map_no_match_ip_next_hop_prefix_list_hook(generic_match_delete);
7282
7283
1
  route_map_match_ip_next_hop_type_hook(generic_match_add);
7284
1
  route_map_no_match_ip_next_hop_type_hook(generic_match_delete);
7285
7286
1
  route_map_match_ipv6_address_hook(generic_match_add);
7287
1
  route_map_no_match_ipv6_address_hook(generic_match_delete);
7288
7289
1
  route_map_match_ipv6_address_prefix_list_hook(generic_match_add);
7290
1
  route_map_no_match_ipv6_address_prefix_list_hook(generic_match_delete);
7291
7292
1
  route_map_match_ipv6_next_hop_type_hook(generic_match_add);
7293
1
  route_map_no_match_ipv6_next_hop_type_hook(generic_match_delete);
7294
7295
1
  route_map_match_ipv6_next_hop_prefix_list_hook(generic_match_add);
7296
1
  route_map_no_match_ipv6_next_hop_prefix_list_hook(generic_match_delete);
7297
7298
1
  route_map_match_metric_hook(generic_match_add);
7299
1
  route_map_no_match_metric_hook(generic_match_delete);
7300
7301
1
  route_map_match_tag_hook(generic_match_add);
7302
1
  route_map_no_match_tag_hook(generic_match_delete);
7303
7304
1
  route_map_set_srte_color_hook(generic_set_add);
7305
1
  route_map_no_set_srte_color_hook(generic_set_delete);
7306
7307
1
  route_map_set_ip_nexthop_hook(generic_set_add);
7308
1
  route_map_no_set_ip_nexthop_hook(generic_set_delete);
7309
7310
1
  route_map_set_ipv6_nexthop_local_hook(generic_set_add);
7311
1
  route_map_no_set_ipv6_nexthop_local_hook(generic_set_delete);
7312
7313
1
  route_map_set_metric_hook(generic_set_add);
7314
1
  route_map_no_set_metric_hook(generic_set_delete);
7315
7316
1
  route_map_set_tag_hook(generic_set_add);
7317
1
  route_map_no_set_tag_hook(generic_set_delete);
7318
7319
1
  route_map_install_match(&route_match_peer_cmd);
7320
1
  route_map_install_match(&route_match_alias_cmd);
7321
1
  route_map_install_match(&route_match_local_pref_cmd);
7322
#ifdef HAVE_SCRIPTING
7323
  route_map_install_match(&route_match_script_cmd);
7324
#endif
7325
1
  route_map_install_match(&route_match_ip_address_cmd);
7326
1
  route_map_install_match(&route_match_ip_next_hop_cmd);
7327
1
  route_map_install_match(&route_match_ip_route_source_cmd);
7328
1
  route_map_install_match(&route_match_ip_address_prefix_list_cmd);
7329
1
  route_map_install_match(&route_match_ip_next_hop_prefix_list_cmd);
7330
1
  route_map_install_match(&route_match_ip_next_hop_type_cmd);
7331
1
  route_map_install_match(&route_match_source_protocol_cmd);
7332
1
  route_map_install_match(&route_match_ip_route_source_prefix_list_cmd);
7333
1
  route_map_install_match(&route_match_aspath_cmd);
7334
1
  route_map_install_match(&route_match_community_cmd);
7335
1
  route_map_install_match(&route_match_lcommunity_cmd);
7336
1
  route_map_install_match(&route_match_ecommunity_cmd);
7337
1
  route_map_install_match(&route_match_local_pref_cmd);
7338
1
  route_map_install_match(&route_match_metric_cmd);
7339
1
  route_map_install_match(&route_match_origin_cmd);
7340
1
  route_map_install_match(&route_match_probability_cmd);
7341
1
  route_map_install_match(&route_match_interface_cmd);
7342
1
  route_map_install_match(&route_match_tag_cmd);
7343
1
  route_map_install_match(&route_match_mac_address_cmd);
7344
1
  route_map_install_match(&route_match_evpn_vni_cmd);
7345
1
  route_map_install_match(&route_match_evpn_route_type_cmd);
7346
1
  route_map_install_match(&route_match_evpn_rd_cmd);
7347
1
  route_map_install_match(&route_match_evpn_default_route_cmd);
7348
1
  route_map_install_match(&route_match_vrl_source_vrf_cmd);
7349
7350
1
  route_map_install_set(&route_set_evpn_gateway_ip_ipv4_cmd);
7351
1
  route_map_install_set(&route_set_evpn_gateway_ip_ipv6_cmd);
7352
1
  route_map_install_set(&route_set_table_id_cmd);
7353
1
  route_map_install_set(&route_set_srte_color_cmd);
7354
1
  route_map_install_set(&route_set_ip_nexthop_cmd);
7355
1
  route_map_install_set(&route_set_local_pref_cmd);
7356
1
  route_map_install_set(&route_set_weight_cmd);
7357
1
  route_map_install_set(&route_set_label_index_cmd);
7358
1
  route_map_install_set(&route_set_metric_cmd);
7359
1
  route_map_install_set(&route_set_distance_cmd);
7360
1
  route_map_install_set(&route_set_aspath_prepend_cmd);
7361
1
  route_map_install_set(&route_set_aspath_exclude_cmd);
7362
1
  route_map_install_set(&route_set_aspath_replace_cmd);
7363
1
  route_map_install_set(&route_set_origin_cmd);
7364
1
  route_map_install_set(&route_set_atomic_aggregate_cmd);
7365
1
  route_map_install_set(&route_set_aigp_metric_cmd);
7366
1
  route_map_install_set(&route_set_aggregator_as_cmd);
7367
1
  route_map_install_set(&route_set_community_cmd);
7368
1
  route_map_install_set(&route_set_community_delete_cmd);
7369
1
  route_map_install_set(&route_set_lcommunity_cmd);
7370
1
  route_map_install_set(&route_set_lcommunity_delete_cmd);
7371
1
  route_map_install_set(&route_set_vpnv4_nexthop_cmd);
7372
1
  route_map_install_set(&route_set_vpnv6_nexthop_cmd);
7373
1
  route_map_install_set(&route_set_originator_id_cmd);
7374
1
  route_map_install_set(&route_set_ecommunity_rt_cmd);
7375
1
  route_map_install_set(&route_set_ecommunity_nt_cmd);
7376
1
  route_map_install_set(&route_set_ecommunity_soo_cmd);
7377
1
  route_map_install_set(&route_set_ecommunity_lb_cmd);
7378
1
  route_map_install_set(&route_set_ecommunity_none_cmd);
7379
1
  route_map_install_set(&route_set_tag_cmd);
7380
1
  route_map_install_set(&route_set_label_index_cmd);
7381
1
  route_map_install_set(&route_set_l3vpn_nexthop_encapsulation_cmd);
7382
7383
1
  install_element(RMAP_NODE, &match_peer_cmd);
7384
1
  install_element(RMAP_NODE, &match_peer_local_cmd);
7385
1
  install_element(RMAP_NODE, &no_match_peer_cmd);
7386
1
  install_element(RMAP_NODE, &match_ip_route_source_cmd);
7387
1
  install_element(RMAP_NODE, &no_match_ip_route_source_cmd);
7388
1
  install_element(RMAP_NODE, &match_ip_route_source_prefix_list_cmd);
7389
1
  install_element(RMAP_NODE, &no_match_ip_route_source_prefix_list_cmd);
7390
1
  install_element(RMAP_NODE, &match_mac_address_cmd);
7391
1
  install_element(RMAP_NODE, &no_match_mac_address_cmd);
7392
1
  install_element(RMAP_NODE, &match_evpn_vni_cmd);
7393
1
  install_element(RMAP_NODE, &no_match_evpn_vni_cmd);
7394
1
  install_element(RMAP_NODE, &match_evpn_route_type_cmd);
7395
1
  install_element(RMAP_NODE, &no_match_evpn_route_type_cmd);
7396
1
  install_element(RMAP_NODE, &match_evpn_rd_cmd);
7397
1
  install_element(RMAP_NODE, &no_match_evpn_rd_cmd);
7398
1
  install_element(RMAP_NODE, &match_evpn_default_route_cmd);
7399
1
  install_element(RMAP_NODE, &no_match_evpn_default_route_cmd);
7400
1
  install_element(RMAP_NODE, &set_evpn_gw_ip_ipv4_cmd);
7401
1
  install_element(RMAP_NODE, &no_set_evpn_gw_ip_ipv4_cmd);
7402
1
  install_element(RMAP_NODE, &set_evpn_gw_ip_ipv6_cmd);
7403
1
  install_element(RMAP_NODE, &no_set_evpn_gw_ip_ipv6_cmd);
7404
1
  install_element(RMAP_NODE, &match_vrl_source_vrf_cmd);
7405
1
  install_element(RMAP_NODE, &no_match_vrl_source_vrf_cmd);
7406
7407
1
  install_element(RMAP_NODE, &match_aspath_cmd);
7408
1
  install_element(RMAP_NODE, &no_match_aspath_cmd);
7409
1
  install_element(RMAP_NODE, &match_local_pref_cmd);
7410
1
  install_element(RMAP_NODE, &no_match_local_pref_cmd);
7411
1
  install_element(RMAP_NODE, &match_alias_cmd);
7412
1
  install_element(RMAP_NODE, &no_match_alias_cmd);
7413
1
  install_element(RMAP_NODE, &match_community_cmd);
7414
1
  install_element(RMAP_NODE, &no_match_community_cmd);
7415
1
  install_element(RMAP_NODE, &match_lcommunity_cmd);
7416
1
  install_element(RMAP_NODE, &no_match_lcommunity_cmd);
7417
1
  install_element(RMAP_NODE, &match_ecommunity_cmd);
7418
1
  install_element(RMAP_NODE, &no_match_ecommunity_cmd);
7419
1
  install_element(RMAP_NODE, &match_origin_cmd);
7420
1
  install_element(RMAP_NODE, &no_match_origin_cmd);
7421
1
  install_element(RMAP_NODE, &match_probability_cmd);
7422
1
  install_element(RMAP_NODE, &no_match_probability_cmd);
7423
7424
1
  install_element(RMAP_NODE, &no_set_table_id_cmd);
7425
1
  install_element(RMAP_NODE, &set_table_id_cmd);
7426
1
  install_element(RMAP_NODE, &set_ip_nexthop_peer_cmd);
7427
1
  install_element(RMAP_NODE, &set_ip_nexthop_unchanged_cmd);
7428
1
  install_element(RMAP_NODE, &set_local_pref_cmd);
7429
1
  install_element(RMAP_NODE, &set_distance_cmd);
7430
1
  install_element(RMAP_NODE, &no_set_distance_cmd);
7431
1
  install_element(RMAP_NODE, &no_set_local_pref_cmd);
7432
1
  install_element(RMAP_NODE, &set_weight_cmd);
7433
1
  install_element(RMAP_NODE, &set_label_index_cmd);
7434
1
  install_element(RMAP_NODE, &no_set_weight_cmd);
7435
1
  install_element(RMAP_NODE, &no_set_label_index_cmd);
7436
1
  install_element(RMAP_NODE, &set_aspath_prepend_asn_cmd);
7437
1
  install_element(RMAP_NODE, &set_aspath_prepend_lastas_cmd);
7438
1
  install_element(RMAP_NODE, &set_aspath_exclude_cmd);
7439
1
  install_element(RMAP_NODE, &set_aspath_replace_asn_cmd);
7440
1
  install_element(RMAP_NODE, &no_set_aspath_prepend_cmd);
7441
1
  install_element(RMAP_NODE, &no_set_aspath_prepend_lastas_cmd);
7442
1
  install_element(RMAP_NODE, &no_set_aspath_exclude_cmd);
7443
1
  install_element(RMAP_NODE, &no_set_aspath_exclude_all_cmd);
7444
1
  install_element(RMAP_NODE, &no_set_aspath_replace_asn_cmd);
7445
1
  install_element(RMAP_NODE, &set_origin_cmd);
7446
1
  install_element(RMAP_NODE, &no_set_origin_cmd);
7447
1
  install_element(RMAP_NODE, &set_atomic_aggregate_cmd);
7448
1
  install_element(RMAP_NODE, &no_set_atomic_aggregate_cmd);
7449
1
  install_element(RMAP_NODE, &set_aigp_metric_cmd);
7450
1
  install_element(RMAP_NODE, &no_set_aigp_metric_cmd);
7451
1
  install_element(RMAP_NODE, &set_aggregator_as_cmd);
7452
1
  install_element(RMAP_NODE, &no_set_aggregator_as_cmd);
7453
1
  install_element(RMAP_NODE, &set_community_cmd);
7454
1
  install_element(RMAP_NODE, &set_community_none_cmd);
7455
1
  install_element(RMAP_NODE, &no_set_community_cmd);
7456
1
  install_element(RMAP_NODE, &no_set_community_short_cmd);
7457
1
  install_element(RMAP_NODE, &set_community_delete_cmd);
7458
1
  install_element(RMAP_NODE, &no_set_community_delete_cmd);
7459
1
  install_element(RMAP_NODE, &set_lcommunity_cmd);
7460
1
  install_element(RMAP_NODE, &set_lcommunity_none_cmd);
7461
1
  install_element(RMAP_NODE, &no_set_lcommunity_cmd);
7462
1
  install_element(RMAP_NODE, &no_set_lcommunity1_cmd);
7463
1
  install_element(RMAP_NODE, &no_set_lcommunity1_short_cmd);
7464
1
  install_element(RMAP_NODE, &set_lcommunity_delete_cmd);
7465
1
  install_element(RMAP_NODE, &no_set_lcommunity_delete_cmd);
7466
1
  install_element(RMAP_NODE, &no_set_lcommunity_delete_short_cmd);
7467
1
  install_element(RMAP_NODE, &set_ecommunity_rt_cmd);
7468
1
  install_element(RMAP_NODE, &no_set_ecommunity_rt_cmd);
7469
1
  install_element(RMAP_NODE, &no_set_ecommunity_rt_short_cmd);
7470
1
  install_element(RMAP_NODE, &set_ecommunity_soo_cmd);
7471
1
  install_element(RMAP_NODE, &no_set_ecommunity_soo_cmd);
7472
1
  install_element(RMAP_NODE, &no_set_ecommunity_soo_short_cmd);
7473
1
  install_element(RMAP_NODE, &set_ecommunity_lb_cmd);
7474
1
  install_element(RMAP_NODE, &no_set_ecommunity_lb_cmd);
7475
1
  install_element(RMAP_NODE, &no_set_ecommunity_lb_short_cmd);
7476
1
  install_element(RMAP_NODE, &set_ecommunity_none_cmd);
7477
1
  install_element(RMAP_NODE, &no_set_ecommunity_none_cmd);
7478
1
  install_element(RMAP_NODE, &set_ecommunity_nt_cmd);
7479
1
  install_element(RMAP_NODE, &no_set_ecommunity_nt_cmd);
7480
1
  install_element(RMAP_NODE, &no_set_ecommunity_nt_short_cmd);
7481
#ifdef KEEP_OLD_VPN_COMMANDS
7482
  install_element(RMAP_NODE, &set_vpn_nexthop_cmd);
7483
  install_element(RMAP_NODE, &no_set_vpn_nexthop_cmd);
7484
#endif /* KEEP_OLD_VPN_COMMANDS */
7485
1
  install_element(RMAP_NODE, &set_ipx_vpn_nexthop_cmd);
7486
1
  install_element(RMAP_NODE, &no_set_ipx_vpn_nexthop_cmd);
7487
1
  install_element(RMAP_NODE, &set_originator_id_cmd);
7488
1
  install_element(RMAP_NODE, &no_set_originator_id_cmd);
7489
1
  install_element(RMAP_NODE, &set_l3vpn_nexthop_encapsulation_cmd);
7490
7491
1
  route_map_install_match(&route_match_ipv6_address_cmd);
7492
1
  route_map_install_match(&route_match_ipv6_next_hop_cmd);
7493
1
  route_map_install_match(&route_match_ipv6_next_hop_address_cmd);
7494
1
  route_map_install_match(&route_match_ipv6_next_hop_prefix_list_cmd);
7495
1
  route_map_install_match(&route_match_ipv4_next_hop_cmd);
7496
1
  route_map_install_match(&route_match_ipv6_address_prefix_list_cmd);
7497
1
  route_map_install_match(&route_match_ipv6_next_hop_type_cmd);
7498
1
  route_map_install_set(&route_set_ipv6_nexthop_global_cmd);
7499
1
  route_map_install_set(&route_set_ipv6_nexthop_prefer_global_cmd);
7500
1
  route_map_install_set(&route_set_ipv6_nexthop_local_cmd);
7501
1
  route_map_install_set(&route_set_ipv6_nexthop_peer_cmd);
7502
1
  route_map_install_match(&route_match_rpki_extcommunity_cmd);
7503
7504
1
  install_element(RMAP_NODE, &match_ipv6_next_hop_cmd);
7505
1
  install_element(RMAP_NODE, &match_ipv6_next_hop_address_cmd);
7506
1
  install_element(RMAP_NODE, &match_ipv6_next_hop_prefix_list_cmd);
7507
1
  install_element(RMAP_NODE, &no_match_ipv6_next_hop_cmd);
7508
1
  install_element(RMAP_NODE, &no_match_ipv6_next_hop_address_cmd);
7509
1
  install_element(RMAP_NODE, &no_match_ipv6_next_hop_prefix_list_cmd);
7510
1
  install_element(RMAP_NODE, &match_ipv6_next_hop_old_cmd);
7511
1
  install_element(RMAP_NODE, &no_match_ipv6_next_hop_old_cmd);
7512
1
  install_element(RMAP_NODE, &match_ipv4_next_hop_cmd);
7513
1
  install_element(RMAP_NODE, &no_match_ipv4_next_hop_cmd);
7514
1
  install_element(RMAP_NODE, &set_ipv6_nexthop_global_cmd);
7515
1
  install_element(RMAP_NODE, &no_set_ipv6_nexthop_global_cmd);
7516
1
  install_element(RMAP_NODE, &set_ipv6_nexthop_prefer_global_cmd);
7517
1
  install_element(RMAP_NODE, &no_set_ipv6_nexthop_prefer_global_cmd);
7518
1
  install_element(RMAP_NODE, &set_ipv6_nexthop_peer_cmd);
7519
1
  install_element(RMAP_NODE, &no_set_ipv6_nexthop_peer_cmd);
7520
1
  install_element(RMAP_NODE, &match_rpki_extcommunity_cmd);
7521
1
  install_element(RMAP_NODE, &match_source_protocol_cmd);
7522
1
  install_element(RMAP_NODE, &no_match_source_protocol_cmd);
7523
#ifdef HAVE_SCRIPTING
7524
  install_element(RMAP_NODE, &match_script_cmd);
7525
#endif
7526
1
}
7527
7528
void bgp_route_map_terminate(void)
7529
0
{
7530
  /* ToDo: Cleanup all the used memory */
7531
0
  route_map_finish();
7532
0
}