]> git.proxmox.com Git - mirror_frr.git/blame - isisd/isis_tx_queue.c
Merge pull request #3438 from opensourcerouting/bgp-rfapi-default-value
[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"
30#include "dict.h"
31#include "isisd/isis_circuit.h"
32#include "isisd/isis_lsp.h"
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 {
39 void *arg;
40 void (*send_event)(void *arg, struct isis_lsp *, enum isis_tx_type);
41 struct hash *hash;
42};
43
44struct isis_tx_queue_entry {
45 struct isis_lsp *lsp;
46 enum isis_tx_type type;
47 struct thread *retry;
48 struct isis_tx_queue *queue;
49};
50
51static unsigned tx_queue_hash_key(void *p)
52{
53 struct isis_tx_queue_entry *e = p;
54
55 uint32_t id_key = jhash(e->lsp->hdr.lsp_id,
56 ISIS_SYS_ID_LEN + 2, 0x55aa5a5a);
57
58 return jhash_1word(e->lsp->level, id_key);
59}
60
74df8d6d 61static bool tx_queue_hash_cmp(const void *a, const void *b)
9b39405f
CF
62{
63 const struct isis_tx_queue_entry *ea = a, *eb = b;
64
65 if (ea->lsp->level != eb->lsp->level)
74df8d6d 66 return false;
9b39405f
CF
67
68 if (memcmp(ea->lsp->hdr.lsp_id, eb->lsp->hdr.lsp_id,
69 ISIS_SYS_ID_LEN + 2))
74df8d6d 70 return false;
9b39405f 71
74df8d6d 72 return true;
9b39405f
CF
73}
74
75struct isis_tx_queue *isis_tx_queue_new(void *arg,
76 void(*send_event)(void *arg,
77 struct isis_lsp *,
78 enum isis_tx_type))
79{
80 struct isis_tx_queue *rv = XCALLOC(MTYPE_TX_QUEUE, sizeof(*rv));
81
82 rv->arg = arg;
83 rv->send_event = send_event;
84
85 rv->hash = hash_create(tx_queue_hash_key, tx_queue_hash_cmp, NULL);
86 return rv;
87}
88
89static void tx_queue_element_free(void *element)
90{
91 struct isis_tx_queue_entry *e = element;
92
93 if (e->retry)
94 thread_cancel(e->retry);
95
96 XFREE(MTYPE_TX_QUEUE_ENTRY, e);
97}
98
99void isis_tx_queue_free(struct isis_tx_queue *queue)
100{
101 hash_clean(queue->hash, tx_queue_element_free);
102 hash_free(queue->hash);
103 XFREE(MTYPE_TX_QUEUE, queue);
104}
105
106static struct isis_tx_queue_entry *tx_queue_find(struct isis_tx_queue *queue,
107 struct isis_lsp *lsp)
108{
109 struct isis_tx_queue_entry e = {
110 .lsp = lsp
111 };
112
113 return hash_lookup(queue->hash, &e);
114}
115
116static int tx_queue_send_event(struct thread *thread)
117{
118 struct isis_tx_queue_entry *e = THREAD_ARG(thread);
119 struct isis_tx_queue *queue = e->queue;
120
121 e->retry = NULL;
122 thread_add_timer(master, tx_queue_send_event, e, 5, &e->retry);
123
124 queue->send_event(queue->arg, e->lsp, e->type);
125 /* Don't access e here anymore, send_event might have destroyed it */
126
127 return 0;
128}
129
130void isis_tx_queue_add(struct isis_tx_queue *queue,
131 struct isis_lsp *lsp,
132 enum isis_tx_type type)
133{
134 if (!queue)
135 return;
136
137 struct isis_tx_queue_entry *e = tx_queue_find(queue, lsp);
138 if (!e) {
139 e = XCALLOC(MTYPE_TX_QUEUE_ENTRY, sizeof(*e));
140 e->lsp = lsp;
141 e->queue = queue;
142
143 struct isis_tx_queue_entry *inserted;
144 inserted = hash_get(queue->hash, e, hash_alloc_intern);
145 assert(inserted == e);
146 }
147
148 e->type = type;
149
150 if (e->retry)
151 thread_cancel(e->retry);
152 thread_add_event(master, tx_queue_send_event, e, 0, &e->retry);
153}
154
155void isis_tx_queue_del(struct isis_tx_queue *queue, struct isis_lsp *lsp)
156{
157 if (!queue)
158 return;
159
160 struct isis_tx_queue_entry *e = tx_queue_find(queue, lsp);
161 if (!e)
162 return;
163
164 if (e->retry)
165 thread_cancel(e->retry);
166
167 hash_release(queue->hash, e);
168 XFREE(MTYPE_TX_QUEUE_ENTRY, e);
169}
170
171unsigned long isis_tx_queue_len(struct isis_tx_queue *queue)
172{
173 if (!queue)
174 return 0;
175
176 return hashcount(queue->hash);
177}
178
179void isis_tx_queue_clean(struct isis_tx_queue *queue)
180{
181 hash_clean(queue->hash, tx_queue_element_free);
182}