Skip to content

Commit

Permalink
libknet: rework knet_link_enable into knet_link_set_enable
Browse files Browse the repository at this point in the history
make it thread safe and fix all return codes (ret vs errno)

Signed-off-by: Fabio M. Di Nitto <fdinitto@redhat.com>
  • Loading branch information
fabbione committed Jan 28, 2013
1 parent 9250826 commit b2302b3
Show file tree
Hide file tree
Showing 8 changed files with 246 additions and 147 deletions.
6 changes: 3 additions & 3 deletions kronosnetd/vty_cli_cmds.c
Original file line number Diff line number Diff line change
Expand Up @@ -897,7 +897,7 @@ static int knet_cmd_no_link(struct knet_vty *vty)
knet_link_get_status(knet_iface->cfg_ring.knet_h, vty->host_id, vty->link_id, &status);

if (status.enabled) {
if (knet_link_enable(knet_iface->cfg_ring.knet_h, vty->host_id, vty->link_id, 0)) {
if (knet_link_set_enable(knet_iface->cfg_ring.knet_h, vty->host_id, vty->link_id, 0)) {
knet_vty_write(vty, "Error: unable to update switching cache%s", telnet_newline);
return -1;
}
Expand Down Expand Up @@ -955,7 +955,7 @@ static int knet_cmd_link(struct knet_vty *vty)

knet_link_set_timeout(knet_iface->cfg_ring.knet_h, vty->host_id, vty->link_id, 1000, 5000, 2048);

knet_link_enable(knet_iface->cfg_ring.knet_h, vty->host_id, vty->link_id, 1);
knet_link_set_enable(knet_iface->cfg_ring.knet_h, vty->host_id, vty->link_id, 1);
}

vty->node = NODE_LINK;
Expand Down Expand Up @@ -1390,7 +1390,7 @@ static int knet_cmd_no_interface(struct knet_vty *vty)
knet_host_get_host_list(knet_iface->cfg_ring.knet_h, host_ids, &host_ids_entries);
for (j = 0; j < host_ids_entries; j++) {
for (i = 0; i < KNET_MAX_LINK; i++) {
knet_link_enable(knet_iface->cfg_ring.knet_h, host_ids[j], i, 0);
knet_link_set_enable(knet_iface->cfg_ring.knet_h, host_ids[j], i, 0);
}
}

Expand Down
8 changes: 8 additions & 0 deletions libknet/handle.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,13 @@ static int _init_locks(knet_handle_t knet_h)

knet_h->lock_init_done = 1;

savederrno = pthread_rwlock_init(&knet_h->listener_rwlock, NULL);
if (savederrno) {
log_err(knet_h, KNET_SUB_HANDLE, "Unable to initialize listener rwlock: %s",
strerror(savederrno));
goto exit_fail;
}

savederrno = pthread_rwlock_init(&knet_h->host_rwlock, NULL);
if (savederrno) {
log_err(knet_h, KNET_SUB_HANDLE, "Unable to initialize host rwlock: %s",
Expand Down Expand Up @@ -70,6 +77,7 @@ static void _destroy_locks(knet_handle_t knet_h)
{
knet_h->lock_init_done = 0;
pthread_rwlock_destroy(&knet_h->list_rwlock);
pthread_rwlock_destroy(&knet_h->listener_rwlock);
pthread_rwlock_destroy(&knet_h->host_rwlock);
pthread_mutex_destroy(&knet_h->host_mutex);
pthread_cond_destroy(&knet_h->host_cond);
Expand Down
1 change: 1 addition & 0 deletions libknet/internals.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ struct knet_handle {
pthread_t dst_link_handler_thread;
int lock_init_done;
pthread_rwlock_t list_rwlock;
pthread_rwlock_t listener_rwlock;
pthread_rwlock_t host_rwlock;
pthread_mutex_t host_mutex;
pthread_cond_t host_cond;
Expand Down
20 changes: 18 additions & 2 deletions libknet/libknet.h
Original file line number Diff line number Diff line change
Expand Up @@ -488,9 +488,25 @@ int knet_link_get_config(knet_handle_t knet_h, uint16_t host_id, uint8_t link_id
struct sockaddr_storage *src_addr,
struct sockaddr_storage *dst_addr);

/*
* knet_link_set_enable
*
* knet_h - pointer to knet_handle_t
*
* host_id - see above
*
* link_id - see above
*
* enabled - 0 disable the link, 1 enable the link
*
* knet_link_set_enable returns:
*
* 0 on success
* -1 on error and errno is set.
*/

int knet_link_enable(knet_handle_t knet_h, uint16_t node_id, uint8_t link_id,
int enabled);
int knet_link_set_enable(knet_handle_t knet_h, uint16_t host_id, uint8_t link_id,
int enabled);

int knet_link_set_timeout(knet_handle_t knet_h, uint16_t node_id, uint8_t link_id, time_t interval, time_t timeout, unsigned int precision);
int knet_link_get_timeout(knet_handle_t knet_h, uint16_t node_id, uint8_t link_id, time_t *interval, time_t *timeout, unsigned int *precision);
Expand Down
222 changes: 143 additions & 79 deletions libknet/link.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,90 +23,38 @@
#include "host.h"

int _link_updown(knet_handle_t knet_h, uint16_t node_id,
struct knet_link *lnk, int enabled, int connected)
struct knet_link *link, int enabled, int connected)
{
unsigned int old_enabled = lnk->status.enabled;
unsigned int old_connected = lnk->status.connected;
int savederrno = 0, err = 0;
unsigned int old_enabled = link->status.enabled;
unsigned int old_connected = link->status.connected;

if ((lnk->status.enabled == enabled) && (lnk->status.connected == connected))
if ((link->status.enabled == enabled) &&
(link->status.connected == connected))
return 0;

lnk->status.enabled = enabled;
lnk->status.connected = connected;
link->status.enabled = enabled;
link->status.connected = connected;

if (_dst_cache_update(knet_h, node_id)) {
err = _dst_cache_update(knet_h, node_id);
if (err) {
savederrno = errno;
log_debug(knet_h, KNET_SUB_LINK,
"Unable to update link status (host: %s link: %s enabled: %u connected: %u)",
knet_h->host_index[node_id]->name,
lnk->status.dst_ipaddr,
lnk->status.enabled,
lnk->status.connected);
lnk->status.enabled = old_enabled;
lnk->status.connected = old_connected;
return -1;
}

if ((lnk->status.dynconnected) && (!lnk->status.connected))
lnk->status.dynconnected = 0;

return 0;
}

int knet_link_enable(knet_handle_t knet_h, uint16_t node_id, uint8_t link_id, int enabled)
{
int err;
struct knet_link *lnk;

if (!knet_h->host_index[node_id])
link->status.dst_ipaddr,
link->status.enabled,
link->status.connected);
link->status.enabled = old_enabled;
link->status.connected = old_connected;
errno = savederrno;
return -1;

lnk = &knet_h->host_index[node_id]->link[link_id];

if (lnk->status.enabled == enabled)
return 0;

if (enabled) {
if (_listener_add(knet_h, lnk) < 0) {
log_err(knet_h, KNET_SUB_LINK, "Unable to setup listener for this link");
return -1;
}
log_debug(knet_h, KNET_SUB_LINK, "host: %s link: %s is enabled",
knet_h->host_index[node_id]->name, lnk->status.dst_ipaddr);
}

if (!enabled) {
struct knet_hinfo_data knet_hinfo_data;

knet_hinfo_data.khd_type = KNET_HOST_INFO_LINK_UP_DOWN;
knet_hinfo_data.khd_bcast = 0;
knet_hinfo_data.khd_dst_node_id = htons(node_id);
knet_hinfo_data.khd_dype.link_up_down.khdt_link_id = lnk->link_id;
knet_hinfo_data.khd_dype.link_up_down.khdt_link_status = 0;

_send_host_info(knet_h, &knet_hinfo_data, sizeof(struct knet_hinfo_data));
}

err = _link_updown(knet_h, node_id, lnk, enabled, lnk->status.connected);

if ((enabled) && (!err))
return 0;

if (err)
return -1;

err = _listener_remove(knet_h, lnk);
if ((link->status.dynconnected) &&
(!link->status.connected))
link->status.dynconnected = 0;

if ((err) && (err != EBUSY)) {
log_err(knet_h, KNET_SUB_LINK, "Unable to remove listener for this link");
if (_link_updown(knet_h, node_id, lnk, 1, lnk->status.connected))
lnk->status.enabled = 1;
log_debug(knet_h, KNET_SUB_LINK, "host: %s link: %s is NOT disabled",
knet_h->host_index[node_id]->name, lnk->status.dst_ipaddr);
return -1;
}
log_debug(knet_h, KNET_SUB_LINK, "host: %s link: %s is disabled",
knet_h->host_index[node_id]->name, lnk->status.dst_ipaddr);
lnk->host_info_up_sent = 0;
return 0;
}

Expand Down Expand Up @@ -195,6 +143,19 @@ int knet_link_get_timeout(knet_handle_t knet_h, uint16_t node_id, uint8_t link_i
return 0;
}

int knet_link_get_status(knet_handle_t knet_h,
uint16_t node_id,
uint8_t link_id,
struct knet_link_status *status)
{
if (!knet_h->host_index[node_id])
return -1;

memcpy(status, &knet_h->host_index[node_id]->link[link_id].status, sizeof(struct knet_link_status));

return 0;
}

int knet_link_set_config(knet_handle_t knet_h, uint16_t host_id, uint8_t link_id,
struct sockaddr_storage *src_addr,
struct sockaddr_storage *dst_addr)
Expand Down Expand Up @@ -374,15 +335,118 @@ int knet_link_get_config(knet_handle_t knet_h, uint16_t host_id, uint8_t link_id
return err;
}

int knet_link_get_status(knet_handle_t knet_h,
uint16_t node_id,
uint8_t link_id,
struct knet_link_status *status)
int knet_link_set_enable(knet_handle_t knet_h, uint16_t host_id, uint8_t link_id,
int enabled)
{
if (!knet_h->host_index[node_id])
int savederrno = 0, err = 0;
struct knet_host *host;
struct knet_link *link;

if (!knet_h) {
errno = EINVAL;
return -1;
}

memcpy(status, &knet_h->host_index[node_id]->link[link_id].status, sizeof(struct knet_link_status));
if (link_id >= KNET_MAX_LINK) {
errno = EINVAL;
return -1;
}

return 0;
/*
* this read lock might appear as an API violation, but be
* very careful because we cannot use a write lock (yet).
* the _send_host_info requires threads to be operational.
* a write lock here would deadlock.
* a read lock is sufficient as all functions invoked by
* this code are already thread safe.
*/
savederrno = pthread_rwlock_rdlock(&knet_h->list_rwlock);
if (savederrno) {
log_err(knet_h, KNET_SUB_LINK, "Unable to get read lock: %s",
strerror(savederrno));
errno = savederrno;
return -1;
}

host = knet_h->host_index[host_id];
if (!host) {
err = -1;
savederrno = EINVAL;
log_err(knet_h, KNET_SUB_LINK, "Unable to find host %u: %s",
host_id, strerror(savederrno));
goto exit_unlock;
}

link = &host->link[link_id];

if (!link->configured) {
err = -1;
savederrno = EINVAL;
log_err(knet_h, KNET_SUB_LINK, "host %u link %u is not configured: %s",
host_id, link_id, strerror(savederrno));
goto exit_unlock;
}

if (link->status.enabled == enabled) {
err = 0;
goto exit_unlock;
}

if (enabled) {
if (_listener_add(knet_h, link) < 0) {
savederrno = errno;
err = -1;
log_err(knet_h, KNET_SUB_LINK, "Unable to setup listener for this link");
goto exit_unlock;
}
log_debug(knet_h, KNET_SUB_LINK, "host: %u link: %u is enabled",
host_id, link_id);
}

if (!enabled) {
struct knet_hinfo_data knet_hinfo_data;

knet_hinfo_data.khd_type = KNET_HOST_INFO_LINK_UP_DOWN;
knet_hinfo_data.khd_bcast = 0;
knet_hinfo_data.khd_dst_node_id = htons(host_id);
knet_hinfo_data.khd_dype.link_up_down.khdt_link_id = link_id;
knet_hinfo_data.khd_dype.link_up_down.khdt_link_status = 0;
_send_host_info(knet_h, &knet_hinfo_data, sizeof(struct knet_hinfo_data));
}

err = _link_updown(knet_h, host_id, link, enabled, link->status.connected);
savederrno = errno;

if ((!err) && (enabled)) {
err = 0;
goto exit_unlock;
}

if (err) {
err = -1;
goto exit_unlock;
}

err = _listener_remove(knet_h, link);
savederrno = errno;

if ((err) && (savederrno != EBUSY)) {
log_err(knet_h, KNET_SUB_LINK, "Unable to remove listener for this link");
if (_link_updown(knet_h, host_id, link, 1, link->status.connected)) {
/* force link status the hard way */
link->status.enabled = 1;
}
log_debug(knet_h, KNET_SUB_LINK, "host: %s link: %s is NOT disabled",
knet_h->host_index[host_id]->name, link->status.dst_ipaddr);
err = -1;
goto exit_unlock;
}
log_debug(knet_h, KNET_SUB_LINK, "host: %s link: %s is disabled",
knet_h->host_index[host_id]->name, link->status.dst_ipaddr);
link->host_info_up_sent = 0;

exit_unlock:
pthread_rwlock_unlock(&knet_h->list_rwlock);
errno = savederrno;
return err;
}
Loading

0 comments on commit b2302b3

Please sign in to comment.