#include "queue.h"
#include "memory.h"
#include "lib/json.h"
+#include "lib_errors.h"
#include "bgpd/bgpd.h"
#include "bgpd/bgp_table.h"
#include "bgpd/bgp_route.h"
#include "bgpd/bgp_attr.h"
#include "bgpd/bgp_debug.h"
+#include "bgpd/bgp_errors.h"
#include "bgpd/bgp_aspath.h"
#include "bgpd/bgp_regex.h"
#include "bgpd/bgp_community.h"
if (e->parent) {
struct bgp_info *bi = (struct bgp_info *)e->parent;
- if (bi->net)
- bi->net = bgp_unlock_node((struct bgp_node *)bi->net);
+ if (bi->net) {
+ /* FIXME: since multiple e may have the same e->parent
+ * and e->parent->net is holding a refcount for each
+ * of them, we need to do some fudging here.
+ *
+ * WARNING: if bi->net->lock drops to 0, bi may be
+ * freed as well (because bi->net was holding the
+ * last reference to bi) => write after free!
+ */
+ unsigned refcount;
+
+ bi = bgp_info_lock(bi);
+ refcount = bi->net->lock - 1;
+ bgp_unlock_node((struct bgp_node *)bi->net);
+ if (!refcount)
+ bi->net = NULL;
+ bgp_info_unlock(bi);
+ }
bgp_info_unlock(e->parent);
e->parent = NULL;
}
bgp_unlock(e->bgp_orig);
if ((*extra)->bgp_fs_pbr)
- list_delete_all_node((*extra)->bgp_fs_pbr);
- (*extra)->bgp_fs_pbr = NULL;
+ list_delete_and_null(&((*extra)->bgp_fs_pbr));
XFREE(MTYPE_BGP_ROUTE_EXTRA, *extra);
*extra = NULL;
/* slight hack, but more robust against errors. */
if (ri->peer->pcount[table->afi][table->safi])
ri->peer->pcount[table->afi][table->safi]--;
- else {
- zlog_warn(
- "%s: Asked to decrement 0 prefix count for peer %s",
- __func__, ri->peer->host);
- zlog_backtrace(LOG_WARNING);
- zlog_warn("%s: Please report to Quagga bugzilla",
- __func__);
- }
+ else
+ flog_err(LIB_ERR_DEVELOPMENT,
+ "Asked to decrement 0 prefix count for peer");
} else if (BGP_INFO_COUNTABLE(ri)
&& !CHECK_FLAG(ri->flags, BGP_INFO_COUNTED)) {
SET_FLAG(ri->flags, BGP_INFO_COUNTED);
}
if (newattr->sticky && !existattr->sticky) {
- zlog_warn(
- "%s: %s wins over %s due to sticky MAC flag",
- pfx_buf, new_buf, exist_buf);
+ if (debug)
+ zlog_debug(
+ "%s: %s wins over %s due to sticky MAC flag",
+ pfx_buf, new_buf, exist_buf);
return 1;
}
if (!newattr->sticky && existattr->sticky) {
- zlog_warn(
- "%s: %s loses to %s due to sticky MAC flag",
- pfx_buf, new_buf, exist_buf);
+ if (debug)
+ zlog_debug(
+ "%s: %s loses to %s due to sticky MAC flag",
+ pfx_buf, new_buf, exist_buf);
return 0;
}
}
#define FILTER_EXIST_WARN(F, f, filter) \
if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
- zlog_warn("%s: Could not find configured input %s-list %s!", \
- peer->host, #f, F##_IN_NAME(filter));
+ zlog_debug("%s: Could not find configured input %s-list %s!", \
+ peer->host, #f, F##_IN_NAME(filter));
if (DISTRIBUTE_IN_NAME(filter)) {
FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
#define FILTER_EXIST_WARN(F, f, filter) \
if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
- zlog_warn("%s: Could not find configured output %s-list %s!", \
- peer->host, #f, F##_OUT_NAME(filter));
+ zlog_debug("%s: Could not find configured output %s-list %s!", \
+ peer->host, #f, F##_OUT_NAME(filter));
if (DISTRIBUTE_OUT_NAME(filter)) {
FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
void bgp_process_queue_init(void)
{
- if (!bm->process_main_queue) {
+ if (!bm->process_main_queue)
bm->process_main_queue =
work_queue_new(bm->master, "process_main_queue");
- if (!bm->process_main_queue) {
- zlog_err("%s: Failed to allocate work queue", __func__);
- exit(1);
- }
- }
-
bm->process_main_queue->spec.workfunc = &bgp_process_wq;
bm->process_main_queue->spec.del_item_data = &bgp_processq_del;
bm->process_main_queue->spec.max_retries = 0;
snprintf(wname, sizeof(wname), "clear %s", peer->host);
#undef CLEAR_QUEUE_NAME_LEN
- if ((peer->clear_node_queue = work_queue_new(bm->master, wname))
- == NULL) {
- zlog_err("%s: Failed to allocate work queue", __func__);
- exit(1);
- }
+ peer->clear_node_queue = work_queue_new(bm->master, wname);
peer->clear_node_queue->spec.hold = 10;
peer->clear_node_queue->spec.workfunc = &bgp_clear_route_node;
peer->clear_node_queue->spec.del_item_data = &bgp_clear_node_queue_del;
/* Prefix length check. */
if (p.prefixlen > prefix_blen(&p) * 8) {
- zlog_err(
- "%s [Error] Update packet error (wrong perfix length %d for afi %u)",
+ flog_err(
+ BGP_ERR_UPDATE_RCV,
+ "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
peer->host, p.prefixlen, packet->afi);
return -1;
}
/* When packet overflow occur return immediately. */
if (pnt + psize > lim) {
- zlog_err(
+ flog_err(
+ BGP_ERR_UPDATE_RCV,
"%s [Error] Update packet error (prefix length %d overflows packet)",
peer->host, p.prefixlen);
return -1;
/* Defensive coding, double-check the psize fits in a struct
* prefix */
if (psize > (ssize_t)sizeof(p.u)) {
- zlog_err(
+ flog_err(
+ BGP_ERR_UPDATE_RCV,
"%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
peer->host, p.prefixlen, sizeof(p.u));
return -1;
* be logged locally, and the prefix SHOULD be
* ignored.
*/
- zlog_err(
+ flog_err(
+ BGP_ERR_UPDATE_RCV,
"%s: IPv4 unicast NLRI is multicast address %s, ignoring",
peer->host, inet_ntoa(p.u.prefix4));
continue;
if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
char buf[BUFSIZ];
- zlog_err(
+ flog_err(
+ BGP_ERR_UPDATE_RCV,
"%s: IPv6 unicast NLRI is link-local address %s, ignoring",
peer->host,
inet_ntop(AF_INET6, &p.u.prefix6, buf,
if (IN6_IS_ADDR_MULTICAST(&p.u.prefix6)) {
char buf[BUFSIZ];
- zlog_err(
+ flog_err(
+ BGP_ERR_UPDATE_RCV,
"%s: IPv6 unicast NLRI is multicast address %s, ignoring",
peer->host,
inet_ntop(AF_INET6, &p.u.prefix6, buf,
/* Packet length consistency check. */
if (pnt != lim) {
- zlog_err(
+ flog_err(
+ BGP_ERR_UPDATE_RCV,
"%s [Error] Update packet error (prefix length mismatch with total length)",
peer->host);
return -1;
if (routermac) {
bgp_static->router_mac =
XCALLOC(MTYPE_ATTR, ETH_ALEN + 1);
- prefix_str2mac(routermac,
- bgp_static->router_mac);
+ (void)prefix_str2mac(routermac,
+ bgp_static->router_mac);
}
if (gwip)
prefix_copy(&bgp_static->gatewayIp, &gw_ip);
XFREE(MTYPE_BGP_AGGREGATE, aggregate);
}
-static int bgp_aggregate_info_same(struct bgp_info *ri, struct aspath *aspath,
+static int bgp_aggregate_info_same(struct bgp_info *ri, uint8_t origin,
+ struct aspath *aspath,
struct community *comm)
{
static struct aspath *ae = NULL;
if (!ri)
return 0;
+ if (origin != ri->attr->origin)
+ return 0;
+
if (!aspath_cmp(ri->attr->aspath, (aspath) ? aspath : ae))
return 0;
* If the aggregate information has not changed
* no need to re-install it again.
*/
- if (bgp_aggregate_info_same(rn->info, aspath, community)) {
+ if (bgp_aggregate_info_same(rn->info, origin, aspath,
+ community)) {
bgp_unlock_node(rn);
if (aspath)
json_object *json)
{
int len = 0;
- uint32_t destination;
char buf[BUFSIZ];
if (p->family == AF_INET) {
if (!json) {
- len = vty_out(vty, "%s",
- inet_ntop(p->family, &p->u.prefix, buf,
- BUFSIZ));
- destination = ntohl(p->u.prefix4.s_addr);
-
- if ((IN_CLASSC(destination) && p->prefixlen == 24)
- || (IN_CLASSB(destination) && p->prefixlen == 16)
- || (IN_CLASSA(destination) && p->prefixlen == 8)
- || p->u.prefix4.s_addr == 0) {
- /* When mask is natural,
- mask is not displayed. */
- } else
- len += vty_out(vty, "/%d", p->prefixlen);
+ len = vty_out(
+ vty, "%s/%d",
+ inet_ntop(p->family, &p->u.prefix, buf, BUFSIZ),
+ p->prefixlen);
} else {
json_object_string_add(json, "prefix",
inet_ntop(p->family,
else
vty_out(vty, ", localpref %u",
attr->local_pref);
- } else {
- if (json_paths)
- json_object_int_add(json_path, "localpref",
- bgp->default_local_pref);
- else
- vty_out(vty, ", localpref %u",
- bgp->default_local_pref);
}
if (attr->weight != 0) {
vty_out(vty, " \"routeDistinguishers\" : {");
++*json_header_depth;
}
- json_paths = json_object_new_object();
}
if (use_json && rd) {
*total_cum = total_count;
}
if (use_json) {
- if (json_paths)
- json_object_free(json_paths);
if (rd) {
vty_out(vty, " }%s ", (is_last ? "" : ","));
}
int count = 0;
int best = 0;
int suppress = 0;
+ int accept_own = 0;
+ int route_filter_translated_v4 = 0;
+ int route_filter_v4 = 0;
+ int route_filter_translated_v6 = 0;
+ int route_filter_v6 = 0;
+ int llgr_stale = 0;
+ int no_llgr = 0;
+ int accept_own_nexthop = 0;
+ int blackhole = 0;
int no_export = 0;
int no_advertise = 0;
int local_as = 0;
+ int no_peer = 0;
int first = 1;
int has_valid_label = 0;
mpls_label_t label = 0;
} else
vty_out(vty, ", no best path");
- if (no_advertise)
- vty_out(vty, ", not advertised to any peer");
+ if (accept_own)
+ vty_out(vty,
+ ", accept own local route exported and imported in different VRF");
+ else if (route_filter_translated_v4)
+ vty_out(vty,
+ ", mark translated RTs for VPNv4 route filtering");
+ else if (route_filter_v4)
+ vty_out(vty,
+ ", attach RT as-is for VPNv4 route filtering");
+ else if (route_filter_translated_v6)
+ vty_out(vty,
+ ", mark translated RTs for VPNv6 route filtering");
+ else if (route_filter_v6)
+ vty_out(vty,
+ ", attach RT as-is for VPNv6 route filtering");
+ else if (llgr_stale)
+ vty_out(vty,
+ ", mark routes to be retained for a longer time. Requeres support for Long-lived BGP Graceful Restart");
+ else if (no_llgr)
+ vty_out(vty,
+ ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
+ else if (accept_own_nexthop)
+ vty_out(vty,
+ ", accept local nexthop");
+ else if (blackhole)
+ vty_out(vty, ", inform peer to blackhole prefix");
else if (no_export)
vty_out(vty, ", not advertised to EBGP peer");
+ else if (no_advertise)
+ vty_out(vty, ", not advertised to any peer");
else if (local_as)
vty_out(vty, ", not advertised outside local AS");
+ else if (no_peer)
+ vty_out(vty,
+ ", inform EBGP peer not to advertise to their EBGP peers");
if (suppress)
vty_out(vty,
|prefix-list WORD\
|filter-list WORD\
|statistics\
+ |community <AA:NN|local-AS|no-advertise|no-export|graceful-shutdown\
+ no-peer|blackhole|llgr-stale|no-llgr|accept-own|accept-own-nexthop\
+ route-filter-v6|route-filter-v4|route-filter-translated-v6|\
+ route-filter-translated-v4> [exact-match]\
|community-list <(1-500)|WORD> [exact-match]\
|A.B.C.D/M longer-prefixes\
|X:X::X:X/M longer-prefixes\
"Display routes conforming to the filter-list\n"
"Regular expression access list name\n"
"BGP RIB advertisement statistics\n"
+ "Display routes matching the communities\n"
+ COMMUNITY_AANN_STR
+ "Do not send outside local AS (well-known community)\n"
+ "Do not advertise to any peer (well-known community)\n"
+ "Do not export to next AS (well-known community)\n"
+ "Graceful shutdown (well-known community)\n"
+ "Do not export to any peer (well-known community)\n"
+ "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
+ "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
+ "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
+ "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
+ "Should accept VPN route with local nexthop (well-known community)\n"
+ "RT VPNv6 route filtering (well-known community)\n"
+ "RT VPNv4 route filtering (well-known community)\n"
+ "RT translated VPNv6 route filtering (well-known community)\n"
+ "RT translated VPNv4 route filtering (well-known community)\n"
+ "Exact match of the communities\n"
"Display routes matching the community-list\n"
"community-list number\n"
"community-list name\n"
unsigned long newtot = (count-1) * oldavg + (newval * TALLY_SIGFIG);
unsigned long res = (newtot * TALLY_SIGFIG) / count;
unsigned long ret = newtot / count;
-
+
if ((res % TALLY_SIGFIG) > (TALLY_SIGFIG/2))
return ret + 1;
else
ts->counts[BGP_STATS_ASPATH_TOTHOPS] += hops;
ts->counts[BGP_STATS_ASPATH_TOTSIZE] += size;
#if 0
- ts->counts[BGP_STATS_ASPATH_AVGHOPS]
+ ts->counts[BGP_STATS_ASPATH_AVGHOPS]
= ravg_tally (ts->counts[BGP_STATS_ASPATH_COUNT],
ts->counts[BGP_STATS_ASPATH_AVGHOPS],
hops);
pc->count[PCOUNT_ADJ_IN]++;
for (ri = rn->info; ri; ri = ri->next) {
- char buf[SU_ADDRSTRLEN];
-
if (ri->peer != peer)
continue;
if (CHECK_FLAG(ri->flags, BGP_INFO_COUNTED)) {
pc->count[PCOUNT_COUNTED]++;
if (CHECK_FLAG(ri->flags, BGP_INFO_UNUSEABLE))
- zlog_warn(
- "%s [pcount] %s/%d is counted but flags 0x%x",
- peer->host,
- inet_ntop(rn->p.family,
- &rn->p.u.prefix, buf,
- SU_ADDRSTRLEN),
- rn->p.prefixlen, ri->flags);
+ flog_err(LIB_ERR_DEVELOPMENT,
+ "Attempting to count but flags say it is unusable");
} else {
if (!CHECK_FLAG(ri->flags, BGP_INFO_UNUSEABLE))
- zlog_warn(
- "%s [pcount] %s/%d not counted but flags 0x%x",
- peer->host,
- inet_ntop(rn->p.family,
- &rn->p.u.prefix, buf,
- SU_ADDRSTRLEN),
- rn->p.prefixlen, ri->flags);
+ flog_err(LIB_ERR_DEVELOPMENT,
+ "Not counted but flags say we should");
}
}
}
json_scode);
json_object_object_add(json, "bgpOriginCodes",
json_ocode);
- json_object_string_add(json,
- "bgpOriginatingDefaultNetwork",
- "0.0.0.0");
+ json_object_string_add(
+ json, "bgpOriginatingDefaultNetwork",
+ (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
} else {
vty_out(vty, "BGP table version is %" PRIu64
", local router ID is %s, vrf id ",
vty_out(vty, BGP_SHOW_NCODE_HEADER);
vty_out(vty, BGP_SHOW_OCODE_HEADER);
- vty_out(vty, "Originating default network 0.0.0.0\n\n");
+ vty_out(vty, "Originating default network %s\n\n",
+ (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
}
header1 = 0;
}