From: Pierre Pfister Date: Wed, 22 Jun 2016 11:54:48 +0000 (+0100) Subject: Add admin-up flag to L2TP tunnels and start tunnels set to down X-Git-Tag: v16.09-rc1~248 X-Git-Url: https://gerrit.fd.io/r/gitweb?a=commitdiff_plain;h=80ee21386cea217d0e9292d2a8b15ea88bf99d30;p=vpp.git Add admin-up flag to L2TP tunnels and start tunnels set to down L2TP tunnels use virtual interfaces but directly send packets to l2-input node (not ethernet-input). This node requires a bridge-domain to be associated with the interface. Past code was immediatly turning the interface up, but some packets could be sent to l2-input without bridge domain between interface creation and association with a bridge domain. The tunnel is now created as down and has to be set up later (typically after being associated with a bridge-domain). Another option would have been to change the api and enforce a bridge-domain to be specified before the tunnel, but this is less flexible for the user. Change-Id: I26d1f36bb4f327d9fa1c8044023f2210c4117904 Signed-off-by: Pierre Pfister --- diff --git a/vnet/vnet/l2tp/decap.c b/vnet/vnet/l2tp/decap.c index 54400281890..68b7fabe76d 100644 --- a/vnet/vnet/l2tp/decap.c +++ b/vnet/vnet/l2tp/decap.c @@ -27,7 +27,8 @@ _(USER_TO_NETWORK, "L2TP user (ip6) to L2 network pkts") \ _(SESSION_ID_MISMATCH, "l2tpv3 local session id mismatches") \ _(COOKIE_MISMATCH, "l2tpv3 local cookie mismatches") \ -_(NO_SESSION, "l2tpv3 session not found") +_(NO_SESSION, "l2tpv3 session not found") \ +_(ADMIN_DOWN, "l2tpv3 tunnel is down") static char * l2t_decap_error_strings[] = { #define _(sym,string) string, @@ -169,6 +170,12 @@ static inline u32 last_stage (vlib_main_t *vm, vlib_node_runtime_t *node, vnet_buffer(b)->sw_if_index[VLIB_RX] = session->sw_if_index; + if (PREDICT_FALSE(!(session->admin_up))) { + b->error = node->errors[L2T_DECAP_ERROR_ADMIN_DOWN]; + next_index = L2T_DECAP_NEXT_DROP; + goto done; + } + /* strip the ip6 and L2TP header */ vlib_buffer_advance (b, sizeof (*ip6) + session->l2tp_hdr_size); diff --git a/vnet/vnet/l2tp/encap.c b/vnet/vnet/l2tp/encap.c index eca098cb07b..49f5a15fb5c 100644 --- a/vnet/vnet/l2tp/encap.c +++ b/vnet/vnet/l2tp/encap.c @@ -25,7 +25,8 @@ /* Statistics (not really errors) */ #define foreach_l2t_encap_error \ _(NETWORK_TO_USER, "L2TP L2 network to user (ip6) pkts") \ -_(LOOKUP_FAIL_TO_L3, "L2TP L2 session lookup failed pkts") +_(LOOKUP_FAIL_TO_L3, "L2TP L2 session lookup failed pkts") \ +_(ADMIN_DOWN, "L2TP tunnel is down") static char * l2t_encap_error_strings[] = { #define _(sym,string) string, @@ -105,6 +106,7 @@ static inline u32 last_stage (vlib_main_t *vm, vlib_node_runtime_t *node, l2t_session_t *s; ip6_header_t *ip6; u16 payload_length; + u32 next_index = L2T_ENCAP_NEXT_IP6_LOOKUP; /* Other-than-output pkt? We're done... */ if (vnet_buffer(b)->l2t.next_index != L2T_ENCAP_NEXT_IP6_LOOKUP) @@ -144,6 +146,12 @@ static inline u32 last_stage (vlib_main_t *vm, vlib_node_runtime_t *node, vlib_buffer_advance (b, -(sizeof (*ip6))); ip6 = vlib_buffer_get_current (b); + if (PREDICT_FALSE(!(s->admin_up))) { + b->error = node->errors[L2T_ENCAP_ERROR_ADMIN_DOWN]; + next_index = L2T_ENCAP_NEXT_DROP; + goto done; + } + ip6->ip_version_traffic_class_and_flow_label = clib_host_to_net_u32 (0x6<<28); @@ -159,6 +167,8 @@ static inline u32 last_stage (vlib_main_t *vm, vlib_node_runtime_t *node, ip6->dst_address.as_u64[0] = s->client_address.as_u64[0]; ip6->dst_address.as_u64[1] = s->client_address.as_u64[1]; + + done: if (PREDICT_FALSE(b->flags & VLIB_BUFFER_IS_TRACED)) { l2t_trace_t *t = vlib_add_trace (vm, node, b, sizeof (*t)); t->is_user_to_network = 0; @@ -173,7 +183,7 @@ static inline u32 last_stage (vlib_main_t *vm, vlib_node_runtime_t *node, t->session_index = session_index; } - return L2T_ENCAP_NEXT_IP6_LOOKUP; + return next_index; } #include diff --git a/vnet/vnet/l2tp/l2tp.c b/vnet/vnet/l2tp/l2tp.c index 4380137704b..85f9c30ed11 100644 --- a/vnet/vnet/l2tp/l2tp.c +++ b/vnet/vnet/l2tp/l2tp.c @@ -345,6 +345,7 @@ int create_l2tpv3_ipv6_tunnel (l2t_main_t * lm, s->l2tp_hdr_size = l2_sublayer_present ? sizeof (l2tpv3_header_t) : sizeof (l2tpv3_header_t) - sizeof(l2tp_hdr.l2_specific_sublayer); + s->admin_up = 0; /* Setup hash table entries */ switch (lm->lookup_type) { @@ -402,9 +403,6 @@ int create_l2tpv3_ipv6_tunnel (l2t_main_t * lm, if (sw_if_index) *sw_if_index = hi->sw_if_index; - vnet_sw_interface_set_flags (vnm, hi->sw_if_index, - VNET_SW_INTERFACE_FLAG_ADMIN_UP); - return 0; } @@ -665,6 +663,25 @@ l2tp_config (vlib_main_t * vm, unformat_input_t * input) VLIB_CONFIG_FUNCTION (l2tp_config, "l2tp"); + +clib_error_t * +l2tp_sw_interface_up_down (vnet_main_t * vnm, + u32 sw_if_index, + u32 flags) +{ + l2t_main_t *lm = &l2t_main; + vnet_hw_interface_t *hi = vnet_get_sup_hw_interface (vnm, sw_if_index); + if (hi->hw_class_index != l2tpv3_hw_class.index) + return 0; + + u32 session_index = hi->dev_instance; + l2t_session_t *s = pool_elt_at_index (lm->sessions, session_index); + s->admin_up = !! (flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP); + return 0; +} + +VNET_SW_INTERFACE_ADMIN_UP_DOWN_FUNCTION (l2tp_sw_interface_up_down); + clib_error_t *l2tp_init (vlib_main_t *vm) { l2t_main_t *lm = &l2t_main; diff --git a/vnet/vnet/l2tp/l2tp.h b/vnet/vnet/l2tp/l2tp.h index 2fc90fb9622..6ca9d7b6a9f 100644 --- a/vnet/vnet/l2tp/l2tp.h +++ b/vnet/vnet/l2tp/l2tp.h @@ -42,6 +42,8 @@ typedef struct { u8 l2tp_hdr_size; u8 l2_sublayer_present; u8 cookie_flags; /* in host byte order */ + + u8 admin_up; } l2t_session_t; typedef enum {