Line data Source code
1 : /* BGP routing table
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 : */
20 :
21 : #include <zebra.h>
22 :
23 : #include "prefix.h"
24 : #include "memory.h"
25 : #include "sockunion.h"
26 : #include "queue.h"
27 : #include "filter.h"
28 : #include "command.h"
29 : #include "printfrr.h"
30 :
31 : #include "bgpd/bgpd.h"
32 : #include "bgpd/bgp_table.h"
33 : #include "bgp_addpath.h"
34 : #include "bgp_trace.h"
35 :
36 3023 : void bgp_table_lock(struct bgp_table *rt)
37 : {
38 3023 : rt->lock++;
39 197 : }
40 :
41 1620 : void bgp_table_unlock(struct bgp_table *rt)
42 : {
43 1620 : assert(rt->lock > 0);
44 1620 : rt->lock--;
45 :
46 1620 : if (rt->lock != 0) {
47 : return;
48 : }
49 :
50 1506 : route_table_finish(rt->route_table);
51 1506 : rt->route_table = NULL;
52 :
53 1506 : XFREE(MTYPE_BGP_TABLE, rt);
54 : }
55 :
56 756 : void bgp_table_finish(struct bgp_table **rt)
57 : {
58 756 : if (*rt != NULL) {
59 756 : bgp_table_unlock(*rt);
60 756 : *rt = NULL;
61 : }
62 756 : }
63 :
64 : /*
65 : * bgp_dest_unlock_node
66 : */
67 982 : void bgp_dest_unlock_node(struct bgp_dest *dest)
68 : {
69 982 : frrtrace(1, frr_bgp, bgp_dest_unlock, dest);
70 982 : bgp_delete_listnode(dest);
71 982 : route_unlock_node(bgp_dest_to_rnode(dest));
72 982 : }
73 :
74 : /*
75 : * bgp_dest_lock_node
76 : */
77 364 : struct bgp_dest *bgp_dest_lock_node(struct bgp_dest *dest)
78 : {
79 364 : frrtrace(1, frr_bgp, bgp_dest_lock, dest);
80 364 : struct route_node *rn = route_lock_node(bgp_dest_to_rnode(dest));
81 :
82 364 : return bgp_dest_from_rnode(rn);
83 : }
84 :
85 : /*
86 : * bgp_dest_get_prefix_str
87 : */
88 0 : const char *bgp_dest_get_prefix_str(struct bgp_dest *dest)
89 : {
90 0 : const struct prefix *p = NULL;
91 0 : static char str[PREFIX_STRLEN] = {0};
92 :
93 0 : p = bgp_dest_get_prefix(dest);
94 0 : if (p)
95 0 : return prefix2str(p, str, sizeof(str));
96 :
97 : return NULL;
98 : }
99 :
100 : /*
101 : * bgp_node_create
102 : */
103 468 : static struct route_node *bgp_node_create(route_table_delegate_t *delegate,
104 : struct route_table *table)
105 : {
106 468 : struct bgp_node *node;
107 468 : node = XCALLOC(MTYPE_BGP_NODE, sizeof(struct bgp_node));
108 :
109 468 : RB_INIT(bgp_adj_out_rb, &node->adj_out);
110 468 : return bgp_dest_to_rnode(node);
111 : }
112 :
113 : /*
114 : * bgp_node_destroy
115 : */
116 294 : static void bgp_node_destroy(route_table_delegate_t *delegate,
117 : struct route_table *table, struct route_node *node)
118 : {
119 294 : struct bgp_node *bgp_node;
120 294 : struct bgp_table *rt;
121 294 : bgp_node = bgp_dest_from_rnode(node);
122 294 : rt = table->info;
123 :
124 294 : if (rt->bgp) {
125 294 : bgp_addpath_free_node_data(&rt->bgp->tx_addpath,
126 : &bgp_node->tx_addpath,
127 : rt->afi, rt->safi);
128 : }
129 :
130 294 : XFREE(MTYPE_BGP_NODE, bgp_node);
131 294 : }
132 :
133 : /*
134 : * Function vector to customize the behavior of the route table
135 : * library for BGP route tables.
136 : */
137 : route_table_delegate_t bgp_table_delegate = {.create_node = bgp_node_create,
138 : .destroy_node = bgp_node_destroy};
139 :
140 : /*
141 : * bgp_table_init
142 : */
143 2826 : struct bgp_table *bgp_table_init(struct bgp *bgp, afi_t afi, safi_t safi)
144 : {
145 2826 : struct bgp_table *rt;
146 :
147 2826 : rt = XCALLOC(MTYPE_BGP_TABLE, sizeof(struct bgp_table));
148 :
149 2826 : rt->route_table = route_table_init_with_delegate(&bgp_table_delegate);
150 :
151 : /*
152 : * Set up back pointer to bgp_table.
153 : */
154 2826 : route_table_set_info(rt->route_table, rt);
155 :
156 : /*
157 : * pointer to bgp instance allows working back from bgp_path_info to bgp
158 : */
159 2826 : rt->bgp = bgp;
160 :
161 2826 : bgp_table_lock(rt);
162 2826 : rt->afi = afi;
163 2826 : rt->safi = safi;
164 :
165 2826 : return rt;
166 : }
167 :
168 : /* Delete the route node from the selection deferral route list */
169 982 : void bgp_delete_listnode(struct bgp_node *node)
170 : {
171 982 : struct route_node *rn = NULL;
172 982 : struct bgp_table *table = NULL;
173 982 : struct bgp *bgp = NULL;
174 982 : afi_t afi;
175 982 : safi_t safi;
176 :
177 : /* If the route to be deleted is selection pending, update the
178 : * route node in gr_info
179 : */
180 982 : if (CHECK_FLAG(node->flags, BGP_NODE_SELECT_DEFER)) {
181 0 : table = bgp_dest_table(node);
182 :
183 0 : if (table) {
184 0 : bgp = table->bgp;
185 0 : afi = table->afi;
186 0 : safi = table->safi;
187 : } else
188 : return;
189 :
190 0 : rn = bgp_dest_to_rnode(node);
191 :
192 0 : if (bgp && rn && rn->lock == 1) {
193 : /* Delete the route from the selection pending list */
194 0 : bgp->gr_info[afi][safi].gr_deferred--;
195 0 : UNSET_FLAG(node->flags, BGP_NODE_SELECT_DEFER);
196 : }
197 : }
198 : }
199 :
200 0 : struct bgp_node *bgp_table_subtree_lookup(const struct bgp_table *table,
201 : const struct prefix *p)
202 : {
203 0 : struct bgp_node *node = bgp_dest_from_rnode(table->route_table->top);
204 0 : struct bgp_node *matched = NULL;
205 :
206 0 : if (node == NULL)
207 : return NULL;
208 :
209 :
210 0 : while (node) {
211 0 : const struct prefix *node_p = bgp_dest_get_prefix(node);
212 :
213 0 : if (node_p->prefixlen >= p->prefixlen) {
214 0 : if (!prefix_match(p, node_p))
215 : return NULL;
216 :
217 : matched = node;
218 : break;
219 : }
220 :
221 0 : if (!prefix_match(node_p, p))
222 : return NULL;
223 :
224 0 : if (node_p->prefixlen == p->prefixlen) {
225 : matched = node;
226 : break;
227 : }
228 :
229 0 : node = bgp_dest_from_rnode(node->link[prefix_bit(
230 : &p->u.prefix, node_p->prefixlen)]);
231 : }
232 :
233 0 : if (!matched)
234 : return NULL;
235 :
236 0 : bgp_dest_lock_node(matched);
237 0 : return matched;
238 : }
239 :
240 34 : printfrr_ext_autoreg_p("BD", printfrr_bd);
241 0 : static ssize_t printfrr_bd(struct fbuf *buf, struct printfrr_eargs *ea,
242 : const void *ptr)
243 : {
244 0 : const struct bgp_dest *dest = ptr;
245 0 : const struct prefix *p = bgp_dest_get_prefix(dest);
246 0 : char cbuf[PREFIX_STRLEN];
247 :
248 0 : if (!dest)
249 0 : return bputs(buf, "(null)");
250 :
251 : /* need to get the real length even if buffer too small */
252 0 : prefix2str(p, cbuf, sizeof(cbuf));
253 0 : return bputs(buf, cbuf);
254 : }
|