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