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