mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-13 22:57:45 +00:00
Merge pull request #9676 from donaldsharp/import_register
This commit is contained in:
commit
c5726f0314
@ -664,7 +664,7 @@ void bgp_nht_interface_events(struct peer *peer)
|
||||
void bgp_parse_nexthop_update(int command, vrf_id_t vrf_id)
|
||||
{
|
||||
struct bgp_nexthop_cache_head *tree = NULL;
|
||||
struct bgp_nexthop_cache *bnc;
|
||||
struct bgp_nexthop_cache *bnc_nhc, *bnc_import;
|
||||
struct bgp *bgp;
|
||||
struct zapi_route nhr;
|
||||
afi_t afi;
|
||||
@ -685,22 +685,38 @@ void bgp_parse_nexthop_update(int command, vrf_id_t vrf_id)
|
||||
}
|
||||
|
||||
afi = family2afi(nhr.prefix.family);
|
||||
if (command == ZEBRA_NEXTHOP_UPDATE)
|
||||
tree = &bgp->nexthop_cache_table[afi];
|
||||
else if (command == ZEBRA_IMPORT_CHECK_UPDATE)
|
||||
tree = &bgp->import_check_table[afi];
|
||||
tree = &bgp->nexthop_cache_table[afi];
|
||||
|
||||
bnc = bnc_find(tree, &nhr.prefix, nhr.srte_color);
|
||||
if (!bnc) {
|
||||
bnc_nhc = bnc_find(tree, &nhr.prefix, nhr.srte_color);
|
||||
if (!bnc_nhc) {
|
||||
if (BGP_DEBUG(nht, NHT))
|
||||
zlog_debug(
|
||||
"parse nexthop update(%pFX(%u)(%s)): bnc info not found",
|
||||
"parse nexthop update(%pFX(%u)(%s)): bnc info not found for nexthop cache",
|
||||
&nhr.prefix, nhr.srte_color, bgp->name_pretty);
|
||||
} else
|
||||
bgp_process_nexthop_update(bnc_nhc, &nhr);
|
||||
|
||||
tree = &bgp->import_check_table[afi];
|
||||
|
||||
bnc_import = bnc_find(tree, &nhr.prefix, nhr.srte_color);
|
||||
if (!bnc_import) {
|
||||
if (BGP_DEBUG(nht, NHT))
|
||||
zlog_debug(
|
||||
"parse nexthop update(%pFX(%u)(%s)): bnc info not found for import check",
|
||||
&nhr.prefix, nhr.srte_color, bgp->name_pretty);
|
||||
return;
|
||||
} else {
|
||||
if (nhr.type == ZEBRA_ROUTE_BGP
|
||||
|| !prefix_same(&bnc_import->prefix, &nhr.prefix)) {
|
||||
if (BGP_DEBUG(nht, NHT))
|
||||
zlog_debug(
|
||||
"%s: Import Check does not resolve to the same prefix for %pFX received %pFX",
|
||||
__func__, &bnc_import->prefix, &nhr.prefix);
|
||||
return;
|
||||
}
|
||||
bgp_process_nexthop_update(bnc_import, &nhr);
|
||||
}
|
||||
|
||||
bgp_process_nexthop_update(bnc, &nhr);
|
||||
|
||||
/*
|
||||
* HACK: if any BGP route is dependant on an SR-policy that doesn't
|
||||
* exist, zebra will never send NH updates relative to that policy. In
|
||||
@ -712,12 +728,12 @@ void bgp_parse_nexthop_update(int command, vrf_id_t vrf_id)
|
||||
* which should provide a better infrastructure to solve this issue in
|
||||
* a more efficient and elegant way.
|
||||
*/
|
||||
if (nhr.srte_color == 0) {
|
||||
if (nhr.srte_color == 0 && bnc_nhc) {
|
||||
struct bgp_nexthop_cache *bnc_iter;
|
||||
|
||||
frr_each (bgp_nexthop_cache, &bgp->nexthop_cache_table[afi],
|
||||
bnc_iter) {
|
||||
if (!prefix_same(&bnc->prefix, &bnc_iter->prefix)
|
||||
if (!prefix_same(&bnc_import->prefix, &bnc_iter->prefix)
|
||||
|| bnc_iter->srte_color == 0
|
||||
|| CHECK_FLAG(bnc_iter->flags, BGP_NEXTHOP_VALID))
|
||||
continue;
|
||||
@ -843,6 +859,7 @@ static int make_prefix(int afi, struct bgp_path_info *pi, struct prefix *p)
|
||||
static void sendmsg_zebra_rnh(struct bgp_nexthop_cache *bnc, int command)
|
||||
{
|
||||
bool exact_match = false;
|
||||
bool resolve_via_default = false;
|
||||
int ret;
|
||||
|
||||
if (!zclient)
|
||||
@ -863,11 +880,12 @@ static void sendmsg_zebra_rnh(struct bgp_nexthop_cache *bnc, int command)
|
||||
"%s: We have not connected yet, cannot send nexthops",
|
||||
__func__);
|
||||
}
|
||||
if ((command == ZEBRA_NEXTHOP_REGISTER
|
||||
|| command == ZEBRA_IMPORT_ROUTE_REGISTER)
|
||||
&& (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED)
|
||||
|| CHECK_FLAG(bnc->flags, BGP_STATIC_ROUTE_EXACT_MATCH)))
|
||||
exact_match = true;
|
||||
if (command == ZEBRA_NEXTHOP_REGISTER) {
|
||||
if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED))
|
||||
exact_match = true;
|
||||
if (CHECK_FLAG(bnc->flags, BGP_STATIC_ROUTE_EXACT_MATCH))
|
||||
resolve_via_default = true;
|
||||
}
|
||||
|
||||
if (BGP_DEBUG(zebra, ZEBRA))
|
||||
zlog_debug("%s: sending cmd %s for %pFX (vrf %s)", __func__,
|
||||
@ -875,17 +893,15 @@ static void sendmsg_zebra_rnh(struct bgp_nexthop_cache *bnc, int command)
|
||||
bnc->bgp->name_pretty);
|
||||
|
||||
ret = zclient_send_rnh(zclient, command, &bnc->prefix, exact_match,
|
||||
bnc->bgp->vrf_id);
|
||||
resolve_via_default, bnc->bgp->vrf_id);
|
||||
/* TBD: handle the failure */
|
||||
if (ret == ZCLIENT_SEND_FAILURE)
|
||||
flog_warn(EC_BGP_ZEBRA_SEND,
|
||||
"sendmsg_nexthop: zclient_send_message() failed");
|
||||
|
||||
if ((command == ZEBRA_NEXTHOP_REGISTER)
|
||||
|| (command == ZEBRA_IMPORT_ROUTE_REGISTER))
|
||||
if (command == ZEBRA_NEXTHOP_REGISTER)
|
||||
SET_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED);
|
||||
else if ((command == ZEBRA_NEXTHOP_UNREGISTER)
|
||||
|| (command == ZEBRA_IMPORT_ROUTE_UNREGISTER))
|
||||
else if (command == ZEBRA_NEXTHOP_UNREGISTER)
|
||||
UNSET_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED);
|
||||
return;
|
||||
}
|
||||
@ -910,10 +926,7 @@ static void register_zebra_rnh(struct bgp_nexthop_cache *bnc,
|
||||
return;
|
||||
}
|
||||
|
||||
if (is_bgp_import_route)
|
||||
sendmsg_zebra_rnh(bnc, ZEBRA_IMPORT_ROUTE_REGISTER);
|
||||
else
|
||||
sendmsg_zebra_rnh(bnc, ZEBRA_NEXTHOP_REGISTER);
|
||||
sendmsg_zebra_rnh(bnc, ZEBRA_NEXTHOP_REGISTER);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -935,10 +948,7 @@ static void unregister_zebra_rnh(struct bgp_nexthop_cache *bnc,
|
||||
return;
|
||||
}
|
||||
|
||||
if (is_bgp_import_route)
|
||||
sendmsg_zebra_rnh(bnc, ZEBRA_IMPORT_ROUTE_UNREGISTER);
|
||||
else
|
||||
sendmsg_zebra_rnh(bnc, ZEBRA_NEXTHOP_UNREGISTER);
|
||||
sendmsg_zebra_rnh(bnc, ZEBRA_NEXTHOP_UNREGISTER);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -112,12 +112,6 @@ static int bgp_read_nexthop_update(ZAPI_CALLBACK_ARGS)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bgp_read_import_check_update(ZAPI_CALLBACK_ARGS)
|
||||
{
|
||||
bgp_parse_nexthop_update(cmd, vrf_id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Set or clear interface on which unnumbered neighbor is configured. This
|
||||
* would in turn cause BGP to initiate or turn off IPv6 RAs on this
|
||||
* interface.
|
||||
@ -3217,7 +3211,6 @@ void bgp_zebra_init(struct thread_master *master, unsigned short instance)
|
||||
zclient->redistribute_route_add = zebra_read_route;
|
||||
zclient->redistribute_route_del = zebra_read_route;
|
||||
zclient->nexthop_update = bgp_read_nexthop_update;
|
||||
zclient->import_check_update = bgp_read_import_check_update;
|
||||
zclient->fec_update = bgp_read_fec_update;
|
||||
zclient->local_es_add = bgp_zebra_process_local_es_add;
|
||||
zclient->local_es_del = bgp_zebra_process_local_es_del;
|
||||
|
@ -355,9 +355,6 @@ static const struct zebra_desc_table command_types[] = {
|
||||
DESC_ENTRY(ZEBRA_INTERFACE_NBR_ADDRESS_ADD),
|
||||
DESC_ENTRY(ZEBRA_INTERFACE_NBR_ADDRESS_DELETE),
|
||||
DESC_ENTRY(ZEBRA_INTERFACE_BFD_DEST_UPDATE),
|
||||
DESC_ENTRY(ZEBRA_IMPORT_ROUTE_REGISTER),
|
||||
DESC_ENTRY(ZEBRA_IMPORT_ROUTE_UNREGISTER),
|
||||
DESC_ENTRY(ZEBRA_IMPORT_CHECK_UPDATE),
|
||||
DESC_ENTRY(ZEBRA_BFD_DEST_REGISTER),
|
||||
DESC_ENTRY(ZEBRA_BFD_DEST_DEREGISTER),
|
||||
DESC_ENTRY(ZEBRA_BFD_DEST_UPDATE),
|
||||
|
@ -765,15 +765,17 @@ static int zclient_connect(struct thread *t)
|
||||
|
||||
enum zclient_send_status zclient_send_rnh(struct zclient *zclient, int command,
|
||||
const struct prefix *p,
|
||||
bool exact_match, vrf_id_t vrf_id)
|
||||
bool connected,
|
||||
bool resolve_via_def, vrf_id_t vrf_id)
|
||||
{
|
||||
struct stream *s;
|
||||
|
||||
s = zclient->obuf;
|
||||
stream_reset(s);
|
||||
zclient_create_header(s, command, vrf_id);
|
||||
stream_putc(s, (exact_match) ? 1 : 0);
|
||||
|
||||
stream_putc(s, (connected) ? 1 : 0);
|
||||
stream_putc(s, (resolve_via_def) ? 1 : 0);
|
||||
stream_putw(s, SAFI_UNICAST);
|
||||
stream_putw(s, PREFIX_FAMILY(p));
|
||||
stream_putc(s, p->prefixlen);
|
||||
switch (PREFIX_FAMILY(p)) {
|
||||
@ -1925,6 +1927,7 @@ bool zapi_nexthop_update_decode(struct stream *s, struct zapi_route *nhr)
|
||||
memset(nhr, 0, sizeof(*nhr));
|
||||
|
||||
STREAM_GETL(s, nhr->message);
|
||||
STREAM_GETW(s, nhr->safi);
|
||||
STREAM_GETW(s, nhr->prefix.family);
|
||||
STREAM_GETC(s, nhr->prefix.prefixlen);
|
||||
switch (nhr->prefix.family) {
|
||||
@ -4016,13 +4019,6 @@ static int zclient_read(struct thread *thread)
|
||||
(*zclient->nexthop_update)(command, zclient, length,
|
||||
vrf_id);
|
||||
break;
|
||||
case ZEBRA_IMPORT_CHECK_UPDATE:
|
||||
if (zclient_debug)
|
||||
zlog_debug("zclient rcvd import check update");
|
||||
if (zclient->import_check_update)
|
||||
(*zclient->import_check_update)(command, zclient,
|
||||
length, vrf_id);
|
||||
break;
|
||||
case ZEBRA_BFD_DEST_REPLAY:
|
||||
if (zclient->bfd_dest_replay)
|
||||
(*zclient->bfd_dest_replay)(command, zclient, length,
|
||||
|
@ -126,9 +126,6 @@ typedef enum {
|
||||
ZEBRA_INTERFACE_NBR_ADDRESS_ADD,
|
||||
ZEBRA_INTERFACE_NBR_ADDRESS_DELETE,
|
||||
ZEBRA_INTERFACE_BFD_DEST_UPDATE,
|
||||
ZEBRA_IMPORT_ROUTE_REGISTER,
|
||||
ZEBRA_IMPORT_ROUTE_UNREGISTER,
|
||||
ZEBRA_IMPORT_CHECK_UPDATE,
|
||||
ZEBRA_BFD_DEST_REGISTER,
|
||||
ZEBRA_BFD_DEST_DEREGISTER,
|
||||
ZEBRA_BFD_DEST_UPDATE,
|
||||
@ -362,7 +359,6 @@ struct zclient {
|
||||
int (*interface_nbr_address_delete)(ZAPI_CALLBACK_ARGS);
|
||||
int (*interface_vrf_update)(ZAPI_CALLBACK_ARGS);
|
||||
int (*nexthop_update)(ZAPI_CALLBACK_ARGS);
|
||||
int (*import_check_update)(ZAPI_CALLBACK_ARGS);
|
||||
int (*bfd_dest_replay)(ZAPI_CALLBACK_ARGS);
|
||||
int (*redistribute_route_add)(ZAPI_CALLBACK_ARGS);
|
||||
int (*redistribute_route_del)(ZAPI_CALLBACK_ARGS);
|
||||
@ -1107,7 +1103,7 @@ extern enum zclient_send_status zclient_route_send(uint8_t, struct zclient *,
|
||||
struct zapi_route *);
|
||||
extern enum zclient_send_status
|
||||
zclient_send_rnh(struct zclient *zclient, int command, const struct prefix *p,
|
||||
bool exact_match, vrf_id_t vrf_id);
|
||||
bool connected, bool resolve_via_default, vrf_id_t vrf_id);
|
||||
int zapi_nexthop_encode(struct stream *s, const struct zapi_nexthop *api_nh,
|
||||
uint32_t api_flags, uint32_t api_message);
|
||||
extern int zapi_route_encode(uint8_t, struct stream *, struct zapi_route *);
|
||||
|
@ -145,16 +145,17 @@ void ospf6_zebra_import_default_route(struct ospf6 *ospf6, bool unreg)
|
||||
prefix.prefixlen = 0;
|
||||
|
||||
if (unreg)
|
||||
command = ZEBRA_IMPORT_ROUTE_UNREGISTER;
|
||||
command = ZEBRA_NEXTHOP_UNREGISTER;
|
||||
else
|
||||
command = ZEBRA_IMPORT_ROUTE_REGISTER;
|
||||
command = ZEBRA_NEXTHOP_REGISTER;
|
||||
|
||||
if (IS_OSPF6_DEBUG_ZEBRA(SEND))
|
||||
zlog_debug("%s: sending cmd %s for %pFX (vrf %u)", __func__,
|
||||
zserv_command_string(command), &prefix,
|
||||
ospf6->vrf_id);
|
||||
|
||||
if (zclient_send_rnh(zclient, command, &prefix, true, ospf6->vrf_id)
|
||||
if (zclient_send_rnh(zclient, command, &prefix, false, true,
|
||||
ospf6->vrf_id)
|
||||
== ZCLIENT_SEND_FAILURE)
|
||||
flog_err(EC_LIB_ZAPI_SOCKET, "%s: zclient_send_rnh() failed",
|
||||
__func__);
|
||||
@ -720,7 +721,7 @@ void ospf6_zebra_init(struct thread_master *master)
|
||||
ospf6_zebra_if_address_update_delete;
|
||||
zclient->redistribute_route_add = ospf6_zebra_read_route;
|
||||
zclient->redistribute_route_del = ospf6_zebra_read_route;
|
||||
zclient->import_check_update = ospf6_zebra_import_check_update;
|
||||
zclient->nexthop_update = ospf6_zebra_import_check_update;
|
||||
|
||||
/* Install command element for zebra node. */
|
||||
install_element(VIEW_NODE, &show_ospf6_zebra_cmd);
|
||||
|
@ -478,7 +478,7 @@ void pbr_send_rnh(struct nexthop *nhop, bool reg)
|
||||
break;
|
||||
}
|
||||
|
||||
if (zclient_send_rnh(zclient, command, &p, false, nhop->vrf_id)
|
||||
if (zclient_send_rnh(zclient, command, &p, false, false, nhop->vrf_id)
|
||||
== ZCLIENT_SEND_FAILURE) {
|
||||
zlog_warn("%s: Failure to send nexthop to zebra", __func__);
|
||||
}
|
||||
|
@ -54,7 +54,8 @@ void pim_sendmsg_zebra_rnh(struct pim_instance *pim, struct zclient *zclient,
|
||||
int ret;
|
||||
|
||||
p = &(pnc->rpf.rpf_addr);
|
||||
ret = zclient_send_rnh(zclient, command, p, false, pim->vrf->vrf_id);
|
||||
ret = zclient_send_rnh(zclient, command, p, false, false,
|
||||
pim->vrf->vrf_id);
|
||||
if (ret == ZCLIENT_SEND_FAILURE)
|
||||
zlog_warn("sendmsg_nexthop: zclient_send_message() failed");
|
||||
|
||||
|
@ -626,19 +626,12 @@ void sharp_zebra_nexthop_watch(struct prefix *p, vrf_id_t vrf_id, bool import,
|
||||
{
|
||||
int command;
|
||||
|
||||
if (!import) {
|
||||
command = ZEBRA_NEXTHOP_REGISTER;
|
||||
command = ZEBRA_NEXTHOP_REGISTER;
|
||||
|
||||
if (!watch)
|
||||
command = ZEBRA_NEXTHOP_UNREGISTER;
|
||||
} else {
|
||||
command = ZEBRA_IMPORT_ROUTE_REGISTER;
|
||||
if (!watch)
|
||||
command = ZEBRA_NEXTHOP_UNREGISTER;
|
||||
|
||||
if (!watch)
|
||||
command = ZEBRA_IMPORT_ROUTE_UNREGISTER;
|
||||
}
|
||||
|
||||
if (zclient_send_rnh(zclient, command, p, connected, vrf_id)
|
||||
if (zclient_send_rnh(zclient, command, p, connected, false, vrf_id)
|
||||
== ZCLIENT_SEND_FAILURE)
|
||||
zlog_warn("%s: Failure to send nexthop to zebra", __func__);
|
||||
}
|
||||
@ -984,7 +977,6 @@ void sharp_zebra_init(void)
|
||||
zclient->interface_address_delete = interface_address_delete;
|
||||
zclient->route_notify_owner = route_notify_owner;
|
||||
zclient->nexthop_update = sharp_nexthop_update;
|
||||
zclient->import_check_update = sharp_nexthop_update;
|
||||
zclient->nhg_notify_owner = nhg_notify_owner;
|
||||
zclient->zebra_buffer_write_ready = sharp_zclient_buffer_ready;
|
||||
zclient->redistribute_route_add = sharp_redistribute_route;
|
||||
|
@ -332,7 +332,7 @@ void static_zebra_nht_register(struct static_nexthop *nh, bool reg)
|
||||
static_nht_hash_free(nhtd);
|
||||
}
|
||||
|
||||
if (zclient_send_rnh(zclient, cmd, &p, false, nh->nh_vrf_id)
|
||||
if (zclient_send_rnh(zclient, cmd, &p, false, false, nh->nh_vrf_id)
|
||||
== ZCLIENT_SEND_FAILURE)
|
||||
zlog_warn("%s: Failure to send nexthop to zebra", __func__);
|
||||
}
|
||||
|
12
zebra/rib.h
12
zebra/rib.h
@ -46,24 +46,22 @@ DECLARE_MGROUP(ZEBRA);
|
||||
|
||||
DECLARE_MTYPE(RE);
|
||||
|
||||
enum rnh_type { RNH_NEXTHOP_TYPE, RNH_IMPORT_CHECK_TYPE };
|
||||
|
||||
PREDECL_LIST(rnh_list);
|
||||
|
||||
/* Nexthop structure. */
|
||||
struct rnh {
|
||||
uint8_t flags;
|
||||
|
||||
#define ZEBRA_NHT_CONNECTED 0x1
|
||||
#define ZEBRA_NHT_DELETED 0x2
|
||||
#define ZEBRA_NHT_EXACT_MATCH 0x4
|
||||
#define ZEBRA_NHT_CONNECTED 0x1
|
||||
#define ZEBRA_NHT_DELETED 0x2
|
||||
#define ZEBRA_NHT_EXACT_MATCH 0x4
|
||||
#define ZEBRA_NHT_RESOLVE_VIA_DEFAULT 0x8
|
||||
|
||||
/* VRF identifier. */
|
||||
vrf_id_t vrf_id;
|
||||
|
||||
afi_t afi;
|
||||
|
||||
enum rnh_type type;
|
||||
safi_t safi;
|
||||
|
||||
uint32_t seqno;
|
||||
|
||||
|
@ -1164,13 +1164,6 @@ int zsend_zebra_srv6_locator_delete(struct zserv *client,
|
||||
|
||||
/* Inbound message handling ------------------------------------------------ */
|
||||
|
||||
const int cmd2type[] = {
|
||||
[ZEBRA_NEXTHOP_REGISTER] = RNH_NEXTHOP_TYPE,
|
||||
[ZEBRA_NEXTHOP_UNREGISTER] = RNH_NEXTHOP_TYPE,
|
||||
[ZEBRA_IMPORT_ROUTE_REGISTER] = RNH_IMPORT_CHECK_TYPE,
|
||||
[ZEBRA_IMPORT_ROUTE_UNREGISTER] = RNH_IMPORT_CHECK_TYPE,
|
||||
};
|
||||
|
||||
/* Nexthop register */
|
||||
static void zread_rnh_register(ZAPI_HANDLER_ARGS)
|
||||
{
|
||||
@ -1178,17 +1171,17 @@ static void zread_rnh_register(ZAPI_HANDLER_ARGS)
|
||||
struct stream *s;
|
||||
struct prefix p;
|
||||
unsigned short l = 0;
|
||||
uint8_t flags = 0;
|
||||
uint16_t type = cmd2type[hdr->command];
|
||||
uint8_t connected = 0;
|
||||
uint8_t resolve_via_default;
|
||||
bool exist;
|
||||
bool flag_changed = false;
|
||||
uint8_t orig_flags;
|
||||
safi_t safi;
|
||||
|
||||
if (IS_ZEBRA_DEBUG_NHT)
|
||||
zlog_debug(
|
||||
"rnh_register msg from client %s: hdr->length=%d, type=%s vrf=%u",
|
||||
"rnh_register msg from client %s: hdr->length=%d vrf=%u",
|
||||
zebra_route_string(client->proto), hdr->length,
|
||||
(type == RNH_NEXTHOP_TYPE) ? "nexthop" : "route",
|
||||
zvrf->vrf->vrf_id);
|
||||
|
||||
s = msg;
|
||||
@ -1197,10 +1190,12 @@ static void zread_rnh_register(ZAPI_HANDLER_ARGS)
|
||||
client->nh_reg_time = monotime(NULL);
|
||||
|
||||
while (l < hdr->length) {
|
||||
STREAM_GETC(s, flags);
|
||||
STREAM_GETC(s, connected);
|
||||
STREAM_GETC(s, resolve_via_default);
|
||||
STREAM_GETW(s, safi);
|
||||
STREAM_GETW(s, p.family);
|
||||
STREAM_GETC(s, p.prefixlen);
|
||||
l += 4;
|
||||
l += 7;
|
||||
if (p.family == AF_INET) {
|
||||
client->v4_nh_watch_add_cnt++;
|
||||
if (p.prefixlen > IPV4_MAX_BITLEN) {
|
||||
@ -1228,37 +1223,29 @@ static void zread_rnh_register(ZAPI_HANDLER_ARGS)
|
||||
p.family);
|
||||
return;
|
||||
}
|
||||
rnh = zebra_add_rnh(&p, zvrf_id(zvrf), type, &exist);
|
||||
rnh = zebra_add_rnh(&p, zvrf_id(zvrf), &exist);
|
||||
if (!rnh)
|
||||
return;
|
||||
|
||||
orig_flags = rnh->flags;
|
||||
if (type == RNH_NEXTHOP_TYPE) {
|
||||
if (flags
|
||||
&& !CHECK_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED))
|
||||
SET_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED);
|
||||
else if (!flags
|
||||
&& CHECK_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED))
|
||||
UNSET_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED);
|
||||
} else if (type == RNH_IMPORT_CHECK_TYPE) {
|
||||
if (flags
|
||||
&& !CHECK_FLAG(rnh->flags, ZEBRA_NHT_EXACT_MATCH))
|
||||
SET_FLAG(rnh->flags, ZEBRA_NHT_EXACT_MATCH);
|
||||
else if (!flags
|
||||
&& CHECK_FLAG(rnh->flags,
|
||||
ZEBRA_NHT_EXACT_MATCH))
|
||||
UNSET_FLAG(rnh->flags, ZEBRA_NHT_EXACT_MATCH);
|
||||
}
|
||||
if (connected && !CHECK_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED))
|
||||
SET_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED);
|
||||
else if (!connected
|
||||
&& CHECK_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED))
|
||||
UNSET_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED);
|
||||
|
||||
if (resolve_via_default)
|
||||
SET_FLAG(rnh->flags, ZEBRA_NHT_RESOLVE_VIA_DEFAULT);
|
||||
|
||||
if (orig_flags != rnh->flags)
|
||||
flag_changed = true;
|
||||
|
||||
/* Anything not AF_INET/INET6 has been filtered out above */
|
||||
if (!exist || flag_changed)
|
||||
zebra_evaluate_rnh(zvrf, family2afi(p.family), 1, type,
|
||||
&p);
|
||||
zebra_evaluate_rnh(zvrf, family2afi(p.family), 1, &p,
|
||||
safi);
|
||||
|
||||
zebra_add_rnh_client(rnh, client, type, zvrf_id(zvrf));
|
||||
zebra_add_rnh_client(rnh, client, zvrf_id(zvrf));
|
||||
}
|
||||
|
||||
stream_failure:
|
||||
@ -1272,7 +1259,7 @@ static void zread_rnh_unregister(ZAPI_HANDLER_ARGS)
|
||||
struct stream *s;
|
||||
struct prefix p;
|
||||
unsigned short l = 0;
|
||||
uint16_t type = cmd2type[hdr->command];
|
||||
safi_t safi;
|
||||
|
||||
if (IS_ZEBRA_DEBUG_NHT)
|
||||
zlog_debug(
|
||||
@ -1283,15 +1270,19 @@ static void zread_rnh_unregister(ZAPI_HANDLER_ARGS)
|
||||
s = msg;
|
||||
|
||||
while (l < hdr->length) {
|
||||
uint8_t flags;
|
||||
uint8_t ignore;
|
||||
|
||||
STREAM_GETC(s, flags);
|
||||
if (flags != 0)
|
||||
STREAM_GETC(s, ignore);
|
||||
if (ignore != 0)
|
||||
goto stream_failure;
|
||||
STREAM_GETC(s, ignore);
|
||||
if (ignore != 0)
|
||||
goto stream_failure;
|
||||
|
||||
STREAM_GETW(s, safi);
|
||||
STREAM_GETW(s, p.family);
|
||||
STREAM_GETC(s, p.prefixlen);
|
||||
l += 4;
|
||||
l += 7;
|
||||
if (p.family == AF_INET) {
|
||||
client->v4_nh_watch_rem_cnt++;
|
||||
if (p.prefixlen > IPV4_MAX_BITLEN) {
|
||||
@ -1319,10 +1310,10 @@ static void zread_rnh_unregister(ZAPI_HANDLER_ARGS)
|
||||
p.family);
|
||||
return;
|
||||
}
|
||||
rnh = zebra_lookup_rnh(&p, zvrf_id(zvrf), type);
|
||||
rnh = zebra_lookup_rnh(&p, zvrf_id(zvrf), safi);
|
||||
if (rnh) {
|
||||
client->nh_dereg_time = monotime(NULL);
|
||||
zebra_remove_rnh_client(rnh, client, type);
|
||||
zebra_remove_rnh_client(rnh, client);
|
||||
}
|
||||
}
|
||||
stream_failure:
|
||||
@ -3683,8 +3674,6 @@ void (*const zserv_handlers[])(ZAPI_HANDLER_ARGS) = {
|
||||
[ZEBRA_HELLO] = zread_hello,
|
||||
[ZEBRA_NEXTHOP_REGISTER] = zread_rnh_register,
|
||||
[ZEBRA_NEXTHOP_UNREGISTER] = zread_rnh_unregister,
|
||||
[ZEBRA_IMPORT_ROUTE_REGISTER] = zread_rnh_register,
|
||||
[ZEBRA_IMPORT_ROUTE_UNREGISTER] = zread_rnh_unregister,
|
||||
[ZEBRA_BFD_DEST_UPDATE] = zebra_ptm_bfd_dst_register,
|
||||
[ZEBRA_BFD_DEST_REGISTER] = zebra_ptm_bfd_dst_register,
|
||||
[ZEBRA_BFD_DEST_DEREGISTER] = zebra_ptm_bfd_dst_deregister,
|
||||
|
@ -730,10 +730,9 @@ void zebra_rib_evaluate_rn_nexthops(struct route_node *rn, uint32_t seq)
|
||||
|
||||
if (IS_ZEBRA_DEBUG_NHT_DETAILED)
|
||||
zlog_debug(
|
||||
"%s(%u):%pRN has Nexthop(%pFX) Type: %s depending on it, evaluating %u:%u",
|
||||
zvrf_name(zvrf), zvrf_id(zvrf),
|
||||
rn, p, rnh_type2str(rnh->type), seq,
|
||||
rnh->seqno);
|
||||
"%s(%u):%pRN has Nexthop(%pFX) depending on it, evaluating %u:%u",
|
||||
zvrf_name(zvrf), zvrf_id(zvrf), rn, p,
|
||||
seq, rnh->seqno);
|
||||
|
||||
/*
|
||||
* If we have evaluated this node on this pass
|
||||
@ -755,8 +754,8 @@ void zebra_rib_evaluate_rn_nexthops(struct route_node *rn, uint32_t seq)
|
||||
}
|
||||
|
||||
rnh->seqno = seq;
|
||||
zebra_evaluate_rnh(zvrf, family2afi(p->family), 0,
|
||||
rnh->type, p);
|
||||
zebra_evaluate_rnh(zvrf, family2afi(p->family), 0, p,
|
||||
rnh->safi);
|
||||
}
|
||||
|
||||
rn = rn->parent;
|
||||
|
@ -71,21 +71,18 @@ void zebra_rnh_init(void)
|
||||
}
|
||||
|
||||
static inline struct route_table *get_rnh_table(vrf_id_t vrfid, afi_t afi,
|
||||
enum rnh_type type)
|
||||
safi_t safi)
|
||||
{
|
||||
struct zebra_vrf *zvrf;
|
||||
struct route_table *t = NULL;
|
||||
|
||||
zvrf = zebra_vrf_lookup_by_id(vrfid);
|
||||
if (zvrf)
|
||||
switch (type) {
|
||||
case RNH_NEXTHOP_TYPE:
|
||||
if (zvrf) {
|
||||
if (safi == SAFI_UNICAST)
|
||||
t = zvrf->rnh_table[afi];
|
||||
break;
|
||||
case RNH_IMPORT_CHECK_TYPE:
|
||||
t = zvrf->import_check_table[afi];
|
||||
break;
|
||||
}
|
||||
else if (safi == SAFI_MULTICAST)
|
||||
t = zvrf->rnh_table_multicast[afi];
|
||||
}
|
||||
|
||||
return t;
|
||||
}
|
||||
@ -93,7 +90,7 @@ static inline struct route_table *get_rnh_table(vrf_id_t vrfid, afi_t afi,
|
||||
static void zebra_rnh_remove_from_routing_table(struct rnh *rnh)
|
||||
{
|
||||
struct zebra_vrf *zvrf = zebra_vrf_lookup_by_id(rnh->vrf_id);
|
||||
struct route_table *table = zvrf->table[rnh->afi][SAFI_UNICAST];
|
||||
struct route_table *table = zvrf->table[rnh->afi][rnh->safi];
|
||||
struct route_node *rn;
|
||||
rib_dest_t *dest;
|
||||
|
||||
@ -117,7 +114,7 @@ static void zebra_rnh_remove_from_routing_table(struct rnh *rnh)
|
||||
static void zebra_rnh_store_in_routing_table(struct rnh *rnh)
|
||||
{
|
||||
struct zebra_vrf *zvrf = zebra_vrf_lookup_by_id(rnh->vrf_id);
|
||||
struct route_table *table = zvrf->table[rnh->afi][SAFI_UNICAST];
|
||||
struct route_table *table = zvrf->table[rnh->afi][rnh->safi];
|
||||
struct route_node *rn;
|
||||
rib_dest_t *dest;
|
||||
|
||||
@ -135,27 +132,28 @@ static void zebra_rnh_store_in_routing_table(struct rnh *rnh)
|
||||
route_unlock_node(rn);
|
||||
}
|
||||
|
||||
struct rnh *zebra_add_rnh(struct prefix *p, vrf_id_t vrfid, enum rnh_type type,
|
||||
bool *exists)
|
||||
struct rnh *zebra_add_rnh(struct prefix *p, vrf_id_t vrfid, bool *exists)
|
||||
{
|
||||
struct route_table *table;
|
||||
struct route_node *rn;
|
||||
struct rnh *rnh = NULL;
|
||||
afi_t afi = family2afi(p->family);
|
||||
safi_t safi = SAFI_UNICAST;
|
||||
|
||||
if (IS_ZEBRA_DEBUG_NHT) {
|
||||
struct vrf *vrf = vrf_lookup_by_id(vrfid);
|
||||
|
||||
zlog_debug("%s(%u): Add RNH %pFX type %s", VRF_LOGNAME(vrf),
|
||||
vrfid, p, rnh_type2str(type));
|
||||
zlog_debug("%s(%u): Add RNH %pFX for safi: %u",
|
||||
VRF_LOGNAME(vrf), vrfid, p, safi);
|
||||
}
|
||||
table = get_rnh_table(vrfid, afi, type);
|
||||
|
||||
table = get_rnh_table(vrfid, afi, safi);
|
||||
if (!table) {
|
||||
struct vrf *vrf = vrf_lookup_by_id(vrfid);
|
||||
|
||||
flog_warn(EC_ZEBRA_RNH_NO_TABLE,
|
||||
"%s(%u): Add RNH %pFX type %s - table not found",
|
||||
VRF_LOGNAME(vrf), vrfid, p, rnh_type2str(type));
|
||||
"%s(%u): Add RNH %pFX - table not found",
|
||||
VRF_LOGNAME(vrf), vrfid, p);
|
||||
*exists = false;
|
||||
return NULL;
|
||||
}
|
||||
@ -178,9 +176,9 @@ struct rnh *zebra_add_rnh(struct prefix *p, vrf_id_t vrfid, enum rnh_type type,
|
||||
rnh->resolved_route.family = p->family;
|
||||
rnh->client_list = list_new();
|
||||
rnh->vrf_id = vrfid;
|
||||
rnh->type = type;
|
||||
rnh->seqno = 0;
|
||||
rnh->afi = afi;
|
||||
rnh->safi = safi;
|
||||
rnh->zebra_pseudowire_list = list_new();
|
||||
route_lock_node(rn);
|
||||
rn->info = rnh;
|
||||
@ -195,13 +193,12 @@ struct rnh *zebra_add_rnh(struct prefix *p, vrf_id_t vrfid, enum rnh_type type,
|
||||
return (rn->info);
|
||||
}
|
||||
|
||||
struct rnh *zebra_lookup_rnh(struct prefix *p, vrf_id_t vrfid,
|
||||
enum rnh_type type)
|
||||
struct rnh *zebra_lookup_rnh(struct prefix *p, vrf_id_t vrfid, safi_t safi)
|
||||
{
|
||||
struct route_table *table;
|
||||
struct route_node *rn;
|
||||
|
||||
table = get_rnh_table(vrfid, family2afi(PREFIX_FAMILY(p)), type);
|
||||
table = get_rnh_table(vrfid, family2afi(PREFIX_FAMILY(p)), safi);
|
||||
if (!table)
|
||||
return NULL;
|
||||
|
||||
@ -228,7 +225,7 @@ void zebra_free_rnh(struct rnh *rnh)
|
||||
list_delete(&rnh->zebra_pseudowire_list);
|
||||
|
||||
zvrf = zebra_vrf_lookup_by_id(rnh->vrf_id);
|
||||
table = zvrf->table[family2afi(rnh->resolved_route.family)][SAFI_UNICAST];
|
||||
table = zvrf->table[family2afi(rnh->resolved_route.family)][rnh->safi];
|
||||
|
||||
if (table) {
|
||||
struct route_node *rern;
|
||||
@ -247,7 +244,7 @@ void zebra_free_rnh(struct rnh *rnh)
|
||||
XFREE(MTYPE_RNH, rnh);
|
||||
}
|
||||
|
||||
static void zebra_delete_rnh(struct rnh *rnh, enum rnh_type type)
|
||||
static void zebra_delete_rnh(struct rnh *rnh)
|
||||
{
|
||||
struct route_node *rn;
|
||||
|
||||
@ -261,8 +258,8 @@ static void zebra_delete_rnh(struct rnh *rnh, enum rnh_type type)
|
||||
if (IS_ZEBRA_DEBUG_NHT) {
|
||||
struct vrf *vrf = vrf_lookup_by_id(rnh->vrf_id);
|
||||
|
||||
zlog_debug("%s(%u): Del RNH %pRN type %s", VRF_LOGNAME(vrf),
|
||||
rnh->vrf_id, rnh->node, rnh_type2str(type));
|
||||
zlog_debug("%s(%u): Del RNH %pRN", VRF_LOGNAME(vrf),
|
||||
rnh->vrf_id, rnh->node);
|
||||
}
|
||||
|
||||
zebra_free_rnh(rnh);
|
||||
@ -279,15 +276,14 @@ static void zebra_delete_rnh(struct rnh *rnh, enum rnh_type type)
|
||||
* and as such it will have a resolved rnh.
|
||||
*/
|
||||
void zebra_add_rnh_client(struct rnh *rnh, struct zserv *client,
|
||||
enum rnh_type type, vrf_id_t vrf_id)
|
||||
vrf_id_t vrf_id)
|
||||
{
|
||||
if (IS_ZEBRA_DEBUG_NHT) {
|
||||
struct vrf *vrf = vrf_lookup_by_id(vrf_id);
|
||||
|
||||
zlog_debug("%s(%u): Client %s registers for RNH %pRN type %s",
|
||||
zlog_debug("%s(%u): Client %s registers for RNH %pRN",
|
||||
VRF_LOGNAME(vrf), vrf_id,
|
||||
zebra_route_string(client->proto), rnh->node,
|
||||
rnh_type2str(type));
|
||||
zebra_route_string(client->proto), rnh->node);
|
||||
}
|
||||
if (!listnode_lookup(rnh->client_list, client))
|
||||
listnode_add(rnh->client_list, client);
|
||||
@ -296,21 +292,20 @@ void zebra_add_rnh_client(struct rnh *rnh, struct zserv *client,
|
||||
* We always need to respond with known information,
|
||||
* currently multiple daemons expect this behavior
|
||||
*/
|
||||
zebra_send_rnh_update(rnh, client, type, vrf_id, 0);
|
||||
zebra_send_rnh_update(rnh, client, vrf_id, 0);
|
||||
}
|
||||
|
||||
void zebra_remove_rnh_client(struct rnh *rnh, struct zserv *client,
|
||||
enum rnh_type type)
|
||||
void zebra_remove_rnh_client(struct rnh *rnh, struct zserv *client)
|
||||
{
|
||||
if (IS_ZEBRA_DEBUG_NHT) {
|
||||
struct vrf *vrf = vrf_lookup_by_id(rnh->vrf_id);
|
||||
|
||||
zlog_debug("Client %s unregisters for RNH %s(%u)%pRN type %s",
|
||||
zlog_debug("Client %s unregisters for RNH %s(%u)%pRN",
|
||||
zebra_route_string(client->proto), VRF_LOGNAME(vrf),
|
||||
vrf->vrf_id, rnh->node, rnh_type2str(type));
|
||||
vrf->vrf_id, rnh->node);
|
||||
}
|
||||
listnode_delete(rnh->client_list, client);
|
||||
zebra_delete_rnh(rnh, type);
|
||||
zebra_delete_rnh(rnh);
|
||||
}
|
||||
|
||||
/* XXX move this utility function elsewhere? */
|
||||
@ -350,15 +345,15 @@ void zebra_register_rnh_pseudowire(vrf_id_t vrf_id, struct zebra_pw *pw,
|
||||
return;
|
||||
|
||||
addr2hostprefix(pw->af, &pw->nexthop, &nh);
|
||||
rnh = zebra_add_rnh(&nh, vrf_id, RNH_NEXTHOP_TYPE, &exists);
|
||||
rnh = zebra_add_rnh(&nh, vrf_id, &exists);
|
||||
if (!rnh)
|
||||
return;
|
||||
|
||||
if (!listnode_lookup(rnh->zebra_pseudowire_list, pw)) {
|
||||
listnode_add(rnh->zebra_pseudowire_list, pw);
|
||||
pw->rnh = rnh;
|
||||
zebra_evaluate_rnh(zvrf, family2afi(pw->af), 1,
|
||||
RNH_NEXTHOP_TYPE, &nh);
|
||||
zebra_evaluate_rnh(zvrf, family2afi(pw->af), 1, &nh,
|
||||
SAFI_UNICAST);
|
||||
} else
|
||||
*nht_exists = true;
|
||||
}
|
||||
@ -374,7 +369,7 @@ void zebra_deregister_rnh_pseudowire(vrf_id_t vrf_id, struct zebra_pw *pw)
|
||||
listnode_delete(rnh->zebra_pseudowire_list, pw);
|
||||
pw->rnh = NULL;
|
||||
|
||||
zebra_delete_rnh(rnh, RNH_NEXTHOP_TYPE);
|
||||
zebra_delete_rnh(rnh);
|
||||
}
|
||||
|
||||
/* Clear the NEXTHOP_FLAG_RNH_FILTERED flags on all nexthops
|
||||
@ -418,111 +413,6 @@ static int zebra_rnh_apply_nht_rmap(afi_t afi, struct zebra_vrf *zvrf,
|
||||
return (at_least_one);
|
||||
}
|
||||
|
||||
/*
|
||||
* Determine appropriate route (RE entry) resolving a tracked BGP route
|
||||
* for BGP route for import.
|
||||
*/
|
||||
static struct route_entry *
|
||||
zebra_rnh_resolve_import_entry(struct zebra_vrf *zvrf, afi_t afi,
|
||||
struct route_node *nrn, struct rnh *rnh,
|
||||
struct route_node **prn)
|
||||
{
|
||||
struct route_table *route_table;
|
||||
struct route_node *rn;
|
||||
struct route_entry *re;
|
||||
|
||||
*prn = NULL;
|
||||
|
||||
route_table = zvrf->table[afi][SAFI_UNICAST];
|
||||
if (!route_table) // unexpected
|
||||
return NULL;
|
||||
|
||||
rn = route_node_match(route_table, &nrn->p);
|
||||
if (!rn)
|
||||
return NULL;
|
||||
|
||||
/* Unlock route node - we don't need to lock when walking the tree. */
|
||||
route_unlock_node(rn);
|
||||
|
||||
if (CHECK_FLAG(rnh->flags, ZEBRA_NHT_EXACT_MATCH)
|
||||
&& !prefix_same(&nrn->p, &rn->p))
|
||||
return NULL;
|
||||
|
||||
if (IS_ZEBRA_DEBUG_NHT_DETAILED) {
|
||||
zlog_debug("%s: %s(%u):%pRN Resolved Import Entry to %pRN",
|
||||
__func__, VRF_LOGNAME(zvrf->vrf), rnh->vrf_id,
|
||||
rnh->node, rn);
|
||||
}
|
||||
|
||||
/* Identify appropriate route entry. */
|
||||
RNODE_FOREACH_RE (rn, re) {
|
||||
if (!CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED)
|
||||
&& CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED)
|
||||
&& !CHECK_FLAG(re->status, ROUTE_ENTRY_QUEUED)
|
||||
&& (re->type != ZEBRA_ROUTE_BGP))
|
||||
break;
|
||||
}
|
||||
|
||||
if (re)
|
||||
*prn = rn;
|
||||
|
||||
if (!re && IS_ZEBRA_DEBUG_NHT_DETAILED)
|
||||
zlog_debug(" Rejected due to removed or is a bgp route");
|
||||
|
||||
return re;
|
||||
}
|
||||
|
||||
/*
|
||||
* See if a tracked route entry for import (by BGP) has undergone any
|
||||
* change, and if so, notify the client.
|
||||
*/
|
||||
static void zebra_rnh_eval_import_check_entry(struct zebra_vrf *zvrf, afi_t afi,
|
||||
int force, struct route_node *nrn,
|
||||
struct rnh *rnh,
|
||||
struct route_node *prn,
|
||||
struct route_entry *re)
|
||||
{
|
||||
int state_changed = 0;
|
||||
struct zserv *client;
|
||||
struct listnode *node;
|
||||
|
||||
zebra_rnh_remove_from_routing_table(rnh);
|
||||
if (prn) {
|
||||
prefix_copy(&rnh->resolved_route, &prn->p);
|
||||
} else {
|
||||
int family = rnh->resolved_route.family;
|
||||
|
||||
memset(&rnh->resolved_route.family, 0, sizeof(struct prefix));
|
||||
rnh->resolved_route.family = family;
|
||||
}
|
||||
zebra_rnh_store_in_routing_table(rnh);
|
||||
|
||||
if (re && (rnh->state == NULL)) {
|
||||
if (CHECK_FLAG(re->status, ROUTE_ENTRY_INSTALLED))
|
||||
state_changed = 1;
|
||||
} else if (!re && (rnh->state != NULL))
|
||||
state_changed = 1;
|
||||
|
||||
if (compare_state(re, rnh->state)) {
|
||||
copy_state(rnh, re, nrn);
|
||||
state_changed = 1;
|
||||
}
|
||||
|
||||
if (state_changed || force) {
|
||||
if (IS_ZEBRA_DEBUG_NHT)
|
||||
zlog_debug("%s(%u):%pRN: Route import check %s %s",
|
||||
VRF_LOGNAME(zvrf->vrf), zvrf->vrf->vrf_id,
|
||||
nrn, rnh->state ? "passed" : "failed",
|
||||
state_changed ? "(state changed)" : "");
|
||||
/* state changed, notify clients */
|
||||
for (ALL_LIST_ELEMENTS_RO(rnh->client_list, node, client)) {
|
||||
zebra_send_rnh_update(rnh, client,
|
||||
RNH_IMPORT_CHECK_TYPE,
|
||||
zvrf->vrf->vrf_id, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Notify clients registered for this nexthop about a change.
|
||||
*/
|
||||
@ -580,8 +470,7 @@ static void zebra_rnh_notify_protocol_clients(struct zebra_vrf *zvrf, afi_t afi,
|
||||
zebra_route_string(client->proto));
|
||||
}
|
||||
|
||||
zebra_send_rnh_update(rnh, client, RNH_NEXTHOP_TYPE,
|
||||
zvrf->vrf->vrf_id, 0);
|
||||
zebra_send_rnh_update(rnh, client, zvrf->vrf->vrf_id, 0);
|
||||
}
|
||||
|
||||
if (re)
|
||||
@ -676,7 +565,7 @@ zebra_rnh_resolve_nexthop_entry(struct zebra_vrf *zvrf, afi_t afi,
|
||||
|
||||
*prn = NULL;
|
||||
|
||||
route_table = zvrf->table[afi][SAFI_UNICAST];
|
||||
route_table = zvrf->table[afi][rnh->safi];
|
||||
if (!route_table)
|
||||
return NULL;
|
||||
|
||||
@ -700,10 +589,14 @@ zebra_rnh_resolve_nexthop_entry(struct zebra_vrf *zvrf, afi_t afi,
|
||||
* match route to be exact if so specified
|
||||
*/
|
||||
if (is_default_prefix(&rn->p)
|
||||
&& !rnh_resolve_via_default(zvrf, rn->p.family)) {
|
||||
&& (!CHECK_FLAG(rnh->flags, ZEBRA_NHT_RESOLVE_VIA_DEFAULT)
|
||||
&& !rnh_resolve_via_default(zvrf, rn->p.family))) {
|
||||
if (IS_ZEBRA_DEBUG_NHT_DETAILED)
|
||||
zlog_debug(
|
||||
" Not allowed to resolve through default prefix");
|
||||
" Not allowed to resolve through default prefix: rnh->resolve_via_default: %u",
|
||||
CHECK_FLAG(
|
||||
rnh->flags,
|
||||
ZEBRA_NHT_RESOLVE_VIA_DEFAULT));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -823,26 +716,22 @@ static void zebra_rnh_eval_nexthop_entry(struct zebra_vrf *zvrf, afi_t afi,
|
||||
|
||||
/* Evaluate one tracked entry */
|
||||
static void zebra_rnh_evaluate_entry(struct zebra_vrf *zvrf, afi_t afi,
|
||||
int force, enum rnh_type type,
|
||||
struct route_node *nrn)
|
||||
int force, struct route_node *nrn)
|
||||
{
|
||||
struct rnh *rnh;
|
||||
struct route_entry *re;
|
||||
struct route_node *prn;
|
||||
|
||||
if (IS_ZEBRA_DEBUG_NHT) {
|
||||
zlog_debug("%s(%u):%pRN: Evaluate RNH, type %s %s",
|
||||
zlog_debug("%s(%u):%pRN: Evaluate RNH, %s",
|
||||
VRF_LOGNAME(zvrf->vrf), zvrf->vrf->vrf_id, nrn,
|
||||
rnh_type2str(type), force ? "(force)" : "");
|
||||
force ? "(force)" : "");
|
||||
}
|
||||
|
||||
rnh = nrn->info;
|
||||
|
||||
/* Identify route entry (RE) resolving this tracked entry. */
|
||||
if (type == RNH_IMPORT_CHECK_TYPE)
|
||||
re = zebra_rnh_resolve_import_entry(zvrf, afi, nrn, rnh, &prn);
|
||||
else
|
||||
re = zebra_rnh_resolve_nexthop_entry(zvrf, afi, nrn, rnh, &prn);
|
||||
re = zebra_rnh_resolve_nexthop_entry(zvrf, afi, nrn, rnh, &prn);
|
||||
|
||||
/* If the entry cannot be resolved and that is also the existing state,
|
||||
* there is nothing further to do.
|
||||
@ -851,12 +740,7 @@ static void zebra_rnh_evaluate_entry(struct zebra_vrf *zvrf, afi_t afi,
|
||||
return;
|
||||
|
||||
/* Process based on type of entry. */
|
||||
if (type == RNH_IMPORT_CHECK_TYPE)
|
||||
zebra_rnh_eval_import_check_entry(zvrf, afi, force, nrn, rnh,
|
||||
prn, re);
|
||||
else
|
||||
zebra_rnh_eval_nexthop_entry(zvrf, afi, force, nrn, rnh, prn,
|
||||
re);
|
||||
zebra_rnh_eval_nexthop_entry(zvrf, afi, force, nrn, rnh, prn, re);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -869,7 +753,7 @@ static void zebra_rnh_evaluate_entry(struct zebra_vrf *zvrf, afi_t afi,
|
||||
* covers multiple nexthops we are interested in.
|
||||
*/
|
||||
static void zebra_rnh_clear_nhc_flag(struct zebra_vrf *zvrf, afi_t afi,
|
||||
enum rnh_type type, struct route_node *nrn)
|
||||
struct route_node *nrn)
|
||||
{
|
||||
struct rnh *rnh;
|
||||
struct route_entry *re;
|
||||
@ -878,12 +762,7 @@ static void zebra_rnh_clear_nhc_flag(struct zebra_vrf *zvrf, afi_t afi,
|
||||
rnh = nrn->info;
|
||||
|
||||
/* Identify route entry (RIB) resolving this tracked entry. */
|
||||
if (type == RNH_IMPORT_CHECK_TYPE)
|
||||
re = zebra_rnh_resolve_import_entry(zvrf, afi, nrn, rnh,
|
||||
&prn);
|
||||
else
|
||||
re = zebra_rnh_resolve_nexthop_entry(zvrf, afi, nrn, rnh,
|
||||
&prn);
|
||||
re = zebra_rnh_resolve_nexthop_entry(zvrf, afi, nrn, rnh, &prn);
|
||||
|
||||
if (re)
|
||||
UNSET_FLAG(re->status, ROUTE_ENTRY_LABELS_CHANGED);
|
||||
@ -893,12 +772,12 @@ static void zebra_rnh_clear_nhc_flag(struct zebra_vrf *zvrf, afi_t afi,
|
||||
* of a particular VRF and address-family or a specific prefix.
|
||||
*/
|
||||
void zebra_evaluate_rnh(struct zebra_vrf *zvrf, afi_t afi, int force,
|
||||
enum rnh_type type, struct prefix *p)
|
||||
struct prefix *p, safi_t safi)
|
||||
{
|
||||
struct route_table *rnh_table;
|
||||
struct route_node *nrn;
|
||||
|
||||
rnh_table = get_rnh_table(zvrf->vrf->vrf_id, afi, type);
|
||||
rnh_table = get_rnh_table(zvrf->vrf->vrf_id, afi, safi);
|
||||
if (!rnh_table) // unexpected
|
||||
return;
|
||||
|
||||
@ -906,7 +785,7 @@ void zebra_evaluate_rnh(struct zebra_vrf *zvrf, afi_t afi, int force,
|
||||
/* Evaluating a specific entry, make sure it exists. */
|
||||
nrn = route_node_lookup(rnh_table, p);
|
||||
if (nrn && nrn->info)
|
||||
zebra_rnh_evaluate_entry(zvrf, afi, force, type, nrn);
|
||||
zebra_rnh_evaluate_entry(zvrf, afi, force, nrn);
|
||||
|
||||
if (nrn)
|
||||
route_unlock_node(nrn);
|
||||
@ -915,26 +794,25 @@ void zebra_evaluate_rnh(struct zebra_vrf *zvrf, afi_t afi, int force,
|
||||
nrn = route_top(rnh_table);
|
||||
while (nrn) {
|
||||
if (nrn->info)
|
||||
zebra_rnh_evaluate_entry(zvrf, afi, force, type,
|
||||
nrn);
|
||||
zebra_rnh_evaluate_entry(zvrf, afi, force, nrn);
|
||||
nrn = route_next(nrn); /* this will also unlock nrn */
|
||||
}
|
||||
nrn = route_top(rnh_table);
|
||||
while (nrn) {
|
||||
if (nrn->info)
|
||||
zebra_rnh_clear_nhc_flag(zvrf, afi, type, nrn);
|
||||
zebra_rnh_clear_nhc_flag(zvrf, afi, nrn);
|
||||
nrn = route_next(nrn); /* this will also unlock nrn */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void zebra_print_rnh_table(vrf_id_t vrfid, afi_t afi, struct vty *vty,
|
||||
enum rnh_type type, struct prefix *p)
|
||||
struct prefix *p)
|
||||
{
|
||||
struct route_table *table;
|
||||
struct route_node *rn;
|
||||
|
||||
table = get_rnh_table(vrfid, afi, type);
|
||||
table = get_rnh_table(vrfid, afi, SAFI_UNICAST);
|
||||
if (!table) {
|
||||
if (IS_ZEBRA_DEBUG_NHT)
|
||||
zlog_debug("print_rnhs: rnh table not found");
|
||||
@ -1271,8 +1149,7 @@ static bool compare_state(struct route_entry *r1,
|
||||
}
|
||||
|
||||
int zebra_send_rnh_update(struct rnh *rnh, struct zserv *client,
|
||||
enum rnh_type type, vrf_id_t vrf_id,
|
||||
uint32_t srte_color)
|
||||
vrf_id_t vrf_id, uint32_t srte_color)
|
||||
{
|
||||
struct stream *s = NULL;
|
||||
struct route_entry *re;
|
||||
@ -1282,8 +1159,6 @@ int zebra_send_rnh_update(struct rnh *rnh, struct zserv *client,
|
||||
struct route_node *rn;
|
||||
int ret;
|
||||
uint32_t message = 0;
|
||||
int cmd = (type == RNH_IMPORT_CHECK_TYPE) ? ZEBRA_IMPORT_CHECK_UPDATE
|
||||
: ZEBRA_NEXTHOP_UPDATE;
|
||||
|
||||
rn = rnh->node;
|
||||
re = rnh->state;
|
||||
@ -1291,13 +1166,14 @@ int zebra_send_rnh_update(struct rnh *rnh, struct zserv *client,
|
||||
/* Get output stream. */
|
||||
s = stream_new(ZEBRA_MAX_PACKET_SIZ);
|
||||
|
||||
zclient_create_header(s, cmd, vrf_id);
|
||||
zclient_create_header(s, ZEBRA_NEXTHOP_UPDATE, vrf_id);
|
||||
|
||||
/* Message flags. */
|
||||
if (srte_color)
|
||||
SET_FLAG(message, ZAPI_MESSAGE_SRTE);
|
||||
stream_putl(s, message);
|
||||
|
||||
stream_putw(s, rnh->safi);
|
||||
stream_putw(s, rn->p.family);
|
||||
switch (rn->p.family) {
|
||||
case AF_INET:
|
||||
@ -1444,7 +1320,7 @@ static void print_rnh(struct route_node *rn, struct vty *vty)
|
||||
}
|
||||
|
||||
static int zebra_cleanup_rnh_client(vrf_id_t vrf_id, afi_t afi,
|
||||
struct zserv *client, enum rnh_type type)
|
||||
struct zserv *client)
|
||||
{
|
||||
struct route_table *ntable;
|
||||
struct route_node *nrn;
|
||||
@ -1453,14 +1329,12 @@ static int zebra_cleanup_rnh_client(vrf_id_t vrf_id, afi_t afi,
|
||||
if (IS_ZEBRA_DEBUG_NHT) {
|
||||
struct vrf *vrf = vrf_lookup_by_id(vrf_id);
|
||||
|
||||
zlog_debug(
|
||||
"%s(%u): Client %s RNH cleanup for family %s type %s",
|
||||
VRF_LOGNAME(vrf), vrf_id,
|
||||
zebra_route_string(client->proto), afi2str(afi),
|
||||
rnh_type2str(type));
|
||||
zlog_debug("%s(%u): Client %s RNH cleanup for family %s",
|
||||
VRF_LOGNAME(vrf), vrf_id,
|
||||
zebra_route_string(client->proto), afi2str(afi));
|
||||
}
|
||||
|
||||
ntable = get_rnh_table(vrf_id, afi, type);
|
||||
ntable = get_rnh_table(vrf_id, afi, SAFI_UNICAST);
|
||||
if (!ntable) {
|
||||
zlog_debug("cleanup_rnh_client: rnh table not found");
|
||||
return -1;
|
||||
@ -1471,7 +1345,7 @@ static int zebra_cleanup_rnh_client(vrf_id_t vrf_id, afi_t afi,
|
||||
continue;
|
||||
|
||||
rnh = nrn->info;
|
||||
zebra_remove_rnh_client(rnh, client, type);
|
||||
zebra_remove_rnh_client(rnh, client);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
@ -1485,14 +1359,9 @@ static int zebra_client_cleanup_rnh(struct zserv *client)
|
||||
RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) {
|
||||
zvrf = vrf->info;
|
||||
if (zvrf) {
|
||||
zebra_cleanup_rnh_client(zvrf_id(zvrf), AFI_IP, client,
|
||||
RNH_NEXTHOP_TYPE);
|
||||
zebra_cleanup_rnh_client(zvrf_id(zvrf), AFI_IP6, client,
|
||||
RNH_NEXTHOP_TYPE);
|
||||
zebra_cleanup_rnh_client(zvrf_id(zvrf), AFI_IP, client,
|
||||
RNH_IMPORT_CHECK_TYPE);
|
||||
zebra_cleanup_rnh_client(zvrf_id(zvrf), AFI_IP6, client,
|
||||
RNH_IMPORT_CHECK_TYPE);
|
||||
zebra_cleanup_rnh_client(zvrf_id(zvrf), AFI_IP, client);
|
||||
zebra_cleanup_rnh_client(zvrf_id(zvrf), AFI_IP6,
|
||||
client);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -31,36 +31,22 @@ extern "C" {
|
||||
|
||||
extern void zebra_rnh_init(void);
|
||||
|
||||
static inline const char *rnh_type2str(enum rnh_type type)
|
||||
{
|
||||
switch (type) {
|
||||
case RNH_NEXTHOP_TYPE:
|
||||
return "Nexthop";
|
||||
case RNH_IMPORT_CHECK_TYPE:
|
||||
return "Import";
|
||||
}
|
||||
|
||||
return "ERROR";
|
||||
}
|
||||
|
||||
extern struct rnh *zebra_add_rnh(struct prefix *p, vrf_id_t vrfid,
|
||||
enum rnh_type type, bool *exists);
|
||||
bool *exists);
|
||||
extern struct rnh *zebra_lookup_rnh(struct prefix *p, vrf_id_t vrfid,
|
||||
enum rnh_type type);
|
||||
safi_t safi);
|
||||
extern void zebra_free_rnh(struct rnh *rnh);
|
||||
extern void zebra_add_rnh_client(struct rnh *rnh, struct zserv *client,
|
||||
enum rnh_type type, vrf_id_t vrfid);
|
||||
vrf_id_t vrfid);
|
||||
extern int zebra_send_rnh_update(struct rnh *rnh, struct zserv *client,
|
||||
enum rnh_type type, vrf_id_t vrf_id,
|
||||
uint32_t srte_color);
|
||||
vrf_id_t vrf_id, uint32_t srte_color);
|
||||
extern void zebra_register_rnh_pseudowire(vrf_id_t, struct zebra_pw *, bool *);
|
||||
extern void zebra_deregister_rnh_pseudowire(vrf_id_t, struct zebra_pw *);
|
||||
extern void zebra_remove_rnh_client(struct rnh *rnh, struct zserv *client,
|
||||
enum rnh_type type);
|
||||
extern void zebra_remove_rnh_client(struct rnh *rnh, struct zserv *client);
|
||||
extern void zebra_evaluate_rnh(struct zebra_vrf *zvrf, afi_t afi, int force,
|
||||
enum rnh_type type, struct prefix *p);
|
||||
struct prefix *p, safi_t safi);
|
||||
extern void zebra_print_rnh_table(vrf_id_t vrfid, afi_t afi, struct vty *vty,
|
||||
enum rnh_type type, struct prefix *p);
|
||||
struct prefix *p);
|
||||
|
||||
extern int rnh_resolve_via_default(struct zebra_vrf *zvrf, int family);
|
||||
|
||||
|
@ -319,7 +319,7 @@ static int ip_nht_rm_add(struct zebra_vrf *zvrf, const char *rmap, int rtype,
|
||||
route_map_counter_increment(NHT_RM_MAP(zvrf, afi, rtype));
|
||||
|
||||
if (NHT_RM_MAP(zvrf, afi, rtype))
|
||||
zebra_evaluate_rnh(zvrf, AFI_IP, 1, RNH_NEXTHOP_TYPE, NULL);
|
||||
zebra_evaluate_rnh(zvrf, AFI_IP, 1, NULL, SAFI_UNICAST);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
@ -340,8 +340,7 @@ static int ip_nht_rm_del(struct zebra_vrf *zvrf, const char *rmap, int rtype,
|
||||
zvrf->vrf->vrf_id, rtype);
|
||||
NHT_RM_MAP(zvrf, afi, rtype) = NULL;
|
||||
|
||||
zebra_evaluate_rnh(zvrf, AFI_IP, 1, RNH_NEXTHOP_TYPE,
|
||||
NULL);
|
||||
zebra_evaluate_rnh(zvrf, AFI_IP, 1, NULL, SAFI_UNICAST);
|
||||
}
|
||||
XFREE(MTYPE_ROUTE_MAP_NAME, NHT_RM_NAME(zvrf, afi, rtype));
|
||||
}
|
||||
@ -1589,8 +1588,8 @@ static void zebra_nht_rm_update(const char *rmap)
|
||||
afi_ip = 1;
|
||||
|
||||
zebra_evaluate_rnh(
|
||||
zvrf, AFI_IP, 1,
|
||||
RNH_NEXTHOP_TYPE, NULL);
|
||||
zvrf, AFI_IP, 1, NULL,
|
||||
SAFI_UNICAST);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1620,8 +1619,8 @@ static void zebra_nht_rm_update(const char *rmap)
|
||||
afi_ipv6 = 1;
|
||||
|
||||
zebra_evaluate_rnh(
|
||||
zvrf, AFI_IP, 1,
|
||||
RNH_NEXTHOP_TYPE, NULL);
|
||||
zvrf, AFI_IP, 1, NULL,
|
||||
SAFI_UNICAST);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -116,6 +116,7 @@ static int zebra_sr_policy_notify_update_client(struct zebra_sr_policy *policy,
|
||||
SET_FLAG(message, ZAPI_MESSAGE_SRTE);
|
||||
stream_putl(s, message);
|
||||
|
||||
stream_putw(s, SAFI_UNICAST);
|
||||
switch (policy->endpoint.ipa_type) {
|
||||
case IPADDR_V4:
|
||||
stream_putw(s, AF_INET);
|
||||
@ -196,7 +197,7 @@ static void zebra_sr_policy_notify_update(struct zebra_sr_policy *policy)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
rnh = zebra_lookup_rnh(&p, zvrf_id(zvrf), RNH_NEXTHOP_TYPE);
|
||||
rnh = zebra_lookup_rnh(&p, zvrf_id(zvrf), SAFI_UNICAST);
|
||||
if (!rnh)
|
||||
return;
|
||||
|
||||
@ -205,8 +206,8 @@ static void zebra_sr_policy_notify_update(struct zebra_sr_policy *policy)
|
||||
zebra_sr_policy_notify_update_client(policy, client);
|
||||
else
|
||||
/* Fallback to the IGP shortest path. */
|
||||
zebra_send_rnh_update(rnh, client, RNH_NEXTHOP_TYPE,
|
||||
zvrf_id(zvrf), policy->color);
|
||||
zebra_send_rnh_update(rnh, client, zvrf_id(zvrf),
|
||||
policy->color);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -158,7 +158,7 @@ static int zebra_vrf_enable(struct vrf *vrf)
|
||||
|
||||
table = route_table_init();
|
||||
table->cleanup = zebra_rnhtable_node_cleanup;
|
||||
zvrf->import_check_table[afi] = table;
|
||||
zvrf->rnh_table_multicast[afi] = table;
|
||||
}
|
||||
|
||||
/* Kick off any VxLAN-EVPN processing. */
|
||||
@ -203,8 +203,8 @@ static int zebra_vrf_disable(struct vrf *vrf)
|
||||
for (afi = AFI_IP; afi <= AFI_IP6; afi++) {
|
||||
route_table_finish(zvrf->rnh_table[afi]);
|
||||
zvrf->rnh_table[afi] = NULL;
|
||||
route_table_finish(zvrf->import_check_table[afi]);
|
||||
zvrf->import_check_table[afi] = NULL;
|
||||
route_table_finish(zvrf->rnh_table_multicast[afi]);
|
||||
zvrf->rnh_table_multicast[afi] = NULL;
|
||||
|
||||
for (safi = SAFI_UNICAST; safi <= SAFI_MULTICAST; safi++)
|
||||
rib_close_table(zvrf->table[afi][safi]);
|
||||
@ -305,8 +305,8 @@ static int zebra_vrf_delete(struct vrf *vrf)
|
||||
|
||||
if (zvrf->rnh_table[afi])
|
||||
route_table_finish(zvrf->rnh_table[afi]);
|
||||
if (zvrf->import_check_table[afi])
|
||||
route_table_finish(zvrf->import_check_table[afi]);
|
||||
if (zvrf->rnh_table_multicast[afi])
|
||||
route_table_finish(zvrf->rnh_table[afi]);
|
||||
}
|
||||
|
||||
otable = otable_pop(&zvrf->other_tables);
|
||||
|
@ -78,9 +78,7 @@ struct zebra_vrf {
|
||||
|
||||
/* Recursive Nexthop table */
|
||||
struct route_table *rnh_table[AFI_MAX];
|
||||
|
||||
/* Import check table (used mostly by BGP */
|
||||
struct route_table *import_check_table[AFI_MAX];
|
||||
struct route_table *rnh_table_multicast[AFI_MAX];
|
||||
|
||||
struct otable_head other_tables;
|
||||
|
||||
@ -183,8 +181,8 @@ struct zebra_vrf {
|
||||
struct rtadv rtadv;
|
||||
#endif /* HAVE_RTADV */
|
||||
|
||||
int zebra_rnh_ip_default_route;
|
||||
int zebra_rnh_ipv6_default_route;
|
||||
bool zebra_rnh_ip_default_route;
|
||||
bool zebra_rnh_ipv6_default_route;
|
||||
};
|
||||
#define PROTO_RM_NAME(zvrf, afi, rtype) zvrf->proto_rm[afi][rtype].name
|
||||
#define NHT_RM_NAME(zvrf, afi, rtype) zvrf->nht_rm[afi][rtype].name
|
||||
|
@ -1332,12 +1332,6 @@ DEFPY (show_ip_nht,
|
||||
afi_t afi = ipv4 ? AFI_IP : AFI_IP6;
|
||||
vrf_id_t vrf_id = VRF_DEFAULT;
|
||||
struct prefix prefix, *p = NULL;
|
||||
enum rnh_type rtype;
|
||||
|
||||
if (strcmp(type, "nht") == 0)
|
||||
rtype = RNH_NEXTHOP_TYPE;
|
||||
else
|
||||
rtype = RNH_IMPORT_CHECK_TYPE;
|
||||
|
||||
if (vrf_all) {
|
||||
struct vrf *vrf;
|
||||
@ -1347,7 +1341,7 @@ DEFPY (show_ip_nht,
|
||||
if ((zvrf = vrf->info) != NULL) {
|
||||
vty_out(vty, "\nVRF %s:\n", zvrf_name(zvrf));
|
||||
zebra_print_rnh_table(zvrf_id(zvrf), afi, vty,
|
||||
rtype, NULL);
|
||||
NULL);
|
||||
}
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
@ -1361,7 +1355,7 @@ DEFPY (show_ip_nht,
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
zebra_print_rnh_table(vrf_id, afi, vty, rtype, p);
|
||||
zebra_print_rnh_table(vrf_id, afi, vty, p);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
@ -1380,9 +1374,9 @@ DEFUN (ip_nht_default_route,
|
||||
if (zvrf->zebra_rnh_ip_default_route)
|
||||
return CMD_SUCCESS;
|
||||
|
||||
zvrf->zebra_rnh_ip_default_route = 1;
|
||||
zvrf->zebra_rnh_ip_default_route = true;
|
||||
|
||||
zebra_evaluate_rnh(zvrf, AFI_IP, 0, RNH_NEXTHOP_TYPE, NULL);
|
||||
zebra_evaluate_rnh(zvrf, AFI_IP, 0, NULL, SAFI_UNICAST);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
@ -1719,8 +1713,8 @@ DEFUN (no_ip_nht_default_route,
|
||||
if (!zvrf->zebra_rnh_ip_default_route)
|
||||
return CMD_SUCCESS;
|
||||
|
||||
zvrf->zebra_rnh_ip_default_route = 0;
|
||||
zebra_evaluate_rnh(zvrf, AFI_IP, 0, RNH_NEXTHOP_TYPE, NULL);
|
||||
zvrf->zebra_rnh_ip_default_route = false;
|
||||
zebra_evaluate_rnh(zvrf, AFI_IP, 0, NULL, SAFI_UNICAST);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
@ -1739,8 +1733,8 @@ DEFUN (ipv6_nht_default_route,
|
||||
if (zvrf->zebra_rnh_ipv6_default_route)
|
||||
return CMD_SUCCESS;
|
||||
|
||||
zvrf->zebra_rnh_ipv6_default_route = 1;
|
||||
zebra_evaluate_rnh(zvrf, AFI_IP6, 0, RNH_NEXTHOP_TYPE, NULL);
|
||||
zvrf->zebra_rnh_ipv6_default_route = true;
|
||||
zebra_evaluate_rnh(zvrf, AFI_IP6, 0, NULL, SAFI_UNICAST);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
@ -1760,8 +1754,8 @@ DEFUN (no_ipv6_nht_default_route,
|
||||
if (!zvrf->zebra_rnh_ipv6_default_route)
|
||||
return CMD_SUCCESS;
|
||||
|
||||
zvrf->zebra_rnh_ipv6_default_route = 0;
|
||||
zebra_evaluate_rnh(zvrf, AFI_IP6, 0, RNH_NEXTHOP_TYPE, NULL);
|
||||
zvrf->zebra_rnh_ipv6_default_route = false;
|
||||
zebra_evaluate_rnh(zvrf, AFI_IP6, 0, NULL, SAFI_UNICAST);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user