@@ -12,15 +12,16 @@ use crate::dendrite::{
1212use crate :: error:: Error ;
1313use ddm:: {
1414 add_tunnel_routes, new_ddm_client, remove_tunnel_routes,
15- update_tunnel_endpoints ,
15+ BOUNDARY_SERVICES_VNI ,
1616} ;
17+ use ddm_admin_client:: types:: TunnelOrigin ;
1718use ddm_admin_client:: Client as DdmClient ;
18- use dendrite:: ensure_tep_addr;
19+ use dendrite:: { ensure_tep_addr, link_is_up } ;
1920use dpd_client:: Client as DpdClient ;
2021use mg_common:: stats:: MgLowerStats as Stats ;
2122use rdb:: db:: Rib ;
22- use rdb:: { Db , Prefix , PrefixChangeNotification } ;
23- use slog:: { error, info, Logger } ;
23+ use rdb:: { Db , Prefix , PrefixChangeNotification , DEFAULT_ROUTE_PRIORITY } ;
24+ use slog:: { error, info, warn , Logger } ;
2425use std:: collections:: HashSet ;
2526use std:: net:: Ipv6Addr ;
2627use std:: sync:: mpsc:: { channel, RecvTimeoutError } ;
@@ -129,13 +130,10 @@ fn full_sync(
129130 // Make sure our tunnel endpoint address is on the switch ASIC
130131 ensure_tep_addr ( tep, dpd, rt. clone ( ) , log) ;
131132
132- // Announce tunnel endpoints via ddm
133- update_tunnel_endpoints ( tep, ddm, & rib, rt. clone ( ) , log) ;
134-
135133 // Compute the bestpath for each prefix and synchronize the ASIC routing
136134 // tables with the chosen paths.
137135 for ( prefix, _paths) in rib. iter ( ) {
138- sync_prefix ( tep, db. loc_rib ( ) , prefix, dpd, ddm, log, & rt) ?;
136+ sync_prefix ( tep, & db. loc_rib ( ) , prefix, dpd, ddm, log, & rt) ?;
139137 }
140138
141139 Ok ( ( ) )
@@ -152,23 +150,31 @@ fn handle_change(
152150 rt : Arc < tokio:: runtime:: Handle > ,
153151) -> Result < ( ) , Error > {
154152 for prefix in notification. changed . iter ( ) {
155- sync_prefix ( tep, db. loc_rib ( ) , prefix, dpd, ddm, log, & rt) ?;
153+ sync_prefix ( tep, & db. loc_rib ( ) , prefix, dpd, ddm, log, & rt) ?;
156154 }
157155
158156 Ok ( ( ) )
159157}
160158
161159fn sync_prefix (
162160 tep : Ipv6Addr ,
163- rib_loc : Rib ,
161+ rib_loc : & Rib ,
164162 prefix : & Prefix ,
165163 dpd : & DpdClient ,
166164 ddm : & DdmClient ,
167165 log : & Logger ,
168166 rt : & Arc < tokio:: runtime:: Handle > ,
169167) -> Result < ( ) , Error > {
170168 // The current routes that are on the ASIC.
171- let current = get_routes_for_prefix ( dpd, prefix, rt. clone ( ) , log. clone ( ) ) ?;
169+ let dpd_current =
170+ get_routes_for_prefix ( dpd, prefix, rt. clone ( ) , log. clone ( ) ) ?;
171+
172+ // The current tunnel routes in ddm
173+ let ddm_current = rt
174+ . block_on ( async { ddm. get_originated_tunnel_endpoints ( ) . await } ) ?
175+ . into_inner ( )
176+ . into_iter ( )
177+ . collect :: < HashSet < _ > > ( ) ;
172178
173179 // The best routes in the RIB
174180 let mut best: HashSet < RouteHash > = HashSet :: new ( ) ;
@@ -178,18 +184,74 @@ fn sync_prefix(
178184 }
179185 }
180186
187+ // Remove paths for which the link is down.
188+ best. retain ( |x| match link_is_up ( dpd, & x. port_id , & x. link_id , rt) {
189+ Err ( e) => {
190+ error ! (
191+ log,
192+ "sync_prefix: failed to get link state for {:?}/{:?} \
193+ not installing route {:?} -> {:?}: {e}",
194+ x. port_id,
195+ x. link_id,
196+ x. cidr,
197+ x. nexthop,
198+ ) ;
199+ false
200+ }
201+ Ok ( false ) => {
202+ warn ! (
203+ log,
204+ "sync_prefix: link {:?}/{:?} is not up, \
205+ not installing route {:?} -> {:?}",
206+ x. port_id,
207+ x. link_id,
208+ x. cidr,
209+ x. nexthop,
210+ ) ;
211+ false
212+ }
213+ Ok ( true ) => true ,
214+ } ) ;
215+
216+ //
217+ // Update the ASIC routing tables
218+ //
219+
181220 // Routes that are in the best set but not on the asic should be added.
182- let add: HashSet < RouteHash > = best. difference ( & current) . cloned ( ) . collect ( ) ;
221+ let add: HashSet < RouteHash > =
222+ best. difference ( & dpd_current) . cloned ( ) . collect ( ) ;
183223
184224 // Routes that are on the asic but not in the best set should be removed.
185- let del: HashSet < RouteHash > = current. difference ( & best) . cloned ( ) . collect ( ) ;
225+ let del: HashSet < RouteHash > =
226+ dpd_current. difference ( & best) . cloned ( ) . collect ( ) ;
186227
187- // Update DDM tunnel routing
188- add_tunnel_routes ( tep, ddm, & add, rt. clone ( ) , log) ;
189- remove_tunnel_routes ( tep, ddm, & del, rt. clone ( ) , log) ;
190-
191- // Update the ASIC routing tables
192228 update_dendrite ( add. iter ( ) , del. iter ( ) , dpd, rt. clone ( ) , log) ?;
193229
230+ //
231+ // Update the ddm tunnel advertisements
232+ //
233+
234+ let best_tunnel = best
235+ . clone ( )
236+ . into_iter ( )
237+ . map ( |x| TunnelOrigin {
238+ boundary_addr : tep,
239+ overlay_prefix : x. cidr ,
240+ metric : DEFAULT_ROUTE_PRIORITY ,
241+ vni : BOUNDARY_SERVICES_VNI ,
242+ } )
243+ . collect :: < HashSet < _ > > ( ) ;
244+
245+ // Routes that are in the best set but not in ddm should be added.
246+ let add: HashSet < TunnelOrigin > =
247+ best_tunnel. difference ( & ddm_current) . cloned ( ) . collect ( ) ;
248+
249+ // Routes that are in ddm but not in the best set should be removed.
250+ let del: HashSet < TunnelOrigin > =
251+ ddm_current. difference ( & best_tunnel) . cloned ( ) . collect ( ) ;
252+
253+ add_tunnel_routes ( tep, ddm, add. iter ( ) , rt, log) ;
254+ remove_tunnel_routes ( ddm, del. iter ( ) , rt, log) ;
255+
194256 Ok ( ( ) )
195257}
0 commit comments