]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_table.c
Merge pull request #13649 from donaldsharp/unlock_the_node_or_else
[mirror_frr.git] / bgpd / bgp_table.c
CommitLineData
acddc0ed 1// SPDX-License-Identifier: GPL-2.0-or-later
718e3744 2/* BGP routing table
896014f4 3 * Copyright (C) 1998, 2001 Kunihiro Ishiguro
896014f4 4 */
718e3744 5
6#include <zebra.h>
7
8#include "prefix.h"
9#include "memory.h"
10#include "sockunion.h"
3f9c7369 11#include "queue.h"
039f3a34 12#include "filter.h"
4dcadbef 13#include "command.h"
56ca3b5b 14#include "printfrr.h"
718e3744 15
16#include "bgpd/bgpd.h"
17#include "bgpd/bgp_table.h"
dcc68b5e 18#include "bgp_addpath.h"
63836a96 19#include "bgp_trace.h"
718e3744 20
d62a17ae 21void bgp_table_lock(struct bgp_table *rt)
228da428 22{
d62a17ae 23 rt->lock++;
228da428
CC
24}
25
d62a17ae 26void bgp_table_unlock(struct bgp_table *rt)
228da428 27{
d62a17ae 28 assert(rt->lock > 0);
29 rt->lock--;
228da428 30
d62a17ae 31 if (rt->lock != 0) {
32 return;
33 }
718e3744 34
d62a17ae 35 route_table_finish(rt->route_table);
36 rt->route_table = NULL;
228da428 37
d62a17ae 38 XFREE(MTYPE_BGP_TABLE, rt);
718e3744 39}
40
d62a17ae 41void bgp_table_finish(struct bgp_table **rt)
718e3744 42{
d62a17ae 43 if (*rt != NULL) {
44 bgp_table_unlock(*rt);
45 *rt = NULL;
46 }
718e3744 47}
48
63836a96
DA
49/*
50 * bgp_dest_unlock_node
51 */
52void bgp_dest_unlock_node(struct bgp_dest *dest)
53{
54 frrtrace(1, frr_bgp, bgp_dest_unlock, dest);
55 bgp_delete_listnode(dest);
56 route_unlock_node(bgp_dest_to_rnode(dest));
57}
58
59/*
60 * bgp_dest_lock_node
61 */
62struct bgp_dest *bgp_dest_lock_node(struct bgp_dest *dest)
63{
64 frrtrace(1, frr_bgp, bgp_dest_lock, dest);
65 struct route_node *rn = route_lock_node(bgp_dest_to_rnode(dest));
66
67 return bgp_dest_from_rnode(rn);
68}
69
70/*
71 * bgp_dest_get_prefix_str
72 */
73const char *bgp_dest_get_prefix_str(struct bgp_dest *dest)
74{
75 const struct prefix *p = NULL;
95f473e0 76 static char str[PREFIX_STRLEN] = {0};
63836a96
DA
77
78 p = bgp_dest_get_prefix(dest);
79 if (p)
80 return prefix2str(p, str, sizeof(str));
81
82 return NULL;
83}
84
67174041
AS
85/*
86 * bgp_node_create
87 */
d62a17ae 88static struct route_node *bgp_node_create(route_table_delegate_t *delegate,
89 struct route_table *table)
718e3744 90{
d62a17ae 91 struct bgp_node *node;
92 node = XCALLOC(MTYPE_BGP_NODE, sizeof(struct bgp_node));
a79c04e7
DS
93
94 RB_INIT(bgp_adj_out_rb, &node->adj_out);
9bcb3eef 95 return bgp_dest_to_rnode(node);
718e3744 96}
97
67174041
AS
98/*
99 * bgp_node_destroy
100 */
d62a17ae 101static void bgp_node_destroy(route_table_delegate_t *delegate,
102 struct route_table *table, struct route_node *node)
718e3744 103{
d62a17ae 104 struct bgp_node *bgp_node;
dcc68b5e 105 struct bgp_table *rt;
9bcb3eef 106 bgp_node = bgp_dest_from_rnode(node);
dcc68b5e
MS
107 rt = table->info;
108
109 if (rt->bgp) {
110 bgp_addpath_free_node_data(&rt->bgp->tx_addpath,
111 &bgp_node->tx_addpath,
112 rt->afi, rt->safi);
113 }
114
d62a17ae 115 XFREE(MTYPE_BGP_NODE, bgp_node);
718e3744 116}
117
67174041
AS
118/*
119 * Function vector to customize the behavior of the route table
120 * library for BGP route tables.
121 */
d62a17ae 122route_table_delegate_t bgp_table_delegate = {.create_node = bgp_node_create,
123 .destroy_node = bgp_node_destroy};
718e3744 124
67174041
AS
125/*
126 * bgp_table_init
127 */
960035b2 128struct bgp_table *bgp_table_init(struct bgp *bgp, afi_t afi, safi_t safi)
718e3744 129{
d62a17ae 130 struct bgp_table *rt;
718e3744 131
d62a17ae 132 rt = XCALLOC(MTYPE_BGP_TABLE, sizeof(struct bgp_table));
718e3744 133
d62a17ae 134 rt->route_table = route_table_init_with_delegate(&bgp_table_delegate);
718e3744 135
d62a17ae 136 /*
137 * Set up back pointer to bgp_table.
138 */
6ca30e9e 139 route_table_set_info(rt->route_table, rt);
718e3744 140
960035b2 141 /*
9b6d8fcf 142 * pointer to bgp instance allows working back from bgp_path_info to bgp
960035b2
PZ
143 */
144 rt->bgp = bgp;
145
d62a17ae 146 bgp_table_lock(rt);
147 rt->afi = afi;
148 rt->safi = safi;
cbdfbaa5 149
d62a17ae 150 return rt;
cbdfbaa5 151}
1dacdd8b 152
f009ff26 153/* Delete the route node from the selection deferral route list */
154void bgp_delete_listnode(struct bgp_node *node)
155{
156 struct route_node *rn = NULL;
157 struct bgp_table *table = NULL;
158 struct bgp *bgp = NULL;
159 afi_t afi;
160 safi_t safi;
161
162 /* If the route to be deleted is selection pending, update the
163 * route node in gr_info
164 */
165 if (CHECK_FLAG(node->flags, BGP_NODE_SELECT_DEFER)) {
9bcb3eef 166 table = bgp_dest_table(node);
9e3b51a7 167
168 if (table) {
f009ff26 169 bgp = table->bgp;
9e3b51a7 170 afi = table->afi;
171 safi = table->safi;
2ba1fe69 172 } else
173 return;
174
9bcb3eef 175 rn = bgp_dest_to_rnode(node);
f009ff26 176
f009ff26 177 if (bgp && rn && rn->lock == 1) {
178 /* Delete the route from the selection pending list */
26742171
DS
179 bgp->gr_info[afi][safi].gr_deferred--;
180 UNSET_FLAG(node->flags, BGP_NODE_SELECT_DEFER);
f009ff26 181 }
182 }
183}
184
bac31cb8
MR
185struct bgp_node *bgp_table_subtree_lookup(const struct bgp_table *table,
186 const struct prefix *p)
1dacdd8b 187{
9bcb3eef 188 struct bgp_node *node = bgp_dest_from_rnode(table->route_table->top);
bac31cb8 189 struct bgp_node *matched = NULL;
b54892e0 190
bac31cb8
MR
191 if (node == NULL)
192 return NULL;
b54892e0 193
b54892e0 194
bac31cb8 195 while (node) {
9bcb3eef 196 const struct prefix *node_p = bgp_dest_get_prefix(node);
b54892e0 197
bac31cb8
MR
198 if (node_p->prefixlen >= p->prefixlen) {
199 if (!prefix_match(p, node_p))
200 return NULL;
1dacdd8b 201
bac31cb8
MR
202 matched = node;
203 break;
1dacdd8b 204 }
1dacdd8b 205
bac31cb8
MR
206 if (!prefix_match(node_p, p))
207 return NULL;
1dacdd8b 208
bac31cb8 209 if (node_p->prefixlen == p->prefixlen) {
1dacdd8b
MR
210 matched = node;
211 break;
212 }
bac31cb8 213
9bcb3eef 214 node = bgp_dest_from_rnode(node->link[prefix_bit(
b54892e0 215 &p->u.prefix, node_p->prefixlen)]);
1dacdd8b
MR
216 }
217
5911f65c 218 if (!matched)
bac31cb8 219 return NULL;
1dacdd8b 220
9bcb3eef 221 bgp_dest_lock_node(matched);
bac31cb8 222 return matched;
1dacdd8b 223}
56ca3b5b 224
54929fd3 225printfrr_ext_autoreg_p("BD", printfrr_bd);
3ea79430
DL
226static ssize_t printfrr_bd(struct fbuf *buf, struct printfrr_eargs *ea,
227 const void *ptr)
56ca3b5b
DL
228{
229 const struct bgp_dest *dest = ptr;
212e04e5
DL
230 const struct prefix *p = bgp_dest_get_prefix(dest);
231 char cbuf[PREFIX_STRLEN];
001ab42b 232
212e04e5 233 if (!dest)
eba599a3 234 return bputs(buf, "(null)");
56ca3b5b 235
212e04e5
DL
236 /* need to get the real length even if buffer too small */
237 prefix2str(p, cbuf, sizeof(cbuf));
238 return bputs(buf, cbuf);
56ca3b5b 239}