mirror_frr/lib/routemap_cli.c
Philippe Guibert 1bb550b63c bgpd: add resolution for l3vpn traffic over gre interfaces
When a route imported from l3vpn is analysed, the nexthop from default
VRF is looked up against a valid MPLS path. Generally, this is done on
backbones with a MPLS signalisation transport layer like LDP. Generally,
the BGP connection is multiple hops away. That scenario is already
working.

There is case where it is possible to run L3VPN over GRE interfaces, and
where there is no LSP path over that GRE interface: GRE is just here to
tunnel MPLS traffic. On that case, the nexthop given in the path does not
have MPLS path, but should be authorized to convey MPLS traffic provided
that the user permits it via a configuration command.

That commit introduces a new command that can be activated in route-map:
 > set l3vpn next-hop encapsulation gre

That command authorizes the nexthop tracking engine to accept paths that
o have a GRE interface as output, independently of the presence of an LSP
path or not.

A configuration example is given below. When bgp incoming vpnv4 updates
are received, the nexthop of NLRI is 192.168.0.2. Based on nexthop
tracking service from zebra, BGP knows that the output interface to reach
192.168.0.2 is r1-gre0. Because that interface is not MPLS based, but is
a GRE tunnel, then the update will be using that nexthop to be installed.

    interface r1-gre0
     ip address 192.168.0.1/24
    exit
    router bgp 65500
     bgp router-id 1.1.1.1
     neighbor 192.168.0.2 remote-as 65500
     !
     address-family ipv4 unicast
      no neighbor 192.168.0.2 activate
     exit-address-family
     !
     address-family ipv4 vpn
      neighbor 192.168.0.2 activate
      neighbor 192.168.0.2 route-map rmap in
     exit-address-family
    exit
    !
    router bgp 65500 vrf vrf1
     bgp router-id 1.1.1.1
     no bgp network import-check
     !
     address-family ipv4 unicast
      network 10.201.0.0/24
      redistribute connected
      label vpn export 101
      rd vpn export 444:1
      rt vpn both 52:100
      export vpn
      import vpn
     exit-address-family
    exit
    !
    route-map rmap permit 1
     set l3vpn next-hop encapsulation gre
    exit

Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
2022-09-05 22:26:25 +02:00

1566 lines
45 KiB
C

/*
* Route map northbound CLI implementation.
*
* Copyright (C) 2019 Network Device Education Foundation, Inc. ("NetDEF")
* Rafael Zalamena
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA.
*/
#include <zebra.h>
#include "lib/command.h"
#include "lib/northbound_cli.h"
#include "lib/routemap.h"
#ifndef VTYSH_EXTRACT_PL
#include "lib/routemap_cli_clippy.c"
#endif /* VTYSH_EXTRACT_PL */
#define ROUTE_MAP_CMD_STR \
"Create route-map or enter route-map command mode\n" \
"Route map tag\n"
#define ROUTE_MAP_OP_CMD_STR \
"Route map denies set operations\n" \
"Route map permits set operations\n"
#define ROUTE_MAP_SEQUENCE_CMD_STR \
"Sequence to insert to/delete from existing route-map entry\n"
DEFPY_YANG_NOSH(
route_map, route_map_cmd,
"route-map RMAP_NAME$name <deny|permit>$action (1-65535)$sequence",
ROUTE_MAP_CMD_STR
ROUTE_MAP_OP_CMD_STR
ROUTE_MAP_SEQUENCE_CMD_STR)
{
char xpath_action[XPATH_MAXLEN + 64];
char xpath_index[XPATH_MAXLEN + 32];
char xpath[XPATH_MAXLEN];
int rv;
snprintf(xpath, sizeof(xpath),
"/frr-route-map:lib/route-map[name='%s']", name);
nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
snprintf(xpath_index, sizeof(xpath_index), "%s/entry[sequence='%lu']",
xpath, sequence);
nb_cli_enqueue_change(vty, xpath_index, NB_OP_CREATE, NULL);
snprintf(xpath_action, sizeof(xpath_action), "%s/action", xpath_index);
nb_cli_enqueue_change(vty, xpath_action, NB_OP_MODIFY, action);
rv = nb_cli_apply_changes(vty, NULL);
if (rv == CMD_SUCCESS)
VTY_PUSH_XPATH(RMAP_NODE, xpath_index);
return rv;
}
DEFPY_YANG(
no_route_map_all, no_route_map_all_cmd,
"no route-map RMAP_NAME$name",
NO_STR
ROUTE_MAP_CMD_STR)
{
char xpath[XPATH_MAXLEN];
snprintf(xpath, sizeof(xpath),
"/frr-route-map:lib/route-map[name='%s']", name);
nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
return nb_cli_apply_changes(vty, NULL);
}
DEFPY_YANG(
no_route_map, no_route_map_cmd,
"no route-map RMAP_NAME$name <deny|permit>$action (1-65535)$sequence",
NO_STR
ROUTE_MAP_CMD_STR
ROUTE_MAP_OP_CMD_STR
ROUTE_MAP_SEQUENCE_CMD_STR)
{
char xpath[XPATH_MAXLEN];
snprintf(xpath, sizeof(xpath),
"/frr-route-map:lib/route-map[name='%s']/entry[sequence='%lu']",
name, sequence);
nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
return nb_cli_apply_changes(vty, NULL);
}
int route_map_instance_cmp(const struct lyd_node *dnode1,
const struct lyd_node *dnode2)
{
uint16_t seq1 = yang_dnode_get_uint16(dnode1, "./sequence");
uint16_t seq2 = yang_dnode_get_uint16(dnode2, "./sequence");
return seq1 - seq2;
}
void route_map_instance_show(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
const char *name = yang_dnode_get_string(dnode, "../name");
const char *action = yang_dnode_get_string(dnode, "./action");
const char *sequence = yang_dnode_get_string(dnode, "./sequence");
vty_out(vty, "route-map %s %s %s\n", name, action, sequence);
}
void route_map_instance_show_end(struct vty *vty, const struct lyd_node *dnode)
{
vty_out(vty, "exit\n");
vty_out(vty, "!\n");
}
DEFPY_YANG(
match_interface, match_interface_cmd,
"match interface IFNAME",
MATCH_STR
"Match first hop interface of route\n"
INTERFACE_STR)
{
const char *xpath =
"./match-condition[condition='frr-route-map:interface']";
char xpath_value[XPATH_MAXLEN];
nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
snprintf(xpath_value, sizeof(xpath_value),
"%s/rmap-match-condition/interface", xpath);
nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, ifname);
return nb_cli_apply_changes(vty, NULL);
}
DEFPY_YANG(
no_match_interface, no_match_interface_cmd,
"no match interface [IFNAME]",
NO_STR
MATCH_STR
"Match first hop interface of route\n"
INTERFACE_STR)
{
const char *xpath =
"./match-condition[condition='frr-route-map:interface']";
nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
return nb_cli_apply_changes(vty, NULL);
}
DEFPY_YANG(
match_ip_address, match_ip_address_cmd,
"match ip address ACCESSLIST4_NAME$name",
MATCH_STR
IP_STR
"Match address of route\n"
"IP Access-list name\n")
{
const char *xpath =
"./match-condition[condition='frr-route-map:ipv4-address-list']";
char xpath_value[XPATH_MAXLEN + 32];
nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
snprintf(xpath_value, sizeof(xpath_value),
"%s/rmap-match-condition/list-name", xpath);
nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, name);
return nb_cli_apply_changes(vty, NULL);
}
DEFPY_YANG(
no_match_ip_address, no_match_ip_address_cmd,
"no match ip address [ACCESSLIST4_NAME]",
NO_STR
MATCH_STR
IP_STR
"Match address of route\n"
"IP Access-list name\n")
{
const char *xpath =
"./match-condition[condition='frr-route-map:ipv4-address-list']";
nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
return nb_cli_apply_changes(vty, NULL);
}
DEFPY_YANG(
match_ip_address_prefix_list,
match_ip_address_prefix_list_cmd,
"match ip address prefix-list PREFIXLIST_NAME$name",
MATCH_STR
IP_STR
"Match address of route\n"
"Match entries of prefix-lists\n"
"IP prefix-list name\n")
{
const char *xpath =
"./match-condition[condition='frr-route-map:ipv4-prefix-list']";
char xpath_value[XPATH_MAXLEN];
nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
snprintf(xpath_value, sizeof(xpath_value),
"%s/rmap-match-condition/list-name", xpath);
nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, name);
return nb_cli_apply_changes(vty, NULL);
}
DEFPY_YANG(
no_match_ip_address_prefix_list, no_match_ip_address_prefix_list_cmd,
"no match ip address prefix-list [PREFIXLIST_NAME]",
NO_STR
MATCH_STR
IP_STR
"Match address of route\n"
"Match entries of prefix-lists\n"
"IP prefix-list name\n")
{
const char *xpath =
"./match-condition[condition='frr-route-map:ipv4-prefix-list']";
nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
return nb_cli_apply_changes(vty, NULL);
}
DEFPY_YANG(
match_ip_next_hop, match_ip_next_hop_cmd,
"match ip next-hop ACCESSLIST4_NAME$name",
MATCH_STR
IP_STR
"Match next-hop address of route\n"
"IP Access-list name\n")
{
const char *xpath =
"./match-condition[condition='frr-route-map:ipv4-next-hop-list']";
char xpath_value[XPATH_MAXLEN + 32];
nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
snprintf(xpath_value, sizeof(xpath_value),
"%s/rmap-match-condition/list-name", xpath);
nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, name);
return nb_cli_apply_changes(vty, NULL);
}
DEFPY_YANG(
no_match_ip_next_hop, no_match_ip_next_hop_cmd,
"no match ip next-hop [ACCESSLIST4_NAME]",
NO_STR
MATCH_STR
IP_STR
"Match address of route\n"
"IP Access-list name\n")
{
const char *xpath =
"./match-condition[condition='frr-route-map:ipv4-next-hop-list']";
nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
return nb_cli_apply_changes(vty, NULL);
}
DEFPY_YANG(
match_ip_next_hop_prefix_list,
match_ip_next_hop_prefix_list_cmd,
"match ip next-hop prefix-list PREFIXLIST_NAME$name",
MATCH_STR
IP_STR
"Match next-hop address of route\n"
"Match entries of prefix-lists\n"
"IP prefix-list name\n")
{
const char *xpath =
"./match-condition[condition='frr-route-map:ipv4-next-hop-prefix-list']";
char xpath_value[XPATH_MAXLEN];
nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
snprintf(xpath_value, sizeof(xpath_value),
"%s/rmap-match-condition/list-name", xpath);
nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, name);
return nb_cli_apply_changes(vty, NULL);
}
DEFPY_YANG(
no_match_ip_next_hop_prefix_list,
no_match_ip_next_hop_prefix_list_cmd,
"no match ip next-hop prefix-list [PREFIXLIST_NAME]",
NO_STR
MATCH_STR
IP_STR
"Match next-hop address of route\n"
"Match entries of prefix-lists\n"
"IP prefix-list name\n")
{
const char *xpath =
"./match-condition[condition='frr-route-map:ipv4-next-hop-prefix-list']";
nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
return nb_cli_apply_changes(vty, NULL);
}
DEFPY_YANG(
match_ip_next_hop_type, match_ip_next_hop_type_cmd,
"match ip next-hop type <blackhole>$type",
MATCH_STR
IP_STR
"Match next-hop address of route\n"
"Match entries by type\n"
"Blackhole\n")
{
const char *xpath =
"./match-condition[condition='frr-route-map:ipv4-next-hop-type']";
char xpath_value[XPATH_MAXLEN];
nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
snprintf(xpath_value, sizeof(xpath_value),
"%s/rmap-match-condition/ipv4-next-hop-type", xpath);
nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, type);
return nb_cli_apply_changes(vty, NULL);
}
DEFPY_YANG(
no_match_ip_next_hop_type, no_match_ip_next_hop_type_cmd,
"no match ip next-hop type [<blackhole>]",
NO_STR MATCH_STR IP_STR
"Match next-hop address of route\n"
"Match entries by type\n"
"Blackhole\n")
{
const char *xpath =
"./match-condition[condition='frr-route-map:ipv4-next-hop-type']";
nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
return nb_cli_apply_changes(vty, NULL);
}
DEFPY_YANG(
match_ipv6_address, match_ipv6_address_cmd,
"match ipv6 address ACCESSLIST6_NAME$name",
MATCH_STR
IPV6_STR
"Match IPv6 address of route\n"
"IPv6 access-list name\n")
{
const char *xpath =
"./match-condition[condition='frr-route-map:ipv6-address-list']";
char xpath_value[XPATH_MAXLEN];
nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
snprintf(xpath_value, sizeof(xpath_value),
"%s/rmap-match-condition/list-name", xpath);
nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, name);
return nb_cli_apply_changes(vty, NULL);
}
DEFPY_YANG(
no_match_ipv6_address, no_match_ipv6_address_cmd,
"no match ipv6 address [ACCESSLIST6_NAME]",
NO_STR
MATCH_STR
IPV6_STR
"Match IPv6 address of route\n"
"IPv6 access-list name\n")
{
const char *xpath =
"./match-condition[condition='frr-route-map:ipv6-address-list']";
nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
return nb_cli_apply_changes(vty, NULL);
}
DEFPY_YANG(
match_ipv6_address_prefix_list, match_ipv6_address_prefix_list_cmd,
"match ipv6 address prefix-list PREFIXLIST_NAME$name",
MATCH_STR
IPV6_STR
"Match address of route\n"
"Match entries of prefix-lists\n"
"IP prefix-list name\n")
{
const char *xpath =
"./match-condition[condition='frr-route-map:ipv6-prefix-list']";
char xpath_value[XPATH_MAXLEN];
nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
snprintf(xpath_value, sizeof(xpath_value),
"%s/rmap-match-condition/list-name", xpath);
nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, name);
return nb_cli_apply_changes(vty, NULL);
}
DEFPY_YANG(
no_match_ipv6_address_prefix_list,
no_match_ipv6_address_prefix_list_cmd,
"no match ipv6 address prefix-list [PREFIXLIST_NAME]",
NO_STR
MATCH_STR
IPV6_STR
"Match address of route\n"
"Match entries of prefix-lists\n"
"IP prefix-list name\n")
{
const char *xpath =
"./match-condition[condition='frr-route-map:ipv6-prefix-list']";
nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
return nb_cli_apply_changes(vty, NULL);
}
DEFPY_YANG(
match_ipv6_next_hop_type, match_ipv6_next_hop_type_cmd,
"match ipv6 next-hop type <blackhole>$type",
MATCH_STR IPV6_STR
"Match next-hop address of route\n"
"Match entries by type\n"
"Blackhole\n")
{
const char *xpath =
"./match-condition[condition='frr-route-map:ipv6-next-hop-type']";
char xpath_value[XPATH_MAXLEN];
nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
snprintf(xpath_value, sizeof(xpath_value),
"%s/rmap-match-condition/ipv6-next-hop-type", xpath);
nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, type);
return nb_cli_apply_changes(vty, NULL);
}
DEFPY_YANG(
no_match_ipv6_next_hop_type, no_match_ipv6_next_hop_type_cmd,
"no match ipv6 next-hop type [<blackhole>]",
NO_STR MATCH_STR IPV6_STR
"Match address of route\n"
"Match entries by type\n"
"Blackhole\n")
{
const char *xpath =
"./match-condition[condition='frr-route-map:ipv6-next-hop-type']";
nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
return nb_cli_apply_changes(vty, NULL);
}
DEFPY_YANG(
match_metric, match_metric_cmd,
"match metric (0-4294967295)$metric",
MATCH_STR
"Match metric of route\n"
"Metric value\n")
{
const char *xpath =
"./match-condition[condition='frr-route-map:match-metric']";
char xpath_value[XPATH_MAXLEN];
nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
snprintf(xpath_value, sizeof(xpath_value),
"%s/rmap-match-condition/metric", xpath);
nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, metric_str);
return nb_cli_apply_changes(vty, NULL);
}
DEFPY_YANG(
no_match_metric, no_match_metric_cmd,
"no match metric [(0-4294967295)]",
NO_STR
MATCH_STR
"Match metric of route\n"
"Metric value\n")
{
const char *xpath =
"./match-condition[condition='frr-route-map:match-metric']";
nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
return nb_cli_apply_changes(vty, NULL);
}
DEFPY_YANG(
match_tag, match_tag_cmd,
"match tag (1-4294967295)$tag",
MATCH_STR
"Match tag of route\n"
"Tag value\n")
{
const char *xpath =
"./match-condition[condition='frr-route-map:match-tag']";
char xpath_value[XPATH_MAXLEN];
nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
snprintf(xpath_value, sizeof(xpath_value),
"%s/rmap-match-condition/tag", xpath);
nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, tag_str);
return nb_cli_apply_changes(vty, NULL);
}
DEFPY_YANG(
no_match_tag, no_match_tag_cmd,
"no match tag [(1-4294967295)]",
NO_STR
MATCH_STR
"Match tag of route\n"
"Tag value\n")
{
const char *xpath =
"./match-condition[condition='frr-route-map:match-tag']";
nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
return nb_cli_apply_changes(vty, NULL);
}
void route_map_condition_show(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
const char *condition = yang_dnode_get_string(dnode, "./condition");
const struct lyd_node *ln;
const char *acl;
if (IS_MATCH_INTERFACE(condition)) {
vty_out(vty, " match interface %s\n",
yang_dnode_get_string(
dnode, "./rmap-match-condition/interface"));
} else if (IS_MATCH_IPv4_ADDRESS_LIST(condition)) {
vty_out(vty, " match ip address %s\n",
yang_dnode_get_string(
dnode, "./rmap-match-condition/list-name"));
} else if (IS_MATCH_IPv4_NEXTHOP_LIST(condition)) {
vty_out(vty, " match ip next-hop %s\n",
yang_dnode_get_string(
dnode, "./rmap-match-condition/list-name"));
} else if (IS_MATCH_IPv6_NEXTHOP_LIST(condition)) {
vty_out(vty, " match ipv6 next-hop %s\n",
yang_dnode_get_string(
dnode, "./rmap-match-condition/list-name"));
} else if (IS_MATCH_IPv4_PREFIX_LIST(condition)) {
vty_out(vty, " match ip address prefix-list %s\n",
yang_dnode_get_string(
dnode, "./rmap-match-condition/list-name"));
} else if (IS_MATCH_IPv4_NEXTHOP_PREFIX_LIST(condition)) {
vty_out(vty, " match ip next-hop prefix-list %s\n",
yang_dnode_get_string(
dnode, "./rmap-match-condition/list-name"));
} else if (IS_MATCH_IPv6_NEXTHOP_PREFIX_LIST(condition)) {
vty_out(vty, " match ipv6 next-hop prefix-list %s\n",
yang_dnode_get_string(
dnode, "./rmap-match-condition/list-name"));
} else if (IS_MATCH_IPv6_ADDRESS_LIST(condition)) {
vty_out(vty, " match ipv6 address %s\n",
yang_dnode_get_string(
dnode, "./rmap-match-condition/list-name"));
} else if (IS_MATCH_IPv6_PREFIX_LIST(condition)) {
vty_out(vty, " match ipv6 address prefix-list %s\n",
yang_dnode_get_string(
dnode, "./rmap-match-condition/list-name"));
} else if (IS_MATCH_IPv4_NEXTHOP_TYPE(condition)) {
vty_out(vty, " match ip next-hop type %s\n",
yang_dnode_get_string(
dnode,
"./rmap-match-condition/ipv4-next-hop-type"));
} else if (IS_MATCH_IPv6_NEXTHOP_TYPE(condition)) {
vty_out(vty, " match ipv6 next-hop type %s\n",
yang_dnode_get_string(
dnode,
"./rmap-match-condition/ipv6-next-hop-type"));
} else if (IS_MATCH_METRIC(condition)) {
vty_out(vty, " match metric %s\n",
yang_dnode_get_string(dnode,
"./rmap-match-condition/metric"));
} else if (IS_MATCH_TAG(condition)) {
vty_out(vty, " match tag %s\n",
yang_dnode_get_string(dnode,
"./rmap-match-condition/tag"));
} else if (IS_MATCH_IPv4_PREFIX_LEN(condition)) {
vty_out(vty, " match ip address prefix-len %s\n",
yang_dnode_get_string(
dnode,
"./rmap-match-condition/frr-zebra-route-map:ipv4-prefix-length"));
} else if (IS_MATCH_IPv6_PREFIX_LEN(condition)) {
vty_out(vty, " match ipv6 address prefix-len %s\n",
yang_dnode_get_string(
dnode,
"./rmap-match-condition/frr-zebra-route-map:ipv6-prefix-length"));
} else if (IS_MATCH_IPv4_NH_PREFIX_LEN(condition)) {
vty_out(vty, " match ip next-hop prefix-len %s\n",
yang_dnode_get_string(
dnode,
"./rmap-match-condition/frr-zebra-route-map:ipv4-prefix-length"));
} else if (IS_MATCH_SRC_PROTO(condition)) {
vty_out(vty, " match source-protocol %s\n",
yang_dnode_get_string(
dnode,
"./rmap-match-condition/frr-zebra-route-map:source-protocol"));
} else if (IS_MATCH_SRC_INSTANCE(condition)) {
vty_out(vty, " match source-instance %s\n",
yang_dnode_get_string(
dnode,
"./rmap-match-condition/frr-zebra-route-map:source-instance"));
} else if (IS_MATCH_LOCAL_PREF(condition)) {
vty_out(vty, " match local-preference %s\n",
yang_dnode_get_string(
dnode,
"./rmap-match-condition/frr-bgp-route-map:local-preference"));
} else if (IS_MATCH_ALIAS(condition)) {
vty_out(vty, " match alias %s\n",
yang_dnode_get_string(
dnode,
"./rmap-match-condition/frr-bgp-route-map:alias"));
} else if (IS_MATCH_SCRIPT(condition)) {
vty_out(vty, " match script %s\n",
yang_dnode_get_string(
dnode,
"./rmap-match-condition/frr-bgp-route-map:script"));
} else if (IS_MATCH_ORIGIN(condition)) {
vty_out(vty, " match origin %s\n",
yang_dnode_get_string(
dnode,
"./rmap-match-condition/frr-bgp-route-map:origin"));
} else if (IS_MATCH_RPKI(condition)) {
vty_out(vty, " match rpki %s\n",
yang_dnode_get_string(
dnode,
"./rmap-match-condition/frr-bgp-route-map:rpki"));
} else if (IS_MATCH_PROBABILITY(condition)) {
vty_out(vty, " match probability %s\n",
yang_dnode_get_string(
dnode,
"./rmap-match-condition/frr-bgp-route-map:probability"));
} else if (IS_MATCH_SRC_VRF(condition)) {
vty_out(vty, " match source-vrf %s\n",
yang_dnode_get_string(
dnode,
"./rmap-match-condition/frr-bgp-route-map:source-vrf"));
} else if (IS_MATCH_PEER(condition)) {
acl = NULL;
if ((ln = yang_dnode_get(
dnode,
"./rmap-match-condition/frr-bgp-route-map:peer-ipv4-address"))
!= NULL)
acl = yang_dnode_get_string(ln, NULL);
else if (
(ln = yang_dnode_get(
dnode,
"./rmap-match-condition/frr-bgp-route-map:peer-ipv6-address"))
!= NULL)
acl = yang_dnode_get_string(ln, NULL);
else if (
(ln = yang_dnode_get(
dnode,
"./rmap-match-condition/frr-bgp-route-map:peer-interface"))
!= NULL)
acl = yang_dnode_get_string(ln, NULL);
else if (yang_dnode_get(
dnode,
"./rmap-match-condition/frr-bgp-route-map:peer-local")
!= NULL)
acl = "local";
vty_out(vty, " match peer %s\n", acl);
} else if (IS_MATCH_AS_LIST(condition)) {
vty_out(vty, " match as-path %s\n",
yang_dnode_get_string(
dnode,
"./rmap-match-condition/frr-bgp-route-map:list-name"));
} else if (IS_MATCH_EVPN_ROUTE_TYPE(condition)) {
vty_out(vty, " match evpn route-type %s\n",
yang_dnode_get_string(
dnode,
"./rmap-match-condition/frr-bgp-route-map:evpn-route-type"));
} else if (IS_MATCH_EVPN_DEFAULT_ROUTE(condition)) {
vty_out(vty, " match evpn default-route\n");
} else if (IS_MATCH_EVPN_VNI(condition)) {
vty_out(vty, " match evpn vni %s\n",
yang_dnode_get_string(
dnode,
"./rmap-match-condition/frr-bgp-route-map:evpn-vni"));
} else if (IS_MATCH_EVPN_DEFAULT_ROUTE(condition)) {
vty_out(vty, " match evpn default-route %s\n",
yang_dnode_get_string(
dnode,
"./rmap-match-condition/frr-bgp-route-map:evpn-default-route"));
} else if (IS_MATCH_EVPN_RD(condition)) {
vty_out(vty, " match evpn rd %s\n",
yang_dnode_get_string(
dnode,
"./rmap-match-condition/frr-bgp-route-map:route-distinguisher"));
} else if (IS_MATCH_MAC_LIST(condition)) {
vty_out(vty, " match mac address %s\n",
yang_dnode_get_string(
dnode,
"./rmap-match-condition/frr-bgp-route-map:list-name"));
} else if (IS_MATCH_ROUTE_SRC(condition)) {
vty_out(vty, " match ip route-source %s\n",
yang_dnode_get_string(
dnode,
"./rmap-match-condition/frr-bgp-route-map:list-name"));
} else if (IS_MATCH_ROUTE_SRC_PL(condition)) {
vty_out(vty, " match ip route-source prefix-list %s\n",
yang_dnode_get_string(
dnode,
"./rmap-match-condition/frr-bgp-route-map:list-name"));
} else if (IS_MATCH_COMMUNITY(condition)) {
vty_out(vty, " match community %s",
yang_dnode_get_string(
dnode,
"./rmap-match-condition/frr-bgp-route-map:comm-list/comm-list-name"));
if (yang_dnode_get_bool(
dnode,
"./rmap-match-condition/frr-bgp-route-map:comm-list/comm-list-name-exact-match"))
vty_out(vty, " exact-match");
vty_out(vty, "\n");
} else if (IS_MATCH_LCOMMUNITY(condition)) {
vty_out(vty, " match large-community %s",
yang_dnode_get_string(
dnode,
"./rmap-match-condition/frr-bgp-route-map:comm-list/comm-list-name"));
if (yang_dnode_get_bool(
dnode,
"./rmap-match-condition/frr-bgp-route-map:comm-list/comm-list-name-exact-match"))
vty_out(vty, " exact-match");
vty_out(vty, "\n");
} else if (IS_MATCH_EXTCOMMUNITY(condition)) {
vty_out(vty, " match extcommunity %s\n",
yang_dnode_get_string(
dnode,
"./rmap-match-condition/frr-bgp-route-map:comm-list/comm-list-name"));
} else if (IS_MATCH_IPV4_NH(condition)) {
vty_out(vty, " match ip next-hop address %s\n",
yang_dnode_get_string(
dnode,
"./rmap-match-condition/frr-bgp-route-map:ipv4-address"));
} else if (IS_MATCH_IPV6_NH(condition)) {
vty_out(vty, " match ipv6 next-hop address %s\n",
yang_dnode_get_string(
dnode,
"./rmap-match-condition/frr-bgp-route-map:ipv6-address"));
}
}
DEFPY_YANG(
set_ip_nexthop, set_ip_nexthop_cmd,
"set ip next-hop A.B.C.D$addr",
SET_STR
IP_STR
"Next hop address\n"
"IP address of next hop\n")
{
const char *xpath =
"./set-action[action='frr-route-map:ipv4-next-hop']";
char xpath_value[XPATH_MAXLEN];
nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
snprintf(xpath_value, sizeof(xpath_value),
"%s/rmap-set-action/ipv4-address", xpath);
nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, addr_str);
return nb_cli_apply_changes(vty, NULL);
}
DEFPY_YANG(
no_set_ip_nexthop, no_set_ip_nexthop_cmd,
"no set ip next-hop [A.B.C.D]",
NO_STR
SET_STR
IP_STR
"Next hop address\n"
"IP address of next hop\n")
{
const char *xpath =
"./set-action[action='frr-route-map:ipv4-next-hop']";
nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
return nb_cli_apply_changes(vty, NULL);
}
DEFPY_YANG(
set_ipv6_nexthop_local, set_ipv6_nexthop_local_cmd,
"set ipv6 next-hop local X:X::X:X$addr",
SET_STR
IPV6_STR
"IPv6 next-hop address\n"
"IPv6 local address\n"
"IPv6 address of next hop\n")
{
const char *xpath =
"./set-action[action='frr-route-map:ipv6-next-hop']";
char xpath_value[XPATH_MAXLEN];
nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
snprintf(xpath_value, sizeof(xpath_value),
"%s/rmap-set-action/ipv6-address", xpath);
nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, addr_str);
return nb_cli_apply_changes(vty, NULL);
}
DEFPY_YANG(
no_set_ipv6_nexthop_local, no_set_ipv6_nexthop_local_cmd,
"no set ipv6 next-hop local [X:X::X:X]",
NO_STR
SET_STR
IPV6_STR
"IPv6 next-hop address\n"
"IPv6 local address\n"
"IPv6 address of next hop\n")
{
const char *xpath =
"./set-action[action='frr-route-map:ipv6-next-hop']";
nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
return nb_cli_apply_changes(vty, NULL);
}
DEFPY_YANG(
set_metric, set_metric_cmd,
"set metric <(-4294967295-4294967295)$metric|rtt$rtt|+rtt$artt|-rtt$srtt>",
SET_STR
"Metric value for destination routing protocol\n"
"Metric value (use +/- for additions or subtractions)\n"
"Assign round trip time\n"
"Add round trip time\n"
"Subtract round trip time\n")
{
const char *xpath = "./set-action[action='frr-route-map:set-metric']";
char xpath_value[XPATH_MAXLEN];
char value[64];
nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
if (rtt) {
snprintf(xpath_value, sizeof(xpath_value),
"%s/rmap-set-action/use-round-trip-time", xpath);
snprintf(value, sizeof(value), "true");
} else if (artt) {
snprintf(xpath_value, sizeof(xpath_value),
"%s/rmap-set-action/add-round-trip-time", xpath);
snprintf(value, sizeof(value), "true");
} else if (srtt) {
snprintf(xpath_value, sizeof(xpath_value),
"%s/rmap-set-action/subtract-round-trip-time", xpath);
snprintf(value, sizeof(value), "true");
} else if (metric_str && metric_str[0] == '+') {
snprintf(xpath_value, sizeof(xpath_value),
"%s/rmap-set-action/add-metric", xpath);
snprintf(value, sizeof(value), "%s", ++metric_str);
} else if (metric_str && metric_str[0] == '-') {
snprintf(xpath_value, sizeof(xpath_value),
"%s/rmap-set-action/subtract-metric", xpath);
snprintf(value, sizeof(value), "%s", ++metric_str);
} else {
snprintf(xpath_value, sizeof(xpath_value),
"%s/rmap-set-action/value", xpath);
snprintf(value, sizeof(value), "%s", metric_str);
}
nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, value);
return nb_cli_apply_changes(vty, NULL);
}
DEFPY_YANG(
no_set_metric, no_set_metric_cmd,
"no set metric [OPTVAL]",
NO_STR
SET_STR
"Metric value for destination routing protocol\n"
"Metric value\n")
{
const char *xpath = "./set-action[action='frr-route-map:set-metric']";
nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
return nb_cli_apply_changes(vty, NULL);
}
DEFPY_YANG(
set_tag, set_tag_cmd,
"set tag (1-4294967295)$tag",
SET_STR
"Tag value for routing protocol\n"
"Tag value\n")
{
const char *xpath = "./set-action[action='frr-route-map:set-tag']";
char xpath_value[XPATH_MAXLEN];
nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
snprintf(xpath_value, sizeof(xpath_value), "%s/rmap-set-action/tag",
xpath);
nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, tag_str);
return nb_cli_apply_changes(vty, NULL);
}
DEFPY_YANG(
no_set_tag, no_set_tag_cmd,
"no set tag [(1-4294967295)]",
NO_STR
SET_STR
"Tag value for routing protocol\n"
"Tag value\n")
{
const char *xpath = "./set-action[action='frr-route-map:set-tag']";
nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
return nb_cli_apply_changes(vty, NULL);
}
DEFUN_YANG (set_srte_color,
set_srte_color_cmd,
"set sr-te color (1-4294967295)",
SET_STR
SRTE_STR
SRTE_COLOR_STR
"Color of the SR-TE Policies to match with\n")
{
const char *xpath =
"./set-action[action='frr-route-map:set-sr-te-color']";
char xpath_value[XPATH_MAXLEN];
int idx = 0;
char *arg = argv_find(argv, argc, "(1-4294967295)", &idx)
? argv[idx]->arg
: NULL;
nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
snprintf(xpath_value, sizeof(xpath_value),
"%s/rmap-set-action/policy", xpath);
nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, arg);
return nb_cli_apply_changes(vty, NULL);
}
DEFUN_YANG (no_set_srte_color,
no_set_srte_color_cmd,
"no set sr-te color [(1-4294967295)]",
NO_STR
SET_STR
SRTE_STR
SRTE_COLOR_STR
"Color of the SR-TE Policies to match with\n")
{
const char *xpath =
"./set-action[action='frr-route-map:set-sr-te-color']";
nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
return nb_cli_apply_changes(vty, NULL);
}
void route_map_action_show(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
const char *action = yang_dnode_get_string(dnode, "./action");
const struct lyd_node *ln;
const char *acl;
if (IS_SET_IPv4_NH(action)) {
vty_out(vty, " set ip next-hop %s\n",
yang_dnode_get_string(
dnode, "./rmap-set-action/ipv4-address"));
} else if (IS_SET_IPv6_NH(action)) {
vty_out(vty, " set ipv6 next-hop local %s\n",
yang_dnode_get_string(
dnode, "./rmap-set-action/ipv6-address"));
} else if (IS_SET_METRIC(action)) {
if (yang_dnode_get(dnode,
"./rmap-set-action/use-round-trip-time")) {
vty_out(vty, " set metric rtt\n");
} else if (yang_dnode_get(
dnode,
"./rmap-set-action/add-round-trip-time")) {
vty_out(vty, " set metric +rtt\n");
} else if (
yang_dnode_get(
dnode,
"./rmap-set-action/subtract-round-trip-time")) {
vty_out(vty, " set metric -rtt\n");
} else if (yang_dnode_get(dnode,
"./rmap-set-action/add-metric")) {
vty_out(vty, " set metric +%s\n",
yang_dnode_get_string(
dnode, "./rmap-set-action/add-metric"));
} else if (yang_dnode_get(
dnode,
"./rmap-set-action/subtract-metric")) {
vty_out(vty, " set metric -%s\n",
yang_dnode_get_string(
dnode,
"./rmap-set-action/subtract-metric"));
} else {
vty_out(vty, " set metric %s\n",
yang_dnode_get_string(
dnode, "./rmap-set-action/value"));
}
} else if (IS_SET_TAG(action)) {
vty_out(vty, " set tag %s\n",
yang_dnode_get_string(dnode, "./rmap-set-action/tag"));
} else if (IS_SET_SR_TE_COLOR(action)) {
vty_out(vty, " set sr-te color %s\n",
yang_dnode_get_string(dnode,
"./rmap-set-action/policy"));
} else if (IS_SET_SRC(action)) {
if (yang_dnode_exists(
dnode,
"./rmap-set-action/frr-zebra-route-map:ipv4-src-address"))
vty_out(vty, " set src %s\n",
yang_dnode_get_string(
dnode,
"./rmap-set-action/frr-zebra-route-map:ipv4-src-address"));
else
vty_out(vty, " set src %s\n",
yang_dnode_get_string(
dnode,
"./rmap-set-action/frr-zebra-route-map:ipv6-src-address"));
} else if (IS_SET_METRIC_TYPE(action)) {
vty_out(vty, " set metric-type %s\n",
yang_dnode_get_string(
dnode,
"./rmap-set-action/frr-ospf-route-map:metric-type"));
} else if (IS_SET_FORWARDING_ADDR(action)) {
vty_out(vty, " set forwarding-address %s\n",
yang_dnode_get_string(
dnode,
"./rmap-set-action/frr-ospf6-route-map:ipv6-address"));
} else if (IS_SET_WEIGHT(action)) {
vty_out(vty, " set weight %s\n",
yang_dnode_get_string(
dnode,
"./rmap-set-action/frr-bgp-route-map:weight"));
} else if (IS_SET_TABLE(action)) {
vty_out(vty, " set table %s\n",
yang_dnode_get_string(
dnode,
"./rmap-set-action/frr-bgp-route-map:table"));
} else if (IS_SET_LOCAL_PREF(action)) {
vty_out(vty, " set local-preference %s\n",
yang_dnode_get_string(
dnode,
"./rmap-set-action/frr-bgp-route-map:local-pref"));
} else if (IS_SET_LABEL_INDEX(action)) {
vty_out(vty, " set label-index %s\n",
yang_dnode_get_string(
dnode,
"./rmap-set-action/frr-bgp-route-map:label-index"));
} else if (IS_SET_DISTANCE(action)) {
vty_out(vty, " set distance %s\n",
yang_dnode_get_string(
dnode,
"./rmap-set-action/frr-bgp-route-map:distance"));
} else if (IS_SET_ORIGIN(action)) {
vty_out(vty, " set origin %s\n",
yang_dnode_get_string(
dnode,
"./rmap-set-action/frr-bgp-route-map:origin"));
} else if (IS_SET_ATOMIC_AGGREGATE(action)) {
vty_out(vty, " set atomic-aggregate\n");
} else if (IS_SET_ORIGINATOR_ID(action)) {
vty_out(vty, " set originator-id %s\n",
yang_dnode_get_string(
dnode,
"./rmap-set-action/frr-bgp-route-map:originator-id"));
} else if (IS_SET_COMM_LIST_DEL(action)) {
acl = NULL;
if ((ln = yang_dnode_get(
dnode,
"./rmap-set-action/frr-bgp-route-map:comm-list-name"))
!= NULL)
acl = yang_dnode_get_string(ln, NULL);
assert(acl);
vty_out(vty, " set comm-list %s delete\n", acl);
} else if (IS_SET_LCOMM_LIST_DEL(action)) {
acl = NULL;
if ((ln = yang_dnode_get(
dnode,
"./rmap-set-action/frr-bgp-route-map:comm-list-name"))
!= NULL)
acl = yang_dnode_get_string(ln, NULL);
assert(acl);
vty_out(vty, " set large-comm-list %s delete\n", acl);
} else if (IS_SET_LCOMMUNITY(action)) {
if (yang_dnode_exists(
dnode,
"./rmap-set-action/frr-bgp-route-map:large-community-string"))
vty_out(vty, " set large-community %s\n",
yang_dnode_get_string(
dnode,
"./rmap-set-action/frr-bgp-route-map:large-community-string"));
else {
if (true
== yang_dnode_get_bool(
dnode,
"./rmap-set-action/frr-bgp-route-map:large-community-none"))
vty_out(vty, " set large-community none\n");
}
} else if (IS_SET_COMMUNITY(action)) {
if (yang_dnode_exists(
dnode,
"./rmap-set-action/frr-bgp-route-map:community-string"))
vty_out(vty, " set community %s\n",
yang_dnode_get_string(
dnode,
"./rmap-set-action/frr-bgp-route-map:community-string"));
else {
if (true
== yang_dnode_get_bool(
dnode,
"./rmap-set-action/frr-bgp-route-map:community-none"))
vty_out(vty, " set community none\n");
}
} else if (IS_SET_EXTCOMMUNITY_RT(action)) {
vty_out(vty, " set extcommunity rt %s\n",
yang_dnode_get_string(
dnode,
"./rmap-set-action/frr-bgp-route-map:extcommunity-rt"));
} else if (IS_SET_EXTCOMMUNITY_SOO(action)) {
vty_out(vty, " set extcommunity soo %s\n",
yang_dnode_get_string(
dnode,
"./rmap-set-action/frr-bgp-route-map:extcommunity-soo"));
} else if (IS_SET_EXTCOMMUNITY_LB(action)) {
enum ecommunity_lb_type lb_type;
char str[VTY_BUFSIZ];
uint16_t bandwidth;
lb_type = yang_dnode_get_enum(
dnode,
"./rmap-set-action/frr-bgp-route-map:extcommunity-lb/lb-type");
switch (lb_type) {
case EXPLICIT_BANDWIDTH:
bandwidth = yang_dnode_get_uint16(
dnode,
"./rmap-set-action/frr-bgp-route-map:extcommunity-lb/bandwidth");
snprintf(str, sizeof(str), "%d", bandwidth);
break;
case CUMULATIVE_BANDWIDTH:
snprintf(str, sizeof(str), "%s", "cumulative");
break;
case COMPUTED_BANDWIDTH:
snprintf(str, sizeof(str), "%s", "num-multipaths");
}
if (yang_dnode_get_bool(
dnode,
"./rmap-set-action/frr-bgp-route-map:extcommunity-lb/two-octet-as-specific"))
strlcat(str, " non-transitive", sizeof(str));
vty_out(vty, " set extcommunity bandwidth %s\n", str);
} else if (IS_SET_EXTCOMMUNITY_NONE(action)) {
if (yang_dnode_get_bool(
dnode,
"./rmap-set-action/frr-bgp-route-map:extcommunity-none"))
vty_out(vty, " set extcommunity none\n");
} else if (IS_SET_AGGREGATOR(action)) {
vty_out(vty, " set aggregator as %s %s\n",
yang_dnode_get_string(
dnode,
"./rmap-set-action/frr-bgp-route-map:aggregator/aggregator-asn"),
yang_dnode_get_string(
dnode,
"./rmap-set-action/frr-bgp-route-map:aggregator/aggregator-address"));
} else if (IS_SET_AS_EXCLUDE(action)) {
vty_out(vty, " set as-path exclude %s\n",
yang_dnode_get_string(
dnode,
"./rmap-set-action/frr-bgp-route-map:exclude-as-path"));
} else if (IS_SET_AS_REPLACE(action)) {
vty_out(vty, " set as-path replace %s\n",
yang_dnode_get_string(
dnode,
"./rmap-set-action/frr-bgp-route-map:replace-as-path"));
} else if (IS_SET_AS_PREPEND(action)) {
if (yang_dnode_exists(
dnode,
"./rmap-set-action/frr-bgp-route-map:prepend-as-path"))
vty_out(vty, " set as-path prepend %s\n",
yang_dnode_get_string(
dnode,
"./rmap-set-action/frr-bgp-route-map:prepend-as-path"));
else {
vty_out(vty, " set as-path prepend last-as %u\n",
yang_dnode_get_uint8(
dnode,
"./rmap-set-action/frr-bgp-route-map:last-as"));
}
} else if (IS_SET_IPV6_NH_GLOBAL(action)) {
vty_out(vty, " set ipv6 next-hop global %s\n",
yang_dnode_get_string(
dnode,
"./rmap-set-action/frr-bgp-route-map:ipv6-address"));
} else if (IS_SET_IPV6_VPN_NH(action)) {
vty_out(vty, " set ipv6 vpn next-hop %s\n",
yang_dnode_get_string(
dnode,
"./rmap-set-action/frr-bgp-route-map:ipv6-address"));
} else if (IS_SET_IPV6_PEER_ADDR(action)) {
if (true
== yang_dnode_get_bool(
dnode,
"./rmap-set-action/frr-bgp-route-map:preference"))
vty_out(vty, " set ipv6 next-hop peer-address\n");
} else if (IS_SET_IPV6_PREFER_GLOBAL(action)) {
if (true
== yang_dnode_get_bool(
dnode,
"./rmap-set-action/frr-bgp-route-map:preference"))
vty_out(vty, " set ipv6 next-hop prefer-global\n");
} else if (IS_SET_IPV4_VPN_NH(action)) {
vty_out(vty, " set ipv4 vpn next-hop %s\n",
yang_dnode_get_string(
dnode,
"./rmap-set-action/frr-bgp-route-map:ipv4-address"));
} else if (IS_SET_BGP_IPV4_NH(action)) {
vty_out(vty, " set ip next-hop %s\n",
yang_dnode_get_string(
dnode,
"./rmap-set-action/frr-bgp-route-map:ipv4-nexthop"));
} else if (IS_SET_BGP_EVPN_GATEWAY_IP_IPV4(action)) {
vty_out(vty, " set evpn gateway-ip ipv4 %s\n",
yang_dnode_get_string(
dnode,
"./rmap-set-action/frr-bgp-route-map:evpn-gateway-ip-ipv4"));
} else if (IS_SET_BGP_EVPN_GATEWAY_IP_IPV6(action)) {
vty_out(vty, " set evpn gateway-ip ipv6 %s\n",
yang_dnode_get_string(
dnode,
"./rmap-set-action/frr-bgp-route-map:evpn-gateway-ip-ipv6"));
} else if (IS_SET_BGP_L3VPN_NEXTHOP_ENCAPSULATION(action)) {
vty_out(vty, " set l3vpn next-hop encapsulation %s\n",
yang_dnode_get_string(
dnode,
"./rmap-set-action/frr-bgp-route-map:l3vpn-nexthop-encapsulation"));
}
}
DEFPY_YANG(
rmap_onmatch_next, rmap_onmatch_next_cmd,
"on-match next",
"Exit policy on matches\n"
"Next clause\n")
{
nb_cli_enqueue_change(vty, "./exit-policy", NB_OP_MODIFY, "next");
return nb_cli_apply_changes(vty, NULL);
}
DEFPY_YANG(
no_rmap_onmatch_next,
no_rmap_onmatch_next_cmd,
"no on-match next",
NO_STR
"Exit policy on matches\n"
"Next clause\n")
{
nb_cli_enqueue_change(vty, "./exit-policy", NB_OP_DESTROY, NULL);
return nb_cli_apply_changes(vty, NULL);
}
DEFPY_YANG(
rmap_onmatch_goto, rmap_onmatch_goto_cmd,
"on-match goto (1-65535)$rm_num",
"Exit policy on matches\n"
"Goto Clause number\n"
"Number\n")
{
nb_cli_enqueue_change(vty, "./exit-policy", NB_OP_MODIFY, "goto");
nb_cli_enqueue_change(vty, "./goto-value", NB_OP_MODIFY, rm_num_str);
return nb_cli_apply_changes(vty, NULL);
}
DEFPY_YANG(
no_rmap_onmatch_goto, no_rmap_onmatch_goto_cmd,
"no on-match goto",
NO_STR
"Exit policy on matches\n"
"Goto Clause number\n")
{
nb_cli_enqueue_change(vty, "./exit-policy", NB_OP_DESTROY, NULL);
return nb_cli_apply_changes(vty, NULL);
}
/* Cisco/GNU Zebra compatibility aliases */
ALIAS_YANG(
rmap_onmatch_goto, rmap_continue_cmd,
"continue (1-65535)$rm_num",
"Continue on a different entry within the route-map\n"
"Route-map entry sequence number\n")
ALIAS_YANG(
no_rmap_onmatch_goto, no_rmap_continue_cmd,
"no continue [(1-65535)]",
NO_STR
"Continue on a different entry within the route-map\n"
"Route-map entry sequence number\n")
void route_map_exit_policy_show(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
int exit_policy = yang_dnode_get_enum(dnode, NULL);
switch (exit_policy) {
case 0: /* permit-or-deny */
/* NOTHING: default option. */
break;
case 1: /* next */
vty_out(vty, " on-match next\n");
break;
case 2: /* goto */
vty_out(vty, " on-match goto %s\n",
yang_dnode_get_string(dnode, "../goto-value"));
break;
}
}
DEFPY_YANG(
rmap_call, rmap_call_cmd,
"call WORD$name",
"Jump to another Route-Map after match+set\n"
"Target route-map name\n")
{
nb_cli_enqueue_change(vty, "./call", NB_OP_MODIFY, name);
return nb_cli_apply_changes(vty, NULL);
}
DEFPY_YANG(
no_rmap_call, no_rmap_call_cmd,
"no call [NAME]",
NO_STR
"Jump to another Route-Map after match+set\n"
"Target route-map name\n")
{
nb_cli_enqueue_change(vty, "./call", NB_OP_DESTROY, NULL);
return nb_cli_apply_changes(vty, NULL);
}
void route_map_call_show(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
vty_out(vty, " call %s\n", yang_dnode_get_string(dnode, NULL));
}
DEFPY_YANG(
rmap_description, rmap_description_cmd,
"description LINE...",
"Route-map comment\n"
"Comment describing this route-map rule\n")
{
char *desc;
int rv;
desc = argv_concat(argv, argc, 1);
nb_cli_enqueue_change(vty, "./description", NB_OP_MODIFY, desc);
rv = nb_cli_apply_changes(vty, NULL);
XFREE(MTYPE_TMP, desc);
return rv;
}
DEFUN_YANG (no_rmap_description,
no_rmap_description_cmd,
"no description",
NO_STR
"Route-map comment\n")
{
nb_cli_enqueue_change(vty, "./description", NB_OP_DESTROY, NULL);
return nb_cli_apply_changes(vty, NULL);
}
void route_map_description_show(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults)
{
vty_out(vty, " description %s\n", yang_dnode_get_string(dnode, NULL));
}
DEFPY_YANG(
route_map_optimization, route_map_optimization_cmd,
"[no] route-map RMAP_NAME$name optimization",
NO_STR
ROUTE_MAP_CMD_STR
"Configure route-map optimization\n")
{
char xpath[XPATH_MAXLEN];
snprintf(xpath, sizeof(xpath),
"/frr-route-map:lib/route-map[name='%s']", name);
nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
snprintf(
xpath, sizeof(xpath),
"/frr-route-map:lib/route-map[name='%s']/optimization-disabled",
name);
nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, no ? "true" : "false");
return nb_cli_apply_changes(vty, NULL);
}
void route_map_optimization_disabled_show(struct vty *vty,
const struct lyd_node *dnode,
bool show_defaults)
{
const char *name = yang_dnode_get_string(dnode, "../name");
const bool disabled = yang_dnode_get_bool(dnode, NULL);
vty_out(vty, "%sroute-map %s optimization\n", disabled ? "no " : "",
name);
}
static int route_map_config_write(struct vty *vty)
{
const struct lyd_node *dnode;
int written = 0;
dnode = yang_dnode_get(running_config->dnode,
"/frr-route-map:lib");
if (dnode) {
nb_cli_show_dnode_cmds(vty, dnode, false);
written = 1;
}
return written;
}
/* Route map node structure. */
static int route_map_config_write(struct vty *vty);
static struct cmd_node rmap_node = {
.name = "routemap",
.node = RMAP_NODE,
.parent_node = CONFIG_NODE,
.prompt = "%s(config-route-map)# ",
.config_write = route_map_config_write,
};
static void rmap_autocomplete(vector comps, struct cmd_token *token)
{
struct route_map *map;
for (map = route_map_master.head; map; map = map->next)
vector_set(comps, XSTRDUP(MTYPE_COMPLETION, map->name));
}
static const struct cmd_variable_handler rmap_var_handlers[] = {
{.varname = "route_map", .completions = rmap_autocomplete},
{.tokenname = "ROUTEMAP_NAME", .completions = rmap_autocomplete},
{.tokenname = "RMAP_NAME", .completions = rmap_autocomplete},
{.completions = NULL}
};
void route_map_cli_init(void)
{
/* Auto complete handler. */
cmd_variable_handler_register(rmap_var_handlers);
/* CLI commands. */
install_node(&rmap_node);
install_default(RMAP_NODE);
install_element(CONFIG_NODE, &route_map_cmd);
install_element(CONFIG_NODE, &no_route_map_cmd);
install_element(CONFIG_NODE, &no_route_map_all_cmd);
install_element(CONFIG_NODE, &route_map_optimization_cmd);
/* Install the on-match stuff */
install_element(RMAP_NODE, &rmap_onmatch_next_cmd);
install_element(RMAP_NODE, &no_rmap_onmatch_next_cmd);
install_element(RMAP_NODE, &rmap_onmatch_goto_cmd);
install_element(RMAP_NODE, &no_rmap_onmatch_goto_cmd);
install_element(RMAP_NODE, &rmap_continue_cmd);
install_element(RMAP_NODE, &no_rmap_continue_cmd);
/* Install the call stuff. */
install_element(RMAP_NODE, &rmap_call_cmd);
install_element(RMAP_NODE, &no_rmap_call_cmd);
/* Install description commands. */
install_element(RMAP_NODE, &rmap_description_cmd);
install_element(RMAP_NODE, &no_rmap_description_cmd);
/* Install 'match' commands. */
install_element(RMAP_NODE, &match_interface_cmd);
install_element(RMAP_NODE, &no_match_interface_cmd);
install_element(RMAP_NODE, &match_ip_address_cmd);
install_element(RMAP_NODE, &no_match_ip_address_cmd);
install_element(RMAP_NODE, &match_ip_address_prefix_list_cmd);
install_element(RMAP_NODE, &no_match_ip_address_prefix_list_cmd);
install_element(RMAP_NODE, &match_ip_next_hop_cmd);
install_element(RMAP_NODE, &no_match_ip_next_hop_cmd);
install_element(RMAP_NODE, &match_ip_next_hop_prefix_list_cmd);
install_element(RMAP_NODE, &no_match_ip_next_hop_prefix_list_cmd);
install_element(RMAP_NODE, &match_ip_next_hop_type_cmd);
install_element(RMAP_NODE, &no_match_ip_next_hop_type_cmd);
install_element(RMAP_NODE, &match_ipv6_address_cmd);
install_element(RMAP_NODE, &no_match_ipv6_address_cmd);
install_element(RMAP_NODE, &match_ipv6_address_prefix_list_cmd);
install_element(RMAP_NODE, &no_match_ipv6_address_prefix_list_cmd);
install_element(RMAP_NODE, &match_ipv6_next_hop_type_cmd);
install_element(RMAP_NODE, &no_match_ipv6_next_hop_type_cmd);
install_element(RMAP_NODE, &match_metric_cmd);
install_element(RMAP_NODE, &no_match_metric_cmd);
install_element(RMAP_NODE, &match_tag_cmd);
install_element(RMAP_NODE, &no_match_tag_cmd);
/* Install 'set' commands. */
install_element(RMAP_NODE, &set_ip_nexthop_cmd);
install_element(RMAP_NODE, &no_set_ip_nexthop_cmd);
install_element(RMAP_NODE, &set_ipv6_nexthop_local_cmd);
install_element(RMAP_NODE, &no_set_ipv6_nexthop_local_cmd);
install_element(RMAP_NODE, &set_metric_cmd);
install_element(RMAP_NODE, &no_set_metric_cmd);
install_element(RMAP_NODE, &set_tag_cmd);
install_element(RMAP_NODE, &no_set_tag_cmd);
install_element(RMAP_NODE, &set_srte_color_cmd);
install_element(RMAP_NODE, &no_set_srte_color_cmd);
}