mirror of
				https://git.proxmox.com/git/mirror_frr
				synced 2025-11-03 23:47:16 +00:00 
			
		
		
		
	==361630== 24,780 (96 direct, 24,684 indirect) bytes in 3 blocks are definitely lost in loss record 94 of 97 ==361630== at 0x483DD99: calloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so) ==361630== by 0x492EB8E: qcalloc (in /usr/local/lib/libfrr.so.0.0.0) ==361630== by 0x490BB12: hash_get (in /usr/local/lib/libfrr.so.0.0.0) ==361630== by 0x1FD3CC: bgp_ca_alias_insert (in /usr/lib/frr/bgpd) ==361630== by 0x2CF8E5: bgp_community_alias_magic (in /usr/lib/frr/bgpd) ==361630== by 0x2C980B: bgp_community_alias (in /usr/lib/frr/bgpd) ==361630== by 0x48E3556: cmd_execute_command_real (in /usr/local/lib/libfrr.so.0.0.0) ==361630== by 0x48E384B: cmd_execute_command_strict (in /usr/local/lib/libfrr.so.0.0.0) ==361630== by 0x48E3D41: command_config_read_one_line (in /usr/local/lib/libfrr.so.0.0.0) ==361630== by 0x48E3EBA: config_from_file (in /usr/local/lib/libfrr.so.0.0.0) ==361630== by 0x499065C: vty_read_file (in /usr/local/lib/libfrr.so.0.0.0) ==361630== by 0x4990FF4: vty_read_config (in /usr/local/lib/libfrr.so.0.0.0) ==361630== by 0x491CB95: frr_config_read_in (in /usr/local/lib/libfrr.so.0.0.0) ==361630== by 0x4985380: thread_call (in /usr/local/lib/libfrr.so.0.0.0) ==361630== by 0x491D521: frr_run (in /usr/local/lib/libfrr.so.0.0.0) ==361630== by 0x1EBEE8: main (in /usr/lib/frr/bgpd) ==361630== ==361630== 24,780 (96 direct, 24,684 indirect) bytes in 3 blocks are definitely lost in loss record 95 of 97 ==361630== at 0x483DD99: calloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so) ==361630== by 0x492EB8E: qcalloc (in /usr/local/lib/libfrr.so.0.0.0) ==361630== by 0x490BB12: hash_get (in /usr/local/lib/libfrr.so.0.0.0) ==361630== by 0x1FD39C: bgp_ca_community_insert (in /usr/lib/frr/bgpd) ==361630== by 0x2CF8F4: bgp_community_alias_magic (in /usr/lib/frr/bgpd) ==361630== by 0x2C980B: bgp_community_alias (in /usr/lib/frr/bgpd) ==361630== by 0x48E3556: cmd_execute_command_real (in /usr/local/lib/libfrr.so.0.0.0) ==361630== by 0x48E384B: cmd_execute_command_strict (in /usr/local/lib/libfrr.so.0.0.0) ==361630== by 0x48E3D41: command_config_read_one_line (in /usr/local/lib/libfrr.so.0.0.0) ==361630== by 0x48E3EBA: config_from_file (in /usr/local/lib/libfrr.so.0.0.0) ==361630== by 0x499065C: vty_read_file (in /usr/local/lib/libfrr.so.0.0.0) ==361630== by 0x4990FF4: vty_read_config (in /usr/local/lib/libfrr.so.0.0.0) ==361630== by 0x491CB95: frr_config_read_in (in /usr/local/lib/libfrr.so.0.0.0) ==361630== by 0x4985380: thread_call (in /usr/local/lib/libfrr.so.0.0.0) ==361630== by 0x491D521: frr_run (in /usr/local/lib/libfrr.so.0.0.0) ==361630== by 0x1EBEE8: main (in /usr/lib/frr/bgpd) Signed-off-by: Donatas Abraitis <donatas@opensourcerouting.org>
		
			
				
	
	
		
			233 lines
		
	
	
		
			5.8 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			233 lines
		
	
	
		
			5.8 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/* BGP community, large-community aliasing.
 | 
						|
 *
 | 
						|
 * Copyright (C) 2021 Donatas Abraitis <donatas.abraitis@gmail.com>
 | 
						|
 *
 | 
						|
 * This file is part of FRRouting (FRR).
 | 
						|
 *
 | 
						|
 * FRR 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, or (at your option) any later version.
 | 
						|
 *
 | 
						|
 * FRR is distributed in the hope that it will be useful, but WITHOUT ANY
 | 
						|
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 | 
						|
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
 | 
						|
 * details.
 | 
						|
 *
 | 
						|
 * You should have received a copy of the GNU General Public License along
 | 
						|
 * with this program; see the file COPYING; if not, write to the Free Software
 | 
						|
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
 | 
						|
 */
 | 
						|
 | 
						|
#include "zebra.h"
 | 
						|
 | 
						|
#include "memory.h"
 | 
						|
#include "lib/jhash.h"
 | 
						|
#include "frrstr.h"
 | 
						|
 | 
						|
#include "bgpd/bgpd.h"
 | 
						|
#include "bgpd/bgp_community_alias.h"
 | 
						|
 | 
						|
static struct hash *bgp_ca_alias_hash;
 | 
						|
static struct hash *bgp_ca_community_hash;
 | 
						|
 | 
						|
static unsigned int bgp_ca_community_hash_key(const void *p)
 | 
						|
{
 | 
						|
	const struct community_alias *ca = p;
 | 
						|
 | 
						|
	return jhash(ca->community, sizeof(ca->community), 0);
 | 
						|
}
 | 
						|
 | 
						|
static bool bgp_ca_community_hash_cmp(const void *p1, const void *p2)
 | 
						|
{
 | 
						|
	const struct community_alias *ca1 = p1;
 | 
						|
	const struct community_alias *ca2 = p2;
 | 
						|
 | 
						|
	return (strcmp(ca1->community, ca2->community) == 0);
 | 
						|
}
 | 
						|
 | 
						|
static unsigned int bgp_ca_alias_hash_key(const void *p)
 | 
						|
{
 | 
						|
	const struct community_alias *ca = p;
 | 
						|
 | 
						|
	return jhash(ca->alias, sizeof(ca->alias), 0);
 | 
						|
}
 | 
						|
 | 
						|
static bool bgp_ca_alias_hash_cmp(const void *p1, const void *p2)
 | 
						|
{
 | 
						|
	const struct community_alias *ca1 = p1;
 | 
						|
	const struct community_alias *ca2 = p2;
 | 
						|
 | 
						|
	return (strcmp(ca1->alias, ca2->alias) == 0);
 | 
						|
}
 | 
						|
 | 
						|
static void *bgp_community_alias_alloc(void *p)
 | 
						|
{
 | 
						|
	const struct community_alias *ca = p;
 | 
						|
	struct communtiy_alias *new;
 | 
						|
 | 
						|
	new = XCALLOC(MTYPE_COMMUNITY_ALIAS, sizeof(struct community_alias));
 | 
						|
	memcpy(new, ca, sizeof(struct community_alias));
 | 
						|
 | 
						|
	return new;
 | 
						|
}
 | 
						|
 | 
						|
void bgp_community_alias_init(void)
 | 
						|
{
 | 
						|
	bgp_ca_community_hash = hash_create(bgp_ca_community_hash_key,
 | 
						|
					       bgp_ca_community_hash_cmp,
 | 
						|
					       "BGP community alias (community)");
 | 
						|
	bgp_ca_alias_hash =
 | 
						|
		hash_create(bgp_ca_alias_hash_key, bgp_ca_alias_hash_cmp,
 | 
						|
			    "BGP community alias (alias)");
 | 
						|
}
 | 
						|
 | 
						|
static void bgp_ca_free(void *ca)
 | 
						|
{
 | 
						|
	XFREE(MTYPE_COMMUNITY_ALIAS, ca);
 | 
						|
}
 | 
						|
 | 
						|
void bgp_community_alias_finish(void)
 | 
						|
{
 | 
						|
	hash_clean(bgp_ca_community_hash, bgp_ca_free);
 | 
						|
	hash_free(bgp_ca_community_hash);
 | 
						|
	hash_clean(bgp_ca_alias_hash, bgp_ca_free);
 | 
						|
	hash_free(bgp_ca_alias_hash);
 | 
						|
}
 | 
						|
 | 
						|
static void bgp_community_alias_show_iterator(struct hash_bucket *hb,
 | 
						|
					      struct vty *vty)
 | 
						|
{
 | 
						|
	struct community_alias *ca = hb->data;
 | 
						|
 | 
						|
	vty_out(vty, "bgp community alias %s %s\n", ca->community, ca->alias);
 | 
						|
}
 | 
						|
 | 
						|
int bgp_community_alias_write(struct vty *vty)
 | 
						|
{
 | 
						|
	hash_iterate(bgp_ca_community_hash,
 | 
						|
		     (void (*)(struct hash_bucket *,
 | 
						|
			       void *))bgp_community_alias_show_iterator,
 | 
						|
		     vty);
 | 
						|
	return 1;
 | 
						|
}
 | 
						|
 | 
						|
void bgp_ca_community_insert(struct community_alias *ca)
 | 
						|
{
 | 
						|
	(void)hash_get(bgp_ca_community_hash, ca, bgp_community_alias_alloc);
 | 
						|
}
 | 
						|
 | 
						|
void bgp_ca_alias_insert(struct community_alias *ca)
 | 
						|
{
 | 
						|
	(void)hash_get(bgp_ca_alias_hash, ca, bgp_community_alias_alloc);
 | 
						|
}
 | 
						|
 | 
						|
void bgp_ca_community_delete(struct community_alias *ca)
 | 
						|
{
 | 
						|
	struct community_alias *data = hash_release(bgp_ca_community_hash, ca);
 | 
						|
 | 
						|
	XFREE(MTYPE_COMMUNITY_ALIAS, data);
 | 
						|
}
 | 
						|
 | 
						|
void bgp_ca_alias_delete(struct community_alias *ca)
 | 
						|
{
 | 
						|
	struct community_alias *data = hash_release(bgp_ca_alias_hash, ca);
 | 
						|
 | 
						|
	XFREE(MTYPE_COMMUNITY_ALIAS, data);
 | 
						|
}
 | 
						|
 | 
						|
struct community_alias *bgp_ca_community_lookup(struct community_alias *ca)
 | 
						|
{
 | 
						|
	return hash_lookup(bgp_ca_community_hash, ca);
 | 
						|
}
 | 
						|
 | 
						|
struct community_alias *bgp_ca_alias_lookup(struct community_alias *ca)
 | 
						|
{
 | 
						|
	return hash_lookup(bgp_ca_alias_hash, ca);
 | 
						|
}
 | 
						|
 | 
						|
const char *bgp_community2alias(char *community)
 | 
						|
{
 | 
						|
	struct community_alias ca;
 | 
						|
	struct community_alias *find;
 | 
						|
 | 
						|
	memset(&ca, 0, sizeof(ca));
 | 
						|
	strlcpy(ca.community, community, sizeof(ca.community));
 | 
						|
 | 
						|
	find = bgp_ca_community_lookup(&ca);
 | 
						|
	if (find)
 | 
						|
		return find->alias;
 | 
						|
 | 
						|
	return community;
 | 
						|
}
 | 
						|
 | 
						|
const char *bgp_alias2community(char *alias)
 | 
						|
{
 | 
						|
	struct community_alias ca;
 | 
						|
	struct community_alias *find;
 | 
						|
 | 
						|
	memset(&ca, 0, sizeof(ca));
 | 
						|
	strlcpy(ca.alias, alias, sizeof(ca.alias));
 | 
						|
 | 
						|
	find = bgp_ca_alias_lookup(&ca);
 | 
						|
	if (find)
 | 
						|
		return find->community;
 | 
						|
 | 
						|
	return alias;
 | 
						|
}
 | 
						|
 | 
						|
/* Communities structs have `->str` which is used
 | 
						|
 * for vty outputs and extended BGP community lists
 | 
						|
 * with regexp.
 | 
						|
 * This is a helper to convert already aliased version
 | 
						|
 * of communities into numerical-only format.
 | 
						|
 */
 | 
						|
char *bgp_alias2community_str(const char *str)
 | 
						|
{
 | 
						|
	char **aliases;
 | 
						|
	char *comstr;
 | 
						|
	int num, i;
 | 
						|
 | 
						|
	frrstr_split(str, " ", &aliases, &num);
 | 
						|
	const char *communities[num];
 | 
						|
 | 
						|
	for (i = 0; i < num; i++)
 | 
						|
		communities[i] = bgp_alias2community(aliases[i]);
 | 
						|
 | 
						|
	comstr = frrstr_join(communities, num, " ");
 | 
						|
 | 
						|
	for (i = 0; i < num; i++)
 | 
						|
		XFREE(MTYPE_TMP, aliases[i]);
 | 
						|
	XFREE(MTYPE_TMP, aliases);
 | 
						|
 | 
						|
	return comstr;
 | 
						|
}
 | 
						|
 | 
						|
static int bgp_community_alias_vector_walker(struct hash_bucket *bucket,
 | 
						|
					     void *data)
 | 
						|
{
 | 
						|
	vector *comps = data;
 | 
						|
	struct community_alias *alias = bucket->data;
 | 
						|
 | 
						|
	vector_set(*comps, XSTRDUP(MTYPE_COMPLETION, alias->alias));
 | 
						|
 | 
						|
	return 1;
 | 
						|
}
 | 
						|
 | 
						|
static void bgp_community_alias_cmd_completion(vector comps,
 | 
						|
					       struct cmd_token *token)
 | 
						|
{
 | 
						|
	hash_walk(bgp_ca_alias_hash, bgp_community_alias_vector_walker, &comps);
 | 
						|
}
 | 
						|
 | 
						|
static const struct cmd_variable_handler community_alias_handlers[] = {
 | 
						|
	{.varname = "alias_name",
 | 
						|
	 .completions = bgp_community_alias_cmd_completion},
 | 
						|
	{.tokenname = "ALIAS_NAME",
 | 
						|
	 .completions = bgp_community_alias_cmd_completion},
 | 
						|
	{.completions = NULL}};
 | 
						|
 | 
						|
void bgp_community_alias_command_completion_setup(void)
 | 
						|
{
 | 
						|
	cmd_variable_handler_register(community_alias_handlers);
 | 
						|
}
 |