unsigned long conf_bgp_debug_evpn_mh;
unsigned long conf_bgp_debug_bfd;
unsigned long conf_bgp_debug_cond_adv;
-unsigned long conf_bgp_debug_optimal_route_reflection;
unsigned long term_bgp_debug_as4;
unsigned long term_bgp_debug_neighbor_events;
unsigned long term_bgp_debug_evpn_mh;
unsigned long term_bgp_debug_bfd;
unsigned long term_bgp_debug_cond_adv;
-unsigned long term_bgp_debug_optimal_route_reflection;
struct list *bgp_debug_neighbor_events_peers = NULL;
struct list *bgp_debug_keepalive_peers = NULL;
return CMD_SUCCESS;
}
-DEFPY (debug_bgp_optimal_route_reflection,
- debug_bgp_optimal_route_reflection_cmd,
- "[no$no] debug bgp optimal-route-reflection",
- NO_STR
- DEBUG_STR
- BGP_STR
- BGP_ORR_DEBUG)
-{
- if (vty->node == CONFIG_NODE) {
- if (no)
- DEBUG_OFF(optimal_route_reflection, ORR);
- else
- DEBUG_ON(optimal_route_reflection, ORR);
- } else {
- if (no) {
- TERM_DEBUG_OFF(optimal_route_reflection, ORR);
- vty_out(vty,
- "BGP Optimal Route Reflection debugging is off\n");
- } else {
- TERM_DEBUG_ON(optimal_route_reflection, ORR);
- vty_out(vty,
- "BGP Optimal Route Reflection debugging is on\n");
- }
- }
- return CMD_SUCCESS;
-}
-
DEFUN (debug_bgp_labelpool,
debug_bgp_labelpool_cmd,
"debug bgp labelpool",
TERM_DEBUG_OFF(evpn_mh, EVPN_MH_RT);
TERM_DEBUG_OFF(bfd, BFD_LIB);
TERM_DEBUG_OFF(cond_adv, COND_ADV);
- TERM_DEBUG_OFF(optimal_route_reflection, ORR);
vty_out(vty, "All possible debugging has been turned off\n");
vty_out(vty,
" BGP conditional advertisement debugging is on\n");
- if (BGP_DEBUG(optimal_route_reflection, ORR))
- vty_out(vty,
- " BGP Optimal Route Reflection debugging is on\n");
-
cmd_show_lib_debugs(vty);
return CMD_SUCCESS;
write++;
}
- if (CONF_BGP_DEBUG(optimal_route_reflection, ORR)) {
- vty_out(vty, "debug bgp optimal-route-reflection\n");
- write++;
- }
-
return write;
}
/* debug bgp conditional advertisement */
install_element(ENABLE_NODE, &debug_bgp_cond_adv_cmd);
install_element(CONFIG_NODE, &debug_bgp_cond_adv_cmd);
-
- /* debug bgp optimal route reflection */
- install_element(ENABLE_NODE, &debug_bgp_optimal_route_reflection_cmd);
- install_element(CONFIG_NODE, &debug_bgp_optimal_route_reflection_cmd);
}
/* Return true if this prefix is on the per_prefix_list of prefixes to debug
extern unsigned long conf_bgp_debug_evpn_mh;
extern unsigned long conf_bgp_debug_bfd;
extern unsigned long conf_bgp_debug_cond_adv;
-extern unsigned long conf_bgp_debug_optimal_route_reflection;
extern unsigned long term_bgp_debug_as4;
extern unsigned long term_bgp_debug_neighbor_events;
extern unsigned long term_bgp_debug_evpn_mh;
extern unsigned long term_bgp_debug_bfd;
extern unsigned long term_bgp_debug_cond_adv;
-extern unsigned long term_bgp_debug_optimal_route_reflection;
extern struct list *bgp_debug_neighbor_events_peers;
extern struct list *bgp_debug_keepalive_peers;
#define BGP_DEBUG_PBR_ERROR 0x02
#define BGP_DEBUG_EVPN_MH_ES 0x01
#define BGP_DEBUG_EVPN_MH_RT 0x02
-#define BGP_DEBUG_ORR 0x01
#define BGP_DEBUG_PACKET_SEND 0x01
#define BGP_DEBUG_PACKET_SEND_DETAIL 0x02
&& bgp_update_delay_applicable(peer->bgp))
bgp_update_delay_process_status_change(peer);
- /* BGP ORR : Update Active Root */
- bgp_peer_update_orr_active_roots(peer);
-
if (bgp_debug_neighbor_events(peer))
zlog_debug("%s fd %d went from %s to %s", peer->host, peer->fd,
lookup_msg(bgp_status_msg, peer->ostatus, NULL),
const char *print_global_gr_mode(enum global_mode gl_mode);
const char *print_global_gr_cmd(enum global_gr_command gl_gr_cmd);
int bgp_peer_reg_with_nht(struct peer *peer);
-
-extern void bgp_peer_update_orr_active_roots(struct peer *peer);
#endif /* _QUAGGA_BGP_FSM_H */
DEFINE_MTYPE(BGPD, BGP_SRV6_L3VPN, "BGP prefix-sid srv6 l3vpn servcie");
DEFINE_MTYPE(BGPD, BGP_SRV6_VPN, "BGP prefix-sid srv6 vpn service");
-
DEFINE_MTYPE(BGPD, BGP_SRV6_SID, "BGP srv6 segment-id");
DEFINE_MTYPE(BGPD, BGP_SRV6_FUNCTION, "BGP srv6 function");
DEFINE_MTYPE(BGPD, EVPN_REMOTE_IP, "BGP EVPN Remote IP hash entry");
DEFINE_MTYPE(BGPD, BGP_NOTIFICATION, "BGP Notification Message");
-DEFINE_MTYPE(BGPD, BGP_ORR_GROUP, "BGP Optimal Route Reflection Group");
-DEFINE_MTYPE(BGPD, BGP_ORR_GROUP_NAME,
- "BGP Optimal Route Reflection Group Name");
DECLARE_MTYPE(EVPN_REMOTE_IP);
DECLARE_MTYPE(BGP_NOTIFICATION);
-DECLARE_MTYPE(BGP_ORR_GROUP);
-DECLARE_MTYPE(BGP_ORR_GROUP_NAME);
#endif /* _QUAGGA_BGP_MEMORY_H */
+++ /dev/null
-/*
- * BGP Optimal Route Reflection
- * Copyright (C) 2021 Samsung R&D Institute India - Bangalore.
- * Madhurilatha Kuruganti
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; see the file COPYING; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include <zebra.h>
-#include "bgpd/bgpd.h"
-#include "bgpd/bgp_debug.h"
-#include "bgpd/bgp_orr.h"
-#include "bgpd/bgp_vty.h"
-#include "zclient.h"
-
-DEFINE_MTYPE_STATIC(BGPD, ORR_IGP_INFO, "ORR IGP Metric info");
-
-static inline bool is_orr_primary_root(struct bgp_orr_group *orr_group,
- char *host)
-{
- return orr_group->primary && strmatch(orr_group->primary->host, host);
-}
-
-static inline bool is_orr_secondary_root(struct bgp_orr_group *orr_group,
- char *host)
-{
- return orr_group->secondary &&
- strmatch(orr_group->secondary->host, host);
-}
-
-static inline bool is_orr_tertiary_root(struct bgp_orr_group *orr_group,
- char *host)
-{
- return orr_group->tertiary && strmatch(orr_group->tertiary->host, host);
-}
-
-static inline bool is_orr_active_root(struct bgp_orr_group *orr_group,
- char *host)
-{
- return orr_group->active && strmatch(orr_group->active->host, host);
-}
-
-static inline bool is_orr_root_node(struct bgp_orr_group *orr_group, char *host)
-{
- return is_orr_primary_root(orr_group, host) ||
- is_orr_secondary_root(orr_group, host) ||
- is_orr_tertiary_root(orr_group, host);
-}
-
-static inline bool is_peer_orr_group_member(struct peer *peer, afi_t afi,
- safi_t safi, const char *name)
-{
- return peer_af_flag_check(peer, afi, safi, PEER_FLAG_ORR_GROUP) &&
- strmatch(peer->orr_group_name[afi][safi], name);
-}
-
-static inline bool is_peer_reachable(struct peer *peer, afi_t afi, safi_t safi)
-{
- return peer && peer->afc_nego[afi][safi] && peer_established(peer);
-}
-
-static inline bool is_peer_active_eligible(struct peer *peer, afi_t afi,
- safi_t safi, const char *name)
-{
- return is_peer_reachable(peer, afi, safi) &&
- is_peer_orr_group_member(peer, afi, safi, name);
-}
-
-static void bgp_orr_igp_metric_register(struct bgp_orr_group *orr_group,
- bool reg);
-
-static void
-bgp_peer_update_orr_group_active_root(struct peer *peer, afi_t afi, safi_t safi,
- struct bgp_orr_group *orr_group);
-
-static struct bgp_orr_group *bgp_orr_group_new(struct bgp *bgp, afi_t afi,
- safi_t safi, const char *name)
-{
- int ret;
- struct list *orr_group_list = NULL;
- struct bgp_orr_group *orr_group = NULL;
-
- assert(bgp && name);
-
- if (!bgp->orr_group[afi][safi])
- bgp->orr_group[afi][safi] = list_new();
-
- orr_group_list = bgp->orr_group[afi][safi];
- orr_group = XCALLOC(MTYPE_BGP_ORR_GROUP, sizeof(struct bgp_orr_group));
-
- listnode_add(orr_group_list, orr_group);
-
- orr_group->name = XSTRDUP(MTYPE_BGP_ORR_GROUP_NAME, name);
- orr_group->afi = afi;
- orr_group->safi = safi;
- orr_group->primary = orr_group->secondary = orr_group->tertiary = NULL;
- orr_group->bgp = bgp;
-
- /* Initialize ORR Group route table */
- orr_group->route_table = bgp_table_init(bgp, afi, safi);
- assert(orr_group->route_table);
-
- /*
- * Register for opaque messages from IGPs when first ORR group is
- * configured.
- */
- if (!bgp->orr_group_count) {
- ret = zclient_register_opaque(zclient, ORR_IGP_METRIC_UPDATE);
- if (ret != ZCLIENT_SEND_SUCCESS)
- bgp_orr_debug(
- "%s: zclient_register_opaque failed with ret = %d",
- __func__, ret);
- }
-
- bgp->orr_group_count++;
-
- return orr_group;
-}
-
-static void bgp_orr_group_free(struct bgp_orr_group *orr_group)
-{
- afi_t afi;
- safi_t safi;
- struct bgp *bgp;
-
- assert(orr_group && orr_group->bgp && orr_group->name);
-
- bgp_orr_debug("%s: Deleting ORR group %s", __func__, orr_group->name);
-
- afi = orr_group->afi;
- safi = orr_group->safi;
- bgp = orr_group->bgp;
-
- /*
- * Unregister with IGP for metric calculation from specified location
- * and delete igp_metric_info calculated for this group
- */
- bgp_orr_igp_metric_register(orr_group, false);
-
- /* Free RR client list associated with this ORR group */
- if (orr_group->rr_client_list)
- list_delete(&orr_group->rr_client_list);
-
- /* Free route table */
- bgp_table_unlock(orr_group->route_table);
- orr_group->route_table = NULL;
-
- /* Unset ORR Group parameters */
- XFREE(MTYPE_BGP_ORR_GROUP_NAME, orr_group->name);
-
- listnode_delete(bgp->orr_group[afi][safi], orr_group);
- XFREE(MTYPE_BGP_ORR_GROUP, orr_group);
-
- bgp->orr_group_count--;
-
- if (!bgp->orr_group[afi][safi]->count)
- list_delete(&bgp->orr_group[afi][safi]);
-}
-
-struct bgp_orr_group *bgp_orr_group_lookup_by_name(struct bgp *bgp, afi_t afi,
- safi_t safi,
- const char *name)
-{
- struct list *orr_group_list = NULL;
- struct bgp_orr_group *group = NULL;
- struct listnode *node;
-
- assert(bgp);
-
- orr_group_list = bgp->orr_group[afi][safi];
- if (!orr_group_list)
- return NULL;
-
- for (ALL_LIST_ELEMENTS_RO(orr_group_list, node, group))
- if (strmatch(group->name, name))
- return group;
-
- bgp_orr_debug("%s: For %s, ORR Group '%s' not found.", __func__,
- get_afi_safi_str(afi, safi, false), name);
-
- return NULL;
-}
-
-static char *bgp_orr_group_rrclient_lookup(struct bgp_orr_group *orr_group,
- const char *rr_client_host)
-{
- char *rrclient = NULL;
- struct list *orr_group_rrclient_list = NULL;
- struct listnode *node;
-
- orr_group_rrclient_list = orr_group->rr_client_list;
- if (!orr_group_rrclient_list)
- return NULL;
-
- for (ALL_LIST_ELEMENTS_RO(orr_group_rrclient_list, node, rrclient))
- if (strmatch(rrclient, rr_client_host))
- return rrclient;
-
- bgp_orr_debug(
- "%s: For %s, %s not found in ORR Group '%s' RR Client list",
- __func__,
- get_afi_safi_str(orr_group->afi, orr_group->safi, false),
- rr_client_host, orr_group->name);
-
- return NULL;
-}
-
-static void bgp_orr_group_rrclient_update(struct peer *peer, afi_t afi,
- safi_t safi,
- const char *orr_group_name, bool add)
-{
- char *rr_client = NULL;
- struct bgp_orr_group *orr_group = NULL;
- struct list *rr_client_list = NULL;
-
- assert(peer && peer->bgp && orr_group_name);
-
- /* Get BGP ORR entry for the given address-family */
- orr_group = bgp_orr_group_lookup_by_name(peer->bgp, afi, safi,
- orr_group_name);
- if (!orr_group) {
- bgp_orr_debug("%s: For %s, ORR Group '%s' not found.", __func__,
- get_afi_safi_str(afi, safi, false),
- orr_group_name);
- return;
- }
-
- /* Get BGP ORR client entry for the given RR client */
- rr_client = bgp_orr_group_rrclient_lookup(orr_group, peer->host);
-
- /* Nothing to do */
- if ((rr_client && add) || (!rr_client && !add))
- return;
-
- if (add) {
- /* Create BGP ORR RR client entry to the ORR Group */
- if (!orr_group->rr_client_list)
- orr_group->rr_client_list = list_new();
- rr_client_list = orr_group->rr_client_list;
- rr_client = XSTRDUP(MTYPE_BGP_PEER_HOST, peer->host);
-
- listnode_add(rr_client_list, rr_client);
-
- bgp_orr_debug(
- "%s: For %s, %pBP is added to ORR Group '%s' RR Client list.",
- __func__, get_afi_safi_str(afi, safi, false), peer,
- orr_group_name);
- } else {
- /* Delete BGP ORR RR client entry from the ORR Group */
- listnode_delete(orr_group->rr_client_list, rr_client);
- XFREE(MTYPE_BGP_PEER_HOST, rr_client);
- if (!orr_group->rr_client_list->count)
- list_delete(&orr_group->rr_client_list);
-
- bgp_orr_debug(
- "%s: For %s, %pBP is removed from ORR Group '%s' RR Client list.",
- __func__, get_afi_safi_str(afi, safi, false), peer,
- orr_group_name);
- }
-}
-
-/* Create/Update BGP Optimal Route Reflection Group */
-int bgp_afi_safi_orr_group_set(struct bgp *bgp, afi_t afi, safi_t safi,
- const char *name, struct peer *primary,
- struct peer *secondary, struct peer *tertiary)
-{
- bool primary_eligible = false;
- bool secondary_eligible = false;
- bool tertiary_eligible = false;
- struct bgp_orr_group *orr_group = NULL;
-
- bgp_orr_debug(
- "%s: For %s, ORR Group '%s' Primary %pBP Secondary %pBP Tertiary %pBP",
- __func__, get_afi_safi_str(afi, safi, false), name, primary,
- secondary, tertiary);
-
- /* Get BGP ORR entry for the given address-family */
- orr_group = bgp_orr_group_lookup_by_name(bgp, afi, safi, name);
- if (!orr_group) {
- /* Create BGP ORR entry for the given address-family */
- orr_group = bgp_orr_group_new(bgp, afi, safi, name);
- }
-
- /* Compare and update Primary Root Address */
- if (primary) {
- if (!orr_group->primary ||
- !strmatch(orr_group->primary->host, primary->host))
- orr_group->primary = primary;
- else
- bgp_orr_debug("%s: No change in Primary Root",
- __func__);
-
- /*
- * Update Active Root if there is a change and primary is
- * reachable.
- */
- primary_eligible =
- is_peer_active_eligible(primary, afi, safi, name);
- if (!orr_group->active) {
- orr_group->active = primary;
- bgp_orr_igp_metric_register(orr_group, true);
- } else if (orr_group->primary &&
- !strmatch(orr_group->active->host,
- orr_group->primary->host)) {
- bgp_orr_igp_metric_register(orr_group, false);
- orr_group->active = primary;
- bgp_orr_igp_metric_register(orr_group, true);
- } else
- bgp_orr_debug("%s: %s", __func__,
- orr_group->primary
- ? "No change in Active Root"
- : "Primary Root is NULL");
- } else {
- if (orr_group->primary) {
- if (orr_group->active &&
- strmatch(orr_group->active->host,
- orr_group->primary->host)) {
- bgp_orr_igp_metric_register(orr_group, false);
-
- orr_group->active = NULL;
- }
- orr_group->primary = NULL;
- }
- }
-
- /* Compare and update Secondary Root Address */
- if (secondary) {
- if (!orr_group->secondary ||
- !strmatch(orr_group->secondary->host, secondary->host))
- orr_group->secondary = secondary;
- else
- bgp_orr_debug("%s: No change in Secondary Root",
- __func__);
-
- /* Update Active Root if Primary is not reachable */
- secondary_eligible =
- is_peer_active_eligible(secondary, afi, safi, name);
- if (!orr_group->active) {
- orr_group->active = secondary;
- bgp_orr_igp_metric_register(orr_group, true);
- } else if (!primary_eligible && orr_group->secondary &&
- !strmatch(orr_group->active->host,
- orr_group->secondary->host)) {
- bgp_orr_igp_metric_register(orr_group, false);
- orr_group->active = secondary;
- bgp_orr_igp_metric_register(orr_group, true);
- } else
- bgp_orr_debug(
- "%s: %s", __func__,
- primary_eligible
- ? "Primary is Active Root"
- : orr_group->secondary
- ? "No change in Active Root"
- : "Secondary Root is NULL");
- } else {
- if (orr_group->secondary) {
- if (orr_group->active &&
- strmatch(orr_group->active->host,
- orr_group->secondary->host)) {
- bgp_orr_igp_metric_register(orr_group, false);
-
- orr_group->active = NULL;
- }
- orr_group->secondary = NULL;
- }
- }
-
- /* Compare and update Tertiary Root Address */
- if (tertiary) {
- if (!orr_group->tertiary ||
- !strmatch(orr_group->tertiary->host, tertiary->host))
- orr_group->tertiary = tertiary;
- else
- bgp_orr_debug("%s: No change in Tertiay Root",
- __func__);
-
- /*
- * Update Active Root if Primary & Secondary are not reachable
- */
- tertiary_eligible =
- is_peer_active_eligible(tertiary, afi, safi, name);
- if (!orr_group->active) {
- orr_group->active = tertiary;
- bgp_orr_igp_metric_register(orr_group, true);
- } else if (!primary_eligible && !secondary_eligible &&
- orr_group->tertiary &&
- !strmatch(orr_group->active->host,
- orr_group->tertiary->host)) {
- bgp_orr_igp_metric_register(orr_group, false);
-
- orr_group->active = tertiary;
- bgp_orr_igp_metric_register(orr_group, true);
- } else
- bgp_orr_debug(
- "%s: %s", __func__,
- primary_eligible
- ? "Primary is Active Root"
- : secondary_eligible
- ? "Secondary is Active Root"
- : !orr_group->tertiary
- ? "Tertiary Root is NULL"
- : "No change in Active Root");
- } else {
- if (orr_group->tertiary) {
- if (orr_group->active &&
- strmatch(orr_group->active->host,
- orr_group->tertiary->host)) {
- bgp_orr_igp_metric_register(orr_group, false);
-
- orr_group->active = NULL;
- }
- orr_group->tertiary = NULL;
- }
- }
-
- if (orr_group->active && !primary_eligible && !secondary_eligible &&
- !tertiary_eligible) {
- bgp_orr_igp_metric_register(orr_group, false);
-
- orr_group->active = NULL;
- }
-
- bgp_orr_debug("%s: For %s, ORR Group '%s' Active Root is %pBP",
- __func__, get_afi_safi_str(afi, safi, false), name,
- orr_group->active);
-
- return CMD_SUCCESS;
-}
-
-/* Delete BGP Optimal Route Reflection Group */
-int bgp_afi_safi_orr_group_unset(struct bgp *bgp, afi_t afi, safi_t safi,
- const char *name)
-{
- struct bgp_orr_group *orr_group;
-
- orr_group = bgp_orr_group_lookup_by_name(bgp, afi, safi, name);
- if (!orr_group)
- return CMD_WARNING;
-
- /* Check if there are any neighbors configured with this ORR Group */
- if (orr_group->rr_client_list) {
- bgp_orr_debug(
- "%s: For %s, ORR Group '%s' not removed as '%s' is configured on neighbor(s)",
- __func__,
- get_afi_safi_str(orr_group->afi, orr_group->safi,
- false),
- name, name);
- return CMD_WARNING;
- }
-
- bgp_orr_group_free(orr_group);
- return CMD_SUCCESS;
-}
-
-/* Set optimal route reflection group to the peer */
-static int peer_orr_group_set(struct peer *peer, afi_t afi, safi_t safi,
- const char *orr_group_name)
-{
- struct bgp_orr_group *orr_group = NULL;
-
- if (!peer)
- return CMD_WARNING;
-
- /* Get BGP ORR entry for the given address-family */
- orr_group = bgp_orr_group_lookup_by_name(peer->bgp, afi, safi,
- orr_group_name);
- if (!orr_group) {
- /* Create BGP ORR entry for the given address-family */
- orr_group =
- bgp_orr_group_new(peer->bgp, afi, safi, orr_group_name);
- }
-
- /* Skip processing if there is no change in ORR Group */
- if (peer_af_flag_check(peer, afi, safi, PEER_FLAG_ORR_GROUP)) {
- if (strmatch(peer->orr_group_name[afi][safi], orr_group_name)) {
- bgp_orr_debug(
- "%s: For %s, ORR Group '%s' is already configured on %pBP",
- __func__, get_afi_safi_str(afi, safi, false),
- orr_group_name, peer);
- return CMD_SUCCESS;
- }
- /* Remove the peer from ORR Group's peer list */
- bgp_orr_group_rrclient_update(peer, afi, safi,
- peer->orr_group_name[afi][safi],
- false);
- XFREE(MTYPE_BGP_ORR_GROUP_NAME,
- peer->orr_group_name[afi][safi]);
- }
-
- peer->orr_group_name[afi][safi] =
- XSTRDUP(MTYPE_BGP_ORR_GROUP_NAME, orr_group_name);
- SET_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ORR_GROUP);
-
- /* Add the peer to ORR Group's client list */
- bgp_orr_group_rrclient_update(peer, afi, safi, orr_group_name, true);
-
- /* Update ORR group active root and register with IGP */
- bgp_peer_update_orr_group_active_root(peer, afi, safi, orr_group);
-
- return CMD_SUCCESS;
-}
-
-/* Unset optimal route reflection group from the peer*/
-int peer_orr_group_unset(struct peer *peer, afi_t afi, safi_t safi,
- const char *orr_group_name)
-{
- struct bgp_orr_group *orr_group = NULL;
-
- assert(peer && peer->bgp && orr_group_name);
-
- if (!peer_af_flag_check(peer, afi, safi, PEER_FLAG_ORR_GROUP) ||
- !strmatch(peer->orr_group_name[afi][safi], orr_group_name)) {
- bgp_orr_debug(
- "%s: For %s, ORR Group '%s' is not configured on %pBP",
- __func__, get_afi_safi_str(afi, safi, false),
- orr_group_name, peer);
- return CMD_ERR_NO_MATCH;
- }
-
- /* Check if this RR Client is one of the root nodes */
- orr_group = bgp_orr_group_lookup_by_name(peer->bgp, afi, safi,
- orr_group_name);
-
- /* Should not be Null when orr-group is enabled on peer */
- assert(orr_group);
-
- /* Check if the peer is one of the root nodes of the ORR group */
- if (is_orr_root_node(orr_group, peer->host))
- return CMD_WARNING;
-
- /* Remove the peer from ORR Group's client list */
- bgp_orr_group_rrclient_update(peer, afi, safi, orr_group_name, false);
-
- /* Update ORR group active root and unregister with IGP */
- bgp_peer_update_orr_group_active_root(peer, afi, safi, orr_group);
-
- UNSET_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ORR_GROUP);
- XFREE(MTYPE_BGP_ORR_GROUP_NAME, peer->orr_group_name[afi][safi]);
-
- return CMD_SUCCESS;
-}
-
-int bgp_afi_safi_orr_group_set_vty(struct vty *vty, afi_t afi, safi_t safi,
- const char *name, const char *primary_str,
- const char *secondary_str,
- const char *tertiary_str, bool unset)
-{
- int ret = CMD_WARNING_CONFIG_FAILED;
- struct bgp *bgp;
- struct peer *primary = NULL, *secondary = NULL, *tertiary = NULL;
-
- bgp = bgp_get_default();
- if (!bgp) {
- vty_out(vty, "%% No BGP process is configured\n");
- return ret;
- }
-
- if (unset) {
- ret = bgp_afi_safi_orr_group_unset(bgp, afi, safi, name);
- if (ret != CMD_SUCCESS)
- vty_out(vty,
- "%% ORR Group %s not removed as '%s' is not found OR configured on neighbor(s)\n",
- name, name);
- return ret;
- }
-
- primary = peer_and_group_lookup_vty(vty, primary_str);
- if (!primary || !peer_af_flag_check(primary, afi, safi,
- PEER_FLAG_REFLECTOR_CLIENT)) {
- vty_out(vty,
- "%% Primary Root is not a Route Reflector Client\n");
- return ret;
- }
-
- if (secondary_str) {
- secondary = peer_and_group_lookup_vty(vty, secondary_str);
- if (!secondary ||
- !peer_af_flag_check(secondary, afi, safi,
- PEER_FLAG_REFLECTOR_CLIENT)) {
- vty_out(vty,
- "%% Secondary Root is not a Route Reflector Client\n");
- return ret;
- }
- }
-
- if (tertiary_str) {
- tertiary = peer_and_group_lookup_vty(vty, tertiary_str);
- if (!tertiary ||
- !peer_af_flag_check(tertiary, afi, safi,
- PEER_FLAG_REFLECTOR_CLIENT)) {
- vty_out(vty,
- "%% Tertiary Root is not a Route Reflector Client\n");
- return ret;
- }
- }
- return bgp_afi_safi_orr_group_set(bgp, afi, safi, name, primary,
- secondary, tertiary);
-}
-
-/* Set optimal route reflection group name to the peer. */
-int peer_orr_group_set_vty(struct vty *vty, const char *ip_str, afi_t afi,
- safi_t safi, const char *orr_group_name, bool unset)
-{
- int ret = CMD_WARNING_CONFIG_FAILED;
- struct peer *peer;
-
- peer = peer_and_group_lookup_vty(vty, ip_str);
- if (!peer)
- return ret;
-
- if (!peer_af_flag_check(peer, afi, safi, PEER_FLAG_REFLECTOR_CLIENT)) {
- vty_out(vty, "%% Neighbor %s is not a Route Reflector Client\n",
- peer->host);
- return ret;
- }
-
- if (!unset) {
- ret = peer_orr_group_set(peer, afi, safi, orr_group_name);
- if (ret != CMD_SUCCESS)
- vty_out(vty, "%% ORR Group '%s' is not configured\n",
- orr_group_name);
- } else {
- ret = peer_orr_group_unset(peer, afi, safi, orr_group_name);
- if (ret == CMD_ERR_NO_MATCH)
- vty_out(vty,
- "%% ORR Group '%s' is not configured on %s\n",
- orr_group_name, peer->host);
- else if (ret == CMD_WARNING)
- vty_out(vty,
- "%% %s is one of the root nodes of ORR Group '%s'.\n",
- peer->host, orr_group_name);
- }
- return bgp_vty_return(vty, ret);
-}
-
-void bgp_config_write_orr(struct vty *vty, struct bgp *bgp, afi_t afi,
- safi_t safi)
-{
- struct list *orr_group_list;
- struct listnode *node;
- struct bgp_orr_group *orr_group;
-
- orr_group_list = bgp->orr_group[afi][safi];
- if (!orr_group_list)
- return;
-
- for (ALL_LIST_ELEMENTS_RO(orr_group_list, node, orr_group)) {
- /* optimal route reflection configuration */
- vty_out(vty, " optimal-route-reflection %s", orr_group->name);
- if (orr_group->primary)
- vty_out(vty, " %s", orr_group->primary->host);
- if (orr_group->secondary)
- vty_out(vty, " %s", orr_group->secondary->host);
- if (orr_group->tertiary)
- vty_out(vty, " %s", orr_group->tertiary->host);
- vty_out(vty, "\n");
- }
-}
-
-static void bgp_show_orr_group(struct vty *vty, struct bgp_orr_group *orr_group,
- afi_t afi, safi_t safi)
-{
- char *rrclient = NULL;
- struct listnode *node;
- struct bgp_orr_igp_metric *igp_metric = NULL;
- struct list *orr_group_rrclient_list = NULL;
- struct list *orr_group_igp_metric_info = NULL;
-
- if (!orr_group)
- return;
-
- vty_out(vty, "\nORR group: %s, %s\n", orr_group->name,
- get_afi_safi_str(afi, safi, false));
- vty_out(vty, "Configured root:");
- vty_out(vty, " primary: %pBP,", orr_group->primary);
- vty_out(vty, " secondary: %pBP,", orr_group->secondary);
- vty_out(vty, " tertiary: %pBP\n", orr_group->tertiary);
- vty_out(vty, "Active Root: %pBP\n", orr_group->active);
-
- orr_group_rrclient_list = orr_group->rr_client_list;
- if (!orr_group_rrclient_list)
- return;
-
- vty_out(vty, "\nRR Clients mapped:\n");
-
- for (ALL_LIST_ELEMENTS_RO(orr_group_rrclient_list, node, rrclient))
- vty_out(vty, "%s\n", rrclient);
-
- vty_out(vty, "\nNumber of mapping entries: %d\n\n",
- orr_group_rrclient_list->count);
-
-
- orr_group_igp_metric_info = orr_group->igp_metric_info;
- if (!orr_group_igp_metric_info)
- return;
- vty_out(vty, "Prefix\t\t\t\t\t\tCost\n");
- for (ALL_LIST_ELEMENTS_RO(orr_group_igp_metric_info, node,
- igp_metric)) {
- vty_out(vty, "%pFX\t\t\t\t\t\t%d\n", &igp_metric->prefix,
- igp_metric->igp_metric);
- }
- vty_out(vty, "\nNumber of mapping entries: %d\n\n",
- orr_group_igp_metric_info->count);
-}
-
-int bgp_show_orr(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
- const char *orr_group_name, uint8_t show_flags)
-{
- struct listnode *node;
- struct bgp_orr_group *orr_group = NULL;
- struct list *orr_group_list = NULL;
- int ret = 0;
-
- assert(bgp);
-
- /* Display the matching entries for the given ORR Group */
- if (orr_group_name) {
- orr_group = bgp_orr_group_lookup_by_name(bgp, afi, safi,
- orr_group_name);
- if (!orr_group) {
- vty_out(vty, "%% ORR Group %s not found\n",
- orr_group_name);
- return CMD_WARNING;
- }
- bgp_show_orr_group(vty, orr_group, afi, safi);
- return ret;
- }
- orr_group_list = bgp->orr_group[afi][safi];
- if (!orr_group_list)
- return ret;
-
- for (ALL_LIST_ELEMENTS_RO(orr_group_list, node, orr_group))
- bgp_show_orr_group(vty, orr_group, afi, safi);
-
- return ret;
-}
-
-/* Check if the Route Reflector Client belongs to any ORR Group */
-bool peer_orr_rrclient_check(struct peer *peer, afi_t afi, safi_t safi)
-{
- char *rrclient = NULL;
- struct listnode *node;
- struct list *orr_group_list = NULL;
- struct list *orr_group_rrclient_list = NULL;
- struct bgp_orr_group *orr_group = NULL;
-
- assert(peer && peer->bgp);
-
- orr_group_list = peer->bgp->orr_group[afi][safi];
- if (!orr_group_list)
- return false;
-
- for (ALL_LIST_ELEMENTS_RO(orr_group_list, node, orr_group)) {
- /* Check if peer configured as primary/secondary/tertiary root
- */
- if (is_orr_root_node(orr_group, peer->host))
- return true;
- /*
- * Check if peer is mapped to any ORR Group in this
- * Address Family.
- */
- orr_group_rrclient_list = orr_group->rr_client_list;
- if (!orr_group_rrclient_list)
- continue;
-
- for (ALL_LIST_ELEMENTS_RO(orr_group_rrclient_list, node,
- rrclient))
- if (strmatch(rrclient, peer->host))
- return true;
- }
- return false;
-}
-
-static void
-bgp_peer_update_orr_group_active_root(struct peer *peer, afi_t afi, safi_t safi,
- struct bgp_orr_group *orr_group)
-{
- assert(peer && orr_group);
-
- /* Nothing to do if this peer is not one of the root nodes */
- if (!is_orr_root_node(orr_group, peer->host))
- return;
-
- /* Root is reachable and group member, update Active Root if needed */
- if (is_peer_active_eligible(peer, afi, safi, orr_group->name)) {
- /* Nothing to do, if this is the current Active Root */
- if (is_orr_active_root(orr_group, peer->host))
- return;
-
- /* If Active is null, update this node as Active Root */
- if (!orr_group->active) {
- orr_group->active = peer;
- bgp_orr_igp_metric_register(orr_group, true);
- return;
- }
-
- /* If this is Primary and current Active is not Primary */
- if (is_orr_primary_root(orr_group, peer->host)) {
- bgp_orr_igp_metric_register(orr_group, false);
- orr_group->active = peer;
- bgp_orr_igp_metric_register(orr_group, true);
- return;
- }
-
- /*
- * If this is Secondary and current Active is not
- * Primary/Secondary
- */
- if (is_orr_secondary_root(orr_group, peer->host)) {
- if (is_orr_active_root(orr_group,
- orr_group->primary->host))
- return;
- bgp_orr_igp_metric_register(orr_group, false);
- orr_group->active = peer;
- bgp_orr_igp_metric_register(orr_group, true);
- return;
- }
- return;
- }
-
- /* Non Active Root is unreachable, so nothing to do */
- if (!is_orr_active_root(orr_group, peer->host))
- return;
-
- if (is_orr_primary_root(orr_group, peer->host)) {
- /* If secondary is reachable, update it as Active */
- if (is_peer_active_eligible(orr_group->secondary, afi, safi,
- orr_group->name)) {
- bgp_orr_igp_metric_register(orr_group, false);
-
- orr_group->active = orr_group->secondary;
- bgp_orr_igp_metric_register(orr_group, true);
- return;
- }
-
- /* If tertiary is reachable, update it as Active */
- if (is_peer_active_eligible(orr_group->tertiary, afi, safi,
- orr_group->name)) {
- bgp_orr_igp_metric_register(orr_group, false);
-
- orr_group->active = orr_group->tertiary;
- bgp_orr_igp_metric_register(orr_group, true);
- return;
- }
- } else {
- if (is_orr_secondary_root(orr_group, peer->host)) {
- /* If tertiary is reachable, update it as Active */
- if (is_peer_active_eligible(orr_group->tertiary, afi,
- safi, orr_group->name)) {
- bgp_orr_igp_metric_register(orr_group, false);
-
- orr_group->active = orr_group->tertiary;
- bgp_orr_igp_metric_register(orr_group, true);
- return;
- }
- }
- }
-
- /* Assign Active as null */
- bgp_orr_igp_metric_register(orr_group, false);
- orr_group->active = NULL;
-
- bgp_orr_debug("%s: For %s, ORR Group '%s' has no active root", __func__,
- get_afi_safi_str(afi, safi, false),
- peer->orr_group_name[afi][safi]);
-}
-
-void bgp_peer_update_orr_active_roots(struct peer *peer)
-{
- afi_t afi;
- safi_t safi;
- struct bgp_orr_group *orr_group;
-
- assert(peer && peer->bgp);
-
- FOREACH_AFI_SAFI (afi, safi) {
- if (!peer->orr_group_name[afi][safi])
- continue;
-
- /* Get BGP ORR entry for the given address-family */
- orr_group = bgp_orr_group_lookup_by_name(
- peer->bgp, afi, safi, peer->orr_group_name[afi][safi]);
- assert(orr_group);
-
- /* Free ORR related memory. */
- if (peer->status != Deleted) {
- bgp_peer_update_orr_group_active_root(peer, afi, safi,
- orr_group);
- continue;
- }
-
- if (!is_orr_root_node(orr_group, peer->host)) {
- peer_orr_group_unset(peer, afi, safi,
- peer->orr_group_name[afi][safi]);
- continue;
- }
-
- if (is_orr_primary_root(orr_group, peer->host)) {
- orr_group->primary = orr_group->secondary;
- orr_group->secondary = orr_group->tertiary;
- } else if (is_orr_secondary_root(orr_group, peer->host))
- orr_group->secondary = orr_group->tertiary;
- orr_group->tertiary = NULL;
-
- bgp_afi_safi_orr_group_set(peer->bgp, afi, safi,
- orr_group->name, orr_group->primary,
- orr_group->secondary,
- orr_group->tertiary);
- peer_orr_group_unset(peer, afi, safi,
- peer->orr_group_name[afi][safi]);
- }
-}
-
-/* IGP metric calculated from Active Root */
-static int bgp_orr_igp_metric_update(struct orr_igp_metric_info *table)
-{
- afi_t afi;
- safi_t safi;
- bool add = false;
- bool root_found = false;
- uint32_t instId = 0;
- uint32_t numEntries = 0;
- uint32_t entry = 0;
- uint8_t proto = ZEBRA_ROUTE_MAX;
- struct bgp *bgp = NULL;
- struct prefix pfx, root = {0};
-
- struct list *orr_group_list = NULL;
- struct bgp_orr_group *group = NULL;
- struct listnode *node, *nnode;
-
- struct bgp_orr_igp_metric *igp_metric = NULL;
- struct list *bgp_orr_igp_metric = NULL;
-
- bgp = bgp_get_default();
- assert(bgp && table);
-
- proto = table->proto;
- afi = family2afi(table->root.family);
- safi = table->safi;
- instId = table->instId;
- add = table->add;
- numEntries = table->num_entries;
- prefix_copy(&root, &table->root);
-
- if ((proto != ZEBRA_ROUTE_OSPF) && (proto != ZEBRA_ROUTE_OSPF6) &&
- (proto != ZEBRA_ROUTE_ISIS)) {
- bgp_orr_debug("%s: Message received from unsupported protocol",
- __func__);
- return -1;
- }
-
- orr_group_list = bgp->orr_group[afi][safi];
- if (!orr_group_list) {
- bgp_orr_debug(
- "%s: Address family %s has no ORR Groups configured",
- __func__, get_afi_safi_str(afi, safi, false));
- return -1;
- }
-
- if (BGP_DEBUG(optimal_route_reflection, ORR)) {
- zlog_debug(
- "[BGP-ORR] %s: Received metric update from protocol %s instance %d",
- __func__,
- proto == ZEBRA_ROUTE_ISIS
- ? "ISIS"
- : (proto == ZEBRA_ROUTE_OSPF ? "OSPF"
- : "OSPF6"),
- instId);
- zlog_debug("[BGP-ORR] %s: Address family %s", __func__,
- get_afi_safi_str(afi, safi, false));
- zlog_debug("[BGP-ORR] %s: Root %pFX", __func__, &root);
- zlog_debug("[BGP-ORR] %s: Number of entries to be %s %d",
- __func__, add ? "added" : "deleted", numEntries);
- zlog_debug("[BGP-ORR] %s: Prefix (Cost) :", __func__);
- for (entry = 0; entry < numEntries; entry++)
- zlog_debug("[BGP-ORR] %s: %pFX (%d)", __func__,
- &table->nexthop[entry].prefix,
- table->nexthop[entry].metric);
- }
- /*
- * Update IGP metric info of all ORR Groups having this as active root
- */
- for (ALL_LIST_ELEMENTS_RO(orr_group_list, node, group)) {
- if (str2prefix(group->active->host, &pfx) == 0) {
- bgp_orr_debug("%s: Malformed prefix for %pBP", __func__,
- group->active);
- continue;
- }
- /*
- * Copy IGP info if root matches with the active root of the
- * group
- */
- if (prefix_cmp(&pfx, &root) == 0) {
- if (add) {
- /* Add new routes */
- if (!group->igp_metric_info)
- group->igp_metric_info = list_new();
-
- bgp_orr_igp_metric = group->igp_metric_info;
- if (!bgp_orr_igp_metric)
- bgp_orr_igp_metric_register(group,
- false);
- assert(bgp_orr_igp_metric);
-
- for (entry = 0; entry < numEntries; entry++) {
- igp_metric = XCALLOC(
- MTYPE_ORR_IGP_INFO,
- sizeof(struct
- bgp_orr_igp_metric));
- if (!igp_metric)
- bgp_orr_igp_metric_register(
- group, false);
-
- prefix_copy(
- &igp_metric->prefix,
- &table->nexthop[entry].prefix);
- igp_metric->igp_metric =
- table->nexthop[entry].metric;
- listnode_add(bgp_orr_igp_metric,
- igp_metric);
- }
- } else {
- /* Delete old routes */
- for (entry = 0; entry < numEntries; entry++) {
- for (ALL_LIST_ELEMENTS(
- group->igp_metric_info,
- node, nnode, igp_metric)) {
- if (prefix_cmp(
- &igp_metric->prefix,
- &table->nexthop[entry]
- .prefix))
- continue;
- listnode_delete(
- group->igp_metric_info,
- igp_metric);
- XFREE(MTYPE_ORR_IGP_INFO,
- igp_metric);
- }
- }
- }
- root_found = true;
- break;
- }
- }
- /* Received IGP for root node thats not found in ORR active roots */
- if (!root_found) {
- bgp_orr_debug(
- "%s: Received IGP SPF information for root %pFX which is not an ORR active root",
- __func__, &root);
- }
- assert(root_found);
- return 0;
-}
-
-/* Register with IGP for sending SPF info */
-static void bgp_orr_igp_metric_register(struct bgp_orr_group *orr_group,
- bool reg)
-{
- int ret;
- struct orr_igp_metric_reg msg;
- struct prefix p;
- char *rr_client = NULL;
-
- assert(orr_group);
-
- if (!orr_group->active)
- return;
-
- memset(&msg, 0, sizeof(msg));
- ret = str2prefix(orr_group->active->host, &p);
-
- /* Malformed prefix */
- assert(ret);
-
- /* Check if the active root is part of this ORR group */
- rr_client = bgp_orr_group_rrclient_lookup(orr_group,
- orr_group->active->host);
- if (reg && !rr_client) {
- bgp_orr_debug(
- "%s: active root %pBP is not part of this ORR group",
- __func__, orr_group->active);
- return;
- }
-
- msg.reg = reg;
- msg.proto = ZEBRA_ROUTE_BGP;
- msg.safi = orr_group->safi;
- prefix_copy(&msg.prefix, &p);
- strlcpy(msg.group_name, orr_group->name, sizeof(msg.group_name));
-
- bgp_orr_debug(
- "%s: %s with IGP for metric calculation from location %pFX",
- __func__, reg ? "Register" : "Unregister", &msg.prefix);
-
- if (zclient_send_opaque(zclient, ORR_IGP_METRIC_REGISTER,
- (uint8_t *)&msg,
- sizeof(msg)) == ZCLIENT_SEND_FAILURE)
- zlog_warn("[BGP-ORR] %s: Failed to send message to IGP.",
- __func__);
-
- /* Free IGP metric info calculated from previous active location */
- if (!reg && orr_group->igp_metric_info)
- list_delete(&orr_group->igp_metric_info);
-}
-
-/* BGP ORR message processing */
-int bgg_orr_message_process(enum bgp_orr_msg_type msg_type, void *msg)
-{
- int ret = 0;
-
- assert(msg && msg_type > BGP_ORR_IMSG_INVALID &&
- msg_type < BGP_ORR_IMSG_MAX);
- switch (msg_type) {
- case BGP_ORR_IMSG_GROUP_CREATE:
- break;
- case BGP_ORR_IMSG_GROUP_DELETE:
- break;
- case BGP_ORR_IMSG_GROUP_UPDATE:
- break;
- case BGP_ORR_IMSG_SET_ORR_ON_PEER:
- break;
- case BGP_ORR_IMSG_UNSET_ORR_ON_PEER:
- break;
- case BGP_ORR_IMSG_IGP_METRIC_UPDATE:
- ret = bgp_orr_igp_metric_update(
- (struct orr_igp_metric_info *)msg);
- break;
- case BGP_ORR_IMSG_SHOW_ORR:
- /* bgp_show_orr */
- break;
- case BGP_ORR_IMSG_SHOW_ORR_GROUP:
- /* bgp_show_orr_group */
- break;
- default:
- break;
- }
-
- /* Free Memory */
- return ret;
-}
-
-/*
- * Cleanup ORR information - invoked at the time of bgpd exit or
- * when the BGP instance (default) is being freed.
- */
-void bgp_orr_cleanup(struct bgp *bgp)
-{
- afi_t afi;
- safi_t safi;
- struct listnode *node, *nnode;
- struct bgp_orr_group *orr_group;
-
- assert(bgp);
-
- if (!bgp->orr_group_count)
- return;
-
- FOREACH_AFI_SAFI (afi, safi) {
- for (ALL_LIST_ELEMENTS(bgp->orr_group[afi][safi], node, nnode,
- orr_group))
- bgp_orr_group_free(orr_group);
- }
-}
+++ /dev/null
-/*
- * BGP Optimal Route Reflection
- * Copyright (C) 2021 Samsung R&D Institute India - Bangalore.
- * Madhurilatha Kuruganti
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; see the file COPYING; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#ifndef _FRR_BGP_ORR_H
-#define _FRR_BGP_ORR_H
-#include <zebra.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* Macro to log debug message */
-#define bgp_orr_debug(...) \
- do { \
- if (BGP_DEBUG(optimal_route_reflection, ORR)) \
- zlog_debug("[BGP-ORR] " __VA_ARGS__); \
- } while (0)
-
-
-/* BGP ORR Message Type */
-enum bgp_orr_msg_type {
- BGP_ORR_IMSG_INVALID = 0,
-
- /* ORR group update */
- BGP_ORR_IMSG_GROUP_CREATE = 1,
- BGP_ORR_IMSG_GROUP_DELETE,
- BGP_ORR_IMSG_GROUP_UPDATE,
-
- /* ORR group update on a BGP RR Client */
- BGP_ORR_IMSG_SET_ORR_ON_PEER = 4,
- BGP_ORR_IMSG_UNSET_ORR_ON_PEER,
-
- /* ORR IGP Metric Update from IGP from requested Location */
- BGP_ORR_IMSG_IGP_METRIC_UPDATE = 6,
-
- /* ORR Group Related Information display */
- BGP_ORR_IMSG_SHOW_ORR = 7,
- BGP_ORR_IMSG_SHOW_ORR_GROUP,
-
- /* Invalid Message Type*/
- BGP_ORR_IMSG_MAX
-};
-
-extern struct zclient *zclient;
-
-extern void bgp_config_write_orr(struct vty *vty, struct bgp *bgp, afi_t afi,
- safi_t safi);
-
-extern int bgp_afi_safi_orr_group_set_vty(struct vty *vty, afi_t afi,
- safi_t safi, const char *name,
- const char *primary_str,
- const char *secondary_str,
- const char *tertiary_str, bool unset);
-extern int peer_orr_group_unset(struct peer *peer, afi_t afi, safi_t safi,
- const char *orr_group_name);
-extern int peer_orr_group_set_vty(struct vty *vty, const char *ip_str,
- afi_t afi, safi_t safi,
- const char *orr_group_name, bool unset);
-extern bool peer_orr_rrclient_check(struct peer *peer, afi_t afi, safi_t safi);
-
-extern int bgp_show_orr(struct vty *vty, struct bgp *bgp, afi_t afi,
- safi_t safi, const char *orr_group_name,
- uint8_t show_flags);
-
-extern int bgp_afi_safi_orr_group_set(struct bgp *bgp, afi_t afi, safi_t safi,
- const char *name, struct peer *primary,
- struct peer *secondary,
- struct peer *tertiary);
-extern int bgp_afi_safi_orr_group_unset(struct bgp *bgp, afi_t afi, safi_t safi,
- const char *name);
-
-extern void bgp_peer_update_orr_active_roots(struct peer *peer);
-
-extern int bgg_orr_message_process(enum bgp_orr_msg_type msg_type, void *msg);
-
-extern struct bgp_orr_group *bgp_orr_group_lookup_by_name(struct bgp *bgp,
- afi_t afi,
- safi_t safi,
- const char *name);
-extern void bgp_orr_cleanup(struct bgp *bgp);
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _FRR_BGP_ORR_H */
#include "bgpd/bgp_addpath.h"
#include "bgpd/bgp_mac.h"
#include "bgpd/bgp_network.h"
-#include "bgpd/bgp_orr.h"
#include "bgpd/bgp_trace.h"
#include "bgpd/bgp_rpki.h"
enum bgp_path_selection_reason *reason)
{
const struct prefix *new_p;
- struct prefix exist_p;
struct attr *newattr, *existattr;
enum bgp_peer_sort new_sort;
enum bgp_peer_sort exist_sort;
bool new_origin, exist_origin;
struct bgp_path_info *bpi_ultimate;
- struct bgp_orr_group *orr_group = NULL;
- struct listnode *node;
- struct bgp_orr_igp_metric *igp_metric = NULL;
- struct list *orr_group_igp_metric_info = NULL;
-
*paths_eq = 0;
/* 0. Null check. */
if (exist->extra)
existm = exist->extra->igpmetric;
- if (new->peer->orr_group_name[afi][safi]) {
- ret = str2prefix(new->peer->host, &exist_p);
- orr_group = bgp_orr_group_lookup_by_name(
- bgp, afi, safi, new->peer->orr_group_name[afi][safi]);
- if (orr_group) {
- orr_group_igp_metric_info = orr_group->igp_metric_info;
- if (orr_group_igp_metric_info) {
- for (ALL_LIST_ELEMENTS_RO(
- orr_group_igp_metric_info, node,
- igp_metric)) {
- if (ret &&
- prefix_cmp(&exist_p,
- &igp_metric->prefix) ==
- 0) {
- newm = igp_metric->igp_metric;
- break;
- }
- }
- }
- }
- }
- if (exist->peer->orr_group_name[afi][safi]) {
- ret = str2prefix(exist->peer->host, &exist_p);
- orr_group = bgp_orr_group_lookup_by_name(
- bgp, afi, safi, exist->peer->orr_group_name[afi][safi]);
- if (orr_group) {
- orr_group_igp_metric_info = orr_group->igp_metric_info;
- if (orr_group_igp_metric_info) {
- for (ALL_LIST_ELEMENTS_RO(
- orr_group_igp_metric_info, node,
- igp_metric)) {
- if (ret &&
- prefix_cmp(&exist_p,
- &igp_metric->prefix) ==
- 0) {
- existm = igp_metric->igp_metric;
- break;
- }
- }
- }
- }
- }
-
if (newm < existm) {
if (debug && peer_sort_ret < 0)
zlog_debug(
|alias ALIAS_NAME\
|A.B.C.D/M longer-prefixes\
|X:X::X:X/M longer-prefixes\
- |optimal-route-reflection [WORD$orr_group_name]\
|detail-routes$detail_routes\
] [json$uj [detail$detail_json] | wide$wide]",
SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
"Display route and more specific routes\n"
"IPv6 prefix\n"
"Display route and more specific routes\n"
- "Display Optimal Route Reflection RR Clients\n"
- "ORR Group name\n"
"Display detailed version of all routes\n"
JSON_STR
"Display detailed version of JSON output\n"
uint16_t show_flags = 0;
enum rpki_states rpki_target_state = RPKI_NOT_BEING_USED;
struct prefix p;
- bool orr_group = false;
if (uj) {
argc--;
output_arg = &p;
}
- if (argv_find(argv, argc, "optimal-route-reflection", &idx))
- orr_group = true;
-
if (!all) {
/* show bgp: AFI_IP6, show ip bgp: AFI_IP */
if (community)
return bgp_show_community(vty, bgp, community,
exact_match, afi, safi,
show_flags);
- else if (orr_group)
- return bgp_show_orr(vty, bgp, afi, safi, orr_group_name,
- show_flags);
else
return bgp_show(vty, bgp, afi, safi, sh_type,
output_arg, show_flags,
vty, abgp, community,
exact_match, afi, safi,
show_flags);
- else if (orr_group)
- bgp_show_orr(vty, bgp, afi,
- safi,
- orr_group_name,
- show_flags);
else
bgp_show(vty, abgp, afi, safi,
sh_type, output_arg,
vty, abgp, community,
exact_match, afi, safi,
show_flags);
- else if (orr_group)
- bgp_show_orr(vty, bgp, afi,
- safi,
- orr_group_name,
- show_flags);
else
bgp_show(vty, abgp, afi, safi,
sh_type, output_arg,
#ifdef ENABLE_BGP_VNC
#include "bgpd/rfapi/bgp_rfapi_cfg.h"
#endif
-#include "bgpd/bgp_orr.h"
-
FRR_CFG_DEFAULT_BOOL(BGP_IMPORT_CHECK,
{
case BGP_ERR_INVALID_INTERNAL_ROLE:
str = "External roles can be set only on eBGP session";
break;
- case BGP_ERR_PEER_ORR_CONFIGURED:
- str = "Deconfigure optimal-route-reflection on this peer first";
- break;
}
if (str) {
vty_out(vty, "%% %s\n", str);
NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2
"Configure a neighbor as Route Reflector client\n")
-/* optimal-route-reflection Root Routers configuration */
-DEFPY (optimal_route_reflection,
- optimal_route_reflection_cmd,
- "[no$no] optimal-route-reflection WORD$orr_group [<A.B.C.D|X:X::X:X>$primary [<A.B.C.D|X:X::X:X>$secondary [<A.B.C.D|X:X::X:X>$tertiary]]]",
- NO_STR
- "Create ORR group and assign root router(s)\n"
- "ORR Group name\n"
- "Primary Root address\n"
- "Primary Root IPv6 address\n"
- "Secondary Root address\n"
- "Secondary Root IPv6 address\n"
- "Tertiary Root address\n"
- "Tertiary Root IPv6 address\n")
-{
- if (!no && !primary) {
- vty_out(vty, "%% Specify Primary Root address\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
- return bgp_afi_safi_orr_group_set_vty(
- vty, bgp_node_afi(vty), bgp_node_safi(vty), orr_group,
- primary_str, secondary_str, tertiary_str, !!no);
-}
-
-/* neighbor optimal-route-reflection group*/
-DEFPY (neighbor_optimal_route_reflection,
- neighbor_optimal_route_reflection_cmd,
- "[no$no] neighbor <A.B.C.D|X:X::X:X|WORD>$neighbor optimal-route-reflection WORD$orr_group",
- NO_STR
- NEIGHBOR_STR
- NEIGHBOR_ADDR_STR2
- "Apply ORR group configuration to the neighbor\n"
- "ORR group name\n")
-{
- return peer_orr_group_set_vty(vty, neighbor, bgp_node_afi(vty),
- bgp_node_safi(vty), orr_group, !!no);
-}
-
/* neighbor route-server-client. */
DEFUN (neighbor_route_server_client,
neighbor_route_server_client_cmd,
if (CHECK_FLAG(p->af_flags[afi][safi],
PEER_FLAG_RSERVER_CLIENT))
vty_out(vty, " Route-Server Client\n");
-
- if (peer_af_flag_check(p, afi, safi, PEER_FLAG_ORR_GROUP))
- vty_out(vty, " ORR group (configured) : %s\n",
- p->orr_group_name[afi][safi]);
-
if (CHECK_FLAG(p->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
vty_out(vty,
" Inbound soft reconfiguration allowed\n");
: "");
}
}
-
- if (peer_af_flag_check(peer, afi, safi, PEER_FLAG_ORR_GROUP))
- vty_out(vty, " neighbor %s optimal-route-reflection %s\n",
- addr, peer->orr_group_name[afi][safi]);
}
static void bgp_vpn_config_write(struct vty *vty, struct bgp *bgp, afi_t afi,
}
}
- /* Optimal Route Reflection */
- bgp_config_write_orr(vty, bgp, afi, safi);
-
vty_endframe(vty, " exit-address-family\n");
}
install_element(BGP_EVPN_NODE, &neighbor_route_reflector_client_cmd);
install_element(BGP_EVPN_NODE, &no_neighbor_route_reflector_client_cmd);
- /* "optimal-route-reflection" commands */
- install_element(BGP_IPV4_NODE, &optimal_route_reflection_cmd);
- install_element(BGP_IPV4M_NODE, &optimal_route_reflection_cmd);
- install_element(BGP_IPV4L_NODE, &optimal_route_reflection_cmd);
- install_element(BGP_IPV6_NODE, &optimal_route_reflection_cmd);
- install_element(BGP_IPV6M_NODE, &optimal_route_reflection_cmd);
- install_element(BGP_IPV6L_NODE, &optimal_route_reflection_cmd);
- install_element(BGP_VPNV4_NODE, &optimal_route_reflection_cmd);
- install_element(BGP_VPNV6_NODE, &optimal_route_reflection_cmd);
- install_element(BGP_FLOWSPECV4_NODE, &optimal_route_reflection_cmd);
- install_element(BGP_FLOWSPECV6_NODE, &optimal_route_reflection_cmd);
- install_element(BGP_EVPN_NODE, &optimal_route_reflection_cmd);
-
- /* "neighbor optimal-route-reflection" commands */
- install_element(BGP_IPV4_NODE, &neighbor_optimal_route_reflection_cmd);
- install_element(BGP_IPV4M_NODE, &neighbor_optimal_route_reflection_cmd);
- install_element(BGP_IPV4L_NODE, &neighbor_optimal_route_reflection_cmd);
- install_element(BGP_IPV6_NODE, &neighbor_optimal_route_reflection_cmd);
- install_element(BGP_IPV6M_NODE, &neighbor_optimal_route_reflection_cmd);
- install_element(BGP_IPV6L_NODE, &neighbor_optimal_route_reflection_cmd);
- install_element(BGP_VPNV4_NODE, &neighbor_optimal_route_reflection_cmd);
- install_element(BGP_VPNV6_NODE, &neighbor_optimal_route_reflection_cmd);
- install_element(BGP_FLOWSPECV4_NODE,
- &neighbor_optimal_route_reflection_cmd);
- install_element(BGP_FLOWSPECV6_NODE,
- &neighbor_optimal_route_reflection_cmd);
- install_element(BGP_EVPN_NODE, &neighbor_optimal_route_reflection_cmd);
-
/* "neighbor route-server" commands.*/
install_element(BGP_NODE, &neighbor_route_server_client_hidden_cmd);
install_element(BGP_NODE, &no_neighbor_route_server_client_hidden_cmd);
#include "bgpd/bgp_trace.h"
#include "bgpd/bgp_community.h"
#include "bgpd/bgp_lcommunity.h"
-#include "bgpd/bgp_orr.h"
/* All information about zebra. */
struct zclient *zclient = NULL;
-static int bgp_opaque_msg_handler(ZAPI_CALLBACK_ARGS);
-
/* hook to indicate vrf status change for SNMP */
DEFINE_HOOK(bgp_vrf_status_changed, (struct bgp *bgp, struct interface *ifp),
(bgp, ifp));
[ZEBRA_SRV6_LOCATOR_DELETE] = bgp_zebra_process_srv6_locator_delete,
[ZEBRA_SRV6_MANAGER_GET_LOCATOR_CHUNK] =
bgp_zebra_process_srv6_locator_chunk,
- [ZEBRA_OPAQUE_MESSAGE] = bgp_opaque_msg_handler,
};
static int bgp_if_new_hook(struct interface *ifp)
{
return srv6_manager_release_locator_chunk(zclient, name);
}
-
-/*
- * ORR messages between processes
- */
-static int bgp_opaque_msg_handler(ZAPI_CALLBACK_ARGS)
-{
- struct stream *s;
- struct zapi_opaque_msg info;
- struct orr_igp_metric_info table;
- int ret = 0;
-
- s = zclient->ibuf;
-
- if (zclient_opaque_decode(s, &info) != 0) {
- bgp_orr_debug("%s: opaque decode failed", __func__);
- return -1;
- }
-
- switch (info.type) {
- case ORR_IGP_METRIC_UPDATE:
- STREAM_GET(&table, s, sizeof(table));
- ret = bgg_orr_message_process(BGP_ORR_IMSG_IGP_METRIC_UPDATE,
- (void *)&table);
- break;
- default:
- break;
- }
-
-stream_failure:
- return ret;
-}
#include "bgpd/bgp_evpn_private.h"
#include "bgpd/bgp_evpn_mh.h"
#include "bgpd/bgp_mac.h"
-#include "bgpd/bgp_orr.h"
#include "bgp_trace.h"
DEFINE_MTYPE_STATIC(BGPD, PEER_TX_SHUTDOWN_MSG, "Peer shutdown message (TX)");
/* Change peer's AS number. */
void peer_as_change(struct peer *peer, as_t as, int as_specified)
{
- afi_t afi;
- safi_t safi;
enum bgp_peer_sort origtype, newtype;
/* Stop peer. */
/* reflector-client reset */
if (newtype != BGP_PEER_IBGP) {
-
- FOREACH_AFI_SAFI (afi, safi)
- UNSET_FLAG(peer->af_flags[afi][safi],
- PEER_FLAG_ORR_GROUP);
-
UNSET_FLAG(peer->af_flags[AFI_IP][SAFI_UNICAST],
PEER_FLAG_REFLECTOR_CLIENT);
UNSET_FLAG(peer->af_flags[AFI_IP][SAFI_MULTICAST],
ecommunity_free(&bgp->vpn_policy[afi].rtlist[dir]);
}
- bgp_orr_cleanup(bgp);
-
XFREE(MTYPE_BGP, bgp->name);
XFREE(MTYPE_BGP, bgp->name_pretty);
XFREE(MTYPE_BGP, bgp->snmp_stats);
if (flag & PEER_FLAG_REFLECTOR_CLIENT && ptype != BGP_PEER_IBGP)
return BGP_ERR_NOT_INTERNAL_PEER;
- /* Do not remove reflector client when ORR is configured on this peer */
- if (flag & PEER_FLAG_REFLECTOR_CLIENT && !set &&
- peer_orr_rrclient_check(peer, afi, safi))
- return BGP_ERR_PEER_ORR_CONFIGURED;
-
/* Special check for remove-private-AS. */
if (flag & PEER_FLAG_REMOVE_PRIVATE_AS && ptype == BGP_PEER_IBGP)
return BGP_ERR_REMOVE_PRIVATE_AS;
#include "bgp_io.h"
#include "lib/bfd.h"
-#include "lib/orr_msg.h"
#define BGP_MAX_HOSTNAME 64 /* Linux max, is larger than most other sys */
#define BGP_PEER_MAX_HASH_SIZE 16384
struct bgp_rmap rmap;
};
-struct bgp_orr_igp_metric {
- struct prefix prefix;
- uint32_t igp_metric;
-};
-
-struct bgp_orr_group {
- /* Name of this ORR group */
- char *name;
-
- /* Address Family Identifiers */
- afi_t afi;
- safi_t safi;
-
- /* Pointer to BGP */
- struct bgp *bgp;
-
- /* Root Routers of the group */
- struct peer *primary;
- struct peer *secondary;
- struct peer *tertiary;
-
- /* Active Root Router of the group */
- struct peer *active;
-
- /* RR clients belong to this group */
- struct list *rr_client_list;
-
- /* IGP metric data from active root */
- struct list *igp_metric_info;
-
- /* Route table calculated from active root for this group */
- struct bgp_table *route_table;
-};
-
enum vpn_policy_direction {
BGP_VPN_POLICY_DIR_FROMVPN = 0,
BGP_VPN_POLICY_DIR_TOVPN = 1,
bool allow_martian;
- /* BGP optimal route reflection group and Root Router configuration */
- uint32_t orr_group_count;
- struct list *orr_group[AFI_MAX][SAFI_MAX];
-
QOBJ_FIELDS;
};
DECLARE_QOBJ_TYPE(bgp);
#define PEER_FLAG_MAX_PREFIX_FORCE (1ULL << 28)
#define PEER_FLAG_DISABLE_ADDPATH_RX (1ULL << 29)
#define PEER_FLAG_SOO (1ULL << 30)
-#define PEER_FLAG_ORR_GROUP (1ULL << 31) /* Optimal-Route-Reflection */
-#define PEER_FLAG_ACCEPT_OWN (1ULL << 32)
-
- /* BGP Optimal Route Reflection Group name */
- char *orr_group_name[AFI_MAX][SAFI_MAX];
+#define PEER_FLAG_ACCEPT_OWN (1ULL << 31)
enum bgp_addpath_strat addpath_type[AFI_MAX][SAFI_MAX];
/*BGP Open Policy ERRORS */
BGP_ERR_INVALID_ROLE_NAME = -35,
- BGP_ERR_INVALID_INTERNAL_ROLE = -36,
-
- /* BGP ORR ERRORS */
- BGP_ERR_PEER_ORR_CONFIGURED = -37,
+ BGP_ERR_INVALID_INTERNAL_ROLE = -36
};
/*
extern struct peer *peer_lookup_dynamic_neighbor(struct bgp *,
union sockunion *);
-extern bool peer_orr_rrclient_check(struct peer *peer, afi_t afi, safi_t safi);
/*
* Peers are incredibly easy to memory leak
* due to the various ways that they are actually used
extern void bgp_close(void);
extern void bgp_free(struct bgp *);
void bgp_gr_apply_running_config(void);
-extern int bgp_afi_safi_orr_group_set(struct bgp *bgp, afi_t afi, safi_t safi,
- const char *name, struct peer *primary,
- struct peer *secondary,
- struct peer *tertiary);
-extern int bgp_afi_safi_orr_group_unset(struct bgp *bgp, afi_t afi, safi_t safi,
- const char *name);
/* BGP GR */
int bgp_global_gr_init(struct bgp *bgp);
bgpd/bgp_vty.c \
bgpd/bgp_zebra.c \
bgpd/bgpd.c \
- bgpd/bgp_orr.c \
bgpd/bgp_trace.c \
# end
bgpd/bgp_vty.h \
bgpd/bgp_zebra.h \
bgpd/bgpd.h \
- bgpd/bgp_orr.h \
bgpd/bgp_trace.h \
\
bgpd/rfapi/bgp_rfapi_cfg.h \
Total number of prefixes 3
Router2#
-.. _bgp-optimal-route-reflection:
-
-BGP Optimal Route Reflection
-----------------------------
-BGP Route Reflectors (RRs) are used to improve network scalability by reducing
-or eliminating the need for a full-mesh of IBGP sessions.
-
-When a BGP RR receives multiple paths for the same IP prefix, it typically
-selects a single best path to send for all its clients.
-If the RR has multiple nearly-equal best paths and the tie-break is determined
-by the next-hop cost, the RR advertises the path based on its view of next-hop
-costs, which leads to a non-optimal routing.
-The advertised route may differ from the path that a client would select
-if it had the visibility of the same set of candidate paths and used
-its own view of next-hop costs.
-
-Non-optimal advertisements by the RR can be a problem in hot-potato routing.
-Hot-potato routing aims to hand off traffic to the next AS using the closest
-possible exit point from the local AS.
-In this context, the closest exit point implies minimum IGP cost to
-reach the BGP next-hop.
-
-The BGP Optimal Route Reflection allows the RR to choose and send a different
-best path to a different or a set of RR clients.
-
-A link-state protocol is required. It can be OSPF or IS-IS.
-Current implementation of BGP ORR is based on the IGP cost to the BGP next hop,
-and not based on some configured policy.
-
-RR runs Shortest Path First (SPF) calculation with the selected
-router as the root of the tree and calculates the cost to every other router.
-
-This special SPF calculation with another router as the root, is referred to as
-a Reverse SPF (rSPF). This can only be done if the RR learns all the BGP paths
-from all the BGP border routers.
-
-There could be as many rSPFs run as there are RR clients.
-This will increase the CPU load somewhat on the RR.
-
-Current implementation allows up to three root nodes for the rSPF calculation.
-There is no need to configure each RR client as a root and run rSPF.
-Current implementation allows to configure three, the primary, the secondary,
-and the tertiary root, per set of RR clients, for redundancy purposes.
-For the BGP ORR feature to apply to any RR client, that RR client must be
-configured to be part of an ORR policy group.
-
-The BGP ORR feature is enabled per address family.
-
-The minimal configuration needed:
-
-1. ORR needs to be enabled for specific groups of BGP neighbors.
-2. For each group of BGP neighbors, at least one root needs to be configured.
- Optionally, a secondary and tertiary root can be configured.
-3. For OSPF, the root routers(RR clients) need additional configuration
- to make BGP ORR work.
- i.e. The MPLS TE configuration on the root router needs to have the minimal
- configuration for MPLS TE enabled so that OSPF advertises the MPLS TE
- router ID in an opaque-area LSA (type 10).
- Once the RR has an opaque-area LSA with the MPLS TE router-ID matching the
- configured root router address, rSPF can run and BGP on the RR can
- advertise the optimal route.
-
-.. clicmd:: neighbor A.B.C.D optimal-route-reflection NAME
-
- This command allows the neighbor to be part of the ORR group.
-
-.. clicmd:: optimal-route-reflection orr-1 A.B.C.D [A.B.C.D] [A.B.C.D]
-
- This command creates an ORR group with a mandatory primary root
- and optional secondary and/or tertiary roots.
- When primary is reachable it will be the active root.
- when primary goes down, secondary followed by tertiary takes over
- the active root's role.
- Always rSPF calculation runs active root as the root.
- Which means the RR advertises the path based on active root's
- view of next-hop costs.
-
-Sample Configuration
-^^^^^^^^^^^^^^^^^^^^
-
-Sample configuration on Route Reflector
-
-.. code-block:: frr
-
- !
- debug ospf 8 orr
- debug bgp optimal-route-reflection
- !
- interface enp0s8
- ip address 10.10.68.8/24
- ip ospf 8 area 0
- exit
- !
- interface lo
- ip address 10.100.1.8/32
- ip ospf 8 area 0
- exit
- !
- router bgp 1
- neighbor 10.100.1.1 remote-as 1
- neighbor 10.100.1.1 update-source lo
- neighbor 10.100.1.2 remote-as 1
- neighbor 10.100.1.2 update-source lo
- neighbor 10.100.1.3 remote-as 1
- neighbor 10.100.1.3 update-source lo
- neighbor 10.100.1.4 remote-as 1
- neighbor 10.100.1.4 update-source lo
- !
- address-family ipv4 unicast
- neighbor 10.100.1.1 route-reflector-client
- neighbor 10.100.1.1 optimal-route-reflection orr-1
- neighbor 10.100.1.2 route-reflector-client
- neighbor 10.100.1.2 optimal-route-reflection orr-1
- neighbor 10.100.1.3 route-reflector-client
- neighbor 10.100.1.3 optimal-route-reflection orr-1
- neighbor 10.100.1.4 route-reflector-client
- neighbor 10.100.1.4 optimal-route-reflection orr-1
- optimal-route-reflection orr-1 10.100.1.4 10.100.1.3 10.100.1.1
- exit-address-family
- exit
- !
- router ospf 8
- ospf router-id 8.8.8.8
- area 0 authentication
- capability opaque
- exit
- !
- end
-
-Sample configuration on RR clients
-
-.. code-block:: frr
-
- interface enp0s8
- ip address 10.10.34.4/24
- ip ospf 4 area 0
- link-params
- enable
- exit-link-params
- exit
- !
- interface enp0s9
- ip address 10.10.74.4/24
- ip ospf 4 area 0
- link-params
- enable
- exit-link-params
- exit
- !
- interface lo
- ip address 10.100.1.4/32
- ip ospf 4 area 0
- exit
- !
- router bgp 1
- neighbor 10.100.1.8 remote-as 1
- neighbor 10.100.1.8 update-source lo
- !
- address-family ipv4 unicast
- neighbor 10.100.1.8 soft-reconfiguration inbound
- exit-address-family
- exit
- !
- router ospf 4
- ospf router-id 4.4.4.4
- area 0 authentication
- capability opaque
- mpls-te on
- mpls-te router-address 10.100.1.4
- mpls-te inter-as area 0.0.0.0
- mpls-te export
- exit
- !
- end
-
-Sample Output
-^^^^^^^^^^^^^
-
-When Optimal Route Reflection is not enabled on RR, it sends 10.100.1.1 as the best path to its clients.
-
-.. code-block:: frr
-
- Router-RR# show ip bgp neighbors 10.100.1.4
-
- !--- Output suppressed.
-
- For address family: IPv4 Unicast
- Update group 2, subgroup 2
- Packet Queue length 0
- Route-Reflector Client
- Community attribute sent to this neighbor(all)
- 0 accepted prefixes
-
- !--- Output suppressed.
-
- Router-RR#
- Router-RR# show ip bgp
- BGP table version is 3, local router ID is 10.100.1.8, vrf id 0
- Default local pref 100, local AS 1
- Status codes: s suppressed, d damped, h history, * valid, > best, = multipath,
- i internal, r RIB-failure, S Stale, R Removed
- Nexthop codes: @NNN nexthop's vrf id, < announce-nh-self
- Origin codes: i - IGP, e - EGP, ? - incomplete
- RPKI validation codes: V valid, I invalid, N Not found
-
- Network Next Hop Metric LocPrf Weight Path
- * i203.0.113.0/24 10.100.1.2 0 100 0 i
- *>i 10.100.1.1 0 100 0 i
- *=i 10.100.1.3 0 100 0 i
-
- Displayed 1 routes and 3 total paths
- Router-RR#
-
- Router-PE4# show ip bgp
- BGP table version is 5, local router ID is 10.100.1.4, vrf id 0
- Default local pref 100, local AS 1
- Status codes: s suppressed, d damped, h history, * valid, > best, = multipath,
- i internal, r RIB-failure, S Stale, R Removed
- Nexthop codes: @NNN nexthop's vrf id, < announce-nh-self
- Origin codes: i - IGP, e - EGP, ? - incomplete
- RPKI validation codes: V valid, I invalid, N Not found
-
- Network Next Hop Metric LocPrf Weight Path
- *>i203.0.113.0/24 10.100.1.1 0 100 0 i
-
- Displayed 1 routes and 1 total paths
- Router-PE4#
-
-When Optimal Route Reflection is enabled on RR, it sends 10.100.1.3 as the best path to its clients.
-
-.. code-block:: frr
-
- Router-RR# show ip bgp neighbors 10.100.1.4
-
- !--- Output suppressed.
-
- For address family: IPv4 Unicast
- Update group 1, subgroup 1
- Packet Queue length 0
- Route-Reflector Client
- ORR group (configured) : orr-1
- Community attribute sent to this neighbor(all)
- 0 accepted prefixes
-
- !--- Output suppressed.
-
- Router-RR#
- Router-RR# show ip bgp
- BGP table version is 1, local router ID is 10.100.1.8, vrf id 0
- Default local pref 100, local AS 1
- Status codes: s suppressed, d damped, h history, * valid, > best, = multipath,
- i internal, r RIB-failure, S Stale, R Removed
- Nexthop codes: @NNN nexthop's vrf id, < announce-nh-self
- Origin codes: i - IGP, e - EGP, ? - incomplete
- RPKI validation codes: V valid, I invalid, N Not found
-
- Network Next Hop Metric LocPrf Weight Path
- * i203.0.113.0/24 10.100.1.2 0 100 0 i
- *>i 10.100.1.3 0 100 0 i
- * i 10.100.1.1 0 100 0 i
-
- Displayed 1 routes and 3 total paths
- Router-RR#
-
- Router-RR# show ip bgp optimal-route-reflection
-
- ORR group: orr-1, IPv4 Unicast
- Configured root: primary: 10.100.1.4(Router-PE4), secondary: 10.100.1.3(Router-PE3), tertiary: 10.100.1.1(Router-PE1)
- Active Root: 10.100.1.4(Router-PE4)
-
- RR Clients mapped:
- 10.100.1.1
- 10.100.1.2
- 10.100.1.3
- 10.100.1.4
-
- Number of mapping entries: 4
-
- Prefix Cost
- 10.10.34.0/24 100
- 10.10.61.0/24 300
- 10.10.63.0/24 200
- 10.10.67.0/24 200
- 10.10.68.0/24 300
- 10.10.72.0/24 200
- 10.10.74.0/24 100
- 10.100.1.1/32 300
- 10.100.1.2/32 200
- 10.100.1.3/32 100
- 10.100.1.4/32 0
- 10.100.1.6/32 200
- 10.100.1.7/32 100
- 10.100.1.8/32 300
-
- Number of mapping entries: 14
-
- Router-RR#
-
- Router-PE4# show ip bgp
- BGP table version is 3, local router ID is 10.100.1.4, vrf id 0
- Default local pref 100, local AS 1
- Status codes: s suppressed, d damped, h history, * valid, > best, = multipath,
- i internal, r RIB-failure, S Stale, R Removed
- Nexthop codes: @NNN nexthop's vrf id, < announce-nh-self
- Origin codes: i - IGP, e - EGP, ? - incomplete
- RPKI validation codes: V valid, I invalid, N Not found
-
- Network Next Hop Metric LocPrf Weight Path
- *>i203.0.113.0/24 10.100.1.3 0 100 0 i
-
- Displayed 1 routes and 1 total paths
- Router-PE4#
-
.. _bgp-debugging:
Debugging
Enable or disable debugging of communications between *bgpd* and *zebra*.
-.. clicmd:: debug bgp optimal-route-reflection
-
- Enable or disable debugging of BGP Optimal Route Reflection.
-
Dumping Messages and Routing Tables
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
User can get that information as JSON format when ``json`` keyword
at the end of cli is presented.
-.. clicmd:: show ip ospf (1-65535) route orr [NAME]
-
-.. clicmd:: show ip ospf [vrf <NAME|all>] route orr [NAME]
-
- Show the OSPF routing table, calculated from the active root of all ORR groups or specified ORR group.
-
.. clicmd:: show ip ospf graceful-restart helper [detail] [json]
Displays the Grcaeful Restart Helper details including helper
.. clicmd:: show debugging ospf
-.. clicmd:: debug ospf orr
-
- Enable or disable debugging of BGP Optimal Route Reflection.
-
Sample Configuration
====================
#define BGP_SOFT_IN_STR "Send route-refresh unless using 'soft-reconfiguration inbound'\n"
#define BGP_SOFT_OUT_STR "Resend all outbound updates\n"
#define BGP_SOFT_RSCLIENT_RIB_STR "Soft reconfig for rsclient RIB\n"
-#define BGP_ORR_DEBUG "Enable Optimal Route Reflection Debugging logs\n"
#define OSPF_STR "OSPF information\n"
#define NEIGHBOR_STR "Specify neighbor router\n"
#define DEBUG_STR "Debugging functions\n"
+++ /dev/null
-/*
- * Structures common to BGP, OSPF and ISIS for BGP Optimal Route Reflection
- * Copyright (C) 2021 Samsung R&D Institute India - Bangalore.
- * Madhurilatha Kuruganti
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; see the file COPYING; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#ifndef _FRR_ORR_MSG_H
-#define _FRR_ORR_MSG_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* REVISIT: Need to check if we can use zero length array */
-#define ORR_MAX_PREFIX 100
-#define ORR_GROUP_NAME_SIZE 32
-
-struct orr_prefix_metric {
- struct prefix prefix;
- uint32_t metric;
-};
-
-/* BGP-IGP Register for IGP metric */
-struct orr_igp_metric_reg {
- bool reg;
- uint8_t proto;
- safi_t safi;
- struct prefix prefix;
- char group_name[ORR_GROUP_NAME_SIZE];
-};
-
-/* IGP-BGP message structures */
-struct orr_igp_metric_info {
- /* IGP instance data. */
- uint8_t proto;
- uint32_t instId;
-
- safi_t safi;
-
- /* Add or delete routes */
- bool add;
-
- /* IGP metric from Active Root. */
- struct prefix root;
- uint32_t num_entries;
- struct orr_prefix_metric nexthop[ORR_MAX_PREFIX];
-};
-
-/* BGP ORR Root node */
-struct orr_root {
- afi_t afi;
- safi_t safi;
-
- char group_name[ORR_GROUP_NAME_SIZE];
-
- /* MPLS_TE prefix and router ID */
- struct prefix prefix;
- struct in_addr router_id;
-
- /* Advertising OSPF Router ID. */
- struct in_addr adv_router;
-
- /* BGP-ORR Received LSAs */
- struct ospf_lsa *router_lsa_rcvd;
-
- /* Routing tables from root node */
- struct route_table *old_table; /* Old routing table. */
- struct route_table *new_table; /* Current routing table. */
-
- struct route_table *old_rtrs; /* Old ABR/ASBR RT. */
- struct route_table *new_rtrs; /* New ABR/ASBR RT. */
-};
-
-/* Prototypes. */
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _FRR_ORR_MSG_H */
lib/ns.h \
lib/openbsd-queue.h \
lib/openbsd-tree.h \
- lib/orr_msg.h \
lib/plist.h \
lib/prefix.h \
lib/printfrr.h \
struct vrf *vrfp = (struct vrf *)args->list_entry;
if (vrfp->status == VRF_ACTIVE)
- return yang_data_new_bool(
- args->xpath, vrfp->status == VRF_ACTIVE ? true : false);
+ return yang_data_new_bool(args->xpath, true);
return NULL;
}
extern struct sockaddr_storage zclient_addr;
extern socklen_t zclient_addr_len;
-#define ZAPI_ORR_FLAG_UNICAST 0x01
-
/* Zebra message types. */
typedef enum {
ZEBRA_INTERFACE_ADD,
LDP_RLFA_UNREGISTER_ALL = 8,
/* Announce LDP labels associated to a previously registered RLFA */
LDP_RLFA_LABELS = 9,
- /* Register for IGP METRIC with OSPF/ISIS */
- ORR_IGP_METRIC_REGISTER = 10,
- /* Send SPF data to BGP */
- ORR_IGP_METRIC_UPDATE = 11
};
/* Send the hello message.
unsigned long conf_debug_ospf_gr;
unsigned long conf_debug_ospf_bfd;
unsigned long conf_debug_ospf_client_api;
-unsigned long conf_debug_ospf_orr;
/* Enable debug option variables -- valid only session. */
unsigned long term_debug_ospf_packet[5] = {0, 0, 0, 0, 0};
unsigned long term_debug_ospf_gr;
unsigned long term_debug_ospf_bfd;
unsigned long term_debug_ospf_client_api;
-unsigned long term_debug_ospf_orr;
const char *ospf_redist_string(unsigned int route_type)
{
return CMD_SUCCESS;
}
-DEFPY (debug_ospf_orr,
- debug_ospf_orr_cmd,
- "[no$no] debug ospf [(1-65535)$instance] orr",
- NO_STR
- DEBUG_STR
- OSPF_STR
- "Instance ID\n"
- "OSPF ORR information\n")
-{
- if (instance && instance != ospf_instance)
- return CMD_NOT_MY_INSTANCE;
-
- if (vty->node == CONFIG_NODE) {
- if (no)
- DEBUG_OFF(orr, ORR);
- else
- DEBUG_ON(orr, ORR);
- } else {
- if (no)
- TERM_DEBUG_OFF(orr, ORR);
- else
- TERM_DEBUG_ON(orr, ORR);
- }
-
- return CMD_SUCCESS;
-}
-
DEFUN (no_debug_ospf,
no_debug_ospf_cmd,
"no debug ospf",
for (i = 0; i < 5; i++)
DEBUG_PACKET_OFF(i, flag);
-
- DEBUG_OFF(orr, ORR);
}
for (i = 0; i < 5; i++)
TERM_DEBUG_OFF(ti_lfa, TI_LFA);
TERM_DEBUG_OFF(bfd, BFD_LIB);
TERM_DEBUG_OFF(client_api, CLIENT_API);
- TERM_DEBUG_OFF(orr, ORR);
return CMD_SUCCESS;
}
if (IS_DEBUG_OSPF(client_api, CLIENT_API) == OSPF_DEBUG_CLIENT_API)
vty_out(vty, " OSPF client-api debugging is on\n");
- /* Show debug status for ORR. */
- if (IS_DEBUG_OSPF(orr, ORR) == OSPF_DEBUG_ORR)
- vty_out(vty, " OSPF ORR debugging is on\n");
-
- vty_out(vty, "\n");
-
return CMD_SUCCESS;
}
write = 1;
}
- /* debug ospf orr */
- if (IS_CONF_DEBUG_OSPF(orr, ORR) == OSPF_DEBUG_ORR) {
- vty_out(vty, "debug ospf%s orr\n", str);
- write = 1;
- }
-
return write;
}
install_element(ENABLE_NODE, &debug_ospf_default_info_cmd);
install_element(ENABLE_NODE, &debug_ospf_ldp_sync_cmd);
install_element(ENABLE_NODE, &debug_ospf_client_api_cmd);
- install_element(ENABLE_NODE, &debug_ospf_orr_cmd);
install_element(ENABLE_NODE, &no_debug_ospf_ism_cmd);
install_element(ENABLE_NODE, &no_debug_ospf_nsm_cmd);
install_element(ENABLE_NODE, &no_debug_ospf_lsa_cmd);
install_element(CONFIG_NODE, &debug_ospf_default_info_cmd);
install_element(CONFIG_NODE, &debug_ospf_ldp_sync_cmd);
install_element(CONFIG_NODE, &debug_ospf_client_api_cmd);
- install_element(CONFIG_NODE, &debug_ospf_orr_cmd);
install_element(CONFIG_NODE, &no_debug_ospf_nsm_cmd);
install_element(CONFIG_NODE, &no_debug_ospf_lsa_cmd);
install_element(CONFIG_NODE, &no_debug_ospf_zebra_cmd);
#define OSPF_DEBUG_CLIENT_API 0x01
-#define OSPF_DEBUG_ORR 0x01
-
/* Macro for setting debug option. */
#define CONF_DEBUG_PACKET_ON(a, b) conf_debug_ospf_packet[a] |= (b)
#define CONF_DEBUG_PACKET_OFF(a, b) conf_debug_ospf_packet[a] &= ~(b)
#define AREA_NAME(A) ospf_area_name_string ((A))
#define IF_NAME(I) ospf_if_name_string ((I))
-#define IS_DEBUG_OSPF_ORR IS_DEBUG_OSPF(orr, ORR)
-
/* Extern debug flag. */
extern unsigned long term_debug_ospf_packet[];
extern unsigned long term_debug_ospf_event;
extern unsigned long term_debug_ospf_gr;
extern unsigned long term_debug_ospf_bfd;
extern unsigned long term_debug_ospf_client_api;
-extern unsigned long term_debug_ospf_orr;
/* Message Strings. */
extern char *ospf_lsa_type_str[];
#include "ospfd/ospf_zebra.h"
#include "ospfd/ospf_abr.h"
#include "ospfd/ospf_errors.h"
-#include "ospfd/ospf_te.h"
-#include "ospfd/ospf_orr.h"
static struct ospf_lsa *ospf_handle_summarylsa_lsId_chg(struct ospf *ospf,
struct prefix_ipv4 *p,
ospf_refresher_register_lsa(ospf, new);
}
- /* For BGP ORR SPF should be calculated from specified root(s) */
- else if (ospf->orr_spf_request) {
- ospf_lsa_unlock(&area->router_lsa_rcvd);
- area->router_lsa_rcvd = ospf_lsa_lock(new);
- ospf_orr_root_update_rcvd_lsa(area->router_lsa_rcvd);
- }
-
if (rt_recalc)
ospf_spf_calculate_schedule(ospf, SPF_FLAG_ROUTER_LSA_INSTALL);
return new;
struct ospf_lsa *new,
int rt_recalc)
{
+
/* RFC 2328 Section 13.2 Router-LSAs and network-LSAs
The entire routing table must be recalculated, starting with
the shortest path calculations for each area (not just the
return NULL;
}
-struct ospf_lsa *ospf_lsa_lookup_by_adv_rid(struct ospf_area *area,
- uint32_t type, struct in_addr id)
-{
- struct ospf_lsa *lsa = NULL;
- struct route_node *rn = NULL;
-
- switch (type) {
- case OSPF_ROUTER_LSA:
- for (rn = route_top(ROUTER_LSDB(area)); rn;
- rn = route_next(rn)) {
- lsa = rn->info;
- if (lsa) {
- if (IPV4_ADDR_SAME(&lsa->data->adv_router,
- &id)) {
- route_unlock_node(rn);
- return lsa;
- }
- }
- }
- break;
- case OSPF_NETWORK_LSA:
- case OSPF_SUMMARY_LSA:
- case OSPF_ASBR_SUMMARY_LSA:
- case OSPF_AS_EXTERNAL_LSA:
- case OSPF_AS_NSSA_LSA:
- case OSPF_OPAQUE_LINK_LSA:
- case OSPF_OPAQUE_AREA_LSA:
- case OSPF_OPAQUE_AS_LSA:
- /* Currently not used. */
- break;
- default:
- break;
- }
-
- return NULL;
-}
-
-struct ospf_lsa *ospf_lsa_lookup_by_mpls_te_rid(struct ospf_area *area,
- uint32_t type,
- struct in_addr id)
-{
- struct ospf_lsa *lsa = NULL;
- struct route_node *rn = NULL;
- struct lsa_header *lsah = NULL;
- uint32_t lsid;
- uint8_t opaque_type;
- struct tlv_header *tlvh = NULL;
- struct te_tlv_router_addr *router_addr = NULL;
-
- if (type != OSPF_OPAQUE_AREA_LSA)
- return NULL;
-
- for (rn = route_top(OPAQUE_AREA_LSDB(area)); rn; rn = route_next(rn)) {
- lsa = rn->info;
- if (lsa) {
- lsah = lsa->data;
- lsid = ntohl(lsah->id.s_addr);
- opaque_type = GET_OPAQUE_TYPE(lsid);
- if (opaque_type != OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA)
- continue;
-
- tlvh = TLV_HDR_TOP(lsah);
- if (!tlvh ||
- (ntohs(tlvh->type) != TE_TLV_ROUTER_ADDR) ||
- (ntohs(tlvh->length) != TE_LINK_SUBTLV_DEF_SIZE))
- continue;
- router_addr = (struct te_tlv_router_addr *)tlvh;
- if (IPV4_ADDR_SAME(&router_addr->value, &id)) {
- route_unlock_node(rn);
- return lsa;
- }
- }
- }
- return NULL;
-}
-
struct ospf_lsa *ospf_lsa_lookup_by_header(struct ospf_area *area,
struct lsa_header *lsah)
{
struct as_external_lsa *al;
struct prefix_ipv4 p;
- if (!CHECK_FLAG(lsa->flags, OSPF_LSA_SELF) && !IS_LSA_SELF(lsa) &&
- !IS_LSA_ORR(lsa))
- return NULL;
+ assert(CHECK_FLAG(lsa->flags, OSPF_LSA_SELF));
+ assert(IS_LSA_SELF(lsa));
assert(lsa->lock > 0);
switch (lsa->data->type) {
uint16_t index, current_index;
assert(lsa->lock > 0);
- if (!IS_LSA_SELF(lsa) && !IS_LSA_ORR(lsa))
- return;
+ assert(IS_LSA_SELF(lsa));
if (lsa->refresh_list < 0) {
int delay;
void ospf_refresher_unregister_lsa(struct ospf *ospf, struct ospf_lsa *lsa)
{
assert(lsa->lock > 0);
- if (!IS_LSA_SELF(lsa) || !IS_LSA_ORR(lsa))
- return;
+ assert(IS_LSA_SELF(lsa));
if (lsa->refresh_list >= 0) {
struct list *refresh_list =
ospf->lsa_refresh_queue.qs[lsa->refresh_list];
/* OSPF LSA. */
struct ospf_lsa {
/* LSA origination flag. */
- uint16_t flags;
-#define OSPF_LSA_SELF 0x0001
-#define OSPF_LSA_SELF_CHECKED 0x0002
-#define OSPF_LSA_RECEIVED 0x0004
-#define OSPF_LSA_APPROVED 0x0008
-#define OSPF_LSA_DISCARD 0x0010
-#define OSPF_LSA_LOCAL_XLT 0x0020
-#define OSPF_LSA_PREMATURE_AGE 0x0040
-#define OSPF_LSA_IN_MAXAGE 0x0080
-#define OSPF_LSA_ORR 0x0100
+ uint8_t flags;
+#define OSPF_LSA_SELF 0x01
+#define OSPF_LSA_SELF_CHECKED 0x02
+#define OSPF_LSA_RECEIVED 0x04
+#define OSPF_LSA_APPROVED 0x08
+#define OSPF_LSA_DISCARD 0x10
+#define OSPF_LSA_LOCAL_XLT 0x20
+#define OSPF_LSA_PREMATURE_AGE 0x40
+#define OSPF_LSA_IN_MAXAGE 0x80
/* LSA data. and size */
struct lsa_header *data;
#define IS_LSA_MAXAGE(L) (LS_AGE ((L)) == OSPF_LSA_MAXAGE)
#define IS_LSA_MAX_SEQ(L) \
((L)->data->ls_seqnum == htonl(OSPF_MAX_SEQUENCE_NUMBER))
-#define IS_LSA_ORR(L) (CHECK_FLAG ((L)->flags, OSPF_LSA_ORR))
#define OSPF_LSA_UPDATE_DELAY 2
struct in_addr);
extern struct ospf_lsa *ospf_lsa_lookup_by_id(struct ospf_area *, uint32_t,
struct in_addr);
-extern struct ospf_lsa *ospf_lsa_lookup_by_adv_rid(struct ospf_area *area,
- uint32_t type,
- struct in_addr id);
-extern struct ospf_lsa *ospf_lsa_lookup_by_mpls_te_rid(struct ospf_area *area,
- uint32_t type,
- struct in_addr id);
extern struct ospf_lsa *ospf_lsa_lookup_by_header(struct ospf_area *,
struct lsa_header *);
extern int ospf_lsa_more_recent(struct ospf_lsa *, struct ospf_lsa *);
#include "ospfd/ospf_asbr.h"
#include "ospfd/ospf_lsa.h"
#include "ospfd/ospf_lsdb.h"
-#include "ospfd/ospf_orr.h"
struct ospf_lsdb *ospf_lsdb_new(void)
{
assert(rn->table == lsdb->type[lsa->data->type].db);
- /* Update ORR Root table MPLS-TE Router address's advertise router */
- if (lsa->data->type == OSPF_OPAQUE_AREA_LSA)
- ospf_orr_root_table_update(lsa, false);
-
if (IS_LSA_SELF(lsa))
lsdb->type[lsa->data->type].count_self--;
lsdb->type[lsa->data->type].count--;
#endif /* MONITOR_LSDB_CHANGE */
lsdb->type[lsa->data->type].checksum += ntohs(lsa->data->checksum);
rn->info = ospf_lsa_lock(lsa); /* lsdb */
-
- /* Update ORR Root table MPLS-TE Router address's advertise router */
- if (lsa->data->type == OSPF_OPAQUE_AREA_LSA)
- ospf_orr_root_table_update(lsa, true);
}
void ospf_lsdb_delete(struct ospf_lsdb *lsdb, struct ospf_lsa *lsa)
DEFINE_MTYPE(OSPFD, OSPF_EXTERNAL_RT_AGGR, "OSPF External Route Summarisation");
DEFINE_MTYPE(OSPFD, OSPF_P_SPACE, "OSPF TI-LFA P-Space");
DEFINE_MTYPE(OSPFD, OSPF_Q_SPACE, "OSPF TI-LFA Q-Space");
-DEFINE_MTYPE(OSPFD, OSPF_ORR_ROOT, "OSPF ORR Root");
DECLARE_MTYPE(OSPF_EXTERNAL_RT_AGGR);
DECLARE_MTYPE(OSPF_P_SPACE);
DECLARE_MTYPE(OSPF_Q_SPACE);
-DECLARE_MTYPE(OSPF_ORR_ROOT);
#endif /* _QUAGGA_OSPF_MEMORY_H */
+++ /dev/null
-/*
- * OSPF BGP-IGP IGP metric update handling routines
- * Copyright (C) 2021 Samsung R&D Institute India - Bangalore.
- * Madhurilatha Kuruganti
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; see the file COPYING; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include <zebra.h>
-#include <string.h>
-
-#include "monotime.h"
-#include "memory.h"
-#include "thread.h"
-#include "prefix.h"
-#include "table.h"
-#include "vty.h"
-#include "command.h"
-#include "plist.h"
-#include "log.h"
-#include "zclient.h"
-#include <lib/json.h>
-#include "defaults.h"
-#include "orr_msg.h"
-
-#include "ospfd.h"
-#include "ospf_asbr.h"
-#include "ospf_dump.h"
-#include "ospf_lsa.h"
-#include "ospf_orr.h"
-#include "ospf_route.h"
-#include "ospf_spf.h"
-#include "ospf_te.h"
-
-static void ospf_show_orr_root(struct orr_root *root);
-static void ospf_show_orr(struct ospf *ospf, afi_t afi, safi_t safi);
-static struct orr_root *ospf_orr_root_new(struct ospf *ospf, afi_t afi,
- safi_t safi, struct prefix *p,
- char *group_name)
-{
- struct list *orr_root_list = NULL;
- struct orr_root *root = NULL;
-
- if (!ospf->orr_root[afi][safi])
- ospf->orr_root[afi][safi] = list_new();
-
- orr_root_list = ospf->orr_root[afi][safi];
- root = XCALLOC(MTYPE_OSPF_ORR_ROOT, sizeof(struct orr_root));
-
- listnode_add(orr_root_list, root);
-
- root->afi = afi;
- root->safi = safi;
- prefix_copy(&root->prefix, p);
- IPV4_ADDR_COPY(&root->router_id, &p->u.prefix4);
- strlcpy(root->group_name, group_name, sizeof(root->group_name));
- root->new_rtrs = NULL;
- root->new_table = NULL;
-
- ospf_orr_debug(
- "%s: For %s %s, ORR Group %s, created ORR Root entry %pFX.",
- __func__, afi2str(afi), safi2str(safi), root->group_name, p);
-
- return root;
-}
-
-static struct orr_root *ospf_orr_root_lookup(struct ospf *ospf, afi_t afi,
- safi_t safi, struct in_addr *rid)
-{
- struct list *orr_root_list = NULL;
- struct orr_root *root = NULL;
- struct listnode *node;
-
- orr_root_list = ospf->orr_root[afi][safi];
- if (!orr_root_list)
- return NULL;
-
- for (ALL_LIST_ELEMENTS_RO(orr_root_list, node, root))
- if (IPV4_ADDR_SAME(&root->router_id, rid))
- return root;
-
- ospf_orr_debug("%s: For %s %s, ORR Root '%pI4' not found.", __func__,
- afi2str(afi), safi2str(safi), rid);
-
- return NULL;
-}
-
-static struct orr_root *ospf_orr_root_lookup_by_adv_rid(struct ospf *ospf,
- afi_t afi, safi_t safi,
- struct in_addr *rid)
-{
- struct list *orr_root_list = NULL;
- struct orr_root *root = NULL;
- struct listnode *node;
-
- orr_root_list = ospf->orr_root[afi][safi];
- if (!orr_root_list)
- return NULL;
-
- for (ALL_LIST_ELEMENTS_RO(orr_root_list, node, root))
- if (IPV4_ADDR_SAME(&root->adv_router, rid))
- return root;
-
- return NULL;
-}
-
-/*
- * Lookup each area's LSDB if is there is any opaque area LSA received and
- * update the root database with the advertising router.
- */
-static struct ospf_lsa *
-ospf_orr_lookup_opaque_area_lsa_by_id(struct in_addr rid)
-{
- struct ospf_lsa *lsa = NULL;
- struct ospf_area *area = NULL;
- struct ospf *ospf = NULL;
- struct listnode *node = NULL, *nnode = NULL;
-
- /* if ospf is not enabled ignore */
- ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
- if (!ospf)
- return NULL;
-
- /* Lookup for Opaque area LSA in each area. */
- for (ALL_LIST_ELEMENTS(ospf->areas, node, nnode, area)) {
- lsa = ospf_lsa_lookup_by_mpls_te_rid(area, OSPF_OPAQUE_AREA_LSA,
- rid);
- if (!lsa)
- continue;
- ospf_orr_debug(
- "%s: Opaque Area LSA found in area %pI4 for %pI4",
- __func__, &area->area_id, &rid);
- return lsa;
- }
- return NULL;
-}
-
-/*
- * Lookup each area's LSDB if is there is any opaque area LSA received and
- * update the root database with the advertising router.
- */
-static struct ospf_lsa *ospf_orr_lookup_router_lsa_by_id(struct in_addr rid)
-{
- struct ospf_lsa *lsa = NULL;
- struct ospf_area *area = NULL;
- struct ospf *ospf = NULL;
- struct listnode *node = NULL, *nnode = NULL;
-
- /* if ospf is not enabled ignore */
- ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
- if (!ospf)
- return NULL;
-
- /* Lookup for Router LSA in each area. */
- for (ALL_LIST_ELEMENTS(ospf->areas, node, nnode, area)) {
- lsa = ospf_lsa_lookup_by_adv_rid(area, OSPF_ROUTER_LSA, rid);
- if (!lsa)
- continue;
- ospf_orr_debug("%s: Router LSA found in area %pI4 for %pI4",
- __func__, &area->area_id, &rid);
- return lsa;
- }
- return NULL;
-}
-
-/*
- * BGP-IGP IGP metric msg between BGP and IGP
- */
-int ospf_orr_igp_metric_register(struct orr_igp_metric_reg msg)
-{
- afi_t afi;
- safi_t safi;
- struct ospf *ospf = NULL;
- struct ospf_lsa *lsa = NULL;
- struct orr_root *root = NULL;
-
- /* if ospf is not enabled ignore */
- ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
- if (!ospf)
- return -1;
-
- if (msg.proto != ZEBRA_ROUTE_BGP)
- return -1;
-
- afi = family2afi(msg.prefix.family);
- safi = msg.safi;
-
- ospf_orr_debug(
- "%s: Received IGP metric %s message from BGP for ORR Group %s from location %pFX",
- __func__, msg.reg ? "Register" : "Unregister", msg.group_name,
- &msg.prefix);
-
- /* Get ORR Root entry for the given address-family */
- root = ospf_orr_root_lookup(ospf, afi, safi, &msg.prefix.u.prefix4);
-
- /* Should not hit this condition */
- if ((root && msg.reg) || (!root && !msg.reg))
- return -1;
-
- /* Create ORR Root entry and calculate SPF from root */
- if (!root) {
- root = ospf_orr_root_new(ospf, afi, safi, &msg.prefix,
- msg.group_name);
- if (!root) {
- ospf_orr_debug(
- "%s: For %s %s, Failed to create ORR Root entry %pFX.",
- __func__, afi2str(afi), safi2str(safi),
- &msg.prefix);
- return -1;
- }
- ospf->orr_spf_request++;
-
- lsa = ospf_orr_lookup_opaque_area_lsa_by_id(root->router_id);
- if (!lsa || !lsa->data)
- return -1;
-
- IPV4_ADDR_COPY(&root->adv_router, &lsa->data->adv_router);
-
- /* Lookup LSDB for Router LSA */
- if (!root->router_lsa_rcvd) {
- lsa = ospf_orr_lookup_router_lsa_by_id(
- root->adv_router);
- if (!lsa || !lsa->data)
- return -1;
- root->router_lsa_rcvd = lsa;
- }
-
- /* Compute SPF for all root nodes */
- ospf_orr_spf_calculate_schedule(ospf);
- }
- /* Delete ORR Root entry. SPF calculation not required. */
- else {
- listnode_delete(ospf->orr_root[afi][safi], root);
- XFREE(MTYPE_OSPF_ORR_ROOT, root);
-
- /* If last node is deleted in the list */
- if (!ospf->orr_root[afi][safi]->count)
- list_delete(&ospf->orr_root[afi][safi]);
-
- ospf->orr_spf_request--;
- }
-
- if (IS_DEBUG_OSPF_ORR)
- ospf_show_orr(ospf, afi, safi);
-
- return 0;
-}
-
-void ospf_orr_igp_metric_send_update_add(struct orr_root *root,
- unsigned short instance)
-{
- int ret;
- uint8_t count = 0;
- struct route_node *rn;
- struct ospf_route *or;
- struct orr_igp_metric_info msg;
-
- memset(&msg, 0, sizeof(msg));
- msg.proto = ZEBRA_ROUTE_OSPF;
- msg.safi = root->safi;
- msg.instId = instance;
- msg.add = true;
- prefix_copy(&msg.root, &root->prefix);
-
- /* Update prefix table from ORR Route table */
- for (rn = route_top(root->new_table); rn; rn = route_next(rn)) {
- or = rn->info;
- if (!or)
- continue;
-
- if (or->type != OSPF_DESTINATION_NETWORK &&
- or->type != OSPF_DESTINATION_DISCARD)
- continue;
-
- if (ospf_route_match_same(root->old_table,
- (struct prefix_ipv4 *)&rn->p, or))
- continue;
-
- if (count < ORR_MAX_PREFIX) {
- prefix_copy(&msg.nexthop[count].prefix,
- (struct prefix_ipv4 *)&rn->p);
- msg.nexthop[count].metric = or->cost;
- count++;
- } else {
- msg.num_entries = count;
- ret = zclient_send_opaque(zclient,
- ORR_IGP_METRIC_UPDATE,
- (uint8_t *)&msg, sizeof(msg));
- if (ret != ZCLIENT_SEND_SUCCESS)
- ospf_orr_debug(
- "%s: Failed to send message to BGP.",
- __func__);
- count = 0;
- prefix_copy(&msg.nexthop[count].prefix,
- (struct prefix_ipv4 *)&rn->p);
- msg.nexthop[count].metric = or->cost;
- count++;
- }
- }
- if (count > 0 && count <= ORR_MAX_PREFIX) {
- msg.num_entries = count;
- ret = zclient_send_opaque(zclient, ORR_IGP_METRIC_UPDATE,
- (uint8_t *)&msg, sizeof(msg));
- if (ret != ZCLIENT_SEND_SUCCESS)
- ospf_orr_debug("%s: Failed to send message to BGP.",
- __func__);
- }
-}
-
-void ospf_orr_igp_metric_send_update_delete(struct orr_root *root,
- unsigned short instance)
-{
- int ret;
- uint8_t count = 0;
- struct route_node *rn;
- struct ospf_route *or;
- struct orr_igp_metric_info msg;
-
- if (!root->old_table)
- return;
-
- memset(&msg, 0, sizeof(msg));
- msg.proto = ZEBRA_ROUTE_OSPF;
- msg.instId = instance;
- msg.safi = root->safi;
- msg.add = false;
- prefix_copy(&msg.root, &root->prefix);
-
- /* Update prefix table from ORR Route table */
- for (rn = route_top(root->old_table); rn; rn = route_next(rn)) {
- or = rn->info;
- if (!or)
- continue;
-
- if (or->path_type != OSPF_PATH_INTRA_AREA &&
- or->path_type != OSPF_PATH_INTER_AREA)
- continue;
-
- if (or->type != OSPF_DESTINATION_NETWORK &&
- or->type != OSPF_DESTINATION_DISCARD)
- continue;
-
- if (ospf_route_exist_new_table(root->new_table,
- (struct prefix_ipv4 *)&rn->p))
- continue;
-
- if (count < ORR_MAX_PREFIX) {
- prefix_copy(&msg.nexthop[count].prefix,
- (struct prefix_ipv4 *)&rn->p);
- msg.nexthop[count].metric = or->cost;
- count++;
- } else {
- msg.num_entries = count;
- ret = zclient_send_opaque(zclient,
- ORR_IGP_METRIC_UPDATE,
- (uint8_t *)&msg, sizeof(msg));
- if (ret != ZCLIENT_SEND_SUCCESS)
- ospf_orr_debug(
- "%s: Failed to send message to BGP.",
- __func__);
- count = 0;
- prefix_copy(&msg.nexthop[count].prefix,
- (struct prefix_ipv4 *)&rn->p);
- msg.nexthop[count].metric = or->cost;
- count++;
- }
- }
- if (count > 0 && count <= ORR_MAX_PREFIX) {
- msg.num_entries = count;
- ret = zclient_send_opaque(zclient, ORR_IGP_METRIC_UPDATE,
- (uint8_t *)&msg, sizeof(msg));
- if (ret != ZCLIENT_SEND_SUCCESS)
- ospf_orr_debug("%s: Failed to send message to BGP.",
- __func__);
- }
-}
-
-static void ospf_show_orr_root(struct orr_root *root)
-{
- if (!root)
- return;
-
- ospf_orr_debug("%s: Address Family: %s %s", __func__,
- afi2str(root->afi), safi2str(root->safi));
- ospf_orr_debug("%s: ORR Group: %s", __func__, root->group_name);
- ospf_orr_debug("%s: Router-Address: %pI4:", __func__, &root->router_id);
- ospf_orr_debug("%s: Advertising Router: %pI4:", __func__,
- &root->adv_router);
-}
-
-static void ospf_show_orr(struct ospf *ospf, afi_t afi, safi_t safi)
-{
- struct listnode *node = NULL;
- struct orr_root *orr_root = NULL;
- struct list *orr_root_list = NULL;
-
- FOREACH_AFI_SAFI (afi, safi) {
- orr_root_list = ospf->orr_root[afi][safi];
- if (!orr_root_list)
- return;
-
- for (ALL_LIST_ELEMENTS_RO(orr_root_list, node, orr_root))
- ospf_show_orr_root(orr_root);
- }
-}
-
-void ospf_orr_root_table_update(struct ospf_lsa *lsa, bool add)
-{
- afi_t afi;
- safi_t safi;
- struct lsa_header *lsah = lsa->data;
- uint32_t lsid = ntohl(lsah->id.s_addr);
- uint8_t opaque_type = GET_OPAQUE_TYPE(lsid);
- uint32_t opaque_id = GET_OPAQUE_ID(lsid);
- struct tlv_header *tlvh = TLV_HDR_TOP(lsah);
- struct te_tlv_router_addr *router_addr = NULL;
- struct orr_root *root = NULL;
- struct ospf *ospf = NULL;
-
- /* if ospf is not enabled ignore */
- ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
- if (!ospf)
- return;
-
- if (opaque_type != OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA)
- return;
-
- if (!tlvh || (ntohs(tlvh->type) != TE_TLV_ROUTER_ADDR) ||
- (ntohs(tlvh->length) != TE_LINK_SUBTLV_DEF_SIZE))
- return;
-
- router_addr = (struct te_tlv_router_addr *)tlvh;
- if (IS_DEBUG_OSPF_ORR) {
- zlog_debug("[OSPF-ORR] %s: Opaque-area LSA %s LSDB", __func__,
- add ? "added to" : "deleted from");
- zlog_debug("[OSPF-ORR] %s: Opaque-Type %u (%s)", __func__,
- opaque_type, "Traffic Engineering LSA");
- zlog_debug("[OSPF-ORR] %s: Opaque-ID 0x%x", __func__,
- opaque_id);
- zlog_debug("[OSPF-ORR] %s: Opaque-Info: %u octets of data%s",
- __func__, ntohs(lsah->length) - OSPF_LSA_HEADER_SIZE,
- VALID_OPAQUE_INFO_LEN(lsah) ? ""
- : "(Invalid length?)");
- zlog_debug("[OSPF-ORR] %s: Router-Address: %pI4", __func__,
- &router_addr->value);
- zlog_debug("[OSPF-ORR] %s: Advertising Router: %pI4", __func__,
- &lsa->data->adv_router);
- }
- /*
- * When Opaque LSA is added or removed from LSDB check if there is any
- * change in MPLS-TE Router address and Advertising router address and
- * update the table accordingly if there is no change in the mapping
- * ignore update
- *
- * Get ORR Root entry for the given address-family
- */
- FOREACH_AFI_SAFI (afi, safi) {
- root = ospf_orr_root_lookup(ospf, afi, safi,
- &router_addr->value);
- if (root) {
- IPV4_ADDR_COPY(&root->adv_router,
- &lsa->data->adv_router);
- if (IS_DEBUG_OSPF_ORR)
- ospf_show_orr(ospf, afi, safi);
- break;
- }
- }
-}
-
-void ospf_orr_root_update_rcvd_lsa(struct ospf_lsa *lsa)
-{
- afi_t afi;
- safi_t safi;
- struct orr_root *root = NULL;
-
- if (!lsa || !lsa->area || !lsa->area->ospf)
- return;
-
- FOREACH_AFI_SAFI (afi, safi) {
- root = ospf_orr_root_lookup_by_adv_rid(
- lsa->area->ospf, afi, safi, &lsa->data->adv_router);
- if (root) {
- SET_FLAG(lsa->flags, OSPF_LSA_ORR);
- ospf_refresher_register_lsa(lsa->area->ospf, lsa);
- root->router_lsa_rcvd = lsa;
- }
-
- ospf_orr_debug("%s: Received LSA[Type%d:%pI4]", __func__,
- lsa->data->type, &lsa->data->adv_router);
-
- /* Compute SPF for all root nodes */
- ospf_orr_spf_calculate_schedule(lsa->area->ospf);
- return;
- }
-}
-
-/* Do not Install routes to root table. Just update table ponters */
-void ospf_orr_route_install(struct orr_root *root, struct route_table *rt,
- unsigned short instance)
-{
- /*
- * rt contains new routing table, new_table contains an old one.
- * updating pointers
- */
- if (root->old_table)
- ospf_route_table_free(root->old_table);
-
- root->old_table = root->new_table;
- root->new_table = rt;
-
- /* Send update to BGP to delete old routes. */
- ospf_orr_igp_metric_send_update_delete(root, instance);
-
- /* REVISIT: Skipping external route table for now */
-
- /* Send update to BGP to add new routes. */
- ospf_orr_igp_metric_send_update_add(root, instance);
-}
-
-void ospf_orr_spf_calculate_schedule(struct ospf *ospf)
-{
- /* OSPF instance does not exist. */
- if (ospf == NULL)
- return;
-
- /* No roots nodes rgistered for rSPF */
- if (!ospf->orr_spf_request)
- return;
-
- /* ORR SPF calculation timer is already scheduled. */
- if (ospf->t_orr_calc) {
- ospf_orr_debug(
- "SPF: calculation timer is already scheduled: %p",
- (void *)ospf->t_orr_calc);
- return;
- }
-
- ospf->t_orr_calc = NULL;
-
- ospf_orr_debug("%s: SPF: calculation timer scheduled", __func__);
-
- thread_add_timer(master, ospf_orr_spf_calculate_schedule_worker, ospf,
- OSPF_ORR_CALC_INTERVAL, &ospf->t_orr_calc);
-}
-
-void ospf_orr_spf_calculate_area(struct ospf *ospf, struct ospf_area *area,
- struct route_table *new_table,
- struct route_table *all_rtrs,
- struct route_table *new_rtrs,
- struct ospf_lsa *lsa_rcvd)
-{
- ospf_spf_calculate(area, lsa_rcvd, new_table, all_rtrs, new_rtrs, false,
- true);
-}
-
-void ospf_orr_spf_calculate_areas(struct ospf *ospf,
- struct route_table *new_table,
- struct route_table *all_rtrs,
- struct route_table *new_rtrs,
- struct ospf_lsa *lsa_rcvd)
-{
- struct ospf_area *area;
- struct listnode *node, *nnode;
-
- /* Calculate SPF for each area. */
- for (ALL_LIST_ELEMENTS(ospf->areas, node, nnode, area)) {
- /*
- * Do backbone last, so as to first discover intra-area paths
- * for any back-bone virtual-links
- */
- if (ospf->backbone && ospf->backbone == area)
- continue;
-
- ospf_orr_spf_calculate_area(ospf, area, new_table, all_rtrs,
- new_rtrs, lsa_rcvd);
- }
-
- /* SPF for backbone, if required */
- if (ospf->backbone)
- ospf_orr_spf_calculate_area(ospf, ospf->backbone, new_table,
- all_rtrs, new_rtrs, lsa_rcvd);
-}
+++ /dev/null
-/*
- * OSPF BGP-IGP IGP metric update handling routines
- * Copyright (C) 2021 Samsung R&D Institute India - Bangalore.
- * Madhurilatha Kuruganti
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; see the file COPYING; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#ifndef _ZEBRA_OSPF_ORR_H
-#define _ZEBRA_OSPF_ORR_H
-
-#define BGP_OSPF_LSINFINITY 65535
-#define OSPF_ORR_CALC_INTERVAL 1
-
-/* Macro to log debug message */
-#define ospf_orr_debug(...) \
- do { \
- if (IS_DEBUG_OSPF_ORR) \
- zlog_debug("[OSPF-ORR] "__VA_ARGS__); \
- } while (0)
-
-extern struct zclient *zclient;
-
-extern int ospf_orr_igp_metric_register(struct orr_igp_metric_reg orr_reg);
-extern void ospf_orr_igp_metric_send_update_add(struct orr_root *root,
- unsigned short instance);
-extern void ospf_orr_igp_metric_send_update_delete(struct orr_root *root,
- unsigned short instance);
-extern void ospf_orr_root_table_update(struct ospf_lsa *lsa, bool add);
-extern void ospf_orr_root_update_rcvd_lsa(struct ospf_lsa *lsa);
-extern void ospf_orr_route_install(struct orr_root *root,
- struct route_table *rt,
- unsigned short instance);
-extern void ospf_orr_spf_calculate_schedule(struct ospf *ospf);
-extern void ospf_orr_spf_calculate_area(struct ospf *ospf,
- struct ospf_area *area,
- struct route_table *new_table,
- struct route_table *all_rtrs,
- struct route_table *new_rtrs,
- struct ospf_lsa *lsa_rcvd);
-extern void ospf_orr_spf_calculate_areas(struct ospf *ospf,
- struct route_table *new_table,
- struct route_table *all_rtrs,
- struct route_table *new_rtrs,
- struct ospf_lsa *lsa_rcvd);
-#endif /* _ZEBRA_OSPF_ORR_H */
otherwise return 0. Since the ZEBRA-RIB does an implicit
withdraw, it is not necessary to send a delete, an add later
will act like an implicit delete. */
-int ospf_route_exist_new_table(struct route_table *rt,
- struct prefix_ipv4 *prefix)
+static int ospf_route_exist_new_table(struct route_table *rt,
+ struct prefix_ipv4 *prefix)
{
struct route_node *rn;
struct prefix_ipv4 *);
extern int ospf_route_match_same(struct route_table *, struct prefix_ipv4 *,
struct ospf_route *);
-extern int ospf_route_exist_new_table(struct route_table *rt,
- struct prefix_ipv4 *prefix);
+
#endif /* _ZEBRA_OSPF_ROUTE_H */
#include "ospfd/ospf_apiserver.h"
#endif
-#include "ospfd/ospf_orr.h"
-
/* Variables to ensure a SPF scheduled log message is printed only once */
static unsigned int spf_reason_flags = 0;
all_rtrs, new_rtrs);
}
-/* Print Reason for SPF calculation */
-static void ospf_spf_calculation_reason2str(char *rbuf, size_t len)
-{
- rbuf[0] = '\0';
- if (spf_reason_flags) {
- if (spf_reason_flags & (1 << SPF_FLAG_ROUTER_LSA_INSTALL))
- strlcat(rbuf, "R, ", len);
- if (spf_reason_flags & (1 << SPF_FLAG_NETWORK_LSA_INSTALL))
- strlcat(rbuf, "N, ", len);
- if (spf_reason_flags & (1 << SPF_FLAG_SUMMARY_LSA_INSTALL))
- strlcat(rbuf, "S, ", len);
- if (spf_reason_flags & (1 << SPF_FLAG_ASBR_SUMMARY_LSA_INSTALL))
- strlcat(rbuf, "AS, ", len);
- if (spf_reason_flags & (1 << SPF_FLAG_ABR_STATUS_CHANGE))
- strlcat(rbuf, "ABR, ", len);
- if (spf_reason_flags & (1 << SPF_FLAG_ASBR_STATUS_CHANGE))
- strlcat(rbuf, "ASBR, ", len);
- if (spf_reason_flags & (1 << SPF_FLAG_MAXAGE))
- strlcat(rbuf, "M, ", len);
- if (spf_reason_flags & (1 << SPF_FLAG_ORR_ROOT_CHANGE))
- strlcat(rbuf, "ORR, ", len);
-
- size_t rbuflen = strlen(rbuf);
- if (rbuflen >= 2)
- rbuf[rbuflen - 2] = '\0'; /* skip the last ", " */
- else
- rbuf[0] = '\0';
- }
-}
-
/* Worker for SPF calculation scheduler. */
static void ospf_spf_calculate_schedule_worker(struct thread *thread)
{
ospf_ase_calculate_schedule(ospf);
ospf_ase_calculate_timer_add(ospf);
- ospf_orr_spf_calculate_schedule(ospf);
-
if (IS_DEBUG_OSPF_EVENT)
zlog_debug(
"%s: ospf install new route, vrf %s id %u new_table count %lu",
#ifdef SUPPORT_OSPF_API
ospf_apiserver_notify_reachable(ospf->oall_rtrs, ospf->all_rtrs);
#endif
+
/* Free old ABR/ASBR routing table */
if (ospf->old_rtrs) {
ospf_rtrs_free(ospf->old_rtrs);
total_spf_time =
monotime_since(&spf_start_time, &ospf->ts_spf_duration);
- ospf_spf_calculation_reason2str(rbuf, sizeof(rbuf));
+ rbuf[0] = '\0';
+ if (spf_reason_flags) {
+ if (spf_reason_flags & (1 << SPF_FLAG_ROUTER_LSA_INSTALL))
+ strlcat(rbuf, "R, ", sizeof(rbuf));
+ if (spf_reason_flags & (1 << SPF_FLAG_NETWORK_LSA_INSTALL))
+ strlcat(rbuf, "N, ", sizeof(rbuf));
+ if (spf_reason_flags & (1 << SPF_FLAG_SUMMARY_LSA_INSTALL))
+ strlcat(rbuf, "S, ", sizeof(rbuf));
+ if (spf_reason_flags & (1 << SPF_FLAG_ASBR_SUMMARY_LSA_INSTALL))
+ strlcat(rbuf, "AS, ", sizeof(rbuf));
+ if (spf_reason_flags & (1 << SPF_FLAG_ABR_STATUS_CHANGE))
+ strlcat(rbuf, "ABR, ", sizeof(rbuf));
+ if (spf_reason_flags & (1 << SPF_FLAG_ASBR_STATUS_CHANGE))
+ strlcat(rbuf, "ASBR, ", sizeof(rbuf));
+ if (spf_reason_flags & (1 << SPF_FLAG_MAXAGE))
+ strlcat(rbuf, "M, ", sizeof(rbuf));
+ if (spf_reason_flags & (1 << SPF_FLAG_GR_FINISH))
+ strlcat(rbuf, "GR, ", sizeof(rbuf));
+
+ size_t rbuflen = strlen(rbuf);
+ if (rbuflen >= 2)
+ rbuf[rbuflen - 2] = '\0'; /* skip the last ", " */
+ else
+ rbuf[0] = '\0';
+ }
if (IS_DEBUG_OSPF_EVENT) {
zlog_info("SPF Processing Time(usecs): %ld", total_spf_time);
ospf_clear_spf_reason_flags();
}
-/* Worker for ORR SPF calculation scheduler. */
-void ospf_orr_spf_calculate_schedule_worker(struct thread *thread)
-{
- afi_t afi;
- safi_t safi;
- struct ospf *ospf = THREAD_ARG(thread);
- struct route_table *new_table, *new_rtrs;
- struct route_table *all_rtrs = NULL;
- struct timeval start_time, spf_start_time;
- unsigned long ia_time, rt_time;
- unsigned long abr_time, total_spf_time, spf_time;
- struct listnode *rnode;
- struct list *orr_root_list;
- struct orr_root *root;
- char rbuf[32]; /* reason_buf */
-
- ospf_orr_debug("%s: SPF: Timer (SPF calculation expire)", __func__);
-
- ospf->t_orr_calc = NULL;
-
- /* Execute SPF for each ORR Root node */
- FOREACH_AFI_SAFI (afi, safi) {
- orr_root_list = ospf->orr_root[afi][safi];
- if (!orr_root_list)
- continue;
- for (ALL_LIST_ELEMENTS_RO(orr_root_list, rnode, root)) {
- if (!root || !root->router_lsa_rcvd)
- continue;
- ospf_orr_debug(
- "%s: For %s %s, MPLS TE Router address %pI4 advertised by %pI4",
- __func__, afi2str(afi), safi2str(safi),
- &root->router_id, &root->adv_router);
-
- ospf_vl_unapprove(ospf);
-
- /*
- * Execute SPF for each area including backbone, see RFC
- * 2328 16.1.
- */
- monotime(&spf_start_time);
- new_table = route_table_init(); /* routing table */
- new_rtrs =
- route_table_init(); /* ABR/ASBR routing table */
-
- /*
- * If we have opaque enabled then track all router
- * reachability
- */
- if (CHECK_FLAG(ospf->opaque,
- OPAQUE_OPERATION_READY_BIT))
- all_rtrs = route_table_init();
- ospf_orr_spf_calculate_areas(ospf, new_table, all_rtrs,
- new_rtrs,
- root->router_lsa_rcvd);
-
- spf_time = monotime_since(&spf_start_time, NULL);
-
- ospf_vl_shut_unapproved(ospf);
-
- /* Calculate inter-area routes, see RFC 2328 16.2. */
- monotime(&start_time);
- ospf_ia_routing(ospf, new_table, new_rtrs);
- ia_time = monotime_since(&start_time, NULL);
-
- /*
- * REVISIT :
- * Pruning of unreachable networks, routers skipped.
- */
-
- /* Note: RFC 2328 16.3. is apparently missing. */
- /* Calculate AS external routes, see RFC 2328 16.4.
- * There is a dedicated routing table for external
- * routes which is not handled here directly
- */
- ospf_ase_calculate_schedule(ospf);
- ospf_ase_calculate_timer_add(ospf);
-
- ospf_orr_debug(
- "%s: ospf install new route, vrf %s id %u new_table count %lu",
- __func__, ospf_vrf_id_to_name(ospf->vrf_id),
- ospf->vrf_id, new_table->count);
-
- /* Update routing table. */
- monotime(&start_time);
- ospf_orr_route_install(root, new_table, ospf->instance);
- rt_time = monotime_since(&start_time, NULL);
-
- /*
- * REVISIT :
- * Freeing up and Updating old all routers routing table
- * skipped.
- */
-
- /* Free old ABR/ASBR routing table */
- if (root->old_rtrs)
- /* ospf_route_delete (ospf->old_rtrs); */
- ospf_rtrs_free(root->old_rtrs);
-
- /* Update ABR/ASBR routing table */
- root->old_rtrs = root->new_rtrs;
- root->new_rtrs = new_rtrs;
-
- /*
- * ABRs may require additional changes, see RFC
- * 2328 16.7.
- */
- monotime(&start_time);
- if (IS_OSPF_ABR(ospf)) {
- if (ospf->anyNSSA)
- ospf_abr_nssa_check_status(ospf);
- ospf_abr_task(ospf);
- }
- abr_time = monotime_since(&start_time, NULL);
-
- /* Schedule Segment Routing update */
- ospf_sr_update_task(ospf);
-
- total_spf_time = monotime_since(&spf_start_time,
- &ospf->ts_spf_duration);
-
- ospf_spf_calculation_reason2str(rbuf, sizeof(rbuf));
-
- if (IS_DEBUG_OSPF_ORR) {
- zlog_info("SPF Processing Time(usecs): %ld",
- total_spf_time);
- zlog_info(" SPF Time: %ld",
- spf_time);
- zlog_info(" InterArea: %ld", ia_time);
- zlog_info(" RouteInstall: %ld", rt_time);
- if (IS_OSPF_ABR(ospf))
- zlog_info(
- " ABR: %ld (%d areas)",
- abr_time, ospf->areas->count);
- zlog_info("Reason(s) for SPF: %s", rbuf);
- }
- } /* ALL_LIST_ELEMENTS_RO() */
- } /* FOREACH_AFI_SAFI() */
-}
-
/*
* Add schedule for SPF calculation. To avoid frequenst SPF calc, we set timer
* for SPF calc.
zlog_debug("SPF: calculation timer delay = %ld msec", delay);
ospf->t_spf_calc = NULL;
-
thread_add_timer_msec(master, ospf_spf_calculate_schedule_worker, ospf,
delay, &ospf->t_spf_calc);
}
SPF_FLAG_ASBR_STATUS_CHANGE,
SPF_FLAG_CONFIG_CHANGE,
SPF_FLAG_GR_FINISH,
- SPF_FLAG_ORR_ROOT_CHANGE,
} ospf_spf_reason_t;
-extern unsigned int ospf_get_spf_reason_flags(void);
extern void ospf_spf_calculate_schedule(struct ospf *, ospf_spf_reason_t);
extern void ospf_spf_calculate(struct ospf_area *area,
struct ospf_lsa *root_lsa,
extern void ospf_spf_print(struct vty *vty, struct vertex *v, int i);
extern void ospf_restart_spf(struct ospf *ospf);
-extern void ospf_orr_spf_calculate_schedule_worker(struct thread *thread);
/* void ospf_spf_calculate_timer_add (); */
#endif /* _QUAGGA_OSPF_SPF_H */
#include "ospfd/ospf_dump.h"
#include "ospfd/ospf_bfd.h"
#include "ospfd/ospf_ldp_sync.h"
-#include "ospfd/ospf_orr.h"
FRR_CFG_DEFAULT_BOOL(OSPF_LOG_ADJACENCY_CHANGES,
vty_out(vty, "\n");
}
-static void show_ip_ospf_route_orr_root(struct vty *vty, struct ospf *ospf,
- struct orr_root *root, bool use_vrf)
-{
- if (ospf->instance)
- vty_out(vty, "\nOSPF Instance: %d\n", ospf->instance);
-
- ospf_show_vrf_name(ospf, vty, NULL, use_vrf);
-
- vty_out(vty, "ORR Group: %s\n", root->group_name);
- vty_out(vty, "Active Root: %pI4\n\n", &root->router_id);
- vty_out(vty, "SPF calculated from %pI4\n\n", &root->router_id);
-
- if (root->new_table)
- show_ip_ospf_route_network(vty, ospf, root->new_table, NULL);
-
- if (root->new_rtrs)
- show_ip_ospf_route_router(vty, ospf, root->new_rtrs, NULL);
-
- vty_out(vty, "\n");
-}
-
-static void show_ip_ospf_route_orr_common(struct vty *vty, struct ospf *ospf,
- const char *orr_group, bool use_vrf)
-{
- afi_t afi;
- safi_t safi;
- struct orr_root *root = NULL;
- struct listnode *node = NULL;
- struct list *orr_root_list = NULL;
-
- if (!ospf->orr_spf_request)
- return;
-
- FOREACH_AFI_SAFI (afi, safi) {
- orr_root_list = ospf->orr_root[afi][safi];
- if (!orr_root_list)
- continue;
- for (ALL_LIST_ELEMENTS_RO(orr_root_list, node, root)) {
- if (orr_group) {
- if (!strmatch(root->group_name, orr_group))
- continue;
- show_ip_ospf_route_orr_root(vty, ospf, root,
- use_vrf);
- } else
- show_ip_ospf_route_orr_root(vty, ospf, root,
- use_vrf);
- }
- }
-}
-
-DEFPY (show_ip_ospf_instance_route_orr,
- show_ip_ospf_instance_route_orr_cmd,
- "show ip ospf (1-65535)$instance route orr [WORD$orr_group]",
- SHOW_STR
- IP_STR
- OSPF_STR
- "Instance ID\n"
- "OSPF routing table\n"
- "Optimal Route Reflection\n"
- "ORR Group name\n")
-{
- struct ospf *ospf;
-
- if (instance != ospf_instance)
- return CMD_NOT_MY_INSTANCE;
-
- ospf = ospf_lookup_instance(instance);
- if (!ospf || !ospf->oi_running)
- return CMD_SUCCESS;
-
- show_ip_ospf_route_orr_common(vty, ospf, orr_group, false);
-
- return CMD_SUCCESS;
-}
-
-DEFPY (show_ip_ospf_route_orr,
- show_ip_ospf_route_orr_cmd,
- "show ip ospf [vrf <NAME$vrf_name|all$all_vrf>] route orr [WORD$orr_group]",
- SHOW_STR
- IP_STR
- OSPF_STR
- VRF_CMD_HELP_STR
- "All VRFs\n"
- "OSPF routing table\n"
- "Optimal Route Reflection\n"
- "ORR Group name\n")
-{
- struct ospf *ospf = NULL;
- struct listnode *node = NULL;
- int ret = CMD_SUCCESS;
- int inst = 0;
- bool use_vrf = vrf_name || all_vrf;
-
- if (all_vrf) {
- bool ospf_output = false;
-
- for (ALL_LIST_ELEMENTS_RO(om->ospf, node, ospf)) {
- if (!ospf->oi_running)
- continue;
- ospf_output = true;
-
- show_ip_ospf_route_orr_common(vty, ospf, orr_group,
- use_vrf);
- }
- if (!ospf_output)
- vty_out(vty, "%% OSPF is not enabled\n");
- return ret;
- }
-
- if (vrf_name)
- ospf = ospf_lookup_by_inst_name(inst, vrf_name);
- else
- ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
-
- if (!ospf || !ospf->oi_running) {
- vty_out(vty, "%% OSPF is not enabled in vrf %s\n",
- vrf_name ? vrf_name : "default");
- return CMD_SUCCESS;
- }
-
- show_ip_ospf_route_orr_common(vty, ospf, orr_group, use_vrf);
-
- return ret;
-}
-
static int show_ip_ospf_reachable_routers_common(struct vty *vty,
struct ospf *ospf,
uint8_t use_vrf)
install_element(VIEW_NODE, &show_ip_ospf_route_cmd);
install_element(VIEW_NODE, &show_ip_ospf_border_routers_cmd);
install_element(VIEW_NODE, &show_ip_ospf_reachable_routers_cmd);
- install_element(VIEW_NODE, &show_ip_ospf_route_orr_cmd);
install_element(VIEW_NODE, &show_ip_ospf_instance_route_cmd);
install_element(VIEW_NODE, &show_ip_ospf_instance_border_routers_cmd);
install_element(VIEW_NODE,
&show_ip_ospf_instance_reachable_routers_cmd);
- install_element(VIEW_NODE, &show_ip_ospf_instance_route_orr_cmd);
/* "show ip ospf vrfs" commands. */
install_element(VIEW_NODE, &show_ip_ospf_vrfs_cmd);
#include "ospfd/ospf_te.h"
#include "ospfd/ospf_sr.h"
#include "ospfd/ospf_ldp_sync.h"
-#include "ospfd/ospf_orr.h"
DEFINE_MTYPE_STATIC(OSPFD, OSPF_EXTERNAL, "OSPF External route table");
DEFINE_MTYPE_STATIC(OSPFD, OSPF_REDISTRIBUTE, "OSPF Redistriute");
bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER, VRF_DEFAULT);
zclient_send_reg_requests(zclient, VRF_DEFAULT);
- zclient_register_opaque(zclient, ORR_IGP_METRIC_REGISTER);
}
/*
struct ldp_igp_sync_if_state state;
struct ldp_igp_sync_announce announce;
struct zapi_opaque_reg_info dst;
- struct orr_igp_metric_reg orr_reg;
int ret = 0;
s = zclient->ibuf;
STREAM_GET(&announce, s, sizeof(announce));
ret = ospf_ldp_sync_announce_update(announce);
break;
- case ORR_IGP_METRIC_REGISTER:
- STREAM_GET(&orr_reg, s, sizeof(orr_reg));
- ret = ospf_orr_igp_metric_register(orr_reg);
- break;
default:
break;
}
THREAD_OFF(ospf->t_write);
THREAD_OFF(ospf->t_spf_calc);
THREAD_OFF(ospf->t_ase_calc);
- THREAD_OFF(ospf->t_orr_calc);
THREAD_OFF(ospf->t_maxage);
THREAD_OFF(ospf->t_maxage_walker);
THREAD_OFF(ospf->t_abr_task);
#include "ospf_memory.h"
#include "ospf_dump_api.h"
-#include "orr_msg.h"
-
#define OSPF_VERSION 2
/* VTY port number. */
struct thread *t_distribute_update; /* Distirbute list update timer. */
struct thread *t_spf_calc; /* SPF calculation timer. */
struct thread *t_ase_calc; /* ASE calculation timer. */
- struct thread *t_orr_calc; /* ORR calculation timer. */
struct thread
*t_opaque_lsa_self; /* Type-11 Opaque-LSAs origin event. */
struct thread *t_sr_update; /* Segment Routing update timer */
bool ti_lfa_enabled;
enum protection_type ti_lfa_protection_type;
- /* BGP ORR Root node list */
- uint32_t orr_spf_request;
- struct list *orr_root[AFI_MAX][SAFI_MAX];
-
QOBJ_FIELDS;
};
DECLARE_QOBJ_TYPE(ospf);
uint32_t act_ints; /* Active interfaces. */
uint32_t full_nbrs; /* Fully adjacent neighbors. */
uint32_t full_vls; /* Fully adjacent virtual neighbors. */
-
- /* BGP-ORR Received LSAs */
- struct ospf_lsa *router_lsa_rcvd;
};
/* OSPF config network structure. */
ospfd/ospf_network.c \
ospfd/ospf_nsm.c \
ospfd/ospf_opaque.c \
- ospfd/ospf_orr.c \
ospfd/ospf_packet.c \
ospfd/ospf_ri.c \
ospfd/ospf_route.c \
ospfd/ospf_memory.h \
ospfd/ospf_neighbor.h \
ospfd/ospf_network.h \
- ospfd/ospf_orr.h \
ospfd/ospf_packet.h \
ospfd/ospf_ri.h \
ospfd/ospf_gr.h \
}
result = verify_rib(tgen, addr_type, "d2", input_routes, expected=False)
- assert (
- result is not True
- ), "Testcase {} :Failed \n Routes are still present: {}".format(tc_name, result)
- logger.info("Expected Behavior: {}".format(result))
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: Routes should not be present in {} RIB \n "
+ "Found: {}".format(tc_name, "d2", result)
+ )
step(
"Revert back to original VNI number for all 3 VRFs on Edge-1 "
result = verify_attributes_for_evpn_routes(
tgen, topo, "d2", input_routes_1, rt="auto", rt_peer="e1", expected=False
)
- assert (
- result is not True
- ), "Testcase {} :Failed \n Malfaromed Auto-RT value accepted: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: Malformed Auto-RT value should not be accepted in {} \n "
+ "Found: {}".format(tc_name, "d2", result)
)
- logger.info("Expected Behavior: {}".format(result))
step("Configure VNI number more than boundary limit (16777215)")
result = verify_attributes_for_evpn_routes(
tgen, topo, "d2", input_routes_1, rt="auto", rt_peer="e1", expected=False
)
- assert (
- result is not True
- ), "Testcase {} :Failed \n Malfaromed Auto-RT value accepted: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: Malformed Auto-RT value should not be accepted in {} \n "
+ "Found: {}".format(tc_name, "d2", result)
)
- logger.info("Expected Behavior: {}".format(result))
step("Un-configure VNI number more than boundary limit (16777215)")
}
result = verify_rib(tgen, addr_type, "d1", input_routes, expected=False)
assert result is not True, (
- "Testcase {} :Failed \n Expected Behavior: Routes are still "
- "present \n Error: {}".format(tc_name, result)
+ "Testcase {} : Failed \n "
+ "Expected: Routes should not be present in {} RIB \n "
+ "Found: {}".format(tc_name, "d1", result)
)
- logger.info("Expected Behavior: {}".format(result))
result = verify_rib(tgen, addr_type, "d2", input_routes, expected=False)
assert result is not True, (
- "Testcase {} :Failed \n Expected Behavior: Routes are still "
- "present \n Error: {}".format(tc_name, result)
+ "Testcase {} : Failed \n "
+ "Expected: Routes should not be present in {} RIB \n "
+ "Found: {}".format(tc_name, "d2", result)
)
- logger.info("Expected Behavior: {}".format(result))
step(
"Configure RT value as 100:100000010000010000101010 to check "
tgen, topo, dut, input_routes, rt="100:100000010000010000101010", expected=False
)
assert result is not True, (
- "Testcase {} :Failed \n Expected Behavior: RT value of out"
- " of boundary \n Error: {}".format(tc_name, result)
+ "Testcase {} : Failed \n "
+ "Expected: RT value out of boundary error in {} \n "
+ "Found: {}".format(tc_name, dut, result)
)
- logger.info("Expected Behavior: {}".format(result))
write_test_footer(tc_name)
for addr_type in ADDR_TYPES:
input_routes = {key: topo["routers"][key] for key in ["r1"]}
result = verify_rib(tgen, addr_type, "d2", input_routes, expected=False)
- assert (
- result is not True
- ), "Testcase :Failed \n Routes are still present: {}".format(result)
- logger.info("Expected Behavior: {}".format(result))
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: Routes should not be present in {} RIB \n "
+ "Found: {}".format(tc_name, "d2", result)
+ )
for addr_type in ADDR_TYPES:
input_routes = {key: topo["routers"][key] for key in ["r1"]}
result = verify_rib(tgen, addr_type, "r3", input_routes, expected=False)
- assert (
- result is not True
- ), "Testcase {} :Failed \n Routes are still present: {}".format(tc_name, result)
- logger.info("Expected Behavior: {}".format(result))
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: Routes should not be present in {} RIB \n "
+ "Found: {}".format(tc_name, "r3", result)
+ )
step("Re-advertise IP prefixes from VFN(R1).")
step(
}
result = verify_rib(tgen, addr_type, "d2", input_routes, expected=False)
- assert (
- result is not True
- ), "Testcase {} :Failed \n Routes are still present: {}".format(tc_name, result)
- logger.info("Expected Behavior: {}".format(result))
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: Routes should not be present in {} RIB \n "
+ "Found: {}".format(tc_name, "d2", result)
+ )
result = verify_rib(tgen, addr_type, "r4", input_routes, expected=False)
- assert (
- result is not True
- ), "Testcase {} :Failed \n Routes are still present: {}".format(tc_name, result)
- logger.info("Expected Behavior: {}".format(result))
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: Routes should not be present in {} RIB \n "
+ "Found: {}".format(tc_name, "r4", result)
+ )
step("Add vrf BLUE on router Edge-1 again.")
interface = topo["routers"]["e1"]["links"]["r2-link1"]["interface"]
}
result = verify_rib(tgen, addr_type, "d2", input_routes, expected=False)
- assert (
- result is not True
- ), "Testcase {} :Failed \n Routes are still present: {}".format(tc_name, result)
- logger.info("Expected Behavior: {}".format(result))
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: Routes should not be present in {} RIB \n "
+ "Found: {}".format(tc_name, "d2", result)
+ )
result = verify_rib(tgen, addr_type, "r4", input_routes, expected=False)
- assert (
- result is not True
- ), "Testcase {} :Failed \n Routes are still present: {}".format(tc_name, result)
- logger.info("Expected Behavior: {}".format(result))
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: Routes should not be present in {} RIB \n "
+ "Found: {}".format(tc_name, "r4", result)
+ )
step("Advertise IPv6 address-family in EVPN advertisements " "for VRF GREEN.")
addr_type = "ipv6"
"debug pim packets register",
"debug pim nht",
],
+ "pim6d": [
+ "debug pimv6 events",
+ "debug pimv6 packets",
+ "debug pimv6 packet-dump send",
+ "debug pimv6 packet-dump receive",
+ "debug pimv6 trace",
+ "debug pimv6 trace detail",
+ "debug pimv6 zebra",
+ "debug pimv6 bsm",
+ "debug pimv6 packets hello",
+ "debug pimv6 packets joins",
+ "debug pimv6 packets register",
+ "debug pimv6 nht",
+ "debug pimv6 nht detail",
+ "debug mroute6",
+ "debug mroute6 detail",
+ "debug mld events",
+ "debug mld packets",
+ "debug mld trace",
+ ],
"bgpd": [
"debug bgp neighbor-events",
"debug bgp updates",
if group_addr_json[src_address]["joinState"] != "Joined":
errormsg = (
"[DUT %s]: Verifying iif "
- "(Inbound Interface) for (%s,%s) and"
- " joinState :%s [FAILED]!! "
- " Expected: %s, Found: %s"
+ "(Inbound Interface) and joinState "
+ "for (%s, %s), Expected iif: %s, "
+ "Found iif : %s, and Expected "
+ "joinState :%s , Found joinState: %s"
% (
dut,
src_address,
grp_addr,
- group_addr_json[src_address]["joinState"],
in_interface,
group_addr_json[src_address]["inboundInterface"],
+ joinState,
+ group_addr_json[src_address]["joinState"],
)
)
return errormsg
elif group_addr_json[src_address]["joinState"] != joinState:
errormsg = (
"[DUT %s]: Verifying iif "
- "(Inbound Interface) for (%s,%s) and"
- " joinState :%s [FAILED]!! "
- " Expected: %s, Found: %s"
+ "(Inbound Interface) and joinState "
+ "for (%s, %s), Expected iif: %s, "
+ "Found iif : %s, and Expected "
+ "joinState :%s , Found joinState: %s"
% (
dut,
src_address,
grp_addr,
- group_addr_json[src_address]["joinState"],
in_interface,
group_addr_json[src_address]["inboundInterface"],
+ joinState,
+ group_addr_json[src_address]["joinState"],
)
)
return errormsg
if group_addr_json[src_address]["regState"] != regState:
errormsg = (
"[DUT %s]: Verifying iif "
- "(Inbound Interface) for (%s,%s) and"
- " rejstate :%s [FAILED]!! "
- " Expected: %s, Found: %s"
+ "(Inbound Interface) and regState "
+ "for (%s, %s), Expected iif: %s, "
+ "Found iif : %s, and Expected "
+ "regState :%s , Found regState: %s"
% (
dut,
src_address,
grp_addr,
- group_addr_json[src_address]["regState"],
in_interface,
group_addr_json[src_address]["inboundInterface"],
+ regState,
+ group_addr_json[src_address]["regState"],
)
)
return errormsg
)
return errormsg
- logger.debug("Exiting lib API: {}".format(sys._getframe().f_code.co_name))
- return True
+ logger.debug("Exiting lib API: {}".format(sys._getframe().f_code.co_name))
+ return True
@retry(retry_timeout=12)
check_router_status(tgen)
step("Creating configuration from JSON")
- kill_socat(tgen)
- clear_pim6_mroute(tgen)
- clear_pim6_interface_traffic(tgen, TOPO)
reset_config_on_routers(tgen)
step("Shut link b/w R1 and R3 and R1 and R4 as per testcase topology")
pytest.skip(tgen.errors)
step("Creating configuration from JSON")
- kill_socat(tgen)
- clear_pim6_mroute(tgen)
- clear_pim6_interface_traffic(tgen, TOPO)
reset_config_on_routers(tgen)
step("Shut link b/w R1->R3, R1->R4 and R3->R1, R3->R4 as per " "testcase topology")
pytest.skip(tgen.errors)
step("Creating configuration from JSON")
- kill_socat(tgen)
- clear_pim6_mroute(tgen)
- clear_pim6_interface_traffic(tgen, TOPO)
reset_config_on_routers(tgen)
step("Enable MLD on r1 interface")
pytest.skip(tgen.errors)
step("Creating configuration from JSON")
- kill_socat(tgen)
- clear_pim6_mroute(tgen)
- clear_pim6_interface_traffic(tgen, TOPO)
reset_config_on_routers(tgen)
step("Enable MLD on r1 interface")
pytest.skip(tgen.errors)
step("Creating configuration from JSON")
- kill_socat(tgen)
- clear_pim6_mroute(tgen)
- clear_pim6_interface_traffic(tgen, TOPO)
reset_config_on_routers(tgen)
step("Enable MLD on r1 interface")
pytest.skip(tgen.errors)
step("Creating configuration from JSON")
- kill_socat(tgen)
- clear_pim6_mroute(tgen)
- clear_pim6_interface_traffic(tgen, TOPO)
reset_config_on_routers(tgen)
step("Enable MLD on r1 interface")
socat_send_mld_join,
socat_send_pim6_traffic,
kill_socat,
+ create_debug_log_config,
)
from lib.pim import (
create_pim_config,
pytest.skip(tgen.errors)
step("Creating configuration from JSON")
- kill_socat(tgen)
- clear_pim6_mroute(tgen)
- clear_pim6_interface_traffic(tgen, TOPO)
reset_config_on_routers(tgen)
+ input_dict = {
+ "r1": {"debug": {"log_file": "r1_debug.log", "enable": ["pim6d"]}},
+ "r2": {"debug": {"log_file": "r2_debug.log", "enable": ["pim6d"]}},
+ "r3": {"debug": {"log_file": "r3_debug.log", "enable": ["pim6d"]}},
+ "r4": {"debug": {"log_file": "r4_debug.log", "enable": ["pim6d"]}},
+ }
+
+ result = create_debug_log_config(tgen, input_dict)
+
step("Enable MLD on r1 interface")
step("Enable the PIM6 on all the interfaces of r1, r2, r3 and r4 routers")
step("r2: Configure r2 as RP")
pytest.skip(tgen.errors)
step("Creating configuration from JSON")
- kill_socat(tgen)
- clear_pim6_mroute(tgen)
- clear_pim6_interface_traffic(tgen, TOPO)
reset_config_on_routers(tgen)
step("Enable MLD on r1 interface")
step("r1: Verify (*, G) upstream IIF interface")
dut = "r1"
- iif = TOPO["routers"]["r1"]["links"]["r2"]["interface"]
- result = verify_upstream_iif(tgen, dut, iif, STAR, group_address_list)
- assert result is True, ASSERT_MSG.format(tc_name, result)
+ iif1 = TOPO["routers"]["r1"]["links"]["r2"]["interface"]
+ iif2 = TOPO["routers"]["r1"]["links"]["r4"]["interface"]
- step("r1: Verify (*, G) upstream join state and join timer")
- result = verify_join_state_and_timer(
- tgen, dut, iif, STAR, group_address_list, addr_type="ipv6"
- )
- assert result is True, ASSERT_MSG.format(tc_name, result)
+ for _iif, _group in zip([iif1, iif2], [GROUP_ADDRESS_LIST_1, GROUP_ADDRESS_LIST_2]):
+ result = verify_upstream_iif(tgen, dut, _iif, STAR, _group)
+ assert result is True, ASSERT_MSG.format(tc_name, result)
+
+ step("r1: Verify (*, G) upstream join state and join timer")
+ result = verify_join_state_and_timer(
+ tgen, dut, _iif, STAR, _group, addr_type="ipv6"
+ )
+ assert result is True, ASSERT_MSG.format(tc_name, result)
step("r1: Verify (*, G) ip mroutes")
+ iif = TOPO["routers"]["r1"]["links"]["r2"]["interface"]
oif = TOPO["routers"]["r1"]["links"]["r0"]["interface"]
result = verify_mroutes(tgen, dut, STAR, GROUP_ADDRESS_LIST_1, iif, oif)
assert result is True, ASSERT_MSG.format(tc_name, result)
pytest.skip(tgen.errors)
step("Creating configuration from JSON")
- kill_socat(tgen)
- clear_pim6_mroute(tgen)
- clear_pim6_interface_traffic(tgen, TOPO)
reset_config_on_routers(tgen)
step("Enable MLD on r1 interface")
# Required linux kernel version for this suite to run.
result = required_linux_kernel_version("4.15")
if result is not True:
- pytest.skip("Kernel requirements are not met")
+ pytest.skip("Kernel version should be >= 4.15")
testsuite_run_time = time.asctime(time.localtime(time.time()))
logger.info("Testsuite start time: {}".format(testsuite_run_time))
result = verify_rib(
tgen, "ipv4", "f1", input_routes, protocol="static", expected=False
)
- assert (
- result is not True
- ), "Testcase {} : Failed \n " "Route is still present \n Error {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: Routes should not be present in {} RIB \n "
+ "Found: {}".format(tc_name, "f1", result)
)
# Use scapy to send pre-defined packet from senser to receiver
step("Verify if b1 chosen as BSR in l1")
result = verify_pim_bsr(tgen, topo, "l1", BSR_IP_1, expected=False)
- assert (
- result is not True
- ), "Testcase {} : Failed \n " "b1 is not chosen as BSR in l1 \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: b1 should be chosen as BSR in {} \n "
+ "Found: {}".format(tc_name, "l1", result)
)
state_after = get_pim_interface_traffic(tgen, state_dict)
)
assert result is not True, (
"Testcase {} : Failed \n "
- "Routes:[{}, {}] are still present \n Error {}".format(
- tc_name, BSR1_ADDR, CRP, result
- )
+ "Expected: Routes should not be present in {} RIB \n "
+ "Found: {}".format(tc_name, "f1", result)
)
step("Sending BSR after removing black-hole address for BSR and candidate RP")
result = verify_pim_bsr(tgen, topo, "l1", bsr_ip, expected=False)
assert result is not True, (
"Testcase {} : Failed \n "
- "BSR data is present after no-forward bsm also \n Error: {}".format(
- tc_name, result
- )
+ "Expected: [{}]: BSR data should not be present after no-forward bsm \n "
+ "Found: {}".format(tc_name, "l1", result)
)
# unconfigure unicast bsm on f1-i1-eth2
result = verify_mroutes(
tgen, "i1", src_addr, GROUP_ADDRESS, iif, oil, expected=False
)
- assert (
- result is not True
- ), "Testcase {} : Failed \n " "Mroutes are still present \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: mroute (S, G) should be cleared from mroute table\n "
+ "Found: {}".format(tc_name, "i1", result)
)
# unconfigure bsm processing on f1 on f1-i1-eth2
# Verify bsr state in i1
step("Verify if b1 is not chosen as BSR in i1")
result = verify_pim_bsr(tgen, topo, "i1", bsr_ip, expected=False)
- assert (
- result is not True
- ), "Testcase {} : Failed \n " "b1 is chosen as BSR in i1 \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: b1 should not be chosen as BSR \n "
+ "Found: {}".format(tc_name, "i1", result)
)
# check if mroute still not installed because of rp not available
)
assert result is not True, (
"Testcase {} : Failed \n "
- "mroute installed but rp not available \n Error: {}".format(tc_name, result)
+ "Expected: [{}]: mroute (S, G) should not be installed as RP is not available\n "
+ "Found: {}".format(tc_name, "i1", result)
)
# configure bsm processing on i1 on f1-i1-eth2
result = verify_pim_grp_rp_source(
tgen, topo, "f1", group, rp_source="BSR", expected=False
)
-
- assert (
- result is not True
- ), "Testcase {} : Failed \n " "bsr has not aged out in f1 \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: bsr should be aged out \n "
+ "Found: {}".format(tc_name, "f1", result)
)
# Verify RP mapping removed after hold timer expires
)
assert result is not True, (
"Testcase {} : Failed \n "
- "join state is up and join timer is running in l1 \n Error: {}".format(
- tc_name, result
- )
+ "Expected: [{}]: Upstream Join State timer should not run\n "
+ "Found: {}".format(tc_name, dut, result)
)
# Verify ip mroute is not installed
result = verify_mroutes(
tgen, dut, src_addr, GROUP_ADDRESS, iif, oil, expected=False
)
- assert (
- result is not True
- ), "Testcase {} : Failed \n " "mroute installed in l1 \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: mroute (S, G) should not be installed \n "
+ "Found: {}".format(tc_name, dut, result)
)
step("clear BSM database before moving to next case")
result = verify_rib(
tgen, "ipv4", "l1", input_dict, protocol="static", expected=False
)
- assert (
- result is not True
- ), "Testcase {} : Failed \n " "Routes:{} are still present \n Error {}".format(
- tc_name, rp_ip, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: Routes should not be present in {} BGP RIB \n "
+ "Found: {}".format(tc_name, "l1", result)
)
# Check RP unreachable
result = verify_mroutes(
tgen, dut, src_addr, GROUP_ADDRESS, iif, oil, expected=False
)
- assert (
- result is not True
- ), "Testcase {} : Failed \n " "mroute installed in l1 \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: mroute (S, G) should not be installed \n "
+ "Found: {}".format(tc_name, dut, result)
)
# Add back route for RP to make it reachable
# Required linux kernel version for this suite to run.
result = required_linux_kernel_version("4.15")
if result is not True:
- pytest.skip("Kernel requirements are not met")
+ pytest.skip("Kernel version should be >= 4.15")
testsuite_run_time = time.asctime(time.localtime(time.time()))
logger.info("Testsuite start time: {}".format(testsuite_run_time))
result = verify_mroutes(
tgen, dut, src_addr, GROUP_ADDRESS, iif, oil, retry_timeout=20, expected=False
)
- assert (
- result is not True
- ), "Testcase {} : Failed \n " "mroute installed in l1 \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: mroute (S, G) should not be installed \n "
+ "Found: {}".format(tc_name, dut, result)
)
# Send BSM again to configure rp
# Verify bsr state in FHR
step("Verify if b2 is not chosen as bsr in f1")
result = verify_pim_bsr(tgen, topo, "f1", bsr_ip2, expected=False)
- assert (
- result is not True
- ), "Testcase {} : Failed \n " "b2 is chosen as bsr in f1 \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: b2 should not be chosen as bsr \n "
+ "Found: {}".format(tc_name, "f1", result)
)
# Verify if b1 is still chosen as bsr
# Required linux kernel version for this suite to run.
result = required_linux_kernel_version("4.19")
if result is not True:
- pytest.skip("Kernel requirements are not met")
+ pytest.skip("Kernel version should be >= 4.19")
testsuite_run_time = time.asctime(time.localtime(time.time()))
logger.info("Testsuite start time: {}".format(testsuite_run_time))
data["oil"],
expected=False,
)
- assert (
- result is not True
- ), "Testcase {} : Failed \n mroutes are still present \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: mroute (S, G) should not be present in mroute table \n "
+ "Found: {}".format(tc_name, data["dut"], result)
)
- logger.info("Expected Behavior: {}".format(result))
step(
"Source which is stopped got removed , other source"
result = verify_mroutes(
tgen, "c1", "*", IGMP_JOIN, "c1-c2-eth1", "c1-l1-eth0", expected=False
)
- assert (
- result is not True
- ), "Testcase {} : Failed \n mroutes are still present \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: mroute (*, G) should not be present in mroute table \n "
+ "Found: {}".format(tc_name, "c1", result)
)
- logger.info("Expected Behavior: {}".format(result))
write_test_footer(tc_name)
result = verify_mroutes(
tgen, "f1", "*", IGMP_JOIN, "f1-r2-eth3", "f1-i8-eth2", expected=False
)
- assert (
- result is not True
- ), "Testcase {} : Failed \n mroutes are still present \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: mroute (*, G) should not be present in mroute table \n "
+ "Found: {}".format(tc_name, "f1", result)
)
- logger.info("Expected Behavior: {}".format(result))
step("IGMP groups are present verify using 'show ip igmp group'")
dut = "l1"
# Required linux kernel version for this suite to run.
result = required_linux_kernel_version("4.19")
if result is not True:
- pytest.skip("Kernel requirements are not met")
+ pytest.skip("Kernel version should be >= 4.19")
testsuite_run_time = time.asctime(time.localtime(time.time()))
logger.info("Testsuite start time: {}".format(testsuite_run_time))
data["oil"],
expected=False,
)
- assert (
- result is not True
- ), "Testcase {} : Failed \n mroutes are still present \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: mroute (S, G) should not be present in mroute table \n "
+ "Found: {}".format(tc_name, data["dut"], result)
)
- logger.info("Expected Behavior: {}".format(result))
write_test_footer(tc_name)
data["oil"],
expected=False,
)
- assert (
- result is not True
- ), "Testcase {} : Failed \n mroutes are still present \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: mroute (S, G) should not be present in mroute table \n "
+ "Found: {}".format(tc_name, data["dut"], result)
)
- logger.info("Expected Behavior: {}".format(result))
write_test_footer(tc_name)
tgen, "l1", "Unknown", source, IGMP_JOIN_RANGE_2, expected=False
)
assert result is not True, (
- "Testcase {} : Failed Error: \n "
- "mroutes are still present, after waiting for 10 mins".format(tc_name)
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: Upstream IIF should be unknown \n "
+ "Found: {}".format(tc_name, "l1", result)
)
step("No shut the Source interface just after the upstream is expired" " from FRR1")
data["oil"],
expected=False,
)
- assert (
- result is not True
- ), "Testcase {} : Failed \n mroutes are still present \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: mroute (S, G) should not be present in mroute table \n "
+ "Found: {}".format(tc_name, data["dut"], result)
)
- logger.info("Expected Behavior: {}".format(result))
write_test_footer(tc_name)
data["oil"],
expected=False,
)
- assert (
- result is not True
- ), "Testcase {} : Failed Error: \nmroutes are still present".format(tc_name)
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: mroute (S, G) should not be present in mroute table \n "
+ "Found: {}".format(tc_name, data["dut"], result)
+ )
write_test_footer(tc_name)
data["oil"],
expected=False,
)
- assert (
- result is not True
- ), "Testcase {} : Failed \n mroutes are still present \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: mroute (S, G) should not be present in mroute table \n "
+ "Found: {}".format(tc_name, data["dut"], result)
)
- logger.info("Expected Behavior: {}".format(result))
step(
"No traffic impact observed on other receivers verify using"
"f1-i8-eth2",
expected=False,
)
- assert (
- result is not True
- ), "Testcase {} : Failed \n mroutes are" " still present \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: mroute (S, G) should not be present in mroute table \n "
+ "Found: {}".format(tc_name, data["dut"], result)
)
- logger.info("Expected Behavior: {}".format(result))
result = verify_upstream_iif(
tgen, "f1", "Unknown", "10.0.5.2", _IGMP_JOIN_RANGE, joinState="NotJoined"
# Required linux kernel version for this suite to run.
result = required_linux_kernel_version("4.19")
if result is not True:
- pytest.skip("Kernel requirements are not met")
+ pytest.skip("Kernel version should be >= 4.19")
testsuite_run_time = time.asctime(time.localtime(time.time()))
logger.info("Testsuite start time: {}".format(testsuite_run_time))
input_traffic = {"l1": {"traffic_sent": [intf_l1_i1]}}
result = verify_multicast_traffic(tgen, input_traffic, expected=False)
- assert (
- result is not True
- ), "Testcase {} : Failed \n " " Traffic is not stopped yet \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: Multicast traffic should be stopped \n "
+ "Found: {}".format(tc_name, "l1", result)
)
- logger.info("Expected Behaviour: {}".format(result))
step(
"IGMP groups are remove from FRR1 node 'show ip igmp groups'"
result = verify_igmp_groups(
tgen, dut, intf_l1_i1, IGMP_JOIN_RANGE_1, expected=False
)
- assert (
- result is not True
- ), "Testcase {} : Failed \n " "IGMP groups are not deleted \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: IGMP groups should be deleted \n "
+ "Found: {}".format(tc_name, dut, result)
)
- logger.info("Expected Behaviour: {}".format(result))
dut = "f1"
result = verify_igmp_groups(tgen, dut, intf_f1_i8, IGMP_JOIN_RANGE_1)
data["oil"],
expected=False,
)
- assert (
- result is not True
- ), "Testcase {} : Failed \n " "mroutes are still present \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: mroute (S, G) should not be present in mroute table \n "
+ "Found: {}".format(tc_name, data["dut"], result)
)
- logger.info("Expected Behaviour: {}".format(result))
for data in input_dict_l1:
result = verify_upstream_iif(
)
assert result is not True, (
"Testcase {} : Failed \n "
- "upstream entries are still present \n Error: {}".format(tc_name, result)
+ "Expected: [{}]: Upstream IIF {} should not be present \n "
+ "Found: {}".format(tc_name, data["dut"], data["iif"], result)
)
- logger.info("Expected Behaviour: {}".format(result))
input_dict_f1 = [
{
input_traffic = {"f1": {"traffic_sent": [intf_f1_i8]}}
result = verify_multicast_traffic(tgen, input_traffic, expected=False)
- assert (
- result is not True
- ), "Testcase {} : Failed \n " " Traffic is not stopped yet \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: Multicast traffic should be stopped \n "
+ "Found: {}".format(tc_name, "f1", result)
)
- logger.info("Expected Behaviour: {}".format(result))
step(
"IGMP groups are remove from FRR1 node 'show ip igmp groups'"
result = verify_igmp_groups(
tgen, dut, intf_f1_i8, IGMP_JOIN_RANGE_1, expected=False
)
- assert (
- result is not True
- ), "Testcase {} : Failed \n " "IGMP groups are not deleted \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: IGMP groups should be deleted \n "
+ "Found: {}".format(tc_name, dut, result)
)
- logger.info("Expected Behaviour: {}".format(result))
step(
"(*,G) and (S,G) OIL got prune state (none) from all the nodes"
data["oil"],
expected=False,
)
- assert (
- result is not True
- ), "Testcase {} : Failed \n " "mroutes are still present \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: mroute (S, G) should not be present in mroute table \n "
+ "Found: {}".format(tc_name, data["dut"], result)
)
- logger.info("Expected Behaviour: {}".format(result))
for data in input_dict_l1:
result = verify_upstream_iif(
)
assert result is not True, (
"Testcase {} : Failed \n "
- "upstream entries are still present \n Error: {}".format(tc_name, result)
+ "Expected: [{}]: Upstream IIF {} should not be present \n "
+ "Found: {}".format(tc_name, data["dut"], data["iif"], result)
)
- logger.info("Expected Behaviour: {}".format(result))
shutdown_bringup_interface(tgen, "f1", intf_f1_i8, True)
shutdown_bringup_interface(tgen, "l1", intf_l1_i1, True)
data["oil"],
expected=False,
)
- assert (
- result is not True
- ), "Testcase {} : Failed \n " "mroutes are still present \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: mroute (S, G) should not be present in mroute table \n "
+ "Found: {}".format(tc_name, data["dut"], result)
)
- logger.info("Expected Behaviour: {}".format(result))
input_dict_l1_r2 = [
{
data["oil"],
expected=False,
)
- assert (
- result is not True
- ), "Testcase {} : Failed \n " "mroutes are still present \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: mroute (S, G) should not be present in mroute table \n "
+ "Found: {}".format(tc_name, data["dut"], result)
)
- logger.info("Expected Behaviour: {}".format(result))
step("After prune is sent verify upstream got removed in FRR1 node")
)
assert result is not True, (
"Testcase {} : Failed \n "
- "upstream entries are still present \n Error: {}".format(tc_name, result)
+ "Expected: [{}]: Upstream IIF {} should not be present \n "
+ "Found: {}".format(tc_name, data["dut"], data["iif"], result)
)
- logger.info("Expected Behaviour: {}".format(result))
write_test_footer(tc_name)
result = verify_mroutes(
tgen, "f1", source_i2, IGMP_JOIN_RANGE_1, intf_f1_i2, intf_f1_r2, expected=False
)
- assert (
- result is not True
- ), "Testcase {} : Failed \n mroutes are" " still present \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: mroute (S, G) should not be present in mroute table \n "
+ "Found: {}".format(tc_name, "f1", result)
)
- logger.info("Expected Behavior: {}".format(result))
step(
"After waiting for (S,G) timeout from FRR1 for same"
result = verify_upstream_iif(
tgen, "l1", "Unknown", source_i2, IGMP_JOIN_RANGE_1, expected=False
)
- assert (
- result is not True
- ), "Testcase {} : Failed Error: \n mroutes are still present".format(tc_name)
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: Upstream IIF should be Unknown \n "
+ "Found: {}".format(tc_name, "l1", result)
+ )
step("No shut the Source interface just after the upstream is expired" " from FRR1")
shutdown_bringup_interface(tgen, "f1", intf_f1_i2, True)
result = verify_upstream_iif(
tgen, "l1", "Unknown", source_i2, IGMP_JOIN_RANGE_1, expected=False
)
- assert (
- result is not True
- ), "Testcase {} : Failed Error: \nmroutes are still present".format(tc_name)
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: Upstream IIF should be Unknown \n "
+ "Found: {}".format(tc_name, "l1", result)
+ )
step("No shut the Source interface just after the upstream is expired" " from FRR1")
shutdown_bringup_interface(tgen, "l1", intf_l1_i1, True)
dut = "l1"
interface = topo["routers"]["l1"]["links"]["i1"]["interface"]
result = verify_igmp_groups(tgen, dut, interface, IGMP_JOIN_RANGE_1, expected=False)
- assert (
- result is not True
- ), "Testcase {} : Failed \n Groups are not" " present \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: IGMP groups should not be present \n "
+ "Found: {}".format(tc_name, dut, result)
)
- logger.info("Expected Behaviour: {}".format(result))
intf_l1_r2 = topo["routers"]["l1"]["links"]["r2"]["interface"]
intf_l1_i1 = topo["routers"]["l1"]["links"]["i1"]["interface"]
dut = "l1"
interface = topo["routers"]["l1"]["links"]["i1"]["interface"]
result = verify_igmp_groups(tgen, dut, interface, IGMP_JOIN_RANGE_1, expected=False)
- assert (
- result is not True
- ), "Testcase {} : Failed \n Groups are not" " present \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: IGMP groups should not be present \n "
+ "Found: {}".format(tc_name, dut, result)
)
- logger.info("Expected Behaviour: {}".format(result))
result = verify_multicast_traffic(tgen, input_traffic)
assert result is True, "Testcase {}: Failed Error: {}".format(tc_name, result)
result = verify_mroutes(
tgen, dut, source, IGMP_JOIN_RANGE_1, iif, oil, expected=False
)
- assert (
- result is not True
- ), "Testcase {} : Failed \n routes are still" " present \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: mroute (S, G) should not be present in mroute table \n "
+ "Found: {}".format(tc_name, dut, result)
)
- logger.info("Expected Behaviour: {}".format(result))
write_test_footer(tc_name)
)
result = verify_igmp_config(tgen, input_dict_1, expected=False)
- assert (
- result is not True
- ), "Testcase {} : Failed \n " "IGMP interface is not removed \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: IGMP interface should be removed \n "
+ "Found: {}".format(tc_name, data["dut"], result)
)
- logger.info("Expected Behaviour: {}".format(result))
step("Verify that no core is observed")
if tgen.routers_have_failure():
data["oil"],
expected=False,
)
- assert (
- result is not True
- ), "Testcase {} : Failed \n " "mroute still present \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: mroute (S, G) should not be present in mroute table \n "
+ "Found: {}".format(tc_name, data["dut"], result)
)
- logger.info("Expected Behaviour: {}".format(result))
for data in input_dict_sg:
result = verify_mroutes(
)
assert result is not True, (
"Testcase {} : Failed \n "
- "IGMP groups still present still present \n Error: {}".format(tc_name, result)
+ "Expected: [{}]: IGMP groups should not present \n "
+ "Found: {}".format(tc_name, dut, result)
)
- logger.info("Expected Behaviour: {}".format(result))
step(
"After receiving the IGMP prune from FRR1 , verify traffic "
data["oil"],
expected=False,
)
- assert (
- result is not True
- ), "Testcase {} : Failed \n " "mroute still present \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: mroute (S, G) should not be present in mroute table \n "
+ "Found: {}".format(tc_name, data["dut"], result)
)
- logger.info("Expected Behaviour: {}".format(result))
for data in input_dict_sg_i1:
result = verify_mroutes(
IGMP_JOIN_RANGE_1,
expected=False,
)
- assert (
- result is not True
- ), "Testcase {} : Failed \n " "upstream still present \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: Upstream IIF interface {} should not be present\n"
+ "Found: {}".format(tc_name, data["dut"], data["iif"], result)
)
- logger.info("Expected Behaviour: {}".format(result))
for data in input_dict_sg_i1:
result = verify_upstream_iif(
result = verify_pim_rp_info(
tgen, topo, dut, GROUP_RANGE_1, "Unknown", rp_address, SOURCE, expected=False
)
- assert (
- result is not True
- ), "Testcase {} : Failed \n " "RP iif is not updated \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: RP IIF should be updated as Unknown \n "
+ "Found: {}".format(tc_name, dut, result)
)
- logger.info("Expected Behaviour: {}".format(result))
step("Verify mroute after No shut the link from LHR to RP from RP node")
)
assert result is not True, (
"Testcase {} : Failed \n "
- "upstream is still present after shut the link from "
- "FHR to RP from RP node \n Error: {}".format(tc_name, result)
+ "Expected: [{}]: Upstream IIF interface {} should not be present"
+ " after shutting link from RP to FHR \n"
+ "Found: {}".format(tc_name, data["dut"], data["iif"], result)
)
step(" No shut the link from FHR to RP from RP node")
result = verify_pim_rp_info(
tgen, topo, dut, GROUP_RANGE_1, "Unknown", rp_address, SOURCE, expected=False
)
- assert (
- result is not True
- ), "Testcase {} : Failed \n " "RP iif is not updated \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: RP IIF should be updated as Unknown \n"
+ "Found: {}".format(tc_name, dut, result)
)
- logger.info("Expected Behaviour: {}".format(result))
step("Verify mroute after Noshut the link from FHR to RP from RP node")
)
assert result is not True, (
"Testcase {} : Failed \n "
- "upstream is still present after shut the link from "
- "FHR to RP from FHR node \n Error: {}".format(tc_name, result)
+ "Expected: [{}]: Upstream IIF interface {} should not be present"
+ " after shutting link from FHR to RP \n"
+ "Found: {}".format(tc_name, data["dut"], data["iif"], result)
)
step(" No shut the link from FHR to RP from FHR node")
result = verify_pim_rp_info(
tgen, topo, dut, GROUP_RANGE_1, "Unknown", rp_address, SOURCE, expected=False
)
- assert (
- result is not True
- ), "Testcase {} : Failed \n " "RP iif is not updated \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: RP IIF should be updated as Unknown \n"
+ "Found: {}".format(tc_name, dut, result)
)
- logger.info("Expected Behaviour: {}".format(result))
step("Verify mroute after No Shut the link from FHR to RP from FHR node")
expected=False,
)
assert result is not True, (
- "Testcase {} : Failed \n"
- " Expected Behaviour: mroutes are cleared \n Error: {}".format(
- tc_name, result
- )
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: mroute (S, G) should not be present in mroute table \n "
+ "Found: {}".format(tc_name, data["dut"], result)
)
- logger.info("Expected Behaviour: {}".format(result))
shutdown_bringup_interface(tgen, "r2", intf_r2_i3, True)
data["oil"],
expected=False,
)
- assert (
- result is not True
- ), "Testcase {} : Failed \n" "mroutes are cleared \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: mroute (S, G) should not be present in mroute table \n "
+ "Found: {}".format(tc_name, data["dut"], result)
)
- logger.info("Expected Behaviour: {}".format(result))
shutdown_bringup_interface(tgen, "l1", intf_l1_i1, True)
data["oil"],
expected=False,
)
- assert (
- result is not True
- ), "Testcase {} : Failed \n" " mroutes are cleared \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: mroute (S, G) should not be present in mroute table \n "
+ "Found: {}".format(tc_name, data["dut"], result)
)
- logger.info("Expected Behaviour: {}".format(result))
shutdown_bringup_interface(tgen, "r2", intf_r2_f1, True)
result = verify_mroutes(
tgen, dut, src_address, _IGMP_JOIN_RANGE, iif, oil, expected=False
)
- assert (
- result is not True
- ), "Testcase {} : Failed \n" " mroutes are cleared \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: mroute (S, G) should not be present in mroute table \n "
+ "Found: {}".format(tc_name, dut, result)
)
- logger.info("Expected Behaviour: {}".format(result))
shutdown_bringup_interface(tgen, "l1", intf_l1_r2, True)
data["oil"],
expected=False,
)
- assert (
- result is not True
- ), "Testcase {} : Failed \n" " mroutes are cleared \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: mroute (S, G) should not be present in mroute table \n "
+ "Found: {}".format(tc_name, data["dut"], result)
)
- logger.info("Expected Behaviour: {}".format(result))
step("No shut the receiver(l1) port in 1 min interval")
data["oil"],
expected=False,
)
- assert (
- result is not True
- ), "Testcase {} : Failed \n" " mroutes are cleared \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: mroute (S, G) should not be present in mroute table \n "
+ "Found: {}".format(tc_name, data["dut"], result)
)
- logger.info("Expected Behaviour: {}".format(result))
step("No shut the source(r2) port in 1 min interval")
data["oil"],
expected=False,
)
- assert (
- result is not True
- ), "Testcase {} : Failed \n" " mroutes are cleared \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: mroute (S, G) should not be present in mroute table \n "
+ "Found: {}".format(tc_name, data["dut"], result)
)
- logger.info("Expected Behaviour: {}".format(result))
write_test_footer(tc_name)
# Required linux kernel version for this suite to run.
result = required_linux_kernel_version("4.19")
if result is not True:
- pytest.skip("Kernel requirements are not met")
+ pytest.skip("Kernel version should be >= 4.19")
testsuite_run_time = time.asctime(time.localtime(time.time()))
logger.info("Testsuite start time: {}".format(testsuite_run_time))
)
assert result is not True, (
"Testcase {} : Failed \n "
- "mroutes(S,G) are present after delete of static routes on c1 \n Error: {}".format(
- tc_name, result
- )
+ "Expected: [{}]: mroute (S, G) should not be present in mroute table \n "
+ "Found: {}".format(tc_name, data["dut"], result)
)
result = verify_upstream_iif(
)
assert result is not True, (
"Testcase {} : Failed \n "
- "upstream is present after delete of static routes on c1 \n Error: {}".format(
- tc_name, result
- )
+ "Expected: [{}]: Upstream IIF interface {} should not be present\n "
+ "Found: {}".format(tc_name, data["dut"], data["iif"], result)
)
for data in input_dict_starg:
)
assert result is not True, (
"Testcase {} : Failed \n "
- "mroutes(*,G) are present after delete of static routes on c1 \n Error: {}".format(
- tc_name, result
- )
+ "Expected: [{}]: mroute (S, G) should not be present in mroute table \n "
+ "Found: {}".format(tc_name, data["dut"], result)
)
result = verify_upstream_iif(
)
assert result is not True, (
"Testcase {} : Failed \n "
- "upstream is present after delete of static routes on c1 \n Error: {}".format(
- tc_name, result
- )
+ "Expected: [{}]: Upstream IIF interface {} should not be present\n "
+ "Found: {}".format(tc_name, data["dut"], data["iif"], result)
)
step("Configure default routes on c2")
)
assert result is not True, (
"Testcase {} : Failed \n "
- "RP info is unknown after removing static route from c2 \n Error: {}".format(
- tc_name, result
- )
+ "Expected: [{}]: RP Info should not be Unknown after removing static"
+ " route from c2 \n"
+ "Found: {}".format(tc_name, data["dut"], result)
)
step("Verify (s,g) populated after adding default route ")
data["oil"],
expected=False,
)
- assert (
- result is not True
- ), "Testcase {} : Failed \n " "mroutes are still present \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: mroute (S, G) should not be present in mroute table \n "
+ "Found: {}".format(tc_name, data["dut"], result)
)
result = verify_upstream_iif(
IGMP_JOIN_RANGE_1,
expected=False,
)
- assert (
- result is not True
- ), "Testcase {} : Failed \n " "upstream is still present \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: Upstream IIF interface {} should not be present\n "
+ "Found: {}".format(tc_name, data["dut"], data["iif"], result)
)
step("Configure default routes on all the nodes")
)
assert result is not True, (
"Testcase {} : Failed \n "
- "RP info is unknown after removing static route from c2 \n Error: {}".format(
- tc_name, result
- )
+ "Expected: [{}]: RP Info should not be Unknown after removing static"
+ " route from c2 \n"
+ "Found: {}".format(tc_name, data["dut"], result)
)
step("Verify (s,g) populated after adding default route ")
result = verify_igmp_groups(tgen, dut, interface, GROUP_ADDRESS, expected=False)
assert result is not True, (
"Testcase {} : Failed \n "
- "r1: igmp group present without any IGMP join \n Error: {}".format(
- tc_name, result
- )
+ "Expected: [{}]: IGMP groups should not be present without any IGMP join\n "
+ "Found: {}".format(tc_name, dut, result)
)
step("r1: Verify show ip pim interface traffic without any IGMP join")
result = verify_pim_rp_info(
tgen, TOPO, dut, GROUP_RANGE_ALL, iif, rp_address, SOURCE, expected=False
)
- assert (
- result is not True
- ), "Testcase {} : Failed \n " "r1: RP info present \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: RP info should not be present \n "
+ "Found: {}".format(tc_name, dut, result)
)
step("r1: Verify upstream IIF interface")
result = verify_upstream_iif(tgen, dut, iif, STAR, GROUP_ADDRESS, expected=False)
assert result is not True, (
"Testcase {} : Failed \n "
- "r1: upstream IIF interface present \n Error: {}".format(tc_name, result)
+ "Expected: [{}]: Upstream IIF interface {} should not be present\n "
+ "Found: {}".format(tc_name, dut, iif, result)
)
step("r1: Verify upstream join state and join timer")
)
assert result is not True, (
"Testcase {} : Failed \n "
- "r1: upstream join state is up and join timer is running \n Error: {}".format(
- tc_name, result
- )
+ "Expected: [{}]: Upstream Join State timer should not run\n "
+ "Found: {}".format(tc_name, dut, result)
)
# 20
step("r1: Verify PIM state")
result = verify_pim_state(tgen, dut, iif, oif, GROUP_ADDRESS, expected=False)
- assert result is not True, "Testcase {} :Failed \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: PIM state should not be up \n "
+ "Found: {}".format(tc_name, dut, result)
)
step("r1: Verify ip mroutes")
result = verify_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif, expected=False)
- assert (
- result is not True
- ), "Testcase {} : Failed \n " "r1: mroutes are still present \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: mroute (*, G) should not be present \n "
+ "Found: {}".format(tc_name, dut, result)
)
step("r1: Verify show ip pim interface traffic without any IGMP join")
)
assert result is not True, (
"Testcase {} : Failed \n "
- "r3: (S, G) upstream join state is up and join timer is running\n Error: {}".format(
- tc_name, result
- )
+ "Expected: [{}]: Upstream Join State timer should not run\n "
+ "Found: {}".format(tc_name, dut, result)
)
step("r3: Verify (S, G) ip mroutes")
result = verify_pim_state(tgen, dut, iif, oif, GROUP_ADDRESS, expected=False)
assert result is not True, (
"Testcase {} : Failed \n "
- "OIL is not same and IIF is not cleared on R1 \n Error: {}".format(
- tc_name, result
- )
+ "Expected: [{}]: OIL should be same and IIF should be cleared\n "
+ "Found: {}".format(tc_name, dut, result)
)
step("r1: upstream IIF should be unknown , verify using show ip pim" "upstream")
result = verify_upstream_iif(tgen, dut, iif, STAR, GROUP_ADDRESS, expected=False)
assert result is not True, (
"Testcase {} : Failed \n "
- "r1: upstream IIF is not unknown \n Error: {}".format(tc_name, result)
+ "Expected: [{}]: Upstream IIF interface {} should be unknown \n "
+ "Found: {}".format(tc_name, dut, iif, result)
)
step(
)
assert result is not True, (
"Testcase {} : Failed \n "
- "r1: join state is joined and timer is not stopped \n Error: {}".format(
- tc_name, result
- )
+ "Expected: [{}]: Upstream Join State timer should not run\n "
+ "Found: {}".format(tc_name, dut, result)
)
step(
result = verify_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif, expected=False)
assert result is not True, (
"Testcase {} : Failed \n "
- "r1: (*, G) are not cleared from mroute table \n Error: {}".format(
- tc_name, result
- )
+ "Expected: [{}]: mroute (*, G) should be cleared from mroute table\n "
+ "Found: {}".format(tc_name, dut, result)
)
- logger.info("Expected behavior: %s", result)
# Uncomment next line for debugging
# tgen.mininet_cli()
result = verify_pim_rp_info(
tgen, TOPO, dut, GROUP_RANGE_ALL, iif, rp_address, SOURCE, expected=False
)
- assert (
- result is not True
- ), "Testcase {} : Failed \n " "r1: rp-info is present \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: RP-info should not be present \n "
+ "Found: {}".format(tc_name, dut, result)
)
step("joinTx value before join sent")
result = verify_upstream_iif(tgen, dut, iif, STAR, GROUP_ADDRESS, expected=False)
assert result is not True, (
"Testcase {} : Failed \n "
- "r1: upstream IFF interface is present \n Error: {}".format(tc_name, result)
+ "Expected: [{}]: Upstream IIF interface {} should not be present \n "
+ "Found: {}".format(tc_name, dut, iif, result)
)
step("r1: Verify upstream join state and join timer")
)
assert result is not True, (
"Testcase {} : Failed \n "
- "r1: upstream join state is joined and timer is running \n Error: {}".format(
- tc_name, result
- )
+ "Expected: [{}]: Upstream Join State timer should not run\n "
+ "Found: {}".format(tc_name, dut, result)
)
step("r1: Verify PIM state")
result = verify_pim_state(tgen, dut, iif, oif, GROUP_ADDRESS, expected=False)
- assert (
- result is not True
- ), "Testcase {} : Failed \n " "r1: PIM state is up\n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: PIM state should not be up\n "
+ "Found: {}".format(tc_name, dut, result)
)
step("r1: Verify ip mroutes")
result = verify_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif, expected=False)
- assert (
- result is not True
- ), "Testcase {} : Failed \n " "r1: mroutes are still present\n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: mroute (*, G) should not be present in mroute table \n "
+ "Found: {}".format(tc_name, dut, result)
)
step("r1: Configure static RP")
result = verify_upstream_iif(tgen, dut, iif, STAR, GROUP_ADDRESS, expected=False)
assert result is not True, (
"Testcase {} : Failed \n "
- "r1: upstream IIF interface is present\n Error: {}".format(tc_name, result)
+ "Expected: [{}]: Upstream IIF interface {} should not be present \n "
+ "Found: {}".format(tc_name, dut, iif, result)
)
step("r1 : Verify upstream join state and join timer")
)
assert result is not True, (
"Testcase {} : Failed \n "
- "r1: upstream join state is joined and timer is running\n Error: {}".format(
- tc_name, result
- )
+ "Expected: [{}]: Upstream Join State timer should not run\n "
+ "Found: {}".format(tc_name, dut, result)
)
step("r1 : Verify PIM state")
result = verify_pim_state(tgen, dut, iif, oif, GROUP_ADDRESS, expected=False)
- assert (
- result is not True
- ), "Testcase {} : Failed \n " "r1: PIM state is up\n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: PIM state should not be up \n "
+ "Found: {}".format(tc_name, dut, result)
)
step("r1 : Verify ip mroutes")
result = verify_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif, expected=False)
- assert (
- result is not True
- ), "Testcase {} : Failed \n " "r1: mroutes are still present\n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: mroute (*, G) should not be present \n "
+ "Found: {}".format(tc_name, dut, result)
)
step("r1: Make RP reachable")
)
assert result is not True, (
"Testcase {} : Failed \n "
- "r1: rp-info is present for group 225.1.1.1 \n Error: {}".format(
- tc_name, result
- )
+ "Expected: [{}]: RP-info should not be present \n "
+ "Found: {}".format(tc_name, dut, result)
)
step(
)
assert result is not True, (
"Testcase {} : Failed \n "
- "r3: (S, G) upstream join state is joined and join"
- " timer is running \n Error: {}".format(tc_name, result)
+ "Expected: [{}]: Upstream Join State should not be Joined and "
+ "join timer should not run\n "
+ "Found: {}".format(tc_name, dut, result)
)
step("r3: Verify (S, G) ip mroutes")
)
assert result is not True, (
"Testcase {} : Failed \n "
- "r3: (S,G) upstream state is joined and join timer is running\n Error: {}".format(
- tc_name, result
- )
+ "Expected: [{}]: Upstream Join State should not be Joined and "
+ "join timer should not run\n "
+ "Found: {}".format(tc_name, dut, result)
)
step("r3: Verify (S, G) ip mroutes")
)
assert result is not True, (
"Testcase {} : Failed \n "
- "r3: (S,G) upstream state is joined and join timer is running\n Error: {}".format(
- tc_name, result
- )
+ "Expected: [{}]: Upstream Join State should not be Joined and "
+ "join timer should not run\n "
+ "Found: {}".format(tc_name, dut, result)
)
step("r3: Verify (S, G) ip mroutes")
)
assert result is not True, (
"Testcase {} : Failed \n "
- "r3: (S,G) upstream state is joined and join timer is running\n Error: {}".format(
- tc_name, result
- )
+ "Expected: [{}]: Upstream Join State should not be Joined and "
+ "join timer should not run\n "
+ "Found: {}".format(tc_name, dut, result)
)
step("r3: Verify (S, G) ip mroutes")
)
assert result is not True, (
"Testcase {} : Failed \n "
- "r3: (S,G) upstream state is joined and join timer is running\n Error: {}".format(
- tc_name, result
- )
+ "Expected: [{}]: Upstream Join State should not be Joined and "
+ "join timer should not run\n "
+ "Found: {}".format(tc_name, dut, result)
)
step("r3: Verify (S, G) ip mroutes")
)
assert result is not True, (
"Testcase {} : Failed \n "
- "r2: (S,G) upstream state is joined and join timer is running\n Error: {}".format(
- tc_name, result
- )
+ "Expected: [{}]: Upstream Join State should not be Joined and "
+ "join timer should not run\n "
+ "Found: {}".format(tc_name, dut, result)
)
step("r2: Verify (S, G) ip mroutes")
)
assert result is not True, (
"Testcase {} : Failed \n "
- "r3: (S,G) upstream state is joined and join timer is running\n Error: {}".format(
- tc_name, result
- )
+ "Expected: [{}]: Upstream Join State should not be Joined and "
+ "join timer should not run\n "
+ "Found: {}".format(tc_name, dut, result)
)
step("r3: Verify (S, G) ip mroutes")
)
assert result is not True, (
"Testcase {} : Failed \n "
- "r3: (S,G) upstream state is joined and join timer is running\n Error: {}".format(
- tc_name, result
- )
+ "Expected: [{}]: Upstream Join State should not be Joined and "
+ "join timer should not run\n "
+ "Found: {}".format(tc_name, dut, result)
)
step("r3: Verify (S, G) ip mroutes")
)
assert result is not True, (
"Testcase {} : Failed \n "
- "r2: (S,G) upstream state is joined and join timer is running\n Error: {}".format(
- tc_name, result
- )
+ "Expected: [{}]: Upstream Join State should not be Joined and "
+ "join timer should not run\n "
+ "Found: {}".format(tc_name, dut, result)
)
step("r2: Verify (S, G) ip mroutes")
)
assert result is not True, (
"Testcase {} : Failed \n "
- "r2: (S,G) upstream state is joined and join timer is running\n Error: {}".format(
- tc_name, result
- )
+ "Expected: [{}]: Upstream Join State should not be Joined and "
+ "join timer should not run\n "
+ "Found: {}".format(tc_name, dut, result)
)
step("r2: Verify (S, G) ip mroutes")
)
assert result is not True, (
"Testcase {} : Failed \n "
- "r3: (S,G) upstream state is joined and join timer is running\n Error: {}".format(
- tc_name, result
- )
+ "Expected: [{}]: Upstream Join State should not be Joined and "
+ "join timer should not run\n "
+ "Found: {}".format(tc_name, dut, result)
)
step("r3: Verify (S, G) ip mroutes")
)
assert result is not True, (
"Testcase {} : Failed \n "
- "r2: (S,G) upstream state is joined and join timer is running\n Error: {}".format(
- tc_name, result
- )
+ "Expected: [{}]: Upstream Join State should not be Joined and "
+ "join timer should not run\n "
+ "Found: {}".format(tc_name, dut, result)
)
step("r2: Verify (S, G) ip mroutes")
)
assert result is not True, (
"Testcase {} : Failed \n "
- "r3: (S,G) upstream state is joined and join timer is running\n Error: {}".format(
- tc_name, result
- )
+ "Expected: [{}]: Upstream Join State should not be Joined and "
+ "join timer should not run\n "
+ "Found: {}".format(tc_name, dut, result)
)
step("r3: Verify (S, G) ip mroutes")
)
assert result is not True, (
"Testcase {} : Failed \n "
- "r4: (S,G) upstream state is joined and join timer is running\n Error: {}".format(
- tc_name, result
- )
+ "Expected: [{}]: Upstream Join State should not be Joined and "
+ "join timer should not run\n "
+ "Found: {}".format(tc_name, dut, result)
)
step("r4: Verify (S, G) ip mroutes")
result = verify_join_state_and_timer(
tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_2, expected=False
)
- assert result is not True, "Testcase {} :Failed \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: [{}]: Upstream Join State should not be Joined and "
+ "join timer should not run\n "
+ "Found: {}".format(tc_name, dut, result)
)
step("r3: Verify (S, G) ip mroutes")
)
assert result is not True, (
"Testcase {} : Failed \n "
- "r2: (S,G) upstream state is joined and join timer is running\n Error: {}".format(
- tc_name, result
- )
+ "Expected: [{}]: Upstream Join State should not be Joined and "
+ "join timer should not run\n "
+ "Found: {}".format(tc_name, dut, result)
)
step("r2: Verify (S, G) ip mroutes")
)
assert result is not True, (
"Testcase {} : Failed \n "
- "r3: (S,G) upstream state is joined and join timer is running\n Error: {}".format(
- tc_name, result
- )
+ "Expected: [{}]: Upstream Join State should not be Joined and "
+ "join timer should not run\n "
+ "Found: {}".format(tc_name, dut, result)
)
step("r3: Verify (S, G) ip mroutes")
)
assert result is not True, (
"Testcase {} : Failed \n "
- "r4: (S,G) upstream state is joined and join timer is running\n Error: {}".format(
- tc_name, result
- )
+ "Expected: [{}]: Upstream Join State should not be Joined and "
+ "join timer should not run\n "
+ "Found: {}".format(tc_name, dut, result)
)
step("r4: Verify (S, G) ip mroutes")
)
assert result is not True, (
"Testcase {} : Failed \n "
- "r3: (S,G) upstream state is joined and join timer is running\n Error: {}".format(
- tc_name, result
- )
+ "Expected: [{}]: Upstream Join State should not be Joined and "
+ "join timer should not run\n "
+ "Found: {}".format(tc_name, dut, result)
)
step("r3: Verify (S, G) ip mroutes")
result = verify_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif, expected=False)
assert result is not True, (
"Testcase {} : Failed \n "
- "r1: (*,G) mroutes are not cleared after shut of R1 to R3 link\n Error: {}".format(
- tc_name, result
- )
+ "Expected: [{}]: mroute (*, G) should be cleared \n"
+ "Found: {}".format(tc_name, dut, result)
)
step("r2: Verify (*, G) ip mroutes")
result = verify_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif, expected=False)
assert result is not True, (
"Testcase {} : Failed \n "
- "r2: (*,G) mroutes are not cleared after shut of R1 to R3 link\n Error: {}".format(
- tc_name, result
- )
+ "Expected: [{}]: mroute (*, G) should be cleared \n"
+ "Found: {}".format(tc_name, dut, result)
)
step("r3: Verify (*, G) ip mroutes")
result = verify_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif, expected=False)
assert result is not True, (
"Testcase {} : Failed \n "
- "r3: (*,G) mroutes are not cleared after shut of R1 to R3 link\n Error: {}".format(
- tc_name, result
- )
+ "Expected: [{}]: mroute (*, G) should be cleared after shutting"
+ "link from R1 to R3 \n"
+ "Found: {}".format(tc_name, dut, result)
)
step("r3: No shutdown the link from R1 to R3 from R3 node")
result = verify_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif, expected=False)
assert result is not True, (
"Testcase {} : Failed \n "
- "r1: (*,G) mroutes are not cleared after shut of R1 to R0 link\n Error: {}".format(
- tc_name, result
- )
+ "Expected: [{}]: mroute (*, G) should be cleared after shutting"
+ "link from R1 to R0 \n"
+ "Found: {}".format(tc_name, dut, result)
)
step("r2: Verify (*, G) ip mroutes cleared")
result = verify_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif, expected=False)
assert result is not True, (
"Testcase {} : Failed \n "
- "r2: (*,G) mroutes are not cleared after shut of R1 to R0 link\n Error: {}".format(
- tc_name, result
- )
+ "Expected: [{}]: mroute (*, G) should be cleared after shutting"
+ "link from R1 to R0 \n"
+ "Found: {}".format(tc_name, dut, result)
)
write_test_footer(tc_name)
result = verify_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif, expected=False)
assert result is not True, (
"Testcase {} : Failed \n "
- "r1: (*,G) mroutes are not cleared after shut of R1 to R2 and R3 link\n Error: {}".format(
- tc_name, result
- )
+ "Expected: [{}]: mroute (*, G) should be cleared after shutting"
+ "link from R2 to R3 \n"
+ "Found: {}".format(tc_name, dut, result)
)
step("r2: Verify (*, G) ip mroutes cleared")
result = verify_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif, expected=False)
assert result is not True, (
"Testcase {} : Failed \n "
- "r2: (*,G) mroutes are not cleared after shut of R1 to R2 and R3 link\n Error: {}".format(
- tc_name, result
- )
+ "Expected: [{}]: mroute (*, G) should be cleared after shutting"
+ "link from R2 to R3 \n"
+ "Found: {}".format(tc_name, dut, result)
)
write_test_footer(tc_name)
test_func = partial(
topotest.router_json_cmp, r1, "show ip pim rp-info json", expected
)
- _, result = topotest.run_and_expect(test_func, None, count=15, wait=5)
+ _, result = topotest.run_and_expect(test_func, None, count=30, wait=1)
assertmsg = '"{}" JSON output mismatches'.format(r1.name)
assert result is None, assertmsg
# tgen.mininet_cli()
# Let's establish a S,G stream from r2 -> r1
CWD = os.path.dirname(os.path.realpath(__file__))
r2.run(
- "{}/mcast-tx.py --ttl 5 --count 5 --interval 10 229.1.1.1 r2-eth0 > /tmp/bar".format(
+ "{}/mcast-tx.py --ttl 5 --count 40 --interval 2 229.1.1.1 r2-eth0 > /tmp/bar".format(
CWD
)
)
# And from r3 -> r1
r3.run(
- "{}/mcast-tx.py --ttl 5 --count 5 --interval 10 229.1.1.1 r3-eth0 > /tmp/bar".format(
+ "{}/mcast-tx.py --ttl 5 --count 40 --interval 2 229.1.1.1 r3-eth0 > /tmp/bar".format(
CWD
)
)
test_func = partial(
topotest.router_json_cmp, r1, "show ip pim upstream json", expected
)
- _, result = topotest.run_and_expect(test_func, None, count=20, wait=1)
+ _, result = topotest.run_and_expect(test_func, None, count=40, wait=1)
assert result is None, "failed to converge pim"
# tgen.mininet_cli()
test_func = partial(
topotest.router_json_cmp, rp, "show ip pim upstream json", expected
)
- _, result = topotest.run_and_expect(test_func, None, count=20, wait=0.5)
+ _, result = topotest.run_and_expect(test_func, None, count=40, wait=1)
assertmsg = '"{}" JSON output mismatches'.format(rp.name)
assert result is None, assertmsg
test_func = partial(
topotest.router_json_cmp, r1, "show ip pim upstream json", expected
)
- _, result = topotest.run_and_expect(test_func, None, count=10, wait=0.5)
+ _, result = topotest.run_and_expect(test_func, None, count=40, wait=1)
assertmsg = '"{}" JSON output mismatches'.format(r1.name)
assert result is None, assertmsg
finally:
pfx = str(ipaddress.ip_network((i, 32)))
match[pfx] = [dict(entry, prefix=pfx)]
- ok = topotest.router_json_cmp_retry(r1, "show ip route json", match)
+ ok = topotest.router_json_cmp_retry(r1, "show ip route json", match, False, 30)
assert ok, '"r1" JSON output mismatches'
r1.vtysh_cmd("sharp remove routes 2.1.3.7 " + str(count))
if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug(
"%s: if %s(%u) zebra info pointer is NULL",
- __func__, ifp->name, ifp->ifindex);
+ __func__, ifp ? ifp->name : "(null)",
+ ifp ? ifp->ifindex : ifindex);
return;
}
if (afi == AFI_IP) {