]> git.proxmox.com Git - mirror_frr.git/blob - isisd/isis_tx_queue.c
lib: enforce vrf_name_to_id by returning default_vrf when name is null
[mirror_frr.git] / isisd / isis_tx_queue.c
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"
30 #include "dict.h"
31 #include "isisd/isis_circuit.h"
32 #include "isisd/isis_lsp.h"
33 #include "isisd/isis_misc.h"
34 #include "isisd/isis_tx_queue.h"
35
36 DEFINE_MTYPE_STATIC(ISISD, TX_QUEUE, "ISIS TX Queue")
37 DEFINE_MTYPE_STATIC(ISISD, TX_QUEUE_ENTRY, "ISIS TX Queue Entry")
38
39 struct isis_tx_queue {
40 struct isis_circuit *circuit;
41 void (*send_event)(struct isis_circuit *circuit,
42 struct isis_lsp *, enum isis_tx_type);
43 struct hash *hash;
44 };
45
46 struct isis_tx_queue_entry {
47 struct isis_lsp *lsp;
48 enum isis_tx_type type;
49 bool is_retry;
50 struct thread *retry;
51 struct isis_tx_queue *queue;
52 };
53
54 static unsigned tx_queue_hash_key(void *p)
55 {
56 struct isis_tx_queue_entry *e = p;
57
58 uint32_t id_key = jhash(e->lsp->hdr.lsp_id,
59 ISIS_SYS_ID_LEN + 2, 0x55aa5a5a);
60
61 return jhash_1word(e->lsp->level, id_key);
62 }
63
64 static bool tx_queue_hash_cmp(const void *a, const void *b)
65 {
66 const struct isis_tx_queue_entry *ea = a, *eb = b;
67
68 if (ea->lsp->level != eb->lsp->level)
69 return false;
70
71 if (memcmp(ea->lsp->hdr.lsp_id, eb->lsp->hdr.lsp_id,
72 ISIS_SYS_ID_LEN + 2))
73 return false;
74
75 return true;
76 }
77
78 struct isis_tx_queue *isis_tx_queue_new(
79 struct isis_circuit *circuit,
80 void(*send_event)(struct isis_circuit *circuit,
81 struct isis_lsp *,
82 enum isis_tx_type))
83 {
84 struct isis_tx_queue *rv = XCALLOC(MTYPE_TX_QUEUE, sizeof(*rv));
85
86 rv->circuit = circuit;
87 rv->send_event = send_event;
88
89 rv->hash = hash_create(tx_queue_hash_key, tx_queue_hash_cmp, NULL);
90 return rv;
91 }
92
93 static void tx_queue_element_free(void *element)
94 {
95 struct isis_tx_queue_entry *e = element;
96
97 if (e->retry)
98 thread_cancel(e->retry);
99
100 XFREE(MTYPE_TX_QUEUE_ENTRY, e);
101 }
102
103 void isis_tx_queue_free(struct isis_tx_queue *queue)
104 {
105 hash_clean(queue->hash, tx_queue_element_free);
106 hash_free(queue->hash);
107 XFREE(MTYPE_TX_QUEUE, queue);
108 }
109
110 static struct isis_tx_queue_entry *tx_queue_find(struct isis_tx_queue *queue,
111 struct isis_lsp *lsp)
112 {
113 struct isis_tx_queue_entry e = {
114 .lsp = lsp
115 };
116
117 return hash_lookup(queue->hash, &e);
118 }
119
120 static int tx_queue_send_event(struct thread *thread)
121 {
122 struct isis_tx_queue_entry *e = THREAD_ARG(thread);
123 struct isis_tx_queue *queue = e->queue;
124
125 e->retry = NULL;
126 thread_add_timer(master, tx_queue_send_event, e, 5, &e->retry);
127
128 if (e->is_retry)
129 queue->circuit->area->lsp_rxmt_count++;
130 else
131 e->is_retry = true;
132
133 queue->send_event(queue->circuit, e->lsp, e->type);
134 /* Don't access e here anymore, send_event might have destroyed it */
135
136 return 0;
137 }
138
139 void _isis_tx_queue_add(struct isis_tx_queue *queue,
140 struct isis_lsp *lsp,
141 enum isis_tx_type type,
142 const char *func, const char *file,
143 int line)
144 {
145 if (!queue)
146 return;
147
148 if (isis->debugs & DEBUG_TX_QUEUE) {
149 zlog_debug("Add LSP %s to %s queue as %s LSP. (From %s %s:%d)",
150 rawlspid_print(lsp->hdr.lsp_id),
151 queue->circuit->interface->name,
152 (type == TX_LSP_CIRCUIT_SCOPED) ?
153 "circuit scoped" : "regular",
154 func, file, line);
155 }
156
157 struct isis_tx_queue_entry *e = tx_queue_find(queue, lsp);
158 if (!e) {
159 e = XCALLOC(MTYPE_TX_QUEUE_ENTRY, sizeof(*e));
160 e->lsp = lsp;
161 e->queue = queue;
162
163 struct isis_tx_queue_entry *inserted;
164 inserted = hash_get(queue->hash, e, hash_alloc_intern);
165 assert(inserted == e);
166 }
167
168 e->type = type;
169
170 if (e->retry)
171 thread_cancel(e->retry);
172 thread_add_event(master, tx_queue_send_event, e, 0, &e->retry);
173
174 e->is_retry = false;
175 }
176
177 void _isis_tx_queue_del(struct isis_tx_queue *queue, struct isis_lsp *lsp,
178 const char *func, const char *file, int line)
179 {
180 if (!queue)
181 return;
182
183 struct isis_tx_queue_entry *e = tx_queue_find(queue, lsp);
184 if (!e)
185 return;
186
187 if (isis->debugs & DEBUG_TX_QUEUE) {
188 zlog_debug("Remove LSP %s from %s queue. (From %s %s:%d)",
189 rawlspid_print(lsp->hdr.lsp_id),
190 queue->circuit->interface->name,
191 func, file, line);
192 }
193
194 if (e->retry)
195 thread_cancel(e->retry);
196
197 hash_release(queue->hash, e);
198 XFREE(MTYPE_TX_QUEUE_ENTRY, e);
199 }
200
201 unsigned long isis_tx_queue_len(struct isis_tx_queue *queue)
202 {
203 if (!queue)
204 return 0;
205
206 return hashcount(queue->hash);
207 }
208
209 void isis_tx_queue_clean(struct isis_tx_queue *queue)
210 {
211 hash_clean(queue->hash, tx_queue_element_free);
212 }