1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (C) 2018 Cumulus Networks, Inc.
9 #include "lib/frratomic.h"
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"
19 #include "zebra_script.h"
21 DEFINE_MTYPE_STATIC(ZEBRA
, RIB_TABLE_INFO
, "RIB table info");
22 DEFINE_MTYPE_STATIC(ZEBRA
, ZEBRA_RT_TABLE
, "Zebra VRF table");
24 struct zebra_router zrouter
= {
25 .multipath_num
= MULTIPATH_NUM
,
26 .ipv4_multicast_mode
= MCAST_NO_CONFIG
,
30 zebra_router_table_entry_compare(const struct zebra_router_table
*e1
,
31 const struct zebra_router_table
*e2
);
33 RB_GENERATE(zebra_router_table_head
, zebra_router_table
,
34 zebra_router_table_entry
, zebra_router_table_entry_compare
);
38 zebra_router_table_entry_compare(const struct zebra_router_table
*e1
,
39 const struct zebra_router_table
*e2
)
41 if (e1
->tableid
< e2
->tableid
)
43 if (e1
->tableid
> e2
->tableid
)
45 if (e1
->ns_id
< e2
->ns_id
)
47 if (e1
->ns_id
> e2
->ns_id
)
49 if (e1
->afi
< e2
->afi
)
51 if (e1
->afi
> e2
->afi
)
53 return (e1
->safi
- e2
->safi
);
56 struct zebra_router_table
*zebra_router_find_zrt(struct zebra_vrf
*zvrf
,
57 uint32_t tableid
, afi_t afi
,
60 struct zebra_router_table finder
;
61 struct zebra_router_table
*zrt
;
63 memset(&finder
, 0, sizeof(finder
));
66 finder
.tableid
= tableid
;
67 finder
.ns_id
= zvrf
->zns
->ns_id
;
68 zrt
= RB_FIND(zebra_router_table_head
, &zrouter
.tables
, &finder
);
73 struct route_table
*zebra_router_find_table(struct zebra_vrf
*zvrf
,
74 uint32_t tableid
, afi_t afi
,
77 struct zebra_router_table finder
;
78 struct zebra_router_table
*zrt
;
80 memset(&finder
, 0, sizeof(finder
));
83 finder
.tableid
= tableid
;
84 finder
.ns_id
= zvrf
->zns
->ns_id
;
85 zrt
= RB_FIND(zebra_router_table_head
, &zrouter
.tables
, &finder
);
93 struct route_table
*zebra_router_get_table(struct zebra_vrf
*zvrf
,
94 uint32_t tableid
, afi_t afi
,
97 struct zebra_router_table finder
;
98 struct zebra_router_table
*zrt
;
99 struct rib_table_info
*info
;
101 memset(&finder
, 0, sizeof(finder
));
104 finder
.tableid
= tableid
;
105 finder
.ns_id
= zvrf
->zns
->ns_id
;
106 zrt
= RB_FIND(zebra_router_table_head
, &zrouter
.tables
, &finder
);
111 zrt
= XCALLOC(MTYPE_ZEBRA_RT_TABLE
, sizeof(*zrt
));
112 zrt
->tableid
= tableid
;
115 zrt
->ns_id
= zvrf
->zns
->ns_id
;
117 (afi
== AFI_IP6
) ? srcdest_table_init() : route_table_init();
119 info
= XCALLOC(MTYPE_RIB_TABLE_INFO
, sizeof(*info
));
123 info
->table_id
= tableid
;
124 route_table_set_info(zrt
->table
, info
);
125 zrt
->table
->cleanup
= zebra_rtable_node_cleanup
;
127 RB_INSERT(zebra_router_table_head
, &zrouter
.tables
, zrt
);
131 void zebra_router_show_table_summary(struct vty
*vty
)
133 struct zebra_router_table
*zrt
;
136 "VRF NS ID VRF ID AFI SAFI Table Count\n");
138 "---------------------------------------------------------------------------\n");
139 RB_FOREACH (zrt
, zebra_router_table_head
, &zrouter
.tables
) {
140 struct rib_table_info
*info
= route_table_get_info(zrt
->table
);
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
),
150 void zebra_router_sweep_route(void)
152 struct zebra_router_table
*zrt
;
154 RB_FOREACH (zrt
, zebra_router_table_head
, &zrouter
.tables
) {
155 if (zrt
->ns_id
!= NS_DEFAULT
)
157 rib_sweep_table(zrt
->table
);
161 void zebra_router_sweep_nhgs(void)
163 zebra_nhg_sweep_table(zrouter
.nhgs_id
);
166 static void zebra_router_free_table(struct zebra_router_table
*zrt
)
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
);
174 XFREE(MTYPE_RIB_TABLE_INFO
, table_info
);
175 XFREE(MTYPE_ZEBRA_RT_TABLE
, zrt
);
178 void zebra_router_release_table(struct zebra_vrf
*zvrf
, uint32_t tableid
,
179 afi_t afi
, safi_t safi
)
181 struct zebra_router_table finder
;
182 struct zebra_router_table
*zrt
;
184 memset(&finder
, 0, sizeof(finder
));
187 finder
.tableid
= tableid
;
188 finder
.ns_id
= zvrf
->zns
->ns_id
;
189 zrt
= RB_FIND(zebra_router_table_head
, &zrouter
.tables
, &finder
);
194 zebra_router_free_table(zrt
);
197 uint32_t zebra_router_get_next_sequence(void)
200 + atomic_fetch_add_explicit(&zrouter
.sequence_num
, 1,
201 memory_order_relaxed
);
204 void multicast_mode_ipv4_set(enum multicast_mode mode
)
206 if (IS_ZEBRA_DEBUG_RIB
)
207 zlog_debug("%s: multicast lookup mode set (%d)", __func__
,
209 zrouter
.ipv4_multicast_mode
= mode
;
212 enum multicast_mode
multicast_mode_ipv4_get(void)
214 return zrouter
.ipv4_multicast_mode
;
217 void zebra_router_terminate(void)
219 struct zebra_router_table
*zrt
, *tmp
;
221 EVENT_OFF(zrouter
.sweeper
);
223 RB_FOREACH_SAFE (zrt
, zebra_router_table_head
, &zrouter
.tables
, tmp
)
224 zebra_router_free_table(zrt
);
226 work_queue_free_and_null(&zrouter
.ribq
);
227 meta_queue_free(zrouter
.mq
, NULL
);
229 zebra_vxlan_disable();
230 zebra_mlag_terminate();
231 zebra_neigh_terminate();
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
);
238 hash_clean_and_free(&zrouter
.rules_hash
, zebra_pbr_rules_free
);
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
);
245 #ifdef HAVE_SCRIPTING
246 zebra_script_destroy();
249 /* OS-specific deinit */
250 kernel_router_terminate();
253 bool zebra_router_notify_on_ack(void)
255 return !zrouter
.asic_offloaded
|| zrouter
.notify_on_ack
;
258 void zebra_router_init(bool asic_offload
, bool notify_on_ack
)
260 zrouter
.sequence_num
= 0;
262 zrouter
.allow_delete
= false;
264 zrouter
.packets_to_process
= ZEBRA_ZAPI_PACKETS_TO_PROCESS
;
266 zrouter
.nhg_keep
= ZEBRA_DEFAULT_NHG_KEEP_TIMER
;
272 zrouter
.rules_hash
= hash_create_size(8, zebra_pbr_rules_hash_key
,
273 zebra_pbr_rules_hash_equal
,
277 hash_create_size(8, zebra_pbr_ipset_hash_key
,
278 zebra_pbr_ipset_hash_equal
, "IPset Hash");
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");
284 zrouter
.iptable_hash
= hash_create_size(8, zebra_pbr_iptable_hash_key
,
285 zebra_pbr_iptable_hash_equal
,
286 "IPtable Hash Entry");
289 hash_create_size(8, zebra_nhg_hash_key
, zebra_nhg_hash_equal
,
290 "Zebra Router Nexthop Groups");
292 hash_create_size(8, zebra_nhg_id_key
, zebra_nhg_hash_id_equal
,
293 "Zebra Router Nexthop Groups ID index");
296 hash_create_size(8, zebra_pbr_rules_hash_key
,
297 zebra_pbr_rules_hash_equal
, "Rules 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
,
309 zrouter
.asic_offloaded
= asic_offload
;
310 zrouter
.notify_on_ack
= notify_on_ack
;
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.
317 #if CONFDATE > 20251231
319 "Remove zrouter.asic_notification_nexthop_control as that it's not being maintained or used");
321 zrouter
.asic_notification_nexthop_control
= false;
323 #ifdef HAVE_SCRIPTING
327 /* OS-specific init */
328 kernel_router_init();