]> git.proxmox.com Git - mirror_frr.git/blame - zebra/table_manager.c
tests: clean up all_proto_startup a bit
[mirror_frr.git] / zebra / table_manager.c
CommitLineData
50261279
PG
1/* zebra table Manager for routing table identifier management
2 * Copyright (C) 2018 6WIND
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the Free
6 * Software Foundation; either version 2 of the License, or (at your option)
7 * any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; see the file COPYING; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18
453844ab
QY
19#include "zebra.h"
20
50261279
PG
21#include <stdio.h>
22#include <string.h>
23#include <sys/types.h>
24
50261279
PG
25#include "lib/log.h"
26#include "lib/memory.h"
27#include "lib/table.h"
28#include "lib/network.h"
29#include "lib/stream.h"
30#include "lib/zclient.h"
31#include "lib/libfrr.h"
32#include "lib/vrf.h"
33
453844ab
QY
34#include "zebra/zserv.h"
35#include "zebra/zebra_vrf.h"
36#include "zebra/label_manager.h" /* for NO_PROTO */
37#include "zebra/table_manager.h"
43e52561 38#include "zebra/zebra_errors.h"
50261279
PG
39
40/* routing table identifiers
41 *
42 */
cae8bc96 43#if !defined(GNU_LINUX)
50261279
PG
44/* BSD systems
45 */
46#else
47/* Linux Systems
48 */
49#define RT_TABLE_ID_LOCAL 255
50#define RT_TABLE_ID_MAIN 254
51#define RT_TABLE_ID_DEFAULT 253
52#define RT_TABLE_ID_COMPAT 252
53#define RT_TABLE_ID_UNSPEC 0
cae8bc96 54#endif /* !def(GNU_LINUX) */
50261279
PG
55#define RT_TABLE_ID_UNRESERVED_MIN 1
56#define RT_TABLE_ID_UNRESERVED_MAX 0xffffffff
57
58struct table_manager tbl_mgr;
59
60DEFINE_MGROUP(TABLE_MGR, "Table Manager");
61DEFINE_MTYPE_STATIC(TABLE_MGR, TM_CHUNK, "Table Manager Chunk");
62
63static void delete_table_chunk(void *val)
64{
65 XFREE(MTYPE_TM_CHUNK, val);
66}
67
68/**
69 * Init table manager
70 */
71void table_manager_enable(ns_id_t ns_id)
72{
73 if (ns_id != NS_DEFAULT)
74 return;
75 tbl_mgr.lc_list = list_new();
76 tbl_mgr.lc_list->del = delete_table_chunk;
21ccc0cf 77 hook_register(zserv_client_close, release_daemon_table_chunks);
50261279
PG
78}
79
80/**
81 * Core function, assigns table chunks
82 *
83 * It first searches through the list to check if there's one available
84 * (previously released). Otherwise it creates and assigns a new one
85 *
86 * @param proto Daemon protocol of client, to identify the owner
87 * @param instance Instance, to identify the owner
88 * @para size Size of the table chunk
89 * @return Pointer to the assigned table chunk
90 */
91struct table_manager_chunk *assign_table_chunk(uint8_t proto, uint16_t instance,
92 uint32_t size)
93{
94 struct table_manager_chunk *tmc;
95 struct listnode *node;
96 uint32_t start;
97
98 /* first check if there's one available */
99 for (ALL_LIST_ELEMENTS_RO(tbl_mgr.lc_list, node, tmc)) {
100 if (tmc->proto == NO_PROTO
101 && tmc->end - tmc->start + 1 == size) {
102 tmc->proto = proto;
103 tmc->instance = instance;
104 return tmc;
105 }
106 }
107 /* otherwise create a new one */
108 tmc = XCALLOC(MTYPE_TM_CHUNK, sizeof(struct table_manager_chunk));
109 if (!tmc)
110 return NULL;
111
112 /* table RT IDs range are [1;252] and [256;0xffffffff]
113 * - check if the requested range can be within the first range,
114 * otherwise elect second one
115 * - TODO : vrf-lites have their own table identifier.
116 * In that case, table_id should be removed from the table range.
117 */
118 if (list_isempty(tbl_mgr.lc_list))
119 start = RT_TABLE_ID_UNRESERVED_MIN;
120 else
121 start = ((struct table_manager_chunk *)listgetdata(
122 listtail(tbl_mgr.lc_list)))->end + 1;
123
cae8bc96 124#if !defined(GNU_LINUX)
50261279
PG
125/* BSD systems
126 */
127#else
128/* Linux Systems
129 */
130 /* if not enough room space between MIN and COMPAT,
131 * then begin after LOCAL
132 */
133 if (start < RT_TABLE_ID_COMPAT && (size >
134 RT_TABLE_ID_COMPAT
135 - RT_TABLE_ID_UNRESERVED_MIN))
136 start = RT_TABLE_ID_LOCAL + 1;
cae8bc96 137#endif /* !def(GNU_LINUX) */
50261279
PG
138 tmc->start = start;
139 if (RT_TABLE_ID_UNRESERVED_MAX - size + 1 < start) {
e914ccbe 140 flog_err(EC_ZEBRA_TM_EXHAUSTED_IDS,
1c50c1c0 141 "Reached max table id. Start/Size %u/%u", start, size);
50261279
PG
142 XFREE(MTYPE_TM_CHUNK, tmc);
143 return NULL;
144 }
145 tmc->end = tmc->start + size - 1;
146 tmc->proto = proto;
147 tmc->instance = instance;
148 listnode_add(tbl_mgr.lc_list, tmc);
149
150 return tmc;
151}
152
153/**
154 * Core function, release no longer used table chunks
155 *
156 * @param proto Daemon protocol of client, to identify the owner
157 * @param instance Instance, to identify the owner
158 * @param start First table RT ID of the chunk
159 * @param end Last table RT ID of the chunk
160 * @return 0 on success, -1 otherwise
161 */
162int release_table_chunk(uint8_t proto, uint16_t instance, uint32_t start,
163 uint32_t end)
164{
165 struct listnode *node;
166 struct table_manager_chunk *tmc;
167 int ret = -1;
168
169 /* check that size matches */
170 zlog_debug("Releasing table chunk: %u - %u", start, end);
171 /* find chunk and disown */
172 for (ALL_LIST_ELEMENTS_RO(tbl_mgr.lc_list, node, tmc)) {
173 if (tmc->start != start)
174 continue;
175 if (tmc->end != end)
176 continue;
177 if (tmc->proto != proto || tmc->instance != instance) {
e914ccbe 178 flog_err(EC_ZEBRA_TM_DAEMON_MISMATCH,
1c50c1c0 179 "%s: Daemon mismatch!!", __func__);
50261279
PG
180 continue;
181 }
182 tmc->proto = NO_PROTO;
183 tmc->instance = 0;
184 ret = 0;
185 break;
186 }
187 if (ret != 0)
e914ccbe 188 flog_err(EC_ZEBRA_TM_UNRELEASED_CHUNK,
1c50c1c0 189 "%s: Table chunk not released!!", __func__);
50261279
PG
190
191 return ret;
192}
193
194/**
195 * Release table chunks from a client.
196 *
197 * Called on client disconnection or reconnection. It only releases chunks
198 * with empty keep value.
199 *
453844ab 200 * @param client the client to release chunks from
50261279
PG
201 * @return Number of chunks released
202 */
453844ab 203int release_daemon_table_chunks(struct zserv *client)
50261279 204{
453844ab
QY
205 uint8_t proto = client->proto;
206 uint16_t instance = client->instance;
50261279
PG
207 struct listnode *node;
208 struct table_manager_chunk *tmc;
209 int count = 0;
210 int ret;
211
212 for (ALL_LIST_ELEMENTS_RO(tbl_mgr.lc_list, node, tmc)) {
213 if (tmc->proto == proto && tmc->instance == instance) {
214 ret = release_table_chunk(tmc->proto, tmc->instance,
215 tmc->start, tmc->end);
216 if (ret == 0)
217 count++;
218 }
219 }
220
221 zlog_debug("%s: Released %d table chunks", __func__, count);
222
223 return count;
224}
225
226void table_manager_disable(ns_id_t ns_id)
227{
228 if (ns_id != NS_DEFAULT)
229 return;
6a154c88 230 list_delete(&tbl_mgr.lc_list);
50261279 231}