{
.arc_name = "device-input",
.start_nodes = VNET_FEATURES ("device-input"),
+ .last_in_arc = "ethernet-input",
.arc_index_ptr = &feature_main.device_input_feature_arc_index,
};
VNET_FEATURE_ARC_INIT (ethernet_output, static) =
{
.arc_name = "ethernet-output",
+ .last_in_arc = "error-drop",
.start_nodes = VNET_FEATURES ("adj-l2-midchain"),
.arc_index_ptr = ðernet_main.output_feature_arc_index,
};
clib_error_t *error;
vnet_feature_config_main_t *cm;
vnet_config_main_t *vcm;
+ char **features_in_order, *last_feature;
arc_index = areg->feature_arc_index;
cm = &fm->feature_config_mains[arc_index];
os_exit (1);
}
+ features_in_order = fm->feature_nodes[arc_index];
+
+ /* If specificed, verify that the last node in the arc is actually last */
+ if (areg->last_in_arc && vec_len (features_in_order) > 0)
+ {
+ last_feature = features_in_order[vec_len (features_in_order) - 1];
+ if (strncmp (areg->last_in_arc, last_feature,
+ strlen (areg->last_in_arc)))
+ clib_warning
+ ("WARNING: %s arc: last node is %s, but expected %s!",
+ areg->arc_name, last_feature, areg->last_in_arc);
+ }
+
fm->next_feature_by_name[arc_index] =
hash_create_string (0, sizeof (uword));
freg = fm->next_feature_by_arc[arc_index];
/** Start nodes */
char **start_nodes;
int n_start_nodes;
+ /** End of the arc (optional, for consistency-checking) */
+ char *last_in_arc;
/* Feature arc index, assigned by init function */
u8 feature_arc_index;
u8 *arc_index_ptr;
{
.arc_name = "interface-output",
.start_nodes = VNET_FEATURES (0),
+ .last_in_arc = "interface-tx",
.arc_index_ptr = &vnet_main.interface_main.output_feature_arc_index,
};
{
.arc_name = "ip4-unicast",
.start_nodes = VNET_FEATURES ("ip4-input", "ip4-input-no-checksum"),
+ .last_in_arc = "ip4-lookup",
.arc_index_ptr = &ip4_main.lookup_main.ucast_feature_arc_index,
};
{
.arc_name = "ip4-multicast",
.start_nodes = VNET_FEATURES ("ip4-input", "ip4-input-no-checksum"),
+ .last_in_arc = "ip4-mfib-forward-lookup",
.arc_index_ptr = &ip4_main.lookup_main.mcast_feature_arc_index,
};
{
.arc_name = "ip4-output",
.start_nodes = VNET_FEATURES ("ip4-rewrite", "ip4-midchain", "ip4-dvr-dpo"),
+ .last_in_arc = "interface-output",
.arc_index_ptr = &ip4_main.lookup_main.output_feature_arc_index,
};
{
.arc_name = "ip4-local",
.start_nodes = VNET_FEATURES ("ip4-local"),
+ .last_in_arc = "ip4-local-end-of-arc",
};
/* *INDENT-ON* */
{
.arc_name = "ip6-unicast",
.start_nodes = VNET_FEATURES ("ip6-input"),
+ .last_in_arc = "ip6-lookup",
.arc_index_ptr = &ip6_main.lookup_main.ucast_feature_arc_index,
};
{
.arc_name = "ip6-multicast",
.start_nodes = VNET_FEATURES ("ip6-input"),
+ .last_in_arc = "ip6-mfib-forward-lookup",
.arc_index_ptr = &ip6_main.lookup_main.mcast_feature_arc_index,
};
{
.arc_name = "ip6-output",
.start_nodes = VNET_FEATURES ("ip6-rewrite", "ip6-midchain", "ip6-dvr-dpo"),
+ .last_in_arc = "interface-output",
.arc_index_ptr = &ip6_main.lookup_main.output_feature_arc_index,
};
{
.arc_name = "mpls-input",
.start_nodes = VNET_FEATURES ("mpls-input"),
+ .last_in_arc = "mpls-lookup",
.arc_index_ptr = &mpls_main.input_feature_arc_index,
};
{
.arc_name = "mpls-output",
.start_nodes = VNET_FEATURES ("mpls-output", "mpls-midchain"),
+ .last_in_arc = "interface-output",
.arc_index_ptr = &mpls_main.output_feature_arc_index,
};