]>
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" |
718e3744 | 34 | |
d62a17ae | 35 | void bgp_table_lock(struct bgp_table *rt) |
228da428 | 36 | { |
d62a17ae | 37 | rt->lock++; |
228da428 CC |
38 | } |
39 | ||
d62a17ae | 40 | void bgp_table_unlock(struct bgp_table *rt) |
228da428 | 41 | { |
d62a17ae | 42 | assert(rt->lock > 0); |
43 | rt->lock--; | |
228da428 | 44 | |
d62a17ae | 45 | if (rt->lock != 0) { |
46 | return; | |
47 | } | |
718e3744 | 48 | |
d62a17ae | 49 | route_table_finish(rt->route_table); |
50 | rt->route_table = NULL; | |
228da428 | 51 | |
d62a17ae | 52 | XFREE(MTYPE_BGP_TABLE, rt); |
718e3744 | 53 | } |
54 | ||
d62a17ae | 55 | void bgp_table_finish(struct bgp_table **rt) |
718e3744 | 56 | { |
d62a17ae | 57 | if (*rt != NULL) { |
58 | bgp_table_unlock(*rt); | |
59 | *rt = NULL; | |
60 | } | |
718e3744 | 61 | } |
62 | ||
67174041 AS |
63 | /* |
64 | * bgp_node_create | |
65 | */ | |
d62a17ae | 66 | static struct route_node *bgp_node_create(route_table_delegate_t *delegate, |
67 | struct route_table *table) | |
718e3744 | 68 | { |
d62a17ae | 69 | struct bgp_node *node; |
70 | node = XCALLOC(MTYPE_BGP_NODE, sizeof(struct bgp_node)); | |
a79c04e7 DS |
71 | |
72 | RB_INIT(bgp_adj_out_rb, &node->adj_out); | |
9bcb3eef | 73 | return bgp_dest_to_rnode(node); |
718e3744 | 74 | } |
75 | ||
67174041 AS |
76 | /* |
77 | * bgp_node_destroy | |
78 | */ | |
d62a17ae | 79 | static void bgp_node_destroy(route_table_delegate_t *delegate, |
80 | struct route_table *table, struct route_node *node) | |
718e3744 | 81 | { |
d62a17ae | 82 | struct bgp_node *bgp_node; |
dcc68b5e | 83 | struct bgp_table *rt; |
9bcb3eef | 84 | bgp_node = bgp_dest_from_rnode(node); |
dcc68b5e MS |
85 | rt = table->info; |
86 | ||
87 | if (rt->bgp) { | |
88 | bgp_addpath_free_node_data(&rt->bgp->tx_addpath, | |
89 | &bgp_node->tx_addpath, | |
90 | rt->afi, rt->safi); | |
91 | } | |
92 | ||
d62a17ae | 93 | XFREE(MTYPE_BGP_NODE, bgp_node); |
718e3744 | 94 | } |
95 | ||
67174041 AS |
96 | /* |
97 | * Function vector to customize the behavior of the route table | |
98 | * library for BGP route tables. | |
99 | */ | |
d62a17ae | 100 | route_table_delegate_t bgp_table_delegate = {.create_node = bgp_node_create, |
101 | .destroy_node = bgp_node_destroy}; | |
718e3744 | 102 | |
67174041 AS |
103 | /* |
104 | * bgp_table_init | |
105 | */ | |
960035b2 | 106 | struct bgp_table *bgp_table_init(struct bgp *bgp, afi_t afi, safi_t safi) |
718e3744 | 107 | { |
d62a17ae | 108 | struct bgp_table *rt; |
718e3744 | 109 | |
d62a17ae | 110 | rt = XCALLOC(MTYPE_BGP_TABLE, sizeof(struct bgp_table)); |
718e3744 | 111 | |
d62a17ae | 112 | rt->route_table = route_table_init_with_delegate(&bgp_table_delegate); |
718e3744 | 113 | |
d62a17ae | 114 | /* |
115 | * Set up back pointer to bgp_table. | |
116 | */ | |
6ca30e9e | 117 | route_table_set_info(rt->route_table, rt); |
718e3744 | 118 | |
960035b2 | 119 | /* |
9b6d8fcf | 120 | * pointer to bgp instance allows working back from bgp_path_info to bgp |
960035b2 PZ |
121 | */ |
122 | rt->bgp = bgp; | |
123 | ||
d62a17ae | 124 | bgp_table_lock(rt); |
125 | rt->afi = afi; | |
126 | rt->safi = safi; | |
cbdfbaa5 | 127 | |
d62a17ae | 128 | return rt; |
cbdfbaa5 | 129 | } |
1dacdd8b | 130 | |
f009ff26 | 131 | /* Delete the route node from the selection deferral route list */ |
132 | void bgp_delete_listnode(struct bgp_node *node) | |
133 | { | |
134 | struct route_node *rn = NULL; | |
135 | struct bgp_table *table = NULL; | |
136 | struct bgp *bgp = NULL; | |
137 | afi_t afi; | |
138 | safi_t safi; | |
139 | ||
140 | /* If the route to be deleted is selection pending, update the | |
141 | * route node in gr_info | |
142 | */ | |
143 | if (CHECK_FLAG(node->flags, BGP_NODE_SELECT_DEFER)) { | |
9bcb3eef | 144 | table = bgp_dest_table(node); |
9e3b51a7 | 145 | |
146 | if (table) { | |
f009ff26 | 147 | bgp = table->bgp; |
9e3b51a7 | 148 | afi = table->afi; |
149 | safi = table->safi; | |
2ba1fe69 | 150 | } else |
151 | return; | |
152 | ||
9bcb3eef | 153 | rn = bgp_dest_to_rnode(node); |
f009ff26 | 154 | |
f009ff26 | 155 | if (bgp && rn && rn->lock == 1) { |
156 | /* Delete the route from the selection pending list */ | |
26742171 DS |
157 | bgp->gr_info[afi][safi].gr_deferred--; |
158 | UNSET_FLAG(node->flags, BGP_NODE_SELECT_DEFER); | |
f009ff26 | 159 | } |
160 | } | |
161 | } | |
162 | ||
bac31cb8 MR |
163 | struct bgp_node *bgp_table_subtree_lookup(const struct bgp_table *table, |
164 | const struct prefix *p) | |
1dacdd8b | 165 | { |
9bcb3eef | 166 | struct bgp_node *node = bgp_dest_from_rnode(table->route_table->top); |
bac31cb8 | 167 | struct bgp_node *matched = NULL; |
b54892e0 | 168 | |
bac31cb8 MR |
169 | if (node == NULL) |
170 | return NULL; | |
b54892e0 | 171 | |
b54892e0 | 172 | |
bac31cb8 | 173 | while (node) { |
9bcb3eef | 174 | const struct prefix *node_p = bgp_dest_get_prefix(node); |
b54892e0 | 175 | |
bac31cb8 MR |
176 | if (node_p->prefixlen >= p->prefixlen) { |
177 | if (!prefix_match(p, node_p)) | |
178 | return NULL; | |
1dacdd8b | 179 | |
bac31cb8 MR |
180 | matched = node; |
181 | break; | |
1dacdd8b | 182 | } |
1dacdd8b | 183 | |
bac31cb8 MR |
184 | if (!prefix_match(node_p, p)) |
185 | return NULL; | |
1dacdd8b | 186 | |
bac31cb8 | 187 | if (node_p->prefixlen == p->prefixlen) { |
1dacdd8b MR |
188 | matched = node; |
189 | break; | |
190 | } | |
bac31cb8 | 191 | |
9bcb3eef | 192 | node = bgp_dest_from_rnode(node->link[prefix_bit( |
b54892e0 | 193 | &p->u.prefix, node_p->prefixlen)]); |
1dacdd8b MR |
194 | } |
195 | ||
5911f65c | 196 | if (!matched) |
bac31cb8 | 197 | return NULL; |
1dacdd8b | 198 | |
9bcb3eef | 199 | bgp_dest_lock_node(matched); |
bac31cb8 | 200 | return matched; |
1dacdd8b | 201 | } |
56ca3b5b DL |
202 | |
203 | printfrr_ext_autoreg_p("BD", printfrr_bd) | |
212e04e5 | 204 | static ssize_t printfrr_bd(struct fbuf *buf, const char **fmt, |
56ca3b5b DL |
205 | int prec, const void *ptr) |
206 | { | |
207 | const struct bgp_dest *dest = ptr; | |
212e04e5 DL |
208 | const struct prefix *p = bgp_dest_get_prefix(dest); |
209 | char cbuf[PREFIX_STRLEN]; | |
001ab42b | 210 | |
212e04e5 DL |
211 | if (!dest) |
212 | return bputs(buf, "NULL"); | |
56ca3b5b | 213 | |
212e04e5 DL |
214 | /* need to get the real length even if buffer too small */ |
215 | prefix2str(p, cbuf, sizeof(cbuf)); | |
216 | return bputs(buf, cbuf); | |
56ca3b5b | 217 | } |