summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--vnet/vnet/devices/devices.c1
-rw-r--r--vnet/vnet/feature/feature.c54
-rw-r--r--vnet/vnet/feature/feature.h3
3 files changed, 35 insertions, 23 deletions
diff --git a/vnet/vnet/devices/devices.c b/vnet/vnet/devices/devices.c
index a1100194f3d..624cf76b2c2 100644
--- a/vnet/vnet/devices/devices.c
+++ b/vnet/vnet/devices/devices.c
@@ -52,6 +52,7 @@ VNET_FEATURE_ARC_INIT (device_input, static) =
{
.arc_name = "device-input",
.start_nodes = VNET_FEATURES ("device-input"),
+ .end_node = "ethernet-input",
.arc_index_ptr = &feature_main.device_input_feature_arc_index,
};
diff --git a/vnet/vnet/feature/feature.c b/vnet/vnet/feature/feature.c
index e1d172e5707..032fe784ace 100644
--- a/vnet/vnet/feature/feature.c
+++ b/vnet/vnet/feature/feature.c
@@ -108,6 +108,9 @@ vnet_feature_init (vlib_main_t * vm)
freg = freg->next;
}
+ cm->end_feature_index =
+ vnet_get_feature_index (arc_index, areg->end_node);
+
/* next */
areg = areg->next;
arc_index++;
@@ -118,25 +121,6 @@ vnet_feature_init (vlib_main_t * vm)
VLIB_INIT_FUNCTION (vnet_feature_init);
-void
-vnet_config_update_feature_count (vnet_feature_main_t * fm, u8 arc,
- u32 sw_if_index, int is_add)
-{
- uword bit_value;
-
- vec_validate (fm->feature_count_by_sw_if_index[arc], sw_if_index);
-
- fm->feature_count_by_sw_if_index[arc][sw_if_index] += is_add ? 1 : -1;
-
- ASSERT (fm->feature_count_by_sw_if_index[arc][sw_if_index] >= 0);
-
- bit_value = fm->feature_count_by_sw_if_index[arc][sw_if_index] > 0;
-
- fm->sw_if_index_has_features[arc] =
- clib_bitmap_set (fm->sw_if_index_has_features[arc], sw_if_index,
- bit_value);
-}
-
u8
vnet_get_feature_arc_index (const char *s)
{
@@ -180,6 +164,9 @@ vnet_get_feature_index (u8 arc, const char *s)
vnet_feature_registration_t *reg;
uword *p;
+ if (s == 0)
+ return ~0;
+
p = hash_get_mem (fm->next_feature_by_name[arc], s);
if (p == 0)
return ~0;
@@ -196,6 +183,8 @@ vnet_feature_enable_disable_with_index (u8 arc_index, u32 feature_index,
{
vnet_feature_main_t *fm = &feature_main;
vnet_feature_config_main_t *cm;
+ i16 feature_count;
+ int is_first_or_last;
u32 ci;
if (arc_index == (u8) ~ 0)
@@ -209,8 +198,9 @@ vnet_feature_enable_disable_with_index (u8 arc_index, u32 feature_index,
ci = cm->config_index_by_sw_if_index[sw_if_index];
vec_validate (fm->feature_count_by_sw_if_index[arc_index], sw_if_index);
- if (!enable_disable
- && fm->feature_count_by_sw_if_index[arc_index][sw_if_index] < 1)
+ feature_count = fm->feature_count_by_sw_if_index[arc_index][sw_if_index];
+
+ if (!enable_disable && feature_count < 1)
return 0;
ci = (enable_disable
@@ -220,9 +210,27 @@ vnet_feature_enable_disable_with_index (u8 arc_index, u32 feature_index,
n_feature_config_bytes);
cm->config_index_by_sw_if_index[sw_if_index] = ci;
- vnet_config_update_feature_count (fm, arc_index, sw_if_index,
- enable_disable);
+ /* update feature count */
+ enable_disable = (enable_disable > 0);
+ feature_count += enable_disable ? 1 : -1;
+ is_first_or_last = (feature_count == enable_disable);
+ ASSERT (feature_count >= 0);
+
+ if (is_first_or_last && cm->end_feature_index != ~0)
+ {
+ /*register end node */
+ ci = (enable_disable
+ ? vnet_config_add_feature
+ : vnet_config_del_feature)
+ (vlib_get_main (), &cm->config_main, ci, cm->end_feature_index, 0, 0);
+ cm->config_index_by_sw_if_index[sw_if_index] = ci;
+ }
+
+ fm->sw_if_index_has_features[arc_index] =
+ clib_bitmap_set (fm->sw_if_index_has_features[arc_index], sw_if_index,
+ (feature_count > 0));
+ fm->feature_count_by_sw_if_index[arc_index][sw_if_index] = feature_count;
return 0;
}
diff --git a/vnet/vnet/feature/feature.h b/vnet/vnet/feature/feature.h
index 0b33f0567e9..b27aaf17804 100644
--- a/vnet/vnet/feature/feature.h
+++ b/vnet/vnet/feature/feature.h
@@ -29,6 +29,8 @@ typedef struct _vnet_feature_arc_registration
/** Start nodes */
char **start_nodes;
int n_start_nodes;
+ /** End node */
+ char *end_node;
/* Feature arc index, assigned by init function */
u8 feature_arc_index;
u8 *arc_index_ptr;
@@ -63,6 +65,7 @@ typedef struct vnet_feature_config_main_t_
{
vnet_config_main_t config_main;
u32 *config_index_by_sw_if_index;
+ u32 end_feature_index;
} vnet_feature_config_main_t;
typedef struct