]> git.proxmox.com Git - mirror_frr.git/blame - isisd/isis_tx_queue.c
Merge pull request #13060 from opensourcerouting/feature/allow_peering_with_127.0.0.1
[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) {
161fa356
CF
129 zlog_debug("Add LSP %s to %s queue as %s LSP. (From %s %s:%d)",
130 rawlspid_print(lsp->hdr.lsp_id),
131 queue->circuit->interface->name,
132 (type == TX_LSP_CIRCUIT_SCOPED) ?
133 "circuit scoped" : "regular",
134 func, file, line);
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) {
161fa356
CF
167 zlog_debug("Remove LSP %s from %s queue. (From %s %s:%d)",
168 rawlspid_print(lsp->hdr.lsp_id),
169 queue->circuit->interface->name,
170 func, file, line);
171 }
172
e16d030c 173 EVENT_OFF(e->retry);
9b39405f
CF
174
175 hash_release(queue->hash, e);
176 XFREE(MTYPE_TX_QUEUE_ENTRY, e);
177}
178
179unsigned long isis_tx_queue_len(struct isis_tx_queue *queue)
180{
181 if (!queue)
182 return 0;
183
184 return hashcount(queue->hash);
185}
186
187void isis_tx_queue_clean(struct isis_tx_queue *queue)
188{
189 hash_clean(queue->hash, tx_queue_element_free);
190}