Skip to content

Commit

Permalink
lib: introduce a read-write lock for northbound configurations
Browse files Browse the repository at this point in the history
The upcoming gRPC-based northbound plugin will run on a separate
pthread, and it will need to have access to the running configuration
global variable.  Introduce a rw-lock to control concurrent access
to the running configuration. Add the lock inside the "nb_config"
structure so that it can be used to protect candidate configurations
as well (this might be necessary depending on the threading scheme
of future northbound plugins).

Signed-off-by: Renato Westphal <renato@opensourcerouting.org>
  • Loading branch information
rwestphal committed Apr 26, 2019
1 parent 364ad67 commit 8398113
Show file tree
Hide file tree
Showing 10 changed files with 305 additions and 183 deletions.
111 changes: 59 additions & 52 deletions isisd/isis_cli.c
Original file line number Diff line number Diff line change
Expand Up @@ -188,10 +188,14 @@ DEFPY(ip_router_isis, ip_router_isis_cmd, "ip router isis WORD$tag",
}

/* check if the interface is a loopback and if so set it as passive */
ifp = nb_running_get_entry(NULL, VTY_CURR_XPATH, false);
if (ifp && if_is_loopback(ifp))
nb_cli_enqueue_change(vty, "./frr-isisd:isis/passive",
NB_OP_MODIFY, "true");
pthread_rwlock_rdlock(&running_config->lock);
{
ifp = nb_running_get_entry(NULL, VTY_CURR_XPATH, false);
if (ifp && if_is_loopback(ifp))
nb_cli_enqueue_change(vty, "./frr-isisd:isis/passive",
NB_OP_MODIFY, "true");
}
pthread_rwlock_unlock(&running_config->lock);

return nb_cli_apply_changes(vty, NULL);
}
Expand Down Expand Up @@ -258,10 +262,14 @@ DEFPY(ip6_router_isis, ip6_router_isis_cmd, "ipv6 router isis WORD$tag",
}

/* check if the interface is a loopback and if so set it as passive */
ifp = nb_running_get_entry(NULL, VTY_CURR_XPATH, false);
if (ifp && if_is_loopback(ifp))
nb_cli_enqueue_change(vty, "./frr-isisd:isis/passive",
NB_OP_MODIFY, "true");
pthread_rwlock_rdlock(&running_config->lock);
{
ifp = nb_running_get_entry(NULL, VTY_CURR_XPATH, false);
if (ifp && if_is_loopback(ifp))
nb_cli_enqueue_change(vty, "./frr-isisd:isis/passive",
NB_OP_MODIFY, "true");
}
pthread_rwlock_unlock(&running_config->lock);

return nb_cli_apply_changes(vty, NULL);
}
Expand Down Expand Up @@ -368,20 +376,26 @@ DEFPY(no_is_type, no_is_type_cmd,
"Act as both a station router and an area router\n"
"Act as an area router only\n")
{
const char *value = NULL;
struct isis_area *area;
const char *value;

area = nb_running_get_entry(NULL, VTY_CURR_XPATH, false);
pthread_rwlock_rdlock(&running_config->lock);
{
struct isis_area *area;

area = nb_running_get_entry(NULL, VTY_CURR_XPATH, false);

/*
* Put the is-type back to defaults:
* - level-1-2 on first area
* - level-1 for the rest
*/
if (area && listgetdata(listhead(isis->area_list)) == area)
value = "level-1-2";
else
value = NULL;
}
pthread_rwlock_unlock(&running_config->lock);

/*
* Put the is-type back to defaults:
* - level-1-2 on first area
* - level-1 for the rest
*/
if (area && listgetdata(listhead(isis->area_list)) == area)
value = "level-1-2";
else
value = NULL;
nb_cli_enqueue_change(vty, "./is-type", NB_OP_MODIFY, value);

return nb_cli_apply_changes(vty, NULL);
Expand Down Expand Up @@ -1769,50 +1783,43 @@ DEFPY(no_isis_circuit_type, no_isis_circuit_type_cmd,
"Level-1-2 adjacencies are formed\n"
"Level-2 only adjacencies are formed\n")
{
struct interface *ifp;
struct isis_circuit *circuit;
int is_type;
const char *circ_type;
const char *circ_type = NULL;

/*
* Default value depends on whether the circuit is part of an area,
* and the is-type of the area if there is one. So we need to do this
* here.
*/
ifp = nb_running_get_entry(NULL, VTY_CURR_XPATH, false);
if (!ifp)
goto def_val;
pthread_rwlock_rdlock(&running_config->lock);
{
struct interface *ifp;
struct isis_circuit *circuit;

circuit = circuit_scan_by_ifp(ifp);
if (!circuit)
goto def_val;
ifp = nb_running_get_entry(NULL, VTY_CURR_XPATH, false);
if (!ifp)
goto unlock;

if (circuit->state == C_STATE_UP)
is_type = circuit->area->is_type;
else
goto def_val;
circuit = circuit_scan_by_ifp(ifp);
if (!circuit || circuit->state != C_STATE_UP)
goto unlock;

switch (is_type) {
case IS_LEVEL_1:
circ_type = "level-1";
break;
case IS_LEVEL_2:
circ_type = "level-2";
break;
case IS_LEVEL_1_AND_2:
circ_type = "level-1-2";
break;
default:
return CMD_ERR_NO_MATCH;
switch (circuit->area->is_type) {
case IS_LEVEL_1:
circ_type = "level-1";
break;
case IS_LEVEL_2:
circ_type = "level-2";
break;
case IS_LEVEL_1_AND_2:
circ_type = "level-1-2";
break;
}
}
nb_cli_enqueue_change(vty, "./frr-isisd:isis/circuit-type",
NB_OP_MODIFY, circ_type);

return nb_cli_apply_changes(vty, NULL);
unlock:
pthread_rwlock_unlock(&running_config->lock);

def_val:
nb_cli_enqueue_change(vty, "./frr-isisd:isis/circuit-type",
NB_OP_MODIFY, NULL);
NB_OP_MODIFY, circ_type);

return nb_cli_apply_changes(vty, NULL);
}
Expand Down
16 changes: 10 additions & 6 deletions lib/command.c
Original file line number Diff line number Diff line change
Expand Up @@ -1705,12 +1705,16 @@ static int vty_write_config(struct vty *vty)
vty_out(vty, "frr defaults %s\n", DFLT_NAME);
vty_out(vty, "!\n");

for (i = 0; i < vector_active(cmdvec); i++)
if ((node = vector_slot(cmdvec, i)) && node->func
&& (node->vtysh || vty->type != VTY_SHELL)) {
if ((*node->func)(vty))
vty_out(vty, "!\n");
}
pthread_rwlock_rdlock(&running_config->lock);
{
for (i = 0; i < vector_active(cmdvec); i++)
if ((node = vector_slot(cmdvec, i)) && node->func
&& (node->vtysh || vty->type != VTY_SHELL)) {
if ((*node->func)(vty))
vty_out(vty, "!\n");
}
}
pthread_rwlock_unlock(&running_config->lock);

if (vty->type == VTY_TERM) {
vty_out(vty, "end\n");
Expand Down
19 changes: 11 additions & 8 deletions lib/if.c
Original file line number Diff line number Diff line change
Expand Up @@ -187,18 +187,21 @@ void if_update_to_new_vrf(struct interface *ifp, vrf_id_t vrf_id)
if (yang_module_find("frr-interface")) {
struct lyd_node *if_dnode;

if_dnode = yang_dnode_get(
running_config->dnode,
"/frr-interface:lib/interface[name='%s'][vrf='%s']/vrf",
ifp->name, old_vrf->name);
if (if_dnode) {
yang_dnode_change_leaf(if_dnode, vrf->name);
running_config->version++;
pthread_rwlock_wrlock(&running_config->lock);
{
if_dnode = yang_dnode_get(
running_config->dnode,
"/frr-interface:lib/interface[name='%s'][vrf='%s']/vrf",
ifp->name, old_vrf->name);
if (if_dnode) {
yang_dnode_change_leaf(if_dnode, vrf->name);
running_config->version++;
}
}
pthread_rwlock_unlock(&running_config->lock);
}
}


/* Delete interface structure. */
void if_delete_retain(struct interface *ifp)
{
Expand Down
7 changes: 6 additions & 1 deletion lib/libfrr.c
Original file line number Diff line number Diff line change
Expand Up @@ -830,7 +830,12 @@ static int frr_config_read_in(struct thread *t)
/*
* Update the shared candidate after reading the startup configuration.
*/
nb_config_replace(vty_shared_candidate_config, running_config, true);
pthread_rwlock_rdlock(&running_config->lock);
{
nb_config_replace(vty_shared_candidate_config, running_config,
true);
}
pthread_rwlock_unlock(&running_config->lock);

return 0;
}
Expand Down
Loading

0 comments on commit 8398113

Please sign in to comment.