]> git.proxmox.com Git - mirror_frr.git/blame - isisd/isis_tx_queue.c
Merge pull request #13649 from donaldsharp/unlock_the_node_or_else
[mirror_frr.git] / isisd / isis_tx_queue.c
CommitLineData
acddc0ed 1// SPDX-License-Identifier: GPL-2.0-or-later
9b39405f
CF
2/*
3 * IS-IS Rout(e)ing protocol - LSP TX Queuing logic
4 *
5 * Copyright (C) 2018 Christian Franke
6 *
8678d638 7 * This file is part of FRRouting (FRR)
9b39405f
CF
8 */
9#include <zebra.h>
10
11#include "hash.h"
12#include "jhash.h"
13
14#include "isisd/isisd.h"
9b39405f 15#include "isisd/isis_flags.h"
9b39405f
CF
16#include "isisd/isis_circuit.h"
17#include "isisd/isis_lsp.h"
161fa356 18#include "isisd/isis_misc.h"
9b39405f
CF
19#include "isisd/isis_tx_queue.h"
20
bf8d3d6a
DL
21DEFINE_MTYPE_STATIC(ISISD, TX_QUEUE, "ISIS TX Queue");
22DEFINE_MTYPE_STATIC(ISISD, TX_QUEUE_ENTRY, "ISIS TX Queue Entry");
9b39405f
CF
23
24struct isis_tx_queue {
161fa356
CF
25 struct isis_circuit *circuit;
26 void (*send_event)(struct isis_circuit *circuit,
27 struct isis_lsp *, enum isis_tx_type);
9b39405f
CF
28 struct hash *hash;
29};
30
31struct isis_tx_queue_entry {
32 struct isis_lsp *lsp;
33 enum isis_tx_type type;
86d6f80d 34 bool is_retry;
e6685141 35 struct event *retry;
9b39405f
CF
36 struct isis_tx_queue *queue;
37};
38
d8b87afe 39static unsigned tx_queue_hash_key(const void *p)
9b39405f 40{
d8b87afe 41 const struct isis_tx_queue_entry *e = p;
9b39405f
CF
42
43 uint32_t id_key = jhash(e->lsp->hdr.lsp_id,
44 ISIS_SYS_ID_LEN + 2, 0x55aa5a5a);
45
46 return jhash_1word(e->lsp->level, id_key);
47}
48
74df8d6d 49static bool tx_queue_hash_cmp(const void *a, const void *b)
9b39405f
CF
50{
51 const struct isis_tx_queue_entry *ea = a, *eb = b;
52
53 if (ea->lsp->level != eb->lsp->level)
74df8d6d 54 return false;
9b39405f
CF
55
56 if (memcmp(ea->lsp->hdr.lsp_id, eb->lsp->hdr.lsp_id,
57 ISIS_SYS_ID_LEN + 2))
74df8d6d 58 return false;
9b39405f 59
74df8d6d 60 return true;
9b39405f
CF
61}
62
161fa356
CF
63struct isis_tx_queue *isis_tx_queue_new(
64 struct isis_circuit *circuit,
65 void(*send_event)(struct isis_circuit *circuit,
66 struct isis_lsp *,
67 enum isis_tx_type))
9b39405f
CF
68{
69 struct isis_tx_queue *rv = XCALLOC(MTYPE_TX_QUEUE, sizeof(*rv));
70
161fa356 71 rv->circuit = circuit;
9b39405f
CF
72 rv->send_event = send_event;
73
74 rv->hash = hash_create(tx_queue_hash_key, tx_queue_hash_cmp, NULL);
75 return rv;
76}
77
78static void tx_queue_element_free(void *element)
79{
80 struct isis_tx_queue_entry *e = element;
81
e16d030c 82 EVENT_OFF(e->retry);
9b39405f
CF
83
84 XFREE(MTYPE_TX_QUEUE_ENTRY, e);
85}
86
87void isis_tx_queue_free(struct isis_tx_queue *queue)
88{
d8bc11a5 89 hash_clean_and_free(&queue->hash, tx_queue_element_free);
9b39405f
CF
90 XFREE(MTYPE_TX_QUEUE, queue);
91}
92
93static struct isis_tx_queue_entry *tx_queue_find(struct isis_tx_queue *queue,
94 struct isis_lsp *lsp)
95{
96 struct isis_tx_queue_entry e = {
97 .lsp = lsp
98 };
99
100 return hash_lookup(queue->hash, &e);
101}
102
e6685141 103static void tx_queue_send_event(struct event *thread)
9b39405f 104{
e16d030c 105 struct isis_tx_queue_entry *e = EVENT_ARG(thread);
9b39405f
CF
106 struct isis_tx_queue *queue = e->queue;
107
907a2395 108 event_add_timer(master, tx_queue_send_event, e, 5, &e->retry);
9b39405f 109
89cdc4df 110 if (e->is_retry)
86d6f80d 111 queue->circuit->area->lsp_rxmt_count++;
89cdc4df 112 else
86d6f80d 113 e->is_retry = true;
89cdc4df 114
161fa356 115 queue->send_event(queue->circuit, e->lsp, e->type);
9b39405f 116 /* Don't access e here anymore, send_event might have destroyed it */
9b39405f
CF
117}
118
161fa356
CF
119void _isis_tx_queue_add(struct isis_tx_queue *queue,
120 struct isis_lsp *lsp,
121 enum isis_tx_type type,
122 const char *func, const char *file,
123 int line)
9b39405f
CF
124{
125 if (!queue)
126 return;
127
e740f9c1 128 if (IS_DEBUG_TX_QUEUE) {
5d39a819
OD
129 zlog_debug(
130 "Add LSP %pLS to %s queue as %s LSP. (From %s %s:%d)",
131 lsp->hdr.lsp_id, queue->circuit->interface->name,
132 (type == TX_LSP_CIRCUIT_SCOPED) ? "circuit scoped"
133 : "regular",
134 func, file, line);
161fa356
CF
135 }
136
9b39405f
CF
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
e16d030c 150 EVENT_OFF(e->retry);
907a2395 151 event_add_event(master, tx_queue_send_event, e, 0, &e->retry);
86d6f80d
CF
152
153 e->is_retry = false;
9b39405f
CF
154}
155
161fa356
CF
156void _isis_tx_queue_del(struct isis_tx_queue *queue, struct isis_lsp *lsp,
157 const char *func, const char *file, int line)
9b39405f
CF
158{
159 if (!queue)
160 return;
161
162 struct isis_tx_queue_entry *e = tx_queue_find(queue, lsp);
163 if (!e)
164 return;
165
e740f9c1 166 if (IS_DEBUG_TX_QUEUE) {
5d39a819
OD
167 zlog_debug("Remove LSP %pLS from %s queue. (From %s %s:%d)",
168 lsp->hdr.lsp_id, queue->circuit->interface->name,
161fa356
CF
169 func, file, line);
170 }
171
e16d030c 172 EVENT_OFF(e->retry);
9b39405f
CF
173
174 hash_release(queue->hash, e);
175 XFREE(MTYPE_TX_QUEUE_ENTRY, e);
176}
177
178unsigned long isis_tx_queue_len(struct isis_tx_queue *queue)
179{
180 if (!queue)
181 return 0;
182
183 return hashcount(queue->hash);
184}
185
186void isis_tx_queue_clean(struct isis_tx_queue *queue)
187{
188 hash_clean(queue->hash, tx_queue_element_free);
189}