Coverage Report

Created: 2025-10-08 06:07

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/frr/bgpd/bgp_community_alias.c
Line
Count
Source
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
/* BGP community, large-community aliasing.
3
 *
4
 * Copyright (C) 2021 Donatas Abraitis <donatas.abraitis@gmail.com>
5
 */
6
7
#include "zebra.h"
8
9
#include "memory.h"
10
#include "lib/jhash.h"
11
#include "frrstr.h"
12
13
#include "bgpd/bgpd.h"
14
#include "bgpd/bgp_community_alias.h"
15
16
static struct hash *bgp_ca_alias_hash;
17
static struct hash *bgp_ca_community_hash;
18
19
static unsigned int bgp_ca_community_hash_key(const void *p)
20
0
{
21
0
  const struct community_alias *ca = p;
22
23
0
  return jhash(ca->community, sizeof(ca->community), 0);
24
0
}
25
26
static bool bgp_ca_community_hash_cmp(const void *p1, const void *p2)
27
0
{
28
0
  const struct community_alias *ca1 = p1;
29
0
  const struct community_alias *ca2 = p2;
30
31
0
  return (strcmp(ca1->community, ca2->community) == 0);
32
0
}
33
34
static unsigned int bgp_ca_alias_hash_key(const void *p)
35
0
{
36
0
  const struct community_alias *ca = p;
37
38
0
  return jhash(ca->alias, sizeof(ca->alias), 0);
39
0
}
40
41
static bool bgp_ca_alias_hash_cmp(const void *p1, const void *p2)
42
0
{
43
0
  const struct community_alias *ca1 = p1;
44
0
  const struct community_alias *ca2 = p2;
45
46
0
  return (strcmp(ca1->alias, ca2->alias) == 0);
47
0
}
48
49
static void *bgp_community_alias_alloc(void *p)
50
0
{
51
0
  const struct community_alias *ca = p;
52
0
  struct communtiy_alias *new;
53
54
0
  new = XCALLOC(MTYPE_COMMUNITY_ALIAS, sizeof(struct community_alias));
55
0
  memcpy(new, ca, sizeof(struct community_alias));
56
57
0
  return new;
58
0
}
59
60
void bgp_community_alias_init(void)
61
1
{
62
1
  bgp_ca_community_hash = hash_create(bgp_ca_community_hash_key,
63
1
                 bgp_ca_community_hash_cmp,
64
1
                 "BGP community alias (community)");
65
1
  bgp_ca_alias_hash =
66
1
    hash_create(bgp_ca_alias_hash_key, bgp_ca_alias_hash_cmp,
67
1
          "BGP community alias (alias)");
68
1
}
69
70
static void bgp_ca_free(void *ca)
71
0
{
72
0
  XFREE(MTYPE_COMMUNITY_ALIAS, ca);
73
0
}
74
75
void bgp_community_alias_finish(void)
76
0
{
77
0
  hash_clean_and_free(&bgp_ca_community_hash, bgp_ca_free);
78
0
  hash_clean_and_free(&bgp_ca_alias_hash, bgp_ca_free);
79
0
}
80
81
static void bgp_community_alias_show_iterator(struct hash_bucket *hb,
82
                struct vty *vty)
83
0
{
84
0
  struct community_alias *ca = hb->data;
85
86
0
  vty_out(vty, "bgp community alias %s %s\n", ca->community, ca->alias);
87
0
}
88
89
int bgp_community_alias_write(struct vty *vty)
90
0
{
91
0
  hash_iterate(bgp_ca_community_hash,
92
0
         (void (*)(struct hash_bucket *,
93
0
             void *))bgp_community_alias_show_iterator,
94
0
         vty);
95
0
  return 1;
96
0
}
97
98
void bgp_ca_community_insert(struct community_alias *ca)
99
0
{
100
0
  (void)hash_get(bgp_ca_community_hash, ca, bgp_community_alias_alloc);
101
0
}
102
103
void bgp_ca_alias_insert(struct community_alias *ca)
104
0
{
105
0
  (void)hash_get(bgp_ca_alias_hash, ca, bgp_community_alias_alloc);
106
0
}
107
108
void bgp_ca_community_delete(struct community_alias *ca)
109
0
{
110
0
  struct community_alias *data = hash_release(bgp_ca_community_hash, ca);
111
112
0
  XFREE(MTYPE_COMMUNITY_ALIAS, data);
113
0
}
114
115
void bgp_ca_alias_delete(struct community_alias *ca)
116
0
{
117
0
  struct community_alias *data = hash_release(bgp_ca_alias_hash, ca);
118
119
0
  XFREE(MTYPE_COMMUNITY_ALIAS, data);
120
0
}
121
122
struct community_alias *bgp_ca_community_lookup(struct community_alias *ca)
123
1.42k
{
124
1.42k
  return hash_lookup(bgp_ca_community_hash, ca);
125
1.42k
}
126
127
struct community_alias *bgp_ca_alias_lookup(struct community_alias *ca)
128
0
{
129
0
  return hash_lookup(bgp_ca_alias_hash, ca);
130
0
}
131
132
const char *bgp_community2alias(char *community)
133
1.42k
{
134
1.42k
  struct community_alias ca;
135
1.42k
  struct community_alias *find;
136
137
1.42k
  memset(&ca, 0, sizeof(ca));
138
1.42k
  strlcpy(ca.community, community, sizeof(ca.community));
139
140
1.42k
  find = bgp_ca_community_lookup(&ca);
141
1.42k
  if (find)
142
0
    return find->alias;
143
144
1.42k
  return community;
145
1.42k
}
146
147
const char *bgp_alias2community(char *alias)
148
0
{
149
0
  struct community_alias ca;
150
0
  struct community_alias *find;
151
152
0
  memset(&ca, 0, sizeof(ca));
153
0
  strlcpy(ca.alias, alias, sizeof(ca.alias));
154
155
0
  find = bgp_ca_alias_lookup(&ca);
156
0
  if (find)
157
0
    return find->community;
158
159
0
  return alias;
160
0
}
161
162
/* Communities structs have `->str` which is used
163
 * for vty outputs and extended BGP community lists
164
 * with regexp.
165
 * This is a helper to convert already aliased version
166
 * of communities into numerical-only format.
167
 */
168
char *bgp_alias2community_str(const char *str)
169
0
{
170
0
  char **aliases;
171
0
  char *comstr;
172
0
  int num, i;
173
174
0
  frrstr_split(str, " ", &aliases, &num);
175
0
  const char *communities[num];
176
177
0
  for (i = 0; i < num; i++)
178
0
    communities[i] = bgp_alias2community(aliases[i]);
179
180
0
  comstr = frrstr_join(communities, num, " ");
181
182
0
  for (i = 0; i < num; i++)
183
0
    XFREE(MTYPE_TMP, aliases[i]);
184
0
  XFREE(MTYPE_TMP, aliases);
185
186
0
  return comstr;
187
0
}
188
189
static int bgp_community_alias_vector_walker(struct hash_bucket *bucket,
190
               void *data)
191
0
{
192
0
  vector *comps = data;
193
0
  struct community_alias *alias = bucket->data;
194
195
0
  vector_set(*comps, XSTRDUP(MTYPE_COMPLETION, alias->alias));
196
197
0
  return 1;
198
0
}
199
200
static void bgp_community_alias_cmd_completion(vector comps,
201
                 struct cmd_token *token)
202
0
{
203
0
  hash_walk(bgp_ca_alias_hash, bgp_community_alias_vector_walker, &comps);
204
0
}
205
206
static const struct cmd_variable_handler community_alias_handlers[] = {
207
  {.varname = "alias_name",
208
   .completions = bgp_community_alias_cmd_completion},
209
  {.tokenname = "ALIAS_NAME",
210
   .completions = bgp_community_alias_cmd_completion},
211
  {.completions = NULL}};
212
213
void bgp_community_alias_command_completion_setup(void)
214
0
{
215
0
  cmd_variable_handler_register(community_alias_handlers);
216
0
}