Coverage Report

Created: 2026-01-13 06:56

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/frr/bgpd/bgp_advertise.c
Line
Count
Source
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
/* BGP advertisement and adjacency
3
 * Copyright (C) 1996, 97, 98, 99, 2000 Kunihiro Ishiguro
4
 */
5
6
#include <zebra.h>
7
8
#include "command.h"
9
#include "memory.h"
10
#include "prefix.h"
11
#include "hash.h"
12
#include "frrevent.h"
13
#include "queue.h"
14
#include "filter.h"
15
16
#include "bgpd/bgpd.h"
17
#include "bgpd/bgp_table.h"
18
#include "bgpd/bgp_route.h"
19
#include "bgpd/bgp_advertise.h"
20
#include "bgpd/bgp_attr.h"
21
#include "bgpd/bgp_debug.h"
22
#include "bgpd/bgp_aspath.h"
23
#include "bgpd/bgp_packet.h"
24
#include "bgpd/bgp_fsm.h"
25
#include "bgpd/bgp_mplsvpn.h"
26
#include "bgpd/bgp_updgrp.h"
27
28
/* BGP advertise attribute is used for pack same attribute update into
29
   one packet.  To do that we maintain attribute hash in struct
30
   peer.  */
31
struct bgp_advertise_attr *bgp_advertise_attr_new(void)
32
0
{
33
0
  return XCALLOC(MTYPE_BGP_ADVERTISE_ATTR,
34
0
           sizeof(struct bgp_advertise_attr));
35
0
}
36
37
void bgp_advertise_attr_free(struct bgp_advertise_attr *baa)
38
0
{
39
0
  XFREE(MTYPE_BGP_ADVERTISE_ATTR, baa);
40
0
}
41
42
static void *bgp_advertise_attr_hash_alloc(void *p)
43
0
{
44
0
  struct bgp_advertise_attr *ref = (struct bgp_advertise_attr *)p;
45
0
  struct bgp_advertise_attr *baa;
46
47
0
  baa = bgp_advertise_attr_new();
48
0
  baa->attr = ref->attr;
49
0
  return baa;
50
0
}
51
52
unsigned int bgp_advertise_attr_hash_key(const void *p)
53
0
{
54
0
  const struct bgp_advertise_attr *baa = p;
55
56
0
  return attrhash_key_make(baa->attr);
57
0
}
58
59
bool bgp_advertise_attr_hash_cmp(const void *p1, const void *p2)
60
0
{
61
0
  const struct bgp_advertise_attr *baa1 = p1;
62
0
  const struct bgp_advertise_attr *baa2 = p2;
63
64
0
  return attrhash_cmp(baa1->attr, baa2->attr);
65
0
}
66
67
/* BGP update and withdraw information is stored in BGP advertise
68
   structure.  This structure is referred from BGP adjacency
69
   information.  */
70
struct bgp_advertise *bgp_advertise_new(void)
71
0
{
72
0
  return XCALLOC(MTYPE_BGP_ADVERTISE, sizeof(struct bgp_advertise));
73
0
}
74
75
void bgp_advertise_free(struct bgp_advertise *adv)
76
0
{
77
0
  if (adv->pathi)
78
    /* bgp_advertise bgp_path_info reference */
79
0
    bgp_path_info_unlock(adv->pathi);
80
0
  XFREE(MTYPE_BGP_ADVERTISE, adv);
81
0
}
82
83
void bgp_advertise_add(struct bgp_advertise_attr *baa,
84
           struct bgp_advertise *adv)
85
0
{
86
0
  adv->next = baa->adv;
87
0
  if (baa->adv)
88
0
    baa->adv->prev = adv;
89
0
  baa->adv = adv;
90
0
}
91
92
void bgp_advertise_delete(struct bgp_advertise_attr *baa,
93
        struct bgp_advertise *adv)
94
0
{
95
0
  if (adv->next)
96
0
    adv->next->prev = adv->prev;
97
0
  if (adv->prev)
98
0
    adv->prev->next = adv->next;
99
0
  else
100
0
    baa->adv = adv->next;
101
0
}
102
103
struct bgp_advertise_attr *bgp_advertise_attr_intern(struct hash *hash,
104
                 struct attr *attr)
105
0
{
106
0
  struct bgp_advertise_attr ref;
107
0
  struct bgp_advertise_attr *baa;
108
109
0
  ref.attr = bgp_attr_intern(attr);
110
0
  baa = (struct bgp_advertise_attr *)hash_get(
111
0
    hash, &ref, bgp_advertise_attr_hash_alloc);
112
0
  baa->refcnt++;
113
114
0
  return baa;
115
0
}
116
117
void bgp_advertise_attr_unintern(struct hash *hash,
118
         struct bgp_advertise_attr *baa)
119
0
{
120
0
  if (baa->refcnt)
121
0
    baa->refcnt--;
122
123
0
  if (baa->refcnt && baa->attr)
124
0
    bgp_attr_unintern(&baa->attr);
125
0
  else {
126
0
    if (baa->attr) {
127
0
      hash_release(hash, baa);
128
0
      bgp_attr_unintern(&baa->attr);
129
0
    }
130
0
    bgp_advertise_attr_free(baa);
131
0
  }
132
0
}
133
134
bool bgp_adj_out_lookup(struct peer *peer, struct bgp_dest *dest,
135
      uint32_t addpath_tx_id)
136
0
{
137
0
  struct bgp_adj_out *adj;
138
0
  struct peer_af *paf;
139
0
  afi_t afi;
140
0
  safi_t safi;
141
0
  bool addpath_capable;
142
143
0
  RB_FOREACH (adj, bgp_adj_out_rb, &dest->adj_out)
144
0
    SUBGRP_FOREACH_PEER (adj->subgroup, paf)
145
0
      if (paf->peer == peer) {
146
0
        afi = SUBGRP_AFI(adj->subgroup);
147
0
        safi = SUBGRP_SAFI(adj->subgroup);
148
0
        addpath_capable =
149
0
          bgp_addpath_encode_tx(peer, afi, safi);
150
151
        /* Match on a specific addpath_tx_id if we are
152
         * using addpath for
153
         * this
154
         * peer and if an addpath_tx_id was specified */
155
0
        if (addpath_capable && addpath_tx_id
156
0
            && adj->addpath_tx_id != addpath_tx_id)
157
0
          continue;
158
159
0
        return (adj->adv
160
0
            ? (adj->adv->baa ? true : false)
161
0
            : (adj->attr ? true : false));
162
0
      }
163
164
0
  return false;
165
0
}
166
167
168
void bgp_adj_in_set(struct bgp_dest *dest, struct peer *peer, struct attr *attr,
169
        uint32_t addpath_id)
170
0
{
171
0
  struct bgp_adj_in *adj;
172
173
0
  for (adj = dest->adj_in; adj; adj = adj->next) {
174
0
    if (adj->peer == peer && adj->addpath_rx_id == addpath_id) {
175
0
      if (adj->attr != attr) {
176
0
        bgp_attr_unintern(&adj->attr);
177
0
        adj->attr = bgp_attr_intern(attr);
178
0
      }
179
0
      return;
180
0
    }
181
0
  }
182
0
  adj = XCALLOC(MTYPE_BGP_ADJ_IN, sizeof(struct bgp_adj_in));
183
0
  adj->peer = peer_lock(peer); /* adj_in peer reference */
184
0
  adj->attr = bgp_attr_intern(attr);
185
0
  adj->uptime = monotime(NULL);
186
0
  adj->addpath_rx_id = addpath_id;
187
0
  BGP_ADJ_IN_ADD(dest, adj);
188
0
  bgp_dest_lock_node(dest);
189
0
}
190
191
void bgp_adj_in_remove(struct bgp_dest *dest, struct bgp_adj_in *bai)
192
0
{
193
0
  bgp_attr_unintern(&bai->attr);
194
0
  BGP_ADJ_IN_DEL(dest, bai);
195
0
  bgp_dest_unlock_node(dest);
196
0
  peer_unlock(bai->peer); /* adj_in peer reference */
197
0
  XFREE(MTYPE_BGP_ADJ_IN, bai);
198
0
}
199
200
bool bgp_adj_in_unset(struct bgp_dest *dest, struct peer *peer,
201
          uint32_t addpath_id)
202
0
{
203
0
  struct bgp_adj_in *adj;
204
0
  struct bgp_adj_in *adj_next;
205
206
0
  adj = dest->adj_in;
207
208
0
  if (!adj)
209
0
    return false;
210
211
0
  while (adj) {
212
0
    adj_next = adj->next;
213
214
0
    if (adj->peer == peer && adj->addpath_rx_id == addpath_id)
215
0
      bgp_adj_in_remove(dest, adj);
216
217
0
    adj = adj_next;
218
0
  }
219
220
  return true;
221
0
}