]> git.proxmox.com Git - mirror_frr.git/blame - zebra/table_manager.c
isisd: implement the 'lsp-too-large' notification
[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 */
43#ifdef SUNOS_5
44/* SunOS
45 */
46#else
47#if !defined(GNU_LINUX) && !defined(SUNOS_5)
48/* BSD systems
49 */
50#else
51/* Linux Systems
52 */
53#define RT_TABLE_ID_LOCAL 255
54#define RT_TABLE_ID_MAIN 254
55#define RT_TABLE_ID_DEFAULT 253
56#define RT_TABLE_ID_COMPAT 252
57#define RT_TABLE_ID_UNSPEC 0
58#endif /* !def(GNU_LINUX) && !defined(SUNOS_5) */
59#endif /* SUNOS_5 */
60#define RT_TABLE_ID_UNRESERVED_MIN 1
61#define RT_TABLE_ID_UNRESERVED_MAX 0xffffffff
62
63struct table_manager tbl_mgr;
64
65DEFINE_MGROUP(TABLE_MGR, "Table Manager");
66DEFINE_MTYPE_STATIC(TABLE_MGR, TM_CHUNK, "Table Manager Chunk");
67
68static void delete_table_chunk(void *val)
69{
70 XFREE(MTYPE_TM_CHUNK, val);
71}
72
73/**
74 * Init table manager
75 */
76void table_manager_enable(ns_id_t ns_id)
77{
78 if (ns_id != NS_DEFAULT)
79 return;
80 tbl_mgr.lc_list = list_new();
81 tbl_mgr.lc_list->del = delete_table_chunk;
21ccc0cf 82 hook_register(zserv_client_close, release_daemon_table_chunks);
50261279
PG
83}
84
85/**
86 * Core function, assigns table chunks
87 *
88 * It first searches through the list to check if there's one available
89 * (previously released). Otherwise it creates and assigns a new one
90 *
91 * @param proto Daemon protocol of client, to identify the owner
92 * @param instance Instance, to identify the owner
93 * @para size Size of the table chunk
94 * @return Pointer to the assigned table chunk
95 */
96struct table_manager_chunk *assign_table_chunk(uint8_t proto, uint16_t instance,
97 uint32_t size)
98{
99 struct table_manager_chunk *tmc;
100 struct listnode *node;
101 uint32_t start;
102
103 /* first check if there's one available */
104 for (ALL_LIST_ELEMENTS_RO(tbl_mgr.lc_list, node, tmc)) {
105 if (tmc->proto == NO_PROTO
106 && tmc->end - tmc->start + 1 == size) {
107 tmc->proto = proto;
108 tmc->instance = instance;
109 return tmc;
110 }
111 }
112 /* otherwise create a new one */
113 tmc = XCALLOC(MTYPE_TM_CHUNK, sizeof(struct table_manager_chunk));
114 if (!tmc)
115 return NULL;
116
117 /* table RT IDs range are [1;252] and [256;0xffffffff]
118 * - check if the requested range can be within the first range,
119 * otherwise elect second one
120 * - TODO : vrf-lites have their own table identifier.
121 * In that case, table_id should be removed from the table range.
122 */
123 if (list_isempty(tbl_mgr.lc_list))
124 start = RT_TABLE_ID_UNRESERVED_MIN;
125 else
126 start = ((struct table_manager_chunk *)listgetdata(
127 listtail(tbl_mgr.lc_list)))->end + 1;
128
129#ifdef SUNOS_5
130/* SunOS
131 */
132#else
133#if !defined(GNU_LINUX) && !defined(SUNOS_5)
134/* BSD systems
135 */
136#else
137/* Linux Systems
138 */
139 /* if not enough room space between MIN and COMPAT,
140 * then begin after LOCAL
141 */
142 if (start < RT_TABLE_ID_COMPAT && (size >
143 RT_TABLE_ID_COMPAT
144 - RT_TABLE_ID_UNRESERVED_MIN))
145 start = RT_TABLE_ID_LOCAL + 1;
146#endif /* !def(GNU_LINUX) && !defined(SUNOS_5) */
147#endif /* SUNOS_5 */
148 tmc->start = start;
149 if (RT_TABLE_ID_UNRESERVED_MAX - size + 1 < start) {
e914ccbe 150 flog_err(EC_ZEBRA_TM_EXHAUSTED_IDS,
1c50c1c0 151 "Reached max table id. Start/Size %u/%u", start, size);
50261279
PG
152 XFREE(MTYPE_TM_CHUNK, tmc);
153 return NULL;
154 }
155 tmc->end = tmc->start + size - 1;
156 tmc->proto = proto;
157 tmc->instance = instance;
158 listnode_add(tbl_mgr.lc_list, tmc);
159
160 return tmc;
161}
162
163/**
164 * Core function, release no longer used table chunks
165 *
166 * @param proto Daemon protocol of client, to identify the owner
167 * @param instance Instance, to identify the owner
168 * @param start First table RT ID of the chunk
169 * @param end Last table RT ID of the chunk
170 * @return 0 on success, -1 otherwise
171 */
172int release_table_chunk(uint8_t proto, uint16_t instance, uint32_t start,
173 uint32_t end)
174{
175 struct listnode *node;
176 struct table_manager_chunk *tmc;
177 int ret = -1;
178
179 /* check that size matches */
180 zlog_debug("Releasing table chunk: %u - %u", start, end);
181 /* find chunk and disown */
182 for (ALL_LIST_ELEMENTS_RO(tbl_mgr.lc_list, node, tmc)) {
183 if (tmc->start != start)
184 continue;
185 if (tmc->end != end)
186 continue;
187 if (tmc->proto != proto || tmc->instance != instance) {
e914ccbe 188 flog_err(EC_ZEBRA_TM_DAEMON_MISMATCH,
1c50c1c0 189 "%s: Daemon mismatch!!", __func__);
50261279
PG
190 continue;
191 }
192 tmc->proto = NO_PROTO;
193 tmc->instance = 0;
194 ret = 0;
195 break;
196 }
197 if (ret != 0)
e914ccbe 198 flog_err(EC_ZEBRA_TM_UNRELEASED_CHUNK,
1c50c1c0 199 "%s: Table chunk not released!!", __func__);
50261279
PG
200
201 return ret;
202}
203
204/**
205 * Release table chunks from a client.
206 *
207 * Called on client disconnection or reconnection. It only releases chunks
208 * with empty keep value.
209 *
453844ab 210 * @param client the client to release chunks from
50261279
PG
211 * @return Number of chunks released
212 */
453844ab 213int release_daemon_table_chunks(struct zserv *client)
50261279 214{
453844ab
QY
215 uint8_t proto = client->proto;
216 uint16_t instance = client->instance;
50261279
PG
217 struct listnode *node;
218 struct table_manager_chunk *tmc;
219 int count = 0;
220 int ret;
221
222 for (ALL_LIST_ELEMENTS_RO(tbl_mgr.lc_list, node, tmc)) {
223 if (tmc->proto == proto && tmc->instance == instance) {
224 ret = release_table_chunk(tmc->proto, tmc->instance,
225 tmc->start, tmc->end);
226 if (ret == 0)
227 count++;
228 }
229 }
230
231 zlog_debug("%s: Released %d table chunks", __func__, count);
232
233 return count;
234}
235
236void table_manager_disable(ns_id_t ns_id)
237{
238 if (ns_id != NS_DEFAULT)
239 return;
6a154c88 240 list_delete(&tbl_mgr.lc_list);
50261279 241}