Skip to content

Commit

Permalink
dhcp6: fix to send up to 5 release retransmissions
Browse files Browse the repository at this point in the history
  • Loading branch information
mtomaschewski committed Jul 24, 2017
1 parent 553893a commit cfb2ee2
Show file tree
Hide file tree
Showing 7 changed files with 56 additions and 21 deletions.
4 changes: 4 additions & 0 deletions man/wicked-config.5.in
Expand Up @@ -575,6 +575,10 @@ lease time to one hour:
.IP
.B " <lease-time>3600</lease-time>
.PP
.TP
.B release-retransmits
Specifies the number of lease release retransmissions in the range 1..5.
Default is to send up to 5 (REL_MAX_RC) retransmissions.

.TP
.B ignore-server
Expand Down
1 change: 1 addition & 0 deletions src/appconfig.h
Expand Up @@ -135,6 +135,7 @@ typedef struct ni_config_dhcp6 {

unsigned int allow_update;
unsigned int lease_time;
unsigned int release_nretries;

ni_string_array_t user_class_data;
unsigned int vendor_class_en;
Expand Down
4 changes: 4 additions & 0 deletions src/config.c
Expand Up @@ -80,6 +80,7 @@ ni_config_new()
conf->addrconf.auto4.allow_update = ni_config_addrconf_update_auto4();
conf->addrconf.auto6.allow_update = ni_config_addrconf_update_auto6();
conf->addrconf.dhcp4.routes_opts = -1U;
conf->addrconf.dhcp6.release_nretries = -1U;

ni_config_fslocation_init(&conf->piddir, WICKED_PIDDIR, 0755);
ni_config_fslocation_init(&conf->statedir, WICKED_STATEDIR, 0755);
Expand Down Expand Up @@ -1071,6 +1072,9 @@ ni_config_parse_addrconf_dhcp6_nodes(ni_config_dhcp6_t *dhcp6, xml_node_t *node)
if (!strcmp(child->name, "lease-time") && child->cdata) {
dhcp6->lease_time = strtoul(child->cdata, NULL, 0);
} else
if (!strcmp(child->name, "release-retransmits") && child->cdata) {
dhcp6->release_nretries = strtoul(child->cdata, NULL, 0);
} else
if (!strcmp(child->name, "ignore-server")
&& (attrval = xml_node_get_attr(child, "ip")) != NULL) {
ni_string_array_append(&dhcp6->ignore_servers, attrval);
Expand Down
35 changes: 23 additions & 12 deletions src/dhcp6/device.c
Expand Up @@ -774,22 +774,25 @@ ni_dhcp6_device_retransmit_advance(ni_dhcp6_device_t *dev)

return TRUE;
}
ni_debug_dhcp("Retransmissions are disabled");
ni_debug_dhcp("%s: retransmission limit reached", dev->ifname);
return FALSE;
}

int
ni_dhcp6_device_retransmit(ni_dhcp6_device_t *dev)
{
int rv;

if (!ni_dhcp6_device_retransmit_advance(dev)) {
rv = ni_dhcp6_fsm_retransmit_end(dev);
ni_dhcp6_device_retransmit_disarm(dev);
return -1;
return rv;
}

if (ni_dhcp6_fsm_retransmit(dev) < 0)
return -1;
if ((rv = ni_dhcp6_fsm_retransmit(dev)) < 0)
return rv;

ni_debug_dhcp("Retransmitted, next deadline at %s",
ni_debug_dhcp("%s: retransmitted, next deadline at %s", dev->ifname,
ni_dhcp6_print_timeval(&dev->retrans.deadline));
return 0;
}
Expand Down Expand Up @@ -1049,13 +1052,12 @@ ni_dhcp6_start_release(void *user_data, const ni_timer_t *timer)
return;
dev->fsm.timer = NULL;

/* We just send out a singe RELEASE without waiting for the
* server's reply. We just keep our fingers crossed that it's
* getting out. If it doesn't, it's rather likely the network
* is hosed anyway, so there's little point in delaying. */
ni_dhcp6_fsm_release(dev);
ni_dhcp6_device_stop(dev);
ni_dhcp6_device_set_request(dev, NULL);
if (ni_dhcp6_fsm_release(dev) > 0)
return;

ni_dhcp6_device_drop_lease(dev);
ni_dhcp6_device_stop(dev);
}

int
Expand All @@ -1069,8 +1071,9 @@ ni_dhcp6_release(ni_dhcp6_device_t *dev, const ni_uuid_t *req_uuid)
rel_uuid ? " using UUID " : "", rel_uuid ? rel_uuid : "");
ni_string_free(&rel_uuid);

ni_dhcp6_device_stop(dev);
ni_dhcp6_device_set_request(dev, NULL);
ni_dhcp6_device_drop_lease(dev);
ni_dhcp6_device_stop(dev);
return -NI_ERROR_ADDRCONF_NO_LEASE;
}

Expand Down Expand Up @@ -1354,6 +1357,14 @@ ni_dhcp6_config_max_lease_time(void)
return ni_global.config->addrconf.dhcp6.lease_time;
}

unsigned int
ni_dhcp6_config_release_nretries(const char *ifname)
{
const ni_config_dhcp6_t *conf = ni_config_dhcp6_find_device(ifname);
/* >0: RFC 3315 Section 18.1.6, SHOULD retransmit one or more times */
return conf && conf->release_nretries ? conf->release_nretries : -1U;
}

static void
ni_dhcp6_config_set_request_options(const char *ifname, ni_uint_array_t *cfg, const ni_string_array_t *req)
{
Expand Down
1 change: 1 addition & 0 deletions src/dhcp6/device.h
Expand Up @@ -55,5 +55,6 @@ extern int ni_dhcp6_config_ignore_server(struct in6_addr);
extern ni_bool_t ni_dhcp6_config_have_server_preference(void);
extern ni_bool_t ni_dhcp6_config_server_preference(const struct in6_addr *, const ni_opaque_t *, int *);
extern unsigned int ni_dhcp6_config_max_lease_time(void);
extern unsigned int ni_dhcp6_config_release_nretries(const char *);

#endif /* __WICKED_DHCP6_DEVICE_H__ */
31 changes: 22 additions & 9 deletions src/dhcp6/fsm.c
Expand Up @@ -203,6 +203,19 @@ ni_dhcp6_fsm_retransmit(ni_dhcp6_device_t *dev)
}
}

int
ni_dhcp6_fsm_retransmit_end(ni_dhcp6_device_t *dev)
{
switch (dev->fsm.state) {
case NI_DHCP6_STATE_RELEASING:
ni_dhcp6_fsm_commit_lease(dev, NULL);
ni_dhcp6_device_stop(dev);
return 0;
default:
return -1;
}
}

void
ni_dhcp6_fsm_set_timeout_msec(ni_dhcp6_device_t *dev, unsigned long msec)
{
Expand Down Expand Up @@ -442,6 +455,7 @@ ni_dhcp6_fsm_timeout(ni_dhcp6_device_t *dev)
break;

case NI_DHCP6_STATE_RELEASING:
ni_dhcp6_fsm_commit_lease(dev, NULL);
ni_dhcp6_device_drop_lease(dev);
ni_dhcp6_device_stop(dev);
break;
Expand Down Expand Up @@ -1586,7 +1600,7 @@ __ni_dhcp6_fsm_release(ni_dhcp6_device_t *dev, unsigned int nretries)
return -1;

dev->fsm.state = NI_DHCP6_STATE_RELEASING;
if (nretries != -1U)
if (nretries < (unsigned int)dev->retrans.params.nretries)
dev->retrans.params.nretries = nretries;
rv = ni_dhcp6_device_transmit_init(dev);
} else {
Expand All @@ -1603,20 +1617,19 @@ __ni_dhcp6_fsm_release(ni_dhcp6_device_t *dev, unsigned int nretries)
int
ni_dhcp6_fsm_release(ni_dhcp6_device_t *dev)
{
if (dev->config == NULL) {
ni_debug_dhcp("%s: not configured, dropping lease", dev->ifname);
return ni_dhcp6_fsm_commit_lease(dev, NULL);
}
unsigned int nretries;

/* When all IA's are expired, just commit a release */
if (ni_dhcp6_lease_with_active_address(dev->lease)) {
if (dev->config->release_lease)
__ni_dhcp6_fsm_release(dev, 0);
return ni_dhcp6_fsm_commit_lease(dev, NULL);
if (dev->config && dev->config->release_lease) {
nretries = ni_dhcp6_config_release_nretries(dev->ifname);
if (__ni_dhcp6_fsm_release(dev, nretries) == 0)
return 1;
}
}

if (dev->lease)
ni_dhcp6_fsm_commit_lease(dev, NULL);
ni_dhcp6_send_event(NI_DHCP6_EVENT_RELEASED, dev, dev->lease);
return 0;
}

Expand Down
1 change: 1 addition & 0 deletions src/dhcp6/fsm.h
Expand Up @@ -59,6 +59,7 @@ extern void ni_dhcp6_fsm_reset(ni_dhcp6_device_t *dev);
extern int ni_dhcp6_fsm_release(ni_dhcp6_device_t *dev);

extern int ni_dhcp6_fsm_retransmit(ni_dhcp6_device_t *dev);
extern int ni_dhcp6_fsm_retransmit_end(ni_dhcp6_device_t *dev);

extern void ni_dhcp6_fsm_address_event(ni_dhcp6_device_t *, ni_netdev_t *,
ni_event_t, const ni_address_t *);
Expand Down

0 comments on commit cfb2ee2

Please sign in to comment.