From 5f7a4718e201724a8ca697dedaa8ce008949c3f5 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 30 Nov 2017 14:03:07 -0500 Subject: [PATCH 01/48] zebra: Replace SELECTED_FIB flag with a rib_dest_t pointer The SELECTED_FIB flag was placed upon the entry that we have inserted into the kernel. Remove this flag and replace with a `rib_dest_t` *selected_fib. Just keep track of the selected_fib as we modify it. This removes allot of FOREACH_RE loops as that we do not need to find the entry anymore. At this point in time I think this is a very minor performance boost. Most `rib_dest_t` structures do not typically carry more than 1 route_entry, but the minute you start having more than one entry you can and will start having significant processing time spent finding the selected_fib. A future commit may re-order the route entries and possibly keep more pointers on `rib_dest_t` to avoid lookup. This is a bit tricky because of the FIB_OVERRIDE code. Signed-off-by Donald Sharp --- zebra/rib.h | 5 +- zebra/zebra_fpm.c | 14 +---- zebra/zebra_rib.c | 137 ++++++++++++++++++++----------------------- zebra/zebra_static.c | 8 +-- zebra/zebra_vty.c | 6 +- 5 files changed, 76 insertions(+), 94 deletions(-) diff --git a/zebra/rib.h b/zebra/rib.h index 818844cb6d..6027385cac 100644 --- a/zebra/rib.h +++ b/zebra/rib.h @@ -85,8 +85,7 @@ struct route_entry { /* to simplify NHT logic when NHs change, instead of doing a NH by NH cmp */ #define ROUTE_ENTRY_NEXTHOPS_CHANGED 0x2 #define ROUTE_ENTRY_CHANGED 0x4 -#define ROUTE_ENTRY_SELECTED_FIB 0x8 -#define ROUTE_ENTRY_LABELS_CHANGED 0x10 +#define ROUTE_ENTRY_LABELS_CHANGED 0x8 /* Nexthop information. */ u_char nexthop_num; @@ -122,6 +121,8 @@ typedef struct rib_dest_t_ { */ struct route_entry *routes; + struct route_entry *selected_fib; + /* * Flags, see below. */ diff --git a/zebra/zebra_fpm.c b/zebra/zebra_fpm.c index 7448292d9f..0d0a2cb3bf 100644 --- a/zebra/zebra_fpm.c +++ b/zebra/zebra_fpm.c @@ -842,19 +842,7 @@ static inline int zfpm_encode_route(rib_dest_t *dest, struct route_entry *re, */ struct route_entry *zfpm_route_for_update(rib_dest_t *dest) { - struct route_entry *re; - - RE_DEST_FOREACH_ROUTE (dest, re) { - if (!CHECK_FLAG(re->status, ROUTE_ENTRY_SELECTED_FIB)) - continue; - - return re; - } - - /* - * We have no route for this destination. - */ - return NULL; + return dest->selected_fib; } /* diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index 58b6965995..603d90b599 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -383,10 +383,11 @@ static int nexthop_active(afi_t afi, struct route_entry *re, struct prefix p; struct route_table *table; struct route_node *rn; - struct route_entry *match; + struct route_entry *match = NULL; int resolved; struct nexthop *newhop; struct interface *ifp; + rib_dest_t *dest; if ((nexthop->type == NEXTHOP_TYPE_IPV4) || nexthop->type == NEXTHOP_TYPE_IPV6) @@ -466,17 +467,12 @@ static int nexthop_active(afi_t afi, struct route_entry *re, && !nh_resolve_via_default(p.family)) return 0; - RNODE_FOREACH_RE (rn, match) { - if (CHECK_FLAG(match->status, ROUTE_ENTRY_REMOVED)) - continue; - - /* if the next hop is imported from another table, skip - * it */ - if (match->type == ZEBRA_ROUTE_TABLE) - continue; - if (CHECK_FLAG(match->status, ROUTE_ENTRY_SELECTED_FIB)) - break; - } + dest = rib_dest_from_rnode(rn); + if (dest && dest->selected_fib && + !CHECK_FLAG(dest->selected_fib->status, + ROUTE_ENTRY_REMOVED) && + dest->selected_fib->type != ZEBRA_ROUTE_TABLE) + match = dest->selected_fib; /* If there is no selected route or matched route is EGP, go up tree. */ @@ -553,7 +549,7 @@ struct route_entry *rib_match(afi_t afi, safi_t safi, vrf_id_t vrf_id, struct prefix p; struct route_table *table; struct route_node *rn; - struct route_entry *match; + struct route_entry *match = NULL; struct nexthop *newhop; /* Lookup table. */ @@ -574,15 +570,14 @@ struct route_entry *rib_match(afi_t afi, safi_t safi, vrf_id_t vrf_id, rn = route_node_match(table, (struct prefix *)&p); while (rn) { + rib_dest_t *dest; + route_unlock_node(rn); - /* Pick up selected route. */ - RNODE_FOREACH_RE (rn, match) { - if (CHECK_FLAG(match->status, ROUTE_ENTRY_REMOVED)) - continue; - if (CHECK_FLAG(match->status, ROUTE_ENTRY_SELECTED_FIB)) - break; - } + dest = rib_dest_from_rnode(rn); + if (dest && dest->selected_fib && + !CHECK_FLAG(dest->selected_fib->status, ROUTE_ENTRY_REMOVED)) + match = dest->selected_fib; /* If there is no selected route or matched route is EGP, go up tree. */ @@ -689,8 +684,9 @@ struct route_entry *rib_lookup_ipv4(struct prefix_ipv4 *p, vrf_id_t vrf_id) { struct route_table *table; struct route_node *rn; - struct route_entry *match; + struct route_entry *match = NULL; struct nexthop *nexthop; + rib_dest_t *dest; /* Lookup table. */ table = zebra_vrf_table(AFI_IP, SAFI_UNICAST, vrf_id); @@ -705,13 +701,11 @@ struct route_entry *rib_lookup_ipv4(struct prefix_ipv4 *p, vrf_id_t vrf_id) /* Unlock node. */ route_unlock_node(rn); + dest = rib_dest_from_rnode(rn); - RNODE_FOREACH_RE (rn, match) { - if (CHECK_FLAG(match->status, ROUTE_ENTRY_REMOVED)) - continue; - if (CHECK_FLAG(match->status, ROUTE_ENTRY_SELECTED_FIB)) - break; - } + if (dest && dest->selected_fib && + !CHECK_FLAG(dest->selected_fib->status, ROUTE_ENTRY_REMOVED)) + match = dest->selected_fib; if (!match) return NULL; @@ -743,9 +737,10 @@ int rib_lookup_ipv4_route(struct prefix_ipv4 *p, union sockunion *qgate, { struct route_table *table; struct route_node *rn; - struct route_entry *match; + struct route_entry *match = NULL; struct nexthop *nexthop; int nexthops_active; + rib_dest_t *dest; /* Lookup table. */ table = zebra_vrf_table(AFI_IP, SAFI_UNICAST, vrf_id); @@ -761,15 +756,13 @@ int rib_lookup_ipv4_route(struct prefix_ipv4 *p, union sockunion *qgate, /* Unlock node. */ route_unlock_node(rn); + dest = rib_dest_from_rnode(rn); /* Find out if a "selected" RR for the discovered RIB entry exists ever. */ - RNODE_FOREACH_RE (rn, match) { - if (CHECK_FLAG(match->status, ROUTE_ENTRY_REMOVED)) - continue; - if (CHECK_FLAG(match->status, ROUTE_ENTRY_SELECTED_FIB)) - break; - } + if (dest && dest->selected_fib && + !CHECK_FLAG(dest->selected_fib->status, ROUTE_ENTRY_REMOVED)) + match = dest->selected_fib; /* None such found :( */ if (!match) @@ -1115,8 +1108,9 @@ void rib_uninstall_kernel(struct route_node *rn, struct route_entry *re) static void rib_uninstall(struct route_node *rn, struct route_entry *re) { rib_table_info_t *info = srcdest_rnode_table_info(rn); + rib_dest_t *dest = rib_dest_from_rnode(rn); - if (CHECK_FLAG(re->status, ROUTE_ENTRY_SELECTED_FIB)) { + if (dest && dest->selected_fib == re) { if (info->safi == SAFI_UNICAST) hook_call(rib_update, rn, "rib_uninstall"); @@ -1127,7 +1121,7 @@ static void rib_uninstall(struct route_node *rn, struct route_entry *re) if (zebra_rib_labeled_unicast(re)) zebra_mpls_lsp_uninstall(info->zvrf, rn, re); - UNSET_FLAG(re->status, ROUTE_ENTRY_SELECTED_FIB); + dest->selected_fib = NULL; } if (CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED)) { @@ -1201,6 +1195,8 @@ int rib_gc_dest(struct route_node *rn) static void rib_process_add_fib(struct zebra_vrf *zvrf, struct route_node *rn, struct route_entry *new) { + rib_dest_t *dest = rib_dest_from_rnode(rn); + hook_call(rib_update, rn, "new route selected"); /* Update real nexthop. This may actually determine if nexthop is active @@ -1210,7 +1206,7 @@ static void rib_process_add_fib(struct zebra_vrf *zvrf, struct route_node *rn, return; } - SET_FLAG(new->status, ROUTE_ENTRY_SELECTED_FIB); + dest->selected_fib = new; if (IS_ZEBRA_DEBUG_RIB) { char buf[SRCDEST2STR_BUFFER]; srcdest_rnode2str(rn, buf, sizeof(buf)); @@ -1231,6 +1227,7 @@ static void rib_process_add_fib(struct zebra_vrf *zvrf, struct route_node *rn, static void rib_process_del_fib(struct zebra_vrf *zvrf, struct route_node *rn, struct route_entry *old) { + rib_dest_t *dest = rib_dest_from_rnode(rn); hook_call(rib_update, rn, "removing existing route"); /* Uninstall from kernel. */ @@ -1248,7 +1245,7 @@ static void rib_process_del_fib(struct zebra_vrf *zvrf, struct route_node *rn, if (!RIB_SYSTEM_ROUTE(old)) rib_uninstall_kernel(rn, old); - UNSET_FLAG(old->status, ROUTE_ENTRY_SELECTED_FIB); + dest->selected_fib = NULL; /* Update nexthop for route, reset changed flag. */ nexthop_active_update(rn, old, 1); @@ -1263,6 +1260,7 @@ static void rib_process_update_fib(struct zebra_vrf *zvrf, struct nexthop *nexthop = NULL; int nh_active = 0; int installed = 1; + rib_dest_t *dest = rib_dest_from_rnode(rn); /* * We have to install or update if a new route has been selected or @@ -1329,7 +1327,7 @@ static void rib_process_update_fib(struct zebra_vrf *zvrf, /* Update for redistribution. */ if (installed) - SET_FLAG(new->status, ROUTE_ENTRY_SELECTED_FIB); + dest->selected_fib = new; } /* @@ -1364,7 +1362,7 @@ static void rib_process_update_fib(struct zebra_vrf *zvrf, if (!RIB_SYSTEM_ROUTE(old)) rib_uninstall_kernel(rn, old); - UNSET_FLAG(new->status, ROUTE_ENTRY_SELECTED_FIB); + dest->selected_fib = NULL; } } else { /* @@ -1392,8 +1390,6 @@ static void rib_process_update_fib(struct zebra_vrf *zvrf, /* Update prior route. */ if (new != old) { - UNSET_FLAG(old->status, ROUTE_ENTRY_SELECTED_FIB); - /* Set real nexthop. */ nexthop_active_update(rn, old, 1); UNSET_FLAG(old->status, ROUTE_ENTRY_CHANGED); @@ -1475,6 +1471,8 @@ static void rib_process(struct route_node *rn) if (IS_ZEBRA_DEBUG_RIB_DETAILED) zlog_debug("%u:%s: Processing rn %p", vrf_id, buf, rn); + old_fib = dest->selected_fib; + RNODE_FOREACH_RE_SAFE (rn, re, next) { if (IS_ZEBRA_DEBUG_RIB_DETAILED) zlog_debug( @@ -1490,11 +1488,6 @@ static void rib_process(struct route_node *rn) assert(old_selected == NULL); old_selected = re; } - /* Currently in fib */ - if (CHECK_FLAG(re->status, ROUTE_ENTRY_SELECTED_FIB)) { - assert(old_fib == NULL); - old_fib = re; - } /* Skip deleted entries from selection */ if (CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED)) @@ -2183,8 +2176,8 @@ void rib_lookup_and_pushup(struct prefix_ipv4 *p, vrf_id_t vrf_id) { struct route_table *table; struct route_node *rn; - struct route_entry *re; unsigned changed = 0; + rib_dest_t *dest; if (NULL == (table = zebra_vrf_table(AFI_IP, SAFI_UNICAST, vrf_id))) { zlog_err("%s: zebra_vrf_table() returned NULL", __func__); @@ -2198,6 +2191,7 @@ void rib_lookup_and_pushup(struct prefix_ipv4 *p, vrf_id_t vrf_id) /* Unlock node. */ route_unlock_node(rn); + dest = rib_dest_from_rnode(rn); /* Check all RE entries. In case any changes have to be done, requeue * the RN into RIBQ head. If the routing message about the new connected * route (generated by the IP address we are going to assign very soon) @@ -2206,20 +2200,17 @@ void rib_lookup_and_pushup(struct prefix_ipv4 *p, vrf_id_t vrf_id) * revalidation * of the rest of the RE. */ - RNODE_FOREACH_RE (rn, re) { - if (CHECK_FLAG(re->status, ROUTE_ENTRY_SELECTED_FIB) - && !RIB_SYSTEM_ROUTE(re)) { - changed = 1; - if (IS_ZEBRA_DEBUG_RIB) { - char buf[PREFIX_STRLEN]; - zlog_debug( - "%u:%s: freeing way for connected prefix", - re->vrf_id, - prefix2str(&rn->p, buf, sizeof(buf))); - route_entry_dump(&rn->p, NULL, re); - } - rib_uninstall(rn, re); + if (dest->selected_fib && !RIB_SYSTEM_ROUTE(dest->selected_fib)) { + changed = 1; + if (IS_ZEBRA_DEBUG_RIB) { + char buf[PREFIX_STRLEN]; + + zlog_debug("%u:%s: freeing way for connected prefix", + dest->selected_fib->vrf_id, + prefix2str(&rn->p, buf, sizeof(buf))); + route_entry_dump(&rn->p, NULL, dest->selected_fib); } + rib_uninstall(rn, dest->selected_fib); } if (changed) rib_queue_add(rn); @@ -2325,6 +2316,7 @@ void rib_delete(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, struct route_entry *same = NULL; struct nexthop *rtnh; char buf2[INET6_ADDRSTRLEN]; + rib_dest_t *dest; assert(!src_p || afi == AFI_IP6); @@ -2357,14 +2349,14 @@ void rib_delete(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, return; } + dest = rib_dest_from_rnode(rn); + fib = dest->selected_fib; + /* Lookup same type route. */ RNODE_FOREACH_RE (rn, re) { if (CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED)) continue; - if (CHECK_FLAG(re->status, ROUTE_ENTRY_SELECTED_FIB)) - fib = re; - if (re->type != type) continue; if (re->instance != instance) @@ -2427,8 +2419,7 @@ void rib_delete(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, UNSET_FLAG(rtnh->flags, NEXTHOP_FLAG_FIB); - UNSET_FLAG(fib->status, - ROUTE_ENTRY_SELECTED_FIB); + dest->selected_fib = NULL; } else { /* This means someone else, other than Zebra, * has deleted @@ -2740,24 +2731,24 @@ void rib_close_table(struct route_table *table) { struct route_node *rn; rib_table_info_t *info; - struct route_entry *re; + rib_dest_t *dest; if (!table) return; info = table->info; - for (rn = route_top(table); rn; rn = srcdest_route_next(rn)) - RNODE_FOREACH_RE (rn, re) { - if (!CHECK_FLAG(re->status, ROUTE_ENTRY_SELECTED_FIB)) - continue; + for (rn = route_top(table); rn; rn = srcdest_route_next(rn)) { + dest = rib_dest_from_rnode(rn); + if (dest && dest->selected_fib) { if (info->safi == SAFI_UNICAST) hook_call(rib_update, rn, NULL); - if (!RIB_SYSTEM_ROUTE(re)) - rib_uninstall_kernel(rn, re); + if (!RIB_SYSTEM_ROUTE(dest->selected_fib)) + rib_uninstall_kernel(rn, dest->selected_fib); } + } } /* Routing information base initialize. */ diff --git a/zebra/zebra_static.c b/zebra/zebra_static.c index 5927ba9d75..751ea08a38 100644 --- a/zebra/zebra_static.c +++ b/zebra/zebra_static.c @@ -331,11 +331,12 @@ void static_uninstall_route(afi_t afi, safi_t safi, struct prefix *p, } UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE); if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB)) { + rib_dest_t *dest = rib_dest_from_rnode(rn); + /* If there are other active nexthops, do an update. */ if (re->nexthop_active_num > 1) { /* Update route in kernel if it's in fib */ - if (CHECK_FLAG(re->status, - ROUTE_ENTRY_SELECTED_FIB)) + if (dest->selected_fib) rib_install_kernel(rn, re, re); /* Update redistribution if it's selected */ if (CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED)) @@ -350,8 +351,7 @@ void static_uninstall_route(afi_t afi, safi_t safi, struct prefix *p, p, (struct prefix *)src_p, re); /* Remove from kernel if fib route becomes * inactive */ - if (CHECK_FLAG(re->status, - ROUTE_ENTRY_SELECTED_FIB)) + if (dest->selected_fib) rib_uninstall_kernel(rn, re); } } diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c index c2c7075671..198eb090cd 100644 --- a/zebra/zebra_vty.c +++ b/zebra/zebra_vty.c @@ -961,6 +961,7 @@ static int do_show_ip_route(struct vty *vty, const char *vrf_name, afi_t afi, u_short ospf_instance_id) { struct route_table *table; + rib_dest_t *dest; struct route_node *rn; struct route_entry *re; int first = 1; @@ -998,10 +999,11 @@ static int do_show_ip_route(struct vty *vty, const char *vrf_name, afi_t afi, /* Show all routes. */ for (rn = route_top(table); rn; rn = route_next(rn)) { + dest = rib_dest_from_rnode(rn); + RNODE_FOREACH_RE (rn, re) { if (use_fib - && !CHECK_FLAG(re->status, - ROUTE_ENTRY_SELECTED_FIB)) + && re != dest->selected_fib) continue; if (tag && re->tag != tag) From d616d6397af219205562bf77e79d24028d6bc716 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Mon, 4 Dec 2017 09:29:08 -0500 Subject: [PATCH 02/48] configure, zebra: Kame is not responsible for on/off of v6 forwarding The KAME flag should not be used to turn on/of v6 forwarding on *bsd systems. Create a configure #define to better describe what we are doing and the why of it. Signed-off-by: Donald Sharp --- configure.ac | 2 ++ zebra/ipforward_sysctl.c | 6 +++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/configure.ac b/configure.ac index 16cc8901a3..cd0aab1adf 100755 --- a/configure.ac +++ b/configure.ac @@ -875,6 +875,7 @@ case "$host_os" in AC_DEFINE(OPEN_BSD,,OpenBSD) AC_DEFINE(KAME,1,KAME IPv6) + AC_DEFINE(BSD_V6_SYSCTL,1,BSD v6 sysctl to turn on and off forwarding) if test "x${enable_pimd}" != "xno"; then case "$host_os" in @@ -891,6 +892,7 @@ case "$host_os" in AC_DEFINE(HAVE_NET_RT_IFLIST,,NET_RT_IFLIST) AC_DEFINE(KAME,1,KAME IPv6) + AC_DEFINE(BSD_V6_SYSCTL,1,BSD v6 sysctl to turn on and off forwarding) ;; esac AM_CONDITIONAL(SOLARIS, test "${SOLARIS}" = "solaris") diff --git a/zebra/ipforward_sysctl.c b/zebra/ipforward_sysctl.c index 36212a0132..cdf426b9b8 100644 --- a/zebra/ipforward_sysctl.c +++ b/zebra/ipforward_sysctl.c @@ -87,11 +87,11 @@ int ipforward_off(void) /* IPv6 forwarding control MIB. */ int mib_ipv6[MIB_SIZ] = {CTL_NET, PF_INET6, -#if defined(KAME) +#if defined(BSD_V6_SYSCTL) IPPROTO_IPV6, IPV6CTL_FORWARDING -#else /* NOT KAME */ +#else /* NOT BSD_V6_SYSCTL */ IPPROTO_IP, IP6CTL_FORWARDING -#endif /* KAME */ +#endif /* BSD_V6_SYSCTL */ }; int ipforward_ipv6(void) From a7ea39668db8281c5f0713f7c467d2bd3fe41770 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Mon, 4 Dec 2017 10:12:36 -0500 Subject: [PATCH 03/48] *: Remove cvs control points The $Id: lines would allow code kept in cvs to substitute the file version upon checkout. Since we are not using cvs there is no need to keep these lines anymore. Signed-off-by: Donald Sharp --- isisd/dict.h | 2 -- lib/md5.c | 4 ---- lib/md5.h | 4 ---- lib/zassert.h | 2 -- ospfd/OSPF-ALIGNMENT.txt | 2 -- pkgsrc/README.txt | 2 -- ripd/ripd.conf.sample | 2 -- ripngd/ripngd.conf.sample | 2 -- tests/helpers/c/main.c | 2 -- tests/lib/test_heavy.c | 2 -- tests/lib/test_heavy_thread.c | 2 -- tests/lib/test_privs.c | 2 -- zebra/zebra.conf.sample | 2 -- 13 files changed, 30 deletions(-) diff --git a/isisd/dict.h b/isisd/dict.h index a5ee922318..32683c57d5 100644 --- a/isisd/dict.h +++ b/isisd/dict.h @@ -14,8 +14,6 @@ * into proprietary software; there is no requirement for such software to * contain a copyright notice related to this source. * - * $Id: dict.h,v 1.3 2005/09/25 12:04:25 hasso Exp $ - * $Name: $ */ #ifndef DICT_H diff --git a/lib/md5.c b/lib/md5.c index cce67d7ec1..8989a93c59 100644 --- a/lib/md5.c +++ b/lib/md5.c @@ -1,7 +1,3 @@ -/* $USAGI: md5.c,v 1.2 2000/11/02 11:59:24 yoshfuji Exp $ */ -/* $KAME: md5.c,v 1.2 2000/05/27 07:07:48 jinmei Exp $ */ -/* $Id: md5.c,v 1.6 2006/01/17 23:39:04 vincent Exp $ */ - /* * Copyright (C) 2004 6WIND * diff --git a/lib/md5.h b/lib/md5.h index adc92d670d..59291c7df3 100644 --- a/lib/md5.h +++ b/lib/md5.h @@ -1,7 +1,3 @@ -/* $USAGI: md5.h,v 1.2 2000/11/02 11:59:25 yoshfuji Exp $ */ -/* $KAME: md5.h,v 1.4 2000/03/27 04:36:22 sumikawa Exp $ */ -/* $Id: md5.h,v 1.3 2006/01/17 17:40:45 paul Exp $ */ - /* * Copyright (C) 2004 6WIND * diff --git a/lib/zassert.h b/lib/zassert.h index 5c06d933e6..d45e1be5f8 100644 --- a/lib/zassert.h +++ b/lib/zassert.h @@ -1,6 +1,4 @@ /* - * $Id: zassert.h,v 1.2 2004/12/03 18:01:04 ajs Exp $ - * * This file is part of Quagga. * * Quagga is free software; you can redistribute it and/or modify it diff --git a/ospfd/OSPF-ALIGNMENT.txt b/ospfd/OSPF-ALIGNMENT.txt index dac6182fde..905bd228b1 100644 --- a/ospfd/OSPF-ALIGNMENT.txt +++ b/ospfd/OSPF-ALIGNMENT.txt @@ -1,5 +1,3 @@ -$Id: OSPF-ALIGNMENT.txt,v 1.1 2004/11/17 17:59:52 gdt Exp $ - Greg Troxel 2004-11-17 diff --git a/pkgsrc/README.txt b/pkgsrc/README.txt index 13ec449a1f..b70bb3fc1d 100644 --- a/pkgsrc/README.txt +++ b/pkgsrc/README.txt @@ -1,5 +1,3 @@ -$Id: README.txt,v 1.1 2004/08/27 15:57:35 gdt Exp $ - This directory contains files for use with the pkgsrc framework (http://www.pkgsrc.org) used with NetBSD and other operating systems. Eventually it will be hooked into automake such that they can be diff --git a/ripd/ripd.conf.sample b/ripd/ripd.conf.sample index 2902ff9cca..e11bf0bb23 100644 --- a/ripd/ripd.conf.sample +++ b/ripd/ripd.conf.sample @@ -2,8 +2,6 @@ ! ! RIPd sample configuration file ! -! $Id: ripd.conf.sample,v 1.1 2002/12/13 20:15:30 paul Exp $ -! hostname ripd password zebra ! diff --git a/ripngd/ripngd.conf.sample b/ripngd/ripngd.conf.sample index ad673e57e0..28f08c399a 100644 --- a/ripngd/ripngd.conf.sample +++ b/ripngd/ripngd.conf.sample @@ -2,8 +2,6 @@ ! ! RIPngd sample configuration file ! -! $Id: ripngd.conf.sample,v 1.1 2002/12/13 20:15:30 paul Exp $ -! hostname ripngd password zebra ! diff --git a/tests/helpers/c/main.c b/tests/helpers/c/main.c index 9bf56dde14..fed1d5a537 100644 --- a/tests/helpers/c/main.c +++ b/tests/helpers/c/main.c @@ -1,6 +1,4 @@ /* - * $Id: main.c,v 1.1 2005/04/25 16:42:24 paul Exp $ - * * This file is part of Quagga. * * Quagga is free software; you can redistribute it and/or modify it diff --git a/tests/lib/test_heavy.c b/tests/lib/test_heavy.c index 604a5733ca..e2a0a2d49a 100644 --- a/tests/lib/test_heavy.c +++ b/tests/lib/test_heavy.c @@ -1,6 +1,4 @@ /* - * $Id: heavy.c,v 1.3 2005/04/25 16:42:24 paul Exp $ - * * This file is part of Quagga. * * Quagga is free software; you can redistribute it and/or modify it diff --git a/tests/lib/test_heavy_thread.c b/tests/lib/test_heavy_thread.c index 9a75780060..075bcb6daf 100644 --- a/tests/lib/test_heavy_thread.c +++ b/tests/lib/test_heavy_thread.c @@ -1,6 +1,4 @@ /* - * $Id: heavy-thread.c,v 1.2 2005/04/25 16:42:24 paul Exp $ - * * This file is part of Quagga. * * Quagga is free software; you can redistribute it and/or modify it diff --git a/tests/lib/test_privs.c b/tests/lib/test_privs.c index 1984f28e63..421c345436 100644 --- a/tests/lib/test_privs.c +++ b/tests/lib/test_privs.c @@ -1,6 +1,4 @@ /* - * $Id: test-privs.c,v 1.1 2005/10/11 03:48:28 paul Exp $ - * * This file is part of Quagga. * * Quagga is free software; you can redistribute it and/or modify it diff --git a/zebra/zebra.conf.sample b/zebra/zebra.conf.sample index a5d0732f6b..03042eb083 100644 --- a/zebra/zebra.conf.sample +++ b/zebra/zebra.conf.sample @@ -2,8 +2,6 @@ ! ! zebra sample configuration file ! -! $Id: zebra.conf.sample,v 1.1 2002/12/13 20:15:30 paul Exp $ -! hostname Router password zebra enable password zebra From 14b8641a5e49df620dcdcb686f67be0b37908f40 Mon Sep 17 00:00:00 2001 From: Quentin Young Date: Wed, 6 Dec 2017 17:35:21 -0500 Subject: [PATCH 04/48] bgpd: fix config display of coalesce-time Since coalesce time is now heuristically adjusted based on peer count, we need to separate out specific configuration by the user from the current value. Behavior established is to not adjust if the user has a value set. Signed-off-by: Quentin Young --- bgpd/bgp_vty.c | 8 +++++--- bgpd/bgpd.c | 9 ++++++--- bgpd/bgpd.h | 5 ++++- 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index 5515643ed1..1c6d38dccf 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -1423,8 +1423,8 @@ DEFUN (no_bgp_rpkt_quanta, void bgp_config_write_coalesce_time(struct vty *vty, struct bgp *bgp) { - if (bgp->coalesce_time != BGP_DEFAULT_SUBGROUP_COALESCE_TIME) - vty_out(vty, " coalesce-time %u\n", bgp->coalesce_time); + if (bgp->v_coalesce_time) + vty_out(vty, " coalesce-time %u\n", bgp->v_coalesce_time); } @@ -1438,7 +1438,8 @@ DEFUN (bgp_coalesce_time, int idx = 0; argv_find(argv, argc, "(0-4294967295)", &idx); - bgp->coalesce_time = strtoul(argv[idx]->arg, NULL, 10); + bgp->coalesce_time = bgp->v_coalesce_time = + strtoul(argv[idx]->arg, NULL, 10); return CMD_SUCCESS; } @@ -1451,6 +1452,7 @@ DEFUN (no_bgp_coalesce_time, { VTY_DECLVAR_CONTEXT(bgp, bgp); + bgp->v_coalesce_time = 0; bgp->coalesce_time = BGP_DEFAULT_SUBGROUP_COALESCE_TIME; return CMD_SUCCESS; } diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index 8b27a0e905..ed92246dbc 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -1475,9 +1475,12 @@ struct peer *peer_create(union sockunion *su, const char *conf_if, hash_get(bgp->peerhash, peer, hash_alloc_intern); /* Adjust update-group coalesce timer heuristics for # peers. */ - long ct = BGP_DEFAULT_SUBGROUP_COALESCE_TIME - + (bgp->peer->count * BGP_PEER_ADJUST_SUBGROUP_COALESCE_TIME); - bgp->coalesce_time = MIN(BGP_MAX_SUBGROUP_COALESCE_TIME, ct); + if (!bgp->v_coalesce_time) { + long ct = BGP_DEFAULT_SUBGROUP_COALESCE_TIME + + (bgp->peer->count + * BGP_PEER_ADJUST_SUBGROUP_COALESCE_TIME); + bgp->coalesce_time = MIN(BGP_MAX_SUBGROUP_COALESCE_TIME, ct); + } active = peer_active(peer); diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h index e5e363ef52..e8189dbf8c 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h @@ -381,7 +381,10 @@ struct bgp { _Atomic uint32_t wpkt_quanta; // max # packets to write per i/o cycle _Atomic uint32_t rpkt_quanta; // max # packets to read per i/o cycle - u_int32_t coalesce_time; + /* Configured coalesce time */ + uint32_t v_coalesce_time; + /* Actual coalesce time */ + uint32_t coalesce_time; u_int32_t addpath_tx_id; int addpath_tx_used[AFI_MAX][SAFI_MAX]; From b456bceb4a4f7cfd8d926d400a27da611bf51e15 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 12 Dec 2017 20:29:38 -0500 Subject: [PATCH 05/48] pimd: Really, Actually send S,G rpt prune upstream When we receive a S,G rpt prune message for a mroute, really, absolutely, guarantee the send upstream immediately. Signed-off-by: Donald Sharp --- pimd/pim_ifchannel.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c index 5f597b17b1..7d3b783adf 100644 --- a/pimd/pim_ifchannel.c +++ b/pimd/pim_ifchannel.c @@ -640,6 +640,13 @@ static int on_ifjoin_prune_pending_timer(struct thread *t) ch = THREAD_ARG(t); + if (PIM_DEBUG_TRACE) + zlog_debug("%s: IFCHANNEL%s %s Prune Pending Timer Popped", + __PRETTY_FUNCTION__, + pim_str_sg_dump(&ch->sg), + pim_ifchannel_ifjoin_name(ch->ifjoin_state, + ch->flags)); + if (ch->ifjoin_state == PIM_IFJOIN_PRUNE_PENDING) { ifp = ch->interface; pim_ifp = ifp->info; @@ -665,16 +672,19 @@ static int on_ifjoin_prune_pending_timer(struct thread *t) * message on RP path upon prune timer expiry. */ ch->ifjoin_state = PIM_IFJOIN_PRUNE; - if (ch->upstream) + if (ch->upstream) { + struct pim_upstream *parent = + ch->upstream->parent; + pim_upstream_update_join_desired(pim_ifp->pim, ch->upstream); + + pim_jp_agg_single_upstream_send(&parent->rpf, + parent, + true); + } } /* from here ch may have been deleted */ - } else { - zlog_warn( - "%s: IFCHANNEL%s Prune Pending Timer Popped while in %s state", - __PRETTY_FUNCTION__, pim_str_sg_dump(&ch->sg), - pim_ifchannel_ifjoin_name(ch->ifjoin_state, ch->flags)); } return 0; From c71b85570e3ad6c06de3762d6cb2c2221af79af7 Mon Sep 17 00:00:00 2001 From: Lucian Cristian Date: Wed, 13 Dec 2017 23:13:59 +0200 Subject: [PATCH 06/48] configure: exclude some checks not needed on clippy host build from David Lamparter Signed-off-by: Lucian Cristian --- configure.ac | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 16cc8901a3..911de537ec 100755 --- a/configure.ac +++ b/configure.ac @@ -40,7 +40,7 @@ AS_IF([test "$host" != "$build"], [ ( CPPFLAGS="$HOST_CPPFLAGS"; \ CFLAGS="$HOST_CFLAGS"; \ LDFLAGS="$HOST_LDFLAGS"; \ - cd hosttools; "${abssrc}/configure" "--host=$build" "--build=$build"; ) + cd hosttools; "${abssrc}/configure" "--host=$build" "--build=$build" "--enable-clippy-only" "--disable-nhrpd" "--disable-vtysh"; ) AC_MSG_NOTICE([...]) AC_MSG_NOTICE([... cross-compilation: finished self-configuring for build platform tools]) @@ -392,7 +392,10 @@ AC_ARG_ENABLE([oldvpn_commands], AS_HELP_STRING([--enable-oldvpn-commands], [Keep old vpn commands])) AC_ARG_ENABLE(rpki, AS_HELP_STRING([--enable-rpki], [enable RPKI prefix validation support])) +AC_ARG_ENABLE([clippy-only], + AS_HELP_STRING([--enable-clippy-only], [Only build clippy])) +AS_IF([test "${enable_clippy_only}" != "yes"], [ AC_CHECK_HEADERS(json-c/json.h) AC_CHECK_LIB(json-c, json_object_get, LIBS="$LIBS -ljson-c", [], [-lm]) if test $ac_cv_lib_json_c_json_object_get = no; then @@ -401,6 +404,7 @@ if test $ac_cv_lib_json_c_json_object_get = no; then AC_MSG_ERROR([lib json is needed to compile]) fi fi +]) AC_ARG_ENABLE([dev_build], AS_HELP_STRING([--enable-dev-build], [build for development])) From 0d0268a6ba48d1b93e3a29a8e2deb02367defb16 Mon Sep 17 00:00:00 2001 From: Lou Berger Date: Tue, 12 Dec 2017 08:26:20 -0500 Subject: [PATCH 07/48] bgpd: minor performance enhancement Signed-off-by: Lou Berger --- bgpd/bgp_attr.c | 30 ++++++++++++------------------ 1 file changed, 12 insertions(+), 18 deletions(-) diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c index e80889500f..00bad08fbe 100644 --- a/bgpd/bgp_attr.c +++ b/bgpd/bgp_attr.c @@ -492,19 +492,13 @@ unsigned int attrhash_key_make(void *p) const struct attr *attr = (struct attr *)p; uint32_t key = 0; #define MIX(val) key = jhash_1word(val, key) +#define MIX3(a, b, c) key = jhash_3words((a), (b), (c), key) - MIX(attr->origin); - MIX(attr->nexthop.s_addr); - MIX(attr->med); - MIX(attr->local_pref); - MIX(attr->aggregator_as); - MIX(attr->aggregator_addr.s_addr); - MIX(attr->weight); - MIX(attr->mp_nexthop_global_in.s_addr); - MIX(attr->originator_id.s_addr); - MIX(attr->tag); - MIX(attr->label); - MIX(attr->label_index); + MIX3(attr->origin, attr->nexthop.s_addr, attr->med); + MIX3(attr->local_pref, attr->aggregator_as, attr->aggregator_addr.s_addr); + MIX3(attr->weight, attr->mp_nexthop_global_in.s_addr, + attr->originator_id.s_addr); + MIX3(attr->tag, attr->label, attr->label_index); if (attr->aspath) MIX(aspath_key_make(attr->aspath)); @@ -550,12 +544,6 @@ int attrhash_cmp(const void *p1, const void *p2) && attr1->tag == attr2->tag && attr1->label_index == attr2->label_index && attr1->mp_nexthop_len == attr2->mp_nexthop_len - && IPV6_ADDR_SAME(&attr1->mp_nexthop_global, - &attr2->mp_nexthop_global) - && IPV6_ADDR_SAME(&attr1->mp_nexthop_local, - &attr2->mp_nexthop_local) - && IPV4_ADDR_SAME(&attr1->mp_nexthop_global_in, - &attr2->mp_nexthop_global_in) && attr1->ecommunity == attr2->ecommunity && attr1->lcommunity == attr2->lcommunity && attr1->cluster == attr2->cluster @@ -565,6 +553,12 @@ int attrhash_cmp(const void *p1, const void *p2) #if ENABLE_BGP_VNC && encap_same(attr1->vnc_subtlvs, attr2->vnc_subtlvs) #endif + && IPV6_ADDR_SAME(&attr1->mp_nexthop_global, + &attr2->mp_nexthop_global) + && IPV6_ADDR_SAME(&attr1->mp_nexthop_local, + &attr2->mp_nexthop_local) + && IPV4_ADDR_SAME(&attr1->mp_nexthop_global_in, + &attr2->mp_nexthop_global_in) && IPV4_ADDR_SAME(&attr1->originator_id, &attr2->originator_id) && overlay_index_same(attr1, attr2)) From 23b2a7ef524c9fe083b217c7f6ebaec0effc8f52 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 14 Dec 2017 09:31:26 -0500 Subject: [PATCH 08/48] bgpd: Speedup vtysh handling of 'show bgp afi safi json' display When bgp has a metric butt-load of routes w/ ecmp, this command can take an inordinate amount of time to run and complete via vtysh. Converting the bgp route output in this case back to not using the json pretty-print drops ~2 minutes of runtime off. It is assumed that if users would like pretty output they can run it through an appropriate tool via a pipe command. Signed-off-by: Donald Sharp --- bgpd/bgp_route.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 2323572488..54a1bcda50 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -8394,7 +8394,7 @@ static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi, vty_out(vty, ",\"%s\": ", buf2); vty_out(vty, "%s", - json_object_to_json_string_ext(json_paths, JSON_C_TO_STRING_PRETTY)); + json_object_to_json_string(json_paths)); json_object_free(json_paths); first = 0; } From 4e40b6d61548eda00277c1c59c5a6ace0c1d6055 Mon Sep 17 00:00:00 2001 From: Kaloyan Kovachev Date: Fri, 8 Dec 2017 14:44:15 -0500 Subject: [PATCH 09/48] zebra: Add ability to support tags -> realms in linux Linux has the ability to support a concept of 'realms'. This concept allows you to mark routes with a realm id value of 1-255. If you have marked the realm of a route then you can use the tc program to apply policy to the routes. This commit adds the ability of FRR to interpret a tag from (1-255) as a realm when installing into the kernel. Please note that at this point in time there is no way to set policy from within FRR. This must be done outside of it. The normal methodology for setting tags is valid here via a route-map. Finally this is only applied if the --enable-realms configure option is applied. Signed-off-by: Kaloyan Kovachev --- configure.ac | 18 ++++++++++++++++++ zebra/connected.c | 4 ++-- zebra/kernel_socket.c | 4 ++-- zebra/rib.h | 2 +- zebra/rt_netlink.c | 15 +++++++++++++-- zebra/rtread_getmsg.c | 2 +- zebra/zebra_rib.c | 3 ++- 7 files changed, 39 insertions(+), 9 deletions(-) diff --git a/configure.ac b/configure.ac index 16cc8901a3..762ce14816 100755 --- a/configure.ac +++ b/configure.ac @@ -354,6 +354,8 @@ AC_ARG_ENABLE(logfile_mask, AS_HELP_STRING([--enable-logfile-mask=ARG], [set mask for log files])) AC_ARG_ENABLE(shell_access, AS_HELP_STRING([--enable-shell-access], [Allow users to access shell/telnet/ssh])) +AC_ARG_ENABLE(realms, + AS_HELP_STRING([--enable-realms], [enable REALMS support under Linux])) AC_ARG_ENABLE(rtadv, AS_HELP_STRING([--disable-rtadv], [disable IPV6 router advertisement feature])) AC_ARG_ENABLE(irdp, @@ -897,6 +899,22 @@ AM_CONDITIONAL(SOLARIS, test "${SOLARIS}" = "solaris") AC_SYS_LARGEFILE +dnl ------------------------ +dnl Integrated REALMS option +dnl ------------------------ +if test "${enable_realms}" = "yes"; then + case "$host_os" in + linux*) + AC_DEFINE(SUPPORT_REALMS,, Realms support) + ;; + *) + echo "Sorry, only Linux has REALMS support" + exit 1 + ;; + esac +fi +AM_CONDITIONAL([SUPPORT_REALMS], [test "${enable_realms}" = "yes"]) + dnl --------------------- dnl Integrated VTY option dnl --------------------- diff --git a/zebra/connected.c b/zebra/connected.c index 18dc6a970b..9c0a3af8e3 100644 --- a/zebra/connected.c +++ b/zebra/connected.c @@ -239,10 +239,10 @@ void connected_up(struct interface *ifp, struct connected *ifc) } rib_add(afi, SAFI_UNICAST, ifp->vrf_id, ZEBRA_ROUTE_CONNECT, 0, 0, - &p, NULL, &nh, RT_TABLE_MAIN, ifp->metric, 0, 0); + &p, NULL, &nh, RT_TABLE_MAIN, ifp->metric, 0, 0, 0); rib_add(afi, SAFI_MULTICAST, ifp->vrf_id, ZEBRA_ROUTE_CONNECT, 0, 0, - &p, NULL, &nh, RT_TABLE_MAIN, ifp->metric, 0, 0); + &p, NULL, &nh, RT_TABLE_MAIN, ifp->metric, 0, 0, 0); if (IS_ZEBRA_DEBUG_RIB_DETAILED) { char buf[PREFIX_STRLEN]; diff --git a/zebra/kernel_socket.c b/zebra/kernel_socket.c index 89c933f90f..d45a502543 100644 --- a/zebra/kernel_socket.c +++ b/zebra/kernel_socket.c @@ -1050,7 +1050,7 @@ void rtm_read(struct rt_msghdr *rtm) || rtm->rtm_type == RTM_CHANGE) rib_add(AFI_IP, SAFI_UNICAST, VRF_DEFAULT, ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, NULL, - &nh, 0, 0, 0, 0); + &nh, 0, 0, 0, 0, 0); else rib_delete(AFI_IP, SAFI_UNICAST, VRF_DEFAULT, ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, NULL, @@ -1098,7 +1098,7 @@ void rtm_read(struct rt_msghdr *rtm) || rtm->rtm_type == RTM_CHANGE) rib_add(AFI_IP6, SAFI_UNICAST, VRF_DEFAULT, ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, NULL, - &nh, 0, 0, 0, 0); + &nh, 0, 0, 0, 0, 0); else rib_delete(AFI_IP6, SAFI_UNICAST, VRF_DEFAULT, ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, NULL, diff --git a/zebra/rib.h b/zebra/rib.h index 4b82e8d8d5..7e166f7e1c 100644 --- a/zebra/rib.h +++ b/zebra/rib.h @@ -296,7 +296,7 @@ extern int rib_add(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, u_short instance, int flags, struct prefix *p, struct prefix_ipv6 *src_p, const struct nexthop *nh, u_int32_t table_id, u_int32_t metric, u_int32_t mtu, - uint8_t distance); + uint8_t distance, route_tag_t tag); extern int rib_add_multipath(afi_t afi, safi_t safi, struct prefix *, struct prefix_ipv6 *src_p, struct route_entry *); diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index cbe736e00c..910f9b3d93 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -230,6 +230,7 @@ static int netlink_route_change_read_unicast(struct sockaddr_nl *snl, int metric = 0; u_int32_t mtu = 0; uint8_t distance = 0; + route_tag_t tag = 0; void *dest = NULL; void *gate = NULL; @@ -321,6 +322,11 @@ static int netlink_route_change_read_unicast(struct sockaddr_nl *snl, if (tb[RTA_PRIORITY]) metric = *(int *)RTA_DATA(tb[RTA_PRIORITY]); +#if defined(SUPPORT_REALMS) + if (tb[RTA_FLOW]) + tag = *(uint32_t *)RTA_DATA(tb[RTA_FLOW]); +#endif + if (tb[RTA_METRICS]) { struct rtattr *mxrta[RTAX_MAX + 1]; @@ -429,7 +435,8 @@ static int netlink_route_change_read_unicast(struct sockaddr_nl *snl, memcpy(&nh.gate, gate, sz); rib_add(afi, SAFI_UNICAST, vrf_id, proto, - 0, flags, &p, NULL, &nh, table, metric, mtu, distance); + 0, flags, &p, NULL, &nh, table, metric, + mtu, distance, tag); } else { /* This is a multipath route */ @@ -449,6 +456,7 @@ static int netlink_route_change_read_unicast(struct sockaddr_nl *snl, re->table = table; re->nexthop_num = 0; re->uptime = time(NULL); + re->tag = tag; for (;;) { if (len < (int)sizeof(*rtnh) @@ -1310,7 +1318,10 @@ static int netlink_route_multipath(int cmd, struct prefix *p, * by the routing protocol and for communicating with protocol peers. */ addattr32(&req.n, sizeof req, RTA_PRIORITY, NL_DEFAULT_ROUTE_METRIC); - +#if defined(SUPPORT_REALMS) + if (re->tag > 0 && re->tag <= 255) + addattr32(&req.n, sizeof req, RTA_FLOW, re->tag); +#endif /* Table corresponding to this route. */ if (re->table < 256) req.r.rtm_table = re->table; diff --git a/zebra/rtread_getmsg.c b/zebra/rtread_getmsg.c index 39ecdb335c..69e45f9a6c 100644 --- a/zebra/rtread_getmsg.c +++ b/zebra/rtread_getmsg.c @@ -98,7 +98,7 @@ static void handle_route_entry(mib2_ipRouteEntry_t *routeEntry) nh.gate.ipv4.s_addr = routeEntry->ipRouteNextHop; rib_add(AFI_IP, SAFI_UNICAST, VRF_DEFAULT, ZEBRA_ROUTE_KERNEL, 0, - zebra_flags, &prefix, NULL, &nh, 0, 0, 0, 0); + zebra_flags, &prefix, NULL, &nh, 0, 0, 0, 0, 0); } void route_read(struct zebra_ns *zns) diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index 58b6965995..6406386b1a 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -2480,7 +2480,7 @@ void rib_delete(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, int rib_add(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, u_short instance, int flags, struct prefix *p, struct prefix_ipv6 *src_p, const struct nexthop *nh, u_int32_t table_id, u_int32_t metric, - u_int32_t mtu, uint8_t distance) + u_int32_t mtu, uint8_t distance, route_tag_t tag) { struct route_entry *re; struct nexthop *nexthop; @@ -2497,6 +2497,7 @@ int rib_add(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, u_short instance, re->vrf_id = vrf_id; re->nexthop_num = 0; re->uptime = time(NULL); + re->tag = tag; /* Add nexthop. */ nexthop = nexthop_new(); From 6347ca161f94af4baa853bf09be7fff076e75491 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 8 Dec 2017 14:55:58 -0500 Subject: [PATCH 10/48] doc: Add documentation for the tag/realm commands Add some documentation for the tag and realm commands. Signed-off-by: Donald Sharp --- doc/install.texi | 4 ++++ doc/routemap.texi | 13 +++++++++++++ 2 files changed, 17 insertions(+) diff --git a/doc/install.texi b/doc/install.texi index 19d9614420..d0d56804b0 100644 --- a/doc/install.texi +++ b/doc/install.texi @@ -85,6 +85,10 @@ Enable Traffic Engineering Extension for ISIS (RFC5305) @item --enable-multipath=@var{ARG} Enable support for Equal Cost Multipath. @var{ARG} is the maximum number of ECMP paths to allow, set to 0 to allow unlimited number of paths. +@item --enable-realms +Enable the support of linux Realms. Convert tag values from 1-255 +into a realm value when inserting into the linux kernel. Then +routing policy can be assigned to the realm. See the tc man page. @item --disable-rtadv Disable support IPV6 router advertisement in zebra. @item --enable-gcc-rdynamic diff --git a/doc/routemap.texi b/doc/routemap.texi index b72f539c46..3e683f44d1 100644 --- a/doc/routemap.texi +++ b/doc/routemap.texi @@ -171,6 +171,11 @@ Matches the specified @var{as_path}. Matches the specified @var{metric}. @end deffn +@deffn {Route-map Command} {match tag @var{tag}} {} +Matches the specified tag value associated with the route. +This tag value can be in the range of (1-4294967295). +@end deffn + @deffn {Route-map Command} {match local-preference @var{metric}} {} Matches the specified @var{local-preference}. @end deffn @@ -198,6 +203,14 @@ in this manner. @node Route Map Set Command @section Route Map Set Command +@deffn {Route-map Command} {set tag @var{tag}} {} +Set a tag on the matched route. This tag value can be from +(1-4294967295). Additionally if you have compiled with +the --enable-realms configure option. Tag values from (1-255) +are sent to the linux kernel as a realm value. Then route +policy can be applied. See the tc man page. +@end deffn + @deffn {Route-map Command} {set ip next-hop @var{ipv4_address}} {} Set the BGP nexthop address. @end deffn From 0efb5e9b4b5ce9f1548203d59b366c8a2f69b338 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 8 Dec 2017 15:02:46 -0500 Subject: [PATCH 11/48] zebra: Display if a taged route is being used as a realm When displaying a specific route and if it has a tag and if we have turned on realm support notify the user that a tag value of (1-255) is installed into the kernel with the realm set. Signed-off-by: Donald Sharp --- zebra/zebra_vty.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c index e4407d7316..9dab3f9466 100644 --- a/zebra/zebra_vty.c +++ b/zebra/zebra_vty.c @@ -474,8 +474,13 @@ static void vty_show_ip_route_detail(struct vty *vty, struct route_node *rn, vty_out(vty, "\""); vty_out(vty, ", distance %u, metric %u", re->distance, re->metric); - if (re->tag) + if (re->tag) { vty_out(vty, ", tag %u", re->tag); +#if defined(SUPPORT_REALMS) + if (re->tag > 0 && re->tag <= 255) + vty_out(vty, "(realm)"); +#endif + } if (re->mtu) vty_out(vty, ", mtu %u", re->mtu); if (re->vrf_id != VRF_DEFAULT) { From 42642babdd1bb3a350affb459f56a4494461c203 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 8 Dec 2017 19:38:24 -0500 Subject: [PATCH 12/48] doc: Add some PIM documentation Signed-off-by: Donald Sharp --- doc/Makefile.am | 3 +- doc/pimd.texi | 366 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 368 insertions(+), 1 deletion(-) create mode 100644 doc/pimd.texi diff --git a/doc/Makefile.am b/doc/Makefile.am index 6c80ddeaa4..bb5fa32d59 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -69,7 +69,8 @@ frr_TEXINFOS = appendix.texi basic.texi bgpd.texi isisd.texi filter.texi \ overview.texi protocol.texi ripd.texi ripngd.texi routemap.texi \ snmp.texi vtysh.texi routeserver.texi $(figures_png) \ snmptrap.texi ospf_fundamentals.texi isisd.texi $(figures_txt) \ - rpki.texi + rpki.texi \ + pimd.texi .png.eps: $(PNGTOEPS) $< "$@" diff --git a/doc/pimd.texi b/doc/pimd.texi new file mode 100644 index 0000000000..30e85afbb0 --- /dev/null +++ b/doc/pimd.texi @@ -0,0 +1,366 @@ +@c -*-texinfo-*- +@c This is part of the Frr Manual. +@c @value{COPYRIGHT_STR} +@c See file frr.texi for copying conditions. +@node PIM +@chapter PIM + +PIM -- Protocol Independent Multicast + +@command{pimd} supports pim-sm as well as igmp v2 and v3. pim is +vrf aware and can work within the context of vrf's in order to +do S,G mrouting. + +@menu +* Starting and Stopping pimd:: +* PIM Configuration:: +* PIM Interface Configuration:: +* PIM Multicast RIB insertion:: +* Show PIM Information:: +* PIM Debug Commands:: +@end menu + +@node Starting and Stopping pimd +@section Starting and Stopping pimd + +The default configuration file name of @command{pimd}'s is +@file{pimd.conf}. When invocation @command{pimd} searches directory +@value{INSTALL_PREFIX_ETC}. If @file{pimd.conf} is not there +then next search current directory. + +@command{pimd} requires zebra for proper operation. Additionally +@command{pimd} depends on routing properly setup and working +in the network that it is working on. + +@example +@group +# zebra -d +# pimd -d +@end group +@end example + +Please note that @command{zebra} must be invoked before @command{pimd}. + +To stop @command{pimd}. Please use @command{kill `cat +/var/run/pimd.pid`}. Certain signals have special meanings to @command{pimd}. + +@table @samp +@item SIGUSR1 +Rotate @command{pimd} logfile. +@item SIGINT +@itemx SIGTERM +@command{pimd} sweeps all installed PIM mroutes then terminates properly. +@end table + +@command{pimd} invocation options. Common options that can be specified +(@pxref{Common Invocation Options}). + +@node PIM Configuration + +@deffn Command {ip pim rp A.B.C.D A.B.C.D/M} {} +In order to use pim, it is necessary to configure a RP for join +messages to be sent to. Currently the only methodology to +do this is via static rp commands. All routers in the +pim network must agree on these values. The first ip address +is the RP's address and the second value is the matching +prefix of group ranges covered. This command is vrf aware, +to configure for a vrf, enter the vrf submode. +@end deffn + +@deffn Command {ip pim spt-switchover infinity-and-beyond} {} +On the last hop router if it is desired to not switch over +to the SPT tree. Configure this command. This command is +vrf aware, to configure for a vrf, enter the vrf submode. +#end deffn + +@deffn Comand {ip pim ecmp} {} +If pim has the a choice of ECMP nexthops for a particular +RPF, pim will cause S,G flows to be spread out amongst +the nexthops. If this command is not specified then +the first nexthop found will be used. This command +is vrf aware, to configure for a vrf, enter the vrf submode. +@end deffn + +@deffn Command {ip pim ecmp rebalance} {} +If pim is using ECMP and an interface goes down, cause +pim to rebalance all S,G flows aross the remaining +nexthops. If this command is not configured pim only +modifies those S,G flows that were using the interface +that went down. This command is vrf aware, to configure +for a vrf, enter the vrf submode. +@end deffn + +@deffn Command {ip pim join-prune-interval (60-600)} {} +Modify the join/prune interval that pim uses to the +new value. Time is specified in seconds. This command +is vrf aware, to configure for a vrf, enter the vrf submode. +@end deffn + +@deffn Command {ip pim keep-alive-timer (31-60000)} {} +Modify the time out value for a S,G flow from 31-60000 +seconds. 31 seconds is choosen for a lower bound +because some hardware platforms cannot see data flowing +in better than 30 second chunks. This comand is vrf +aware, to configure for a vrf, enter the vrf submode. +@end deffn + +@deffn Command {ip pim packets (1-100)} {} +When processing packets from a neighbor process the +number of packets incoming at one time before moving +on to the next task. The default value is 3 packets. +This command is only useful at scale when you can +possibly have a large number of pim control packets +flowing. This command is vrf aware, to configure for +a vrf, enter the vrf submode. +@end deffn + +@deffn Command {ip pim register-suppress-time (5-60000)} {} +Modify the time that pim will register suppress a FHR +will send register notifications to the kernel. This command +is vrf aware, to configure for a vrf, enter the vrf submode. +@end deffn + +@deffn Command {ip pim send-v6-secondary} {} +When sending pim hello packets tell pim to send +any v6 secondary addresses on the interface. This +information is used to allow pim to use v6 nexthops +in it's decision for RPF lookup. This command +is vrf aware, to configure for a vrf, enter the vrf submode. +@end deffn + +@deffn Command {ip pim ssm prefix-list WORD} {} +Specify a range of group addresses via a prefix-list +that forces pim to never do SM over. This command +is vrf aware, to configure for a vrf, enter the vrf submode. +@end deffn + +@deffn Command {ip multicast rpf-lookup-mode WORD} {} +Modify how PIM does RPF lookups in the zebra routing table. +You can use these choices: +@table @lookup_modes +@item longer-prefix +Lookup the RPF in both tables using the longer prefix as a match +@item lower-distance +Lookup the RPF in both tables using the lower distance as a match +@item mrib-only +Lookup in the Multicast RIB only +@item mrib-then-urib +Lookup in the Multicast RIB then the Unicast Rib, returning first found. +This is the default value for lookup if this command is not entered +@item urib-only +Lookup in the Unicast Rib only. +@end table +@end deffn + +@node PIM Interface Configuration +@section PIM Interface Configuration + +PIM interface commands allow you to configure an +interface as either a Receiver or a interface +that you would like to form pim neighbors on. If the +interface is in a vrf, enter the interface command with +the vrf keyword at the end. + +@deffn {PIM Interface Command] {ip pim bfd} {} +Turns on BFD support for PIM for this interface. +@end deffn + +@deffn {PIM Interface Command} {ip pim drpriority (1-4294967295)} {} +Set the DR Priority for the interface. This command is useful +to allow the user to influence what node becomes the DR for a +lan segment. +@end deffn + +@deffn {PIM Interface Command} {ip pim hello (1-180) (1-180)} {} +Set the pim hello and hold interval for a interface. +@end deffn + +@deffn {PIM Interface Command} {ip pim sm} {} +Tell pim that we would like to use this interface to form +pim neighbors over. Please note we will *not* accept +igmp reports over this interface with this command. +@end deffn + +@deffn {PIM Interface Command} {ip igmp} {} +Tell pim to receive IGMP reports and Query on this +interface. The default version is v3. This command +is useful on the LHR. +@end deffn + +@deffn {PIM Interface Command} {ip igmp query-interval (1-1800)} {} +Set the IGMP query interval that PIM will use. +@end deffn + +@deffn {PIM Interface Command} {ip igmp query-max-response-time (10-250)} {} +Set the IGMP query response timeout value. If an report is not returned +in the specified time we will assume the S,G or *,G has timed out. +@end deffn + +@deffn {PIM Interface Command} {ip igmp version (2-3)} {} +Set the IGMP version used on this interface. The default value +is 3. +@end deffn + +@deffn {PIM Interface Command} {ip multicat boundary oil WORD} {} +Set a pim multicast boundary, based upon the WORD prefix-list. If +a pim join or IGMP report is received on this interface and the Group +is denyed by the prefix-list, PIM will ignore the join or report. +@end deffn + +@node PIM Multicast RIB insertion:: +@section PIM Multicast RIB insertion:: + +In order to influence Multicast RPF lookup, it is possible to insert +into zebra routes for the Multicast RIB. These routes are only +used for RPF lookup and will not be used by zebra for insertion +into the kernel *or* for normal rib processing. As such it is +possible to create weird states with these commands. Use with +caution. Most of the time this will not be necessary. + +@deffn {PIM Multicast RIB insertion} {ip mroute A.B.C.D/M A.B.C.D (1-255)} {} +Insert into the Multicast Rib Route A.B.C.D/M with specified nexthop. The distance can be specified as well if desired. +@end deffn + +@deffn {PIM Multicast RIB insertion} {ip mroute A.B.C.D/M INTERFACE (1-255)} {} +Insert into the Multicast Rib Route A.B.C.D/M using the specified INTERFACE. +The distance can be specified as well if desired. +@end deffn + +@node Show PIM Information:: +@section Show PIM Information + +All PIM show commands are vrf aware and typically allow you to insert +a specified vrf command if information is desired about a specific vrf. +If no vrf is specified then the default vrf is assumed. Finally +the special keyword 'all' allows you to look at all vrfs for the command. +Naming a vrf 'all' will cause great confusion. + +@deffn {Show PIM Information} {show ip multicast} +Display various information about the interfaces used in this pim +instance. +@end deffn + +@deffn {Show PIM Information} {show ip mroute} +Display information about installed into the kernel S,G mroutes. +@end deffn + +@deffn {Show PIM Information} {show ip mroute count} +Display information about installed into the kernel S,G mroutes +and in addition display data about packet flow for the mroutes. +@end deffn + +@deffn {Show PIM Information} {show ip pim assert} +Display information about asserts in the PIM system for S,G mroutes. +@end deffn + +@deffn {Show PIM Information} {show ip pim assert-internal} +Display internal assert state for S,G mroutes +@end deffn + +@deffn {Show PIM Information} {show ip pim assert-metric} +Display metric information about assert state for S,G mroutes +@end deffn + +@deffn {Show PIM Information} {show ip pim assert-winner-metric} +Display winner metric for assert state for S,G mroutes +@end deffn + +@deffn {Show PIM Information} {show ip pim group-type} +Display SSM group ranges +@end deffn + +@deffn {Show PIM Information} {show ip pim interface} +Display information about interfaces PIM is using. +@end deffn + +@deffn {Show PIM Information} {show ip pim join} +Display information about PIM joins received. +@end deffn + +@deffn {Show PIM Information} {show ip pim local-membership} {} +Display information about PIM interface local-membership +@end deffn + +@deffn {Show PIM Information} {show ip pim neighbor} {} +Display information about PIM neighbors +@end deffn + +@deffn {Show PIM Information} {show ip pim nexthop} {} +Display information about pim nexthops that are being +used +@end deffn + +@deffn {Show PIM Information} {show ip pim nexthop-lookup} {} +Display information about a S,G pair and how the RPF would +be choosen. This is especially useful if there are ECMP's +available from the RPF lookup. +@end deffn + +@deffn {Show PIM Information} {show ip pim rp-info} {} +Display information about RP's that are configured on +this router +@end deffn + +@deffn {Show PIM Information} {show ip pim rpf} {} +Display information about currently being used S,G's +and their RPF lookup information. Additionally display +some statistics about what has been happening on the +router +@end deffn + +@deffn {show PIM Information} {show ip pim secondary} {} +Display information about an interface and all the +secondary addresses associated with it +@end deffn + +@deffn {show PIM Information} {show ip pim state} {} +Display information about known S,G's and incoming +interface as well as the OIL and how they were choosen +@end deffn + +@deffn {show PIM Information} {show ip pim upstream} {} +Display upstream information about a S,G mroute +@end deffn + +@deffn {show PIM Information} {show ip pim upstream-join-desired} {} +Display upstream information for S,G's and if we desire to +join the mcast tree +@end deffn + +@deffn {show PIM Information} {show ip pim upstream-rpf} {} +Display upstream information for S,G's and the RPF data +associated with them +@end deffn + +@deffn {show PIM Information} {show ip rpf} {} +Display the multicast RIB created in zebra +@end deffn + +@node PIM Debug Commands +@section PIM Debug Commands + +The debugging subsystem for PIM behaves in accordance with how FRR handles debugging. You can specify debugging at the enable cli mode as well as the configure cli mode. If you specify debug commands in the configuration cli mode, the debug commands can be persistent across restarts of the FRR pimd if the config was written out. + +@deffn {PIM Debug Commands} {debug pim events} +This turns on debugging for PIM system events. Especially timers. +@end deffn + +@deffn {PIM Debug Commands} {debug pim nht} +This turns on debugging for PIM nexthop tracking. It will display information about RPF lookups and information about when a nexthop changes. +@end deffn + +@deffn {PIM Debug Commands} {debug pim packet-dump} +This turns on an extraordinary amount of data. Each pim packet sent and received is dumped for debugging purposes. This should be considered a developer only command +@end deffn + +@deffn {PIM Debug Commands} {debug pim packets} +This turns on information about packet generation for sending and about packet handling from a received packet +@end deffn + +@deffn {PIM Debug Commands} {debug pim trace} +This traces pim code and how it is running. +@end deffn + +@deffn {PIM Debug Commands} {debug pim zebra} +This gathers data about events from zebra that come up through the zapi +@end deffn From 2ce92994937427d799d87f79ed894b6b49683225 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 8 Dec 2017 19:40:30 -0500 Subject: [PATCH 13/48] doc: Cleanup the doc Makefile some Signed-off-by: Donald Sharp --- doc/Makefile.am | 33 ++++++++++++++++++++++++++------- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/doc/Makefile.am b/doc/Makefile.am index bb5fa32d59..7aaa36556f 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -59,18 +59,37 @@ $(srcdir)/frr.info: $(frr_TEXINFOS) defines.texi frr.dvi: $(frr_TEXINFOS) defines.texi frr.html: $(frr_TEXINFOS) defines.texi -frr_TEXINFOS = appendix.texi basic.texi bgpd.texi isisd.texi filter.texi \ +frr_TEXINFOS = \ + appendix.texi \ + basic.texi \ + bgpd.texi \ + isisd.texi \ + filter.texi \ vnc.texi \ babeld.texi \ - install.texi ipv6.texi kernel.texi main.texi \ + install.texi \ + ipv6.texi \ + kernel.texi \ + main.texi \ nhrpd.texi \ eigrpd.texi \ - ospf6d.texi ospfd.texi \ - overview.texi protocol.texi ripd.texi ripngd.texi routemap.texi \ - snmp.texi vtysh.texi routeserver.texi $(figures_png) \ - snmptrap.texi ospf_fundamentals.texi isisd.texi $(figures_txt) \ + ospf6d.texi \ + ospfd.texi \ + overview.texi \ + protocol.texi \ + ripd.texi \ + ripngd.texi \ + routemap.texi \ + snmp.texi \ + vtysh.texi \ + routeserver.texi \ + $(figures_png) \ + snmptrap.texi \ + ospf_fundamentals.texi \ + isisd.texi $(figures_txt) \ rpki.texi \ - pimd.texi + pimd.texi \ + #END .png.eps: $(PNGTOEPS) $< "$@" From 070b4959fa6dcc6eb963f902a859f59ca9b55b83 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 13 Dec 2017 10:32:54 -0500 Subject: [PATCH 14/48] zebra: Remove possible NULL dereference in if_delete_connected It is technically possible to attempt to use a NULL pointer. Remove this from happening. Additionally cleanup code indentation a small bit. Signed-off-by: Donald Sharp --- zebra/interface.c | 71 ++++++++++++++++++++++++----------------------- 1 file changed, 36 insertions(+), 35 deletions(-) diff --git a/zebra/interface.c b/zebra/interface.c index dd1050ee7f..18588ee52c 100644 --- a/zebra/interface.c +++ b/zebra/interface.c @@ -561,33 +561,35 @@ static void if_delete_connected(struct interface *ifp) struct prefix cp; struct route_node *rn; struct zebra_if *zebra_if; + struct listnode *node; + struct listnode *last = NULL; zebra_if = ifp->info; - if (ifp->connected) { - struct listnode *node; - struct listnode *last = NULL; + if (!ifp->connected) + return; - while ((node = (last ? last->next - : listhead(ifp->connected)))) { - ifc = listgetdata(node); + while ((node = (last ? last->next + : listhead(ifp->connected)))) { + ifc = listgetdata(node); - cp = *CONNECTED_PREFIX(ifc); - apply_mask(&cp); + cp = *CONNECTED_PREFIX(ifc); + apply_mask(&cp); - if (cp.family == AF_INET - && (rn = route_node_lookup(zebra_if->ipv4_subnets, - &cp))) { - struct listnode *anode; - struct listnode *next; - struct listnode *first; - struct list *addr_list; + if (cp.family == AF_INET + && (rn = route_node_lookup(zebra_if->ipv4_subnets, + &cp))) { + struct listnode *anode; + struct listnode *next; + struct listnode *first; + struct list *addr_list; - route_unlock_node(rn); - addr_list = (struct list *)rn->info; + route_unlock_node(rn); + addr_list = (struct list *)rn->info; - /* Remove addresses, secondaries first. */ - first = listhead(addr_list); + /* Remove addresses, secondaries first. */ + first = listhead(addr_list); + if (first) for (anode = first->next; anode || first; anode = next) { if (!anode) { @@ -626,27 +628,26 @@ static void if_delete_connected(struct interface *ifp) last = node; } - /* Free chain list and respective route node. */ - list_delete_and_null(&addr_list); - rn->info = NULL; - route_unlock_node(rn); - } else if (cp.family == AF_INET6) { - connected_down(ifp, ifc); + /* Free chain list and respective route node. */ + list_delete_and_null(&addr_list); + rn->info = NULL; + route_unlock_node(rn); + } else if (cp.family == AF_INET6) { + connected_down(ifp, ifc); - zebra_interface_address_delete_update(ifp, ifc); + zebra_interface_address_delete_update(ifp, ifc); - UNSET_FLAG(ifc->conf, ZEBRA_IFC_REAL); - UNSET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED); + UNSET_FLAG(ifc->conf, ZEBRA_IFC_REAL); + UNSET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED); - if (CHECK_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED)) - last = node; - else { - listnode_delete(ifp->connected, ifc); - connected_free(ifc); - } - } else { + if (CHECK_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED)) last = node; + else { + listnode_delete(ifp->connected, ifc); + connected_free(ifc); } + } else { + last = node; } } } From b8ca17c230a1c324e34f96c61ccac3ef7357be8e Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 13 Dec 2017 10:36:53 -0500 Subject: [PATCH 15/48] pimd: Fix memory allocation error When creating the pim_ifp, and we run out of memory there existed a chance that we would dereference the failed memory pointer. Signed-off-by: Donald Sharp --- pimd/pim_iface.c | 1 + 1 file changed, 1 insertion(+) diff --git a/pimd/pim_iface.c b/pimd/pim_iface.c index b2a8a6ff8f..f02cf7ed31 100644 --- a/pimd/pim_iface.c +++ b/pimd/pim_iface.c @@ -205,6 +205,7 @@ struct pim_interface *pim_if_new(struct interface *ifp, int igmp, int pim) if (!pim_ifp->sec_addr_list) { zlog_err("%s: failure: secondary addresslist", __PRETTY_FUNCTION__); + return if_list_clean(pim_ifp); } pim_ifp->sec_addr_list->del = (void (*)(void *))pim_sec_addr_free; pim_ifp->sec_addr_list->cmp = From a35bb96dee99fbadb4f03395ad34d657b3d5e110 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 13 Dec 2017 10:58:55 -0500 Subject: [PATCH 16/48] ospf6d: Don't assign to values that are never read offset and offsetlen are never used without reassigning in the code. So comment out the assignments and in case we want to start using the code for snmp changes in the future. Signed-off-by: Donald Sharp --- ospf6d/ospf6_snmp.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/ospf6d/ospf6_snmp.c b/ospf6d/ospf6_snmp.c index c148107449..a448645960 100644 --- a/ospf6d/ospf6_snmp.c +++ b/ospf6d/ospf6_snmp.c @@ -914,7 +914,7 @@ static u_char *ospfv3WwLsdbEntry(struct variable *v, oid *name, size_t *length, if (len) id = htonl(*offset); offset += len; - offsetlen -= len; + //offsetlen -= len; // Add back in if we need it again if (exact) { if (v->magic & OSPFv3WWASTABLE) { @@ -1080,8 +1080,8 @@ static u_char *ospfv3IfEntry(struct variable *v, oid *name, size_t *length, len = (offsetlen < 1 ? 0 : 1); if (len) instid = *offset; - offset += len; - offsetlen -= len; + //offset += len; // Add back in if we ever start using again + //offsetlen -= len; if (exact) { oi = ospf6_interface_lookup_by_ifindex(ifindex); @@ -1241,8 +1241,8 @@ static u_char *ospfv3NbrEntry(struct variable *v, oid *name, size_t *length, len = (offsetlen < 1 ? 0 : 1); if (len) rtrid = htonl(*offset); - offset += len; - offsetlen -= len; + //offset += len; // Add back in if we ever start looking at data + //offsetlen -= len; if (exact) { oi = ospf6_interface_lookup_by_ifindex(ifindex); From 37a333fef1cc398849691ae31996407e00767a43 Mon Sep 17 00:00:00 2001 From: Quentin Young Date: Thu, 14 Dec 2017 16:43:31 -0500 Subject: [PATCH 17/48] bgpd: fix configuration of 0 for coalesce-time Was using 0 as a sentinel value, so user couldn't configure 0 as the value of the coalesce timer. Signed-off-by: Quentin Young --- bgpd/bgp_vty.c | 10 +++++----- bgpd/bgpd.c | 2 +- bgpd/bgpd.h | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index 1c6d38dccf..d1d684ccb3 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -1423,8 +1423,8 @@ DEFUN (no_bgp_rpkt_quanta, void bgp_config_write_coalesce_time(struct vty *vty, struct bgp *bgp) { - if (bgp->v_coalesce_time) - vty_out(vty, " coalesce-time %u\n", bgp->v_coalesce_time); + if (!bgp->heuristic_coalesce) + vty_out(vty, " coalesce-time %u\n", bgp->coalesce_time); } @@ -1438,8 +1438,8 @@ DEFUN (bgp_coalesce_time, int idx = 0; argv_find(argv, argc, "(0-4294967295)", &idx); - bgp->coalesce_time = bgp->v_coalesce_time = - strtoul(argv[idx]->arg, NULL, 10); + bgp->heuristic_coalesce = false; + bgp->coalesce_time = strtoul(argv[idx]->arg, NULL, 10); return CMD_SUCCESS; } @@ -1452,7 +1452,7 @@ DEFUN (no_bgp_coalesce_time, { VTY_DECLVAR_CONTEXT(bgp, bgp); - bgp->v_coalesce_time = 0; + bgp->heuristic_coalesce = true; bgp->coalesce_time = BGP_DEFAULT_SUBGROUP_COALESCE_TIME; return CMD_SUCCESS; } diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index ed92246dbc..5963f822f3 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -1475,7 +1475,7 @@ struct peer *peer_create(union sockunion *su, const char *conf_if, hash_get(bgp->peerhash, peer, hash_alloc_intern); /* Adjust update-group coalesce timer heuristics for # peers. */ - if (!bgp->v_coalesce_time) { + if (bgp->heuristic_coalesce) { long ct = BGP_DEFAULT_SUBGROUP_COALESCE_TIME + (bgp->peer->count * BGP_PEER_ADJUST_SUBGROUP_COALESCE_TIME); diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h index e8189dbf8c..6bb49e0c53 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h @@ -381,8 +381,8 @@ struct bgp { _Atomic uint32_t wpkt_quanta; // max # packets to write per i/o cycle _Atomic uint32_t rpkt_quanta; // max # packets to read per i/o cycle - /* Configured coalesce time */ - uint32_t v_coalesce_time; + /* Automatic coalesce adjust on/off */ + bool heuristic_coalesce; /* Actual coalesce time */ uint32_t coalesce_time; From 12386e86db93502bdcd3ec6c2ae24bcef0ba8ca3 Mon Sep 17 00:00:00 2001 From: Rafael Zalamena Date: Mon, 18 Dec 2017 13:19:08 -0200 Subject: [PATCH 18/48] Revert "isisd: bpf: ETHER_HDR_LEN -> ETH_ALEN" This reverts commit d9e5b009554f99230be1eee62daf098403c3cadf. ETH_ALEN is not equivalent to ETHER_HDR_LEN. ETHER_HDR_LEN is the definition for the length of the full ethernet header, meanwhile ETH_ALEN is just the length of the ethernet address. Here is the OpenBSD/FreeBSD definition for ETHER_HDR_LEN: #define ETHER_ADDR_LEN 6 /* Ethernet address length */ #define ETHER_TYPE_LEN 2 /* Ethernet type field length */ #define ETHER_HDR_LEN ((ETHER_ADDR_LEN * 2) + ETHER_TYPE_LEN) (OpenBSD's definition is at net/if_ether.h, FreeBSD's is at net/ethernet.h) Linux definitions can be found at: net/ethernet.h #define ETHER_ADDR_LEN ETH_ALEN /* size of ethernet addr */ #define ETHER_TYPE_LEN 2 /* bytes in type field */ #define ETHER_HDR_LEN ETH_HLEN /* total octets in header */ net/if_ether.h: #define ETH_HLEN 14 /* Total octets in header. */ #define ETH_ALEN 6 /* Octets in one ethernet addr */ Signed-off-by: Rafael Zalamena --- isisd/isis_bpf.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/isisd/isis_bpf.c b/isisd/isis_bpf.c index 591af3b8ed..a4c6b4c75d 100644 --- a/isisd/isis_bpf.c +++ b/isisd/isis_bpf.c @@ -46,15 +46,14 @@ #include "privs.h" struct bpf_insn llcfilter[] = { - /* check first byte */ - BPF_STMT(BPF_LD + BPF_B + BPF_ABS, ETH_ALEN), + BPF_STMT(BPF_LD + BPF_B + BPF_ABS, + ETHER_HDR_LEN), /* check first byte */ BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ISO_SAP, 0, 5), - /* check second byte */ - BPF_STMT(BPF_LD + BPF_B + BPF_ABS, ETH_ALEN + 1), - BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ISO_SAP, 0, 3), - /* check third byte */ - BPF_STMT(BPF_LD + BPF_B + BPF_ABS, ETH_ALEN + 2), - BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0x03, 0, 1), + BPF_STMT(BPF_LD + BPF_B + BPF_ABS, ETHER_HDR_LEN + 1), + BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ISO_SAP, 0, + 3), /* check second byte */ + BPF_STMT(BPF_LD + BPF_B + BPF_ABS, ETHER_HDR_LEN + 2), + BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0x03, 0, 1), /* check third byte */ BPF_STMT(BPF_RET + BPF_K, (u_int)-1), BPF_STMT(BPF_RET + BPF_K, 0)}; u_int readblen = 0; @@ -242,14 +241,15 @@ int isis_recv_pdu_bcast(struct isis_circuit *circuit, u_char *ssnpa) assert(bpf_hdr->bh_caplen == bpf_hdr->bh_datalen); - offset = bpf_hdr->bh_hdrlen + LLC_LEN + ETH_ALEN; + offset = bpf_hdr->bh_hdrlen + LLC_LEN + ETHER_HDR_LEN; /* then we lose the BPF, LLC and ethernet headers */ stream_write(circuit->rcv_stream, readbuff + offset, - bpf_hdr->bh_caplen - LLC_LEN - ETH_ALEN); + bpf_hdr->bh_caplen - LLC_LEN - ETHER_HDR_LEN); stream_set_getp(circuit->rcv_stream, 0); - memcpy(ssnpa, readbuff + bpf_hdr->bh_hdrlen + ETH_ALEN, ETH_ALEN); + memcpy(ssnpa, readbuff + bpf_hdr->bh_hdrlen + ETH_ALEN, + ETH_ALEN); if (ioctl(circuit->fd, BIOCFLUSH, &one) < 0) zlog_warn("Flushing failed: %s", safe_strerror(errno)); @@ -263,7 +263,7 @@ int isis_send_pdu_bcast(struct isis_circuit *circuit, int level) ssize_t written; size_t buflen; - buflen = stream_get_endp(circuit->snd_stream) + LLC_LEN + ETH_ALEN; + buflen = stream_get_endp(circuit->snd_stream) + LLC_LEN + ETHER_HDR_LEN; if (buflen > sizeof(sock_buff)) { zlog_warn( "isis_send_pdu_bcast: sock_buff size %zu is less than " @@ -289,12 +289,12 @@ int isis_send_pdu_bcast(struct isis_circuit *circuit, int level) /* * Then the LLC */ - sock_buff[ETH_ALEN] = ISO_SAP; - sock_buff[ETH_ALEN + 1] = ISO_SAP; - sock_buff[ETH_ALEN + 2] = 0x03; + sock_buff[ETHER_HDR_LEN] = ISO_SAP; + sock_buff[ETHER_HDR_LEN + 1] = ISO_SAP; + sock_buff[ETHER_HDR_LEN + 2] = 0x03; /* then we copy the data */ - memcpy(sock_buff + (LLC_LEN + ETH_ALEN), circuit->snd_stream->data, + memcpy(sock_buff + (LLC_LEN + ETHER_HDR_LEN), circuit->snd_stream->data, stream_get_endp(circuit->snd_stream)); /* now we can send this */ From fb8f41e455aec592eebcc4ccf4716e0c853133a6 Mon Sep 17 00:00:00 2001 From: "Raymond P. Burkholder" Date: Sun, 17 Dec 2017 11:53:34 -0400 Subject: [PATCH 19/48] bgpd: fixed '-Werror=maybe-uninitialized' warnings - used @sharpd's slack patch as a starting point - fixes compile time issue, but code path not tested Signed-off-by: Raymond P. Burkholder --- bgpd/bgp_evpn_vty.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bgpd/bgp_evpn_vty.c b/bgpd/bgp_evpn_vty.c index f473b4604a..4114c45221 100644 --- a/bgpd/bgp_evpn_vty.c +++ b/bgpd/bgp_evpn_vty.c @@ -414,9 +414,9 @@ static void show_vni_entry(struct hash_backet *backet, void *args[]) { struct vty *vty; json_object *json; - json_object *json_vni; - json_object *json_import_rtl; - json_object *json_export_rtl; + json_object *json_vni = NULL; + json_object *json_import_rtl = NULL; + json_object *json_export_rtl = NULL; struct bgpevpn *vpn = (struct bgpevpn *)backet->data; char buf1[10]; char buf2[RD_ADDRSTRLEN]; From 449feb8ef98347c28148af86dbcbaad35070a8ad Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 19 Dec 2017 08:20:30 -0500 Subject: [PATCH 20/48] bgpd: Fix double free The json code was freeing json_paths and then turning around and free'ing it again. Newer versions of json-c have started to assert this bad behavior. Signed-off-by: Donald Sharp --- bgpd/bgp_route.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 2323572488..09759628cb 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -8396,6 +8396,7 @@ static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi, vty_out(vty, "%s", json_object_to_json_string_ext(json_paths, JSON_C_TO_STRING_PRETTY)); json_object_free(json_paths); + json_paths = NULL; first = 0; } } @@ -8409,7 +8410,8 @@ static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi, *total_cum = total_count; } if (use_json) { - json_object_free(json_paths); + if (json_paths) + json_object_free(json_paths); if (is_last) vty_out(vty, " } }\n"); else From 5318d8963816f607e8ab648eb17c784617b90270 Mon Sep 17 00:00:00 2001 From: Quentin Young Date: Tue, 19 Dec 2017 16:28:45 -0500 Subject: [PATCH 21/48] lib: add ring buffer Simple ring buffer implementation useful for fixed size FIFO queues. Signed-off-by: Quentin Young --- lib/ringbuf.c | 104 ++++++++++++++++++++++ lib/ringbuf.h | 100 ++++++++++++++++++++++ lib/subdir.am | 2 + tests/Makefile.am | 4 + tests/lib/test_ringbuf.c | 175 ++++++++++++++++++++++++++++++++++++++ tests/lib/test_ringbuf.py | 4 + 6 files changed, 389 insertions(+) create mode 100644 lib/ringbuf.c create mode 100644 lib/ringbuf.h create mode 100644 tests/lib/test_ringbuf.c create mode 100644 tests/lib/test_ringbuf.py diff --git a/lib/ringbuf.c b/lib/ringbuf.c new file mode 100644 index 0000000000..fee5b5d691 --- /dev/null +++ b/lib/ringbuf.c @@ -0,0 +1,104 @@ +/* + * Circular buffer implementation. + * Copyright (C) 2017 Cumulus Networks + * Quentin Young + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include + +#include "ringbuf.h" +#include "memory.h" + +DEFINE_MTYPE_STATIC(LIB, RINGBUFFER, "Ring buffer") + +struct ringbuf *ringbuf_new(size_t size) +{ + struct ringbuf *buf = XCALLOC(MTYPE_RINGBUFFER, sizeof(struct ringbuf)); + buf->data = XCALLOC(MTYPE_RINGBUFFER, size); + buf->size = size; + buf->empty = true; + return buf; +} + +void ringbuf_del(struct ringbuf *buf) +{ + XFREE(MTYPE_RINGBUFFER, buf->data); + XFREE(MTYPE_RINGBUFFER, buf); +} + +size_t ringbuf_remain(struct ringbuf *buf) +{ + ssize_t diff = buf->end - buf->start; + diff += ((diff == 0) && !buf->empty) ? buf->size : 0; + diff += (diff < 0) ? buf->size : 0; + return (size_t)diff; +} + +size_t ringbuf_space(struct ringbuf *buf) +{ + return buf->size - ringbuf_remain(buf); +} + +size_t ringbuf_put(struct ringbuf *buf, const void *data, size_t size) +{ + const uint8_t *dp = data; + size_t space = ringbuf_space(buf); + size_t copysize = MIN(size, space); + size_t tocopy = copysize; + if (tocopy > buf->size - buf->end) { + size_t ts = buf->size - buf->end; + memcpy(buf->data + buf->end, dp, ts); + buf->end = 0; + tocopy -= ts; + dp += ts; + } + memcpy(buf->data + buf->end, dp, tocopy); + buf->end += tocopy; + buf->empty = (buf->start == buf->end) && (buf->empty && !copysize); + return copysize; +} + +size_t ringbuf_get(struct ringbuf *buf, void *data, size_t size) +{ + uint8_t *dp = data; + size_t remain = ringbuf_remain(buf); + size_t copysize = MIN(remain, size); + size_t tocopy = copysize; + if (tocopy > buf->size - buf->start) { + size_t ts = buf->size - buf->start; + memcpy(dp, buf->data + buf->start, ts); + buf->start = 0; + tocopy -= ts; + dp += ts; + } + memcpy(dp, buf->data + buf->start, tocopy); + buf->start = buf->start + tocopy; + buf->empty = (buf->start == buf->end) && (buf->empty || copysize); + return copysize; +} + +void ringbuf_reset(struct ringbuf *buf) +{ + buf->start = buf->end = 0; + buf->empty = true; +} + +void ringbuf_wipe(struct ringbuf *buf) +{ + memset(buf->data, 0x00, buf->size); + ringbuf_reset(buf); + buf->empty = true; +} diff --git a/lib/ringbuf.h b/lib/ringbuf.h new file mode 100644 index 0000000000..af07c93a66 --- /dev/null +++ b/lib/ringbuf.h @@ -0,0 +1,100 @@ +/* + * Circular buffer implementation. + * Copyright (C) 2017 Cumulus Networks + * Quentin Young + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#ifndef _FRR_RINGBUF_H_ +#define _FRR_RINGBUF_H_ + +#include +#include + +#include "memory.h" + +struct ringbuf { + size_t size; + ssize_t start; + ssize_t end; + bool empty; + uint8_t *data; +}; + +/* + * Creates a new ring buffer. + * + * @param size buffer size, in bytes + * @return the newly created buffer + */ +struct ringbuf *ringbuf_new(size_t size); + +/* + * Deletes a ring buffer and frees all associated resources. + * + * @param buf the ring buffer to destroy + */ +void ringbuf_del(struct ringbuf *buf); + +/* + * Get amount of data left to read from the buffer. + * + * @return number of readable bytes + */ +size_t ringbuf_remain(struct ringbuf *buf); + +/* + * Get amount of space left to write to the buffer + * + * @return number of writeable bytes + */ +size_t ringbuf_space(struct ringbuf *buf); + + +/* + * Put data into the ring buffer. + * + * @param data the data to put in the buffer + * @param size how much of data to put in + * @return number of bytes written; will be less than size if there was not + * enough space + */ +size_t ringbuf_put(struct ringbuf *buf, const void *data, size_t size); + +/* + * Get data from the ring buffer. + * + * @param data where to put the data + * @param size how much of data to get + * @return number of bytes read into data; will be less than size if there was + * not enough data to read + */ +size_t ringbuf_get(struct ringbuf *buf, void *data, size_t size); + +/* + * Reset buffer. Does not wipe. + * + * @param buf + */ +void ringbuf_reset(struct ringbuf *buf); + +/* + * Reset buffer. Wipes. + * + * @param buf + */ +void ringbuf_wipe(struct ringbuf *buf); + +#endif /* _FRR_RINGBUF_H_ */ diff --git a/lib/subdir.am b/lib/subdir.am index c8eddc8e25..44870917bd 100644 --- a/lib/subdir.am +++ b/lib/subdir.am @@ -51,6 +51,7 @@ lib_libfrr_la_SOURCES = \ lib/privs.c \ lib/ptm_lib.c \ lib/qobj.c \ + lib/ringbuf.c \ lib/routemap.c \ lib/sbuf.c \ lib/sha256.c \ @@ -130,6 +131,7 @@ pkginclude_HEADERS += \ lib/pw.h \ lib/qobj.h \ lib/queue.h \ + lib/ringbuf.h \ lib/routemap.h \ lib/sbuf.h \ lib/sha256.h \ diff --git a/tests/Makefile.am b/tests/Makefile.am index 2ee05fa935..f4ab2a126a 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -64,6 +64,7 @@ check_PROGRAMS = \ lib/test_memory \ lib/test_nexthop_iter \ lib/test_privs \ + lib/test_ringbuf \ lib/test_srcdest_table \ lib/test_segv \ lib/test_sig \ @@ -116,6 +117,7 @@ lib_test_nexthop_iter_SOURCES = lib/test_nexthop_iter.c helpers/c/prng.c lib_test_privs_SOURCES = lib/test_privs.c lib_test_srcdest_table_SOURCES = lib/test_srcdest_table.c \ helpers/c/prng.c +lib_test_ringbuf_SOURCES = lib/test_ringbuf.c lib_test_segv_SOURCES = lib/test_segv.c lib_test_sig_SOURCES = lib/test_sig.c lib_test_stream_SOURCES = lib/test_stream.c @@ -156,6 +158,7 @@ lib_test_heavy_LDADD = $(ALL_TESTS_LDADD) -lm lib_test_memory_LDADD = $(ALL_TESTS_LDADD) lib_test_nexthop_iter_LDADD = $(ALL_TESTS_LDADD) lib_test_privs_LDADD = $(ALL_TESTS_LDADD) +lib_test_ringbuf_LDADD = $(ALL_TESTS_LDADD) lib_test_srcdest_table_LDADD = $(ALL_TESTS_LDADD) lib_test_segv_LDADD = $(ALL_TESTS_LDADD) lib_test_sig_LDADD = $(ALL_TESTS_LDADD) @@ -196,6 +199,7 @@ EXTRA_DIST = \ lib/cli/test_cli.py \ lib/cli/test_cli.refout \ lib/test_nexthop_iter.py \ + lib/test_ringbuf.py \ lib/test_srcdest_table.py \ lib/test_stream.py \ lib/test_stream.refout \ diff --git a/tests/lib/test_ringbuf.c b/tests/lib/test_ringbuf.c new file mode 100644 index 0000000000..c689563dd6 --- /dev/null +++ b/tests/lib/test_ringbuf.c @@ -0,0 +1,175 @@ +/* + * Circular buffer tests. + * Copyright (C) 2017 Cumulus Networks + * Quentin Young + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include +#include +#include "ringbuf.h" + +static void validate_state(struct ringbuf *buf, size_t size, size_t contains) +{ + assert(buf->size == size); + assert(ringbuf_remain(buf) == contains); + assert(ringbuf_space(buf) == buf->size - contains); + assert(buf->empty != (bool)contains); +} + +int main(int argc, char **argv) +{ + struct ringbuf *soil = ringbuf_new(BUFSIZ); + + validate_state(soil, BUFSIZ, 0); + + /* verify reset functionality on clean buffer */ + printf("Validating reset on empty buffer...\n"); + ringbuf_reset(soil); + + validate_state(soil, BUFSIZ, 0); + + /* put one byte */ + printf("Validating write...\n"); + uint8_t walnut = 47; + assert(ringbuf_put(soil, &walnut, sizeof(walnut)) == 1); + + validate_state(soil, BUFSIZ, 1); + + /* validate read limitations */ + printf("Validating read limits...\n"); + uint8_t nuts[2]; + assert(ringbuf_get(soil, &nuts, sizeof(nuts)) == 1); + + /* reset */ + printf("Validating reset on full buffer...\n"); + ringbuf_reset(soil); + validate_state(soil, BUFSIZ, 0); + + /* copy stack garbage to buffer */ + printf("Validating big write...\n"); + uint8_t compost[BUFSIZ]; + assert(ringbuf_put(soil, &compost, sizeof(compost)) == BUFSIZ); + + validate_state(soil, BUFSIZ, BUFSIZ); + assert(soil->start == 0); + assert(soil->end == BUFSIZ); + + /* read 15 bytes of garbage */ + printf("Validating read...\n"); + assert(ringbuf_get(soil, &compost, 15) == 15); + + validate_state(soil, BUFSIZ, BUFSIZ - 15); + assert(soil->start == 15); + assert(soil->end == BUFSIZ); + + /* put another 10 bytes and validate wraparound */ + printf("Validating wraparound...\n"); + assert(ringbuf_put(soil, &compost[BUFSIZ / 2], 10) == 10); + + validate_state(soil, BUFSIZ, BUFSIZ - 15 + 10); + assert(soil->start == 15); + assert(soil->end == 10); + + /* put another 15 bytes and validate state */ + printf("Validating size limits...\n"); + assert(ringbuf_put(soil, &compost, 15) == 5); + validate_state(soil, BUFSIZ, BUFSIZ); + + /* read entire buffer */ + printf("Validating big read...\n"); + assert(ringbuf_get(soil, &compost, BUFSIZ) == BUFSIZ); + + validate_state(soil, BUFSIZ, 0); + assert(soil->empty = true); + assert(soil->start == soil->end); + assert(soil->start == 15); + + /* read empty buffer */ + printf("Validating empty read...\n"); + assert(ringbuf_get(soil, &compost, 1) == 0); + validate_state(soil, BUFSIZ, 0); + + /* reset, validate state */ + printf("Validating reset...\n"); + ringbuf_reset(soil); + validate_state(soil, BUFSIZ, 0); + assert(soil->start == 0); + assert(soil->end == 0); + + /* wipe, validate state */ + printf("Validating wipe...\n"); + memset(&compost, 0x00, sizeof(compost)); + ringbuf_wipe(soil); + assert(memcmp(&compost, soil->data, sizeof(compost)) == 0); + + /* validate maximum write */ + printf("Validating very big write...\n"); + const char flower[BUFSIZ * 2]; + assert(ringbuf_put(soil, &flower, sizeof(flower)) == BUFSIZ); + + validate_state(soil, BUFSIZ, BUFSIZ); + + /* wipe, validate state */ + printf("Validating wipe...\n"); + memset(&compost, 0x00, sizeof(compost)); + ringbuf_wipe(soil); + assert(memcmp(&compost, soil->data, sizeof(compost)) == 0); + + /* validate simple data encode / decode */ + const char *organ = "seed"; + printf("Encoding: '%s'\n", organ); + ringbuf_put(soil, organ, strlen(organ)); + char water[strlen(organ) + 1]; + ringbuf_get(soil, &water, strlen(organ)); + water[strlen(organ)] = '\0'; + printf("Retrieved: '%s'\n", water); + + validate_state(soil, BUFSIZ, 0); + + /* validate simple data encode / decode across ring boundary */ + soil->start = soil->size - 2; + soil->end = soil->start; + const char *phloem = "root"; + printf("Encoding: '%s'\n", phloem); + ringbuf_put(soil, phloem, strlen(phloem)); + char xylem[strlen(phloem) + 1]; + ringbuf_get(soil, &xylem, 100); + xylem[strlen(phloem)] = '\0'; + printf("Retrieved: '%s'\n", xylem); + + printf("Deleting...\n"); + ringbuf_del(soil); + + printf("Creating new buffer...\n"); + soil = ringbuf_new(15); + soil->start = soil->end = 7; + + /* validate data encode of excessive data */ + const char *twenty = "vascular plants----"; + char sixteen[16]; + printf("Encoding: %s\n", twenty); + assert(ringbuf_put(soil, twenty, strlen(twenty)) == 15); + assert(ringbuf_get(soil, sixteen, 20)); + sixteen[15] = '\0'; + printf("Retrieved: %s\n", sixteen); + assert(!strcmp(sixteen, "vascular plants")); + + printf("Deleting...\n"); + ringbuf_del(soil); + + printf("Done.\n"); + return 0; +} diff --git a/tests/lib/test_ringbuf.py b/tests/lib/test_ringbuf.py new file mode 100644 index 0000000000..860d872f86 --- /dev/null +++ b/tests/lib/test_ringbuf.py @@ -0,0 +1,4 @@ +import frrtest + +class TestRingbuf(frrtest.TestExitNonzero): + program = './test_ringbuf' From e2a86ad9b44b2b7f1f9f754324086e460d971542 Mon Sep 17 00:00:00 2001 From: Don Slice Date: Mon, 18 Dec 2017 10:40:56 -0500 Subject: [PATCH 22/48] bgpd: convert network statements from DEFUN to DEFPY Problems reported with inconsistent use of parameters for bgp network statements. Converted 12 DEFUNs to 2 DEFPY statements, making the parameter use consistent with the exception of keeping the "backdoor" keywork ipv4 only. Also verified that if a route-map or label-index is specified in the "no" case it matches what had been previously defined. Manual testing looks good and bgp-smoke will be performed before pushing. Ticket: CM-16860 Signed-off-by: Don Slice Reviewed-by: CCR-7056 --- bgpd/Makefile.am | 1 + bgpd/bgp_route.c | 666 +++++++++++------------------------------------ 2 files changed, 149 insertions(+), 518 deletions(-) diff --git a/bgpd/Makefile.am b/bgpd/Makefile.am index b0d34dc43b..5e08f82774 100644 --- a/bgpd/Makefile.am +++ b/bgpd/Makefile.am @@ -133,6 +133,7 @@ dist_examples_DATA = bgpd.conf.sample bgpd.conf.sample2 \ bgpd.conf.vnc.sample bgp_vty.o: bgp_vty_clippy.c +bgp_route.o: bgp_route_clippy.c EXTRA_DIST = BGP4-MIB.txt diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 88d2044f45..64391e9d45 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -74,6 +74,9 @@ #include "bgpd/bgp_evpn.h" #include "bgpd/bgp_evpn_vty.h" +#ifndef VTYSH_EXTRACT_PL +#include "bgpd/bgp_route_clippy.c" +#endif /* Extern from bgp_dump.c */ extern const char *bgp_origin_str[]; @@ -4480,9 +4483,9 @@ static void bgp_static_update_safi(struct bgp *bgp, struct prefix *p, /* Configure static BGP network. When user don't run zebra, static route should be installed as valid. */ -static int bgp_static_set(struct vty *vty, const char *ip_str, afi_t afi, - safi_t safi, const char *rmap, int backdoor, - u_int32_t label_index) +static int bgp_static_set(struct vty *vty, const char *negate, + const char *ip_str, afi_t afi, safi_t safi, + const char *rmap, int backdoor, u_int32_t label_index) { VTY_DECLVAR_CONTEXT(bgp, bgp); int ret; @@ -4504,113 +4507,110 @@ static int bgp_static_set(struct vty *vty, const char *ip_str, afi_t afi, apply_mask(&p); - /* Set BGP static route configuration. */ - rn = bgp_node_get(bgp->route[afi][safi], &p); + if (negate) { - if (rn->info) { - /* Configuration change. */ - bgp_static = rn->info; + /* Set BGP static route configuration. */ + rn = bgp_node_lookup(bgp->route[afi][safi], &p); - /* Label index cannot be changed. */ - if (bgp_static->label_index != label_index) { - vty_out(vty, "%% Label index cannot be changed\n"); + if (!rn) { + vty_out(vty, + "%% Can't find static route specified\n"); return CMD_WARNING_CONFIG_FAILED; } - /* Check previous routes are installed into BGP. */ - if (bgp_static->valid && bgp_static->backdoor != backdoor) - need_update = 1; + bgp_static = rn->info; - bgp_static->backdoor = backdoor; - - if (rmap) { - if (bgp_static->rmap.name) - XFREE(MTYPE_ROUTE_MAP_NAME, - bgp_static->rmap.name); - bgp_static->rmap.name = - XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap); - bgp_static->rmap.map = route_map_lookup_by_name(rmap); - } else { - if (bgp_static->rmap.name) - XFREE(MTYPE_ROUTE_MAP_NAME, - bgp_static->rmap.name); - bgp_static->rmap.name = NULL; - bgp_static->rmap.map = NULL; - bgp_static->valid = 0; + if ((label_index != BGP_INVALID_LABEL_INDEX) + && (label_index != bgp_static->label_index)) { + vty_out(vty, + "%% label-index doesn't match static route\n"); + return CMD_WARNING_CONFIG_FAILED; } + + if ((rmap && bgp_static->rmap.name) + && strcmp(rmap, bgp_static->rmap.name)) { + vty_out(vty, + "%% route-map name doesn't match static route\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + /* Update BGP RIB. */ + if (!bgp_static->backdoor) + bgp_static_withdraw(bgp, &p, afi, safi); + + /* Clear configuration. */ + bgp_static_free(bgp_static); + rn->info = NULL; + bgp_unlock_node(rn); bgp_unlock_node(rn); } else { - /* New configuration. */ - bgp_static = bgp_static_new(); - bgp_static->backdoor = backdoor; - bgp_static->valid = 0; - bgp_static->igpmetric = 0; - bgp_static->igpnexthop.s_addr = 0; - bgp_static->label_index = label_index; - if (rmap) { - if (bgp_static->rmap.name) - XFREE(MTYPE_ROUTE_MAP_NAME, - bgp_static->rmap.name); - bgp_static->rmap.name = - XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap); - bgp_static->rmap.map = route_map_lookup_by_name(rmap); + /* Set BGP static route configuration. */ + rn = bgp_node_get(bgp->route[afi][safi], &p); + + if (rn->info) { + /* Configuration change. */ + bgp_static = rn->info; + + /* Label index cannot be changed. */ + if (bgp_static->label_index != label_index) { + vty_out(vty, "%% cannot change label-index\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + /* Check previous routes are installed into BGP. */ + if (bgp_static->valid && + bgp_static->backdoor != backdoor) + need_update = 1; + + bgp_static->backdoor = backdoor; + + if (rmap) { + if (bgp_static->rmap.name) + XFREE(MTYPE_ROUTE_MAP_NAME, + bgp_static->rmap.name); + bgp_static->rmap.name = + XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap); + bgp_static->rmap.map = + route_map_lookup_by_name(rmap); + } else { + if (bgp_static->rmap.name) + XFREE(MTYPE_ROUTE_MAP_NAME, + bgp_static->rmap.name); + bgp_static->rmap.name = NULL; + bgp_static->rmap.map = NULL; + bgp_static->valid = 0; + } + bgp_unlock_node(rn); + } else { + /* New configuration. */ + bgp_static = bgp_static_new(); + bgp_static->backdoor = backdoor; + bgp_static->valid = 0; + bgp_static->igpmetric = 0; + bgp_static->igpnexthop.s_addr = 0; + bgp_static->label_index = label_index; + + if (rmap) { + if (bgp_static->rmap.name) + XFREE(MTYPE_ROUTE_MAP_NAME, + bgp_static->rmap.name); + bgp_static->rmap.name = + XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap); + bgp_static->rmap.map = + route_map_lookup_by_name(rmap); + } + rn->info = bgp_static; } - rn->info = bgp_static; + + bgp_static->valid = 1; + if (need_update) + bgp_static_withdraw(bgp, &p, afi, safi); + + if (!bgp_static->backdoor) + bgp_static_update(bgp, &p, bgp_static, afi, safi); } - bgp_static->valid = 1; - if (need_update) - bgp_static_withdraw(bgp, &p, afi, safi); - - if (!bgp_static->backdoor) - bgp_static_update(bgp, &p, bgp_static, afi, safi); - - return CMD_SUCCESS; -} - -/* Configure static BGP network. */ -static int bgp_static_unset(struct vty *vty, const char *ip_str, afi_t afi, - safi_t safi) -{ - VTY_DECLVAR_CONTEXT(bgp, bgp); - int ret; - struct prefix p; - struct bgp_static *bgp_static; - struct bgp_node *rn; - - /* Convert IP prefix string to struct prefix. */ - ret = str2prefix(ip_str, &p); - if (!ret) { - vty_out(vty, "%% Malformed prefix\n"); - return CMD_WARNING_CONFIG_FAILED; - } - if (afi == AFI_IP6 && IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) { - vty_out(vty, "%% Malformed prefix (link-local address)\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - apply_mask(&p); - - rn = bgp_node_lookup(bgp->route[afi][safi], &p); - if (!rn) { - vty_out(vty, - "%% Can't find specified static route configuration.\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - bgp_static = rn->info; - - /* Update BGP RIB. */ - if (!bgp_static->backdoor) - bgp_static_withdraw(bgp, &p, afi, safi); - - /* Clear configuration. */ - bgp_static_free(bgp_static); - rn->info = NULL; - bgp_unlock_node(rn); - bgp_unlock_node(rn); - return CMD_SUCCESS; } @@ -5036,387 +5036,60 @@ DEFUN (no_bgp_table_map, argv[idx_word]->arg); } -DEFUN (bgp_network, - bgp_network_cmd, - "network A.B.C.D/M", - "Specify a network to announce via BGP\n" - "IPv4 prefix\n") +DEFPY(bgp_network, + bgp_network_cmd, + "[no] network \ + \ + [{route-map WORD$map_name|label-index (0-1048560)$label_index| \ + backdoor$backdoor}]", + NO_STR + "Specify a network to announce via BGP\n" + "IPv4 prefix\n" + "Network number\n" + "Network mask\n" + "Network mask\n" + "Route-map to modify the attributes\n" + "Name of the route map\n" + "Label index to associate with the prefix\n" + "Label index value\n" + "Specify a BGP backdoor route\n") { - int idx_ipv4_prefixlen = 1; - return bgp_static_set(vty, argv[idx_ipv4_prefixlen]->arg, AFI_IP, - bgp_node_safi(vty), NULL, 0, - BGP_INVALID_LABEL_INDEX); -} + char addr_prefix_str[BUFSIZ]; -DEFUN (bgp_network_route_map, - bgp_network_route_map_cmd, - "network A.B.C.D/M route-map WORD", - "Specify a network to announce via BGP\n" - "IPv4 prefix\n" - "Route-map to modify the attributes\n" - "Name of the route map\n") -{ - int idx_ipv4_prefixlen = 1; - int idx_word = 3; - return bgp_static_set(vty, argv[idx_ipv4_prefixlen]->arg, AFI_IP, - bgp_node_safi(vty), argv[idx_word]->arg, 0, - BGP_INVALID_LABEL_INDEX); -} + if (address_str) { + int ret; -DEFUN (bgp_network_backdoor, - bgp_network_backdoor_cmd, - "network A.B.C.D/M backdoor", - "Specify a network to announce via BGP\n" - "IPv4 prefix\n" - "Specify a BGP backdoor route\n") -{ - int idx_ipv4_prefixlen = 1; - return bgp_static_set(vty, argv[idx_ipv4_prefixlen]->arg, AFI_IP, - SAFI_UNICAST, NULL, 1, BGP_INVALID_LABEL_INDEX); -} - -DEFUN (bgp_network_mask, - bgp_network_mask_cmd, - "network A.B.C.D mask A.B.C.D", - "Specify a network to announce via BGP\n" - "Network number\n" - "Network mask\n" - "Network mask\n") -{ - int idx_ipv4 = 1; - int idx_ipv4_2 = 3; - int ret; - char prefix_str[BUFSIZ]; - - ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg, - prefix_str); - if (!ret) { - vty_out(vty, "%% Inconsistent address and mask\n"); - return CMD_WARNING_CONFIG_FAILED; + ret = netmask_str2prefix_str(address_str, netmask_str, + addr_prefix_str); + if (!ret) { + vty_out(vty, "%% Inconsistent address and mask\n"); + return CMD_WARNING_CONFIG_FAILED; + } } - return bgp_static_set(vty, prefix_str, AFI_IP, bgp_node_safi(vty), NULL, - 0, BGP_INVALID_LABEL_INDEX); + return bgp_static_set(vty, no, address_str ? addr_prefix_str:prefix_str, + AFI_IP, bgp_node_safi(vty), + map_name, backdoor?1:0, + label_index ? label_index:BGP_INVALID_LABEL_INDEX); } -DEFUN (bgp_network_mask_route_map, - bgp_network_mask_route_map_cmd, - "network A.B.C.D mask A.B.C.D route-map WORD", - "Specify a network to announce via BGP\n" - "Network number\n" - "Network mask\n" - "Network mask\n" - "Route-map to modify the attributes\n" - "Name of the route map\n") +DEFPY(ipv6_bgp_network, + ipv6_bgp_network_cmd, + "[no] network X:X::X:X/M$prefix \ + [{route-map WORD$map_name|label-index (0-1048560)$label_index}]", + NO_STR + "Specify a network to announce via BGP\n" + "IPv6 prefix\n" + "Route-map to modify the attributes\n" + "Name of the route map\n" + "Label index to associate with the prefix\n" + "Label index value\n") { - int idx_ipv4 = 1; - int idx_ipv4_2 = 3; - int idx_word = 5; - int ret; - char prefix_str[BUFSIZ]; - - ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg, - prefix_str); - if (!ret) { - vty_out(vty, "%% Inconsistent address and mask\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - return bgp_static_set(vty, prefix_str, AFI_IP, bgp_node_safi(vty), - argv[idx_word]->arg, 0, BGP_INVALID_LABEL_INDEX); + return bgp_static_set(vty, no, prefix_str, AFI_IP6, + bgp_node_safi(vty), map_name, 0, + label_index ? label_index:BGP_INVALID_LABEL_INDEX); } -DEFUN (bgp_network_mask_backdoor, - bgp_network_mask_backdoor_cmd, - "network A.B.C.D mask A.B.C.D backdoor", - "Specify a network to announce via BGP\n" - "Network number\n" - "Network mask\n" - "Network mask\n" - "Specify a BGP backdoor route\n") -{ - int idx_ipv4 = 1; - int idx_ipv4_2 = 3; - int ret; - char prefix_str[BUFSIZ]; - - ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg, - prefix_str); - if (!ret) { - vty_out(vty, "%% Inconsistent address and mask\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - return bgp_static_set(vty, prefix_str, AFI_IP, SAFI_UNICAST, NULL, 1, - BGP_INVALID_LABEL_INDEX); -} - -DEFUN (bgp_network_mask_natural, - bgp_network_mask_natural_cmd, - "network A.B.C.D", - "Specify a network to announce via BGP\n" - "Network number\n") -{ - int idx_ipv4 = 1; - int ret; - char prefix_str[BUFSIZ]; - - ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, NULL, prefix_str); - if (!ret) { - vty_out(vty, "%% Inconsistent address and mask\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - return bgp_static_set(vty, prefix_str, AFI_IP, bgp_node_safi(vty), NULL, - 0, BGP_INVALID_LABEL_INDEX); -} - -DEFUN (bgp_network_mask_natural_route_map, - bgp_network_mask_natural_route_map_cmd, - "network A.B.C.D route-map WORD", - "Specify a network to announce via BGP\n" - "Network number\n" - "Route-map to modify the attributes\n" - "Name of the route map\n") -{ - int idx_ipv4 = 1; - int idx_word = 3; - int ret; - char prefix_str[BUFSIZ]; - - ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, NULL, prefix_str); - if (!ret) { - vty_out(vty, "%% Inconsistent address and mask\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - return bgp_static_set(vty, prefix_str, AFI_IP, bgp_node_safi(vty), - argv[idx_word]->arg, 0, BGP_INVALID_LABEL_INDEX); -} - -DEFUN (bgp_network_mask_natural_backdoor, - bgp_network_mask_natural_backdoor_cmd, - "network A.B.C.D backdoor", - "Specify a network to announce via BGP\n" - "Network number\n" - "Specify a BGP backdoor route\n") -{ - int idx_ipv4 = 1; - int ret; - char prefix_str[BUFSIZ]; - - ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, NULL, prefix_str); - if (!ret) { - vty_out(vty, "%% Inconsistent address and mask\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - return bgp_static_set(vty, prefix_str, AFI_IP, SAFI_UNICAST, NULL, 1, - BGP_INVALID_LABEL_INDEX); -} - -DEFUN (bgp_network_label_index, - bgp_network_label_index_cmd, - "network A.B.C.D/M label-index (0-1048560)", - "Specify a network to announce via BGP\n" - "IP prefix /, e.g., 35.0.0.0/8\n" - "Label index to associate with the prefix\n" - "Label index value\n") -{ - u_int32_t label_index; - - label_index = strtoul(argv[3]->arg, NULL, 10); - return bgp_static_set(vty, argv[1]->arg, AFI_IP, bgp_node_safi(vty), - NULL, 0, label_index); -} - -DEFUN (bgp_network_label_index_route_map, - bgp_network_label_index_route_map_cmd, - "network A.B.C.D/M label-index (0-1048560) route-map WORD", - "Specify a network to announce via BGP\n" - "IP prefix\n" - "Label index to associate with the prefix\n" - "Label index value\n" - "Route-map to modify the attributes\n" - "Name of the route map\n") -{ - u_int32_t label_index; - - label_index = strtoul(argv[3]->arg, NULL, 10); - return bgp_static_set(vty, argv[1]->arg, AFI_IP, bgp_node_safi(vty), - argv[5]->arg, 0, label_index); -} - -DEFUN (no_bgp_network, - no_bgp_network_cmd, - "no network A.B.C.D/M []", - NO_STR - "Specify a network to announce via BGP\n" - "IPv4 prefix\n" - "Specify a BGP backdoor route\n" - "Route-map to modify the attributes\n" - "Name of the route map\n") -{ - int idx_ipv4_prefixlen = 2; - return bgp_static_unset(vty, argv[idx_ipv4_prefixlen]->arg, AFI_IP, - bgp_node_safi(vty)); -} - -DEFUN (no_bgp_network_mask, - no_bgp_network_mask_cmd, - "no network A.B.C.D mask A.B.C.D []", - NO_STR - "Specify a network to announce via BGP\n" - "Network number\n" - "Network mask\n" - "Network mask\n" - "Specify a BGP backdoor route\n" - "Route-map to modify the attributes\n" - "Name of the route map\n") -{ - int idx_ipv4 = 2; - int idx_ipv4_2 = 4; - int ret; - char prefix_str[BUFSIZ]; - - ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg, - prefix_str); - if (!ret) { - vty_out(vty, "%% Inconsistent address and mask\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - return bgp_static_unset(vty, prefix_str, AFI_IP, bgp_node_safi(vty)); -} - -DEFUN (no_bgp_network_mask_natural, - no_bgp_network_mask_natural_cmd, - "no network A.B.C.D []", - NO_STR - "Specify a network to announce via BGP\n" - "Network number\n" - "Specify a BGP backdoor route\n" - "Route-map to modify the attributes\n" - "Name of the route map\n") -{ - int idx_ipv4 = 2; - int ret; - char prefix_str[BUFSIZ]; - - ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, NULL, prefix_str); - if (!ret) { - vty_out(vty, "%% Inconsistent address and mask\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - return bgp_static_unset(vty, prefix_str, AFI_IP, bgp_node_safi(vty)); -} - -ALIAS(no_bgp_network, no_bgp_network_label_index_cmd, - "no network A.B.C.D/M label-index (0-1048560)", NO_STR - "Specify a network to announce via BGP\n" - "IP prefix /, e.g., 35.0.0.0/8\n" - "Label index to associate with the prefix\n" - "Label index value\n") - -ALIAS(no_bgp_network, no_bgp_network_label_index_route_map_cmd, - "no network A.B.C.D/M label-index (0-1048560) route-map WORD", NO_STR - "Specify a network to announce via BGP\n" - "IP prefix\n" - "Label index to associate with the prefix\n" - "Label index value\n" - "Route-map to modify the attributes\n" - "Name of the route map\n") - -DEFUN (ipv6_bgp_network, - ipv6_bgp_network_cmd, - "network X:X::X:X/M", - "Specify a network to announce via BGP\n" - "IPv6 prefix\n") -{ - int idx_ipv6_prefixlen = 1; - return bgp_static_set(vty, argv[idx_ipv6_prefixlen]->arg, AFI_IP6, - bgp_node_safi(vty), NULL, 0, - BGP_INVALID_LABEL_INDEX); -} - -DEFUN (ipv6_bgp_network_route_map, - ipv6_bgp_network_route_map_cmd, - "network X:X::X:X/M route-map WORD", - "Specify a network to announce via BGP\n" - "IPv6 prefix\n" - "Route-map to modify the attributes\n" - "Name of the route map\n") -{ - int idx_ipv6_prefixlen = 1; - int idx_word = 3; - return bgp_static_set(vty, argv[idx_ipv6_prefixlen]->arg, AFI_IP6, - bgp_node_safi(vty), argv[idx_word]->arg, 0, - BGP_INVALID_LABEL_INDEX); -} - -DEFUN (ipv6_bgp_network_label_index, - ipv6_bgp_network_label_index_cmd, - "network X:X::X:X/M label-index (0-1048560)", - "Specify a network to announce via BGP\n" - "IPv6 prefix /\n" - "Label index to associate with the prefix\n" - "Label index value\n") -{ - u_int32_t label_index; - - label_index = strtoul(argv[3]->arg, NULL, 10); - return bgp_static_set(vty, argv[1]->arg, AFI_IP6, bgp_node_safi(vty), - NULL, 0, label_index); -} - -DEFUN (ipv6_bgp_network_label_index_route_map, - ipv6_bgp_network_label_index_route_map_cmd, - "network X:X::X:X/M label-index (0-1048560) route-map WORD", - "Specify a network to announce via BGP\n" - "IPv6 prefix\n" - "Label index to associate with the prefix\n" - "Label index value\n" - "Route-map to modify the attributes\n" - "Name of the route map\n") -{ - u_int32_t label_index; - - label_index = strtoul(argv[3]->arg, NULL, 10); - return bgp_static_set(vty, argv[1]->arg, AFI_IP6, bgp_node_safi(vty), - argv[5]->arg, 0, label_index); -} - -DEFUN (no_ipv6_bgp_network, - no_ipv6_bgp_network_cmd, - "no network X:X::X:X/M [route-map WORD]", - NO_STR - "Specify a network to announce via BGP\n" - "IPv6 prefix\n" - "Route-map to modify the attributes\n" - "Name of the route map\n") -{ - int idx_ipv6_prefixlen = 2; - return bgp_static_unset(vty, argv[idx_ipv6_prefixlen]->arg, AFI_IP6, - bgp_node_safi(vty)); -} - -ALIAS(no_ipv6_bgp_network, no_ipv6_bgp_network_label_index_cmd, - "no network X:X::X:X/M label-index (0-1048560)", NO_STR - "Specify a network to announce via BGP\n" - "IPv6 prefix /\n" - "Label index to associate with the prefix\n" - "Label index value\n") - -ALIAS(no_ipv6_bgp_network, no_ipv6_bgp_network_label_index_route_map_cmd, - "no network X:X::X:X/M label-index (0-1048560) route-map WORD", NO_STR - "Specify a network to announce via BGP\n" - "IPv6 prefix\n" - "Label index to associate with the prefix\n" - "Label index value\n" - "Route-map to modify the attributes\n" - "Name of the route map\n") - /* Aggreagete address: advertise-map Set condition to advertise attribute @@ -11156,10 +10829,10 @@ static void bgp_config_write_network_vpn(struct vty *vty, struct bgp *bgp, if (bgp_static->rmap.name) vty_out(vty, " route-map %s", bgp_static->rmap.name); - else { - if (bgp_static->backdoor) - vty_out(vty, " backdoor"); - } + + if (bgp_static->backdoor) + vty_out(vty, " backdoor"); + vty_out(vty, "\n"); } } @@ -11292,10 +10965,9 @@ void bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi, if (bgp_static->rmap.name) vty_out(vty, " route-map %s", bgp_static->rmap.name); - else { - if (bgp_static->backdoor) - vty_out(vty, " backdoor"); - } + + if (bgp_static->backdoor) + vty_out(vty, " backdoor"); vty_out(vty, "\n"); } @@ -11378,18 +11050,7 @@ void bgp_route_init(void) /* IPv4 BGP commands. */ install_element(BGP_NODE, &bgp_table_map_cmd); install_element(BGP_NODE, &bgp_network_cmd); - install_element(BGP_NODE, &bgp_network_mask_cmd); - install_element(BGP_NODE, &bgp_network_mask_natural_cmd); - install_element(BGP_NODE, &bgp_network_route_map_cmd); - install_element(BGP_NODE, &bgp_network_mask_route_map_cmd); - install_element(BGP_NODE, &bgp_network_mask_natural_route_map_cmd); - install_element(BGP_NODE, &bgp_network_backdoor_cmd); - install_element(BGP_NODE, &bgp_network_mask_backdoor_cmd); - install_element(BGP_NODE, &bgp_network_mask_natural_backdoor_cmd); install_element(BGP_NODE, &no_bgp_table_map_cmd); - install_element(BGP_NODE, &no_bgp_network_cmd); - install_element(BGP_NODE, &no_bgp_network_mask_cmd); - install_element(BGP_NODE, &no_bgp_network_mask_natural_cmd); install_element(BGP_NODE, &aggregate_address_cmd); install_element(BGP_NODE, &aggregate_address_mask_cmd); @@ -11399,20 +11060,7 @@ void bgp_route_init(void) /* IPv4 unicast configuration. */ install_element(BGP_IPV4_NODE, &bgp_table_map_cmd); install_element(BGP_IPV4_NODE, &bgp_network_cmd); - install_element(BGP_IPV4_NODE, &bgp_network_mask_cmd); - install_element(BGP_IPV4_NODE, &bgp_network_mask_natural_cmd); - install_element(BGP_IPV4_NODE, &bgp_network_route_map_cmd); - install_element(BGP_IPV4_NODE, &bgp_network_mask_route_map_cmd); - install_element(BGP_IPV4_NODE, &bgp_network_mask_natural_route_map_cmd); - install_element(BGP_IPV4_NODE, &bgp_network_label_index_cmd); - install_element(BGP_IPV4_NODE, &bgp_network_label_index_route_map_cmd); - install_element(BGP_IPV4_NODE, &no_bgp_network_label_index_cmd); - install_element(BGP_IPV4_NODE, - &no_bgp_network_label_index_route_map_cmd); install_element(BGP_IPV4_NODE, &no_bgp_table_map_cmd); - install_element(BGP_IPV4_NODE, &no_bgp_network_cmd); - install_element(BGP_IPV4_NODE, &no_bgp_network_mask_cmd); - install_element(BGP_IPV4_NODE, &no_bgp_network_mask_natural_cmd); install_element(BGP_IPV4_NODE, &aggregate_address_cmd); install_element(BGP_IPV4_NODE, &aggregate_address_mask_cmd); @@ -11422,16 +11070,7 @@ void bgp_route_init(void) /* IPv4 multicast configuration. */ install_element(BGP_IPV4M_NODE, &bgp_table_map_cmd); install_element(BGP_IPV4M_NODE, &bgp_network_cmd); - install_element(BGP_IPV4M_NODE, &bgp_network_mask_cmd); - install_element(BGP_IPV4M_NODE, &bgp_network_mask_natural_cmd); - install_element(BGP_IPV4M_NODE, &bgp_network_route_map_cmd); - install_element(BGP_IPV4M_NODE, &bgp_network_mask_route_map_cmd); - install_element(BGP_IPV4M_NODE, - &bgp_network_mask_natural_route_map_cmd); install_element(BGP_IPV4M_NODE, &no_bgp_table_map_cmd); - install_element(BGP_IPV4M_NODE, &no_bgp_network_cmd); - install_element(BGP_IPV4M_NODE, &no_bgp_network_mask_cmd); - install_element(BGP_IPV4M_NODE, &no_bgp_network_mask_natural_cmd); install_element(BGP_IPV4M_NODE, &aggregate_address_cmd); install_element(BGP_IPV4M_NODE, &aggregate_address_mask_cmd); install_element(BGP_IPV4M_NODE, &no_aggregate_address_cmd); @@ -11474,21 +11113,12 @@ void bgp_route_init(void) /* New config IPv6 BGP commands. */ install_element(BGP_IPV6_NODE, &bgp_table_map_cmd); install_element(BGP_IPV6_NODE, &ipv6_bgp_network_cmd); - install_element(BGP_IPV6_NODE, &ipv6_bgp_network_route_map_cmd); install_element(BGP_IPV6_NODE, &no_bgp_table_map_cmd); - install_element(BGP_IPV6_NODE, &no_ipv6_bgp_network_cmd); - install_element(BGP_IPV6_NODE, &ipv6_bgp_network_label_index_cmd); - install_element(BGP_IPV6_NODE, &no_ipv6_bgp_network_label_index_cmd); - install_element(BGP_IPV6_NODE, - &ipv6_bgp_network_label_index_route_map_cmd); - install_element(BGP_IPV6_NODE, - &no_ipv6_bgp_network_label_index_route_map_cmd); install_element(BGP_IPV6_NODE, &ipv6_aggregate_address_cmd); install_element(BGP_IPV6_NODE, &no_ipv6_aggregate_address_cmd); install_element(BGP_IPV6M_NODE, &ipv6_bgp_network_cmd); - install_element(BGP_IPV6M_NODE, &no_ipv6_bgp_network_cmd); install_element(BGP_NODE, &bgp_distance_cmd); install_element(BGP_NODE, &no_bgp_distance_cmd); From a5080622b2de7c09393daa208a56606c068db1f3 Mon Sep 17 00:00:00 2001 From: Quentin Young Date: Tue, 26 Dec 2017 18:47:19 -0500 Subject: [PATCH 23/48] lib: add ringbuf_peek() Peek functionality for ring buffers and associated tests. Also: * Slight optimization to avoid 0-byte memcpy() by changing > to >= * Add rv checks for some ringbuf_[put|get] calls that were missing them in the test Signed-off-by: Quentin Young --- lib/ringbuf.c | 22 +++++++++++++++++++++- lib/ringbuf.h | 15 +++++++++++++++ tests/lib/test_ringbuf.c | 25 ++++++++++++++++++++----- 3 files changed, 56 insertions(+), 6 deletions(-) diff --git a/lib/ringbuf.c b/lib/ringbuf.c index fee5b5d691..f8e9a9bd8a 100644 --- a/lib/ringbuf.c +++ b/lib/ringbuf.c @@ -77,7 +77,7 @@ size_t ringbuf_get(struct ringbuf *buf, void *data, size_t size) size_t remain = ringbuf_remain(buf); size_t copysize = MIN(remain, size); size_t tocopy = copysize; - if (tocopy > buf->size - buf->start) { + if (tocopy >= buf->size - buf->start) { size_t ts = buf->size - buf->start; memcpy(dp, buf->data + buf->start, ts); buf->start = 0; @@ -90,6 +90,26 @@ size_t ringbuf_get(struct ringbuf *buf, void *data, size_t size) return copysize; } +size_t ringbuf_peek(struct ringbuf *buf, size_t offset, void *data, size_t size) +{ + uint8_t *dp = data; + size_t remain = ringbuf_remain(buf); + if (offset >= remain) + return 0; + size_t copysize = MAX(MIN(remain - offset, size), (size_t) 0); + size_t tocopy = copysize; + size_t cstart = (buf->start + offset) % buf->size; + if (tocopy >= buf->size - cstart) { + size_t ts = buf->size - cstart; + memcpy(dp, buf->data + cstart, ts); + buf->start = cstart = 0; + tocopy -= ts; + dp += ts; + } + memcpy(dp, buf->data + cstart, tocopy); + return copysize; +} + void ringbuf_reset(struct ringbuf *buf) { buf->start = buf->end = 0; diff --git a/lib/ringbuf.h b/lib/ringbuf.h index af07c93a66..2288a2716f 100644 --- a/lib/ringbuf.h +++ b/lib/ringbuf.h @@ -83,6 +83,21 @@ size_t ringbuf_put(struct ringbuf *buf, const void *data, size_t size); */ size_t ringbuf_get(struct ringbuf *buf, void *data, size_t size); +/* + * Peek data from the ring buffer. + * + * @param offset where to get the data from, in bytes offset from the + * start of the data + * @param data where to put the data + * @param size how much data to get + * @return number of bytes read into data; will be less than size + * if there was not enough data to read; will be -1 if the + * offset exceeds the amount of data left in the ring + * buffer + */ +size_t ringbuf_peek(struct ringbuf *buf, size_t offset, void *data, + size_t size); + /* * Reset buffer. Does not wipe. * diff --git a/tests/lib/test_ringbuf.c b/tests/lib/test_ringbuf.c index c689563dd6..c2f4f76a6f 100644 --- a/tests/lib/test_ringbuf.c +++ b/tests/lib/test_ringbuf.c @@ -77,7 +77,7 @@ int main(int argc, char **argv) /* put another 10 bytes and validate wraparound */ printf("Validating wraparound...\n"); - assert(ringbuf_put(soil, &compost[BUFSIZ / 2], 10) == 10); + assert(ringbuf_put(soil, &compost[BUFSIZ/2], 10) == 10); validate_state(soil, BUFSIZ, BUFSIZ - 15 + 10); assert(soil->start == 15); @@ -131,9 +131,9 @@ int main(int argc, char **argv) /* validate simple data encode / decode */ const char *organ = "seed"; printf("Encoding: '%s'\n", organ); - ringbuf_put(soil, organ, strlen(organ)); + assert(ringbuf_put(soil, organ, strlen(organ)) == 4); char water[strlen(organ) + 1]; - ringbuf_get(soil, &water, strlen(organ)); + assert(ringbuf_get(soil, &water, strlen(organ)) == 4); water[strlen(organ)] = '\0'; printf("Retrieved: '%s'\n", water); @@ -144,12 +144,27 @@ int main(int argc, char **argv) soil->end = soil->start; const char *phloem = "root"; printf("Encoding: '%s'\n", phloem); - ringbuf_put(soil, phloem, strlen(phloem)); + assert(ringbuf_put(soil, phloem, strlen(phloem)) == 4); char xylem[strlen(phloem) + 1]; - ringbuf_get(soil, &xylem, 100); + assert(ringbuf_get(soil, &xylem, 100) == 4); xylem[strlen(phloem)] = '\0'; printf("Retrieved: '%s'\n", xylem); + ringbuf_wipe(soil); + + /* validate simple data peek across ring boundary */ + soil->start = soil->size - 2; + soil->end = soil->start; + const char *cytoplasm = "tree"; + printf("Encoding: '%s'\n", cytoplasm); + assert(ringbuf_put(soil, cytoplasm, strlen(cytoplasm)) == 4); + char chloroplast[strlen(cytoplasm) + 1]; + assert(ringbuf_peek(soil, 2, &chloroplast[0], 100) == 2); + assert(ringbuf_peek(soil, 0, &chloroplast[2], 2) == 2); + chloroplast[strlen(cytoplasm)] = '\0'; + assert(!strcmp(chloroplast, "eetr")); + printf("Retrieved: '%s'\n", chloroplast); + printf("Deleting...\n"); ringbuf_del(soil); From 05ba78e4d9522ebc10bdd9312fb8c004feb3ea24 Mon Sep 17 00:00:00 2001 From: Chirag Shah Date: Tue, 26 Dec 2017 09:45:25 -0800 Subject: [PATCH 24/48] ospfd: Set filter to unbound debug logs Ticket:CM-19213 Signed-off-by: Chirag Shah --- ospfd/ospf_ase.c | 5 +++-- ospfd/ospf_network.c | 20 +++++++++++--------- ospfd/ospf_nsm.c | 12 ++++++------ ospfd/ospf_packet.c | 18 +++++++++++------- ospfd/ospf_snmp.c | 12 +++++++----- ospfd/ospf_spf.c | 4 +--- 6 files changed, 39 insertions(+), 32 deletions(-) diff --git a/ospfd/ospf_ase.c b/ospfd/ospf_ase.c index 2f1b27f0f1..368987a2ba 100644 --- a/ospfd/ospf_ase.c +++ b/ospfd/ospf_ase.c @@ -679,8 +679,9 @@ static int ospf_ase_calculate_timer(struct thread *t) monotime(&stop_time); - zlog_info("SPF Processing Time(usecs): External Routes: %lld\n", - (stop_time.tv_sec - start_time.tv_sec) * 1000000LL + if (IS_DEBUG_OSPF_EVENT) + zlog_info("SPF Processing Time(usecs): External Routes: %lld\n", + (stop_time.tv_sec - start_time.tv_sec) * 1000000LL + (stop_time.tv_usec - start_time.tv_usec)); } return 0; diff --git a/ospfd/ospf_network.c b/ospfd/ospf_network.c index ed5e8e027d..022a5a138a 100644 --- a/ospfd/ospf_network.c +++ b/ospfd/ospf_network.c @@ -38,7 +38,7 @@ #include "ospfd/ospf_lsdb.h" #include "ospfd/ospf_neighbor.h" #include "ospfd/ospf_packet.h" - +#include "ospfd/ospf_dump.h" /* Join to the OSPF ALL SPF ROUTERS multicast group. */ int ospf_if_add_allspfrouters(struct ospf *top, struct prefix *p, @@ -56,10 +56,11 @@ int ospf_if_add_allspfrouters(struct ospf *top, struct prefix *p, "on # of multicast group memberships has been exceeded?", top->fd, inet_ntoa(p->u.prefix4), ifindex, safe_strerror(errno)); - else - zlog_debug( - "interface %s [%u] join AllSPFRouters Multicast group.", - inet_ntoa(p->u.prefix4), ifindex); + else { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("interface %s [%u] join AllSPFRouters Multicast group.", + inet_ntoa(p->u.prefix4), ifindex); + } return ret; } @@ -78,10 +79,11 @@ int ospf_if_drop_allspfrouters(struct ospf *top, struct prefix *p, "ifindex %u, AllSPFRouters): %s", top->fd, inet_ntoa(p->u.prefix4), ifindex, safe_strerror(errno)); - else - zlog_debug( - "interface %s [%u] leave AllSPFRouters Multicast group.", - inet_ntoa(p->u.prefix4), ifindex); + else { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("interface %s [%u] leave AllSPFRouters Multicast group.", + inet_ntoa(p->u.prefix4), ifindex); + } return ret; } diff --git a/ospfd/ospf_nsm.c b/ospfd/ospf_nsm.c index a0ff2bfccf..c87001294d 100644 --- a/ospfd/ospf_nsm.c +++ b/ospfd/ospf_nsm.c @@ -702,12 +702,12 @@ static void nsm_change_state(struct ospf_neighbor *nbr, int state) oi->ospf); } - zlog_info( - "nsm_change_state(%s, %s -> %s): " - "scheduling new router-LSA origination", - inet_ntoa(nbr->router_id), - lookup_msg(ospf_nsm_state_msg, old_state, NULL), - lookup_msg(ospf_nsm_state_msg, state, NULL)); + if (CHECK_FLAG(oi->ospf->config, OSPF_LOG_ADJACENCY_DETAIL)) + zlog_info("%s:(%s, %s -> %s): " + "scheduling new router-LSA origination", + __PRETTY_FUNCTION__, inet_ntoa(nbr->router_id), + lookup_msg(ospf_nsm_state_msg, old_state, NULL), + lookup_msg(ospf_nsm_state_msg, state, NULL)); ospf_router_lsa_update_area(oi->area); diff --git a/ospfd/ospf_packet.c b/ospfd/ospf_packet.c index 65e9cac837..8670359610 100644 --- a/ospfd/ospf_packet.c +++ b/ospfd/ospf_packet.c @@ -1363,9 +1363,11 @@ static void ospf_db_desc(struct ip *iph, struct ospf_header *ospfh, if (IPV4_ADDR_CMP(&nbr->router_id, &oi->ospf->router_id) > 0) { /* We're Slave---obey */ - zlog_info( - "Packet[DD]: Neighbor %s Negotiation done (Slave).", - inet_ntoa(nbr->router_id)); + if (CHECK_FLAG(oi->ospf->config, + OSPF_LOG_ADJACENCY_DETAIL)) + zlog_info("Packet[DD]: Neighbor %s Negotiation done (Slave).", + inet_ntoa(nbr->router_id)); + nbr->dd_seqnum = ntohl(dd->dd_seqnum); /* Reset I/MS */ @@ -1374,10 +1376,12 @@ static void ospf_db_desc(struct ip *iph, struct ospf_header *ospfh, } else { /* We're Master, ignore the initial DBD from * Slave */ - zlog_info( - "Packet[DD]: Neighbor %s: Initial DBD from Slave, " - "ignoring.", - inet_ntoa(nbr->router_id)); + if (CHECK_FLAG(oi->ospf->config, + OSPF_LOG_ADJACENCY_DETAIL)) + zlog_info( + "Packet[DD]: Neighbor %s: Initial DBD from Slave, " + "ignoring.", + inet_ntoa(nbr->router_id)); break; } } diff --git a/ospfd/ospf_snmp.c b/ospfd/ospf_snmp.c index 36ae091f99..b28aebb81f 100644 --- a/ospfd/ospf_snmp.c +++ b/ospfd/ospf_snmp.c @@ -2589,8 +2589,9 @@ static void ospfTrapNbrStateChange(struct ospf_neighbor *on) char msgbuf[16]; ospf_nbr_state_message(on, msgbuf, sizeof(msgbuf)); - zlog_info("ospfTrapNbrStateChange trap sent: %s now %s", - inet_ntoa(on->address.u.prefix4), msgbuf); + if (IS_DEBUG_OSPF_EVENT) + zlog_info("%s: trap sent: %s now %s", __PRETTY_FUNCTION__, + inet_ntoa(on->address.u.prefix4), msgbuf); oid_copy_addr(index, &(on->address.u.prefix4), IN_ADDR_SIZE); index[IN_ADDR_SIZE] = 0; @@ -2646,9 +2647,10 @@ static void ospfTrapIfStateChange(struct ospf_interface *oi) { oid index[sizeof(oid) * (IN_ADDR_SIZE + 1)]; - zlog_info("ospfTrapIfStateChange trap sent: %s now %s", - inet_ntoa(oi->address->u.prefix4), - lookup_msg(ospf_ism_state_msg, oi->state, NULL)); + if (IS_DEBUG_OSPF_EVENT) + zlog_info("%s: trap sent: %s now %s", __PRETTY_FUNCTION__, + inet_ntoa(oi->address->u.prefix4), + lookup_msg(ospf_ism_state_msg, oi->state, NULL)); oid_copy_addr(index, &(oi->address->u.prefix4), IN_ADDR_SIZE); index[IN_ADDR_SIZE] = 0; diff --git a/ospfd/ospf_spf.c b/ospfd/ospf_spf.c index 65437dba9e..22fff1b53d 100644 --- a/ospfd/ospf_spf.c +++ b/ospfd/ospf_spf.c @@ -1463,9 +1463,7 @@ void ospf_spf_calculate_schedule(struct ospf *ospf, ospf_spf_reason_t reason) } if (IS_DEBUG_OSPF_EVENT) - zlog_debug("SPF: calculation timer delay = %ld", delay); - - zlog_info("SPF: Scheduled in %ld msec", delay); + zlog_debug("SPF: calculation timer delay = %ld msec", delay); ospf->t_spf_calc = NULL; thread_add_timer_msec(master, ospf_spf_calculate_timer, ospf, delay, From c600ce450f3fc6938aa1381d0090a014a145da11 Mon Sep 17 00:00:00 2001 From: Chirag Shah Date: Thu, 28 Dec 2017 11:12:35 -0800 Subject: [PATCH 25/48] ospf6d: Fix ospf6 redist with route-map When ospf6 configure with redistribute connected/protocol with route-map. Upon restart of frr.service, ospf6 receives redistribute update then route-map update. During redistribute route update, since route-map info is not filled, route is suppressed from injected as external route. Fix: reset redistribute when route-map update received matches with redistribution (type) and route-map name. Ticket:CM-13800 Testing Done: Configure ospf6 redistribute with route-map to inject Type-2 external routes into database. Trigger frr restart redistribute with route-map happens. Signed-off-by: Chirag Shah --- ospf6d/ospf6_asbr.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/ospf6d/ospf6_asbr.c b/ospf6d/ospf6_asbr.c index c65578c11e..5fbf2dafa5 100644 --- a/ospf6d/ospf6_asbr.c +++ b/ospf6d/ospf6_asbr.c @@ -369,10 +369,21 @@ static void ospf6_asbr_routemap_update(const char *mapname) return; for (type = 0; type < ZEBRA_ROUTE_MAX; type++) { - if (ospf6->rmap[type].name) + if (ospf6->rmap[type].name) { ospf6->rmap[type].map = route_map_lookup_by_name( ospf6->rmap[type].name); - else + + if (mapname && ospf6->rmap[type].map && + (strcmp(ospf6->rmap[type].name, mapname) == 0)) { + if (IS_OSPF6_DEBUG_ASBR) + zlog_debug("%s: route-map %s update, reset redist %s", + __PRETTY_FUNCTION__, mapname, + ZROUTE_NAME(type)); + + ospf6_zebra_no_redistribute(type); + ospf6_zebra_redistribute(type); + } + } else ospf6->rmap[type].map = NULL; } } From 18e1d1129f265e571429fb49daf37707c28aedfb Mon Sep 17 00:00:00 2001 From: "Raymond P. Burkholder" Date: Sat, 16 Dec 2017 23:48:20 -0400 Subject: [PATCH 26/48] debianpkg: fix indentation and variable name Signed-off-by: Raymond P. Burkholder --- debianpkg/README.deb_build.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debianpkg/README.deb_build.md b/debianpkg/README.deb_build.md index 0d02bc3dc2..889e831744 100644 --- a/debianpkg/README.deb_build.md +++ b/debianpkg/README.deb_build.md @@ -72,7 +72,7 @@ adding a new backport. (see `rules` file for available options) export WANT_BGP_VNC=1 - export WANT_WANT_CUMULUS_MODE=1 + export WANT_CUMULUS_MODE=1 debuild -b -uc -us DONE. From 607425e5544a3f3afbb4d9b811e62433daf2c691 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 2 Jan 2018 09:09:09 -0500 Subject: [PATCH 27/48] zebra: Fix dest dereference The rn can not have an rn->info pointer and as such the dest may be NULL. Don't assign the old_fib pointer if so. This is ok because we know RNODE_FOREACH... will not iterate if dest is NULL. Fixes: #1575 Signed-off-by: Donald Sharp --- zebra/zebra_rib.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index 3eaf5597b2..83834899c8 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -1471,7 +1471,14 @@ static void rib_process(struct route_node *rn) if (IS_ZEBRA_DEBUG_RIB_DETAILED) zlog_debug("%u:%s: Processing rn %p", vrf_id, buf, rn); - old_fib = dest->selected_fib; + /* + * we can have rn's that have a NULL info pointer + * (dest). As such let's not let the deref happen + * additionally we know RNODE_FOREACH_RE_SAFE + * will not iterate so we are ok. + */ + if (dest) + old_fib = dest->selected_fib; RNODE_FOREACH_RE_SAFE (rn, re, next) { if (IS_ZEBRA_DEBUG_RIB_DETAILED) From 01841ed3a70c2086f74a75f114d7941e97a24493 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 3 Jan 2018 09:06:44 -0500 Subject: [PATCH 28/48] pimd: Add finer grain return codes for configuration When PIM handles some MSDP commands, a repeated command was causing a CMD_WARNING_CONFIG_FAILED. This should be a CMD_WARNING. Fix the code to allow vtysh to handle this appropriately. Ticket: CM-19053 Signed-off-by: Donald Sharp --- pimd/pim_cmd.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 10b68ab735..374e2c52a9 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -7485,6 +7485,7 @@ static int ip_msdp_peer_cmd_worker(struct pim_instance *pim, struct vty *vty, enum pim_msdp_err result; struct in_addr peer_addr; struct in_addr local_addr; + int ret = CMD_SUCCESS; result = inet_pton(AF_INET, peer, &peer_addr); if (result <= 0) { @@ -7506,19 +7507,23 @@ static int ip_msdp_peer_cmd_worker(struct pim_instance *pim, struct vty *vty, case PIM_MSDP_ERR_NONE: break; case PIM_MSDP_ERR_OOM: + ret = CMD_WARNING_CONFIG_FAILED; vty_out(vty, "%% Out of memory\n"); break; case PIM_MSDP_ERR_PEER_EXISTS: + ret = CMD_WARNING; vty_out(vty, "%% Peer exists\n"); break; case PIM_MSDP_ERR_MAX_MESH_GROUPS: + ret = CMD_WARNING_CONFIG_FAILED; vty_out(vty, "%% Only one mesh-group allowed currently\n"); break; default: + ret = CMD_WARNING_CONFIG_FAILED; vty_out(vty, "%% peer add failed\n"); } - return result ? CMD_WARNING_CONFIG_FAILED : CMD_SUCCESS; + return ret; } DEFUN_HIDDEN (ip_msdp_peer, @@ -7581,6 +7586,7 @@ static int ip_msdp_mesh_group_member_cmd_worker(struct pim_instance *pim, { enum pim_msdp_err result; struct in_addr mbr_ip; + int ret = CMD_SUCCESS; result = inet_pton(AF_INET, mbr, &mbr_ip); if (result <= 0) { @@ -7594,19 +7600,23 @@ static int ip_msdp_mesh_group_member_cmd_worker(struct pim_instance *pim, case PIM_MSDP_ERR_NONE: break; case PIM_MSDP_ERR_OOM: + ret = CMD_WARNING_CONFIG_FAILED; vty_out(vty, "%% Out of memory\n"); break; case PIM_MSDP_ERR_MG_MBR_EXISTS: + ret = CMD_WARNING; vty_out(vty, "%% mesh-group member exists\n"); break; case PIM_MSDP_ERR_MAX_MESH_GROUPS: + ret = CMD_WARNING_CONFIG_FAILED; vty_out(vty, "%% Only one mesh-group allowed currently\n"); break; default: + ret = CMD_WARNING_CONFIG_FAILED; vty_out(vty, "%% member add failed\n"); } - return result ? CMD_WARNING_CONFIG_FAILED : CMD_SUCCESS; + return ret; } DEFUN (ip_msdp_mesh_group_member, From e3e0481542c034b00fab4caa0b1bcd919f50b91c Mon Sep 17 00:00:00 2001 From: lihongguang Date: Wed, 3 Jan 2018 22:47:28 +0800 Subject: [PATCH 29/48] ospfd: return non-zero for configuration failures Signed-off-by: lihongguang --- ospfd/ospf_vty.h | 1 + 1 file changed, 1 insertion(+) diff --git a/ospfd/ospf_vty.h b/ospfd/ospf_vty.h index 9fd0c3ed4c..5eb6842be3 100644 --- a/ospfd/ospf_vty.h +++ b/ospfd/ospf_vty.h @@ -44,6 +44,7 @@ vty_out(vty, \ "%% You can't configure %s to backbone\n", \ NAME); \ + return CMD_WARNING; \ } \ } From e0330274590f87f53838b0a2e62f467dae77d566 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 2 Jan 2018 09:47:38 -0500 Subject: [PATCH 30/48] bgpd: Fix peer uptime display in milliseconds For some reason bgp is calculating the peer uptime in miliseconds incorrectly. Additionally we have the peer_uptime function call that should be doing this! But since we've choosen different names for the json output we cannot fix it at this point. uptime contains the number of seconds of uptime here. Just multiply by 1k and display that( as peer_uptime does ) Fixes: #1585 Signed-off-by: Donald Sharp --- bgpd/bgp_vty.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index d1d684ccb3..2d37e6bd57 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -8288,17 +8288,13 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, u_char use_json, if (p->status == Established) { time_t uptime; - struct tm *tm; uptime = bgp_clock(); uptime -= p->uptime; - tm = gmtime(&uptime); epoch_tbuf = time(NULL) - uptime; json_object_int_add(json_neigh, "bgpTimerUp", - (tm->tm_sec * 1000) - + (tm->tm_min * 60000) - + (tm->tm_hour * 3600000)); + uptime * 1000); json_object_string_add(json_neigh, "bgpTimerUpString", peer_uptime(p->uptime, timebuf, BGP_UPTIME_LEN, 0, From d3c7efede79f88c978efadd850034d472e02cfdb Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 2 Jan 2018 10:12:05 -0500 Subject: [PATCH 31/48] bgpd: Allow for deprecation of json bgpTimerUp The bgpTimerUp value was incorrectly named, add a correct name bgpTimerUpMsec and add some code to allow for deprecation. Signed-off-by: Donald Sharp --- bgpd/bgp_vty.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index 2d37e6bd57..af05a1f3b1 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -8293,8 +8293,24 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, u_char use_json, uptime -= p->uptime; epoch_tbuf = time(NULL) - uptime; +#if CONFDATE > 20200101 + CPP_NOTICE("bgpTimerUp should be deprecated and can be removed now"); +#endif + /* + * bgpTimerUp was miliseconds that was accurate + * up to 1 day, then the value returned + * became garbage. So in order to provide + * some level of backwards compatability, + * we still provde the data, but now + * we are returning the correct value + * and also adding a new bgpTimerUpMsec + * which will allow us to deprecate + * this eventually + */ json_object_int_add(json_neigh, "bgpTimerUp", uptime * 1000); + json_object_int_add(json_neigh, "bgpTimerUpMsec", + uptime * 1000); json_object_string_add(json_neigh, "bgpTimerUpString", peer_uptime(p->uptime, timebuf, BGP_UPTIME_LEN, 0, From cb94eaebffb96aded4784fd89221b11f22336c6a Mon Sep 17 00:00:00 2001 From: Quentin Young Date: Tue, 2 Jan 2018 18:19:40 +0000 Subject: [PATCH 32/48] lib: add ringbuf_copy() Quick 'n easy way to copy the contents of one ringbuf to another. Signed-off-by: Quentin Young --- lib/ringbuf.c | 9 +++++++++ lib/ringbuf.h | 10 ++++++++++ 2 files changed, 19 insertions(+) diff --git a/lib/ringbuf.c b/lib/ringbuf.c index f8e9a9bd8a..d4efbe05fb 100644 --- a/lib/ringbuf.c +++ b/lib/ringbuf.c @@ -110,6 +110,15 @@ size_t ringbuf_peek(struct ringbuf *buf, size_t offset, void *data, size_t size) return copysize; } +size_t ringbuf_copy(struct ringbuf *to, struct ringbuf *from, size_t size) +{ + size_t tocopy = MIN(ringbuf_space(to), size); + uint8_t *cbuf = XCALLOC(MTYPE_TMP, tocopy); + tocopy = ringbuf_peek(from, 0, cbuf, tocopy); + XFREE(MTYPE_TMP, cbuf); + return ringbuf_put(to, cbuf, tocopy); +} + void ringbuf_reset(struct ringbuf *buf) { buf->start = buf->end = 0; diff --git a/lib/ringbuf.h b/lib/ringbuf.h index 2288a2716f..15049e3eea 100644 --- a/lib/ringbuf.h +++ b/lib/ringbuf.h @@ -98,6 +98,16 @@ size_t ringbuf_get(struct ringbuf *buf, void *data, size_t size); size_t ringbuf_peek(struct ringbuf *buf, size_t offset, void *data, size_t size); +/* + * Copy data from one ringbuf to another. + * + * @param to destination ringbuf + * @param from source ringbuf + * @param size how much data to copy + * @return amount of data copied + */ +size_t ringbuf_copy(struct ringbuf *to, struct ringbuf *from, size_t size); + /* * Reset buffer. Does not wipe. * From 74e4a329a34b1d1ad5e3ee5653ae3b7f0680c9fe Mon Sep 17 00:00:00 2001 From: Quentin Young Date: Wed, 3 Jan 2018 13:58:53 -0500 Subject: [PATCH 33/48] lib: fix a few bugs in ring buffers * Fix rare failure caused when end pointer is at end of buffer memory and a call to ringbuf_get() is made that reads all of the data in the buffer; start pointer was advanced past end pointer, causing some special handling to be skipped * Fix ringbuf_peek() moving start pointer * Fix use after free * Remove extraneous assignment * Update relevant tests Signed-off-by: Quentin Young --- lib/ringbuf.c | 8 ++++---- tests/lib/test_ringbuf.c | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/ringbuf.c b/lib/ringbuf.c index d4efbe05fb..11db502a94 100644 --- a/lib/ringbuf.c +++ b/lib/ringbuf.c @@ -58,7 +58,7 @@ size_t ringbuf_put(struct ringbuf *buf, const void *data, size_t size) size_t space = ringbuf_space(buf); size_t copysize = MIN(size, space); size_t tocopy = copysize; - if (tocopy > buf->size - buf->end) { + if (tocopy >= buf->size - buf->end) { size_t ts = buf->size - buf->end; memcpy(buf->data + buf->end, dp, ts); buf->end = 0; @@ -102,7 +102,7 @@ size_t ringbuf_peek(struct ringbuf *buf, size_t offset, void *data, size_t size) if (tocopy >= buf->size - cstart) { size_t ts = buf->size - cstart; memcpy(dp, buf->data + cstart, ts); - buf->start = cstart = 0; + cstart = 0; tocopy -= ts; dp += ts; } @@ -115,8 +115,9 @@ size_t ringbuf_copy(struct ringbuf *to, struct ringbuf *from, size_t size) size_t tocopy = MIN(ringbuf_space(to), size); uint8_t *cbuf = XCALLOC(MTYPE_TMP, tocopy); tocopy = ringbuf_peek(from, 0, cbuf, tocopy); + size_t put = ringbuf_put(to, cbuf, tocopy); XFREE(MTYPE_TMP, cbuf); - return ringbuf_put(to, cbuf, tocopy); + return put; } void ringbuf_reset(struct ringbuf *buf) @@ -129,5 +130,4 @@ void ringbuf_wipe(struct ringbuf *buf) { memset(buf->data, 0x00, buf->size); ringbuf_reset(buf); - buf->empty = true; } diff --git a/tests/lib/test_ringbuf.c b/tests/lib/test_ringbuf.c index c2f4f76a6f..7ba5a29b62 100644 --- a/tests/lib/test_ringbuf.c +++ b/tests/lib/test_ringbuf.c @@ -65,7 +65,7 @@ int main(int argc, char **argv) validate_state(soil, BUFSIZ, BUFSIZ); assert(soil->start == 0); - assert(soil->end == BUFSIZ); + assert(soil->end == 0); /* read 15 bytes of garbage */ printf("Validating read...\n"); @@ -73,7 +73,7 @@ int main(int argc, char **argv) validate_state(soil, BUFSIZ, BUFSIZ - 15); assert(soil->start == 15); - assert(soil->end == BUFSIZ); + assert(soil->end == 0); /* put another 10 bytes and validate wraparound */ printf("Validating wraparound...\n"); From 74ffbfe6fe65e4d30c6053c26a0f5df0e0795870 Mon Sep 17 00:00:00 2001 From: Quentin Young Date: Tue, 2 Jan 2018 18:20:00 +0000 Subject: [PATCH 34/48] bgpd: use ring buffer for network input The multithreading code has a comment that reads: "XXX: Heavy abuse of stream API. This needs a ring buffer." This patch makes the relevant code use a ring buffer. Signed-off-by: Quentin Young --- bgpd/bgp_fsm.c | 8 ++-- bgpd/bgp_io.c | 90 ++++++++++++++++++------------------------ bgpd/bgpd.c | 7 +++- bgpd/bgpd.h | 4 +- bgpd/rfapi/rfapi.c | 3 +- bgpd/rfapi/vnc_zebra.c | 3 +- 6 files changed, 55 insertions(+), 60 deletions(-) diff --git a/bgpd/bgp_fsm.c b/bgpd/bgp_fsm.c index 9e58e466e1..831aca1e35 100644 --- a/bgpd/bgp_fsm.c +++ b/bgpd/bgp_fsm.c @@ -27,6 +27,7 @@ #include "thread.h" #include "log.h" #include "stream.h" +#include "ringbuf.h" #include "memory.h" #include "plist.h" #include "workqueue.h" @@ -155,7 +156,6 @@ static struct peer *peer_xfer_conn(struct peer *from_peer) stream_fifo_clean(peer->ibuf); stream_fifo_clean(peer->obuf); - stream_reset(peer->ibuf_work); /* * this should never happen, since bgp_process_packet() is the @@ -183,7 +183,9 @@ static struct peer *peer_xfer_conn(struct peer *from_peer) stream_fifo_push(peer->ibuf, stream_fifo_pop(from_peer->ibuf)); - stream_copy(peer->ibuf_work, from_peer->ibuf_work); + ringbuf_wipe(peer->ibuf_work); + ringbuf_copy(peer->ibuf_work, from_peer->ibuf_work, + ringbuf_remain(from_peer->ibuf_work)); } pthread_mutex_unlock(&from_peer->io_mtx); pthread_mutex_unlock(&peer->io_mtx); @@ -1097,7 +1099,7 @@ int bgp_stop(struct peer *peer) stream_fifo_clean(peer->obuf); if (peer->ibuf_work) - stream_reset(peer->ibuf_work); + ringbuf_wipe(peer->ibuf_work); if (peer->obuf_work) stream_reset(peer->obuf_work); diff --git a/bgpd/bgp_io.c b/bgpd/bgp_io.c index 548167b3a3..24f55a66f6 100644 --- a/bgpd/bgp_io.c +++ b/bgpd/bgp_io.c @@ -29,6 +29,7 @@ #include "memory.h" // for MTYPE_TMP, XCALLOC, XFREE #include "network.h" // for ERRNO_IO_RETRY #include "stream.h" // for stream_get_endp, stream_getw_from, str... +#include "ringbuf.h" // for ringbuf_remain, ringbuf_peek, ringbuf_... #include "thread.h" // for THREAD_OFF, THREAD_ARG, thread, thread... #include "zassert.h" // for assert @@ -273,14 +274,12 @@ static int bgp_process_reads(struct thread *thread) /* static buffer for transferring packets */ static unsigned char pktbuf[BGP_MAX_PACKET_SIZE]; /* shorter alias to peer's input buffer */ - struct stream *ibw = peer->ibuf_work; - /* offset of start of current packet */ - size_t offset = stream_get_getp(ibw); + struct ringbuf *ibw = peer->ibuf_work; /* packet size as given by header */ - u_int16_t pktsize = 0; + uint16_t pktsize = 0; /* check that we have enough data for a header */ - if (STREAM_READABLE(ibw) < BGP_HEADER_SIZE) + if (ringbuf_remain(ibw) < BGP_HEADER_SIZE) break; /* validate header */ @@ -292,16 +291,18 @@ static int bgp_process_reads(struct thread *thread) } /* header is valid; retrieve packet size */ - pktsize = stream_getw_from(ibw, offset + BGP_MARKER_SIZE); + ringbuf_peek(ibw, BGP_MARKER_SIZE, &pktsize, sizeof(pktsize)); + + pktsize = ntohs(pktsize); /* if this fails we are seriously screwed */ assert(pktsize <= BGP_MAX_PACKET_SIZE); /* If we have that much data, chuck it into its own * stream and append to input queue for processing. */ - if (STREAM_READABLE(ibw) >= pktsize) { + if (ringbuf_remain(ibw) >= pktsize) { struct stream *pkt = stream_new(pktsize); - stream_get(pktbuf, ibw, pktsize); + assert(ringbuf_get(ibw, pktbuf, pktsize) == pktsize); stream_put(pkt, pktbuf, pktsize); pthread_mutex_lock(&peer->io_mtx); @@ -315,28 +316,12 @@ static int bgp_process_reads(struct thread *thread) break; } - /* - * After reading: - * 1. Move unread data to stream start to make room for more. - * 2. Reschedule and return when we have additional data. - * - * XXX: Heavy abuse of stream API. This needs a ring buffer. - */ - if (more && STREAM_WRITEABLE(peer->ibuf_work) < BGP_MAX_PACKET_SIZE) { - void *from = stream_pnt(peer->ibuf_work); - void *to = peer->ibuf_work->data; - size_t siz = STREAM_READABLE(peer->ibuf_work); - memmove(to, from, siz); - stream_set_getp(peer->ibuf_work, 0); - stream_set_endp(peer->ibuf_work, siz); - } - - assert(STREAM_WRITEABLE(peer->ibuf_work) >= BGP_MAX_PACKET_SIZE); + assert(ringbuf_space(peer->ibuf_work) >= BGP_MAX_PACKET_SIZE); /* handle invalid header */ if (fatal) { /* wipe buffer just in case someone screwed up */ - stream_reset(peer->ibuf_work); + ringbuf_wipe(peer->ibuf_work); } else { thread_add_read(fpt->master, bgp_process_reads, peer, peer->fd, &peer->t_read); @@ -474,14 +459,16 @@ static uint16_t bgp_read(struct peer *peer) size_t readsize; // how many bytes we want to read ssize_t nbytes; // how many bytes we actually read uint16_t status = 0; + static uint8_t ibw[BGP_MAX_PACKET_SIZE * BGP_READ_PACKET_MAX]; - readsize = STREAM_WRITEABLE(peer->ibuf_work); + readsize = MIN(ringbuf_space(peer->ibuf_work), sizeof(ibw)); + nbytes = read(peer->fd, ibw, readsize); - nbytes = stream_read_try(peer->ibuf_work, peer->fd, readsize); - - switch (nbytes) { + /* EAGAIN or EWOULDBLOCK; come back later */ + if (nbytes < 0 && ERRNO_IO_RETRY(errno)) { + SET_FLAG(status, BGP_IO_TRANS_ERR); /* Fatal error; tear down session */ - case -1: + } else if (nbytes < 0) { zlog_err("%s [Error] bgp_read_packet error: %s", peer->host, safe_strerror(errno)); @@ -495,10 +482,8 @@ static uint16_t bgp_read(struct peer *peer) BGP_EVENT_ADD(peer, TCP_fatal_error); SET_FLAG(status, BGP_IO_FATAL_ERR); - break; - /* Received EOF / TCP session closed */ - case 0: + } else if (nbytes == 0) { if (bgp_debug_neighbor_events(peer)) zlog_debug("%s [Event] BGP connection closed fd %d", peer->host, peer->fd); @@ -513,14 +498,9 @@ static uint16_t bgp_read(struct peer *peer) BGP_EVENT_ADD(peer, TCP_connection_closed); SET_FLAG(status, BGP_IO_FATAL_ERR); - break; - - /* EAGAIN or EWOULDBLOCK; come back later */ - case -2: - SET_FLAG(status, BGP_IO_TRANS_ERR); - break; - default: - break; + } else { + assert(ringbuf_put(peer->ibuf_work, ibw, nbytes) + == (size_t)nbytes); } return status; @@ -529,27 +509,35 @@ static uint16_t bgp_read(struct peer *peer) /* * Called after we have read a BGP packet header. Validates marker, message * type and packet length. If any of these aren't correct, sends a notify. + * + * Assumes that there are at least BGP_HEADER_SIZE readable bytes in the input + * buffer. */ static bool validate_header(struct peer *peer) { uint16_t size; uint8_t type; - struct stream *pkt = peer->ibuf_work; - size_t getp = stream_get_getp(pkt); + struct ringbuf *pkt = peer->ibuf_work; - static uint8_t marker[BGP_MARKER_SIZE] = { - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + static uint8_t m_correct[BGP_MARKER_SIZE] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + uint8_t m_rx[BGP_MARKER_SIZE] = {0x00}; - if (memcmp(marker, stream_pnt(pkt), BGP_MARKER_SIZE) != 0) { + if (ringbuf_peek(pkt, 0, m_rx, BGP_MARKER_SIZE) != BGP_MARKER_SIZE) + return false; + + if (memcmp(m_correct, m_rx, BGP_MARKER_SIZE) != 0) { bgp_notify_send(peer, BGP_NOTIFY_HEADER_ERR, BGP_NOTIFY_HEADER_NOT_SYNC); return false; } - /* Get size and type in host byte order. */ - size = stream_getw_from(pkt, getp + BGP_MARKER_SIZE); - type = stream_getc_from(pkt, getp + BGP_MARKER_SIZE + 2); + /* Get size and type in network byte order. */ + ringbuf_peek(pkt, BGP_MARKER_SIZE, &size, sizeof(size)); + ringbuf_peek(pkt, BGP_MARKER_SIZE + 2, &type, sizeof(type)); + + size = ntohs(size); /* BGP type check. */ if (type != BGP_MSG_OPEN && type != BGP_MSG_UPDATE diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index 6dcb603cb6..7b29820db1 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -24,6 +24,7 @@ #include "thread.h" #include "buffer.h" #include "stream.h" +#include "ringbuf.h" #include "command.h" #include "sockunion.h" #include "sockopt.h" @@ -1162,7 +1163,9 @@ struct peer *peer_new(struct bgp *bgp) */ peer->obuf_work = stream_new(BGP_MAX_PACKET_SIZE + BGP_MAX_PACKET_SIZE_OVERFLOW); - peer->ibuf_work = stream_new(BGP_MAX_PACKET_SIZE * BGP_READ_PACKET_MAX); + peer->ibuf_work = + ringbuf_new(BGP_MAX_PACKET_SIZE * BGP_READ_PACKET_MAX); + peer->scratch = stream_new(BGP_MAX_PACKET_SIZE); bgp_sync_init(peer); @@ -2179,7 +2182,7 @@ int peer_delete(struct peer *peer) } if (peer->ibuf_work) { - stream_free(peer->ibuf_work); + ringbuf_del(peer->ibuf_work); peer->ibuf_work = NULL; } diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h index 6bb49e0c53..ee829f33d1 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h @@ -598,8 +598,8 @@ struct peer { struct stream_fifo *ibuf; // packets waiting to be processed struct stream_fifo *obuf; // packets waiting to be written - struct stream *ibuf_work; // WiP buffer used by bgp_read() only - struct stream *obuf_work; // WiP buffer used to construct packets + struct ringbuf *ibuf_work; // WiP buffer used by bgp_read() only + struct stream *obuf_work; // WiP buffer used to construct packets struct stream *curr; // the current packet being parsed diff --git a/bgpd/rfapi/rfapi.c b/bgpd/rfapi/rfapi.c index 5ba7a96a8f..1e3c5a0352 100644 --- a/bgpd/rfapi/rfapi.c +++ b/bgpd/rfapi/rfapi.c @@ -31,6 +31,7 @@ #include "lib/linklist.h" #include "lib/command.h" #include "lib/stream.h" +#include "lib/ringbuf.h" #include "bgpd/bgpd.h" #include "bgpd/bgp_ecommunity.h" @@ -1310,7 +1311,7 @@ static int rfapi_open_inner(struct rfapi_descriptor *rfd, struct bgp *bgp, stream_fifo_free(rfd->peer->obuf); if (rfd->peer->ibuf_work) - stream_free(rfd->peer->ibuf_work); + ringbuf_del(rfd->peer->ibuf_work); if (rfd->peer->obuf_work) stream_free(rfd->peer->obuf_work); diff --git a/bgpd/rfapi/vnc_zebra.c b/bgpd/rfapi/vnc_zebra.c index 07be7833b6..f8b38468f5 100644 --- a/bgpd/rfapi/vnc_zebra.c +++ b/bgpd/rfapi/vnc_zebra.c @@ -30,6 +30,7 @@ #include "lib/command.h" #include "lib/zclient.h" #include "lib/stream.h" +#include "lib/ringbuf.h" #include "lib/memory.h" #include "bgpd/bgpd.h" @@ -198,7 +199,7 @@ static void vnc_redistribute_add(struct prefix *p, u_int32_t metric, stream_fifo_free(vncHD1VR.peer->obuf); if (vncHD1VR.peer->ibuf_work) - stream_free(vncHD1VR.peer->ibuf_work); + ringbuf_del(vncHD1VR.peer->ibuf_work); if (vncHD1VR.peer->obuf_work) stream_free(vncHD1VR.peer->obuf_work); From 1505b537a8abba9d4fc199caa7b0a21b0af7f0e5 Mon Sep 17 00:00:00 2001 From: Chirag Shah Date: Wed, 3 Jan 2018 11:41:45 -0800 Subject: [PATCH 35/48] lib: Fix no interface cmd vrf parsing For no interface vrf VRFNAME, vrf-name is not parsed properly. Ticket:CM-19274 Signed-off-by: Chirag Shah --- lib/if.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/if.c b/lib/if.c index 0fe7da1c0d..8e6a9a6968 100644 --- a/lib/if.c +++ b/lib/if.c @@ -663,8 +663,9 @@ DEFUN_NOSH (no_interface, "Interface's name\n" VRF_CMD_HELP_STR) { + int idx_vrf = 4; const char *ifname = argv[2]->arg; - const char *vrfname = (argc > 3) ? argv[3]->arg : NULL; + const char *vrfname = (argc > 3) ? argv[idx_vrf]->arg : NULL; // deleting interface struct interface *ifp; From ca19319b2e172a199efb8beeed4e3e222a5264ae Mon Sep 17 00:00:00 2001 From: lihongguang Date: Thu, 4 Jan 2018 07:01:58 +0800 Subject: [PATCH 36/48] ospfd: fix [no] area authentication command Signed-off-by: lihongguang lhg803@163.com --- ospfd/ospf_vty.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c index a5ea14793a..b1a0acf83c 100644 --- a/ospfd/ospf_vty.c +++ b/ospfd/ospf_vty.c @@ -1974,12 +1974,13 @@ DEFUN (ospf_area_authentication_message_digest, "Use message-digest authentication\n") { VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); - int idx_ipv4_number = 1; + int idx = 0; struct ospf_area *area; struct in_addr area_id; int format; - VTY_GET_OSPF_AREA_ID(area_id, format, argv[idx_ipv4_number]->arg); + argv_find(argv, argc, "area", &idx); + VTY_GET_OSPF_AREA_ID(area_id, format, argv[idx + 1]->arg); area = ospf_area_get(ospf, area_id); ospf_area_display_format_set(ospf, area, format); From 8356e9b7b08c89145eaca264a040c2a8e70f5702 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 4 Jan 2018 05:45:28 -0500 Subject: [PATCH 37/48] bgpd: fix failing to compile on 32 bit systems -Werror=sign-compare is failing with signed/unsigned usage in the conditional expression. Fixes: #1593 Signed-off-by: Donald Sharp --- bgpd/bgp_route.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 64391e9d45..81b605ad79 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -5068,9 +5068,10 @@ DEFPY(bgp_network, } return bgp_static_set(vty, no, address_str ? addr_prefix_str:prefix_str, - AFI_IP, bgp_node_safi(vty), - map_name, backdoor?1:0, - label_index ? label_index:BGP_INVALID_LABEL_INDEX); + AFI_IP, bgp_node_safi(vty), + map_name, backdoor?1:0, + label_index ? + (uint32_t)label_index : BGP_INVALID_LABEL_INDEX); } DEFPY(ipv6_bgp_network, @@ -5086,8 +5087,9 @@ DEFPY(ipv6_bgp_network, "Label index value\n") { return bgp_static_set(vty, no, prefix_str, AFI_IP6, - bgp_node_safi(vty), map_name, 0, - label_index ? label_index:BGP_INVALID_LABEL_INDEX); + bgp_node_safi(vty), map_name, 0, + label_index ? + (uint32_t)label_index : BGP_INVALID_LABEL_INDEX); } /* Aggreagete address: From a21bd7a3b973f5717fc4f47de51281827309b80b Mon Sep 17 00:00:00 2001 From: Dario Wiesner Date: Thu, 4 Jan 2018 12:34:24 +0100 Subject: [PATCH 38/48] bgpd: add PMSI_TUNNEL_ATTRIBUTE to EVPN IMET routes Signed-off-by: Dario Wiesner --- bgpd/bgp_attr.c | 14 ++++++++++++++ bgpd/bgp_evpn.c | 2 ++ bgpd/bgpd.h | 1 + 3 files changed, 17 insertions(+) diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c index 00bad08fbe..5b917fc814 100644 --- a/bgpd/bgp_attr.c +++ b/bgpd/bgp_attr.c @@ -74,6 +74,7 @@ static const struct message attr_str[] = { {BGP_ATTR_AS4_PATH, "AS4_PATH"}, {BGP_ATTR_AS4_AGGREGATOR, "AS4_AGGREGATOR"}, {BGP_ATTR_AS_PATHLIMIT, "AS_PATHLIMIT"}, + {BGP_ATTR_PMSI_TUNNEL, "PMSI_TUNNEL_ATTRIBUTE"}, {BGP_ATTR_ENCAP, "ENCAP"}, #if ENABLE_BGP_VNC {BGP_ATTR_VNC, "VNC"}, @@ -1034,6 +1035,8 @@ const u_int8_t attr_flags_values[] = { BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS, [BGP_ATTR_AS4_AGGREGATOR] = BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS, + [BGP_ATTR_PMSI_TUNNEL] = + BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS, [BGP_ATTR_LARGE_COMMUNITIES] = BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS, [BGP_ATTR_PREFIX_SID] = @@ -3246,6 +3249,17 @@ bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer, #endif } + /* PMSI Tunnel */ + if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL)) { + stream_putc(s, BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS); + stream_putc(s, BGP_ATTR_PMSI_TUNNEL); + stream_putc(s, 9); // Length + stream_putc(s, 0); // Flags + stream_putc(s, 6); // Tunnel type: Ingress Replication (6) + stream_put(s, &(attr->label), BGP_LABEL_BYTES); // MPLS Label / VXLAN VNI + stream_put_ipv4(s, attr->nexthop.s_addr); // Unicast tunnel endpoint IP address + } + /* Unknown transit attribute. */ if (attr->transit) stream_put(s, attr->transit->val, attr->transit->length); diff --git a/bgpd/bgp_evpn.c b/bgpd/bgp_evpn.c index 182a6c64f2..ca2e1a54d4 100644 --- a/bgpd/bgp_evpn.c +++ b/bgpd/bgp_evpn.c @@ -834,6 +834,8 @@ static int update_evpn_route(struct bgp *bgp, struct bgpevpn *vpn, attr.mp_nexthop_global_in = vpn->originator_ip; attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4; attr.sticky = CHECK_FLAG(flags, ZEBRA_MAC_TYPE_STICKY) ? 1 : 0; + attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL); + vni2label(vpn->vni, &(attr.label)); /* Set up RT and ENCAP extended community. */ build_evpn_route_extcomm(vpn, &attr); diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h index 6bb49e0c53..ce56587727 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h @@ -1020,6 +1020,7 @@ struct bgp_nlri { #define BGP_ATTR_AS4_PATH 17 #define BGP_ATTR_AS4_AGGREGATOR 18 #define BGP_ATTR_AS_PATHLIMIT 21 +#define BGP_ATTR_PMSI_TUNNEL 22 #define BGP_ATTR_ENCAP 23 #define BGP_ATTR_LARGE_COMMUNITIES 32 #define BGP_ATTR_PREFIX_SID 40 From 7bfe377d63f41d21e0b7dece264bcf54a197ac13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=9Fingen?= Date: Mon, 13 Nov 2017 21:41:58 +0100 Subject: [PATCH 39/48] ldpd: Add privs to label manager MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: ßingen --- zebra/label_manager.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/zebra/label_manager.c b/zebra/label_manager.c index bf4522b70f..f38206d8e1 100644 --- a/zebra/label_manager.c +++ b/zebra/label_manager.c @@ -41,6 +41,8 @@ struct label_manager lbl_mgr; +extern struct zebra_privs_t zserv_privs; + DEFINE_MGROUP(LBL_MGR, "Label Manager"); DEFINE_MTYPE_STATIC(LBL_MGR, LM_CHUNK, "Label Manager Chunk"); @@ -222,6 +224,7 @@ static void lm_zclient_init(char *lm_zserv_path) /* Set default values. */ zclient = zclient_new_notify(zebrad.master, &zclient_options_default); + zclient->privs = &zserv_privs; zclient->sock = -1; zclient->t_connect = NULL; lm_zclient_connect(NULL); From b2140cb7c8620d51f55942d349612129f51d6552 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Sat, 6 Jan 2018 11:48:11 -0500 Subject: [PATCH 40/48] lib: Add pthread_yield Signed-off-by: Donald Sharp --- lib/frr_pthread.c | 6 ++++++ lib/frr_pthread.h | 3 +++ 2 files changed, 9 insertions(+) diff --git a/lib/frr_pthread.c b/lib/frr_pthread.c index 8b23640fa4..19dfbaf54b 100644 --- a/lib/frr_pthread.c +++ b/lib/frr_pthread.c @@ -19,6 +19,7 @@ #include #include +#include #include "frr_pthread.h" #include "memory.h" @@ -182,3 +183,8 @@ unsigned int frr_pthread_get_id() { return next_id++; } + +void frr_pthread_yield(void) +{ + (void)sched_yield(); +} diff --git a/lib/frr_pthread.h b/lib/frr_pthread.h index 9dee5fcca4..f6000340a7 100644 --- a/lib/frr_pthread.h +++ b/lib/frr_pthread.h @@ -130,6 +130,9 @@ int frr_pthread_stop(unsigned int id, void **result); /* Stops all frr_pthread's. */ void frr_pthread_stop_all(void); +/* Yields the current thread of execution */ +void frr_pthread_yield(void); + /* Returns a unique identifier for use with frr_pthread_new(). * * Internally, this is an integer that increments after each call to this From 88b24dee19fcf88ed32d5574e4f45c005f66a642 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Sat, 6 Jan 2018 14:04:35 -0500 Subject: [PATCH 41/48] bgpd: Ensure that io thread is running after start The BGP IO thread must be running before other threads can start using it. So at startup check to see that it running once, instead of before every function call into. Signed-off-by: Donald Sharp --- bgpd/bgp_io.c | 22 ++++++---------------- bgpd/bgp_io.h | 10 ++++++++++ bgpd/bgpd.c | 8 ++++++++ 3 files changed, 24 insertions(+), 16 deletions(-) diff --git a/bgpd/bgp_io.c b/bgpd/bgp_io.c index 548167b3a3..cc9c1bda56 100644 --- a/bgpd/bgp_io.c +++ b/bgpd/bgp_io.c @@ -109,13 +109,15 @@ int bgp_io_stop(void **result, struct frr_pthread *fpt) } /* Extern API -------------------------------------------------------------- */ +void bgp_io_running(void) +{ + while (!atomic_load_explicit(&bgp_io_thread_started, + memory_order_seq_cst)) + frr_pthread_yield(); +} void bgp_writes_on(struct peer *peer) { - while ( - !atomic_load_explicit(&bgp_io_thread_started, memory_order_seq_cst)) - ; - assert(peer->status != Deleted); assert(peer->obuf); assert(peer->ibuf); @@ -133,10 +135,6 @@ void bgp_writes_on(struct peer *peer) void bgp_writes_off(struct peer *peer) { - while ( - !atomic_load_explicit(&bgp_io_thread_started, memory_order_seq_cst)) - ; - struct frr_pthread *fpt = frr_pthread_get(PTHREAD_IO); thread_cancel_async(fpt->master, &peer->t_write, NULL); @@ -147,10 +145,6 @@ void bgp_writes_off(struct peer *peer) void bgp_reads_on(struct peer *peer) { - while ( - !atomic_load_explicit(&bgp_io_thread_started, memory_order_seq_cst)) - ; - assert(peer->status != Deleted); assert(peer->ibuf); assert(peer->fd); @@ -170,10 +164,6 @@ void bgp_reads_on(struct peer *peer) void bgp_reads_off(struct peer *peer) { - while ( - !atomic_load_explicit(&bgp_io_thread_started, memory_order_seq_cst)) - ; - struct frr_pthread *fpt = frr_pthread_get(PTHREAD_IO); thread_cancel_async(fpt->master, &peer->t_read, NULL); diff --git a/bgpd/bgp_io.h b/bgpd/bgp_io.h index c4bd3c2dd9..73587366d7 100644 --- a/bgpd/bgp_io.h +++ b/bgpd/bgp_io.h @@ -36,6 +36,16 @@ */ extern void bgp_io_init(void); +/** + * Ensure that the BGP IO thread is actually up and running + * + * This function must be called immediately after the thread + * has been created for running. This is because we want + * to make sure that the io thread is ready before other + * threads start attempting to use it. + */ +extern void bgp_io_running(void); + /** * Start function for write thread. * diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index 6dcb603cb6..4d8e4ffe37 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -7437,7 +7437,15 @@ void bgp_pthreads_run() pthread_attr_init(&attr); pthread_attr_setschedpolicy(&attr, SCHED_FIFO); + /* + * Please ensure that the io thread is running + * by calling bgp_io_running. The BGP threads + * depend on it being running when we start + * looking for it. + */ frr_pthread_run(PTHREAD_IO, &attr, NULL); + bgp_io_running(); + frr_pthread_run(PTHREAD_KEEPALIVES, &attr, NULL); } From 9a0dfa3aa9cd7944d6c18f401525fe4c9c52aeff Mon Sep 17 00:00:00 2001 From: Chirag Shah Date: Sat, 6 Jan 2018 08:24:00 -0800 Subject: [PATCH 42/48] ospfd: Fix no passive interface command parsing Ticket: CM-19365 Signed-off-by: Chirag Shah --- ospfd/ospf_vty.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c index b1a0acf83c..dab7bd4944 100644 --- a/ospfd/ospf_vty.c +++ b/ospfd/ospf_vty.c @@ -534,11 +534,11 @@ DEFUN (no_ospf_passive_interface, } if (ospf->vrf_id != VRF_UNKNOWN) - ifp = if_get_by_name(argv[1]->arg, ospf->vrf_id, 0); + ifp = if_get_by_name(argv[2]->arg, ospf->vrf_id, 0); if (ifp == NULL) { vty_out(vty, "interface %s not found.\n", - (char *)argv[1]->arg); + (char *)argv[2]->arg); return CMD_WARNING_CONFIG_FAILED; } From 23f1c68bb2e38a26ac9e1aea90d84cf45a7f7b41 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Mon, 8 Jan 2018 16:01:22 -0500 Subject: [PATCH 43/48] pimd: Allow use-source to return more subtle error codes The 'ip pim use-source ...' command returns a hard success/failure. Allow it to return a soft-failure for when we re-enter the same line. Signed-off-by: Donald Sharp --- pimd/pim_cmd.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 374e2c52a9..76ba505ad4 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -7333,6 +7333,7 @@ static int interface_pim_use_src_cmd_worker(struct vty *vty, const char *source) { int result; struct in_addr source_addr; + int ret = CMD_SUCCESS; VTY_DECLVAR_CONTEXT(interface, ifp); result = inet_pton(AF_INET, source, &source_addr); @@ -7347,16 +7348,19 @@ static int interface_pim_use_src_cmd_worker(struct vty *vty, const char *source) case PIM_SUCCESS: break; case PIM_IFACE_NOT_FOUND: + ret = CMD_WARNING_CONFIG_FAILED; vty_out(vty, "Pim not enabled on this interface\n"); break; case PIM_UPDATE_SOURCE_DUP: + ret = CMD_WARNING; vty_out(vty, "%% Source already set to %s\n", source); break; default: + ret = CMD_WARNING_CONFIG_FAILED; vty_out(vty, "%% Source set failed\n"); } - return result ? CMD_WARNING_CONFIG_FAILED : CMD_SUCCESS; + return ret; } DEFUN (interface_pim_use_source, From 2b0a905a2ee0c25da73fd5f5051858e7e13c9579 Mon Sep 17 00:00:00 2001 From: Daniel Walton Date: Mon, 8 Jan 2018 21:16:18 +0000 Subject: [PATCH 44/48] ospfd: do not complain if same area is reconfigured Signed-off-by: Daniel Walton Before ------ cel-redxp-10(config)# router ospf vrf RED cel-redxp-10(config-router)# network 1.1.1.1/32 area 0.0.0.0 cel-redxp-10(config-router)# network 1.1.1.1/32 area 0.0.0.0 There is already same network statement. cel-redxp-10(config-router)# When we see the "There is already same network statement." message vtysh exits non-zero. This scenario breaks frr-reload because the command took and it in the config, it should exit zero here. After ----- cel-redxp-10(config)# router ospf vrf RED cel-redxp-10(config-router)# network 1.1.1.1/32 area 0.0.0.0 cel-redxp-10(config-router)# network 1.1.1.1/32 area 0.0.0.0 cel-redxp-10(config-router)# network 1.1.1.1/32 area 0.0.0.0 cel-redxp-10(config-router)# network 1.1.1.1/32 area 0 cel-redxp-10(config-router)# cel-redxp-10(config-router)# network 1.1.1.1/32 area 0.0.0.1 There is already same network statement. cel-redxp-10(config-router)# --- ospfd/ospf_vty.c | 2 +- ospfd/ospfd.c | 10 ++++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c index dab7bd4944..0541bfeee7 100644 --- a/ospfd/ospf_vty.c +++ b/ospfd/ospf_vty.c @@ -619,7 +619,7 @@ DEFUN (ospf_network_area, ret = ospf_network_set(ospf, &p, area_id, format); if (ret == 0) { vty_out(vty, "There is already same network statement.\n"); - return CMD_WARNING; + return CMD_WARNING_CONFIG_FAILED; } return CMD_SUCCESS; diff --git a/ospfd/ospfd.c b/ospfd/ospfd.c index ceb8440eeb..1926197430 100644 --- a/ospfd/ospfd.c +++ b/ospfd/ospfd.c @@ -1031,9 +1031,15 @@ int ospf_network_set(struct ospf *ospf, struct prefix_ipv4 *p, rn = route_node_get(ospf->networks, (struct prefix *)p); if (rn->info) { - /* There is already same network statement. */ + network = rn->info; route_unlock_node(rn); - return 0; + + if (IPV4_ADDR_SAME(&area_id, &network->area_id)) { + return 1; + } else { + /* There is already same network statement. */ + return 0; + } } rn->info = network = ospf_network_new(area_id); From 0112e9e0b9f422b0df4e3b1304297569274c9eab Mon Sep 17 00:00:00 2001 From: Quentin Young Date: Tue, 9 Jan 2018 15:38:17 -0500 Subject: [PATCH 45/48] bgpd: use atomic_* ops on _Atomic variables Signed-off-by: Quentin Young --- bgpd/bgp_fsm.c | 8 ++- bgpd/bgp_packet.c | 21 ++++--- bgpd/bgp_snmp.c | 18 +++--- bgpd/bgp_vty.c | 150 ++++++++++++++++++++-------------------------- bgpd/bgpd.h | 16 +++++ 5 files changed, 110 insertions(+), 103 deletions(-) diff --git a/bgpd/bgp_fsm.c b/bgpd/bgp_fsm.c index 9e58e466e1..b29536088c 100644 --- a/bgpd/bgp_fsm.c +++ b/bgpd/bgp_fsm.c @@ -264,14 +264,16 @@ static struct peer *peer_xfer_conn(struct peer *from_peer) } } + + // Note: peer_xfer_stats() must be called with I/O turned OFF + if (from_peer) + peer_xfer_stats(peer, from_peer); + bgp_reads_on(peer); bgp_writes_on(peer); thread_add_timer_msec(bm->master, bgp_process_packet, peer, 0, &peer->t_process_packet); - if (from_peer) - peer_xfer_stats(peer, from_peer); - return (peer); } diff --git a/bgpd/bgp_packet.c b/bgpd/bgp_packet.c index 4b018aef4d..eed5fdc65d 100644 --- a/bgpd/bgp_packet.c +++ b/bgpd/bgp_packet.c @@ -595,6 +595,7 @@ static int bgp_write_notify(struct peer *peer) assert(type == BGP_MSG_NOTIFY); /* Type should be notify. */ + atomic_fetch_add_explicit(&peer->notify_out, 1, memory_order_relaxed); peer->notify_out++; /* Double start timer. */ @@ -1682,7 +1683,7 @@ static int bgp_notify_receive(struct peer *peer, bgp_size_t size) } /* peer count update */ - peer->notify_in++; + atomic_fetch_add_explicit(&peer->notify_in, 1, memory_order_relaxed); peer->last_reset = PEER_DOWN_NOTIFY_RECEIVED; @@ -2192,7 +2193,8 @@ int bgp_process_packet(struct thread *thread) */ switch (type) { case BGP_MSG_OPEN: - peer->open_in++; + atomic_fetch_add_explicit(&peer->open_in, 1, + memory_order_relaxed); mprc = bgp_open_receive(peer, size); if (mprc == BGP_Stop) zlog_err( @@ -2200,7 +2202,8 @@ int bgp_process_packet(struct thread *thread) __FUNCTION__, peer->host); break; case BGP_MSG_UPDATE: - peer->update_in++; + atomic_fetch_add_explicit(&peer->update_in, 1, + memory_order_relaxed); peer->readtime = monotime(NULL); mprc = bgp_update_receive(peer, size); if (mprc == BGP_Stop) @@ -2209,7 +2212,8 @@ int bgp_process_packet(struct thread *thread) __FUNCTION__, peer->host); break; case BGP_MSG_NOTIFY: - peer->notify_in++; + atomic_fetch_add_explicit(&peer->notify_in, 1, + memory_order_relaxed); mprc = bgp_notify_receive(peer, size); if (mprc == BGP_Stop) zlog_err( @@ -2218,7 +2222,8 @@ int bgp_process_packet(struct thread *thread) break; case BGP_MSG_KEEPALIVE: peer->readtime = monotime(NULL); - peer->keepalive_in++; + atomic_fetch_add_explicit(&peer->keepalive_in, 1, + memory_order_relaxed); mprc = bgp_keepalive_receive(peer, size); if (mprc == BGP_Stop) zlog_err( @@ -2227,7 +2232,8 @@ int bgp_process_packet(struct thread *thread) break; case BGP_MSG_ROUTE_REFRESH_NEW: case BGP_MSG_ROUTE_REFRESH_OLD: - peer->refresh_in++; + atomic_fetch_add_explicit(&peer->refresh_in, 1, + memory_order_relaxed); mprc = bgp_route_refresh_receive(peer, size); if (mprc == BGP_Stop) zlog_err( @@ -2235,7 +2241,8 @@ int bgp_process_packet(struct thread *thread) __FUNCTION__, peer->host); break; case BGP_MSG_CAPABILITY: - peer->dynamic_cap_in++; + atomic_fetch_add_explicit(&peer->dynamic_cap_in, 1, + memory_order_relaxed); mprc = bgp_capability_receive(peer, size); if (mprc == BGP_Stop) zlog_err( diff --git a/bgpd/bgp_snmp.c b/bgpd/bgp_snmp.c index 484ea7c433..8317a252e1 100644 --- a/bgpd/bgp_snmp.c +++ b/bgpd/bgp_snmp.c @@ -512,6 +512,7 @@ static u_char *bgpPeerTable(struct variable *v, oid name[], size_t *length, { static struct in_addr addr; struct peer *peer; + uint32_t ui, uo; if (smux_header_table(v, name, length, exact, var_len, write_method) == MATCH_FAILED) @@ -571,21 +572,20 @@ static u_char *bgpPeerTable(struct variable *v, oid name[], size_t *length, return SNMP_INTEGER(peer->as); break; case BGPPEERINUPDATES: - return SNMP_INTEGER(peer->update_in); + ui = atomic_load_explicit(&peer->update_in, + memory_order_relaxed); + return SNMP_INTEGER(ui); break; case BGPPEEROUTUPDATES: - return SNMP_INTEGER(peer->update_out); + uo = atomic_load_explicit(&peer->update_out, + memory_order_relaxed); + return SNMP_INTEGER(uo); break; case BGPPEERINTOTALMESSAGES: - return SNMP_INTEGER(peer->open_in + peer->update_in - + peer->keepalive_in + peer->notify_in - + peer->refresh_in + peer->dynamic_cap_in); + return SNMP_INTEGER(PEER_TOTAL_RX(peer)); break; case BGPPEEROUTTOTALMESSAGES: - return SNMP_INTEGER(peer->open_out + peer->update_out - + peer->keepalive_out + peer->notify_out - + peer->refresh_out - + peer->dynamic_cap_out); + return SNMP_INTEGER(PEER_TOTAL_TX(peer)); break; case BGPPEERLASTERROR: { static u_char lasterror[2]; diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index d1d684ccb3..1be71d1e46 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -7053,17 +7053,9 @@ static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi, json_object_int_add(json_peer, "remoteAs", peer->as); json_object_int_add(json_peer, "version", 4); json_object_int_add(json_peer, "msgRcvd", - peer->open_in + peer->update_in - + peer->keepalive_in - + peer->notify_in - + peer->refresh_in - + peer->dynamic_cap_in); + PEER_TOTAL_RX(peer)); json_object_int_add(json_peer, "msgSent", - peer->open_out + peer->update_out - + peer->keepalive_out - + peer->notify_out - + peer->refresh_out - + peer->dynamic_cap_out); + PEER_TOTAL_TX(peer)); json_object_int_add(json_peer, "tableVersion", peer->version[afi][safi]); @@ -7120,42 +7112,9 @@ static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi, " "); vty_out(vty, "4 %10u %7u %7u %8" PRIu64 " %4d %4zd %8s", - peer->as, - atomic_load_explicit(&peer->open_in, - memory_order_relaxed) - + atomic_load_explicit( - &peer->update_in, - memory_order_relaxed) - + atomic_load_explicit( - &peer->keepalive_in, - memory_order_relaxed) - + atomic_load_explicit( - &peer->notify_in, - memory_order_relaxed) - + atomic_load_explicit( - &peer->refresh_in, - memory_order_relaxed) - + atomic_load_explicit( - &peer->dynamic_cap_in, - memory_order_relaxed), - atomic_load_explicit(&peer->open_out, - memory_order_relaxed) - + atomic_load_explicit( - &peer->update_out, - memory_order_relaxed) - + atomic_load_explicit( - &peer->keepalive_out, - memory_order_relaxed) - + atomic_load_explicit( - &peer->notify_out, - memory_order_relaxed) - + atomic_load_explicit( - &peer->refresh_out, - memory_order_relaxed) - + atomic_load_explicit( - &peer->dynamic_cap_out, - memory_order_relaxed), - peer->version[afi][safi], 0, peer->obuf->count, + peer->as, PEER_TOTAL_RX(peer), + PEER_TOTAL_TX(peer), peer->version[afi][safi], + 0, peer->obuf->count, peer_uptime(peer->uptime, timebuf, BGP_UPTIME_LEN, 0, NULL)); @@ -9329,34 +9288,44 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, u_char use_json, json_object_int_add(json_stat, "depthInq", 0); json_object_int_add(json_stat, "depthOutq", (unsigned long)p->obuf->count); - json_object_int_add(json_stat, "opensSent", p->open_out); - json_object_int_add(json_stat, "opensRecv", p->open_in); + json_object_int_add(json_stat, "opensSent", + atomic_load_explicit(&p->open_out, + memory_order_relaxed)); + json_object_int_add(json_stat, "opensRecv", + atomic_load_explicit(&p->open_in, + memory_order_relaxed)); json_object_int_add(json_stat, "notificationsSent", - p->notify_out); + atomic_load_explicit(&p->notify_out, + memory_order_relaxed)); json_object_int_add(json_stat, "notificationsRecv", - p->notify_in); - json_object_int_add(json_stat, "updatesSent", p->update_out); - json_object_int_add(json_stat, "updatesRecv", p->update_in); + atomic_load_explicit(&p->notify_in, + memory_order_relaxed)); + json_object_int_add(json_stat, "updatesSent", + atomic_load_explicit(&p->update_out, + memory_order_relaxed)); + json_object_int_add(json_stat, "updatesRecv", + atomic_load_explicit(&p->update_in, + memory_order_relaxed)); json_object_int_add(json_stat, "keepalivesSent", - p->keepalive_out); + atomic_load_explicit(&p->keepalive_out, + memory_order_relaxed)); json_object_int_add(json_stat, "keepalivesRecv", - p->keepalive_in); + atomic_load_explicit(&p->keepalive_in, + memory_order_relaxed)); json_object_int_add(json_stat, "routeRefreshSent", - p->refresh_out); + atomic_load_explicit(&p->refresh_out, + memory_order_relaxed)); json_object_int_add(json_stat, "routeRefreshRecv", - p->refresh_in); + atomic_load_explicit(&p->refresh_in, + memory_order_relaxed)); json_object_int_add(json_stat, "capabilitySent", - p->dynamic_cap_out); + atomic_load_explicit(&p->dynamic_cap_out, + memory_order_relaxed)); json_object_int_add(json_stat, "capabilityRecv", - p->dynamic_cap_in); - json_object_int_add(json_stat, "totalSent", - p->open_out + p->notify_out + p->update_out - + p->keepalive_out + p->refresh_out - + p->dynamic_cap_out); - json_object_int_add(json_stat, "totalRecv", - p->open_in + p->notify_in + p->update_in - + p->keepalive_in + p->refresh_in - + p->dynamic_cap_in); + atomic_load_explicit(&p->dynamic_cap_in, + memory_order_relaxed)); + json_object_int_add(json_stat, "totalSent", PEER_TOTAL_TX(p)); + json_object_int_add(json_stat, "totalRecv", PEER_TOTAL_RX(p)); json_object_object_add(json_neigh, "messageStats", json_stat); } else { /* Packet counts. */ @@ -9365,25 +9334,38 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, u_char use_json, vty_out(vty, " Outq depth is %lu\n", (unsigned long)p->obuf->count); vty_out(vty, " Sent Rcvd\n"); - vty_out(vty, " Opens: %10d %10d\n", p->open_out, - p->open_in); - vty_out(vty, " Notifications: %10d %10d\n", p->notify_out, - p->notify_in); - vty_out(vty, " Updates: %10d %10d\n", p->update_out, - p->update_in); - vty_out(vty, " Keepalives: %10d %10d\n", p->keepalive_out, - p->keepalive_in); - vty_out(vty, " Route Refresh: %10d %10d\n", p->refresh_out, - p->refresh_in); + vty_out(vty, " Opens: %10d %10d\n", + atomic_load_explicit(&p->open_out, + memory_order_relaxed), + atomic_load_explicit(&p->open_in, + memory_order_relaxed)); + vty_out(vty, " Notifications: %10d %10d\n", + atomic_load_explicit(&p->notify_out, + memory_order_relaxed), + atomic_load_explicit(&p->notify_in, + memory_order_relaxed)); + vty_out(vty, " Updates: %10d %10d\n", + atomic_load_explicit(&p->update_out, + memory_order_relaxed), + atomic_load_explicit(&p->update_in, + memory_order_relaxed)); + vty_out(vty, " Keepalives: %10d %10d\n", + atomic_load_explicit(&p->keepalive_out, + memory_order_relaxed), + atomic_load_explicit(&p->keepalive_in, + memory_order_relaxed)); + vty_out(vty, " Route Refresh: %10d %10d\n", + atomic_load_explicit(&p->refresh_out, + memory_order_relaxed), + atomic_load_explicit(&p->refresh_in, + memory_order_relaxed)); vty_out(vty, " Capability: %10d %10d\n", - p->dynamic_cap_out, p->dynamic_cap_in); - vty_out(vty, " Total: %10d %10d\n", - p->open_out + p->notify_out + p->update_out - + p->keepalive_out + p->refresh_out - + p->dynamic_cap_out, - p->open_in + p->notify_in + p->update_in - + p->keepalive_in + p->refresh_in - + p->dynamic_cap_in); + atomic_load_explicit(&p->dynamic_cap_out, + memory_order_relaxed), + atomic_load_explicit(&p->dynamic_cap_in, + memory_order_relaxed)); + vty_out(vty, " Total: %10d %10d\n", PEER_TOTAL_TX(p), + PEER_TOTAL_RX(p)); } if (use_json) { diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h index ce56587727..df46a6112a 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h @@ -829,6 +829,22 @@ struct peer { /* workqueues */ struct work_queue *clear_node_queue; +#define PEER_TOTAL_RX(peer) \ + atomic_load_explicit(&peer->open_in, memory_order_relaxed) + \ + atomic_load_explicit(&peer->update_in, memory_order_relaxed) + \ + atomic_load_explicit(&peer->notify_in, memory_order_relaxed) + \ + atomic_load_explicit(&peer->refresh_in, memory_order_relaxed) + \ + atomic_load_explicit(&peer->keepalive_in, memory_order_relaxed) + \ + atomic_load_explicit(&peer->dynamic_cap_in, memory_order_relaxed) + +#define PEER_TOTAL_TX(peer) \ + atomic_load_explicit(&peer->open_out, memory_order_relaxed) + \ + atomic_load_explicit(&peer->update_out, memory_order_relaxed) + \ + atomic_load_explicit(&peer->notify_out, memory_order_relaxed) + \ + atomic_load_explicit(&peer->refresh_out, memory_order_relaxed) + \ + atomic_load_explicit(&peer->keepalive_out, memory_order_relaxed) + \ + atomic_load_explicit(&peer->dynamic_cap_out, memory_order_relaxed) + /* Statistics field */ _Atomic uint32_t open_in; /* Open message input count */ _Atomic uint32_t open_out; /* Open message output count */ From 1de8dd93f1d3d48593ae70d2a09a5dd1463428cd Mon Sep 17 00:00:00 2001 From: Quentin Young Date: Tue, 9 Jan 2018 15:53:51 -0500 Subject: [PATCH 46/48] sharpd: add .gitignore Signed-off-by: Quentin Young --- sharpd/.gitignore | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 sharpd/.gitignore diff --git a/sharpd/.gitignore b/sharpd/.gitignore new file mode 100644 index 0000000000..c396f3ef94 --- /dev/null +++ b/sharpd/.gitignore @@ -0,0 +1,18 @@ +Makefile +Makefile.in +*.o +tags +TAGS +.deps +.nfs* +*.lo +*.la +*.a +*.libs +.arch-inventory +.arch-ids +*~ +*.loT +*clippy.c +sharpd +sharpd.conf From 95077abf60fb8fb5c656aa477e5d36a644f9bae5 Mon Sep 17 00:00:00 2001 From: Daniel Walton Date: Thu, 31 Aug 2017 16:58:38 +0000 Subject: [PATCH 47/48] bgpd: 'summary' to show NoNeg if peer did not negotiate afi/safi If we have configured neighbor 1.1.1.1 for an afi/safi but they have not activated that afi/safi with us then display "NoNeg" in the state column of the summary output. This is to make troubleshooting afi/safi easier. Signed-off-by: Daniel Walton --- bgpd/bgp_vty.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index 1be71d1e46..fd03f6ca7c 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -7119,8 +7119,11 @@ static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi, BGP_UPTIME_LEN, 0, NULL)); if (peer->status == Established) - vty_out(vty, " %12ld", - peer->pcount[afi][pfx_rcd_safi]); + if (peer->afc_recv[afi][pfx_rcd_safi]) + vty_out(vty, " %12ld", + peer->pcount[afi][pfx_rcd_safi]); + else + vty_out(vty, " NoNeg"); else { if (CHECK_FLAG(peer->flags, PEER_FLAG_SHUTDOWN)) vty_out(vty, " Idle (Admin)"); From 48c74f88259c8f706035d6fc80765f4a6f6594f7 Mon Sep 17 00:00:00 2001 From: Don Slice Date: Wed, 10 Jan 2018 19:40:45 +0000 Subject: [PATCH 48/48] bgpd: fix updating redist bitmask when vrf_id changes Problem reported that when "systemctl restart networking" was performed, prefixes previously redistributed into bgp from connected were deleted from the bgp table. Determined that we were not correctly changing the redistribution bitmask when the vrf_id of the vrf was changed. This patch corrects that behavior. Manual tests look good. bgp-min and vrf-min completed with no new failures. Ticket: CM-19369 Signed-off-by: Don Slice Reviewed-by: Donald Sharp --- bgpd/bgp_zebra.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index 1cf04abfce..b2db54ef79 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -1516,8 +1516,9 @@ void bgp_update_redist_vrf_bitmaps(struct bgp *bgp, vrf_id_t old_vrf_id) for (afi = AFI_IP; afi < AFI_MAX; afi++) for (i = 0; i < ZEBRA_ROUTE_MAX; i++) - if (vrf_bitmap_check(zclient->redist[afi][i], - old_vrf_id)) { + if ((old_vrf_id == VRF_UNKNOWN) + || vrf_bitmap_check(zclient->redist[afi][i], + old_vrf_id)) { vrf_bitmap_unset(zclient->redist[afi][i], old_vrf_id); vrf_bitmap_set(zclient->redist[afi][i],