summary |
shortlog |
log |
commit | commitdiff |
review |
tree
raw |
patch |
inline | side by side (from parent 1:
de393bb)
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 <ppfister@cisco.com>
_(USER_TO_NETWORK, "L2TP user (ip6) to L2 network pkts") \
_(SESSION_ID_MISMATCH, "l2tpv3 local session id mismatches") \
_(COOKIE_MISMATCH, "l2tpv3 local cookie mismatches") \
_(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,
static char * l2t_decap_error_strings[] = {
#define _(sym,string) string,
vnet_buffer(b)->sw_if_index[VLIB_RX] = session->sw_if_index;
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);
/* strip the ip6 and L2TP header */
vlib_buffer_advance (b, sizeof (*ip6) + session->l2tp_hdr_size);
/* Statistics (not really errors) */
#define foreach_l2t_encap_error \
_(NETWORK_TO_USER, "L2TP L2 network to user (ip6) pkts") \
/* 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,
static char * l2t_encap_error_strings[] = {
#define _(sym,string) string,
l2t_session_t *s;
ip6_header_t *ip6;
u16 payload_length;
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)
/* Other-than-output pkt? We're done... */
if (vnet_buffer(b)->l2t.next_index != L2T_ENCAP_NEXT_IP6_LOOKUP)
vlib_buffer_advance (b, -(sizeof (*ip6)));
ip6 = vlib_buffer_get_current (b);
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);
ip6->ip_version_traffic_class_and_flow_label =
clib_host_to_net_u32 (0x6<<28);
ip6->dst_address.as_u64[0] = s->client_address.as_u64[0];
ip6->dst_address.as_u64[1] = s->client_address.as_u64[1];
ip6->dst_address.as_u64[0] = s->client_address.as_u64[0];
ip6->dst_address.as_u64[1] = s->client_address.as_u64[1];
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;
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;
t->session_index = session_index;
}
t->session_index = session_index;
}
- return L2T_ENCAP_NEXT_IP6_LOOKUP;
}
#include <vnet/pipeline.h>
}
#include <vnet/pipeline.h>
s->l2tp_hdr_size = l2_sublayer_present ?
sizeof (l2tpv3_header_t) :
sizeof (l2tpv3_header_t) - sizeof(l2tp_hdr.l2_specific_sublayer);
s->l2tp_hdr_size = l2_sublayer_present ?
sizeof (l2tpv3_header_t) :
sizeof (l2tpv3_header_t) - sizeof(l2tp_hdr.l2_specific_sublayer);
/* Setup hash table entries */
switch (lm->lookup_type) {
/* Setup hash table entries */
switch (lm->lookup_type) {
if (sw_if_index)
*sw_if_index = hi->sw_if_index;
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);
-
VLIB_CONFIG_FUNCTION (l2tp_config, "l2tp");
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;
clib_error_t *l2tp_init (vlib_main_t *vm)
{
l2t_main_t *lm = &l2t_main;
u8 l2tp_hdr_size;
u8 l2_sublayer_present;
u8 cookie_flags; /* in host byte order */
u8 l2tp_hdr_size;
u8 l2_sublayer_present;
u8 cookie_flags; /* in host byte order */
} l2t_session_t;
typedef enum {
} l2t_session_t;
typedef enum {