@@ -1619,6 +1619,10 @@ static bool rib_compare_routes(const struct route_entry *re1,
1619
1619
* v6 link-locals, and we also support multiple addresses in the same
1620
1620
* subnet on a single interface.
1621
1621
*/
1622
+ if (re1 -> type == ZEBRA_ROUTE_CONNECT &&
1623
+ (re1 -> nhe -> nhg .nexthop -> ifindex == re2 -> nhe -> nhg .nexthop -> ifindex ))
1624
+ return true;
1625
+
1622
1626
if (re1 -> type != ZEBRA_ROUTE_CONNECT && re1 -> type != ZEBRA_ROUTE_LOCAL )
1623
1627
return true;
1624
1628
@@ -2863,10 +2867,11 @@ static void process_subq_early_route_add(struct zebra_early_route *ere)
2863
2867
2864
2868
/* Link new re to node.*/
2865
2869
if (IS_ZEBRA_DEBUG_RIB ) {
2866
- rnode_debug (
2867
- rn , re -> vrf_id ,
2868
- "Inserting route rn %p, re %p (%s) existing %p, same_count %d" ,
2869
- rn , re , zebra_route_string (re -> type ), same , same_count );
2870
+ rnode_debug (rn , re -> vrf_id ,
2871
+ "Inserting route rn %p, re %p (%s/%s/%s) existing %p, same_count %d" ,
2872
+ rn , re , zebra_route_string (re -> type ),
2873
+ afi2str (ere -> afi ), safi2str (ere -> safi ), same ,
2874
+ same_count );
2870
2875
2871
2876
if (IS_ZEBRA_DEBUG_RIB_DETAILED )
2872
2877
route_entry_dump (
@@ -4370,8 +4375,10 @@ int rib_add_multipath(afi_t afi, safi_t safi, struct prefix *p,
4370
4375
return -1 ;
4371
4376
4372
4377
/* We either need nexthop(s) or an existing nexthop id */
4373
- if (ng == NULL && re -> nhe_id == 0 )
4378
+ if (ng == NULL && re -> nhe_id == 0 ) {
4379
+ zebra_rib_route_entry_free (re );
4374
4380
return -1 ;
4381
+ }
4375
4382
4376
4383
/*
4377
4384
* Use a temporary nhe to convey info to the common/main api.
@@ -4383,6 +4390,34 @@ int rib_add_multipath(afi_t afi, safi_t safi, struct prefix *p,
4383
4390
nhe .id = re -> nhe_id ;
4384
4391
4385
4392
n = zebra_nhe_copy (& nhe , 0 );
4393
+
4394
+ if (re -> type == ZEBRA_ROUTE_KERNEL ) {
4395
+ struct interface * ifp ;
4396
+ struct connected * connected ;
4397
+
4398
+ if (p -> family == AF_INET6 &&
4399
+ IN6_IS_ADDR_LINKLOCAL (& p -> u .prefix6 )) {
4400
+ zebra_nhg_free (n );
4401
+ zebra_rib_route_entry_free (re );
4402
+ return -1 ;
4403
+ }
4404
+
4405
+ ifp = if_lookup_prefix (p , re -> vrf_id );
4406
+ if (ifp ) {
4407
+ connected = connected_lookup_prefix (ifp , p );
4408
+
4409
+ if (connected && !CHECK_FLAG (connected -> flags ,
4410
+ ZEBRA_IFA_NOPREFIXROUTE )) {
4411
+ zebra_nhg_free (n );
4412
+ zebra_rib_route_entry_free (re );
4413
+ return -1 ;
4414
+ }
4415
+
4416
+ if (ifp -> ifindex == ng -> nexthop -> ifindex )
4417
+ re -> type = ZEBRA_ROUTE_CONNECT ;
4418
+ }
4419
+ }
4420
+
4386
4421
ret = rib_add_multipath_nhe (afi , safi , p , src_p , re , n , startup );
4387
4422
4388
4423
/* In error cases, free the route also */
@@ -4393,8 +4428,8 @@ int rib_add_multipath(afi_t afi, safi_t safi, struct prefix *p,
4393
4428
}
4394
4429
4395
4430
void rib_delete (afi_t afi , safi_t safi , vrf_id_t vrf_id , int type ,
4396
- unsigned short instance , uint32_t flags , struct prefix * p ,
4397
- struct prefix_ipv6 * src_p , const struct nexthop * nh ,
4431
+ unsigned short instance , uint32_t flags , const struct prefix * p ,
4432
+ const struct prefix_ipv6 * src_p , const struct nexthop * nh ,
4398
4433
uint32_t nhe_id , uint32_t table_id , uint32_t metric ,
4399
4434
uint8_t distance , bool fromkernel )
4400
4435
{
@@ -4458,6 +4493,9 @@ static const char *rib_update_event2str(enum rib_update_event event)
4458
4493
const char * ret = "UNKNOWN" ;
4459
4494
4460
4495
switch (event ) {
4496
+ case RIB_UPDATE_INTERFACE_DOWN :
4497
+ ret = "RIB_UPDATE_INTERFACE_DOWN" ;
4498
+ break ;
4461
4499
case RIB_UPDATE_KERNEL :
4462
4500
ret = "RIB_UPDATE_KERNEL" ;
4463
4501
break ;
@@ -4474,15 +4512,56 @@ static const char *rib_update_event2str(enum rib_update_event event)
4474
4512
return ret ;
4475
4513
}
4476
4514
4515
+ /*
4516
+ * We now keep kernel routes, but we don't have any
4517
+ * trigger events for them when they are implicitly
4518
+ * deleted. Since we are already walking the
4519
+ * entire table on a down event let's look at
4520
+ * the few kernel routes we may have
4521
+ */
4522
+ static void
4523
+ rib_update_handle_kernel_route_down_possibility (struct route_node * rn ,
4524
+ struct route_entry * re )
4525
+ {
4526
+ struct nexthop * nexthop = NULL ;
4527
+ bool alive = false;
4528
+
4529
+ for (ALL_NEXTHOPS (re -> nhe -> nhg , nexthop )) {
4530
+ struct interface * ifp = if_lookup_by_index (nexthop -> ifindex ,
4531
+ nexthop -> vrf_id );
4532
+
4533
+ if (ifp && if_is_up (ifp )) {
4534
+ alive = true;
4535
+ break ;
4536
+ }
4537
+ }
4538
+
4539
+ if (!alive ) {
4540
+ struct rib_table_info * rib_table = srcdest_rnode_table_info (rn );
4541
+ const struct prefix * p ;
4542
+ const struct prefix_ipv6 * src_p ;
4543
+
4544
+ srcdest_rnode_prefixes (rn , & p , (const struct prefix * * )& src_p );
4545
+
4546
+ rib_delete (rib_table -> afi , rib_table -> safi , re -> vrf_id ,
4547
+ re -> type , re -> instance , re -> flags , p , src_p , NULL , 0 ,
4548
+ re -> table , re -> metric , re -> distance , true);
4549
+ }
4550
+ }
4551
+
4477
4552
4478
4553
/* Schedule route nodes to be processed if they match the type */
4479
- static void rib_update_route_node (struct route_node * rn , int type )
4554
+ static void rib_update_route_node (struct route_node * rn , int type ,
4555
+ enum rib_update_event event )
4480
4556
{
4481
4557
struct route_entry * re , * next ;
4482
4558
bool re_changed = false;
4483
4559
4484
4560
RNODE_FOREACH_RE_SAFE (rn , re , next ) {
4485
- if (type == ZEBRA_ROUTE_ALL || type == re -> type ) {
4561
+ if (event == RIB_UPDATE_INTERFACE_DOWN && type == re -> type &&
4562
+ type == ZEBRA_ROUTE_KERNEL )
4563
+ rib_update_handle_kernel_route_down_possibility (rn , re );
4564
+ else if (type == ZEBRA_ROUTE_ALL || type == re -> type ) {
4486
4565
SET_FLAG (re -> status , ROUTE_ENTRY_CHANGED );
4487
4566
re_changed = true;
4488
4567
}
@@ -4522,28 +4601,32 @@ void rib_update_table(struct route_table *table, enum rib_update_event event,
4522
4601
/*
4523
4602
* If we are looking at a route node and the node
4524
4603
* has already been queued we don't
4525
- * need to queue it up again
4604
+ * need to queue it up again, unless it is
4605
+ * an interface down event as that we need
4606
+ * to process this no matter what.
4526
4607
*/
4527
- if (rn -> info
4528
- && CHECK_FLAG (rib_dest_from_rnode (rn )-> flags ,
4529
- RIB_ROUTE_ANY_QUEUED ))
4608
+ if (rn -> info &&
4609
+ CHECK_FLAG (rib_dest_from_rnode (rn )-> flags ,
4610
+ RIB_ROUTE_ANY_QUEUED ) &&
4611
+ event != RIB_UPDATE_INTERFACE_DOWN )
4530
4612
continue ;
4531
4613
4532
4614
switch (event ) {
4615
+ case RIB_UPDATE_INTERFACE_DOWN :
4533
4616
case RIB_UPDATE_KERNEL :
4534
- rib_update_route_node (rn , ZEBRA_ROUTE_KERNEL );
4617
+ rib_update_route_node (rn , ZEBRA_ROUTE_KERNEL , event );
4535
4618
break ;
4536
4619
case RIB_UPDATE_RMAP_CHANGE :
4537
4620
case RIB_UPDATE_OTHER :
4538
- rib_update_route_node (rn , rtype );
4621
+ rib_update_route_node (rn , rtype , event );
4539
4622
break ;
4540
4623
case RIB_UPDATE_MAX :
4541
4624
break ;
4542
4625
}
4543
4626
}
4544
4627
}
4545
4628
4546
- static void rib_update_handle_vrf_all (enum rib_update_event event , int rtype )
4629
+ void rib_update_handle_vrf_all (enum rib_update_event event , int rtype )
4547
4630
{
4548
4631
struct zebra_router_table * zrt ;
4549
4632
0 commit comments