Line data Source code
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 12 : DEFINE_MTYPE_STATIC(ZEBRA, RIB_TABLE_INFO, "RIB table info");
38 12 : 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 64 : 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 64 : zebra_router_table_entry_compare(const struct zebra_router_table *e1,
55 : const struct zebra_router_table *e2)
56 : {
57 64 : if (e1->tableid < e2->tableid)
58 : return -1;
59 64 : if (e1->tableid > e2->tableid)
60 : return 1;
61 64 : if (e1->ns_id < e2->ns_id)
62 : return -1;
63 64 : if (e1->ns_id > e2->ns_id)
64 : return 1;
65 64 : if (e1->afi < e2->afi)
66 : return -1;
67 60 : if (e1->afi > e2->afi)
68 : return 1;
69 36 : return (e1->safi - e2->safi);
70 : }
71 :
72 0 : 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 0 : struct zebra_router_table finder;
77 0 : struct zebra_router_table *zrt;
78 :
79 0 : memset(&finder, 0, sizeof(finder));
80 0 : finder.afi = afi;
81 0 : finder.safi = safi;
82 0 : finder.tableid = tableid;
83 0 : finder.ns_id = zvrf->zns->ns_id;
84 0 : zrt = RB_FIND(zebra_router_table_head, &zrouter.tables, &finder);
85 :
86 0 : return zrt;
87 : }
88 :
89 0 : struct route_table *zebra_router_find_table(struct zebra_vrf *zvrf,
90 : uint32_t tableid, afi_t afi,
91 : safi_t safi)
92 : {
93 0 : struct zebra_router_table finder;
94 0 : struct zebra_router_table *zrt;
95 :
96 0 : memset(&finder, 0, sizeof(finder));
97 0 : finder.afi = afi;
98 0 : finder.safi = safi;
99 0 : finder.tableid = tableid;
100 0 : finder.ns_id = zvrf->zns->ns_id;
101 0 : zrt = RB_FIND(zebra_router_table_head, &zrouter.tables, &finder);
102 :
103 0 : if (zrt)
104 0 : return zrt->table;
105 : else
106 : return NULL;
107 : }
108 :
109 16 : struct route_table *zebra_router_get_table(struct zebra_vrf *zvrf,
110 : uint32_t tableid, afi_t afi,
111 : safi_t safi)
112 : {
113 16 : struct zebra_router_table finder;
114 16 : struct zebra_router_table *zrt;
115 16 : struct rib_table_info *info;
116 :
117 16 : memset(&finder, 0, sizeof(finder));
118 16 : finder.afi = afi;
119 16 : finder.safi = safi;
120 16 : finder.tableid = tableid;
121 16 : finder.ns_id = zvrf->zns->ns_id;
122 16 : zrt = RB_FIND(zebra_router_table_head, &zrouter.tables, &finder);
123 :
124 16 : if (zrt)
125 0 : return zrt->table;
126 :
127 16 : zrt = XCALLOC(MTYPE_ZEBRA_RT_TABLE, sizeof(*zrt));
128 16 : zrt->tableid = tableid;
129 16 : zrt->afi = afi;
130 16 : zrt->safi = safi;
131 16 : zrt->ns_id = zvrf->zns->ns_id;
132 32 : zrt->table =
133 16 : (afi == AFI_IP6) ? srcdest_table_init() : route_table_init();
134 :
135 16 : info = XCALLOC(MTYPE_RIB_TABLE_INFO, sizeof(*info));
136 16 : info->zvrf = zvrf;
137 16 : info->afi = afi;
138 16 : info->safi = safi;
139 16 : info->table_id = tableid;
140 16 : route_table_set_info(zrt->table, info);
141 16 : zrt->table->cleanup = zebra_rtable_node_cleanup;
142 :
143 16 : RB_INSERT(zebra_router_table_head, &zrouter.tables, zrt);
144 16 : return zrt->table;
145 : }
146 :
147 0 : void zebra_router_show_table_summary(struct vty *vty)
148 : {
149 0 : struct zebra_router_table *zrt;
150 :
151 0 : vty_out(vty,
152 : "VRF NS ID VRF ID AFI SAFI Table Count\n");
153 0 : vty_out(vty,
154 : "---------------------------------------------------------------------------\n");
155 0 : RB_FOREACH (zrt, zebra_router_table_head, &zrouter.tables) {
156 0 : struct rib_table_info *info = route_table_get_info(zrt->table);
157 :
158 0 : vty_out(vty, "%-16s%5d %9d %7s %15s %8d %10lu\n", info->zvrf->vrf->name,
159 0 : zrt->ns_id, info->zvrf->vrf->vrf_id,
160 : afi2str(zrt->afi), safi2str(zrt->safi),
161 : zrt->tableid,
162 : zrt->table->count);
163 : }
164 0 : }
165 :
166 4 : void zebra_router_sweep_route(void)
167 : {
168 4 : struct zebra_router_table *zrt;
169 :
170 24 : RB_FOREACH (zrt, zebra_router_table_head, &zrouter.tables) {
171 16 : if (zrt->ns_id != NS_DEFAULT)
172 0 : continue;
173 16 : rib_sweep_table(zrt->table);
174 : }
175 4 : }
176 :
177 4 : void zebra_router_sweep_nhgs(void)
178 : {
179 4 : zebra_nhg_sweep_table(zrouter.nhgs_id);
180 4 : }
181 :
182 16 : static void zebra_router_free_table(struct zebra_router_table *zrt)
183 : {
184 16 : void *table_info;
185 :
186 16 : table_info = route_table_get_info(zrt->table);
187 16 : route_table_finish(zrt->table);
188 16 : RB_REMOVE(zebra_router_table_head, &zrouter.tables, zrt);
189 :
190 16 : XFREE(MTYPE_RIB_TABLE_INFO, table_info);
191 16 : XFREE(MTYPE_ZEBRA_RT_TABLE, zrt);
192 16 : }
193 :
194 16 : void zebra_router_release_table(struct zebra_vrf *zvrf, uint32_t tableid,
195 : afi_t afi, safi_t safi)
196 : {
197 16 : struct zebra_router_table finder;
198 16 : struct zebra_router_table *zrt;
199 :
200 16 : memset(&finder, 0, sizeof(finder));
201 16 : finder.afi = afi;
202 16 : finder.safi = safi;
203 16 : finder.tableid = tableid;
204 16 : finder.ns_id = zvrf->zns->ns_id;
205 16 : zrt = RB_FIND(zebra_router_table_head, &zrouter.tables, &finder);
206 :
207 16 : if (!zrt)
208 0 : return;
209 :
210 16 : zebra_router_free_table(zrt);
211 : }
212 :
213 342 : uint32_t zebra_router_get_next_sequence(void)
214 : {
215 342 : return 1
216 342 : + atomic_fetch_add_explicit(&zrouter.sequence_num, 1,
217 : memory_order_relaxed);
218 : }
219 :
220 0 : void multicast_mode_ipv4_set(enum multicast_mode mode)
221 : {
222 0 : if (IS_ZEBRA_DEBUG_RIB)
223 0 : zlog_debug("%s: multicast lookup mode set (%d)", __func__,
224 : mode);
225 0 : zrouter.ipv4_multicast_mode = mode;
226 0 : }
227 :
228 0 : enum multicast_mode multicast_mode_ipv4_get(void)
229 : {
230 0 : return zrouter.ipv4_multicast_mode;
231 : }
232 :
233 4 : void zebra_router_terminate(void)
234 : {
235 4 : struct zebra_router_table *zrt, *tmp;
236 :
237 4 : THREAD_OFF(zrouter.sweeper);
238 :
239 8 : RB_FOREACH_SAFE (zrt, zebra_router_table_head, &zrouter.tables, tmp)
240 0 : zebra_router_free_table(zrt);
241 :
242 4 : work_queue_free_and_null(&zrouter.ribq);
243 4 : meta_queue_free(zrouter.mq, NULL);
244 :
245 4 : zebra_vxlan_disable();
246 4 : zebra_mlag_terminate();
247 4 : zebra_neigh_terminate();
248 :
249 : /* Free NHE in ID table only since it has unhashable entries as well */
250 4 : hash_iterate(zrouter.nhgs_id, zebra_nhg_hash_free_zero_id, NULL);
251 4 : hash_clean(zrouter.nhgs_id, zebra_nhg_hash_free);
252 4 : hash_free(zrouter.nhgs_id);
253 4 : hash_clean(zrouter.nhgs, NULL);
254 4 : hash_free(zrouter.nhgs);
255 :
256 4 : hash_clean(zrouter.rules_hash, zebra_pbr_rules_free);
257 4 : hash_free(zrouter.rules_hash);
258 :
259 4 : hash_clean(zrouter.ipset_entry_hash, zebra_pbr_ipset_entry_free),
260 4 : hash_clean(zrouter.ipset_hash, zebra_pbr_ipset_free);
261 4 : hash_free(zrouter.ipset_hash);
262 4 : hash_free(zrouter.ipset_entry_hash);
263 4 : hash_clean(zrouter.iptable_hash, zebra_pbr_iptable_free);
264 4 : hash_free(zrouter.iptable_hash);
265 :
266 : #ifdef HAVE_SCRIPTING
267 : zebra_script_destroy();
268 : #endif
269 :
270 : /* OS-specific deinit */
271 4 : kernel_router_terminate();
272 4 : }
273 :
274 41 : bool zebra_router_notify_on_ack(void)
275 : {
276 41 : return !zrouter.asic_offloaded || zrouter.notify_on_ack;
277 : }
278 :
279 4 : void zebra_router_init(bool asic_offload, bool notify_on_ack)
280 : {
281 4 : zrouter.sequence_num = 0;
282 :
283 4 : zrouter.allow_delete = false;
284 :
285 4 : zrouter.packets_to_process = ZEBRA_ZAPI_PACKETS_TO_PROCESS;
286 :
287 4 : zrouter.nhg_keep = ZEBRA_DEFAULT_NHG_KEEP_TIMER;
288 :
289 4 : zebra_vxlan_init();
290 4 : zebra_mlag_init();
291 4 : zebra_neigh_init();
292 :
293 4 : zrouter.rules_hash = hash_create_size(8, zebra_pbr_rules_hash_key,
294 : zebra_pbr_rules_hash_equal,
295 : "Rules Hash");
296 :
297 8 : zrouter.ipset_hash =
298 4 : hash_create_size(8, zebra_pbr_ipset_hash_key,
299 : zebra_pbr_ipset_hash_equal, "IPset Hash");
300 :
301 4 : 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 4 : zrouter.iptable_hash = hash_create_size(8, zebra_pbr_iptable_hash_key,
306 : zebra_pbr_iptable_hash_equal,
307 : "IPtable Hash Entry");
308 :
309 8 : zrouter.nhgs =
310 4 : hash_create_size(8, zebra_nhg_hash_key, zebra_nhg_hash_equal,
311 : "Zebra Router Nexthop Groups");
312 8 : zrouter.nhgs_id =
313 4 : hash_create_size(8, zebra_nhg_id_key, zebra_nhg_hash_id_equal,
314 : "Zebra Router Nexthop Groups ID index");
315 :
316 8 : zrouter.rules_hash =
317 4 : hash_create_size(8, zebra_pbr_rules_hash_key,
318 : zebra_pbr_rules_hash_equal, "Rules Hash");
319 :
320 8 : zrouter.qdisc_hash =
321 4 : hash_create_size(8, zebra_tc_qdisc_hash_key,
322 : zebra_tc_qdisc_hash_equal, "TC (qdisc) Hash");
323 4 : zrouter.class_hash = hash_create_size(8, zebra_tc_class_hash_key,
324 : zebra_tc_class_hash_equal,
325 : "TC (classes) Hash");
326 4 : zrouter.filter_hash = hash_create_size(8, zebra_tc_filter_hash_key,
327 : zebra_tc_filter_hash_equal,
328 : "TC (filter) Hash");
329 :
330 4 : zrouter.asic_offloaded = asic_offload;
331 4 : zrouter.notify_on_ack = notify_on_ack;
332 :
333 : /*
334 : * If you start using asic_notification_nexthop_control
335 : * come talk to the FRR community about what you are doing
336 : * We would like to know.
337 : */
338 : #if CONFDATE > 20251231
339 : CPP_NOTICE(
340 : "Remove zrouter.asic_notification_nexthop_control as that it's not being maintained or used");
341 : #endif
342 4 : zrouter.asic_notification_nexthop_control = false;
343 :
344 : #ifdef HAVE_SCRIPTING
345 : zebra_script_init();
346 : #endif
347 :
348 : /* OS-specific init */
349 4 : kernel_router_init();
350 4 : }
|