Skip to content

Commit d158696

Browse files
Dave Barachdmarion
authored andcommitted
dhcp: update secondary radv_info structures
For details, see the Jira ticket below. Fix gerrit 23350. Type: fix Fixes: 28a6eb7 Ticket: VPP-1840 Signed-off-by: Dave Barach <[email protected]> Change-Id: Ic9248734bb330eadb302f8410e8db9c64723f075
1 parent 2695494 commit d158696

File tree

3 files changed

+122
-27
lines changed

3 files changed

+122
-27
lines changed

src/plugins/dhcp/dhcp6_pd_client_cp.c

Lines changed: 47 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@ typedef struct
7070
{
7171
prefix_info_t *prefix_pool;
7272
const u8 **prefix_group_name_by_index;
73+
/* vector of active prefix pool indicies, prep-H for pool_foreach(..) */
74+
u32 *indices;
7375
} ip6_prefix_main_t;
7476

7577
static ip6_prefix_main_t ip6_prefix_main;
@@ -277,6 +279,7 @@ dhcp6_pd_reply_event_handler (vl_api_dhcp6_pd_reply_event_t * mp)
277279
f64 current_time;
278280
clib_error_t *error = 0;
279281
u32 i;
282+
prefix_info_t *prefix_info;
280283

281284
current_time = vlib_time_now (vm);
282285

@@ -363,13 +366,26 @@ dhcp6_pd_reply_event_handler (vl_api_dhcp6_pd_reply_event_t * mp)
363366
send_client_message_start_stop (sw_if_index, server_index,
364367
mp->msg_type, 0, 0);
365368

369+
vec_reset_length (pm->indices);
370+
/*
371+
* We're going to loop through the pool multiple times,
372+
* so collect active indices.
373+
*/
374+
/* *INDENT-OFF* */
375+
pool_foreach (prefix_info, pm->prefix_pool,
376+
({
377+
vec_add1 (pm->indices, prefix_info - pm->prefix_pool);
378+
}));
379+
/* *INDENT-ON* */
380+
366381
for (i = 0; i < n_prefixes; i++)
367382
{
368-
prefix_info_t *prefix_info = 0;
369383
u8 prefix_length;
370384
u32 valid_time;
371385
u32 preferred_time;
386+
int j;
372387

388+
prefix_info = 0;
373389
api_prefix = &mp->prefixes[i];
374390

375391
prefix = (ip6_address_t *) api_prefix->prefix.address;
@@ -386,39 +402,48 @@ dhcp6_pd_reply_event_handler (vl_api_dhcp6_pd_reply_event_t * mp)
386402
continue;
387403

388404
u8 address_prefix_present = 0;
389-
/* *INDENT-OFF* */
390-
pool_foreach (prefix_info, pm->prefix_pool,
391-
({
392-
if (is_dhcpv6_pd_prefix (prefix_info) &&
393-
prefix_info->opaque_data == sw_if_index &&
394-
prefix_info->prefix_length == prefix_length &&
395-
ip6_prefixes_equal (&prefix_info->prefix, prefix, prefix_length))
396-
{
397-
address_prefix_present = 1;
398-
goto prefix_pool_foreach_out;
399-
}
400-
}));
401-
/* *INDENT-ON* */
402-
prefix_pool_foreach_out:
405+
406+
/* Look for a matching prefix_info */
407+
for (j = 0; j < vec_len (pm->indices); j++)
408+
{
409+
prefix_info = pool_elt_at_index (pm->prefix_pool, pm->indices[j]);
410+
411+
if (is_dhcpv6_pd_prefix (prefix_info) &&
412+
prefix_info->opaque_data == sw_if_index &&
413+
prefix_info->prefix_length == prefix_length &&
414+
ip6_prefixes_equal (&prefix_info->prefix, prefix,
415+
prefix_length))
416+
{
417+
address_prefix_present = 1;
418+
break;
419+
}
420+
}
403421

404422
if (address_prefix_present)
405423
{
424+
/* Found the (primary) prefix, update prefix timers */
425+
prefix_info->preferred_lt = preferred_time;
426+
prefix_info->valid_lt = valid_time;
427+
prefix_info->due_time = current_time + valid_time;
428+
if (prefix_info->due_time > rm->max_valid_due_time)
429+
rm->max_valid_due_time = prefix_info->due_time;
430+
406431
/*
407-
* We found the prefix. Move along.
408-
* Don't touch the prefix timers!
409-
* If we happen to receive a renew reply just before we
410-
* would have sent a solicit to renew the prefix delegation,
411-
* we forget to renew the delegation. Worse luck, we start
412-
* sending router advertisements with a valid time of zero,
413-
* and the wheels fall off...
432+
* Tell the RA code to update any secondary per-interface
433+
* timers that it might be hoarding.
414434
*/
435+
ip6_ra_update_secondary_radv_info
436+
(prefix, prefix_length,
437+
prefix_info->opaque_data /* sw_if_index */ ,
438+
valid_time, preferred_time);
415439
continue;
416440
}
417441

418442
if (valid_time == 0)
419443
continue;
420444

421445
pool_get (pm->prefix_pool, prefix_info);
446+
vec_add1 (pm->indices, prefix_info - pm->prefix_pool);
422447
prefix_info->prefix_group_index = client_state->prefix_group_index;
423448
set_is_dhcpv6_pd_prefix (prefix_info, 1);
424449
prefix_info->opaque_data = sw_if_index;

src/vnet/ip6-nd/ip6_ra.c

Lines changed: 70 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -559,13 +559,18 @@ icmp6_router_solicitation (vlib_main_t * vm,
559559
}
560560
h.unused = 0;
561561

562-
clib_warning ("Prefix %U valid %u preferred %u",
563-
format_ip6_address, &pr_info->prefix,
564-
clib_net_to_host_u32 (h.valid_time),
565-
clib_net_to_host_u32 (h.preferred_time));
562+
/* Handy for debugging, but too noisy... */
563+
if (0 && CLIB_DEBUG > 0)
564+
clib_warning
565+
("send RA for prefix %U/%d "
566+
"sw_if_index %d valid %u preferred %u",
567+
format_ip6_address, &pr_info->prefix,
568+
pr_info->prefix_len, sw_if_index0,
569+
clib_net_to_host_u32 (h.valid_time),
570+
clib_net_to_host_u32 (h.preferred_time));
566571

567572
if (h.valid_time == 0)
568-
clib_warning ("WARNING: valid_time 0!!!");
573+
clib_warning ("BUG: send RA with valid_time 0");
569574

570575
clib_memcpy(&h.dst_address, &pr_info->prefix, sizeof(ip6_address_t));
571576

@@ -1414,6 +1419,66 @@ ip6_ra_delegate_disable (index_t rai)
14141419
pool_put (ip6_ra_pool, radv_info);
14151420
}
14161421

1422+
void
1423+
ip6_ra_update_secondary_radv_info (ip6_address_t * address, u8 prefix_len,
1424+
u32 primary_sw_if_index,
1425+
u32 valid_time, u32 preferred_time)
1426+
{
1427+
vlib_main_t *vm = vlib_get_main ();
1428+
static u32 *radv_indices;
1429+
ip6_ra_t *radv_info;
1430+
int i;
1431+
ip6_address_t mask;
1432+
ip6_address_mask_from_width (&mask, prefix_len);
1433+
1434+
vec_reset_length (radv_indices);
1435+
/* *INDENT-OFF* */
1436+
pool_foreach (radv_info, ip6_ra_pool,
1437+
({
1438+
vec_add1 (radv_indices, radv_info - ip6_ra_pool);
1439+
}));
1440+
/* *INDENT-ON* */
1441+
1442+
/*
1443+
* If we have another customer for this prefix,
1444+
* tell the RA code about it...
1445+
*/
1446+
for (i = 0; i < vec_len (radv_indices); i++)
1447+
{
1448+
ip6_radv_prefix_t *this_prefix;
1449+
radv_info = pool_elt_at_index (ip6_ra_pool, radv_indices[i]);
1450+
1451+
/* We already took care of these timers... */
1452+
if (radv_info->sw_if_index == primary_sw_if_index)
1453+
continue;
1454+
1455+
/* *INDENT-OFF* */
1456+
pool_foreach (this_prefix, radv_info->adv_prefixes_pool,
1457+
({
1458+
if (this_prefix->prefix_len == prefix_len
1459+
&& ip6_address_is_equal_masked (&this_prefix->prefix, address,
1460+
&mask))
1461+
{
1462+
int rv = ip6_ra_prefix (vm,
1463+
radv_info->sw_if_index,
1464+
address,
1465+
prefix_len,
1466+
0 /* use_default */,
1467+
valid_time,
1468+
preferred_time,
1469+
0 /* no_advertise */,
1470+
0 /* off_link */,
1471+
0 /* no_autoconfig */,
1472+
0 /* no_onlink */,
1473+
0 /* is_no */);
1474+
if (rv != 0)
1475+
clib_warning ("ip6_neighbor_ra_prefix returned %d", rv);
1476+
}
1477+
}));
1478+
/* *INDENT-ON*/
1479+
}
1480+
}
1481+
14171482
/* send a RA or update the timer info etc.. */
14181483
static uword
14191484
ip6_ra_process_timer_event (vlib_main_t * vm,

src/vnet/ip6-nd/ip6_ra.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,11 @@ typedef void (*ip6_ra_report_notify_t) (const ip6_ra_report_t * rap);
7777

7878
extern void ip6_ra_report_register (ip6_ra_report_notify_t fn);
7979
extern void ip6_ra_report_unregister (ip6_ra_report_notify_t fn);
80+
extern void ip6_ra_update_secondary_radv_info (ip6_address_t * address,
81+
u8 prefix_len,
82+
u32 primary_sw_if_index,
83+
u32 valid_time,
84+
u32 preferred_time);
8085

8186
#endif /* included_ip6_neighbor_h */
8287

0 commit comments

Comments
 (0)