Coverage Report

Created: 2025-08-03 06:36

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