Skip to content

Commit

Permalink
Merge pull request #557 from pwieczorkiewicz/master_req
Browse files Browse the repository at this point in the history
fsm: cleanup netif-reference meta:require, do not recurse policy matches
  • Loading branch information
mtomaschewski committed Jul 1, 2015
2 parents 3060ebe + 210e5da commit 0001a99
Show file tree
Hide file tree
Showing 8 changed files with 93 additions and 83 deletions.
5 changes: 3 additions & 2 deletions client/ifup.c
Expand Up @@ -95,8 +95,9 @@ __ni_ifup_generate_match(const char *name, ni_ifworker_t *w)
ni_ifworker_t *child = w->children.data[i];
xml_node_t *cnode;

cnode = __ni_ifup_generate_match(NI_NANNY_IFPOLICY_MATCH_COND_CHILD, child);
xml_node_add_child(or ,cnode);
cnode = xml_node_new(NI_NANNY_IFPOLICY_MATCH_COND_CHILD, or);
if (!cnode || !__ni_ifup_generate_match_dev(cnode, child))
goto error;
}
}

Expand Down
2 changes: 1 addition & 1 deletion include/wicked/fsm.h
Expand Up @@ -186,7 +186,7 @@ struct ni_ifworker {
const ni_timer_t *timer;
const ni_timer_t *secondary_timer;

ni_fsm_require_t *child_state_req_list;
ni_fsm_require_t *check_state_req_list;

} fsm;
unsigned int extra_waittime;
Expand Down
6 changes: 3 additions & 3 deletions schema/bridge.xml
Expand Up @@ -12,10 +12,10 @@
-->
<device type="string">
<meta:netif-reference shared="false"/>
<meta:require check="netif-child-state" op="changeDevice" min-state="device-up" />
<meta:require check="netif-check-state" op="changeDevice" min-state="device-up" />
<!-- bnc#862530 workaround to not require link-up on all ports
<meta:require check="netif-child-state" op="login" min-state="link-authenticated" />
<meta:require check="netif-child-state" op="linkUp" min-state="link-up" />
<meta:require check="netif-check-state" op="login" min-state="link-authenticated" />
<meta:require check="netif-check-state" op="linkUp" min-state="link-up" />
-->
</device>

Expand Down
2 changes: 1 addition & 1 deletion schema/infiniband.xml
Expand Up @@ -35,7 +35,7 @@

<device type="string" description="Infiniband parent / lower device reference">
<meta:netif-reference shared="true"/>
<!-- meta:require check="netif-child-state" op="newDevice" min-state="device-exists" / -->
<!-- meta:require check="netif-check-state" op="newDevice" min-state="device-exists" / -->
</device>

<pkey type="uint16" description="Infiniband partition key"/>
Expand Down
6 changes: 3 additions & 3 deletions schema/macvlan.xml
Expand Up @@ -16,9 +16,9 @@
<define name="configuration" class="dict">
<device type="string">
<meta:netif-reference shared="true"/>
<meta:require check="netif-child-state" op="newDevice" min-state="device-up" />
<meta:require check="netif-child-state" op="linkUp" min-state="link-up" />
<meta:require check="netif-child-state" op="login" min-state="link-authenticated" />
<meta:require check="netif-check-state" op="newDevice" min-state="device-up" />
<meta:require check="netif-check-state" op="linkUp" min-state="link-up" />
<meta:require check="netif-check-state" op="login" min-state="link-authenticated" />
</device>
<address type="ethernet-address"/>
<mode type="builtin-macvlan-mode"/>
Expand Down
10 changes: 5 additions & 5 deletions schema/ppp.xml
Expand Up @@ -87,8 +87,8 @@
-->
<device type="string" constraint="required">
<meta:modem-reference shared="false"/>
<meta:require check="netif-child-state" op="newDevice" min-state="device-up" />
<meta:require check="netif-child-state" op="linkUp" min-state="link-up"/>
<meta:require check="netif-check-state" op="newDevice" min-state="device-up" />
<meta:require check="netif-check-state" op="linkUp" min-state="link-up"/>
</device>
</define>

Expand Down Expand Up @@ -121,9 +121,9 @@
<define name="pppoe-linkinfo" class="dict" extends="ppp:linkinfo">
<device type="string">
<meta:netif-reference shared="true" object-class="netif-ethernet"/>
<meta:require check="netif-child-state" op="newDevice" min-state="device-up" />
<meta:require check="netif-child-state" op="login" min-state="link-authenticated" />
<meta:require check="netif-child-state" op="linkUp" min-state="link-up" />
<meta:require check="netif-check-state" op="newDevice" min-state="device-up" />
<meta:require check="netif-check-state" op="login" min-state="link-authenticated" />
<meta:require check="netif-check-state" op="linkUp" min-state="link-up" />
</device>
</define>

Expand Down
6 changes: 3 additions & 3 deletions schema/vlan.xml
Expand Up @@ -11,9 +11,9 @@
<define name="linkinfo" class="dict">
<device type="string">
<meta:netif-reference shared="true"/>
<meta:require check="netif-child-state" op="newDevice" min-state="device-up" />
<meta:require check="netif-child-state" op="login" min-state="link-authenticated" />
<meta:require check="netif-child-state" op="linkUp" min-state="link-up" />
<meta:require check="netif-check-state" op="newDevice" min-state="device-up" />
<meta:require check="netif-check-state" op="login" min-state="link-authenticated" />
<meta:require check="netif-check-state" op="linkUp" min-state="link-up" />
</device>
<address type="ethernet-address"/>
<protocol type="builtin-vlan-protocol"/>
Expand Down
139 changes: 74 additions & 65 deletions src/fsm.c
Expand Up @@ -283,7 +283,7 @@ __ni_ifworker_destroy_fsm(ni_ifworker_t *w)
__ni_ifworker_reset_fsm(w);

__ni_ifworker_destroy_action_table(w);
ni_fsm_require_list_destroy(&w->fsm.child_state_req_list);
ni_fsm_require_list_destroy(&w->fsm.check_state_req_list);
}

void
Expand Down Expand Up @@ -1941,16 +1941,16 @@ static ni_bool_t
ni_fsm_require_netif_resolve(ni_fsm_t *fsm, ni_ifworker_t *w, ni_fsm_require_t *req)
{
xml_node_t *devnode = req->user_data;
ni_ifworker_t *child_worker;
ni_ifworker_t *cw;

if (req->user_data == NULL)
return TRUE;

if (!(child_worker = ni_ifworker_resolve_reference(fsm, devnode, NI_IFWORKER_TYPE_NETDEV, w->name)))
if (!(cw = ni_ifworker_resolve_reference(fsm, devnode, NI_IFWORKER_TYPE_NETDEV, w->name)))
return FALSE;

ni_debug_application("%s: resolved reference to subordinate device %s", w->name, child_worker->name);
if (!ni_ifworker_add_child(w, child_worker, devnode, FALSE))
ni_debug_application("%s: resolved reference to subordinate device %s", w->name, cw->name);
if (!ni_ifworker_add_child(w, cw, devnode, FALSE))
return FALSE;

req->user_data = NULL;
Expand All @@ -1975,16 +1975,16 @@ static ni_bool_t
ni_fsm_require_modem_resolve(ni_fsm_t *fsm, ni_ifworker_t *w, ni_fsm_require_t *req)
{
xml_node_t *devnode = req->user_data;
ni_ifworker_t *child_worker;
ni_ifworker_t *cw;

if (req->user_data == NULL)
return TRUE;

if (!(child_worker = ni_ifworker_resolve_reference(fsm, devnode, NI_IFWORKER_TYPE_MODEM, w->name)))
if (!(cw = ni_ifworker_resolve_reference(fsm, devnode, NI_IFWORKER_TYPE_MODEM, w->name)))
return FALSE;

ni_debug_application("%s: resolved reference to subordinate device %s", w->name, child_worker->name);
if (!ni_ifworker_add_child(w, child_worker, devnode, FALSE))
ni_debug_application("%s: resolved reference to subordinate device %s", w->name, cw->name);
if (!ni_ifworker_add_child(w, cw, devnode, FALSE))
return FALSE;

req->user_data = NULL;
Expand Down Expand Up @@ -2040,99 +2040,100 @@ ni_ifworker_link_detection_timeout(const ni_timer_t *timer, ni_fsm_timer_ctx_t *
/*
* Handle dependencies that check for a specific child state.
*/
struct ni_child_state_req_data {
ni_ifworker_t * child;
struct ni_check_state_req_data {
ni_ifworker_t * check_worker;
char * method;
ni_uint_range_t child_state;
ni_uint_range_t check_state;
};

static ni_bool_t
ni_ifworker_child_state_req_test(ni_fsm_t *fsm, ni_ifworker_t *w, ni_fsm_require_t *req)
ni_ifworker_check_state_req_test(ni_fsm_t *fsm, ni_ifworker_t *w, ni_fsm_require_t *req)
{
struct ni_child_state_req_data *data = (struct ni_child_state_req_data *) req->user_data;
ni_ifworker_t *child = data->child;
struct ni_check_state_req_data *data = (struct ni_check_state_req_data *) req->user_data;
ni_ifworker_t *cw = data->check_worker;
unsigned int wait_for_state;

if (child->fsm.state < data->child_state.min) {
wait_for_state = data->child_state.min;
if (cw->fsm.state < data->check_state.min) {
wait_for_state = data->check_state.min;
} else
if (child->fsm.state > data->child_state.max) {
wait_for_state = data->child_state.max;
if (cw->fsm.state > data->check_state.max) {
wait_for_state = data->check_state.max;
} else {
/* Okay, child interface is ready */
/* Okay, dependency worker's interface is ready */
return TRUE;
}

if (child->failed) {
/* Child is not in the expected state, but as it failed, it'll
* never get there. Fail the parent as well. */
ni_ifworker_fail(w, "subordinate device %s failed", child->name);
if (cw->failed) {
/* Dependency worker is not in the expected state,
* but as it failed, it'll never get there. Fail the parent as well.
*/
ni_ifworker_fail(w, "subordinate device %s failed", cw->name);
return FALSE;
}

ni_debug_application("%s: waiting for %s to reach state %s",
w->name, child->name,
w->name, cw->name,
ni_ifworker_state_name(wait_for_state));
return FALSE;
}

static void
ni_ifworker_child_state_req_free(ni_fsm_require_t *req)
ni_ifworker_check_state_req_free(ni_fsm_require_t *req)
{
struct ni_child_state_req_data *data = (struct ni_child_state_req_data *) req->user_data;
struct ni_check_state_req_data *data = (struct ni_check_state_req_data *) req->user_data;

if (data) {
ni_ifworker_release(data->child);
ni_ifworker_release(data->check_worker);
ni_string_free(&data->method);
free(data);
}
req->user_data = NULL;
}

static void
ni_ifworker_add_child_state_req(ni_ifworker_t *w, const char *method, ni_ifworker_t *child_worker,
ni_ifworker_add_check_state_req(ni_ifworker_t *w, const char *method, ni_ifworker_t *check_worker,
unsigned int min_state, unsigned int max_state)
{
struct ni_child_state_req_data *data;
struct ni_check_state_req_data *data;
ni_fsm_require_t *req;

data = xcalloc(1, sizeof(*data));
data->child = ni_ifworker_get(child_worker);
data->check_worker = ni_ifworker_get(check_worker);
ni_string_dup(&data->method, method);
data->child_state.min = min_state;
data->child_state.max = max_state;
data->check_state.min = min_state;
data->check_state.max = max_state;

req = ni_fsm_require_new(ni_ifworker_child_state_req_test, ni_ifworker_child_state_req_free);
req = ni_fsm_require_new(ni_ifworker_check_state_req_test, ni_ifworker_check_state_req_free);
req->user_data = data;

req->next = w->fsm.child_state_req_list;
w->fsm.child_state_req_list = req;
req->next = w->fsm.check_state_req_list;
w->fsm.check_state_req_list = req;
}

static void
ni_ifworker_get_child_state_reqs_for_method(ni_ifworker_t *w, ni_fsm_transition_t *action)
ni_ifworker_get_check_state_reqs_for_method(ni_ifworker_t *w, ni_fsm_transition_t *action)
{
ni_fsm_require_t **list, *req;

for (list = &w->fsm.child_state_req_list; (req = *list) != NULL; ) {
struct ni_child_state_req_data *data = req->user_data;
unsigned int min_state = data->child_state.min;
unsigned int max_state = data->child_state.max;
ni_ifworker_t *child = data->child;
for (list = &w->fsm.check_state_req_list; (req = *list) != NULL; ) {
struct ni_check_state_req_data *data = req->user_data;
unsigned int min_state = data->check_state.min;
unsigned int max_state = data->check_state.max;
ni_ifworker_t *cw = data->check_worker;

if (!ni_string_eq(data->method, action->common.method_name)) {
list = &req->next;
continue;
}

ni_debug_application("%s: %s transition requires state of child %s to be in range [%s, %s]",
w->name, data->method, child->name,
ni_debug_application("%s: %s transition requires state of worker %s to be in range [%s, %s]",
w->name, data->method, cw->name,
ni_ifworker_state_name(min_state),
ni_ifworker_state_name(max_state));
if (min_state > child->target_range.min)
child->target_range.min = min_state;
if (max_state < child->target_range.max)
child->target_range.max = max_state;
if (min_state > cw->target_range.min)
cw->target_range.min = min_state;
if (max_state < cw->target_range.max)
cw->target_range.max = max_state;

/* Move this requirement to the action's req list */
*list = req->next;
Expand Down Expand Up @@ -2867,7 +2868,7 @@ ni_ifworker_start(ni_fsm_t *fsm, ni_ifworker_t *w, unsigned long timeout)
* minimum/maximum state.
*/
for (j = 0; j < w->fsm.action_table[j].next_state; ++j) {
ni_ifworker_get_child_state_reqs_for_method(w, &w->fsm.action_table[j]);
ni_ifworker_get_check_state_reqs_for_method(w, &w->fsm.action_table[j]);
}

return 0;
Expand Down Expand Up @@ -3086,8 +3087,8 @@ ni_fsm_build_hierarchy(ni_fsm_t *fsm, ni_bool_t destructive)
continue;
}

ni_fsm_require_list_destroy(&w->fsm.child_state_req_list);
w->fsm.child_state_req_list = NULL;
ni_fsm_require_list_destroy(&w->fsm.check_state_req_list);
w->fsm.check_state_req_list = NULL;

if ((rv = ni_ifworker_bind_early(w, fsm, FALSE)) < 0) {
if (destructive) {
Expand Down Expand Up @@ -3125,7 +3126,7 @@ ni_ifworker_netif_resolve_cb(xml_node_t *node, const ni_xs_type_t *type, const x
{
struct ni_ifworker_xml_validation_user_data *closure = user_data;
ni_ifworker_t *w = closure->worker;
ni_ifworker_t *child_worker = NULL;
ni_ifworker_t *cw = NULL;
xml_node_t *mchild;

for (mchild = metadata->children; mchild; mchild = mchild->next) {
Expand All @@ -3134,43 +3135,51 @@ ni_ifworker_netif_resolve_cb(xml_node_t *node, const ni_xs_type_t *type, const x
if (ni_string_eq(mchild->name, "netif-reference")) {
ni_bool_t shared = FALSE;

if (child_worker) {
if (cw) {
ni_error("%s: duplicate/conflicting references", xml_node_location(node));
return FALSE;
}
if (!(child_worker = ni_ifworker_resolve_reference(closure->fsm, node, NI_IFWORKER_TYPE_NETDEV, w->name)))
if (!(cw = ni_ifworker_resolve_reference(closure->fsm, node, NI_IFWORKER_TYPE_NETDEV, w->name)))
continue;

if ((attr = xml_node_get_attr(mchild, "shared")) != NULL)
shared = ni_string_eq(attr, "true");

ni_debug_application("%s: resolved reference to subordinate device %s", w->name, child_worker->name);
if (!ni_ifworker_add_child(w, child_worker, node, shared))
ni_debug_application("%s: resolved reference to subordinate device %s", w->name, cw->name);
if (!ni_ifworker_add_child(w, cw, node, shared))
return FALSE;
} else
if (ni_string_eq(mchild->name, "modem-reference")) {
ni_bool_t shared = FALSE;

if (child_worker) {
if (cw) {
ni_error("%s: duplicate/conflicting references", xml_node_location(node));
return FALSE;
}
if (!(child_worker = ni_ifworker_resolve_reference(closure->fsm, node, NI_IFWORKER_TYPE_MODEM, w->name)))
if (!(cw = ni_ifworker_resolve_reference(closure->fsm, node, NI_IFWORKER_TYPE_MODEM, w->name)))
return FALSE;

if ((attr = xml_node_get_attr(mchild, "shared")) != NULL)
shared = ni_string_eq(attr, "true");

ni_debug_application("%s: resolved reference to subordinate device %s", w->name, child_worker->name);
if (!ni_ifworker_add_child(w, child_worker, node, shared))
ni_debug_application("%s: resolved reference to subordinate device %s", w->name, cw->name);
if (!ni_ifworker_add_child(w, cw, node, shared))
return FALSE;
} else
if (ni_string_eq(mchild->name, "require")) {
unsigned int min_state = NI_FSM_STATE_NONE, max_state = __NI_FSM_STATE_MAX;
const char *method;

if ((attr = xml_node_get_attr(mchild, "check")) == NULL
|| !ni_string_eq(attr, "netif-child-state"))
/* Ignore if there is no check attribute */
if (!(attr = xml_node_get_attr(mchild, "check")))
continue;

/* Compatibility name "netif-child-state" */
if (ni_string_eq(attr, "netif-child-state"))
attr = "netif-check-state";

/* Ignore if check attribute value is wrong */
if (!ni_string_eq(attr, "netif-check-state"))
continue;

if ((attr = xml_node_get_attr(mchild, "min-state")) != NULL) {
Expand All @@ -3194,13 +3203,13 @@ ni_ifworker_netif_resolve_cb(xml_node_t *node, const ni_xs_type_t *type, const x
return FALSE;
}

if (child_worker == NULL) {
ni_debug_application("%s: <meta:require check=netif-child-state> without netif-reference",
if (cw == NULL) {
ni_debug_application("%s: <meta:require check=netif-check-state> without netif-reference",
xml_node_location(mchild));
return FALSE;
}

ni_ifworker_add_child_state_req(w, method, child_worker, min_state, max_state);
ni_ifworker_add_check_state_req(w, method, cw, min_state, max_state);
}
}

Expand Down

0 comments on commit 0001a99

Please sign in to comment.