Skip to content

Commit ccfe452

Browse files
donaldsharpraja-rajasekar
authored andcommitted
bgpd : backpressure - Handle BGP-Zebra Install evt Creation
BGP is now keeping a list of dests with the dest having a pointer to the bgp_path_info that it will be working on. 1) When bgp receives a prefix, process it, add the bgp_dest of the prefix into the new Fifo list if not present, update the flags (Ex: earlier if the prefix was advertised and now it is a withdrawn), increment the ref_count and DO NOT advertise the install/withdraw to zebra yet. 2) Schedule an event to wake up to invoke the new function which will walk the list one by one and installs/withdraws the routes into zebra. a) if BUFFER_EMPTY, process the next item on the list b) if BUFFER_PENDING, bail out and the callback in zclient_flush_data() will invoke the same function when BUFFER_EMPTY Changes - rename old bgp_zebra_announce to bgp_zebra_announce_actual - rename old bgp_zebra_withdrw to bgp_zebra_withdraw_actual - Handle new fifo list cleanup in bgp_exit() - New funcs: bgp_handle_route_announcements_to_zebra() and bgp_zebra_route_install() - Define a callback function to invoke bgp_handle_route_announcements_to_zebra() when BUFFER_EMPTY in zclient_flush_data() The current change deals with bgp installing routes via bgp_process_main_one() Ticket: #3390099 Signed-off-by: Donald Sharp <sharpd@nvidia.com> Signed-off-by: Rajasekar Raja <rajasekarr@nvidia.com>
1 parent 5f379be commit ccfe452

File tree

7 files changed

+211
-52
lines changed

7 files changed

+211
-52
lines changed

bgpd/bgp_route.c

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3399,8 +3399,8 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
33993399
|| new_select->sub_type
34003400
== BGP_ROUTE_IMPORTED))
34013401

3402-
bgp_zebra_announce(dest, old_select,
3403-
bgp);
3402+
bgp_zebra_route_install(dest, old_select,
3403+
bgp, true);
34043404
}
34053405
}
34063406

@@ -3517,17 +3517,19 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
35173517
*/
35183518
if (old_select &&
35193519
is_route_parent_evpn(old_select))
3520-
bgp_zebra_withdraw(dest, old_select, bgp);
3520+
bgp_zebra_route_install(dest, old_select, bgp,
3521+
false);
35213522

3522-
bgp_zebra_announce(dest, new_select, bgp);
3523+
bgp_zebra_route_install(dest, new_select, bgp, true);
35233524
} else {
35243525
/* Withdraw the route from the kernel. */
35253526
if (old_select && old_select->type == ZEBRA_ROUTE_BGP
35263527
&& (old_select->sub_type == BGP_ROUTE_NORMAL
35273528
|| old_select->sub_type == BGP_ROUTE_AGGREGATE
35283529
|| old_select->sub_type == BGP_ROUTE_IMPORTED))
35293530

3530-
bgp_zebra_withdraw(dest, old_select, bgp);
3531+
bgp_zebra_route_install(dest, old_select, bgp,
3532+
false);
35313533
}
35323534
}
35333535

@@ -4424,7 +4426,7 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
44244426
if (pi && pi->attr->rmap_table_id != new_attr.rmap_table_id) {
44254427
if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
44264428
/* remove from RIB previous entry */
4427-
bgp_zebra_withdraw(dest, pi, bgp);
4429+
bgp_zebra_route_install(dest, pi, bgp, false);
44284430
}
44294431

44304432
if (peer->sort == BGP_PEER_EBGP) {
@@ -6050,7 +6052,7 @@ static void bgp_cleanup_table(struct bgp *bgp, struct bgp_table *table,
60506052
|| pi->sub_type == BGP_ROUTE_IMPORTED)) {
60516053

60526054
if (bgp_fibupd_safi(safi))
6053-
bgp_zebra_withdraw(dest, pi, bgp);
6055+
bgp_zebra_withdraw_actual(dest, pi, bgp);
60546056
}
60556057

60566058
dest = bgp_path_info_reap(dest, pi);

bgpd/bgp_table.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ struct bgp_dest {
7777
STAILQ_ENTRY(bgp_dest) pq;
7878

7979
struct zebra_announce_item zai;
80+
struct bgp_path_info *za_bgp_pi;
8081

8182
uint64_t version;
8283

@@ -93,6 +94,8 @@ struct bgp_dest {
9394
#define BGP_NODE_LABEL_REQUESTED (1 << 7)
9495
#define BGP_NODE_SOFT_RECONFIG (1 << 8)
9596
#define BGP_NODE_PROCESS_CLEAR (1 << 9)
97+
#define BGP_NODE_SCHEDULE_FOR_INSTALL (1 << 10)
98+
#define BGP_NODE_SCHEDULE_FOR_DELETE (1 << 11)
9699

97100
struct bgp_addpath_node_data tx_addpath;
98101

bgpd/bgp_zebra.c

Lines changed: 178 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1524,8 +1524,9 @@ static void bgp_debug_zebra_nh(struct zapi_route *api)
15241524
}
15251525
}
15261526

1527-
void bgp_zebra_announce(struct bgp_dest *dest, struct bgp_path_info *info,
1528-
struct bgp *bgp)
1527+
static enum zclient_send_status
1528+
bgp_zebra_announce_actual(struct bgp_dest *dest, struct bgp_path_info *info,
1529+
struct bgp *bgp)
15291530
{
15301531
struct bgp_path_info *bpi_ultimate;
15311532
struct zapi_route api = { 0 };
@@ -1541,27 +1542,10 @@ void bgp_zebra_announce(struct bgp_dest *dest, struct bgp_path_info *info,
15411542
struct bgp_table *table = bgp_dest_table(dest);
15421543
const struct prefix *p = bgp_dest_get_prefix(dest);
15431544

1544-
/*
1545-
* BGP is installing this route and bgp has been configured
1546-
* to suppress announcements until the route has been installed
1547-
* let's set the fact that we expect this route to be installed
1548-
*/
1549-
if (BGP_SUPPRESS_FIB_ENABLED(bgp))
1550-
SET_FLAG(dest->flags, BGP_NODE_FIB_INSTALL_PENDING);
1551-
1552-
/* Don't try to install if we're not connected to Zebra or Zebra doesn't
1553-
* know of this instance.
1554-
*/
1555-
if (!bgp_install_info_to_zebra(bgp))
1556-
return;
1557-
1558-
if (bgp->main_zebra_update_hold)
1559-
return;
1560-
15611545
if (table->safi == SAFI_FLOWSPEC) {
15621546
bgp_pbr_update_entry(bgp, p, info, table->afi, table->safi,
15631547
true);
1564-
return;
1548+
return ZCLIENT_SEND_SUCCESS;
15651549
}
15661550

15671551
/* Make Zebra API structure. */
@@ -1678,10 +1662,11 @@ void bgp_zebra_announce(struct bgp_dest *dest, struct bgp_path_info *info,
16781662
zlog_debug("%s: %pFX: announcing to zebra (recursion %sset)",
16791663
__func__, p, (recursion_flag ? "" : "NOT "));
16801664
}
1681-
zclient_route_send(is_add ? ZEBRA_ROUTE_ADD : ZEBRA_ROUTE_DELETE,
1682-
zclient, &api);
1665+
return zclient_route_send(is_add ? ZEBRA_ROUTE_ADD : ZEBRA_ROUTE_DELETE,
1666+
zclient, &api);
16831667
}
16841668

1669+
16851670
/* Announce all routes of a table to zebra */
16861671
void bgp_zebra_announce_table(struct bgp *bgp, afi_t afi, safi_t safi)
16871672
{
@@ -1707,7 +1692,7 @@ void bgp_zebra_announce_table(struct bgp *bgp, afi_t afi, safi_t safi)
17071692
&& (pi->sub_type == BGP_ROUTE_NORMAL
17081693
|| pi->sub_type == BGP_ROUTE_IMPORTED)))
17091694

1710-
bgp_zebra_announce(dest, pi, bgp);
1695+
bgp_zebra_route_install(dest, pi, bgp, true);
17111696
}
17121697

17131698
/* Announce routes of any bgp subtype of a table to zebra */
@@ -1729,34 +1714,23 @@ void bgp_zebra_announce_table_all_subtypes(struct bgp *bgp, afi_t afi,
17291714
for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
17301715
if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED) &&
17311716
pi->type == ZEBRA_ROUTE_BGP)
1732-
bgp_zebra_announce(dest, pi, bgp);
1717+
bgp_zebra_route_install(dest, pi, bgp, true);
17331718
}
17341719

1735-
void bgp_zebra_withdraw(struct bgp_dest *dest, struct bgp_path_info *info,
1736-
struct bgp *bgp)
1720+
enum zclient_send_status bgp_zebra_withdraw_actual(struct bgp_dest *dest,
1721+
struct bgp_path_info *info,
1722+
struct bgp *bgp)
17371723
{
17381724
struct zapi_route api;
17391725
struct peer *peer;
17401726
struct bgp_table *table = bgp_dest_table(dest);
17411727
const struct prefix *p = bgp_dest_get_prefix(dest);
17421728

1743-
/*
1744-
* If we are withdrawing the route, we don't need to have this
1745-
* flag set. So unset it.
1746-
*/
1747-
UNSET_FLAG(info->net->flags, BGP_NODE_FIB_INSTALL_PENDING);
1748-
1749-
/* Don't try to install if we're not connected to Zebra or Zebra doesn't
1750-
* know of this instance.
1751-
*/
1752-
if (!bgp_install_info_to_zebra(bgp))
1753-
return;
1754-
17551729
if (table->safi == SAFI_FLOWSPEC) {
17561730
peer = info->peer;
17571731
bgp_pbr_update_entry(peer->bgp, p, info, table->afi,
17581732
table->safi, false);
1759-
return;
1733+
return ZCLIENT_SEND_SUCCESS;
17601734
}
17611735

17621736
memset(&api, 0, sizeof(api));
@@ -1774,7 +1748,169 @@ void bgp_zebra_withdraw(struct bgp_dest *dest, struct bgp_path_info *info,
17741748
zlog_debug("Tx route delete VRF %u %pFX", bgp->vrf_id,
17751749
&api.prefix);
17761750

1777-
zclient_route_send(ZEBRA_ROUTE_DELETE, zclient, &api);
1751+
return zclient_route_send(ZEBRA_ROUTE_DELETE, zclient, &api);
1752+
}
1753+
1754+
/*
1755+
* Walk the new Fifo list one by one and invoke bgp_zebra_announce/withdraw
1756+
* to install/withdraw the routes to zebra.
1757+
*
1758+
* If status = ZCLIENT_SEND_SUCCESS (Buffer empt)y i.e. Zebra is free to
1759+
* receive more incoming data, then pick the next item on the list and
1760+
* continue processing.
1761+
*
1762+
* If status = ZCLIENT_SEND_BUFFERED (Buffer pending) i.e. Zebra is busy,
1763+
* break and bail out of the function because once at some point when zebra
1764+
* is free, a callback is triggered which inturn call this same function and
1765+
* continue processing items on list.
1766+
*/
1767+
#define ZEBRA_ANNOUNCEMENTS_LIMIT 1000
1768+
static void bgp_handle_route_announcements_to_zebra(struct event *e)
1769+
{
1770+
uint32_t count = 0;
1771+
struct bgp_dest *dest = NULL;
1772+
struct bgp_table *table = NULL;
1773+
enum zclient_send_status status = ZCLIENT_SEND_SUCCESS;
1774+
bool install;
1775+
1776+
while (count < ZEBRA_ANNOUNCEMENTS_LIMIT) {
1777+
dest = zebra_announce_pop(&bm->zebra_announce_head);
1778+
1779+
if (!dest)
1780+
break;
1781+
1782+
table = bgp_dest_table(dest);
1783+
install = CHECK_FLAG(dest->flags, BGP_NODE_SCHEDULE_FOR_INSTALL);
1784+
1785+
if (BGP_DEBUG(zebra, ZEBRA))
1786+
zlog_debug("BGP %s route %pBD(%s) with dest %p and flags 0x%x to zebra",
1787+
install ? "announcing" : "withdrawing", dest,
1788+
table->bgp->name_pretty, dest, dest->flags);
1789+
1790+
if (install) {
1791+
status = bgp_zebra_announce_actual(dest, dest->za_bgp_pi,
1792+
table->bgp);
1793+
UNSET_FLAG(dest->flags, BGP_NODE_SCHEDULE_FOR_INSTALL);
1794+
} else {
1795+
status = bgp_zebra_withdraw_actual(dest, dest->za_bgp_pi,
1796+
table->bgp);
1797+
UNSET_FLAG(dest->flags, BGP_NODE_SCHEDULE_FOR_DELETE);
1798+
}
1799+
1800+
bgp_path_info_unlock(dest->za_bgp_pi);
1801+
dest->za_bgp_pi = NULL;
1802+
bgp_dest_unlock_node(dest);
1803+
1804+
if (status == ZCLIENT_SEND_BUFFERED)
1805+
break;
1806+
1807+
count++;
1808+
}
1809+
1810+
if (status != ZCLIENT_SEND_BUFFERED &&
1811+
zebra_announce_count(&bm->zebra_announce_head))
1812+
event_add_event(bm->master,
1813+
bgp_handle_route_announcements_to_zebra, NULL,
1814+
0, &bm->t_bgp_zebra_route);
1815+
}
1816+
1817+
/*
1818+
* Callback function invoked when zclient_flush_data() receives a BUFFER_EMPTY
1819+
* i.e. zebra is free to receive more incoming data.
1820+
*/
1821+
static void bgp_zebra_buffer_write_ready(void)
1822+
{
1823+
bgp_handle_route_announcements_to_zebra(NULL);
1824+
}
1825+
1826+
/*
1827+
* BGP is now keeping a list of dests with the dest having a pointer
1828+
* to the bgp_path_info that it will be working on.
1829+
* Here is the sequence of events that should happen:
1830+
*
1831+
* Current State New State Action
1832+
* ------------- --------- ------
1833+
* ---- Install Place dest on list, save pi, mark
1834+
* as going to be installed
1835+
* ---- Withdrawal Place dest on list, save pi, mark
1836+
* as going to be deleted
1837+
*
1838+
* Install Install Leave dest on list, release old pi,
1839+
* save new pi, mark as going to be
1840+
* Installed
1841+
* Install Withdrawal Leave dest on list, release old pi,
1842+
* save new pi, mark as going to be
1843+
* withdrawan, remove install flag
1844+
*
1845+
* Withdrawal Install Special case, send withdrawal immediately
1846+
* Leave dest on list, release old pi,
1847+
* save new pi, mark as going to be
1848+
* installed. <see note about evpn
1849+
* in bgp_route.c in bgp_process_main_one>
1850+
* Withdrawal Withdrawal Leave dest on list, release old pi,
1851+
* save new pi, mark as going to be
1852+
* withdrawn.
1853+
*/
1854+
void bgp_zebra_route_install(struct bgp_dest *dest, struct bgp_path_info *info,
1855+
struct bgp *bgp, bool install)
1856+
{
1857+
/*
1858+
* BGP is installing this route and bgp has been configured
1859+
* to suppress announcements until the route has been installed
1860+
* let's set the fact that we expect this route to be installed
1861+
*/
1862+
if (install) {
1863+
if (BGP_SUPPRESS_FIB_ENABLED(bgp))
1864+
SET_FLAG(dest->flags, BGP_NODE_FIB_INSTALL_PENDING);
1865+
1866+
if (bgp->main_zebra_update_hold)
1867+
return;
1868+
} else {
1869+
UNSET_FLAG(dest->flags, BGP_NODE_FIB_INSTALL_PENDING);
1870+
}
1871+
1872+
/*
1873+
* Don't try to install if we're not connected to Zebra or Zebra doesn't
1874+
* know of this instance.
1875+
*/
1876+
if (!bgp_install_info_to_zebra(bgp))
1877+
return;
1878+
1879+
if (!CHECK_FLAG(dest->flags, BGP_NODE_SCHEDULE_FOR_INSTALL) &&
1880+
!CHECK_FLAG(dest->flags, BGP_NODE_SCHEDULE_FOR_DELETE)) {
1881+
zebra_announce_add_tail(&bm->zebra_announce_head, dest);
1882+
/*
1883+
* If neither flag is set and za_bgp_pi is not set then it is a bug
1884+
*/
1885+
assert(!dest->za_bgp_pi);
1886+
bgp_path_info_lock(info);
1887+
bgp_dest_lock_node(dest);
1888+
dest->za_bgp_pi = info;
1889+
} else if (CHECK_FLAG(dest->flags, BGP_NODE_SCHEDULE_FOR_INSTALL)) {
1890+
assert(dest->za_bgp_pi);
1891+
bgp_path_info_unlock(dest->za_bgp_pi);
1892+
bgp_path_info_lock(info);
1893+
dest->za_bgp_pi = info;
1894+
} else if (CHECK_FLAG(dest->flags, BGP_NODE_SCHEDULE_FOR_DELETE)) {
1895+
assert(dest->za_bgp_pi);
1896+
if (install)
1897+
bgp_zebra_withdraw_actual(dest, dest->za_bgp_pi, bgp);
1898+
1899+
bgp_path_info_unlock(dest->za_bgp_pi);
1900+
bgp_path_info_lock(info);
1901+
dest->za_bgp_pi = info;
1902+
}
1903+
1904+
if (install) {
1905+
UNSET_FLAG(dest->flags, BGP_NODE_SCHEDULE_FOR_DELETE);
1906+
SET_FLAG(dest->flags, BGP_NODE_SCHEDULE_FOR_INSTALL);
1907+
} else {
1908+
UNSET_FLAG(dest->flags, BGP_NODE_SCHEDULE_FOR_INSTALL);
1909+
SET_FLAG(dest->flags, BGP_NODE_SCHEDULE_FOR_DELETE);
1910+
}
1911+
1912+
event_add_event(bm->master, bgp_handle_route_announcements_to_zebra,
1913+
NULL, 0, &bm->t_bgp_zebra_route);
17781914
}
17791915

17801916
/* Withdraw all entries in a BGP instances RIB table from Zebra */
@@ -1795,7 +1931,7 @@ void bgp_zebra_withdraw_table_all_subtypes(struct bgp *bgp, afi_t afi, safi_t sa
17951931
for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
17961932
if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)
17971933
&& (pi->type == ZEBRA_ROUTE_BGP))
1798-
bgp_zebra_withdraw(dest, pi, bgp);
1934+
bgp_zebra_route_install(dest, pi, bgp, false);
17991935
}
18001936
}
18011937
}
@@ -3470,6 +3606,7 @@ void bgp_zebra_init(struct event_loop *master, unsigned short instance)
34703606
zclient = zclient_new(master, &zclient_options_default, bgp_handlers,
34713607
array_size(bgp_handlers));
34723608
zclient_init(zclient, ZEBRA_ROUTE_BGP, 0, &bgpd_privs);
3609+
zclient->zebra_buffer_write_ready = bgp_zebra_buffer_write_ready;
34733610
zclient->zebra_connected = bgp_zebra_connected;
34743611
zclient->zebra_capabilities = bgp_zebra_capabilities;
34753612
zclient->nexthop_update = bgp_nexthop_update;

bgpd/bgp_zebra.h

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,10 @@ extern void bgp_zebra_destroy(void);
2828
extern int bgp_zebra_get_table_range(struct zclient *zc, uint32_t chunk_size,
2929
uint32_t *start, uint32_t *end);
3030
extern int bgp_if_update_all(void);
31-
extern void bgp_zebra_announce(struct bgp_dest *dest,
32-
struct bgp_path_info *path, struct bgp *bgp);
31+
extern void bgp_zebra_route_install(struct bgp_dest *dest,
32+
struct bgp_path_info *path, struct bgp *bgp,
33+
bool install);
3334
extern void bgp_zebra_announce_table(struct bgp *bgp, afi_t afi, safi_t safi);
34-
extern void bgp_zebra_withdraw(struct bgp_dest *dest,
35-
struct bgp_path_info *path, struct bgp *bgp);
3635

3736
/* Announce routes of any bgp subtype of a table to zebra */
3837
extern void bgp_zebra_announce_table_all_subtypes(struct bgp *bgp, afi_t afi,
@@ -125,4 +124,7 @@ extern void bgp_zebra_send_nexthop_label(int cmd, mpls_label_t label,
125124
extern bool bgp_zebra_request_label_range(uint32_t base, uint32_t chunk_size,
126125
bool label_auto);
127126
extern void bgp_zebra_release_label_range(uint32_t start, uint32_t end);
127+
extern enum zclient_send_status
128+
bgp_zebra_withdraw_actual(struct bgp_dest *dest, struct bgp_path_info *info,
129+
struct bgp *bgp);
128130
#endif /* _QUAGGA_BGP_ZEBRA_H */

0 commit comments

Comments
 (0)