summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bgpd/bgp_route.c17
-rw-r--r--bgpd/bgp_routemap.c36
-rw-r--r--doc/developer/workflow.rst23
-rw-r--r--lib/command.c10
-rw-r--r--lib/command.h11
-rw-r--r--lib/libfrr.c2
-rw-r--r--lib/northbound.c2
-rw-r--r--lib/zclient.c7
-rw-r--r--lib/zclient.h2
-rw-r--r--pimd/pim_cmd.c52
-rw-r--r--pimd/pim_igmp.c2
-rw-r--r--pimd/pim_igmp.h1
-rw-r--r--vtysh/vtysh.c2
-rw-r--r--vtysh/vtysh_config.c4
-rw-r--r--zebra/zapi_msg.c4
-rw-r--r--zebra/zebra_rnh.c2
-rw-r--r--zebra/zserv.c6
17 files changed, 155 insertions, 28 deletions
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index edaab88286..543df2b048 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -1236,10 +1236,12 @@ static int bgp_cluster_filter(struct peer *peer, struct attr *attr)
static int bgp_input_modifier(struct peer *peer, struct prefix *p,
struct attr *attr, afi_t afi, safi_t safi,
- const char *rmap_name)
+ const char *rmap_name, mpls_label_t *label,
+ uint32_t num_labels)
{
struct bgp_filter *filter;
- struct bgp_path_info rmap_path;
+ struct bgp_path_info rmap_path = { 0 };
+ struct bgp_path_info_extra extra = { 0 };
route_map_result_t ret;
struct route_map *rmap = NULL;
@@ -1269,6 +1271,11 @@ static int bgp_input_modifier(struct peer *peer, struct prefix *p,
/* Duplicate current value to new strucutre for modification. */
rmap_path.peer = peer;
rmap_path.attr = attr;
+ rmap_path.extra = &extra;
+ extra.num_labels = num_labels;
+ if (label && num_labels && num_labels <= BGP_MAX_LABELS)
+ memcpy(extra.label, label,
+ num_labels * sizeof(mpls_label_t));
SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN);
@@ -3124,8 +3131,8 @@ int bgp_update(struct peer *peer, struct prefix *p, uint32_t addpath_id,
* commands, so we need bgp_attr_flush in the error paths, until we
* intern
* the attr (which takes over the memory references) */
- if (bgp_input_modifier(peer, p, &new_attr, afi, safi, NULL)
- == RMAP_DENY) {
+ if (bgp_input_modifier(peer, p, &new_attr, afi, safi, NULL,
+ label, num_labels) == RMAP_DENY) {
reason = "route-map;";
bgp_attr_flush(&new_attr);
goto filtered;
@@ -11191,7 +11198,7 @@ static void show_adj_route(struct vty *vty, struct peer *peer, afi_t afi,
/* Filter prefix using route-map */
ret = bgp_input_modifier(peer, &rn->p, &attr,
- afi, safi, rmap_name);
+ afi, safi, rmap_name, NULL, 0);
if (type == bgp_show_adj_route_filtered &&
!route_filtered && ret != RMAP_DENY) {
diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c
index 329db187fe..8c3a024295 100644
--- a/bgpd/bgp_routemap.c
+++ b/bgpd/bgp_routemap.c
@@ -60,6 +60,7 @@
#include "bgpd/bgp_evpn_private.h"
#include "bgpd/bgp_evpn_vty.h"
#include "bgpd/bgp_mplsvpn.h"
+#include "bgpd/bgp_encap_types.h"
#if ENABLE_BGP_VNC
#include "bgpd/rfapi/bgp_rfapi_cfg.h"
@@ -795,26 +796,49 @@ struct route_map_rule_cmd route_match_mac_address_cmd = {
"mac address", route_match_mac_address, route_match_mac_address_compile,
route_match_mac_address_free};
-/* `match vni' */
-
-/* Match function should return 1 if match is success else return
- zero. */
+/*
+ * Match function returns:
+ * ...RMAP_MATCH if match is found.
+ * ...RMAP_NOMATCH if match is not found.
+ * ...RMAP_NOOP to ignore this match check.
+ */
static enum route_map_match_result_t
route_match_vni(void *rule, const struct prefix *prefix,
route_map_object_t type, void *object)
{
vni_t vni = 0;
+ unsigned int label_cnt = 0;
struct bgp_path_info *path = NULL;
+ struct prefix_evpn *evp = (struct prefix_evpn *) prefix;
if (type == RMAP_BGP) {
vni = *((vni_t *)rule);
path = (struct bgp_path_info *)object;
+ /*
+ * This rmap filter is valid for vxlan tunnel type only.
+ * For any other tunnel type, return noop to ignore
+ * this check.
+ */
+ if (path->attr && path->attr->encap_tunneltype !=
+ BGP_ENCAP_TYPE_VXLAN)
+ return RMAP_NOOP;
+
+ /*
+ * We do not want to filter type 3 routes because
+ * they do not have vni associated with them.
+ */
+ if (evp && evp->prefix.route_type == BGP_EVPN_IMET_ROUTE)
+ return RMAP_NOOP;
+
if (path->extra == NULL)
return RMAP_NOMATCH;
- if (vni == label2vni(&path->extra->label[0]))
- return RMAP_MATCH;
+ for ( ; label_cnt < BGP_MAX_LABELS &&
+ label_cnt < path->extra->num_labels; label_cnt++) {
+ if (vni == label2vni(&path->extra->label[label_cnt]))
+ return RMAP_MATCH;
+ }
}
return RMAP_NOMATCH;
diff --git a/doc/developer/workflow.rst b/doc/developer/workflow.rst
index b3b3a47cb0..16707c0bdd 100644
--- a/doc/developer/workflow.rst
+++ b/doc/developer/workflow.rst
@@ -750,7 +750,8 @@ developer will use this convention to allow control of their debugs.
Static Analysis and Sanitizers
------------------------------
-Clang/LLVM comes with a variety of tools that can be used to help find bugs in FRR.
+Clang/LLVM and GCC come with a variety of tools that can be used to help find
+bugs in FRR.
clang-analyze
This is a static analyzer that scans the source code looking for patterns
@@ -794,11 +795,31 @@ All of the above tools are available in the Clang/LLVM toolchain since 3.4.
AddressSanitizer and ThreadSanitizer are available in recent versions of GCC,
but are no longer actively maintained. MemorySanitizer is not available in GCC.
+.. note::
+
+ The different Sanitizers are mostly incompatible with each other. Please
+ refer to GCC/LLVM documentation for details.
+
Additionally, the FRR codebase is regularly scanned with Coverity.
Unfortunately Coverity does not have the ability to handle scanning pull
requests, but after code is merged it will send an email notifying project
members with Coverity access of newly introduced defects.
+Executing non-installed dynamic binaries
+----------------------------------------
+
+Since FRR uses the GNU autotools build system, it inherits its shortcomings.
+To execute a binary directly from the build tree under a wrapper like
+`valgrind`, `gdb` or `strace`, use::
+
+ ./libtool --mode=execute valgrind [--valgrind-opts] zebra/zebra [--zebra-opts]
+
+While replacing valgrind/zebra as needed. The `libtool` script is found in
+the root of the build directory after `./configure` has completed. Its purpose
+is to correctly set up `LD_LIBRARY_PATH` so that libraries from the build tree
+are used. (On some systems, `libtool` is also available from PATH, but this is
+not always the case.)
+
CLI changes
-----------
diff --git a/lib/command.c b/lib/command.c
index 5335969fbc..e5e0623163 100644
--- a/lib/command.c
+++ b/lib/command.c
@@ -1962,7 +1962,15 @@ DEFUN (config_hostname,
struct cmd_token *word = argv[1];
if (!isalnum((int)word->arg[0])) {
- vty_out(vty, "Please specify string starting with alphabet\n");
+ vty_out(vty,
+ "Please specify string starting with alphabet or number\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ /* With reference to RFC 1123 Section 2.1 */
+ if (strlen(word->arg) > HOSTNAME_LEN) {
+ vty_out(vty, "Hostname length should be less than %d chars\n",
+ HOSTNAME_LEN);
return CMD_WARNING_CONFIG_FAILED;
}
diff --git a/lib/command.h b/lib/command.h
index d96ec97e67..d6c41e0824 100644
--- a/lib/command.h
+++ b/lib/command.h
@@ -37,6 +37,17 @@ extern "C" {
DECLARE_MTYPE(HOST)
DECLARE_MTYPE(COMPLETION)
+/*
+ * From RFC 1123 (Requirements for Internet Hosts), Section 2.1 on hostnames:
+ * One aspect of host name syntax is hereby changed: the restriction on
+ * the first character is relaxed to allow either a letter or a digit.
+ * Host software MUST support this more liberal syntax.
+ *
+ * Host software MUST handle host names of up to 63 characters and
+ * SHOULD handle host names of up to 255 characters.
+ */
+#define HOSTNAME_LEN 255
+
/* Host configuration variable */
struct host {
/* Host name of this router. */
diff --git a/lib/libfrr.c b/lib/libfrr.c
index 15de96feee..c60e26085f 100644
--- a/lib/libfrr.c
+++ b/lib/libfrr.c
@@ -61,7 +61,7 @@ static char pidfile_default[512];
#ifdef HAVE_SQLITE3
static char dbfile_default[512];
#endif
-static char vtypath_default[256];
+static char vtypath_default[512];
bool debug_memstats_at_exit = false;
static bool nodetach_term, nodetach_daemon;
diff --git a/lib/northbound.c b/lib/northbound.c
index dbf90c58d4..8a5cd0ef14 100644
--- a/lib/northbound.c
+++ b/lib/northbound.c
@@ -777,7 +777,7 @@ static void nb_log_callback(const enum nb_event event,
zlog_debug(
"northbound callback: event [%s] op [%s] xpath [%s] value [%s]",
nb_event_name(event), nb_operation_name(operation), xpath,
- value);
+ value ? value : "(NULL)");
}
/*
diff --git a/lib/zclient.c b/lib/zclient.c
index 0972590ca6..e9b4f5a58b 100644
--- a/lib/zclient.c
+++ b/lib/zclient.c
@@ -62,10 +62,13 @@ struct zclient *zclient_new(struct thread_master *master,
struct zclient_options *opt)
{
struct zclient *zclient;
+ size_t stream_size =
+ MAX(ZEBRA_MAX_PACKET_SIZ, sizeof(struct zapi_route));
+
zclient = XCALLOC(MTYPE_ZCLIENT, sizeof(struct zclient));
- zclient->ibuf = stream_new(ZEBRA_MAX_PACKET_SIZ);
- zclient->obuf = stream_new(ZEBRA_MAX_PACKET_SIZ);
+ zclient->ibuf = stream_new(stream_size);
+ zclient->obuf = stream_new(stream_size);
zclient->wb = buffer_new(0);
zclient->master = master;
diff --git a/lib/zclient.h b/lib/zclient.h
index 09f0acad84..c61c8d4226 100644
--- a/lib/zclient.h
+++ b/lib/zclient.h
@@ -39,7 +39,7 @@
#include "mlag.h"
/* For input/output buffer to zebra. */
-#define ZEBRA_MAX_PACKET_SIZ 16384
+#define ZEBRA_MAX_PACKET_SIZ 16384U
/* Zebra header size. */
#define ZEBRA_HEADER_SIZE 10
diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c
index 8cbacf53ad..2b97dd3822 100644
--- a/pimd/pim_cmd.c
+++ b/pimd/pim_cmd.c
@@ -3848,6 +3848,55 @@ static void mroute_del_all(struct pim_instance *pim)
}
}
+static void clear_mroute(struct pim_instance *pim)
+{
+ struct pim_upstream *up;
+ struct interface *ifp;
+
+ /* scan interfaces */
+ FOR_ALL_INTERFACES (pim->vrf, ifp) {
+ struct pim_interface *pim_ifp = ifp->info;
+ struct listnode *sock_node;
+ struct igmp_sock *igmp;
+ struct pim_ifchannel *ch;
+
+ if (!pim_ifp)
+ continue;
+
+ /* deleting all ifchannels */
+ while (!RB_EMPTY(pim_ifchannel_rb, &pim_ifp->ifchannel_rb)) {
+ ch = RB_ROOT(pim_ifchannel_rb, &pim_ifp->ifchannel_rb);
+
+ pim_ifchannel_delete(ch);
+ }
+
+ /* clean up all igmp groups */
+ /* scan igmp sockets */
+ for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node,
+ igmp)) {
+
+ struct igmp_group *grp;
+
+ if (igmp->igmp_group_list) {
+ while (igmp->igmp_group_list->count) {
+ grp = listnode_head(
+ igmp->igmp_group_list);
+ igmp_group_delete(grp);
+ }
+ }
+
+ }
+ }
+
+ /* clean up all upstreams*/
+ if (pim->upstream_list) {
+ while (pim->upstream_list->count) {
+ up = listnode_head(pim->upstream_list);
+ pim_upstream_del(pim, up, __PRETTY_FUNCTION__);
+ }
+ }
+}
+
DEFUN (clear_ip_mroute,
clear_ip_mroute_cmd,
"clear ip mroute [vrf NAME]",
@@ -3862,8 +3911,7 @@ DEFUN (clear_ip_mroute,
if (!vrf)
return CMD_WARNING;
- mroute_del_all(vrf->info);
- mroute_add_all(vrf->info);
+ clear_mroute(vrf->info);
return CMD_SUCCESS;
}
diff --git a/pimd/pim_igmp.c b/pimd/pim_igmp.c
index 213ca48bb5..4ae6f69d3e 100644
--- a/pimd/pim_igmp.c
+++ b/pimd/pim_igmp.c
@@ -741,7 +741,7 @@ static void igmp_group_free(struct igmp_group *group)
XFREE(MTYPE_PIM_IGMP_GROUP, group);
}
-static void igmp_group_delete(struct igmp_group *group)
+void igmp_group_delete(struct igmp_group *group)
{
struct listnode *src_node;
struct listnode *src_nextnode;
diff --git a/pimd/pim_igmp.h b/pimd/pim_igmp.h
index c8b880ddd7..7db568dcfe 100644
--- a/pimd/pim_igmp.h
+++ b/pimd/pim_igmp.h
@@ -197,4 +197,5 @@ void igmp_send_query(int igmp_version, struct igmp_group *group, int fd,
int query_max_response_time_dsec, uint8_t s_flag,
uint8_t querier_robustness_variable,
uint16_t querier_query_interval);
+void igmp_group_delete(struct igmp_group *group);
#endif /* PIM_IGMP_H */
diff --git a/vtysh/vtysh.c b/vtysh/vtysh.c
index 1ab70eeed2..baf77d1cb7 100644
--- a/vtysh/vtysh.c
+++ b/vtysh/vtysh.c
@@ -3438,7 +3438,7 @@ void vtysh_readline_init(void)
char *vtysh_prompt(void)
{
- static char buf[100];
+ static char buf[512];
snprintf(buf, sizeof buf, cmd_prompt(vty->node), cmd_hostname_get());
return buf;
diff --git a/vtysh/vtysh_config.c b/vtysh/vtysh_config.c
index cf94ab643a..9c2de0f62b 100644
--- a/vtysh/vtysh_config.c
+++ b/vtysh/vtysh_config.c
@@ -521,10 +521,10 @@ int vtysh_read_config(const char *config_default_dir)
*/
void vtysh_config_write(void)
{
- char line[81];
+ char line[512];
if (cmd_hostname_get()) {
- sprintf(line, "hostname %s", cmd_hostname_get());
+ snprintf(line, sizeof(line), "hostname %s", cmd_hostname_get());
vtysh_config_parse_line(NULL, line);
}
diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c
index 94bfa34b38..49e43f4942 100644
--- a/zebra/zapi_msg.c
+++ b/zebra/zapi_msg.c
@@ -524,6 +524,8 @@ int zsend_redistribute_route(int cmd, struct zserv *client,
struct nexthop *nexthop;
int count = 0;
afi_t afi;
+ size_t stream_size =
+ MAX(ZEBRA_MAX_PACKET_SIZ, sizeof(struct zapi_route));
memset(&api, 0, sizeof(api));
api.vrf_id = re->vrf_id;
@@ -605,7 +607,7 @@ int zsend_redistribute_route(int cmd, struct zserv *client,
SET_FLAG(api.message, ZAPI_MESSAGE_MTU);
api.mtu = re->mtu;
- struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ);
+ struct stream *s = stream_new(stream_size);
/* Encode route and send. */
if (zapi_route_encode(cmd, s, &api) < 0) {
diff --git a/zebra/zebra_rnh.c b/zebra/zebra_rnh.c
index 1ccc3bc36b..a8389f2adf 100644
--- a/zebra/zebra_rnh.c
+++ b/zebra/zebra_rnh.c
@@ -1132,7 +1132,7 @@ static int send_client(struct rnh *rnh, struct zserv *client, rnh_type_t type,
static void print_nh(struct nexthop *nexthop, struct vty *vty)
{
char buf[BUFSIZ];
- struct zebra_ns *zns = zebra_ns_lookup(NS_DEFAULT);
+ struct zebra_ns *zns = zebra_ns_lookup(nexthop->vrf_id);
switch (nexthop->type) {
case NEXTHOP_TYPE_IPV4:
diff --git a/zebra/zserv.c b/zebra/zserv.c
index fbb5af875d..49fb302ba8 100644
--- a/zebra/zserv.c
+++ b/zebra/zserv.c
@@ -682,6 +682,8 @@ static int zserv_handle_client_fail(struct thread *thread)
static struct zserv *zserv_client_create(int sock)
{
struct zserv *client;
+ size_t stream_size =
+ MAX(ZEBRA_MAX_PACKET_SIZ, sizeof(struct zapi_route));
int i;
afi_t afi;
@@ -691,8 +693,8 @@ static struct zserv *zserv_client_create(int sock)
client->sock = sock;
client->ibuf_fifo = stream_fifo_new();
client->obuf_fifo = stream_fifo_new();
- client->ibuf_work = stream_new(ZEBRA_MAX_PACKET_SIZ);
- client->obuf_work = stream_new(ZEBRA_MAX_PACKET_SIZ);
+ client->ibuf_work = stream_new(stream_size);
+ client->obuf_work = stream_new(stream_size);
pthread_mutex_init(&client->ibuf_mtx, NULL);
pthread_mutex_init(&client->obuf_mtx, NULL);
client->wb = buffer_new(0);