summaryrefslogtreecommitdiffstats
path: root/test/vpp_papi_provider.py
diff options
context:
space:
mode:
authorNeale Ranns <neale.ranns@cisco.com>2018-10-10 07:22:51 -0700
committerDamjan Marion <dmarion@me.com>2018-11-07 12:00:10 +0000
commit93cc3ee3b3a9c9224a1446625882205f3282a949 (patch)
tree077421ee51238c22181a3b3f4871b648bb1299d3 /test/vpp_papi_provider.py
parentc3df1e9a0ab79c1fe254394748ef441ffe224c43 (diff)
GBP Endpoint Learning
Learning GBP endpoints over vxlan-gbp tunnels Change-Id: I1db9fda5a16802d9ad8b4efd4e475614f3b21502 Signed-off-by: Neale Ranns <neale.ranns@cisco.com>
Diffstat (limited to 'test/vpp_papi_provider.py')
-rw-r--r--test/vpp_papi_provider.py166
1 files changed, 127 insertions, 39 deletions
diff --git a/test/vpp_papi_provider.py b/test/vpp_papi_provider.py
index c2192471437..1adcc1ba24b 100644
--- a/test/vpp_papi_provider.py
+++ b/test/vpp_papi_provider.py
@@ -18,6 +18,7 @@ except:
if do_import:
from vpp_papi import VPP
+ from vpp_l2 import L2_PORT_TYPE
# from vnet/vnet/mpls/mpls_types.h
MPLS_IETF_MAX_LABEL = 0xfffff
@@ -43,21 +44,6 @@ class QOS_SOURCE:
IP = 3
-class L2_PORT_TYPE:
- NORMAL = 0
- BVI = 1
- UU_FWD = 2
-
-
-class BRIDGE_FLAGS:
- NONE = 0
- LEARN = 1
- FWD = 2
- FLOOD = 4
- UU_FLOOD = 8
- ARP_TERM = 16
-
-
class UnexpectedApiReturnValueError(Exception):
""" exception raised when the API return value is unexpected """
pass
@@ -257,6 +243,17 @@ class VppPapiProvider(object):
{'sw_if_index': sw_if_index, 'is_ipv6': is_ipv6,
'vrf_id': table_id})
+ def sw_interface_get_table(self, sw_if_index, is_ipv6):
+ """ Get the IPvX Table-id for the Interface
+
+ :param sw_if_index:
+ :param is_ipv6:
+ :return table_id
+
+ """
+ return self.api(self.papi.sw_interface_get_table,
+ {'sw_if_index': sw_if_index, 'is_ipv6': is_ipv6})
+
def sw_interface_add_del_address(self, sw_if_index, addr, addr_len,
is_ipv6=0, is_add=1, del_all=0):
"""
@@ -277,6 +274,11 @@ class VppPapiProvider(object):
'address_length': addr_len,
'address': addr})
+ def ip_address_dump(self, sw_if_index, is_ipv6=0):
+ return self.api(self.papi.ip_address_dump,
+ {'sw_if_index': sw_if_index,
+ 'is_ipv6': is_ipv6})
+
def sw_interface_set_unnumbered(self, sw_if_index, ip_sw_if_index,
is_add=1):
""" Set the Interface to be unnumbered
@@ -477,10 +479,13 @@ class VppPapiProvider(object):
return self.api(self.papi.bd_ip_mac_add_del,
{'bd_id': bd_id,
'is_add': is_add,
- 'is_ipv6': is_ipv6,
'ip': ip,
'mac': mac})
+ def bd_ip_mac_dump(self, bd_id):
+ return self.api(self.papi.bd_ip_mac_dump,
+ {'bd_id': bd_id})
+
def want_ip4_arp_events(self, enable_disable=1, address=0):
return self.api(self.papi.want_ip4_arp_events,
{'enable_disable': enable_disable,
@@ -647,6 +652,11 @@ class VppPapiProvider(object):
"""
return self.api(self.papi.l2fib_flush_all, {})
+ def l2_fib_table_dump(self, bd_id):
+ """ Dump the L2 FIB """
+ return self.api(self.papi.l2_fib_table_dump,
+ {'bd_id': bd_id})
+
def sw_interface_set_l2_bridge(self, sw_if_index, bd_id,
shg=0, port_type=L2_PORT_TYPE.NORMAL,
enable=1):
@@ -2771,7 +2781,6 @@ class VppPapiProvider(object):
is_add=1,
is_ipv6=0,
encap_table_id=0,
- decap_next_index=0xFFFFFFFF,
vni=0,
instance=0xFFFFFFFF):
"""
@@ -2794,7 +2803,6 @@ class VppPapiProvider(object):
'dst': dst,
'mcast_sw_if_index': mcast_sw_if_index,
'encap_table_id': encap_table_id,
- 'decap_next_index': decap_next_index,
'vni': vni,
'instance': instance}})
@@ -3482,15 +3490,22 @@ class VppPapiProvider(object):
'enable_ip6': 1 if enable_ip6 else 0,
})
- def gbp_endpoint_add(self, sw_if_index, ips, mac, epg):
+ def gbp_endpoint_add(self, sw_if_index, ips, mac, epg, flags,
+ tun_src, tun_dst):
""" GBP endpoint Add """
return self.api(self.papi.gbp_endpoint_add,
{'endpoint': {
'sw_if_index': sw_if_index,
+ 'flags': 0,
'ips': ips,
'n_ips': len(ips),
'mac': mac,
- 'epg_id': epg}})
+ 'epg_id': epg,
+ 'flags': flags,
+ 'tun': {
+ 'src': tun_src,
+ 'dst': tun_dst,
+ }}})
def gbp_endpoint_del(self, handle):
""" GBP endpoint Del """
@@ -3501,24 +3516,73 @@ class VppPapiProvider(object):
""" GBP endpoint Dump """
return self.api(self.papi.gbp_endpoint_dump, {})
- def gbp_endpoint_group_add_del(self, is_add, epg, bd,
- ip4_rd,
- ip6_rd,
- uplink_sw_if_index):
- """ GBP endpoint group Add/Del """
- return self.api(self.papi.gbp_endpoint_group_add_del,
- {'is_add': is_add,
- 'epg': {
+ def gbp_endpoint_group_add(self, epg, bd,
+ rd, uplink_sw_if_index):
+ """ GBP endpoint group Add """
+ return self.api(self.papi.gbp_endpoint_group_add,
+ {'epg':
+ {
'uplink_sw_if_index': uplink_sw_if_index,
'bd_id': bd,
- 'ip4_table_id': ip4_rd,
- 'ip6_table_id': ip6_rd,
- 'epg_id': epg}})
+ 'rd_id': rd,
+ 'epg_id': epg
+ }})
+
+ def gbp_endpoint_group_del(self, epg):
+ """ GBP endpoint group Del """
+ return self.api(self.papi.gbp_endpoint_group_del,
+ {'epg_id': epg})
def gbp_endpoint_group_dump(self):
""" GBP endpoint group Dump """
return self.api(self.papi.gbp_endpoint_group_dump, {})
+ def gbp_bridge_domain_add(self, bd_id,
+ bvi_sw_if_index,
+ uu_fwd_sw_if_index):
+ """ GBP bridge-domain Add """
+ return self.api(self.papi.gbp_bridge_domain_add,
+ {'bd':
+ {
+ 'bvi_sw_if_index': bvi_sw_if_index,
+ 'uu_fwd_sw_if_index': uu_fwd_sw_if_index,
+ 'bd_id': bd_id
+ }})
+
+ def gbp_bridge_domain_del(self, bd_id):
+ """ GBP bridge-domain Del """
+ return self.api(self.papi.gbp_bridge_domain_del,
+ {'bd_id': bd_id})
+
+ def gbp_bridge_domain_dump(self):
+ """ GBP Bridge Domain Dump """
+ return self.api(self.papi.gbp_bridge_domain_dump, {})
+
+ def gbp_route_domain_add(self, rd_id,
+ ip4_table_id,
+ ip6_table_id,
+ ip4_uu_sw_if_index,
+ ip6_uu_sw_if_index):
+ """ GBP route-domain Add """
+ return self.api(self.papi.gbp_route_domain_add,
+ {'rd':
+ {
+ 'ip4_table_id': ip4_table_id,
+ 'ip6_table_id': ip6_table_id,
+ 'ip4_uu_sw_if_index': ip4_uu_sw_if_index,
+ 'ip6_uu_sw_if_index': ip6_uu_sw_if_index,
+ 'rd_id': rd_id
+ }})
+
+ def gbp_route_domain_del(self, rd_id):
+ """ GBP route-domain Del """
+ return self.api(self.papi.gbp_route_domain_del,
+ {'rd_id': rd_id})
+
+ def gbp_route_domain_dump(self):
+ """ GBP Route Domain Dump """
+ return self.api(self.papi.gbp_route_domain_dump, {})
+
def gbp_recirc_add_del(self, is_add, sw_if_index, epg, is_ext):
""" GBP recirc Add/Del """
return self.api(self.papi.gbp_recirc_add_del,
@@ -3532,22 +3596,19 @@ class VppPapiProvider(object):
""" GBP recirc Dump """
return self.api(self.papi.gbp_recirc_dump, {})
- def gbp_subnet_add_del(self, is_add, table_id,
- is_internal,
- prefix,
+ def gbp_subnet_add_del(self, is_add, rd_id,
+ prefix, type,
sw_if_index=0xffffffff,
- epg_id=0xffff,
- is_ip6=False):
+ epg_id=0xffff):
""" GBP Subnet Add/Del """
return self.api(self.papi.gbp_subnet_add_del,
{'is_add': is_add,
'subnet': {
- 'is_internal': is_internal,
- 'is_ip6': is_ip6,
+ 'type': type,
'sw_if_index': sw_if_index,
'epg_id': epg_id,
'prefix': prefix,
- 'table_id': table_id}})
+ 'rd_id': rd_id}})
def gbp_subnet_dump(self):
""" GBP Subnet Dump """
@@ -3566,6 +3627,33 @@ class VppPapiProvider(object):
""" GBP contract Dump """
return self.api(self.papi.gbp_contract_dump, {})
+ def gbp_endpoint_learn_set_inactive_threshold(self, threshold):
+ """ GBP set inactive threshold """
+ return self.api(self.papi.gbp_endpoint_learn_set_inactive_threshold,
+ {'threshold': threshold})
+
+ def gbp_vxlan_tunnel_add(self, vni, bd_rd_id, mode):
+ """ GBP VXLAN tunnel add """
+ return self.api(self.papi.gbp_vxlan_tunnel_add,
+ {
+ 'tunnel': {
+ 'vni': vni,
+ 'mode': mode,
+ 'bd_rd_id': bd_rd_id
+ }
+ })
+
+ def gbp_vxlan_tunnel_del(self, vni):
+ """ GBP VXLAN tunnel del """
+ return self.api(self.papi.gbp_vxlan_tunnel_del,
+ {
+ 'vni': vni,
+ })
+
+ def gbp_vxlan_tunnel_dump(self):
+ """ GBP VXLAN tunnel add/del """
+ return self.api(self.papi.gbp_vxlan_tunnel_dump, {})
+
def ipip_6rd_add_tunnel(self, ip6_table_id, ip6_prefix, ip6_prefix_len,
ip4_table_id, ip4_prefix, ip4_prefix_len, ip4_src,
security_check):
.kd { color: #66d9ef } /* Keyword.Declaration */ .highlight .kn { color: #f92672 } /* Keyword.Namespace */ .highlight .kp { color: #66d9ef } /* Keyword.Pseudo */ .highlight .kr { color: #66d9ef } /* Keyword.Reserved */ .highlight .kt { color: #66d9ef } /* Keyword.Type */ .highlight .ld { color: #e6db74 } /* Literal.Date */ .highlight .m { color: #ae81ff } /* Literal.Number */ .highlight .s { color: #e6db74 } /* Literal.String */ .highlight .na { color: #a6e22e } /* Name.Attribute */ .highlight .nb { color: #f8f8f2 } /* Name.Builtin */ .highlight .nc { color: #a6e22e } /* Name.Class */ .highlight .no { color: #66d9ef } /* Name.Constant */ .highlight .nd { color: #a6e22e } /* Name.Decorator */ .highlight .ni { color: #f8f8f2 } /* Name.Entity */ .highlight .ne { color: #a6e22e } /* Name.Exception */ .highlight .nf { color: #a6e22e } /* Name.Function */ .highlight .nl { color: #f8f8f2 } /* Name.Label */ .highlight .nn { color: #f8f8f2 } /* Name.Namespace */ .highlight .nx { color: #a6e22e } /* Name.Other */ .highlight .py { color: #f8f8f2 } /* Name.Property */ .highlight .nt { color: #f92672 } /* Name.Tag */ .highlight .nv { color: #f8f8f2 } /* Name.Variable */ .highlight .ow { color: #f92672 } /* Operator.Word */ .highlight .w { color: #f8f8f2 } /* Text.Whitespace */ .highlight .mb { color: #ae81ff } /* Literal.Number.Bin */ .highlight .mf { color: #ae81ff } /* Literal.Number.Float */ .highlight .mh { color: #ae81ff } /* Literal.Number.Hex */ .highlight .mi { color: #ae81ff } /* Literal.Number.Integer */ .highlight .mo { color: #ae81ff } /* Literal.Number.Oct */ .highlight .sa { color: #e6db74 } /* Literal.String.Affix */ .highlight .sb { color: #e6db74 } /* Literal.String.Backtick */ .highlight .sc { color: #e6db74 } /* Literal.String.Char */ .highlight .dl { color: #e6db74 } /* Literal.String.Delimiter */ .highlight .sd { color: #e6db74 } /* Literal.String.Doc */ .highlight .s2 { color: #e6db74 } /* Literal.String.Double */ .highlight .se { color: #ae81ff } /* Literal.String.Escape */ .highlight .sh { color: #e6db74 } /* Literal.String.Heredoc */ .highlight .si { color: #e6db74 } /* Literal.String.Interpol */ .highlight .sx { color: #e6db74 } /* Literal.String.Other */ .highlight .sr { color: #e6db74 } /* Literal.String.Regex */ .highlight .s1 { color: #e6db74 } /* Literal.String.Single */ .highlight .ss { color: #e6db74 } /* Literal.String.Symbol */ .highlight .bp { color: #f8f8f2 } /* Name.Builtin.Pseudo */ .highlight .fm { color: #a6e22e } /* Name.Function.Magic */ .highlight .vc { color: #f8f8f2 } /* Name.Variable.Class */ .highlight .vg { color: #f8f8f2 } /* Name.Variable.Global */ .highlight .vi { color: #f8f8f2 } /* Name.Variable.Instance */ .highlight .vm { color: #f8f8f2 } /* Name.Variable.Magic */ .highlight .il { color: #ae81ff } /* Literal.Number.Integer.Long */ } @media (prefers-color-scheme: light) { .highlight .hll { background-color: #ffffcc } .highlight .c { color: #888888 } /* Comment */ .highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */ .highlight .k { color: #008800; font-weight: bold } /* Keyword */ .highlight .ch { color: #888888 } /* Comment.Hashbang */ .highlight .cm { color: #888888 } /* Comment.Multiline */ .highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */ .highlight .cpf { color: #888888 } /* Comment.PreprocFile */ .highlight .c1 { color: #888888 } /* Comment.Single */ .highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */ .highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */ .highlight .ge { font-style: italic } /* Generic.Emph */ .highlight .gr { color: #aa0000 } /* Generic.Error */ .highlight .gh { color: #333333 } /* Generic.Heading */ .highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */ .highlight .go { color: #888888 } /* Generic.Output */ .highlight .gp { color: #555555 } /* Generic.Prompt */ .highlight .gs { font-weight: bold } /* Generic.Strong */ .highlight .gu { color: #666666 } /* Generic.Subheading */ .highlight .gt { color: #aa0000 } /* Generic.Traceback */ .highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */ .highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */ .highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */ .highlight .kp { color: #008800 } /* Keyword.Pseudo */ .highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */ .highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */ .highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */ .highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */ .highlight .na { color: #336699 } /* Name.Attribute */ .highlight .nb { color: #003388 } /* Name.Builtin */ .highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */ .highlight .no { color: #003366; font-weight: bold } /* Name.Constant */ .highlight .nd { color: #555555 } /* Name.Decorator */ .highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */ .highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */ .highlight .nl { color: #336699; font-style: italic } /* Name.Label */ .highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */ .highlight .py { color: #336699; font-weight: bold } /* Name.Property */ .highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */ .highlight .nv { color: #336699 } /* Name.Variable */ .highlight .ow { color: #008800 } /* Operator.Word */ .highlight .w { color: #bbbbbb } /* Text.Whitespace */ .highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */ .highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */ .highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */ .highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */ .highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */ .highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */ .highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */ .highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */ .highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */ .highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */ .highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */ .highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */ .highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */ .highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */ .highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */ .highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */ .highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */ .highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */ .highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */ .highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */ .highlight .vc { color: #336699 } /* Name.Variable.Class */ .highlight .vg { color: #dd7700 } /* Name.Variable.Global */ .highlight .vi { color: #3333bb } /* Name.Variable.Instance */ .highlight .vm { color: #336699 } /* Name.Variable.Magic */ .highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */ }
# 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.

export WS_ROOT=$(CURDIR)
export BR=$(WS_ROOT)/build-root
CCACHE_DIR?=$(BR)/.ccache
GDB?=gdb
PLATFORM?=vpp
SAMPLE_PLUGIN?=no
STARTUP_DIR?=$(PWD)
MACHINE=$(shell uname -m)
SUDO?=sudo
DPDK_CONFIG?=no-pci

,:=,
define disable_plugins
$(if $(1), \
  "plugins {" \
  $(patsubst %,"plugin %_plugin.so { disable }",$(subst $(,), ,$(1))) \
  " }" \
  ,)
endef

MINIMAL_STARTUP_CONF="							\
unix { 									\
	interactive 							\
	cli-listen /run/vpp/cli.sock					\
	gid $(shell id -g)						\
	$(if $(wildcard startup.vpp),"exec startup.vpp",)		\
}									\
$(if $(DPDK_CONFIG), "dpdk { $(DPDK_CONFIG) }",)			\
$(call disable_plugins,$(DISABLED_PLUGINS))				\
"

GDB_ARGS= -ex "handle SIGUSR1 noprint nostop"

#
# OS Detection
#
# We allow Darwin (MacOS) for docs generation; VPP build will still fail.
ifneq ($(shell uname),Darwin)
OS_ID        = $(shell grep '^ID=' /etc/os-release | cut -f2- -d= | sed -e 's/\"//g')
OS_VERSION_ID= $(shell grep '^VERSION_ID=' /etc/os-release | cut -f2- -d= | sed -e 's/\"//g')
endif

ifeq ($(filter ubuntu debian,$(OS_ID)),$(OS_ID))
PKG=deb
else ifeq ($(filter rhel centos fedora opensuse opensuse-leap opensuse-tumbleweed,$(OS_ID)),$(OS_ID))
PKG=rpm
endif

# +libganglia1-dev if building the gmond plugin

DEB_DEPENDS  = curl build-essential autoconf automake ccache
DEB_DEPENDS += debhelper dkms git libtool libapr1-dev dh-systemd
DEB_DEPENDS += libconfuse-dev git-review exuberant-ctags cscope pkg-config
DEB_DEPENDS += lcov chrpath autoconf indent clang-format libnuma-dev
DEB_DEPENDS += python-all python3-all python3-setuptools python-dev
DEB_DEPENDS += python-virtualenv python-pip libffi6 check
DEB_DEPENDS += libboost-all-dev libffi-dev python3-ply libmbedtls-dev
DEB_DEPENDS += cmake ninja-build uuid-dev python3-jsonschema
ifeq ($(OS_VERSION_ID),14.04)
	DEB_DEPENDS += libssl-dev
else ifeq ($(OS_ID)-$(OS_VERSION_ID),debian-8)
	DEB_DEPENDS += libssl-dev
	APT_ARGS = -t jessie-backports
else ifeq ($(OS_ID)-$(OS_VERSION_ID),debian-9)
	DEB_DEPENDS += libssl1.0-dev
else
	DEB_DEPENDS += libssl-dev
endif

RPM_DEPENDS  = redhat-lsb glibc-static
RPM_DEPENDS += apr-devel
RPM_DEPENDS += numactl-devel
RPM_DEPENDS += check check-devel
RPM_DEPENDS += boost boost-devel
RPM_DEPENDS += selinux-policy selinux-policy-devel
RPM_DEPENDS += ninja-build
RPM_DEPENDS += libuuid-devel
RPM_DEPENDS += mbedtls-devel

ifeq ($(OS_ID),fedora)
	RPM_DEPENDS += dnf-utils
	RPM_DEPENDS += subunit subunit-devel
	RPM_DEPENDS += compat-openssl10-devel
	RPM_DEPENDS += python3-devel python3-ply
	RPM_DEPENDS += python3-virtualenv python3-jsonschema
	RPM_DEPENDS += cmake
	RPM_DEPENDS_GROUPS = 'C Development Tools and Libraries'
else
	RPM_DEPENDS += yum-utils
	RPM_DEPENDS += openssl-devel
	RPM_DEPENDS += python-devel python36-ply
	RPM_DEPENDS += python3-devel python3-pip
	RPM_DEPENDS += python-virtualenv python36-jsonschema
	RPM_DEPENDS += devtoolset-7
	RPM_DEPENDS += cmake3
	RPM_DEPENDS_GROUPS = 'Development Tools'
endif

# +ganglia-devel if building the ganglia plugin

RPM_DEPENDS += chrpath libffi-devel rpm-build
# lowercase- replace spaces with dashes.
SUSE_NAME= $(shell grep '^NAME=' /etc/os-release | cut -f2- -d= | sed -e 's/\"//g' | sed -e 's/ /-/' | awk '{print tolower($$0)}')
SUSE_ID= $(shell grep '^VERSION_ID=' /etc/os-release | cut -f2- -d= | sed -e 's/\"//g' | cut -d' ' -f2)
RPM_SUSE_BUILDTOOLS_DEPS = autoconf automake ccache check-devel chrpath
RPM_SUSE_BUILDTOOLS_DEPS += clang cmake indent libtool make ninja python3-ply

RPM_SUSE_DEVEL_DEPS = glibc-devel-static libnuma-devel
RPM_SUSE_DEVEL_DEPS += libopenssl-devel openssl-devel mbedtls-devel libuuid-devel

RPM_SUSE_PYTHON_DEPS = python-devel python3-devel python-pip python3-pip
RPM_SUSE_PYTHON_DEPS += python-rpm-macros python3-rpm-macros

RPM_SUSE_PLATFORM_DEPS = distribution-release shadow rpm-build

ifeq ($(OS_ID),opensuse)
ifeq ($(SUSE_NAME),tumbleweed)
	RPM_SUSE_DEVEL_DEPS = libboost_headers1_68_0-devel-1.68.0  libboost_thread1_68_0-devel-1.68.0 gcc
	RPM_SUSE_PYTHON_DEPS += python3-ply python2-virtualenv
endif
ifeq ($(SUSE_ID),15.0)
	RPM_SUSE_DEVEL_DEPS += libboost_headers-devel libboost_thread-devel gcc
	RPM_SUSE_PYTHON_DEPS += python3-ply python2-virtualenv
else
	RPM_SUSE_DEVEL_DEPS += libboost_headers1_68_0-devel-1.68.0 gcc6
	RPM_SUSE_PYTHON_DEPS += python-virtualenv
endif
endif

ifeq ($(OS_ID),opensuse-leap)
ifeq ($(SUSE_ID),15.0)
	RPM_SUSE_DEVEL_DEPS += libboost_headers-devel libboost_thread-devel gcc git curl
	RPM_SUSE_PYTHON_DEPS += python3-ply python2-virtualenv
endif
endif

RPM_SUSE_DEPENDS += $(RPM_SUSE_BUILDTOOLS_DEPS) $(RPM_SUSE_DEVEL_DEPS) $(RPM_SUSE_PYTHON_DEPS) $(RPM_SUSE_PLATFORM_DEPS)

ifneq ($(wildcard $(STARTUP_DIR)/startup.conf),)
        STARTUP_CONF ?= $(STARTUP_DIR)/startup.conf
endif

ifeq ($(findstring y,$(UNATTENDED)),y)
CONFIRM=-y
FORCE=--force-yes
endif

TARGETS = vpp

ifneq ($(SAMPLE_PLUGIN),no)
TARGETS += sample-plugin
endif

.PHONY: help wipe wipe-release build build-release rebuild rebuild-release
.PHONY: run run-release debug debug-release build-vat run-vat pkg-deb pkg-rpm
.PHONY: ctags cscope
.PHONY: test test-debug retest retest-debug test-doc test-wipe-doc test-help test-wipe
.PHONY: test-cov test-wipe-cov

define banner
	@echo "========================================================================"
	@echo " $(1)"
	@echo "========================================================================"
	@echo " "
endef

help:
	@echo "Make Targets:"
	@echo " install-dep          - install software dependencies"
	@echo " wipe                 - wipe all products of debug build "
	@echo " wipe-release         - wipe all products of release build "
	@echo " build                - build debug binaries"
	@echo " build-release        - build release binaries"
	@echo " build-coverity       - build coverity artifacts"
	@echo " rebuild              - wipe and build debug binares"
	@echo " rebuild-release      - wipe and build release binares"
	@echo " run                  - run debug binary"
	@echo " run-release          - run release binary"
	@echo " debug                - run debug binary with debugger"
	@echo " debug-release        - run release binary with debugger"
	@echo " test                 - build and run (basic) functional tests"
	@echo " test-debug           - build and run (basic) functional tests (debug build)"
	@echo " test-all             - build and run functional and extended tests"
	@echo " test-all-debug       - build and run functional and extended tests (debug build)"
	@echo " test-gcov            - build and run functional tests (gcov build)"
	@echo " test-shell           - enter shell with test environment"
	@echo " test-shell-debug     - enter shell with test environment (debug build)"
	@echo " test-wipe            - wipe files generated by unit tests"
	@echo " retest               - run functional tests"
	@echo " retest-debug         - run functional tests (debug build)"
	@echo " test-help            - show help on test framework"
	@echo " run-vat              - run vpp-api-test tool"
	@echo " pkg-deb              - build DEB packages"
	@echo " pkg-deb-debug        - build DEB debug packages"
	@echo " vom-pkg-deb          - build vom DEB packages"
	@echo " vom-pkg-deb-debug    - build vom DEB debug packages"
	@echo " pkg-rpm              - build RPM packages"
	@echo " install-ext-deps     - install external development dependencies"
	@echo " ctags                - (re)generate ctags database"
	@echo " gtags                - (re)generate gtags database"
	@echo " cscope               - (re)generate cscope database"
	@echo " checkstyle           - check coding style"
	@echo " fixstyle             - fix coding style"
	@echo " doxygen              - (re)generate documentation"
	@echo " bootstrap-doxygen    - setup Doxygen dependencies"
	@echo " wipe-doxygen         - wipe all generated documentation"
	@echo " checkfeaturelist     - check FEATURE.yaml according to schema"
	@echo " featurelist          - dump feature list in markdown"
	@echo " json-api-files       - (re)-generate json api files"
	@echo " json-api-files-debug - (re)-generate json api files for debug target"
	@echo " docs                 - Build the Sphinx documentation"
	@echo " docs-venv            - Build the virtual environment for the Sphinx docs"
	@echo " docs-clean           - Remove the generated files from the Sphinx docs"
	@echo " test-doc             - generate documentation for test framework"
	@echo " test-wipe-doc        - wipe documentation for test framework"
	@echo " test-cov             - generate code coverage report for test framework"
	@echo " test-wipe-cov        - wipe code coverage report for test framework"
	@echo " test-checkstyle      - check PEP8 compliance for test framework"
	@echo " test-refresh-deps    - refresh the Python dependencies for the tests"
	@echo ""
	@echo "Make Arguments:"
	@echo " V=[0|1]                  - set build verbosity level"
	@echo " STARTUP_CONF=<path>      - startup configuration file"
	@echo "                            (e.g. /etc/vpp/startup.conf)"
	@echo " STARTUP_DIR=<path>       - startup drectory (e.g. /etc/vpp)"
	@echo "                            It also sets STARTUP_CONF if"
	@echo "                            startup.conf file is present"
	@echo " GDB=<path>               - gdb binary to use for debugging"
	@echo " PLATFORM=<name>          - target platform. default is vpp"
	@echo " TEST=<filter>            - apply filter to test set, see test-help"
	@echo " DPDK_CONFIG=<conf>       - add specified dpdk config commands to"
	@echo "                            autogenerated startup.conf"
	@echo "                            (e.g. \"no-pci\" )"
	@echo " SAMPLE_PLUGIN=yes        - in addition build/run/debug sample plugin"
	@echo " DISABLED_PLUGINS=<list>  - comma separated list of plugins which"
	@echo "                            should not be loaded"
	@echo ""
	@echo "Current Argument Values:"
	@echo " V                 = $(V)"
	@echo " STARTUP_CONF      = $(STARTUP_CONF)"
	@echo " STARTUP_DIR       = $(STARTUP_DIR)"
	@echo " GDB               = $(GDB)"
	@echo " PLATFORM          = $(PLATFORM)"
	@echo " DPDK_VERSION      = $(DPDK_VERSION)"
	@echo " DPDK_CONFIG       = $(DPDK_CONFIG)"
	@echo " SAMPLE_PLUGIN     = $(SAMPLE_PLUGIN)"
	@echo " DISABLED_PLUGINS  = $(DISABLED_PLUGINS)"

$(BR)/.deps.ok:
ifeq ($(findstring y,$(UNATTENDED)),y)
	make install-dep
endif
ifeq ($(filter ubuntu debian,$(OS_ID)),$(OS_ID))
	@MISSING=$$(apt-get install -y -qq -s $(DEB_DEPENDS) | grep "^Inst ") ; \
	if [ -n "$$MISSING" ] ; then \
	  echo "\nPlease install missing packages: \n$$MISSING\n" ; \
	  echo "by executing \"make install-dep\"\n" ; \
	  exit 1 ; \
	fi ; \
	exit 0
else ifneq ("$(wildcard /etc/redhat-release)","")
	@for i in $(RPM_DEPENDS) ; do \
	    RPM=$$(basename -s .rpm "$${i##*/}" | cut -d- -f1,2,3)  ;	\
	    MISSING+=$$(rpm -q $$RPM | grep "^package")	   ;    \
	done							   ;	\
	if [ -n "$$MISSING" ] ; then \
	  echo "Please install missing RPMs: \n$$MISSING\n" ; \
	  echo "by executing \"make install-dep\"\n" ; \
	  exit 1 ; \
	fi ; \
	exit 0
endif
	@touch $@

bootstrap:
	@echo "'make bootstrap' is not needed anymore"

install-dep:
ifeq ($(filter ubuntu debian,$(OS_ID)),$(OS_ID))
ifeq ($(OS_VERSION_ID),14.04)
	@sudo -E apt-get $(CONFIRM) $(FORCE) install software-properties-common
endif
ifeq ($(OS_ID)-$(OS_VERSION_ID),debian-8)
	@grep -q jessie-backports /etc/apt/sources.list /etc/apt/sources.list.d/* 2> /dev/null \
           || ( echo "Please install jessie-backports" ; exit 1 )
endif
	@sudo -E apt-get update
	@sudo -E apt-get $(APT_ARGS) $(CONFIRM) $(FORCE) install $(DEB_DEPENDS)
else ifneq ("$(wildcard /etc/redhat-release)","")
ifeq ($(OS_ID),rhel)
	@sudo -E yum-config-manager --enable rhel-server-rhscl-7-rpms
	@sudo -E yum groupinstall $(CONFIRM) $(RPM_DEPENDS_GROUPS)
	@sudo -E yum install $(CONFIRM) $(RPM_DEPENDS)
	@sudo -E debuginfo-install $(CONFIRM) glibc openssl-libs mbedtls-devel zlib
else ifeq ($(OS_ID),centos)
	@sudo -E yum install $(CONFIRM) centos-release-scl-rh epel-release
	@sudo -E yum groupinstall $(CONFIRM) $(RPM_DEPENDS_GROUPS)
	@sudo -E yum install $(CONFIRM) $(RPM_DEPENDS)
	@sudo -E debuginfo-install $(CONFIRM) glibc openssl-libs mbedtls-devel zlib
else ifeq ($(OS_ID),fedora)
	@sudo -E dnf groupinstall $(CONFIRM) $(RPM_DEPENDS_GROUPS)
	@sudo -E dnf install $(CONFIRM) $(RPM_DEPENDS)
	@sudo -E debuginfo-install $(CONFIRM) glibc openssl-libs mbedtls-devel zlib
endif
else ifeq ($(filter opensuse-tumbleweed,$(OS_ID)),$(OS_ID))
	@sudo -E zypper refresh
	@sudo -E zypper install -y $(RPM_SUSE_DEPENDS)
else ifeq ($(filter opensuse-leap,$(OS_ID)),$(OS_ID))
	@sudo -E zypper refresh
	@sudo -E zypper install  -y $(RPM_SUSE_DEPENDS)
else ifeq ($(filter opensuse,$(OS_ID)),$(OS_ID))
	@sudo -E zypper refresh
	@sudo -E zypper install -y $(RPM_SUSE_DEPENDS)
else
	$(error "This option currently works only on Ubuntu, Debian, RHEL, CentOS or openSUSE systems")
endif
	git config commit.template .git_commit_template.txt

define make
	@make -C $(BR) PLATFORM=$(PLATFORM) TAG=$(1) $(2)
endef

$(BR)/scripts/.version:
ifneq ("$(wildcard /etc/redhat-release)","")
	$(shell $(BR)/scripts/version rpm-string > $(BR)/scripts/.version)
else
	$(shell $(BR)/scripts/version > $(BR)/scripts/.version)
endif

DIST_FILE = $(BR)/vpp-$(shell src/scripts/version).tar
DIST_SUBDIR = vpp-$(shell src/scripts/version|cut -f1 -d-)

dist:
	@if git rev-parse 2> /dev/null ; then \
	    git archive \
	      --prefix=$(DIST_SUBDIR)/ \
	      --format=tar \
	      -o $(DIST_FILE) \
	    HEAD ; \
	    git describe > $(BR)/.version ; \
	else \
	    (cd .. ; tar -cf $(DIST_FILE) $(DIST_SUBDIR) --exclude=*.tar) ; \
	    src/scripts/version > $(BR)/.version ; \
	fi
	@tar --append \
	  --file $(DIST_FILE) \
	  --transform='s,.*/.version,$(DIST_SUBDIR)/src/scripts/.version,' \
	  $(BR)/.version
	@$(RM) $(BR)/.version $(DIST_FILE).xz
	@xz -v --threads=0 $(DIST_FILE)
	@$(RM) $(BR)/vpp-latest.tar.xz
	@ln -rs $(DIST_FILE).xz $(BR)/vpp-latest.tar.xz

build: $(BR)/.deps.ok
	$(call make,$(PLATFORM)_debug,$(addsuffix -install,$(TARGETS)))

wipedist:
	@$(RM) $(BR)/*.tar.xz

wipe: wipedist test-wipe $(BR)/.deps.ok
	$(call make,$(PLATFORM)_debug,$(addsuffix -wipe,$(TARGETS)))
	@find . -type f -name "*.api.json" ! -path "./test/*" -exec rm {} \;

rebuild: wipe build

build-release: $(BR)/.deps.ok
	$(call make,$(PLATFORM),$(addsuffix -install,$(TARGETS)))

wipe-release: test-wipe $(BR)/.deps.ok
	$(call make,$(PLATFORM),$(addsuffix -wipe,$(TARGETS)))

rebuild-release: wipe-release build-release

libexpand = $(subst $(subst ,, ),:,$(foreach lib,$(1),$(BR)/install-$(2)-native/vpp/$(lib)/$(3)))

export TEST_DIR ?= $(WS_ROOT)/test

define test
	$(if $(filter-out $(3),retest),make -C $(BR) PLATFORM=$(1) TAG=$(2) vpp-install,)
	$(eval libs:=lib lib64)
	make -C test \
	  VPP_BUILD_DIR=$(BR)/build-$(2)-native \
	  VPP_BIN=$(BR)/install-$(2)-native/vpp/bin/vpp \
	  VPP_PLUGIN_PATH=$(call libexpand,$(libs),$(2),vpp_plugins) \
	  VPP_TEST_PLUGIN_PATH=$(call libexpand,$(libs),$(2),vpp_api_test_plugins) \
	  VPP_INSTALL_PATH=$(BR)/install-$(2)-native/ \
	  LD_LIBRARY_PATH=$(call libexpand,$(libs),$(2),) \
	  EXTENDED_TESTS=$(EXTENDED_TESTS) \
	  PYTHON=$(PYTHON) \
	  OS_ID=$(OS_ID) \
	  CACHE_OUTPUT=$(CACHE_OUTPUT) \
	  $(3)
endef

test:
	$(call test,vpp,vpp,test)

test-debug:
	$(call test,vpp,vpp_debug,test)

test-gcov:
	$(call test,vpp,vpp_gcov,test)

test-all:
	$(if $(filter-out $(3),retest),make -C $(BR) PLATFORM=vpp TAG=vpp vom-install,)
	$(eval EXTENDED_TESTS=yes)
	$(call test,vpp,vpp,test)

test-all-debug:
	$(if $(filter-out $(3),retest),make -C $(BR) PLATFORM=vpp TAG=vpp_debug vom-install,)
	$(eval EXTENDED_TESTS=yes)
	$(call test,vpp,vpp_debug,test)

papi-wipe:
	@make -C test papi-wipe

test-help:
	@make -C test help

test-wipe:
	@make -C test wipe

test-shell:
	$(call test,vpp,vpp,shell)

test-shell-debug:
	$(call test,vpp,vpp_debug,shell)

test-shell-gcov:
	$(call test,vpp,vpp_gcov,shell)

test-dep:
	@make -C test test-dep

test-doc:
	@make -C test doc

test-wipe-doc:
	@make -C test wipe-doc

test-cov:
	@make -C $(BR) PLATFORM=vpp TAG=vpp_gcov vom-install
	$(eval EXTENDED_TESTS=yes)
	$(call test,vpp,vpp_gcov,cov)

test-wipe-cov:
	@make -C test wipe-cov

test-checkstyle:
	@make -C test checkstyle

test-refresh-deps:
	@make -C test refresh-deps

retest:
	$(call test,vpp,vpp,retest)

retest-debug:
	$(call test,vpp,vpp_debug,retest)

ifeq ("$(wildcard $(STARTUP_CONF))","")
define run
	@echo "WARNING: STARTUP_CONF not defined or file doesn't exist."
	@echo "         Running with minimal startup config: $(MINIMAL_STARTUP_CONF)\n"
	@cd $(STARTUP_DIR) && \
	  $(SUDO) $(2) $(1)/vpp/bin/vpp $(MINIMAL_STARTUP_CONF)
endef
else
define run
	@cd $(STARTUP_DIR) && \
	  $(SUDO) $(2) $(1)/vpp/bin/vpp $(shell cat $(STARTUP_CONF) | sed -e 's/#.*//')
endef
endif

%.files: .FORCE
	@find . \( -name '*\.[chyS]' -o -name '*\.java' -o -name '*\.lex' \) -and \
		\( -not -path './build-root*' -o -path \
		'./build-root/build-vpp_debug-native/dpdk*' \) > $@

.FORCE:

run:
	$(call run, $(BR)/install-$(PLATFORM)_debug-native)

run-release:
	$(call run, $(BR)/install-$(PLATFORM)-native)

debug:
	$(call run, $(BR)/install-$(PLATFORM)_debug-native,$(GDB) $(GDB_ARGS) --args)

build-coverity:
	$(call make,$(PLATFORM)_coverity,install-packages)

debug-release:
	$(call run, $(BR)/install-$(PLATFORM)-native,$(GDB) $(GDB_ARGS) --args)

build-vat:
	$(call make,$(PLATFORM)_debug,vpp-api-test-install)

run-vat:
	@$(SUDO) $(BR)/install-$(PLATFORM)_debug-native/vpp/bin/vpp_api_test

pkg-deb:
	$(call make,$(PLATFORM),vpp-package-deb)

vom-pkg-deb:
	$(call make,$(PLATFORM),vpp-package-deb)
	$(call make,$(PLATFORM),vom-package-deb)

pkg-deb-debug:
	$(call make,$(PLATFORM)_debug,vpp-package-deb)

vom-pkg-deb-debug:
	$(call make,$(PLATFORM)_debug,vpp-package-deb)
	$(call make,$(PLATFORM)_debug,vom-package-deb)

pkg-rpm: dist
	make -C extras/rpm

pkg-srpm: dist
	make -C extras/rpm srpm

dpdk-install-dev:
	$(call banner,"This command is deprecated. Please use 'make install-ext-deps'")
	make -C build/external install-$(PKG)

install-ext-deps:
	make -C build/external install-$(PKG)

json-api-files:
	$(WS_ROOT)/src/tools/vppapigen/generate_json.py

json-api-files-debug:
	$(WS_ROOT)/src/tools/vppapigen/generate_json.py --debug-target

ctags: ctags.files
	@ctags --totals --tag-relative -L $<
	@rm $<

gtags: ctags
	@gtags --gtagslabel=ctags

cscope: cscope.files
	@cscope -b -q -v

checkstyle:
	@build-root/scripts/checkstyle.sh

fixstyle:
	@build-root/scripts/checkstyle.sh --fix

featurelist:
	@build-root/scripts/fts.py --all --markdown

checkfeaturelist:
	@build-root/scripts/fts.py --validate --git-status

#
# Build the documentation
#

# Doxygen configuration and our utility scripts
export DOXY_DIR ?= $(WS_ROOT)/doxygen

define make-doxy
	@OS_ID="$(OS_ID)" make -C $(DOXY_DIR) $@
endef

.PHONY: bootstrap-doxygen doxygen wipe-doxygen

bootstrap-doxygen:
	$(call make-doxy)

doxygen:
	$(call make-doxy)

wipe-doxygen:
	$(call make-doxy)

# Sphinx Documents
export DOCS_DIR = $(WS_ROOT)/docs
export VENV_DIR = $(WS_ROOT)/sphinx_venv
export SPHINX_SCRIPTS_DIR = $(WS_ROOT)/docs/scripts

.PHONY: docs-venv docs docs-clean

docs-venv:
	@($(SPHINX_SCRIPTS_DIR)/sphinx-make.sh venv)

docs: $(DOCS_DIR)
	@($(SPHINX_SCRIPTS_DIR)/sphinx-make.sh html)

docs-clean:
	@($(SPHINX_SCRIPTS_DIR)/sphinx-make.sh clean)

pkg-verify: install-dep $(BR)/.deps.ok install-ext-deps
	$(call banner,"Building for PLATFORM=vpp using gcc")
	@make -C build-root PLATFORM=vpp TAG=vpp wipe-all install-packages
	$(call banner,"Building sample-plugin")
	@make -C build-root PLATFORM=vpp TAG=vpp sample-plugin-install
	$(call banner,"Building libmemif")
	@make -C build-root PLATFORM=vpp TAG=vpp libmemif-install
	$(call banner,"Building VOM")
	@make -C build-root PLATFORM=vpp TAG=vpp vom-install
	$(call banner,"Building $(PKG) packages")
	@make pkg-$(PKG)
ifeq ($(OS_ID),ubuntu)
	$(call banner,"Building VOM $(PKG) package")
	@make vom-pkg-deb
endif

verify: pkg-verify
ifeq ($(OS_ID)-$(OS_VERSION_ID),ubuntu-18.04)
	$(call banner,"Testing vppapigen")
	@src/tools/vppapigen/test_vppapigen.py
	$(call banner,"Running tests")
	@make COMPRESS_FAILED_TEST_LOGS=yes RETRIES=3 test
endif