Compare commits
26 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
cd111b2228 | ||
|
7067350c41 | ||
|
fa87080d31 | ||
|
78aab80634 | ||
|
7104f93c75 | ||
|
12713c70fc | ||
|
1b3d4ded5f | ||
|
cd8a22ae1f | ||
|
df44cc846f | ||
|
257d5e25bf | ||
|
bf2fcad04a | ||
|
2d7e16330f | ||
|
ee85bfabc9 | ||
|
b95a916dc3 | ||
|
235c64f067 | ||
|
cdffe06bab | ||
|
35dc387354 | ||
|
c48b58a216 | ||
|
856ab8aca3 | ||
|
81c09d03d8 | ||
|
b4f2525866 | ||
|
800429ddef | ||
|
e4e9fbbb7c | ||
|
fe7cdfa629 | ||
|
e73d0a3aab | ||
|
436b319354 |
@ -2,3 +2,4 @@
|
||||
host=gerrit.fd.io
|
||||
port=29418
|
||||
project=vpp
|
||||
defaultbranch=stable/1701
|
||||
|
73
RELEASE.md
73
RELEASE.md
@ -7,14 +7,85 @@
|
||||
@page release_notes_1701 Release notes for VPP 17.01
|
||||
|
||||
@note This release was for a while known as 16.12.
|
||||
@todo Release 17.01 needs release notes.
|
||||
|
||||
## Features
|
||||
|
||||
- [Integrated November 2016 DPDK release](http://www.dpdk.org/doc/guides/rel_notes/release_16_11.html)
|
||||
|
||||
- Complete rework of Forwarding Information Base (FIB)
|
||||
|
||||
- Performance Improvements
|
||||
- Improvements in DPDK input and output nodes
|
||||
- Improvements in L2 path
|
||||
- Improvmeents in IPv4 lookup node
|
||||
|
||||
- Feature Arcs Improvements
|
||||
- Consolidation of the code
|
||||
- New feature arcs
|
||||
- device-input
|
||||
- interface-output
|
||||
|
||||
- DPDK Cryptodev Support
|
||||
- Software and Hardware Crypto Support
|
||||
|
||||
- DPDK HQoS support
|
||||
|
||||
- Simple Port Analyzer (SPAN)
|
||||
|
||||
- Bidirectional Forwarding Detection
|
||||
- Basic implementation
|
||||
|
||||
- IPFIX Improvements
|
||||
|
||||
- L2 GRE over IPSec tunnels
|
||||
|
||||
- Link Layer Discovery Protocol (LLDP)
|
||||
|
||||
- Vhost-user Improvements
|
||||
- Performance Improvements
|
||||
- Multiqueue
|
||||
- Reconnect
|
||||
|
||||
- LISP Enhancements
|
||||
- Source/Dest control plane support
|
||||
- L2 over LISP and GRE
|
||||
- Map-Register/Map-Notify/RLOC-probing support
|
||||
- L2 API improvements, overall code hardening
|
||||
|
||||
- Plugins:
|
||||
- New: ACL
|
||||
- New: Flow per Packet
|
||||
- Improved: SNAT
|
||||
- Mutlithreading
|
||||
- Flow export
|
||||
|
||||
- Doxygen Enhancements
|
||||
|
||||
- Luajit API bindings
|
||||
|
||||
- API Refactoring
|
||||
- file split
|
||||
- message signatures
|
||||
|
||||
- Python and Scapy based unit testing infrastructure
|
||||
- Infrastructure
|
||||
- Various tests
|
||||
|
||||
- Packet Generator improvements
|
||||
|
||||
- TUN/TAP jumbo frames support
|
||||
|
||||
- Other various bug fixes and improvements
|
||||
|
||||
## Known issues
|
||||
|
||||
For the full list of issues please reffer to fd.io [JIRA](https://jira.fd.io).
|
||||
|
||||
## Issues fixed
|
||||
|
||||
For the full list of fixed issues please reffer to:
|
||||
- fd.io [JIRA](https://jira.fd.io)
|
||||
- git [commit log](https://git.fd.io/vpp/log/?h=stable/1701)
|
||||
|
||||
@page release_notes_1609 Release notes for VPP 16.09
|
||||
|
||||
|
5
build-root/deb/debian/vpp-python-api.postinst
Normal file
5
build-root/deb/debian/vpp-python-api.postinst
Normal file
@ -0,0 +1,5 @@
|
||||
#!/bin/sh -e
|
||||
|
||||
# after installing python-api files
|
||||
python2_sitedir=$(python -c "from distutils.sysconfig import get_python_lib; print(get_python_lib())")
|
||||
easy_install --install-dir=$python2_sitedir -z $python2_sitedir/vpp_papi/vpp_papi-*.egg
|
8
build-root/deb/debian/vpp-python-api.prerm
Normal file
8
build-root/deb/debian/vpp-python-api.prerm
Normal file
@ -0,0 +1,8 @@
|
||||
#!/bin/sh -e
|
||||
|
||||
# before removing python-api files
|
||||
python2_sitedir=$(python -c "from distutils.sysconfig import get_python_lib; print(get_python_lib())")
|
||||
easy_install --install-dir=$python2_sitedir -mxNq vpp_papi
|
||||
|
||||
# the egg has been copied during install
|
||||
rm $python2_sitedir/vpp_papi-*.egg
|
@ -1,2 +1,2 @@
|
||||
#!/bin/sh
|
||||
echo oper-161218
|
||||
echo oper-rls1701-170115
|
||||
|
@ -50,5 +50,5 @@ fi
|
||||
echo ${TAG}-${ADD}${CMT:+~${CMT}}${BLD}
|
||||
fi
|
||||
else
|
||||
echo ${TAG}
|
||||
echo ${TAG}-release
|
||||
fi
|
||||
|
@ -1044,6 +1044,7 @@ typedef struct
|
||||
u8 prefix_len;
|
||||
u32 count;
|
||||
u32 table_index;
|
||||
u32 arp_table_index;
|
||||
} macip_match_type_t;
|
||||
|
||||
static u32
|
||||
@ -1127,6 +1128,34 @@ macip_create_classify_tables (acl_main_t * am, u32 macip_acl_index)
|
||||
vec_sort_with_function (mvec, match_type_compare);
|
||||
/* Create the classifier tables */
|
||||
last_table = ~0;
|
||||
/* First add ARP tables */
|
||||
vec_foreach (mt, mvec)
|
||||
{
|
||||
int mask_len;
|
||||
int is6 = mt->is_ipv6;
|
||||
|
||||
mt->arp_table_index = ~0;
|
||||
if (!is6)
|
||||
{
|
||||
memset (mask, 0, sizeof (mask));
|
||||
memcpy (&mask[6], mt->mac_mask, 6);
|
||||
memset (&mask[12], 0xff, 2); /* ethernet protocol */
|
||||
memcpy (&mask[14 + 8], mt->mac_mask, 6);
|
||||
|
||||
for (i = 0; i < (mt->prefix_len / 8); i++)
|
||||
mask[14 + 14 + i] = 0xff;
|
||||
if (mt->prefix_len % 8)
|
||||
mask[14 + 14 + (mt->prefix_len / 8)] = 0xff - ((1 << (8 - mt->prefix_len % 8)) - 1);
|
||||
|
||||
mask_len = ((14 + 14 + ((mt->prefix_len+7) / 8) +
|
||||
(sizeof (u32x4)-1))/sizeof(u32x4)) * sizeof (u32x4);
|
||||
acl_classify_add_del_table_small (cm, mask, mask_len, last_table,
|
||||
(~0 == last_table) ? 0 : ~0, &mt->arp_table_index,
|
||||
1);
|
||||
last_table = mt->arp_table_index;
|
||||
}
|
||||
}
|
||||
/* Now add IP[46] tables */
|
||||
vec_foreach (mt, mvec)
|
||||
{
|
||||
int mask_len;
|
||||
@ -1167,13 +1196,18 @@ macip_create_classify_tables (acl_main_t * am, u32 macip_acl_index)
|
||||
int l3_src_offs = get_l3_src_offset(is6);
|
||||
memset (mask, 0, sizeof (mask));
|
||||
memcpy (&mask[6], a->rules[i].src_mac, 6);
|
||||
memset (&mask[12], 0xff, 2); /* ethernet protocol */
|
||||
if (is6)
|
||||
{
|
||||
memcpy (&mask[l3_src_offs], &a->rules[i].src_ip_addr.ip6, 16);
|
||||
mask[12] = 0x86;
|
||||
mask[13] = 0xdd;
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy (&mask[l3_src_offs], &a->rules[i].src_ip_addr.ip4, 4);
|
||||
mask[12] = 0x08;
|
||||
mask[13] = 0x00;
|
||||
}
|
||||
match_type_index =
|
||||
macip_find_match_type (mvec, a->rules[i].src_mac_mask,
|
||||
@ -1183,6 +1217,19 @@ macip_create_classify_tables (acl_main_t * am, u32 macip_acl_index)
|
||||
vnet_classify_add_del_session (cm, mvec[match_type_index].table_index,
|
||||
mask, a->rules[i].is_permit ? ~0 : 0, i,
|
||||
0, action, metadata, 1);
|
||||
/* add ARP table entry too */
|
||||
if (!is6 && (mvec[match_type_index].arp_table_index != ~0))
|
||||
{
|
||||
memset (mask, 0, sizeof (mask));
|
||||
memcpy (&mask[6], a->rules[i].src_mac, 6);
|
||||
mask[12] = 0x08;
|
||||
mask[13] = 0x06;
|
||||
memcpy (&mask[14 + 8], a->rules[i].src_mac, 6);
|
||||
memcpy (&mask[14 + 14], &a->rules[i].src_ip_addr.ip4, 4);
|
||||
vnet_classify_add_del_session (cm, mvec[match_type_index].arp_table_index,
|
||||
mask, a->rules[i].is_permit ? ~0 : 0, i,
|
||||
0, action, metadata, 1);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
AC_INIT(acl_plugin, 1.0)
|
||||
AC_INIT(acl_plugin, 17.01)
|
||||
AC_CONFIG_MACRO_DIR([../../vpp-api/java/m4])
|
||||
LT_INIT
|
||||
AM_INIT_AUTOMAKE
|
||||
|
@ -17,20 +17,8 @@ AM_CFLAGS = -Wall
|
||||
AM_LDFLAGS = -module -shared -avoid-version
|
||||
|
||||
########################################
|
||||
# iOAM Proof of Transit
|
||||
# iOAM APIs
|
||||
########################################
|
||||
|
||||
ioam_pot_plugin_la_SOURCES = \
|
||||
ioam/lib-pot/pot_util.c \
|
||||
ioam/encap/ip6_ioam_pot.c \
|
||||
ioam/lib-pot/pot_util.h \
|
||||
ioam/lib-pot/math64.h \
|
||||
ioam/lib-pot/pot_api.c
|
||||
|
||||
BUILT_SOURCES = \
|
||||
ioam/lib-pot/pot.api.h \
|
||||
ioam/lib-pot/pot.api.json
|
||||
|
||||
SUFFIXES = .api.h .api
|
||||
|
||||
%.api.h: %.api
|
||||
@ -39,129 +27,135 @@ SUFFIXES = .api.h .api
|
||||
| vppapigen --input - --output $@ --show-name $@
|
||||
|
||||
%.api.json: %.api
|
||||
@echo " JSON APIGEN " $@ ; \
|
||||
@echo " JSON APIGEN " $@ ; \
|
||||
mkdir -p `dirname $@` ; \
|
||||
$(CC) $(CPPFLAGS) -E -P -C -x c $^ \
|
||||
$(CC) $(CPPFLAGS) -E -P -C -x c $^ \
|
||||
| vppapigen --input - --json $@
|
||||
|
||||
apidir = $(prefix)/ioam/
|
||||
api_DATA = \
|
||||
ioam/lib-pot/pot.api.json \
|
||||
api_DATA = \
|
||||
ioam/lib-pot/pot.api.json \
|
||||
ioam/lib-trace/trace.api.json \
|
||||
ioam/export/ioam_export.api.json
|
||||
|
||||
noinst_HEADERS = \
|
||||
ioam/lib-pot/pot_all_api_h.h \
|
||||
ioam/lib-pot/pot_msg_enum.h \
|
||||
ioam/lib-pot/pot.api.h \
|
||||
ioam/lib-pot/pot_util.h \
|
||||
ioam/lib-pot/math64.h
|
||||
########################################
|
||||
# iOAM Proof of Transit
|
||||
########################################
|
||||
|
||||
ioam_pot_test_plugin_la_SOURCES = \
|
||||
IOAM_POT_SRC = \
|
||||
ioam/lib-pot/pot_util.c \
|
||||
ioam/encap/ip6_ioam_pot.c \
|
||||
ioam/lib-pot/pot_util.h \
|
||||
ioam/lib-pot/math64.h \
|
||||
ioam/lib-pot/pot_api.c
|
||||
|
||||
IOAM_POT_BUILT_SRC = \
|
||||
ioam/lib-pot/pot.api.h \
|
||||
ioam/lib-pot/pot.api.json
|
||||
|
||||
IOAM_POT_NOINST_HDR = \
|
||||
ioam/lib-pot/pot_all_api_h.h \
|
||||
ioam/lib-pot/pot_msg_enum.h \
|
||||
ioam/lib-pot/pot.api.h \
|
||||
ioam/lib-pot/pot_util.h \
|
||||
ioam/lib-pot/math64.h
|
||||
|
||||
ioam_pot_test_plugin_la_SOURCES = \
|
||||
ioam/lib-pot/pot_test.c \
|
||||
ioam/lib-pot/pot_plugin.api.h
|
||||
|
||||
vppapitestpluginsdir = ${libdir}/vpp_api_test_plugins
|
||||
vpppluginsdir = ${libdir}/vpp_plugins
|
||||
|
||||
vppapitestplugins_LTLIBRARIES = ioam_pot_test_plugin.la
|
||||
vppplugins_LTLIBRARIES = ioam_pot_plugin.la
|
||||
|
||||
########################################
|
||||
# iOAM trace export for IPv6
|
||||
########################################
|
||||
|
||||
ioam_export_plugin_la_SOURCES = \
|
||||
ioam/export/ioam_export.c \
|
||||
ioam/export/node.c \
|
||||
ioam/export/ioam_export.api.h \
|
||||
ioam/export/ioam_export_thread.c
|
||||
IOAM_EXPORT_SRC = \
|
||||
ioam/export/ioam_export.c \
|
||||
ioam/export/node.c \
|
||||
ioam/export/ioam_export.api.h \
|
||||
ioam/export/ioam_export_thread.c
|
||||
|
||||
BUILT_SOURCES += \
|
||||
IOAM_EXPORT_BUILT_SRC = \
|
||||
ioam/export/ioam_export.api.h \
|
||||
ioam/export/ioam_export.api.json
|
||||
|
||||
noinst_HEADERS += \
|
||||
ioam/export/ioam_export_all_api_h.h \
|
||||
ioam/export/ioam_export_msg_enum.h \
|
||||
ioam/export/ioam_export.api.h
|
||||
IOAM_EXPORT_NOINST_HDR = \
|
||||
ioam/export/ioam_export_all_api_h.h \
|
||||
ioam/export/ioam_export_msg_enum.h \
|
||||
ioam/export/ioam_export.api.h
|
||||
|
||||
ioam_export_test_plugin_la_SOURCES = \
|
||||
ioam/export/ioam_export_test.c \
|
||||
ioam/export/ioam_export_plugin.api.h
|
||||
ioam_export_test_plugin_la_SOURCES = \
|
||||
ioam/export/ioam_export_test.c \
|
||||
ioam/export/ioam_export_plugin.api.h
|
||||
|
||||
vppapitestplugins_LTLIBRARIES += ioam_export_test_plugin.la
|
||||
vppplugins_LTLIBRARIES += ioam_export_plugin.la
|
||||
|
||||
########################################
|
||||
# iOAM Trace
|
||||
########################################
|
||||
libioam_trace_plugin_la_SOURCES = \
|
||||
IOAM_TRACE_SRC = \
|
||||
ioam/lib-trace/trace_util.c \
|
||||
ioam/encap/ip6_ioam_trace.c \
|
||||
ioam/lib-trace/trace_util.h \
|
||||
ioam/lib-trace/trace_api.c
|
||||
|
||||
BUILT_SOURCES += \
|
||||
IOAM_TRACE_BUILT_SRC = \
|
||||
ioam/lib-trace/trace.api.h \
|
||||
ioam/lib-trace/trace.api.json
|
||||
|
||||
noinst_HEADERS += \
|
||||
IOAM_TRACE_NOINST_HDR = \
|
||||
ioam/export/ioam_export_all_api_h.h \
|
||||
ioam/lib-trace/trace_all_api_h.h \
|
||||
ioam/lib-trace/trace_msg_enum.h \
|
||||
ioam/lib-trace/trace.api.h \
|
||||
ioam/lib-trace/trace_all_api_h.h \
|
||||
ioam/lib-trace/trace_msg_enum.h \
|
||||
ioam/lib-trace/trace.api.h \
|
||||
ioam/lib-trace/trace_util.h
|
||||
|
||||
ioam_trace_test_plugin_la_SOURCES = \
|
||||
ioam/lib-trace/trace_test.c \
|
||||
ioam/lib-trace/trace_test.c \
|
||||
ioam/lib-trace/trace_plugin.api.h
|
||||
|
||||
vppapitestplugins_LTLIBRARIES += ioam_trace_test_plugin.la
|
||||
vppplugins_LTLIBRARIES += libioam_trace_plugin.la
|
||||
|
||||
########################################
|
||||
# VxLAN-GPE
|
||||
########################################
|
||||
libioam_vxlan_gpe_plugin_la_SOURCES = \
|
||||
ioam/lib-vxlan-gpe/ioam_encap.c \
|
||||
ioam/lib-vxlan-gpe/ioam_decap.c \
|
||||
ioam/lib-vxlan-gpe/ioam_transit.c \
|
||||
ioam/lib-vxlan-gpe/ioam_pop.c \
|
||||
ioam/lib-vxlan-gpe/vxlan_gpe_api.c \
|
||||
ioam/lib-vxlan-gpe/vxlan_gpe_ioam_trace.c \
|
||||
ioam/lib-vxlan-gpe/vxlan_gpe_ioam.c \
|
||||
ioam/export-vxlan-gpe/vxlan_gpe_ioam_export.c \
|
||||
ioam/export-vxlan-gpe/vxlan_gpe_node.c \
|
||||
ioam/export-vxlan-gpe/vxlan_gpe_ioam_export.api.h\
|
||||
IOAM_VXLAN_GPE_SRC = \
|
||||
ioam/lib-vxlan-gpe/ioam_encap.c \
|
||||
ioam/lib-vxlan-gpe/ioam_decap.c \
|
||||
ioam/lib-vxlan-gpe/ioam_transit.c \
|
||||
ioam/lib-vxlan-gpe/ioam_pop.c \
|
||||
ioam/lib-vxlan-gpe/vxlan_gpe_api.c \
|
||||
ioam/lib-vxlan-gpe/vxlan_gpe_ioam_trace.c \
|
||||
ioam/lib-vxlan-gpe/vxlan_gpe_ioam.c \
|
||||
ioam/export-vxlan-gpe/vxlan_gpe_ioam_export.c \
|
||||
ioam/export-vxlan-gpe/vxlan_gpe_node.c \
|
||||
ioam/export-vxlan-gpe/vxlan_gpe_ioam_export.api.h \
|
||||
ioam/export-vxlan-gpe/vxlan_gpe_ioam_export_thread.c
|
||||
|
||||
BUILT_SOURCES += \
|
||||
ioam/lib-vxlan-gpe/vxlan_gpe.api.h \
|
||||
ioam/lib-vxlan-gpe/vxlan_gpe.api.json \
|
||||
IOAM_VXLAN_GPE_BUILT_SRC = \
|
||||
ioam/lib-vxlan-gpe/vxlan_gpe.api.h \
|
||||
ioam/lib-vxlan-gpe/vxlan_gpe.api.json \
|
||||
ioam/export-vxlan-gpe/vxlan_gpe_ioam_export.api.h \
|
||||
ioam/export-vxlan-gpe/vxlan_gpe_ioam_export.api.json
|
||||
|
||||
noinst_HEADERS += \
|
||||
ioam/export/ioam_export_all_api_h.h \
|
||||
ioam/lib-vxlan-gpe/vxlan_gpe_all_api_h.h \
|
||||
ioam/lib-vxlan-gpe/vxlan_gpe_msg_enum.h \
|
||||
ioam/lib-vxlan-gpe/vxlan_gpe.api.h \
|
||||
ioam/lib-vxlan-gpe/vxlan_gpe_ioam_util.h \
|
||||
ioam/lib-vxlan-gpe/vxlan_gpe_ioam_packet.h \
|
||||
ioam/lib-vxlan-gpe/vxlan_gpe_ioam.h \
|
||||
ioam/export-vxlan-gpe/vxlan_gpe_ioam_export_all_api_h.h \
|
||||
ioam/export-vxlan-gpe/vxlan_gpe_ioam_export_msg_enum.h \
|
||||
IOAM_VXLAN_GPE_NOINST_HDR = \
|
||||
ioam/export/ioam_export_all_api_h.h \
|
||||
ioam/lib-vxlan-gpe/vxlan_gpe_all_api_h.h \
|
||||
ioam/lib-vxlan-gpe/vxlan_gpe_msg_enum.h \
|
||||
ioam/lib-vxlan-gpe/vxlan_gpe.api.h \
|
||||
ioam/lib-vxlan-gpe/vxlan_gpe_ioam_util.h \
|
||||
ioam/lib-vxlan-gpe/vxlan_gpe_ioam_packet.h \
|
||||
ioam/lib-vxlan-gpe/vxlan_gpe_ioam.h \
|
||||
ioam/export-vxlan-gpe/vxlan_gpe_ioam_export_all_api_h.h \
|
||||
ioam/export-vxlan-gpe/vxlan_gpe_ioam_export_msg_enum.h \
|
||||
ioam/export-vxlan-gpe/vxlan_gpe_ioam_export.api.h
|
||||
|
||||
ioam_vxlan_gpe_test_plugin_la_SOURCES = \
|
||||
ioam_vxlan_gpe_test_plugin_la_SOURCES = \
|
||||
ioam/lib-vxlan-gpe/vxlan_gpe_test.c \
|
||||
ioam/lib-vxlan-gpe/vxlan_gpe_plugin.api.h
|
||||
|
||||
libioam_vxlan_gpe_plugin_la_LIBADD = libioam_trace_plugin.la
|
||||
|
||||
vppapitestplugins_LTLIBRARIES += ioam_vxlan_gpe_test_plugin.la
|
||||
vppplugins_LTLIBRARIES += libioam_vxlan_gpe_plugin.la
|
||||
|
||||
vxlan_gpe_ioam_export_test_plugin_la_SOURCES = \
|
||||
ioam/export-vxlan-gpe/vxlan_gpe_ioam_export_test.c \
|
||||
@ -170,26 +164,53 @@ vxlan_gpe_ioam_export_test_plugin_la_SOURCES = \
|
||||
vppapitestplugins_LTLIBRARIES += vxlan_gpe_ioam_export_test_plugin.la
|
||||
|
||||
########################################
|
||||
# iOAM E2E plugin
|
||||
# iOAM E2E
|
||||
########################################
|
||||
|
||||
ioam_e2e_plugin_la_SOURCES = \
|
||||
IOAM_E2E_SRC = \
|
||||
ioam/encap/ip6_ioam_e2e.c \
|
||||
ioam/encap/ip6_ioam_seqno.c \
|
||||
ioam/encap/ip6_ioam_seqno_analyse.c
|
||||
|
||||
noinst_HEADERS += \
|
||||
ioam/encap/ip6_ioam_e2e.h \
|
||||
IOAM_E2E_BUILT_SRC = \
|
||||
ioam/encap/ip6_ioam_e2e.h \
|
||||
ioam/encap/ip6_ioam_seqno.h
|
||||
|
||||
vppplugins_LTLIBRARIES += ioam_e2e_plugin.la
|
||||
########################################
|
||||
# iOAM plugins
|
||||
########################################
|
||||
|
||||
vppapitestpluginsdir = ${libdir}/vpp_api_test_plugins
|
||||
vpppluginsdir = ${libdir}/vpp_plugins
|
||||
|
||||
ioam_plugin_la_SOURCES = \
|
||||
$(IOAM_POT_SRC) \
|
||||
$(IOAM_EXPORT_SRC) \
|
||||
$(IOAM_TRACE_SRC) \
|
||||
$(IOAM_VXLAN_GPE_SRC) \
|
||||
$(IOAM_E2E_SRC)
|
||||
|
||||
BUILT_SOURCES = \
|
||||
$(IOAM_POT_BUILT_SRC) \
|
||||
$(IOAM_EXPORT_BUILT_SRC) \
|
||||
$(IOAM_TRACE_BUILT_SRC) \
|
||||
$(IOAM_VXLAN_GPE_BUILT_SRC) \
|
||||
$(IOAM_E2E_BUILT_SRC)
|
||||
|
||||
noinst_HEADERS = \
|
||||
$(IOAM_POT_NOINST_HDR) \
|
||||
$(IOAM_EXPORT_NOINST_HDR) \
|
||||
$(IOAM_TRACE_NOINST_HDR) \
|
||||
$(IOAM_VXLAN_GPE_NOINST_HDR) \
|
||||
$(IOAM_E2E_NOINST_HDR)
|
||||
|
||||
vppplugins_LTLIBRARIES = ioam_plugin.la
|
||||
|
||||
# Remove *.la files
|
||||
install-data-hook:
|
||||
@(cd $(vpppluginsdir) && $(RM) $(vppplugins_LTLIBRARIES))
|
||||
@(cd $(vppapitestpluginsdir) && $(RM) $(vppapitestplugins_LTLIBRARIES))
|
||||
|
||||
|
||||
#
|
||||
# Java code generation
|
||||
#
|
||||
|
@ -1,4 +1,4 @@
|
||||
AC_INIT(ioam_plugin, 1.0)
|
||||
AC_INIT(ioam_plugin, 17.01)
|
||||
LT_INIT
|
||||
AC_CONFIG_MACRO_DIR([../../vpp-api/java/m4])
|
||||
AM_INIT_AUTOMAKE
|
||||
|
@ -25,8 +25,6 @@
|
||||
#include <vppinfra/elog.h>
|
||||
|
||||
#include <vnet/ip/ip6_hop_by_hop.h>
|
||||
#include <vnet/plugin/plugin.h>
|
||||
|
||||
#include "ip6_ioam_e2e.h"
|
||||
|
||||
ioam_e2e_main_t ioam_e2e_main;
|
||||
@ -166,23 +164,6 @@ VLIB_CLI_COMMAND (ioam_show_e2e_cmd, static) = {
|
||||
.function = ioam_show_e2e_cmd_fn,
|
||||
};
|
||||
|
||||
/*
|
||||
* This routine exists to convince the vlib plugin framework that
|
||||
* we haven't accidentally copied a random .dll into the plugin directory.
|
||||
*
|
||||
* Also collects global variable pointers passed from the vpp engine
|
||||
*/
|
||||
clib_error_t *
|
||||
vlib_plugin_register (vlib_main_t * vm, vnet_plugin_handoff_t * h,
|
||||
int from_early_init)
|
||||
{
|
||||
clib_error_t * error = 0;
|
||||
|
||||
ioam_e2e_main.vlib_main = vm;
|
||||
ioam_e2e_main.vnet_main = h->vnet_main;
|
||||
return error;
|
||||
}
|
||||
|
||||
/*
|
||||
* Init handler E2E headet handling.
|
||||
* Init hanlder registers encap, decap, trace and Rewrite handlers.
|
||||
@ -222,6 +203,9 @@ ioam_e2e_init (vlib_main_t * vm)
|
||||
"HBH_OPTION_TYPE_IOAM_EDGE_TO_EDGE Flow handler failed"));
|
||||
}
|
||||
|
||||
ioam_e2e_main.vlib_main = vm;
|
||||
ioam_e2e_main.vnet_main = vnet_get_main();
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include <vppinfra/hash.h>
|
||||
#include <vppinfra/error.h>
|
||||
#include <vppinfra/elog.h>
|
||||
#include <vnet/plugin/plugin.h>
|
||||
|
||||
#include <ioam/lib-trace/trace_util.h>
|
||||
|
||||
@ -348,6 +349,18 @@ VLIB_CLI_COMMAND (ip6_show_ioam_trace_cmd, static) = {
|
||||
};
|
||||
/* *INDENT-ON* */
|
||||
|
||||
/*
|
||||
* This routine exists to convince the vlib plugin framework that
|
||||
* we haven't accidentally copied a random .dll into the plugin directory.
|
||||
*
|
||||
* Also collects global variable pointers passed from the vpp engine
|
||||
*/
|
||||
clib_error_t *
|
||||
vlib_plugin_register (vlib_main_t * vm, vnet_plugin_handoff_t * h,
|
||||
int from_early_init)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static clib_error_t *
|
||||
ip6_hop_by_hop_ioam_trace_init (vlib_main_t * vm)
|
||||
|
@ -76,7 +76,8 @@ typedef struct
|
||||
ioam_export_main_t ioam_export_main;
|
||||
ioam_export_main_t vxlan_gpe_ioam_export_main;
|
||||
|
||||
vlib_node_registration_t export_node;
|
||||
extern vlib_node_registration_t export_node;
|
||||
extern vlib_node_registration_t vxlan_export_node;
|
||||
|
||||
#define DEFAULT_EXPORT_SIZE (3 * CLIB_CACHE_LINE_BYTES)
|
||||
/*
|
||||
|
@ -92,7 +92,7 @@ vxlan_gpe_ioam_export_enable_disable (ioam_export_main_t * em,
|
||||
ip4_address_t * src_address)
|
||||
{
|
||||
vlib_main_t *vm = em->vlib_main;
|
||||
u32 node_index = export_node.index;
|
||||
u32 node_index = vxlan_export_node.index;
|
||||
vlib_node_t *vxlan_gpe_decap_ioam_node = NULL;
|
||||
|
||||
if (is_disable == 0)
|
||||
|
@ -40,7 +40,7 @@ format_export_trace (u8 * s, va_list * args)
|
||||
return s;
|
||||
}
|
||||
|
||||
vlib_node_registration_t export_node;
|
||||
vlib_node_registration_t vxlan_export_node;
|
||||
|
||||
#define foreach_export_error \
|
||||
_(RECORDED, "Packets recorded for export")
|
||||
@ -137,7 +137,7 @@ vxlan_gpe_export_node_fn (vlib_main_t * vm,
|
||||
* Node for VXLAN-GPE export
|
||||
*/
|
||||
/* *INDENT-OFF* */
|
||||
VLIB_REGISTER_NODE (export_node) =
|
||||
VLIB_REGISTER_NODE (vxlan_export_node) =
|
||||
{
|
||||
.function = vxlan_gpe_export_node_fn,
|
||||
.name = "vxlan-gpe-ioam-export",
|
||||
|
@ -81,26 +81,6 @@ do { \
|
||||
#define foreach_ioam_export_plugin_api_msg \
|
||||
_(IOAM_EXPORT_IP6_ENABLE_DISABLE, ioam_export_ip6_enable_disable)
|
||||
|
||||
/*
|
||||
* This routine exists to convince the vlib plugin framework that
|
||||
* we haven't accidentally copied a random .dll into the plugin directory.
|
||||
*
|
||||
* Also collects global variable pointers passed from the vpp engine
|
||||
*/
|
||||
|
||||
clib_error_t *
|
||||
vlib_plugin_register (vlib_main_t * vm, vnet_plugin_handoff_t * h,
|
||||
int from_early_init)
|
||||
{
|
||||
ioam_export_main_t *em = &ioam_export_main;
|
||||
clib_error_t *error = 0;
|
||||
|
||||
em->vlib_main = vm;
|
||||
em->vnet_main = h->vnet_main;
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
/* Action function shared between message handler and debug CLI */
|
||||
|
||||
int
|
||||
@ -250,6 +230,9 @@ ioam_export_init (vlib_main_t * vm)
|
||||
u32 node_index = export_node.index;
|
||||
vlib_node_t *ip6_hbyh_node = NULL;
|
||||
|
||||
em->vlib_main = vm;
|
||||
em->vnet_main = vnet_get_main ();
|
||||
|
||||
name = format (0, "ioam_export_%08x%c", api_version, 0);
|
||||
|
||||
/* Ask for a correctly-sized block of API message decode slots */
|
||||
|
@ -213,26 +213,6 @@ static void vl_api_pot_profile_del_t_handler
|
||||
REPLY_MACRO(VL_API_POT_PROFILE_DEL_REPLY);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* This routine exists to convince the vlib plugin framework that
|
||||
* we haven't accidentally copied a random .dll into the plugin directory.
|
||||
*
|
||||
* Also collects global variable pointers passed from the vpp engine
|
||||
*/
|
||||
|
||||
clib_error_t *
|
||||
vlib_plugin_register (vlib_main_t * vm, vnet_plugin_handoff_t * h,
|
||||
int from_early_init)
|
||||
{
|
||||
pot_main_t * sm = &pot_main;
|
||||
clib_error_t * error = 0;
|
||||
|
||||
sm->vlib_main = vm;
|
||||
sm->vnet_main = h->vnet_main;
|
||||
return error;
|
||||
}
|
||||
|
||||
/* Set up the API message handling tables */
|
||||
static clib_error_t *
|
||||
pot_plugin_api_hookup (vlib_main_t *vm)
|
||||
@ -273,6 +253,10 @@ static clib_error_t * pot_init (vlib_main_t * vm)
|
||||
|
||||
bzero(sm, sizeof(pot_main));
|
||||
(void)pot_util_init();
|
||||
|
||||
sm->vlib_main = vm;
|
||||
sm->vnet_main = vnet_get_main();
|
||||
|
||||
name = format (0, "ioam_pot_%08x%c", api_version, 0);
|
||||
|
||||
/* Ask for a correctly-sized block of API message decode slots */
|
||||
|
@ -165,25 +165,6 @@ static void vl_api_trace_profile_show_config_t_handler
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This routine exists to convince the vlib plugin framework that
|
||||
* we haven't accidentally copied a random .dll into the plugin directory.
|
||||
*
|
||||
* Also collects global variable pointers passed from the vpp engine
|
||||
*/
|
||||
|
||||
clib_error_t *
|
||||
vlib_plugin_register (vlib_main_t * vm, vnet_plugin_handoff_t * h,
|
||||
int from_early_init)
|
||||
{
|
||||
trace_main_t *sm = &trace_main;
|
||||
clib_error_t *error = 0;
|
||||
|
||||
sm->vlib_main = vm;
|
||||
sm->vnet_main = h->vnet_main;
|
||||
return error;
|
||||
}
|
||||
|
||||
/* Set up the API message handling tables */
|
||||
static clib_error_t *
|
||||
trace_plugin_api_hookup (vlib_main_t * vm)
|
||||
@ -225,6 +206,10 @@ trace_init (vlib_main_t * vm)
|
||||
|
||||
bzero (sm, sizeof (trace_main));
|
||||
(void) trace_util_init ();
|
||||
|
||||
sm->vlib_main = vm;
|
||||
sm->vnet_main = vnet_get_main ();
|
||||
|
||||
name = format (0, "ioam_trace_%08x%c", api_version, 0);
|
||||
|
||||
/* Ask for a correctly-sized block of API message decode slots */
|
||||
|
@ -284,28 +284,6 @@ static void vl_api_vxlan_gpe_ioam_transit_disable_t_handler
|
||||
VXLAN_GPE_REPLY_MACRO (VL_API_VXLAN_GPE_IOAM_TRANSIT_DISABLE_REPLY);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* This routine exists to convince the vlib plugin framework that
|
||||
* we haven't accidentally copied a random .dll into the plugin directory.
|
||||
*
|
||||
* Also collects global variable pointers passed from the vpp engine
|
||||
*/
|
||||
|
||||
clib_error_t *
|
||||
vlib_plugin_register (vlib_main_t * vm, vnet_plugin_handoff_t * h,
|
||||
int from_early_init)
|
||||
{
|
||||
vxlan_gpe_ioam_main_t *sm = &vxlan_gpe_ioam_main;
|
||||
clib_error_t *error = 0;
|
||||
|
||||
sm->vlib_main = vm;
|
||||
sm->vnet_main = h->vnet_main;
|
||||
sm->unix_time_0 = (u32) time (0); /* Store starting time */
|
||||
sm->vlib_time_0 = vlib_time_now (vm);
|
||||
return error;
|
||||
}
|
||||
|
||||
/* Set up the API message handling tables */
|
||||
static clib_error_t *
|
||||
vxlan_gpe_plugin_api_hookup (vlib_main_t * vm)
|
||||
@ -337,6 +315,11 @@ vxlan_gpe_init (vlib_main_t * vm)
|
||||
vlib_node_t *vxlan_gpe_decap_node = NULL;
|
||||
uword next_node = 0;
|
||||
|
||||
sm->vlib_main = vm;
|
||||
sm->vnet_main = vnet_get_main ();
|
||||
sm->unix_time_0 = (u32) time (0); /* Store starting time */
|
||||
sm->vlib_time_0 = vlib_time_now (vm);
|
||||
|
||||
name = format (0, "ioam_vxlan_gpe_%08x%c", api_version, 0);
|
||||
|
||||
/* Ask for a correctly-sized block of API message decode slots */
|
||||
|
@ -466,7 +466,7 @@ api_vxlan_gpe_ioam_transit_disable (vat_main_t * vam)
|
||||
ip6_address_t local6;
|
||||
u8 ipv4_set = 0, ipv6_set = 0;
|
||||
u8 local_set = 0;
|
||||
u32 outer_fib_index;
|
||||
u32 outer_fib_index = 0;
|
||||
f64 timeout;
|
||||
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
AC_INIT(snat_plugin, 1.0)
|
||||
AC_INIT(snat_plugin, 17.01)
|
||||
AC_CONFIG_MACRO_DIR([../../vpp-api/java/m4])
|
||||
AM_INIT_AUTOMAKE
|
||||
AM_SILENT_RULES([yes])
|
||||
|
@ -203,7 +203,7 @@ static u32 slow_path (snat_main_t *sm, vlib_buffer_t *b0,
|
||||
/* Get the session */
|
||||
s = pool_elt_at_index (sm->per_thread_data[cpu_index].sessions,
|
||||
session_index);
|
||||
} while (!snat_is_session_static (s));
|
||||
} while (snat_is_session_static (s));
|
||||
|
||||
/* Remove in2out, out2in keys */
|
||||
kv0.key = s->in2out.as_u64;
|
||||
|
@ -872,6 +872,13 @@ snat_out2in_worker_handoff_fn (vlib_main_t * vm,
|
||||
key0.port = udp0->dst_port;
|
||||
key0.fib_index = rx_fib_index0;
|
||||
|
||||
if (PREDICT_FALSE(ip0->protocol == IP_PROTOCOL_ICMP))
|
||||
{
|
||||
icmp46_header_t * icmp0 = (icmp46_header_t *) udp0;
|
||||
icmp_echo_header_t *echo0 = (icmp_echo_header_t *)(icmp0+1);
|
||||
key0.port = echo0->identifier;
|
||||
}
|
||||
|
||||
kv0.key = key0.as_u64;
|
||||
|
||||
/* Ever heard of of the "user" before? */
|
||||
|
@ -974,13 +974,13 @@ vl_api_snat_show_config_t_handler
|
||||
|
||||
REPLY_MACRO2(VL_API_SNAT_SHOW_CONFIG_REPLY,
|
||||
({
|
||||
rmp->translation_buckets = htons (sm->translation_buckets);
|
||||
rmp->translation_memory_size = htons (sm->translation_memory_size);
|
||||
rmp->user_buckets = htons (sm->user_buckets);
|
||||
rmp->user_memory_size = htons (sm->user_memory_size);
|
||||
rmp->max_translations_per_user = htons (sm->max_translations_per_user);
|
||||
rmp->outside_vrf_id = htons (sm->outside_vrf_id);
|
||||
rmp->inside_vrf_id = htons (sm->inside_vrf_id);
|
||||
rmp->translation_buckets = htonl (sm->translation_buckets);
|
||||
rmp->translation_memory_size = htonl (sm->translation_memory_size);
|
||||
rmp->user_buckets = htonl (sm->user_buckets);
|
||||
rmp->user_memory_size = htonl (sm->user_memory_size);
|
||||
rmp->max_translations_per_user = htonl (sm->max_translations_per_user);
|
||||
rmp->outside_vrf_id = htonl (sm->outside_vrf_id);
|
||||
rmp->inside_vrf_id = htonl (sm->inside_vrf_id);
|
||||
rmp->static_mapping_only = sm->static_mapping_only;
|
||||
rmp->static_mapping_connection_tracking =
|
||||
sm->static_mapping_connection_tracking;
|
||||
@ -1860,7 +1860,7 @@ show_snat_command_fn (vlib_main_t * vm,
|
||||
({
|
||||
s = format (s, " %d", j);
|
||||
}));
|
||||
vlib_cli_output (vm, " %d busy ports:%s", ap->busy_ports, s);
|
||||
vlib_cli_output (vm, " %d busy ports:%v", ap->busy_ports, s);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1873,7 +1873,7 @@ show_snat_command_fn (vlib_main_t * vm,
|
||||
{
|
||||
vlib_worker_thread_t *w =
|
||||
vlib_worker_threads + *worker + sm->first_worker_index;
|
||||
vlib_cli_output (vm, " %s", w->name);
|
||||
vlib_cli_output (vm, " %v", w->name);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1924,7 +1924,7 @@ show_snat_command_fn (vlib_main_t * vm,
|
||||
continue;
|
||||
|
||||
vlib_worker_thread_t *w = vlib_worker_threads + j;
|
||||
vlib_cli_output (vm, "Thread %d (%s at lcore %u):", j, w->name,
|
||||
vlib_cli_output (vm, "Thread %d (%v at lcore %u):", j, w->name,
|
||||
w->lcore_id);
|
||||
vlib_cli_output (vm, " %d list pool elements",
|
||||
pool_elts (tsm->list_pool));
|
||||
|
@ -11,23 +11,28 @@ class BridgeDomain(object):
|
||||
__metaclass__ = ABCMeta
|
||||
|
||||
@property
|
||||
def frame_pg0_to_pg1(self):
|
||||
""" Ethernet frame sent from pg0 and expected to arrive at pg1 """
|
||||
def frame_request(self):
|
||||
""" Ethernet frame modeling a generic request """
|
||||
return (Ether(src='00:00:00:00:00:01', dst='00:00:00:00:00:02') /
|
||||
IP(src='1.2.3.4', dst='4.3.2.1') /
|
||||
UDP(sport=10000, dport=20000) /
|
||||
Raw('\xa5' * 100))
|
||||
|
||||
@property
|
||||
def frame_pg1_to_pg0(self):
|
||||
""" Ethernet frame sent from pg1 and expected to arrive at pg0 """
|
||||
def frame_reply(self):
|
||||
""" Ethernet frame modeling a generic reply """
|
||||
return (Ether(src='00:00:00:00:00:02', dst='00:00:00:00:00:01') /
|
||||
IP(src='4.3.2.1', dst='1.2.3.4') /
|
||||
UDP(sport=20000, dport=10000) /
|
||||
Raw('\xa5' * 100))
|
||||
|
||||
@abstractmethod
|
||||
def encapsulate(self, pkt):
|
||||
def encap_mcast(self, pkt, src_ip, src_mac, vni):
|
||||
""" Encapsulate mcast packet """
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def encapsulate(self, pkt, vni):
|
||||
""" Encapsulate packet """
|
||||
pass
|
||||
|
||||
@ -37,17 +42,30 @@ class BridgeDomain(object):
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def check_encapsulation(self, pkt):
|
||||
def check_encapsulation(self, pkt, vni, local_only=False):
|
||||
""" Verify the encapsulation """
|
||||
pass
|
||||
|
||||
def assert_eq_pkts(self, pkt1, pkt2):
|
||||
""" Verify the Ether, IP, UDP, payload are equal in both
|
||||
packets
|
||||
"""
|
||||
self.assertEqual(pkt1[Ether].src, pkt2[Ether].src)
|
||||
self.assertEqual(pkt1[Ether].dst, pkt2[Ether].dst)
|
||||
self.assertEqual(pkt1[IP].src, pkt2[IP].src)
|
||||
self.assertEqual(pkt1[IP].dst, pkt2[IP].dst)
|
||||
self.assertEqual(pkt1[UDP].sport, pkt2[UDP].sport)
|
||||
self.assertEqual(pkt1[UDP].dport, pkt2[UDP].dport)
|
||||
self.assertEqual(pkt1[Raw], pkt2[Raw])
|
||||
|
||||
def test_decap(self):
|
||||
""" Decapsulation test
|
||||
Send encapsulated frames from pg0
|
||||
Verify receipt of decapsulated frames on pg1
|
||||
"""
|
||||
|
||||
encapsulated_pkt = self.encapsulate(self.frame_pg0_to_pg1)
|
||||
encapsulated_pkt = self.encapsulate(self.frame_request,
|
||||
self.single_tunnel_bd)
|
||||
|
||||
self.pg0.add_stream([encapsulated_pkt, ])
|
||||
|
||||
@ -61,22 +79,14 @@ class BridgeDomain(object):
|
||||
'Invalid number of packets on '
|
||||
'output: {}'.format(len(out)))
|
||||
pkt = out[0]
|
||||
|
||||
# TODO: add error messages
|
||||
self.assertEqual(pkt[Ether].src, self.frame_pg0_to_pg1[Ether].src)
|
||||
self.assertEqual(pkt[Ether].dst, self.frame_pg0_to_pg1[Ether].dst)
|
||||
self.assertEqual(pkt[IP].src, self.frame_pg0_to_pg1[IP].src)
|
||||
self.assertEqual(pkt[IP].dst, self.frame_pg0_to_pg1[IP].dst)
|
||||
self.assertEqual(pkt[UDP].sport, self.frame_pg0_to_pg1[UDP].sport)
|
||||
self.assertEqual(pkt[UDP].dport, self.frame_pg0_to_pg1[UDP].dport)
|
||||
self.assertEqual(pkt[Raw], self.frame_pg0_to_pg1[Raw])
|
||||
self.assert_eq_pkts(pkt, self.frame_request)
|
||||
|
||||
def test_encap(self):
|
||||
""" Encapsulation test
|
||||
Send frames from pg1
|
||||
Verify receipt of encapsulated frames on pg0
|
||||
"""
|
||||
self.pg1.add_stream([self.frame_pg1_to_pg0])
|
||||
self.pg1.add_stream([self.frame_reply])
|
||||
|
||||
self.pg0.enable_capture()
|
||||
|
||||
@ -88,14 +98,77 @@ class BridgeDomain(object):
|
||||
'Invalid number of packets on '
|
||||
'output: {}'.format(len(out)))
|
||||
pkt = out[0]
|
||||
self.check_encapsulation(pkt)
|
||||
self.check_encapsulation(pkt, self.single_tunnel_bd)
|
||||
|
||||
payload = self.decapsulate(pkt)
|
||||
# TODO: add error messages
|
||||
self.assertEqual(payload[Ether].src, self.frame_pg1_to_pg0[Ether].src)
|
||||
self.assertEqual(payload[Ether].dst, self.frame_pg1_to_pg0[Ether].dst)
|
||||
self.assertEqual(payload[IP].src, self.frame_pg1_to_pg0[IP].src)
|
||||
self.assertEqual(payload[IP].dst, self.frame_pg1_to_pg0[IP].dst)
|
||||
self.assertEqual(payload[UDP].sport, self.frame_pg1_to_pg0[UDP].sport)
|
||||
self.assertEqual(payload[UDP].dport, self.frame_pg1_to_pg0[UDP].dport)
|
||||
self.assertEqual(payload[Raw], self.frame_pg1_to_pg0[Raw])
|
||||
self.assert_eq_pkts(payload, self.frame_reply)
|
||||
|
||||
def test_ucast_flood(self):
|
||||
""" Unicast flood test
|
||||
Send frames from pg3
|
||||
Verify receipt of encapsulated frames on pg0
|
||||
"""
|
||||
self.pg3.add_stream([self.frame_reply])
|
||||
|
||||
self.pg0.enable_capture()
|
||||
|
||||
self.pg_start()
|
||||
|
||||
# Get packet from each tunnel and assert it's corectly encapsulated.
|
||||
out = self.pg0.get_capture()
|
||||
self.assertEqual(len(out), 10,
|
||||
'Invalid number of packets on '
|
||||
'output: {}'.format(len(out)))
|
||||
for pkt in out:
|
||||
self.check_encapsulation(pkt, self.ucast_flood_bd, True)
|
||||
payload = self.decapsulate(pkt)
|
||||
self.assert_eq_pkts(payload, self.frame_reply)
|
||||
|
||||
def test_mcast_flood(self):
|
||||
""" Multicast flood test
|
||||
Send frames from pg2
|
||||
Verify receipt of encapsulated frames on pg0
|
||||
"""
|
||||
self.pg2.add_stream([self.frame_reply])
|
||||
|
||||
self.pg0.enable_capture()
|
||||
|
||||
self.pg_start()
|
||||
|
||||
# Pick first received frame and check if it's corectly encapsulated.
|
||||
out = self.pg0.get_capture()
|
||||
self.assertEqual(len(out), 1,
|
||||
'Invalid number of packets on '
|
||||
'output: {}'.format(len(out)))
|
||||
pkt = out[0]
|
||||
self.check_encapsulation(pkt, self.mcast_flood_bd, True)
|
||||
|
||||
payload = self.decapsulate(pkt)
|
||||
self.assert_eq_pkts(payload, self.frame_reply)
|
||||
|
||||
@staticmethod
|
||||
def ipn_to_ip(ipn):
|
||||
return '.'.join(str(i) for i in bytearray(ipn))
|
||||
|
||||
def test_mcast_rcv(self):
|
||||
""" Multicast receive test
|
||||
Send 20 encapsulated frames from pg0 only 10 match unicast tunnels
|
||||
Verify receipt of 10 decap frames on pg2
|
||||
"""
|
||||
mac = self.pg0.remote_mac
|
||||
ip_range_start = 10
|
||||
ip_range_end = 30
|
||||
mcast_stream = [
|
||||
self.encap_mcast(self.frame_request, self.ipn_to_ip(ip), mac,
|
||||
self.mcast_flood_bd)
|
||||
for ip in self.ip4_range(self.pg0.remote_ip4n,
|
||||
ip_range_start, ip_range_end)]
|
||||
self.pg0.add_stream(mcast_stream)
|
||||
self.pg2.enable_capture()
|
||||
self.pg_start()
|
||||
out = self.pg2.get_capture()
|
||||
self.assertEqual(len(out), 10,
|
||||
'Invalid number of packets on '
|
||||
'output: {}'.format(len(out)))
|
||||
for pkt in out:
|
||||
self.assert_eq_pkts(pkt, self.frame_request)
|
||||
|
@ -589,6 +589,33 @@ class TestSNAT(VppTestCase):
|
||||
self.logger.error(ppp("Unexpected or invalid packet:"), p)
|
||||
raise
|
||||
|
||||
def test_max_translations_per_user(self):
|
||||
""" MAX translations per user - recycle the least recently used """
|
||||
|
||||
self.snat_add_address(self.snat_addr)
|
||||
self.vapi.snat_interface_add_del_feature(self.pg0.sw_if_index)
|
||||
self.vapi.snat_interface_add_del_feature(self.pg1.sw_if_index,
|
||||
is_inside=0)
|
||||
|
||||
# get maximum number of translations per user
|
||||
snat_config = self.vapi.snat_show_config()
|
||||
|
||||
# send more than maximum number of translations per user packets
|
||||
pkts_num = snat_config.max_translations_per_user + 5
|
||||
pkts = []
|
||||
for port in range(0, pkts_num):
|
||||
p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
|
||||
IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
|
||||
TCP(sport=1025 + port))
|
||||
pkts.append(p)
|
||||
self.pg0.add_stream(pkts)
|
||||
self.pg_enable_capture(self.pg_interfaces)
|
||||
self.pg_start()
|
||||
|
||||
# verify number of translated packet
|
||||
capture = self.pg1.get_capture()
|
||||
self.assertEqual(pkts_num, len(capture))
|
||||
|
||||
def tearDown(self):
|
||||
super(TestSNAT, self).tearDown()
|
||||
if not self.vpp_dead:
|
||||
|
@ -1,5 +1,6 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import socket
|
||||
import unittest
|
||||
from framework import VppTestCase, VppTestRunner
|
||||
from template_bd import BridgeDomain
|
||||
@ -7,6 +8,7 @@ from template_bd import BridgeDomain
|
||||
from scapy.layers.l2 import Ether
|
||||
from scapy.layers.inet import IP, UDP
|
||||
from scapy.layers.vxlan import VXLAN
|
||||
from scapy.utils import atol
|
||||
|
||||
|
||||
class TestVxlan(BridgeDomain, VppTestCase):
|
||||
@ -16,7 +18,7 @@ class TestVxlan(BridgeDomain, VppTestCase):
|
||||
BridgeDomain.__init__(self)
|
||||
VppTestCase.__init__(self, *args)
|
||||
|
||||
def encapsulate(self, pkt):
|
||||
def encapsulate(self, pkt, vni):
|
||||
"""
|
||||
Encapsulate the original payload frame by adding VXLAN header with its
|
||||
UDP, IP and Ethernet fields
|
||||
@ -24,7 +26,18 @@ class TestVxlan(BridgeDomain, VppTestCase):
|
||||
return (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
|
||||
IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4) /
|
||||
UDP(sport=self.dport, dport=self.dport, chksum=0) /
|
||||
VXLAN(vni=self.vni, flags=self.flags) /
|
||||
VXLAN(vni=vni, flags=self.flags) /
|
||||
pkt)
|
||||
|
||||
def encap_mcast(self, pkt, src_ip, src_mac, vni):
|
||||
"""
|
||||
Encapsulate the original payload frame by adding VXLAN header with its
|
||||
UDP, IP and Ethernet fields
|
||||
"""
|
||||
return (Ether(src=src_mac, dst=self.mcast_mac4) /
|
||||
IP(src=src_ip, dst=self.mcast_ip4) /
|
||||
UDP(sport=self.dport, dport=self.dport, chksum=0) /
|
||||
VXLAN(vni=vni, flags=self.flags) /
|
||||
pkt)
|
||||
|
||||
def decapsulate(self, pkt):
|
||||
@ -37,21 +50,66 @@ class TestVxlan(BridgeDomain, VppTestCase):
|
||||
|
||||
# Method for checking VXLAN encapsulation.
|
||||
#
|
||||
def check_encapsulation(self, pkt):
|
||||
def check_encapsulation(self, pkt, vni, local_only=False):
|
||||
# TODO: add error messages
|
||||
# Verify source MAC is VPP_MAC and destination MAC is MY_MAC resolved
|
||||
# by VPP using ARP.
|
||||
self.assertEqual(pkt[Ether].src, self.pg0.local_mac)
|
||||
self.assertEqual(pkt[Ether].dst, self.pg0.remote_mac)
|
||||
if not local_only:
|
||||
self.assertEqual(pkt[Ether].dst, self.pg0.remote_mac)
|
||||
# Verify VXLAN tunnel source IP is VPP_IP and destination IP is MY_IP.
|
||||
self.assertEqual(pkt[IP].src, self.pg0.local_ip4)
|
||||
self.assertEqual(pkt[IP].dst, self.pg0.remote_ip4)
|
||||
if not local_only:
|
||||
self.assertEqual(pkt[IP].dst, self.pg0.remote_ip4)
|
||||
# Verify UDP destination port is VXLAN 4789, source UDP port could be
|
||||
# arbitrary.
|
||||
self.assertEqual(pkt[UDP].dport, type(self).dport)
|
||||
# TODO: checksum check
|
||||
# Verify VNI, based on configuration it must be 1.
|
||||
self.assertEqual(pkt[VXLAN].vni, type(self).vni)
|
||||
# Verify VNI
|
||||
self.assertEqual(pkt[VXLAN].vni, vni)
|
||||
|
||||
@staticmethod
|
||||
def ip4_range(ip4n, s=10, e=20):
|
||||
base = str(bytearray(ip4n)[:3])
|
||||
return ((base + ip) for ip in str(bytearray(range(s, e))))
|
||||
|
||||
@classmethod
|
||||
def create_vxlan_flood_test_bd(cls, vni):
|
||||
# Create 10 ucast vxlan tunnels under bd
|
||||
ip_range_start = 10
|
||||
ip_range_end = 20
|
||||
next_hop_address = cls.pg0.remote_ip4n
|
||||
for dest_addr in cls.ip4_range(next_hop_address, ip_range_start,
|
||||
ip_range_end):
|
||||
# add host route so dest_addr will not be resolved
|
||||
cls.vapi.ip_add_del_route(dest_addr, 32, next_hop_address)
|
||||
r = cls.vapi.vxlan_add_del_tunnel(
|
||||
src_addr=cls.pg0.local_ip4n,
|
||||
dst_addr=dest_addr,
|
||||
vni=vni)
|
||||
cls.vapi.sw_interface_set_l2_bridge(r.sw_if_index, bd_id=vni)
|
||||
|
||||
@classmethod
|
||||
def add_del_mcast_load(cls, is_add):
|
||||
ip_range_start = 10
|
||||
ip_range_end = 210
|
||||
for dest_addr in cls.ip4_range(cls.mcast_ip4n, ip_range_start,
|
||||
ip_range_end):
|
||||
vni = bytearray(dest_addr)[3]
|
||||
cls.vapi.vxlan_add_del_tunnel(
|
||||
src_addr=cls.pg0.local_ip4n,
|
||||
dst_addr=dest_addr,
|
||||
mcast_sw_if_index=1,
|
||||
vni=vni,
|
||||
is_add=is_add)
|
||||
|
||||
@classmethod
|
||||
def add_mcast_load(cls):
|
||||
cls.add_del_mcast_load(is_add=1)
|
||||
|
||||
@classmethod
|
||||
def del_mcast_load(cls):
|
||||
cls.add_del_mcast_load(is_add=0)
|
||||
|
||||
# Class method to start the VXLAN test case.
|
||||
# Overrides setUpClass method in VppTestCase class.
|
||||
@ -65,12 +123,11 @@ class TestVxlan(BridgeDomain, VppTestCase):
|
||||
try:
|
||||
cls.dport = 4789
|
||||
cls.flags = 0x8
|
||||
cls.vni = 1
|
||||
|
||||
# Create 2 pg interfaces.
|
||||
cls.create_pg_interfaces(range(2))
|
||||
cls.pg0.admin_up()
|
||||
cls.pg1.admin_up()
|
||||
cls.create_pg_interfaces(range(4))
|
||||
for pg in cls.pg_interfaces:
|
||||
pg.admin_up()
|
||||
|
||||
# Configure IPv4 addresses on VPP pg0.
|
||||
cls.pg0.config_ip4()
|
||||
@ -78,14 +135,47 @@ class TestVxlan(BridgeDomain, VppTestCase):
|
||||
# Resolve MAC address for VPP's IP address on pg0.
|
||||
cls.pg0.resolve_arp()
|
||||
|
||||
# Our Multicast address
|
||||
cls.mcast_ip4 = '239.1.1.1'
|
||||
cls.mcast_ip4n = socket.inet_pton(socket.AF_INET, cls.mcast_ip4)
|
||||
iplong = atol(cls.mcast_ip4)
|
||||
cls.mcast_mac4 = "01:00:5e:%02x:%02x:%02x" % (
|
||||
(iplong >> 16) & 0x7F, (iplong >> 8) & 0xFF, iplong & 0xFF)
|
||||
|
||||
# Create VXLAN VTEP on VPP pg0, and put vxlan_tunnel0 and pg1
|
||||
# into BD.
|
||||
cls.single_tunnel_bd = 1
|
||||
r = cls.vapi.vxlan_add_del_tunnel(
|
||||
src_addr=cls.pg0.local_ip4n,
|
||||
dst_addr=cls.pg0.remote_ip4n,
|
||||
vni=cls.vni)
|
||||
cls.vapi.sw_interface_set_l2_bridge(r.sw_if_index, bd_id=1)
|
||||
cls.vapi.sw_interface_set_l2_bridge(cls.pg1.sw_if_index, bd_id=1)
|
||||
vni=cls.single_tunnel_bd)
|
||||
cls.vapi.sw_interface_set_l2_bridge(r.sw_if_index,
|
||||
bd_id=cls.single_tunnel_bd)
|
||||
cls.vapi.sw_interface_set_l2_bridge(cls.pg1.sw_if_index,
|
||||
bd_id=cls.single_tunnel_bd)
|
||||
|
||||
# Setup vni 2 to test multicast flooding
|
||||
cls.mcast_flood_bd = 2
|
||||
cls.create_vxlan_flood_test_bd(cls.mcast_flood_bd)
|
||||
r = cls.vapi.vxlan_add_del_tunnel(
|
||||
src_addr=cls.pg0.local_ip4n,
|
||||
dst_addr=cls.mcast_ip4n,
|
||||
mcast_sw_if_index=1,
|
||||
vni=cls.mcast_flood_bd)
|
||||
cls.vapi.sw_interface_set_l2_bridge(r.sw_if_index,
|
||||
bd_id=cls.mcast_flood_bd)
|
||||
cls.vapi.sw_interface_set_l2_bridge(cls.pg2.sw_if_index,
|
||||
bd_id=cls.mcast_flood_bd)
|
||||
|
||||
# Add and delete mcast tunnels to check stability
|
||||
cls.add_mcast_load()
|
||||
cls.del_mcast_load()
|
||||
|
||||
# Setup vni 3 to test unicast flooding
|
||||
cls.ucast_flood_bd = 3
|
||||
cls.create_vxlan_flood_test_bd(cls.ucast_flood_bd)
|
||||
cls.vapi.sw_interface_set_l2_bridge(cls.pg3.sw_if_index,
|
||||
bd_id=cls.ucast_flood_bd)
|
||||
except Exception:
|
||||
super(TestVxlan, cls).tearDownClass()
|
||||
raise
|
||||
@ -97,6 +187,9 @@ class TestVxlan(BridgeDomain, VppTestCase):
|
||||
super(TestVxlan, self).tearDown()
|
||||
if not self.vpp_dead:
|
||||
self.logger.info(self.vapi.cli("show bridge-domain 1 detail"))
|
||||
self.logger.info(self.vapi.cli("show bridge-domain 2 detail"))
|
||||
self.logger.info(self.vapi.cli("show bridge-domain 3 detail"))
|
||||
self.logger.info(self.vapi.cli("show vxlan tunnel"))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
@ -842,6 +842,12 @@ class VppPapiProvider(object):
|
||||
"""
|
||||
return self.api(self.papi.snat_static_mapping_dump, {})
|
||||
|
||||
def snat_show_config(self):
|
||||
"""Show S-NAT config
|
||||
:return: S-NAT config parameters
|
||||
"""
|
||||
return self.api(self.papi.snat_show_config, {})
|
||||
|
||||
def control_ping(self):
|
||||
self.api(self.papi.control_ping)
|
||||
|
||||
|
@ -691,6 +691,8 @@ vl_msg_api_set_handlers (int id, char *name, void *handler, void *cleanup,
|
||||
vl_msg_api_msg_config_t cfg;
|
||||
vl_msg_api_msg_config_t *c = &cfg;
|
||||
|
||||
memset (c, 0, sizeof (*c));
|
||||
|
||||
c->id = id;
|
||||
c->name = name;
|
||||
c->handler = handler;
|
||||
|
@ -347,6 +347,8 @@ memory_api_init (char *region_name)
|
||||
vl_msg_api_msg_config_t cfg;
|
||||
vl_msg_api_msg_config_t *c = &cfg;
|
||||
|
||||
memset (c, 0, sizeof (*c));
|
||||
|
||||
if ((rv = vl_map_shmem (region_name, 1 /* is_vlib */ )) < 0)
|
||||
return rv;
|
||||
|
||||
@ -360,6 +362,7 @@ memory_api_init (char *region_name)
|
||||
c->size = sizeof(vl_api_##n##_t); \
|
||||
c->traced = 1; /* trace, so these msgs print */ \
|
||||
c->replay = 0; /* don't replay client create/delete msgs */ \
|
||||
c->message_bounce = 0; /* don't bounce this message */ \
|
||||
vl_msg_api_config(c);} while (0);
|
||||
|
||||
foreach_vlib_api_msg;
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user