aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOle Troan <ot@cisco.com>2016-08-25 12:26:47 +0200
committerDave Barach <openvpp@barachs.net>2016-08-29 11:57:31 +0000
commitd575e69177cc1462658ec1de1149730e0ffb0425 (patch)
tree8dd59056b41c380ffb1cd24ef9adc14d21fd3794
parentd46cca174394794073585da4819eacc2bd72e862 (diff)
VPP-310 Mapping algorithm compute wrong ea-bits
Mapping of IPv4 prefixes ended up writing past IPv6 prefix + EA bits length. (Added some unit testing code). Change-Id: I59893b44eea5cebf00a23afc405832741f84cf4f Signed-off-by: Ole Troan <ot@cisco.com>
-rw-r--r--build-data/platforms/vpp_lite.mk3
-rw-r--r--vnet/Makefile.am29
-rw-r--r--vnet/vnet/map/map.c3
-rw-r--r--vnet/vnet/map/map.h2
-rw-r--r--vnet/vnet/map/test.c205
5 files changed, 231 insertions, 11 deletions
diff --git a/build-data/platforms/vpp_lite.mk b/build-data/platforms/vpp_lite.mk
index 9375a7a90e3..94e695112f5 100644
--- a/build-data/platforms/vpp_lite.mk
+++ b/build-data/platforms/vpp_lite.mk
@@ -24,6 +24,9 @@ vpp_lite_native_tools = vppapigen
vpp_lite_uses_dpdk = no
+# Uncoment to enable building unit tests
+#vpp_lite_enable_tests = yes
+
vpp_lite_root_packages = vpp vlib vlib-api vnet svm vpp-api-test \
vpp-api gmod
diff --git a/vnet/Makefile.am b/vnet/Makefile.am
index a763291c2af..fd9c3e508b7 100644
--- a/vnet/Makefile.am
+++ b/vnet/Makefile.am
@@ -21,6 +21,11 @@ nobase_include_HEADERS =
noinst_PROGRAMS =
TESTS =
+dpdk_libs =
+if WITH_DPDK
+dpdk_libs += -l:libdpdk.a
+endif
+
########################################
# Generic stuff
########################################
@@ -358,6 +363,20 @@ libvnet_la_SOURCES += \
nobase_include_HEADERS += \
vnet/map/map.h
+if ENABLE_TESTS
+TESTS += test_map
+test_map_SOURCES = \
+ vnet/map/test.c
+test_map_CPPFLAGS = $(AM_CPPFLAGS) -DCLIB_DEBUG
+
+test_map_LDADD = libvnet.la -lvppinfra -lvlib \
+ -lpthread -lvlibmemory -lvlibapi -lvlib_unix \
+ -ldl -lsvm -lrt
+
+test_map_LDFLAGS = -static
+endif
+
+
########################################
# Tunnel protocol: gre
########################################
@@ -448,7 +467,7 @@ nobase_include_HEADERS += \
if ENABLE_TESTS
-LDS = -lvppinfra -l:libvlib.a -l:libdpdk.a -l:libvlibmemory.a \
+LDS = -lvppinfra -l:libvlib.a $(dpdk_libs) -l:libvlibmemory.a \
-l:libvlibapi.a -l:libsvm.a -lpthread -ldl -lrt -lm -l:libvlib_unix.a
TESTS += test_cp_serdes test_lisp_types
@@ -698,12 +717,6 @@ nobase_include_HEADERS += \
lib_LTLIBRARIES = libvnet.la libvnetplugin.la
-dpdk_libs =
-
-if WITH_DPDK
-dpdk_libs += -l:libdpdk.a
-endif
-
pcap2pg_SOURCES = \
vnet/unix/pcap2pg.c \
vnet/unix/pcap.h
@@ -712,5 +725,3 @@ pcap2pg_LDFLAGS = -static
pcap2pg_LDADD = libvnet.la -l:libvppinfra.a -lpthread -lm -ldl
noinst_PROGRAMS += pcap2pg
-
-
diff --git a/vnet/vnet/map/map.c b/vnet/vnet/map/map.c
index 17ecf460f51..91811df2f63 100644
--- a/vnet/vnet/map/map.c
+++ b/vnet/vnet/map/map.c
@@ -193,7 +193,8 @@ map_create_domain (ip4_address_t * ip4_prefix,
if (ip4_prefix_len + ea_bits_len < 32)
{
flags |= MAP_DOMAIN_PREFIX;
- suffix_len = suffix_shift = 32 - ip4_prefix_len - ea_bits_len;
+ suffix_shift = 32 - ip4_prefix_len - ea_bits_len;
+ suffix_len = ea_bits_len;
}
else
{
diff --git a/vnet/vnet/map/map.h b/vnet/vnet/map/map.h
index 4b3df5f0842..fb532291f8a 100644
--- a/vnet/vnet/map/map.h
+++ b/vnet/vnet/map/map.h
@@ -358,7 +358,7 @@ map_get_sfx (map_domain_t *d, u32 addr, u16 port)
/* IPv4 prefix */
if (d->flags & MAP_DOMAIN_PREFIX)
- return (u64) (addr & ~d->suffix_mask) << 16;
+ return (u64) (addr & (0xFFFFFFFF << d->suffix_shift)) << 16;
/* Shared or full IPv4 address */
return ((u64) addr << 16) | psid;
diff --git a/vnet/vnet/map/test.c b/vnet/vnet/map/test.c
new file mode 100644
index 00000000000..f3c893a7a31
--- /dev/null
+++ b/vnet/vnet/map/test.c
@@ -0,0 +1,205 @@
+/*
+ * test.c : MAP unit tests
+ *
+ * Copyright (c) 2016 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 <assert.h>
+#include "map.h"
+
+static map_domain_t *
+get_domain(ip4_address_t * ip4_prefix, u8 ip4_prefix_len,
+ ip6_address_t * ip6_prefix, u8 ip6_prefix_len,
+ ip6_address_t * ip6_src, u8 ip6_src_len,
+ u8 ea_bits_len, u8 psid_offset,
+ u8 psid_length, u16 mtu, u8 flags)
+{
+ map_domain_t * d = malloc(sizeof(*d));
+ u8 suffix_len;
+
+ /* EA bits must be within the first 64 bits */
+ if (ea_bits_len > 0 && (ip6_prefix_len + ea_bits_len) > 64)
+ return NULL;
+
+ /* Init domain struct */
+ d->ip4_prefix.as_u32 = ip4_prefix->as_u32;
+ d->ip4_prefix_len = ip4_prefix_len;
+ d->ip6_prefix = *ip6_prefix;
+ d->ip6_prefix_len = ip6_prefix_len;
+ d->ip6_src = *ip6_src;
+ d->ip6_src_len = ip6_src_len;
+ d->ea_bits_len = ea_bits_len;
+ d->psid_offset = psid_offset;
+ d->psid_length = psid_length;
+ d->mtu = mtu;
+ d->flags = flags;
+
+ /* How many, and which bits to grab from the IPv4 DA */
+ if (ip4_prefix_len + ea_bits_len < 32)
+ {
+ d->flags |= MAP_DOMAIN_PREFIX;
+ d->suffix_shift = 32 - ip4_prefix_len - ea_bits_len;
+ suffix_len = ea_bits_len;
+ }
+ else
+ {
+ d->suffix_shift = 0;
+ suffix_len = 32 - ip4_prefix_len;
+ }
+ d->suffix_mask = (1 << suffix_len) - 1;
+
+ d->psid_shift = 16 - psid_length - psid_offset;
+ d->psid_mask = (1 << d->psid_length) - 1;
+
+ if (ip6_prefix_len + suffix_len + d->psid_length > 64)
+ return NULL;
+
+ d->ea_shift = 64 - ip6_prefix_len - suffix_len - d->psid_length;
+
+ return d;
+}
+
+
+/*
+ * VPP-340:
+ * map_add_domain ip4-pfx 20.0.0.0/8 ip6-pfx 2001:db8::/40 ip6-src 2001:db8:ffff::/96 ea-bits-len 24 psid-offset 0 psid-len 0 map-t
+ * IPv4 src = 100.0.0.1
+ * IPv4 dst = 20.169.201.219
+ * UDP dest port = 1232
+ * IPv6 src = 2001:db8:ffff::6400:1
+ * IPv6 dst = a9c9:dfb8::14a9:c9db:0
+ * a9c9:dfb8::14a9:c9db:0 != 2001:db8:a9:c9db:0:14a9:c9db:0
+ */
+static void
+test_map_t_destaddr (void)
+{
+ ip4_address_t ip4_prefix;
+ ip6_address_t ip6_prefix;
+ ip6_address_t ip6_src;
+
+ ip4_prefix.as_u32 = clib_host_to_net_u32(0x14000000);
+ ip6_prefix.as_u64[0] = clib_host_to_net_u64(0x20010db800000000);
+ ip6_prefix.as_u64[1] = 0;
+ ip6_src.as_u64[0] = clib_host_to_net_u64(0x20010db8ffff0000);
+ map_domain_t * d = get_domain (&ip4_prefix, 8, &ip6_prefix, 40, &ip6_src, 96, 24, 0, 0, 0, MAP_DOMAIN_TRANSLATION);
+
+ ip6_address_t dst6;
+
+ dst6.as_u64[0] = map_get_pfx(d, 0x14a9c9db, 1232);
+ dst6.as_u64[1] = map_get_sfx(d, 0x14a9c9db, 1232);
+ assert(dst6.as_u64[0] == 0x20010db800a9c9db);
+ assert(dst6.as_u64[1] == 0x000014a9c9db0000);
+}
+
+/*
+ * VPP-228
+ * ip4-pfx 20.0.0.0/8
+ * ip6-pfx 2001:db8::/<n>
+ * ip6-src 2001:db8:ffff::1
+ * ea-bits-len 16 psid-offset 6 psid-len 8
+ * 20.169.201.219 port 1232
+ */
+static void
+test_map_eabits (void)
+{
+ ip4_address_t ip4_prefix;
+ ip6_address_t ip6_prefix;
+ ip6_address_t ip6_src;
+ ip6_address_t dst6;
+
+ ip4_prefix.as_u32 = clib_host_to_net_u32(0x14000000);
+ ip6_prefix.as_u64[0] = clib_host_to_net_u64(0x20010db800000000);
+ ip6_prefix.as_u64[1] = 0;
+ ip6_src.as_u64[0] = clib_host_to_net_u64(0x20010db8ffff0000);
+ ip6_src.as_u64[1] = clib_host_to_net_u64(0x0000000000000001);
+ map_domain_t * d = get_domain (&ip4_prefix, 16, &ip6_prefix, 48, &ip6_src,
+ 128, 16, 6, 8, 0, 0);
+ assert(!d);
+
+ //20.0.0.0/8 2001:db8::/32 4 2001:db8:a000::14a0:0:0
+ d = get_domain (&ip4_prefix, 8, &ip6_prefix, 32, &ip6_src,
+ 128, 4, 0, 0, 0, 0);
+ dst6.as_u64[0] = map_get_pfx(d, 0x14a9c9db, 1232);
+ dst6.as_u64[1] = map_get_sfx(d, 0x14a9c9db, 1232);
+ assert(dst6.as_u64[0] == 0x20010db8a0000000);
+ assert(dst6.as_u64[1] == 0x000014a000000000);
+
+ //20.0.0.0/8 2001:db8::/32 8 2001:db8:a900::14a9:0:0
+ d = get_domain (&ip4_prefix, 8, &ip6_prefix, 32, &ip6_src,
+ 128, 8, 0, 0, 0, 0);
+ dst6.as_u64[0] = map_get_pfx(d, 0x14a9c9db, 1232);
+ dst6.as_u64[1] = map_get_sfx(d, 0x14a9c9db, 1232);
+ assert(dst6.as_u64[0] == 0x20010db8a9000000);
+ assert(dst6.as_u64[1] == 0x000014a900000000);
+
+ //20.0.0.0/8 2001:db8::/32 10 2001:db8:a9c0::14a9:c000:0
+ d = get_domain (&ip4_prefix, 8, &ip6_prefix, 32, &ip6_src,
+ 128, 10, 0, 0, 0, 0);
+ dst6.as_u64[0] = map_get_pfx(d, 0x14a9c9db, 1232);
+ dst6.as_u64[1] = map_get_sfx(d, 0x14a9c9db, 1232);
+ assert(dst6.as_u64[0] == 0x20010db8a9c00000);
+ assert(dst6.as_u64[1] == 0x000014a9c0000000);
+
+ //20.0.0.0/8 2001:db8::/32 16 2001:db8:a9c9::14a9:c900:0
+ d = get_domain (&ip4_prefix, 8, &ip6_prefix, 32, &ip6_src,
+ 128, 16, 0, 0, 0, 0);
+ dst6.as_u64[0] = map_get_pfx(d, 0x14a9c9db, 1232);
+ dst6.as_u64[1] = map_get_sfx(d, 0x14a9c9db, 1232);
+ assert(dst6.as_u64[0] == 0x20010db8a9c90000);
+ assert(dst6.as_u64[1] == 0x000014a9c9000000);
+
+ //20.0.0.0/8 2001:db8::/32 20 2001:db8:a9c9:d000:0:14a9:c9d0:0
+ d = get_domain (&ip4_prefix, 8, &ip6_prefix, 32, &ip6_src,
+ 128, 20, 0, 0, 0, 0);
+ dst6.as_u64[0] = map_get_pfx(d, 0x14a9c9db, 1232);
+ dst6.as_u64[1] = map_get_sfx(d, 0x14a9c9db, 1232);
+ assert(dst6.as_u64[0] == 0x20010db8a9c9d000);
+ assert(dst6.as_u64[1] == 0x000014a9c9d00000);
+
+ //20.0.0.0/8 2001:db8::/32 23 2001:db8:a9c9:da00:0:14a9:c9da:0
+ d = get_domain (&ip4_prefix, 8, &ip6_prefix, 32, &ip6_src,
+ 128, 23, 0, 0, 0, 0);
+ dst6.as_u64[0] = map_get_pfx(d, 0x14a9c9db, 1232);
+ dst6.as_u64[1] = map_get_sfx(d, 0x14a9c9db, 1232);
+ assert(dst6.as_u64[0] == 0x20010db8a9c9da00);
+ assert(dst6.as_u64[1] == 0x000014a9c9da0000);
+
+ //20.169.201.0/24 2001:db8::/32 7 2001:db8:da00::14a9:c9da:0
+ d = get_domain (&ip4_prefix, 8, &ip6_prefix, 32, &ip6_src,
+ 128, 7, 0, 0, 0, 0);
+ dst6.as_u64[0] = map_get_pfx(d, 0x14a9c9db, 1232);
+ dst6.as_u64[1] = map_get_sfx(d, 0x14a9c9db, 1232);
+ assert(dst6.as_u64[0] == 0x20010db8a8000000);
+ assert(dst6.as_u64[1] == 0x000014a800000000);
+}
+
+#define foreach_test_case \
+ _(map_t_destaddr) \
+ _(map_eabits)
+
+static void
+run_tests (void)
+{
+#define _(_test_name) \
+ test_ ## _test_name ();
+
+ foreach_test_case
+#undef _
+}
+
+int main()
+{
+ run_tests ();
+ return 0;
+}