2 * Copyright (C) 2018 Cumulus Networks, Inc.
5 * This file is part of FRR.
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
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.
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
25 #include "lib/frratomic.h"
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"
35 #include "zebra_script.h"
37 DEFINE_MTYPE_STATIC(ZEBRA
, RIB_TABLE_INFO
, "RIB table info");
38 DEFINE_MTYPE_STATIC(ZEBRA
, ZEBRA_RT_TABLE
, "Zebra VRF table");
40 struct zebra_router zrouter
= {
41 .multipath_num
= MULTIPATH_NUM
,
42 .ipv4_multicast_mode
= MCAST_NO_CONFIG
,
46 zebra_router_table_entry_compare(const struct zebra_router_table
*e1
,
47 const struct zebra_router_table
*e2
);
49 RB_GENERATE(zebra_router_table_head
, zebra_router_table
,
50 zebra_router_table_entry
, zebra_router_table_entry_compare
);
54 zebra_router_table_entry_compare(const struct zebra_router_table
*e1
,
55 const struct zebra_router_table
*e2
)
57 if (e1
->tableid
< e2
->tableid
)
59 if (e1
->tableid
> e2
->tableid
)
61 if (e1
->ns_id
< e2
->ns_id
)
63 if (e1
->ns_id
> e2
->ns_id
)
65 if (e1
->afi
< e2
->afi
)
67 if (e1
->afi
> e2
->afi
)
69 return (e1
->safi
- e2
->safi
);
72 struct zebra_router_table
*zebra_router_find_zrt(struct zebra_vrf
*zvrf
,
73 uint32_t tableid
, afi_t afi
,
76 struct zebra_router_table finder
;
77 struct zebra_router_table
*zrt
;
79 memset(&finder
, 0, sizeof(finder
));
82 finder
.tableid
= tableid
;
83 finder
.ns_id
= zvrf
->zns
->ns_id
;
84 zrt
= RB_FIND(zebra_router_table_head
, &zrouter
.tables
, &finder
);
89 struct route_table
*zebra_router_find_table(struct zebra_vrf
*zvrf
,
90 uint32_t tableid
, afi_t afi
,
93 struct zebra_router_table finder
;
94 struct zebra_router_table
*zrt
;
96 memset(&finder
, 0, sizeof(finder
));
99 finder
.tableid
= tableid
;
100 finder
.ns_id
= zvrf
->zns
->ns_id
;
101 zrt
= RB_FIND(zebra_router_table_head
, &zrouter
.tables
, &finder
);
109 struct route_table
*zebra_router_get_table(struct zebra_vrf
*zvrf
,
110 uint32_t tableid
, afi_t afi
,
113 struct zebra_router_table finder
;
114 struct zebra_router_table
*zrt
;
115 struct rib_table_info
*info
;
117 memset(&finder
, 0, sizeof(finder
));
120 finder
.tableid
= tableid
;
121 finder
.ns_id
= zvrf
->zns
->ns_id
;
122 zrt
= RB_FIND(zebra_router_table_head
, &zrouter
.tables
, &finder
);
127 zrt
= XCALLOC(MTYPE_ZEBRA_RT_TABLE
, sizeof(*zrt
));
128 zrt
->tableid
= tableid
;
131 zrt
->ns_id
= zvrf
->zns
->ns_id
;
133 (afi
== AFI_IP6
) ? srcdest_table_init() : route_table_init();
135 info
= XCALLOC(MTYPE_RIB_TABLE_INFO
, sizeof(*info
));
139 info
->table_id
= tableid
;
140 route_table_set_info(zrt
->table
, info
);
141 zrt
->table
->cleanup
= zebra_rtable_node_cleanup
;
143 RB_INSERT(zebra_router_table_head
, &zrouter
.tables
, zrt
);
147 void zebra_router_show_table_summary(struct vty
*vty
)
149 struct zebra_router_table
*zrt
;
152 "VRF NS ID VRF ID AFI SAFI Table Count\n");
154 "---------------------------------------------------------------------------\n");
155 RB_FOREACH (zrt
, zebra_router_table_head
, &zrouter
.tables
) {
156 struct rib_table_info
*info
= route_table_get_info(zrt
->table
);
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
),
166 void zebra_router_sweep_route(void)
168 struct zebra_router_table
*zrt
;
170 RB_FOREACH (zrt
, zebra_router_table_head
, &zrouter
.tables
) {
171 if (zrt
->ns_id
!= NS_DEFAULT
)
173 rib_sweep_table(zrt
->table
);
177 void zebra_router_sweep_nhgs(void)
179 zebra_nhg_sweep_table(zrouter
.nhgs_id
);
182 static void zebra_router_free_table(struct zebra_router_table
*zrt
)
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
);
190 XFREE(MTYPE_RIB_TABLE_INFO
, table_info
);
191 XFREE(MTYPE_ZEBRA_RT_TABLE
, zrt
);
194 void zebra_router_release_table(struct zebra_vrf
*zvrf
, uint32_t tableid
,
195 afi_t afi
, safi_t safi
)
197 struct zebra_router_table finder
;
198 struct zebra_router_table
*zrt
;
200 memset(&finder
, 0, sizeof(finder
));
203 finder
.tableid
= tableid
;
204 finder
.ns_id
= zvrf
->zns
->ns_id
;
205 zrt
= RB_FIND(zebra_router_table_head
, &zrouter
.tables
, &finder
);
210 zebra_router_free_table(zrt
);
213 uint32_t zebra_router_get_next_sequence(void)
216 + atomic_fetch_add_explicit(&zrouter
.sequence_num
, 1,
217 memory_order_relaxed
);
220 void multicast_mode_ipv4_set(enum multicast_mode mode
)
222 if (IS_ZEBRA_DEBUG_RIB
)
223 zlog_debug("%s: multicast lookup mode set (%d)", __func__
,
225 zrouter
.ipv4_multicast_mode
= mode
;
228 enum multicast_mode
multicast_mode_ipv4_get(void)
230 return zrouter
.ipv4_multicast_mode
;
233 void zebra_router_terminate(void)
235 struct zebra_router_table
*zrt
, *tmp
;
237 THREAD_OFF(zrouter
.sweeper
);
239 RB_FOREACH_SAFE (zrt
, zebra_router_table_head
, &zrouter
.tables
, tmp
)
240 zebra_router_free_table(zrt
);
242 work_queue_free_and_null(&zrouter
.ribq
);
243 meta_queue_free(zrouter
.mq
, NULL
);
245 zebra_vxlan_disable();
246 zebra_mlag_terminate();
247 zebra_neigh_terminate();
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
);
256 hash_clean(zrouter
.rules_hash
, zebra_pbr_rules_free
);
257 hash_free(zrouter
.rules_hash
);
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
);
266 #ifdef HAVE_SCRIPTING
267 zebra_script_destroy();
270 /* OS-specific deinit */
271 kernel_router_terminate();
274 bool zebra_router_notify_on_ack(void)
276 return !zrouter
.asic_offloaded
|| zrouter
.notify_on_ack
;
279 void zebra_router_init(bool asic_offload
, bool notify_on_ack
)
281 zrouter
.sequence_num
= 0;
283 zrouter
.allow_delete
= false;
285 zrouter
.packets_to_process
= ZEBRA_ZAPI_PACKETS_TO_PROCESS
;
287 zrouter
.nhg_keep
= ZEBRA_DEFAULT_NHG_KEEP_TIMER
;
293 zrouter
.rules_hash
= hash_create_size(8, zebra_pbr_rules_hash_key
,
294 zebra_pbr_rules_hash_equal
,
298 hash_create_size(8, zebra_pbr_ipset_hash_key
,
299 zebra_pbr_ipset_hash_equal
, "IPset Hash");
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");
305 zrouter
.iptable_hash
= hash_create_size(8, zebra_pbr_iptable_hash_key
,
306 zebra_pbr_iptable_hash_equal
,
307 "IPtable Hash Entry");
310 hash_create_size(8, zebra_nhg_hash_key
, zebra_nhg_hash_equal
,
311 "Zebra Router Nexthop Groups");
313 hash_create_size(8, zebra_nhg_id_key
, zebra_nhg_hash_id_equal
,
314 "Zebra Router Nexthop Groups ID index");
317 hash_create_size(8, zebra_pbr_rules_hash_key
,
318 zebra_pbr_rules_hash_equal
, "Rules 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
,
330 zrouter
.asic_offloaded
= asic_offload
;
331 zrouter
.notify_on_ack
= notify_on_ack
;
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.
338 #if CONFDATE > 20251231
340 "Remove zrouter.asic_notification_nexthop_control as that it's not being maintained or used");
342 zrouter
.asic_notification_nexthop_control
= false;
344 #ifdef HAVE_SCRIPTING
348 /* OS-specific init */
349 kernel_router_init();