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