mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-07-31 22:44:58 +00:00
staticd: track nexthops per-SAFI
This stops intermixing SAFI_UNICAST NHT into SAFI_MULTICAST static routes. Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
This commit is contained in:
parent
e203efe87b
commit
6bcc46657e
@ -101,18 +101,15 @@ static void static_nht_update_safi(struct prefix *sp, struct prefix *nhp,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void static_nht_update(struct prefix *sp, struct prefix *nhp,
|
void static_nht_update(struct prefix *sp, struct prefix *nhp, uint32_t nh_num,
|
||||||
uint32_t nh_num, afi_t afi, vrf_id_t nh_vrf_id)
|
afi_t afi, safi_t safi, vrf_id_t nh_vrf_id)
|
||||||
{
|
{
|
||||||
|
|
||||||
struct vrf *vrf;
|
struct vrf *vrf;
|
||||||
|
|
||||||
RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
|
RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name)
|
||||||
static_nht_update_safi(sp, nhp, nh_num, afi, SAFI_UNICAST,
|
static_nht_update_safi(sp, nhp, nh_num, afi, safi, vrf,
|
||||||
vrf, nh_vrf_id);
|
nh_vrf_id);
|
||||||
static_nht_update_safi(sp, nhp, nh_num, afi, SAFI_MULTICAST,
|
|
||||||
vrf, nh_vrf_id);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void static_nht_reset_start_safi(struct prefix *nhp, afi_t afi,
|
static void static_nht_reset_start_safi(struct prefix *nhp, afi_t afi,
|
||||||
@ -166,16 +163,13 @@ static void static_nht_reset_start_safi(struct prefix *nhp, afi_t afi,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void static_nht_reset_start(struct prefix *nhp, afi_t afi, vrf_id_t nh_vrf_id)
|
void static_nht_reset_start(struct prefix *nhp, afi_t afi, safi_t safi,
|
||||||
|
vrf_id_t nh_vrf_id)
|
||||||
{
|
{
|
||||||
struct vrf *vrf;
|
struct vrf *vrf;
|
||||||
|
|
||||||
RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
|
RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name)
|
||||||
static_nht_reset_start_safi(nhp, afi, SAFI_UNICAST,
|
static_nht_reset_start_safi(nhp, afi, safi, vrf, nh_vrf_id);
|
||||||
vrf, nh_vrf_id);
|
|
||||||
static_nht_reset_start_safi(nhp, afi, SAFI_MULTICAST,
|
|
||||||
vrf, nh_vrf_id);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void static_nht_mark_state_safi(struct prefix *sp, afi_t afi,
|
static void static_nht_mark_state_safi(struct prefix *sp, afi_t afi,
|
||||||
@ -212,7 +206,7 @@ static void static_nht_mark_state_safi(struct prefix *sp, afi_t afi,
|
|||||||
route_unlock_node(rn);
|
route_unlock_node(rn);
|
||||||
}
|
}
|
||||||
|
|
||||||
void static_nht_mark_state(struct prefix *sp, vrf_id_t vrf_id,
|
void static_nht_mark_state(struct prefix *sp, safi_t safi, vrf_id_t vrf_id,
|
||||||
enum static_install_states state)
|
enum static_install_states state)
|
||||||
{
|
{
|
||||||
struct vrf *vrf;
|
struct vrf *vrf;
|
||||||
@ -226,6 +220,5 @@ void static_nht_mark_state(struct prefix *sp, vrf_id_t vrf_id,
|
|||||||
if (!vrf || !vrf->info)
|
if (!vrf || !vrf->info)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
static_nht_mark_state_safi(sp, afi, SAFI_UNICAST, vrf, state);
|
static_nht_mark_state_safi(sp, afi, safi, vrf, state);
|
||||||
static_nht_mark_state_safi(sp, afi, SAFI_MULTICAST, vrf, state);
|
|
||||||
}
|
}
|
||||||
|
@ -37,19 +37,21 @@ extern "C" {
|
|||||||
* vrf_id -> The vrf the nexthop is in.
|
* vrf_id -> The vrf the nexthop is in.
|
||||||
*/
|
*/
|
||||||
extern void static_nht_update(struct prefix *sp, struct prefix *nhp,
|
extern void static_nht_update(struct prefix *sp, struct prefix *nhp,
|
||||||
uint32_t nh_num, afi_t afi, vrf_id_t vrf_id);
|
uint32_t nh_num, afi_t afi, safi_t safi,
|
||||||
|
vrf_id_t vrf_id);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* For the given tracked nexthop, nhp, mark all routes that use
|
* For the given tracked nexthop, nhp, mark all routes that use
|
||||||
* this route as in starting state again.
|
* this route as in starting state again.
|
||||||
*/
|
*/
|
||||||
extern void static_nht_reset_start(struct prefix *nhp, afi_t afi,
|
extern void static_nht_reset_start(struct prefix *nhp, afi_t afi, safi_t safi,
|
||||||
vrf_id_t nh_vrf_id);
|
vrf_id_t nh_vrf_id);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* For the given prefix, sp, mark it as in a particular state
|
* For the given prefix, sp, mark it as in a particular state
|
||||||
*/
|
*/
|
||||||
extern void static_nht_mark_state(struct prefix *sp, vrf_id_t vrf_id,
|
extern void static_nht_mark_state(struct prefix *sp, safi_t safi,
|
||||||
|
vrf_id_t vrf_id,
|
||||||
enum static_install_states state);
|
enum static_install_states state);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -51,6 +51,7 @@ struct static_nht_data {
|
|||||||
struct static_nht_hash_item itm;
|
struct static_nht_hash_item itm;
|
||||||
|
|
||||||
struct prefix nh;
|
struct prefix nh;
|
||||||
|
safi_t safi;
|
||||||
|
|
||||||
vrf_id_t nh_vrf_id;
|
vrf_id_t nh_vrf_id;
|
||||||
|
|
||||||
@ -63,6 +64,8 @@ static int static_nht_data_cmp(const struct static_nht_data *nhtd1,
|
|||||||
{
|
{
|
||||||
if (nhtd1->nh_vrf_id != nhtd2->nh_vrf_id)
|
if (nhtd1->nh_vrf_id != nhtd2->nh_vrf_id)
|
||||||
return numcmp(nhtd1->nh_vrf_id, nhtd2->nh_vrf_id);
|
return numcmp(nhtd1->nh_vrf_id, nhtd2->nh_vrf_id);
|
||||||
|
if (nhtd1->safi != nhtd2->safi)
|
||||||
|
return numcmp(nhtd1->safi, nhtd2->safi);
|
||||||
|
|
||||||
return prefix_cmp(&nhtd1->nh, &nhtd2->nh);
|
return prefix_cmp(&nhtd1->nh, &nhtd2->nh);
|
||||||
}
|
}
|
||||||
@ -72,7 +75,7 @@ static unsigned int static_nht_data_hash(const struct static_nht_data *nhtd)
|
|||||||
unsigned int key = 0;
|
unsigned int key = 0;
|
||||||
|
|
||||||
key = prefix_hash_key(&nhtd->nh);
|
key = prefix_hash_key(&nhtd->nh);
|
||||||
return jhash_1word(nhtd->nh_vrf_id, key);
|
return jhash_2words(nhtd->nh_vrf_id, nhtd->safi, key);
|
||||||
}
|
}
|
||||||
|
|
||||||
DECLARE_HASH(static_nht_hash, struct static_nht_data, itm, static_nht_data_cmp,
|
DECLARE_HASH(static_nht_hash, struct static_nht_data, itm, static_nht_data_cmp,
|
||||||
@ -139,31 +142,32 @@ static int route_notify_owner(ZAPI_CALLBACK_ARGS)
|
|||||||
struct prefix p;
|
struct prefix p;
|
||||||
enum zapi_route_notify_owner note;
|
enum zapi_route_notify_owner note;
|
||||||
uint32_t table_id;
|
uint32_t table_id;
|
||||||
|
safi_t safi;
|
||||||
|
|
||||||
if (!zapi_route_notify_decode(zclient->ibuf, &p, &table_id, ¬e,
|
if (!zapi_route_notify_decode(zclient->ibuf, &p, &table_id, ¬e, NULL,
|
||||||
NULL, NULL))
|
&safi))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
switch (note) {
|
switch (note) {
|
||||||
case ZAPI_ROUTE_FAIL_INSTALL:
|
case ZAPI_ROUTE_FAIL_INSTALL:
|
||||||
static_nht_mark_state(&p, vrf_id, STATIC_NOT_INSTALLED);
|
static_nht_mark_state(&p, safi, vrf_id, STATIC_NOT_INSTALLED);
|
||||||
zlog_warn("%s: Route %pFX failed to install for table: %u",
|
zlog_warn("%s: Route %pFX failed to install for table: %u",
|
||||||
__func__, &p, table_id);
|
__func__, &p, table_id);
|
||||||
break;
|
break;
|
||||||
case ZAPI_ROUTE_BETTER_ADMIN_WON:
|
case ZAPI_ROUTE_BETTER_ADMIN_WON:
|
||||||
static_nht_mark_state(&p, vrf_id, STATIC_NOT_INSTALLED);
|
static_nht_mark_state(&p, safi, vrf_id, STATIC_NOT_INSTALLED);
|
||||||
zlog_warn(
|
zlog_warn(
|
||||||
"%s: Route %pFX over-ridden by better route for table: %u",
|
"%s: Route %pFX over-ridden by better route for table: %u",
|
||||||
__func__, &p, table_id);
|
__func__, &p, table_id);
|
||||||
break;
|
break;
|
||||||
case ZAPI_ROUTE_INSTALLED:
|
case ZAPI_ROUTE_INSTALLED:
|
||||||
static_nht_mark_state(&p, vrf_id, STATIC_INSTALLED);
|
static_nht_mark_state(&p, safi, vrf_id, STATIC_INSTALLED);
|
||||||
break;
|
break;
|
||||||
case ZAPI_ROUTE_REMOVED:
|
case ZAPI_ROUTE_REMOVED:
|
||||||
static_nht_mark_state(&p, vrf_id, STATIC_NOT_INSTALLED);
|
static_nht_mark_state(&p, safi, vrf_id, STATIC_NOT_INSTALLED);
|
||||||
break;
|
break;
|
||||||
case ZAPI_ROUTE_REMOVE_FAIL:
|
case ZAPI_ROUTE_REMOVE_FAIL:
|
||||||
static_nht_mark_state(&p, vrf_id, STATIC_INSTALLED);
|
static_nht_mark_state(&p, safi, vrf_id, STATIC_INSTALLED);
|
||||||
zlog_warn("%s: Route %pFX failure to remove for table: %u",
|
zlog_warn("%s: Route %pFX failure to remove for table: %u",
|
||||||
__func__, &p, table_id);
|
__func__, &p, table_id);
|
||||||
break;
|
break;
|
||||||
@ -215,15 +219,17 @@ static int static_zebra_nexthop_update(ZAPI_CALLBACK_ARGS)
|
|||||||
memset(&lookup, 0, sizeof(lookup));
|
memset(&lookup, 0, sizeof(lookup));
|
||||||
lookup.nh = matched;
|
lookup.nh = matched;
|
||||||
lookup.nh_vrf_id = vrf_id;
|
lookup.nh_vrf_id = vrf_id;
|
||||||
|
lookup.safi = nhr.safi;
|
||||||
|
|
||||||
nhtd = static_nht_hash_find(static_nht_hash, &lookup);
|
nhtd = static_nht_hash_find(static_nht_hash, &lookup);
|
||||||
|
|
||||||
if (nhtd) {
|
if (nhtd) {
|
||||||
nhtd->nh_num = nhr.nexthop_num;
|
nhtd->nh_num = nhr.nexthop_num;
|
||||||
|
|
||||||
static_nht_reset_start(&matched, afi, nhtd->nh_vrf_id);
|
static_nht_reset_start(&matched, afi, nhr.safi,
|
||||||
|
nhtd->nh_vrf_id);
|
||||||
static_nht_update(NULL, &matched, nhr.nexthop_num, afi,
|
static_nht_update(NULL, &matched, nhr.nexthop_num, afi,
|
||||||
nhtd->nh_vrf_id);
|
nhr.safi, nhtd->nh_vrf_id);
|
||||||
} else
|
} else
|
||||||
zlog_err("No nhtd?");
|
zlog_err("No nhtd?");
|
||||||
|
|
||||||
@ -247,6 +253,7 @@ static_nht_hash_getref(const struct static_nht_data *ref)
|
|||||||
|
|
||||||
prefix_copy(&nhtd->nh, &ref->nh);
|
prefix_copy(&nhtd->nh, &ref->nh);
|
||||||
nhtd->nh_vrf_id = ref->nh_vrf_id;
|
nhtd->nh_vrf_id = ref->nh_vrf_id;
|
||||||
|
nhtd->safi = ref->safi;
|
||||||
|
|
||||||
static_nht_hash_add(static_nht_hash, nhtd);
|
static_nht_hash_add(static_nht_hash, nhtd);
|
||||||
}
|
}
|
||||||
@ -277,6 +284,7 @@ void static_zebra_nht_register(struct static_nexthop *nh, bool reg)
|
|||||||
{
|
{
|
||||||
struct static_path *pn = nh->pn;
|
struct static_path *pn = nh->pn;
|
||||||
struct route_node *rn = pn->rn;
|
struct route_node *rn = pn->rn;
|
||||||
|
struct static_route_info *si = static_route_info_from_rnode(rn);
|
||||||
struct static_nht_data lookup;
|
struct static_nht_data lookup;
|
||||||
uint32_t cmd;
|
uint32_t cmd;
|
||||||
struct prefix p;
|
struct prefix p;
|
||||||
@ -315,6 +323,7 @@ void static_zebra_nht_register(struct static_nexthop *nh, bool reg)
|
|||||||
memset(&lookup, 0, sizeof(lookup));
|
memset(&lookup, 0, sizeof(lookup));
|
||||||
lookup.nh = p;
|
lookup.nh = p;
|
||||||
lookup.nh_vrf_id = nh->nh_vrf_id;
|
lookup.nh_vrf_id = nh->nh_vrf_id;
|
||||||
|
lookup.safi = si->safi;
|
||||||
|
|
||||||
nh->nh_registered = reg;
|
nh->nh_registered = reg;
|
||||||
|
|
||||||
@ -329,7 +338,7 @@ void static_zebra_nht_register(struct static_nexthop *nh, bool reg)
|
|||||||
&p, rn, nhtd->nh_num);
|
&p, rn, nhtd->nh_num);
|
||||||
if (nhtd->nh_num)
|
if (nhtd->nh_num)
|
||||||
static_nht_update(&rn->p, &nhtd->nh,
|
static_nht_update(&rn->p, &nhtd->nh,
|
||||||
nhtd->nh_num, afi,
|
nhtd->nh_num, afi, si->safi,
|
||||||
nh->nh_vrf_id);
|
nh->nh_vrf_id);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -346,7 +355,7 @@ void static_zebra_nht_register(struct static_nexthop *nh, bool reg)
|
|||||||
DEBUGD(&static_dbg_route, "%s nexthop(%pFX) for %pRN",
|
DEBUGD(&static_dbg_route, "%s nexthop(%pFX) for %pRN",
|
||||||
reg ? "Registering" : "Unregistering", &p, rn);
|
reg ? "Registering" : "Unregistering", &p, rn);
|
||||||
|
|
||||||
if (zclient_send_rnh(zclient, cmd, &p, SAFI_UNICAST, false, false,
|
if (zclient_send_rnh(zclient, cmd, &p, si->safi, false, false,
|
||||||
nh->nh_vrf_id) == ZCLIENT_SEND_FAILURE)
|
nh->nh_vrf_id) == ZCLIENT_SEND_FAILURE)
|
||||||
zlog_warn("%s: Failure to send nexthop to zebra", __func__);
|
zlog_warn("%s: Failure to send nexthop to zebra", __func__);
|
||||||
}
|
}
|
||||||
@ -358,6 +367,7 @@ int static_zebra_nh_update(struct static_nexthop *nh)
|
|||||||
{
|
{
|
||||||
struct static_path *pn = nh->pn;
|
struct static_path *pn = nh->pn;
|
||||||
struct route_node *rn = pn->rn;
|
struct route_node *rn = pn->rn;
|
||||||
|
struct static_route_info *si = static_route_info_from_rnode(rn);
|
||||||
struct static_nht_data *nhtd, lookup = {};
|
struct static_nht_data *nhtd, lookup = {};
|
||||||
struct prefix p = {};
|
struct prefix p = {};
|
||||||
afi_t afi = AFI_IP;
|
afi_t afi = AFI_IP;
|
||||||
@ -387,12 +397,13 @@ int static_zebra_nh_update(struct static_nexthop *nh)
|
|||||||
|
|
||||||
lookup.nh = p;
|
lookup.nh = p;
|
||||||
lookup.nh_vrf_id = nh->nh_vrf_id;
|
lookup.nh_vrf_id = nh->nh_vrf_id;
|
||||||
|
lookup.safi = si->safi;
|
||||||
|
|
||||||
nhtd = static_nht_hash_find(static_nht_hash, &lookup);
|
nhtd = static_nht_hash_find(static_nht_hash, &lookup);
|
||||||
if (nhtd && nhtd->nh_num) {
|
if (nhtd && nhtd->nh_num) {
|
||||||
nh->state = STATIC_START;
|
nh->state = STATIC_START;
|
||||||
static_nht_update(&rn->p, &nhtd->nh, nhtd->nh_num, afi,
|
static_nht_update(&rn->p, &nhtd->nh, nhtd->nh_num, afi,
|
||||||
nh->nh_vrf_id);
|
si->safi, nh->nh_vrf_id);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
Loading…
Reference in New Issue
Block a user