mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-01 16:09:53 +00:00
Merge branch 'master' into docuser
Signed-off-by: Quentin Young <qlyoung@cumulusnetworks.com>
This commit is contained in:
commit
5da39765e2
@ -106,7 +106,7 @@ static int retain_mode = 0;
|
|||||||
|
|
||||||
/* privileges */
|
/* privileges */
|
||||||
static zebra_capabilities_t _caps_p[] = {
|
static zebra_capabilities_t _caps_p[] = {
|
||||||
ZCAP_BIND, ZCAP_NET_RAW, ZCAP_NET_ADMIN,
|
ZCAP_BIND, ZCAP_NET_RAW, ZCAP_NET_ADMIN, ZCAP_SYS_ADMIN
|
||||||
};
|
};
|
||||||
|
|
||||||
struct zebra_privs_t bgpd_privs = {
|
struct zebra_privs_t bgpd_privs = {
|
||||||
|
@ -1054,6 +1054,9 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p,
|
|||||||
else
|
else
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
api_nh = &api.nexthops[valid_nh_count];
|
||||||
|
api_nh->vrf_id = bgp->vrf_id;
|
||||||
|
|
||||||
if (nh_family == AF_INET) {
|
if (nh_family == AF_INET) {
|
||||||
struct in_addr *nexthop;
|
struct in_addr *nexthop;
|
||||||
|
|
||||||
@ -1078,9 +1081,7 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p,
|
|||||||
|
|
||||||
nexthop = &mpinfo_cp->attr->nexthop;
|
nexthop = &mpinfo_cp->attr->nexthop;
|
||||||
|
|
||||||
api_nh = &api.nexthops[valid_nh_count];
|
|
||||||
api_nh->gate.ipv4 = *nexthop;
|
api_nh->gate.ipv4 = *nexthop;
|
||||||
api_nh->vrf_id = bgp->vrf_id;
|
|
||||||
/* EVPN type-2 routes are
|
/* EVPN type-2 routes are
|
||||||
programmed as onlink on l3-vni SVI
|
programmed as onlink on l3-vni SVI
|
||||||
*/
|
*/
|
||||||
@ -1135,7 +1136,6 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p,
|
|||||||
if (ifindex == 0)
|
if (ifindex == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
api_nh = &api.nexthops[valid_nh_count];
|
|
||||||
api_nh->gate.ipv6 = *nexthop;
|
api_nh->gate.ipv6 = *nexthop;
|
||||||
api_nh->ifindex = ifindex;
|
api_nh->ifindex = ifindex;
|
||||||
api_nh->type = NEXTHOP_TYPE_IPV6_IFINDEX;
|
api_nh->type = NEXTHOP_TYPE_IPV6_IFINDEX;
|
||||||
|
@ -1085,7 +1085,7 @@ int zapi_route_decode(struct stream *s, struct zapi_route *api)
|
|||||||
STREAM_GETC(s, api->message);
|
STREAM_GETC(s, api->message);
|
||||||
STREAM_GETC(s, api->safi);
|
STREAM_GETC(s, api->safi);
|
||||||
if (CHECK_FLAG(api->flags, ZEBRA_FLAG_EVPN_ROUTE))
|
if (CHECK_FLAG(api->flags, ZEBRA_FLAG_EVPN_ROUTE))
|
||||||
stream_get(&(api->rmac), s, sizeof(struct ethaddr));
|
STREAM_GET(&(api->rmac), s, sizeof(struct ethaddr));
|
||||||
|
|
||||||
/* Prefix. */
|
/* Prefix. */
|
||||||
STREAM_GETC(s, api->prefix.family);
|
STREAM_GETC(s, api->prefix.family);
|
||||||
|
@ -204,26 +204,142 @@ void ospf6_asbr_update_route_ecmp_path(struct ospf6_route *old,
|
|||||||
{
|
{
|
||||||
struct ospf6_route *old_route;
|
struct ospf6_route *old_route;
|
||||||
struct ospf6_path *ecmp_path, *o_path = NULL;
|
struct ospf6_path *ecmp_path, *o_path = NULL;
|
||||||
struct listnode *anode;
|
struct listnode *anode, *anext;
|
||||||
struct listnode *nnode, *rnode, *rnext;
|
struct listnode *nnode, *rnode, *rnext;
|
||||||
struct ospf6_nexthop *nh, *rnh;
|
struct ospf6_nexthop *nh, *rnh;
|
||||||
char buf[PREFIX2STR_BUFFER];
|
char buf[PREFIX2STR_BUFFER];
|
||||||
bool route_found = false;
|
bool route_found = false;
|
||||||
|
|
||||||
|
/* check for old entry match with new route origin,
|
||||||
|
* delete old entry.
|
||||||
|
*/
|
||||||
for (old_route = old; old_route; old_route = old_route->next) {
|
for (old_route = old; old_route; old_route = old_route->next) {
|
||||||
if (ospf6_route_is_same(old_route, route) &&
|
bool route_updated = false;
|
||||||
(old_route->path.type == route->path.type) &&
|
|
||||||
(old_route->path.cost == route->path.cost) &&
|
if (!ospf6_route_is_same(old_route, route) ||
|
||||||
(old_route->path.u.cost_e2 == route->path.u.cost_e2)) {
|
(old_route->path.type != route->path.type))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* Current and New route has same origin,
|
||||||
|
* delete old entry.
|
||||||
|
*/
|
||||||
|
for (ALL_LIST_ELEMENTS(old_route->paths, anode, anext,
|
||||||
|
o_path)) {
|
||||||
|
/* Check old route path and route has same
|
||||||
|
* origin.
|
||||||
|
*/
|
||||||
|
if (o_path->area_id != route->path.area_id ||
|
||||||
|
(memcmp(&(o_path)->origin, &(route)->path.origin,
|
||||||
|
sizeof(struct ospf6_ls_origin)) != 0))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* Cost is not same then delete current path */
|
||||||
|
if ((o_path->cost == route->path.cost) &&
|
||||||
|
(o_path->u.cost_e2 == route->path.u.cost_e2))
|
||||||
|
continue;
|
||||||
|
|
||||||
if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL)) {
|
if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL)) {
|
||||||
prefix2str(&old_route->prefix, buf,
|
prefix2str(&old_route->prefix, buf,
|
||||||
sizeof(buf));
|
sizeof(buf));
|
||||||
zlog_debug("%s: old route %s path cost %u [%u]",
|
zlog_debug("%s: route %s cost old %u new %u is not same, replace route",
|
||||||
|
__PRETTY_FUNCTION__, buf,
|
||||||
|
o_path->cost, route->path.cost);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Remove selected current rout path's nh from
|
||||||
|
* effective nh list.
|
||||||
|
*/
|
||||||
|
for (ALL_LIST_ELEMENTS_RO(o_path->nh_list, nnode, nh)) {
|
||||||
|
for (ALL_LIST_ELEMENTS(old_route->nh_list,
|
||||||
|
rnode, rnext, rnh)) {
|
||||||
|
if (!ospf6_nexthop_is_same(rnh, nh))
|
||||||
|
continue;
|
||||||
|
listnode_delete(old_route->nh_list,
|
||||||
|
rnh);
|
||||||
|
ospf6_nexthop_delete(rnh);
|
||||||
|
route_updated = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
listnode_delete(old_route->paths, o_path);
|
||||||
|
ospf6_path_free(o_path);
|
||||||
|
|
||||||
|
/* Current route's path (adv_router info) is similar
|
||||||
|
* to route being added.
|
||||||
|
* Replace current route's path with paths list head.
|
||||||
|
* Update FIB with effective NHs.
|
||||||
|
*/
|
||||||
|
if (listcount(old_route->paths)) {
|
||||||
|
if (old_route->path.origin.id ==
|
||||||
|
route->path.origin.id &&
|
||||||
|
old_route->path.origin.adv_router ==
|
||||||
|
route->path.origin.adv_router) {
|
||||||
|
struct ospf6_path *h_path;
|
||||||
|
|
||||||
|
h_path = (struct ospf6_path *)
|
||||||
|
listgetdata(listhead(old_route->paths));
|
||||||
|
old_route->path.origin.type =
|
||||||
|
h_path->origin.type;
|
||||||
|
old_route->path.origin.id =
|
||||||
|
h_path->origin.id;
|
||||||
|
old_route->path.origin.adv_router =
|
||||||
|
h_path->origin.adv_router;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (route_updated) {
|
||||||
|
for (ALL_LIST_ELEMENTS(old_route->paths,
|
||||||
|
anode, anext, o_path)) {
|
||||||
|
ospf6_merge_nexthops(
|
||||||
|
old_route->nh_list,
|
||||||
|
o_path->nh_list);
|
||||||
|
}
|
||||||
|
/* Update RIB/FIB with effective
|
||||||
|
* nh_list
|
||||||
|
*/
|
||||||
|
if (ospf6->route_table->hook_add)
|
||||||
|
(*ospf6->route_table->hook_add)
|
||||||
|
(old_route);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL)) {
|
||||||
|
prefix2str(&old_route->prefix, buf,
|
||||||
|
sizeof(buf));
|
||||||
|
zlog_debug("%s: route %s old cost %u new cost %u, delete old entry.",
|
||||||
|
__PRETTY_FUNCTION__, buf,
|
||||||
|
old_route->path.cost,
|
||||||
|
route->path.cost);
|
||||||
|
}
|
||||||
|
ospf6_route_remove(old_route,
|
||||||
|
ospf6->route_table);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (route_updated)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add new route */
|
||||||
|
for (old_route = old; old_route; old_route = old_route->next) {
|
||||||
|
|
||||||
|
/* Current and New Route prefix or route type
|
||||||
|
* is not same skip this current node.
|
||||||
|
*/
|
||||||
|
if (!ospf6_route_is_same(old_route, route) ||
|
||||||
|
(old_route->path.type != route->path.type))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* Old Route and New Route have Equal Cost, Merge NHs */
|
||||||
|
if ((old_route->path.cost == route->path.cost) &&
|
||||||
|
(old_route->path.u.cost_e2 == route->path.u.cost_e2)) {
|
||||||
|
|
||||||
|
if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL)) {
|
||||||
|
prefix2str(&old_route->prefix, buf,
|
||||||
|
sizeof(buf));
|
||||||
|
zlog_debug("%s: old route %s path cost %u e2 %u",
|
||||||
__PRETTY_FUNCTION__, buf,
|
__PRETTY_FUNCTION__, buf,
|
||||||
old_route->path.cost,
|
old_route->path.cost,
|
||||||
ospf6_route_is_same(old_route,
|
old_route->path.u.cost_e2);
|
||||||
route));
|
|
||||||
}
|
}
|
||||||
route_found = true;
|
route_found = true;
|
||||||
/* check if this path exists already in
|
/* check if this path exists already in
|
||||||
@ -232,9 +348,10 @@ void ospf6_asbr_update_route_ecmp_path(struct ospf6_route *old,
|
|||||||
*/
|
*/
|
||||||
for (ALL_LIST_ELEMENTS_RO(old_route->paths, anode,
|
for (ALL_LIST_ELEMENTS_RO(old_route->paths, anode,
|
||||||
o_path)) {
|
o_path)) {
|
||||||
if ((o_path->origin.id == route->path.origin.id)
|
if (o_path->area_id == route->path.area_id &&
|
||||||
&& (o_path->origin.adv_router ==
|
(memcmp(&(o_path)->origin,
|
||||||
route->path.origin.adv_router))
|
&(route)->path.origin,
|
||||||
|
sizeof(struct ospf6_ls_origin)) == 0))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/* If path is not found in old_route paths's list,
|
/* If path is not found in old_route paths's list,
|
||||||
@ -262,12 +379,13 @@ void ospf6_asbr_update_route_ecmp_path(struct ospf6_route *old,
|
|||||||
if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL)) {
|
if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL)) {
|
||||||
prefix2str(&route->prefix, buf,
|
prefix2str(&route->prefix, buf,
|
||||||
sizeof(buf));
|
sizeof(buf));
|
||||||
zlog_debug("%s: route %s another path added with nh %u, Paths %u",
|
zlog_debug("%s: route %s another path added with nh %u, effective paths %u nh %u",
|
||||||
__PRETTY_FUNCTION__, buf,
|
__PRETTY_FUNCTION__, buf,
|
||||||
listcount(ecmp_path->nh_list),
|
listcount(ecmp_path->nh_list),
|
||||||
old_route->paths ?
|
old_route->paths ?
|
||||||
listcount(old_route->paths)
|
listcount(old_route->paths)
|
||||||
: 0);
|
: 0,
|
||||||
|
listcount(old_route->nh_list));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (ALL_LIST_ELEMENTS_RO(o_path->nh_list,
|
for (ALL_LIST_ELEMENTS_RO(o_path->nh_list,
|
||||||
@ -313,6 +431,7 @@ void ospf6_asbr_update_route_ecmp_path(struct ospf6_route *old,
|
|||||||
* route.
|
* route.
|
||||||
*/
|
*/
|
||||||
ospf6_route_delete(route);
|
ospf6_route_delete(route);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -426,11 +545,12 @@ void ospf6_asbr_lsa_add(struct ospf6_lsa *lsa)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ospf6_asbr_lsa_remove(struct ospf6_lsa *lsa)
|
void ospf6_asbr_lsa_remove(struct ospf6_lsa *lsa,
|
||||||
|
struct ospf6_route *asbr_entry)
|
||||||
{
|
{
|
||||||
struct ospf6_as_external_lsa *external;
|
struct ospf6_as_external_lsa *external;
|
||||||
struct prefix prefix;
|
struct prefix prefix;
|
||||||
struct ospf6_route *route, *nroute;
|
struct ospf6_route *route, *nroute, *route_to_del;
|
||||||
char buf[PREFIX2STR_BUFFER];
|
char buf[PREFIX2STR_BUFFER];
|
||||||
|
|
||||||
external = (struct ospf6_as_external_lsa *)OSPF6_LSA_HEADER_END(
|
external = (struct ospf6_as_external_lsa *)OSPF6_LSA_HEADER_END(
|
||||||
@ -445,6 +565,35 @@ void ospf6_asbr_lsa_remove(struct ospf6_lsa *lsa)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
route_to_del = ospf6_route_create();
|
||||||
|
route_to_del->type = OSPF6_DEST_TYPE_NETWORK;
|
||||||
|
route_to_del->prefix.family = AF_INET6;
|
||||||
|
route_to_del->prefix.prefixlen = external->prefix.prefix_length;
|
||||||
|
ospf6_prefix_in6_addr(&route_to_del->prefix.u.prefix6,
|
||||||
|
&external->prefix);
|
||||||
|
|
||||||
|
route_to_del->path.origin.type = lsa->header->type;
|
||||||
|
route_to_del->path.origin.id = lsa->header->id;
|
||||||
|
route_to_del->path.origin.adv_router = lsa->header->adv_router;
|
||||||
|
|
||||||
|
if (asbr_entry) {
|
||||||
|
route_to_del->path.area_id = asbr_entry->path.area_id;
|
||||||
|
if (CHECK_FLAG(external->bits_metric, OSPF6_ASBR_BIT_E)) {
|
||||||
|
route_to_del->path.type = OSPF6_PATH_TYPE_EXTERNAL2;
|
||||||
|
route_to_del->path.metric_type = 2;
|
||||||
|
route_to_del->path.cost = asbr_entry->path.cost;
|
||||||
|
route_to_del->path.u.cost_e2 =
|
||||||
|
OSPF6_ASBR_METRIC(external);
|
||||||
|
} else {
|
||||||
|
route_to_del->path.type = OSPF6_PATH_TYPE_EXTERNAL1;
|
||||||
|
route_to_del->path.metric_type = 1;
|
||||||
|
route_to_del->path.cost =
|
||||||
|
asbr_entry->path.cost +
|
||||||
|
OSPF6_ASBR_METRIC(external);
|
||||||
|
route_to_del->path.u.cost_e2 = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
memset(&prefix, 0, sizeof(struct prefix));
|
memset(&prefix, 0, sizeof(struct prefix));
|
||||||
prefix.family = AF_INET6;
|
prefix.family = AF_INET6;
|
||||||
prefix.prefixlen = external->prefix.prefix_length;
|
prefix.prefixlen = external->prefix.prefix_length;
|
||||||
@ -459,14 +608,25 @@ void ospf6_asbr_lsa_remove(struct ospf6_lsa *lsa)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (ospf6_route_lock(route);
|
if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL)) {
|
||||||
route && ospf6_route_is_prefix(&prefix, route); route = nroute) {
|
prefix2str(&prefix, buf, sizeof(buf));
|
||||||
|
zlog_debug("%s: Current route %s cost %u e2 %u, route to del cost %u e2 %u",
|
||||||
|
__PRETTY_FUNCTION__, buf, route->path.cost,
|
||||||
|
route->path.u.cost_e2,
|
||||||
|
route_to_del->path.cost,
|
||||||
|
route_to_del->path.u.cost_e2);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (ospf6_route_lock(route); route &&
|
||||||
|
ospf6_route_is_prefix(&prefix, route); route = nroute) {
|
||||||
nroute = ospf6_route_next(route);
|
nroute = ospf6_route_next(route);
|
||||||
|
|
||||||
if (route->type != OSPF6_DEST_TYPE_NETWORK)
|
if (route->type != OSPF6_DEST_TYPE_NETWORK)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* Route has multiple ECMP paths remove,
|
/* Route has multiple ECMP paths, remove matching
|
||||||
* matching path and update effective route's nh list.
|
* path. Update current route's effective nh list
|
||||||
|
* after removal of one of the path.
|
||||||
*/
|
*/
|
||||||
if (listcount(route->paths) > 1) {
|
if (listcount(route->paths) > 1) {
|
||||||
struct listnode *anode, *anext;
|
struct listnode *anode, *anext;
|
||||||
@ -481,18 +641,36 @@ void ospf6_asbr_lsa_remove(struct ospf6_lsa *lsa)
|
|||||||
*/
|
*/
|
||||||
for (ALL_LIST_ELEMENTS(route->paths, anode, anext,
|
for (ALL_LIST_ELEMENTS(route->paths, anode, anext,
|
||||||
o_path)) {
|
o_path)) {
|
||||||
if (o_path->origin.type != lsa->header->type)
|
if ((o_path->origin.type != lsa->header->type)
|
||||||
|
|| (o_path->origin.adv_router !=
|
||||||
|
lsa->header->adv_router) ||
|
||||||
|
(o_path->origin.id != lsa->header->id))
|
||||||
continue;
|
continue;
|
||||||
if (o_path->origin.id != lsa->header->id)
|
|
||||||
continue;
|
/* Compare LSA cost with current
|
||||||
if (o_path->origin.adv_router !=
|
* route info.
|
||||||
lsa->header->adv_router)
|
*/
|
||||||
|
if (!asbr_entry && (o_path->cost !=
|
||||||
|
route_to_del->path.cost ||
|
||||||
|
o_path->u.cost_e2 !=
|
||||||
|
route_to_del->path.u.cost_e2)) {
|
||||||
|
if (IS_OSPF6_DEBUG_EXAMIN(
|
||||||
|
AS_EXTERNAL)) {
|
||||||
|
prefix2str(&prefix, buf,
|
||||||
|
sizeof(buf));
|
||||||
|
zlog_debug(
|
||||||
|
"%s: route %s to delete is not same, cost %u del cost %u. skip",
|
||||||
|
__PRETTY_FUNCTION__, buf,
|
||||||
|
route->path.cost,
|
||||||
|
route_to_del->path.cost);
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL)) {
|
if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL)) {
|
||||||
prefix2str(&prefix, buf, sizeof(buf));
|
prefix2str(&prefix, buf, sizeof(buf));
|
||||||
zlog_debug(
|
zlog_debug(
|
||||||
"%s: route %s path found with nh %u",
|
"%s: route %s path found with nh %u to remove.",
|
||||||
__PRETTY_FUNCTION__, buf,
|
__PRETTY_FUNCTION__, buf,
|
||||||
listcount(o_path->nh_list));
|
listcount(o_path->nh_list));
|
||||||
}
|
}
|
||||||
@ -542,13 +720,13 @@ void ospf6_asbr_lsa_remove(struct ospf6_lsa *lsa)
|
|||||||
listcount(route->nh_list));
|
listcount(route->nh_list));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Update RIB/FIB w/ effective nh_list */
|
/* Update RIB/FIB with effective nh_list */
|
||||||
if (ospf6->route_table->hook_add)
|
if (ospf6->route_table->hook_add)
|
||||||
(*ospf6->route_table->hook_add)(route);
|
(*ospf6->route_table->hook_add)(route);
|
||||||
|
|
||||||
/* route's path is similar to lsa header,
|
/* route's primary path is similar to LSA,
|
||||||
* replace route's path with route's
|
* replace route's primary path with
|
||||||
* paths list head.
|
* route's paths list head.
|
||||||
*/
|
*/
|
||||||
if (route->path.origin.id == lsa->header->id &&
|
if (route->path.origin.id == lsa->header->id &&
|
||||||
route->path.origin.adv_router ==
|
route->path.origin.adv_router ==
|
||||||
@ -568,12 +746,29 @@ void ospf6_asbr_lsa_remove(struct ospf6_lsa *lsa)
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
if (route->path.origin.type != lsa->header->type)
|
/* Compare LSA origin and cost with current route info.
|
||||||
|
* if any check fails skip del this route node.
|
||||||
|
*/
|
||||||
|
if (asbr_entry && (!ospf6_route_is_same_origin(route,
|
||||||
|
route_to_del) ||
|
||||||
|
(route->path.type != route_to_del->path.type) ||
|
||||||
|
(route->path.cost != route_to_del->path.cost) ||
|
||||||
|
(route->path.u.cost_e2 !=
|
||||||
|
route_to_del->path.u.cost_e2))) {
|
||||||
|
if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL)) {
|
||||||
|
prefix2str(&prefix, buf, sizeof(buf));
|
||||||
|
zlog_debug("%s: route %s to delete is not same, cost %u del cost %u. skip",
|
||||||
|
__PRETTY_FUNCTION__, buf,
|
||||||
|
route->path.cost,
|
||||||
|
route_to_del->path.cost);
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
if (route->path.origin.id != lsa->header->id)
|
}
|
||||||
continue;
|
|
||||||
if (route->path.origin.adv_router !=
|
if ((route->path.origin.type != lsa->header->type) ||
|
||||||
lsa->header->adv_router)
|
(route->path.origin.adv_router !=
|
||||||
|
lsa->header->adv_router) ||
|
||||||
|
(route->path.origin.id != lsa->header->id))
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL)) {
|
if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL)) {
|
||||||
@ -589,6 +784,8 @@ void ospf6_asbr_lsa_remove(struct ospf6_lsa *lsa)
|
|||||||
}
|
}
|
||||||
if (route != NULL)
|
if (route != NULL)
|
||||||
ospf6_route_unlock(route);
|
ospf6_route_unlock(route);
|
||||||
|
|
||||||
|
ospf6_route_delete(route_to_del);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ospf6_asbr_lsentry_add(struct ospf6_route *asbr_entry)
|
void ospf6_asbr_lsentry_add(struct ospf6_route *asbr_entry)
|
||||||
@ -622,7 +819,7 @@ void ospf6_asbr_lsentry_remove(struct ospf6_route *asbr_entry)
|
|||||||
type = htons(OSPF6_LSTYPE_AS_EXTERNAL);
|
type = htons(OSPF6_LSTYPE_AS_EXTERNAL);
|
||||||
router = ospf6_linkstate_prefix_adv_router(&asbr_entry->prefix);
|
router = ospf6_linkstate_prefix_adv_router(&asbr_entry->prefix);
|
||||||
for (ALL_LSDB_TYPED_ADVRTR(ospf6->lsdb, type, router, lsa))
|
for (ALL_LSDB_TYPED_ADVRTR(ospf6->lsdb, type, router, lsa))
|
||||||
ospf6_asbr_lsa_remove(lsa);
|
ospf6_asbr_lsa_remove(lsa, asbr_entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -71,7 +71,8 @@ struct ospf6_as_external_lsa {
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern void ospf6_asbr_lsa_add(struct ospf6_lsa *lsa);
|
extern void ospf6_asbr_lsa_add(struct ospf6_lsa *lsa);
|
||||||
extern void ospf6_asbr_lsa_remove(struct ospf6_lsa *lsa);
|
extern void ospf6_asbr_lsa_remove(struct ospf6_lsa *lsa,
|
||||||
|
struct ospf6_route *asbr_entry);
|
||||||
extern void ospf6_asbr_lsentry_add(struct ospf6_route *asbr_entry);
|
extern void ospf6_asbr_lsentry_add(struct ospf6_route *asbr_entry);
|
||||||
extern void ospf6_asbr_lsentry_remove(struct ospf6_route *asbr_entry);
|
extern void ospf6_asbr_lsentry_remove(struct ospf6_route *asbr_entry);
|
||||||
|
|
||||||
|
@ -469,6 +469,8 @@ int ospf6_route_cmp(struct ospf6_route *ra, struct ospf6_route *rb)
|
|||||||
if (ra->path.type == OSPF6_PATH_TYPE_EXTERNAL2) {
|
if (ra->path.type == OSPF6_PATH_TYPE_EXTERNAL2) {
|
||||||
if (ra->path.u.cost_e2 != rb->path.u.cost_e2)
|
if (ra->path.u.cost_e2 != rb->path.u.cost_e2)
|
||||||
return (ra->path.u.cost_e2 - rb->path.u.cost_e2);
|
return (ra->path.u.cost_e2 - rb->path.u.cost_e2);
|
||||||
|
else
|
||||||
|
return (ra->path.cost - rb->path.cost);
|
||||||
} else {
|
} else {
|
||||||
if (ra->path.cost != rb->path.cost)
|
if (ra->path.cost != rb->path.cost)
|
||||||
return (ra->path.cost - rb->path.cost);
|
return (ra->path.cost - rb->path.cost);
|
||||||
@ -627,10 +629,10 @@ struct ospf6_route *ospf6_route_add(struct ospf6_route *route,
|
|||||||
if (ospf6_route_is_identical(old, route)) {
|
if (ospf6_route_is_identical(old, route)) {
|
||||||
if (IS_OSPF6_DEBUG_ROUTE(MEMORY))
|
if (IS_OSPF6_DEBUG_ROUTE(MEMORY))
|
||||||
zlog_debug(
|
zlog_debug(
|
||||||
"%s %p: route add %p: needless update of %p",
|
"%s %p: route add %p: needless update of %p old cost %u",
|
||||||
ospf6_route_table_name(table),
|
ospf6_route_table_name(table),
|
||||||
(void *)table, (void *)route,
|
(void *)table, (void *)route,
|
||||||
(void *)old);
|
(void *)old, old->path.cost);
|
||||||
else if (IS_OSPF6_DEBUG_ROUTE(TABLE))
|
else if (IS_OSPF6_DEBUG_ROUTE(TABLE))
|
||||||
zlog_debug("%s: route add: needless update",
|
zlog_debug("%s: route add: needless update",
|
||||||
ospf6_route_table_name(table));
|
ospf6_route_table_name(table));
|
||||||
@ -645,9 +647,10 @@ struct ospf6_route *ospf6_route_add(struct ospf6_route *route,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (IS_OSPF6_DEBUG_ROUTE(MEMORY))
|
if (IS_OSPF6_DEBUG_ROUTE(MEMORY))
|
||||||
zlog_debug("%s %p: route add %p: update of %p",
|
zlog_debug("%s %p: route add %p cost %u: update of %p old cost %u",
|
||||||
ospf6_route_table_name(table), (void *)table,
|
ospf6_route_table_name(table), (void *)table,
|
||||||
(void *)route, (void *)old);
|
(void *)route, route->path.cost, (void *)old,
|
||||||
|
old->path.cost);
|
||||||
else if (IS_OSPF6_DEBUG_ROUTE(TABLE))
|
else if (IS_OSPF6_DEBUG_ROUTE(TABLE))
|
||||||
zlog_debug("%s: route add: update",
|
zlog_debug("%s: route add: update",
|
||||||
ospf6_route_table_name(table));
|
ospf6_route_table_name(table));
|
||||||
@ -686,13 +689,14 @@ struct ospf6_route *ospf6_route_add(struct ospf6_route *route,
|
|||||||
if (prev || next) {
|
if (prev || next) {
|
||||||
if (IS_OSPF6_DEBUG_ROUTE(MEMORY))
|
if (IS_OSPF6_DEBUG_ROUTE(MEMORY))
|
||||||
zlog_debug(
|
zlog_debug(
|
||||||
"%s %p: route add %p: another path: prev %p, next %p node refcount %u",
|
"%s %p: route add %p cost %u: another path: prev %p, next %p node ref %u",
|
||||||
ospf6_route_table_name(table), (void *)table,
|
ospf6_route_table_name(table), (void *)table,
|
||||||
(void *)route, (void *)prev, (void *)next,
|
(void *)route, route->path.cost, (void *)prev,
|
||||||
node->lock);
|
(void *)next, node->lock);
|
||||||
else if (IS_OSPF6_DEBUG_ROUTE(TABLE))
|
else if (IS_OSPF6_DEBUG_ROUTE(TABLE))
|
||||||
zlog_debug("%s: route add: another path found",
|
zlog_debug("%s: route add cost %u: another path found",
|
||||||
ospf6_route_table_name(table));
|
ospf6_route_table_name(table),
|
||||||
|
route->path.cost);
|
||||||
|
|
||||||
if (prev == NULL)
|
if (prev == NULL)
|
||||||
prev = next->prev;
|
prev = next->prev;
|
||||||
@ -814,9 +818,9 @@ void ospf6_route_remove(struct ospf6_route *route,
|
|||||||
prefix2str(&route->prefix, buf, sizeof(buf));
|
prefix2str(&route->prefix, buf, sizeof(buf));
|
||||||
|
|
||||||
if (IS_OSPF6_DEBUG_ROUTE(MEMORY))
|
if (IS_OSPF6_DEBUG_ROUTE(MEMORY))
|
||||||
zlog_debug("%s %p: route remove %p: %s refcount %u",
|
zlog_debug("%s %p: route remove %p: %s cost %u refcount %u",
|
||||||
ospf6_route_table_name(table), (void *)table,
|
ospf6_route_table_name(table), (void *)table,
|
||||||
(void *)route, buf, route->lock);
|
(void *)route, buf, route->path.cost, route->lock);
|
||||||
else if (IS_OSPF6_DEBUG_ROUTE(TABLE))
|
else if (IS_OSPF6_DEBUG_ROUTE(TABLE))
|
||||||
zlog_debug("%s: route remove: %s",
|
zlog_debug("%s: route remove: %s",
|
||||||
ospf6_route_table_name(table), buf);
|
ospf6_route_table_name(table), buf);
|
||||||
|
@ -72,7 +72,7 @@ static void ospf6_top_lsdb_hook_remove(struct ospf6_lsa *lsa)
|
|||||||
{
|
{
|
||||||
switch (ntohs(lsa->header->type)) {
|
switch (ntohs(lsa->header->type)) {
|
||||||
case OSPF6_LSTYPE_AS_EXTERNAL:
|
case OSPF6_LSTYPE_AS_EXTERNAL:
|
||||||
ospf6_asbr_lsa_remove(lsa);
|
ospf6_asbr_lsa_remove(lsa, NULL);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -96,11 +96,16 @@ static void ospf6_top_route_hook_remove(struct ospf6_route *route)
|
|||||||
static void ospf6_top_brouter_hook_add(struct ospf6_route *route)
|
static void ospf6_top_brouter_hook_add(struct ospf6_route *route)
|
||||||
{
|
{
|
||||||
if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL)) {
|
if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL)) {
|
||||||
char buf[PREFIX2STR_BUFFER];
|
uint32_t brouter_id;
|
||||||
|
char brouter_name[16];
|
||||||
|
|
||||||
prefix2str(&route->prefix, buf, sizeof(buf));
|
brouter_id = ADV_ROUTER_IN_PREFIX(&route->prefix);
|
||||||
zlog_debug("%s: brouter %s add with nh count %u",
|
inet_ntop(AF_INET, &brouter_id, brouter_name,
|
||||||
__PRETTY_FUNCTION__, buf, listcount(route->nh_list));
|
sizeof(brouter_name));
|
||||||
|
zlog_debug("%s: brouter %s add with adv router %x nh count %u",
|
||||||
|
__PRETTY_FUNCTION__, brouter_name,
|
||||||
|
route->path.origin.adv_router,
|
||||||
|
listcount(route->nh_list));
|
||||||
}
|
}
|
||||||
ospf6_abr_examin_brouter(ADV_ROUTER_IN_PREFIX(&route->prefix));
|
ospf6_abr_examin_brouter(ADV_ROUTER_IN_PREFIX(&route->prefix));
|
||||||
ospf6_asbr_lsentry_add(route);
|
ospf6_asbr_lsentry_add(route);
|
||||||
@ -110,11 +115,15 @@ static void ospf6_top_brouter_hook_add(struct ospf6_route *route)
|
|||||||
static void ospf6_top_brouter_hook_remove(struct ospf6_route *route)
|
static void ospf6_top_brouter_hook_remove(struct ospf6_route *route)
|
||||||
{
|
{
|
||||||
if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL)) {
|
if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL)) {
|
||||||
char buf[PREFIX2STR_BUFFER];
|
uint32_t brouter_id;
|
||||||
|
char brouter_name[16];
|
||||||
|
|
||||||
prefix2str(&route->prefix, buf, sizeof(buf));
|
brouter_id = ADV_ROUTER_IN_PREFIX(&route->prefix);
|
||||||
|
inet_ntop(AF_INET, &brouter_id, brouter_name,
|
||||||
|
sizeof(brouter_name));
|
||||||
zlog_debug("%s: brouter %s del with nh count %u",
|
zlog_debug("%s: brouter %s del with nh count %u",
|
||||||
__PRETTY_FUNCTION__, buf, listcount(route->nh_list));
|
__PRETTY_FUNCTION__, brouter_name,
|
||||||
|
listcount(route->nh_list));
|
||||||
}
|
}
|
||||||
route->flag |= OSPF6_ROUTE_REMOVE;
|
route->flag |= OSPF6_ROUTE_REMOVE;
|
||||||
ospf6_abr_examin_brouter(ADV_ROUTER_IN_PREFIX(&route->prefix));
|
ospf6_abr_examin_brouter(ADV_ROUTER_IN_PREFIX(&route->prefix));
|
||||||
|
@ -55,7 +55,7 @@
|
|||||||
|
|
||||||
/* ospfd privileges */
|
/* ospfd privileges */
|
||||||
zebra_capabilities_t _caps_p[] = {
|
zebra_capabilities_t _caps_p[] = {
|
||||||
ZCAP_NET_RAW, ZCAP_BIND, ZCAP_NET_ADMIN,
|
ZCAP_NET_RAW, ZCAP_BIND, ZCAP_NET_ADMIN, ZCAP_SYS_ADMIN
|
||||||
};
|
};
|
||||||
|
|
||||||
struct zebra_privs_t ospfd_privs = {
|
struct zebra_privs_t ospfd_privs = {
|
||||||
|
262
ospfd/ospf_sr.c
262
ospfd/ospf_sr.c
@ -47,6 +47,7 @@
|
|||||||
#include "thread.h"
|
#include "thread.h"
|
||||||
#include "vty.h"
|
#include "vty.h"
|
||||||
#include "zclient.h"
|
#include "zclient.h"
|
||||||
|
#include <lib/json.h>
|
||||||
|
|
||||||
#include "ospfd/ospfd.h"
|
#include "ospfd/ospfd.h"
|
||||||
#include "ospfd/ospf_interface.h"
|
#include "ospfd/ospf_interface.h"
|
||||||
@ -306,7 +307,8 @@ int ospf_sr_init(void)
|
|||||||
{
|
{
|
||||||
int rc = -1;
|
int rc = -1;
|
||||||
|
|
||||||
zlog_info("SR (%s): Initialize SR Data Base", __func__);
|
if (IS_DEBUG_OSPF_SR)
|
||||||
|
zlog_info("SR (%s): Initialize SR Data Base", __func__);
|
||||||
|
|
||||||
memset(&OspfSR, 0, sizeof(struct ospf_sr_db));
|
memset(&OspfSR, 0, sizeof(struct ospf_sr_db));
|
||||||
OspfSR.enabled = false;
|
OspfSR.enabled = false;
|
||||||
@ -675,6 +677,7 @@ static int ospf_zebra_send_mpls_ftn(int cmd, struct sr_nhlfe nhlfe)
|
|||||||
SET_FLAG(api.message, ZAPI_MESSAGE_LABEL);
|
SET_FLAG(api.message, ZAPI_MESSAGE_LABEL);
|
||||||
api_nh->labels[0] = nhlfe.label_out;
|
api_nh->labels[0] = nhlfe.label_out;
|
||||||
api_nh->label_num = 1;
|
api_nh->label_num = 1;
|
||||||
|
api_nh->vrf_id = VRF_DEFAULT;
|
||||||
api.nexthop_num = 1;
|
api.nexthop_num = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1616,11 +1619,11 @@ static int ospf_sr_update_schedule(struct thread *t)
|
|||||||
|
|
||||||
monotime(&stop_time);
|
monotime(&stop_time);
|
||||||
|
|
||||||
zlog_info(
|
if (IS_DEBUG_OSPF_SR)
|
||||||
"SR (%s): SPF Processing Time(usecs): %lld\n",
|
zlog_debug("SR (%s): SPF Processing Time(usecs): %lld\n",
|
||||||
__func__,
|
__func__,
|
||||||
(stop_time.tv_sec - start_time.tv_sec) * 1000000LL
|
(stop_time.tv_sec - start_time.tv_sec) * 1000000LL
|
||||||
+ (stop_time.tv_usec - start_time.tv_usec));
|
+ (stop_time.tv_usec - start_time.tv_usec));
|
||||||
|
|
||||||
OspfSR.update = false;
|
OspfSR.update = false;
|
||||||
return 1;
|
return 1;
|
||||||
@ -2128,91 +2131,197 @@ DEFUN (no_sr_prefix_sid,
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void show_vty_sr_node(struct vty *vty, struct sr_node *srn)
|
static void show_sr_node(struct vty *vty, struct json_object *json,
|
||||||
|
struct sr_node *srn)
|
||||||
{
|
{
|
||||||
|
|
||||||
struct listnode *node;
|
struct listnode *node;
|
||||||
struct sr_link *srl;
|
struct sr_link *srl;
|
||||||
struct sr_prefix *srp;
|
struct sr_prefix *srp;
|
||||||
struct interface *itf;
|
struct interface *itf;
|
||||||
char pref[16];
|
char pref[19];
|
||||||
char sid[22];
|
char sid[22];
|
||||||
char label[8];
|
char label[8];
|
||||||
|
json_object *json_node = NULL, *json_algo, *json_obj;
|
||||||
|
json_object *json_prefix = NULL, *json_link = NULL;
|
||||||
|
|
||||||
/* Sanity Check */
|
/* Sanity Check */
|
||||||
if (srn == NULL)
|
if (srn == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
vty_out(vty, "SR-Node: %s", inet_ntoa(srn->adv_router));
|
if (json) {
|
||||||
vty_out(vty, "\tSRGB (Size/Label): %u/%u", srn->srgb.range_size,
|
json_node = json_object_new_object();
|
||||||
srn->srgb.lower_bound);
|
json_object_string_add(json_node, "routerID",
|
||||||
vty_out(vty, "\tAlgorithm(s): %s",
|
inet_ntoa(srn->adv_router));
|
||||||
srn->algo[0] == SR_ALGORITHM_SPF ? "SPF" : "S-SPF");
|
json_object_int_add(json_node, "srgbSize",
|
||||||
for (int i = 1; i < ALGORITHM_COUNT; i++) {
|
srn->srgb.range_size);
|
||||||
if (srn->algo[i] == SR_ALGORITHM_UNSET)
|
json_object_int_add(json_node, "srgbLabel",
|
||||||
continue;
|
srn->srgb.lower_bound);
|
||||||
vty_out(vty, "/%s",
|
json_algo = json_object_new_array();
|
||||||
srn->algo[i] == SR_ALGORITHM_SPF ? "SPF" : "S-SPF");
|
json_object_object_add(json_node, "algorithms", json_algo);
|
||||||
}
|
for (int i = 0; i < ALGORITHM_COUNT; i++) {
|
||||||
if (srn->msd != 0)
|
if (srn->algo[i] == SR_ALGORITHM_UNSET)
|
||||||
vty_out(vty, "\tMSD: %u", srn->msd);
|
continue;
|
||||||
|
json_obj = json_object_new_object();
|
||||||
|
char tmp[2];
|
||||||
|
|
||||||
vty_out(vty,
|
snprintf(tmp, 2, "%u", i);
|
||||||
"\n\n Prefix or Link Label In Label Out "
|
json_object_string_add(json_obj, tmp,
|
||||||
"Node or Adj. SID Interface Nexthop\n");
|
srn->algo[i] == SR_ALGORITHM_SPF ?
|
||||||
vty_out(vty,
|
"SPF" : "S-SPF");
|
||||||
"------------------ -------- --------- "
|
json_object_array_add(json_algo, json_obj);
|
||||||
"--------------------- --------- ---------------\n");
|
}
|
||||||
|
if (srn->msd != 0)
|
||||||
|
json_object_int_add(json_node, "nodeMsd", srn->msd);
|
||||||
|
} else {
|
||||||
|
vty_out(vty, "SR-Node: %s", inet_ntoa(srn->adv_router));
|
||||||
|
vty_out(vty, "\tSRGB (Size/Label): %u/%u",
|
||||||
|
srn->srgb.range_size, srn->srgb.lower_bound);
|
||||||
|
vty_out(vty, "\tAlgorithm(s): %s",
|
||||||
|
srn->algo[0] == SR_ALGORITHM_SPF ? "SPF" : "S-SPF");
|
||||||
|
for (int i = 1; i < ALGORITHM_COUNT; i++) {
|
||||||
|
if (srn->algo[i] == SR_ALGORITHM_UNSET)
|
||||||
|
continue;
|
||||||
|
vty_out(vty, "/%s",
|
||||||
|
srn->algo[i] == SR_ALGORITHM_SPF ?
|
||||||
|
"SPF" : "S-SPF");
|
||||||
|
}
|
||||||
|
if (srn->msd != 0)
|
||||||
|
vty_out(vty, "\tMSD: %u", srn->msd);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!json) {
|
||||||
|
vty_out(vty,
|
||||||
|
"\n\n Prefix or Link Label In Label Out "
|
||||||
|
"Node or Adj. SID Interface Nexthop\n");
|
||||||
|
vty_out(vty,
|
||||||
|
"------------------ -------- --------- "
|
||||||
|
"--------------------- --------- ---------------\n");
|
||||||
|
}
|
||||||
for (ALL_LIST_ELEMENTS_RO(srn->ext_prefix, node, srp)) {
|
for (ALL_LIST_ELEMENTS_RO(srn->ext_prefix, node, srp)) {
|
||||||
strncpy(pref, inet_ntoa(srp->nhlfe.prefv4.prefix), 16);
|
snprintf(pref, 19, "%s/%u",
|
||||||
|
inet_ntoa(srp->nhlfe.prefv4.prefix),
|
||||||
|
srp->nhlfe.prefv4.prefixlen);
|
||||||
snprintf(sid, 22, "SR Pfx (idx %u)", srp->sid);
|
snprintf(sid, 22, "SR Pfx (idx %u)", srp->sid);
|
||||||
if (srp->nhlfe.label_out == MPLS_LABEL_IMPLICIT_NULL)
|
if (srp->nhlfe.label_out == MPLS_LABEL_IMPLICIT_NULL)
|
||||||
sprintf(label, "pop");
|
sprintf(label, "pop");
|
||||||
else
|
else
|
||||||
sprintf(label, "%u", srp->nhlfe.label_out);
|
sprintf(label, "%u", srp->nhlfe.label_out);
|
||||||
itf = if_lookup_by_index(srp->nhlfe.ifindex, VRF_DEFAULT);
|
itf = if_lookup_by_index(srp->nhlfe.ifindex, VRF_DEFAULT);
|
||||||
vty_out(vty, "%15s/%u %8u %9s %21s %9s %15s\n", pref,
|
if (json) {
|
||||||
srp->nhlfe.prefv4.prefixlen, srp->nhlfe.label_in, label,
|
if (!json_prefix) {
|
||||||
sid, itf ? itf->name : "-",
|
json_prefix = json_object_new_array();
|
||||||
inet_ntoa(srp->nhlfe.nexthop));
|
json_object_object_add(json_node,
|
||||||
|
"extendedPrefix", json_prefix);
|
||||||
|
}
|
||||||
|
json_obj = json_object_new_object();
|
||||||
|
json_object_string_add(json_obj, "prefix", pref);
|
||||||
|
json_object_int_add(json_obj, "sid", srp->sid);
|
||||||
|
json_object_int_add(json_obj, "inputLabel",
|
||||||
|
srp->nhlfe.label_in);
|
||||||
|
json_object_string_add(json_obj, "outputLabel",
|
||||||
|
label);
|
||||||
|
json_object_string_add(json_obj, "interface",
|
||||||
|
itf ? itf->name : "-");
|
||||||
|
json_object_string_add(json_obj, "nexthop",
|
||||||
|
inet_ntoa(srp->nhlfe.nexthop));
|
||||||
|
json_object_array_add(json_prefix, json_obj);
|
||||||
|
} else {
|
||||||
|
vty_out(vty, "%18s %8u %9s %21s %9s %15s\n",
|
||||||
|
pref, srp->nhlfe.label_in, label,
|
||||||
|
sid, itf ? itf->name : "-",
|
||||||
|
inet_ntoa(srp->nhlfe.nexthop));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (ALL_LIST_ELEMENTS_RO(srn->ext_link, node, srl)) {
|
for (ALL_LIST_ELEMENTS_RO(srn->ext_link, node, srl)) {
|
||||||
strncpy(pref, inet_ntoa(srl->nhlfe[0].prefv4.prefix), 16);
|
snprintf(pref, 19, "%s/%u",
|
||||||
|
inet_ntoa(srl->nhlfe[0].prefv4.prefix),
|
||||||
|
srl->nhlfe[0].prefv4.prefixlen);
|
||||||
snprintf(sid, 22, "SR Adj. (lbl %u)", srl->sid[0]);
|
snprintf(sid, 22, "SR Adj. (lbl %u)", srl->sid[0]);
|
||||||
if (srl->nhlfe[0].label_out == MPLS_LABEL_IMPLICIT_NULL)
|
if (srl->nhlfe[0].label_out == MPLS_LABEL_IMPLICIT_NULL)
|
||||||
sprintf(label, "pop");
|
sprintf(label, "pop");
|
||||||
else
|
else
|
||||||
sprintf(label, "%u", srl->nhlfe[0].label_out);
|
sprintf(label, "%u", srl->nhlfe[0].label_out);
|
||||||
itf = if_lookup_by_index(srl->nhlfe[0].ifindex, VRF_DEFAULT);
|
itf = if_lookup_by_index(srl->nhlfe[0].ifindex, VRF_DEFAULT);
|
||||||
vty_out(vty, "%15s/%u %8u %9s %21s %9s %15s\n", pref,
|
if (json) {
|
||||||
srl->nhlfe[0].prefv4.prefixlen, srl->nhlfe[0].label_in,
|
if (!json_link) {
|
||||||
label, sid, itf ? itf->name : "-",
|
json_link = json_object_new_array();
|
||||||
inet_ntoa(srl->nhlfe[0].nexthop));
|
json_object_object_add(json_node,
|
||||||
snprintf(sid, 22, "SR Adj. (lbl %u)", srl->sid[1]);
|
"extendedLink", json_link);
|
||||||
if (srl->nhlfe[1].label_out == MPLS_LABEL_IMPLICIT_NULL)
|
}
|
||||||
sprintf(label, "pop");
|
/* Primary Link */
|
||||||
else
|
json_obj = json_object_new_object();
|
||||||
sprintf(label, "%u", srl->nhlfe[0].label_out);
|
json_object_string_add(json_obj, "prefix", pref);
|
||||||
vty_out(vty, "%15s/%u %8u %9s %21s %9s %15s\n", pref,
|
json_object_int_add(json_obj, "sid", srl->sid[0]);
|
||||||
srl->nhlfe[1].prefv4.prefixlen, srl->nhlfe[1].label_in,
|
json_object_int_add(json_obj, "inputLabel",
|
||||||
label, sid, itf ? itf->name : "-",
|
srl->nhlfe[0].label_in);
|
||||||
inet_ntoa(srl->nhlfe[1].nexthop));
|
json_object_string_add(json_obj, "outputLabel",
|
||||||
|
label);
|
||||||
|
json_object_string_add(json_obj, "interface",
|
||||||
|
itf ? itf->name : "-");
|
||||||
|
json_object_string_add(json_obj, "nexthop",
|
||||||
|
inet_ntoa(srl->nhlfe[0].nexthop));
|
||||||
|
json_object_array_add(json_link, json_obj);
|
||||||
|
/* Backup Link */
|
||||||
|
json_obj = json_object_new_object();
|
||||||
|
snprintf(sid, 22, "SR Adj. (lbl %u)", srl->sid[1]);
|
||||||
|
if (srl->nhlfe[1].label_out == MPLS_LABEL_IMPLICIT_NULL)
|
||||||
|
sprintf(label, "pop");
|
||||||
|
else
|
||||||
|
sprintf(label, "%u", srl->nhlfe[0].label_out);
|
||||||
|
json_object_string_add(json_obj, "prefix", pref);
|
||||||
|
json_object_int_add(json_obj, "sid", srl->sid[1]);
|
||||||
|
json_object_int_add(json_obj, "inputLabel",
|
||||||
|
srl->nhlfe[1].label_in);
|
||||||
|
json_object_string_add(json_obj, "outputLabel",
|
||||||
|
label);
|
||||||
|
json_object_string_add(json_obj, "interface",
|
||||||
|
itf ? itf->name : "-");
|
||||||
|
json_object_string_add(json_obj, "nexthop",
|
||||||
|
inet_ntoa(srl->nhlfe[1].nexthop));
|
||||||
|
json_object_array_add(json_link, json_obj);
|
||||||
|
} else {
|
||||||
|
vty_out(vty, "%18s %8u %9s %21s %9s %15s\n",
|
||||||
|
pref, srl->nhlfe[0].label_in,
|
||||||
|
label, sid, itf ? itf->name : "-",
|
||||||
|
inet_ntoa(srl->nhlfe[0].nexthop));
|
||||||
|
snprintf(sid, 22, "SR Adj. (lbl %u)", srl->sid[1]);
|
||||||
|
if (srl->nhlfe[1].label_out == MPLS_LABEL_IMPLICIT_NULL)
|
||||||
|
sprintf(label, "pop");
|
||||||
|
else
|
||||||
|
sprintf(label, "%u", srl->nhlfe[1].label_out);
|
||||||
|
vty_out(vty, "%18s %8u %9s %21s %9s %15s\n",
|
||||||
|
pref, srl->nhlfe[1].label_in,
|
||||||
|
label, sid, itf ? itf->name : "-",
|
||||||
|
inet_ntoa(srl->nhlfe[1].nexthop));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
vty_out(vty, "\n");
|
if (json)
|
||||||
|
json_object_array_add(json, json_node);
|
||||||
|
else
|
||||||
|
vty_out(vty, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void show_srdb_entry(struct hash_backet *backet, void *args)
|
static void show_vty_srdb(struct hash_backet *backet, void *args)
|
||||||
{
|
{
|
||||||
struct vty *vty = (struct vty *)args;
|
struct vty *vty = (struct vty *)args;
|
||||||
struct sr_node *srn = (struct sr_node *)backet->data;
|
struct sr_node *srn = (struct sr_node *)backet->data;
|
||||||
|
|
||||||
show_vty_sr_node(vty, srn);
|
show_sr_node(vty, NULL, srn);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void show_json_srdb(struct hash_backet *backet, void *args)
|
||||||
|
{
|
||||||
|
struct json_object *json = (struct json_object *)args;
|
||||||
|
struct sr_node *srn = (struct sr_node *)backet->data;
|
||||||
|
|
||||||
|
show_sr_node(NULL, json, srn);
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFUN (show_ip_opsf_srdb,
|
DEFUN (show_ip_opsf_srdb,
|
||||||
show_ip_ospf_srdb_cmd,
|
show_ip_ospf_srdb_cmd,
|
||||||
"show ip ospf database segment-routing [adv-router A.B.C.D|self-originate]",
|
"show ip ospf database segment-routing [adv-router A.B.C.D|self-originate] [json]",
|
||||||
SHOW_STR
|
SHOW_STR
|
||||||
IP_STR
|
IP_STR
|
||||||
OSPF_STR
|
OSPF_STR
|
||||||
@ -2220,23 +2329,41 @@ DEFUN (show_ip_opsf_srdb,
|
|||||||
"Show Segment Routing Data Base\n"
|
"Show Segment Routing Data Base\n"
|
||||||
"Advertising SR node\n"
|
"Advertising SR node\n"
|
||||||
"Advertising SR node ID (as an IP address)\n"
|
"Advertising SR node ID (as an IP address)\n"
|
||||||
"Self-originated SR node\n")
|
"Self-originated SR node\n"
|
||||||
|
JSON_STR)
|
||||||
{
|
{
|
||||||
int idx = 0;
|
int idx = 0;
|
||||||
struct in_addr rid;
|
struct in_addr rid;
|
||||||
struct sr_node *srn;
|
struct sr_node *srn;
|
||||||
|
u_char uj = use_json(argc, argv);
|
||||||
|
json_object *json = NULL, *json_node_array = NULL;
|
||||||
|
|
||||||
if (!OspfSR.enabled) {
|
if (!OspfSR.enabled) {
|
||||||
vty_out(vty, "Segment Routing is disabled on this router\n");
|
vty_out(vty, "Segment Routing is disabled on this router\n");
|
||||||
return CMD_WARNING;
|
return CMD_WARNING;
|
||||||
}
|
}
|
||||||
|
|
||||||
vty_out(vty, "\n OSPF Segment Routing database for ID %s\n\n",
|
if (uj) {
|
||||||
inet_ntoa(OspfSR.self->adv_router));
|
json = json_object_new_object();
|
||||||
|
json_node_array = json_object_new_array();
|
||||||
|
json_object_string_add(json, "srdbID",
|
||||||
|
inet_ntoa(OspfSR.self->adv_router));
|
||||||
|
json_object_object_add(json, "srNodes", json_node_array);
|
||||||
|
} else {
|
||||||
|
vty_out(vty,
|
||||||
|
"\n\t\tOSPF Segment Routing database for ID %s\n\n",
|
||||||
|
inet_ntoa(OspfSR.self->adv_router));
|
||||||
|
}
|
||||||
|
|
||||||
if (argv_find(argv, argc, "self-originate", &idx)) {
|
if (argv_find(argv, argc, "self-originate", &idx)) {
|
||||||
srn = OspfSR.self;
|
srn = OspfSR.self;
|
||||||
show_vty_sr_node(vty, srn);
|
show_sr_node(vty, json_node_array, srn);
|
||||||
|
if (uj) {
|
||||||
|
vty_out(vty, "%s\n",
|
||||||
|
json_object_to_json_string_ext(json,
|
||||||
|
JSON_C_TO_STRING_PRETTY));
|
||||||
|
json_object_free(json);
|
||||||
|
}
|
||||||
return CMD_SUCCESS;
|
return CMD_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2250,15 +2377,32 @@ DEFUN (show_ip_opsf_srdb,
|
|||||||
/* Get the SR Node from the SRDB */
|
/* Get the SR Node from the SRDB */
|
||||||
srn = (struct sr_node *)hash_lookup(OspfSR.neighbors,
|
srn = (struct sr_node *)hash_lookup(OspfSR.neighbors,
|
||||||
(void *)&rid);
|
(void *)&rid);
|
||||||
show_vty_sr_node(vty, srn);
|
show_sr_node(vty, json_node_array, srn);
|
||||||
|
if (uj) {
|
||||||
|
vty_out(vty, "%s\n",
|
||||||
|
json_object_to_json_string_ext(json,
|
||||||
|
JSON_C_TO_STRING_PRETTY));
|
||||||
|
json_object_free(json);
|
||||||
|
}
|
||||||
return CMD_SUCCESS;
|
return CMD_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* No parameters have been provided, Iterate through all the SRDB */
|
/* No parameters have been provided, Iterate through all the SRDB */
|
||||||
hash_iterate(
|
if (uj) {
|
||||||
OspfSR.neighbors,
|
hash_iterate(
|
||||||
(void (*)(struct hash_backet *, void *))show_srdb_entry,
|
OspfSR.neighbors,
|
||||||
(void *)vty);
|
(void (*)(struct hash_backet *, void *))show_json_srdb,
|
||||||
|
(void *)json_node_array);
|
||||||
|
vty_out(vty, "%s\n",
|
||||||
|
json_object_to_json_string_ext(json,
|
||||||
|
JSON_C_TO_STRING_PRETTY));
|
||||||
|
json_object_free(json);
|
||||||
|
} else {
|
||||||
|
hash_iterate(
|
||||||
|
OspfSR.neighbors,
|
||||||
|
(void (*)(struct hash_backet *, void *))show_vty_srdb,
|
||||||
|
(void *)vty);
|
||||||
|
}
|
||||||
return CMD_SUCCESS;
|
return CMD_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
4
tests/.gitignore
vendored
4
tests/.gitignore
vendored
@ -24,10 +24,12 @@ __pycache__
|
|||||||
/bgpd/test_ecommunity
|
/bgpd/test_ecommunity
|
||||||
/bgpd/test_mp_attr
|
/bgpd/test_mp_attr
|
||||||
/bgpd/test_mpath
|
/bgpd/test_mpath
|
||||||
|
/bgpd/test_packet
|
||||||
/isisd/test_fuzz_isis_tlv
|
/isisd/test_fuzz_isis_tlv
|
||||||
/isisd/test_fuzz_isis_tlv_tests.h
|
/isisd/test_fuzz_isis_tlv_tests.h
|
||||||
/isisd/test_isis_vertex_queue
|
/isisd/test_isis_vertex_queue
|
||||||
/lib/cli/test_cli
|
/lib/cli/test_cli
|
||||||
|
/lib/cli/test_cli_clippy.c
|
||||||
/lib/cli/test_commands
|
/lib/cli/test_commands
|
||||||
/lib/cli/test_commands_defun.c
|
/lib/cli/test_commands_defun.c
|
||||||
/lib/test_buffer
|
/lib/test_buffer
|
||||||
@ -38,6 +40,7 @@ __pycache__
|
|||||||
/lib/test_memory
|
/lib/test_memory
|
||||||
/lib/test_nexthop_iter
|
/lib/test_nexthop_iter
|
||||||
/lib/test_privs
|
/lib/test_privs
|
||||||
|
/lib/test_ringbuf
|
||||||
/lib/test_srcdest_table
|
/lib/test_srcdest_table
|
||||||
/lib/test_segv
|
/lib/test_segv
|
||||||
/lib/test_sig
|
/lib/test_sig
|
||||||
@ -48,3 +51,4 @@ __pycache__
|
|||||||
/lib/test_ttable
|
/lib/test_ttable
|
||||||
/lib/test_zmq
|
/lib/test_zmq
|
||||||
/ospf6d/test_lsdb
|
/ospf6d/test_lsdb
|
||||||
|
/ospf6d/test_lsdb_clippy.c
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
import frrtest
|
import frrtest
|
||||||
|
|
||||||
class TestRingbuf(frrtest.TestExitNonzero):
|
class TestRingbuf(frrtest.TestMultiOut):
|
||||||
program = './test_ringbuf'
|
program = './test_ringbuf'
|
||||||
|
|
||||||
|
TestRingbuf.exit_cleanly()
|
||||||
|
@ -1166,12 +1166,12 @@ static int zread_route_add(struct zserv *client, u_short length,
|
|||||||
switch (api_nh->type) {
|
switch (api_nh->type) {
|
||||||
case NEXTHOP_TYPE_IFINDEX:
|
case NEXTHOP_TYPE_IFINDEX:
|
||||||
nexthop = route_entry_nexthop_ifindex_add(
|
nexthop = route_entry_nexthop_ifindex_add(
|
||||||
re, api_nh->ifindex, re->vrf_id);
|
re, api_nh->ifindex, api_nh->vrf_id);
|
||||||
break;
|
break;
|
||||||
case NEXTHOP_TYPE_IPV4:
|
case NEXTHOP_TYPE_IPV4:
|
||||||
nexthop = route_entry_nexthop_ipv4_add(
|
nexthop = route_entry_nexthop_ipv4_add(
|
||||||
re, &api_nh->gate.ipv4, NULL,
|
re, &api_nh->gate.ipv4, NULL,
|
||||||
re->vrf_id);
|
api_nh->vrf_id);
|
||||||
break;
|
break;
|
||||||
case NEXTHOP_TYPE_IPV4_IFINDEX: {
|
case NEXTHOP_TYPE_IPV4_IFINDEX: {
|
||||||
|
|
||||||
@ -1188,7 +1188,7 @@ static int zread_route_add(struct zserv *client, u_short length,
|
|||||||
|
|
||||||
nexthop = route_entry_nexthop_ipv4_ifindex_add(
|
nexthop = route_entry_nexthop_ipv4_ifindex_add(
|
||||||
re, &api_nh->gate.ipv4, NULL, ifindex,
|
re, &api_nh->gate.ipv4, NULL, ifindex,
|
||||||
re->vrf_id);
|
api_nh->vrf_id);
|
||||||
|
|
||||||
/* if this an EVPN route entry,
|
/* if this an EVPN route entry,
|
||||||
program the nh as neigh
|
program the nh as neigh
|
||||||
@ -1211,12 +1211,12 @@ static int zread_route_add(struct zserv *client, u_short length,
|
|||||||
}
|
}
|
||||||
case NEXTHOP_TYPE_IPV6:
|
case NEXTHOP_TYPE_IPV6:
|
||||||
nexthop = route_entry_nexthop_ipv6_add(
|
nexthop = route_entry_nexthop_ipv6_add(
|
||||||
re, &api_nh->gate.ipv6, re->vrf_id);
|
re, &api_nh->gate.ipv6, api_nh->vrf_id);
|
||||||
break;
|
break;
|
||||||
case NEXTHOP_TYPE_IPV6_IFINDEX:
|
case NEXTHOP_TYPE_IPV6_IFINDEX:
|
||||||
nexthop = route_entry_nexthop_ipv6_ifindex_add(
|
nexthop = route_entry_nexthop_ipv6_ifindex_add(
|
||||||
re, &api_nh->gate.ipv6, api_nh->ifindex,
|
re, &api_nh->gate.ipv6, api_nh->ifindex,
|
||||||
re->vrf_id);
|
api_nh->vrf_id);
|
||||||
break;
|
break;
|
||||||
case NEXTHOP_TYPE_BLACKHOLE:
|
case NEXTHOP_TYPE_BLACKHOLE:
|
||||||
nexthop = route_entry_nexthop_blackhole_add(
|
nexthop = route_entry_nexthop_blackhole_add(
|
||||||
|
Loading…
Reference in New Issue
Block a user