2 * BGP Conditional advertisement
3 * Copyright (C) 2020 Samsung Research Institute Bangalore.
4 * Madhurilatha Kuruganti
6 * This program 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 Free
8 * Software Foundation; either version 2 of the License, or (at your option)
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
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
21 #include "bgpd/bgp_conditional_adv.h"
23 const char *get_afi_safi_str(afi_t afi
, safi_t safi
, bool for_json
);
25 static route_map_result_t
26 bgp_check_rmap_prefixes_in_bgp_table(struct bgp_table
*table
,
27 struct route_map
*rmap
)
29 struct bgp_dest
*dest
;
30 struct attr dummy_attr
;
31 struct bgp_path_info path
;
32 const struct prefix
*dest_p
;
33 struct bgp_path_info
*pi
;
34 route_map_result_t ret
= RMAP_PERMITMATCH
;
36 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
37 dest_p
= bgp_dest_get_prefix(dest
);
41 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
42 dummy_attr
= *pi
->attr
;
44 path
.attr
= &dummy_attr
;
46 ret
= route_map_apply(rmap
, dest_p
, RMAP_BGP
, &path
);
47 if (ret
== RMAP_PERMITMATCH
)
54 static void bgp_conditional_adv_routes(struct peer
*peer
, afi_t afi
,
55 safi_t safi
, struct bgp_table
*table
,
56 struct route_map
*rmap
,
57 enum advertise advertise
)
60 const struct prefix
*dest_p
;
61 struct attr dummy_attr
, attr
;
62 struct bgp_path_info path
;
63 struct bgp_path_info
*pi
;
64 struct peer_af
*paf
= NULL
;
65 struct bgp_dest
*dest
= NULL
;
66 struct update_subgroup
*subgrp
= NULL
;
68 paf
= peer_af_find(peer
, afi
, safi
);
72 subgrp
= PAF_SUBGRP(paf
);
73 /* Ignore if subgroup doesn't exist (implies AF is not negotiated) */
77 addpath_capable
= bgp_addpath_encode_tx(peer
, afi
, safi
);
79 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
80 dest_p
= bgp_dest_get_prefix(dest
);
84 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
85 dummy_attr
= *pi
->attr
;
87 path
.attr
= &dummy_attr
;
89 if (route_map_apply(rmap
, dest_p
, RMAP_BGP
, &path
)
93 if (CHECK_FLAG(pi
->flags
, BGP_PATH_SELECTED
)
95 && bgp_addpath_tx_path(
96 peer
->addpath_type
[afi
][safi
],
99 /* Skip route-map checks in
100 * subgroup_announce_check while executing from
101 * the conditional advertise scanner process.
102 * otherwise when route-map is also configured
103 * on same peer, routes in advertise-map may not
104 * be advertised as expected.
106 if ((advertise
== ADVERTISE
)
107 && subgroup_announce_check(dest
, pi
, subgrp
,
110 bgp_adj_out_set_subgroup(dest
, subgrp
,
113 /* If default originate is enabled for
114 * the peer, do not send explicit
115 * withdraw. This will prevent deletion
116 * of default route advertised through
120 peer
->af_flags
[afi
][safi
],
121 PEER_FLAG_DEFAULT_ORIGINATE
)
122 && is_default_prefix(dest_p
))
125 bgp_adj_out_unset_subgroup(
127 bgp_addpath_id_for_peer(
136 /* Handler of conditional advertisement timer event.
137 * Each route in the condition-map is evaluated.
139 static int bgp_conditional_adv_timer(struct thread
*t
)
144 struct bgp
*bgp
= NULL
;
145 struct peer
*peer
= NULL
;
146 struct peer_af
*paf
= NULL
;
147 struct bgp_table
*table
= NULL
;
148 struct bgp_filter
*filter
= NULL
;
149 struct listnode
*node
, *nnode
= NULL
;
150 struct update_subgroup
*subgrp
= NULL
;
151 route_map_result_t ret
;
156 bgp
->t_condition_check
= NULL
;
157 thread_add_timer(bm
->master
, bgp_conditional_adv_timer
, bgp
,
158 CONDITIONAL_ROUTES_POLL_TIME
, &bgp
->t_condition_check
);
160 /* loop through each peer and advertise or withdraw routes if
161 * advertise-map is configured and prefix(es) in condition-map
162 * does exist(exist-map)/not exist(non-exist-map) in BGP table
163 * based on condition(exist-map or non-exist map)
165 for (ALL_LIST_ELEMENTS(bgp
->peer
, node
, nnode
, peer
)) {
166 if (!CHECK_FLAG(peer
->flags
, PEER_FLAG_CONFIG_NODE
))
169 FOREACH_AFI_SAFI (afi
, safi
) {
170 if (strmatch(get_afi_safi_str(afi
, safi
, true),
174 if (!peer
->afc
[afi
][safi
])
177 /* labeled-unicast routes are installed in the unicast
178 * table so in order to display the correct PfxRcd value
179 * we must look at SAFI_UNICAST
181 pfx_rcd_safi
= (safi
== SAFI_LABELED_UNICAST
)
185 table
= bgp
->rib
[afi
][pfx_rcd_safi
];
189 filter
= &peer
->filter
[afi
][safi
];
191 if (!filter
->advmap
.aname
|| !filter
->advmap
.cname
192 || !filter
->advmap
.amap
|| !filter
->advmap
.cmap
)
195 if (!peer
->advmap_config_change
[afi
][safi
]
196 && !peer
->advmap_table_change
)
199 /* cmap (route-map attached to exist-map or
200 * non-exist-map) map validation
202 ret
= bgp_check_rmap_prefixes_in_bgp_table(
203 table
, filter
->advmap
.cmap
);
205 /* Derive conditional advertisement status from
206 * condition and return value of condition-map
209 if (filter
->advmap
.condition
== CONDITION_EXIST
)
210 filter
->advmap
.advertise
=
211 (ret
== RMAP_PERMITMATCH
) ? ADVERTISE
214 filter
->advmap
.advertise
=
215 (ret
== RMAP_PERMITMATCH
) ? WITHDRAW
218 /* Send regular update as per the existing policy.
219 * There is a change in route-map, match-rule, ACLs,
220 * or route-map filter configuration on the same peer.
222 if (peer
->advmap_config_change
[afi
][safi
]) {
223 paf
= peer_af_find(peer
, afi
, safi
);
225 update_subgroup_split_peer(paf
, NULL
);
226 subgrp
= paf
->subgroup
;
227 if (subgrp
&& subgrp
->update_group
)
228 subgroup_announce_table(
229 paf
->subgroup
, NULL
);
231 peer
->advmap_config_change
[afi
][safi
] = false;
234 /* Send update as per the conditional advertisement */
235 bgp_conditional_adv_routes(peer
, afi
, safi
, table
,
237 filter
->advmap
.advertise
);
239 peer
->advmap_table_change
= false;
244 void bgp_conditional_adv_enable(struct peer
*peer
, afi_t afi
, safi_t safi
)
246 struct bgp
*bgp
= peer
->bgp
;
250 /* This flag is used to monitor conditional routes status in BGP table,
251 * and advertise/withdraw routes only when there is a change in BGP
252 * table w.r.t conditional routes
254 peer
->advmap_config_change
[afi
][safi
] = true;
256 /* advertise-map is already configured on atleast one of its
257 * neighbors (AFI/SAFI). So just increment the counter.
259 if (++bgp
->condition_filter_count
> 1)
262 /* Register for conditional routes polling timer */
263 thread_add_timer(bm
->master
, bgp_conditional_adv_timer
, bgp
,
264 CONDITIONAL_ROUTES_POLL_TIME
, &bgp
->t_condition_check
);
267 void bgp_conditional_adv_disable(struct peer
*peer
, afi_t afi
, safi_t safi
)
269 struct bgp
*bgp
= peer
->bgp
;
273 /* advertise-map is not configured on any of its neighbors or
274 * it is configured on more than one neighbor(AFI/SAFI).
275 * So there's nothing to do except decrementing the counter.
277 if (--bgp
->condition_filter_count
!= 0)
280 /* Last filter removed. So cancel conditional routes polling thread. */
281 THREAD_OFF(bgp
->t_condition_check
);