Add map resolver failover test 57/2057/2
authorFilip Tehlar <ftehlar@cisco.com>
Fri, 22 Jul 2016 08:42:41 +0000 (10:42 +0200)
committerFilip Tehlar <ftehlar@cisco.com>
Fri, 22 Jul 2016 11:11:56 +0000 (13:11 +0200)
Change-Id: Ic4d5a553950e7d3dee36a818f4b06f69890b1719
Signed-off-by: Filip Tehlar <ftehlar@cisco.com>
tests/data_plane/configs/vpp_lite_config/basic/4o4_failover/vpp1.config [new file with mode: 0644]
tests/data_plane/configs/vpp_lite_config/basic/4o4_failover/vpp2.config [new file with mode: 0644]
tests/data_plane/vpp_lite_topo/scripts/dummy_mr.py [new file with mode: 0755]
tests/data_plane/vpp_lite_topo/test_driver/resolver_failover.sh [new file with mode: 0644]
tests/data_plane/vpp_lite_topo/tests/manual_test_resolver_failover.sh [new file with mode: 0755]
tests/data_plane/vpp_lite_topo/topologies/basic_two_odls.sh [new file with mode: 0644]

diff --git a/tests/data_plane/configs/vpp_lite_config/basic/4o4_failover/vpp1.config b/tests/data_plane/configs/vpp_lite_config/basic/4o4_failover/vpp1.config
new file mode 100644 (file)
index 0000000..72ac2ab
--- /dev/null
@@ -0,0 +1,15 @@
+create host-interface name vpp1
+set int state host-vpp1 up
+set int ip address host-vpp1 6.0.1.1/24
+
+create host-interface name intervpp1
+set int state host-intervpp1 up
+set int ip address host-intervpp1 6.0.3.1/24
+
+lisp enable
+
+lisp locator-set add ls1 iface host-intervpp1 p 1 w 1
+lisp eid-table add eid 6.0.1.0/24 locator-set ls1
+
+lisp map-resolver add 6.0.3.99
+lisp map-resolver add 6.0.3.100
diff --git a/tests/data_plane/configs/vpp_lite_config/basic/4o4_failover/vpp2.config b/tests/data_plane/configs/vpp_lite_config/basic/4o4_failover/vpp2.config
new file mode 100644 (file)
index 0000000..1bac043
--- /dev/null
@@ -0,0 +1,13 @@
+create host-interface name vpp2
+set int state host-vpp2 up
+set int ip address host-vpp2 6.0.2.1/24
+
+create host-interface name intervpp2
+set int state host-intervpp2 up
+set int ip address host-intervpp2 6.0.3.2/24
+
+lisp enable
+
+lisp locator-set add ls1 iface host-intervpp2 p 1 w 1
+lisp eid-table add eid 6.0.2.0/24 locator-set ls1
+lisp map-resolver add 6.0.3.100
diff --git a/tests/data_plane/vpp_lite_topo/scripts/dummy_mr.py b/tests/data_plane/vpp_lite_topo/scripts/dummy_mr.py
new file mode 100755 (executable)
index 0000000..4740586
--- /dev/null
@@ -0,0 +1,94 @@
+#/usr/bin/env python
+
+# Simple map resolver
+#
+# This script creates an UDP socket and starts listening on it.
+# When a map-request is received nonce is extracted from the request and
+# used in map-reply.
+#
+# Notes:
+# * works only with ipv4 in both under/over-lays.
+# * exact address matching is done while looking for a mapping
+#
+# Usage:
+#   ./dummy_mr <bind-ip> <port>
+#
+
+import sys
+import socket
+
+# mapping between EIDs and RLOCs
+mappings = {
+  b'\x06\x00\x02\x02' : (b'\x06\x00\x03\x02', ),
+  b'\x06\x00\x01\x02' : (b'\x06\x00\x03\x01', )
+}
+
+# LISP map-reply message
+reply_data = (b'\x20\x00\x00\x01'   # type, PES, reserved, record count
+             + '\x00\x00\x00\x00'   # nonce
+             + '\x00\x00\x00\x00'   # nonce
+             + '\x00\x00\x05\xa0'   # record TTL
+             + '\x01\x18\x10\x00'   # loc-count, EID-len, ACT
+             + '\x00\x00\x00\x01'   # rsvd, map-version, EID-AFI=ipv4
+             + '\x06\x00\x02\x00'   # EID prefix
+             + '\x01\x01\xff\x00'   # prio, weight, mprio, mweight
+             + '\x00\x05\x00\x01'   # unused, LpR, Loc-AFI
+             + '\x06\x00\x03\x02')  # locator
+
+request_nonce_offset = 36
+reply_nonce_offset = 4
+
+request_eid_offset = 60
+reply_eid_offset = 24
+
+reply_rloc_offset = 36
+
+
+def build_reply(nonce, deid):
+  if deid not in mappings:
+    raise Exception('No mapping found for eid {}!'.format(repr(deid)))
+  m = mappings[deid]
+
+  # prepare reply data
+  reply = bytearray(reply_data)
+
+  # update rloc field in reply message
+  rloc = bytearray(m[0])
+
+  for i in range(0, 4):
+    reply[reply_rloc_offset + i] = rloc[i]
+
+  # update eid prefix field
+  for i in range(0, 4):
+    reply[reply_eid_offset + i] = deid[i]
+
+  # update nonce
+  for i in range(0, 8):
+    reply[reply_nonce_offset + i] = nonce[i]
+
+  return reply
+
+
+def run(host, port):
+  sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+  server_address = (host, int(port))
+  sock.bind(server_address)
+
+  while True:
+    data, address = sock.recvfrom(4096)
+
+    # extract nonce from request
+    nonce = data[request_nonce_offset:request_nonce_offset+8]
+
+    # extract deid
+    deid = data[request_eid_offset:request_eid_offset+4]
+
+    rp = build_reply(nonce, deid)
+    sock.sendto(rp, address)
+
+
+if __name__ == "__main__":
+  if len(sys.argv) < 2:
+    raise Exception('IP and port expected')
+
+  run(sys.argv[1], sys.argv[2])
diff --git a/tests/data_plane/vpp_lite_topo/test_driver/resolver_failover.sh b/tests/data_plane/vpp_lite_topo/test_driver/resolver_failover.sh
new file mode 100644 (file)
index 0000000..3f07a7e
--- /dev/null
@@ -0,0 +1,56 @@
+source config.sh
+source odl_utils.sh
+source topologies/basic_two_odls.sh
+
+ODL_CONFIG_FILE1="vpp1.json"
+ODL_CONFIG_FILE2="vpp2.json"
+
+if [ "$1" == "clean" ] ; then
+  basic_two_odls_clean
+  exit 0
+fi
+
+if [[ $(id -u) != 0 ]]; then
+  echo "Error: run this as a root."
+  exit 1
+fi
+
+function start_map_resolver
+{
+  echo "starting dummy map resolver on interface $1"
+  python scripts/dummy_mr.py "$1" 4342 &
+  mr_id=$!
+}
+
+function test_resolver_failover
+{
+  basic_two_odls_setup
+
+  start_map_resolver "6.0.3.100"
+
+  test_result=1
+
+  if [ "$3" == "wait" ] ; then
+    read -p  "press any key to continue .." -n1
+  fi
+
+  ip netns exec vppns1 "${1}" -w 20 -c 1 "${2}"
+  rc=$?
+
+  # test done
+  if [ "$3" == "wait" ] ; then
+    read -p  "press any key to continue .." -n1
+  fi
+
+  basic_two_odls_clean
+  kill $mr_id
+
+  if [ $rc -ne 0 ] ; then
+    echo "Test failed: No ICMP response received within specified timeout limit!"
+  else
+    echo "Test passed."
+    test_result=0
+  fi
+
+  exit $test_result
+}
diff --git a/tests/data_plane/vpp_lite_topo/tests/manual_test_resolver_failover.sh b/tests/data_plane/vpp_lite_topo/tests/manual_test_resolver_failover.sh
new file mode 100755 (executable)
index 0000000..1e505b3
--- /dev/null
@@ -0,0 +1,14 @@
+#!/usr/bin/env bash
+
+# Test map resover failover scenario
+#
+# Current implementation selects first map resolver that is configured
+# and sends map requests towards it. If there is no response try next one.
+# This test verifies whether ITR is able to switch ultimately to a working one.
+
+VPP_LITE_CONF=`pwd`/../configs/vpp_lite_config/basic/4o4_failover
+ODL_CONFIG_DIR=`pwd`/../configs/odl/basic/4o4
+
+source test_driver/resolver_failover.sh
+
+test_resolver_failover ping "6.0.2.2"
diff --git a/tests/data_plane/vpp_lite_topo/topologies/basic_two_odls.sh b/tests/data_plane/vpp_lite_topo/topologies/basic_two_odls.sh
new file mode 100644 (file)
index 0000000..73c0a1d
--- /dev/null
@@ -0,0 +1,97 @@
+
+#!/usr/bin/env bash
+
+function basic_two_odls_clean
+{
+  echo "Clearing all VPP instances.."
+  pkill vpp --signal 9
+  rm /dev/shm/*
+
+  echo "Cleaning topology.."
+  ip netns exec intervppns ifconfig vppbr down
+  ip netns exec intervppns brctl delbr vppbr
+  ip link del dev veth_vpp1 &> /dev/null
+  ip link del dev veth_vpp2 &> /dev/null
+  ip link del dev veth_intervpp1 &> /dev/null
+  ip link del dev veth_intervpp2 &> /dev/null
+  ip link del dev veth_odl1 &> /dev/null
+  ip link del dev veth_odl2 &> /dev/null
+  ip netns del vppns1 &> /dev/null
+  ip netns del vppns2 &> /dev/null
+  ip netns del intervppns &> /dev/null
+}
+
+function basic_two_odls_setup
+{
+
+  # create vpp to clients and inter-vpp namespaces
+  ip netns add vppns1
+  ip netns add vppns2
+  ip netns add intervppns
+
+  # create vpp and odl interfaces and set them in intervppns
+  ip link add veth_intervpp1 type veth peer name intervpp1
+  ip link add veth_intervpp2 type veth peer name intervpp2
+  ip link add veth_odl1 type veth peer name odl1
+  ip link add veth_odl2 type veth peer name odl2
+  ip link set dev intervpp1 up
+  ip link set dev intervpp2 up
+  ip link set dev odl1 up
+  ip link set dev odl2 up
+  ip link set dev veth_intervpp1 up netns intervppns
+  ip link set dev veth_intervpp2 up netns intervppns
+  ip link set dev veth_odl1 up netns intervppns
+  ip link set dev veth_odl2 up netns intervppns
+
+  # create bridge in intervppns and add vpp and odl interfaces
+  ip netns exec intervppns brctl addbr vppbr
+  ip netns exec intervppns brctl addif vppbr veth_intervpp1
+  ip netns exec intervppns brctl addif vppbr veth_intervpp2
+  ip netns exec intervppns brctl addif vppbr veth_odl1
+  ip netns exec intervppns brctl addif vppbr veth_odl2
+  ip netns exec intervppns ifconfig vppbr up
+
+  # create and configure 1st veth client to vpp pair
+  ip link add veth_vpp1 type veth peer name vpp1
+  ip link set dev vpp1 up
+  ip link set dev veth_vpp1 up netns vppns1
+
+  # create and configure 2nd veth client to vpp pair
+  ip link add veth_vpp2 type veth peer name vpp2
+  ip link set dev vpp2 up
+  ip link set dev veth_vpp2 up netns vppns2
+
+  ip netns exec vppns1 \
+  bash -c "
+    ip link set dev lo up
+    ip addr add 6.0.1.2/24 dev veth_vpp1
+    ip route add 6.0.2.0/24 via 6.0.1.1
+  "
+
+  ip netns exec vppns2 \
+  bash -c "
+    ip link set dev lo up
+    ip addr add 6.0.2.2/24 dev veth_vpp2
+    ip route add 6.0.1.0/24 via 6.0.2.1
+  "
+
+  # set odl iface ip and disable checksum offloading
+  ip addr add 6.0.3.100/24 dev odl1
+  ethtool --offload  odl1 rx off tx off
+
+  #ip addr add 6.0.3.100/24 dev odl2
+  #ethtool --offload  odl2 rx off tx off
+
+  # start vpp1 and vpp2 in separate chroot
+  ${VPP_LITE_BIN}                                 \
+    unix { log /tmp/vpp1.log cli-listen           \
+           localhost:5002 full-coredump           \
+           exec ${VPP_LITE_CONF}/vpp1.config }    \
+           api-trace { on } api-segment {prefix xtr1}
+
+  ${VPP_LITE_BIN}                                 \
+    unix { log /tmp/vpp2.log cli-listen           \
+           localhost:5003 full-coredump           \
+           exec ${VPP_LITE_CONF}/vpp2.config }    \
+           api-trace { on } api-segment {prefix xtr2}
+}