1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (C) 1998, 2001 Kunihiro Ishiguro
10 #include "sockunion.h"
16 #include "bgpd/bgpd.h"
17 #include "bgpd/bgp_table.h"
18 #include "bgp_addpath.h"
19 #include "bgp_trace.h"
21 void bgp_table_lock(struct bgp_table
*rt
)
26 void bgp_table_unlock(struct bgp_table
*rt
)
35 route_table_finish(rt
->route_table
);
36 rt
->route_table
= NULL
;
38 XFREE(MTYPE_BGP_TABLE
, rt
);
41 void bgp_table_finish(struct bgp_table
**rt
)
44 bgp_table_unlock(*rt
);
50 * bgp_dest_unlock_node
52 void bgp_dest_unlock_node(struct bgp_dest
*dest
)
54 frrtrace(1, frr_bgp
, bgp_dest_unlock
, dest
);
55 bgp_delete_listnode(dest
);
56 route_unlock_node(bgp_dest_to_rnode(dest
));
62 struct bgp_dest
*bgp_dest_lock_node(struct bgp_dest
*dest
)
64 frrtrace(1, frr_bgp
, bgp_dest_lock
, dest
);
65 struct route_node
*rn
= route_lock_node(bgp_dest_to_rnode(dest
));
67 return bgp_dest_from_rnode(rn
);
71 * bgp_dest_get_prefix_str
73 const char *bgp_dest_get_prefix_str(struct bgp_dest
*dest
)
75 const struct prefix
*p
= NULL
;
76 static char str
[PREFIX_STRLEN
] = {0};
78 p
= bgp_dest_get_prefix(dest
);
80 return prefix2str(p
, str
, sizeof(str
));
88 static struct route_node
*bgp_node_create(route_table_delegate_t
*delegate
,
89 struct route_table
*table
)
91 struct bgp_node
*node
;
92 node
= XCALLOC(MTYPE_BGP_NODE
, sizeof(struct bgp_node
));
94 RB_INIT(bgp_adj_out_rb
, &node
->adj_out
);
95 return bgp_dest_to_rnode(node
);
101 static void bgp_node_destroy(route_table_delegate_t
*delegate
,
102 struct route_table
*table
, struct route_node
*node
)
104 struct bgp_node
*bgp_node
;
105 struct bgp_table
*rt
;
106 bgp_node
= bgp_dest_from_rnode(node
);
110 bgp_addpath_free_node_data(&rt
->bgp
->tx_addpath
,
111 &bgp_node
->tx_addpath
,
115 XFREE(MTYPE_BGP_NODE
, bgp_node
);
119 * Function vector to customize the behavior of the route table
120 * library for BGP route tables.
122 route_table_delegate_t bgp_table_delegate
= {.create_node
= bgp_node_create
,
123 .destroy_node
= bgp_node_destroy
};
128 struct bgp_table
*bgp_table_init(struct bgp
*bgp
, afi_t afi
, safi_t safi
)
130 struct bgp_table
*rt
;
132 rt
= XCALLOC(MTYPE_BGP_TABLE
, sizeof(struct bgp_table
));
134 rt
->route_table
= route_table_init_with_delegate(&bgp_table_delegate
);
137 * Set up back pointer to bgp_table.
139 route_table_set_info(rt
->route_table
, rt
);
142 * pointer to bgp instance allows working back from bgp_path_info to bgp
153 /* Delete the route node from the selection deferral route list */
154 void bgp_delete_listnode(struct bgp_node
*node
)
156 struct route_node
*rn
= NULL
;
157 struct bgp_table
*table
= NULL
;
158 struct bgp
*bgp
= NULL
;
162 /* If the route to be deleted is selection pending, update the
163 * route node in gr_info
165 if (CHECK_FLAG(node
->flags
, BGP_NODE_SELECT_DEFER
)) {
166 table
= bgp_dest_table(node
);
175 rn
= bgp_dest_to_rnode(node
);
177 if (bgp
&& rn
&& rn
->lock
== 1) {
178 /* Delete the route from the selection pending list */
179 bgp
->gr_info
[afi
][safi
].gr_deferred
--;
180 UNSET_FLAG(node
->flags
, BGP_NODE_SELECT_DEFER
);
185 struct bgp_node
*bgp_table_subtree_lookup(const struct bgp_table
*table
,
186 const struct prefix
*p
)
188 struct bgp_node
*node
= bgp_dest_from_rnode(table
->route_table
->top
);
189 struct bgp_node
*matched
= NULL
;
196 const struct prefix
*node_p
= bgp_dest_get_prefix(node
);
198 if (node_p
->prefixlen
>= p
->prefixlen
) {
199 if (!prefix_match(p
, node_p
))
206 if (!prefix_match(node_p
, p
))
209 if (node_p
->prefixlen
== p
->prefixlen
) {
214 node
= bgp_dest_from_rnode(node
->link
[prefix_bit(
215 &p
->u
.prefix
, node_p
->prefixlen
)]);
221 bgp_dest_lock_node(matched
);
225 printfrr_ext_autoreg_p("BD", printfrr_bd
);
226 static ssize_t
printfrr_bd(struct fbuf
*buf
, struct printfrr_eargs
*ea
,
229 const struct bgp_dest
*dest
= ptr
;
230 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
231 char cbuf
[PREFIX_STRLEN
];
234 return bputs(buf
, "(null)");
236 /* need to get the real length even if buffer too small */
237 prefix2str(p
, cbuf
, sizeof(cbuf
));
238 return bputs(buf
, cbuf
);