@@ -1524,8 +1524,9 @@ static void bgp_debug_zebra_nh(struct zapi_route *api)
1524
1524
}
1525
1525
}
1526
1526
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 )
1529
1530
{
1530
1531
struct bgp_path_info * bpi_ultimate ;
1531
1532
struct zapi_route api = { 0 };
@@ -1541,27 +1542,10 @@ void bgp_zebra_announce(struct bgp_dest *dest, struct bgp_path_info *info,
1541
1542
struct bgp_table * table = bgp_dest_table (dest );
1542
1543
const struct prefix * p = bgp_dest_get_prefix (dest );
1543
1544
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
-
1561
1545
if (table -> safi == SAFI_FLOWSPEC ) {
1562
1546
bgp_pbr_update_entry (bgp , p , info , table -> afi , table -> safi ,
1563
1547
true);
1564
- return ;
1548
+ return ZCLIENT_SEND_SUCCESS ;
1565
1549
}
1566
1550
1567
1551
/* Make Zebra API structure. */
@@ -1678,10 +1662,11 @@ void bgp_zebra_announce(struct bgp_dest *dest, struct bgp_path_info *info,
1678
1662
zlog_debug ("%s: %pFX: announcing to zebra (recursion %sset)" ,
1679
1663
__func__ , p , (recursion_flag ? "" : "NOT " ));
1680
1664
}
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 );
1683
1667
}
1684
1668
1669
+
1685
1670
/* Announce all routes of a table to zebra */
1686
1671
void bgp_zebra_announce_table (struct bgp * bgp , afi_t afi , safi_t safi )
1687
1672
{
@@ -1707,7 +1692,7 @@ void bgp_zebra_announce_table(struct bgp *bgp, afi_t afi, safi_t safi)
1707
1692
&& (pi -> sub_type == BGP_ROUTE_NORMAL
1708
1693
|| pi -> sub_type == BGP_ROUTE_IMPORTED )))
1709
1694
1710
- bgp_zebra_announce (dest , pi , bgp );
1695
+ bgp_zebra_route_install (dest , pi , bgp , true );
1711
1696
}
1712
1697
1713
1698
/* 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,
1729
1714
for (pi = bgp_dest_get_bgp_path_info (dest ); pi ; pi = pi -> next )
1730
1715
if (CHECK_FLAG (pi -> flags , BGP_PATH_SELECTED ) &&
1731
1716
pi -> type == ZEBRA_ROUTE_BGP )
1732
- bgp_zebra_announce (dest , pi , bgp );
1717
+ bgp_zebra_route_install (dest , pi , bgp , true );
1733
1718
}
1734
1719
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 )
1737
1723
{
1738
1724
struct zapi_route api ;
1739
1725
struct peer * peer ;
1740
1726
struct bgp_table * table = bgp_dest_table (dest );
1741
1727
const struct prefix * p = bgp_dest_get_prefix (dest );
1742
1728
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
-
1755
1729
if (table -> safi == SAFI_FLOWSPEC ) {
1756
1730
peer = info -> peer ;
1757
1731
bgp_pbr_update_entry (peer -> bgp , p , info , table -> afi ,
1758
1732
table -> safi , false);
1759
- return ;
1733
+ return ZCLIENT_SEND_SUCCESS ;
1760
1734
}
1761
1735
1762
1736
memset (& api , 0 , sizeof (api ));
@@ -1774,7 +1748,169 @@ void bgp_zebra_withdraw(struct bgp_dest *dest, struct bgp_path_info *info,
1774
1748
zlog_debug ("Tx route delete VRF %u %pFX" , bgp -> vrf_id ,
1775
1749
& api .prefix );
1776
1750
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 );
1778
1914
}
1779
1915
1780
1916
/* 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
1795
1931
for (pi = bgp_dest_get_bgp_path_info (dest ); pi ; pi = pi -> next ) {
1796
1932
if (CHECK_FLAG (pi -> flags , BGP_PATH_SELECTED )
1797
1933
&& (pi -> type == ZEBRA_ROUTE_BGP ))
1798
- bgp_zebra_withdraw (dest , pi , bgp );
1934
+ bgp_zebra_route_install (dest , pi , bgp , false );
1799
1935
}
1800
1936
}
1801
1937
}
@@ -3470,6 +3606,7 @@ void bgp_zebra_init(struct event_loop *master, unsigned short instance)
3470
3606
zclient = zclient_new (master , & zclient_options_default , bgp_handlers ,
3471
3607
array_size (bgp_handlers ));
3472
3608
zclient_init (zclient , ZEBRA_ROUTE_BGP , 0 , & bgpd_privs );
3609
+ zclient -> zebra_buffer_write_ready = bgp_zebra_buffer_write_ready ;
3473
3610
zclient -> zebra_connected = bgp_zebra_connected ;
3474
3611
zclient -> zebra_capabilities = bgp_zebra_capabilities ;
3475
3612
zclient -> nexthop_update = bgp_nexthop_update ;
0 commit comments