srv6-mobile: Support GTP4/6.DT and User Plane message mapping
Support the following new features in srv6-mobile. 1. GTP4.DT 2. GTP6.DT 3. User Plane Message encoding based on draft-murakami-dmm-user-plane-message-encoding-01 4. Add SRv6 mobile test cases Type: feature Signed-off-by: Tetsuya Murakami <tetsuya.mrk@gmail.com> Change-Id: I890e5171bf03513d54b4830f01b9dc7f47fe7c48 Signed-off-by: Tetsuya Murakami <tetsuya.mrk@gmail.com>
This commit is contained in:

committed by
Damjan Marion

parent
7a6f5a4fee
commit
9e722bd466
@ -15,9 +15,11 @@ add_vpp_plugin(srv6mobile
|
||||
SOURCES
|
||||
gtp4_e.c
|
||||
gtp4_d.c
|
||||
gtp4_dt.c
|
||||
gtp6_e.c
|
||||
gtp6_d.c
|
||||
gtp6_d_di.c
|
||||
gtp6_dt.c
|
||||
node.c
|
||||
|
||||
INSTALL_HEADERS
|
||||
|
@ -16,6 +16,7 @@ RUN set -eux; \
|
||||
iproute2 \
|
||||
tcpdump \
|
||||
python3-cffi \
|
||||
python2.7 \
|
||||
netcat; \
|
||||
rm -rf /var/lib/apt/lists/*; \
|
||||
mv /usr/sbin/tcpdump /usr/bin/tcpdump
|
||||
|
File diff suppressed because it is too large
Load Diff
205
src/plugins/srv6-mobile/gtp4_dt.c
Normal file
205
src/plugins/srv6-mobile/gtp4_dt.c
Normal file
@ -0,0 +1,205 @@
|
||||
/*
|
||||
* srv6_t_m_gtp4_dt.c
|
||||
*
|
||||
* Copyright (c) 2019 Arrcus Inc 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 <vnet/vnet.h>
|
||||
#include <vnet/adj/adj.h>
|
||||
#include <vnet/fib/fib_table.h>
|
||||
#include <vnet/plugin/plugin.h>
|
||||
#include <vpp/app/version.h>
|
||||
#include <srv6-mobile/mobile.h>
|
||||
|
||||
srv6_t_main_v4_dt_t srv6_t_main_v4_dt;
|
||||
|
||||
static void
|
||||
clb_dpo_lock_srv6_t_m_gtp4_dt (dpo_id_t * dpo)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
clb_dpo_unlock_srv6_t_m_gtp4_dt (dpo_id_t * dpo)
|
||||
{
|
||||
}
|
||||
|
||||
static u8 *
|
||||
clb_dpo_format_srv6_t_m_gtp4_dt (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: dynamic_proxy_index:[%u]", index));
|
||||
}
|
||||
|
||||
const static dpo_vft_t dpo_vft = {
|
||||
.dv_lock = clb_dpo_lock_srv6_t_m_gtp4_dt,
|
||||
.dv_unlock = clb_dpo_unlock_srv6_t_m_gtp4_dt,
|
||||
.dv_format = clb_dpo_format_srv6_t_m_gtp4_dt,
|
||||
};
|
||||
|
||||
const static char *const srv6_t_m_gtp4_dt_nodes[] = {
|
||||
"srv6-t-m-gtp4-dt",
|
||||
NULL,
|
||||
};
|
||||
|
||||
const static char *const srv6_t_m_gtp4_dt_v6_nodes[] = {
|
||||
"error-drop",
|
||||
NULL,
|
||||
};
|
||||
|
||||
const static char *const *const dpo_nodes[DPO_PROTO_NUM] = {
|
||||
[DPO_PROTO_IP6] = srv6_t_m_gtp4_dt_v6_nodes,
|
||||
[DPO_PROTO_IP4] = srv6_t_m_gtp4_dt_nodes,
|
||||
};
|
||||
|
||||
static u8 fn_name[] = "SRv6-T.M.GTP4.DT-plugin";
|
||||
static u8 keyword_str[] = "t.m.gtp4.dt";
|
||||
static u8 def_str[] = "Transit function with DT for IPv4/GTP tunnel";
|
||||
static u8 param_str[] = "fib-index <index> [local-fib-table <index>]";
|
||||
|
||||
static u8 *
|
||||
clb_format_srv6_t_m_gtp4_dt (u8 * s, va_list * args)
|
||||
{
|
||||
srv6_t_gtp4_dt_param_t *ls_mem = va_arg (*args, void *);
|
||||
|
||||
s = format (s, "SRv6 Transit gtp4.dt\n\t");
|
||||
|
||||
if (ls_mem->type == SRV6_GTP4_DT4)
|
||||
s = format (s, " Type GTP4.DT4 fib-table %u\n", ls_mem->fib4_index);
|
||||
else if (ls_mem->type == SRV6_GTP4_DT6)
|
||||
s = format (s, " Type GTP4.DT6, fib-table %u, local-fib-table %u\n",
|
||||
ls_mem->fib6_index, ls_mem->local_fib_index);
|
||||
else if (ls_mem->type == SRV6_GTP4_DT46)
|
||||
s = format (s, " Type GTP4.DT46, fib-table %u, local-fib-table %u\n",
|
||||
ls_mem->fib6_index, ls_mem->local_fib_index);
|
||||
else
|
||||
s = format (s, "\n");
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
static uword
|
||||
clb_unformat_srv6_t_m_gtp4_dt (unformat_input_t * input, va_list * args)
|
||||
{
|
||||
void **plugin_mem_p = va_arg (*args, void **);
|
||||
srv6_t_gtp4_dt_param_t *ls_mem;
|
||||
u32 fib_index = 0;
|
||||
u32 local_fib_index = 0;
|
||||
u32 type;
|
||||
|
||||
if (unformat (input, "t.m.gtp4.dt4 fib-table %u", &fib_index))
|
||||
{
|
||||
type = SRV6_GTP4_DT4;
|
||||
}
|
||||
else if (unformat (input, "t.m.gtp4.dt6 fib-table %u local-fib-table %u",
|
||||
&fib_index, &local_fib_index))
|
||||
{
|
||||
type = SRV6_GTP4_DT6;
|
||||
}
|
||||
else if (unformat (input, "t.m.gtp4.dt46 fib-table %u local-fib-table %u",
|
||||
&fib_index, &local_fib_index))
|
||||
{
|
||||
type = SRV6_GTP4_DT46;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
ls_mem = clib_mem_alloc_aligned_at_offset (sizeof *ls_mem, 0, 0, 1);
|
||||
clib_memset (ls_mem, 0, sizeof *ls_mem);
|
||||
*plugin_mem_p = ls_mem;
|
||||
|
||||
ls_mem->fib4_index = fib_table_find (FIB_PROTOCOL_IP4, fib_index);
|
||||
ls_mem->fib6_index = fib_table_find (FIB_PROTOCOL_IP6, fib_index);
|
||||
|
||||
if (type == SRV6_GTP4_DT6 || type == SRV6_GTP4_DT46)
|
||||
{
|
||||
ls_mem->local_fib_index =
|
||||
fib_table_find (FIB_PROTOCOL_IP6, local_fib_index);
|
||||
}
|
||||
|
||||
ls_mem->type = type;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
clb_creation_srv6_t_m_gtp4_dt (ip6_sr_policy_t * sr_policy)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
clb_removal_srv6_t_m_gtp4_dt (ip6_sr_policy_t * sr_policy)
|
||||
{
|
||||
srv6_t_gtp4_dt_param_t *ls_mem;
|
||||
|
||||
ls_mem = (srv6_t_gtp4_dt_param_t *) sr_policy->plugin_mem;
|
||||
|
||||
clib_mem_free (ls_mem);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static clib_error_t *
|
||||
srv6_t_m_gtp4_dt_init (vlib_main_t * vm)
|
||||
{
|
||||
srv6_t_main_v4_dt_t *sm = &srv6_t_main_v4_dt;
|
||||
dpo_type_t dpo_type;
|
||||
vlib_node_t *node;
|
||||
int rc;
|
||||
|
||||
sm->vlib_main = vm;
|
||||
sm->vnet_main = vnet_get_main ();
|
||||
|
||||
node = vlib_get_node_by_name (vm, (u8 *) "srv6-t-m-gtp4-dt");
|
||||
sm->t_m_gtp4_dt_node_index = node->index;
|
||||
|
||||
node = vlib_get_node_by_name (vm, (u8 *) "error-drop");
|
||||
sm->error_node_index = node->index;
|
||||
|
||||
dpo_type = dpo_register_new_type (&dpo_vft, dpo_nodes);
|
||||
|
||||
rc = sr_policy_register_function (vm, fn_name, keyword_str, def_str, param_str, 128, //prefix len
|
||||
&dpo_type,
|
||||
clb_format_srv6_t_m_gtp4_dt,
|
||||
clb_unformat_srv6_t_m_gtp4_dt,
|
||||
clb_creation_srv6_t_m_gtp4_dt,
|
||||
clb_removal_srv6_t_m_gtp4_dt);
|
||||
if (rc < 0)
|
||||
clib_error_return (0, "SRv6 Transit GTP4.DT Policy function"
|
||||
"couldn't be registered");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
VNET_FEATURE_INIT (srv6_t_m_gtp4_dt, static) =
|
||||
{
|
||||
.arc_name = "ip4-unicast",
|
||||
.node_name = "srv6-t-m-gtp4-dt",
|
||||
.runs_before = 0,
|
||||
};
|
||||
|
||||
VLIB_INIT_FUNCTION (srv6_t_m_gtp4_dt_init);
|
||||
/* *INDENT-ON* */
|
||||
|
||||
/*
|
||||
* fd.io coding-style-patch-verification: ON
|
||||
*
|
||||
* Local Variables:
|
||||
* eval: (c-set-style "gnu")
|
||||
* End:
|
||||
*/
|
199
src/plugins/srv6-mobile/gtp6_dt.c
Normal file
199
src/plugins/srv6-mobile/gtp6_dt.c
Normal file
@ -0,0 +1,199 @@
|
||||
/*
|
||||
* srv6_end_m_gtp6_dt.c
|
||||
*
|
||||
* Copyright (c) 2019 Arrcus Inc 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 <vnet/vnet.h>
|
||||
#include <vnet/adj/adj.h>
|
||||
#include <vnet/fib/fib_table.h>
|
||||
#include <vnet/plugin/plugin.h>
|
||||
#include <vpp/app/version.h>
|
||||
#include <srv6-mobile/mobile.h>
|
||||
|
||||
srv6_end_main_v6_dt_t srv6_end_main_v6_dt;
|
||||
|
||||
static void
|
||||
clb_dpo_lock_srv6_end_m_gtp6_dt (dpo_id_t * dpo)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
clb_dpo_unlock_srv6_end_m_gtp6_dt (dpo_id_t * dpo)
|
||||
{
|
||||
}
|
||||
|
||||
static u8 *
|
||||
clb_dpo_format_srv6_end_m_gtp6_dt (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: dynamic_proxy_index:[%u]", index));
|
||||
}
|
||||
|
||||
const static dpo_vft_t dpo_vft = {
|
||||
.dv_lock = clb_dpo_lock_srv6_end_m_gtp6_dt,
|
||||
.dv_unlock = clb_dpo_unlock_srv6_end_m_gtp6_dt,
|
||||
.dv_format = clb_dpo_format_srv6_end_m_gtp6_dt,
|
||||
};
|
||||
|
||||
const static char *const srv6_end_m_gtp6_dt_nodes[] = {
|
||||
"srv6-end-m-gtp6-dt",
|
||||
NULL,
|
||||
};
|
||||
|
||||
const static char *const *const dpo_nodes[DPO_PROTO_NUM] = {
|
||||
[DPO_PROTO_IP6] = srv6_end_m_gtp6_dt_nodes,
|
||||
};
|
||||
|
||||
static u8 fn_name[] = "SRv6-End.M.GTP6.DT-plugin";
|
||||
static u8 keyword_str[] = "end.m.gtp6.dt";
|
||||
static u8 def_str[] = "Endpoint function with DT for IPv6/GTP tunnel";
|
||||
static u8 param_str[] = "fib-index <index> [local-fib-table <index>]";
|
||||
|
||||
static u8 *
|
||||
clb_format_srv6_end_m_gtp6_dt (u8 * s, va_list * args)
|
||||
{
|
||||
srv6_end_gtp6_dt_param_t *ls_mem = va_arg (*args, void *);
|
||||
|
||||
s = format (s, "SRv6 End gtp6.dt\n\t");
|
||||
|
||||
if (ls_mem->type == SRV6_GTP6_DT4)
|
||||
s = format (s, " Type GTP6.DT4 fib-table %u\n", ls_mem->fib4_index);
|
||||
else if (ls_mem->type == SRV6_GTP6_DT6)
|
||||
s = format (s, " Type GTP6.DT6, fib-table %u, local-fib-table %u\n",
|
||||
ls_mem->fib6_index, ls_mem->local_fib_index);
|
||||
else if (ls_mem->type == SRV6_GTP6_DT46)
|
||||
s = format (s, " Type GTP6.DT46, fib-table %u, local-fib-table %u\n",
|
||||
ls_mem->fib6_index, ls_mem->local_fib_index);
|
||||
else
|
||||
s = format (s, "\n");
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
static uword
|
||||
clb_unformat_srv6_end_m_gtp6_dt (unformat_input_t * input, va_list * args)
|
||||
{
|
||||
void **plugin_mem_p = va_arg (*args, void **);
|
||||
srv6_end_gtp6_dt_param_t *ls_mem;
|
||||
u32 fib_index = 0;
|
||||
u32 local_fib_index = 0;
|
||||
u32 type;
|
||||
|
||||
if (unformat (input, "end.m.gtp6.dt4 fib-table %u", &fib_index))
|
||||
{
|
||||
type = SRV6_GTP6_DT4;
|
||||
}
|
||||
else if (unformat (input, "end.m.gtp6.dt6 fib-table %u local-fib-table %u",
|
||||
&fib_index, &local_fib_index))
|
||||
{
|
||||
type = SRV6_GTP6_DT6;
|
||||
}
|
||||
else if (unformat (input, "end.m.gtp6.dt46 fib-table %u local-fib-table %u",
|
||||
&fib_index, &local_fib_index))
|
||||
{
|
||||
type = SRV6_GTP6_DT46;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
ls_mem = clib_mem_alloc_aligned_at_offset (sizeof *ls_mem, 0, 0, 1);
|
||||
clib_memset (ls_mem, 0, sizeof *ls_mem);
|
||||
*plugin_mem_p = ls_mem;
|
||||
|
||||
ls_mem->fib4_index = fib_table_find (FIB_PROTOCOL_IP4, fib_index);
|
||||
ls_mem->fib6_index = fib_table_find (FIB_PROTOCOL_IP6, fib_index);
|
||||
|
||||
if (type == SRV6_GTP6_DT6 || type == SRV6_GTP6_DT46)
|
||||
{
|
||||
ls_mem->local_fib_index =
|
||||
fib_table_find (FIB_PROTOCOL_IP6, local_fib_index);
|
||||
}
|
||||
|
||||
ls_mem->type = type;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
clb_creation_srv6_end_m_gtp6_dt (ip6_sr_localsid_t * localsid)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
clb_removal_srv6_end_m_gtp6_dt (ip6_sr_localsid_t * localsid)
|
||||
{
|
||||
srv6_end_gtp6_dt_param_t *ls_mem;
|
||||
|
||||
ls_mem = localsid->plugin_mem;
|
||||
|
||||
clib_mem_free (ls_mem);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static clib_error_t *
|
||||
srv6_end_m_gtp6_dt_init (vlib_main_t * vm)
|
||||
{
|
||||
srv6_end_main_v6_dt_t *sm = &srv6_end_main_v6_dt;
|
||||
dpo_type_t dpo_type;
|
||||
vlib_node_t *node;
|
||||
int rc;
|
||||
|
||||
sm->vlib_main = vm;
|
||||
sm->vnet_main = vnet_get_main ();
|
||||
|
||||
node = vlib_get_node_by_name (vm, (u8 *) "srv6-end-m-gtp6-dt");
|
||||
sm->end_m_gtp6_dt_node_index = node->index;
|
||||
|
||||
node = vlib_get_node_by_name (vm, (u8 *) "error-drop");
|
||||
sm->error_node_index = node->index;
|
||||
|
||||
dpo_type = dpo_register_new_type (&dpo_vft, dpo_nodes);
|
||||
|
||||
rc = sr_localsid_register_function (vm, fn_name, keyword_str, def_str, param_str, 128, //prefix len
|
||||
&dpo_type,
|
||||
clb_format_srv6_end_m_gtp6_dt,
|
||||
clb_unformat_srv6_end_m_gtp6_dt,
|
||||
clb_creation_srv6_end_m_gtp6_dt,
|
||||
clb_removal_srv6_end_m_gtp6_dt);
|
||||
if (rc < 0)
|
||||
clib_error_return (0, "SRv6 Endpoint GTP6.DT LocalSID function"
|
||||
"couldn't be registered");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
VNET_FEATURE_INIT (srv6_end_m_gtp6_dt, static) =
|
||||
{
|
||||
.arc_name = "ip6-unicast",
|
||||
.node_name = "srv6-end-m-gtp6-dt",
|
||||
.runs_before = 0,
|
||||
};
|
||||
|
||||
VLIB_INIT_FUNCTION (srv6_end_m_gtp6_dt_init);
|
||||
/* *INDENT-ON* */
|
||||
|
||||
/*
|
||||
* fd.io coding-style-patch-verification: ON
|
||||
*
|
||||
* Local Variables:
|
||||
* eval: (c-set-style "gnu")
|
||||
* End:
|
||||
*/
|
@ -42,6 +42,11 @@
|
||||
#define SRV6_GTP6_DT6 2
|
||||
#define SRV6_GTP6_DT46 3
|
||||
|
||||
#define SRV6_GTP4_UNKNOW 0
|
||||
#define SRV6_GTP4_DT4 1
|
||||
#define SRV6_GTP4_DT6 2
|
||||
#define SRV6_GTP4_DT46 3
|
||||
|
||||
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
||||
#define BITALIGN2(A,B) A; B
|
||||
#define BITALIGN3(A,B,C) A; B; C
|
||||
@ -59,6 +64,19 @@
|
||||
#define SRH_TAG_ERROR_INDICATION 0x0002
|
||||
#define SRH_TAG_END_MARKER 0x0001
|
||||
|
||||
#define GTPU_RECOVERY_IE_TYPE 0x0e
|
||||
|
||||
#define GTPU_IE_MAX_SIZ 256
|
||||
#define SRH_TLV_USER_PLANE_CONTAINER 0x0a /* tentative */
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
typedef struct
|
||||
{
|
||||
u8 type;
|
||||
u8 restart_counter;
|
||||
} __attribute__ ((packed)) gtpu_recovery_ie;
|
||||
/* *INDENT-ON* */
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
typedef struct
|
||||
{
|
||||
@ -145,6 +163,17 @@ typedef struct
|
||||
|
||||
#define GTPU_PT_GTP (1<<4)
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
typedef struct
|
||||
{
|
||||
u8 type;
|
||||
u8 length;
|
||||
u8 value[0];
|
||||
} __attribute__ ((packed)) user_plane_sub_tlv_t;
|
||||
/* *INDENT-ON* */
|
||||
|
||||
#define USER_PLANE_SUB_TLV_IE 0x01
|
||||
|
||||
typedef struct srv6_end_gtp6_param_s
|
||||
{
|
||||
u8 nhtype;
|
||||
@ -153,6 +182,24 @@ typedef struct srv6_end_gtp6_param_s
|
||||
u32 sr_prefixlen;
|
||||
} srv6_end_gtp6_param_t;
|
||||
|
||||
typedef struct srv6_end_gtp6_dt_param_s
|
||||
{
|
||||
u8 type;
|
||||
|
||||
u32 fib4_index;
|
||||
u32 fib6_index;
|
||||
u32 local_fib_index;
|
||||
} srv6_end_gtp6_dt_param_t;
|
||||
|
||||
typedef struct srv6_t_gtp4_dt_param_s
|
||||
{
|
||||
u8 type;
|
||||
|
||||
u32 fib4_index;
|
||||
u32 fib6_index;
|
||||
u32 local_fib_index;
|
||||
} srv6_t_gtp4_dt_param_t;
|
||||
|
||||
typedef struct srv6_end_gtp4_param_s
|
||||
{
|
||||
u8 nhtype;
|
||||
@ -238,6 +285,30 @@ typedef struct srv6_end_main_v6_decap_di_s
|
||||
extern srv6_end_main_v6_decap_di_t srv6_end_main_v6_decap_di;
|
||||
extern vlib_node_registration_t srv6_end_m_gtp6_d_di;
|
||||
|
||||
typedef struct srv6_end_main_v6_dt_s
|
||||
{
|
||||
vlib_main_t *vlib_main;
|
||||
vnet_main_t *vnet_main;
|
||||
|
||||
u32 end_m_gtp6_dt_node_index;
|
||||
u32 error_node_index;
|
||||
} srv6_end_main_v6_dt_t;
|
||||
|
||||
extern srv6_end_main_v6_dt_t srv6_end_main_v6_dt;
|
||||
extern vlib_node_registration_t srv6_end_m_gtp6_dt;
|
||||
|
||||
typedef struct srv6_t_main_v4_dt_s
|
||||
{
|
||||
vlib_main_t *vlib_main;
|
||||
vnet_main_t *vnet_main;
|
||||
|
||||
u32 t_m_gtp4_dt_node_index;
|
||||
u32 error_node_index;
|
||||
} srv6_t_main_v4_dt_t;
|
||||
|
||||
extern srv6_t_main_v4_dt_t srv6_t_main_v4_dt;
|
||||
extern vlib_node_registration_t srv6_t_m_gtp4_dt;
|
||||
|
||||
#endif /* __included_srv6_end_h__ */
|
||||
|
||||
/*
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,160 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
from framework import VppTestCase
|
||||
from ipaddress import IPv4Address
|
||||
from ipaddress import IPv6Address
|
||||
from scapy.contrib.gtp import *
|
||||
from scapy.all import *
|
||||
|
||||
|
||||
class TestSRv6EndMGTP4E(VppTestCase):
|
||||
""" SRv6 End.M.GTP4.E (SRv6 -> GTP-U) """
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(TestSRv6EndMGTP4E, cls).setUpClass()
|
||||
try:
|
||||
cls.create_pg_interfaces(range(2))
|
||||
cls.pg_if_i = cls.pg_interfaces[0]
|
||||
cls.pg_if_o = cls.pg_interfaces[1]
|
||||
|
||||
cls.pg_if_i.config_ip6()
|
||||
cls.pg_if_o.config_ip4()
|
||||
|
||||
cls.ip4_dst = cls.pg_if_o.remote_ip4
|
||||
# cls.ip4_src = cls.pg_if_o.local_ip4
|
||||
cls.ip4_src = "192.168.192.10"
|
||||
|
||||
for pg_if in cls.pg_interfaces:
|
||||
pg_if.admin_up()
|
||||
pg_if.resolve_arp()
|
||||
|
||||
except Exception:
|
||||
super(TestSRv6EndMGTP4E, cls).tearDownClass()
|
||||
raise
|
||||
|
||||
def create_packets(self, inner):
|
||||
|
||||
ip4_dst = IPv4Address(str(self.ip4_dst))
|
||||
# 32bit prefix + 32bit IPv4 DA + 8bit + 32bit TEID + 24bit
|
||||
dst = b'\xaa' * 4 + ip4_dst.packed + \
|
||||
b'\x11' + b'\xbb' * 4 + b'\x11' * 3
|
||||
ip6_dst = IPv6Address(dst)
|
||||
|
||||
ip4_src = IPv4Address(str(self.ip4_src))
|
||||
# 64bit prefix + 32bit IPv4 SA + 16 bit port + 16bit
|
||||
src = b'\xcc' * 8 + ip4_src.packed + \
|
||||
b'\xdd' * 2 + b'\x11' * 2
|
||||
ip6_src = IPv6Address(src)
|
||||
|
||||
self.logger.info("ip4 dst: {}".format(ip4_dst))
|
||||
self.logger.info("ip4 src: {}".format(ip4_src))
|
||||
self.logger.info("ip6 dst (remote srgw): {}".format(ip6_dst))
|
||||
self.logger.info("ip6 src (local srgw): {}".format(ip6_src))
|
||||
|
||||
pkts = list()
|
||||
for d, s in inner:
|
||||
pkt = (Ether() /
|
||||
IPv6(dst=str(ip6_dst), src=str(ip6_src)) /
|
||||
IPv6ExtHdrSegmentRouting() /
|
||||
IPv6(dst=d, src=s) /
|
||||
UDP(sport=1000, dport=23))
|
||||
self.logger.info(pkt.show2(dump=True))
|
||||
pkts.append(pkt)
|
||||
|
||||
return pkts
|
||||
|
||||
def test_srv6_end(self):
|
||||
""" test_srv6_end """
|
||||
pkts = self.create_packets([("A::1", "B::1"), ("C::1", "D::1")])
|
||||
|
||||
self.vapi.cli(
|
||||
"sr localsid address {} behavior end.m.gtp4.e v4src_position 64"
|
||||
.format(pkts[0]['IPv6'].dst))
|
||||
self.logger.info(self.vapi.cli("show sr localsids"))
|
||||
|
||||
self.vapi.cli("clear errors")
|
||||
|
||||
self.pg0.add_stream(pkts)
|
||||
self.pg_enable_capture(self.pg_interfaces)
|
||||
self.pg_start()
|
||||
|
||||
self.logger.info(self.vapi.cli("show errors"))
|
||||
self.logger.info(self.vapi.cli("show int address"))
|
||||
|
||||
capture = self.pg1.get_capture(len(pkts))
|
||||
|
||||
for pkt in capture:
|
||||
self.logger.info(pkt.show2(dump=True))
|
||||
self.assertEqual(pkt[IP].dst, self.ip4_dst)
|
||||
self.assertEqual(pkt[IP].src, self.ip4_src)
|
||||
self.assertEqual(pkt[GTP_U_Header].teid, 0xbbbbbbbb)
|
||||
|
||||
|
||||
class TestSRv6TMTmap(VppTestCase):
|
||||
""" SRv6 T.M.Tmap (GTP-U -> SRv6) """
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(TestSRv6TMTmap, cls).setUpClass()
|
||||
try:
|
||||
cls.create_pg_interfaces(range(2))
|
||||
cls.pg_if_i = cls.pg_interfaces[0]
|
||||
cls.pg_if_o = cls.pg_interfaces[1]
|
||||
|
||||
cls.pg_if_i.config_ip4()
|
||||
cls.pg_if_o.config_ip6()
|
||||
|
||||
for pg_if in cls.pg_interfaces:
|
||||
pg_if.admin_up()
|
||||
pg_if.resolve_arp()
|
||||
|
||||
except Exception:
|
||||
super(TestSRv6TMTmap, cls).tearDownClass()
|
||||
raise
|
||||
|
||||
|
||||
class TestSRv6EndMGTP6E(VppTestCase):
|
||||
""" SRv6 End.M.GTP6.E """
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(TestSRv6EndMGTP6E, cls).setUpClass()
|
||||
try:
|
||||
cls.create_pg_interfaces(range(2))
|
||||
cls.pg_if_i = cls.pg_interfaces[0]
|
||||
cls.pg_if_o = cls.pg_interfaces[1]
|
||||
|
||||
cls.pg_if_i.config_ip4()
|
||||
cls.pg_if_o.config_ip6()
|
||||
|
||||
for pg_if in cls.pg_interfaces:
|
||||
pg_if.admin_up()
|
||||
pg_if.resolve_arp()
|
||||
|
||||
except Exception:
|
||||
super(TestSRv6EndMGTP6E, cls).tearDownClass()
|
||||
raise
|
||||
|
||||
|
||||
class TestSRv6EndMGTP6D(VppTestCase):
|
||||
""" SRv6 End.M.GTP6.D """
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(TestSRv6EndMGTP6D, cls).setUpClass()
|
||||
try:
|
||||
cls.create_pg_interfaces(range(2))
|
||||
cls.pg_if_i = cls.pg_interfaces[0]
|
||||
cls.pg_if_o = cls.pg_interfaces[1]
|
||||
|
||||
cls.pg_if_i.config_ip4()
|
||||
cls.pg_if_o.config_ip6()
|
||||
|
||||
for pg_if in cls.pg_interfaces:
|
||||
pg_if.admin_up()
|
||||
pg_if.resolve_arp()
|
||||
|
||||
except Exception:
|
||||
super(TestSRv6EndMGTP6D, cls).tearDownClass()
|
||||
raise
|
340
src/plugins/srv6-mobile/test/test_srv6_mobile.py
Normal file
340
src/plugins/srv6-mobile/test/test_srv6_mobile.py
Normal file
File diff suppressed because it is too large
Load Diff
@ -149,6 +149,13 @@ typedef struct
|
||||
ip6_address_t segments[0];
|
||||
} __attribute__ ((packed)) ip6_sr_header_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u8 type;
|
||||
u8 length;
|
||||
u8 value[0];
|
||||
} __attribute__ ((packed)) ip6_sr_tlv_t;
|
||||
|
||||
/*
|
||||
* fd.io coding-style-patch-verification: ON
|
||||
*
|
||||
|
Reference in New Issue
Block a user