Merge pull request #5183 from opensourcerouting/zebra-route-map-nb

yang/zebra: migrate route map to northbound
This commit is contained in:
Quentin Young 2020-03-31 14:21:20 -04:00 committed by GitHub
commit e0bf2057b4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 2531 additions and 295 deletions

View File

@ -148,6 +148,12 @@ void route_map_instance_show(struct vty *vty, struct lyd_node *dnode,
SKIP_RULE("ipv6 next-hop type");
SKIP_RULE("metric");
SKIP_RULE("tag");
/* Zebra specific match conditions. */
SKIP_RULE("ip address prefix-len");
SKIP_RULE("ipv6 address prefix-len");
SKIP_RULE("ip next-hop prefix-len");
SKIP_RULE("source-protocol");
SKIP_RULE("source-instance");
vty_out(vty, " match %s %s\n", rmr->cmd->str,
rmr->rule_str ? rmr->rule_str : "");
@ -158,6 +164,8 @@ void route_map_instance_show(struct vty *vty, struct lyd_node *dnode,
/* Skip all sets implemented by northbound. */
SKIP_RULE("metric");
SKIP_RULE("tag");
/* Zebra specific set actions. */
SKIP_RULE("src");
vty_out(vty, " set %s %s\n", rmr->cmd->str,
rmr->rule_str ? rmr->rule_str : "");
@ -666,8 +674,25 @@ void route_map_condition_show(struct vty *vty, struct lyd_node *dnode,
vty_out(vty, " match tag %s\n",
yang_dnode_get_string(dnode, "./tag"));
break;
case 100:
/* NOTHING: custom field, should be handled by daemon. */
case 100: /* ipv4-prefix-length */
vty_out(vty, " match ip address prefix-len %s\n",
yang_dnode_get_string(dnode,"./frr-zebra:ipv4-prefix-length"));
break;
case 101: /* ipv6-prefix-length */
vty_out(vty, " match ipv6 address prefix-len %s\n",
yang_dnode_get_string(dnode, "./frr-zebra:ipv6-prefix-length"));
break;
case 102: /* ipv4-next-hop-prefix-length */
vty_out(vty, " match ip next-hop prefix-len %s\n",
yang_dnode_get_string(dnode, "./frr-zebra:ipv4-prefix-length"));
break;
case 103: /* source-protocol */
vty_out(vty, " match source-protocol %s\n",
yang_dnode_get_string(dnode, "./frr-zebra:source-protocol"));
break;
case 104: /* source-instance */
vty_out(vty, " match source-instance %s\n",
yang_dnode_get_string(dnode, "./frr-zebra:source-instance"));
break;
}
}
@ -868,8 +893,13 @@ void route_map_action_show(struct vty *vty, struct lyd_node *dnode,
vty_out(vty, " set tag %s\n",
yang_dnode_get_string(dnode, "./tag"));
break;
case 100:
/* NOTHING: custom field, should be handled by daemon. */
case 100: /* source */
if (yang_dnode_exists(dnode, "./frr-zebra:source-v4"))
vty_out(vty, " set src %s\n",
yang_dnode_get_string(dnode, "./frr-zebra:source-v4"));
else
vty_out(vty, " set src %s\n",
yang_dnode_get_string(dnode, "./frr-zebra:source-v6"));
break;
}
}

View File

@ -179,17 +179,27 @@ module frr-route-map {
description "Match a route tag";
value 10;
}
/*
* Protocol YANG models should augment the parent node to
* contain the routing protocol specific value. The protocol
* must also augment `condition-value` to include its specific
* values or expand the `when` statement on the existing cases.
*/
enum routing-protocol-specific {
description "Match a routing protocol specific type";
/* zebra specific conditions. */
enum ipv4-prefix-length {
description "Match IPv4 prefix length";
value 100;
}
enum ipv6-prefix-length {
description "Match IPv6 prefix length";
value 101;
}
enum ipv4-next-hop-prefix-length {
description "Match next-hop prefix length";
value 102;
}
enum source-protocol {
description "Match source protocol";
value 103;
}
enum source-instance {
description "Match source protocol instance";
value 104;
}
}
}
@ -291,15 +301,9 @@ module frr-route-map {
description "Set tag";
value 3;
}
/*
* Protocol YANG models should augment the parent node to
* contain the routing protocol specific value. The protocol
* must also augment `action-value` to include its specific
* values or expand the `when` statement on the existing cases.
*/
enum routing-protocol-specific {
description "Set a routing protocol specific action";
/* zebra specific conditions. */
enum source {
description "Set source address for route";
value 100;
}
}

View File

@ -106,4 +106,12 @@ module frr-route-types {
}
}
}
typedef frr-route-types {
description "Route types as enumerated in `lib/route_types.txt`";
type union {
type frr-route-types-v4;
type frr-route-types-v6;
}
}
}

View File

@ -11,6 +11,10 @@ module frr-zebra {
prefix inet;
}
import frr-route-map {
prefix frr-route-map;
}
import frr-route-types {
prefix frr-route-types;
}
@ -1985,4 +1989,63 @@ module frr-zebra {
}
// End interface model augmentation
augment "/frr-route-map:lib"
+ "/frr-route-map:route-map"
+ "/frr-route-map:entry"
+ "/frr-route-map:match-condition"
+ "/frr-route-map:condition-value" {
case ipv4-prefix-length {
when "./condition = 'ipv4-prefix-length' or
./condition = 'ipv4-next-hop-prefix-length'";
leaf ipv4-prefix-length {
type uint8 {
range "0..32";
}
}
}
case ipv6-prefix-length {
when "./condition = 'ipv6-prefix-length'";
leaf ipv6-prefix-length {
type uint8 {
range "0..128";
}
}
}
case source-protocol {
when "./condition = 'source-protocol'";
leaf source-protocol {
type frr-route-types:frr-route-types;
}
}
case source-instance {
when "./condition = 'source-instance'";
leaf source-instance {
type uint8 {
range "0..255";
}
}
}
}
augment "/frr-route-map:lib"
+ "/frr-route-map:route-map"
+ "/frr-route-map:entry"
+ "/frr-route-map:set-action"
+ "/frr-route-map:action-value" {
case source-v4 {
when "./action = 'source'";
leaf source-v4 {
description "IPv4 address";
type inet:ipv4-address;
}
}
case source-v6 {
when "./action = 'source'";
leaf source-v6 {
description "IPv6 address";
type inet:ipv6-address;
}
}
}
}

View File

@ -21,10 +21,12 @@ EXTRA_DIST += yang/embedmodel.py
dist_yangmodels_DATA += yang/frr-filter.yang
dist_yangmodels_DATA += yang/frr-module-translator.yang
dist_yangmodels_DATA += yang/frr-nexthop.yang
dist_yangmodels_DATA += yang/frr-test-module.yang
dist_yangmodels_DATA += yang/frr-interface.yang
dist_yangmodels_DATA += yang/frr-route-map.yang
dist_yangmodels_DATA += yang/frr-route-types.yang
dist_yangmodels_DATA += yang/frr-zebra.yang
dist_yangmodels_DATA += yang/ietf/ietf-routing-types.yang
if BFDD

View File

@ -245,6 +245,7 @@ struct quagga_signal_t zebra_signals[] = {
static const struct frr_yang_module_info *const zebra_yang_modules[] = {
&frr_interface_info,
&frr_route_map_info,
&frr_zebra_info,
};
FRR_DAEMON_INFO(

View File

@ -75,6 +75,7 @@ zebra_zebra_SOURCES = \
zebra/zebra_mlag.c \
zebra/zebra_mlag_vty.c \
zebra/zebra_l2.c \
zebra/zebra_northbound.c \
zebra/zebra_memory.c \
zebra/zebra_dplane.c \
zebra/zebra_mpls.c \
@ -191,5 +192,10 @@ zebra_zebra_fpm_la_SOURCES += zebra/zebra_fpm_dt.c
endif
endif
nodist_zebra_zebra_SOURCES = \
yang/frr-nexthop.yang.c \
yang/frr-zebra.yang.c \
# end
zebra_zebra_cumulus_mlag_la_SOURCES = zebra/zebra_mlag_private.c
zebra_zebra_cumulus_mlag_la_LDFLAGS = -avoid-version -module -shared -export-dynamic

2212
zebra/zebra_northbound.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -30,6 +30,8 @@
#include "filter.h"
#include "plist.h"
#include "nexthop.h"
#include "northbound_cli.h"
#include "route_types.h"
#include "vrf.h"
#include "frrstr.h"
@ -58,82 +60,6 @@ struct nh_rmap_obj {
static void zebra_route_map_set_delay_timer(uint32_t value);
/* Add zebra route map rule */
static int zebra_route_match_add(struct vty *vty, const char *command,
const char *arg, route_map_event_t type)
{
VTY_DECLVAR_CONTEXT(route_map_index, index);
enum rmap_compile_rets ret;
int retval = CMD_SUCCESS;
ret = route_map_add_match(index, command, arg, type);
switch (ret) {
case RMAP_RULE_MISSING:
vty_out(vty, "%% Zebra Can't find rule.\n");
retval = CMD_WARNING_CONFIG_FAILED;
break;
case RMAP_COMPILE_ERROR:
vty_out(vty, "%% Zebra Argument is malformed.\n");
retval = CMD_WARNING_CONFIG_FAILED;
break;
case RMAP_COMPILE_SUCCESS:
/*
* Nothing to do here
*/
break;
}
return retval;
}
/* Delete zebra route map rule. */
static int zebra_route_match_delete(struct vty *vty, const char *command,
const char *arg, route_map_event_t type)
{
VTY_DECLVAR_CONTEXT(route_map_index, index);
enum rmap_compile_rets ret;
int retval = CMD_SUCCESS;
char *dep_name = NULL;
const char *tmpstr;
char *rmap_name = NULL;
if (type != RMAP_EVENT_MATCH_DELETED) {
/* ignore the mundane, the types without any dependency */
if (arg == NULL) {
if ((tmpstr = route_map_get_match_arg(index, command))
!= NULL)
dep_name =
XSTRDUP(MTYPE_ROUTE_MAP_RULE, tmpstr);
} else {
dep_name = XSTRDUP(MTYPE_ROUTE_MAP_RULE, arg);
}
rmap_name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, index->map->name);
}
ret = route_map_delete_match(index, command, arg, type);
switch (ret) {
case RMAP_RULE_MISSING:
vty_out(vty, "%% Zebra Can't find rule.\n");
retval = CMD_WARNING_CONFIG_FAILED;
break;
case RMAP_COMPILE_ERROR:
vty_out(vty, "%% Zebra Argument is malformed.\n");
retval = CMD_WARNING_CONFIG_FAILED;
break;
case RMAP_COMPILE_SUCCESS:
/*
* Nothing to do here
*/
break;
}
XFREE(MTYPE_ROUTE_MAP_RULE, dep_name);
XFREE(MTYPE_ROUTE_MAP_NAME, rmap_name);
return retval;
}
/* 'match tag TAG'
* Match function return 1 if match is success else return 0
*/
@ -425,246 +351,227 @@ static int ip_nht_rm_del(struct zebra_vrf *zvrf, const char *rmap, int rtype,
return CMD_SUCCESS;
}
DEFUN (match_ip_address_prefix_len,
match_ip_address_prefix_len_cmd,
"match ip address prefix-len (0-32)",
MATCH_STR
IP_STR
"Match prefix length of ip address\n"
"Match prefix length of ip address\n"
"Prefix length\n")
DEFPY(
match_ip_address_prefix_len, match_ip_address_prefix_len_cmd,
"match ip address prefix-len (0-32)$length",
MATCH_STR
IP_STR
"Match prefix length of IP address\n"
"Match prefix length of IP address\n"
"Prefix length\n")
{
return zebra_route_match_add(vty, "ip address prefix-len", argv[4]->arg,
RMAP_EVENT_MATCH_ADDED);
const char *xpath = "./match-condition[condition='ipv4-prefix-length']";
char xpath_value[XPATH_MAXLEN];
nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
snprintf(xpath_value, sizeof(xpath_value),
"%s/frr-zebra:ipv4-prefix-length", xpath);
nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, length_str);
return nb_cli_apply_changes(vty, NULL);
}
DEFUN (no_match_ip_address_prefix_len,
no_match_ip_address_prefix_len_cmd,
"no match ip address prefix-len [(0-32)]",
NO_STR
MATCH_STR
IP_STR
"Match prefix length of ip address\n"
"Match prefix length of ip address\n"
"Prefix length\n")
DEFPY(
no_match_ip_address_prefix_len, no_match_ip_address_prefix_len_cmd,
"no match ip address prefix-len [(0-32)]",
NO_STR
MATCH_STR
IP_STR
"Match prefix length of IP address\n"
"Match prefix length of IP address\n"
"Prefix length\n")
{
char *plen = (argc == 6) ? argv[5]->arg : NULL;
return zebra_route_match_delete(vty, "ip address prefix-len", plen,
RMAP_EVENT_MATCH_DELETED);
const char *xpath = "./match-condition[condition='ipv4-prefix-length']";
nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
return nb_cli_apply_changes(vty, NULL);
}
DEFUN (match_ipv6_address_prefix_len,
match_ipv6_address_prefix_len_cmd,
"match ipv6 address prefix-len (0-128)",
MATCH_STR
IPV6_STR
"Match prefix length of ipv6 address\n"
"Match prefix length of ipv6 address\n"
"Prefix length\n")
DEFPY(
match_ipv6_address_prefix_len, match_ipv6_address_prefix_len_cmd,
"match ipv6 address prefix-len (0-128)$length",
MATCH_STR
IPV6_STR
"Match prefix length of IPv6 address\n"
"Match prefix length of IPv6 address\n"
"Prefix length\n")
{
return zebra_route_match_add(vty, "ipv6 address prefix-len",
argv[4]->arg, RMAP_EVENT_MATCH_ADDED);
const char *xpath = "./match-condition[condition='ipv6-prefix-length']";
char xpath_value[XPATH_MAXLEN];
nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
snprintf(xpath_value, sizeof(xpath_value),
"%s/frr-zebra:ipv6-prefix-length", xpath);
nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, length_str);
return nb_cli_apply_changes(vty, NULL);
}
DEFUN (no_match_ipv6_address_prefix_len,
no_match_ipv6_address_prefix_len_cmd,
"no match ipv6 address prefix-len [(0-128)]",
NO_STR
MATCH_STR
IPV6_STR
"Match prefix length of ip address\n"
"Match prefix length of ip address\n"
"Prefix length\n")
DEFPY(
no_match_ipv6_address_prefix_len, no_match_ipv6_address_prefix_len_cmd,
"no match ipv6 address prefix-len [(0-128)]",
NO_STR
MATCH_STR
IPV6_STR
"Match prefix length of IPv6 address\n"
"Match prefix length of IPv6 address\n"
"Prefix length\n")
{
char *plen = (argc == 6) ? argv[5]->arg : NULL;
return zebra_route_match_delete(vty, "ipv6 address prefix-len", plen,
RMAP_EVENT_MATCH_DELETED);
const char *xpath = "./match-condition[condition='ipv6-prefix-length']";
nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
return nb_cli_apply_changes(vty, NULL);
}
DEFUN (match_ip_nexthop_prefix_len,
match_ip_nexthop_prefix_len_cmd,
"match ip next-hop prefix-len (0-32)",
MATCH_STR
IP_STR
"Match prefixlen of nexthop ip address\n"
"Match prefixlen of given nexthop\n"
"Prefix length\n")
DEFPY(
match_ip_nexthop_prefix_len, match_ip_nexthop_prefix_len_cmd,
"match ip next-hop prefix-len (0-32)$length",
MATCH_STR
IP_STR
"Match prefixlen of nexthop IP address\n"
"Match prefixlen of given nexthop\n"
"Prefix length\n")
{
return zebra_route_match_add(vty, "ip next-hop prefix-len",
argv[4]->arg, RMAP_EVENT_MATCH_ADDED);
const char *xpath =
"./match-condition[condition='ipv4-next-hop-prefix-length']";
char xpath_value[XPATH_MAXLEN];
nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
snprintf(xpath_value, sizeof(xpath_value),
"%s/frr-zebra:ipv4-prefix-length", xpath);
nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, length_str);
return nb_cli_apply_changes(vty, NULL);
}
DEFUN (no_match_ip_nexthop_prefix_len,
no_match_ip_nexthop_prefix_len_cmd,
"no match ip next-hop prefix-len [(0-32)]",
NO_STR
MATCH_STR
IP_STR
"Match prefixlen of nexthop ip address\n"
"Match prefix length of nexthop\n"
"Prefix length\n")
DEFPY(
no_match_ip_nexthop_prefix_len, no_match_ip_nexthop_prefix_len_cmd,
"no match ip next-hop prefix-len [(0-32)]",
NO_STR
MATCH_STR
IP_STR
"Match prefixlen of nexthop IP address\n"
"Match prefix length of nexthop\n"
"Prefix length\n")
{
char *plen = (argc == 6) ? argv[5]->arg : NULL;
return zebra_route_match_delete(vty, "ip next-hop prefix-len", plen,
RMAP_EVENT_MATCH_DELETED);
const char *xpath =
"./match-condition[condition='ipv4-next-hop-prefix-length']";
nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
return nb_cli_apply_changes(vty, NULL);
}
DEFUN (match_source_protocol,
match_source_protocol_cmd,
"match source-protocol <bgp|ospf|rip|ripng|isis|ospf6|pim|nhrp|eigrp|babel|connected|system|kernel|static|sharp>",
MATCH_STR
"Match protocol via which the route was learnt\n"
"BGP protocol\n"
"OSPF protocol\n"
"RIP protocol\n"
"RIPNG protocol\n"
"ISIS protocol\n"
"OSPF6 protocol\n"
"PIM protocol\n"
"NHRP protocol\n"
"EIGRP protocol\n"
"BABEL protocol\n"
"Routes from directly connected peer\n"
"Routes from system configuration\n"
"Routes from kernel\n"
"Statically configured routes\n"
"SHARP process\n")
DEFPY(
match_source_protocol, match_source_protocol_cmd,
"match source-protocol " FRR_REDIST_STR_ZEBRA "$proto",
MATCH_STR
"Match protocol via which the route was learnt\n"
FRR_REDIST_HELP_STR_ZEBRA)
{
char *proto = argv[2]->text;
int i;
const char *xpath = "./match-condition[condition='source-protocol']";
char xpath_value[XPATH_MAXLEN];
i = proto_name2num(proto);
if (i < 0) {
vty_out(vty, "invalid protocol name \"%s\"\n", proto);
return CMD_WARNING_CONFIG_FAILED;
}
return zebra_route_match_add(vty, "source-protocol", proto,
RMAP_EVENT_MATCH_ADDED);
nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
snprintf(xpath_value, sizeof(xpath_value),
"%s/frr-zebra:source-protocol", xpath);
nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, proto);
return nb_cli_apply_changes(vty, NULL);
}
DEFUN (no_match_source_protocol,
no_match_source_protocol_cmd,
"no match source-protocol [<bgp|ospf|rip|ripng|isis|ospf6|pim|nhrp|eigrp|babel|connected|system|kernel|static|sharp>]",
NO_STR
MATCH_STR
"No match protocol via which the route was learnt\n"
"BGP protocol\n"
"OSPF protocol\n"
"RIP protocol\n"
"RIPNG protocol\n"
"ISIS protocol\n"
"OSPF6 protocol\n"
"PIM protocol\n"
"NHRP protocol\n"
"EIGRP protocol\n"
"BABEL protocol\n"
"Routes from directly connected peer\n"
"Routes from system configuration\n"
"Routes from kernel\n"
"Statically configured routes\n"
"SHARP process\n")
DEFPY(
no_match_source_protocol, no_match_source_protocol_cmd,
"no match source-protocol [" FRR_REDIST_STR_ZEBRA "]",
NO_STR
MATCH_STR
"Match protocol via which the route was learnt\n"
FRR_REDIST_HELP_STR_ZEBRA)
{
char *proto = (argc == 4) ? argv[3]->text : NULL;
return zebra_route_match_delete(vty, "source-protocol", proto,
RMAP_EVENT_MATCH_DELETED);
const char *xpath = "./match-condition[condition='source-protocol']";
nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
return nb_cli_apply_changes(vty, NULL);
}
DEFUN (match_source_instance,
match_source_instance_cmd,
"match source-instance (0-255)",
MATCH_STR
"Match the protocol's instance number\n"
"The instance number\n")
DEFPY(
match_source_instance, match_source_instance_cmd,
"match source-instance (0-255)$instance",
MATCH_STR
"Match the protocol's instance number\n"
"The instance number\n")
{
char *instance = argv[2]->arg;
const char *xpath = "./match-condition[condition='source-instance']";
char xpath_value[XPATH_MAXLEN];
return zebra_route_match_add(vty, "source-instance", instance,
RMAP_EVENT_MATCH_ADDED);
nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
snprintf(xpath_value, sizeof(xpath_value),
"%s/frr-zebra:source-instance", xpath);
nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, instance_str);
return nb_cli_apply_changes(vty, NULL);
}
DEFUN (no_match_source_instance,
no_match_source_instance_cmd,
"no match source-instance [(0-255)]",
NO_STR MATCH_STR
"Match the protocol's instance number\n"
"The instance number\n")
DEFPY(
no_match_source_instance, no_match_source_instance_cmd,
"no match source-instance [(0-255)]",
NO_STR MATCH_STR
"Match the protocol's instance number\n"
"The instance number\n")
{
char *instance = (argc == 4) ? argv[3]->arg : NULL;
const char *xpath = "./match-condition[condition='source-instance']";
return zebra_route_match_delete(vty, "source-instance", instance,
RMAP_EVENT_MATCH_ADDED);
nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
return nb_cli_apply_changes(vty, NULL);
}
/* set functions */
DEFUN (set_src,
set_src_cmd,
"set src <A.B.C.D|X:X::X:X>",
SET_STR
"src address for route\n"
"IPv4 src address\n"
"IPv6 src address\n")
DEFPY(
set_src, set_src_cmd,
"set src <A.B.C.D$addrv4|X:X::X:X$addrv6>",
SET_STR
"src address for route\n"
"IPv4 src address\n"
"IPv6 src address\n")
{
int idx_ip = 2;
union g_addr src;
struct interface *pif = NULL;
int family;
struct prefix p;
struct vrf *vrf;
const char *xpath = "./set-action[action='source']";
char xpath_value[XPATH_MAXLEN];
if (inet_pton(AF_INET, argv[idx_ip]->arg, &src.ipv4) != 1) {
if (inet_pton(AF_INET6, argv[idx_ip]->arg, &src.ipv6) != 1) {
vty_out(vty, "%% not a valid IPv4/v6 address\n");
return CMD_WARNING_CONFIG_FAILED;
}
p.family = family = AF_INET6;
p.u.prefix6 = src.ipv6;
p.prefixlen = IPV6_MAX_BITLEN;
nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
if (addrv4_str) {
snprintf(xpath_value, sizeof(xpath_value),
"%s/frr-zebra:source-v4", xpath);
nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
addrv4_str);
} else {
p.family = family = AF_INET;
p.u.prefix4 = src.ipv4;
p.prefixlen = IPV4_MAX_BITLEN;
snprintf(xpath_value, sizeof(xpath_value),
"%s/frr-zebra:source-v6", xpath);
nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
addrv6_str);
}
if (!zebra_check_addr(&p)) {
vty_out(vty, "%% not a valid source IPv4/v6 address\n");
return CMD_WARNING_CONFIG_FAILED;
}
RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) {
if (family == AF_INET)
pif = if_lookup_exact_address((void *)&src.ipv4,
AF_INET, vrf->vrf_id);
else if (family == AF_INET6)
pif = if_lookup_exact_address((void *)&src.ipv6,
AF_INET6, vrf->vrf_id);
if (pif != NULL)
break;
}
if (!pif) {
vty_out(vty, "%% not a local address\n");
return CMD_WARNING_CONFIG_FAILED;
}
VTY_DECLVAR_CONTEXT(route_map_index, index);
return generic_set_add(vty, index, "src", argv[idx_ip]->arg);
return nb_cli_apply_changes(vty, NULL);
}
DEFUN (no_set_src,
no_set_src_cmd,
"no set src [<A.B.C.D|X:X::X:X>]",
NO_STR
SET_STR
"Source address for route\n"
"IPv4 address\n"
"IPv6 address\n")
DEFPY(
no_set_src, no_set_src_cmd,
"no set src [<A.B.C.D|X:X::X:X>]",
NO_STR
SET_STR
"Source address for route\n"
"IPv4 address\n"
"IPv6 address\n")
{
char *ip = (argc == 4) ? argv[3]->arg : NULL;
VTY_DECLVAR_CONTEXT(route_map_index, index);
return generic_set_delete(vty, index, "src", ip);
const char *xpath = "./set-action[action='source']";
nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
return nb_cli_apply_changes(vty, NULL);
}
DEFUN (zebra_route_map_timer,

View File

@ -218,6 +218,9 @@ extern void multicast_mode_ipv4_set(enum multicast_mode mode);
extern enum multicast_mode multicast_mode_ipv4_get(void);
/* zebra_northbound.c */
extern const struct frr_yang_module_info frr_zebra_info;
#ifdef __cplusplus
}
#endif