aboutsummaryrefslogtreecommitdiffstats
path: root/src/plugins/srv6-as
diff options
context:
space:
mode:
authorFrancois Clad <fclad@cisco.com>2018-07-04 11:47:21 +0200
committerDamjan Marion <dmarion@me.com>2018-07-13 19:19:27 +0000
commitb02f3b7b8a1c68a974ce43c64b28625b3ca2d4a5 (patch)
tree816ef9b8fd5e7c5330df002c68edee4c55806ae7 /src/plugins/srv6-as
parent0928da903f6be7c95189ac692e13d8edee4ebcd5 (diff)
srv6-as: Adding support for L2 traffic
Change-Id: I72978c5957cb1acf154c9de7ad153092bac37785 Signed-off-by: Francois Clad <fclad@cisco.com>
Diffstat (limited to 'src/plugins/srv6-as')
-rw-r--r--src/plugins/srv6-as/as.c110
-rw-r--r--src/plugins/srv6-as/as.h8
-rw-r--r--src/plugins/srv6-as/node.c163
3 files changed, 243 insertions, 38 deletions
diff --git a/src/plugins/srv6-as/as.c b/src/plugins/srv6-as/as.c
index 5cd5226a462..e771cb485ef 100644
--- a/src/plugins/srv6-as/as.c
+++ b/src/plugins/srv6-as/as.c
@@ -121,18 +121,21 @@ srv6_as_localsid_creation_fn (ip6_sr_localsid_t * localsid)
/* Retrieve the adjacency corresponding to the (OIF, next_hop) */
adj_index_t nh_adj_index = ADJ_INDEX_INVALID;
- if (ls_mem->ip_version == DA_IP4)
- nh_adj_index = adj_nbr_add_or_lock (FIB_PROTOCOL_IP4,
- VNET_LINK_IP4, &ls_mem->nh_addr,
- ls_mem->sw_if_index_out);
- else if (ls_mem->ip_version == DA_IP6)
- nh_adj_index = adj_nbr_add_or_lock (FIB_PROTOCOL_IP6,
- VNET_LINK_IP6, &ls_mem->nh_addr,
- ls_mem->sw_if_index_out);
- if (nh_adj_index == ADJ_INDEX_INVALID)
+ if (ls_mem->inner_type != AS_TYPE_L2)
{
- free_ls_mem (ls_mem);
- return SID_CREATE_INVALID_ADJ_INDEX;
+ if (ls_mem->inner_type == AS_TYPE_IP4)
+ nh_adj_index = adj_nbr_add_or_lock (FIB_PROTOCOL_IP4,
+ VNET_LINK_IP4, &ls_mem->nh_addr,
+ ls_mem->sw_if_index_out);
+ else if (ls_mem->inner_type == AS_TYPE_IP6)
+ nh_adj_index = adj_nbr_add_or_lock (FIB_PROTOCOL_IP6,
+ VNET_LINK_IP6, &ls_mem->nh_addr,
+ ls_mem->sw_if_index_out);
+ if (nh_adj_index == ADJ_INDEX_INVALID)
+ {
+ free_ls_mem (ls_mem);
+ return SID_CREATE_INVALID_ADJ_INDEX;
+ }
}
ls_mem->nh_adj = nh_adj_index;
@@ -159,7 +162,37 @@ srv6_as_localsid_creation_fn (ip6_sr_localsid_t * localsid)
return SID_CREATE_INVALID_IFACE_TYPE;
}
- if (ls_mem->ip_version == DA_IP4)
+ if (ls_mem->inner_type == AS_TYPE_L2)
+ {
+ /* Enable End.AS2 rewrite node for this interface */
+ int ret =
+ vnet_feature_enable_disable ("device-input", "srv6-as2-rewrite",
+ ls_mem->sw_if_index_in, 1, 0, 0);
+ if (ret != 0)
+ {
+ free_ls_mem (ls_mem);
+ return SID_CREATE_IFACE_FEATURE_ERROR;
+ }
+
+ /* Set interface in promiscuous mode */
+ vnet_main_t *vnm = vnet_get_main ();
+ ethernet_set_flags (vnm, ls_mem->sw_if_index_in,
+ ETHERNET_INTERFACE_FLAG_ACCEPT_ALL);
+
+ /* Prepare rewrite string */
+ ls_mem->rewrite = prepare_rewrite (ls_mem->src_addr, ls_mem->sid_list,
+ IP_PROTOCOL_IP6_NONXT);
+
+ /* Associate local SID index to this interface (resize vector if needed) */
+ if (ls_mem->sw_if_index_in >= vec_len (sm->sw_iface_localsid2))
+ {
+ vec_resize (sm->sw_iface_localsid2,
+ (pool_len (sm->vnet_main->interface_main.sw_interfaces)
+ - vec_len (sm->sw_iface_localsid2)));
+ }
+ sm->sw_iface_localsid2[ls_mem->sw_if_index_in] = localsid_index;
+ }
+ else if (ls_mem->inner_type == AS_TYPE_IP4)
{
/* Enable End.AS4 rewrite node for this interface */
int ret =
@@ -185,7 +218,7 @@ srv6_as_localsid_creation_fn (ip6_sr_localsid_t * localsid)
}
sm->sw_iface_localsid4[ls_mem->sw_if_index_in] = localsid_index;
}
- else if (ls_mem->ip_version == DA_IP6)
+ else if (ls_mem->inner_type == AS_TYPE_IP6)
{
/* Enable End.AS6 rewrite node for this interface */
int ret =
@@ -233,7 +266,23 @@ srv6_as_localsid_removal_fn (ip6_sr_localsid_t * localsid)
srv6_as_main_t *sm = &srv6_as_main;
srv6_as_localsid_t *ls_mem = localsid->plugin_mem;
- if (ls_mem->ip_version == DA_IP4)
+ if (ls_mem->inner_type == AS_TYPE_L2)
+ {
+ /* Disable End.AS2 rewrite node for this interface */
+ int ret;
+ ret = vnet_feature_enable_disable ("device-input", "srv6-as2-rewrite",
+ ls_mem->sw_if_index_in, 0, 0, 0);
+ if (ret != 0)
+ return -1;
+
+ /* Disable promiscuous mode on the interface */
+ vnet_main_t *vnm = vnet_get_main ();
+ ethernet_set_flags (vnm, ls_mem->sw_if_index_in, 0);
+
+ /* Remove local SID index from interface table */
+ sm->sw_iface_localsid2[ls_mem->sw_if_index_in] = ~(u32) 0;
+ }
+ else if (ls_mem->inner_type == AS_TYPE_IP4)
{
/* Disable End.AS4 rewrite node for this interface */
int ret;
@@ -245,7 +294,7 @@ srv6_as_localsid_removal_fn (ip6_sr_localsid_t * localsid)
/* Remove local SID index from interface table */
sm->sw_iface_localsid4[ls_mem->sw_if_index_in] = ~(u32) 0;
}
- else if (ls_mem->ip_version == DA_IP6)
+ else if (ls_mem->inner_type == AS_TYPE_IP6)
{
/* Disable End.AS6 rewrite node for this interface */
int ret;
@@ -285,20 +334,20 @@ format_srv6_as_localsid (u8 * s, va_list * args)
vnet_main_t *vnm = vnet_get_main ();
srv6_as_main_t *sm = &srv6_as_main;
- if (ls_mem->ip_version == DA_IP4)
+ if (ls_mem->inner_type == AS_TYPE_IP4)
{
s =
- format (s, "Next-hop:\t%U\n", format_ip4_address,
+ format (s, "Next-hop:\t%U\n\t", format_ip4_address,
&ls_mem->nh_addr.ip4);
}
- else
+ else if (ls_mem->inner_type == AS_TYPE_IP6)
{
s =
- format (s, "Next-hop:\t%U\n", format_ip6_address,
+ format (s, "Next-hop:\t%U\n\t", format_ip6_address,
&ls_mem->nh_addr.ip6);
}
- s = format (s, "\tOutgoing iface:\t%U\n", format_vnet_sw_if_index_name, vnm,
+ s = format (s, "Outgoing iface:\t%U\n", format_vnet_sw_if_index_name, vnm,
ls_mem->sw_if_index_out);
s = format (s, "\tIncoming iface:\t%U\n", format_vnet_sw_if_index_name, vnm,
ls_mem->sw_if_index_in);
@@ -342,7 +391,7 @@ unformat_srv6_as_localsid (unformat_input_t * input, va_list * args)
vnet_main_t *vnm = vnet_get_main ();
- u8 ip_version = 0;
+ u8 inner_type = AS_TYPE_L2;
ip46_address_t nh_addr;
u32 sw_if_index_out;
u32 sw_if_index_in;
@@ -365,14 +414,14 @@ unformat_srv6_as_localsid (unformat_input_t * input, va_list * args)
unformat_ip4_address,
&nh_addr.ip4))
{
- ip_version = DA_IP4;
+ inner_type = AS_TYPE_IP4;
params |= PARAM_AS_NH;
}
if (!(params & PARAM_AS_NH) && unformat (input, "nh %U",
unformat_ip6_address,
&nh_addr.ip6))
{
- ip_version = DA_IP6;
+ inner_type = AS_TYPE_IP6;
params |= PARAM_AS_NH;
}
else if (!(params & PARAM_AS_OIF) && unformat (input, "oif %U",
@@ -404,7 +453,7 @@ unformat_srv6_as_localsid (unformat_input_t * input, va_list * args)
}
/* Make sure that all parameters are supplied */
- u8 params_chk = (PARAM_AS_NH | PARAM_AS_OIF | PARAM_AS_IIF | PARAM_AS_SRC);
+ u8 params_chk = (PARAM_AS_OIF | PARAM_AS_IIF | PARAM_AS_SRC);
if ((params & params_chk) != params_chk || sid_list == NULL)
{
vec_free (sid_list);
@@ -417,10 +466,10 @@ unformat_srv6_as_localsid (unformat_input_t * input, va_list * args)
*plugin_mem_p = ls_mem;
/* Set local SID parameters */
- ls_mem->ip_version = ip_version;
- if (ip_version == DA_IP4)
+ ls_mem->inner_type = inner_type;
+ if (inner_type == AS_TYPE_IP4)
ls_mem->nh_addr.ip4 = nh_addr.ip4;
- else
+ else if (inner_type == AS_TYPE_IP6)
ls_mem->nh_addr.ip6 = nh_addr.ip6;
ls_mem->sw_if_index_out = sw_if_index_out;
ls_mem->sw_if_index_in = sw_if_index_in;
@@ -499,6 +548,13 @@ srv6_as_init (vlib_main_t * vm)
}
/* *INDENT-OFF* */
+VNET_FEATURE_INIT (srv6_as2_rewrite, static) =
+{
+ .arc_name = "device-input",
+ .node_name = "srv6-as2-rewrite",
+ .runs_before = VNET_FEATURES ("ethernet-input"),
+};
+
VNET_FEATURE_INIT (srv6_as4_rewrite, static) =
{
.arc_name = "ip4-unicast",
diff --git a/src/plugins/srv6-as/as.h b/src/plugins/srv6-as/as.h
index 5cb3e4cb784..0eed05d3156 100644
--- a/src/plugins/srv6-as/as.h
+++ b/src/plugins/srv6-as/as.h
@@ -23,8 +23,9 @@
#include <vppinfra/error.h>
#include <vppinfra/elog.h>
-#define DA_IP4 4
-#define DA_IP6 6
+#define AS_TYPE_L2 2
+#define AS_TYPE_IP4 4
+#define AS_TYPE_IP6 6
/*
* This is the memory that will be stored per each localsid
@@ -35,7 +36,7 @@ typedef struct
ip46_address_t nh_addr; /**< Proxied device address */
u32 sw_if_index_out; /**< Outgoing iface to proxied dev. */
u32 nh_adj; /**< Adjacency index for out. iface */
- u8 ip_version;
+ u8 inner_type;
u32 sw_if_index_in; /**< Incoming iface from proxied dev. */
u8 *rewrite; /**< Headers to be rewritten */
@@ -57,6 +58,7 @@ typedef struct
u32 srv6_localsid_behavior_id; /**< SRv6 LocalSID behavior number */
+ u32 *sw_iface_localsid2; /**< Retrieve local SID from iface */
u32 *sw_iface_localsid4; /**< Retrieve local SID from iface */
u32 *sw_iface_localsid6; /**< Retrieve local SID from iface */
diff --git a/src/plugins/srv6-as/node.c b/src/plugins/srv6-as/node.c
index 0e5a16e5e7b..d81a7e88722 100644
--- a/src/plugins/srv6-as/node.c
+++ b/src/plugins/srv6-as/node.c
@@ -92,6 +92,7 @@ typedef enum
SRV6_AS_LOCALSID_NEXT_ERROR,
SRV6_AS_LOCALSID_NEXT_REWRITE4,
SRV6_AS_LOCALSID_NEXT_REWRITE6,
+ SRV6_AS_LOCALSID_NEXT_INTERFACE,
SRV6_AS_LOCALSID_N_NEXT,
} srv6_as_localsid_next_t;
@@ -129,9 +130,10 @@ end_as_processing (vlib_buffer_t * b0,
ext_hdr = ip6_ext_next_header (ext_hdr);
}
- /* Make sure next header is IP */
+ /* Make sure next header is valid */
if (PREDICT_FALSE (hdr_type != IP_PROTOCOL_IPV6 &&
- hdr_type != IP_PROTOCOL_IP_IN_IP))
+ hdr_type != IP_PROTOCOL_IP_IN_IP &&
+ hdr_type != IP_PROTOCOL_IP6_NONXT))
{
return;
}
@@ -139,13 +141,23 @@ end_as_processing (vlib_buffer_t * b0,
/* Remove IP header and extensions */
vlib_buffer_advance (b0, encap_len);
- /* Set Xconnect adjacency to VNF */
- vnet_buffer (b0)->ip.adj_index[VLIB_TX] = ls0_mem->nh_adj;
+ if (hdr_type == IP_PROTOCOL_IP6_NONXT)
+ {
+ /* Set output interface */
+ vnet_buffer (b0)->sw_if_index[VLIB_TX] = ls0_mem->sw_if_index_out;
+
+ /* Set next node to interface-output */
+ *next0 = SRV6_AS_LOCALSID_NEXT_INTERFACE;
+ }
+ else
+ {
+ /* Set Xconnect adjacency to VNF */
+ vnet_buffer (b0)->ip.adj_index[VLIB_TX] = ls0_mem->nh_adj;
- if (ls0_mem->ip_version == DA_IP4)
- *next0 = SRV6_AS_LOCALSID_NEXT_REWRITE4;
- else if (ls0_mem->ip_version == DA_IP6)
- *next0 = SRV6_AS_LOCALSID_NEXT_REWRITE6;
+ /* Set next node to ip-rewrite */
+ *next0 = (hdr_type == IP_PROTOCOL_IPV6) ?
+ SRV6_AS_LOCALSID_NEXT_REWRITE6 : SRV6_AS_LOCALSID_NEXT_REWRITE4;
+ }
}
/**
@@ -236,6 +248,7 @@ VLIB_REGISTER_NODE (srv6_as_localsid_node) = {
.next_nodes = {
[SRV6_AS_LOCALSID_NEXT_REWRITE4] = "ip4-rewrite",
[SRV6_AS_LOCALSID_NEXT_REWRITE6] = "ip6-rewrite",
+ [SRV6_AS_LOCALSID_NEXT_INTERFACE] = "interface-output",
[SRV6_AS_LOCALSID_NEXT_ERROR] = "error-drop",
},
};
@@ -248,6 +261,140 @@ VLIB_REGISTER_NODE (srv6_as_localsid_node) = {
* @brief Graph node for applying a SR policy into an IPv6 packet. Encapsulation
*/
static uword
+srv6_as2_rewrite_fn (vlib_main_t * vm,
+ vlib_node_runtime_t * node, vlib_frame_t * frame)
+{
+ ip6_sr_main_t *srm = &sr_main;
+ srv6_as_main_t *sm = &srv6_as_main;
+ u32 n_left_from, next_index, *from, *to_next;
+ u32 cnt_packets = 0;
+
+ from = vlib_frame_vector_args (frame);
+ n_left_from = frame->n_vectors;
+ next_index = node->cached_next_index;
+
+ while (n_left_from > 0)
+ {
+ u32 n_left_to_next;
+
+ vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
+
+ /* TODO: Dual/quad loop */
+
+ while (n_left_from > 0 && n_left_to_next > 0)
+ {
+ u32 bi0;
+ vlib_buffer_t *b0;
+ ethernet_header_t *en0;
+ ip6_header_t *ip0 = 0;
+ ip6_sr_localsid_t *ls0;
+ srv6_as_localsid_t *ls0_mem;
+ u32 next0 = SRV6_AS_REWRITE_NEXT_LOOKUP;
+
+ bi0 = from[0];
+ to_next[0] = bi0;
+ from += 1;
+ to_next += 1;
+ n_left_from -= 1;
+ n_left_to_next -= 1;
+
+ b0 = vlib_get_buffer (vm, bi0);
+ en0 = vlib_buffer_get_current (b0);
+ ls0 = pool_elt_at_index (srm->localsids,
+ sm->sw_iface_localsid2[vnet_buffer
+ (b0)->sw_if_index
+ [VLIB_RX]]);
+ ls0_mem = ls0->plugin_mem;
+
+ if (PREDICT_FALSE (ls0_mem == NULL || ls0_mem->rewrite == NULL))
+ {
+ next0 = SRV6_AS_REWRITE_NEXT_ERROR;
+ b0->error = node->errors[SRV6_AS_REWRITE_COUNTER_NO_RW];
+ }
+ else
+ {
+ ASSERT (VLIB_BUFFER_PRE_DATA_SIZE >=
+ (vec_len (ls0_mem->rewrite) + b0->current_data));
+
+ clib_memcpy (((u8 *) en0) - vec_len (ls0_mem->rewrite),
+ ls0_mem->rewrite, vec_len (ls0_mem->rewrite));
+ vlib_buffer_advance (b0, -(word) vec_len (ls0_mem->rewrite));
+
+ ip0 = vlib_buffer_get_current (b0);
+
+ ip0->payload_length =
+ clib_host_to_net_u16 (b0->current_length -
+ sizeof (ip6_header_t));
+ }
+
+ if (PREDICT_FALSE (node->flags & VLIB_NODE_FLAG_TRACE) &&
+ PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
+ {
+ srv6_as_rewrite_trace_t *tr =
+ vlib_add_trace (vm, node, b0, sizeof *tr);
+ tr->error = 0;
+
+ if (next0 == SRV6_AS_REWRITE_NEXT_ERROR)
+ {
+ tr->error = 1;
+ }
+ else
+ {
+ clib_memcpy (tr->src.as_u8, ip0->src_address.as_u8,
+ sizeof tr->src.as_u8);
+ clib_memcpy (tr->dst.as_u8, ip0->dst_address.as_u8,
+ sizeof tr->dst.as_u8);
+ }
+ }
+
+ /* Increment per-SID AS rewrite counters */
+ vlib_increment_combined_counter (((next0 ==
+ SRV6_AS_LOCALSID_NEXT_ERROR) ?
+ &(sm->invalid_counters) :
+ &(sm->valid_counters)),
+ vm->thread_index, ls0_mem->index,
+ 1, vlib_buffer_length_in_chain (vm,
+ b0));
+
+ vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
+ n_left_to_next, bi0, next0);
+
+ cnt_packets++;
+ }
+
+ vlib_put_next_frame (vm, node, next_index, n_left_to_next);
+ }
+
+ /* Update counters */
+ vlib_node_increment_counter (vm, srv6_as4_rewrite_node.index,
+ SRV6_AS_REWRITE_COUNTER_PROCESSED,
+ cnt_packets);
+
+ return frame->n_vectors;
+}
+
+/* *INDENT-OFF* */
+VLIB_REGISTER_NODE (srv6_as2_rewrite_node) = {
+ .function = srv6_as2_rewrite_fn,
+ .name = "srv6-as2-rewrite",
+ .vector_size = sizeof (u32),
+ .format_trace = format_srv6_as_rewrite_trace,
+ .type = VLIB_NODE_TYPE_INTERNAL,
+ .n_errors = SRV6_AS_REWRITE_N_COUNTERS,
+ .error_strings = srv6_as_rewrite_counter_strings,
+ .n_next_nodes = SRV6_AS_REWRITE_N_NEXT,
+ .next_nodes = {
+ [SRV6_AS_REWRITE_NEXT_LOOKUP] = "ip6-lookup",
+ [SRV6_AS_REWRITE_NEXT_ERROR] = "error-drop",
+ },
+};
+/* *INDENT-ON* */
+
+
+/**
+ * @brief Graph node for applying a SR policy into an IPv6 packet. Encapsulation
+ */
+static uword
srv6_as4_rewrite_fn (vlib_main_t * vm,
vlib_node_runtime_t * node, vlib_frame_t * frame)
{