debug_babel_config_write(vty);
+ cmd_show_lib_debugs(vty);
+
return CMD_SUCCESS;
}
if (bglobal.debug_network)
vty_out(vty, " Network layer debugging is on.\n");
+ cmd_show_lib_debugs(vty);
+
return CMD_SUCCESS;
}
+++ /dev/null
-$Id: IMPLEMENTATION.txt,v 1.2 2005/02/15 17:10:03 gdt Exp $
-
-This file contains notes about the internals of the BGP
-implementation. The initial impetus is understanding the memory usage
-of Quagga'a BGP implementation. There may be some inaccuracies; it is
-in the repository in the hopes that it will be significantly more
-helpful than not.
-
-* FILES
-
-bgp_advertise.[hc]:
- data structures: advertised prefixes, attributes
-
-bgp_aspath.[hc]:
- struct aspath:
- These are stored in a hash, apparently in wire format.
-
-bgp_attr.[hc]:
- struct attr: contains all attributes
- size(ILP32) 26 words/104 bytes (poor packing, v6/multicast is 10)
-
- bgp_attr_parse: origin, aspath, next hop probably most of interest
- bgp_attr_origin: set flag bit
- bgp_attr_aspath: put in refcounted hash table, so share pointer
- bgp_attr_nexthop: store in attribute structure
-
-bgp_btoa.c: ? test program
-
-bgp_clist.[hc]:
- data structures: community lists (including permit/deny state)
-
-bgp_community.[hc]:
- data structures: community atttributes (multiple communities per struct)
-
-bgp_damp.[hc]:
- per-route damping data, and damping control information
-
-bgp_debug.[hc]:
- debugging support (vty config, dump of packets)
-
-bgp_dump.[hc]:
- MRT-compatible dump format routines
-
-bgp_ecommunity.[hc]:
- Extended communities attributes (multiple ecommmunities per struct)
-
-bgp_filter.[hc]:
- AS path access list filtering
-
-bgp_fsm.[hc]:
- Per-peer state machine for TCP connection, hold time, etc.
-
-bgp_main.c:
- Daemon startup.
-
-bgp_mplsvpn.[hc]:
- parsing of attribute structures for MPLS VPNs [need better description]
-
-bgp_network.[hc]:
- Opening and binding of sockets, finding addresses for interfaces
-
-bgp_nexthop.[hc]:
- data structures: Nexthop cache [not clear how used, if truly cache
- in sense of memoization, or something else]
-
- importing EGP routes into IGP (thread created)
- "scanning" (thread created)
- bgp_scan: has useful clues to data structure complexity. Scanning
- process iterates over database of received advertisements, and
- builds 'cache' structure.
-
-bgp_open.[ch]:
- Open messages, and capability negotiation
-
-bgp_packet.[hc]
- sending and receiving of UPDATE/WITHDRAW
- collision resolution for simultanteous opens
- bgp_read: top-level read routine: reads whole packet (nonblocking)
- and dispatches to per-message-type receive
-
- bgp_update_receive:
- calls bgp_attr_parse
- reads nrli into struct bgp_nrli update
-
- uninterning of aspath, community, ecommmunity, cluster,
- transit which were interned in bgp_attr_parse
-
-bgp_regex.[ch]:
- Glue to convert BGP regexps to standard (_ means many things).
-
-bgp_route.[hc]:
- data structures: routes as received, static routes
- Application of filters. Lots of route processing.
-
- bgp_nlri_parse:
- sanity checks, then calls bgp_update with peer, prefix, attributes pointer
-
- bgp_update: bgp_update_main, then RS processing
-
- bgp_update_main:
- find 'struct bgp_node *' for this afi/safi
- look for route in table, then 'intern' attributes
- ** interning is process of
- looking for data in hash table, and putting there if missing, refcnt
- using pointer to existing data
- many validity checks
- get new struct bgp_path_info
- call bgp_path_info_add with rn and bgp_path_info
- call bgp_process
-
-bgp_routemap.c
- implementation of route maps (match and set)
-
-bgp_snmp.c
- SNMP glue. Not particularly interesting except to add variables or
- debug SNMP.
-
-bgp_table.[hc]
- data structures: struct bgp_table, struct bgp_node
- allocation/lookup/utility operations - not a lot of protocol processin
-
-bgp_vty.[hc]
- protocol-wide vty hooks
-
-bgp_zebra.[hc]
- Processing interface events from zebra, redistribution of routes.
-
-bgpd.h
- struct bgp_master: daemon main data structure
- struct bgp: per-instance structure
- struct peer_group
- struct bgp_notify: (in-core representation of wire format?)
- struct bgp_nexthop: (v4 and v6 addresses, *ifp)
- struct bgp_filter: distribute, prefix, aslist, route_maps
- struct peer: neighbor structure (very rich/complex)
- struct bgp_nlri: reference to wire format
- #define of protocol constants
- attribute type codes
- fsm states/events
- timer values
-
-bgpd.c
- instance/peer allocation
- configuration
- initialization/termination
-
-* DATA STRUCTURE SIZES
-
-Question: How much memory does quagga's bgpd use as a function of
-state received from peers?
-
-It seems that a struct bgp_path_info is kept for each prefix. The "struct
-attr *" is interned, and variables within that are interned. So, 40
-bytes are kept per received prefix, plus interned shared values. This
-could be 36 if 'int suppress' where changed to a u_char and moved to
-be with the other u_chars. Without MPLS, this could be 32 bytes.
-Note that 8 bytes of this is linked list overhead, meaning that 24
-bytes are the raw per-prefix storage requirements.
-
-Also, a struct bgp_damp_info is apparently maintained per route; this
-is fairly large (about 44 bytes).
-
-[TODO: the role of struct bgp_node.]
-
-* TIME COMPLEXITY
-
-It appears that received prefixes from each peer are stored in a
-linked list.
{
struct attr attr;
struct attr *new;
- int ret;
+ route_map_result_t ret;
memset(&attr, 0, sizeof(attr));
if (ret == RMAP_PERMITMATCH) {
bgp_dest_unlock_node(dest);
- if (BGP_DEBUG(update, UPDATE_OUT))
- zlog_debug(
- "%s: Condition map routes present in BGP table",
- __func__);
+ bgp_cond_adv_debug(
+ "%s: Condition map routes present in BGP table",
+ __func__);
return ret;
}
}
}
- if (BGP_DEBUG(update, UPDATE_OUT))
- zlog_debug("%s: Condition map routes not present in BGP table",
+ bgp_cond_adv_debug("%s: Condition map routes not present in BGP table",
__func__);
return ret;
subgrp->pscount = 0;
SET_FLAG(subgrp->sflags, SUBGRP_STATUS_TABLE_REPARSING);
- if (BGP_DEBUG(update, UPDATE_OUT))
- zlog_debug("%s: %s routes to/from %s for %s", __func__,
+ bgp_cond_adv_debug("%s: %s routes to/from %s for %s", __func__,
update_type == UPDATE_TYPE_ADVERTISE ? "Advertise"
: "Withdraw",
peer->host, get_afi_safi_str(afi, safi, false));
&& !peer->advmap_table_change)
continue;
- if (BGP_DEBUG(update, UPDATE_OUT)) {
+ if (BGP_DEBUG(cond_adv, COND_ADV)) {
if (peer->advmap_table_change)
zlog_debug(
"%s: %s - routes changed in BGP table.",
.advmap.update_type !=
filter->advmap.update_type)) {
/* Handle change to peer advmap */
- if (BGP_DEBUG(update, UPDATE_OUT))
- zlog_debug(
- "%s: advmap.update_type changed for peer %s, adjusting update_group.",
- __func__, peer->host);
+ bgp_cond_adv_debug(
+ "%s: advmap.update_type changed for peer %s, adjusting update_group.",
+ __func__, peer->host);
update_group_adjust_peer(paf);
}
*/
if (peer->advmap_config_change[afi][safi]) {
- if (BGP_DEBUG(update, UPDATE_OUT))
- zlog_debug(
- "%s: Configuration is changed on peer %s for %s, send the normal update first.",
- __func__, peer->host,
- get_afi_safi_str(afi, safi,
- false));
+ bgp_cond_adv_debug(
+ "%s: Configuration is changed on peer %s for %s, send the normal update first.",
+ __func__, peer->host,
+ get_afi_safi_str(afi, safi, false));
if (paf) {
update_subgroup_split_peer(paf, NULL);
subgrp = paf->subgroup;
* neighbors (AFI/SAFI). So just increment the counter.
*/
if (++bgp->condition_filter_count > 1) {
- if (BGP_DEBUG(update, UPDATE_OUT))
- zlog_debug("%s: condition_filter_count %d", __func__,
+ bgp_cond_adv_debug("%s: condition_filter_count %d", __func__,
bgp->condition_filter_count);
return;
* So there's nothing to do except decrementing the counter.
*/
if (--bgp->condition_filter_count != 0) {
- if (BGP_DEBUG(update, UPDATE_OUT))
- zlog_debug("%s: condition_filter_count %d", __func__,
+ bgp_cond_adv_debug("%s: condition_filter_count %d", __func__,
bgp->condition_filter_count);
return;
/* Last filter removed. So cancel conditional routes polling thread. */
THREAD_OFF(bgp->t_condition_check);
}
+
+static void peer_advertise_map_filter_update(struct peer *peer, afi_t afi,
+ safi_t safi, const char *amap_name,
+ struct route_map *amap,
+ const char *cmap_name,
+ struct route_map *cmap,
+ bool condition, bool set)
+{
+ struct bgp_filter *filter;
+ bool filter_exists = false;
+
+ filter = &peer->filter[afi][safi];
+
+ /* advertise-map is already configured. */
+ if (filter->advmap.aname) {
+ filter_exists = true;
+ XFREE(MTYPE_BGP_FILTER_NAME, filter->advmap.aname);
+ XFREE(MTYPE_BGP_FILTER_NAME, filter->advmap.cname);
+ }
+
+ route_map_counter_decrement(filter->advmap.amap);
+
+ /* Removed advertise-map configuration */
+ if (!set) {
+ memset(&filter->advmap, 0, sizeof(filter->advmap));
+
+ /* decrement condition_filter_count delete timer if
+ * this is the last advertise-map to be removed.
+ */
+ if (filter_exists)
+ bgp_conditional_adv_disable(peer, afi, safi);
+
+ /* Process peer route updates. */
+ peer_on_policy_change(peer, afi, safi, 1);
+
+ return;
+ }
+
+ /* Update filter data with newly configured values. */
+ filter->advmap.aname = XSTRDUP(MTYPE_BGP_FILTER_NAME, amap_name);
+ filter->advmap.cname = XSTRDUP(MTYPE_BGP_FILTER_NAME, cmap_name);
+ filter->advmap.amap = amap;
+ filter->advmap.cmap = cmap;
+ filter->advmap.condition = condition;
+ route_map_counter_increment(filter->advmap.amap);
+ peer->advmap_config_change[afi][safi] = true;
+
+ /* Increment condition_filter_count and/or create timer. */
+ if (!filter_exists) {
+ filter->advmap.update_type = UPDATE_TYPE_ADVERTISE;
+ bgp_conditional_adv_enable(peer, afi, safi);
+ }
+
+ /* Process peer route updates. */
+ peer_on_policy_change(peer, afi, safi, 1);
+}
+
+/* Set advertise-map to the peer. */
+int peer_advertise_map_set(struct peer *peer, afi_t afi, safi_t safi,
+ const char *advertise_name,
+ struct route_map *advertise_map,
+ const char *condition_name,
+ struct route_map *condition_map, bool condition)
+{
+ struct peer *member;
+ struct listnode *node, *nnode;
+
+ /* Set configuration on peer. */
+ peer_advertise_map_filter_update(peer, afi, safi, advertise_name,
+ advertise_map, condition_name,
+ condition_map, condition, true);
+
+ /* Check if handling a regular peer & Skip peer-group mechanics. */
+ if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
+ /* Set override-flag and process peer route updates. */
+ SET_FLAG(peer->filter_override[afi][safi][RMAP_OUT],
+ PEER_FT_ADVERTISE_MAP);
+ return 0;
+ }
+
+ /*
+ * Set configuration on all peer-group members, unless they are
+ * explicitly overriding peer-group configuration.
+ */
+ for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
+ /* Skip peers with overridden configuration. */
+ if (CHECK_FLAG(member->filter_override[afi][safi][RMAP_OUT],
+ PEER_FT_ADVERTISE_MAP))
+ continue;
+
+ /* Set configuration on peer-group member. */
+ peer_advertise_map_filter_update(
+ member, afi, safi, advertise_name, advertise_map,
+ condition_name, condition_map, condition, true);
+ }
+
+ return 0;
+}
+
+/* Unset advertise-map from the peer. */
+int peer_advertise_map_unset(struct peer *peer, afi_t afi, safi_t safi,
+ const char *advertise_name,
+ struct route_map *advertise_map,
+ const char *condition_name,
+ struct route_map *condition_map, bool condition)
+{
+ struct peer *member;
+ struct listnode *node, *nnode;
+
+ /* advertise-map is not configured */
+ if (!peer->filter[afi][safi].advmap.aname)
+ return 0;
+
+ /* Unset override-flag unconditionally. */
+ UNSET_FLAG(peer->filter_override[afi][safi][RMAP_OUT],
+ PEER_FT_ADVERTISE_MAP);
+
+ /* Inherit configuration from peer-group if peer is member. */
+ if (peer_group_active(peer)) {
+ PEER_STR_ATTR_INHERIT(peer, peer->group,
+ filter[afi][safi].advmap.aname,
+ MTYPE_BGP_FILTER_NAME);
+ PEER_ATTR_INHERIT(peer, peer->group,
+ filter[afi][safi].advmap.amap);
+ } else
+ peer_advertise_map_filter_update(
+ peer, afi, safi, advertise_name, advertise_map,
+ condition_name, condition_map, condition, false);
+
+ /* Check if handling a regular peer and skip peer-group mechanics. */
+ if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
+ /* Process peer route updates. */
+ bgp_cond_adv_debug("%s: Send normal update to %s for %s",
+ __func__, peer->host,
+ get_afi_safi_str(afi, safi, false));
+
+ return 0;
+ }
+
+ /*
+ * Remove configuration on all peer-group members, unless they are
+ * explicitly overriding peer-group configuration.
+ */
+ for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
+ /* Skip peers with overridden configuration. */
+ if (CHECK_FLAG(member->filter_override[afi][safi][RMAP_OUT],
+ PEER_FT_ADVERTISE_MAP))
+ continue;
+ /* Remove configuration on peer-group member. */
+ peer_advertise_map_filter_update(
+ member, afi, safi, advertise_name, advertise_map,
+ condition_name, condition_map, condition, false);
+
+ /* Process peer route updates. */
+ bgp_cond_adv_debug("%s: Send normal update to %s for %s ",
+ __func__, member->host,
+ get_afi_safi_str(afi, safi, false));
+ }
+
+ return 0;
+}
extern "C" {
#endif
+/* Macro to log debug message */
+#define bgp_cond_adv_debug(...) \
+ do { \
+ if (BGP_DEBUG(cond_adv, COND_ADV)) \
+ zlog_debug("" __VA_ARGS__); \
+ } while (0)
+
/* Polling time for monitoring condition-map routes in route table */
#define DEFAULT_CONDITIONAL_ROUTES_POLL_TIME 60
safi_t safi);
extern void bgp_conditional_adv_disable(struct peer *peer, afi_t afi,
safi_t safi);
+extern int peer_advertise_map_set(struct peer *peer, afi_t afi, safi_t safi,
+ const char *advertise_name,
+ struct route_map *advertise_map,
+ const char *condition_name,
+ struct route_map *condition_map,
+ bool condition);
+extern int peer_advertise_map_unset(struct peer *peer, afi_t afi, safi_t safi,
+ const char *advertise_name,
+ struct route_map *advertise_map,
+ const char *condition_name,
+ struct route_map *condition_map,
+ bool condition);
#ifdef __cplusplus
}
#endif
unsigned long conf_bgp_debug_graceful_restart;
unsigned long conf_bgp_debug_evpn_mh;
unsigned long conf_bgp_debug_bfd;
+unsigned long conf_bgp_debug_cond_adv;
unsigned long term_bgp_debug_as4;
unsigned long term_bgp_debug_neighbor_events;
unsigned long term_bgp_debug_graceful_restart;
unsigned long term_bgp_debug_evpn_mh;
unsigned long term_bgp_debug_bfd;
+unsigned long term_bgp_debug_cond_adv;
struct list *bgp_debug_neighbor_events_peers = NULL;
struct list *bgp_debug_keepalive_peers = NULL;
return CMD_SUCCESS;
}
+DEFPY (debug_bgp_cond_adv,
+ debug_bgp_cond_adv_cmd,
+ "[no$no] debug bgp conditional-advertisement",
+ NO_STR
+ DEBUG_STR
+ BGP_STR
+ "BGP conditional advertisement\n")
+{
+ if (vty->node == CONFIG_NODE) {
+ if (no)
+ DEBUG_OFF(cond_adv, COND_ADV);
+ else
+ DEBUG_ON(cond_adv, COND_ADV);
+ } else {
+ if (no) {
+ TERM_DEBUG_OFF(cond_adv, COND_ADV);
+ vty_out(vty,
+ "BGP conditional advertisement debugging is off\n");
+ } else {
+ TERM_DEBUG_ON(cond_adv, COND_ADV);
+ vty_out(vty,
+ "BGP conditional advertisement debugging is on\n");
+ }
+ }
+ return CMD_SUCCESS;
+}
+
DEFUN (no_debug_bgp,
no_debug_bgp_cmd,
"no debug bgp",
TERM_DEBUG_OFF(evpn_mh, EVPN_MH_ES);
TERM_DEBUG_OFF(evpn_mh, EVPN_MH_RT);
TERM_DEBUG_OFF(bfd, BFD_LIB);
+ TERM_DEBUG_OFF(cond_adv, COND_ADV);
vty_out(vty, "All possible debugging has been turned off\n");
if (BGP_DEBUG(bfd, BFD_LIB))
vty_out(vty, " BGP BFD library debugging is on\n");
+ if (BGP_DEBUG(cond_adv, COND_ADV))
+ vty_out(vty,
+ " BGP conditional advertisement debugging is on\n");
+
+ cmd_show_lib_debugs(vty);
+
return CMD_SUCCESS;
}
write++;
}
+ if (CONF_BGP_DEBUG(cond_adv, COND_ADV)) {
+ vty_out(vty, "debug bgp conditional-advertisement\n");
+ write++;
+ }
+
return write;
}
/* debug bgp bfd */
install_element(ENABLE_NODE, &debug_bgp_bfd_cmd);
install_element(CONFIG_NODE, &debug_bgp_bfd_cmd);
+
+ /* debug bgp conditional advertisement */
+ install_element(ENABLE_NODE, &debug_bgp_cond_adv_cmd);
+ install_element(CONFIG_NODE, &debug_bgp_cond_adv_cmd);
}
/* Return true if this prefix is on the per_prefix_list of prefixes to debug
struct bgp_route_evpn *overlay_index,
char *str, int size)
{
- char rd_buf[RD_ADDRSTRLEN];
char tag_buf[30];
char overlay_index_buf[INET6_ADDRSTRLEN + 14];
const struct prefix_evpn *evp;
}
if (prd)
- snprintfrr(str, size, "RD %s %pFX%s%s%s %s %s",
- prefix_rd2str(prd, rd_buf, sizeof(rd_buf)), pu.p,
+ snprintfrr(str, size, "RD %pRD %pFX%s%s%s %s %s", prd, pu.p,
overlay_index_buf, tag_buf, pathid_buf, afi2str(afi),
safi2str(safi));
else if (safi == SAFI_FLOWSPEC) {
extern unsigned long conf_bgp_debug_graceful_restart;
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 term_bgp_debug_as4;
extern unsigned long term_bgp_debug_neighbor_events;
extern unsigned long term_bgp_debug_graceful_restart;
extern unsigned long term_bgp_debug_evpn_mh;
extern unsigned long term_bgp_debug_bfd;
+extern unsigned long term_bgp_debug_cond_adv;
extern struct list *bgp_debug_neighbor_events_peers;
extern struct list *bgp_debug_keepalive_peers;
#define BGP_DEBUG_GRACEFUL_RESTART 0x01
#define BGP_DEBUG_BFD_LIB 0x01
+#define BGP_DEBUG_COND_ADV 0x01
#define CONF_DEBUG_ON(a, b) (conf_bgp_debug_ ## a |= (BGP_DEBUG_ ## b))
#define CONF_DEBUG_OFF(a, b) (conf_bgp_debug_ ## a &= ~(BGP_DEBUG_ ## b))
XFREE(MTYPE_ECOMMUNITY_VAL, ecom->val);
ecom->val = p;
} else
- ecom->val = NULL;
+ XFREE(MTYPE_ECOMMUNITY_VAL, ecom->val);
return true;
}
struct bgp_evpn_es *es)
{
json_object *json_frag;
- char buf1[RD_ADDRSTRLEN];
struct listnode *node;
struct bgp_evpn_es_frag *es_frag;
for (ALL_LIST_ELEMENTS_RO(es->es_frag_list, node, es_frag)) {
json_frag = json_object_new_object();
- json_object_string_add(
- json_frag, "rd",
- prefix_rd2str(&es_frag->prd, buf1, sizeof(buf1)));
+ json_object_string_addf(json_frag, "rd", "%pRD", &es_frag->prd);
json_object_int_add(json_frag, "eviCount",
listcount(es_frag->es_evi_frag_list));
struct bgp_evpn_es *es)
{
struct listnode *node;
- char buf1[RD_ADDRSTRLEN];
struct bgp_evpn_es_frag *es_frag;
for (ALL_LIST_ELEMENTS_RO(es->es_frag_list, node, es_frag)) {
- vty_out(vty, " %s EVIs: %d\n",
- prefix_rd2str(&es_frag->prd, buf1, sizeof(buf1)),
+ vty_out(vty, " %pRD EVIs: %d\n", &es_frag->prd,
listcount(es_frag->es_evi_frag_list));
}
}
static void bgp_evpn_es_show_entry(struct vty *vty,
struct bgp_evpn_es *es, json_object *json)
{
- char buf1[RD_ADDRSTRLEN];
struct listnode *node;
struct bgp_evpn_es_vtep *es_vtep;
json_object_string_add(json, "esi", es->esi_str);
if (es->es_base_frag)
- json_object_string_add(
- json, "rd",
- prefix_rd2str(&es->es_base_frag->prd, buf1,
- sizeof(buf1)));
+ json_object_string_addf(json, "rd", "%pRD",
+ &es->es_base_frag->prd);
if (es->flags & (BGP_EVPNES_LOCAL | BGP_EVPNES_REMOTE)) {
json_types = json_object_new_array();
bgp_evpn_es_vteps_str(vtep_str, es, sizeof(vtep_str));
- if (es->es_base_frag)
- prefix_rd2str(&es->es_base_frag->prd, buf1,
- sizeof(buf1));
- else
- strlcpy(buf1, "-", sizeof(buf1));
-
- vty_out(vty, "%-30s %-5s %-21s %-8d %s\n",
- es->esi_str, type_str, buf1,
- listcount(es->es_evi_list), vtep_str);
+ vty_out(vty, "%-30s %-5s %-21pRD %-8d %s\n", es->esi_str,
+ type_str, &es->es_base_frag->prd,
+ listcount(es->es_evi_list), vtep_str);
}
}
} else {
char incons_str[BGP_EVPNES_INCONS_STR_SZ];
char type_str[4];
- char buf1[RD_ADDRSTRLEN];
type_str[0] = '\0';
if (es->flags & BGP_EVPNES_LOCAL)
if (es->flags & BGP_EVPNES_REMOTE)
strlcat(type_str, "R", sizeof(type_str));
- if (es->es_base_frag)
- prefix_rd2str(&es->es_base_frag->prd, buf1,
- sizeof(buf1));
- else
- strlcpy(buf1, "-", sizeof(buf1));
-
vty_out(vty, "ESI: %s\n", es->esi_str);
vty_out(vty, " Type: %s\n", type_str);
- vty_out(vty, " RD: %s\n", buf1);
+ vty_out(vty, " RD: %pRD\n", &es->es_base_frag->prd);
vty_out(vty, " Originator-IP: %pI4\n", &es->originator_ip);
if (es->flags & BGP_EVPNES_LOCAL)
vty_out(vty, " Local ES DF preference: %u\n",
static void bgp_evpn_es_evi_show_entry_detail(struct vty *vty,
struct bgp_evpn_es_evi *es_evi, json_object *json)
{
- char buf1[RD_ADDRSTRLEN];
-
if (json) {
json_object *json_flags;
/* Add the "brief" info first */
bgp_evpn_es_evi_show_entry(vty, es_evi, json);
if (es_evi->es_frag)
- json_object_string_add(
- json, "esFragmentRd",
- prefix_rd2str(&es_evi->es_frag->prd, buf1,
- sizeof(buf1)));
+ json_object_string_addf(json, "esFragmentRd", "%pRD",
+ &es_evi->es_frag->prd);
if (es_evi->flags & BGP_EVPNES_EVI_INCONS_VTEP_LIST) {
json_flags = json_object_new_array();
json_array_string_add(json_flags, "es-vtep-mismatch");
es_evi->vpn->vni, es_evi->es->esi_str);
vty_out(vty, " Type: %s\n", type_str);
if (es_evi->es_frag)
- vty_out(vty, " ES fragment RD: %s\n",
- prefix_rd2str(&es_evi->es_frag->prd, buf1,
- sizeof(buf1)));
+ vty_out(vty, " ES fragment RD: %pRD\n",
+ &es_evi->es_frag->prd);
vty_out(vty, " Inconsistencies: %s\n",
(es_evi->flags & BGP_EVPNES_EVI_INCONS_VTEP_LIST) ?
"es-vtep-mismatch":"-");
json_object_int_add(json, "vni", bgp_vrf->l3vni);
json_object_string_add(json, "type", "L3");
json_object_string_add(json, "inKernel", "True");
- json_object_string_add(
- json, "rd",
- prefix_rd2str(&bgp_vrf->vrf_prd, buf1, RD_ADDRSTRLEN));
+ json_object_string_addf(json, "rd", "%pRD", &bgp_vrf->vrf_prd);
json_object_string_addf(json, "originatorIp", "%pI4",
&bgp_vrf->originator_ip);
json_object_string_add(json, "advertiseGatewayMacip", "n/a");
vty_out(vty, " Type: %s\n", "L3");
vty_out(vty, " Tenant VRF: %s\n",
vrf_id_to_name(bgp_vrf->vrf_id));
- vty_out(vty, " RD: %s\n",
- prefix_rd2str(&bgp_vrf->vrf_prd, buf1, RD_ADDRSTRLEN));
+ vty_out(vty, " RD: %pRD\n", &bgp_vrf->vrf_prd);
vty_out(vty, " Originator IP: %pI4\n",
&bgp_vrf->originator_ip);
vty_out(vty, " Advertise-gw-macip : %s\n", "n/a");
static void display_vni(struct vty *vty, struct bgpevpn *vpn, json_object *json)
{
- char buf1[RD_ADDRSTRLEN];
char *ecom_str;
struct listnode *node, *nnode;
struct ecommunity *ecom;
json_object_string_add(json, "type", "L2");
json_object_string_add(json, "inKernel",
is_vni_live(vpn) ? "True" : "False");
- json_object_string_add(
- json, "rd",
- prefix_rd2str(&vpn->prd, buf1, sizeof(buf1)));
+ json_object_string_addf(json, "rd", "%pRD", &vpn->prd);
json_object_string_addf(json, "originatorIp", "%pI4",
&vpn->originator_ip);
json_object_string_addf(json, "mcastGroup", "%pI4",
vty_out(vty, " Type: %s\n", "L2");
vty_out(vty, " Tenant-Vrf: %s\n",
vrf_id_to_name(vpn->tenant_vrf_id));
- vty_out(vty, " RD: %s\n",
- prefix_rd2str(&vpn->prd, buf1, sizeof(buf1)));
+ vty_out(vty, " RD: %pRD\n", &vpn->prd);
vty_out(vty, " Originator IP: %pI4\n", &vpn->originator_ip);
vty_out(vty, " Mcast group: %pI4\n", &vpn->mcast_grp);
if (!vpn->advertise_gw_macip &&
json_object_string_add(json_vni, "inKernel", "True");
json_object_string_addf(json_vni, "originatorIp", "%pI4",
&bgp->originator_ip);
- json_object_string_add(
- json_vni, "rd",
- prefix_rd2str(&bgp->vrf_prd, buf2, RD_ADDRSTRLEN));
+ json_object_string_addf(json_vni, "rd", "%pRD", &bgp->vrf_prd);
json_object_string_add(json_vni, "advertiseGatewayMacip",
"n/a");
json_object_string_add(json_vni, "advertiseSviMacIp", "n/a");
json_vni, "rmac",
prefix_mac2str(&bgp->rmac, buf2, sizeof(buf2)));
} else {
- vty_out(vty, "%-1s %-10u %-4s %-21s", buf1, bgp->l3vni, "L3",
- prefix_rd2str(&bgp->vrf_prd, buf2, RD_ADDRSTRLEN));
+ vty_out(vty, "%-1s %-10u %-4s %-21pRD", buf1, bgp->l3vni, "L3",
+ &bgp->vrf_prd);
}
for (ALL_LIST_ELEMENTS(bgp->vrf_import_rtl, node, nnode, ecom)) {
json_object *json_export_rtl = NULL;
struct bgpevpn *vpn = (struct bgpevpn *)bucket->data;
char buf1[10];
- char buf2[RD_ADDRSTRLEN];
char rt_buf[25];
char *ecom_str;
struct listnode *node, *nnode;
json_object_string_add(json_vni, "type", "L2");
json_object_string_add(json_vni, "inKernel",
is_vni_live(vpn) ? "True" : "False");
- json_object_string_add(
- json_vni, "rd",
- prefix_rd2str(&vpn->prd, buf2, sizeof(buf2)));
+ json_object_string_addf(json_vni, "rd", "%pRD", &vpn->prd);
json_object_string_addf(json_vni, "originatorIp", "%pI4",
&vpn->originator_ip);
json_object_string_addf(json_vni, "mcastGroup", "%pI4",
json_object_string_add(json_vni, "advertiseSviMacIp",
"Disabled");
} else {
- vty_out(vty, "%-1s %-10u %-4s %-21s", buf1, vpn->vni, "L2",
- prefix_rd2str(&vpn->prd, buf2, RD_ADDRSTRLEN));
+ vty_out(vty, "%-1s %-10u %-4s %-21pRD", buf1, vpn->vni, "L2",
+ &vpn->prd);
}
for (ALL_LIST_ELEMENTS(vpn->import_rtl, node, nnode, ecom)) {
afi_t afi;
safi_t safi;
uint32_t prefix_cnt, path_cnt;
- char rd_str[RD_ADDRSTRLEN];
json_object *json_rd = NULL;
int add_rd_to_json = 0;
safi = SAFI_EVPN;
prefix_cnt = path_cnt = 0;
- prefix_rd2str(prd, rd_str, sizeof(rd_str));
-
rd_dest = bgp_node_lookup(bgp->rib[afi][safi], (struct prefix *)prd);
if (!rd_dest)
return;
if (json) {
json_rd = json_object_new_object();
- json_object_string_add(json_rd, "rd", rd_str);
+ json_object_string_addf(json_rd, "rd", "%pRD", prd);
}
bgp_dest_unlock_node(rd_dest);
if (json) {
if (add_rd_to_json)
- json_object_object_add(json, rd_str, json_rd);
+ json_object_object_addf(json, json_rd, "%pRD", prd);
else {
json_object_free(json_rd);
json_rd = NULL;
static void write_vni_config(struct vty *vty, struct bgpevpn *vpn)
{
- char buf1[RD_ADDRSTRLEN];
char *ecom_str;
struct listnode *node, *nnode;
struct ecommunity *ecom;
if (is_vni_configured(vpn)) {
vty_out(vty, " vni %d\n", vpn->vni);
if (is_rd_configured(vpn))
- vty_out(vty, " rd %s\n",
- prefix_rd2str(&vpn->prd, buf1, sizeof(buf1)));
+ vty_out(vty, " rd %pRD\n", &vpn->prd);
if (is_import_rt_configured(vpn)) {
for (ALL_LIST_ELEMENTS(vpn->import_rtl, node, nnode,
JSON_STR)
{
char buf[ETHER_ADDR_STRLEN];
- char buf1[INET6_ADDRSTRLEN];
int idx_vrf = 3;
const char *name = NULL;
struct bgp *bgp = NULL;
for (ALL_LIST_ELEMENTS_RO(bgp->vrf_import_rtl, node, ecom))
vty_out(vty, "%s ", ecommunity_str(ecom));
vty_out(vty, "\n");
- vty_out(vty, " RD: %s\n",
- prefix_rd2str(&bgp->vrf_prd, buf1, RD_ADDRSTRLEN));
+ vty_out(vty, " RD: %pRD\n", &bgp->vrf_prd);
} else {
json_object_string_add(json, "vrf", name);
json_object_string_addf(json, "local-ip", "%pI4",
json_import_rts,
json_object_new_string(ecommunity_str(ecom)));
json_object_object_add(json, "import-rts", json_import_rts);
- json_object_string_add(
- json, "rd",
- prefix_rd2str(&bgp->vrf_prd, buf1, RD_ADDRSTRLEN));
+ json_object_string_addf(json, "rd", "%pRD", &bgp->vrf_prd);
}
if (uj)
if (!bgp_evpn_rt_matches_existing(bgp_mh_info->ead_es_export_rtl,
ecomdel)) {
+ ecommunity_free(&ecomdel);
vty_out(vty,
"%% RT specified does not match EAD-ES RT configuration\n");
return CMD_WARNING;
if (rt_type == RT_TYPE_IMPORT) {
if (!bgp_evpn_rt_matches_existing(vpn->import_rtl, ecomdel)) {
+ ecommunity_free(&ecomdel);
vty_out(vty,
"%% RT specified does not match configuration for this VNI\n");
return CMD_WARNING;
evpn_unconfigure_import_rt(bgp, vpn, ecomdel);
} else if (rt_type == RT_TYPE_EXPORT) {
if (!bgp_evpn_rt_matches_existing(vpn->export_rtl, ecomdel)) {
+ ecommunity_free(&ecomdel);
vty_out(vty,
"%% RT specified does not match configuration for this VNI\n");
return CMD_WARNING;
}
if (!found_ecomdel) {
+ ecommunity_free(&ecomdel);
vty_out(vty,
"%% RT specified does not match configuration for this VNI\n");
return CMD_WARNING;
void bgp_config_write_evpn_info(struct vty *vty, struct bgp *bgp, afi_t afi,
safi_t safi)
{
- char buf1[RD_ADDRSTRLEN];
char buf2[INET6_ADDRSTRLEN];
if (bgp->advertise_all_vni)
}
}
if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_RD_CFGD))
- vty_out(vty, " rd %s\n",
- prefix_rd2str(&bgp->vrf_prd, buf1, sizeof(buf1)));
+ vty_out(vty, " rd %pRD\n", &bgp->vrf_prd);
/* import route-target */
if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_IMPORT_RT_CFGD)) {
/* There is no pending EOR message */
if (gr_info->eor_required == 0) {
+ if (gr_info->t_select_deferral) {
+ void *info = THREAD_ARG(
+ gr_info->t_select_deferral);
+ XFREE(MTYPE_TMP, info);
+ }
THREAD_OFF(gr_info->t_select_deferral);
gr_info->eor_received = 0;
}
bgp->vpn_policy[afi].tovpn_rd = bgp->vrf_prd_auto;
prefix_rd2str(&bgp->vpn_policy[afi].tovpn_rd, buf,
sizeof(buf));
- bgp->vpn_policy[afi].rtlist[edir] =
- ecommunity_str2com(buf,
- ECOMMUNITY_ROUTE_TARGET, 0);
+
+ /* free up pre-existing memory if any and allocate
+ * the ecommunity attribute with new RD/RT
+ */
+ if (bgp->vpn_policy[afi].rtlist[edir])
+ ecommunity_free(
+ &bgp->vpn_policy[afi].rtlist[edir]);
+ bgp->vpn_policy[afi].rtlist[edir] = ecommunity_str2com(
+ buf, ECOMMUNITY_ROUTE_TARGET, 0);
/* Update import_vrf rt_list */
ecom = bgp->vpn_policy[afi].rtlist[edir];
return bgp_md5_set_password(peer, peer->password);
}
+static void bgp_update_setsockopt_tcp_keepalive(struct bgp *bgp, int fd)
+{
+ if (!bgp)
+ return;
+ if (bgp->tcp_keepalive_idle != 0) {
+ int ret;
+
+ ret = setsockopt_tcp_keepalive(fd, bgp->tcp_keepalive_idle,
+ bgp->tcp_keepalive_intvl,
+ bgp->tcp_keepalive_probes);
+ if (ret < 0)
+ zlog_err(
+ "Can't set TCP keepalive on socket %d, idle %u intvl %u probes %u",
+ fd, bgp->tcp_keepalive_idle,
+ bgp->tcp_keepalive_intvl,
+ bgp->tcp_keepalive_probes);
+ }
+}
+
int bgp_md5_unset(struct peer *peer)
{
/* Unset the password from listen socket. */
bgp_socket_set_buffer_size(bgp_sock);
+ /* Set TCP keepalive when TCP keepalive is enabled */
+ bgp_update_setsockopt_tcp_keepalive(bgp, bgp_sock);
+
/* Check remote IP address */
peer1 = peer_lookup(bgp, &su);
bgp_socket_set_buffer_size(peer->fd);
+ /* Set TCP keepalive when TCP keepalive is enabled */
+ bgp_update_setsockopt_tcp_keepalive(peer->bgp, peer->fd);
+
if (bgp_set_socket_ttl(peer, peer->fd) < 0) {
peer->last_reset = PEER_DOWN_SOCKET_ERROR;
if (bgp_debug_neighbor_events(peer))
zlog_debug("%s: Failure to set socket ttl for connection to %s, error received: %s(%d)",
__func__, peer->host, safe_strerror(errno),
errno);
+
return -1;
}
safi_t safi;
struct bgp_table *table;
struct bgp *bgp_path;
- char buf1[BUFSIZ];
vty_out(vty, " Paths:\n");
LIST_FOREACH (path, &(bnc->paths), nh_thread) {
safi = table->safi;
bgp_path = table->bgp;
- if (dest->pdest) {
- prefix_rd2str((struct prefix_rd *)bgp_dest_get_prefix(dest->pdest),
- buf1, sizeof(buf1));
- vty_out(vty, " %d/%d %pBD RD %s %s flags 0x%x\n",
- afi, safi, dest, buf1, bgp_path->name_pretty, path->flags);
- } else
+ if (dest->pdest)
+ vty_out(vty, " %d/%d %pBD RD %pRD %s flags 0x%x\n",
+ afi, safi, dest,
+ (struct prefix_rd *)bgp_dest_get_prefix(
+ dest->pdest),
+ bgp_path->name_pretty, path->flags);
+ else
vty_out(vty, " %d/%d %pBD %s flags 0x%x\n",
afi, safi, dest, bgp_path->name_pretty, path->flags);
}
}
tbuf = time(NULL) - (monotime(NULL) - bnc->last_update);
vty_out(vty, " Last update: %s", ctime(&tbuf));
- vty_out(vty, "\n");
/* show paths dependent on nexthop, if needed. */
if (specific)
struct prefix nhop;
struct bgp_nexthop_cache_head (*tree)[AFI_MAX];
struct bgp_nexthop_cache *bnc;
+ bool found = false;
if (!str2prefix(nhopip_str, &nhop)) {
vty_out(vty, "nexthop address is malformed\n");
}
tree = import_table ? &bgp->import_check_table
: &bgp->nexthop_cache_table;
- bnc = bnc_find(tree[family2afi(nhop.family)], &nhop, 0, 0);
- if (!bnc) {
- vty_out(vty, "specified nexthop does not have entry\n");
- return CMD_SUCCESS;
+ frr_each (bgp_nexthop_cache, &(*tree)[family2afi(nhop.family)],
+ bnc) {
+ if (prefix_cmp(&bnc->prefix, &nhop))
+ continue;
+ bgp_show_nexthop(vty, bgp, bnc, true);
+ found = true;
}
- bgp_show_nexthop(vty, bgp, bnc, true);
+ if (!found)
+ vty_out(vty, "nexthop %s does not have entry\n",
+ nhopip_str);
} else
bgp_show_nexthops(vty, bgp, import_table);
}
if (BGP_DEBUG(nht, NHT)) {
- char buf1[RD_ADDRSTRLEN];
-
- if (dest->pdest) {
- prefix_rd2str((struct prefix_rd *)bgp_dest_get_prefix(dest->pdest),
- buf1, sizeof(buf1));
+ if (dest->pdest)
zlog_debug(
- "... eval path %d/%d %pBD RD %s %s flags 0x%x",
- afi, safi, dest, buf1,
+ "... eval path %d/%d %pBD RD %pRD %s flags 0x%x",
+ afi, safi, dest,
+ (struct prefix_rd *)bgp_dest_get_prefix(
+ dest->pdest),
bgp_path->name_pretty, path->flags);
- } else
+ else
zlog_debug(
"... eval path %d/%d %pBD %s flags 0x%x",
afi, safi, dest, bgp_path->name_pretty,
uint8_t opt_type;
uint16_t opt_length;
- /* Check the length. */
- if (stream_get_getp(s) + 2 > end)
+ /* Ensure we can read the option type */
+ if (stream_get_getp(s) + 1 > end)
goto end;
- /* Fetch option type and length. */
+ /* Fetch the option type */
opt_type = stream_getc(s);
- opt_length = BGP_OPEN_EXT_OPT_PARAMS_CAPABLE(peer)
- ? stream_getw(s)
- : stream_getc(s);
+
+ /*
+ * Check the length and fetch the opt_length
+ * If the peer is BGP_OPEN_EXT_OPT_PARAMS_CAPABLE(peer)
+ * then we do a getw which is 2 bytes. So we need to
+ * ensure that we can read that as well
+ */
+ if (BGP_OPEN_EXT_OPT_PARAMS_CAPABLE(peer)) {
+ if (stream_get_getp(s) + 2 > end)
+ goto end;
+
+ opt_length = stream_getw(s);
+ } else {
+ if (stream_get_getp(s) + 1 > end)
+ goto end;
+
+ opt_length = stream_getc(s);
+ }
/* Option length check. */
if (stream_get_getp(s) + opt_length > end)
uint8_t opt_type;
uint16_t opt_length;
- /* Must have at least an OPEN option header */
- if (STREAM_READABLE(s) < 2) {
+ /*
+ * Check that we can read the opt_type and fetch it
+ */
+ if (STREAM_READABLE(s) < 1) {
zlog_info("%s Option length error", peer->host);
bgp_notify_send(peer, BGP_NOTIFY_OPEN_ERR,
BGP_NOTIFY_OPEN_MALFORMED_ATTR);
return -1;
}
-
- /* Fetch option type and length. */
opt_type = stream_getc(s);
- opt_length = BGP_OPEN_EXT_OPT_PARAMS_CAPABLE(peer)
- ? stream_getw(s)
- : stream_getc(s);
+
+ /*
+ * Check the length of the stream to ensure that
+ * FRR can properly read the opt_length. Then read it
+ */
+ if (BGP_OPEN_EXT_OPT_PARAMS_CAPABLE(peer)) {
+ if (STREAM_READABLE(s) < 2) {
+ zlog_info("%s Option length error", peer->host);
+ bgp_notify_send(peer, BGP_NOTIFY_OPEN_ERR,
+ BGP_NOTIFY_OPEN_MALFORMED_ATTR);
+ return -1;
+ }
+
+ opt_length = stream_getw(s);
+ } else {
+ if (STREAM_READABLE(s) < 1) {
+ zlog_info("%s Option length error", peer->host);
+ bgp_notify_send(peer, BGP_NOTIFY_OPEN_ERR,
+ BGP_NOTIFY_OPEN_MALFORMED_ATTR);
+ return -1;
+ }
+
+ opt_length = stream_getc(s);
+ }
/* Option length check. */
if (STREAM_READABLE(s) < opt_length) {
return BGP_NLRI_PARSE_ERROR;
}
+
+/*
+ * Check if route-refresh request from peer is pending (received before EoR),
+ * and process it now.
+ */
+static void bgp_process_pending_refresh(struct peer *peer, afi_t afi,
+ safi_t safi)
+{
+ if (CHECK_FLAG(peer->af_sflags[afi][safi],
+ PEER_STATUS_REFRESH_PENDING)) {
+ UNSET_FLAG(peer->af_sflags[afi][safi],
+ PEER_STATUS_REFRESH_PENDING);
+ bgp_route_refresh_send(peer, afi, safi, 0, 0, 0,
+ BGP_ROUTE_REFRESH_BORR);
+ if (bgp_debug_neighbor_events(peer))
+ zlog_debug(
+ "%pBP sending route-refresh (BoRR) for %s/%s (for pending REQUEST)",
+ peer, afi2str(afi), safi2str(safi));
+
+ SET_FLAG(peer->af_sflags[afi][safi], PEER_STATUS_BORR_SEND);
+ UNSET_FLAG(peer->af_sflags[afi][safi], PEER_STATUS_EORR_SEND);
+ bgp_announce_route(peer, afi, safi, true);
+ }
+}
+
/*
* Checks a variety of conditions to determine whether the peer needs to be
* rescheduled for packet generation again, and does so if necessary.
BGP_UPDATE_EOR_PKT(
peer, afi, safi,
s);
+ bgp_process_pending_refresh(
+ peer, afi,
+ safi);
}
}
}
gr_info->eor_required,
"EOR RCV",
gr_info->eor_received);
+ if (gr_info->t_select_deferral) {
+ void *info = THREAD_ARG(
+ gr_info->t_select_deferral);
+ XFREE(MTYPE_TMP, info);
+ }
THREAD_OFF(gr_info->t_select_deferral);
gr_info->eor_required = 0;
gr_info->eor_received = 0;
"%pBP rcvd route-refresh (REQUEST) for %s/%s before EoR",
peer, afi2str(afi),
safi2str(safi));
+ /* Can't send BoRR now, postpone after EoR */
+ SET_FLAG(peer->af_sflags[afi][safi],
+ PEER_STATUS_REFRESH_PENDING);
return BGP_PACKET_NOOP;
}
snprintfrr(buf, sizeof(buf), "%pI4:%hu", &router_id, rd_id);
(void)str2prefix_rd(buf, prd);
}
+
+printfrr_ext_autoreg_p("RD", printfrr_prd);
+static ssize_t printfrr_prd(struct fbuf *buf, struct printfrr_eargs *ea,
+ const void *ptr)
+{
+ char rd_buf[RD_ADDRSTRLEN];
+
+ if (!ptr)
+ return bputs(buf, "(null)");
+
+ prefix_rd2str(ptr, rd_buf, sizeof(rd_buf));
+
+ return bputs(buf, rd_buf);
+}
int do_loop_check = 1;
int has_valid_label = 0;
afi_t nh_afi;
- uint8_t pi_type = 0;
- uint8_t pi_sub_type = 0;
bool force_evpn_import = false;
safi_t orig_safi = safi;
bool leak_success = true;
bgp_attr_add_gshut_community(&new_attr);
}
- if (pi) {
- pi_type = pi->type;
- pi_sub_type = pi->sub_type;
- }
-
/* next hop check. */
- if (!CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD)
- && bgp_update_martian_nexthop(bgp, afi, safi, pi_type, pi_sub_type,
- &new_attr, dest)) {
+ if (!CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD) &&
+ bgp_update_martian_nexthop(bgp, afi, safi, type, sub_type,
+ &new_attr, dest)) {
peer->stat_pfx_nh_invalid++;
reason = "martian or self next-hop;";
bgp_attr_flush(&new_attr);
if (bgp_debug_neighbor_events(
peer))
zlog_debug(
- "%s: route-refresh for %s/%s, marking prefix %pFX as stale",
- peer->host,
+ "%pBP route-refresh for %s/%s, marking prefix %pFX as stale",
+ peer,
afi2str(afi),
safi2str(safi),
bgp_dest_get_prefix(
BGP_PATH_UNUSEABLE)) {
if (bgp_debug_neighbor_events(peer))
zlog_debug(
- "%s: route-refresh for %s/%s, marking prefix %pFX as stale",
- peer->host,
- afi2str(afi),
+ "%pBP route-refresh for %s/%s, marking prefix %pFX as stale",
+ peer, afi2str(afi),
safi2str(safi),
bgp_dest_get_prefix(
dest));
/* Unintern original. */
aspath_unintern(&attr.aspath);
bgp_static_withdraw(bgp, p, afi, safi);
+ bgp_dest_unlock_node(dest);
return;
}
aspath_unintern(&attr.aspath);
bgp_static_withdraw_safi(bgp, p, afi, safi,
&bgp_static->prd);
+ bgp_dest_unlock_node(dest);
return;
}
dest = parent_ri->net;
if (dest && dest->pdest) {
pdest = dest->pdest;
- prefix_rd2str(
- (struct prefix_rd *)bgp_dest_get_prefix(
- pdest),
- buf1, sizeof(buf1));
if (is_pi_family_evpn(parent_ri)) {
vty_out(vty,
- " Imported from %s:%pFX, VNI %s",
- buf1,
+ " Imported from %pRD:%pFX, VNI %s",
+ (struct prefix_rd *)
+ bgp_dest_get_prefix(
+ pdest),
(struct prefix_evpn *)
bgp_dest_get_prefix(
dest),
} else
vty_out(vty,
- " Imported from %s:%pFX\n",
- buf1,
+ " Imported from %pRD:%pFX\n",
+ (struct prefix_rd *)
+ bgp_dest_get_prefix(
+ pdest),
(struct prefix_evpn *)
bgp_dest_get_prefix(
dest));
/* Display the IGP cost or 'inaccessible' */
if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
- if (json_paths)
+ bool import = CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK);
+
+ if (json_paths) {
json_object_boolean_false_add(json_nexthop_global,
"accessible");
- else
- vty_out(vty, " (inaccessible)");
+ json_object_boolean_add(json_nexthop_global,
+ "importCheckEnabled", import);
+ } else {
+ vty_out(vty, " (inaccessible%s)",
+ import ? ", import-check enabled" : "");
+ }
} else {
if (path->extra && path->extra->igpmetric) {
if (json_paths)
{
struct bgp_path_info *pi;
int header = 1;
- char rdbuf[RD_ADDRSTRLEN];
json_object *json_header = NULL;
json_object *json_paths = NULL;
const struct prefix *p = bgp_dest_get_prefix(bgp_node);
if (json && !json_paths) {
/* Instantiate json_paths only if path is valid */
json_paths = json_object_new_array();
- if (pfx_rd) {
- prefix_rd2str(pfx_rd, rdbuf, sizeof(rdbuf));
+ if (pfx_rd)
json_header = json_object_new_object();
- } else
+ else
json_header = json;
}
json_object_object_add(json_header, "paths", json_paths);
if (pfx_rd)
- json_object_object_add(json, rdbuf, json_header);
+ json_object_object_addf(json, json_header, "%pRD",
+ pfx_rd);
}
}
return CMD_WARNING;
if (argv_find(argv, argc, "AA:BB:CC", &idx)) {
- if (argv_find(argv, argc, "exact-match", &idx))
+ if (argv_find(argv, argc, "exact-match", &idx)) {
+ argc--;
exact_match = 1;
+ }
return bgp_show_lcommunity(vty, bgp, argc, argv,
exact_match, afi, safi, uj);
} else
const struct prefix_rd *prd;
struct bgp_static *bgp_static;
mpls_label_t label;
- char rdbuf[RD_ADDRSTRLEN];
/* Network configuration. */
for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
pdest);
/* "network" configuration display. */
- prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
label = decode_label(&bgp_static->label);
- vty_out(vty, " network %pFX rd %s", p, rdbuf);
+ vty_out(vty, " network %pFX rd %pRD", p, prd);
if (safi == SAFI_MPLS_VPN)
vty_out(vty, " label %u", label);
struct bgp_static *bgp_static;
char buf[PREFIX_STRLEN * 2];
char buf2[SU_ADDRSTRLEN];
- char rdbuf[RD_ADDRSTRLEN];
char esi_buf[ESI_STR_LEN];
/* Network configuration. */
prd = (struct prefix_rd *)bgp_dest_get_prefix(pdest);
/* "network" configuration display. */
- prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
if (p->u.prefix_evpn.route_type == 5) {
char local_buf[PREFIX_STRLEN];
uint8_t family = is_evpn_prefix_ipaddr_v4((
&bgp_static->gatewayIp.u.prefix, buf2,
sizeof(buf2));
vty_out(vty,
- " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
- buf, rdbuf,
- p->u.prefix_evpn.prefix_addr.eth_tag,
+ " network %s rd %pRD ethtag %u label %u esi %s gwip %s routermac %s\n",
+ buf, prd, p->u.prefix_evpn.prefix_addr.eth_tag,
decode_label(&bgp_static->label), esi_buf, buf2,
macrouter);
hook_register(bgp_rpki_prefix_status, rpki_validate_prefix);
hook_register(frr_late_init, bgp_rpki_init);
- hook_register(frr_early_fini, &bgp_rpki_fini);
+ hook_register(frr_early_fini, bgp_rpki_fini);
return 0;
}
const char *xpath =
"./match-condition[condition='frr-bgp-route-map:rpki']";
- nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
+ nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
return nb_cli_apply_changes(vty, NULL);
}
struct srv6_locator_chunk *chunk, *tovpn_sid_locator;
struct bgp_srv6_function *func;
struct bgp *bgp_vrf;
- struct in6_addr *tovpn_sid;
/* release chunk notification via ZAPI */
ret = bgp_zebra_srv6_manager_release_locator_chunk(
continue;
/* refresh vpnv4 tovpn_sid */
- tovpn_sid = bgp_vrf->vpn_policy[AFI_IP].tovpn_sid;
- if (tovpn_sid)
- XFREE(MTYPE_BGP_SRV6_SID,
- bgp_vrf->vpn_policy[AFI_IP].tovpn_sid);
+ XFREE(MTYPE_BGP_SRV6_SID,
+ bgp_vrf->vpn_policy[AFI_IP].tovpn_sid);
/* refresh vpnv6 tovpn_sid */
- tovpn_sid = bgp_vrf->vpn_policy[AFI_IP6].tovpn_sid;
- if (tovpn_sid)
- XFREE(MTYPE_BGP_SRV6_SID,
- bgp_vrf->vpn_policy[AFI_IP6].tovpn_sid);
+ XFREE(MTYPE_BGP_SRV6_SID,
+ bgp_vrf->vpn_policy[AFI_IP6].tovpn_sid);
}
/* update vpn bgp processes */
case BGP_ERR_REMOVE_PRIVATE_AS:
str = "remove-private-AS cannot be configured for IBGP peers";
break;
- case BGP_ERR_LOCAL_AS_ALLOWED_ONLY_FOR_EBGP:
- str = "Local-AS allowed only for EBGP peers";
- break;
case BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS:
str = "Cannot have local-as same as BGP AS number";
break;
case BGP_ERR_AF_UNCONFIGURED:
str = "AFI/SAFI specified is not currently configured.";
break;
- case BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS_REMOTE_AS:
- str = "AS specified for local as is the same as the remote as and this is not allowed.";
- break;
case BGP_ERR_INVALID_AS:
str = "Confederation AS specified is the same AS as our AS.";
break;
vty_out(vty, " coalesce-time %u\n", bgp->coalesce_time);
}
+/* BGP TCP keepalive */
+static void bgp_config_tcp_keepalive(struct vty *vty, struct bgp *bgp)
+{
+ if (bgp->tcp_keepalive_idle) {
+ vty_out(vty, " bgp tcp-keepalive %u %u %u\n",
+ bgp->tcp_keepalive_idle, bgp->tcp_keepalive_intvl,
+ bgp->tcp_keepalive_probes);
+ }
+}
DEFUN (bgp_coalesce_time,
bgp_coalesce_time_cmd,
return CMD_SUCCESS;
}
+DEFPY(bgp_tcp_keepalive, bgp_tcp_keepalive_cmd,
+ "bgp tcp-keepalive (1-65535)$idle (1-65535)$intvl (1-30)$probes",
+ BGP_STR
+ "TCP keepalive parameters\n"
+ "TCP keepalive idle time (seconds)\n"
+ "TCP keepalive interval (seconds)\n"
+ "TCP keepalive maximum probes\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+
+ bgp_tcp_keepalive_set(bgp, (uint16_t)idle, (uint16_t)intvl,
+ (uint16_t)probes);
+
+ return CMD_SUCCESS;
+}
+
+DEFPY(no_bgp_tcp_keepalive, no_bgp_tcp_keepalive_cmd,
+ "no bgp tcp-keepalive [(1-65535) (1-65535) (1-30)]",
+ NO_STR
+ BGP_STR
+ "TCP keepalive parameters\n"
+ "TCP keepalive idle time (seconds)\n"
+ "TCP keepalive interval (seconds)\n"
+ "TCP keepalive maximum probes\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+
+ bgp_tcp_keepalive_unset(bgp);
+
+ return CMD_SUCCESS;
+}
+
DEFUN (bgp_client_to_client_reflection,
bgp_client_to_client_reflection_cmd,
"bgp client-to-client reflection",
struct listnode *node;
struct srv6_locator_chunk *chunk;
struct bgp_srv6_function *func;
- struct in6_addr *tovpn4_sid;
- struct in6_addr *tovpn6_sid;
char buf[256];
- char buf_tovpn4_sid[256];
- char buf_tovpn6_sid[256];
bgp = bgp_get_default();
if (!bgp)
vty_out(vty, "- name: %s\n",
bgp->name ? bgp->name : "default");
- tovpn4_sid = bgp->vpn_policy[AFI_IP].tovpn_sid;
- tovpn6_sid = bgp->vpn_policy[AFI_IP6].tovpn_sid;
- if (tovpn4_sid)
- inet_ntop(AF_INET6, tovpn4_sid, buf_tovpn4_sid,
- sizeof(buf_tovpn4_sid));
- if (tovpn6_sid)
- inet_ntop(AF_INET6, tovpn6_sid, buf_tovpn6_sid,
- sizeof(buf_tovpn6_sid));
-
- vty_out(vty, " vpn_policy[AFI_IP].tovpn_sid: %s\n",
- tovpn4_sid ? buf_tovpn4_sid : "none");
- vty_out(vty, " vpn_policy[AFI_IP6].tovpn_sid: %s\n",
- tovpn6_sid ? buf_tovpn6_sid : "none");
+ vty_out(vty, " vpn_policy[AFI_IP].tovpn_sid: %pI6\n",
+ bgp->vpn_policy[AFI_IP].tovpn_sid);
+ vty_out(vty, " vpn_policy[AFI_IP6].tovpn_sid: %pI6\n",
+ bgp->vpn_policy[AFI_IP6].tovpn_sid);
}
return CMD_SUCCESS;
/* "show [ip] bgp neighbors graceful-restart" commands. */
-DEFUN (show_ip_bgp_neighbors_gracrful_restart,
+DEFUN (show_ip_bgp_neighbors_graceful_restart,
show_ip_bgp_neighbors_graceful_restart_cmd,
"show bgp [<ipv4|ipv6>] neighbors [<A.B.C.D|X:X::X:X|WORD>] graceful-restart [json]",
SHOW_STR
struct bgp *bgp;
struct listnode *node;
char *vname;
- char buf1[INET6_ADDRSTRLEN];
char *ecom_str;
enum vpn_policy_direction dir;
json_object_new_string(vname));
json_object_object_add(json, "exportToVrfs",
json_export_vrfs);
- json_object_string_add(json, "routeDistinguisher",
- prefix_rd2str(&bgp->vpn_policy[afi].tovpn_rd,
- buf1, RD_ADDRSTRLEN));
+ json_object_string_addf(json, "routeDistinguisher",
+ "%pRD",
+ &bgp->vpn_policy[afi].tovpn_rd);
dir = BGP_VPN_POLICY_DIR_TOVPN;
if (bgp->vpn_policy[afi].rtlist[dir]) {
node, vname))
vty_out(vty, " %s\n", vname);
- vty_out(vty, "RD: %s\n",
- prefix_rd2str(&bgp->vpn_policy[afi].tovpn_rd,
- buf1, RD_ADDRSTRLEN));
+ vty_out(vty, "RD: %pRD\n",
+ &bgp->vpn_policy[afi].tovpn_rd);
dir = BGP_VPN_POLICY_DIR_TOVPN;
if (bgp->vpn_policy[afi].rtlist[dir]) {
tovpn_sid_index);
}
- if (CHECK_FLAG(bgp->vpn_policy[afi].flags,
- BGP_VPN_POLICY_TOVPN_RD_SET)) {
- char buf[RD_ADDRSTRLEN];
- vty_out(vty, "%*srd vpn export %s\n", indent, "",
- prefix_rd2str(&bgp->vpn_policy[afi].tovpn_rd, buf,
- sizeof(buf)));
- }
+ if (CHECK_FLAG(bgp->vpn_policy[afi].flags, BGP_VPN_POLICY_TOVPN_RD_SET))
+ vty_out(vty, "%*srd vpn export %pRD\n", indent, "",
+ &bgp->vpn_policy[afi].tovpn_rd);
+
if (CHECK_FLAG(bgp->vpn_policy[afi].flags,
BGP_VPN_POLICY_TOVPN_NEXTHOP_SET)) {
vty_out(vty,
" bgp graceful-restart preserve-fw-state\n");
+ /* BGP TCP keepalive */
+ bgp_config_tcp_keepalive(vty, bgp);
+
/* Stale timer for RIB */
if (bgp->rib_stale_time != BGP_DEFAULT_RIB_STALE_TIME)
vty_out(vty,
install_element(BGP_NODE, &neighbor_ttl_security_cmd);
install_element(BGP_NODE, &no_neighbor_ttl_security_cmd);
+ /* "bgp tcp-keepalive" commands */
+ install_element(BGP_NODE, &bgp_tcp_keepalive_cmd);
+ install_element(BGP_NODE, &no_bgp_tcp_keepalive_cmd);
+
/* "show [ip] bgp memory" commands. */
install_element(VIEW_NODE, &show_bgp_memory_cmd);
{
struct connected *ifc;
struct bgp *bgp;
+ struct peer *peer;
+ struct prefix *addr;
+ struct listnode *node, *nnode;
+ afi_t afi;
+ safi_t safi;
bgp = bgp_lookup_by_vrf_id(vrf_id);
if (IN6_IS_ADDR_LINKLOCAL(&ifc->address->u.prefix6)
&& !list_isempty(ifc->ifp->nbr_connected))
bgp_start_interface_nbrs(bgp, ifc->ifp);
+ else {
+ addr = ifc->address;
+
+ for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
+ if (addr->family == AF_INET)
+ continue;
+
+ /*
+ * If the Peer's interface name matches the
+ * interface name for which BGP received the
+ * update and if the received interface address
+ * is a globalV6 and if the peer is currently
+ * using a v4-mapped-v6 addr or a link local
+ * address, then copy the Rxed global v6 addr
+ * into peer's v6_global and send updates out
+ * with new nexthop addr.
+ */
+ if ((peer->conf_if &&
+ (strcmp(peer->conf_if, ifc->ifp->name) ==
+ 0)) &&
+ !IN6_IS_ADDR_LINKLOCAL(&addr->u.prefix6) &&
+ ((IS_MAPPED_IPV6(
+ &peer->nexthop.v6_global)) ||
+ IN6_IS_ADDR_LINKLOCAL(
+ &peer->nexthop.v6_global))) {
+
+ if (bgp_debug_zebra(ifc->address)) {
+ zlog_debug(
+ "Update peer %pBP's current intf addr %pI6 and send updates",
+ peer,
+ &peer->nexthop
+ .v6_global);
+ }
+ memcpy(&peer->nexthop.v6_global,
+ &addr->u.prefix6,
+ IPV6_MAX_BYTELEN);
+ FOREACH_AFI_SAFI (afi, safi)
+ bgp_announce_route(peer, afi,
+ safi, true);
+ }
+ }
+ }
}
return 0;
bgp->default_delayopen = BGP_DEFAULT_DELAYOPEN;
}
+void bgp_tcp_keepalive_set(struct bgp *bgp, uint16_t keepalive_idle,
+ uint16_t keepalive_intvl, uint16_t keepalive_probes)
+{
+ bgp->tcp_keepalive_idle = keepalive_idle;
+ bgp->tcp_keepalive_intvl = keepalive_intvl;
+ bgp->tcp_keepalive_probes = keepalive_probes;
+}
+
+void bgp_tcp_keepalive_unset(struct bgp *bgp)
+{
+ bgp->tcp_keepalive_idle = 0;
+ bgp->tcp_keepalive_intvl = 0;
+ bgp->tcp_keepalive_probes = 0;
+}
+
/* BGP confederation configuration. */
void bgp_confederation_id_set(struct bgp *bgp, as_t as)
{
static inline enum bgp_peer_sort peer_calc_sort(struct peer *peer)
{
struct bgp *bgp;
+ as_t local_as;
bgp = peer->bgp;
+ if (peer->change_local_as)
+ local_as = peer->change_local_as;
+ else
+ local_as = peer->local_as;
+
/* Peer-group */
if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
if (peer->as_type == AS_INTERNAL)
else if (peer->as_type == AS_SPECIFIED && peer->as) {
assert(bgp);
- return (bgp->as == peer->as ? BGP_PEER_IBGP
- : BGP_PEER_EBGP);
+ return (local_as == peer->as ? BGP_PEER_IBGP
+ : BGP_PEER_EBGP);
}
else {
/* Normal peer */
if (bgp && CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
- if (peer->local_as == 0)
+ if (local_as == 0)
return BGP_PEER_INTERNAL;
- if (peer->local_as == peer->as) {
+ if (local_as == peer->as) {
if (bgp->as == bgp->confed_id) {
- if (peer->local_as == bgp->as)
+ if (local_as == bgp->as)
return BGP_PEER_IBGP;
else
return BGP_PEER_EBGP;
} else {
- if (peer->local_as == bgp->confed_id)
+ if (local_as == bgp->confed_id)
return BGP_PEER_EBGP;
else
return BGP_PEER_IBGP;
&& (peer->group->conf->as_type != AS_UNSPECIFIED)) {
if (peer->group->conf->as_type
== AS_SPECIFIED) {
- if (peer->local_as
- == peer->group->conf->as)
+ if (local_as == peer->group->conf->as)
return BGP_PEER_IBGP;
else
return BGP_PEER_EBGP;
return (peer->as_type == AS_INTERNAL ? BGP_PEER_IBGP
: BGP_PEER_EBGP);
- return (peer->local_as == 0
- ? BGP_PEER_INTERNAL
- : peer->local_as == peer->as ? BGP_PEER_IBGP
+ return (local_as == 0 ? BGP_PEER_INTERNAL
+ : local_as == peer->as ? BGP_PEER_IBGP
: BGP_PEER_EBGP);
}
}
UNSET_FLAG(peer->af_flags[AFI_L2VPN][SAFI_EVPN],
PEER_FLAG_REFLECTOR_CLIENT);
}
-
- /* local-as reset */
- if (newtype != BGP_PEER_EBGP) {
- peer->change_local_as = 0;
- peer_flag_unset(peer, PEER_FLAG_LOCAL_AS);
- peer_flag_unset(peer, PEER_FLAG_LOCAL_AS_NO_PREPEND);
- peer_flag_unset(peer, PEER_FLAG_LOCAL_AS_REPLACE_AS);
- }
}
/* If peer does not exist, create new one. If peer already exists,
UNSET_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT);
UNSET_FLAG(peer->sflags, PEER_STATUS_NSF_MODE);
- FOREACH_AFI_SAFI_NSF (afi, safi)
+ FOREACH_AFI_SAFI_NSF (afi, safi) {
peer->nsf[afi][safi] = 0;
+ THREAD_OFF(peer->t_llgr_stale[afi][safi]);
+ }
if (peer->t_gr_restart) {
THREAD_OFF(peer->t_gr_restart);
BGP_NOTIFY_CEASE_PEER_UNCONFIG);
}
+static void peer_notify_shutdown(struct peer *peer)
+{
+ if (BGP_PEER_GRACEFUL_RESTART_CAPABLE(peer)) {
+ if (bgp_debug_neighbor_events(peer))
+ zlog_debug(
+ "%pBP configured Graceful-Restart, skipping shutdown notification",
+ peer);
+ return;
+ }
+
+ if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
+ bgp_notify_send(peer, BGP_NOTIFY_CEASE,
+ BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
+}
+
void peer_group_notify_unconfig(struct peer_group *group)
{
struct peer *peer, *other;
/* ebgp-multihop reset */
if (gtype == BGP_PEER_IBGP)
group->conf->ttl = MAXTTL;
-
- /* local-as reset */
- if (gtype != BGP_PEER_EBGP) {
- group->conf->change_local_as = 0;
- peer_flag_unset(group->conf,
- PEER_FLAG_LOCAL_AS);
- peer_flag_unset(group->conf,
- PEER_FLAG_LOCAL_AS_NO_PREPEND);
- peer_flag_unset(group->conf,
- PEER_FLAG_LOCAL_AS_REPLACE_AS);
- }
}
SET_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE);
bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF;
bgp->default_subgroup_pkt_queue_max =
BGP_DEFAULT_SUBGROUP_PKT_QUEUE_MAX;
+ bgp_tcp_keepalive_unset(bgp);
bgp_timers_unset(bgp);
bgp->default_min_holdtime = 0;
bgp->restart_time = BGP_DEFAULT_RESTART_TIME;
hook_call(bgp_inst_delete, bgp);
+ THREAD_OFF(bgp->t_condition_check);
THREAD_OFF(bgp->t_startup);
THREAD_OFF(bgp->t_maxmed_onstartup);
THREAD_OFF(bgp->t_update_delay);
gr_info = &bgp->gr_info[afi][safi];
if (!gr_info)
continue;
+ t = gr_info->t_select_deferral;
+ if (t) {
+ void *info = THREAD_ARG(t);
+ XFREE(MTYPE_TMP, info);
+ }
THREAD_OFF(gr_info->t_select_deferral);
t = gr_info->t_route_select;
}
/* Inform peers we're going down. */
- for (ALL_LIST_ELEMENTS(bgp->peer, node, next, peer)) {
- if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
- bgp_notify_send(peer, BGP_NOTIFY_CEASE,
- BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
- }
+ for (ALL_LIST_ELEMENTS(bgp->peer, node, next, peer))
+ peer_notify_shutdown(peer);
/* Delete static routes (networks). */
bgp_static_delete(bgp);
bgp->vpn_policy[afi].import_redirect_rtlist = NULL;
}
+ /* Free any memory allocated to holding routemap references */
+ for (afi = 0; afi < AFI_MAX; ++afi) {
+ for (enum vpn_policy_direction dir = 0;
+ dir < BGP_VPN_POLICY_DIR_MAX; ++dir) {
+ if (bgp->vpn_policy[afi].rmap_name[dir])
+ XFREE(MTYPE_ROUTE_MAP_NAME,
+ bgp->vpn_policy[afi].rmap_name[dir]);
+ bgp->vpn_policy[afi].rmap[dir] = NULL;
+ }
+ }
+
/* Deregister from Zebra, if needed */
if (IS_BGP_INST_KNOWN_TO_ZEBRA(bgp)) {
if (BGP_DEBUG(zebra, ZEBRA))
* being used by a peer has changed (AF specific). Automatically
* initiates inbound or outbound processing as needed.
*/
-static void peer_on_policy_change(struct peer *peer, afi_t afi, safi_t safi,
- int outbound)
+void peer_on_policy_change(struct peer *peer, afi_t afi, safi_t safi,
+ int outbound)
{
if (outbound) {
update_group_adjust_peer(peer_af_find(peer, afi, safi));
struct bgp *bgp = peer->bgp;
struct peer *member;
struct listnode *node, *nnode;
- enum bgp_peer_sort ptype = peer_sort(peer);
-
- if (ptype != BGP_PEER_EBGP && ptype != BGP_PEER_INTERNAL)
- return BGP_ERR_LOCAL_AS_ALLOWED_ONLY_FOR_EBGP;
if (bgp->as == as)
return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS;
- if (peer->as == as)
- return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS_REMOTE_AS;
-
/* Save previous flag states. */
old_no_prepend =
!!CHECK_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
&& old_replace_as == replace_as)
return 0;
peer->change_local_as = as;
+ (void)peer_sort(peer);
/* Check if handling a regular peer. */
if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
return 0;
}
-static void peer_advertise_map_filter_update(struct peer *peer, afi_t afi,
- safi_t safi, const char *amap_name,
- struct route_map *amap,
- const char *cmap_name,
- struct route_map *cmap,
- bool condition, bool set)
-{
- struct bgp_filter *filter;
- bool filter_exists = false;
-
- filter = &peer->filter[afi][safi];
-
- /* advertise-map is already configured. */
- if (filter->advmap.aname) {
- filter_exists = true;
- XFREE(MTYPE_BGP_FILTER_NAME, filter->advmap.aname);
- XFREE(MTYPE_BGP_FILTER_NAME, filter->advmap.cname);
- }
-
- route_map_counter_decrement(filter->advmap.amap);
-
- /* Removed advertise-map configuration */
- if (!set) {
- memset(&filter->advmap, 0, sizeof(filter->advmap));
-
- /* decrement condition_filter_count delete timer if
- * this is the last advertise-map to be removed.
- */
- if (filter_exists)
- bgp_conditional_adv_disable(peer, afi, safi);
-
- return;
- }
-
- /* Update filter data with newly configured values. */
- filter->advmap.aname = XSTRDUP(MTYPE_BGP_FILTER_NAME, amap_name);
- filter->advmap.cname = XSTRDUP(MTYPE_BGP_FILTER_NAME, cmap_name);
- filter->advmap.amap = amap;
- filter->advmap.cmap = cmap;
- filter->advmap.condition = condition;
- route_map_counter_increment(filter->advmap.amap);
- peer->advmap_config_change[afi][safi] = true;
-
- /* Increment condition_filter_count and/or create timer. */
- if (!filter_exists) {
- filter->advmap.update_type = UPDATE_TYPE_ADVERTISE;
- bgp_conditional_adv_enable(peer, afi, safi);
- }
-
- /* Process peer route updates. */
- peer_on_policy_change(peer, afi, safi, 1);
-}
-
-/* Set advertise-map to the peer. */
-int peer_advertise_map_set(struct peer *peer, afi_t afi, safi_t safi,
- const char *advertise_name,
- struct route_map *advertise_map,
- const char *condition_name,
- struct route_map *condition_map, bool condition)
-{
- struct peer *member;
- struct listnode *node, *nnode;
-
- /* Set configuration on peer. */
- peer_advertise_map_filter_update(peer, afi, safi, advertise_name,
- advertise_map, condition_name,
- condition_map, condition, true);
-
- /* Check if handling a regular peer & Skip peer-group mechanics. */
- if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
- /* Set override-flag and process peer route updates. */
- SET_FLAG(peer->filter_override[afi][safi][RMAP_OUT],
- PEER_FT_ADVERTISE_MAP);
- return 0;
- }
-
- /*
- * Set configuration on all peer-group members, unless they are
- * explicitly overriding peer-group configuration.
- */
- for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
- /* Skip peers with overridden configuration. */
- if (CHECK_FLAG(member->filter_override[afi][safi][RMAP_OUT],
- PEER_FT_ADVERTISE_MAP))
- continue;
-
- /* Set configuration on peer-group member. */
- peer_advertise_map_filter_update(
- member, afi, safi, advertise_name, advertise_map,
- condition_name, condition_map, condition, true);
- }
-
- return 0;
-}
-
-/* Unset advertise-map from the peer. */
-int peer_advertise_map_unset(struct peer *peer, afi_t afi, safi_t safi,
- const char *advertise_name,
- struct route_map *advertise_map,
- const char *condition_name,
- struct route_map *condition_map, bool condition)
-{
- struct peer *member;
- struct listnode *node, *nnode;
-
- /* advertise-map is not configured */
- if (!peer->filter[afi][safi].advmap.aname)
- return 0;
-
- /* Unset override-flag unconditionally. */
- UNSET_FLAG(peer->filter_override[afi][safi][RMAP_OUT],
- PEER_FT_ADVERTISE_MAP);
-
- /* Inherit configuration from peer-group if peer is member. */
- if (peer_group_active(peer)) {
- PEER_STR_ATTR_INHERIT(peer, peer->group,
- filter[afi][safi].advmap.aname,
- MTYPE_BGP_FILTER_NAME);
- PEER_ATTR_INHERIT(peer, peer->group,
- filter[afi][safi].advmap.amap);
- } else
- peer_advertise_map_filter_update(
- peer, afi, safi, advertise_name, advertise_map,
- condition_name, condition_map, condition, false);
-
- /* Check if handling a regular peer and skip peer-group mechanics. */
- if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
- /* Process peer route updates. */
- if (BGP_DEBUG(update, UPDATE_OUT))
- zlog_debug("%s: Send normal update to %s for %s",
- __func__, peer->host,
- get_afi_safi_str(afi, safi, false));
-
- return 0;
- }
-
- /*
- * Remove configuration on all peer-group members, unless they are
- * explicitly overriding peer-group configuration.
- */
- for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
- /* Skip peers with overridden configuration. */
- if (CHECK_FLAG(member->filter_override[afi][safi][RMAP_OUT],
- PEER_FT_ADVERTISE_MAP))
- continue;
- /* Remove configuration on peer-group member. */
- peer_advertise_map_filter_update(
- member, afi, safi, advertise_name, advertise_map,
- condition_name, condition_map, condition, false);
-
- /* Process peer route updates. */
- if (BGP_DEBUG(update, UPDATE_OUT))
- zlog_debug("%s: Send normal update to %s for %s ",
- __func__, member->host,
- get_afi_safi_str(afi, safi, false));
- }
-
- return 0;
-}
-
static bool peer_maximum_prefix_clear_overflow(struct peer *peer)
{
if (!CHECK_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
/* reverse bgp_master_init */
for (ALL_LIST_ELEMENTS(bm->bgp, mnode, mnnode, bgp)) {
bgp_close_vrf_socket(bgp);
- for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer))
- if (peer_established(peer) || peer->status == OpenSent
- || peer->status == OpenConfirm)
+ for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
+ if (BGP_PEER_GRACEFUL_RESTART_CAPABLE(peer)) {
+ if (bgp_debug_neighbor_events(peer))
+ zlog_debug(
+ "%pBP configured Graceful-Restart, skipping unconfig notification",
+ peer);
+ continue;
+ }
+ if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
bgp_notify_send(peer, BGP_NOTIFY_CEASE,
BGP_NOTIFY_CEASE_PEER_UNCONFIG);
+ }
}
if (bm->listen_sockets)
+++ /dev/null
-!
-! Zebra configuration saved from vty
-! 2002/07/01 03:16:33
-!
-hostname bgpd
-password zebra
-log file bgpd.log
-log stdout
-!
-router bgp 7675
- no bgp default ipv4-unicast
- neighbor 3ffe:506:1000::2 remote-as 7675
- neighbor fe80::200:c0ff:fe30:9be3 remote-as 9377
- neighbor fe80::200:c0ff:fe30:9be3 interface sit3
- neighbor fe80::210:5aff:fe6b:3cee remote-as 7675
- neighbor fe80::210:5aff:fe6b:3cee interface eth0
- neighbor fe80::290:27ff:fe51:84c7 remote-as 4691
- neighbor fe80::290:27ff:fe51:84c7 description DTI
- neighbor fe80::290:27ff:fe51:84c7 interface sit7
- neighbor fe80::2a0:c9ff:fec8:82ec remote-as 7530
- neighbor fe80::2a0:c9ff:fec8:82ec description IRI
- neighbor fe80::2a0:c9ff:fec8:82ec interface sit8
- neighbor fe80::2e0:18ff:fe98:2725 remote-as 2500
- neighbor fe80::2e0:18ff:fe98:2725 description WIDE
- neighbor fe80::2e0:18ff:fe98:2725 interface sit5
- neighbor fe80::2e0:18ff:fea8:bf5 remote-as 65000
- neighbor fe80::2e0:18ff:fea8:bf5 interface sit6
-!
- address-family ipv6
- network 3ffe:506::/33
- network 3ffe:1800:e800::/40
- aggregate-address 3ffe:506::/32
- redistribute connected
- neighbor 3ffe:506:1000::2 activate
- neighbor fe80::200:c0ff:fe30:9be3 activate
- neighbor fe80::200:c0ff:fe30:9be3 route-map set-nexthop out
- neighbor fe80::210:5aff:fe6b:3cee activate
- neighbor fe80::290:27ff:fe51:84c7 activate
- neighbor fe80::290:27ff:fe51:84c7 route-map set-nexthop out
- neighbor fe80::2a0:c9ff:fec8:82ec activate
- neighbor fe80::2a0:c9ff:fec8:82ec route-map set-nexthop out
- neighbor fe80::2e0:18ff:fe98:2725 activate
- neighbor fe80::2e0:18ff:fe98:2725 distribute-list nla1 out
- neighbor fe80::2e0:18ff:fe98:2725 route-map set-nexthop out
- neighbor fe80::2e0:18ff:fea8:bf5 activate
- neighbor fe80::2e0:18ff:fea8:bf5 route-map set-nexthop out
- exit-address-family
-!
-ipv6 access-list all permit any
-ipv6 access-list nla1 deny 3ffe:506::/33
-ipv6 access-list nla1 permit 3ffe:506::/32
-ipv6 access-list nla1 deny any
-ipv6 access-list ntt-nla1 permit 3ffe:1800:0:ffff::c/127
-ipv6 access-list ntt-nla1 deny 3ffe:1800:e800::/41
-ipv6 access-list ntt-nla1 permit 3ffe:1800:e800::/40
-ipv6 access-list ntt-nla1 deny any
-!
-ipv6 prefix-list 6bone-filter seq 5 permit 3ffe::/17 ge 24 le 24
-ipv6 prefix-list 6bone-filter seq 10 permit 3ffe:8000::/17 ge 28 le 28
-ipv6 prefix-list 6bone-filter seq 12 deny 3ffe::/16
-ipv6 prefix-list 6bone-filter seq 15 permit 2000::/3 ge 16 le 16
-ipv6 prefix-list 6bone-filter seq 20 permit 2001::/16 ge 35 le 35
-!
-route-map set-nexthop permit 10
- match ipv6 address all
- set ipv6 next-hop global 3ffe:506::1
- set ipv6 next-hop local fe80::cbb5:591a
- set ip next-hop 203.181.89.26
- set community 7675:0
-!
-route-map set-link-local permit 10
- match ipv6 address all
- set ipv6 next-hop local fe80::cbb5:591a
- set ipv6 next-hop global 3ffe:1800:0:ffff::d
-!
-line vty
-!
/* Various BGP global configuration. */
uint8_t options;
+
#define BGP_OPT_NO_FIB (1 << 0)
#define BGP_OPT_NO_LISTEN (1 << 1)
#define BGP_OPT_NO_ZEBRA (1 << 2)
char srv6_locator_name[SRV6_LOCNAME_SIZE];
struct list *srv6_locator_chunks;
struct list *srv6_functions;
+ /* TCP keepalive parameters for BGP connection */
+ uint16_t tcp_keepalive_idle;
+ uint16_t tcp_keepalive_intvl;
+ uint16_t tcp_keepalive_probes;
struct timeval ebgprequirespolicywarning;
#define FIFTEENMINUTE2USEC (int64_t)15 * 60 * 1000000
#define PEER_STATUS_EORR_RECEIVED (1U << 10) /* EoRR received from peer */
/* LLGR aware peer */
#define PEER_STATUS_LLGR_WAIT (1U << 11)
+#define PEER_STATUS_REFRESH_PENDING (1U << 12) /* refresh request from peer */
/* Configured timer values. */
_Atomic uint32_t holdtime;
BGP_ERR_AF_UNCONFIGURED = -15,
BGP_ERR_SOFT_RECONFIG_UNCONFIGURED = -16,
BGP_ERR_INSTANCE_MISMATCH = -17,
- BGP_ERR_LOCAL_AS_ALLOWED_ONLY_FOR_EBGP = -18,
BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS = -19,
BGP_ERR_TCPSIG_FAILED = -20,
BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK = -21,
BGP_ERR_NO_IBGP_WITH_TTLHACK = -22,
BGP_ERR_NO_INTERFACE_CONFIG = -23,
- BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS_REMOTE_AS = -24,
BGP_ERR_AS_OVERRIDE = -25,
BGP_ERR_INVALID_DYNAMIC_NEIGHBORS_LIMIT = -26,
BGP_ERR_DYNAMIC_NEIGHBORS_RANGE_EXISTS = -27,
const char *rmap,
struct route_map *route_map);
extern int peer_default_originate_unset(struct peer *, afi_t, safi_t);
+extern void bgp_tcp_keepalive_set(struct bgp *bgp, uint16_t idle,
+ uint16_t interval, uint16_t probes);
+extern void bgp_tcp_keepalive_unset(struct bgp *bgp);
extern void peer_port_set(struct peer *, uint16_t);
extern void peer_port_unset(struct peer *);
extern void bgp_recalculate_afi_safi_bestpaths(struct bgp *bgp, afi_t afi,
safi_t safi);
-
+extern void peer_on_policy_change(struct peer *peer, afi_t afi, safi_t safi,
+ int outbound);
#ifdef _FRR_ATTRIBUTE_PRINTFRR
/* clang-format off */
#pragma FRR printfrr_ext "%pBP" (struct peer *)
}
if (rfg->rd.prefixlen) {
- char buf[RD_ADDRSTRLEN];
-
if (AF_UNIX == rfg->rd.family) {
uint16_t value = 0;
value);
} else
- vty_out(vty, " rd %s\n",
- prefix_rd2str(&rfg->rd, buf,
- sizeof(buf)));
+ vty_out(vty, " rd %pRD\n", &rfg->rd);
}
if (rfg->rt_import_list && rfg->rt_export_list
vty_out(vty, " vnc defaults\n");
if (hc->default_rd.prefixlen) {
- char buf[RD_ADDRSTRLEN];
-
if (AF_UNIX == hc->default_rd.family) {
uint16_t value = 0;
value);
} else
- vty_out(vty, " rd %s\n",
- prefix_rd2str(&hc->default_rd,
- buf,
- sizeof(buf)));
+ vty_out(vty, " rd %pRD\n",
+ &hc->default_rd);
}
if (hc->default_response_lifetime
!= BGP_VNC_DEFAULT_RESPONSE_LIFETIME_DEFAULT) {
if (rfg->rd.prefixlen) {
- char buf[RD_ADDRSTRLEN];
-
if (AF_UNIX == rfg->rd.family) {
uint16_t value = 0;
value);
} else
- vty_out(vty, " rd %s\n",
- prefix_rd2str(
- &rfg->rd, buf,
- sizeof(buf)));
+ vty_out(vty, " rd %pRD\n",
+ &rfg->rd);
}
if (rfg->flags & RFAPI_RFG_RESPONSE_LIFETIME) {
vty_out(vty, " response-lifetime ");
afi_t afi; /* of the VN address */
struct bgp_dest *bn;
struct bgp_path_info *bpi;
- char buf2[RD_ADDRSTRLEN];
struct prefix_rd prd0;
afi = family2afi(p->family);
bn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
vnc_zlog_debug_verbose(
- "%s: peer=%p, prefix=%pFX, prd=%s afi=%d, safi=%d bn=%p, bn->info=%p",
- __func__, peer, p, prefix_rd2str(prd, buf2, sizeof(buf2)), afi,
- safi, bn, (bn ? bgp_dest_get_bgp_path_info(bn) : NULL));
+ "%s: peer=%p, prefix=%pFX, prd=%pRD afi=%d, safi=%d bn=%p, bn->info=%p",
+ __func__, peer, p, prd, afi, safi, bn,
+ (bn ? bgp_dest_get_bgp_path_info(bn) : NULL));
for (bpi = (bn ? bgp_dest_get_bgp_path_info(bn) : NULL); bpi;
bpi = bpi->next) {
struct bgp_attr_encap_subtlv *encaptlv;
char buf[PREFIX_STRLEN];
- char buf2[RD_ADDRSTRLEN];
struct rfapi_nexthop *lnh = NULL; /* local nexthop */
struct rfapi_vn_option *vo;
else
label_val = MPLS_LABEL_IMPLICIT_NULL;
- prefix_rd2str(prd, buf2, sizeof(buf2));
-
afi = family2afi(p->family);
assert(afi == AFI_IP || afi == AFI_IP6);
bgp_process(bgp, bn, afi, safi);
vnc_zlog_debug_any(
- "%s: Added route (safi=%s) at prefix %s (bn=%p, prd=%s)",
- __func__, safi2str(safi), buf, bn, buf2);
+ "%s: Added route (safi=%s) at prefix %s (bn=%p, prd=%pRD)",
+ __func__, safi2str(safi), buf, bn, prd);
done:
/* Loop back to import tables */
memcpy(rd->val + 2, &vn->addr.v6.s6_addr32[3],
4); /* low order 4 bytes */
}
- {
- char buf[RD_ADDRSTRLEN];
-
- vnc_zlog_debug_verbose("%s: auto-RD is set to %s", __func__,
- prefix_rd2str(rd, buf, sizeof(buf)));
- }
+ vnc_zlog_debug_verbose("%s: auto-RD is set to %pRD", __func__, rd);
return 0;
}
assert(bpi);
assert(bpi->extra);
- {
- char buf[RD_ADDRSTRLEN];
-
- vnc_zlog_debug_verbose("%s: bpi %p, peer %p, rd %s", __func__,
- bpi, bpi->peer,
- prefix_rd2str(&bpi->extra->vnc.import.rd,
- buf, sizeof(buf)));
- }
+ vnc_zlog_debug_verbose("%s: bpi %p, peer %p, rd %pRD", __func__, bpi,
+ bpi->peer, &bpi->extra->vnc.import.rd);
sl = RFAPI_RDINDEX_W_ALLOC(rn);
if (!sl) {
#ifdef DEBUG_BI_SEARCH
{
- char buf[RD_ADDRSTRLEN];
char buf_aux_pfx[PREFIX_STRLEN];
if (aux_prefix) {
} else
strlcpy(buf_aux_pfx, "(nil)", sizeof(buf_aux_pfx));
- vnc_zlog_debug_verbose("%s want prd=%s, peer=%p, aux_prefix=%s",
- __func__,
- prefix_rd2str(prd, buf, sizeof(buf)),
- peer, buf_aux_pfx);
+ vnc_zlog_debug_verbose(
+ "%s want prd=%pRD, peer=%p, aux_prefix=%s", __func__,
+ prd, peer, buf_aux_pfx);
rfapiItBiIndexDump(rn);
}
#endif
for (bpi_result = rn->info; bpi_result;
bpi_result = bpi_result->next) {
#ifdef DEBUG_BI_SEARCH
- {
- char buf[RD_ADDRSTRLEN];
-
- vnc_zlog_debug_verbose(
- "%s: bpi has prd=%s, peer=%p", __func__,
- prefix_rd2str(&bpi_result->extra->vnc
- .import.rd,
- buf, sizeof(buf)),
- bpi_result->peer);
- }
+ vnc_zlog_debug_verbose(
+ "%s: bpi has prd=%pRD, peer=%p", __func__,
+ &bpi_result->extra->vnc.import.rd,
+ bpi_result->peer);
#endif
if (peer == bpi_result->peer
&& !prefix_cmp((struct prefix *)&bpi_result->extra
struct skiplist *sl;
int rc;
- {
- char buf[RD_ADDRSTRLEN];
-
- vnc_zlog_debug_verbose("%s: bpi %p, peer %p, rd %s", __func__,
- bpi, bpi->peer,
- prefix_rd2str(&bpi->extra->vnc.import.rd,
- buf, sizeof(buf)));
- }
+ vnc_zlog_debug_verbose("%s: bpi %p, peer %p, rd %pRD", __func__, bpi,
+ bpi->peer, &bpi->extra->vnc.import.rd);
sl = RFAPI_RDINDEX(rn);
assert(sl);
__func__, ri);
} else {
-
- char buf_rd[RD_ADDRSTRLEN];
-
/* not found: add new route to RIB */
ori = rfapi_info_new();
ori->rk = ri->rk;
}
skiplist_insert(slRibPt, &ori->rk, ori);
-#if DEBUG_RIB_SL_RD
- prefix_rd2str(&ori->rk.rd, buf_rd,
- sizeof(buf_rd));
-#else
- buf_rd[0] = 0;
-#endif
-
vnc_zlog_debug_verbose(
- "%s: nomatch lPendCost item %p in slRibPt, added (rd=%s)",
- __func__, ri, buf_rd);
+ "%s: nomatch lPendCost item %p in slRibPt, added (rd=%pRD)",
+ __func__, ri, &ori->rk.rd);
}
/*
0, delete_list->count);
ri->last_sent_time = monotime(NULL);
#if DEBUG_RIB_SL_RD
- {
- char buf_rd[RD_ADDRSTRLEN];
-
- vnc_zlog_debug_verbose(
- "%s: move route to recently deleted list, rd=%s",
- __func__,
- prefix_rd2str(
- &ri->rk.rd,
- buf_rd,
- sizeof(buf_rd)));
- }
+ vnc_zlog_debug_verbose(
+ "%s: move route to recently deleted list, rd=%pRD",
+ __func__, &ri->rk.rd);
#endif
} else {
char str_lifetime[BUFSIZ];
char str_age[BUFSIZ];
char *p;
- char str_rd[RD_ADDRSTRLEN];
++routes_displayed;
}
#endif
- str_rd[0] = 0; /* start empty */
-#if DEBUG_RIB_SL_RD
- prefix_rd2str(&ri->rk.rd, str_rd, sizeof(str_rd));
-#endif
-
- fp(out, " %c %-20s %-15s %-15s %-4u %-8s %-8s %s\n",
+ fp(out, " %c %-20s %-15s %-15s %-4u %-8s %-8s %pRD\n",
deleted ? 'r' : ' ', *printedprefix ? "" : str_pfx, str_vn,
- str_un, ri->cost, str_lifetime, str_age, str_rd);
+ str_un, ri->cost, str_lifetime, str_age, &ri->rk.rd);
if (!*printedprefix)
*printedprefix = 1;
fp(out, "?/?:?");
}
-void rfapiPrintRd(struct vty *vty, struct prefix_rd *prd)
-{
- char buf[RD_ADDRSTRLEN];
-
- prefix_rd2str(prd, buf, sizeof(buf));
- vty_out(vty, "%s", buf);
-}
-
void rfapiPrintAdvertisedInfo(struct vty *vty, struct rfapi_descriptor *rfd,
safi_t safi, struct prefix *p)
{
vty_out(vty, " ");
rfapiPrintRfapiIpAddr(vty, &rfd->vn_addr);
vty_out(vty, " %p %p ", rfd->response_cb, rfd->cookie);
- rfapiPrintRd(vty, &rfd->rd);
+ vty_out(vty, "%pRD", &rfd->rd);
vty_out(vty, " %d", rfd->response_lifetime);
vty_out(vty, " %s", (rfd->rfg ? rfd->rfg->name : "<orphaned>"));
vty_out(vty, "%s", HVTYNL);
extern void rfapiPrintRfapiIpPrefix(void *stream, struct rfapi_ip_prefix *p);
-void rfapiPrintRd(struct vty *vty, struct prefix_rd *prd);
-
extern void rfapiPrintAdvertisedInfo(struct vty *vty,
struct rfapi_descriptor *rfd, safi_t safi,
struct prefix *p);
##
AC_PREREQ([2.69])
-AC_INIT([frr], [8.4-dev], [https://github.com/frrouting/frr/issues])
+AC_INIT([frr], [8.5-dev], [https://github.com/frrouting/frr/issues])
PACKAGE_URL="https://frrouting.org/"
AC_SUBST([PACKAGE_URL])
PACKAGE_FULLNAME="FRRouting"
+frr (8.5~dev-1) UNRELEASED; urgency=medium
+
+ * FRR Dev 8.5
+
+ -- Donatas Abraitis <donatas@opensourcerouting.org> Tue, 04 Oct 2022 16:00:00 +0500
+
frr (8.4~dev-1) UNRELEASED; urgency=medium
* FRR Dev 8.4
default, the DelayOpenTimer is disabled. The timer interval may be set to a
duration of 1 to 240 seconds.
+.. clicmd:: neighbor PEER extended-optional-parameters
+
+ Force the extended optional parameters format for OPEN messages. By default,
+ optional parameters length is 255 octets. With more and more BGP capabilities
+ implemented on top of BGP, this is needed to extend this value.
+
+ This is turned off by default, but it's automatically enabled when this limit
+ is hit. You can force this new encoding to be enabled with this command.
+
.. clicmd:: bgp minimum-holdtime (1-65535)
This command allows user to prevent session establishment with BGP peers
with lower holdtime less than configured minimum holdtime.
When this command is not set, minimum holdtime does not work.
+.. clicmd:: bgp tcp-keepalive (1-65535) (1-65535) (1-30)
+
+ This command allows user to configure TCP keepalive with new BGP peers.
+ Each parameter respectively stands for TCP keepalive idle timer (seconds),
+ interval (seconds), and maximum probes. By default, TCP keepalive is
+ disabled.
+
Displaying Information about Peers
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
library messages and BGP BFD integration messages that are mostly state
transitions and validation problems.
+.. clicmd:: debug bgp conditional-advertisement
+
+ Enable or disable debugging of BGP conditional advertisement.
+
.. clicmd:: debug bgp neighbor-events
Enable or disable debugging for neighbor events. This provides general
Debugging OSPF
==============
-.. clicmd:: debug ospf bfd
+.. clicmd:: debug ospf [(1-65535)] bfd
Enable or disable debugging for BFD events. This will show BFD integration
library messages and OSPF BFD integration messages that are mostly state
transitions and validation problems.
-.. clicmd:: debug ospf client-api
+.. clicmd:: debug ospf [(1-65535)] client-api
Show debug information for the OSPF opaque data client API.
-.. clicmd:: debug ospf packet (hello|dd|ls-request|ls-update|ls-ack|all) (send|recv) [detail]
+.. clicmd:: debug ospf [(1-65535)] default-information
+ Show debug information of default information
- Dump Packet for debugging
+.. clicmd:: debug ospf [(1-65535)] packet (hello|dd|ls-request|ls-update|ls-ack|all) (send|recv) [detail]
-.. clicmd:: debug ospf ism
-.. clicmd:: debug ospf ism (status|events|timers)
+ Dump Packet for debugging
+.. clicmd:: debug ospf [(1-65535)] ism [status|events|timers]
- Show debug information of Interface State Machine
-.. clicmd:: debug ospf nsm
+ Show debug information of Interface State Machine
-.. clicmd:: debug ospf nsm (status|events|timers)
+.. clicmd:: debug ospf [(1-65535)] nsm [status|events|timers]
Show debug information of Network State Machine
-.. clicmd:: debug ospf event
+.. clicmd:: debug ospf [(1-65535)] event
Show debug information of OSPF event
-.. clicmd:: debug ospf nssa
+.. clicmd:: debug ospf [(1-65535)] nssa
Show debug information about Not So Stub Area
-.. clicmd:: debug ospf lsa
+.. clicmd:: debug ospf [(1-65535)] ldp-sync
+
+ Show debug information about LDP-Sync
-.. clicmd:: debug ospf lsa (generate|flooding|refresh)
+.. clicmd:: debug ospf [(1-65535)] lsa [aggregate|flooding|generate|install|refresh]
Show debug detail of Link State messages
-.. clicmd:: debug ospf te
+.. clicmd:: debug ospf [(1-65535)] sr
+
+ Show debug information about Segment Routing
+
+.. clicmd:: debug ospf [(1-65535)] te
Show debug information about Traffic Engineering LSA
-.. clicmd:: debug ospf zebra
+.. clicmd:: debug ospf [(1-65535)] ti-lfa
-.. clicmd:: debug ospf zebra (interface|redistribute)
+ Show debug information about SR TI-LFA
+
+.. clicmd:: debug ospf [(1-65535)] zebra [interface|redistribute]
Show debug information of ZEBRA API
-.. clicmd:: debug ospf graceful-restart helper
+.. clicmd:: debug ospf [(1-65535)] graceful-restart
Enable/disable debug information for OSPF Graceful Restart Helper
.. clicmd:: show debugging ospf
-.. clicmd:: debug ospf lsa aggregate
-
- Debug commnd to enable/disable external route summarisation specific debugs.
Sample Configuration
:t:`Autonomous System Confederations for BGP. P. Traina. June 1996.`
- :rfc:`1997`
:t:`BGP Communities Attribute. R. Chandra, P. Traina & T. Li. August 1996.`
+- :rfc:`1998`
+ :t:`An Application of the BGP Community Attribute in Multi-home Routing. E. Chen, T. Bates. August 1996.`
+- :rfc:`2385`
+ :t:`Protection of BGP Sessions via the TCP MD5 Signature Option. A. Heffernan. August 1998.`
- :rfc:`2439`
:t:`BGP Route Flap Damping. C. Villamizar, R. Chandra, R. Govindan. November 1998.`
- :rfc:`2545`
- :t:`Use of BGP-4 Multiprotocol Extensions for IPv6 Inter-Domain Routing. P.
- Marques, F. Dupont. March 1999.`
+ :t:`Use of BGP-4 Multiprotocol Extensions for IPv6 Inter-Domain Routing. P. Marques, F. Dupont. March 1999.`
- :rfc:`2796`
:t:`BGP Route Reflection An alternative to full mesh IBGP. T. Bates & R. Chandrasekeran. June 1996.`
- :rfc:`2842`
:t:`Capabilities Advertisement with BGP-4. R. Chandra, J. Scudder. May 2000.`
- :rfc:`2858`
- :t:`Multiprotocol Extensions for BGP-4. T. Bates, Y. Rekhter, R. Chandra, D.`
+ :t:`Multiprotocol Extensions for BGP-4. T. Bates, Y. Rekhter, R. Chandra, D. Katz. June 2000.`
+- :rfc:`2918`
+ :t:`Route Refresh Capability for BGP-4. E. Chen, September 2000.`
- :rfc:`3107`
:t:`Carrying Label Information in BGP-4. Y. Rekhter & E. Rosen. May 2001.`
- :rfc:`3765`
- :t:`NOPEER Community for Border Gateway Protocol (BGP) Route Scope Control. G.Huston, April 2001.`
+ :t:`NOPEER Community for Border Gateway Protocol (BGP) Route Scope Control. G.Huston. April 2001.`
- :rfc:`4271`
:t:`A Border Gateway Protocol 4 (BGP-4). Updates RFC1771. Y. Rekhter, T. Li & S. Hares. January 2006.`
+- :rfc:`4360`
+ :t:`BGP Extended Communities Attribute. S. Sangli, D. Tappan, Y. Rekhter. February 2006.`
- :rfc:`4364`
- :t:`BGP/MPLS IP Virtual Private Networks (VPNs). Y. Rekhter. Feb 2006.`
+ :t:`BGP/MPLS IP Virtual Private Networks (VPNs). Y. Rekhter. February 2006.`
+- :rfc:`4456`
+ :t:`BGP Route Reflection An alternative to full mesh IBGP. T. Bates, E. Chen, R. Chandra. April 2006.`
- :rfc:`4486`
:t:`Subcodes for BGP Cease Notification Message. E. Chen, V. Gillet. April 2006.`
- :rfc:`4659`
:t:`BGP-MPLS IP Virtual Private Network (VPN) Extension for IPv6 VPN. J. De Clercq, D. Ooms, M. Carugi, F. Le Faucheur. September 2006.`
+- :rfc:`4724`
+ :t:`Graceful Restart Mechanism for BGP. S. Sangli, E. Chen, R. Fernando, J. Scudder, Y. Rekhter. January 2007.`
+- :rfc:`4760`
+ :t:`Multiprotocol Extensions for BGP-4. T. Bates, R. Chandra, D. Katz, Y. Rekhter. January 2007.`
- :rfc:`4893`
:t:`BGP Support for Four-octet AS Number Space. Q. Vohra, E. Chen May 2007.`
- :rfc:`5004`
:t:`Avoid BGP Best Path Transitions from One External to Another. E. Chen & S. Sangli. September 2007 (Partial support).`
+- :rfc:`5065`
+ :t:`Autonomous System Confederations for BGP. P. Traina, D. McPherson, J. Scudder. August 2007.`
- :rfc:`5082`
:t:`The Generalized TTL Security Mechanism (GTSM). V. Gill, J. Heasley, D. Meyer, P. Savola, C. Pingnataro. October 2007.`
+- :rfc:`5291`
+ :t:`Outbound Route Filtering Capability. E. Chen, Y. Rekhter. August 2008.`
+- :rfc:`5292`
+ :t:`Address-Prefix-Based Outbound Route Filter for BGP-4. E. Chen, S. Sangli. August 2008.`
+- :rfc:`5492`
+ :t:`Capabilities Advertisement with BGP-4. J. Scudder, R. Chandra. February 2009.`
- :rfc:`5575`
- :t:`Dissemination of Flow Specification Rules. P. Marques, N. Sheth, R. Raszuk, B. Greene, J. Mauch, D. McPherson. August 2009`
+ :t:`Dissemination of Flow Specification Rules. P. Marques, N. Sheth, R. Raszuk, B. Greene, J. Mauch, D. McPherson. August 2009.`
- :rfc:`5668`
- :t:`4-Octet AS Specific BGP Extended Community. Y. Rekhter, S. Sangli, D. Tappan October 2009`
+ :t:`4-Octet AS Specific BGP Extended Community. Y. Rekhter, S. Sangli, D. Tappan October 2009.`
- :rfc:`6286`
- :t:`Autonomous-System-Wide Unique BGP Identifier for BGP-4. E. Chen, J. Yuan, June 2011.`
+ :t:`Autonomous-System-Wide Unique BGP Identifier for BGP-4. E. Chen, J. Yuan. June 2011.`
+- :rfc:`6472`
+ :t:`Recommendation for Not Using AS_SET and AS_CONFED_SET in BGP. W. Kumari, K. Sriram. December 2011.`
- :rfc:`6608`
:t:`Subcodes for BGP Finite State Machine Error. J. Dong, M. Chen, Huawei Technologies, A. Suryanarayana, Cisco Systems. May 2012.`
- :rfc:`6810`
:t:`BGP Prefix Origin Validation. P. Mohapatra, J. Scudder, D. Ward, R. Bush, R. Austein. January 2013.`
- :rfc:`6938`
:t:`Deprecation of BGP Path Attributes: DPA, ADVERTISER, and RCID_PATH / CLUSTER_ID. J. Scudder. May 2013.`
+- :rfc:`6996`
+ :t:`Autonomous System (AS) Reservation for Private Use. J. Mitchell. July 2013.`
- :rfc:`7196`
:t:`Making Route Flap Damping Usable. C. Pelsser, R. Bush, K. Patel, P. Mohapatra, O. Maennel. May 2014.`
- :rfc:`7300`
:t:`Codification of AS 0 Processing. W. Kumari, R. Bush, H. Schiller, K. Patel. August 2015.`
- :rfc:`7611`
:t:`BGP ACCEPT_OWN Community Attribute. J. Uttaro, P. Mohapatra, D. Smith, R. Raszuk, J. Scudder. August 2015.`
+- :rfc:`7911`
+ :t:`Advertisement of Multiple Paths in BGP. D. Walton, A. Retana, E. Chen, J. Scudder. July 2016.`
+- :rfc:`7947`
+ :t:`Internet Exchange BGP Route Server. E. Jasinska, N. Hilliard, R. Raszuk, N. Bakker. September 2016.`
- :rfc:`7999`
- :t:`BLACKHOLE Community. T. King, C. Dietzel, J. Snijders, G. Doering, G. Hankins. Oct 2016.`
+ :t:`BLACKHOLE Community. T. King, C. Dietzel, J. Snijders, G. Doering, G. Hankins. October 2016.`
+- :rfc:`8050`
+ :t:`Multi-Threaded Routing Toolkit (MRT) Routing Information Export Format with BGP Additional Path Extensions. C. Petrie, T. King. May 2017.`
- :rfc:`8092`
- :t:`BGP Large Communities Attribute. J. Heitz, Ed., J. Snijders, Ed, K. Patel, I. Bagdonas, N. Hilliard. February 2017`
+ :t:`BGP Large Communities Attribute. J. Heitz, Ed., J. Snijders, Ed, K. Patel, I. Bagdonas, N. Hilliard. February 2017.`
+- :rfc:`8093`
+ :t:`Deprecation of BGP Path Attribute Values 30, 31, 129, 241, 242, and 243. J. Snijders. February 2017.`
- :rfc:`8097`
- :t:`BGP Prefix Origin Validation State Extended Community. P. Mohapatra, K. Patel, J. Scudder, D. Ward, R. Bush. March 2017`
+ :t:`BGP Prefix Origin Validation State Extended Community. P. Mohapatra, K. Patel, J. Scudder, D. Ward, R. Bush. March 2017.`
- :rfc:`8195`
- :t:`Use of BGP Large Communities. J. Snijders, J. Heasley, M. Schmidt, June 2017`
+ :t:`Use of BGP Large Communities. J. Snijders, J. Heasley, M. Schmidt. June 2017.`
- :rfc:`8203`
:t:`BGP Administrative Shutdown Communication. J. Snijders, J. Heitz, J. Scudder. July 2017.`
- :rfc:`8212`
- :t:`Default External BGP (EBGP) Route Propagation Behavior without Policies. J. Mauch, J. Snijders, G. Hankins. July 2017`
+ :t:`Default External BGP (EBGP) Route Propagation Behavior without Policies. J. Mauch, J. Snijders, G. Hankins. July 2017.`
- :rfc:`8277`
- :t:`Using BGP to Bind MPLS Labels to Address Prefixes. E. Rosen. October 2017`
+ :t:`Using BGP to Bind MPLS Labels to Address Prefixes. E. Rosen. October 2017.`
- :rfc:`8538`
- :t:`Notification Message Support for BGP Graceful Restart. K. Patel, R. Fernando, J. Scudder, J. Haas. March 2019`
+ :t:`Notification Message Support for BGP Graceful Restart. K. Patel, R. Fernando, J. Scudder, J. Haas. March 2019.`
- :rfc:`8654`
- :t:`Extended Message Support for BGP. R. Bush, K. Patel, D. Ward. October 2019`
+ :t:`Extended Message Support for BGP. R. Bush, K. Patel, D. Ward. October 2019.`
- :rfc:`9003`
- :t:`Extended BGP Administrative Shutdown Communication. J. Snijders, J. Heitz, J. Scudder, A. Azimov. January 2021`
+ :t:`Extended BGP Administrative Shutdown Communication. J. Snijders, J. Heitz, J. Scudder, A. Azimov. January 2021.`
+- :rfc:`9012`
+ :t:`The BGP Tunnel Encapsulation Attribute. K. Patel, G. Van de Velde, S. Sangli, J. Scudder. April 2021.`
- :rfc:`9072`
- :t:`Extended Optional Parameters Length for BGP OPEN Message. E. Chen, J. Scudder. July 2021`
+ :t:`Extended Optional Parameters Length for BGP OPEN Message. E. Chen, J. Scudder. July 2021.`
- :rfc:`9234`
- :t:`Route Leak Prevention and Detection Using Roles in UPDATE and OPEN Messages. A. Azimov, E. Bogomazov, R. Bush, K. Patel, K. Sriram. May 2022`
+ :t:`Route Leak Prevention and Detection Using Roles in UPDATE and OPEN Messages. A. Azimov, E. Bogomazov, R. Bush, K. Patel, K. Sriram. May 2022.`
OSPF
----
mode, the debug commands can be persistent across restarts of the FRR pim6d if
the config was written out.
+.. clicmd:: debug mld
+
+ This turns on debugging for MLD protocol activity.
+
.. clicmd:: debug pimv6 events
This turns on debugging for PIMv6 system events. Especially timers.
.. clicmd:: debug mroute6 detail
This turns on detailed debugging for PIMv6 interaction with kernel MFC cache.
+
+.. clicmd:: debug mld events
+
+ This turns on debugging for MLD system events.
+
+.. clicmd:: debug mld packets
+
+ This turns on information about MLD protocol packets handling.
+
+.. clicmd:: debug mld trace [detail]
+
+ This traces mld code and how it is running.
This allows the operator to control the number of open file descriptors
each daemon is allowed to start with. The current assumed value on
most operating systems is 1024. If the operator plans to run bgp with
-several thousands of peers than this is where we would modify FRR to
+several thousands of peers then this is where we would modify FRR to
allow this to happen.
::
This may be useful for scripting. Note this command should be run as either the
superuser or the FRR user.
-We recommend you do not mix the use of the two types of files. Further, it is
-better not to use the integrated :file:`frr.conf` file, as any syntax error in
-it can lead to /all/ of your daemons being unable to start up. Per daemon files
-are more robust as impact of errors in configuration are limited to the daemon
-in whose file the error is made.
+We recommend you do not mix the use of the two types of files.
.. clicmd:: service integrated-vtysh-config
&& echo 'builder ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers
RUN adduser -D -G abuild builder && su builder -c 'abuild-keygen -a -n'
-# This stage builds a libyang APK from source
-FROM alpine-builder as libyang-builder
-RUN mkdir -p /libyang && chown -R builder /pkgs /libyang
-# -- Not currently needed - libyang currently available in Alpine upstream
-# COPY docker/alpine/libyang/ /libyang
-# USER builder
-# RUN cd /libyang \
-# && abuild checksum \
-# && abuild -r -P /pkgs/apk
-
# This stage builds a dist tarball from the source
FROM alpine:3.15 as source-builder
py-pip \
rtrlib \
&& pip install pytest
-
RUN mkdir -p /pkgs/apk
-# -- Not needed while libyang is not built
-# COPY --from=libyang-builder /pkgs/apk/ /pkgs/apk/
-# RUN apk add \
-# --no-cache \
-# --allow-untrusted /pkgs/apk/*/*.apk \
-
COPY . /src
ARG PKGVER
RUN cd /src \
&& make dist
# This stage builds an APK from the dist tarball
-FROM alpine-builder as frr-apk-builder
-# -- Not needed while libyang is not built
-# COPY --from=libyang-builder /pkgs/apk/ /pkgs/apk/
-# RUN apk add \
-# --no-cache \
-# --allow-untrusted /pkgs/apk/*/*.apk
+FROM alpine-builder as alpine-apk-builder
COPY --from=source-builder /src/frr-*.tar.gz /src/alpine/* /dist/
RUN find /pkgs/apk -type f -name APKINDEX.tar.gz -delete
RUN chown -R builder /dist /pkgs
# This stage installs frr from the apk
FROM alpine:3.15
RUN mkdir -p /pkgs/apk
-COPY --from=frr-apk-builder /pkgs/apk/ /pkgs/apk/
+COPY --from=alpine-apk-builder /pkgs/apk/ /pkgs/apk/
RUN apk add \
--no-cache \
--update-cache \
--target=alpine-builder \
.
-CONTAINER_ID="$(docker create "frr:alpine-builder-$GITREV")"
+# Keep .apk files for debugging purposes, docker image as well.
+docker build \
+ --pull \
+ --file=docker/alpine/Dockerfile \
+ --build-arg="PKGVER=$PKGVER" \
+ --tag="frr:alpine-apk-builder-$GITREV" \
+ --target=alpine-apk-builder \
+ .
+
+CONTAINER_ID="$(docker create "frr:alpine-apk-builder-$GITREV")"
docker cp "${CONTAINER_ID}:/pkgs/" docker/alpine
docker rm "${CONTAINER_ID}"
.
docker rmi "frr:alpine-builder-$GITREV"
+docker rmi "frr:alpine-apk-builder-$GITREV"
}
}
+ cmd_show_lib_debugs(vty);
return CMD_SUCCESS;
}
RTM_SETHWFLAGS = 119,
#define RTM_SETHWFLAGS RTM_SETHWFLAGS
- RTM_NEWTUNNEL = 120,
-#define RTM_NEWTUNNEL RTM_NEWTUNNEL
- RTM_DELTUNNEL,
-#define RTM_DELTUNNEL RTM_DELTUNNEL
- RTM_GETTUNNEL,
-#define RTM_GETTUNNEL RTM_GETTUNNEL
+ RTM_NEWTUNNEL = 120,
+#define RTM_NEWTUNNEL RTM_NEWTUNNEL
+ RTM_DELTUNNEL,
+#define RTM_DELTUNNEL RTM_DELTUNNEL
+ RTM_GETTUNNEL,
+#define RTM_GETTUNNEL RTM_GETTUNNEL
__RTM_MAX,
#define RTM_MAX (((__RTM_MAX + 3) & ~3) - 1)
{
struct fabricd *f = THREAD_ARG(thread);
- zlog_info("OpenFabric: Initial synchronization on %s timed out!",
- f->initial_sync_circuit->interface->name);
+ if (IS_DEBUG_ADJ_PACKETS)
+ zlog_debug(
+ "OpenFabric: Initial synchronization on %s timed out!",
+ f->initial_sync_circuit->interface->name);
f->initial_sync_state = FABRICD_SYNC_PENDING;
f->initial_sync_circuit = NULL;
}
timeout, &f->initial_sync_timeout);
f->initial_sync_start = monotime(NULL);
- zlog_info("OpenFabric: Started initial synchronization with %s on %s",
- sysid_print(circuit->u.p2p.neighbor->sysid),
- circuit->interface->name);
+ if (IS_DEBUG_ADJ_PACKETS)
+ zlog_debug(
+ "OpenFabric: Started initial synchronization with %s on %s",
+ sysid_print(circuit->u.p2p.neighbor->sysid),
+ circuit->interface->name);
}
bool fabricd_initial_sync_is_in_progress(struct isis_area *area)
#include "isisd/isis_dr.h"
#include "isisd/isis_zebra.h"
-DEFINE_MTYPE_STATIC(ISISD, ISIS_PLIST_NAME, "ISIS prefix-list name");
-
/*
* XPath: /frr-isisd:isis/instance
*/
DEFINE_MTYPE_STATIC(ISISD, ISIS_AREA, "ISIS area");
DEFINE_MTYPE(ISISD, ISIS_AREA_ADDR, "ISIS area address");
DEFINE_MTYPE(ISISD, ISIS_ACL_NAME, "ISIS access-list name");
+DEFINE_MTYPE(ISISD, ISIS_PLIST_NAME, "ISIS prefix-list name");
DEFINE_QOBJ_TYPE(isis_area);
area_mt_finish(area);
+ if (area->rlfa_plist_name[0])
+ XFREE(MTYPE_ISIS_PLIST_NAME, area->rlfa_plist_name[0]);
+ if (area->rlfa_plist_name[1])
+ XFREE(MTYPE_ISIS_PLIST_NAME, area->rlfa_plist_name[1]);
+
XFREE(MTYPE_ISIS_AREA, area);
}
if (IS_DEBUG_LFA)
print_debug(vty, DEBUG_LFA, 1);
+ cmd_show_lib_debugs(vty);
+
return CMD_SUCCESS;
}
DECLARE_MTYPE(ISIS_ACL_NAME); /* isis_area->spf_prefix_prioritites */
DECLARE_MTYPE(ISIS_AREA_ADDR); /* isis_area->area_addrs */
+DECLARE_MTYPE(ISIS_PLIST_NAME);
DECLARE_HOOK(isis_area_overload_bit_update, (struct isis_area * area), (area));
"MPLS information\n"
"Label Distribution Protocol\n")
{
- return (ldp_vty_show_debugging(vty));
+ ldp_vty_show_debugging(vty);
+
+ cmd_show_lib_debugs(vty);
+
+ return CMD_SUCCESS;
}
static void
#include "lib_errors.h"
#include "northbound_cli.h"
#include "network.h"
+#include "routemap.h"
#include "frrscript.h"
return host.config;
}
+void cmd_show_lib_debugs(struct vty *vty)
+{
+ route_map_show_debug(vty);
+}
+
void install_default(enum node_type node)
{
_install_element(node, &config_exit_cmd);
extern void command_setup_early_logging(const char *dest, const char *level);
+/*
+ * Allow a mechanism for `debug XXX` commands that live
+ * under the lib directory to output their debug status
+ */
+extern void cmd_show_lib_debugs(struct vty *vty);
+
#ifdef __cplusplus
}
#endif
while ((plist = plist_first(&master->str))) {
prefix_list_delete(plist);
- plist_pop(&master->str);
}
master->recent = NULL;
#pragma FRR printfrr_ext "%pFX" (struct prefix_eth *)
#pragma FRR printfrr_ext "%pFX" (struct prefix_evpn *)
#pragma FRR printfrr_ext "%pFX" (struct prefix_fs *)
+#pragma FRR printfrr_ext "%pRD" (struct prefix_rd *)
#pragma FRR printfrr_ext "%pPSG4" (struct prefix_sg *)
#endif
if (map) {
vty_show_route_map_entry(vty, map, json_proto);
- return CMD_SUCCESS;
} else if (!use_json) {
vty_out(vty, "%s: 'route-map %s' not found\n",
frr_protonameinst, name);
.config_write = rmap_config_write_debug,
};
+void route_map_show_debug(struct vty *vty)
+{
+ if (rmap_debug)
+ vty_out(vty, "debug route-map\n");
+}
+
/* Configuration write function. */
static int rmap_config_write_debug(struct vty *vty)
{
bool show_defaults);
extern void route_map_cli_init(void);
+extern void route_map_show_debug(struct vty *vty);
+
#ifdef __cplusplus
}
#endif
return tcp_maxseg;
}
+
+int setsockopt_tcp_keepalive(int sock, uint16_t keepalive_idle,
+ uint16_t keepalive_intvl,
+ uint16_t keepalive_probes)
+{
+ int val = 1;
+
+ if (setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &val, sizeof(val)) < 0) {
+ flog_err_sys(EC_LIB_SYSTEM_CALL,
+ "%s failed: setsockopt SO_KEEPALIVE (%d): %s",
+ __func__, sock, safe_strerror(errno));
+ return -1;
+ }
+
+#if defined __OpenBSD__
+ return 0;
+#else
+ /* Send first probe after keepalive_idle seconds */
+ val = keepalive_idle;
+ if (setsockopt(sock, IPPROTO_TCP, TCP_KEEPIDLE, &val, sizeof(val)) <
+ 0) {
+ flog_err_sys(EC_LIB_SYSTEM_CALL,
+ "%s failed: setsockopt TCP_KEEPIDLE (%d): %s",
+ __func__, sock, safe_strerror(errno));
+ return -1;
+ }
+
+ /* Set interval between two probes */
+ val = keepalive_intvl;
+ if (setsockopt(sock, IPPROTO_TCP, TCP_KEEPINTVL, &val, sizeof(val)) <
+ 0) {
+ flog_err_sys(EC_LIB_SYSTEM_CALL,
+ "%s failed: setsockopt TCP_KEEPINTVL (%d): %s",
+ __func__, sock, safe_strerror(errno));
+ return -1;
+ }
+
+ /* Set maximum probes */
+ val = keepalive_probes;
+ if (setsockopt(sock, IPPROTO_TCP, TCP_KEEPCNT, &val, sizeof(val)) < 0) {
+ flog_err_sys(EC_LIB_SYSTEM_CALL,
+ "%s failed: setsockopt TCP_KEEPCNT (%d): %s",
+ __func__, sock, safe_strerror(errno));
+ return -1;
+ }
+
+ return 0;
+#endif
+}
* Socket to get max segement size.
*/
extern int sockopt_tcp_mss_get(int sock);
+
+/*
+ * Configure TCP keepalive for a given socket
+ *
+ * sock
+ * Socket to enable keepalive option on.
+ *
+ * keepalive_idle
+ * number of seconds a connection needs to be idle
+ * before sending out keep-alive proves
+ *
+ * keepalive_intvl
+ * number of seconds between TCP keep-alive probes
+ *
+ * keepalive_probes
+ * max number of probers to send before giving up
+ * and killing tcp connection
+ */
+extern int setsockopt_tcp_keepalive(int sock, uint16_t keepalive_idle,
+ uint16_t keepalive_intvl,
+ uint16_t keepalive_probes);
+
#ifdef __cplusplus
}
#endif
struct thash_item **np = &h->hh.entries[hbits]; \
while (*np && (*np)->hashval < hval) \
np = &(*np)->next; \
- if (*np && cmpfn(container_of(*np, type, field.hi), item) == 0) { \
- h->hh.count--; \
- return container_of(*np, type, field.hi); \
+ while (*np && (*np)->hashval == hval) { \
+ if (cmpfn(container_of(*np, type, field.hi), item) == 0) { \
+ h->hh.count--; \
+ return container_of(*np, type, field.hi); \
+ } \
+ np = &(*np)->next; \
} \
item->field.hi.next = *np; \
*np = &item->field.hi; \
debug_flags_desc[i].str);
}
+ cmd_show_lib_debugs(vty);
+
return CMD_SUCCESS;
}
config_write_ospf6_debug(vty);
+ cmd_show_lib_debugs(vty);
+
return CMD_SUCCESS;
}
unsigned long conf_debug_ospf_lsa = 0;
unsigned long conf_debug_ospf_zebra = 0;
unsigned long conf_debug_ospf_nssa = 0;
-unsigned long conf_debug_ospf_te = 0;
+unsigned long conf_debug_ospf_te;
unsigned long conf_debug_ospf_ext = 0;
-unsigned long conf_debug_ospf_sr = 0;
-unsigned long conf_debug_ospf_ti_lfa = 0;
-unsigned long conf_debug_ospf_defaultinfo = 0;
-unsigned long conf_debug_ospf_ldp_sync = 0;
-unsigned long conf_debug_ospf_gr = 0;
+unsigned long conf_debug_ospf_sr;
+unsigned long conf_debug_ospf_ti_lfa;
+unsigned long conf_debug_ospf_defaultinfo;
+unsigned long conf_debug_ospf_ldp_sync;
+unsigned long conf_debug_ospf_gr;
unsigned long conf_debug_ospf_bfd;
unsigned long conf_debug_ospf_client_api;
unsigned long term_debug_ospf_lsa = 0;
unsigned long term_debug_ospf_zebra = 0;
unsigned long term_debug_ospf_nssa = 0;
-unsigned long term_debug_ospf_te = 0;
+unsigned long term_debug_ospf_te;
unsigned long term_debug_ospf_ext = 0;
-unsigned long term_debug_ospf_sr = 0;
-unsigned long term_debug_ospf_ti_lfa = 0;
+unsigned long term_debug_ospf_sr;
+unsigned long term_debug_ospf_ti_lfa;
unsigned long term_debug_ospf_defaultinfo;
unsigned long term_debug_ospf_ldp_sync;
-unsigned long term_debug_ospf_gr = 0;
+unsigned long term_debug_ospf_gr;
unsigned long term_debug_ospf_bfd;
unsigned long term_debug_ospf_client_api;
stream_set_getp(s, gp);
}
-DEFUN (debug_ospf_packet,
+DEFPY (debug_ospf_packet,
debug_ospf_packet_cmd,
- "debug ospf [(1-65535)] packet <hello|dd|ls-request|ls-update|ls-ack|all> [<send [detail]|recv [detail]|detail>]",
- DEBUG_STR
- OSPF_STR
- "Instance ID\n"
- "OSPF packets\n"
- "OSPF Hello\n"
- "OSPF Database Description\n"
- "OSPF Link State Request\n"
- "OSPF Link State Update\n"
- "OSPF Link State Acknowledgment\n"
- "OSPF all packets\n"
- "Packet sent\n"
- "Detail Information\n"
- "Packet received\n"
- "Detail Information\n"
- "Detail Information\n")
-{
- int inst = (argv[2]->type == RANGE_TKN) ? 1 : 0;
- int detail = strmatch(argv[argc - 1]->text, "detail");
- int send = strmatch(argv[argc - (1 + detail)]->text, "send");
- int recv = strmatch(argv[argc - (1 + detail)]->text, "recv");
- char *packet = argv[3 + inst]->text;
-
- if (inst) // user passed instance ID
- {
- if (inst != ospf_instance)
- return CMD_NOT_MY_INSTANCE;
- }
-
- int type = 0;
- int flag = 0;
- int i;
-
- /* Check packet type. */
- if (strmatch(packet, "hello"))
- type = OSPF_DEBUG_HELLO;
- else if (strmatch(packet, "dd"))
- type = OSPF_DEBUG_DB_DESC;
- else if (strmatch(packet, "ls-request"))
- type = OSPF_DEBUG_LS_REQ;
- else if (strmatch(packet, "ls-update"))
- type = OSPF_DEBUG_LS_UPD;
- else if (strmatch(packet, "ls-ack"))
- type = OSPF_DEBUG_LS_ACK;
- else if (strmatch(packet, "all"))
- type = OSPF_DEBUG_ALL;
-
- /* Cases:
- * (none) = send + recv
- * detail = send + recv + detail
- * recv = recv
- * send = send
- * recv detail = recv + detail
- * send detail = send + detail
- */
- if (!send && !recv)
- send = recv = 1;
-
- flag |= (send) ? OSPF_DEBUG_SEND : 0;
- flag |= (recv) ? OSPF_DEBUG_RECV : 0;
- flag |= (detail) ? OSPF_DEBUG_DETAIL : 0;
-
- for (i = 0; i < 5; i++)
- if (type & (0x01 << i)) {
- if (vty->node == CONFIG_NODE)
- DEBUG_PACKET_ON(i, flag);
- else
- TERM_DEBUG_PACKET_ON(i, flag);
- }
-
- return CMD_SUCCESS;
-}
-
-DEFUN (no_debug_ospf_packet,
- no_debug_ospf_packet_cmd,
- "no debug ospf [(1-65535)] packet <hello|dd|ls-request|ls-update|ls-ack|all> [<send [detail]|recv [detail]|detail>]",
+ "[no$no] debug ospf [(1-65535)$inst] packet <hello|dd|ls-request|ls-update|ls-ack|all>$packet [<send$send [detail$detail]|recv$recv [detail$detail]|detail$detail>]",
NO_STR
DEBUG_STR
OSPF_STR
"Detail Information\n"
"Detail Information\n")
{
- int inst = (argv[3]->type == RANGE_TKN) ? 1 : 0;
- int detail = strmatch(argv[argc - 1]->text, "detail");
- int send = strmatch(argv[argc - (1 + detail)]->text, "send");
- int recv = strmatch(argv[argc - (1 + detail)]->text, "recv");
- char *packet = argv[4 + inst]->text;
-
- if (inst) // user passed instance ID
- {
- if (inst != ospf_instance)
- return CMD_NOT_MY_INSTANCE;
- }
-
int type = 0;
int flag = 0;
int i;
+ if (inst && inst != ospf_instance)
+ return CMD_NOT_MY_INSTANCE;
+
/* Check packet type. */
if (strmatch(packet, "hello"))
type = OSPF_DEBUG_HELLO;
* recv detail = recv + detail
* send detail = send + detail
*/
- if (!send && !recv)
- send = recv = 1;
+ if (!send && !recv) {
+ flag |= OSPF_DEBUG_SEND;
+ flag |= OSPF_DEBUG_RECV;
+ }
flag |= (send) ? OSPF_DEBUG_SEND : 0;
flag |= (recv) ? OSPF_DEBUG_RECV : 0;
for (i = 0; i < 5; i++)
if (type & (0x01 << i)) {
- if (vty->node == CONFIG_NODE)
- DEBUG_PACKET_OFF(i, flag);
- else
- TERM_DEBUG_PACKET_OFF(i, flag);
+ if (vty->node == CONFIG_NODE) {
+ if (no)
+ DEBUG_PACKET_OFF(i, flag);
+ else
+ DEBUG_PACKET_ON(i, flag);
+ } else {
+ if (no)
+ TERM_DEBUG_PACKET_OFF(i, flag);
+ else
+ TERM_DEBUG_PACKET_ON(i, flag);
+ }
}
#ifdef DEBUG
return CMD_SUCCESS;
}
-DEFUN (debug_ospf_te,
+DEFPY (debug_ospf_te,
debug_ospf_te_cmd,
- "debug ospf te",
- DEBUG_STR
- OSPF_STR
- "OSPF-TE information\n")
-{
- if (vty->node == CONFIG_NODE)
- CONF_DEBUG_ON(te, TE);
- TERM_DEBUG_ON(te, TE);
- return CMD_SUCCESS;
-}
-
-DEFUN (no_debug_ospf_te,
- no_debug_ospf_te_cmd,
- "no debug ospf te",
+ "[no$no] debug ospf [(1-65535)$instance] te",
NO_STR
DEBUG_STR
OSPF_STR
+ "Instance ID\n"
"OSPF-TE information\n")
{
- if (vty->node == CONFIG_NODE)
- CONF_DEBUG_OFF(te, TE);
- TERM_DEBUG_OFF(te, TE);
+ if (instance && instance != ospf_instance)
+ return CMD_NOT_MY_INSTANCE;
+
+ if (vty->node == CONFIG_NODE) {
+ if (no)
+ DEBUG_OFF(te, TE);
+ else
+ DEBUG_ON(te, TE);
+ } else {
+ if (no)
+ TERM_DEBUG_OFF(te, TE);
+ else
+ TERM_DEBUG_ON(te, TE);
+ }
+
return CMD_SUCCESS;
}
-DEFUN (debug_ospf_sr,
+DEFPY (debug_ospf_sr,
debug_ospf_sr_cmd,
- "debug ospf sr",
+ "[no$no] debug ospf [(1-65535)$instance] sr",
+ NO_STR
DEBUG_STR
OSPF_STR
+ "Instance ID\n"
"OSPF-SR information\n")
{
- if (vty->node == CONFIG_NODE)
- CONF_DEBUG_ON(sr, SR);
- TERM_DEBUG_ON(sr, SR);
+ if (instance && instance != ospf_instance)
+ return CMD_NOT_MY_INSTANCE;
+
+ if (vty->node == CONFIG_NODE) {
+ if (no)
+ DEBUG_OFF(sr, SR);
+ else
+ DEBUG_ON(sr, SR);
+ } else {
+ if (no)
+ TERM_DEBUG_OFF(sr, SR);
+ else
+ TERM_DEBUG_ON(sr, SR);
+ }
+
return CMD_SUCCESS;
}
-DEFUN (no_debug_ospf_sr,
- no_debug_ospf_sr_cmd,
- "no debug ospf sr",
+DEFPY (debug_ospf_ti_lfa,
+ debug_ospf_ti_lfa_cmd,
+ "[no$no] debug ospf [(1-65535)$instance] ti-lfa",
NO_STR
DEBUG_STR
OSPF_STR
- "OSPF-SR information\n")
+ "Instance ID\n"
+ "OSPF-SR TI-LFA information\n")
{
- if (vty->node == CONFIG_NODE)
- CONF_DEBUG_OFF(sr, SR);
- TERM_DEBUG_OFF(sr, SR);
- return CMD_SUCCESS;
-}
+ if (instance && instance != ospf_instance)
+ return CMD_NOT_MY_INSTANCE;
-DEFUN(debug_ospf_ti_lfa, debug_ospf_ti_lfa_cmd, "debug ospf ti-lfa",
- DEBUG_STR OSPF_STR "OSPF-SR TI-LFA information\n")
-{
- if (vty->node == CONFIG_NODE)
- CONF_DEBUG_ON(ti_lfa, TI_LFA);
- TERM_DEBUG_ON(ti_lfa, TI_LFA);
- return CMD_SUCCESS;
-}
+ if (vty->node == CONFIG_NODE) {
+ if (no)
+ DEBUG_OFF(ti_lfa, TI_LFA);
+ else
+ DEBUG_ON(ti_lfa, TI_LFA);
+ } else {
+ if (no)
+ TERM_DEBUG_OFF(ti_lfa, TI_LFA);
+ else
+ TERM_DEBUG_ON(ti_lfa, TI_LFA);
+ }
-DEFUN(no_debug_ospf_ti_lfa, no_debug_ospf_ti_lfa_cmd, "no debug ospf ti-lfa",
- NO_STR DEBUG_STR OSPF_STR "OSPF-SR TI-LFA information\n")
-{
- if (vty->node == CONFIG_NODE)
- CONF_DEBUG_OFF(ti_lfa, TI_LFA);
- TERM_DEBUG_OFF(ti_lfa, TI_LFA);
return CMD_SUCCESS;
}
-DEFUN (debug_ospf_default_info,
+DEFPY (debug_ospf_default_info,
debug_ospf_default_info_cmd,
- "debug ospf default-information",
+ "[no$no] debug ospf [(1-65535)$instance] default-information",
+ NO_STR
DEBUG_STR
OSPF_STR
+ "Instance ID\n"
"OSPF default information\n")
{
- if (vty->node == CONFIG_NODE)
- CONF_DEBUG_ON(defaultinfo, DEFAULTINFO);
- TERM_DEBUG_ON(defaultinfo, DEFAULTINFO);
+ if (instance && instance != ospf_instance)
+ return CMD_NOT_MY_INSTANCE;
+
+ if (vty->node == CONFIG_NODE) {
+ if (no)
+ DEBUG_OFF(defaultinfo, DEFAULTINFO);
+ else
+ DEBUG_ON(defaultinfo, DEFAULTINFO);
+ } else {
+ if (no)
+ TERM_DEBUG_OFF(defaultinfo, DEFAULTINFO);
+ else
+ TERM_DEBUG_ON(defaultinfo, DEFAULTINFO);
+ }
+
return CMD_SUCCESS;
}
-DEFUN (no_debug_ospf_default_info,
- no_debug_ospf_default_info_cmd,
- "no debug ospf default-information",
+DEFPY (debug_ospf_ldp_sync,
+ debug_ospf_ldp_sync_cmd,
+ "[no$no] debug ospf [(1-65535)$instance] ldp-sync",
NO_STR
DEBUG_STR
OSPF_STR
- "OSPF default information\n")
-{
- if (vty->node == CONFIG_NODE)
- CONF_DEBUG_OFF(defaultinfo, DEFAULTINFO);
- TERM_DEBUG_OFF(defaultinfo, DEFAULTINFO);
- return CMD_SUCCESS;
-}
-
-DEFUN(debug_ospf_ldp_sync,
- debug_ospf_ldp_sync_cmd,
- "debug ospf ldp-sync",
- DEBUG_STR OSPF_STR
- "OSPF LDP-Sync information\n")
+ "Instance ID\n"
+ "OSPF LDP-Sync information\n")
{
- if (vty->node == CONFIG_NODE)
- CONF_DEBUG_ON(ldp_sync, LDP_SYNC);
- TERM_DEBUG_ON(ldp_sync, LDP_SYNC);
- return CMD_SUCCESS;
-}
+ if (instance && instance != ospf_instance)
+ return CMD_NOT_MY_INSTANCE;
-DEFUN(no_debug_ospf_ldp_sync,
- no_debug_ospf_ldp_sync_cmd,
- "no debug ospf ldp-sync",
- NO_STR
- DEBUG_STR
- OSPF_STR
- "OSPF LDP-Sync information\n")
-{
- if (vty->node == CONFIG_NODE)
- CONF_DEBUG_OFF(ldp_sync, LDP_SYNC);
- TERM_DEBUG_OFF(ldp_sync, LDP_SYNC);
+ if (vty->node == CONFIG_NODE) {
+ if (no)
+ DEBUG_OFF(ldp_sync, LDP_SYNC);
+ else
+ DEBUG_ON(ldp_sync, LDP_SYNC);
+ } else {
+ if (no)
+ TERM_DEBUG_OFF(ldp_sync, LDP_SYNC);
+ else
+ TERM_DEBUG_ON(ldp_sync, LDP_SYNC);
+ }
return CMD_SUCCESS;
}
-DEFPY(debug_ospf_gr, debug_ospf_gr_cmd, "[no$no] debug ospf graceful-restart",
- NO_STR DEBUG_STR OSPF_STR "OSPF Graceful Restart\n")
+DEFPY (debug_ospf_gr,
+ debug_ospf_gr_cmd,
+ "[no$no] debug ospf [(1-65535)$instance] graceful-restart",
+ NO_STR
+ DEBUG_STR
+ OSPF_STR
+ "Instance ID\n"
+ "OSPF Graceful Restart\n")
{
- if (vty->node == CONFIG_NODE)
- CONF_DEBUG_ON(gr, GR);
+ if (instance && instance != ospf_instance)
+ return CMD_NOT_MY_INSTANCE;
- if (!no)
- TERM_DEBUG_ON(gr, GR);
- else
+ if (vty->node == CONFIG_NODE) {
+ if (no)
+ CONF_DEBUG_OFF(gr, GR);
+ else
+ CONF_DEBUG_ON(gr, GR);
+ }
+
+ if (no)
TERM_DEBUG_OFF(gr, GR);
+ else
+ TERM_DEBUG_ON(gr, GR);
return CMD_SUCCESS;
}
-DEFPY(debug_ospf_bfd, debug_ospf_bfd_cmd,
- "[no] debug ospf bfd",
- NO_STR
- DEBUG_STR
- OSPF_STR
- "Bidirection Forwarding Detection\n")
+DEFPY (debug_ospf_bfd,
+ debug_ospf_bfd_cmd,
+ "[no] debug ospf [(1-65535)$instance] bfd",
+ NO_STR
+ DEBUG_STR
+ OSPF_STR
+ "Instance ID\n"
+ "Bidirection Forwarding Detection\n")
{
+ if (instance && instance != ospf_instance)
+ return CMD_NOT_MY_INSTANCE;
+
if (vty->node == CONFIG_NODE) {
if (no) {
bfd_protocol_integration_set_debug(false);
- CONF_DEBUG_OFF(bfd, BFD_LIB);
+ DEBUG_OFF(bfd, BFD_LIB);
} else {
bfd_protocol_integration_set_debug(true);
- CONF_DEBUG_ON(bfd, BFD_LIB);
+ DEBUG_ON(bfd, BFD_LIB);
}
+ } else {
+ if (no)
+ TERM_DEBUG_OFF(bfd, BFD_LIB);
+ else
+ TERM_DEBUG_ON(bfd, BFD_LIB);
}
- if (no)
- TERM_DEBUG_OFF(bfd, BFD_LIB);
- else
- TERM_DEBUG_ON(bfd, BFD_LIB);
-
return CMD_SUCCESS;
}
-DEFUN(debug_ospf_client_api,
- debug_ospf_client_api_cmd,
- "debug ospf client-api",
- DEBUG_STR OSPF_STR
- "OSPF client API information\n")
+DEFPY (debug_ospf_client_api,
+ debug_ospf_client_api_cmd,
+ "[no$no] debug ospf [(1-65535)$instance] client-api",
+ NO_STR
+ DEBUG_STR
+ OSPF_STR
+ "Instance ID\n"
+ "OSPF client API information\n")
{
- if (vty->node == CONFIG_NODE)
- CONF_DEBUG_ON(client_api, CLIENT_API);
- TERM_DEBUG_ON(client_api, CLIENT_API);
- return CMD_SUCCESS;
-}
+ if (instance && instance != ospf_instance)
+ return CMD_NOT_MY_INSTANCE;
-DEFUN(no_debug_ospf_client_api,
- no_debug_ospf_client_api_cmd,
- "no debug ospf client-api",
- NO_STR
- DEBUG_STR
- OSPF_STR
- "OSPF client API information\n")
-{
- if (vty->node == CONFIG_NODE)
- CONF_DEBUG_OFF(client_api, CLIENT_API);
- TERM_DEBUG_OFF(client_api, CLIENT_API);
+ if (vty->node == CONFIG_NODE) {
+ if (no)
+ DEBUG_OFF(client_api, CLIENT_API);
+ else
+ DEBUG_ON(client_api, CLIENT_API);
+ } else {
+ if (no)
+ TERM_DEBUG_OFF(client_api, CLIENT_API);
+ else
+ TERM_DEBUG_ON(client_api, CLIENT_API);
+ }
return CMD_SUCCESS;
}
}
if (IS_DEBUG_OSPF(defaultinfo, DEFAULTINFO) == OSPF_DEBUG_DEFAULTINFO)
- vty_out(vty, "OSPF default information is on\n");
+ vty_out(vty, " OSPF default information is on\n");
/* Show debug status for NSSA. */
if (IS_DEBUG_OSPF(nssa, NSSA) == OSPF_DEBUG_NSSA)
DEBUG_STR
OSPF_STR)
{
- return show_debugging_ospf_common(vty);
+ show_debugging_ospf_common(vty);
+
+ cmd_show_lib_debugs(vty);
+
+ return CMD_SUCCESS;
}
DEFUN_NOSH (show_debugging_ospf_instance,
if (instance != ospf_instance)
return CMD_NOT_MY_INSTANCE;
- return show_debugging_ospf_common(vty);
+ show_debugging_ospf_common(vty);
+
+ cmd_show_lib_debugs(vty);
+
+ return CMD_SUCCESS;
}
static int config_write_debug(struct vty *vty);
& (OSPF_DEBUG_SEND_RECV | OSPF_DEBUG_DETAIL);
if (r == (OSPF_DEBUG_SEND_RECV | OSPF_DEBUG_DETAIL)) {
vty_out(vty, "debug ospf%s packet all detail\n", str);
- return 1;
+ write = 1;
}
/* debug ospf packet all. */
if (conf_debug_ospf_packet[i] & OSPF_DEBUG_DETAIL)
vty_out(vty, "debug ospf%s packet %s detail\n",
str, type_str[i]);
- return 1;
+ write = 1;
}
/* debug ospf packet (hello|dd|ls-request|ls-update|ls-ack)
write = 1;
}
+ /* debug ospf default-information */
+ if (IS_CONF_DEBUG_OSPF(defaultinfo, DEFAULTINFO) ==
+ OSPF_DEBUG_DEFAULTINFO) {
+ vty_out(vty, "debug ospf%s default-information\n", str);
+ write = 1;
+ }
+
return write;
}
install_element(ENABLE_NODE, &no_debug_ospf_zebra_cmd);
install_element(ENABLE_NODE, &no_debug_ospf_event_cmd);
install_element(ENABLE_NODE, &no_debug_ospf_nssa_cmd);
- install_element(ENABLE_NODE, &no_debug_ospf_te_cmd);
- install_element(ENABLE_NODE, &no_debug_ospf_sr_cmd);
- install_element(ENABLE_NODE, &no_debug_ospf_ti_lfa_cmd);
- install_element(ENABLE_NODE, &no_debug_ospf_default_info_cmd);
- install_element(ENABLE_NODE, &no_debug_ospf_ldp_sync_cmd);
- install_element(ENABLE_NODE, &no_debug_ospf_client_api_cmd);
install_element(ENABLE_NODE, &debug_ospf_gr_cmd);
install_element(ENABLE_NODE, &debug_ospf_bfd_cmd);
install_element(ENABLE_NODE, &show_debugging_ospf_instance_cmd);
install_element(ENABLE_NODE, &debug_ospf_packet_cmd);
- install_element(ENABLE_NODE, &no_debug_ospf_packet_cmd);
install_element(ENABLE_NODE, &debug_ospf_instance_nsm_cmd);
install_element(ENABLE_NODE, &debug_ospf_instance_lsa_cmd);
install_element(ENABLE_NODE, &no_debug_ospf_cmd);
install_element(CONFIG_NODE, &debug_ospf_packet_cmd);
- install_element(CONFIG_NODE, &no_debug_ospf_packet_cmd);
install_element(CONFIG_NODE, &debug_ospf_ism_cmd);
install_element(CONFIG_NODE, &no_debug_ospf_ism_cmd);
install_element(CONFIG_NODE, &no_debug_ospf_zebra_cmd);
install_element(CONFIG_NODE, &no_debug_ospf_event_cmd);
install_element(CONFIG_NODE, &no_debug_ospf_nssa_cmd);
- install_element(CONFIG_NODE, &no_debug_ospf_te_cmd);
- install_element(CONFIG_NODE, &no_debug_ospf_sr_cmd);
- install_element(CONFIG_NODE, &no_debug_ospf_ti_lfa_cmd);
- install_element(CONFIG_NODE, &no_debug_ospf_default_info_cmd);
- install_element(CONFIG_NODE, &no_debug_ospf_ldp_sync_cmd);
- install_element(CONFIG_NODE, &no_debug_ospf_client_api_cmd);
install_element(CONFIG_NODE, &debug_ospf_gr_cmd);
install_element(CONFIG_NODE, &debug_ospf_bfd_cmd);
return CMD_SUCCESS;
}
-#if CONFDATE > 20220921
-CPP_NOTICE(
- "Time to remove the deprecated \"[no] graceful-restart helper-only\" commands")
-#endif
-
-DEFPY_HIDDEN(ospf_gr_helper_only, ospf_gr_helper_only_cmd,
- "graceful-restart helper-only [A.B.C.D]",
- "OSPF Graceful Restart\n"
- "Enable Helper support\n"
- "Advertising router id\n")
-{
- VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
- struct in_addr addr;
- int ret;
-
- vty_out(vty,
- "%% This command is deprecated. Please, use `graceful-restart helper enable` instead.\n");
-
- if (argc == 3) {
- ret = inet_aton(argv[2]->arg, &addr);
- if (!ret) {
- vty_out(vty,
- "Please specify the valid routerid address.\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- ospf_gr_helper_support_set_per_routerid(ospf, &addr, OSPF_GR_TRUE);
- return CMD_SUCCESS;
- }
-
- ospf_gr_helper_support_set(ospf, OSPF_GR_TRUE);
-
- return CMD_SUCCESS;
-}
-
-ALIAS_HIDDEN(no_ospf_gr_helper_enable,
- no_ospf_gr_helper_only_cmd,
- "no graceful-restart helper-only [A.B.C.D]",
- NO_STR
- "OSPF Graceful Restart\n"
- "Disable Helper support\n"
- "Advertising router id\n")
-
DEFPY(ospf_gr_helper_enable_lsacheck,
ospf_gr_helper_enable_lsacheck_cmd,
"graceful-restart helper strict-lsa-checking",
/*Ospf garcefull restart helper configurations */
install_element(OSPF_NODE, &ospf_gr_helper_enable_cmd);
install_element(OSPF_NODE, &no_ospf_gr_helper_enable_cmd);
- install_element(OSPF_NODE, &ospf_gr_helper_only_cmd);
- install_element(OSPF_NODE, &no_ospf_gr_helper_only_cmd);
install_element(OSPF_NODE, &ospf_gr_helper_enable_lsacheck_cmd);
install_element(OSPF_NODE, &no_ospf_gr_helper_enable_lsacheck_cmd);
install_element(OSPF_NODE, &ospf_gr_helper_supported_grace_time_cmd);
"State of each debugging option\n"
"pathd module debugging\n")
{
+
+ cmd_show_lib_debugs(vty);
/* nothing to do here */
return CMD_SUCCESS;
}
}
break;
case IPADDR_V6:
- key = (uint64_t)(local->ip._v6_addr.s6_addr32[0] & 0xffffffff)
- | ((uint64_t)local->ip._v6_addr.s6_addr32[1] << 32);
+ key = (uint64_t)ntohl(local->ip._v6_addr.s6_addr32[2]) << 32 |
+ (uint64_t)ntohl(local->ip._v6_addr.s6_addr32[3]);
edge = ls_find_edge_by_key(ted_state_g.ted, key);
if (edge) {
- if ((memcmp(&edge->attributes->standard.remote6,
- &remote->ip._v6_addr,
- sizeof(remote->ip._v6_addr))
- && CHECK_FLAG(edge->attributes->flags,
- LS_ATTR_ADJ_SID))) {
- sid = edge->attributes->adj_sid[0]
+ if ((0 == memcmp(&edge->attributes->standard.remote6,
+ &remote->ip._v6_addr,
+ sizeof(remote->ip._v6_addr)) &&
+ CHECK_FLAG(edge->attributes->flags,
+ LS_ATTR_ADJ_SID6))) {
+ sid = edge->attributes->adj_sid[ADJ_PRI_IPV6]
.sid; /* from primary */
break;
}
"Disable the TE Database functionality\n")
/* clang-format on */
{
- if (ted_state_g.enabled) {
+ if (!ted_state_g.enabled) {
PATH_TED_DEBUG("%s: PATHD-TED: OFF -> OFF", __func__);
return CMD_SUCCESS;
}
json_object *json = NULL;
if (!ted_state_g.enabled) {
- vty_out(vty, "PATHD TED database is not enabled\n");
+ vty_out(vty, "Traffic Engineering database is not enabled\n");
return CMD_WARNING;
}
if (strcmp(ver_json, "json") == 0) {
pbr_debug_config_write_helper(vty, false);
+ cmd_show_lib_debugs(vty);
+
return CMD_SUCCESS;
}
pim_debug_config_write(vty);
+ cmd_show_lib_debugs(vty);
+
+ return CMD_SUCCESS;
+}
+
+DEFPY (debug_mld,
+ debug_mld_cmd,
+ "[no] debug mld",
+ NO_STR
+ DEBUG_STR
+ DEBUG_MLD_STR)
+{
+ if (!no) {
+ PIM_DO_DEBUG_GM_EVENTS;
+ PIM_DO_DEBUG_GM_PACKETS;
+ PIM_DO_DEBUG_GM_TRACE;
+ } else {
+ PIM_DONT_DEBUG_GM_EVENTS;
+ PIM_DONT_DEBUG_GM_PACKETS;
+ PIM_DONT_DEBUG_GM_TRACE;
+ }
+
+ return CMD_SUCCESS;
+}
+
+DEFPY (debug_mld_events,
+ debug_mld_events_cmd,
+ "[no] debug mld events",
+ NO_STR
+ DEBUG_STR
+ DEBUG_MLD_STR
+ DEBUG_MLD_EVENTS_STR)
+{
+ if (!no)
+ PIM_DO_DEBUG_GM_EVENTS;
+ else
+ PIM_DONT_DEBUG_GM_EVENTS;
+
+ return CMD_SUCCESS;
+}
+
+DEFPY (debug_mld_packets,
+ debug_mld_packets_cmd,
+ "[no] debug mld packets",
+ NO_STR
+ DEBUG_STR
+ DEBUG_MLD_STR
+ DEBUG_MLD_PACKETS_STR)
+{
+ if (!no)
+ PIM_DO_DEBUG_GM_PACKETS;
+ else
+ PIM_DONT_DEBUG_GM_PACKETS;
+
+ return CMD_SUCCESS;
+}
+
+DEFPY (debug_mld_trace,
+ debug_mld_trace_cmd,
+ "[no] debug mld trace",
+ NO_STR
+ DEBUG_STR
+ DEBUG_MLD_STR
+ DEBUG_MLD_TRACE_STR)
+{
+ if (!no)
+ PIM_DO_DEBUG_GM_TRACE;
+ else
+ PIM_DONT_DEBUG_GM_TRACE;
+
+ return CMD_SUCCESS;
+}
+
+DEFPY (debug_mld_trace_detail,
+ debug_mld_trace_detail_cmd,
+ "[no] debug mld trace detail",
+ NO_STR
+ DEBUG_STR
+ DEBUG_MLD_STR
+ DEBUG_MLD_TRACE_STR
+ "detailed\n")
+{
+ if (!no)
+ PIM_DO_DEBUG_GM_TRACE_DETAIL;
+ else
+ PIM_DONT_DEBUG_GM_TRACE_DETAIL;
+
return CMD_SUCCESS;
}
install_element(ENABLE_NODE, &debug_pimv6_zebra_cmd);
install_element(ENABLE_NODE, &debug_mroute6_cmd);
install_element(ENABLE_NODE, &debug_mroute6_detail_cmd);
+ install_element(ENABLE_NODE, &debug_mld_cmd);
+ install_element(ENABLE_NODE, &debug_mld_events_cmd);
+ install_element(ENABLE_NODE, &debug_mld_packets_cmd);
+ install_element(ENABLE_NODE, &debug_mld_trace_cmd);
+ install_element(ENABLE_NODE, &debug_mld_trace_detail_cmd);
install_element(CONFIG_NODE, &debug_pimv6_cmd);
install_element(CONFIG_NODE, &debug_pimv6_nht_cmd);
install_element(CONFIG_NODE, &debug_pimv6_zebra_cmd);
install_element(CONFIG_NODE, &debug_mroute6_cmd);
install_element(CONFIG_NODE, &debug_mroute6_detail_cmd);
+ install_element(CONFIG_NODE, &debug_mld_cmd);
+ install_element(CONFIG_NODE, &debug_mld_events_cmd);
+ install_element(CONFIG_NODE, &debug_mld_packets_cmd);
+ install_element(CONFIG_NODE, &debug_mld_trace_cmd);
+ install_element(CONFIG_NODE, &debug_mld_trace_detail_cmd);
}
/* clang-format off */
FRR_DAEMON_INFO(pim6d, PIM6,
- .vty_port = 0,
- .flags = FRR_NO_SPLIT_CONFIG,
-
+ .vty_port = PIM6D_VTY_PORT,
.proghelp = "Protocol Independent Multicast (RFC7761) for IPv6",
.signals = pim6d_signals,
char rxbuf[2048];
struct msghdr mh[1] = {};
struct iovec iov[1];
- struct sockaddr_in6 pkt_src[1];
+ struct sockaddr_in6 pkt_src[1] = {};
ssize_t nread;
size_t pktlen;
}
}
-void gm_ifp_teardown(struct interface *ifp)
+void gm_group_delete(struct gm_if *gm_ifp)
{
- struct pim_interface *pim_ifp = ifp->info;
- struct gm_if *gm_ifp;
+ struct gm_sg *sg;
struct gm_packet_state *pkt;
struct gm_grp_pending *pend_grp;
struct gm_gsq_pending *pend_gsq;
struct gm_subscriber *subscriber;
- struct gm_sg *sg;
+
+ while ((pkt = gm_packet_expires_first(gm_ifp->expires)))
+ gm_packet_drop(pkt, false);
+
+ while ((pend_grp = gm_grp_pends_pop(gm_ifp->grp_pends))) {
+ THREAD_OFF(pend_grp->t_expire);
+ XFREE(MTYPE_GM_GRP_PENDING, pend_grp);
+ }
+
+ while ((pend_gsq = gm_gsq_pends_pop(gm_ifp->gsq_pends))) {
+ THREAD_OFF(pend_gsq->t_send);
+ XFREE(MTYPE_GM_GSQ_PENDING, pend_gsq);
+ }
+
+ while ((sg = gm_sgs_pop(gm_ifp->sgs))) {
+ THREAD_OFF(sg->t_sg_expire);
+ assertf(!gm_packet_sg_subs_count(sg->subs_negative), "%pSG",
+ &sg->sgaddr);
+ assertf(!gm_packet_sg_subs_count(sg->subs_positive), "%pSG",
+ &sg->sgaddr);
+
+ gm_sg_free(sg);
+ }
+ while ((subscriber = gm_subscribers_pop(gm_ifp->subscribers))) {
+ assertf(!gm_packets_count(subscriber->packets), "%pPA",
+ &subscriber->addr);
+ XFREE(MTYPE_GM_SUBSCRIBER, subscriber);
+ }
+}
+
+void gm_ifp_teardown(struct interface *ifp)
+{
+ struct pim_interface *pim_ifp = ifp->info;
+ struct gm_if *gm_ifp;
if (!pim_ifp || !pim_ifp->mld)
return;
gm_vrf_socket_decref(gm_ifp->pim);
- while ((pkt = gm_packet_expires_first(gm_ifp->expires)))
- gm_packet_drop(pkt, false);
-
- while ((pend_grp = gm_grp_pends_pop(gm_ifp->grp_pends))) {
- THREAD_OFF(pend_grp->t_expire);
- XFREE(MTYPE_GM_GRP_PENDING, pend_grp);
- }
-
- while ((pend_gsq = gm_gsq_pends_pop(gm_ifp->gsq_pends))) {
- THREAD_OFF(pend_gsq->t_send);
- XFREE(MTYPE_GM_GSQ_PENDING, pend_gsq);
- }
-
- while ((sg = gm_sgs_pop(gm_ifp->sgs))) {
- THREAD_OFF(sg->t_sg_expire);
- assertf(!gm_packet_sg_subs_count(sg->subs_negative), "%pSG",
- &sg->sgaddr);
- assertf(!gm_packet_sg_subs_count(sg->subs_positive), "%pSG",
- &sg->sgaddr);
-
- gm_sg_free(sg);
- }
-
- while ((subscriber = gm_subscribers_pop(gm_ifp->subscribers))) {
- assertf(!gm_packets_count(subscriber->packets), "%pPA",
- &subscriber->addr);
- XFREE(MTYPE_GM_SUBSCRIBER, subscriber);
- }
+ gm_group_delete(gm_ifp);
gm_grp_pends_fini(gm_ifp->grp_pends);
gm_packet_expires_fini(gm_ifp->expires);
}
}
-void gm_group_delete(struct gm_if *gm_ifp)
-{
- struct gm_sg *sg, *sg_start;
-
- sg_start = gm_sgs_first(gm_ifp->sgs);
-
- /* clean up all mld groups */
- frr_each_from (gm_sgs, gm_ifp->sgs, sg, sg_start) {
- THREAD_OFF(sg->t_sg_expire);
- if (sg->oil)
- pim_channel_oil_del(sg->oil, __func__);
- gm_sgs_del(gm_ifp->sgs, sg);
- gm_sg_free(sg);
- }
-}
-
/*
* CLI (show commands only)
*/
gm_ifp->t_other_querier);
json_object_int_add(js_if, "timerRobustnessValue",
gm_ifp->cur_qrv);
+ json_object_int_add(js_if, "lastMemberQueryCount",
+ gm_ifp->cur_lmqc);
json_object_int_add(js_if, "timerQueryIntervalMsec",
gm_ifp->cur_query_intv);
json_object_int_add(js_if, "timerQueryResponseTimerMsec",
DEFPY(gm_show_interface,
gm_show_interface_cmd,
- "show ipv6 mld [vrf <VRF|all>$vrf_str] interface [IFNAME] [detail$detail|json$json]",
- DEBUG_STR
+ "show ipv6 mld [vrf <VRF|all>$vrf_str] interface [IFNAME | detail$detail] [json$json]",
SHOW_STR
IPV6_STR
MLD_STR
VRF_FULL_CMD_HELP_STR
"MLD interface information\n"
+ "Interface name\n"
"Detailed output\n"
JSON_STR)
{
#define PIM_MAX_BITLEN IPV4_MAX_BITLEN
#define PIM_AF_NAME "ip"
#define PIM_AF_DBG "pim"
+#define GM_AF_DBG "igmp"
#define PIM_MROUTE_DBG "mroute"
#define PIMREG "pimreg"
#define GM "IGMP"
#define PIM_MAX_BITLEN IPV6_MAX_BITLEN
#define PIM_AF_NAME "ipv6"
#define PIM_AF_DBG "pimv6"
+#define GM_AF_DBG "mld"
#define PIM_MROUTE_DBG "mroute6"
#define PIMREG "pim6reg"
#define GM "MLD"
bsm_rpinfo = (struct bsmmsg_rpinfo *)buf;
/* unaligned, again */
- memcpy(&rp_addr, &bsm_rpinfo->rpaddr,
+ memcpy(&rp_addr, &bsm_rpinfo->rpaddr.addr,
sizeof(rp_addr));
buf += sizeof(struct bsmmsg_rpinfo);
pim_debug_config_write(vty);
+ cmd_show_lib_debugs(vty);
return CMD_SUCCESS;
}
json_object *json)
{
struct channel_oil *c_oil;
+#if PIM_IPV != 4
+ struct ttable *tt = NULL;
+ char *table = NULL;
+#endif
+ char flag[50];
json_object *json_group = NULL;
json_object *json_ifp_in = NULL;
json_object *json_ifp_out = NULL;
if (!json) {
vty_out(vty,
- "Codes: J -> Pim Join, I -> " GM " Report, S -> Source, * -> Inherited from (*,G), V -> VxLAN, M -> Muted");
+ "Codes: J -> Pim Join, I -> " GM " Report, S -> Source, * -> Inherited from (*,G), V -> VxLAN, M -> Muted\n");
+#if PIM_IPV == 4
vty_out(vty,
- "\nActive Source Group RPT IIF OIL\n");
+ "Active Source Group RPT IIF OIL\n");
+#else
+ /* Prepare table. */
+ tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
+ ttable_add_row(tt, "Active|Source|Group|RPT|IIF|OIL");
+ tt->style.cell.rpad = 2;
+ tt->style.corner = '+';
+ ttable_restyle(tt);
+#endif
}
frr_each (rb_pim_oil, &pim->channel_oil_head, c_oil) {
"wrongInterface",
c_oil->cc.wrong_if);
}
- } else
+ }
+#if PIM_IPV == 4
+ else
vty_out(vty, "%-6d %-15pPAs %-15pPAs %-3s %-16s ",
c_oil->installed, oil_origin(c_oil),
oil_mcastgrp(c_oil), isRpt ? "y" : "n",
in_ifname);
+#endif
for (oif_vif_index = 0; oif_vif_index < MAXVIFS;
++oif_vif_index) {
json_object_object_add(json_ifp_in, out_ifname,
json_ifp_out);
} else {
+ flag[0] = '\0';
+ snprintf(flag, sizeof(flag), "(%c%c%c%c%c)",
+ (c_oil->oif_flags[oif_vif_index] &
+ PIM_OIF_FLAG_PROTO_GM)
+ ? 'I'
+ : ' ',
+ (c_oil->oif_flags[oif_vif_index] &
+ PIM_OIF_FLAG_PROTO_PIM)
+ ? 'J'
+ : ' ',
+ (c_oil->oif_flags[oif_vif_index] &
+ PIM_OIF_FLAG_PROTO_VXLAN)
+ ? 'V'
+ : ' ',
+ (c_oil->oif_flags[oif_vif_index] &
+ PIM_OIF_FLAG_PROTO_STAR)
+ ? '*'
+ : ' ',
+ (c_oil->oif_flags[oif_vif_index] &
+ PIM_OIF_FLAG_MUTE)
+ ? 'M'
+ : ' ');
+
if (first_oif) {
first_oif = 0;
- vty_out(vty, "%s(%c%c%c%c%c)",
- out_ifname,
- (c_oil->oif_flags
- [oif_vif_index] &
- PIM_OIF_FLAG_PROTO_GM)
- ? 'I'
- : ' ',
- (c_oil->oif_flags
- [oif_vif_index] &
- PIM_OIF_FLAG_PROTO_PIM)
- ? 'J'
- : ' ',
- (c_oil->oif_flags
- [oif_vif_index] &
- PIM_OIF_FLAG_PROTO_VXLAN)
- ? 'V'
- : ' ',
- (c_oil->oif_flags
- [oif_vif_index] &
- PIM_OIF_FLAG_PROTO_STAR)
- ? '*'
- : ' ',
- (c_oil->oif_flags
- [oif_vif_index] &
- PIM_OIF_FLAG_MUTE)
- ? 'M'
- : ' ');
- } else
- vty_out(vty, ", %s(%c%c%c%c%c)",
- out_ifname,
- (c_oil->oif_flags
- [oif_vif_index] &
- PIM_OIF_FLAG_PROTO_GM)
- ? 'I'
- : ' ',
- (c_oil->oif_flags
- [oif_vif_index] &
- PIM_OIF_FLAG_PROTO_PIM)
- ? 'J'
- : ' ',
- (c_oil->oif_flags
- [oif_vif_index] &
- PIM_OIF_FLAG_PROTO_VXLAN)
- ? 'V'
- : ' ',
- (c_oil->oif_flags
- [oif_vif_index] &
- PIM_OIF_FLAG_PROTO_STAR)
- ? '*'
- : ' ',
- (c_oil->oif_flags
- [oif_vif_index] &
- PIM_OIF_FLAG_MUTE)
- ? 'M'
- : ' ');
+#if PIM_IPV == 4
+ vty_out(vty, "%s%s", out_ifname, flag);
+#else
+ ttable_add_row(
+ tt, "%d|%pPAs|%pPAs|%s|%s|%s%s",
+ c_oil->installed,
+ oil_origin(c_oil),
+ oil_mcastgrp(c_oil),
+ isRpt ? "y" : "n", in_ifname,
+ out_ifname, flag);
+#endif
+ } else {
+#if PIM_IPV == 4
+ vty_out(vty, ", %s%s", out_ifname,
+ flag);
+#else
+ ttable_add_row(tt,
+ "%c|%c|%c|%c|%c|%s%s",
+ ' ', ' ', ' ', ' ', ' ',
+ out_ifname, flag);
+#endif
+ }
}
}
-
+#if PIM_IPV == 4
if (!json)
vty_out(vty, "\n");
+#endif
}
- if (!json)
+ /* Dump the generated table. */
+ if (!json) {
+#if PIM_IPV == 4
vty_out(vty, "\n");
+#else
+ table = ttable_dump(tt, "\n");
+ vty_out(vty, "%s\n", table);
+ XFREE(MTYPE_TMP, table);
+ ttable_del(tt);
+#endif
+ }
}
/* pim statistics - just adding only bsm related now.
}
}
-static void pim_show_join_helper(struct vty *vty, struct pim_interface *pim_ifp,
+static void pim_show_join_helper(struct pim_interface *pim_ifp,
struct pim_ifchannel *ch, json_object *json,
- time_t now)
+ time_t now, struct ttable *tt)
{
json_object *json_iface = NULL;
json_object *json_row = NULL;
json_object_object_addf(json_grp, json_row, "%pPAs",
&ch->sg.src);
} else {
- vty_out(vty,
- "%-16s %-15pPAs %-15pPAs %-15pPAs %-10s %8s %-6s %5s\n",
+ ttable_add_row(
+ tt, "%s|%pPAs|%pPAs|%pPAs|%s|%s|%s|%s",
ch->interface->name, &ifaddr, &ch->sg.src, &ch->sg.grp,
pim_ifchannel_ifjoin_name(ch->ifjoin_state, ch->flags),
uptime, expire, prune);
struct pim_ifchannel *ch;
struct interface *ifp;
time_t now;
+ struct ttable *tt = NULL;
+ char *table = NULL;
now = pim_time_monotonic_sec();
- if (!json)
- vty_out(vty,
- "Interface Address Source Group State Uptime Expire Prune\n");
+ if (!json) {
+ /* Prepare table. */
+ tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
+ ttable_add_row(
+ tt,
+ "Interface|Address|Source|Group|State|Uptime|Expire|Prune");
+ tt->style.cell.rpad = 2;
+ tt->style.corner = '+';
+ ttable_restyle(tt);
+ }
FOR_ALL_INTERFACES (pim->vrf, ifp) {
pim_ifp = ifp->info;
if (!pim_sgaddr_match(ch->sg, *sg))
continue;
- pim_show_join_helper(vty, pim_ifp, ch, json, now);
+ pim_show_join_helper(pim_ifp, ch, json, now, tt);
} /* scan interface channels */
}
+ /* Dump the generated table. */
+ if (!json) {
+ table = ttable_dump(tt, "\n");
+ vty_out(vty, "%s\n", table);
+ XFREE(MTYPE_TMP, table);
+ ttable_del(tt);
+ }
}
static void pim_show_jp_agg_helper(struct interface *ifp,
enum json_type type;
json_object *json = NULL;
json_object *json_tmp = NULL;
+ struct ttable *tt = NULL;
+ char *table = NULL;
json = json_object_new_object();
if (uj) {
vty_json(vty, json);
} else {
- vty_out(vty,
- "Interface Address Source Group Membership\n");
+ /* Prepare table. */
+ tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
+ ttable_add_row(tt, "Interface|Address|Source|Group|Membership");
+ tt->style.cell.rpad = 2;
+ tt->style.corner = '+';
+ ttable_restyle(tt);
/*
* Example of the json data we are traversing
type = json_object_get_type(if_field_val);
if (type == json_type_object) {
- vty_out(vty, "%-16s ", key);
+ const char *address, *source,
+ *localMembership;
json_object_object_get_ex(
val, "address", &json_tmp);
- vty_out(vty, "%-15s ",
- json_object_get_string(
- json_tmp));
+ address = json_object_get_string(
+ json_tmp);
json_object_object_get_ex(if_field_val,
"source",
&json_tmp);
- vty_out(vty, "%-15s ",
- json_object_get_string(
- json_tmp));
-
- /* Group */
- vty_out(vty, "%-15s ", if_field_key);
+ source = json_object_get_string(
+ json_tmp);
json_object_object_get_ex(
if_field_val, "localMembership",
&json_tmp);
- vty_out(vty, "%-10s\n",
+ localMembership =
json_object_get_string(
- json_tmp));
+ json_tmp);
+
+ ttable_add_row(tt, "%s|%s|%s|%s|%s",
+ key, address, source,
+ if_field_key,
+ localMembership);
}
}
}
json_object_free(json);
+ /* Dump the generated table. */
+ table = ttable_dump(tt, "\n");
+ vty_out(vty, "%s\n", table);
+ XFREE(MTYPE_TMP, table);
+ ttable_del(tt);
}
}
struct interface *ifp;
struct pim_interface *pim_ifp;
struct pim_neighbor *neigh;
+ struct ttable *tt = NULL;
+ char *table = NULL;
time_t now;
char uptime[10];
char expire[10];
now = pim_time_monotonic_sec();
if (!json) {
- vty_out(vty,
- "Interface Neighbor Uptime Holdtime DR Pri\n");
+ /* Prepare table. */
+ tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
+ ttable_add_row(tt, "Interface|Neighbor|Uptime|Holdtime|DR Pri");
+ tt->style.cell.rpad = 2;
+ tt->style.corner = '+';
+ ttable_restyle(tt);
}
FOR_ALL_INTERFACES (pim->vrf, ifp) {
neigh_src_str, json_row);
} else {
- vty_out(vty, "%-16s %15s %8s %8s %6d\n",
- ifp->name, neigh_src_str, uptime,
- expire, neigh->dr_priority);
+ ttable_add_row(tt, "%s|%pPAs|%s|%s|%d",
+ ifp->name, &neigh->source_addr,
+ uptime, expire,
+ neigh->dr_priority);
}
}
json_ifp_rows = NULL;
}
}
+ /* Dump the generated table. */
+ if (!json) {
+ table = ttable_dump(tt, "\n");
+ vty_out(vty, "%s\n", table);
+ XFREE(MTYPE_TMP, table);
+ ttable_del(tt);
+ }
}
int gm_process_query_max_response_time_cmd(struct vty *vty,
uint8_t *curr = tlv_buf;
uint8_t *pastend = tlv_buf + tlv_buf_size;
uint8_t *tmp;
+#if PIM_IPV == 4
struct pim_interface *pim_ifp = ifp->info;
struct pim_instance *pim = pim_ifp->pim;
+#endif
/*
* Append options
/* Secondary Address List */
if (ifp->connected->count) {
- curr = pim_tlv_append_addrlist_ucast(curr, pastend,
- ifp->connected, AF_INET);
+ curr = pim_tlv_append_addrlist_ucast(curr, pastend, ifp,
+ PIM_AF);
if (!curr) {
if (PIM_DEBUG_PIM_HELLO) {
zlog_debug(
- "%s: could not set PIM hello v4 Secondary Address List option for interface %s",
- __func__, ifp->name);
+ "%s: could not set PIM hello %s Secondary Address List option for interface %s",
+ __func__, PIM_AF_NAME, ifp->name);
}
return -4;
}
+#if PIM_IPV == 4
if (pim->send_v6_secondary) {
- curr = pim_tlv_append_addrlist_ucast(
- curr, pastend, ifp->connected, AF_INET6);
+ curr = pim_tlv_append_addrlist_ucast(curr, pastend, ifp,
+ AF_INET6);
if (!curr) {
if (PIM_DEBUG_PIM_HELLO) {
zlog_debug(
return -4;
}
}
+#endif
}
return curr - tlv_buf;
pim_ifp->igmp_version = IGMP_DEFAULT_VERSION;
pim_ifp->mld_version = MLD_DEFAULT_VERSION;
pim_ifp->gm_default_robustness_variable =
- IGMP_DEFAULT_ROBUSTNESS_VARIABLE;
- pim_ifp->gm_default_query_interval = IGMP_GENERAL_QUERY_INTERVAL;
+ GM_DEFAULT_ROBUSTNESS_VARIABLE;
+ pim_ifp->gm_default_query_interval = GM_GENERAL_QUERY_INTERVAL;
pim_ifp->gm_query_max_response_time_dsec =
- IGMP_QUERY_MAX_RESPONSE_TIME_DSEC;
+ GM_QUERY_MAX_RESPONSE_TIME_DSEC;
pim_ifp->gm_specific_query_max_response_time_dsec =
- IGMP_SPECIFIC_QUERY_MAX_RESPONSE_TIME_DSEC;
- pim_ifp->gm_last_member_query_count = IGMP_DEFAULT_ROBUSTNESS_VARIABLE;
+ GM_SPECIFIC_QUERY_MAX_RESPONSE_TIME_DSEC;
+ pim_ifp->gm_last_member_query_count = GM_DEFAULT_ROBUSTNESS_VARIABLE;
/* BSM config on interface: true by default */
pim_ifp->bsm_enable = true;
list_delete(&pim_ifp->upstream_switch_list);
list_delete(&pim_ifp->sec_addr_list);
+ if (pim_ifp->bfd_config.profile)
+ XFREE(MTYPE_TMP, pim_ifp->bfd_config.profile);
+
XFREE(MTYPE_PIM_INTERFACE, pim_ifp->boundary_oil_plist);
XFREE(MTYPE_PIM_INTERFACE, pim_ifp);
return pim_ifp->update_source;
#if PIM_IPV == 6
- if (pim_ifp)
+ if (pim_ifp && !pim_addr_is_any(pim_ifp->ll_highest))
return pim_ifp->ll_highest;
pim_addr best_addr = PIMADDR_ANY;
ntohl(igmp->ifaddr.s_addr), from_str,
ntohl(from.s_addr));
}
- if (ntohl(from.s_addr) < ntohl(igmp->querier_addr.s_addr))
+ /* Reset the other querier timer only if query is received from
+ * the previously elected querier or a better new querier
+ * This will make sure that non-querier elects the new querier
+ * whose ip address is higher than the old querier
+ * in case the old querier goes down via other querier present
+ * timer expiry
+ */
+ if (ntohl(from.s_addr) <= ntohl(igmp->querier_addr.s_addr)) {
igmp->querier_addr.s_addr = from.s_addr;
-
- pim_igmp_other_querier_timer_on(igmp);
+ pim_igmp_other_querier_timer_on(igmp);
+ }
}
/* IGMP version 3 is the only one where we process the RXed query */
#define IGMP_V3_GROUP_RECORD_SOURCE_OFFSET (8)
#define IGMP_CHECKSUM_OFFSET (2)
-/* RFC 3376: 8.1. Robustness Variable - Default: 2 */
-#define IGMP_DEFAULT_ROBUSTNESS_VARIABLE (2)
-
-/* RFC 3376: 8.2. Query Interval - Default: 125 seconds */
-#define IGMP_GENERAL_QUERY_INTERVAL (125)
-
-/* RFC 3376: 8.3. Query Response Interval - Default: 100 deciseconds */
-#define IGMP_QUERY_MAX_RESPONSE_TIME_DSEC (100)
-
-/* RFC 3376: 8.8. Last Member Query Interval - Default: 10 deciseconds */
-#define IGMP_SPECIFIC_QUERY_MAX_RESPONSE_TIME_DSEC (10)
-
#define IGMP_DEFAULT_VERSION (3)
#define IGMP_GET_INT16(ptr, output) \
yang_dnode_get_uint16(args->dnode, NULL);
pim_ifp->gm_specific_query_max_response_time_dsec =
last_member_query_interval;
+#if PIM_IPV == 6
+ gm_ifp_update(ifp);
+#endif
break;
}
last_member_query_count =
yang_dnode_get_uint8(args->dnode, NULL);
pim_ifp->gm_last_member_query_count = last_member_query_count;
-
+#if PIM_IPV == 6
+ gm_ifp_update(ifp);
+#endif
break;
}
#include "pim_tlv.h"
#include "pim_str.h"
#include "pim_msg.h"
+#include "pim_iface.h"
+#include "pim_addr.h"
#if PIM_IPV == 4
#define PIM_MSG_ADDRESS_FAMILY PIM_MSG_ADDRESS_FAMILY_IPV4
}
uint8_t *pim_tlv_append_addrlist_ucast(uint8_t *buf, const uint8_t *buf_pastend,
- struct list *ifconnected, int family)
+ struct interface *ifp, int family)
{
struct listnode *node;
uint16_t option_len = 0;
uint8_t *curr;
size_t uel;
+ struct list *ifconnected = ifp->connected;
+ struct pim_interface *pim_ifp = ifp->info;
+ pim_addr addr;
node = listhead(ifconnected);
struct prefix *p = ifc->address;
int l_encode;
- if (!CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY))
+ addr = pim_addr_from_prefix(p);
+ if (!pim_addr_cmp(pim_ifp->primary_address, addr))
+ /* don't add the primary address
+ * into the secondary address list */
continue;
if ((curr + uel) > buf_pastend)
uint8_t *pim_tlv_append_uint32(uint8_t *buf, const uint8_t *buf_pastend,
uint16_t option_type, uint32_t option_value);
uint8_t *pim_tlv_append_addrlist_ucast(uint8_t *buf, const uint8_t *buf_pastend,
- struct list *ifconnected, int family);
+ struct interface *ifp, int family);
int pim_tlv_parse_holdtime(const char *ifname, pim_addr src_addr,
pim_hello_options *hello_options,
++writes;
}
if (PIM_DEBUG_GM_EVENTS) {
- vty_out(vty, "debug igmp events\n");
+ vty_out(vty, "debug " GM_AF_DBG " events\n");
++writes;
}
if (PIM_DEBUG_GM_PACKETS) {
- vty_out(vty, "debug igmp packets\n");
+ vty_out(vty, "debug " GM_AF_DBG " packets\n");
++writes;
}
/* PIM_DEBUG_GM_TRACE catches _DETAIL too */
if (router->debugs & PIM_MASK_GM_TRACE) {
- vty_out(vty, "debug igmp trace\n");
+ vty_out(vty, "debug " GM_AF_DBG " trace\n");
++writes;
}
if (PIM_DEBUG_GM_TRACE_DETAIL) {
- vty_out(vty, "debug igmp trace detail\n");
+ vty_out(vty, "debug " GM_AF_DBG " trace detail\n");
++writes;
}
/* IF ip igmp query-max-response-time */
if (pim_ifp->gm_query_max_response_time_dsec !=
- IGMP_QUERY_MAX_RESPONSE_TIME_DSEC) {
+ GM_QUERY_MAX_RESPONSE_TIME_DSEC) {
vty_out(vty, " ip igmp query-max-response-time %d\n",
pim_ifp->gm_query_max_response_time_dsec);
++writes;
}
/* IF ip igmp query-interval */
- if (pim_ifp->gm_default_query_interval != IGMP_GENERAL_QUERY_INTERVAL) {
+ if (pim_ifp->gm_default_query_interval != GM_GENERAL_QUERY_INTERVAL) {
vty_out(vty, " ip igmp query-interval %d\n",
pim_ifp->gm_default_query_interval);
++writes;
/* IF ip igmp last-member_query-count */
if (pim_ifp->gm_last_member_query_count !=
- IGMP_DEFAULT_ROBUSTNESS_VARIABLE) {
+ GM_DEFAULT_ROBUSTNESS_VARIABLE) {
vty_out(vty, " ip igmp last-member-query-count %d\n",
pim_ifp->gm_last_member_query_count);
++writes;
/* IF ip igmp last-member_query-interval */
if (pim_ifp->gm_specific_query_max_response_time_dsec !=
- IGMP_SPECIFIC_QUERY_MAX_RESPONSE_TIME_DSEC) {
+ GM_SPECIFIC_QUERY_MAX_RESPONSE_TIME_DSEC) {
vty_out(vty, " ip igmp last-member-query-interval %d\n",
pim_ifp->gm_specific_query_max_response_time_dsec);
++writes;
/* IF ipv6 mld query-max-response-time */
if (pim_ifp->gm_query_max_response_time_dsec !=
- IGMP_QUERY_MAX_RESPONSE_TIME_DSEC)
+ GM_QUERY_MAX_RESPONSE_TIME_DSEC)
vty_out(vty, " ipv6 mld query-max-response-time %d\n",
pim_ifp->gm_query_max_response_time_dsec);
- if (pim_ifp->gm_default_query_interval != IGMP_GENERAL_QUERY_INTERVAL)
+ if (pim_ifp->gm_default_query_interval != GM_GENERAL_QUERY_INTERVAL)
vty_out(vty, " ipv6 mld query-interval %d\n",
pim_ifp->gm_default_query_interval);
/* IF ipv6 mld last-member_query-count */
if (pim_ifp->gm_last_member_query_count !=
- IGMP_DEFAULT_ROBUSTNESS_VARIABLE)
+ GM_DEFAULT_ROBUSTNESS_VARIABLE)
vty_out(vty, " ipv6 mld last-member-query-count %d\n",
pim_ifp->gm_last_member_query_count);
/* IF ipv6 mld last-member_query-interval */
if (pim_ifp->gm_specific_query_max_response_time_dsec !=
- IGMP_SPECIFIC_QUERY_MAX_RESPONSE_TIME_DSEC)
+ GM_SPECIFIC_QUERY_MAX_RESPONSE_TIME_DSEC)
vty_out(vty, " ipv6 mld last-member-query-interval %d\n",
pim_ifp->gm_specific_query_max_response_time_dsec);
#include "pim_memory.h"
#include "pim_assert.h"
-#define PIMD_PROGNAME "pimd"
-#define PIMD_DEFAULT_CONFIG "pimd.conf"
#define PIMD_VTY_PORT 2611
+#define PIM6D_VTY_PORT 2622
#define PIM_IP_PROTO_IGMP (2)
#define PIM_IP_PROTO_PIM (103)
#define PIM_DONT_DEBUG_VXLAN (router->debugs &= ~PIM_MASK_VXLAN)
#define PIM_DONT_DEBUG_BSM (router->debugs &= ~PIM_MASK_BSM_PROC)
+/* RFC 3376: 8.1. Robustness Variable - Default: 2 for IGMP */
+/* RFC 2710: 7.1. Robustness Variable - Default: 2 for MLD */
+#define GM_DEFAULT_ROBUSTNESS_VARIABLE 2
+
+/* RFC 3376: 8.2. Query Interval - Default: 125 seconds for IGMP */
+/* RFC 2710: 7.2. Query Interval - Default: 125 seconds for MLD */
+#define GM_GENERAL_QUERY_INTERVAL 125
+
+/* RFC 3376: 8.3. Query Response Interval - Default: 100 deciseconds for IGMP */
+/* RFC 2710: 7.3. Query Response Interval - Default: 100 deciseconds for MLD */
+#define GM_QUERY_MAX_RESPONSE_TIME_DSEC 100
+
+/* RFC 3376: 8.8. Last Member Query Interval - Default: 10 deciseconds for IGMP
+ */
+/* RFC 2710: 7.8. Last Listener Query Interval - Default: 10 deciseconds for MLD
+ */
+#define GM_SPECIFIC_QUERY_MAX_RESPONSE_TIME_DSEC 10
+
void pim_router_init(void);
void pim_router_terminate(void);
* Wed Jul 20 2022 Martin Winter <mwinter@opensourcerouting.org> - %{version}
+* Tue Oct 04 2022 Donatas Abraitis <donatas@opensourcerouting.org> - 8.4
+
* Wed Jul 13 2022 Jafar Al-Gharaibeh <jafar@atcorp.com> - 8.3
- General:
- Add camelcase json keys in addition to pascalcase (Wrong JSON keys will be depracated)
if (IS_RIP_DEBUG_ZEBRA)
vty_out(vty, " RIP zebra debugging is on\n");
+ cmd_show_lib_debugs(vty);
+
return CMD_SUCCESS;
}
if (IS_RIPNG_DEBUG_ZEBRA)
vty_out(vty, " RIPng zebra debugging is on\n");
+ cmd_show_lib_debugs(vty);
+
return CMD_SUCCESS;
}
{
vty_out(vty, "Sharp debugging status:\n");
+ cmd_show_lib_debugs(vty);
+
return CMD_SUCCESS;
}
static_debug_status_write(vty);
+ cmd_show_lib_debugs(vty);
+
return CMD_SUCCESS;
}
{
#ifdef SHITTY_HASH
/* crappy hash to get some hash collisions */
- return a->val ^ (a->val << 29) ^ 0x55AA0000U;
+ return (a->val & 0xFF) ^ (a->val << 29) ^ 0x55AA0000U;
#else
return jhash_1word(a->val, 0xdeadbeef);
#endif
# 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 requirements are not met, kernel version should be >=4.15")
testsuite_run_time = time.asctime(time.localtime(time.time()))
logger.info("Testsuite start time: {}".format(testsuite_run_time))
tgen, addr_type, dut, input_dict_r1, expected=False
) # pylint: disable=E1123
assert result is not True, (
- "Testcase {} : Failed \n".format(tc_name)
- + "Expected behavior: routes should not present in fib \n"
- + "Error: {}".format(result)
+ "Testcase {} : Failed \n "
+ "Expected: Routes should not be present in {} FIB \n "
+ "Found: {}".format(tc_name, dut, result)
)
step("Verify Ipv4 and Ipv6 network installed in r3 RIB but not in FIB")
tgen, addr_type, dut, input_dict_r1, expected=False
) # pylint: disable=E1123
assert result is not True, (
- "Testcase {} : Failed \n".format(tc_name)
- + "Expected behavior: routes should not present in fib \n"
- + "Error: {}".format(result)
+ "Testcase {} : Failed \n "
+ "Expected: Routes should not be present in {} FIB \n "
+ "Found: {}".format(tc_name, dut, result)
)
write_test_footer(tc_name)
# 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 requirements are not met, 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_bgp_rib(tgen, addr_type, dut, input_dict, expected=False)
- assert result is not True, "Testcase {} : Failed \n ".format(
- tc_name
- ) + " Routes still present in R3 router. Error: {}".format(result)
+ assert result is not True, (
+ "Testcase {} : Failed \n Expected: "
+ "Routes still present in {} router. Found: {}".format(tc_name, dut, result)
+ )
result = verify_rib(
tgen, addr_type, dut, input_dict, protocol=protocol, expected=False
)
assert (
result is not True
- ), "Testcase {} : Failed \n Routes still present in R3 router. Error: {}".format(
- tc_name, result
+ ), "Testcase {} : Failed \n Expected: Routes still present in {} router. Found: {}".format(
+ tc_name, dut, result
)
step("Remove and Add no advertise community")
# Required linux kernel version for this suite to run.
result = required_linux_kernel_version("4.14")
if result is not True:
- pytest.skip("Kernel requirements are not met")
+ pytest.skip("Kernel requirements are not met, kernel version should be >= 4.14")
testsuite_run_time = time.asctime(time.localtime(time.time()))
logger.info("Testsuite start time: {}".format(testsuite_run_time))
],
expected=False,
)
- assert result is not True, "Testcase {} : Failed \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: Routes are still present in rib of r3 \n "
+ "Found: {}".format(tc_name, result)
)
step("Remove route-map from redistribute static on R1")
advertise-map routes present in R2's BGP table are advertised to R3.
TC22: exist-map routes not present in R2's BGP table
advertise-map routes present in R2's BGP table are withdrawn from R3.
+TC23: advertise-map with exist-map configuration is removed from a peer
+ send normal BGP update to advertise previously withdrawn routes if any.
+
TC31: non-exist-map routes not present in R2's BGP table
advertise-map routes present in R2's BGP table are advertised to R3.
TC32: non-exist-map routes present in R2's BGP table
advertise-map routes present in R2's BGP table are withdrawn from R3.
+TC33: advertise-map with non-exist-map configuration is removed from a peer
+ send normal BGP update to advertisepreviously withdrawn routes if any.
TC41: non-exist-map route-map configuration removed in R2.
advertise-map routes present in R2's BGP table are advertised to R3.
return topotest.json_cmp(output, expected)
+def default_route_withdrawn(router):
+ output = json.loads(router.vtysh_cmd("show ip route json"))
+ expected = {
+ "0.0.0.0/0": None,
+ "192.0.2.1/32": [{"protocol": "bgp"}],
+ "192.0.2.5/32": [{"protocol": "bgp"}],
+ "10.139.224.0/20": [{"protocol": "bgp"}],
+ "203.0.113.1/32": [{"protocol": "bgp"}],
+ }
+ return topotest.json_cmp(output, expected)
+
+
# BGP conditional advertisement with route-maps
# EXIST-MAP, ADV-MAP-1 and RMAP-1
def exist_map_routes_present(router):
def non_exist_map_routes_not_present(router):
- output = json.loads(router.vtysh_cmd("show ip route json"))
- expected = {
- "0.0.0.0/0": None,
- "192.0.2.1/32": [{"protocol": "bgp"}],
- "192.0.2.5/32": [{"protocol": "bgp"}],
- "10.139.224.0/20": [{"protocol": "bgp"}],
- "203.0.113.1/32": [{"protocol": "bgp"}],
- }
- return topotest.json_cmp(output, expected)
+ return default_route_withdrawn(router)
def exist_map_no_condition_route_map(router):
failed = "FAILED!!!"
-def test_bgp_conditional_advertisement_step1():
+def test_bgp_conditional_advertisement_tc_1_1():
tgen = get_topogen()
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
logger.info(msg + passed)
-def test_bgp_conditional_advertisement_step2():
+def test_bgp_conditional_advertisement_tc_2_1():
tgen = get_topogen()
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
logger.info(msg + passed)
-def test_bgp_conditional_advertisement_step3():
+def test_bgp_conditional_advertisement_tc_2_2():
tgen = get_topogen()
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
logger.info(msg + passed)
-def test_bgp_conditional_advertisement_step4():
+def test_bgp_conditional_advertisement_tc_2_3():
+ tgen = get_topogen()
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ router1 = tgen.gears["r1"]
+ router2 = tgen.gears["r2"]
+ router3 = tgen.gears["r3"]
+
+ # TC23: advertise-map with exist-map configuration is removed from a peer
+ # send normal BGP update to advertise previously withdrawn routes if any.
+ router2.vtysh_cmd(
+ """
+ configure terminal
+ router bgp 2
+ address-family ipv4 unicast
+ no neighbor 10.10.20.3 advertise-map ADV-MAP-1 exist-map EXIST-MAP
+ """
+ )
+
+ test_func = functools.partial(default_route_withdrawn, router3)
+ success, result = topotest.run_and_expect(test_func, None, count=90, wait=1)
+
+ msg = "TC23: advertise-map with exist-map configuration is removed from peer - "
+ assert result is None, msg + failed
+
+ logger.info(msg + passed)
+
+
+def test_bgp_conditional_advertisement_tc_3_1():
tgen = get_topogen()
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
logger.info(msg + passed)
-def test_bgp_conditional_advertisement_step5():
+def test_bgp_conditional_advertisement_tc_3_2():
tgen = get_topogen()
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
logger.info(msg + passed)
-def test_bgp_conditional_advertisement_step6():
+def test_bgp_conditional_advertisement_tc_3_3():
+ tgen = get_topogen()
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ router1 = tgen.gears["r1"]
+ router2 = tgen.gears["r2"]
+ router3 = tgen.gears["r3"]
+
+ # TC33: advertise-map with non-exist-map configuration is removed from a peer
+ # send normal BGP update to advertisepreviously withdrawn routes if any.
+ router2.vtysh_cmd(
+ """
+ configure terminal
+ router bgp 2
+ address-family ipv4 unicast
+ no neighbor 10.10.20.3 advertise-map ADV-MAP-1 non-exist-map EXIST-MAP
+ """
+ )
+
+ test_func = functools.partial(all_routes_advertised, router3)
+ success, result = topotest.run_and_expect(test_func, None, count=90, wait=1)
+
+ msg = (
+ "TC33: advertise-map with non-exist-map configuration is removed from a peer - "
+ )
+ assert result is None, msg + failed
+
+ logger.info(msg + passed)
+
+
+def test_bgp_conditional_advertisement_tc_4_1():
tgen = get_topogen()
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
router2.vtysh_cmd(
"""
configure terminal
+ router bgp 2
+ address-family ipv4 unicast
+ neighbor 10.10.20.3 advertise-map ADV-MAP-1 non-exist-map EXIST-MAP
no route-map EXIST-MAP permit 10
"""
)
logger.info(msg + passed)
-def test_bgp_conditional_advertisement_step7():
+def test_bgp_conditional_advertisement_tc_4_2():
tgen = get_topogen()
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
logger.info(msg + passed)
-def test_bgp_conditional_advertisement_step8():
+def test_bgp_conditional_advertisement_tc_5_1():
tgen = get_topogen()
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
logger.info(msg + passed)
-def test_bgp_conditional_advertisement_step9():
+def test_bgp_conditional_advertisement_tc_5_2():
tgen = get_topogen()
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
logger.info(msg + passed)
-def test_bgp_conditional_advertisement_step10():
+def test_bgp_conditional_advertisement_tc_5_3():
tgen = get_topogen()
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
logger.info(msg + passed)
-def test_bgp_conditional_advertisement_step11():
+def test_bgp_conditional_advertisement_tc_5_4():
tgen = get_topogen()
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
logger.info(msg + passed)
-def test_bgp_conditional_advertisement_step12():
+def test_bgp_conditional_advertisement_tc_6_1():
tgen = get_topogen()
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
logger.info(msg + passed)
-def test_bgp_conditional_advertisement_step13():
+def test_bgp_conditional_advertisement_tc_6_2():
tgen = get_topogen()
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
logger.info(msg + passed)
-def test_bgp_conditional_advertisement_step14():
+def test_bgp_conditional_advertisement_tc_6_3():
tgen = get_topogen()
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
logger.info(msg + passed)
-def test_bgp_conditional_advertisement_step15():
+def test_bgp_conditional_advertisement_tc_6_4():
tgen = get_topogen()
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
logger.info(msg + passed)
-def test_bgp_conditional_advertisement_step16():
+def test_bgp_conditional_advertisement_tc_7_1():
tgen = get_topogen()
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
logger.info(msg + passed)
-def test_bgp_conditional_advertisement_step17():
+def test_bgp_conditional_advertisement_tc_7_2():
tgen = get_topogen()
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
logger.info(msg + passed)
-def test_bgp_conditional_advertisement_step18():
+def test_bgp_conditional_advertisement_tc_7_3():
tgen = get_topogen()
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
logger.info(msg + passed)
-def test_bgp_conditional_advertisement_step19():
+def test_bgp_conditional_advertisement_tc_7_4():
tgen = get_topogen()
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
logger.info(msg + passed)
-def test_bgp_conditional_advertisement_step20():
+def test_bgp_conditional_advertisement_tc_8_1():
tgen = get_topogen()
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
logger.info(msg + passed)
-def test_bgp_conditional_advertisement_step21():
+def test_bgp_conditional_advertisement_tc_8_2():
tgen = get_topogen()
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
logger.info(msg + passed)
-def test_bgp_conditional_advertisement_step22():
+def test_bgp_conditional_advertisement_tc_8_3():
tgen = get_topogen()
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
logger.info(msg + passed)
-def test_bgp_conditional_advertisement_step23():
+def test_bgp_conditional_advertisement_tc_8_4():
tgen = get_topogen()
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
logger.info(msg + passed)
-def test_bgp_conditional_advertisement_step24():
+def test_bgp_conditional_advertisement_tc_9_1():
tgen = get_topogen()
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
logger.info(msg + passed)
-def test_bgp_conditional_advertisement_step25():
+def test_bgp_conditional_advertisement_tc_9_2():
tgen = get_topogen()
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
logger.info(msg + passed)
-def test_bgp_conditional_advertisement_step26():
+def test_bgp_conditional_advertisement_tc_9_3():
tgen = get_topogen()
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
logger.info(msg + passed)
-def test_bgp_conditional_advertisement_step27():
+def test_bgp_conditional_advertisement_tc_9_4():
tgen = get_topogen()
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
# 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 requirements are not met, kernel version should be >=4.15")
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 Routes still" " present in RIB".format(tc_name)
+ ), "Testcase {} : Failed \n Expected: Routes still present in {} RIB. Found: {}".format(
+ tc_name, dut, result
+ )
logger.info("Enable redistribute static")
input_dict_2 = {
)
assert (
result is not True
- ), "Testcase {} : Failed \n Routes still" " present in RIB".format(tc_name)
+ ), "Testcase {} : Failed \n Expected: Routes still present in {} RIB. Found: {}".format(
+ tc_name, dut, result
+ )
for addr_type in ADDR_TYPES:
# Enable static routes
)
assert (
result is not True
- ), "Testcase {} : Failed \n Routes still" " present in RIB".format(tc_name)
+ ), "Testcase {} : Failed \n Expected: Routes still present in {} RIB. Found: {}".format(
+ tc_name, dut, result
+ )
static_or_nw(tgen, topo, tc_name, "advertise_nw", "r2")
for addr_type in ADDR_TYPES:
# 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 requirements are not met, kernel version should be >=4.15")
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 Routes still" " present in RIB".format(tc_name)
+ ), "Testcase {} : Failed \n Expected: Routes still present in {} RIB. Found: {}".format(
+ tc_name, dut, result
+ )
logger.info("Enable redistribute static")
input_dict_2 = {
)
assert (
result is not True
- ), "Testcase {} : Failed \n Routes still" " present in RIB".format(tc_name)
+ ), "Testcase {} : Failed \n Expected: Routes still present in {} RIB. Found: {}".format(
+ tc_name, dut, result
+ )
for addr_type in ADDR_TYPES:
# Enable static routes
)
assert (
result is not True
- ), "Testcase {} : Failed \n Routes still" " present in RIB".format(tc_name)
+ ), "Testcase {} : Failed \n Expected: Routes still present in {} RIB. Found: {}".format(
+ tc_name, dut, result
+ )
static_or_nw(tgen, topo, tc_name, "advertise_nw", "r2")
for addr_type in ADDR_TYPES:
logger.info("Ensure BGP has processed the cli")
r2 = tgen.gears["r2"]
output = r2.vtysh_cmd("show run")
- verify = re.search(r"fast-convergence", output )
- assert verify is not None, (
- "r2 does not have the fast convergence command yet")
+ verify = re.search(r"fast-convergence", output)
+ assert verify is not None, "r2 does not have the fast convergence command yet"
logger.info("Shutdown one link b/w r2 and r3")
shutdown_bringup_interface(tgen, "r2", intf1, False)
logger.info("Verify bgp neighbors goes down immediately")
result = verify_bgp_convergence(tgen, topo, dut="r2", expected=False)
- assert result is not True, "Testcase {} : Failed \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: BGP should not be converged for {} \n "
+ "Found: {}".format(tc_name, "r2", result)
)
logger.info("Shutdown second link b/w r2 and r3")
logger.info("Verify bgp neighbors goes down immediately")
result = verify_bgp_convergence(tgen, topo, dut="r2", expected=False)
- assert result is not True, "Testcase {} : Failed \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: BGP should not be converged for {} \n "
+ "Found: {}".format(tc_name, "r2", result)
)
write_test_footer(tc_name)
# Required linux kernel version for this suite to run.
result = required_linux_kernel_version("4.16")
if result is not True:
- pytest.skip("Kernel requirements are not met")
+ pytest.skip("Kernel requirements are not met, kernel version should be >=4.16")
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 "
- "r1: routes are still present in BGP RIB\n Error: {}".format(
- tc_name, result
- )
+ "Expected: Routes should not be present in {} BGP RIB \n "
+ "Found: {}".format(tc_name, dut, result)
)
- logger.info(" Expected behavior: {}".format(result))
# Verifying RIB routes
result = verify_rib(
)
assert result is not True, (
"Testcase {} : Failed \n "
- "r1: routes are still present in ZEBRA\n Error: {}".format(tc_name, result)
+ "Expected: Routes should not be present in {} FIB \n "
+ "Found: {}".format(tc_name, dut, result)
)
- logger.info(" Expected behavior: {}".format(result))
logger.info("[Phase 5] : R2 is about to come up now ")
start_router_daemons(tgen, "r2", ["bgpd"])
result = verify_r_bit(
tgen, topo, addr_type, input_dict, dut="r2", peer="r1", expected=False
)
- assert (
- result is not True
- ), "Testcase {} : Failed \n " "r2: R-bit is set to True\n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: R-bit should not be set to True in r2\n"
+ "Found: {}".format(tc_name, result)
)
logger.info("Restart BGPd on R2 ")
result = verify_r_bit(
tgen, topo, addr_type, input_dict, dut="r2", peer="r1", expected=False
)
- assert (
- result is not True
- ), "Testcase {} : Failed \n " "r2: R-bit is set to True\n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: R-bit should not be set to True in r2\n"
+ "Found: {}".format(tc_name, result)
)
write_test_footer(tc_name)
# Required linux kernel version for this suite to run.
result = required_linux_kernel_version("4.16")
if result is not True:
- pytest.skip("Kernel requirements are not met")
+ pytest.skip("Kernel requirements are not met, kernel version should be >=4.16")
testsuite_run_time = time.asctime(time.localtime(time.time()))
logger.info("Testsuite start time: {}".format(testsuite_run_time))
# Required linux kernel version for this suite to run.
result = required_linux_kernel_version("4.16")
if result is not True:
- pytest.skip("Kernel requirements are not met")
+ pytest.skip("Kernel requirements are not met, kernel version should be >=4.16")
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 "
- "r1: routes are still present in BGP RIB\n Error: {}".format(
- tc_name, result
- )
+ "Expected: Routes should not be present in {} BGP RIB \n "
+ "Found: {}".format(tc_name, dut, result)
)
- logger.info(" Expected behavior: {}".format(result))
# Verifying RIB routes
result = verify_rib(
)
assert result is not True, (
"Testcase {} : Failed \n "
- "r1: routes are still present in ZEBRA\n Error: {}".format(tc_name, result)
+ "Expected: Routes should not be present in {} FIB \n "
+ "Found: {}".format(tc_name, dut, result)
)
- logger.info(" Expected behavior: {}".format(result))
logger.info("[Phase 5] : R2 is about to come up now ")
)
assert result is not True, (
"Testcase {} : Failed \n "
- "r1: routes are still present in ZEBRA\n Error: {}".format(tc_name, result)
+ "Expected: Routes should not be present in {} FIB \n "
+ "Found: {}".format(tc_name, dut, result)
)
logger.info("[Phase 4] : R1 is about to come up now ")
)
assert result is not True, (
"Testcase {} : Failed \n "
- "r1: routes are still present in BGP RIB\n Error: {}".format(
- tc_name, result
- )
+ "Expected: Routes should not be present in {} BGP RIB \n "
+ "Found: {}".format(tc_name, dut, result)
)
- logger.info(" Expected behavior: {}".format(result))
# Verifying RIB routes
protocol = "bgp"
)
assert result is not True, (
"Testcase {} : Failed \n "
- "r1: routes are still present in ZEBRA\n Error: {}".format(tc_name, result)
+ "Expected: Routes should not be present in {} FIB \n "
+ "Found: {}".format(tc_name, dut, result)
)
- logger.info(" Expected behavior: {}".format(result))
logger.info("[Phase 5] : R2 is about to come up now ")
start_router_daemons(tgen, "r2", ["bgpd"])
result = verify_f_bit(
tgen, topo, addr_type, input_dict, dut="r1", peer="r2", expected=False
)
- assert (
- result is not True
- ), "Testcase {} : Failed \n " "r1: F-bit is set to True\n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: F-bit should not be set to True in r1\n"
+ "Found: {}".format(tc_name, result)
)
write_test_footer(tc_name)
)
assert result is not True, (
"Testcase {} : Failed \n "
- "r1: routes are still present in BGP RIB\n Error: {}".format(
- tc_name, result
- )
+ "Expected: Routes should not be present in {} BGP RIB \n "
+ "Found: {}".format(tc_name, dut, result)
)
- logger.info(" Expected behavior: {}".format(result))
# Verifying RIB routes
protocol = "bgp"
)
assert result is not True, (
"Testcase {} : Failed \n "
- "r1: routes are still present in ZEBRA\n Error: {}".format(tc_name, result)
+ "Expected: Routes should not be present in {} FIB \n "
+ "Found: {}".format(tc_name, dut, result)
)
- logger.info(" Expected behavior: {}".format(result))
logger.info("[Phase 5] : R2 is about to come up now ")
start_router_daemons(tgen, "r2", ["bgpd"])
result = verify_r_bit(
tgen, topo, addr_type, input_dict, dut="r1", peer="r2", expected=False
)
- assert (
- result is not True
- ), "Testcase {} : Failed \n " "r1: R-bit is set to True\n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: R-bit should not be set to True in r1\n"
+ "Found: {}".format(tc_name, result)
)
# Verifying BGP RIB routes
result = verify_rib(
tgen, addr_type, dut, input_topo, next_hop, protocol, 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: Routes should not be present in {} FIB \n "
+ "Found: {}".format(tc_name, dut, result)
)
dut = "r2"
)
assert result is not True, (
"Testcase {} : Failed \n "
- "r2: routes are still present in BGP RIB\n Error: {}".format(
- tc_name, result
- )
+ "Expected: Routes should not be present in {} BGP RIB \n "
+ "Found: {}".format(tc_name, dut, result)
)
+
protocol = "bgp"
result = verify_rib(
tgen, addr_type, dut, input_topo, next_hop, protocol, 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: Routes should not be present in {} FIB \n "
+ "Found: {}".format(tc_name, dut, result)
)
step(
)
assert result is not True, (
"Testcase {} : Failed \n "
- "r1: routes are still present in BGP RIB\n Error: {}".format(
- tc_name, result
- )
+ "Expected: Routes should not be present in {} BGP RIB \n "
+ "Found: {}".format(tc_name, dut, result)
)
+
result = verify_rib(
tgen, addr_type, dut, input_topo, next_hop, protocol, 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: Routes should not be present in {} FIB \n "
+ "Found: {}".format(tc_name, dut, result)
)
step("Bring up BGPd on R2 and remove GR related config from R1 in global level")
# Required linux kernel version for this suite to run.
result = required_linux_kernel_version("4.16")
if result is not True:
- pytest.skip("Kernel requirements are not met")
+ pytest.skip("Kernel requirements are not met, kernel version should be >=4.16")
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 "
- "r1: routes are still present in ZEBRA\n Error: {}".format(tc_name, result)
+ "Expected: Routes should not be present in {} FIB \n "
+ "Found: {}".format(tc_name, dut, result)
)
dut = "r2"
)
assert result is not True, (
"Testcase {} : Failed \n "
- "r2: routes are still present in BGP RIB\n Error: {}".format(
- tc_name, result
- )
+ "Expected: Routes should not be present in {} BGP RIB \n "
+ "Found: {}".format(tc_name, dut, result)
)
+
result = verify_rib(
tgen, addr_type, dut, input_topo, next_hop, protocol, expected=False
)
assert result is not True, (
"Testcase {} : Failed \n "
- "r2: routes are still present in ZEBRA\n Error: {}".format(tc_name, result)
+ "Expected: Routes should not be present in {} FIB \n "
+ "Found: {}".format(tc_name, dut, result)
)
step("Bring up BGP on R1 and remove Peer-level GR config from R1")
)
assert result is not True, (
"Testcase {} : Failed \n "
- "r1: routes are still present in BGP RIB\n Error: {}".format(
- tc_name, result
- )
+ "Expected: Routes should not be present in {} BGP RIB \n "
+ "Found: {}".format(tc_name, dut, result)
)
+
result = verify_rib(
tgen, addr_type, dut, input_topo, next_hop, protocol, expected=False
)
assert result is not True, (
"Testcase {} : Failed \n "
- "r1: routes are still present in ZEBRA\n Error: {}".format(tc_name, result)
+ "Expected: Routes should not be present in {} FIB \n "
+ "Found: {}".format(tc_name, dut, result)
)
step("Bring up BGP on R2 and remove Peer-level GR config from R1")
# Required linux kernel version for this suite to run.
result = required_linux_kernel_version("4.16")
if result is not True:
- pytest.skip("Kernel requirements are not met")
+ pytest.skip("Kernel requirements are not met, kernel version should be >=4.16")
global ADDR_TYPES
result = verify_eor(
tgen, topo, addr_type, input_dict, dut="r2", peer="r1", expected=False
)
- assert (
- result is not True
- ), "Testcase {} : Failed \n " "r2: EOR is set to True\n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: EOR should not be set to True in r2\n"
+ "Found: {}".format(tc_name, result)
)
logger.info(
result = verify_eor(
tgen, topo, addr_type, input_dict, dut="r1", peer="r3", expected=False
)
- assert (
- result is not True
- ), "Testcase {} : Failed \n " "r1: EOR is set to True\n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: EOR should not be set to True in r1\n"
+ "Found: {}".format(tc_name, result)
)
logger.info(
result = verify_eor(
tgen, topo, addr_type, input_dict, dut="r3", peer="r1", expected=False
)
- assert (
- result is not True
- ), "Testcase {} : Failed \n " "r3: EOR is set to True\n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: EOR should not be set to True in r3\n"
+ "Found: {}".format(tc_name, result)
)
write_test_footer(tc_name)
result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1, expected=False)
assert result is not True, (
"Testcase {} : Failed \n "
- "r6: routes are still present in BGP RIB\n Error: {}".format(
- tc_name, result
- )
+ "Expected: Routes should not be present in {} BGP RIB \n "
+ "Found: {}".format(tc_name, dut, result)
)
- logger.info(" Expected behavior: {}".format(result))
# Verifying RIB routes before shutting down BGPd daemon
result = verify_rib(tgen, addr_type, dut, input_dict_1, expected=False)
assert result is not True, (
"Testcase {} : Failed \n "
- "r6: routes are still present in ZEBRA\n Error: {}".format(tc_name, result)
+ "Expected: Routes should not be present in {} FIB \n "
+ "Found: {}".format(tc_name, dut, result)
)
- logger.info(" Expected behavior: {}".format(result))
# Verifying BGP RIB routes
dut = "r2"
- result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1, expected=False)
assert result is not True, (
"Testcase {} : Failed \n "
- "r2: routes are still present in BGP RIB\n Error: {}".format(
- tc_name, result
- )
+ "Expected: Routes should not be present in {} BGP RIB \n "
+ "Found: {}".format(tc_name, dut, result)
)
- logger.info(" Expected behavior: {}".format(result))
# Verifying RIB routes before shutting down BGPd daemon
result = verify_rib(tgen, addr_type, dut, input_dict_1, expected=False)
assert result is not True, (
"Testcase {} : Failed \n "
- "r6: routes are still present in ZEBRA\n Error: {}".format(tc_name, result)
+ "Expected: Routes should not be present in {} FIB \n "
+ "Found: {}".format(tc_name, dut, result)
)
- logger.info(" Expected behavior: {}".format(result))
write_test_footer(tc_name)
# Required linux kernel version for this suite to run.
result = required_linux_kernel_version("4.16")
if result is not True:
- pytest.skip("Kernel requirements are not met")
+ pytest.skip("Kernel requirements are not met, kernel version should be >=4.16")
global ADDR_TYPES
result = verify_bgp_rib(tgen, addr_type, dut, input_dict, expected=False)
assert result is not True, (
"Testcase {} : Failed \n "
- "r3: routes are still present in BGP RIB\n Error: {}".format(
- tc_name, result
- )
+ "Expected: Routes should not be present in {} BGP RIB \n "
+ "Found: {}".format(tc_name, dut, result)
)
- logger.info(" Expected behavior: {}".format(result))
# Verifying RIB routes before shutting down BGPd daemon
result = verify_rib(tgen, addr_type, dut, input_dict, expected=False)
assert result is not True, (
"Testcase {} : Failed \n "
- "r3: routes are still present in ZEBRA\n Error: {}".format(tc_name, result)
+ "Expected: Routes should not be present in {} FIB \n "
+ "Found: {}".format(tc_name, dut, result)
)
- logger.info(" Expected behavior: {}".format(result))
logger.info("[Step 4] : Start BGPd daemon on R1..")
)
assert result is not True, (
"Testcase {} : Failed \n "
- "r3: routes are still present in BGP RIB\n Error: {}".format(
- tc_name, result
- )
+ "Expected: Routes should not be present in {} FIB \n "
+ "Found: {}".format(tc_name, dut, result)
)
- logger.info(" Expected behavior: {}".format(result))
if addr_type == "ipv6":
if "link_local" in PREFERRED_NEXT_HOP:
)
assert result is not True, (
"Testcase {} : Failed \n "
- "r3: routes are still present in ZEBRA\n Error: {}".format(
- tc_name, result
- )
+ "Expected: Routes should not be present in {} FIB \n "
+ "Found: {}".format(tc_name, dut, result)
)
- logger.info(" Expected behavior: {}".format(result))
logger.info("[Step 4] : Start BGPd daemon on R1 and R4..")
result = verify_f_bit(
tgen, topo, addr_type, input_dict, "r3", "r1", expected=False
)
- assert (
- result is not True
- ), "Testcase {} : Failed \n " "r3: F-bit is set to True\n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: F-bit should not be set to True in r3\n"
+ "Found: {}".format(tc_name, result)
)
- logger.info(" Expected behavior: {}".format(result))
# Verifying BGP RIB routes after starting BGPd daemon
input_dict_1 = {key: topo["routers"][key] for key in ["r1"]}
result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1, expected=False)
assert result is not True, (
"Testcase {} : Failed \n "
- "r3: routes are still present in BGP RIB\n Error: {}".format(
- tc_name, result
- )
+ "Expected: Routes should not be present in {} BGP RIB \n "
+ "Found: {}".format(tc_name, dut, result)
)
- logger.info(" Expected behavior: {}".format(result))
# Verifying RIB routes
result = verify_rib(tgen, addr_type, dut, input_dict_1, expected=False)
assert result is not True, (
"Testcase {} : Failed \n "
- "r3: routes are still present in ZEBRA\n Error: {}".format(tc_name, result)
+ "Expected: Routes should not be present in {} FIB \n "
+ "Found: {}".format(tc_name, dut, result)
)
- logger.info(" Expected behavior: {}".format(result))
write_test_footer(tc_name)
# Required linux kernel version for this suite to run.
result = required_linux_kernel_version("4.16")
if result is not True:
- pytest.skip("Kernel requirements are not met")
+ pytest.skip("Kernel requirements are not met, kernel version should be >=4.16")
global ADDR_TYPES
result = verify_f_bit(
tgen, topo, addr_type, input_dict_2, "r3", "r1", expected=False
)
- assert (
- result is not True
- ), "Testcase {} : Failed \n " "r3: F-bit is set to True\n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: F-bit should not be set to True in r3\n"
+ "Found: {}".format(tc_name, result)
)
- logger.info(" Expected behavior: {}".format(result))
logger.info("[Step 3] : Kill BGPd daemon on R1..")
result = verify_bgp_rib(tgen, addr_type, dut, input_dict, expected=False)
assert result is not True, (
"Testcase {} : Failed \n "
- "r3: routes are still present in BGP RIB\n Error: {}".format(
- tc_name, result
- )
+ "Expected: Routes should not be present in {} BGP RIB \n "
+ "Found: {}".format(tc_name, dut, result)
)
- logger.info(" Expected behavior: {}".format(result))
# Verifying RIB routes
result = verify_rib(tgen, addr_type, dut, input_dict, expected=False)
assert result is not True, (
"Testcase {} : Failed \n "
- "r3: routes are still present in ZEBRA\n Error: {}".format(tc_name, result)
+ "Expected: Routes should not be present in {} FIB \n "
+ "Found: {}".format(tc_name, dut, result)
)
- logger.info(" Expected behavior: {}".format(result))
# Start BGPd daemon on R1
start_router_daemons(tgen, "r1", ["bgpd"])
result = verify_eor(
tgen, topo, addr_type, input_dict_3, dut="r5", peer="r1", expected=False
)
- assert (
- result is not True
- ), "Testcase {} : Failed \n " "r5: EOR is set to TRUE\n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: EOR should not be set to True in r5\n"
+ "Found: {}".format(tc_name, result)
)
- logger.info(" Expected behavior: {}".format(result))
# Verifying BGP RIB routes after starting BGPd daemon
input_dict_1 = {key: topo["routers"][key] for key in ["r5"]}
result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1, expected=False)
assert result is not True, (
"Testcase {} : Failed \n "
- "r3: routes are still present in BGP RIB\n Error: {}".format(
- tc_name, result
- )
+ "Expected: Routes should not be present in {} BGP RIB \n "
+ "Found: {}".format(tc_name, dut, result)
)
- logger.info(" Expected behavior: {}".format(result))
# Verifying RIB routes
result = verify_rib(tgen, addr_type, dut, input_dict_1, expected=False)
assert result is not True, (
"Testcase {} : Failed \n "
- "r3: routes are still present in ZEBRA\n Error: {}".format(tc_name, result)
+ "Expected: Routes should not be present in {} FIB \n "
+ "Found: {}".format(tc_name, dut, result)
)
- logger.info(" Expected behavior: {}".format(result))
write_test_footer(tc_name)
result = verify_eor(
tgen, topo, addr_type, input_dict, dut="r3", peer="r1", expected=False
)
- assert (
- result is not True
- ), "Testcase {} : Failed \n " "r3: EOR is set to True\n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: EOR should not be set to True in r3\n"
+ "Found: {}".format(tc_name, result)
)
- logger.info(" Expected behavior: {}".format(result))
# Verifying BGP RIB routes after starting BGPd daemon
dut = "r1"
result = verify_eor(
tgen, topo, addr_type, input_dict_3, dut="r1", peer="r3", expected=False
)
- assert (
- result is not True
- ), "Testcase {} : Failed \n " "r1: EOR is set to True\n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: EOR should not be set to True in r1\n"
+ "Found: {}".format(tc_name, result)
)
write_test_footer(tc_name)
result = verify_bgp_rib(tgen, addr_type, dut, input_dict, expected=False)
assert result is not True, (
"Testcase {} : Failed \n "
- "r1: routes are still present in BGP RIB\n Error: {}".format(
- tc_name, result
- )
+ "Expected: Routes should not be present in {} BGP RIB \n "
+ "Found: {}".format(tc_name, dut, result)
)
- logger.info(" Expected behavior: {}".format(result))
# Verifying RIB routes before shutting down BGPd daemon
result = verify_rib(tgen, addr_type, dut, input_dict, expected=False)
assert result is not True, (
"Testcase {} : Failed \n "
- "r1: routes are still present in ZEBRA\n Error: {}".format(tc_name, result)
+ "Expected: Routes should not be present in {} FIB \n "
+ "Found: {}".format(tc_name, dut, result)
)
- logger.info(" Expected behavior: {}".format(result))
write_test_footer(tc_name)
result = verify_rib(tgen, addr_type, dut, input_dict_1, expected=False)
assert result is not True, (
"Testcase {} : Failed \n "
- "r1: routes are still present in ZEBRA\n Error: {}".format(tc_name, result)
+ "Expected: Routes should not be present in {} FIB \n "
+ "Found: {}".format(tc_name, dut, result)
)
write_test_footer(tc_name)
# Required linux kernel version for this suite to run.
result = required_linux_kernel_version("4.16")
if result is not True:
- pytest.skip("Kernel requirements are not met")
+ pytest.skip("Kernel requirements are not met, kernel version should be >=4.16")
global ADDR_TYPES
result = verify_eor(
tgen, topo, addr_type, input_dict, dut="r1", peer="r2", expected=False
)
- assert (
- result is not True
- ), "Testcase {} : Failed \n " "r1: EOR is set to True\n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: EOR should not be set to True in r2\n"
+ "Found: {}".format(tc_name, result)
)
# Verifying BGP RIB routes received from router R1
result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1, expected=False)
assert result is not True, (
"Testcase {} : Failed \n "
- "r3: routes are still present in BGP RIB\n Error: {}".format(
- tc_name, result
- )
+ "Expected: Routes should not be present in {} BGP RIB \n "
+ "Found: {}".format(tc_name, dut, result)
)
- logger.info(" Expected behavior: {}".format(result))
# Verifying RIB routes before shutting down BGPd daemon
result = verify_rib(tgen, addr_type, dut, input_dict_1, expected=False)
assert result is not True, (
"Testcase {} : Failed \n "
- "r3: routes are still present in ZEBRA\n Error: {}".format(tc_name, result)
+ "Expected: Routes should not be present in {} FIB \n "
+ "Found: {}".format(tc_name, dut, result)
)
- logger.info(" Expected behavior: {}".format(result))
# Start BGPd daemon on R1
start_router_daemons(tgen, "r1", ["bgpd"])
verify_graceful_restart_timers,
verify_bgp_convergence_from_running_config,
)
+
# Import common_config to use commomnly used APIs
-from lib.common_config import (create_common_configuration,
- InvalidCLIError, retry,
- generate_ips, FRRCFG_FILE,
- find_interface_with_greater_ip,
- check_address_types,
- validate_ip_address,
- run_frr_cmd,
- get_frr_ipv6_linklocal)
+from lib.common_config import (
+ create_common_configuration,
+ InvalidCLIError,
+ retry,
+ generate_ips,
+ FRRCFG_FILE,
+ find_interface_with_greater_ip,
+ check_address_types,
+ validate_ip_address,
+ run_frr_cmd,
+ get_frr_ipv6_linklocal,
+)
from lib.common_config import (
write_test_header,
PREFERRED_NEXT_HOP = "link_local"
-def configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name,
- dut, peer):
+def configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut, peer):
"""
result = configure_gr_followed_by_clear(tgen, topo, dut)
assert result is True, \
"""
result = create_router_bgp(tgen, topo, input_dict)
- assert result is True, "Testcase {} : Failed \n Error: {}".format(
- tc_name, result)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
for addr_type in ADDR_TYPES:
clear_bgp(tgen, addr_type, dut)
return True
+
def verify_stale_routes_list(tgen, addr_type, dut, input_dict):
"""
This API is use verify Stale routes on refering the network with next hop value
command = "show bgp"
# Static routes
sleep(2)
- logger.info('Checking router {} BGP RIB:'.format(dut))
- if 'static_routes' in input_dict[routerInput]:
+ logger.info("Checking router {} BGP RIB:".format(dut))
+ if "static_routes" in input_dict[routerInput]:
static_routes = input_dict[routerInput]["static_routes"]
for static_route in static_routes:
found_routes = []
nh_found = False
vrf = static_route.setdefault("vrf", None)
community = static_route.setdefault("community", None)
- largeCommunity = \
- static_route.setdefault("largeCommunity", None)
+ largeCommunity = static_route.setdefault("largeCommunity", None)
if vrf:
- cmd = "{} vrf {} {}".\
- format(command, vrf, addr_type)
+ cmd = "{} vrf {} {}".format(command, vrf, addr_type)
if community:
- cmd = "{} community {}".\
- format(cmd, community)
+ cmd = "{} community {}".format(cmd, community)
if largeCommunity:
- cmd = "{} large-community {}".\
- format(cmd, largeCommunity)
+ cmd = "{} large-community {}".format(cmd, largeCommunity)
else:
- cmd = "{} {}".\
- format(command, addr_type)
+ cmd = "{} {}".format(command, addr_type)
cmd = "{} json".format(cmd)
rib_routes_json = run_frr_cmd(rnode, cmd, isjson=True)
# Verifying output dictionary rib_routes_json is not empty
if bool(rib_routes_json) == False:
- errormsg = "[DUT: {}]: No route found in rib of router". \
- format(router)
+ errormsg = "[DUT: {}]: No route found in rib of router".format(
+ router
+ )
return errormsg
elif "warning" in rib_routes_json:
- errormsg = "[DUT: {}]: {}". \
- format(router, rib_routes_json["warning"])
+ errormsg = "[DUT: {}]: {}".format(
+ router, rib_routes_json["warning"]
+ )
return errormsg
network = static_route["network"]
if "no_of_ip" in static_route:
st_found = True
found_routes.append(st_rt)
- for mnh in range(0, len(rib_routes_json[
- 'routes'][st_rt])):
- found_hops.append([rib_r[
- "ip"] for rib_r in rib_routes_json[
- 'routes'][st_rt][
- mnh]["nexthops"]])
+ for mnh in range(0, len(rib_routes_json["routes"][st_rt])):
+ found_hops.append(
+ [
+ rib_r["ip"]
+ for rib_r in rib_routes_json["routes"][st_rt][
+ mnh
+ ]["nexthops"]
+ ]
+ )
return found_hops
else:
- return 'error msg - no hops found'
+ return "error msg - no hops found"
def setup_module(mod):
# Required linux kernel version for this suite to run.
result = required_linux_kernel_version("4.16")
if result is not True:
- pytest.skip("Kernel requirements are not met")
+ pytest.skip("Kernel requirements are not met, kernel version should be >=4.16")
global ADDR_TYPES
"Testsuite end time: {}".format(time.asctime(time.localtime(time.time())))
)
logger.info("=" * 40)
+
+
################################################################################
#
# TEST CASES
step("Creating 5 static Routes in Router R3 with NULL0 as Next hop")
for addr_type in ADDR_TYPES:
- input_dict_1 = {
- "r3": {
- "static_routes": [{
- "network": [NETWORK1_1[addr_type]] + [NETWORK1_2[addr_type]],
- "next_hop": NEXT_HOP_IP[addr_type]
- },
- {
- "network": [NETWORK2_1[addr_type]] + [NETWORK2_2[addr_type]],
- "next_hop": NEXT_HOP_IP[addr_type]
- },
- {
- "network": [NETWORK3_1[addr_type]] + [NETWORK3_2[addr_type]],
- "next_hop": NEXT_HOP_IP[addr_type]
- },
- {
- "network": [NETWORK4_1[addr_type]] + [NETWORK4_2[addr_type]],
- "next_hop": NEXT_HOP_IP[addr_type]
- },
- {
- "network": [NETWORK5_1[addr_type]] + [NETWORK5_2[addr_type]],
- "next_hop": NEXT_HOP_IP[addr_type]
- }]
- }
+ input_dict_1 = {
+ "r3": {
+ "static_routes": [
+ {
+ "network": [NETWORK1_1[addr_type]] + [NETWORK1_2[addr_type]],
+ "next_hop": NEXT_HOP_IP[addr_type],
+ },
+ {
+ "network": [NETWORK2_1[addr_type]] + [NETWORK2_2[addr_type]],
+ "next_hop": NEXT_HOP_IP[addr_type],
+ },
+ {
+ "network": [NETWORK3_1[addr_type]] + [NETWORK3_2[addr_type]],
+ "next_hop": NEXT_HOP_IP[addr_type],
+ },
+ {
+ "network": [NETWORK4_1[addr_type]] + [NETWORK4_2[addr_type]],
+ "next_hop": NEXT_HOP_IP[addr_type],
+ },
+ {
+ "network": [NETWORK5_1[addr_type]] + [NETWORK5_2[addr_type]],
+ "next_hop": NEXT_HOP_IP[addr_type],
+ },
+ ]
}
- result = create_static_routes(tgen, input_dict_1)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
- tc_name, result)
+ }
+ result = create_static_routes(tgen, input_dict_1)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
step("verifying Created Route at R3 in VRF default")
for addr_type in ADDR_TYPES:
- dut = 'r3'
- input_dict_1= {'r3': topo['routers']['r3']}
+ dut = "r3"
+ input_dict_1 = {"r3": topo["routers"]["r3"]}
result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, \
- "Testcase {} :Failed \n Error {}". \
- format(tc_name, result)
- #done
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+ # done
step("verifying Created Route at R2 in VRF default")
for addr_type in ADDR_TYPES:
- dut = 'r2'
- input_dict_1= {'r2': topo['routers']['r2']}
+ dut = "r2"
+ input_dict_1 = {"r2": topo["routers"]["r2"]}
result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, \
- "Testcase {} :Failed \n Error {}". \
- format(tc_name, result)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
step("importing vrf RED on R2 under Address Family")
for addr_type in ADDR_TYPES:
- input_import_vrf={
+ input_import_vrf = {
"r2": {
"bgp": [
{
"local_as": 200,
"vrf": "RED",
- "address_family": {addr_type: {"unicast": {"import": {"vrf": "default"}}}},
+ "address_family": {
+ addr_type: {"unicast": {"import": {"vrf": "default"}}}
+ },
}
]
}
}
- result = create_router_bgp(tgen, topo,input_import_vrf)
- assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
- #done
+ result = create_router_bgp(tgen, topo, input_import_vrf)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+ # done
step("verifying static Routes at R2 in VRF RED")
for addr_type in ADDR_TYPES:
- dut = 'r2'
- input_dict_1= {'r2': topo['routers']['r2']}
+ dut = "r2"
+ input_dict_1 = {"r2": topo["routers"]["r2"]}
result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, \
- "Testcase {} :Failed \n Error {}". \
- format(tc_name, result)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
step("verifying static Routes at R1 in VRF RED")
for addr_type in ADDR_TYPES:
- dut = 'r1'
- input_dict_1= {'r1': topo['routers']['r1']}
+ dut = "r1"
+ input_dict_1 = {"r1": topo["routers"]["r1"]}
result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, \
- "Testcase {} :Failed \n Error {}". \
- format(tc_name, result)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
step("Configuring Graceful restart at R2 and R3 ")
input_dict = {
"r2": {
-
"bgp": {
"local_as": "200",
"graceful-restart": {
"graceful-restart": True,
- }
+ },
}
},
"r3": {
- "bgp": {
- "local_as": "300",
- "graceful-restart": {
- "graceful-restart": True
- }
- }
- }
+ "bgp": {"local_as": "300", "graceful-restart": {"graceful-restart": True}}
+ },
}
- configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name,dut='r2', peer='r3')
-
-
+ configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r2", peer="r3")
step("verify Graceful restart at R2")
for addr_type in ADDR_TYPES:
- result = verify_graceful_restart(tgen, topo, addr_type, input_dict,
- dut='r2', peer='r3')
- assert result is True, \
- "Testcase {} :Failed \n Error {}". \
- format(tc_name, result)
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r2", peer="r3"
+ )
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
step("verify Graceful restart at R3")
for addr_type in ADDR_TYPES:
- result = verify_graceful_restart(tgen, topo, addr_type, input_dict,
- dut='r3', peer='r2')
- assert result is True, \
- "Testcase {} :Failed \n Error {}". \
- format(tc_name, result)
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r3", peer="r2"
+ )
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
step("Configuring Graceful-restart-disable at R3")
input_dict = {
"r2": {
-
"bgp": {
"local_as": "200",
"graceful-restart": {
"graceful-restart": False,
- }
+ },
}
},
"r3": {
- "bgp": {
- "local_as": "300",
- "graceful-restart": {
- "graceful-restart": False
- }
- }
- }
+ "bgp": {"local_as": "300", "graceful-restart": {"graceful-restart": False}}
+ },
}
- configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name,dut='r3', peer='r2')
+ configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r3", peer="r2")
step("Verify Graceful-restart-disable at R3")
for addr_type in ADDR_TYPES:
- result = verify_graceful_restart(tgen, topo, addr_type, input_dict,
- dut='r3', peer='r2')
- assert result is True, \
- "Testcase {} :Failed \n Error {}". \
- format(tc_name, result)
+ result = verify_graceful_restart(
+ tgen, topo, addr_type, input_dict, dut="r3", peer="r2"
+ )
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
for iteration in range(5):
step("graceful-restart-disable:True at R3")
input_dict = {
- "r3": {
- "bgp": {
- "graceful-restart": {
- "graceful-restart-disable": True,
+ "r3": {
+ "bgp": {
+ "graceful-restart": {
+ "graceful-restart-disable": True,
+ }
}
}
- }
}
- configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name,
- dut='r3', peer='r2')
+ configure_gr_followed_by_clear(
+ tgen, topo, input_dict, tc_name, dut="r3", peer="r2"
+ )
step("Verifying Routes at R2 on enabling GRD")
- dut = 'r2'
+ dut = "r2"
for addr_type in ADDR_TYPES:
- input_dict_1= {'r2': topo['routers']['r2']}
+ input_dict_1 = {"r2": topo["routers"]["r2"]}
result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(
+ tc_name, result
+ )
step("Verify stale Routes in Router R2 enabling GRD")
for addr_type in ADDR_TYPES:
verify_nh_for_static_rtes = {
"r3": {
"static_routes": [
-
{
"network": [NETWORK1_1[addr_type]],
"no_of_ip": 2,
- "vrf": "RED"
+ "vrf": "RED",
}
]
}
}
bgp_rib_next_hops = verify_stale_routes_list(
- tgen, addr_type, dut, verify_nh_for_static_rtes)
- assert (len(bgp_rib_next_hops)== 1) is True, "Testcase {} : Failed \n Error: {}".format(
- tc_name, bgp_rib_next_hops,expected=True)
+ tgen, addr_type, dut, verify_nh_for_static_rtes
+ )
+ assert (
+ len(bgp_rib_next_hops) == 1
+ ) is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, bgp_rib_next_hops, expected=True
+ )
step("graceful-restart-disable:False at R3")
input_dict = {
- "r3": {
- "bgp": {
- "graceful-restart": {
- "graceful-restart-disable": False,
+ "r3": {
+ "bgp": {
+ "graceful-restart": {
+ "graceful-restart-disable": False,
+ }
}
}
- }
}
- configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name,
- dut='r3', peer='r2')
+ configure_gr_followed_by_clear(
+ tgen, topo, input_dict, tc_name, dut="r3", peer="r2"
+ )
step("Verifying Routes at R2 on disabling GRD")
- dut = 'r2'
+ dut = "r2"
for addr_type in ADDR_TYPES:
- input_dict_1= {'r2': topo['routers']['r2']}
+ input_dict_1 = {"r2": topo["routers"]["r2"]}
result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1)
- assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(
+ tc_name, result
+ )
step("Verify stale Routes in Router R2 on disabling GRD")
for addr_type in ADDR_TYPES:
verify_nh_for_static_rtes = {
"r3": {
"static_routes": [
-
{
"network": [NETWORK1_1[addr_type]],
"no_of_ip": 2,
- "vrf": "RED"
+ "vrf": "RED",
}
]
}
}
- bgp_rib_next_hops = verify_stale_routes_list(tgen, addr_type, dut, verify_nh_for_static_rtes)
-
- stale_route_status=len(bgp_rib_next_hops)== 1
- assert stale_route_status is True, "Testcase {} : Failed \n Error: {}".format(
- tc_name, stale_route_status,expected=True)
+ bgp_rib_next_hops = verify_stale_routes_list(
+ tgen, addr_type, dut, verify_nh_for_static_rtes
+ )
+
+ stale_route_status = len(bgp_rib_next_hops) == 1
+ assert (
+ stale_route_status is True
+ ), "Testcase {} : Failed \n Error: {}".format(
+ tc_name, stale_route_status, expected=True
+ )
write_test_footer(tc_name)
-
--- /dev/null
+router bgp 65001
+ no bgp ebgp-requires-policy
+ bgp graceful-restart
+ bgp graceful-restart preserve-fw-state
+ neighbor 192.168.255.2 remote-as external
+ neighbor 192.168.255.2 timers 1 3
+ neighbor 192.168.255.2 timers connect 1
+ address-family ipv4
+ redistribute connected
+ exit-address-family
+!
--- /dev/null
+!
+interface lo
+ ip address 172.16.255.1/32
+!
+interface r1-eth0
+ ip address 192.168.255.1/24
+!
--- /dev/null
+router bgp 65002
+ no bgp ebgp-requires-policy
+ bgp graceful-restart
+ bgp graceful-restart preserve-fw-state
+ neighbor 192.168.255.1 remote-as external
+ neighbor 192.168.255.1 timers 1 3
+ neighbor 192.168.255.1 timers connect 1
+!
--- /dev/null
+no zebra nexthop kernel enable
+!
+interface r2-eth0
+ ip address 192.168.255.2/24
+!
--- /dev/null
+#!/usr/bin/env python
+
+#
+# Copyright (c) 2022 by
+# Donatas Abraitis <donatas@opensourcerouting.org>
+#
+# Permission to use, copy, modify, and/or distribute this software
+# for any purpose with or without fee is hereby granted, provided
+# that the above copyright notice and this permission notice appear
+# in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND NETDEF DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NETDEF BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
+# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+# OF THIS SOFTWARE.
+#
+
+"""
+Test if routes are retained during BGP restarts.
+"""
+
+import os
+import sys
+import json
+import pytest
+import functools
+
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join(CWD, "../"))
+
+# pylint: disable=C0413
+from lib import topotest
+from lib.topogen import Topogen, TopoRouter, get_topogen
+from lib.common_config import step, stop_router
+
+pytestmark = [pytest.mark.bgpd]
+
+
+def build_topo(tgen):
+ for routern in range(1, 3):
+ tgen.add_router("r{}".format(routern))
+
+ switch = tgen.add_switch("s1")
+ switch.add_link(tgen.gears["r1"])
+ switch.add_link(tgen.gears["r2"])
+
+
+def setup_module(mod):
+ tgen = Topogen(build_topo, mod.__name__)
+ tgen.start_topology()
+
+ router_list = tgen.routers()
+
+ for i, (rname, router) in enumerate(router_list.items(), 1):
+ router.load_config(
+ TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname))
+ )
+ router.load_config(
+ TopoRouter.RD_BGP, os.path.join(CWD, "{}/bgpd.conf".format(rname))
+ )
+
+ tgen.start_router()
+
+
+def teardown_module(mod):
+ tgen = get_topogen()
+ tgen.stop_topology()
+
+
+def test_bgp_gr_restart_retain_routes():
+ tgen = get_topogen()
+
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ r1 = tgen.gears["r1"]
+ r2 = tgen.gears["r2"]
+
+ def _bgp_converge():
+ output = json.loads(r2.vtysh_cmd("show bgp ipv4 neighbors 192.168.255.1 json"))
+ expected = {
+ "192.168.255.1": {
+ "bgpState": "Established",
+ "addressFamilyInfo": {"ipv4Unicast": {"acceptedPrefixCounter": 2}},
+ }
+ }
+ return topotest.json_cmp(output, expected)
+
+ def _bgp_check_bgp_retained_routes():
+ output = json.loads(r2.vtysh_cmd("show bgp ipv4 unicast 172.16.255.1/32 json"))
+ expected = {"paths": [{"stale": True}]}
+ return topotest.json_cmp(output, expected)
+
+ def _bgp_check_kernel_retained_routes():
+ output = (
+ r2.cmd("ip route show 172.16.255.1/32 proto bgp dev r2-eth0")
+ .replace("\n", "")
+ .rstrip()
+ )
+ expected = "172.16.255.1 via 192.168.255.1 metric 20"
+ diff = topotest.get_textdiff(
+ output, expected, "Actual IP Routing Table", "Expected IP RoutingTable"
+ )
+ if diff:
+ return False
+ return True
+
+ step("Initial BGP converge")
+ test_func = functools.partial(_bgp_converge)
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
+ assert result is None, "Failed to see BGP convergence on R2"
+
+ step("Restart R1")
+ stop_router(tgen, "r1")
+
+ step("Check if routes (BGP) are retained at R2")
+ test_func = functools.partial(_bgp_check_bgp_retained_routes)
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
+ assert result is None, "Failed to see BGP retained routes on R2"
+
+ step("Check if routes (Kernel) are retained at R2")
+ assert _bgp_check_kernel_retained_routes() == True
+
+
+if __name__ == "__main__":
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))
# Required linux kernel version for this suite to run.
result = required_linux_kernel_version("4.16")
if result is not True:
- pytest.skip("Kernel requirements are not met")
+ pytest.skip("Kernel requirements are not met, kernel version should be >=4.16")
testsuite_run_time = time.asctime(time.localtime(time.time()))
logger.info("Testsuite start time: {}".format(testsuite_run_time))
# Required linux kernel version for this suite to run.
result = required_linux_kernel_version("4.16")
if result is not True:
- pytest.skip("Kernel requirements are not met")
+ pytest.skip("Kernel requirements are not met, kernel version should be >=4.16")
testsuite_run_time = time.asctime(time.localtime(time.time()))
logger.info("Testsuite start time: {}".format(testsuite_run_time))
import sys
import time
import pytest
+import functools
+import json
# Save the Current Working Directory to find configuration files.
CWD = os.path.dirname(os.path.realpath(__file__))
sys.path.append(os.path.join(CWD, "../"))
sys.path.append(os.path.join(CWD, "../../"))
-from lib.topogen import Topogen, get_topogen
+
+from lib import topotest
+from lib.topogen import Topogen, TopoRouter, get_topogen
from lib.common_config import (
write_test_header,
" received on R2 BGP and routing table , "
"verify using show ip bgp, show ip route for IPv4 routes ."
)
-
llip = get_llip("r1", "r2-link0")
assert llip is not None, "Testcase {} : Failed \n Error: {}".format(tc_name, llip)
write_test_footer(tc_name)
+def test_configure_gua_on_unnumbered_intf(request):
+ """
+ Configure a global V6 address on an unnumbered interface on R1
+
+ """
+ tc_name = request.node.name
+ write_test_header(tc_name)
+ tgen = get_topogen()
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+ reset_config_on_routers(tgen)
+
+ step("Configure IPv6 EBGP Unnumbered session between R1 and R2")
+ step("Enable capability extended-nexthop on both the IPv6 BGP peers")
+ step("Activate same IPv6 nbr from IPv4 unicast family")
+ step("Enable cap ext nh on r1 and r2 and activate in ipv4 addr family")
+ step("Verify bgp convergence as ipv6 nbr is enabled on ipv4 addr family.")
+ bgp_convergence = verify_bgp_convergence(tgen, topo)
+ assert bgp_convergence is True, "Testcase {} :Failed \n Error: {}".format(
+ tc_name, bgp_convergence
+ )
+
+ step(" Configure 5 IPv4 static" " routes on R1, Nexthop as different links of R0")
+ for rte in range(0, NO_OF_RTES):
+ # Create Static routes
+ input_dict = {
+ "r1": {
+ "static_routes": [
+ {
+ "network": NETWORK["ipv4"][rte],
+ "no_of_ip": 1,
+ "next_hop": NEXT_HOP["ipv4"][rte],
+ }
+ ]
+ }
+ }
+ result = create_static_routes(tgen, input_dict)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ step(
+ "Advertise static routes from IPv4 unicast family and IPv6 "
+ "unicast family respectively from R1 using red static cmd "
+ "Advertise loopback from IPv4 unicast family using network command "
+ "from R1"
+ )
+
+ configure_bgp_on_r1 = {
+ "r1": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "redistribute": [{"redist_type": "static"}],
+ "advertise_networks": [
+ {"network": NETWORK_CMD_IP, "no_of_network": 1}
+ ],
+ }
+ },
+ "ipv6": {"unicast": {"redistribute": [{"redist_type": "static"}]}},
+ }
+ }
+ }
+ }
+ result = create_router_bgp(tgen, topo, configure_bgp_on_r1)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ r2 = tgen.gears["r2"]
+
+ def bgp_prefix_received_gua_nh(router):
+ output = json.loads(router.vtysh_cmd("show bgp ipv4 unicast 11.0.20.1/32 json"))
+ expected = {
+ "prefix": "11.0.20.1/32",
+ "paths": [
+ {
+ "nexthops": [
+ {
+ "ip": "5001:dead:beef::1",
+ "hostname": "r1",
+ "afi": "ipv6",
+ "scope": "global",
+ }
+ ]
+ }
+ ],
+ }
+ return topotest.json_cmp(output, expected)
+
+ def bgp_prefix_received_v4_mapped_v6_nh(router):
+ output = json.loads(router.vtysh_cmd("show bgp ipv4 unicast 11.0.20.1/32 json"))
+ expected = {
+ "prefix": "11.0.20.1/32",
+ "paths": [
+ {
+ "nexthops": [
+ {
+ "ip": "::ffff:a00:501",
+ "hostname": "r1",
+ "afi": "ipv6",
+ "scope": "global",
+ }
+ ]
+ }
+ ],
+ }
+ return topotest.json_cmp(output, expected)
+
+ step("Configure a global V6 address on an unnumbered interface on R1")
+ output = tgen.gears["r1"].vtysh_cmd(
+ """
+ configure terminal
+ interface r1-r2-eth5
+ ipv6 address 5001:dead:beef::1/126
+ !
+ """
+ )
+
+ # verify that r2 has received prefix with GUA as nexthop
+ test_func = functools.partial(bgp_prefix_received_gua_nh, r2)
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
+ assert (
+ result is None
+ ), "Testcase {} : Failed \n Error: Nexthop for prefix 11.0.20.1 \
+ is not 5001:dead:beef::1".format(
+ tc_name
+ )
+
+ step("Configure a secondary global V6 address on an unnumbered interface on R1")
+ output = tgen.gears["r1"].vtysh_cmd(
+ """
+ configure terminal
+ interface r1-r2-eth5
+ ipv6 address 7771:dead:beef::1/126
+ !
+ """
+ )
+ # verify that r1 did not readvertise the prefix with secondary V6 address as the nexthop
+ test_func = functools.partial(bgp_prefix_received_gua_nh, r2)
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
+ assert (
+ result is None
+ ), "Testcase {} : Failed \n Error: Nexthop for prefix 11.0.20.1 \
+ is not 5001:dead:beef::1".format(
+ tc_name
+ )
+
+ step("Unconfigure the secondary global V6 address from unnumbered interface on R1")
+ output = tgen.gears["r1"].vtysh_cmd(
+ """
+ configure terminal
+ interface r1-r2-eth5
+ no ipv6 address 7771:dead:beef::1/126
+ !
+ """
+ )
+ # verify that r1 still has the prefix with primary GUA as the nexthop
+ test_func = functools.partial(bgp_prefix_received_gua_nh, r2)
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
+ assert (
+ result is None
+ ), "Testcase {} : Failed \n Error: Nexthop for prefix 11.0.20.1 \
+ is not 5001:dead:beef::1".format(
+ tc_name
+ )
+
+ step("Unconfigure the primary global V6 address from unnumbered interface on R1")
+ output = tgen.gears["r1"].vtysh_cmd(
+ """
+ configure terminal
+ interface r1-r2-eth5
+ no ipv6 address 5001:dead:beef::1/126
+ !
+ """
+ )
+ # verify that r1 has rcvd the prefix with v4-mapped-v6 address as the nexthop
+ test_func = functools.partial(bgp_prefix_received_v4_mapped_v6_nh, r2)
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
+ assert (
+ result is None
+ ), "Testcase {} : Failed \n Error: Nexthop for prefix 11.0.20.1 \
+ is not ::ffff:a00:501".format(
+ tc_name
+ )
+
+ write_test_footer(tc_name)
+
+
if __name__ == "__main__":
args = ["-s"] + sys.argv[1:]
sys.exit(pytest.main(args))
--- /dev/null
+router bgp 65001
+ no bgp ebgp-requires-policy
+ neighbor 192.168.1.2 remote-as 65002
+ neighbor 192.168.1.2 local-as 65002
+ neighbor 192.168.1.2 timers 1 3
+ neighbor 192.168.1.2 timers connect 1
+ neighbor PG peer-group
+ neighbor PG remote-as 65003
+ neighbor PG local-as 65003
+ neighbor 192.168.2.2 peer-group PG
+ address-family ipv4
+ redistribute connected
+ exit-address-family
+!
--- /dev/null
+!
+interface lo
+ ip address 172.16.255.1/32
+!
+interface r1-eth0
+ ip address 192.168.1.1/24
+!
+interface r1-eth1
+ ip address 192.168.2.1/24
+!
--- /dev/null
+router bgp 65002
+ no bgp ebgp-requires-policy
+ neighbor 192.168.1.1 remote-as internal
+ neighbor 192.168.1.1 timers 1 3
+ neighbor 192.168.1.1 timers connect 1
+!
--- /dev/null
+!
+interface r2-eth0
+ ip address 192.168.1.2/24
+!
--- /dev/null
+router bgp 65003
+ no bgp ebgp-requires-policy
+ neighbor 192.168.2.1 remote-as internal
+ neighbor 192.168.2.1 timers 1 3
+ neighbor 192.168.2.1 timers connect 1
+!
--- /dev/null
+!
+interface r3-eth0
+ ip address 192.168.2.2/24
+!
--- /dev/null
+#!/usr/bin/env python
+
+#
+# Copyright (c) 2022 by
+# Donatas Abraitis <donatas@opensourcerouting.org>
+#
+# Permission to use, copy, modify, and/or distribute this software
+# for any purpose with or without fee is hereby granted, provided
+# that the above copyright notice and this permission notice appear
+# in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND NETDEF DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NETDEF BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
+# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+# OF THIS SOFTWARE.
+#
+
+"""
+
+"""
+
+import os
+import sys
+import json
+import pytest
+import functools
+
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join(CWD, "../"))
+
+# pylint: disable=C0413
+from lib import topotest
+from lib.topogen import Topogen, TopoRouter, get_topogen
+from lib.common_config import step
+
+pytestmark = [pytest.mark.bgpd]
+
+
+def build_topo(tgen):
+ for routern in range(1, 4):
+ tgen.add_router("r{}".format(routern))
+
+ switch = tgen.add_switch("s1")
+ switch.add_link(tgen.gears["r1"])
+ switch.add_link(tgen.gears["r2"])
+
+ switch = tgen.add_switch("s2")
+ switch.add_link(tgen.gears["r1"])
+ switch.add_link(tgen.gears["r3"])
+
+
+def setup_module(mod):
+ tgen = Topogen(build_topo, mod.__name__)
+ tgen.start_topology()
+
+ router_list = tgen.routers()
+
+ for i, (rname, router) in enumerate(router_list.items(), 1):
+ router.load_config(
+ TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname))
+ )
+ router.load_config(
+ TopoRouter.RD_BGP, os.path.join(CWD, "{}/bgpd.conf".format(rname))
+ )
+
+ tgen.start_router()
+
+
+def teardown_module(mod):
+ tgen = get_topogen()
+ tgen.stop_topology()
+
+
+def test_bgp_local_as_same_remote_as():
+ tgen = get_topogen()
+
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ def _bgp_check_local_as_same_remote_as():
+ output = json.loads(
+ tgen.gears["r2"].vtysh_cmd("show bgp ipv4 unicast 172.16.255.1/32 json")
+ )
+ expected = {
+ "paths": [
+ {
+ "valid": True,
+ "aspath": {"string": "Local"},
+ "nexthops": [{"ip": "192.168.1.1", "hostname": "r1"}],
+ }
+ ]
+ }
+ return topotest.json_cmp(output, expected)
+
+ step("Check if iBGP works when local-as == remote-as")
+ test_func = functools.partial(_bgp_check_local_as_same_remote_as)
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
+ assert result is None, "Failed to see BGP prefixes on R2"
+
+
+def test_bgp_peer_group_local_as_same_remote_as():
+ tgen = get_topogen()
+
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ def _bgp_check_local_as_same_remote_as():
+ output = json.loads(
+ tgen.gears["r3"].vtysh_cmd("show bgp ipv4 unicast 172.16.255.1/32 json")
+ )
+ expected = {
+ "paths": [
+ {
+ "valid": True,
+ "aspath": {"string": "Local"},
+ "nexthops": [{"ip": "192.168.2.1", "hostname": "r1"}],
+ }
+ ]
+ }
+ return topotest.json_cmp(output, expected)
+
+ step("Initial BGP converge")
+ test_func = functools.partial(_bgp_check_local_as_same_remote_as)
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
+ assert result is None, "Failed to see BGP prefixes on R3"
+
+
+if __name__ == "__main__":
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))
result = verify_rib(
tgen, "ipv4", dut, input_dict, protocol=protocol, expected=False
)
- assert (
- result is not True
- ), "Testcase {} : Failed \n Error: Routes still" " present in RIB".format(tc_name)
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: Routes should not be present in {} FIB \n "
+ "Found: {}".format(tc_name, dut, result)
+ )
+
write_test_footer(tc_name)
result = verify_rib(
tgen, "ipv4", dut, input_dict, protocol=protocol, expected=False
)
- assert (
- result is not True
- ), "Testcase {} : Failed \n Error: Routes still" " present in RIB".format(tc_name)
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: Routes should not be present in {} BGP RIB \n "
+ "Found: {}".format(tc_name, dut, result)
+ )
write_test_footer(tc_name)
result = verify_rib(
tgen, "ipv4", dut, input_dict, protocol=protocol, expected=False
)
- assert (
- result is not True
- ), "Testcase {} : Failed \n Error: Routes still" " present in RIB".format(tc_name)
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: Routes should not be present in {} BGP RIB \n "
+ "Found: {}".format(tc_name, dut, result)
+ )
+
write_test_footer(tc_name)
result = verify_rib(
tgen, "ipv4", dut, input_dict, protocol=protocol, expected=False
)
- assert (
- result is not True
- ), "Testcase {} : Failed \n Error: Routes still" " present in RIB".format(tc_name)
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: Routes should not be present in {} BGP RIB \n "
+ "Found: {}".format(tc_name, dut, result)
+ )
write_test_footer(tc_name)
result = verify_rib(
tgen, "ipv4", dut, input_dict, protocol=protocol, expected=False
)
- assert (
- result is not True
- ), "Testcase {} : Failed \n Error: Routes still" " present in RIB".format(tc_name)
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: Routes should not be present in {} BGP RIB \n "
+ "Found: {}".format(tc_name, dut, result)
+ )
# Modify ip prefix list
input_dict_1 = {
result = verify_rib(
tgen, "ipv4", dut, input_dict, protocol=protocol, expected=False
)
- assert (
- result is not True
- ), "Testcase {} : Failed \n Error: Routes still" " present in RIB".format(tc_name)
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: Routes should not be present in {} BGP RIB \n "
+ "Found: {}".format(tc_name, dut, result)
+ )
write_test_footer(tc_name)
result = verify_rib(
tgen, "ipv4", dut, input_dict, protocol=protocol, expected=False
)
- assert (
- result is not True
- ), "Testcase {} : Failed \n Error: Routes still" " present in RIB".format(tc_name)
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: Routes should not be present in {} BGP RIB \n "
+ "Found: {}".format(tc_name, dut, result)
+ )
# Modify ip prefix list
input_dict_1 = {
result = verify_rib(
tgen, "ipv4", dut, input_dict_1, protocol=protocol, expected=False
)
- assert (
- result is not True
- ), "Testcase {} : Failed \n Error: Routes still" " present in RIB".format(tc_name)
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: Routes should not be present in {} BGP RIB \n "
+ "Found: {}".format(tc_name, dut, result)
+ )
write_test_footer(tc_name)
result = verify_rib(
tgen, adt, dut, input_dict_2, protocol=protocol, expected=False
)
- assert (
- result is not True
- ), "Testcase {} : Failed \nroutes are not present in rib \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: Routes should not be present in {} BGP RIB \n "
+ "Found: {}".format(tc_name, dut, result)
)
- logger.info("Expected behaviour: {}".format(result))
# Verifying RIB routes
dut = "r4"
result = verify_rib(
tgen, adt, dut, input_dict, protocol=protocol, expected=False
)
- assert (
- result is not True
- ), "Testcase {} : Failed \nroutes are not present in rib \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: Routes should not be present in {} FIB \n "
+ "Found: {}".format(tc_name, dut, result)
)
- logger.info("Expected behaviour: {}".format(result))
write_test_footer(tc_name)
result = verify_rib(
tgen, adt, dut, input_dict_2, protocol=protocol, expected=False
)
- assert (
- result is not True
- ), "Testcase {} : Failed \nRoutes are still present \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: Routes should not be present in {} FIB \n "
+ "Found: {}".format(tc_name, dut, result)
)
- logger.info("Expected behaviour: {}".format(result))
else:
result = verify_rib(tgen, adt, dut, input_dict_2, protocol=protocol)
assert result is True, "Testcase {} : Failed \n Error: {}".format(
result = verify_rib(
tgen, addr_type, dut, input_dict, protocol=protocol, expected=False
)
- assert (
- result is not True
- ), "Testcase {} : Failed \nroutes are not present \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: Routes should not be present in {} FIB \n "
+ "Found: {}".format(tc_name, dut, result)
)
- logger.info("Expected behaviour: {}".format(result))
# Verifying RIB routes
dut = "r4"
result = verify_rib(
tgen, addr_type, dut, input_dict, protocol=protocol, expected=False
)
- assert (
- result is not True
- ), "Testcase {} : Failed \nExpected behaviour: routes are not present \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: Routes should not be present in {} FIB \n "
+ "Found: {}".format(tc_name, dut, result)
)
write_test_footer(tc_name)
result = verify_rib(
tgen, addr_type, dut, input_dict, protocol=protocol, expected=False
)
- assert (
- result is not True
- ), "Testcase {} : Failed \nroutes are not present \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: Routes should not be present in {} FIB \n "
+ "Found: {}".format(tc_name, dut, result)
)
- logger.info("Expected behaviour: {}".format(result))
# Verifying RIB routes
dut = "r4"
result = verify_rib(
tgen, addr_type, dut, input_dict, protocol=protocol, expected=False
)
- assert (
- result is not True
- ), "Testcase {} : Failed \nroutes are not present \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: Routes should not be present in {} FIB \n "
+ "Found: {}".format(tc_name, dut, result)
)
- logger.info("Expected behaviour: {}".format(result))
write_test_footer(tc_name)
result = verify_rib(
tgen, addr_type, dut, input_dict, protocol=protocol, expected=False
)
- assert (
- result is not True
- ), "Testcase {} : Failed \n Error Routes are still present: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: Routes should not be present in {} FIB \n "
+ "Found: {}".format(tc_name, dut, result)
)
- logger.info("Expected behaviour: {}".format(result))
# Remove applied rmap from neighbor
input_dict_4 = {
result = verify_rib(
tgen, addr_type, dut, input_dict, protocol=protocol, expected=False
)
- assert (
- result is not True
- ), "Testcase {} : Failed \nroutes are not present \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: Routes should not be present in {} FIB \n "
+ "Found: {}".format(tc_name, dut, result)
)
- logger.info("Expected behaviour: {}".format(result))
write_test_footer(tc_name)
# Uncomment next line for debugging
input_dict_3_addr_type[addr_type],
expected=False,
)
- assert (
- result is not True
- ), "Testcase {} : Failed \nAttributes are not set \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: BGP attributes should not be set in {} FIB \n "
+ "Found: {}".format(tc_name, dut, result)
)
- logger.info("Expected behaviour: {}".format(result))
# Verifying RIB routes
dut = "r5"
input_dict_3_addr_type[addr_type],
expected=False,
)
- assert (
- result is not True
- ), "Testcase {} : Failed \nAttributes are not set \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: BGP attributes should not be set in {} FIB \n "
+ "Found: {}".format(tc_name, dut, result)
)
- logger.info("Expected behaviour: {}".format(result))
write_test_footer(tc_name)
result = verify_rib(
tgen, addr_type, dut, input_dict, protocol=protocol, expected=False
)
- assert (
- result is not True
- ), "Testcase {} : Failed \nroutes are not present \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: Routes should not be present in {} FIB \n "
+ "Found: {}".format(tc_name, dut, result)
)
- logger.info("Expected behaviour: {}".format(result))
# Verifying RIB routes
dut = "r4"
result = verify_rib(
tgen, addr_type, dut, input_dict, protocol=protocol, expected=False
)
- assert (
- result is not True
- ), "Testcase {} : Failed \nroutes are not present \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: Routes should not be present in {} FIB \n "
+ "Found: {}".format(tc_name, dut, result)
)
- logger.info("Expected behaviour: {}".format(result))
write_test_footer(tc_name)
result = verify_rib(
tgen, addr_type, dut, input_dict, protocol=protocol, expected=False
)
- assert (
- result is not True
- ), "Testcase {} : Failed \nroutes are denied \n Error: {}".format(
- tc_name, result
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "Expected: Routes should not be present in {} FIB \n "
+ "Found: {}".format(tc_name, dut, result)
)
- logger.info("Expected behaviour: {}".format(result))
write_test_footer(tc_name)
--- /dev/null
+@rmap@
+identifier ret;
+position p;
+@@
+
+int ret@p;
+...
+* ret = route_map_apply(...);
+
+@script:python@
+p << rmap.p;
+@@
+
+msg = "ERROR: Invalid type of return value variable for route_map_apply_ext()"
+coccilib.report.print_report(p[0], msg)
):
if ctx_keys[0] in del_nbr_dict:
for nbr in del_nbr_dict[ctx_keys[0]]:
- re_nbr_pg = re.search('neighbor (\S+) .*peer-group (\S+)', line)
+ re_nbr_pg = re.search("neighbor (\S+) .*peer-group (\S+)", line)
nb_exp = "neighbor %s .*" % nbr
if not re_nbr_pg:
re_nb = re.search(nb_exp, line)
# 'no neighbor peer [interface] peer-group <>' is in lines_to_del
# copy the neighbor and look for all config removal lines associated
# to neighbor and delete them from the lines_to_del
- re_nbr_pg = re.search('neighbor (\S+) .*peer-group (\S+)', line)
+ re_nbr_pg = re.search("neighbor (\S+) .*peer-group (\S+)", line)
if re_nbr_pg:
if ctx_keys[0] not in del_nbr_dict:
del_nbr_dict[ctx_keys[0]] = list()
lines_to_add.append((add_cmd, None))
lines_to_del_to_del.append((ctx_keys, None))
+ # bgp community-list, large-community-list, extcommunity-list can be
+ # specified without a seq number. However, the running config always
+ # adds `seq X` (sequence number). So, ignore such lines as well.
+ # Examples:
+ # bgp community-list standard clist seq 5 permit 222:213
+ # bgp large-community-list standard llist seq 5 permit 65001:65001:1
+ # bgp extcommunity-list standard elist seq 5 permit soo 123:123
+ re_bgp_lists = re.search(
+ "^(bgp )(community-list|large-community-list|extcommunity-list)(\s+\S+\s+)(\S+\s+)(seq \d+\s+)(permit|deny)(.*)$",
+ ctx_keys[0],
+ )
+ if re_bgp_lists:
+ found = False
+ tmpline = (
+ re_bgp_lists.group(1)
+ + re_bgp_lists.group(2)
+ + re_bgp_lists.group(3)
+ + re_bgp_lists.group(4)
+ + re_bgp_lists.group(6)
+ + re_bgp_lists.group(7)
+ )
+ for ctx in lines_to_add:
+ if ctx[0][0] == tmpline:
+ lines_to_del_to_del.append((ctx_keys, None))
+ lines_to_add_to_del.append(((tmpline,), None))
+ found = True
+ if found is False:
+ add_cmd = ("no " + ctx_keys[0],)
+ lines_to_add.append((add_cmd, None))
+ lines_to_del_to_del.append((ctx_keys, None))
+
if (
len(ctx_keys) == 3
and ctx_keys[0].startswith("router bgp")
TimeoutSec=@TIMEOUT_MIN@m
WatchdogSec=60s
RestartSec=5
-Restart=on-abnormal
+Restart=always
LimitNOFILE=1024
PIDFile=@CFG_STATE@/watchfrr.pid
ExecStart=@CFG_SBIN@/frrinit.sh start
TimeoutSec=@TIMEOUT_MIN@m
WatchdogSec=60s
RestartSec=5
-Restart=on-abnormal
+Restart=always
LimitNOFILE=1024
PIDFile=@CFG_STATE@/%I/watchfrr.pid
ExecStart=@CFG_SBIN@/frrinit.sh start %I
vrrp_debug_status_write(vty);
+ cmd_show_lib_debugs(vty);
+
return CMD_SUCCESS;
}
0 ||
strncmp(line, "domainname", strlen("domainname")) ==
0 ||
+ strncmp(line, "allow-reserved-ranges",
+ strlen("allow-reserved-ranges")) == 0 ||
strncmp(line, "frr", strlen("frr")) == 0 ||
strncmp(line, "agentx", strlen("agentx")) == 0 ||
strncmp(line, "no log", strlen("no log")) == 0 ||
strncmp(line, "no ip prefix-list",
strlen("no ip prefix-list")) == 0 ||
strncmp(line, "no ipv6 prefix-list",
- strlen("no ipv6 prefix-list")) == 0)
+ strlen("no ipv6 prefix-list")) == 0 ||
+ strncmp(line, "service cputime-stats",
+ strlen("service cputime-stats")) == 0 ||
+ strncmp(line, "no service cputime-stats",
+ strlen("no service cputime-stats")) == 0 ||
+ strncmp(line, "service cputime-warning",
+ strlen("service cputime-warning")) == 0)
config_add_line_uniq(config_top, line);
else
config_add_line(config_top, line);
DEBUG_STR
WATCHFRR_STR)
{
+ cmd_show_lib_debugs(vty);
+
return CMD_SUCCESS;
}
vty_out(vty, " Zebra PBR debugging is on\n");
hook_call(zebra_debug_show_debugging, vty);
+
+ cmd_show_lib_debugs(vty);
+
return CMD_SUCCESS;
}
ifp = if_lookup_by_name(ifap->ifa_name, VRF_DEFAULT);
if (ifp == NULL) {
flog_err(EC_LIB_INTERFACE,
- "if_getaddrs(): Can't lookup interface %s",
+ "%s: Can't lookup interface %s", __func__,
ifap->ifa_name);
continue;
}
void interface_list(struct zebra_ns *zns)
{
- zlog_info("interface_list: NS %u", zns->ns_id);
+ zlog_info("%s: NS %u", __func__, zns->ns_id);
/* Linux can do both proc & ioctl, ioctl is the only way to get
interface aliases in 2.2 series kernels. */
if (ret < 0)
return ret;
+ /*
+ * So netlink_tunneldump_read will initiate a request
+ * per tunnel to get data. If we are on a kernel that
+ * does not support this then we will get X error messages
+ * (one per tunnel request )back which netlink_parse_info will
+ * stop after the first one. So we need to read equivalent
+ * error messages per tunnel then we can continue.
+ * if we do not gather all the read failures then
+ * later requests will not work right.
+ */
ret = netlink_tunneldump_read(zns);
if (ret < 0)
return ret;
- ret = netlink_parse_info(netlink_interface, netlink_cmd, &dp_info, 0,
- true);
- if (ret < 0)
- return ret;
/* fixup linkages */
zebra_if_update_all_links(zns);
if (IS_ZEBRA_DEBUG_KERNEL) /* remove this line to see initial ifcfg */
{
char buf[BUFSIZ];
- zlog_debug("netlink_interface_addr %s %s flags 0x%x:",
+ zlog_debug("%s %s %s flags 0x%x:", __func__,
nl_msg_type_to_str(h->nlmsg_type), ifp->name,
kernel_flags);
if (tb[IFA_LOCAL])
/* assume if not default zns, then new VRF */
if (!(h->nlmsg_type == RTM_NEWLINK || h->nlmsg_type == RTM_DELLINK)) {
/* If this is not link add/delete message so print warning. */
- zlog_debug("netlink_link_change: wrong kernel message %s",
+ zlog_debug("%s: wrong kernel message %s", __func__,
nl_msg_type_to_str(h->nlmsg_type));
return 0;
}
struct route_node *rn;
struct interface *tmp_if = NULL;
struct zebra_if *zif;
+ struct nlsock *netlink_cmd = &zns->netlink_cmd;
zebra_dplane_info_from_zns(&dp_info, zns, true /*is_cmd*/);
tmp_if->ifindex);
if (ret < 0)
return ret;
+
+ ret = netlink_parse_info(netlink_interface, netlink_cmd,
+ &dp_info, 0, true);
+
+ if (ret < 0)
+ return ret;
}
+
return 0;
}
#endif /* GNU_LINUX */
NET_RT_IFLIST, 0};
if (zns->ns_id != NS_DEFAULT) {
- zlog_debug("interface_list: ignore NS %u", zns->ns_id);
+ zlog_debug("%s: ignore NS %u", __func__, zns->ns_id);
return;
}
ifam_read((struct ifa_msghdr *)ifm);
break;
default:
- zlog_info("interfaces_list(): unexpected message type");
+ zlog_info("%s: unexpected message type", __func__);
XFREE(MTYPE_TMP, ref);
return;
break;
/* paranoia: sanity check structure */
if (ifm->ifm_msglen < sizeof(struct if_msghdr)) {
flog_err(EC_ZEBRA_NETLINK_LENGTH_ERROR,
- "ifm_read: ifm->ifm_msglen %d too short",
+ "%s: ifm->ifm_msglen %d too short", __func__,
ifm->ifm_msglen);
return -1;
}
* can assume they have the whole message.
*/
if (rtm->rtm_msglen != nbytes) {
- zlog_debug(
- "kernel_read: rtm->rtm_msglen %d, nbytes %d, type %d",
- rtm->rtm_msglen, nbytes, rtm->rtm_type);
+ zlog_debug("%s: rtm->rtm_msglen %d, nbytes %d, type %d",
+ __func__, rtm->rtm_msglen, nbytes, rtm->rtm_type);
return;
}
DECLARE_HOOK(rib_update, (struct route_node * rn, const char *reason),
(rn, reason));
+DECLARE_HOOK(rib_shutdown, (struct route_node * rn), (rn));
/*
* Access installed/fib nexthops, which may be a subset of the
adata = calloc(1, CMSG_SPACE(sizeof(struct in6_pktinfo)));
if (adata == NULL) {
- zlog_debug(
- "rtadv_send_packet: can't malloc control data");
+ zlog_debug("%s: can't malloc control data", __func__);
exit(-1);
}
}
zif->rtadv.lastadvcurhoplimit.tv_sec == 0)) {
flog_warn(
EC_ZEBRA_RA_PARAM_MISMATCH,
- "%s(%u): Rx RA - our AdvCurHopLimit doesn't agree with %s",
- ifp->name, ifp->ifindex, addr_str);
+ "%s(%u): Rx RA - our AdvCurHopLimit (%u) doesn't agree with %s (%u)",
+ ifp->name, ifp->ifindex, zif->rtadv.AdvCurHopLimit,
+ addr_str, radvert->nd_ra_curhoplimit);
monotime(&zif->rtadv.lastadvcurhoplimit);
}
zif->rtadv.lastadvmanagedflag.tv_sec == 0)) {
flog_warn(
EC_ZEBRA_RA_PARAM_MISMATCH,
- "%s(%u): Rx RA - our AdvManagedFlag doesn't agree with %s",
- ifp->name, ifp->ifindex, addr_str);
+ "%s(%u): Rx RA - our AdvManagedFlag (%u) doesn't agree with %s (%u)",
+ ifp->name, ifp->ifindex, zif->rtadv.AdvManagedFlag,
+ addr_str,
+ !!CHECK_FLAG(radvert->nd_ra_flags_reserved,
+ ND_RA_FLAG_MANAGED));
monotime(&zif->rtadv.lastadvmanagedflag);
}
zif->rtadv.lastadvotherconfigflag.tv_sec == 0)) {
flog_warn(
EC_ZEBRA_RA_PARAM_MISMATCH,
- "%s(%u): Rx RA - our AdvOtherConfigFlag doesn't agree with %s",
- ifp->name, ifp->ifindex, addr_str);
+ "%s(%u): Rx RA - our AdvOtherConfigFlag (%u) doesn't agree with %s (%u)",
+ ifp->name, ifp->ifindex, zif->rtadv.AdvOtherConfigFlag,
+ addr_str,
+ !!CHECK_FLAG(radvert->nd_ra_flags_reserved,
+ ND_RA_FLAG_OTHER));
monotime(&zif->rtadv.lastadvotherconfigflag);
}
zif->rtadv.lastadvreachabletime.tv_sec == 0)) {
flog_warn(
EC_ZEBRA_RA_PARAM_MISMATCH,
- "%s(%u): Rx RA - our AdvReachableTime doesn't agree with %s",
- ifp->name, ifp->ifindex, addr_str);
+ "%s(%u): Rx RA - our AdvReachableTime (%u) doesn't agree with %s (%u)",
+ ifp->name, ifp->ifindex, zif->rtadv.AdvReachableTime,
+ addr_str, ntohl(radvert->nd_ra_reachable));
monotime(&zif->rtadv.lastadvreachabletime);
}
- if ((ntohl(radvert->nd_ra_retransmit) !=
+ if ((radvert->nd_ra_retransmit && zif->rtadv.AdvRetransTimer) &&
+ (ntohl(radvert->nd_ra_retransmit) !=
(unsigned int)zif->rtadv.AdvRetransTimer) &&
(monotime_since(&zif->rtadv.lastadvretranstimer, NULL) >
SIXHOUR2USEC ||
zif->rtadv.lastadvretranstimer.tv_sec == 0)) {
flog_warn(
EC_ZEBRA_RA_PARAM_MISMATCH,
- "%s(%u): Rx RA - our AdvRetransTimer doesn't agree with %s",
- ifp->name, ifp->ifindex, addr_str);
+ "%s(%u): Rx RA - our AdvRetransTimer (%u) doesn't agree with %s (%u)",
+ ifp->name, ifp->ifindex, zif->rtadv.AdvRetransTimer,
+ addr_str, ntohl(radvert->nd_ra_retransmit));
monotime(&zif->rtadv.lastadvretranstimer);
}
return 0;
}
+/*
+ * zfpm_trigger_remove
+ *
+ * The zebra code invokes this function to indicate that we should
+ * send an remove to the FPM about the given route_node.
+ */
+
+static int zfpm_trigger_remove(struct route_node *rn)
+{
+ rib_dest_t *dest;
+
+ if (!zfpm_conn_is_up())
+ return 0;
+
+ dest = rib_dest_from_rnode(rn);
+ if (!CHECK_FLAG(dest->flags, RIB_DEST_UPDATE_FPM))
+ return 0;
+
+ zfpm_debug("%pRN Removing from update queue shutting down", rn);
+
+ UNSET_FLAG(dest->flags, RIB_DEST_UPDATE_FPM);
+ TAILQ_REMOVE(&zfpm_g->dest_q, dest, fpm_q_entries);
+
+ return 0;
+}
+
/*
* Generate Key for FPM MAC info hash entry
*/
static int zebra_fpm_module_init(void)
{
hook_register(rib_update, zfpm_trigger_update);
+ hook_register(rib_shutdown, zfpm_trigger_remove);
hook_register(zebra_rmac_update, zfpm_trigger_rmac_update);
hook_register(frr_late_init, zfpm_init);
hook_register(frr_early_fini, zfpm_fini);
DEFINE_HOOK(rib_update, (struct route_node * rn, const char *reason),
(rn, reason));
+DEFINE_HOOK(rib_shutdown, (struct route_node * rn), (rn));
+
/* Meta Q's specific names */
enum meta_queue_indexes {
if (node->info) {
rib_dest_t *dest = node->info;
+ /* Remove from update queue of FPM module */
+ hook_call(rib_shutdown, node);
+
rnh_list_fini(&dest->nht);
XFREE(MTYPE_RIB_DEST, node->info);
}