sr: Support uSID function.

1. Add uSID function in VNET SRv6
2. Add test case for uSID

Type: feature

Signed-off-by: Tetsuya Murakami <tetsuya.mrk@gmail.com>
Change-Id: I354fc687192ed713ceb81fccc9f7b69b6777f6f6
Signed-off-by: Tetsuya Murakami <tetsuya.mrk@gmail.com>
This commit is contained in:
Tetsuya Murakami
2020-03-23 16:10:28 -07:00
committed by Neale Ranns
parent 032a5e3da0
commit ec9cb96687
9 changed files with 1139 additions and 573 deletions

View File

@ -19,7 +19,9 @@ class SRv6LocalSIDBehaviors():
SR_BEHAVIOR_DX4 = 7
SR_BEHAVIOR_DT6 = 8
SR_BEHAVIOR_DT4 = 9
SR_BEHAVIOR_LAST = 10 # Must always be the last one
SR_BEHAVIOR_END_UN_PERF = 10
SR_BEHAVIOR_END_UN = 11
SR_BEHAVIOR_LAST = 12 # Must always be the last one
class SRv6PolicyType():

View File

@ -1,21 +0,0 @@
# Copyright (c) 2018 Cisco and/or its affiliates.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at:
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
add_vpp_plugin(SRv6uN
SOURCES
un.c
node.c
INSTALL_HEADERS
un.h
)

View File

@ -1,289 +0,0 @@
/*
* Copyright (c) 2015 Cisco and/or its affiliates.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <vlib/vlib.h>
#include <vnet/vnet.h>
#include <vppinfra/error.h>
#include <srv6-un/un.h>
/******************************* Packet tracing *******************************/
typedef struct
{
u32 localsid_index;
} srv6_un_localsid_trace_t;
static u8 *
format_srv6_un_localsid_trace (u8 * s, va_list * args)
{
CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
srv6_un_localsid_trace_t *t = va_arg (*args, srv6_un_localsid_trace_t *);
return format (s, "SRv6-uN-localsid: localsid_index %d", t->localsid_index);
}
/********************************* Next nodes *********************************/
typedef enum
{
SRV6_UN_LOCALSID_NEXT_ERROR,
SRV6_UN_LOCALSID_NEXT_IP6LOOKUP,
SRV6_UN_LOCALSID_N_NEXT,
} srv6_un_localsid_next_t;
/******************************* Local SID node *******************************/
/**
* @brief Graph node for applying SRv6 uN.
*/
static uword
srv6_un_localsid_fn (vlib_main_t * vm,
vlib_node_runtime_t * node, vlib_frame_t * frame)
{
ip6_sr_main_t *sm = &sr_main;
u32 n_left_from, next_index, *from, *to_next;
from = vlib_frame_vector_args (frame);
n_left_from = frame->n_vectors;
next_index = node->cached_next_index;
u32 thread_index = vm->thread_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);
/* Quad - Loop */
while (n_left_from >= 8 && n_left_to_next >= 4)
{
u32 bi0, bi1, bi2, bi3;
vlib_buffer_t *b0, *b1, *b2, *b3;
ip6_header_t *ip0, *ip1, *ip2, *ip3;
u32 next0, next1, next2, next3;
next0 = next1 = next2 = next3 = SRV6_UN_LOCALSID_NEXT_IP6LOOKUP;
ip6_sr_localsid_t *ls0, *ls1, *ls2, *ls3;
/* Prefetch next iteration. */
{
vlib_buffer_t *p4, *p5, *p6, *p7;
p4 = vlib_get_buffer (vm, from[4]);
p5 = vlib_get_buffer (vm, from[5]);
p6 = vlib_get_buffer (vm, from[6]);
p7 = vlib_get_buffer (vm, from[7]);
/* Prefetch the buffer header and packet for the N+4 loop iteration */
vlib_prefetch_buffer_header (p4, LOAD);
vlib_prefetch_buffer_header (p5, LOAD);
vlib_prefetch_buffer_header (p6, LOAD);
vlib_prefetch_buffer_header (p7, LOAD);
CLIB_PREFETCH (p4->data, CLIB_CACHE_LINE_BYTES, STORE);
CLIB_PREFETCH (p5->data, CLIB_CACHE_LINE_BYTES, STORE);
CLIB_PREFETCH (p6->data, CLIB_CACHE_LINE_BYTES, STORE);
CLIB_PREFETCH (p7->data, CLIB_CACHE_LINE_BYTES, STORE);
}
to_next[0] = bi0 = from[0];
to_next[1] = bi1 = from[1];
to_next[2] = bi2 = from[2];
to_next[3] = bi3 = from[3];
from += 4;
to_next += 4;
n_left_from -= 4;
n_left_to_next -= 4;
b0 = vlib_get_buffer (vm, bi0);
b1 = vlib_get_buffer (vm, bi1);
b2 = vlib_get_buffer (vm, bi2);
b3 = vlib_get_buffer (vm, bi3);
ls0 =
pool_elt_at_index (sm->localsids,
vnet_buffer (b0)->ip.adj_index[VLIB_TX]);
ls1 =
pool_elt_at_index (sm->localsids,
vnet_buffer (b1)->ip.adj_index[VLIB_TX]);
ls2 =
pool_elt_at_index (sm->localsids,
vnet_buffer (b2)->ip.adj_index[VLIB_TX]);
ls3 =
pool_elt_at_index (sm->localsids,
vnet_buffer (b3)->ip.adj_index[VLIB_TX]);
ip0 = vlib_buffer_get_current (b0);
ip1 = vlib_buffer_get_current (b1);
ip2 = vlib_buffer_get_current (b2);
ip3 = vlib_buffer_get_current (b3);
/* Set Destination Address to Last Segment (index 0) */
ip0->dst_address.as_u16[2] = ip0->dst_address.as_u16[3];
ip0->dst_address.as_u16[3] = ip0->dst_address.as_u16[4];
ip0->dst_address.as_u16[4] = ip0->dst_address.as_u16[5];
ip0->dst_address.as_u16[5] = ip0->dst_address.as_u16[6];
ip0->dst_address.as_u16[6] = ip0->dst_address.as_u16[7];
ip0->dst_address.as_u16[7] = 0x0000;
ip1->dst_address.as_u16[2] = ip1->dst_address.as_u16[3];
ip1->dst_address.as_u16[3] = ip1->dst_address.as_u16[4];
ip1->dst_address.as_u16[4] = ip1->dst_address.as_u16[5];
ip1->dst_address.as_u16[5] = ip1->dst_address.as_u16[6];
ip1->dst_address.as_u16[6] = ip1->dst_address.as_u16[7];
ip1->dst_address.as_u16[7] = 0x0000;
ip2->dst_address.as_u16[2] = ip2->dst_address.as_u16[3];
ip2->dst_address.as_u16[3] = ip2->dst_address.as_u16[4];
ip2->dst_address.as_u16[4] = ip2->dst_address.as_u16[5];
ip2->dst_address.as_u16[5] = ip2->dst_address.as_u16[6];
ip2->dst_address.as_u16[6] = ip2->dst_address.as_u16[7];
ip2->dst_address.as_u16[7] = 0x0000;
ip3->dst_address.as_u16[2] = ip3->dst_address.as_u16[3];
ip3->dst_address.as_u16[3] = ip3->dst_address.as_u16[4];
ip3->dst_address.as_u16[4] = ip3->dst_address.as_u16[5];
ip3->dst_address.as_u16[5] = ip3->dst_address.as_u16[6];
ip3->dst_address.as_u16[6] = ip3->dst_address.as_u16[7];
ip3->dst_address.as_u16[7] = 0x0000;
if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
{
srv6_un_localsid_trace_t *tr =
vlib_add_trace (vm, node, b0, sizeof (*tr));
tr->localsid_index = ls0 - sm->localsids;
}
if (PREDICT_FALSE (b1->flags & VLIB_BUFFER_IS_TRACED))
{
srv6_un_localsid_trace_t *tr =
vlib_add_trace (vm, node, b1, sizeof (*tr));
tr->localsid_index = ls1 - sm->localsids;
}
if (PREDICT_FALSE (b2->flags & VLIB_BUFFER_IS_TRACED))
{
srv6_un_localsid_trace_t *tr =
vlib_add_trace (vm, node, b2, sizeof (*tr));
tr->localsid_index = ls2 - sm->localsids;
}
if (PREDICT_FALSE (b3->flags & VLIB_BUFFER_IS_TRACED))
{
srv6_un_localsid_trace_t *tr =
vlib_add_trace (vm, node, b3, sizeof (*tr));
tr->localsid_index = ls3 - sm->localsids;
}
vlib_increment_combined_counter
(&(sm->sr_ls_valid_counters),
thread_index, ls0 - sm->localsids,
1, vlib_buffer_length_in_chain (vm, b0));
vlib_increment_combined_counter
(&(sm->sr_ls_valid_counters),
thread_index, ls1 - sm->localsids,
1, vlib_buffer_length_in_chain (vm, b1));
vlib_increment_combined_counter
(&(sm->sr_ls_valid_counters),
thread_index, ls2 - sm->localsids,
1, vlib_buffer_length_in_chain (vm, b2));
vlib_increment_combined_counter
(&(sm->sr_ls_valid_counters),
thread_index, ls3 - sm->localsids,
1, vlib_buffer_length_in_chain (vm, b3));
vlib_validate_buffer_enqueue_x4 (vm, node, next_index, to_next,
n_left_to_next, bi0, bi1, bi2, bi3,
next0, next1, next2, next3);
}
while (n_left_from > 0 && n_left_to_next > 0)
{
u32 bi0;
vlib_buffer_t *b0;
ip6_header_t *ip0 = 0;
u32 next0 = SRV6_UN_LOCALSID_NEXT_IP6LOOKUP;
ip6_sr_localsid_t *ls0;
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);
ip0 = vlib_buffer_get_current (b0);
/* Lookup the SR End behavior based on IP DA (adj) */
ls0 =
pool_elt_at_index (sm->localsids,
vnet_buffer (b0)->ip.adj_index[VLIB_TX]);
/* Set Destination Address to Last Segment (index 0) */
ip0->dst_address.as_u16[2] = ip0->dst_address.as_u16[3];
ip0->dst_address.as_u16[3] = ip0->dst_address.as_u16[4];
ip0->dst_address.as_u16[4] = ip0->dst_address.as_u16[5];
ip0->dst_address.as_u16[5] = ip0->dst_address.as_u16[6];
ip0->dst_address.as_u16[6] = ip0->dst_address.as_u16[7];
ip0->dst_address.as_u16[7] = 0x0000;
if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
{
srv6_un_localsid_trace_t *tr =
vlib_add_trace (vm, node, b0, sizeof (*tr));
tr->localsid_index = ls0 - sm->localsids;
}
/* This increments the SRv6 per LocalSID counters. */
vlib_increment_combined_counter
(&(sm->sr_ls_valid_counters),
thread_index, ls0 - sm->localsids,
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);
}
vlib_put_next_frame (vm, node, next_index, n_left_to_next);
}
return frame->n_vectors;
}
/* *INDENT-OFF* */
VLIB_REGISTER_NODE (srv6_un_localsid_node) = {
.function = srv6_un_localsid_fn,
.name = "srv6-un-localsid",
.vector_size = sizeof (u32),
.format_trace = format_srv6_un_localsid_trace,
.type = VLIB_NODE_TYPE_INTERNAL,
.n_next_nodes = SRV6_UN_LOCALSID_N_NEXT,
.next_nodes = {
[SRV6_UN_LOCALSID_NEXT_IP6LOOKUP] = "ip6-lookup",
[SRV6_UN_LOCALSID_NEXT_ERROR] = "error-drop",
},
};
/* *INDENT-ON* */
/*
* fd.io coding-style-patch-verification: ON
*
* Local Variables:
* eval: (c-set-style "gnu")
* End:
*/

View File

@ -1,185 +0,0 @@
/*
* Copyright (c) 2015 Cisco and/or its affiliates.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
*------------------------------------------------------------------
* un.c - SRv6 Masquerading Proxy (AM) function
*------------------------------------------------------------------
*/
#include <vnet/vnet.h>
#include <vnet/adj/adj.h>
#include <vnet/plugin/plugin.h>
#include <vpp/app/version.h>
#include <srv6-un/un.h>
unsigned char function_name[] = "SRv6-uN";
unsigned char keyword_str[] = "uN(32b+16b)";
unsigned char def_str[] = "SRv6 uSID uN";
unsigned char params_str[] = "";
u8 prefix_length = 48;
srv6_un_main_t srv6_un_main;
/*****************************************/
/* SRv6 LocalSID instantiation and removal functions */
static int
srv6_un_localsid_creation_fn (ip6_sr_localsid_t * localsid)
{
srv6_un_localsid_t *ls_mem = localsid->plugin_mem;
//Nothing to do here.
ls_mem->shift = 16;
return 0;
}
static int
srv6_un_localsid_removal_fn (ip6_sr_localsid_t * localsid)
{
//Nothing to do here.
/* Clean up local SID memory */
clib_mem_free (localsid->plugin_mem);
return 0;
}
/**********************************/
/* SRv6 LocalSID format functions */
/*
* Prints nicely the parameters of a localsid
* Example: print "Table 5"
*/
u8 *
format_srv6_un_localsid (u8 * s, va_list * args)
{
srv6_un_localsid_t *ls_mem = va_arg (*args, void *);
return (format (s, "Shift:\t\t%u", ls_mem->shift));
}
/*
* Process the parameters of a localsid
* Example: process from:
* sr localsid address cafe::1 behavior new_srv6_localsid 5
* everything from behavior on... so in this case 'new_srv6_localsid 5'
* Notice that it MUST match the keyword_str and params_str defined above.
*/
uword
unformat_srv6_un_localsid (unformat_input_t * input, va_list * args)
{
void **plugin_mem_p = va_arg (*args, void **);
srv6_un_localsid_t *ls_mem;
if (unformat (input, "uN(32b+16b)"))
{
/* Allocate a portion of memory */
ls_mem = clib_mem_alloc_aligned_at_offset (sizeof *ls_mem, 0, 0, 1);
/* Set to zero the memory */
clib_memset (ls_mem, 0, sizeof *ls_mem);
/* Dont forget to add it to the localsid */
*plugin_mem_p = ls_mem;
return 1;
}
return 0;
}
/*************************/
/* SRv6 LocalSID FIB DPO */
static u8 *
format_srv6_un_dpo (u8 * s, va_list * args)
{
index_t index = va_arg (*args, index_t);
CLIB_UNUSED (u32 indent) = va_arg (*args, u32);
return (format (s, "SR: shift-and-forward 16b:[%u]", index));
}
void
srv6_un_dpo_lock (dpo_id_t * dpo)
{
}
void
srv6_un_dpo_unlock (dpo_id_t * dpo)
{
}
const static dpo_vft_t srv6_un_vft = {
.dv_lock = srv6_un_dpo_lock,
.dv_unlock = srv6_un_dpo_unlock,
.dv_format = format_srv6_un_dpo,
};
const static char *const srv6_un_ip6_nodes[] = {
"srv6-un-localsid",
NULL,
};
const static char *const *const srv6_un_nodes[DPO_PROTO_NUM] = {
[DPO_PROTO_IP6] = srv6_un_ip6_nodes,
};
/**********************/
static clib_error_t *
srv6_un_init (vlib_main_t * vm)
{
srv6_un_main_t *sm = &srv6_un_main;
int rv = 0;
sm->vlib_main = vm;
sm->vnet_main = vnet_get_main ();
/* Create DPO */
sm->srv6_un16_dpo_type =
dpo_register_new_type (&srv6_un_vft, srv6_un_nodes);
/* Register SRv6 LocalSID */
rv = sr_localsid_register_function (vm,
function_name,
keyword_str,
def_str,
params_str,
prefix_length,
&sm->srv6_un16_dpo_type,
format_srv6_un_localsid,
unformat_srv6_un_localsid,
srv6_un_localsid_creation_fn,
srv6_un_localsid_removal_fn);
if (rv < 0)
clib_error_return (0, "SRv6 LocalSID function could not be registered.");
else
sm->srv6_localsid_behavior_id = rv;
return 0;
}
/* *INDENT-OFF* */
VLIB_INIT_FUNCTION (srv6_un_init);
VLIB_PLUGIN_REGISTER () = {
.version = VPP_BUILD_VER,
.description = "Segment Routing Shift And Forward uN 16b",
};
/* *INDENT-ON* */
/*
* fd.io coding-style-patch-verification: ON
*
* Local Variables:
* eval: (c-set-style "gnu")
* End:
*/

View File

@ -1,65 +0,0 @@
/*
* Copyright (c) 2015 Cisco and/or its affiliates.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __included_srv6_un_h__
#define __included_srv6_un_h__
#include <vnet/vnet.h>
#include <vnet/ip/ip.h>
#include <vnet/srv6/sr.h>
#include <vnet/srv6/sr_packet.h>
#include <vppinfra/error.h>
#include <vppinfra/elog.h>
typedef struct
{
u16 msg_id_base; /**< API message ID base */
vlib_main_t *vlib_main; /**< [convenience] vlib main */
vnet_main_t *vnet_main; /**< [convenience] vnet main */
dpo_type_t srv6_un16_dpo_type; /**< DPO type */
u32 srv6_localsid_behavior_id; /**< SRv6 LocalSID behavior number */
} srv6_un_main_t;
/*
* This is the memory that will be stored per each localsid
* the user instantiates
*/
typedef struct
{
u16 shift;
} srv6_un_localsid_t;
extern srv6_un_main_t srv6_un_main;
format_function_t format_srv6_un_localsid;
unformat_function_t unformat_srv6_un_localsid;
void srv6_un_dpo_lock (dpo_id_t * dpo);
void srv6_un_dpo_unlock (dpo_id_t * dpo);
extern vlib_node_registration_t srv6_un_localsid_node;
#endif /* __included_srv6_un_h__ */
/*
* fd.io coding-style-patch-verification: ON
*
* Local Variables:
* eval: (c-set-style "gnu")
* End:
*/

View File

@ -43,7 +43,9 @@
#define SR_BEHAVIOR_DX4 7
#define SR_BEHAVIOR_DT6 8
#define SR_BEHAVIOR_DT4 9
#define SR_BEHAVIOR_LAST 10 /* Must always be the last one */
#define SR_BEHAVIOR_END_UN_PERF 10
#define SR_BEHAVIOR_END_UN 11
#define SR_BEHAVIOR_LAST 12 /* Must always be the last one */
#define SR_STEER_L2 2
#define SR_STEER_IPV4 4
@ -139,6 +141,15 @@ typedef struct
u32 nh_adj; /**< Next_adj for xconnect usage only */
ip6_address_t usid_block;
ip6_address_t usid_block_mask;
u8 usid_index;
u8 usid_len;
u8 usid_next_index;
u8 usid_next_len;
void *plugin_mem; /**< Memory to be used by the plugin callback functions */
} ip6_sr_localsid_t;
@ -231,6 +242,13 @@ typedef struct
u32 sr_policy; /**< SR Policy index */
} ip6_sr_steering_policy_t;
typedef struct
{
ip6_address_t address;
u16 pref_len;
u8 padding[2];
} sr_localsid_key_t;
/**
* @brief Segment Routing main datastructure
*/
@ -334,7 +352,7 @@ extern int
sr_cli_localsid (char is_del, ip6_address_t * localsid_addr,
u16 localsid_prefix_len, char end_psp, u8 behavior,
u32 sw_if_index, u32 vlan_index, u32 fib_table,
ip46_address_t * nh_addr, void *ls_plugin_mem);
ip46_address_t * nh_addr, int usid_len, void *ls_plugin_mem);
extern int
sr_steering_policy (int is_del, ip6_address_t * bsid, u32 sr_policy_index,

View File

@ -84,7 +84,7 @@ static void vl_api_sr_localsid_add_del_t_handler
mp->behavior,
ntohl (mp->sw_if_index),
ntohl (mp->vlan_index),
ntohl (mp->fib_table), &prefix, NULL);
ntohl (mp->fib_table), &prefix, 0, NULL);
BAD_SW_IF_INDEX_LABEL;
REPLY_MACRO (VL_API_SR_LOCALSID_ADD_DEL_REPLY);

File diff suppressed because it is too large Load Diff

323
test/test_srv6_un.py Normal file

File diff suppressed because it is too large Load Diff