]> git.proxmox.com Git - mirror_frr.git/blob - zebra/zebra_router.c
Merge pull request #12367 from rgirada/ospf_valgrind_fix
[mirror_frr.git] / zebra / zebra_router.c
1 /* Zebra Router Code.
2 * Copyright (C) 2018 Cumulus Networks, Inc.
3 * Donald Sharp
4 *
5 * This file is part of FRR.
6 *
7 * FRR is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2, or (at your option) any
10 * later version.
11 *
12 * FRR is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with FRR; see the file COPYING. If not, write to the Free
19 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
20 * 02111-1307, USA.
21 */
22 #include "zebra.h"
23
24 #include <pthread.h>
25 #include "lib/frratomic.h"
26
27 #include "zebra_router.h"
28 #include "zebra_pbr.h"
29 #include "zebra_vxlan.h"
30 #include "zebra_mlag.h"
31 #include "zebra_nhg.h"
32 #include "zebra_neigh.h"
33 #include "zebra/zebra_tc.h"
34 #include "debug.h"
35 #include "zebra_script.h"
36
37 DEFINE_MTYPE_STATIC(ZEBRA, RIB_TABLE_INFO, "RIB table info");
38 DEFINE_MTYPE_STATIC(ZEBRA, ZEBRA_RT_TABLE, "Zebra VRF table");
39
40 struct zebra_router zrouter = {
41 .multipath_num = MULTIPATH_NUM,
42 .ipv4_multicast_mode = MCAST_NO_CONFIG,
43 };
44
45 static inline int
46 zebra_router_table_entry_compare(const struct zebra_router_table *e1,
47 const struct zebra_router_table *e2);
48
49 RB_GENERATE(zebra_router_table_head, zebra_router_table,
50 zebra_router_table_entry, zebra_router_table_entry_compare);
51
52
53 static inline int
54 zebra_router_table_entry_compare(const struct zebra_router_table *e1,
55 const struct zebra_router_table *e2)
56 {
57 if (e1->tableid < e2->tableid)
58 return -1;
59 if (e1->tableid > e2->tableid)
60 return 1;
61 if (e1->ns_id < e2->ns_id)
62 return -1;
63 if (e1->ns_id > e2->ns_id)
64 return 1;
65 if (e1->afi < e2->afi)
66 return -1;
67 if (e1->afi > e2->afi)
68 return 1;
69 return (e1->safi - e2->safi);
70 }
71
72 struct zebra_router_table *zebra_router_find_zrt(struct zebra_vrf *zvrf,
73 uint32_t tableid, afi_t afi,
74 safi_t safi)
75 {
76 struct zebra_router_table finder;
77 struct zebra_router_table *zrt;
78
79 memset(&finder, 0, sizeof(finder));
80 finder.afi = afi;
81 finder.safi = safi;
82 finder.tableid = tableid;
83 finder.ns_id = zvrf->zns->ns_id;
84 zrt = RB_FIND(zebra_router_table_head, &zrouter.tables, &finder);
85
86 return zrt;
87 }
88
89 struct route_table *zebra_router_find_table(struct zebra_vrf *zvrf,
90 uint32_t tableid, afi_t afi,
91 safi_t safi)
92 {
93 struct zebra_router_table finder;
94 struct zebra_router_table *zrt;
95
96 memset(&finder, 0, sizeof(finder));
97 finder.afi = afi;
98 finder.safi = safi;
99 finder.tableid = tableid;
100 finder.ns_id = zvrf->zns->ns_id;
101 zrt = RB_FIND(zebra_router_table_head, &zrouter.tables, &finder);
102
103 if (zrt)
104 return zrt->table;
105 else
106 return NULL;
107 }
108
109 struct route_table *zebra_router_get_table(struct zebra_vrf *zvrf,
110 uint32_t tableid, afi_t afi,
111 safi_t safi)
112 {
113 struct zebra_router_table finder;
114 struct zebra_router_table *zrt;
115 struct rib_table_info *info;
116
117 memset(&finder, 0, sizeof(finder));
118 finder.afi = afi;
119 finder.safi = safi;
120 finder.tableid = tableid;
121 finder.ns_id = zvrf->zns->ns_id;
122 zrt = RB_FIND(zebra_router_table_head, &zrouter.tables, &finder);
123
124 if (zrt)
125 return zrt->table;
126
127 zrt = XCALLOC(MTYPE_ZEBRA_RT_TABLE, sizeof(*zrt));
128 zrt->tableid = tableid;
129 zrt->afi = afi;
130 zrt->safi = safi;
131 zrt->ns_id = zvrf->zns->ns_id;
132 zrt->table =
133 (afi == AFI_IP6) ? srcdest_table_init() : route_table_init();
134
135 info = XCALLOC(MTYPE_RIB_TABLE_INFO, sizeof(*info));
136 info->zvrf = zvrf;
137 info->afi = afi;
138 info->safi = safi;
139 info->table_id = tableid;
140 route_table_set_info(zrt->table, info);
141 zrt->table->cleanup = zebra_rtable_node_cleanup;
142
143 RB_INSERT(zebra_router_table_head, &zrouter.tables, zrt);
144 return zrt->table;
145 }
146
147 void zebra_router_show_table_summary(struct vty *vty)
148 {
149 struct zebra_router_table *zrt;
150
151 vty_out(vty,
152 "VRF NS ID VRF ID AFI SAFI Table Count\n");
153 vty_out(vty,
154 "---------------------------------------------------------------------------\n");
155 RB_FOREACH (zrt, zebra_router_table_head, &zrouter.tables) {
156 struct rib_table_info *info = route_table_get_info(zrt->table);
157
158 vty_out(vty, "%-16s%5d %9d %7s %15s %8d %10lu\n", info->zvrf->vrf->name,
159 zrt->ns_id, info->zvrf->vrf->vrf_id,
160 afi2str(zrt->afi), safi2str(zrt->safi),
161 zrt->tableid,
162 zrt->table->count);
163 }
164 }
165
166 void zebra_router_sweep_route(void)
167 {
168 struct zebra_router_table *zrt;
169
170 RB_FOREACH (zrt, zebra_router_table_head, &zrouter.tables) {
171 if (zrt->ns_id != NS_DEFAULT)
172 continue;
173 rib_sweep_table(zrt->table);
174 }
175 }
176
177 void zebra_router_sweep_nhgs(void)
178 {
179 zebra_nhg_sweep_table(zrouter.nhgs_id);
180 }
181
182 static void zebra_router_free_table(struct zebra_router_table *zrt)
183 {
184 void *table_info;
185
186 table_info = route_table_get_info(zrt->table);
187 route_table_finish(zrt->table);
188 RB_REMOVE(zebra_router_table_head, &zrouter.tables, zrt);
189
190 XFREE(MTYPE_RIB_TABLE_INFO, table_info);
191 XFREE(MTYPE_ZEBRA_RT_TABLE, zrt);
192 }
193
194 void zebra_router_release_table(struct zebra_vrf *zvrf, uint32_t tableid,
195 afi_t afi, safi_t safi)
196 {
197 struct zebra_router_table finder;
198 struct zebra_router_table *zrt;
199
200 memset(&finder, 0, sizeof(finder));
201 finder.afi = afi;
202 finder.safi = safi;
203 finder.tableid = tableid;
204 finder.ns_id = zvrf->zns->ns_id;
205 zrt = RB_FIND(zebra_router_table_head, &zrouter.tables, &finder);
206
207 if (!zrt)
208 return;
209
210 zebra_router_free_table(zrt);
211 }
212
213 uint32_t zebra_router_get_next_sequence(void)
214 {
215 return 1
216 + atomic_fetch_add_explicit(&zrouter.sequence_num, 1,
217 memory_order_relaxed);
218 }
219
220 void multicast_mode_ipv4_set(enum multicast_mode mode)
221 {
222 if (IS_ZEBRA_DEBUG_RIB)
223 zlog_debug("%s: multicast lookup mode set (%d)", __func__,
224 mode);
225 zrouter.ipv4_multicast_mode = mode;
226 }
227
228 enum multicast_mode multicast_mode_ipv4_get(void)
229 {
230 return zrouter.ipv4_multicast_mode;
231 }
232
233 void zebra_router_terminate(void)
234 {
235 struct zebra_router_table *zrt, *tmp;
236
237 THREAD_OFF(zrouter.sweeper);
238
239 RB_FOREACH_SAFE (zrt, zebra_router_table_head, &zrouter.tables, tmp)
240 zebra_router_free_table(zrt);
241
242 work_queue_free_and_null(&zrouter.ribq);
243 meta_queue_free(zrouter.mq, NULL);
244
245 zebra_vxlan_disable();
246 zebra_mlag_terminate();
247 zebra_neigh_terminate();
248
249 /* Free NHE in ID table only since it has unhashable entries as well */
250 hash_iterate(zrouter.nhgs_id, zebra_nhg_hash_free_zero_id, NULL);
251 hash_clean(zrouter.nhgs_id, zebra_nhg_hash_free);
252 hash_free(zrouter.nhgs_id);
253 hash_clean(zrouter.nhgs, NULL);
254 hash_free(zrouter.nhgs);
255
256 hash_clean(zrouter.rules_hash, zebra_pbr_rules_free);
257 hash_free(zrouter.rules_hash);
258
259 hash_clean(zrouter.ipset_entry_hash, zebra_pbr_ipset_entry_free),
260 hash_clean(zrouter.ipset_hash, zebra_pbr_ipset_free);
261 hash_free(zrouter.ipset_hash);
262 hash_free(zrouter.ipset_entry_hash);
263 hash_clean(zrouter.iptable_hash, zebra_pbr_iptable_free);
264 hash_free(zrouter.iptable_hash);
265
266 #ifdef HAVE_SCRIPTING
267 zebra_script_destroy();
268 #endif
269
270 /* OS-specific deinit */
271 kernel_router_terminate();
272 }
273
274 bool zebra_router_notify_on_ack(void)
275 {
276 return !zrouter.asic_offloaded || zrouter.notify_on_ack;
277 }
278
279 void zebra_router_init(bool asic_offload, bool notify_on_ack)
280 {
281 zrouter.sequence_num = 0;
282
283 zrouter.allow_delete = false;
284
285 zrouter.packets_to_process = ZEBRA_ZAPI_PACKETS_TO_PROCESS;
286
287 zrouter.nhg_keep = ZEBRA_DEFAULT_NHG_KEEP_TIMER;
288
289 zebra_vxlan_init();
290 zebra_mlag_init();
291 zebra_neigh_init();
292
293 zrouter.rules_hash = hash_create_size(8, zebra_pbr_rules_hash_key,
294 zebra_pbr_rules_hash_equal,
295 "Rules Hash");
296
297 zrouter.ipset_hash =
298 hash_create_size(8, zebra_pbr_ipset_hash_key,
299 zebra_pbr_ipset_hash_equal, "IPset Hash");
300
301 zrouter.ipset_entry_hash = hash_create_size(
302 8, zebra_pbr_ipset_entry_hash_key,
303 zebra_pbr_ipset_entry_hash_equal, "IPset Hash Entry");
304
305 zrouter.iptable_hash = hash_create_size(8, zebra_pbr_iptable_hash_key,
306 zebra_pbr_iptable_hash_equal,
307 "IPtable Hash Entry");
308
309 zrouter.nhgs =
310 hash_create_size(8, zebra_nhg_hash_key, zebra_nhg_hash_equal,
311 "Zebra Router Nexthop Groups");
312 zrouter.nhgs_id =
313 hash_create_size(8, zebra_nhg_id_key, zebra_nhg_hash_id_equal,
314 "Zebra Router Nexthop Groups ID index");
315
316 zrouter.rules_hash =
317 hash_create_size(8, zebra_pbr_rules_hash_key,
318 zebra_pbr_rules_hash_equal, "Rules Hash");
319
320 zrouter.qdisc_hash =
321 hash_create_size(8, zebra_tc_qdisc_hash_key,
322 zebra_tc_qdisc_hash_equal, "TC (qdisc) Hash");
323 zrouter.class_hash = hash_create_size(8, zebra_tc_class_hash_key,
324 zebra_tc_class_hash_equal,
325 "TC (classes) Hash");
326 zrouter.filter_hash = hash_create_size(8, zebra_tc_filter_hash_key,
327 zebra_tc_filter_hash_equal,
328 "TC (filter) Hash");
329
330 zrouter.asic_offloaded = asic_offload;
331 zrouter.notify_on_ack = notify_on_ack;
332
333 #ifdef HAVE_SCRIPTING
334 zebra_script_init();
335 #endif
336
337 /* OS-specific init */
338 kernel_router_init();
339 }