@@ -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 */
16861671void 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 ;
0 commit comments