]> git.proxmox.com Git - mirror_frr.git/blame - isisd/isis_tx_queue.c
Merge pull request #5580 from mjstapp/zebra_nhg_debug_category
[mirror_frr.git] / isisd / isis_tx_queue.c
CommitLineData
9b39405f
CF
1/*
2 * IS-IS Rout(e)ing protocol - LSP TX Queuing logic
3 *
4 * Copyright (C) 2018 Christian Franke
5 *
6 * This file is part of FreeRangeRouting (FRR)
7 *
8 * FRR is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2, or (at your option) any
11 * later version.
12 *
13 * FRR is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; see the file COPYING; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21 */
22#include <zebra.h>
23
24#include "hash.h"
25#include "jhash.h"
26
27#include "isisd/isisd.h"
28#include "isisd/isis_memory.h"
29#include "isisd/isis_flags.h"
9b39405f
CF
30#include "isisd/isis_circuit.h"
31#include "isisd/isis_lsp.h"
161fa356 32#include "isisd/isis_misc.h"
9b39405f
CF
33#include "isisd/isis_tx_queue.h"
34
35DEFINE_MTYPE_STATIC(ISISD, TX_QUEUE, "ISIS TX Queue")
36DEFINE_MTYPE_STATIC(ISISD, TX_QUEUE_ENTRY, "ISIS TX Queue Entry")
37
38struct isis_tx_queue {
161fa356
CF
39 struct isis_circuit *circuit;
40 void (*send_event)(struct isis_circuit *circuit,
41 struct isis_lsp *, enum isis_tx_type);
9b39405f
CF
42 struct hash *hash;
43};
44
45struct isis_tx_queue_entry {
46 struct isis_lsp *lsp;
47 enum isis_tx_type type;
86d6f80d 48 bool is_retry;
9b39405f
CF
49 struct thread *retry;
50 struct isis_tx_queue *queue;
51};
52
d8b87afe 53static unsigned tx_queue_hash_key(const void *p)
9b39405f 54{
d8b87afe 55 const struct isis_tx_queue_entry *e = p;
9b39405f
CF
56
57 uint32_t id_key = jhash(e->lsp->hdr.lsp_id,
58 ISIS_SYS_ID_LEN + 2, 0x55aa5a5a);
59
60 return jhash_1word(e->lsp->level, id_key);
61}
62
74df8d6d 63static bool tx_queue_hash_cmp(const void *a, const void *b)
9b39405f
CF
64{
65 const struct isis_tx_queue_entry *ea = a, *eb = b;
66
67 if (ea->lsp->level != eb->lsp->level)
74df8d6d 68 return false;
9b39405f
CF
69
70 if (memcmp(ea->lsp->hdr.lsp_id, eb->lsp->hdr.lsp_id,
71 ISIS_SYS_ID_LEN + 2))
74df8d6d 72 return false;
9b39405f 73
74df8d6d 74 return true;
9b39405f
CF
75}
76
161fa356
CF
77struct isis_tx_queue *isis_tx_queue_new(
78 struct isis_circuit *circuit,
79 void(*send_event)(struct isis_circuit *circuit,
80 struct isis_lsp *,
81 enum isis_tx_type))
9b39405f
CF
82{
83 struct isis_tx_queue *rv = XCALLOC(MTYPE_TX_QUEUE, sizeof(*rv));
84
161fa356 85 rv->circuit = circuit;
9b39405f
CF
86 rv->send_event = send_event;
87
88 rv->hash = hash_create(tx_queue_hash_key, tx_queue_hash_cmp, NULL);
89 return rv;
90}
91
92static void tx_queue_element_free(void *element)
93{
94 struct isis_tx_queue_entry *e = element;
95
96 if (e->retry)
97 thread_cancel(e->retry);
98
99 XFREE(MTYPE_TX_QUEUE_ENTRY, e);
100}
101
102void isis_tx_queue_free(struct isis_tx_queue *queue)
103{
104 hash_clean(queue->hash, tx_queue_element_free);
105 hash_free(queue->hash);
106 XFREE(MTYPE_TX_QUEUE, queue);
107}
108
109static struct isis_tx_queue_entry *tx_queue_find(struct isis_tx_queue *queue,
110 struct isis_lsp *lsp)
111{
112 struct isis_tx_queue_entry e = {
113 .lsp = lsp
114 };
115
116 return hash_lookup(queue->hash, &e);
117}
118
119static int tx_queue_send_event(struct thread *thread)
120{
121 struct isis_tx_queue_entry *e = THREAD_ARG(thread);
122 struct isis_tx_queue *queue = e->queue;
123
124 e->retry = NULL;
125 thread_add_timer(master, tx_queue_send_event, e, 5, &e->retry);
126
89cdc4df 127 if (e->is_retry)
86d6f80d 128 queue->circuit->area->lsp_rxmt_count++;
89cdc4df 129 else
86d6f80d 130 e->is_retry = true;
89cdc4df 131
161fa356 132 queue->send_event(queue->circuit, e->lsp, e->type);
9b39405f
CF
133 /* Don't access e here anymore, send_event might have destroyed it */
134
135 return 0;
136}
137
161fa356
CF
138void _isis_tx_queue_add(struct isis_tx_queue *queue,
139 struct isis_lsp *lsp,
140 enum isis_tx_type type,
141 const char *func, const char *file,
142 int line)
9b39405f
CF
143{
144 if (!queue)
145 return;
146
161fa356
CF
147 if (isis->debugs & DEBUG_TX_QUEUE) {
148 zlog_debug("Add LSP %s to %s queue as %s LSP. (From %s %s:%d)",
149 rawlspid_print(lsp->hdr.lsp_id),
150 queue->circuit->interface->name,
151 (type == TX_LSP_CIRCUIT_SCOPED) ?
152 "circuit scoped" : "regular",
153 func, file, line);
154 }
155
9b39405f
CF
156 struct isis_tx_queue_entry *e = tx_queue_find(queue, lsp);
157 if (!e) {
158 e = XCALLOC(MTYPE_TX_QUEUE_ENTRY, sizeof(*e));
159 e->lsp = lsp;
160 e->queue = queue;
161
162 struct isis_tx_queue_entry *inserted;
163 inserted = hash_get(queue->hash, e, hash_alloc_intern);
164 assert(inserted == e);
165 }
166
167 e->type = type;
168
169 if (e->retry)
170 thread_cancel(e->retry);
171 thread_add_event(master, tx_queue_send_event, e, 0, &e->retry);
86d6f80d
CF
172
173 e->is_retry = false;
9b39405f
CF
174}
175
161fa356
CF
176void _isis_tx_queue_del(struct isis_tx_queue *queue, struct isis_lsp *lsp,
177 const char *func, const char *file, int line)
9b39405f
CF
178{
179 if (!queue)
180 return;
181
182 struct isis_tx_queue_entry *e = tx_queue_find(queue, lsp);
183 if (!e)
184 return;
185
161fa356
CF
186 if (isis->debugs & DEBUG_TX_QUEUE) {
187 zlog_debug("Remove LSP %s from %s queue. (From %s %s:%d)",
188 rawlspid_print(lsp->hdr.lsp_id),
189 queue->circuit->interface->name,
190 func, file, line);
191 }
192
9b39405f
CF
193 if (e->retry)
194 thread_cancel(e->retry);
195
196 hash_release(queue->hash, e);
197 XFREE(MTYPE_TX_QUEUE_ENTRY, e);
198}
199
200unsigned long isis_tx_queue_len(struct isis_tx_queue *queue)
201{
202 if (!queue)
203 return 0;
204
205 return hashcount(queue->hash);
206}
207
208void isis_tx_queue_clean(struct isis_tx_queue *queue)
209{
210 hash_clean(queue->hash, tx_queue_element_free);
211}