aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYohanPipereau <ypiperea@cisco.com>2019-03-06 14:01:58 +0100
committerYohanPipereau <ypiperea@cisco.com>2019-03-29 14:39:36 +0100
commita760dfb253161911fc3aa3c8b879c461d53ade6e (patch)
tree0e79953f4ed5615879a58f49a74df3f9c6739a42
parent2b9b6b9b130b75799a40989c0ebe5040fa3e45fb (diff)
Sweetcomb global cleanup
-Merge IETF and Openconfig to use SCVPP 2 -Move L2 bridge from sc_vpp_interface to sc_vpp_v3po -Implement tav2 dump -Make openconfig-interfaces functions static -Try one more dispatch after failure in VAPI_CALL -Add error return code for scvpp -Remove unused length maccros -Return appropriate error code for interface dump when interface not found -Improve scvpp test suite -Change get_interface_id prototype -Use interface_dump_iface in openconfig_interface. -No more vapi types in openconfig_interfaces.c -Move openconfig_local_routing VAPI operations to sc_vpp_ip -Implement a multiple dump with a stack data structure -Comment out state_cb code from openconfig_local_routing to use new functions later. -Rename YANG model to their fully qualified name : <module>@<revision> -Remove headers almost empty and put registration declaration in sc_model.h -Shorten vapi context global variable name -Reorganize scvpp unit test suite -Add instructions to Makefile to install/uninstall YANG models in sysrepo. -Add this new instructions to README.md. -Reimplement interface_dump_all -Use a common message at INFO Log Level to know when sysrepo callbacks are triggered -Remove old structure to perform dump of all interfaces -Reimplement get_interface_name and add scvpp test for it -Clean sys_util -Use UNUSED maccro everywhere to have lighter prototypes -Have ietf-interfaces:interfaces-state work with new dump function -Add setup and teardown for NAT tests -Remove unused tapv2 dump -Remove useless sysrepo module callback -Remove xpath_find_first_key usage in openconfig-interfaces -Remove xpath_find_first_key in oc_local_routing and in the rest of sweetcomb -Reorganize scvpp include dir and fix scvpp_test new warnings -Fix scvpp tests for ip routes -Factorize scvpp nat and test return code of its function -Correct test_dump_if_all if there is an existing hardware interface -Implement a per-prefix dump in scvpp -free changes iterator in ietf-interfaces -Add new XPATH in oc local-routing -Introduce helper methods for sysrepo config callbacks -Factorize config callback -Refactor the openconfig-local-routing config callback -Use common foreach_change to iterate over changes in all models -Create a sample directory gathering example of configurations supposed to work with sweetcomb -Fix state callback of oc-local-routing -Add new sample for get operation on next-hop -foreach_elt maccro condition forgets to read one element Change-Id: I8e87fce577a00337977588f057a6e095a20f457c Signed-off-by: YohanPipereau <ypiperea@cisco.com>
-rw-r--r--Makefile27
-rw-r--r--README.md24
-rw-r--r--samples/ietf-interfaces/set-ip.xml18
-rw-r--r--samples/openconfig-interfaces/get-iface.xpath1
-rw-r--r--samples/openconfig-interfaces/get-subiface.xpath1
-rw-r--r--samples/openconfig-interfaces/set-enable.xml15
-rw-r--r--samples/openconfig-interfaces/set-ip.xml36
-rw-r--r--samples/openconfig-local-routing/add_route_with_iface.xml41
-rw-r--r--samples/openconfig-local-routing/add_route_with_nhop.xml20
-rw-r--r--samples/openconfig-local-routing/get-prefix-nhop-interface.xpath2
-rw-r--r--samples/openconfig-local-routing/get-prefix-nhop.xpath1
-rw-r--r--samples/openconfig-local-routing/get-prefix.xpath1
-rw-r--r--src/plugins/CMakeLists.txt1
-rw-r--r--src/plugins/ietf/ietf_interface.c194
-rw-r--r--src/plugins/ietf/ietf_interface.h25
-rw-r--r--src/plugins/ietf/ietf_nat.c54
-rw-r--r--src/plugins/ietf/ietf_nat.h25
-rw-r--r--src/plugins/openconfig/openconfig_interfaces.c759
-rw-r--r--src/plugins/openconfig/openconfig_interfaces.h26
-rw-r--r--src/plugins/openconfig/openconfig_local_routing.c888
-rw-r--r--src/plugins/openconfig/openconfig_local_routing.h25
-rw-r--r--src/plugins/sc_model.h16
-rw-r--r--src/plugins/sc_plugins.c5
-rw-r--r--src/plugins/sys_util.c170
-rw-r--r--src/plugins/sys_util.h163
-rw-r--r--src/plugins/yang/ietf-interfaces.data.xml21
-rw-r--r--src/plugins/yang/ietf/iana-if-type@2017-01-19.yang1619
-rw-r--r--src/plugins/yang/ietf/ietf-interfaces@2014-05-08.yang707
-rw-r--r--src/plugins/yang/ietf/ietf-interfaces@2018-02-20.yang (renamed from src/plugins/yang/ietf/ietf-interfaces.yang)0
-rw-r--r--src/plugins/yang/openconfig/openconfig-extensions@2017-04-11.yang (renamed from src/plugins/yang/openconfig/openconfig-extensions.yang)0
-rw-r--r--src/plugins/yang/openconfig/openconfig-if-aggregate@2018-03-23.yang (renamed from src/plugins/yang/openconfig/openconfig-if-aggregate.yang)0
-rw-r--r--src/plugins/yang/openconfig/openconfig-if-ethernet@2018-09-04.yang (renamed from src/plugins/yang/openconfig/openconfig-if-ethernet.yang)0
-rw-r--r--src/plugins/yang/openconfig/openconfig-if-ip@2018-01-05.yang (renamed from src/plugins/yang/openconfig/openconfig-if-ip.yang)0
-rw-r--r--src/plugins/yang/openconfig/openconfig-if-types@2018-01-05.yang (renamed from src/plugins/yang/openconfig/openconfig-if-types.yang)0
-rw-r--r--src/plugins/yang/openconfig/openconfig-inet-types@2017-08-24.yang (renamed from src/plugins/yang/openconfig/openconfig-inet-types.yang)0
-rw-r--r--src/plugins/yang/openconfig/openconfig-interfaces@2018-08-07.yang (renamed from src/plugins/yang/openconfig/openconfig-interfaces.yang)0
-rw-r--r--src/plugins/yang/openconfig/openconfig-local-routing@2017-05-15.yang (renamed from src/plugins/yang/openconfig/openconfig-local-routing.yang)0
-rw-r--r--src/plugins/yang/openconfig/openconfig-policy-types@2018-06-05.yang (renamed from src/plugins/yang/openconfig/openconfig-policy-types.yang)0
-rw-r--r--src/plugins/yang/openconfig/openconfig-types@2018-05-05.yang (renamed from src/plugins/yang/openconfig/openconfig-types.yang)0
-rw-r--r--src/plugins/yang/openconfig/openconfig-vlan-types@2018-02-14.yang (renamed from src/plugins/yang/openconfig/openconfig-vlan-types.yang)0
-rw-r--r--src/plugins/yang/openconfig/openconfig-vlan@2018-06-05.yang (renamed from src/plugins/yang/openconfig/openconfig-vlan.yang)0
-rw-r--r--src/plugins/yang/openconfig/openconfig-yang-types@2018-04-24.yang (renamed from src/plugins/yang/openconfig/openconfig-yang-types.yang)0
-rw-r--r--src/scvpp/CMakeLists.txt66
-rw-r--r--src/scvpp/inc/scvpp/comm.h (renamed from src/scvpp/src/sc_vpp_comm.h)107
-rw-r--r--src/scvpp/inc/scvpp/interface.h69
-rw-r--r--src/scvpp/inc/scvpp/ip.h77
-rw-r--r--src/scvpp/inc/scvpp/nat.h (renamed from src/scvpp/src/sc_vpp_nat.h)0
-rw-r--r--src/scvpp/inc/scvpp/v3po.h54
-rw-r--r--src/scvpp/src/CMakeLists.txt57
-rw-r--r--src/scvpp/src/comm.c (renamed from src/scvpp/src/sc_vpp_comm.c)22
-rw-r--r--src/scvpp/src/interface.c176
-rw-r--r--src/scvpp/src/ip.c (renamed from src/scvpp/src/sc_vpp_ip.c)185
-rw-r--r--src/scvpp/src/nat.c (renamed from src/scvpp/src/sc_vpp_nat.c)133
-rw-r--r--src/scvpp/src/sc_vpp_interface.c252
-rw-r--r--src/scvpp/src/sc_vpp_interface.h61
-rw-r--r--src/scvpp/src/sc_vpp_ip.h36
-rw-r--r--src/scvpp/src/sc_vpp_v3po.h26
-rw-r--r--src/scvpp/src/v3po.c (renamed from src/scvpp/src/sc_vpp_v3po.c)66
-rw-r--r--src/scvpp/tests/CMakeLists.txt37
-rw-r--r--src/scvpp/tests/scvpp_iface_test.c130
-rw-r--r--src/scvpp/tests/scvpp_ip_test.c184
-rw-r--r--src/scvpp/tests/scvpp_nat_test.c51
-rw-r--r--src/scvpp/tests/scvpp_test.c160
-rw-r--r--src/scvpp/tests/scvpp_test.h (renamed from src/scvpp/tests/scvpp_nat_test.h)17
64 files changed, 3811 insertions, 3040 deletions
diff --git a/Makefile b/Makefile
index 7933b38..f2ee6ee 100644
--- a/Makefile
+++ b/Makefile
@@ -69,6 +69,8 @@ help:
@echo " install-dep - install software dependencies"
@echo " install-dep-extra - install software extra dependencips from source code"
@echo " install-vpp - install released vpp"
+ @echo " install-models - install YANG models"
+ @echo " uninstall-models - uninstall YANG models"
@echo " install-dep-gnmi-extra - install software extra dependencips from source code for gNMI"
@echo " checkstyle - check coding style"
@echo " fixstyle - fix coding style"
@@ -247,10 +249,10 @@ fixstyle:
@build-root/scripts/checkstyle.sh --fix
build-scvpp:
- @mkdir -p $(BR)/build-scvpp/;cd $(BR)/build-scvpp;cmake -DCMAKE_INSTALL_PREFIX:PATH=/usr $(WS_ROOT)/src/scvpp/;make install;
+ @mkdir -p $(BR)/build-scvpp/;cd $(BR)/build-scvpp;cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX:PATH=/usr $(WS_ROOT)/src/scvpp/;make install;
build-plugins:
- @mkdir -p $(BR)/build-plugins/;cd $(BR)/build-plugins/;cmake -DCMAKE_INSTALL_PREFIX:PATH=/usr $(WS_ROOT)/src/plugins/;make install;
+ @mkdir -p $(BR)/build-plugins/;cd $(BR)/build-plugins/;cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX:PATH=/usr $(WS_ROOT)/src/plugins/;make install;
docker:
@build-root/scripts/docker.sh
@@ -270,6 +272,27 @@ build-package:
@mkdir -p $(BR)/build-scvpp/;cd $(BR)/build-scvpp;cmake -DCMAKE_INSTALL_PREFIX:PATH=/usr $(WS_ROOT)/src/scvpp/;make install;
@mkdir -p $(BR)/build-package/;cd $(BR)/build-package/;$(cmake) $(WS_ROOT)/src/;make package;rm -rf $(BR)/build-package/_CPack_Packages;
+install-models:
+ @cd src/plugins/yang/ietf \
+ && sysrepoctl --install --yang=ietf-ip@2014-06-16.yang \
+ && sysrepoctl --install --yang=ietf-nat@2017-11-16.yang \
+ && sysrepoctl --install --yang=iana-if-type@2017-01-19.yang \
+ && sysrepoctl -e if-mib -m ietf-interfaces;
+ @cd src/plugins/yang/openconfig \
+ && sysrepoctl -S --install --yang=openconfig-local-routing@2017-05-15.yang \
+ && sysrepoctl -S --install --yang=openconfig-interfaces@2018-08-07.yang \
+ && sysrepoctl -S --install --yang=openconfig-if-ip@2018-01-05.yang;
+
+uninstall-models:
+ @sysrepoctl -u -m openconfig-if-ip \
+ && sysrepoctl -u -m openconfig-if-aggregate \
+ && sysrepoctl -u -m openconfig-local-routing \
+ && sysrepoctl -u -m openconfig-interfaces \
+ && sysrepoctl -u -m openconfig-vlan-types \
+ && sysrepoctl -u -m ietf-ip \
+ && sysrepoctl -u -m ietf-nat \
+ && sysrepoctl -u -m iana-if-type;
+
clean:
@cd $(BR)/build-scvpp && make clean;
@cd $(BR)/build-plugins && make clean;
diff --git a/README.md b/README.md
index 96a10b9..83e6864 100644
--- a/README.md
+++ b/README.md
@@ -28,24 +28,32 @@ Details of the changes leading up to this version of Sweetcomb can be found unde
Make sure you have added FD.io repository using https://packagecloud.io/fdio/release/
installation script.
-You should have a sight on the release package, the package name may be defferent in
-rpm and deb on defferent version
-(such vpp-plugins.deb in 19.01 and vpp-plugin-core.deb and vpp-plugin-dpdk.deb in 19.04)
+You should have a sight on the release package, the package name may be different depending on the distribution.
+(ex: vpp-plugins.deb for VPP 19.01 and vpp-plugin-core.deb and vpp-plugin-dpdk.deb in 19.04)
Firstly, please follow below steps to install dependencies and build code:
+```
cd $/sweetcomb/
make install-dep
make install-dep-extra
make install-vpp
make build-scvpp
make build-plugins
+```
+
+Next, install YANG models in sysrepo:
+```
+ make install-models
+```
Then, please start each daemon one by one:
+```
start vpp (for example on Ubuntu: systemctl start vpp)
sysrepod
sysrepo-plugind
netopeer2-server
netopeer2-cli
+```
Now you can utilize Sweetcomb.
@@ -54,13 +62,16 @@ For example, if you want to configure ipv4 address on HW interface TenGigabitEth
You can follow below steps to verify if Sweetcomb is working well.
Firstly, set interface up:
- vppctl set interface state TenGigabitEthernet5/0/0 up
+`vppctl set interface state TenGigabitEthernet5/0/0 up`
Then, starting netopeer2-cli on any host:
netopeer2-cli
+```
> connect --host <ip address running Sweetcomb> --login <user>
> edit-config --target running --config
-## Press Enter and then past below XML example into the editor and quit
+```
+
+```
<interfaces xmlns="urn:ietf:params:xml:ns:yang:ietf-interfaces">
<interface>
<name>TenGigabitEthernet5/0/0</name>
@@ -77,8 +88,9 @@ Then, starting netopeer2-cli on any host:
<enabled>true</enabled>
</interface>
</interfaces>
+```
Finally, check the configuration result.
- vppctl show interface address
+ `vppctl show interface address`
If you configure above successfully, you will get ip address set up on interface TenGigabitEthernet5/0/0.
diff --git a/samples/ietf-interfaces/set-ip.xml b/samples/ietf-interfaces/set-ip.xml
new file mode 100644
index 0000000..2d8f1e2
--- /dev/null
+++ b/samples/ietf-interfaces/set-ip.xml
@@ -0,0 +1,18 @@
+<!-- XML for edit-config RPC to set an IP using ietf-interfaces -->
+<interfaces xmlns="urn:ietf:params:xml:ns:yang:ietf-interfaces">
+ <interface>
+ <name>local0</name>
+ <description>eth0</description>
+ <type xmlns:ianaift="urn:ietf:params:xml:ns:yang:iana-if-type">ianaift:ethernetCsmacd</type>
+ <ipv4 xmlns="urn:ietf:params:xml:ns:yang:ietf-ip">
+ <enabled>true</enabled>
+ <mtu>1514</mtu>
+ <address>
+ <ip>192.168.50.72</ip>
+ <prefix-length>24</prefix-length>
+ </address>
+ </ipv4>
+ <enabled>true</enabled>
+ </interface>
+</interfaces>
+
diff --git a/samples/openconfig-interfaces/get-iface.xpath b/samples/openconfig-interfaces/get-iface.xpath
new file mode 100644
index 0000000..bc829f6
--- /dev/null
+++ b/samples/openconfig-interfaces/get-iface.xpath
@@ -0,0 +1 @@
+get --filter-xpath /openconfig-interfaces:interfaces/interface[name="tap0"]/state
diff --git a/samples/openconfig-interfaces/get-subiface.xpath b/samples/openconfig-interfaces/get-subiface.xpath
new file mode 100644
index 0000000..e38de57
--- /dev/null
+++ b/samples/openconfig-interfaces/get-subiface.xpath
@@ -0,0 +1 @@
+get --filter-xpath /openconfig-interfaces:interfaces/interface[name="tap0"]/subinterfaces/*
diff --git a/samples/openconfig-interfaces/set-enable.xml b/samples/openconfig-interfaces/set-enable.xml
new file mode 100644
index 0000000..dc60769
--- /dev/null
+++ b/samples/openconfig-interfaces/set-enable.xml
@@ -0,0 +1,15 @@
+<!-- XML for edit-config RPC to change interface state using openconfig-interfaces -->
+<interfaces xmlns="http://openconfig.net/yang/interfaces">
+ <interface>
+ <name>GigabitEthernet0/9/0</name>
+ <config>
+ <name>GigabitEthernet0/9/0</name>
+ <type xmlns:ianaift="urn:ietf:params:xml:ns:yang:iana-if-type">ianaift:ethernetCsmacd</type>
+ <mtu>1501</mtu>
+ <loopback-mode>true</loopback-mode>
+ <description>openconfig</description>
+ <enabled>true</enabled>
+ </config>
+ </interface>
+</interfaces>
+
diff --git a/samples/openconfig-interfaces/set-ip.xml b/samples/openconfig-interfaces/set-ip.xml
new file mode 100644
index 0000000..80b368c
--- /dev/null
+++ b/samples/openconfig-interfaces/set-ip.xml
@@ -0,0 +1,36 @@
+<!-- XML for edit-config RPC to set an IP using openconfig-interfaces -->
+<interfaces xmlns="http://openconfig.net/yang/interfaces">
+ <interface>
+ <name>tap0</name>
+ <config>
+ <name>tap0</name>
+ <type xmlns:ianaift="urn:ietf:params:xml:ns:yang:iana-if-type">ianaift:ethernetCsmacd</type>
+ <mtu>1501</mtu>
+ <loopback-mode>true</loopback-mode>
+ <description>openconfig</description>
+ <enabled>true</enabled>
+ </config>
+ <subinterfaces>
+ <subinterface>
+ <index>0</index>
+ <ipv4 xmlns="http://openconfig.net/yang/interfaces/ip">
+ <addresses>
+ <address>
+ <ip>192.168.0.2</ip>
+ <config>
+ <ip>192.168.0.2</ip>
+ <prefix-length>24</prefix-length>
+ </config>
+ </address>
+ </addresses>
+ </ipv4>
+ <config>
+ <index>0</index>
+ <description>openconfig</description>
+ <enabled>true</enabled>
+ </config>
+ </subinterface>
+ </subinterfaces>
+ </interface>
+</interfaces>
+
diff --git a/samples/openconfig-local-routing/add_route_with_iface.xml b/samples/openconfig-local-routing/add_route_with_iface.xml
new file mode 100644
index 0000000..378a927
--- /dev/null
+++ b/samples/openconfig-local-routing/add_route_with_iface.xml
@@ -0,0 +1,41 @@
+<!-- XML for edit-config RPC to set first an interface and then create a route with this interface -->
+<interfaces xmlns="http://openconfig.net/yang/interfaces">
+ <interface>
+ <name>GigabitEthernet0/9/0</name>
+ <config>
+ <name>GigabitEthernet0/9/0</name>
+ <type xmlns:ianaift="urn:ietf:params:xml:ns:yang:iana-if-type">ianaift:ethernetCsmacd</type>
+ <mtu>1501</mtu>
+ <loopback-mode>true</loopback-mode>
+ <description>openconfig</description>
+ <enabled>true</enabled>
+ </config>
+ </interface>
+</interfaces>
+
+
+<!-- Might need to add the interface beforehand -->
+<local-routes xmlns="http://openconfig.net/yang/local-routing">
+ <static-routes>
+ <static>
+ <prefix>10.0.0.0/24</prefix>
+ <config>
+ <prefix>10.0.0.0/24</prefix>
+ </config>
+ <next-hops>
+ <next-hop>
+ <index>0</index>
+ <config>
+ <index>0</index>
+ <next-hop>10.0.0.1</next-hop>
+ </config>
+ <interface-ref>
+ <config>
+ <interface>GigabitEthernet0/9/0</interface>
+ </config>
+ </interface-ref>
+ </next-hop>
+ </next-hops>
+ </static>
+ </static-routes>
+</local-routes>
diff --git a/samples/openconfig-local-routing/add_route_with_nhop.xml b/samples/openconfig-local-routing/add_route_with_nhop.xml
new file mode 100644
index 0000000..8089c4d
--- /dev/null
+++ b/samples/openconfig-local-routing/add_route_with_nhop.xml
@@ -0,0 +1,20 @@
+<!-- XML for edit-config RPC to set a route with prefix and next-hop -->
+<local-routes xmlns="http://openconfig.net/yang/local-routing">
+ <static-routes>
+ <static>
+ <prefix>10.0.0.2/24</prefix>
+ <config>
+ <prefix>10.0.0.2/24</prefix>
+ </config>
+ <next-hops>
+ <next-hop>
+ <index>0</index>
+ <config>
+ <index>0</index>
+ <next-hop>10.0.0.1</next-hop>
+ </config>
+ </next-hop>
+ </next-hops>
+ </static>
+ </static-routes>
+</local-routes>
diff --git a/samples/openconfig-local-routing/get-prefix-nhop-interface.xpath b/samples/openconfig-local-routing/get-prefix-nhop-interface.xpath
new file mode 100644
index 0000000..68c96ca
--- /dev/null
+++ b/samples/openconfig-local-routing/get-prefix-nhop-interface.xpath
@@ -0,0 +1,2 @@
+get --filter-xpath /openconfig-local-routing:local-routes/static-routes/static[prefix="10.0.0.0/24"]/next-hops/next-hop[index="0"]/interface-ref/state
+
diff --git a/samples/openconfig-local-routing/get-prefix-nhop.xpath b/samples/openconfig-local-routing/get-prefix-nhop.xpath
new file mode 100644
index 0000000..4e161da
--- /dev/null
+++ b/samples/openconfig-local-routing/get-prefix-nhop.xpath
@@ -0,0 +1 @@
+get --filter-xpath /openconfig-local-routing:local-routes/static-routes/static[prefix="10.0.0.0/24"]/next-hops/next-hop[index="0"]/state
diff --git a/samples/openconfig-local-routing/get-prefix.xpath b/samples/openconfig-local-routing/get-prefix.xpath
new file mode 100644
index 0000000..936442b
--- /dev/null
+++ b/samples/openconfig-local-routing/get-prefix.xpath
@@ -0,0 +1 @@
+get --filter-xpath /openconfig-local-routing:local-routes/static-routes/static[prefix="10.0.0.0/24"]/state
diff --git a/src/plugins/CMakeLists.txt b/src/plugins/CMakeLists.txt
index d8dba04..d7f38e0 100644
--- a/src/plugins/CMakeLists.txt
+++ b/src/plugins/CMakeLists.txt
@@ -55,7 +55,6 @@ set(CMAKE_C_FLAGS_RELEASE "-Wall -Wextra -std=gnu99 -DNDEBUG -O2 ${RIGOROUS_C_FL
set(PLUGINS_SOURCES
sc_plugins.c
sc_model.c
- sys_util.c
ietf/ietf_interface.c
ietf/ietf_nat.c
openconfig/openconfig_interfaces.c
diff --git a/src/plugins/ietf/ietf_interface.c b/src/plugins/ietf/ietf_interface.c
index 922c84f..0f8c37e 100644
--- a/src/plugins/ietf/ietf_interface.c
+++ b/src/plugins/ietf/ietf_interface.c
@@ -15,33 +15,12 @@
#include <stdio.h>
#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include "ietf_interface.h"
+#include "../sc_model.h"
+#include "../sys_util.h"
-#include "sc_vpp_interface.h"
-#include "sc_vpp_ip.h"
-
-/**
- * @brief Helper function for converting netmask (ex: 255.255.255.0)
- * to prefix length (ex: 24).
- */
-static uint8_t
-netmask_to_prefix(const char *netmask)
-{
- in_addr_t n = 0;
- uint8_t i = 0;
-
- inet_pton(AF_INET, netmask, &n);
-
- while (n > 0) {
- n = n >> 1;
- i++;
- }
-
- return i;
-}
+#include <scvpp/interface.h>
+#include <scvpp/ip.h>
/**
* @brief Callback to be called by any config change of
@@ -51,6 +30,7 @@ static int
ietf_interface_enable_disable_cb(sr_session_ctx_t *session, const char *xpath,
sr_notif_event_t event, void *private_ctx)
{
+ UNUSED(private_ctx);
char *if_name = NULL;
sr_change_iter_t *iter = NULL;
sr_change_oper_t op = SR_OP_CREATED;
@@ -60,22 +40,22 @@ ietf_interface_enable_disable_cb(sr_session_ctx_t *session, const char *xpath,
int rc = SR_ERR_OK, op_rc = SR_ERR_OK;
SRP_LOG_INF("In %s", __FUNCTION__);
+
/* no-op for apply, we only care about SR_EV_ENABLED, SR_EV_VERIFY, SR_EV_ABORT */
- if (SR_EV_APPLY == event) {
+ if (SR_EV_APPLY == event)
return SR_ERR_OK;
- }
+
SRP_LOG_DBG("'%s' modified, event=%d", xpath, event);
/* get changes iterator */
rc = sr_get_changes_iter(session, xpath, &iter);
if (SR_ERR_OK != rc) {
+ sr_free_change_iter(iter);
SRP_LOG_ERR("Unable to retrieve change iterator: %s", sr_strerror(rc));
return rc;
}
- /* iterate over all changes */
- while ((SR_ERR_OK == op_rc || event == SR_EV_ABORT) &&
- (SR_ERR_OK == (rc = sr_get_change_next(session, iter, &op, &old_val, &new_val)))) {
+ foreach_change (session, iter, op, old_val, new_val) {
SRP_LOG_DBG("A change detected in '%s', op=%d", new_val ? new_val->xpath : old_val->xpath, op);
if_name = sr_xpath_key_value(new_val ? new_val->xpath : old_val->xpath, "interface", "name", &xpath_ctx);
@@ -102,23 +82,6 @@ ietf_interface_enable_disable_cb(sr_session_ctx_t *session, const char *xpath,
return op_rc;
}
-static int free_sw_interface_dump_ctx(dump_all_ctx * dctx)
-{
- if(dctx == NULL)
- return -1;
-
- if(dctx->intfcArray != NULL)
- {
- free(dctx->intfcArray);
- }
-
- dctx->intfcArray = NULL;
- dctx->capacity = 0;
- dctx->num_ifs = 0;
-
- return 0;
-}
-
/**
* @brief Modify existing IPv4/IPv6 config on an interface.
*/
@@ -169,7 +132,8 @@ interface_ipv46_config_modify(const char *if_name, sr_val_t *old_val,
}
/**
- * @brief Callback to be called by any config change in subtrees "/ietf-interfaces:interfaces/interface/ietf-ip:ipv4/address"
+ * @brief Callback to be called by any config change in subtrees
+ * "/ietf-interfaces:interfaces/interface/ietf-ip:ipv4/address"
* or "/ietf-interfaces:interfaces/interface/ietf-ip:ipv6/address".
*/
static int
@@ -178,6 +142,7 @@ ietf_interface_ipv46_address_change_cb(sr_session_ctx_t *session,
sr_notif_event_t event,
void *private_ctx)
{
+ UNUSED(private_ctx);
sr_change_iter_t *iter = NULL;
sr_change_oper_t op = SR_OP_CREATED;
sr_val_t *old_val = NULL;
@@ -207,13 +172,12 @@ ietf_interface_ipv46_address_change_cb(sr_session_ctx_t *session,
/* get changes iterator */
rc = sr_get_changes_iter(session, xpath, &iter);
if (SR_ERR_OK != rc) {
+ sr_free_change_iter(iter);
SRP_LOG_ERR("Unable to retrieve change iterator: %s", sr_strerror(rc));
return rc;
}
- /* iterate over all changes */
- while ((SR_ERR_OK == op_rc || event == SR_EV_ABORT) &&
- (SR_ERR_OK == (rc = sr_get_change_next(session, iter, &op, &old_val, &new_val)))) {
+ foreach_change(session, iter, op, old_val, new_val) {
SRP_LOG_DBG("A change detected in '%s', op=%d", new_val ? new_val->xpath : old_val->xpath, op);
if_name = strdup(sr_xpath_key_value(new_val ? new_val->xpath : old_val->xpath, "interface", "name", &xpath_ctx));
@@ -287,8 +251,9 @@ static int
ietf_interface_change_cb(sr_session_ctx_t *session, const char *xpath,
sr_notif_event_t event, void *private_ctx)
{
+ UNUSED(session); UNUSED(xpath); UNUSED(event); UNUSED(private_ctx);
+
SRP_LOG_INF("In %s", __FUNCTION__);
- SRP_LOG_DBG("'%s' modified, event=%d", xpath, event);
return SR_ERR_OK;
}
@@ -298,87 +263,80 @@ ietf_interface_change_cb(sr_session_ctx_t *session, const char *xpath,
*/
static int
ietf_interface_state_cb(const char *xpath, sr_val_t **values,
- size_t *values_cnt,
- __attribute__((unused)) uint64_t request_id,
- __attribute__((unused)) const char *original_xpath,
- __attribute__((unused)) void *private_ctx)
+ size_t *values_cnt, uint64_t request_id,
+ const char *original_xpath, void *private_ctx)
{
- sr_val_t *values_arr = NULL;
- int values_arr_size = 0, values_arr_cnt = 0;
- dump_all_ctx dctx;
- int nb_iface;
- vpp_interface_t* if_details;
- int rc = 0;
+ UNUSED(request_id); UNUSED(original_xpath); UNUSED(private_ctx);
+ struct elt* stack;
+ sw_interface_dump_t *dump;
+ sr_val_t *val = NULL;
+ int vc = 5; //number of answer per interfaces
+ int cnt = 0; //value counter
+ int rc = SR_ERR_OK;
SRP_LOG_INF("In %s", __FUNCTION__);
- if (! sr_xpath_node_name_eq(xpath, "interface")) {
- /* statistics, ipv4 and ipv6 state data not supported */
- *values = NULL;
- *values_cnt = 0;
- return SR_ERR_OK;
- }
+ if (!sr_xpath_node_name_eq(xpath, "interface"))
+ goto nothing_todo; //no interface field specified
/* dump interfaces */
- nb_iface = interface_dump_all(&dctx);
- if (nb_iface <= 0) {
- SRP_LOG_ERR_MSG("Error by processing of a interface dump request.");
- free_sw_interface_dump_ctx(&dctx);
- return SR_ERR_INTERNAL;
- }
+ stack = interface_dump_all();
+ if (!stack)
+ goto nothing_todo; //no element returned
/* allocate array of values to be returned */
- values_arr_size = nb_iface * 5;
- rc = sr_new_values(values_arr_size, &values_arr);
- if (0 != rc) {
- free_sw_interface_dump_ctx(&dctx);
- return rc;
- }
-
- int i = 0;
- for (; i < nb_iface; i++) {
- if_details = dctx.intfcArray+i;
-
- /* currently the only supported interface types are propVirtual / ethernetCsmacd */
- sr_val_build_xpath(&values_arr[values_arr_cnt], "%s[name='%s']/type", xpath, if_details->interface_name);
- sr_val_set_str_data(&values_arr[values_arr_cnt], SR_IDENTITYREF_T,
- strstr((char*)if_details->interface_name, "local0") ? "iana-if-type:propVirtual" : "iana-if-type:ethernetCsmacd");
- values_arr_cnt++;
-
- sr_val_build_xpath(&values_arr[values_arr_cnt], "%s[name='%s']/admin-status", xpath, if_details->interface_name);
- sr_val_set_str_data(&values_arr[values_arr_cnt], SR_ENUM_T, if_details->admin_up_down ? "up" : "down");
- values_arr_cnt++;
-
- sr_val_build_xpath(&values_arr[values_arr_cnt], "%s[name='%s']/oper-status", xpath, if_details->interface_name);
- sr_val_set_str_data(&values_arr[values_arr_cnt], SR_ENUM_T, if_details->link_up_down ? "up" : "down");
- values_arr_cnt++;
-
- if (if_details->l2_address_length > 0) {
- sr_val_build_xpath(&values_arr[values_arr_cnt], "%s[name='%s']/phys-address", xpath, if_details->interface_name);
- sr_val_build_str_data(&values_arr[values_arr_cnt], SR_STRING_T, "%02x:%02x:%02x:%02x:%02x:%02x",
- if_details->l2_address[0], if_details->l2_address[1], if_details->l2_address[2],
- if_details->l2_address[3], if_details->l2_address[4], if_details->l2_address[5]);
- values_arr_cnt++;
+ SRP_LOG_DBG("number of interfaces: %d", stack->id+1);
+ rc = sr_new_values((stack->id + 1)* vc, &val);
+ if (0 != rc)
+ goto nothing_todo;
+
+ foreach_stack_elt(stack) {
+ dump = (sw_interface_dump_t *) data;
+
+ SRP_LOG_DBG("State of interface %s", dump->interface_name);
+ //TODO need support for type propvirtual
+ sr_val_build_xpath(&val[cnt], "%s[name='%s']/type", xpath, dump->interface_name);
+ sr_val_set_str_data(&val[cnt], SR_IDENTITYREF_T, "iana-if-type:ethernetCsmacd");
+ cnt++;
+
+ //Be careful, it needs if-mib feature to work !
+ sr_val_build_xpath(&val[cnt], "%s[name='%s']/admin-status", xpath, dump->interface_name);
+ sr_val_set_str_data(&val[cnt], SR_ENUM_T, dump->link_up_down ? "up" : "down");
+ cnt++;
+
+ sr_val_build_xpath(&val[cnt], "%s[name='%s']/oper-status", xpath, dump->interface_name);
+ sr_val_set_str_data(&val[cnt], SR_ENUM_T, dump->link_up_down ? "up" : "down");
+ cnt++;
+
+ sr_val_build_xpath(&val[cnt], "%s[name='%s']/phys-address", xpath, dump->interface_name);
+ if (dump->l2_address_length > 0) {
+ sr_val_build_str_data(&val[cnt], SR_STRING_T,
+ "%02x:%02x:%02x:%02x:%02x:%02x",
+ dump->l2_address[0], dump->l2_address[1],
+ dump->l2_address[2], dump->l2_address[3],
+ dump->l2_address[4], dump->l2_address[5]);
} else {
- sr_val_build_xpath(&values_arr[values_arr_cnt], "%s[name='%s']/phys-address", xpath, if_details->interface_name);
- sr_val_build_str_data(&values_arr[values_arr_cnt], SR_STRING_T, "%02x:%02x:%02x:%02x:%02x:%02x", 0,0,0,0,0,0);
- values_arr_cnt++;
+ sr_val_build_str_data(&val[cnt], SR_STRING_T, "%02x:%02x:%02x:%02x:%02x:%02x", 0,0,0,0,0,0);
}
+ cnt++;
- sr_val_build_xpath(&values_arr[values_arr_cnt], "%s[name='%s']/speed", xpath, if_details->interface_name);
- values_arr[values_arr_cnt].type = SR_UINT64_T;
- values_arr[values_arr_cnt].data.uint64_val = if_details->link_speed;
- values_arr_cnt++;
- }
-
- SRP_LOG_DBG("Returning %zu state data elements for '%s'", values_arr, xpath);
+ sr_val_build_xpath(&val[cnt], "%s[name='%s']/speed", xpath, dump->interface_name);
+ val[cnt].type = SR_UINT64_T;
+ val[cnt].data.uint64_val = dump->link_speed;
+ cnt++;
- *values = values_arr;
- *values_cnt = values_arr_cnt;
+ free(dump);
+ }
- free_sw_interface_dump_ctx(&dctx);
+ *values = val;
+ *values_cnt = cnt;
return SR_ERR_OK;
+
+nothing_todo:
+ *values = NULL;
+ *values_cnt = 0;
+ return rc;
}
const xpath_t ietf_interfaces_xpaths[IETF_INTERFACES_SIZE] = {
diff --git a/src/plugins/ietf/ietf_interface.h b/src/plugins/ietf/ietf_interface.h
deleted file mode 100644
index 28a3783..0000000
--- a/src/plugins/ietf/ietf_interface.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (c) 2018 HUACHENTEL 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.
- */
-
-#ifndef __IETF_INTERFACE_H__
-#define __IETF_INTERFACE_H__
-
-#include "../sc_model.h"
-
-#define IETF_INTERFACES_SIZE 5
-extern const xpath_t ietf_interfaces_xpaths[IETF_INTERFACES_SIZE];
-
-#endif /* __IETF_INTERFACE_H__ */
-
diff --git a/src/plugins/ietf/ietf_nat.c b/src/plugins/ietf/ietf_nat.c
index 86c8570..9b2890e 100644
--- a/src/plugins/ietf/ietf_nat.c
+++ b/src/plugins/ietf/ietf_nat.c
@@ -14,10 +14,11 @@
* limitations under the License.
*/
-#include "ietf_nat.h"
-#include "sc_vpp_comm.h"
-#include "sc_vpp_interface.h"
-#include "sc_vpp_nat.h"
+#include <scvpp/comm.h>
+#include <scvpp/interface.h>
+#include <scvpp/nat.h>
+
+#include "../sc_model.h"
#include <assert.h>
#include <string.h>
@@ -30,17 +31,6 @@
#include "../sys_util.h"
-static int ietf_nat_mod_cb(
- __attribute__((unused)) sr_session_ctx_t *session,
- __attribute__((unused)) const char *module_name,
- __attribute__((unused)) sr_notif_event_t event,
- __attribute__((unused)) void *private_ctx)
-{
- SRP_LOG_INF("Module subscribe: %s", module_name);
-
- return SR_ERR_OK;
-}
-
/**
* @brief Wrapper struct for VAPI address range payload.
*/
@@ -103,8 +93,7 @@ static int parse_instance_policy_external_ip_address_pool(
if (sr_xpath_node_name_eq(val->xpath, "pool-id")) {
SRP_LOG_WRN("%s not supported.", val->xpath);
} else if(sr_xpath_node_name_eq(val->xpath, "external-ip-pool")) {
- rc = get_address_from_prefix(tmp_str, val->data.string_val,
- VPP_IP4_ADDRESS_STRING_LEN, &prefix);
+ rc = prefix2address(tmp_str, val->data.string_val, &prefix);
if (0 != rc) {
SRP_LOG_ERR_MSG("Error translate");
return SR_ERR_INVAL_ARG;
@@ -136,8 +125,9 @@ static int parse_instance_policy_external_ip_address_pool(
// XPATH: /ietf-nat:nat/instances/instance[id='%s']/policy[id='%s']/external-ip-address-pool[pool-id='%s']/
static int instances_instance_policy_external_ip_address_pool_cb(
sr_session_ctx_t *ds, const char *xpath, sr_notif_event_t event,
- __attribute__((unused)) void *private_ctx)
+ void *private_ctx)
{
+ UNUSED(private_ctx);
sr_error_t rc = SR_ERR_OK;
sr_change_iter_t *it = NULL;
sr_change_oper_t oper;
@@ -150,6 +140,8 @@ static int instances_instance_policy_external_ip_address_pool_cb(
ARG_CHECK2(SR_ERR_INVAL_ARG, ds, xpath);
+ SRP_LOG_INF("In %s", __FUNCTION__);
+
new_address_r.payload.vrf_id = ~0;
old_address_r.payload.vrf_id = ~0;
@@ -165,8 +157,7 @@ static int instances_instance_policy_external_ip_address_pool_cb(
return SR_ERR_OK;
}
- while (sr_get_change_next(ds, it, &oper,
- &old_val, &new_val) == SR_ERR_OK) {
+ foreach_change (ds, it, oper, old_val, new_val) {
SRP_LOG_DBG("A change detected in '%s', op=%d",
new_val ? new_val->xpath : old_val->xpath, oper);
@@ -345,8 +336,7 @@ static int parse_instance_mapping_table_mapping_entry(
return SR_ERR_INVAL_ARG;
}
- rc = get_address_from_prefix(tmp_str, val->data.string_val,
- VPP_IP4_PREFIX_STRING_LEN, NULL);
+ rc = prefix2address(tmp_str, val->data.string_val, NULL);
if (0 != rc) {
SRP_LOG_ERR_MSG("Error translate");
return SR_ERR_INVAL_ARG;
@@ -367,8 +357,7 @@ static int parse_instance_mapping_table_mapping_entry(
return SR_ERR_INVAL_ARG;
}
- rc = get_address_from_prefix(tmp_str, val->data.string_val,
- VPP_IP4_ADDRESS_STRING_LEN, NULL);
+ rc = prefix2address(tmp_str, val->data.string_val, NULL);
if (0 != rc) {
SRP_LOG_ERR_MSG("Error translate");
return SR_ERR_INVAL_ARG;
@@ -402,8 +391,9 @@ static int parse_instance_mapping_table_mapping_entry(
// XPATH: /ietf-nat:nat/instances/instance[id='%s']/mapping-table/mapping-entry[index='%s']/
static int instances_instance_mapping_table_mapping_entry_cb(
sr_session_ctx_t *ds, const char *xpath, sr_notif_event_t event,
- __attribute__((unused)) void *private_ctx)
+ void *private_ctx)
{
+ UNUSED(private_ctx);
sr_error_t rc = SR_ERR_OK;
sr_change_iter_t *it = NULL;
sr_change_oper_t oper;
@@ -416,6 +406,8 @@ static int instances_instance_mapping_table_mapping_entry_cb(
ARG_CHECK2(SR_ERR_INVAL_ARG, ds, xpath);
+ SRP_LOG_INF("In %s", __FUNCTION__);
+
new_mapping.mtype = UNKNOWN;
old_mapping.mtype = UNKNOWN;
@@ -431,8 +423,7 @@ static int instances_instance_mapping_table_mapping_entry_cb(
return SR_ERR_OK;
}
- while (sr_get_change_next(ds, it, &oper,
- &old_val, &new_val) == SR_ERR_OK) {
+ foreach_change (ds, it, oper, old_val, new_val) {
SRP_LOG_DBG("A change detected in '%s', op=%d",
new_val ? new_val->xpath : old_val->xpath, oper);
@@ -503,15 +494,6 @@ error:
const xpath_t ietf_nat_xpaths[IETF_NAT_SIZE] = {
{
- .xpath = "ietf-nat",
- .method = MODULE,
- .datastore = SR_DS_RUNNING,
- .cb.mcb = ietf_nat_mod_cb,
- .private_ctx = NULL,
- .priority = 0,
- .opts = SR_SUBSCR_EV_ENABLED | SR_SUBSCR_APPLY_ONLY | SR_SUBSCR_CTX_REUSE
- },
- {
.xpath = "/ietf-nat:nat/instances/instance/policy/external-ip-address-pool",
.method = XPATH,
.datastore = SR_DS_RUNNING,
diff --git a/src/plugins/ietf/ietf_nat.h b/src/plugins/ietf/ietf_nat.h
deleted file mode 100644
index 7495209..0000000
--- a/src/plugins/ietf/ietf_nat.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (c) 2019 PANTHEON.tech.
- *
- * 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.
- */
-
-#ifndef __IETF_NAT_H__
-#define __IETF_NAT_H__
-
-#include "../sc_model.h"
-
-#define IETF_NAT_SIZE 3
-extern const xpath_t ietf_nat_xpaths[IETF_NAT_SIZE];
-
-#endif
diff --git a/src/plugins/openconfig/openconfig_interfaces.c b/src/plugins/openconfig/openconfig_interfaces.c
index c72ad7f..7242c2b 100644
--- a/src/plugins/openconfig/openconfig_interfaces.c
+++ b/src/plugins/openconfig/openconfig_interfaces.c
@@ -17,119 +17,72 @@
#include <assert.h>
#include <string.h>
-#include "openconfig_interfaces.h"
-#include "../sys_util.h"
-
-#include "sc_vpp_comm.h"
-#include "sc_vpp_interface.h"
-#include "sc_vpp_ip.h"
+#include <scvpp/comm.h>
+#include <scvpp/interface.h>
+#include <scvpp/ip.h>
-#define XPATH_SIZE 2000
+#include "../sc_model.h"
+#include "../sys_util.h"
// XPATH: /openconfig-interfaces:interfaces/interface[name='%s']/config/
-int openconfig_interfaces_interfaces_interface_config_cb(
+static int openconfig_interfaces_interfaces_interface_config_cb(
sr_session_ctx_t *ds, const char *xpath, sr_notif_event_t event,
- __attribute__((unused)) void *private_ctx)
+ void *private_ctx)
{
+ UNUSED(private_ctx);
sr_change_iter_t *it = NULL;
sr_change_oper_t oper;
- sr_val_t *old_val = NULL;
- sr_val_t *new_val = NULL;
+ sr_xpath_ctx_t state = {0};
+ sr_val_t *old = NULL;
+ sr_val_t *new = NULL;
char *tmp = NULL;
char interface_name[XPATH_SIZE] = {0};
int rc = 0;
- SRP_LOG_INF_MSG("In openconfig_interfaces_interfaces_interface_config_cb");
+ SRP_LOG_INF("In %s", __FUNCTION__);
+ SRP_LOG_INF("XPATH %s", xpath);
ARG_CHECK2(SR_ERR_INVAL_ARG, ds, xpath);
- // if we receive event SR_EV_APPLY - config has changed
-
- log_recv_event(event, "subtree_change_cb received");
- SRP_LOG_DBG("[SRP_LOG_DBG] xpath: %s", xpath);
-
- // apply configuration
- //
- //
- // in this type i guess we can call sr_get_item()
- // because we are subscribed to leaf we shouldn't
- // get more than one change in one callback
- // each chage represent change in a hierarchy of
- // xml document
- //
- if (event != SR_EV_APPLY) {
+ if (event == SR_EV_APPLY)
return SR_ERR_OK;
- }
-
- // first we get event VERIFY
- // then we get event APPLY
- // - we can return error from VERIFY event
- // - we can't return error from APPLY event
if (sr_get_changes_iter(ds, (char *)xpath, &it) != SR_ERR_OK) {
- // in example he calls even on fale
sr_free_change_iter(it);
return SR_ERR_OK;
}
- while (sr_get_change_next(ds, it, &oper,
- &old_val, &new_val) == SR_ERR_OK) {
+ foreach_change (ds, it, oper, old, new) {
- log_recv_oper(oper, "subtree_change_cb received");
+ SRP_LOG_DBG("xpath: %s", new->xpath);
- SRP_LOG_DBG("xpath: %s", new_val->xpath);
-
- sr_xpath_ctx_t state = {0};
-
- tmp = xpath_find_first_key(new_val->xpath, "name", &state);
- if (NULL == tmp) {
- SRP_LOG_DBG_MSG("interface_name NOT found.");
- continue;
+ tmp = sr_xpath_key_value(new->xpath, "interface", "name", &state);
+ if (!tmp) {
+ sr_set_error(ds, "XPATH interface name NOT found", new->xpath);
+ return SR_ERR_INVAL_ARG;
}
-
strncpy(interface_name, tmp, XPATH_SIZE);
sr_xpath_recover(&state);
switch (oper) {
case SR_OP_CREATED:
- if (sr_xpath_node_name_eq(new_val->xpath, "name")) {
- //TODO: LEAF: name, type: string
- } else if(sr_xpath_node_name_eq(new_val->xpath, "type")) {
- //TODO: LEAF: type, type: identityref
- } else if(sr_xpath_node_name_eq(new_val->xpath, "mtu")) {
- //TODO: LEAF: mtu, type: uint16
- } else if(sr_xpath_node_name_eq(new_val->xpath,
- "loopback-mode")) {
- //TODO: LEAF: loopback-mode, type: boolean
- } else if(sr_xpath_node_name_eq(new_val->xpath,
- "description")) {
- //TODO: LEAF: description, type: string
- } else if(sr_xpath_node_name_eq(new_val->xpath, "enabled")) {
- rc = interface_enable(interface_name,
- new_val->data.bool_val);
- } else if(sr_xpath_node_name_eq(new_val->xpath,
- "oc-vlan:tpid")) {
- //TODO: LEAF: oc-vlan:tpid, type: identityref
- }
- break;
-
case SR_OP_MODIFIED:
- if (sr_xpath_node_name_eq(new_val->xpath, "name")) {
+ if (sr_xpath_node_name_eq(new->xpath, "name")) {
//TODO: LEAF: name, type: string
- } else if(sr_xpath_node_name_eq(new_val->xpath, "type")) {
+ } else if(sr_xpath_node_name_eq(new->xpath, "type")) {
//TODO: LEAF: type, type: identityref
- } else if(sr_xpath_node_name_eq(new_val->xpath, "mtu")) {
+ } else if(sr_xpath_node_name_eq(new->xpath, "mtu")) {
//TODO: LEAF: mtu, type: uint16
- } else if(sr_xpath_node_name_eq(new_val->xpath,
+ } else if(sr_xpath_node_name_eq(new->xpath,
"loopback-mode")) {
//TODO: LEAF: loopback-mode, type: boolean
- } else if(sr_xpath_node_name_eq(new_val->xpath,
+ } else if(sr_xpath_node_name_eq(new->xpath,
"description")) {
//TODO: LEAF: description, type: string
- } else if(sr_xpath_node_name_eq(new_val->xpath, "enabled")) {
+ } else if(sr_xpath_node_name_eq(new->xpath, "enabled")) {
rc = interface_enable(interface_name,
- new_val->data.bool_val);
- } else if(sr_xpath_node_name_eq(new_val->xpath,
+ new->data.bool_val);
+ } else if(sr_xpath_node_name_eq(new->xpath,
"oc-vlan:tpid")) {
//TODO: LEAF: oc-vlan:tpid, type: identityref
}
@@ -139,21 +92,21 @@ int openconfig_interfaces_interfaces_interface_config_cb(
break;
case SR_OP_DELETED:
- if (sr_xpath_node_name_eq(old_val->xpath, "name")) {
+ if (sr_xpath_node_name_eq(old->xpath, "name")) {
//TODO: LEAF: name, type: string
- } else if(sr_xpath_node_name_eq(old_val->xpath, "type")) {
+ } else if(sr_xpath_node_name_eq(old->xpath, "type")) {
//TODO: LEAF: type, type: identityref
- } else if(sr_xpath_node_name_eq(old_val->xpath, "mtu")) {
+ } else if(sr_xpath_node_name_eq(old->xpath, "mtu")) {
//TODO: LEAF: mtu, type: uint16
- } else if(sr_xpath_node_name_eq(old_val->xpath,
+ } else if(sr_xpath_node_name_eq(old->xpath,
"loopback-mode")) {
//TODO: LEAF: loopback-mode, type: boolean
- } else if(sr_xpath_node_name_eq(old_val->xpath,
+ } else if(sr_xpath_node_name_eq(old->xpath,
"description")) {
//TODO: LEAF: description, type: string
- } else if(sr_xpath_node_name_eq(old_val->xpath, "enabled")) {
+ } else if(sr_xpath_node_name_eq(old->xpath, "enabled")) {
rc = interface_enable(interface_name, false);
- } else if(sr_xpath_node_name_eq(old_val->xpath,
+ } else if(sr_xpath_node_name_eq(old->xpath,
"oc-vlan:tpid")) {
//TODO: LEAF: oc-vlan:tpid, type: identityref
}
@@ -163,8 +116,8 @@ int openconfig_interfaces_interfaces_interface_config_cb(
if (0 != rc) {
sr_xpath_recover(&state);
- sr_free_val(old_val);
- sr_free_val(new_val);
+ sr_free_val(old);
+ sr_free_val(new);
sr_free_change_iter(it);
@@ -173,175 +126,190 @@ int openconfig_interfaces_interfaces_interface_config_cb(
sr_xpath_recover(&state);
- sr_free_val(old_val);
- sr_free_val(new_val);
+ sr_free_val(old);
+ sr_free_val(new);
}
sr_free_change_iter(it);
return SR_ERR_OK;
}
-// openconfig-interfaces
-int openconfig_interface_mod_cb(
- __attribute__((unused)) sr_session_ctx_t *session,
- __attribute__((unused)) const char *module_name,
- __attribute__((unused)) sr_notif_event_t event,
- __attribute__((unused)) void *private_ctx)
-{
- SRP_LOG_INF_MSG("In openconfig_interface_mod_cb");
-
- return SR_ERR_OK;
-}
-
-typedef struct
+//XPATH : /openconfig-interfaces:interfaces/interface/state
+static int
+openconfig_interfaces_interfaces_interface_state_cb(
+ const char *xpath, sr_val_t **values,
+ size_t *values_cnt, uint64_t request_id, const char *original_xpath,
+ void *private_ctx)
{
- bool is_subif;
- u32 subinterface_index;
- sw_interface_details_query_t sw_interface_details_query;
- sysr_values_ctx_t sysr_values_ctx;
-} sys_sw_interface_dump_ctx;
+ UNUSED(request_id); UNUSED(original_xpath); UNUSED(private_ctx);
+ sw_interface_dump_t reply = {0};
+ sr_val_t *vals = NULL;
+ sr_xpath_ctx_t state = {0};
+ char interface_name[VPP_INTFC_NAME_LEN] = {0};
+ char xpath_root[XPATH_SIZE];
+ int vc = 10;
+ char *tmp;
+ int rc;
-#define NOT_AVAL "NA"
+ SRP_LOG_INF("In %s", __FUNCTION__);
+ ARG_CHECK3(SR_ERR_INVAL_ARG, xpath, values, values_cnt);
-static int sw_interface_dump_cb_inner(
- vapi_payload_sw_interface_details * reply,
- sys_sw_interface_dump_ctx * dctx)
-{
- sr_val_t *vals = NULL;
- int rc = 0;
- int vc = 0;
+ tmp = sr_xpath_key_value((char*) xpath, "interface", "name", &state);
+ if (!tmp) {
+ SRP_LOG_ERR_MSG("XPATH interface name not found");
+ return SR_ERR_INVAL_ARG;
+ }
+ strncpy(interface_name, tmp, VPP_INTFC_NAME_LEN);
+ sr_xpath_recover(&state);
- ARG_CHECK2(SR_ERR_INVAL_ARG, reply, dctx);
+ snprintf(xpath_root, XPATH_SIZE,
+ "/openconfig-interfaces:interfaces/interface[name='%s']/state",
+ interface_name);
- vc = 10;
+ //dump interface interface_name
+ rc = interface_dump_iface(&reply, interface_name);
+ if (rc == -SCVPP_NOT_FOUND) {
+ SRP_LOG_ERR_MSG("interface not found");
+ return SR_ERR_NOT_FOUND;
+ }
- /* convenient functions such as this can be found in sysrepo/values.h */
rc = sr_new_values(vc, &vals);
- if (SR_ERR_OK != rc) {
+ if (SR_ERR_OK != rc)
return rc;
- }
-
- const char* interface_name = (const char*)dctx->sw_interface_details_query.sw_interface_details.interface_name;
- sr_val_build_xpath(&vals[0], "%s/name", dctx->sysr_values_ctx.xpath_root);
- sr_val_set_str_data(&vals[0], SR_STRING_T, interface_name);
+ sr_val_build_xpath(&vals[0], "%s/name", xpath_root);
+ sr_val_set_str_data(&vals[0], SR_STRING_T, (char *)reply.interface_name);
- sr_val_build_xpath(&vals[1], "%s/type", dctx->sysr_values_ctx.xpath_root);
+ sr_val_build_xpath(&vals[1], "%s/type", xpath_root);
sr_val_set_str_data(&vals[1], SR_IDENTITYREF_T, "ianaift:ethernetCsmacd");
- sr_val_build_xpath(&vals[2], "%s/mtu", dctx->sysr_values_ctx.xpath_root);
+ sr_val_build_xpath(&vals[2], "%s/mtu", xpath_root);
vals[2].type = SR_UINT16_T;
- vals[2].data.uint16_val = reply->link_mtu;
+ vals[2].data.uint16_val = reply.link_mtu;
- sr_val_build_xpath(&vals[3], "%s/loopback-mode",
- dctx->sysr_values_ctx.xpath_root);
+ sr_val_build_xpath(&vals[3], "%s/loopback-mode", xpath_root);
vals[3].type = SR_BOOL_T;
- vals[3].data.bool_val = (0 == strncmp(interface_name, "loop", 4)) ? 1 : 0;
+ if (strncmp((char*)reply.interface_name, "loop", 4) == 0)
+ vals[3].data.bool_val = 1;
+ else
+ vals[3].data.bool_val = 0;
- sr_val_build_xpath(&vals[4], "%s/description",
- dctx->sysr_values_ctx.xpath_root);
+ sr_val_build_xpath(&vals[4], "%s/description", xpath_root);
sr_val_set_str_data(&vals[4], SR_STRING_T, NOT_AVAL);
- sr_val_build_xpath(&vals[5], "%s/enabled",
- dctx->sysr_values_ctx.xpath_root);
+ sr_val_build_xpath(&vals[5], "%s/enabled", xpath_root);
vals[5].type = SR_BOOL_T;
- vals[5].data.bool_val = reply->admin_up_down;
+ vals[5].data.bool_val = reply.admin_up_down;
- sr_val_build_xpath(&vals[6], "%s/ifindex",
- dctx->sysr_values_ctx.xpath_root);
+ sr_val_build_xpath(&vals[6], "%s/ifindex", xpath_root);
vals[6].type = SR_UINT32_T;
- vals[6].data.uint32_val = reply->sw_if_index;
+ vals[6].data.uint32_val = reply.sw_if_index;
- sr_val_build_xpath(&vals[7], "%s/admin-status",
- dctx->sysr_values_ctx.xpath_root);
+ sr_val_build_xpath(&vals[7], "%s/admin-status", xpath_root);
sr_val_set_str_data(&vals[7], SR_ENUM_T,
- reply->admin_up_down ? "UP" : "DOWN");
+ reply.admin_up_down ? "UP" : "DOWN");
- sr_val_build_xpath(&vals[8], "%s/oper-status",
- dctx->sysr_values_ctx.xpath_root);
+ sr_val_build_xpath(&vals[8], "%s/oper-status", xpath_root);
sr_val_set_str_data(&vals[8], SR_ENUM_T,
- reply->link_up_down ? "UP" : "DOWN");
+ reply.link_up_down ? "UP" : "DOWN");
//TODO: Openconfig required this value
- // sr_val_build_xpath(&vals[9], "%s/last-change", dctx->sysr_values_ctx.xpath_root);
+ // sr_val_build_xpath(&vals[9], "%s/last-change", xpath_root);
// sr_val_set_str_data(&vals[9], YANG INPUT TYPE: oc-types:timeticks64);
- sr_val_build_xpath(&vals[9], "%s/logical",
- dctx->sysr_values_ctx.xpath_root);
+ sr_val_build_xpath(&vals[9], "%s/logical", xpath_root);
vals[9].type = SR_BOOL_T;
- vals[9].data.bool_val = true; //for now, we assume all are logical
+ vals[9].data.bool_val = true; //for now, we assume all are logical
- dctx->sysr_values_ctx.values = vals;
- dctx->sysr_values_ctx.values_cnt = vc;
+ *values = vals;
+ *values_cnt = vc;
return SR_ERR_OK;
}
-static int sw_subinterface_dump_cb_inner(
- vapi_payload_sw_interface_details *reply,
- sys_sw_interface_dump_ctx *dctx)
+//TODO: for some arcane reason, this doesn't work
+static int openconfig_interfaces_interfaces_interface_subinterfaces_subinterface_oc_ip_ipv4_oc_ip_addresses_oc_ip_address_oc_ip_state_cb(
+ const char *xpath, sr_val_t **values, size_t *values_cnt,
+ uint64_t request_id, const char *original_xpath, void *private_ctx)
{
+ UNUSED(request_id); UNUSED(original_xpath); UNUSED(private_ctx);
+ char xpath_root[XPATH_SIZE] = {0};
+ sr_xpath_ctx_t state = {0};
sr_val_t *vals = NULL;
- int rc = 0;
- int vc = 0, val_idx = 0;
+ char interface_name[VPP_INTFC_NAME_LEN] = {0};
+ char subinterface_index[XPATH_SIZE] = {0};
+ char address_ip[XPATH_SIZE] = {0};
+ u8 prefix_len;
+ char *tmp = NULL;
+ int rc, cnt = 0;
- ARG_CHECK2(SR_ERR_INVAL_ARG, reply, dctx);
+ ARG_CHECK3(SR_ERR_INVAL_ARG, xpath, values, values_cnt);
- vc = 6;
- /* convenient functions such as this can be found in sysrepo/values.h */
- rc = sr_new_values(vc, &vals);
- if (SR_ERR_OK != rc) {
- return rc;
+ SRP_LOG_INF("In %s", __FUNCTION__);
+
+ /* Get XPATH parameters name, index and ip */
+
+ tmp = sr_xpath_key_value((char*)xpath, "interface", "name", &state);
+ if (!tmp) {
+ SRP_LOG_ERR_MSG("XPATH interface name not found");
+ return SR_ERR_INVAL_ARG;
}
+ strncpy(interface_name, tmp, VPP_INTFC_NAME_LEN);
+ sr_xpath_recover(&state);
- sr_val_build_xpath(&vals[val_idx], "%s/index",
- dctx->sysr_values_ctx.xpath_root);
- vals[val_idx].type = SR_UINT32_T;
- vals[val_idx++].data.uint32_val = dctx->subinterface_index;
+ tmp = sr_xpath_key_value((char*)xpath, "subinterface", "index", &state);
+ if (NULL == tmp) {
+ SRP_LOG_ERR_MSG("XPATH subinterface index not found.");
+ return SR_ERR_INVAL_ARG;
+ }
+ strncpy(subinterface_index, tmp, XPATH_SIZE);
+ sr_xpath_recover(&state);
- sr_val_build_xpath(&vals[val_idx], "%s/description",
- dctx->sysr_values_ctx.xpath_root);
- sr_val_set_str_data(&vals[val_idx++], SR_STRING_T, NOT_AVAL);
+ tmp = sr_xpath_key_value((char*)xpath, "address", "ip", &state);
+ if (NULL == tmp) {
+ SRP_LOG_ERR_MSG("XPATH address ip not found.");
+ return SR_ERR_INVAL_ARG;
+ }
+ strncpy(address_ip, tmp, XPATH_SIZE);
+ sr_xpath_recover(&state);
- sr_val_build_xpath(&vals[val_idx], "%s/enabled",
- dctx->sysr_values_ctx.xpath_root);
- vals[val_idx].type = SR_BOOL_T;
- vals[val_idx++].data.bool_val = reply->admin_up_down;
+ snprintf(xpath_root, XPATH_SIZE, "/openconfig-interfaces:interfaces/interface[name='%s']/subinterfaces/subinterface[index='%s']/openconfig-if-ip:ipv4/openconfig-if-ip:addresses/openconfig-if-ip:address[ip='%s']/openconfig-if-ip:state",
+ interface_name, subinterface_index, address_ip);
- //TODO: Openconfig required this value
- // sr_val_build_xpath(&vals[val_idx], "%s/name", dctx->sysr_values_ctx.xpath_root);
- // sr_val_set_str_data(&vals[val_idx++], SR_STRING_T, YANG INPUT TYPE: string);
+ rc = ipv46_address_dump(interface_name, address_ip, &prefix_len, false);
+ if (!rc) {
+ SRP_LOG_ERR_MSG("ipv46_address_dump failed");
+ return SR_ERR_INVAL_ARG;
+ }
- // sr_val_build_xpath(&vals[val_idx], "%s/ifindex", interface_name, subinterface_index);
- // vals[val_idx].type = SR_UINT32_T;
- // vals[val_idx++].data.uint32_val = YANG INPUT TYPE: uint32;
+ /* Build answer to state XPATH */
- sr_val_build_xpath(&vals[val_idx], "%s/admin-status",
- dctx->sysr_values_ctx.xpath_root);
- sr_val_set_str_data(&vals[val_idx++], SR_ENUM_T,
- reply->admin_up_down ? "UP" : "DOWN");
+ rc = sr_new_values(3, &vals);
+ if (SR_ERR_OK != rc)
+ return rc;
- sr_val_build_xpath(&vals[val_idx], "%s/oper-status",
- dctx->sysr_values_ctx.xpath_root);
- sr_val_set_str_data(&vals[val_idx++], SR_ENUM_T,
- reply->admin_up_down ? "UP" : "DOWN");
+ sr_val_build_xpath(&vals[cnt], "%s/openconfig-if-ip:ip", xpath_root);
+ sr_val_set_str_data(&vals[cnt], SR_STRING_T, address_ip);
+ cnt++;
- //TODO: Openconfig required this value
- // sr_val_build_xpath(&vals[val_idx], "/openconfig-interfaces:interfaces/interface[name='%s']/subinterfaces/subinterface[index='%s']/state/last-change", interface_name, subinterface_index);
- // sr_val_set_str_data(&vals[val_idx++], YANG INPUT TYPE: oc-types:timeticks64);
+ sr_val_build_xpath(&vals[cnt], "%s/openconfig-if-ip:prefix-length", xpath_root);
+ vals[cnt].type = SR_UINT8_T;
+ vals[cnt].data.uint8_val = prefix_len;
+ cnt++;
- sr_val_build_xpath(&vals[val_idx], "%s/logical",
- dctx->sysr_values_ctx.xpath_root);
- vals[val_idx].type = SR_BOOL_T;
- vals[val_idx++].data.bool_val = true; //for now, we assume all are logical
+ sr_val_build_xpath(&vals[cnt], "%s/openconfig-if-ip:origin", xpath_root);
+ sr_val_set_str_data(&vals[cnt], SR_ENUM_T, "STATIC");
+ cnt++;
- dctx->sysr_values_ctx.values = vals;
- dctx->sysr_values_ctx.values_cnt = vc;
+ sr_xpath_recover(&state);
+ *values = vals;
+ *values_cnt = cnt;
return SR_ERR_OK;
}
+/* TODO move to common functions between all plugins */
static bool
is_subinterface(const char* subif_name, const char* base_name,
const u32 subif_index)
@@ -351,11 +319,10 @@ is_subinterface(const char* subif_name, const char* base_name,
const char* dot = strchr(subif_name, '.');
if (NULL == dot && 0 == subif_index)
- return true; //subif_index == 0 can pass as a "real" interface
+ return true; //subif_index == 0 can pass as a "real" interface
if (dot > subif_name && 0 == strncmp(subif_name, base_name,
- dot - subif_name))
- {
+ dot - subif_name)) {
char * eptr = NULL;
u32 si = strtoul(dot + 1, &eptr, 10);
@@ -366,289 +333,126 @@ is_subinterface(const char* subif_name, const char* base_name,
return false;
}
-static vapi_error_e
-sw_interface_dump_vapi_cb(struct vapi_ctx_s *ctx, void *callback_ctx,
- vapi_error_e rv, bool is_last,
- vapi_payload_sw_interface_details * reply)
-{
- ARG_CHECK(VAPI_EINVAL, callback_ctx);
-
- if (is_last)
- {
- assert (NULL == reply);
- }
- else
- {
- assert (NULL != reply);
- sys_sw_interface_dump_ctx *dctx = callback_ctx;
-
- const char* const dctx_interface_name = (const char *)dctx->sw_interface_details_query.sw_interface_details.interface_name;
-
- SRP_LOG_DBG("interface_name: '%s', if_name: '%s'", reply->interface_name, dctx_interface_name);
-
- if (dctx->is_subif)
- {
- if (is_subinterface((const char*)reply->interface_name,
- dctx_interface_name, dctx->subinterface_index))
- sw_subinterface_dump_cb_inner(reply, dctx);
- }
- else
- {
- if (0 == strcmp(dctx_interface_name, (char *)reply->interface_name))
- {
- dctx->sw_interface_details_query.sw_interface_details = *reply;
- dctx->sw_interface_details_query.interface_found = true;
-
- sw_interface_dump_cb_inner(reply, dctx);
- }
- }
- }
-
- return VAPI_OK;
-}
-
-static vapi_error_e sysr_sw_interface_dump(sys_sw_interface_dump_ctx * dctx)
-{
- vapi_msg_sw_interface_dump *dump;
- vapi_error_e rv;
-
- ARG_CHECK(VAPI_EINVAL, dctx);
-
- dump = vapi_alloc_sw_interface_dump(g_vapi_ctx_instance);
-
- dump->payload.name_filter_valid = true;
- strcpy((char*)dump->payload.name_filter, (const char *)dctx->sw_interface_details_query.sw_interface_details.interface_name);
-
- VAPI_CALL(vapi_sw_interface_dump(g_vapi_ctx_instance, dump, sw_interface_dump_vapi_cb,
- dctx));
-
- if (VAPI_OK != rv) {
- SRP_LOG_DBG("vapi_sw_interface_dump error=%d", rv);
- }
-
- return rv;
-}
-
-int openconfig_interfaces_interfaces_interface_state_cb(
- const char *xpath, sr_val_t **values,
- size_t *values_cnt,
- __attribute__((unused)) uint64_t request_id,
- __attribute__((unused)) const char *original_xpath,
- __attribute__((unused)) void *private_ctx)
-{
- sr_xpath_ctx_t state = {0};
- char *tmp = NULL;
- char interface_name[XPATH_SIZE] = {0};
-
- SRP_LOG_INF_MSG("In openconfig_interfaces_interfaces_interface_state_cb");
-
- ARG_CHECK3(SR_ERR_INVAL_ARG, xpath, values, values_cnt);
-
- tmp = xpath_find_first_key(xpath, "name", &state);
- if (NULL == tmp) {
- SRP_LOG_ERR_MSG("Interface name not found in sysrepo database");
- return SR_ERR_INVAL_ARG;
- }
-
- strncpy(interface_name, tmp, XPATH_SIZE);
- sr_xpath_recover(&state);
-
- sys_sw_interface_dump_ctx dctx = {
- .is_subif = false
- };
- sw_interface_details_query_set_name(&dctx.sw_interface_details_query,
- interface_name);
-
- snprintf(dctx.sysr_values_ctx.xpath_root, XPATH_SIZE,
- "/openconfig-interfaces:interfaces/interface[name='%s']/state",
- interface_name);
-
- sysr_sw_interface_dump(&dctx);
-
- if (!dctx.sw_interface_details_query.interface_found) {
- SRP_LOG_ERR_MSG("interface not found");
- return SR_ERR_NOT_FOUND;
- }
-
- sr_xpath_recover(&state);
- *values = dctx.sysr_values_ctx.values;
- *values_cnt = dctx.sysr_values_ctx.values_cnt;
-
- return SR_ERR_OK;
-}
-
-int oc_dump_ip_helper(char *address_ip, u8 prefix_len,
- sysr_values_ctx_t *sysr_values_ctx)
-{
- sr_val_t *vals = NULL;
- int rc = 0;
- int vc = 0;
-
- ARG_CHECK2(SR_ERR_INVAL_ARG, address_ip, sysr_values_ctx);
-
- vc = 3;
- /* convenient functions such as this can be found in sysrepo/values.h */
- rc = sr_new_values(vc, &vals);
- if (SR_ERR_OK != rc) {
- return rc;
- }
-
- sr_val_build_xpath(&vals[0], "%s/openconfig-if-ip:ip",
- sysr_values_ctx->xpath_root);
- sr_val_set_str_data(&vals[0], SR_STRING_T, address_ip);
-
- sr_val_build_xpath(&vals[1], "%s/openconfig-if-ip:prefix-length",
- sysr_values_ctx->xpath_root);
- vals[1].type = SR_UINT8_T;
- vals[1].data.uint8_val = prefix_len;
-
- sr_val_build_xpath(&vals[2], "%s/openconfig-if-ip:origin",
- sysr_values_ctx->xpath_root);
- sr_val_set_str_data(&vals[2], SR_ENUM_T, "STATIC");
-
- sysr_values_ctx->values = vals;
- sysr_values_ctx->values_cnt = vc;
-
- return SR_ERR_OK;
-}
-
-//TODO: for some arcane reason, this doesn't work
-int openconfig_interfaces_interfaces_interface_subinterfaces_subinterface_oc_ip_ipv4_oc_ip_addresses_oc_ip_address_oc_ip_state_cb(
+// openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/state
+static int openconfig_interfaces_interfaces_interface_subinterfaces_subinterface_state_cb(
const char *xpath, sr_val_t **values, size_t *values_cnt,
- __attribute__((unused)) uint64_t request_id,
- __attribute__((unused)) const char *original_xpath,
- __attribute__((unused)) void *private_ctx)
+ uint64_t request_id, const char *original_xpath, void *private_ctx)
{
+ UNUSED(request_id); UNUSED(original_xpath); UNUSED(private_ctx);
+ sw_interface_dump_t reply = {0};
+ char xpath_root[XPATH_SIZE];
sr_xpath_ctx_t state = {0};
- int rc;
char *tmp = NULL;
- char interface_name[XPATH_SIZE] = {0};
+ char interface_name[VPP_INTFC_NAME_LEN] = {0};
char subinterface_index[XPATH_SIZE] = {0};
- char address_ip[XPATH_SIZE] = {0};
- u8 prefix_len;
+ u32 sub_id;
+ sr_val_t *vals = NULL;
+ int vc = 6;
+ int val_idx = 0;
+ int rc;
ARG_CHECK3(SR_ERR_INVAL_ARG, xpath, values, values_cnt);
- SRP_LOG_INF_MSG("In oc-interfaces oc-ip");
+ SRP_LOG_INF("In %s", __FUNCTION__);
- tmp = xpath_find_first_key(xpath, "name", &state);
- if (NULL == tmp) {
- SRP_LOG_ERR_MSG("interface_name not found.");
+ tmp = sr_xpath_key_value((char*)xpath, "interface", "name", &state);
+ if (!tmp) {
+ SRP_LOG_ERR_MSG("XPATH interface name not found");
return SR_ERR_INVAL_ARG;
}
-
- strncpy(interface_name, tmp, XPATH_SIZE);
+ strncpy(interface_name, tmp, VPP_INTFC_NAME_LEN);
sr_xpath_recover(&state);
- tmp = xpath_find_first_key(xpath, "index", &state);
- if (NULL == tmp) {
- SRP_LOG_ERR_MSG("subinterface_index not found.");
+ tmp = sr_xpath_key_value((char*)xpath, "subinterface", "index", &state);
+ if (!tmp) {
+ SRP_LOG_ERR_MSG("subinterface index not found");
return SR_ERR_INVAL_ARG;
}
-
strncpy(subinterface_index, tmp, XPATH_SIZE);
sr_xpath_recover(&state);
- tmp = xpath_find_first_key(xpath, "ip", &state);
- if (NULL == tmp) {
- SRP_LOG_ERR_MSG("address_ip not found.");
- return SR_ERR_INVAL_ARG;
- }
-
- strncpy(address_ip, tmp, XPATH_SIZE);
- sr_xpath_recover(&state);
-
- sysr_values_ctx_t dctx = {0};
- snprintf(dctx.xpath_root, XPATH_SIZE, "/openconfig-interfaces:interfaces/interface[name='%s']/subinterfaces/subinterface[index='%s']/openconfig-if-ip:ipv4/openconfig-if-ip:addresses/openconfig-if-ip:address[ip='%s']/openconfig-if-ip:state",
- interface_name, subinterface_index, address_ip);
+ snprintf(xpath_root, XPATH_SIZE,
+ "/openconfig-interfaces:interfaces/interface[name='%s']/subinterfaces/subinterface[index='%s']/state",
+ interface_name, subinterface_index);
- rc = ipv46_address_dump(interface_name, address_ip, &prefix_len, false);
- if (!rc) {
- SRP_LOG_ERR_MSG("ipv46_address_dump failed");
- return SR_ERR_INVAL_ARG;
+ rc = interface_dump_iface(&reply, interface_name);
+ if (rc == -SCVPP_NOT_FOUND) {
+ SRP_LOG_ERR_MSG("interface not found");
+ return SR_ERR_NOT_FOUND;
}
- rc = oc_dump_ip_helper(address_ip, prefix_len, &dctx);
- if (!rc) {
- SRP_LOG_ERR_MSG("oc_dump_ip_helper failed");
- return rc;
+ /* Check that requested subinterface index matches reply subid */
+ sub_id = atoi(subinterface_index);
+ if (sub_id != reply.sub_id) {
+ SRP_LOG_ERR_MSG("subinterface index not found.");
+ return SR_ERR_NOT_FOUND;
}
- sr_xpath_recover(&state);
- *values = dctx.values;
- *values_cnt = dctx.values_cnt;
-
- return SR_ERR_OK;
-}
+ /* Check that interface is a sub interface */
+ if (!is_subinterface((char*)reply.interface_name, interface_name, sub_id)) {
+ SRP_LOG_ERR("%s not a subinterface", interface_name);
+ return SR_ERR_OPERATION_FAILED;
+ }
-// openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/state
-int openconfig_interfaces_interfaces_interface_subinterfaces_subinterface_state_cb(
- const char *xpath, sr_val_t **values, size_t *values_cnt,
- __attribute__((unused)) uint64_t request_id,
- __attribute__((unused)) const char *original_xpath,
- __attribute__((unused)) void *private_ctx)
-{
- sr_xpath_ctx_t state = {0};
- char *tmp = NULL;
- char interface_name[XPATH_SIZE] = {0};
- char subinterface_index[XPATH_SIZE] = {0};
+ rc = sr_new_values(vc, &vals);
+ if (SR_ERR_OK != rc)
+ return rc;
- ARG_CHECK3(SR_ERR_INVAL_ARG, xpath, values, values_cnt);
+ sr_val_build_xpath(&vals[val_idx], "%s/index", xpath_root);
+ vals[val_idx].type = SR_UINT32_T;
+ vals[val_idx++].data.uint32_val = sub_id;
- tmp = xpath_find_first_key(xpath, "name", &state);
- if (NULL == tmp) {
- SRP_LOG_ERR_MSG("interface_name not found.");
- return SR_ERR_INVAL_ARG;
- }
+ sr_val_build_xpath(&vals[val_idx], "%s/description", xpath_root);
+ sr_val_set_str_data(&vals[val_idx++], SR_STRING_T, NOT_AVAL);
- strncpy(interface_name, tmp, XPATH_SIZE);
- sr_xpath_recover(&state);
+ sr_val_build_xpath(&vals[val_idx], "%s/enabled", xpath_root);
+ vals[val_idx].type = SR_BOOL_T;
+ vals[val_idx++].data.bool_val = reply.admin_up_down;
- tmp = xpath_find_first_key(xpath, "index", &state);
- if (NULL == tmp) {
- SRP_LOG_ERR_MSG("subinterface_index not found.");
- return SR_ERR_INVAL_ARG;
- }
+ //TODO: Openconfig required this value
+ // sr_val_build_xpath(&vals[val_idx], "%s/name", xpath_root);
+ // sr_val_set_str_data(&vals[val_idx++], SR_STRING_T, YANG INPUT TYPE: string);
- strncpy(subinterface_index, tmp, XPATH_SIZE);
- sr_xpath_recover(&state);
+ // sr_val_build_xpath(&vals[val_idx], "%s/ifindex", interface_name, sub_id);
+ // vals[val_idx].type = SR_UINT32_T;
+ // vals[val_idx++].data.uint32_val = YANG INPUT TYPE: uint32;
- sys_sw_interface_dump_ctx dctx =
- {
- .is_subif = true,
- .subinterface_index = atoi(subinterface_index)
- };
- sw_interface_details_query_set_name(&dctx.sw_interface_details_query,
- interface_name);
+ sr_val_build_xpath(&vals[val_idx], "%s/admin-status", xpath_root);
+ sr_val_set_str_data(&vals[val_idx++], SR_ENUM_T,
+ reply.admin_up_down ? "UP" : "DOWN");
- snprintf(dctx.sysr_values_ctx.xpath_root, XPATH_SIZE, "/openconfig-interfaces:interfaces/interface[name='%s']/subinterfaces/subinterface[index='%s']/state",
- interface_name, subinterface_index);
+ sr_val_build_xpath(&vals[val_idx], "%s/oper-status", xpath_root);
+ sr_val_set_str_data(&vals[val_idx++], SR_ENUM_T, reply.admin_up_down ? "UP" : "DOWN");
- sysr_sw_interface_dump(&dctx);
+ //TODO: Openconfig required this value
+ // sr_val_build_xpath(&vals[val_idx], "/openconfig-interfaces:interfaces/interface[name='%s']/subinterfaces/subinterface[index='%s']/state/last-change", interface_name, sub_id);
+ // sr_val_set_str_data(&vals[val_idx++], YANG INPUT TYPE: oc-types:timeticks64);
- if (!dctx.sw_interface_details_query.interface_found) {
- SRP_LOG_DBG_MSG("interface not found");
- return SR_ERR_NOT_FOUND;
- }
+ sr_val_build_xpath(&vals[val_idx], "%s/logical", xpath_root);
+ vals[val_idx].type = SR_BOOL_T;
+ vals[val_idx++].data.bool_val = true; //for now, we assume all are logical
sr_xpath_recover(&state);
- *values = dctx.sysr_values_ctx.values;
- *values_cnt = dctx.sysr_values_ctx.values_cnt;
+
+ *values = vals;
+ *values_cnt = vc;
return SR_ERR_OK;
}
// openconfig-interfaces:interfaces/interface[name='%s']/subinterfaces/subinterface[index='%s']/oc-ip:ipv4/oc-ip:addresses/oc-ip:address[ip='%s']/oc-ip:config/
-int openconfig_interfaces_interfaces_interface_subinterfaces_subinterface_oc_ip_ipv4_oc_ip_addresses_oc_ip_address_oc_ip_config_cb(
+static int openconfig_interfaces_interfaces_interface_subinterfaces_subinterface_oc_ip_ipv4_oc_ip_addresses_oc_ip_address_oc_ip_config_cb(
sr_session_ctx_t *ds, const char *xpath, sr_notif_event_t event,
- __attribute__((unused)) void *private_ctx)
+ void *private_ctx)
{
+ UNUSED(private_ctx);
sr_change_iter_t *it = NULL;
sr_change_oper_t oper;
- sr_val_t *old_val = NULL;
- sr_val_t *new_val = NULL;
+ sr_xpath_ctx_t state = {0};
+ sr_val_t *old = NULL;
+ sr_val_t *new = NULL;
char *tmp = NULL;
- char interface_name[XPATH_SIZE] = {0};
+ char interface_name[VPP_INTFC_NAME_LEN] = {0};
char subinterface_index[XPATH_SIZE] = {0};
char address_ip[XPATH_SIZE] = {0};
char old_address_ip[XPATH_SIZE] = {0};
@@ -662,82 +466,69 @@ int openconfig_interfaces_interfaces_interface_subinterfaces_subinterface_oc_ip_
// if we receive event SR_EV_APPLY - config has changed
- log_recv_event(event, "subtree_change_cb received");
- SRP_LOG_DBG("[SRP_LOG_DBG] xpath: %s", xpath);
-
- if (event != SR_EV_APPLY) {
+ if (event == SR_EV_APPLY)
return SR_ERR_OK;
- }
if (sr_get_changes_iter(ds, (char *)xpath, &it) != SR_ERR_OK) {
- // in example he calls even on fale
sr_free_change_iter(it);
return SR_ERR_OK;
}
- while (sr_get_change_next(ds, it, &oper, &old_val, &new_val) == SR_ERR_OK) {
-
- log_recv_oper(oper, "subtree_change_cb received");
+ foreach_change (ds, it, oper, old, new) {
- SRP_LOG_DBG("xpath: %s", new_val->xpath);
+ SRP_LOG_DBG("xpath: %s", new->xpath);
- sr_xpath_ctx_t state = {0};
-
- tmp = xpath_find_first_key(new_val->xpath, "name", &state);
- if (NULL == tmp) {
- SRP_LOG_DBG_MSG("interface_name NOT found.");
- continue;
+ tmp = sr_xpath_key_value(new->xpath, "interface", "name", &state);
+ if (!tmp) {
+ sr_set_error(ds, "XPATH interface name NOT found", new->xpath);
+ return SR_ERR_INVAL_ARG;
}
-
- strncpy(interface_name, tmp, XPATH_SIZE);
+ strncpy(interface_name, tmp, VPP_INTFC_NAME_LEN);
sr_xpath_recover(&state);
- tmp = xpath_find_first_key(new_val->xpath, "index", &state);
- if (NULL == tmp) {
- SRP_LOG_DBG_MSG("subinterface_index NOT found.");
- continue;
+ tmp = sr_xpath_key_value(new->xpath, "subinterface", "index", &state);
+ if (!tmp) {
+ sr_set_error(ds, "XPATH subinterface index NOT found", new->xpath);
+ return SR_ERR_INVAL_ARG;
}
-
strncpy(subinterface_index, tmp, XPATH_SIZE);
sr_xpath_recover(&state);
switch (oper) {
case SR_OP_CREATED:
- if (sr_xpath_node_name_eq(new_val->xpath, "ip")) {
+ if (sr_xpath_node_name_eq(new->xpath, "ip")) {
ip_set = true;
- strncpy(address_ip, new_val->data.string_val, XPATH_SIZE);
- } else if (sr_xpath_node_name_eq(new_val->xpath,
+ strncpy(address_ip, new->data.string_val, XPATH_SIZE);
+ } else if (sr_xpath_node_name_eq(new->xpath,
"prefix-length")) {
prefix_len_set = true;
- prefix_len = new_val->data.uint8_val;
+ prefix_len = new->data.uint8_val;
}
- if (ip_set && prefix_len_set) {
- //add ipv4
+ if (ip_set && prefix_len_set) //add ipv4
rc = ipv46_config_add_remove(interface_name, address_ip,
prefix_len, false , true);
- }
break;
case SR_OP_MODIFIED:
- if (sr_xpath_node_name_eq(old_val->xpath, "ip")) {
+ if (sr_xpath_node_name_eq(old->xpath, "ip")) {
old_ip_set = true;
- strncpy(old_address_ip, old_val->data.string_val,
+ strncpy(old_address_ip, old->data.string_val,
XPATH_SIZE);
- } else if (sr_xpath_node_name_eq(old_val->xpath,
+ } else if (sr_xpath_node_name_eq(old->xpath,
" prefix-length")) {
old_prefix_len_set = true;
- old_prefix_len = old_val->data.uint8_val;
+ old_prefix_len = old->data.uint8_val;
}
- if (sr_xpath_node_name_eq(new_val->xpath, "ip")) {
+ if (sr_xpath_node_name_eq(new->xpath, "ip")) {
ip_set = true;
- strncpy(address_ip, new_val->data.string_val, XPATH_SIZE);
- } else if (sr_xpath_node_name_eq(new_val->xpath,
+ strncpy(address_ip, new->data.string_val, XPATH_SIZE);
+ } else if (sr_xpath_node_name_eq(new->xpath,
"prefix-length")) {
prefix_len_set = true;
- prefix_len = new_val->data.uint8_val;
+ prefix_len = new->data.uint8_val;
}
if (old_ip_set && old_prefix_len_set) {
@@ -760,14 +551,14 @@ int openconfig_interfaces_interfaces_interface_subinterfaces_subinterface_oc_ip_
break;
case SR_OP_DELETED:
- if (sr_xpath_node_name_eq(old_val->xpath, "ip")) {
+ if (sr_xpath_node_name_eq(old->xpath, "ip")) {
old_ip_set = true;
- strncpy(old_address_ip, old_val->data.string_val,
+ strncpy(old_address_ip, old->data.string_val,
XPATH_SIZE);
- } else if (sr_xpath_node_name_eq(old_val->xpath,
+ } else if (sr_xpath_node_name_eq(old->xpath,
"prefix-length")) {
old_prefix_len_set = true;
- old_prefix_len = old_val->data.uint8_val;
+ old_prefix_len = old->data.uint8_val;
}
if (old_ip_set && old_prefix_len_set) {
@@ -781,8 +572,8 @@ int openconfig_interfaces_interfaces_interface_subinterfaces_subinterface_oc_ip_
if (0 != rc) {
sr_xpath_recover(&state);
- sr_free_val(old_val);
- sr_free_val(new_val);
+ sr_free_val(old);
+ sr_free_val(new);
sr_free_change_iter(it);
@@ -791,8 +582,8 @@ int openconfig_interfaces_interfaces_interface_subinterfaces_subinterface_oc_ip_
sr_xpath_recover(&state);
- sr_free_val(old_val);
- sr_free_val(new_val);
+ sr_free_val(old);
+ sr_free_val(new);
}
sr_free_change_iter(it);
@@ -801,16 +592,6 @@ int openconfig_interfaces_interfaces_interface_subinterfaces_subinterface_oc_ip_
const xpath_t oc_interfaces_xpaths[OC_INTERFACES_SIZE] = {
{
- .xpath = "openconfig-interfaces",
- .method = MODULE,
- .datastore = SR_DS_RUNNING,
- .cb.mcb = openconfig_interface_mod_cb,
- .private_ctx = NULL,
- .priority = 0,
- //.opts = SR_SUBSCR_EV_ENABLED | SR_SUBSCR_APPLY_ONLY
- .opts = SR_SUBSCR_EV_ENABLED | SR_SUBSCR_APPLY_ONLY | SR_SUBSCR_CTX_REUSE
- },
- {
.xpath = "/openconfig-interfaces:interfaces/interface/config",
.method = XPATH,
.datastore = SR_DS_RUNNING,
diff --git a/src/plugins/openconfig/openconfig_interfaces.h b/src/plugins/openconfig/openconfig_interfaces.h
deleted file mode 100644
index 88d5fe0..0000000
--- a/src/plugins/openconfig/openconfig_interfaces.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (c) 2018 PANTHEON.tech.
- *
- * 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.
- */
-
-
-#ifndef __OPENCONFIG_INTERFACES_H__
-#define __OPENCONFIG_INTERFACES_H__
-
-#include "../sc_model.h"
-
-#define OC_INTERFACES_SIZE 6
-extern const xpath_t oc_interfaces_xpaths[OC_INTERFACES_SIZE];
-
-#endif /* __OPENCONFIG_INTERFACES_H__ */
diff --git a/src/plugins/openconfig/openconfig_local_routing.c b/src/plugins/openconfig/openconfig_local_routing.c
index 5c63eaa..5d18b52 100644
--- a/src/plugins/openconfig/openconfig_local_routing.c
+++ b/src/plugins/openconfig/openconfig_local_routing.c
@@ -17,732 +17,494 @@
#include <assert.h>
#include <string.h>
-#include "openconfig_local_routing.h"
+#include <scvpp/comm.h>
+#include <scvpp/interface.h>
+#include <scvpp/ip.h>
+#include "../sc_model.h"
#include "../sys_util.h"
-#include "sc_vpp_comm.h"
-#include "sc_vpp_interface.h"
-#include "sc_vpp_ip.h"
+#define HOP_INDEX_SIZE 10 //number of digit in max 32 bit integer
-#define XPATH_SIZE 2000
-
-int openconfig_local_routing_mod_cb(
- __attribute__((unused)) sr_session_ctx_t* session,
- __attribute__((unused)) const char* module_name,
- __attribute__((unused)) sr_notif_event_t event,
- __attribute__((unused)) void* private_ctx)
+static inline int
+_set_route (const char *prefix, const char *nhop, bool is_add,
+ const char *iface)
{
- SRP_LOG_DBG("Local routing module subscribe: %s", module_name);
+ int table = 0; //FIB table ID
+ int mask;
+ int rc;
+
+ // Put prefix length in mask and prefix IP in prefix
+ mask = ip_prefix_split(prefix);
+ if (mask < 1) {
+ SRP_LOG_ERR("Prefix length can not be %d", mask);
+ return SR_ERR_INVAL_ARG;
+ }
+
+ rc = ipv46_config_add_del_route(prefix, mask, nhop, is_add, table, iface);
+ if (rc != SCVPP_OK) {
+ SRP_LOG_ERR("Add/delete route failed for %s %s", prefix, iface);
+ return SR_ERR_INVAL_ARG;
+ }
+
+ SRP_LOG_INF("Add/delete route Success for %s %s", prefix, iface);
return SR_ERR_OK;
}
-static int set_route(sr_session_ctx_t *sess, const char *index,
- const char *n_interface /*NULLABLE*/,
- const char *n_next_hop /*NULLABLE*/,
- const char *prefix, bool is_add)
-{
- int rc = SR_ERR_OK;
- sr_val_t *value = NULL;
- char xpath[XPATH_SIZE] = {0};
- const char *interface = NULL;
- const char *next_hop = NULL;
+#define STR(string) #string
- ARG_CHECK3(SR_ERR_INVAL_ARG, sess, index, prefix);
+#define ROOT "/openconfig-local-routing:local-routes/static-routes/static[prefix='%s']/next-hops/next-hop[index='%s']/%s"
- if (NULL == n_interface) {
- snprintf(xpath, XPATH_SIZE,
- "/openconfig-local-routing:local-routes/static-routes/static[prefix='%s']/next-hops/next-hop[index='%s']/interface-ref/config/interface", prefix, index);
+static inline char * _get_ds_elem(sr_session_ctx_t *sess, const char *prefix,
+ const char *index, const char *sub)
+{
+ char xpath[XPATH_SIZE] = {0};
+ sr_val_t *value = NULL;
+ int rc;
- rc = sr_get_item(sess, xpath, &value);
- if (SR_ERR_OK != rc) {
- SRP_LOG_DBG_MSG("Interface not set");
- return 0;
- }
+ snprintf(xpath, XPATH_SIZE, ROOT, prefix, index, sub);
- interface = value->data.string_val;
- } else {
- interface = n_interface;
+ rc = sr_get_item(sess, xpath, &value);
+ if (SR_ERR_OK != rc) {
+ SRP_LOG_DBG("XPATH %s not set", xpath);
+ return NULL;
}
- if (NULL == n_next_hop) {
- snprintf(xpath, XPATH_SIZE,
- "/openconfig-local-routing:local-routes/static-routes/static[prefix='%s']/next-hops/next-hop[index='%s']/config/next-hop", prefix, index);
+ return value->data.string_val;
+}
- rc = sr_get_item(sess, xpath, &value);
- if (SR_ERR_OK != rc) {
- SRP_LOG_DBG_MSG("Next-hop not set");
- return 0;
- }
+/* @brief add/del route to FIB table 0.
+ * If you add/delete an entry to FIB, prefix is mandatory and next hop can be:
+ * - interface only
+ * - next hop IP
+ * - both interface and next hop IP
+ */
+static int set_route(sr_session_ctx_t *sess, const char *index,
+ const char *interface /* NULLABLE*/,
+ const char *next_hop /* NULLABLE*/,
+ const char *prefix, bool is_add)
+{
+ const char *iface = NULL;
+ const char *nhop = NULL;
- next_hop = value->data.string_val;
- } else {
- next_hop = n_next_hop;
- }
+ ARG_CHECK3(SR_ERR_INVAL_ARG, sess, index, prefix);
- int mask = ip_prefix_split(prefix);
- if (mask < 1) {
+ if (!interface && !next_hop)
return SR_ERR_INVAL_ARG;
- }
- rc = ipv46_config_add_del_route(prefix, mask, next_hop, is_add, 0,
- interface);
- if (!rc) {
- return SR_ERR_INVAL_ARG;
- }
+ if (!interface) //fetch interface in datastore, can return NULL
+ iface = _get_ds_elem(sess, prefix, index, "interface-ref/config/interface");
+ else //use interface provided
+ iface = interface;
+
+ if (!next_hop) //fetch next-hop in datastore , can return NULL
+ nhop = _get_ds_elem(sess, prefix, index, "config/next-hop");
+ else //use next hop IP provided
+ nhop = next_hop;
+
+ return _set_route(prefix, nhop, is_add, iface);
+}
+
+/* @brief Callback used to add prefix entry for XPATH:
+ * /openconfig-local-routing:local-routes/static-routes/static/config
+ */
+static int
+oc_prefix_config_cb(sr_session_ctx_t *ds, const char *xpath,
+ sr_notif_event_t event, void *private_ctx)
+{
+ UNUSED(ds); UNUSED(xpath); UNUSED(event); UNUSED(private_ctx);
+
+ SRP_LOG_INF("In %s", __FUNCTION__);
return SR_ERR_OK;
}
// XPATH: /openconfig-local-routing:local-routes/static-routes/static[prefix='%s']/next-hops/next-hop[index='%s']/config/
-int openconfig_local_routing_local_routes_static_routes_static_next_hops_next_hop_config_cb(
- sr_session_ctx_t *ds, const char *xpath, sr_notif_event_t event,
- __attribute__((unused)) void *private_ctx)
+static int oc_next_hop_config_cb(sr_session_ctx_t *ds, const char *xpath,
+ sr_notif_event_t event, void *private_ctx)
{
- sr_change_iter_t *it = NULL;
+ char prefix[VPP_IP4_PREFIX_STRING_LEN] = {0};
+ char next_hop[VPP_IP4_ADDRESS_STRING_LEN] = {0}; //IP of next router
+ char index[HOP_INDEX_SIZE]; //next hop index
+ bool index_set = false, next_hop_set = false;
+ sr_change_iter_t *it;
sr_change_oper_t oper;
- sr_val_t *old_val = NULL;
- sr_val_t *new_val = NULL;
+ sr_val_t *old, *new, *tmp;
+ sr_xpath_ctx_t state = {0};
int rc = SR_ERR_OK;
- char *tmp = NULL;
- char static_prefix[XPATH_SIZE] = {0};
- char next_hop_index[XPATH_SIZE] = {0};
- char next_hop[XPATH_SIZE] = {0};
- char old_next_hop_index[XPATH_SIZE] = {0};
- char old_next_hop[XPATH_SIZE] = {0};
- bool index_set = false, next_hop_set = false;
- bool old_index_set = false, old_next_hop_set = false;
+ UNUSED(private_ctx);
ARG_CHECK2(SR_ERR_INVAL_ARG, ds, xpath);
- // if we receive event SR_EV_APPLY - config has changed
+ SRP_LOG_INF("In %s", __FUNCTION__);
- log_recv_event(event, "subtree_change_cb received");
- SRP_LOG_DBG("[SRP_LOG_DBG] xpath: %s", xpath);
-
- if (event != SR_EV_APPLY) {
+ if (event == SR_EV_APPLY) //SR_EV_VERIFY already applied the changes
return SR_ERR_OK;
- }
- if (sr_get_changes_iter(ds, (char *)xpath, &it) != SR_ERR_OK) {
- // in example he calls even on fale
+ rc = sr_get_changes_iter(ds, (char *)xpath, &it);
+ if (rc != SR_ERR_OK) {
sr_free_change_iter(it);
- return SR_ERR_OK;
+ return rc;
}
- while (sr_get_change_next(ds, it, &oper,
- &old_val, &new_val) == SR_ERR_OK) {
-
- log_recv_oper(oper, "subtree_change_cb received");
-
- SRP_LOG_DBG("xpath: %s", new_val->xpath);
-
- sr_xpath_ctx_t state = {0};
-
- tmp = xpath_find_first_key(new_val->xpath, "prefix", &state);
- if (NULL == tmp) {
- SRP_LOG_DBG_MSG("static_prefix NOT found.");
- continue;
- }
+ foreach_change(ds, it, oper, old, new) {
- strncpy(static_prefix, tmp, XPATH_SIZE);
- sr_xpath_recover(&state);
+ rc = get_xpath_key(prefix, new->xpath, "static", "prefix",
+ VPP_IP4_PREFIX_STRING_LEN, &state);
+ if (rc != 0)
+ goto error;
switch (oper) {
- case SR_OP_CREATED:
- if (sr_xpath_node_name_eq(new_val->xpath, "index")) {
- strncpy(next_hop_index, new_val->data.string_val,
- XPATH_SIZE);
- index_set = true;
- } else if(sr_xpath_node_name_eq(new_val->xpath, "next-hop")) {
- next_hop_set = true;
- strncpy(next_hop, new_val->data.string_val, XPATH_SIZE);
- } else if(sr_xpath_node_name_eq(new_val->xpath, "metric")) {
- //TODO: LEAF: metric, type: uint32
- } else if(sr_xpath_node_name_eq(new_val->xpath, "recurse")) {
- //TODO: LEAF: recurse, type: boolean
- }
-
- if (index_set && next_hop_set) {
- rc = set_route(ds, next_hop_index, NULL, next_hop,
- static_prefix, true);
- }
- break;
-
case SR_OP_MODIFIED:
- if (sr_xpath_node_name_eq(old_val->xpath, "index")) {
- strncpy(old_next_hop_index, old_val->data.string_val,
- XPATH_SIZE);
- old_index_set = true;
- } else if(sr_xpath_node_name_eq(old_val->xpath, "next-hop")) {
- old_next_hop_set = true;
- strncpy(old_next_hop, old_val->data.string_val, XPATH_SIZE);
- } else if(sr_xpath_node_name_eq(old_val->xpath, "metric")) {
- //TODO: LEAF: metric, type: uint32
- } else if(sr_xpath_node_name_eq(old_val->xpath, "recurse")) {
- //TODO: LEAF: recurse, type: boolean
- }
-
- if (sr_xpath_node_name_eq(new_val->xpath, "index")) {
- strncpy(next_hop_index, new_val->data.string_val,
- XPATH_SIZE);
- index_set = true;
- } else if(sr_xpath_node_name_eq(new_val->xpath, "next-hop")) {
- next_hop_set = true;
- strncpy(next_hop, new_val->data.string_val, XPATH_SIZE);
- } else if(sr_xpath_node_name_eq(new_val->xpath, "metric")) {
- //TODO: LEAF: metric, type: uint32
- } else if(sr_xpath_node_name_eq(new_val->xpath, "recurse")) {
- //TODO: LEAF: recurse, type: boolean
- }
-
- if (old_index_set && old_next_hop_set) {
- rc = set_route(ds, old_next_hop_index, NULL, old_next_hop,
- static_prefix, false);
- }
-
- if (index_set && next_hop_set) {
- rc = set_route(ds, next_hop_index, NULL, next_hop,
- static_prefix, true);
- }
- break;
-
- case SR_OP_MOVED:
+ case SR_OP_CREATED:
+ tmp = new;
break;
-
case SR_OP_DELETED:
- if (sr_xpath_node_name_eq(old_val->xpath, "index")) {
- strncpy(old_next_hop_index, old_val->data.string_val,
- XPATH_SIZE);
- old_index_set = true;
- } else if(sr_xpath_node_name_eq(old_val->xpath, "next-hop")) {
- old_next_hop_set = true;
- strncpy(old_next_hop, old_val->data.string_val, XPATH_SIZE);
- } else if(sr_xpath_node_name_eq(old_val->xpath, "metric")) {
- //TODO: LEAF: metric, type: uint32
- } else if(sr_xpath_node_name_eq(old_val->xpath, "recurse")) {
- //TODO: LEAF: recurse, type: boolean
- }
-
- if (old_index_set && old_next_hop_set) {
- rc = set_route(ds, old_next_hop_index, NULL, old_next_hop,
- static_prefix, false);
- }
+ tmp = old;
+ break;
+ default:
+ SRP_LOG_WRN_MSG("Operation not supported");
break;
}
- if (SR_ERR_OK != rc) {
- sr_xpath_recover(&state);
+ if (sr_xpath_node_name_eq(tmp->xpath, "config")) {
+ SRP_LOG_DBG("xpath: %s", tmp->xpath);
+ } else if (sr_xpath_node_name_eq(tmp->xpath, "index")) {
+ strncpy(index, tmp->data.string_val, HOP_INDEX_SIZE);
+ index_set = true;
+ } else if(sr_xpath_node_name_eq(tmp->xpath, "next-hop")) {
+ strncpy(next_hop, tmp->data.string_val, VPP_IP4_ADDRESS_STRING_LEN);
+ next_hop_set = true;
+ } else if(sr_xpath_node_name_eq(tmp->xpath, "recurse")) {
+ //SYSREPO BUG: Just catch it, sysrepo thinks it is mandatory...
+ } else { //metric, recurse
+ SRP_LOG_ERR("Unsupported field %s", tmp->xpath);
+ return SR_ERR_UNSUPPORTED;
+ }
- sr_free_val(old_val);
- sr_free_val(new_val);
+ if (index_set && next_hop_set) {
+ if (oper == SR_OP_CREATED) {
+ rc = set_route(ds, index, NULL, next_hop, prefix, true);
+ } else if (oper == SR_OP_MODIFIED) {
+ rc = set_route(ds, index, NULL, next_hop, prefix, false);
+ rc |= set_route(ds, index, NULL, next_hop, prefix, true);
+ } else if (oper == SR_OP_DELETED) {
+ rc = set_route(ds, index, NULL, next_hop, prefix, false);
+ }
- sr_free_change_iter(it);
- return SR_ERR_OPERATION_FAILED;
+ if (rc != 0) {
+ SRP_LOG_ERR_MSG("setting route failed");
+ goto error;
+ }
+ index_set = false; next_hop_set = false;
}
+ sr_free_val(old);
+ sr_free_val(new);
sr_xpath_recover(&state);
-
- sr_free_val(old_val);
- sr_free_val(new_val);
}
sr_free_change_iter(it);
- return SR_ERR_OK;
+ return rc;
+
+error:
+ sr_free_val(old);
+ sr_free_val(new);
+ sr_xpath_recover(&state);
+ sr_free_change_iter(it);
+ return rc;
}
// XPATH: /openconfig-local-routing:local-routes/static-routes/static[prefix='%s']/next-hops/next-hop[index='%s']/interface-ref/config/
-int openconfig_local_routing_local_routes_static_routes_static_next_hops_next_hop_interface_ref_config_cb(
- sr_session_ctx_t *ds, const char *xpath, sr_notif_event_t event,
- __attribute__((unused)) void *private_ctx)
+static int
+oc_next_hop_interface_config_cb(sr_session_ctx_t *ds, const char *xpath,
+ sr_notif_event_t event, void *private_ctx)
{
+ char prefix[VPP_IP4_PREFIX_STRING_LEN] = {0};
+ char interface[VPP_INTFC_NAME_LEN] = {0};
+ char index[HOP_INDEX_SIZE] = {0};
sr_change_iter_t *it = NULL;
sr_change_oper_t oper;
- sr_val_t *old_val = NULL;
- sr_val_t *new_val = NULL;
- char *tmp = NULL;
- char static_prefix[XPATH_SIZE] = {0};
- char next_hop_index[XPATH_SIZE] = {0};
- char interface[XPATH_SIZE] = {0};
- char old_interface[XPATH_SIZE] = {0};
+ sr_val_t *old, *new, *tmp;
+ sr_xpath_ctx_t state = {0};
+ bool interface_set = false;
int rc = SR_ERR_OK;
+ UNUSED(private_ctx);
- // if we receive event SR_EV_APPLY - config has changed
-
- log_recv_event(event, "subtree_change_cb received");
- SRP_LOG_DBG("[SRP_LOG_DBG] xpath: %s", xpath);
+ SRP_LOG_INF("In %s", __FUNCTION__);
- if (event != SR_EV_APPLY) {
+ if (event == SR_EV_APPLY)
return SR_ERR_OK;
- }
- if (sr_get_changes_iter(ds, (char *)xpath, &it) != SR_ERR_OK) {
- // in example he calls even on fale
+ rc = sr_get_changes_iter(ds, (char *)xpath, &it);
+ if (rc != SR_ERR_OK) {
sr_free_change_iter(it);
- return SR_ERR_OK;
+ return rc;
}
- while (sr_get_change_next(ds, it, &oper,
- &old_val, &new_val) == SR_ERR_OK) {
+ foreach_change(ds, it, oper, old, new) {
- log_recv_oper(oper, "subtree_change_cb received");
+ SRP_LOG_DBG("xpath: %s", new->xpath);
- SRP_LOG_DBG("xpath: %s", new_val->xpath);
+ rc = get_xpath_key(prefix, new->xpath, "static", "prefix",
+ VPP_IP4_PREFIX_STRING_LEN, &state);
- sr_xpath_ctx_t state = {0};
-
- tmp = xpath_find_first_key(new_val->xpath, "prefix", &state);
- if (NULL == tmp) {
- SRP_LOG_DBG_MSG("static_prefix NOT found.");
- continue;
- }
-
- strncpy(static_prefix, tmp, XPATH_SIZE);
- sr_xpath_recover(&state);
-
- tmp = xpath_find_first_key(new_val->xpath, "index", &state);
- if (NULL == tmp) {
- SRP_LOG_DBG_MSG("next-hop_index NOT found.");
- continue;
- }
-
- strncpy(next_hop_index, tmp, XPATH_SIZE);
- sr_xpath_recover(&state);
+ rc |= get_xpath_key(index, new->xpath, "next-hop", "index",
+ HOP_INDEX_SIZE, &state);
+ if (rc)
+ goto error;
switch (oper) {
- case SR_OP_CREATED:
- if (sr_xpath_node_name_eq(new_val->xpath, "interface")) {
- strncpy(interface, new_val->data.string_val, XPATH_SIZE);
- rc = set_route(ds, next_hop_index, interface, NULL,
- static_prefix, true);
- } else if (sr_xpath_node_name_eq(new_val->xpath,
- "subinterface")) {
- }
- break;
-
case SR_OP_MODIFIED:
- if (sr_xpath_node_name_eq(old_val->xpath, "interface")) {
- strncpy(old_interface, old_val->data.string_val,
- XPATH_SIZE);
- rc = set_route(ds, next_hop_index, old_interface, NULL,
- static_prefix, false);
- } else if (sr_xpath_node_name_eq(old_val->xpath,
- "subinterface")) {
- }
-
- if (sr_xpath_node_name_eq(new_val->xpath, "interface")) {
- strncpy(interface, new_val->data.string_val, XPATH_SIZE);
- rc = set_route(ds, next_hop_index, interface, NULL,
- static_prefix, true);
- } else if (sr_xpath_node_name_eq(new_val->xpath,
- "subinterface")) {
- }
- break;
-
- case SR_OP_MOVED:
+ case SR_OP_CREATED:
+ tmp = new;
break;
-
case SR_OP_DELETED:
- if (sr_xpath_node_name_eq(old_val->xpath, "interface")) {
- strncpy(old_interface, old_val->data.string_val,
- XPATH_SIZE);
- rc = set_route(ds, next_hop_index, old_interface, NULL,
- static_prefix, false);
- } else if (sr_xpath_node_name_eq(old_val->xpath,
- "subinterface")) {
- }
+ tmp = old;
+ break;
+ default:
+ SRP_LOG_WRN_MSG("Operation not supported");
break;
}
- if (SR_ERR_OK != rc) {
- sr_xpath_recover(&state);
+ if (sr_xpath_node_name_eq(tmp->xpath, "config")) {
+ SRP_LOG_DBG("xpath: %s", tmp->xpath);
+ } else if (sr_xpath_node_name_eq(tmp->xpath, "interface")) {
+ strncpy(interface, tmp->data.string_val, VPP_INTFC_NAME_LEN);
+ interface_set = true;
+ } else { //metric, recurse
+ SRP_LOG_ERR("Unsupported field %s", tmp->xpath);
+ return SR_ERR_UNSUPPORTED;
+ }
- sr_free_val(old_val);
- sr_free_val(new_val);
+ if (oper == SR_OP_CREATED && interface_set) {
+ rc = set_route(ds, index, interface, NULL, prefix, true);
+ interface_set = false;
+ } else if (oper == SR_OP_MODIFIED && interface_set) {
+ rc = set_route(ds, index, interface, NULL, prefix, false);
+ rc |= set_route(ds, index, interface, NULL, prefix, true);
+ interface_set = false;
+ } else if (oper == SR_OP_DELETED && interface_set) {
+ rc = set_route(ds, index, interface, NULL, prefix, false);
+ interface_set = false;
+ }
- sr_free_change_iter(it);
- return SR_ERR_OPERATION_FAILED;
+ if (rc != 0) {
+ SRP_LOG_ERR_MSG("setting route failed");
+ goto error;
}
+ sr_free_val(old);
+ sr_free_val(new);
sr_xpath_recover(&state);
-
- sr_free_val(old_val);
- sr_free_val(new_val);
}
sr_free_change_iter(it);
return SR_ERR_OK;
-}
-
-typedef struct
-{
- u8 length;
- u8 address[4];
-} address_prefix_t;
-
-typedef struct {
- char *next_hop_index;
- address_prefix_t address_prefix;
- const bool is_interface_ref;
- sw_interface_details_query_t sw_interface_details_query;
- sysr_values_ctx_t sysr_values_ctx;
-} sysr_ip_fib_details_ctx_t;
-
-static
-bool address_prefix_cmp(address_prefix_t* address_prefix,
- vapi_payload_ip_fib_details* reply)
-{
- ARG_CHECK2(false, address_prefix, reply);
-
- if (address_prefix->length == reply->address_length)
- {
- if (0 == memcmp(address_prefix->address, reply->address, sizeof(reply->address)))
- return true;
- }
-
- return false;
-}
-
-static
-bool address_prefix_init(address_prefix_t* address_prefix, char* str_prefix)
-{
- ARG_CHECK2(false, address_prefix, str_prefix);
-
- address_prefix->length = ip_prefix_split(str_prefix);
- if(address_prefix->length < 1)
- {
- SRP_LOG_ERR_MSG("not a valid prefix");
- return false;
- }
- return sc_aton(str_prefix, address_prefix->address,
- sizeof(address_prefix->address));
+error:
+ sr_free_val(old);
+ sr_free_val(new);
+ sr_xpath_recover(&state);
+ sr_free_change_iter(it);
+ return rc;
}
// XPATH: /openconfig-local-routing:local-routes/static-routes/static/state
-int openconfig_local_routing_local_routes_static_routes_static_state_vapi_cb(
- vapi_payload_ip_fib_details *reply,
- sysr_ip_fib_details_ctx_t *sysr_ip_fib_details_ctx)
+static int oc_prefix_state_cb(
+ const char *xpath, sr_val_t **values, size_t *values_cnt,
+ uint64_t request_id, const char *original_xpath, void *private_ctx)
{
+ UNUSED(request_id); UNUSED(original_xpath); UNUSED(private_ctx);
+ char prefix[VPP_IP4_PREFIX_STRING_LEN] = {0};
+ sr_xpath_ctx_t state = {0};
sr_val_t *vals = NULL;
+ fib_dump_t *reply = NULL;
+ int vc = 1;
int rc = 0;
- int vc = 0;
- char address_prefix[INET_ADDRSTRLEN + 3] = {0};
- vc = 1;
- ARG_CHECK2(SR_ERR_INVAL_ARG, reply, sysr_ip_fib_details_ctx);
+ ARG_CHECK3(SR_ERR_INVAL_ARG, xpath, values, values_cnt);
- rc = sr_new_values(vc, &vals);
- if (SR_ERR_OK != rc) {
- return rc;
- }
+ SRP_LOG_INF("In %s", __FUNCTION__);
- //Filling the structure
- snprintf(address_prefix, sizeof(address_prefix), "%s/%u",
- sc_ntoa(reply->address), reply->address_length);
+ rc = get_xpath_key(prefix, (char *)xpath, "static", "prefix",
+ VPP_IP4_PREFIX_STRING_LEN, &state);
+ if (rc != 0)
+ return SR_ERR_INVAL_ARG;
- sr_val_build_xpath(&vals[0], "%s/prefix",
- sysr_ip_fib_details_ctx->sysr_values_ctx.xpath_root);
- sr_val_set_str_data(&vals[0], SR_STRING_T, address_prefix);
+ rc = ipv4_fib_dump_prefix(prefix, &reply);
+ if (rc == -SCVPP_NOT_FOUND) {
+ SRP_LOG_ERR("Prefix %s not found in VPP FIB", prefix);
+ return SR_ERR_NOT_FOUND;
+ }
- sysr_ip_fib_details_ctx->sysr_values_ctx.values = vals;
- sysr_ip_fib_details_ctx->sysr_values_ctx.values_cnt = vc;
+ /* Allocation for number of elements dumped by ipv4_fib_dump_all */
+ rc = sr_new_values(vc, &vals);
+ if (SR_ERR_OK != rc)
+ return rc;
- return SR_ERR_OK;
-}
+ sr_val_build_xpath(&vals[0], "%s/prefix", xpath);
+ sr_val_set_str_data(&vals[0], SR_STRING_T, prefix);
-vapi_error_e
-ip_routing_dump_cb (struct vapi_ctx_s *ctx, void *callback_ctx,
- vapi_error_e rv, bool is_last,
- vapi_payload_ip_fib_details * reply)
-{
- if (is_last)
- {
- assert (NULL == reply);
- }
- else
- {
- sysr_ip_fib_details_ctx_t *dctx = callback_ctx;
- assert(dctx && reply);
+ sr_xpath_recover(&state);
- if (address_prefix_cmp(&dctx->address_prefix, reply))
- {
- openconfig_local_routing_local_routes_static_routes_static_state_vapi_cb(reply,
- dctx);
- }
- }
+ free(reply);
+ *values = vals;
+ *values_cnt = vc;
- return VAPI_OK;
+ return SR_ERR_OK;
}
-int openconfig_local_routing_local_routes_static_routes_static_state_cb(
- const char *xpath, sr_val_t **values, size_t *values_cnt,
- __attribute__((unused)) uint64_t request_id,
- __attribute__((unused)) const char *original_xpath,
- __attribute__((unused)) void *private_ctx)
+// XPATH /openconfig-local-routing:local-routes/static-routes/static/next-hops/next-hop/state
+static int
+oc_next_hop_state_cb(const char *xpath, sr_val_t **values, size_t *values_cnt,
+ uint64_t request_id, const char *original_xpath,
+ void *private_ctx)
{
+ UNUSED(request_id); UNUSED(original_xpath); UNUSED(private_ctx);
+ char prefix[VPP_IP4_PREFIX_STRING_LEN] = {0};
+ char index[HOP_INDEX_SIZE];
+ char next_hop[INET_ADDRSTRLEN] = {0};
+ fib_dump_t *reply = NULL;
sr_xpath_ctx_t state = {0};
- vapi_error_e rv = 0;
- char *tmp = NULL;
- char static_prefix[XPATH_SIZE] = {0};
- sysr_ip_fib_details_ctx_t dctx = {0};
+ sr_val_t *vals = NULL;
+ int vc = 3;
+ int rc = 0;
ARG_CHECK3(SR_ERR_INVAL_ARG, xpath, values, values_cnt);
- tmp = xpath_find_first_key(xpath, "prefix", &state);
- if (NULL == tmp) {
- SRP_LOG_ERR_MSG("static_prefix not found.");
- return SR_ERR_INVAL_ARG;
- }
+ SRP_LOG_INF("In %s", __FUNCTION__);
- strncpy(static_prefix, tmp, XPATH_SIZE);
- sr_xpath_recover(&state);
+ /* Get prefix and index key from XPATH */
+ rc = get_xpath_key(prefix, (char *)xpath, "static", "prefix",
+ VPP_IP4_PREFIX_STRING_LEN, &state);
- //VPP callback
- snprintf(dctx.sysr_values_ctx.xpath_root, XPATH_SIZE, "/openconfig-local-routing:local-routes/static-routes/static[prefix='%s']/state", static_prefix);
+ rc |= get_xpath_key(index, (char*)xpath, "next-hop", "index",
+ VPP_IP4_PREFIX_STRING_LEN, &state);
- if (!address_prefix_init(&dctx.address_prefix, static_prefix))
- {
+ if (rc != 0)
return SR_ERR_INVAL_ARG;
- }
-
- vapi_msg_ip_fib_dump *mp = vapi_alloc_ip_fib_dump (g_vapi_ctx_instance);
-
- VAPI_CALL(vapi_ip_fib_dump(g_vapi_ctx_instance, mp, ip_routing_dump_cb, &dctx));
- if(VAPI_OK != rv)
- {
- SRP_LOG_ERR_MSG("VAPI call failed");
+ rc = ipv4_fib_dump_prefix(prefix, &reply);
+ if (rc != SCVPP_OK) {
+ SRP_LOG_ERR("Fail to dump prefix %s", prefix);
return SR_ERR_INVAL_ARG;
}
- sr_xpath_recover(&state);
- *values = dctx.sysr_values_ctx.values;
- *values_cnt = dctx.sysr_values_ctx.values_cnt;
-
- return SR_ERR_OK;
-}
-
-// // XPATH: /openconfig-local-routing:local-routes/static-routes/l/next-hops/next-hop/state
-int openconfig_local_routing_local_routes_static_routes_static_next_hops_next_hop_state_vapi_cb(
- vapi_type_fib_path *reply,
- sysr_ip_fib_details_ctx_t *sysr_ip_fib_details_ctx)
-{
- sr_val_t *vals = NULL;
- int rc = 0;
- int vc = 0;
- char next_hop[INET_ADDRSTRLEN] = {0};
-
- ARG_CHECK2(SR_ERR_INVAL_ARG, reply, sysr_ip_fib_details_ctx);
-
- vc = 3;
- /* convenient functions such as this can be found in sysrepo/values.h */
rc = sr_new_values(vc, &vals);
- if (SR_ERR_OK != rc) {
+ if (SR_ERR_OK != rc)
return rc;
+
+ // check next hop index equals next hop id
+ if (strtoul(index, NULL, 0) != reply->path[0].next_hop_id) {
+ SRP_LOG_ERR("next hop index is %d for prefix %s",
+ reply->path[0].next_hop_id, prefix);
+ SRP_LOG_ERR("before %s, stroul is %d", index, strtoul(index, NULL, 0));
+ return SR_ERR_INVAL_ARG;
}
- sr_val_build_xpath(&vals[0], "%s/index",
- sysr_ip_fib_details_ctx->sysr_values_ctx.xpath_root);
- sr_val_set_str_data(&vals[0], SR_STRING_T,
- sysr_ip_fib_details_ctx->next_hop_index);
+ sr_val_build_xpath(&vals[0], "%s/index", xpath);
+ sr_val_set_str_data(&vals[0], SR_STRING_T, index);
- strncpy(next_hop, sc_ntoa(reply->next_hop), sizeof(next_hop));
- sr_val_build_xpath(&vals[1], "%s/next-hop", sysr_ip_fib_details_ctx->sysr_values_ctx.xpath_root);
- sr_val_set_str_data(&vals[1], SR_STRING_T, next_hop);
+ strncpy(next_hop, sc_ntoa(reply->path[0].next_hop), VPP_IP4_ADDRESS_LEN);
+ sr_val_build_xpath(&vals[1], "%s/next-hop", xpath);
+ sr_val_set_str_data(&vals[1], SR_STRING_T, (char *)reply->path[0].next_hop);
- sr_val_build_xpath(&vals[2], "%s/metric", sysr_ip_fib_details_ctx->sysr_values_ctx.xpath_root);
+ sr_val_build_xpath(&vals[2], "%s/metric", xpath);
vals[2].type = SR_UINT32_T;
- vals[2].data.uint32_val = reply->weight;
-
- // sr_val_build_xpath(&vals[3], "%s/recurse", sysr_ip_fib_details_ctx->sysr_values_ctx.xpath_root);
- // vals[3].type = SR_BOOL_T;
- // vals[3].data.bool_val = YANG INPUT TYPE: boolean;
+ vals[2].data.uint32_val = reply->path[0].weight;
- sysr_ip_fib_details_ctx->sysr_values_ctx.values = vals;
- sysr_ip_fib_details_ctx->sysr_values_ctx.values_cnt = vc;
+ free(reply);
+ sr_xpath_recover(&state);
+ *values = vals;
+ *values_cnt = vc;
return SR_ERR_OK;
}
-// // XPATH: /openconfig-local-routing:local-routes/static-routes/l/next-hops/next-hop/interface-ref/state
-int openconfig_local_routing_local_routes_static_routes_static_next_hops_next_hop_interface_ref_state_vapi_cb(
- sysr_ip_fib_details_ctx_t * dctx)
+// XPATH /openconfig-local-routing:local-routes/static-routes/static/next-hops/next-hop/interface-ref/state
+static int
+oc_next_hop_interface_state_cb(const char *xpath, sr_val_t **values,
+ size_t *values_cnt, uint64_t request_id,
+ const char *original_xpath, void *private_ctx)
{
+ UNUSED(request_id); UNUSED(original_xpath); UNUSED(private_ctx);
+ sr_xpath_ctx_t state = {0};
+ char prefix[VPP_IP4_PREFIX_STRING_LEN] = {0};
+ char interface[VPP_INTFC_NAME_LEN] = {0};
+ char index[HOP_INDEX_SIZE]; //next hop index
+ fib_dump_t *reply = NULL;
sr_val_t *vals = NULL;
+ int vc = 1;
int rc = 0;
- int vc = 0;
-
- ARG_CHECK(SR_ERR_INVAL_ARG, dctx);
-
- vc = 2;
- /* convenient functions such as this can be found in sysrepo/values.h */
- rc = sr_new_values(vc, &vals);
- if (SR_ERR_OK != rc) {
- return rc;
- }
- sr_val_build_xpath(&vals[0], "%s/interface",
- dctx->sysr_values_ctx.xpath_root);
- sr_val_set_str_data(&vals[0], SR_STRING_T,
- (const char*)dctx->sw_interface_details_query.sw_interface_details.interface_name);
+ //ARG_CHECK3(SR_ERR_INVAL_ARG, xpath, values, values_cnt);
- sr_val_build_xpath(&vals[1], "%s/subinterface",
- dctx->sysr_values_ctx.xpath_root);
- vals[1].type = SR_UINT32_T;
- vals[1].data.uint32_val = 0;
+ SRP_LOG_INF("In %s", __FUNCTION__);
- dctx->sysr_values_ctx.values = vals;
- dctx->sysr_values_ctx.values_cnt = vc;
+ ///* Get prefix key from XPATH */
+ rc = get_xpath_key(prefix, (char*) xpath, "static", "prefix",
+ VPP_IP4_PREFIX_STRING_LEN, &state);
- return SR_ERR_OK;
-}
-
-vapi_error_e
-ip_routing_next_hop_dump_cb (struct vapi_ctx_s *ctx, void *callback_ctx,
- vapi_error_e rv, bool is_last,
- vapi_payload_ip_fib_details * reply)
-{
- ARG_CHECK(VAPI_EINVAL, callback_ctx);
-
- sysr_ip_fib_details_ctx_t *dctx = callback_ctx;
-
- if (is_last)
- {
- assert (NULL == reply);
- }
- else
- {
- assert (NULL != reply);
-
- if (reply->count > 0 && address_prefix_cmp(&dctx->address_prefix, reply))
- {
- if (dctx->is_interface_ref)
- {
- dctx->sw_interface_details_query.interface_found = true;
- dctx->sw_interface_details_query.sw_interface_details.sw_if_index = reply->path[0].sw_if_index;
- //sw_interface_dump will have to be called outside this VAPI
- }
- else
- {
- openconfig_local_routing_local_routes_static_routes_static_next_hops_next_hop_state_vapi_cb(reply->path, dctx);
- }
- }
- }
-
- return VAPI_OK;
-}
-
-int next_hop_inner(
- bool is_interface_ref, const char *xpath, sr_val_t **values,
- size_t *values_cnt, __attribute__((unused)) uint64_t request_id,
- __attribute__((unused)) void *private_ctx)
-{
- sr_xpath_ctx_t state = {0};
- vapi_error_e rv;
- char *tmp = NULL;
- char static_prefix[XPATH_SIZE] = {0};
- char next_hop_index[XPATH_SIZE] = {0};
- sysr_ip_fib_details_ctx_t dctx = {.is_interface_ref = is_interface_ref};
-
- ARG_CHECK3(SR_ERR_INVAL_ARG, xpath, values, values_cnt);
+ rc |= get_xpath_key(index, (char *)xpath, "next-hop", "index",
+ HOP_INDEX_SIZE, &state);
- tmp = xpath_find_first_key(xpath, "prefix", &state);
- if (NULL == tmp) {
- SRP_LOG_ERR_MSG("static_prefix not found.");
+ if (rc != 0)
return SR_ERR_INVAL_ARG;
- }
- strncpy(static_prefix, tmp, XPATH_SIZE);
- sr_xpath_recover(&state);
- tmp = xpath_find_first_key(xpath, "index", &state);
- if (NULL == tmp) {
- SRP_LOG_ERR_MSG("index not found.");
+ rc = ipv4_fib_dump_prefix(prefix, &reply);
+ if (rc != SCVPP_OK) {
+ SRP_LOG_ERR("Fail to dump prefix %s", prefix);
return SR_ERR_INVAL_ARG;
}
- strncpy(next_hop_index, tmp, XPATH_SIZE);
- sr_xpath_recover(&state);
+ //TODO: check nhop?
- //VPP callback
- dctx.next_hop_index = next_hop_index;
- if (is_interface_ref) {
- snprintf(dctx.sysr_values_ctx.xpath_root, XPATH_SIZE,
- "/openconfig-local-routing:local-routes/static-routes/static[prefix='%s']/next-hops/next-hop[index='%s']/interface-ref/state",
- static_prefix, next_hop_index);
- } else {
- snprintf(dctx.sysr_values_ctx.xpath_root, XPATH_SIZE,
- "/openconfig-local-routing:local-routes/static-routes/static[prefix='%s']/next-hops/next-hop[index='%s']/state",
- static_prefix, next_hop_index);
- }
+ rc = sr_new_values(vc, &vals);
+ if (SR_ERR_OK != rc)
+ return rc;
- if (!address_prefix_init(&dctx.address_prefix, static_prefix))
- {
+ // check next hop index equals next hop id
+ if (strtoul(index, NULL, 0) != reply->path[0].next_hop_id) {
+ SRP_LOG_ERR("next hop index is %d for prefix %s",
+ reply->path[0].next_hop_id, prefix);
+ SRP_LOG_ERR("before %s, stroul is %d", index, strtoul(index, NULL, 0));
return SR_ERR_INVAL_ARG;
}
- vapi_msg_ip_fib_dump *mp = vapi_alloc_ip_fib_dump (g_vapi_ctx_instance);
- VAPI_CALL(vapi_ip_fib_dump(g_vapi_ctx_instance, mp, ip_routing_next_hop_dump_cb, &dctx));
- if (VAPI_OK != rv)
- {
- SRP_LOG_ERR_MSG("VAPI call failed");
+ rc = get_interface_name(interface, reply->path[0].sw_if_index);
+ if (rc != SCVPP_OK) {
+ SRP_LOG_ERR("No interface name for id %d", reply->path[0].sw_if_index);
return SR_ERR_INVAL_ARG;
}
- if (is_interface_ref)
- {
- if (dctx.sw_interface_details_query.interface_found)
- {
- if (!get_interface_name(&dctx.sw_interface_details_query))
- {
- return SR_ERR_INVAL_ARG;
- }
- if (strlen((const char*)
- dctx.sw_interface_details_query.sw_interface_details.interface_name)) {
- openconfig_local_routing_local_routes_static_routes_static_next_hops_next_hop_interface_ref_state_vapi_cb(&dctx);
- }
- }
- }
+ sr_val_build_xpath(&vals[0], "%s/interface", xpath);
+ sr_val_set_str_data(&vals[0], SR_STRING_T, interface);
+ free(reply);
sr_xpath_recover(&state);
- *values = dctx.sysr_values_ctx.values;
- *values_cnt = dctx.sysr_values_ctx.values_cnt;
+ *values = vals;
+ *values_cnt = vc;
return SR_ERR_OK;
}
-int openconfig_local_routing_local_routes_static_routes_static_next_hops_next_hop_state_cb(
- const char *xpath, sr_val_t **values, size_t *values_cnt,
- uint64_t request_id, const char *original_xpath, void *private_ctx)
-{
- return next_hop_inner(false, xpath, values, values_cnt, request_id,
- private_ctx);
-}
-
-int openconfig_local_routing_local_routes_static_routes_static_next_hops_next_hop_interface_ref_state_cb(
- const char *xpath, sr_val_t **values, size_t *values_cnt,
- uint64_t request_id, const char *original_xpath, void *private_ctx)
-{
- return next_hop_inner(true, xpath, values, values_cnt, request_id,
- private_ctx);
-}
-
const xpath_t oc_local_routing_xpaths[OC_LROUTING_SIZE] = {
{
- .xpath = "openconfig-local-routing",
- .method = MODULE,
+ .xpath = "/openconfig-local-routing:local-routes/static-routes/static/config",
+ .method = XPATH,
.datastore = SR_DS_RUNNING,
- .cb.mcb = openconfig_local_routing_mod_cb,
+ .cb.scb = oc_prefix_config_cb,
.private_ctx = NULL,
.priority = 0,
- //.opts = SR_SUBSCR_EV_ENABLED | SR_SUBSCR_APPLY_ONLY
- .opts = SR_SUBSCR_EV_ENABLED | SR_SUBSCR_APPLY_ONLY | SR_SUBSCR_CTX_REUSE
+ //.opts = SR_SUBSCR_DEFAULT
+ .opts = SR_SUBSCR_CTX_REUSE
},
{
.xpath = "/openconfig-local-routing:local-routes/static-routes/static/next-hops/next-hop/config",
.method = XPATH,
.datastore = SR_DS_RUNNING,
- .cb.scb = openconfig_local_routing_local_routes_static_routes_static_next_hops_next_hop_config_cb,
+ .cb.scb = oc_next_hop_config_cb,
.private_ctx = NULL,
.priority = 0,
//.opts = SR_SUBSCR_DEFAULT
@@ -752,7 +514,7 @@ const xpath_t oc_local_routing_xpaths[OC_LROUTING_SIZE] = {
.xpath = "/openconfig-local-routing:local-routes/static-routes/static/next-hops/next-hop/interface-ref/config",
.method = XPATH,
.datastore = SR_DS_RUNNING,
- .cb.scb = openconfig_local_routing_local_routes_static_routes_static_next_hops_next_hop_interface_ref_config_cb,
+ .cb.scb = oc_next_hop_interface_config_cb,
.private_ctx = NULL,
.priority = 0,
//.opts = SR_SUBSCR_DEFAULT
@@ -762,7 +524,7 @@ const xpath_t oc_local_routing_xpaths[OC_LROUTING_SIZE] = {
.xpath = "/openconfig-local-routing:local-routes/static-routes/static/state",
.method = GETITEM,
.datastore = SR_DS_RUNNING,
- .cb.gcb = openconfig_local_routing_local_routes_static_routes_static_state_cb,
+ .cb.gcb = oc_prefix_state_cb,
.private_ctx = NULL,
.priority = 0,
.opts = SR_SUBSCR_CTX_REUSE
@@ -771,7 +533,7 @@ const xpath_t oc_local_routing_xpaths[OC_LROUTING_SIZE] = {
.xpath = "/openconfig-local-routing:local-routes/static-routes/static/next-hops/next-hop/state",
.method = GETITEM,
.datastore = SR_DS_RUNNING,
- .cb.gcb = openconfig_local_routing_local_routes_static_routes_static_next_hops_next_hop_state_cb,
+ .cb.gcb = oc_next_hop_state_cb,
.private_ctx = NULL,
.priority = 0,
.opts = SR_SUBSCR_CTX_REUSE
@@ -780,7 +542,7 @@ const xpath_t oc_local_routing_xpaths[OC_LROUTING_SIZE] = {
.xpath = "/openconfig-local-routing:local-routes/static-routes/static/next-hops/next-hop/interface-ref/state",
.method = GETITEM,
.datastore = SR_DS_RUNNING,
- .cb.gcb = openconfig_local_routing_local_routes_static_routes_static_next_hops_next_hop_interface_ref_state_cb,
+ .cb.gcb = oc_next_hop_interface_state_cb,
.private_ctx = NULL,
.priority = 0,
.opts = SR_SUBSCR_CTX_REUSE
diff --git a/src/plugins/openconfig/openconfig_local_routing.h b/src/plugins/openconfig/openconfig_local_routing.h
deleted file mode 100644
index 13d2982..0000000
--- a/src/plugins/openconfig/openconfig_local_routing.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (c) 2018 PANTHEON.tech.
- *
- * 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.
- */
-
-#ifndef __OPENCONFIG_LOCAL_ROUTING_H__
-#define __OPENCONFIG_LOCAL_ROUTING_H__
-
-#include "../sc_model.h"
-
-#define OC_LROUTING_SIZE 6
-extern const xpath_t oc_local_routing_xpaths[OC_LROUTING_SIZE];
-
-#endif /* __OPENCONFIG_LOCAL_ROUTING_H__ */
diff --git a/src/plugins/sc_model.h b/src/plugins/sc_model.h
index ad4055b..a9392f9 100644
--- a/src/plugins/sc_model.h
+++ b/src/plugins/sc_model.h
@@ -29,7 +29,7 @@
#include <sysrepo/values.h>
#include <sysrepo/plugins.h>
-#include "sc_vpp_comm.h" //for ARG_CHECK only
+#include <scvpp/comm.h> //for ARG_CHECK only
typedef enum {
MODULE,
@@ -68,4 +68,18 @@ typedef struct {
int
model_register(plugin_main_t *plugin_main, const xpath_t *xpaths, size_t size);
+/* Declare registration */
+
+#define OC_INTERFACES_SIZE 5
+extern const xpath_t oc_interfaces_xpaths[OC_INTERFACES_SIZE];
+
+#define OC_LROUTING_SIZE 6
+extern const xpath_t oc_local_routing_xpaths[OC_LROUTING_SIZE];
+
+#define IETF_NAT_SIZE 2
+extern const xpath_t ietf_nat_xpaths[IETF_NAT_SIZE];
+
+#define IETF_INTERFACES_SIZE 5
+extern const xpath_t ietf_interfaces_xpaths[IETF_INTERFACES_SIZE];
+
#endif /* __SC_MODEL_H__ */
diff --git a/src/plugins/sc_plugins.c b/src/plugins/sc_plugins.c
index 87ea2d7..4dc6751 100644
--- a/src/plugins/sc_plugins.c
+++ b/src/plugins/sc_plugins.c
@@ -16,11 +16,6 @@
#include "sc_plugins.h"
#include "sc_model.h"
-#include "ietf/ietf_interface.h"
-#include "ietf/ietf_nat.h"
-#include "openconfig/openconfig_interfaces.h"
-#include "openconfig/openconfig_local_routing.h"
-
int sr_plugin_init_cb(sr_session_ctx_t *session, void **private_ctx)
{
plugin_main_t plugin_main;
diff --git a/src/plugins/sys_util.c b/src/plugins/sys_util.c
deleted file mode 100644
index a3ee0c9..0000000
--- a/src/plugins/sys_util.c
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
- * Copyright (c) 2018 PANTHEON.tech.
- *
- * 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 "sys_util.h"
-#include "sc_vpp_comm.h"
-
-#include <string.h>
-#include <sysrepo/plugins.h>
-
-char* xpath_find_first_key(const char *xpath, char *key, sr_xpath_ctx_t *state)
-{
- char *value = NULL;
-
- if (sr_xpath_next_node((char *)xpath, state) == NULL) {
- return NULL;
- }
-
- while (((value = sr_xpath_node_key_value(NULL,
- key, state)) == NULL) &&
- (sr_xpath_next_node(NULL, state) != NULL));
-
- return value;
-}
-
-// we can call sr_get_item after change is called to see if the value has or has not
-// changed (simpleton solution :D)
-// sr_get_item(sess, "/ietf-interfaces:interfaces/interface[name='eth0']/enabled", &value);
-
-void log_recv_event(sr_notif_event_t event, const char *msg) {
- const char *event_s;
- switch (event) {
- case SR_EV_VERIFY: event_s = "SR_EV_VERIFY"; break;
- case SR_EV_APPLY: event_s = "SR_EV_APPLY"; break;
- case SR_EV_ABORT: event_s = "SR_EV_ABORT"; break;
- default: event_s = "SR_EV_UNKNOWN";
- }
- SRP_LOG_DBG("%s: %s\n", msg, event_s);
-}
-
-void log_recv_oper(sr_change_oper_t oper, const char *msg) {
- const char *oper_s;
- switch (oper) {
- case SR_OP_CREATED: oper_s = "SR_OP_CREATED"; break;
- case SR_OP_DELETED: oper_s = "SR_OP_DELETED"; break;
- case SR_OP_MODIFIED: oper_s = "SR_OP_MODIFIED"; break;
- case SR_OP_MOVED: oper_s = "SR_OP_MOVED"; break;
- default: oper_s = "SR_OP_UNKNOWN"; break;
- }
- SRP_LOG_DBG("%s: %s\n", msg, oper_s);
-}
-
-int ip_prefix_split(const char* ip_prefix)
-{
- //find the slash
- char* slash = strchr(ip_prefix, '/');
- if (NULL == slash)
- return -1;
-
- //extract subnet mask length
- char * eptr = NULL;
- u8 mask = strtoul(slash + 1, &eptr, 10);
- if (*eptr || mask <= 0)
- return -1;
-
- //keep just the address part
- *slash = '\0'; //replace '/' with 0
-
- //return mask length
- return mask;
-}
-
-/**
- * @brief Get IPv4 host address from IPv4 prefix.
- *
- * @param[out] dst Host IPv4 address.
- * @param[in] src IPv4 Prefix.
- * @param[in] length dst buffer length.
- * @param[out] prefix Get Prefix length, optional value. Can be NULL.
- * @return -1 when failure, 0 on success.
- */
-int get_address_from_prefix(char *dst, const char *src, size_t length,
- uint8_t *prefix_length)
-{
- ARG_CHECK2(-1, src, dst);
-
- size_t size = 0;
- char *p = strchr(src, '/');
- if (NULL == p) {
- return -1;
- }
-
- size = p - src;
-
- // + 1, need size for \0
- if ((size + 1) > length) {
- return -1;
- }
-
- strncpy(dst, src, size);
-
- if (NULL != prefix_length) {
- *prefix_length = atoi(++p);
- }
-
- return 0;
-}
-
-/**
- * @brief Get IPv4 broadcast IP address form IPv4 network address.
- *
- * @param[out] broadcat Broadcast Ipv4 address.
- * @param[in] network Network IPv4 address.
- * @param[in] prefix Prefix number.
- * @return -1 when failure, 0 on success.
- */
-int get_network_broadcast(sc_ipv4_addr *broadcast, const sc_ipv4_addr *network,
- uint8_t prefix_length)
-{
- uint8_t mask = ~0;
- uint8_t tmp_p = prefix_length;
- int i;
-
- ARG_CHECK2(-1, network, broadcast);
-
- if (32 < prefix_length) {
- SRP_LOG_ERR_MSG("Prefix length to big.");
- return -1;
- }
-
- for (i = 0; i < 4 ; i++) {
- broadcast->address[i] = network->address[i] |
- (mask >> (tmp_p > 8 ? 8 : tmp_p));
- if (tmp_p >= 8) {
- tmp_p -= 8;
- } else {
- tmp_p = 0;
- }
- }
-
- return 0;
-}
-
-/**
- * @brief Get last IPv4 address from the IP range.
- *
- * @param[out] last_ip_address Last Ipv4 address.
- * @param[in] first_ip_address First IPv4 address.
- * @param[in] prefix Prefix number.
- * @return -1 when failure, 0 on success.
- */
-int get_last_ip_address(sc_ipv4_addr* last_ip_address,
- const sc_ipv4_addr* first_ip_address,
- uint8_t prefix_length)
-{
- return get_network_broadcast(last_ip_address, first_ip_address,
- prefix_length);
-}
diff --git a/src/plugins/sys_util.h b/src/plugins/sys_util.h
index d449712..692a012 100644
--- a/src/plugins/sys_util.h
+++ b/src/plugins/sys_util.h
@@ -19,20 +19,71 @@
#include <sysrepo.h>
#include <sysrepo/xpath.h>
+#include <sysrepo/plugins.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <string.h>
+
+#include <scvpp/comm.h>
+
+/* BEGIN sysrepo utils */
+
+#define foreach_change(ds, it, oper, old, new) \
+ while( (event != SR_EV_ABORT) && \
+ sr_get_change_next(ds, it, &oper, &old, &new) == SR_ERR_OK)
#define XPATH_SIZE 2000
+#define NOT_AVAL "NOT AVAILABLE"
+
+static inline int
+get_xpath_key(char *dst, char *xpath, char *node, char *key, int length,
+ sr_xpath_ctx_t *state) {
+ char *tmp;
+
+ tmp = sr_xpath_key_value(xpath, node, key, state);
+ if (!tmp) {
+ SRP_LOG_ERR("%s %s not found.", node, key);
+ return SR_ERR_INVAL_ARG;
+ }
+ strncpy(dst, tmp, length);
+ sr_xpath_recover(state);
+
+ return 0;
+}
+
+/* END of sysrepo utils */
typedef struct
{
- char xpath_root[XPATH_SIZE];
- sr_val_t * values;
- size_t values_cnt;
-} sysr_values_ctx_t;
+ uint8_t address[4];
+} sc_ipv4_addr;
-char* xpath_find_first_key(const char *xpath, char *key, sr_xpath_ctx_t *state);
-void log_recv_event(sr_notif_event_t event, const char *msg);
-void log_recv_oper(sr_change_oper_t oper, const char *msg);
-int ip_prefix_split(const char* ip_prefix);
+/**
+ * @brief Extract IP "AAA.BBB.CCC.DDD" from an IP prefix: "AAA.BBB.CCC.DDD/XX"
+ * @param prefix - IPv4 or IPv6 prefix:
+ * @return prefix length
+ */
+static inline int ip_prefix_split(const char* ip_prefix)
+{
+ //find the slash
+ char* slash = strchr(ip_prefix, '/');
+ if (NULL == slash)
+ return -1;
+
+ //extract subnet mask length
+ char * eptr = NULL;
+ uint8_t plen = strtoul(slash + 1, &eptr, 10);
+ if (*eptr || plen <= 0)
+ return -1;
+
+ //keep just the address part
+ *slash = '\0'; //replace '/' with 0
+
+ //return prefix length
+ return plen;
+}
/**
* @brief Get IPv4 host address from IPv4 prefix.
@@ -43,13 +94,61 @@ int ip_prefix_split(const char* ip_prefix);
* @param[out] prefix Get Prefix length, optional value. Can be NULL.
* @return -1 when failure, 0 on success.
*/
-int get_address_from_prefix(char* dst, const char* src, size_t length,
- uint8_t* prefix_length);
+static inline int
+prefix2address(char *dst, const char *src, uint8_t *prefix_length)
+{
+ if (!src || !dst)
+ return -1;
-typedef struct
+ char *p = strchr(src, '/');
+ if (!p)
+ return -1; // '/' not found
+
+ if ((p - src + 1) > VPP_IP4_ADDRESS_STRING_LEN) //+ 1 needed for \0
+ return -1;
+
+ strncpy(dst, src, VPP_IP4_ADDRESS_STRING_LEN);
+
+ if (!prefix_length)
+ *prefix_length = atoi(++p);
+
+ return 0;
+}
+
+/**
+ * @brief Helper function for converting netmask (ex: 255.255.255.0)
+ * to prefix length (ex: 24).
+ * @param netmask - string of netmask "AAA.BBB.CCC.DDD"
+ * @return prefix length
+ */
+static inline uint8_t netmask_to_prefix(const char *netmask)
{
- uint8_t address[4];
-} sc_ipv4_addr;
+ in_addr_t n = 0;
+ uint8_t i = 0;
+
+ inet_pton(AF_INET, netmask, &n);
+
+ while (n > 0) {
+ n = n >> 1;
+ i++;
+ }
+
+ return i;
+}
+
+/**
+ * @brief Convert prefix length to netmask
+ * @param prefix - prefix length (ex: 24)
+ * @return netmask - integer (ex: 111111111111111111111111100000000b )
+ */
+static inline uint32_t prefix2mask(int prefix)
+{
+ if (prefix) {
+ return htonl(~((1 << (32 - prefix)) - 1));
+ } else {
+ return htonl(0);
+ }
+}
/**
* @brief Get IPv4 broadcast IP address form IPv4 network address.
@@ -59,8 +158,32 @@ typedef struct
* @param[in] prefix Prefix number.
* @return -1 when failure, 0 on success.
*/
-int get_network_broadcast(sc_ipv4_addr *broadcast, const sc_ipv4_addr *network,
- uint8_t prefix_length);
+static inline int get_network_broadcast(sc_ipv4_addr *broadcast, const sc_ipv4_addr *network,
+ uint8_t prefix_length)
+{
+ uint8_t mask = ~0;
+ uint8_t tmp_p = prefix_length;
+ int i;
+
+ ARG_CHECK2(-1, network, broadcast);
+
+ if (32 < prefix_length) {
+ SRP_LOG_ERR_MSG("Prefix length to big.");
+ return -1;
+ }
+
+ for (i = 0; i < 4 ; i++) {
+ broadcast->address[i] = network->address[i] |
+ (mask >> (tmp_p > 8 ? 8 : tmp_p));
+ if (tmp_p >= 8) {
+ tmp_p -= 8;
+ } else {
+ tmp_p = 0;
+ }
+ }
+
+ return 0;
+}
/**
* @brief Get last IPv4 address from the IP range.
@@ -70,8 +193,12 @@ int get_network_broadcast(sc_ipv4_addr *broadcast, const sc_ipv4_addr *network,
* @param[in] prefix Prefix number.
* @return -1 when failure, 0 on success.
*/
-int get_last_ip_address(sc_ipv4_addr *last_ip_address,
- const sc_ipv4_addr *first_ip_address,
- uint8_t prefix_length);
+static inline int get_last_ip_address(sc_ipv4_addr* last_ip_address,
+ const sc_ipv4_addr* first_ip_address,
+ uint8_t prefix_length)
+{
+ return get_network_broadcast(last_ip_address, first_ip_address,
+ prefix_length);
+}
#endif /* __SYS_UTIL_H__ */
diff --git a/src/plugins/yang/ietf-interfaces.data.xml b/src/plugins/yang/ietf-interfaces.data.xml
deleted file mode 100644
index 3aae96e..0000000
--- a/src/plugins/yang/ietf-interfaces.data.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<interfaces xmlns="urn:ietf:params:xml:ns:yang:ietf-interfaces">
- <interface>
- <name>GigabitEthernet0/8/0</name>
- <description>Ethernet 8</description>
- <type>ethernetCsmacd</type>
- <enabled>true</enabled>
- <ipv4 xmlns="urn:ietf:params:xml:ns:yang:ietf-ip">
- <address>
- <ip>192.168.2.100</ip>
- <prefix-length>24</prefix-length>
- </address>
- </ipv4>
- <ipv6 xmlns="urn:ietf:params:xml:ns:yang:ietf-ip">
- <address>
- <ip>2001:db8::10</ip>
- <prefix-length>32</prefix-length>
- </address>
- </ipv6>
- </interface>
-</interfaces>
-
diff --git a/src/plugins/yang/ietf/iana-if-type@2017-01-19.yang b/src/plugins/yang/ietf/iana-if-type@2017-01-19.yang
new file mode 100644
index 0000000..7bfee36
--- /dev/null
+++ b/src/plugins/yang/ietf/iana-if-type@2017-01-19.yang
@@ -0,0 +1,1619 @@
+module iana-if-type {
+ namespace "urn:ietf:params:xml:ns:yang:iana-if-type";
+ prefix ianaift;
+
+ import ietf-interfaces {
+ prefix if;
+ }
+
+ organization "IANA";
+ contact
+ " Internet Assigned Numbers Authority
+
+ Postal: ICANN
+ 12025 Waterfront Drive, Suite 300
+ Los Angeles, CA 90094-2536
+ United States
+
+ Tel: +1 310 301 5800
+ <mailto:iana&iana.org>";
+ description
+ "This YANG module defines YANG identities for IANA-registered
+ interface types.
+
+ This YANG module is maintained by IANA and reflects the
+ 'ifType definitions' registry.
+
+ The latest revision of this YANG module can be obtained from
+ the IANA web site.
+
+ Requests for new values should be made to IANA via
+ email (iana&iana.org).
+
+ Copyright (c) 2014 IETF Trust and the persons identified as
+ authors of the code. All rights reserved.
+
+ Redistribution and use in source and binary forms, with or
+ without modification, is permitted pursuant to, and subject
+ to the license terms contained in, the Simplified BSD License
+ set forth in Section 4.c of the IETF Trust's Legal Provisions
+ Relating to IETF Documents
+ (http://trustee.ietf.org/license-info).
+
+ The initial version of this YANG module is part of RFC 7224;
+ see the RFC itself for full legal notices.";
+ reference
+ "IANA 'ifType definitions' registry.
+ <http://www.iana.org/assignments/smi-numbers>";
+
+ revision 2017-01-19 {
+ description
+ "Registered ifType 289.";
+ }
+
+ revision 2016-11-23 {
+ description
+ "Registered ifTypes 283-288.";
+ }
+
+ revision 2016-06-09 {
+ description
+ "Registered ifType 282.";
+ }
+ revision 2016-05-03 {
+ description
+ "Registered ifType 281.";
+ }
+ revision 2015-06-12 {
+ description
+ "Corrected formatting issue.";
+ }
+ revision 2014-09-24 {
+ description
+ "Registered ifType 280.";
+ }
+ revision 2014-09-19 {
+ description
+ "Registered ifType 279.";
+ }
+ revision 2014-07-03 {
+ description
+ "Registered ifTypes 277-278.";
+ }
+ revision 2014-05-19 {
+ description
+ "Updated the contact address.";
+ }
+ revision 2014-05-08 {
+ description
+ "Initial revision.";
+ reference
+ "RFC 7224: IANA Interface Type YANG Module";
+ }
+
+ identity iana-interface-type {
+ base if:interface-type;
+ description
+ "This identity is used as a base for all interface types
+ defined in the 'ifType definitions' registry.";
+ }
+
+ identity other {
+ base iana-interface-type;
+ }
+ identity regular1822 {
+ base iana-interface-type;
+ }
+ identity hdh1822 {
+ base iana-interface-type;
+ }
+ identity ddnX25 {
+ base iana-interface-type;
+ }
+ identity rfc877x25 {
+ base iana-interface-type;
+ reference
+ "RFC 1382 - SNMP MIB Extension for the X.25 Packet Layer";
+ }
+ identity ethernetCsmacd {
+ base iana-interface-type;
+ description
+ "For all Ethernet-like interfaces, regardless of speed,
+ as per RFC 3635.";
+ reference
+ "RFC 3635 - Definitions of Managed Objects for the
+ Ethernet-like Interface Types";
+ }
+ identity iso88023Csmacd {
+ base iana-interface-type;
+ status deprecated;
+ description
+ "Deprecated via RFC 3635.
+ Use ethernetCsmacd(6) instead.";
+ reference
+ "RFC 3635 - Definitions of Managed Objects for the
+ Ethernet-like Interface Types";
+ }
+ identity iso88024TokenBus {
+ base iana-interface-type;
+ }
+ identity iso88025TokenRing {
+ base iana-interface-type;
+ }
+ identity iso88026Man {
+ base iana-interface-type;
+ }
+ identity starLan {
+ base iana-interface-type;
+ status deprecated;
+ description
+ "Deprecated via RFC 3635.
+ Use ethernetCsmacd(6) instead.";
+ reference
+ "RFC 3635 - Definitions of Managed Objects for the
+ Ethernet-like Interface Types";
+ }
+ identity proteon10Mbit {
+ base iana-interface-type;
+ }
+ identity proteon80Mbit {
+ base iana-interface-type;
+ }
+ identity hyperchannel {
+ base iana-interface-type;
+ }
+ identity fddi {
+ base iana-interface-type;
+ reference
+ "RFC 1512 - FDDI Management Information Base";
+ }
+ identity lapb {
+ base iana-interface-type;
+ reference
+ "RFC 1381 - SNMP MIB Extension for X.25 LAPB";
+ }
+ identity sdlc {
+ base iana-interface-type;
+ }
+ identity ds1 {
+ base iana-interface-type;
+ description
+ "DS1-MIB.";
+ reference
+ "RFC 4805 - Definitions of Managed Objects for the
+ DS1, J1, E1, DS2, and E2 Interface Types";
+ }
+ identity e1 {
+ base iana-interface-type;
+ status obsolete;
+ description
+ "Obsolete; see DS1-MIB.";
+ reference
+ "RFC 4805 - Definitions of Managed Objects for the
+ DS1, J1, E1, DS2, and E2 Interface Types";
+ }
+ identity basicISDN {
+ base iana-interface-type;
+ description
+ "No longer used. See also RFC 2127.";
+ }
+ identity primaryISDN {
+ base iana-interface-type;
+ description
+ "No longer used. See also RFC 2127.";
+ }
+ identity propPointToPointSerial {
+ base iana-interface-type;
+ description
+ "Proprietary serial.";
+ }
+ identity ppp {
+ base iana-interface-type;
+ }
+ identity softwareLoopback {
+ base iana-interface-type;
+ }
+ identity eon {
+ base iana-interface-type;
+ description
+ "CLNP over IP.";
+ }
+ identity ethernet3Mbit {
+ base iana-interface-type;
+ }
+ identity nsip {
+ base iana-interface-type;
+ description
+ "XNS over IP.";
+ }
+ identity slip {
+ base iana-interface-type;
+ description
+ "Generic SLIP.";
+ }
+ identity ultra {
+ base iana-interface-type;
+ description
+ "Ultra Technologies.";
+ }
+ identity ds3 {
+ base iana-interface-type;
+ description
+ "DS3-MIB.";
+ reference
+ "RFC 3896 - Definitions of Managed Objects for the
+ DS3/E3 Interface Type";
+ }
+ identity sip {
+ base iana-interface-type;
+ description
+ "SMDS, coffee.";
+ reference
+ "RFC 1694 - Definitions of Managed Objects for SMDS
+ Interfaces using SMIv2";
+ }
+ identity frameRelay {
+ base iana-interface-type;
+ description
+ "DTE only.";
+ reference
+ "RFC 2115 - Management Information Base for Frame Relay
+ DTEs Using SMIv2";
+ }
+ identity rs232 {
+ base iana-interface-type;
+ reference
+ "RFC 1659 - Definitions of Managed Objects for RS-232-like
+ Hardware Devices using SMIv2";
+ }
+ identity para {
+ base iana-interface-type;
+ description
+ "Parallel-port.";
+ reference
+ "RFC 1660 - Definitions of Managed Objects for
+ Parallel-printer-like Hardware Devices using
+ SMIv2";
+ }
+ identity arcnet {
+ base iana-interface-type;
+ description
+ "ARCnet.";
+ }
+ identity arcnetPlus {
+ base iana-interface-type;
+ description
+ "ARCnet Plus.";
+ }
+ identity atm {
+ base iana-interface-type;
+ description
+ "ATM cells.";
+ }
+ identity miox25 {
+ base iana-interface-type;
+ reference
+ "RFC 1461 - SNMP MIB extension for Multiprotocol
+ Interconnect over X.25";
+ }
+ identity sonet {
+ base iana-interface-type;
+ description
+ "SONET or SDH.";
+ }
+ identity x25ple {
+ base iana-interface-type;
+ reference
+ "RFC 2127 - ISDN Management Information Base using SMIv2";
+ }
+ identity iso88022llc {
+ base iana-interface-type;
+ }
+ identity localTalk {
+ base iana-interface-type;
+ }
+ identity smdsDxi {
+ base iana-interface-type;
+ }
+ identity frameRelayService {
+ base iana-interface-type;
+ description
+ "FRNETSERV-MIB.";
+ reference
+ "RFC 2954 - Definitions of Managed Objects for Frame
+ Relay Service";
+ }
+ identity v35 {
+ base iana-interface-type;
+ }
+ identity hssi {
+ base iana-interface-type;
+ }
+ identity hippi {
+ base iana-interface-type;
+ }
+ identity modem {
+ base iana-interface-type;
+ description
+ "Generic modem.";
+ }
+ identity aal5 {
+ base iana-interface-type;
+ description
+ "AAL5 over ATM.";
+ }
+ identity sonetPath {
+ base iana-interface-type;
+ }
+ identity sonetVT {
+ base iana-interface-type;
+ }
+ identity smdsIcip {
+ base iana-interface-type;
+ description
+ "SMDS InterCarrier Interface.";
+ }
+ identity propVirtual {
+ base iana-interface-type;
+ description
+ "Proprietary virtual/internal.";
+ reference
+ "RFC 2863 - The Interfaces Group MIB";
+ }
+ identity propMultiplexor {
+ base iana-interface-type;
+ description
+ "Proprietary multiplexing.";
+ reference
+ "RFC 2863 - The Interfaces Group MIB";
+ }
+ identity ieee80212 {
+ base iana-interface-type;
+ description
+ "100BaseVG.";
+ }
+ identity fibreChannel {
+ base iana-interface-type;
+ description
+ "Fibre Channel.";
+ }
+ identity hippiInterface {
+ base iana-interface-type;
+ description
+ "HIPPI interfaces.";
+ }
+ identity frameRelayInterconnect {
+ base iana-interface-type;
+ status obsolete;
+ description
+ "Obsolete; use either
+ frameRelay(32) or frameRelayService(44).";
+ }
+ identity aflane8023 {
+ base iana-interface-type;
+ description
+ "ATM Emulated LAN for 802.3.";
+ }
+ identity aflane8025 {
+ base iana-interface-type;
+ description
+ "ATM Emulated LAN for 802.5.";
+ }
+ identity cctEmul {
+ base iana-interface-type;
+ description
+ "ATM Emulated circuit.";
+ }
+ identity fastEther {
+ base iana-interface-type;
+ status deprecated;
+ description
+ "Obsoleted via RFC 3635.
+ ethernetCsmacd(6) should be used instead.";
+ reference
+ "RFC 3635 - Definitions of Managed Objects for the
+ Ethernet-like Interface Types";
+ }
+ identity isdn {
+ base iana-interface-type;
+ description
+ "ISDN and X.25.";
+ reference
+ "RFC 1356 - Multiprotocol Interconnect on X.25 and ISDN
+ in the Packet Mode";
+ }
+ identity v11 {
+ base iana-interface-type;
+ description
+ "CCITT V.11/X.21.";
+ }
+ identity v36 {
+ base iana-interface-type;
+ description
+ "CCITT V.36.";
+ }
+ identity g703at64k {
+ base iana-interface-type;
+ description
+ "CCITT G703 at 64Kbps.";
+ }
+ identity g703at2mb {
+ base iana-interface-type;
+ status obsolete;
+ description
+ "Obsolete; see DS1-MIB.";
+ }
+ identity qllc {
+ base iana-interface-type;
+ description
+ "SNA QLLC.";
+ }
+ identity fastEtherFX {
+ base iana-interface-type;
+ status deprecated;
+ description
+ "Obsoleted via RFC 3635.
+ ethernetCsmacd(6) should be used instead.";
+ reference
+ "RFC 3635 - Definitions of Managed Objects for the
+ Ethernet-like Interface Types";
+ }
+ identity channel {
+ base iana-interface-type;
+ description
+ "Channel.";
+ }
+ identity ieee80211 {
+ base iana-interface-type;
+ description
+ "Radio spread spectrum.";
+ }
+ identity ibm370parChan {
+ base iana-interface-type;
+ description
+ "IBM System 360/370 OEMI Channel.";
+ }
+ identity escon {
+ base iana-interface-type;
+ description
+ "IBM Enterprise Systems Connection.";
+ }
+ identity dlsw {
+ base iana-interface-type;
+ description
+ "Data Link Switching.";
+ }
+ identity isdns {
+ base iana-interface-type;
+ description
+ "ISDN S/T interface.";
+ }
+ identity isdnu {
+ base iana-interface-type;
+ description
+ "ISDN U interface.";
+ }
+ identity lapd {
+ base iana-interface-type;
+ description
+ "Link Access Protocol D.";
+ }
+ identity ipSwitch {
+ base iana-interface-type;
+ description
+ "IP Switching Objects.";
+ }
+ identity rsrb {
+ base iana-interface-type;
+ description
+ "Remote Source Route Bridging.";
+ }
+ identity atmLogical {
+ base iana-interface-type;
+ description
+ "ATM Logical Port.";
+ reference
+ "RFC 3606 - Definitions of Supplemental Managed Objects
+ for ATM Interface";
+ }
+ identity ds0 {
+ base iana-interface-type;
+ description
+ "Digital Signal Level 0.";
+ reference
+ "RFC 2494 - Definitions of Managed Objects for the DS0
+ and DS0 Bundle Interface Type";
+ }
+ identity ds0Bundle {
+ base iana-interface-type;
+ description
+ "Group of ds0s on the same ds1.";
+ reference
+ "RFC 2494 - Definitions of Managed Objects for the DS0
+ and DS0 Bundle Interface Type";
+ }
+ identity bsc {
+ base iana-interface-type;
+ description
+ "Bisynchronous Protocol.";
+ }
+ identity async {
+ base iana-interface-type;
+ description
+ "Asynchronous Protocol.";
+ }
+ identity cnr {
+ base iana-interface-type;
+ description
+ "Combat Net Radio.";
+ }
+ identity iso88025Dtr {
+ base iana-interface-type;
+ description
+ "ISO 802.5r DTR.";
+ }
+ identity eplrs {
+ base iana-interface-type;
+ description
+ "Ext Pos Loc Report Sys.";
+ }
+ identity arap {
+ base iana-interface-type;
+ description
+ "Appletalk Remote Access Protocol.";
+ }
+ identity propCnls {
+ base iana-interface-type;
+ description
+ "Proprietary Connectionless Protocol.";
+ }
+ identity hostPad {
+ base iana-interface-type;
+ description
+ "CCITT-ITU X.29 PAD Protocol.";
+ }
+ identity termPad {
+ base iana-interface-type;
+ description
+ "CCITT-ITU X.3 PAD Facility.";
+ }
+ identity frameRelayMPI {
+ base iana-interface-type;
+ description
+ "Multiproto Interconnect over FR.";
+ }
+ identity x213 {
+ base iana-interface-type;
+ description
+ "CCITT-ITU X213.";
+ }
+ identity adsl {
+ base iana-interface-type;
+ description
+ "Asymmetric Digital Subscriber Loop.";
+ }
+ identity radsl {
+ base iana-interface-type;
+ description
+ "Rate-Adapt. Digital Subscriber Loop.";
+ }
+ identity sdsl {
+ base iana-interface-type;
+ description
+ "Symmetric Digital Subscriber Loop.";
+ }
+ identity vdsl {
+ base iana-interface-type;
+ description
+ "Very H-Speed Digital Subscrib. Loop.";
+ }
+ identity iso88025CRFPInt {
+ base iana-interface-type;
+ description
+ "ISO 802.5 CRFP.";
+ }
+ identity myrinet {
+ base iana-interface-type;
+ description
+ "Myricom Myrinet.";
+ }
+ identity voiceEM {
+ base iana-interface-type;
+ description
+ "Voice recEive and transMit.";
+ }
+ identity voiceFXO {
+ base iana-interface-type;
+ description
+ "Voice Foreign Exchange Office.";
+ }
+ identity voiceFXS {
+ base iana-interface-type;
+ description
+ "Voice Foreign Exchange Station.";
+ }
+ identity voiceEncap {
+ base iana-interface-type;
+ description
+ "Voice encapsulation.";
+ }
+ identity voiceOverIp {
+ base iana-interface-type;
+ description
+ "Voice over IP encapsulation.";
+ }
+ identity atmDxi {
+ base iana-interface-type;
+ description
+ "ATM DXI.";
+ }
+ identity atmFuni {
+ base iana-interface-type;
+ description
+ "ATM FUNI.";
+ }
+ identity atmIma {
+ base iana-interface-type;
+ description
+ "ATM IMA.";
+ }
+ identity pppMultilinkBundle {
+ base iana-interface-type;
+ description
+ "PPP Multilink Bundle.";
+ }
+ identity ipOverCdlc {
+ base iana-interface-type;
+ description
+ "IBM ipOverCdlc.";
+ }
+ identity ipOverClaw {
+ base iana-interface-type;
+ description
+ "IBM Common Link Access to Workstn.";
+ }
+ identity stackToStack {
+ base iana-interface-type;
+ description
+ "IBM stackToStack.";
+ }
+ identity virtualIpAddress {
+ base iana-interface-type;
+ description
+ "IBM VIPA.";
+ }
+ identity mpc {
+ base iana-interface-type;
+ description
+ "IBM multi-protocol channel support.";
+ }
+ identity ipOverAtm {
+ base iana-interface-type;
+ description
+ "IBM ipOverAtm.";
+ reference
+ "RFC 2320 - Definitions of Managed Objects for Classical IP
+ and ARP Over ATM Using SMIv2 (IPOA-MIB)";
+ }
+ identity iso88025Fiber {
+ base iana-interface-type;
+ description
+ "ISO 802.5j Fiber Token Ring.";
+ }
+ identity tdlc {
+ base iana-interface-type;
+ description
+ "IBM twinaxial data link control.";
+ }
+ identity gigabitEthernet {
+ base iana-interface-type;
+ status deprecated;
+ description
+ "Obsoleted via RFC 3635.
+ ethernetCsmacd(6) should be used instead.";
+ reference
+ "RFC 3635 - Definitions of Managed Objects for the
+ Ethernet-like Interface Types";
+ }
+ identity hdlc {
+ base iana-interface-type;
+ description
+ "HDLC.";
+ }
+ identity lapf {
+ base iana-interface-type;
+ description
+ "LAP F.";
+ }
+ identity v37 {
+ base iana-interface-type;
+ description
+ "V.37.";
+ }
+ identity x25mlp {
+ base iana-interface-type;
+ description
+ "Multi-Link Protocol.";
+ }
+ identity x25huntGroup {
+ base iana-interface-type;
+ description
+ "X25 Hunt Group.";
+ }
+ identity transpHdlc {
+ base iana-interface-type;
+ description
+ "Transp HDLC.";
+ }
+ identity interleave {
+ base iana-interface-type;
+ description
+ "Interleave channel.";
+ }
+ identity fast {
+ base iana-interface-type;
+ description
+ "Fast channel.";
+ }
+ identity ip {
+ base iana-interface-type;
+ description
+ "IP (for APPN HPR in IP networks).";
+ }
+ identity docsCableMaclayer {
+ base iana-interface-type;
+ description
+ "CATV Mac Layer.";
+ }
+ identity docsCableDownstream {
+ base iana-interface-type;
+ description
+ "CATV Downstream interface.";
+ }
+ identity docsCableUpstream {
+ base iana-interface-type;
+ description
+ "CATV Upstream interface.";
+ }
+ identity a12MppSwitch {
+ base iana-interface-type;
+ description
+ "Avalon Parallel Processor.";
+ }
+ identity tunnel {
+ base iana-interface-type;
+ description
+ "Encapsulation interface.";
+ }
+ identity coffee {
+ base iana-interface-type;
+ description
+ "Coffee pot.";
+ reference
+ "RFC 2325 - Coffee MIB";
+ }
+ identity ces {
+ base iana-interface-type;
+ description
+ "Circuit Emulation Service.";
+ }
+ identity atmSubInterface {
+ base iana-interface-type;
+ description
+ "ATM Sub Interface.";
+ }
+ identity l2vlan {
+ base iana-interface-type;
+ description
+ "Layer 2 Virtual LAN using 802.1Q.";
+ }
+ identity l3ipvlan {
+ base iana-interface-type;
+ description
+ "Layer 3 Virtual LAN using IP.";
+ }
+ identity l3ipxvlan {
+ base iana-interface-type;
+ description
+ "Layer 3 Virtual LAN using IPX.";
+ }
+ identity digitalPowerline {
+ base iana-interface-type;
+ description
+ "IP over Power Lines.";
+ }
+ identity mediaMailOverIp {
+ base iana-interface-type;
+ description
+ "Multimedia Mail over IP.";
+ }
+ identity dtm {
+ base iana-interface-type;
+ description
+ "Dynamic synchronous Transfer Mode.";
+ }
+ identity dcn {
+ base iana-interface-type;
+ description
+ "Data Communications Network.";
+ }
+ identity ipForward {
+ base iana-interface-type;
+ description
+ "IP Forwarding Interface.";
+ }
+ identity msdsl {
+ base iana-interface-type;
+ description
+ "Multi-rate Symmetric DSL.";
+ }
+ identity ieee1394 {
+ base iana-interface-type;
+
+ description
+ "IEEE1394 High Performance Serial Bus.";
+ }
+ identity if-gsn {
+ base iana-interface-type;
+ description
+ "HIPPI-6400.";
+ }
+ identity dvbRccMacLayer {
+ base iana-interface-type;
+ description
+ "DVB-RCC MAC Layer.";
+ }
+ identity dvbRccDownstream {
+ base iana-interface-type;
+ description
+ "DVB-RCC Downstream Channel.";
+ }
+ identity dvbRccUpstream {
+ base iana-interface-type;
+ description
+ "DVB-RCC Upstream Channel.";
+ }
+ identity atmVirtual {
+ base iana-interface-type;
+ description
+ "ATM Virtual Interface.";
+ }
+ identity mplsTunnel {
+ base iana-interface-type;
+ description
+ "MPLS Tunnel Virtual Interface.";
+ }
+ identity srp {
+ base iana-interface-type;
+ description
+ "Spatial Reuse Protocol.";
+ }
+ identity voiceOverAtm {
+ base iana-interface-type;
+ description
+ "Voice over ATM.";
+ }
+ identity voiceOverFrameRelay {
+ base iana-interface-type;
+ description
+ "Voice Over Frame Relay.";
+ }
+ identity idsl {
+ base iana-interface-type;
+ description
+ "Digital Subscriber Loop over ISDN.";
+ }
+ identity compositeLink {
+ base iana-interface-type;
+ description
+ "Avici Composite Link Interface.";
+ }
+ identity ss7SigLink {
+ base iana-interface-type;
+ description
+ "SS7 Signaling Link.";
+ }
+ identity propWirelessP2P {
+ base iana-interface-type;
+ description
+ "Prop. P2P wireless interface.";
+ }
+ identity frForward {
+ base iana-interface-type;
+ description
+ "Frame Forward Interface.";
+ }
+ identity rfc1483 {
+ base iana-interface-type;
+ description
+ "Multiprotocol over ATM AAL5.";
+ reference
+ "RFC 1483 - Multiprotocol Encapsulation over ATM
+ Adaptation Layer 5";
+ }
+ identity usb {
+ base iana-interface-type;
+ description
+ "USB Interface.";
+ }
+ identity ieee8023adLag {
+ base iana-interface-type;
+ description
+ "IEEE 802.3ad Link Aggregate.";
+ }
+ identity bgppolicyaccounting {
+ base iana-interface-type;
+ description
+ "BGP Policy Accounting.";
+ }
+ identity frf16MfrBundle {
+ base iana-interface-type;
+ description
+ "FRF.16 Multilink Frame Relay.";
+ }
+ identity h323Gatekeeper {
+ base iana-interface-type;
+ description
+ "H323 Gatekeeper.";
+ }
+ identity h323Proxy {
+ base iana-interface-type;
+ description
+ "H323 Voice and Video Proxy.";
+ }
+ identity mpls {
+ base iana-interface-type;
+ description
+ "MPLS.";
+ }
+ identity mfSigLink {
+ base iana-interface-type;
+ description
+ "Multi-frequency signaling link.";
+ }
+ identity hdsl2 {
+ base iana-interface-type;
+ description
+ "High Bit-Rate DSL - 2nd generation.";
+ }
+ identity shdsl {
+ base iana-interface-type;
+ description
+ "Multirate HDSL2.";
+ }
+ identity ds1FDL {
+ base iana-interface-type;
+ description
+ "Facility Data Link (4Kbps) on a DS1.";
+ }
+ identity pos {
+ base iana-interface-type;
+ description
+ "Packet over SONET/SDH Interface.";
+ }
+ identity dvbAsiIn {
+ base iana-interface-type;
+ description
+ "DVB-ASI Input.";
+ }
+ identity dvbAsiOut {
+ base iana-interface-type;
+ description
+ "DVB-ASI Output.";
+ }
+ identity plc {
+ base iana-interface-type;
+ description
+ "Power Line Communications.";
+ }
+ identity nfas {
+ base iana-interface-type;
+ description
+ "Non-Facility Associated Signaling.";
+ }
+ identity tr008 {
+ base iana-interface-type;
+ description
+ "TR008.";
+ }
+ identity gr303RDT {
+ base iana-interface-type;
+ description
+ "Remote Digital Terminal.";
+ }
+ identity gr303IDT {
+ base iana-interface-type;
+ description
+ "Integrated Digital Terminal.";
+ }
+ identity isup {
+ base iana-interface-type;
+ description
+ "ISUP.";
+ }
+ identity propDocsWirelessMaclayer {
+ base iana-interface-type;
+ description
+ "Cisco proprietary Maclayer.";
+ }
+ identity propDocsWirelessDownstream {
+ base iana-interface-type;
+ description
+ "Cisco proprietary Downstream.";
+ }
+ identity propDocsWirelessUpstream {
+ base iana-interface-type;
+ description
+ "Cisco proprietary Upstream.";
+ }
+ identity hiperlan2 {
+ base iana-interface-type;
+ description
+ "HIPERLAN Type 2 Radio Interface.";
+ }
+ identity propBWAp2Mp {
+ base iana-interface-type;
+ description
+ "PropBroadbandWirelessAccesspt2Multipt (use of this value
+ for IEEE 802.16 WMAN interfaces as per IEEE Std 802.16f
+ is deprecated, and ieee80216WMAN(237) should be used
+ instead).";
+ }
+ identity sonetOverheadChannel {
+ base iana-interface-type;
+ description
+ "SONET Overhead Channel.";
+ }
+ identity digitalWrapperOverheadChannel {
+ base iana-interface-type;
+ description
+ "Digital Wrapper.";
+ }
+ identity aal2 {
+ base iana-interface-type;
+ description
+ "ATM adaptation layer 2.";
+ }
+ identity radioMAC {
+ base iana-interface-type;
+ description
+ "MAC layer over radio links.";
+ }
+ identity atmRadio {
+ base iana-interface-type;
+ description
+ "ATM over radio links.";
+ }
+ identity imt {
+ base iana-interface-type;
+ description
+ "Inter-Machine Trunks.";
+ }
+ identity mvl {
+ base iana-interface-type;
+ description
+ "Multiple Virtual Lines DSL.";
+ }
+ identity reachDSL {
+ base iana-interface-type;
+ description
+ "Long Reach DSL.";
+ }
+ identity frDlciEndPt {
+ base iana-interface-type;
+ description
+ "Frame Relay DLCI End Point.";
+ }
+ identity atmVciEndPt {
+ base iana-interface-type;
+ description
+ "ATM VCI End Point.";
+ }
+ identity opticalChannel {
+ base iana-interface-type;
+ description
+ "Optical Channel.";
+ }
+ identity opticalTransport {
+ base iana-interface-type;
+ description
+ "Optical Transport.";
+ }
+ identity propAtm {
+ base iana-interface-type;
+ description
+ "Proprietary ATM.";
+ }
+ identity voiceOverCable {
+ base iana-interface-type;
+ description
+ "Voice Over Cable Interface.";
+ }
+ identity infiniband {
+ base iana-interface-type;
+ description
+ "Infiniband.";
+ }
+ identity teLink {
+ base iana-interface-type;
+ description
+ "TE Link.";
+ }
+ identity q2931 {
+ base iana-interface-type;
+ description
+ "Q.2931.";
+ }
+ identity virtualTg {
+ base iana-interface-type;
+ description
+ "Virtual Trunk Group.";
+ }
+ identity sipTg {
+ base iana-interface-type;
+ description
+ "SIP Trunk Group.";
+ }
+ identity sipSig {
+ base iana-interface-type;
+ description
+ "SIP Signaling.";
+ }
+ identity docsCableUpstreamChannel {
+ base iana-interface-type;
+ description
+ "CATV Upstream Channel.";
+ }
+ identity econet {
+ base iana-interface-type;
+ description
+ "Acorn Econet.";
+ }
+ identity pon155 {
+ base iana-interface-type;
+ description
+ "FSAN 155Mb Symetrical PON interface.";
+ }
+ identity pon622 {
+ base iana-interface-type;
+ description
+ "FSAN 622Mb Symetrical PON interface.";
+ }
+ identity bridge {
+ base iana-interface-type;
+ description
+ "Transparent bridge interface.";
+ }
+ identity linegroup {
+ base iana-interface-type;
+ description
+ "Interface common to multiple lines.";
+ }
+ identity voiceEMFGD {
+ base iana-interface-type;
+ description
+ "Voice E&M Feature Group D.";
+ }
+ identity voiceFGDEANA {
+ base iana-interface-type;
+ description
+ "Voice FGD Exchange Access North American.";
+ }
+ identity voiceDID {
+ base iana-interface-type;
+ description
+ "Voice Direct Inward Dialing.";
+ }
+ identity mpegTransport {
+ base iana-interface-type;
+ description
+ "MPEG transport interface.";
+ }
+ identity sixToFour {
+ base iana-interface-type;
+ status deprecated;
+ description
+ "6to4 interface (DEPRECATED).";
+ reference
+ "RFC 4087 - IP Tunnel MIB";
+ }
+ identity gtp {
+ base iana-interface-type;
+ description
+ "GTP (GPRS Tunneling Protocol).";
+ }
+ identity pdnEtherLoop1 {
+ base iana-interface-type;
+ description
+ "Paradyne EtherLoop 1.";
+ }
+ identity pdnEtherLoop2 {
+ base iana-interface-type;
+ description
+ "Paradyne EtherLoop 2.";
+ }
+ identity opticalChannelGroup {
+ base iana-interface-type;
+ description
+ "Optical Channel Group.";
+ }
+ identity homepna {
+ base iana-interface-type;
+ description
+ "HomePNA ITU-T G.989.";
+ }
+ identity gfp {
+ base iana-interface-type;
+ description
+ "Generic Framing Procedure (GFP).";
+ }
+ identity ciscoISLvlan {
+ base iana-interface-type;
+ description
+ "Layer 2 Virtual LAN using Cisco ISL.";
+ }
+ identity actelisMetaLOOP {
+ base iana-interface-type;
+ description
+ "Acteleis proprietary MetaLOOP High Speed Link.";
+ }
+ identity fcipLink {
+ base iana-interface-type;
+ description
+ "FCIP Link.";
+ }
+ identity rpr {
+ base iana-interface-type;
+ description
+ "Resilient Packet Ring Interface Type.";
+ }
+ identity qam {
+ base iana-interface-type;
+ description
+ "RF Qam Interface.";
+ }
+ identity lmp {
+ base iana-interface-type;
+ description
+ "Link Management Protocol.";
+ reference
+ "RFC 4327 - Link Management Protocol (LMP) Management
+ Information Base (MIB)";
+ }
+ identity cblVectaStar {
+ base iana-interface-type;
+ description
+ "Cambridge Broadband Networks Limited VectaStar.";
+ }
+ identity docsCableMCmtsDownstream {
+ base iana-interface-type;
+ description
+ "CATV Modular CMTS Downstream Interface.";
+ }
+ identity adsl2 {
+ base iana-interface-type;
+ status deprecated;
+ description
+ "Asymmetric Digital Subscriber Loop Version 2
+ (DEPRECATED/OBSOLETED - please use adsl2plus(238)
+ instead).";
+ reference
+ "RFC 4706 - Definitions of Managed Objects for Asymmetric
+ Digital Subscriber Line 2 (ADSL2)";
+ }
+ identity macSecControlledIF {
+ base iana-interface-type;
+ description
+ "MACSecControlled.";
+ }
+ identity macSecUncontrolledIF {
+ base iana-interface-type;
+ description
+ "MACSecUncontrolled.";
+ }
+ identity aviciOpticalEther {
+ base iana-interface-type;
+ description
+ "Avici Optical Ethernet Aggregate.";
+ }
+ identity atmbond {
+ base iana-interface-type;
+ description
+ "atmbond.";
+ }
+ identity voiceFGDOS {
+ base iana-interface-type;
+ description
+ "Voice FGD Operator Services.";
+ }
+ identity mocaVersion1 {
+ base iana-interface-type;
+ description
+ "MultiMedia over Coax Alliance (MoCA) Interface
+ as documented in information provided privately to IANA.";
+ }
+ identity ieee80216WMAN {
+ base iana-interface-type;
+ description
+ "IEEE 802.16 WMAN interface.";
+ }
+ identity adsl2plus {
+ base iana-interface-type;
+ description
+ "Asymmetric Digital Subscriber Loop Version 2 -
+ Version 2 Plus and all variants.";
+ }
+ identity dvbRcsMacLayer {
+ base iana-interface-type;
+ description
+ "DVB-RCS MAC Layer.";
+ reference
+ "RFC 5728 - The SatLabs Group DVB-RCS MIB";
+ }
+ identity dvbTdm {
+ base iana-interface-type;
+ description
+ "DVB Satellite TDM.";
+ reference
+ "RFC 5728 - The SatLabs Group DVB-RCS MIB";
+ }
+ identity dvbRcsTdma {
+ base iana-interface-type;
+ description
+ "DVB-RCS TDMA.";
+ reference
+ "RFC 5728 - The SatLabs Group DVB-RCS MIB";
+ }
+ identity x86Laps {
+ base iana-interface-type;
+ description
+ "LAPS based on ITU-T X.86/Y.1323.";
+ }
+ identity wwanPP {
+ base iana-interface-type;
+ description
+ "3GPP WWAN.";
+ }
+ identity wwanPP2 {
+ base iana-interface-type;
+ description
+ "3GPP2 WWAN.";
+ }
+ identity voiceEBS {
+ base iana-interface-type;
+ description
+ "Voice P-phone EBS physical interface.";
+ }
+ identity ifPwType {
+ base iana-interface-type;
+ description
+ "Pseudowire interface type.";
+ reference
+ "RFC 5601 - Pseudowire (PW) Management Information Base (MIB)";
+ }
+ identity ilan {
+ base iana-interface-type;
+ description
+ "Internal LAN on a bridge per IEEE 802.1ap.";
+ }
+ identity pip {
+ base iana-interface-type;
+ description
+ "Provider Instance Port on a bridge per IEEE 802.1ah PBB.";
+ }
+ identity aluELP {
+ base iana-interface-type;
+ description
+ "Alcatel-Lucent Ethernet Link Protection.";
+ }
+ identity gpon {
+ base iana-interface-type;
+ description
+ "Gigabit-capable passive optical networks (G-PON) as per
+ ITU-T G.948.";
+ }
+ identity vdsl2 {
+ base iana-interface-type;
+ description
+ "Very high speed digital subscriber line Version 2
+ (as per ITU-T Recommendation G.993.2).";
+ reference
+ "RFC 5650 - Definitions of Managed Objects for Very High
+ Speed Digital Subscriber Line 2 (VDSL2)";
+ }
+ identity capwapDot11Profile {
+ base iana-interface-type;
+ description
+ "WLAN Profile Interface.";
+ reference
+ "RFC 5834 - Control and Provisioning of Wireless Access
+ Points (CAPWAP) Protocol Binding MIB for
+ IEEE 802.11";
+ }
+ identity capwapDot11Bss {
+ base iana-interface-type;
+ description
+ "WLAN BSS Interface.";
+ reference
+ "RFC 5834 - Control and Provisioning of Wireless Access
+ Points (CAPWAP) Protocol Binding MIB for
+ IEEE 802.11";
+ }
+ identity capwapWtpVirtualRadio {
+ base iana-interface-type;
+ description
+ "WTP Virtual Radio Interface.";
+ reference
+ "RFC 5833 - Control and Provisioning of Wireless Access
+ Points (CAPWAP) Protocol Base MIB";
+ }
+ identity bits {
+ base iana-interface-type;
+ description
+ "bitsport.";
+ }
+ identity docsCableUpstreamRfPort {
+ base iana-interface-type;
+ description
+ "DOCSIS CATV Upstream RF Port.";
+ }
+ identity cableDownstreamRfPort {
+ base iana-interface-type;
+ description
+ "CATV downstream RF Port.";
+ }
+ identity vmwareVirtualNic {
+ base iana-interface-type;
+ description
+ "VMware Virtual Network Interface.";
+ }
+ identity ieee802154 {
+ base iana-interface-type;
+ description
+ "IEEE 802.15.4 WPAN interface.";
+ reference
+ "IEEE 802.15.4-2006";
+ }
+ identity otnOdu {
+ base iana-interface-type;
+ description
+ "OTN Optical Data Unit.";
+ }
+ identity otnOtu {
+ base iana-interface-type;
+ description
+ "OTN Optical channel Transport Unit.";
+ }
+ identity ifVfiType {
+ base iana-interface-type;
+ description
+ "VPLS Forwarding Instance Interface Type.";
+ }
+ identity g9981 {
+ base iana-interface-type;
+ description
+ "G.998.1 bonded interface.";
+ }
+ identity g9982 {
+ base iana-interface-type;
+ description
+ "G.998.2 bonded interface.";
+ }
+ identity g9983 {
+ base iana-interface-type;
+ description
+ "G.998.3 bonded interface.";
+ }
+
+ identity aluEpon {
+ base iana-interface-type;
+ description
+ "Ethernet Passive Optical Networks (E-PON).";
+ }
+ identity aluEponOnu {
+ base iana-interface-type;
+ description
+ "EPON Optical Network Unit.";
+ }
+ identity aluEponPhysicalUni {
+ base iana-interface-type;
+ description
+ "EPON physical User to Network interface.";
+ }
+ identity aluEponLogicalLink {
+ base iana-interface-type;
+ description
+ "The emulation of a point-to-point link over the EPON
+ layer.";
+ }
+ identity aluGponOnu {
+ base iana-interface-type;
+ description
+ "GPON Optical Network Unit.";
+ reference
+ "ITU-T G.984.2";
+ }
+ identity aluGponPhysicalUni {
+ base iana-interface-type;
+ description
+ "GPON physical User to Network interface.";
+ reference
+ "ITU-T G.984.2";
+ }
+ identity vmwareNicTeam {
+ base iana-interface-type;
+ description
+ "VMware NIC Team.";
+ }
+ identity docsOfdmDownstream {
+ base iana-interface-type;
+ description
+ "CATV Downstream OFDM interface.";
+ }
+ identity docsOfdmaUpstream {
+ base iana-interface-type;
+ description
+ "CATV Upstream OFDMA interface.";
+ }
+ identity gfast {
+ base iana-interface-type;
+ description
+ "G.fast port.";
+ reference
+ "ITU-T G.9701";
+ }
+ identity sdci {
+ base iana-interface-type;
+ description
+ "SDCI (IO-Link).";
+ reference
+ "IEC 61131-9 Edition 1.0 2013-09";
+ }
+ identity xboxWireless {
+ base iana-interface-type;
+ description
+ "Xbox wireless.";
+ }
+ identity fastdsl {
+ base iana-interface-type;
+ description
+ "FastDSL.";
+ reference
+ "BBF TR-355";
+ }
+ identity docsCableScte55d1FwdOob {
+ base iana-interface-type;
+ description
+ "Cable SCTE 55-1 OOB Forward Channel.";
+ }
+ identity docsCableScte55d1RetOob {
+ base iana-interface-type;
+ description
+ "Cable SCTE 55-1 OOB Return Channel.";
+ }
+ identity docsCableScte55d2DsOob {
+ base iana-interface-type;
+ description
+ "Cable SCTE 55-2 OOB Downstream Channel.";
+ }
+ identity docsCableScte55d2UsOob {
+ base iana-interface-type;
+ description
+ "Cable SCTE 55-2 OOB Upstream Channel.";
+ }
+ identity docsCableNdf {
+ base iana-interface-type;
+ description
+ "Cable Narrowband Digital Forward.";
+ }
+ identity docsCableNdr {
+ base iana-interface-type;
+ description
+ "Cable Narrowband Digital Return.";
+ }
+ identity ptm {
+ base iana-interface-type;
+ description
+ "Packet Transfer Mode.";
+ }
+}
diff --git a/src/plugins/yang/ietf/ietf-interfaces@2014-05-08.yang b/src/plugins/yang/ietf/ietf-interfaces@2014-05-08.yang
deleted file mode 100644
index a0eb30e..0000000
--- a/src/plugins/yang/ietf/ietf-interfaces@2014-05-08.yang
+++ /dev/null
@@ -1,707 +0,0 @@
-module ietf-interfaces {
-
- yang-version 1;
-
- namespace
- "urn:ietf:params:xml:ns:yang:ietf-interfaces";
-
- prefix if;
-
- import ietf-yang-types {
- prefix yang;
- }
-
- organization
- "IETF NETMOD (NETCONF Data Modeling Language) Working Group";
-
- contact
- "WG Web: <http://tools.ietf.org/wg/netmod/>
- WG List: <mailto:netmod@ietf.org>
-
- WG Chair: Thomas Nadeau
- <mailto:tnadeau@lucidvision.com>
-
- WG Chair: Juergen Schoenwaelder
- <mailto:j.schoenwaelder@jacobs-university.de>
-
- Editor: Martin Bjorklund
- <mailto:mbj@tail-f.com>";
-
- description
- "This module contains a collection of YANG definitions for
- managing network interfaces.
-
- Copyright (c) 2014 IETF Trust and the persons identified as
- authors of the code. All rights reserved.
-
- Redistribution and use in source and binary forms, with or
- without modification, is permitted pursuant to, and subject
- to the license terms contained in, the Simplified BSD License
- set forth in Section 4.c of the IETF Trust's Legal Provisions
- Relating to IETF Documents
- (http://trustee.ietf.org/license-info).
-
- This version of this YANG module is part of RFC 7223; see
- the RFC itself for full legal notices.";
-
- revision "2014-05-08" {
- description "Initial revision.";
- reference
- "RFC 7223: A YANG Data Model for Interface Management";
-
- }
-
-
- typedef interface-ref {
- type leafref {
- path "/if:interfaces/if:interface/if:name";
- }
- description
- "This type is used by data models that need to reference
- configured interfaces.";
- }
-
- typedef interface-state-ref {
- type leafref {
- path "/if:interfaces-state/if:interface/if:name";
- }
- description
- "This type is used by data models that need to reference
- the operationally present interfaces.";
- }
-
- identity interface-type {
- description
- "Base identity from which specific interface types are
- derived.";
- }
-
- feature arbitrary-names {
- description
- "This feature indicates that the device allows user-controlled
- interfaces to be named arbitrarily.";
- }
-
- feature pre-provisioning {
- description
- "This feature indicates that the device supports
- pre-provisioning of interface configuration, i.e., it is
- possible to configure an interface whose physical interface
- hardware is not present on the device.";
- }
-
- feature if-mib {
- description
- "This feature indicates that the device implements
- the IF-MIB.";
- reference
- "RFC 2863: The Interfaces Group MIB";
-
- }
-
- container interfaces {
- description
- "Interface configuration parameters.";
- list interface {
- key "name";
- description
- "The list of configured interfaces on the device.
-
- The operational state of an interface is available in the
- /interfaces-state/interface list. If the configuration of a
- system-controlled interface cannot be used by the system
- (e.g., the interface hardware present does not match the
- interface type), then the configuration is not applied to
- the system-controlled interface shown in the
- /interfaces-state/interface list. If the configuration
- of a user-controlled interface cannot be used by the system,
- the configured interface is not instantiated in the
- /interfaces-state/interface list.";
- leaf name {
- type string;
- description
- "The name of the interface.
-
- A device MAY restrict the allowed values for this leaf,
- possibly depending on the type of the interface.
- For system-controlled interfaces, this leaf is the
- device-specific name of the interface. The 'config false'
- list /interfaces-state/interface contains the currently
- existing interfaces on the device.
-
- If a client tries to create configuration for a
- system-controlled interface that is not present in the
- /interfaces-state/interface list, the server MAY reject
- the request if the implementation does not support
- pre-provisioning of interfaces or if the name refers to
- an interface that can never exist in the system. A
- NETCONF server MUST reply with an rpc-error with the
- error-tag 'invalid-value' in this case.
-
- If the device supports pre-provisioning of interface
- configuration, the 'pre-provisioning' feature is
- advertised.
-
- If the device allows arbitrarily named user-controlled
- interfaces, the 'arbitrary-names' feature is advertised.
-
- When a configured user-controlled interface is created by
- the system, it is instantiated with the same name in the
- /interface-state/interface list.";
- }
-
- leaf description {
- type string;
- description
- "A textual description of the interface.
-
- A server implementation MAY map this leaf to the ifAlias
- MIB object. Such an implementation needs to use some
- mechanism to handle the differences in size and characters
- allowed between this leaf and ifAlias. The definition of
- such a mechanism is outside the scope of this document.
-
- Since ifAlias is defined to be stored in non-volatile
- storage, the MIB implementation MUST map ifAlias to the
- value of 'description' in the persistently stored
- datastore.
-
- Specifically, if the device supports ':startup', when
- ifAlias is read the device MUST return the value of
- 'description' in the 'startup' datastore, and when it is
- written, it MUST be written to the 'running' and 'startup'
- datastores. Note that it is up to the implementation to
-
- decide whether to modify this single leaf in 'startup' or
- perform an implicit copy-config from 'running' to
- 'startup'.
-
- If the device does not support ':startup', ifAlias MUST
- be mapped to the 'description' leaf in the 'running'
- datastore.";
- reference
- "RFC 2863: The Interfaces Group MIB - ifAlias";
-
- }
-
- leaf type {
- type identityref {
- base interface-type;
- }
- mandatory true;
- description
- "The type of the interface.
-
- When an interface entry is created, a server MAY
- initialize the type leaf with a valid value, e.g., if it
- is possible to derive the type from the name of the
- interface.
-
- If a client tries to set the type of an interface to a
- value that can never be used by the system, e.g., if the
- type is not supported or if the type does not match the
- name of the interface, the server MUST reject the request.
- A NETCONF server MUST reply with an rpc-error with the
- error-tag 'invalid-value' in this case.";
- reference
- "RFC 2863: The Interfaces Group MIB - ifType";
-
- }
-
- leaf enabled {
- type boolean;
- default "true";
- description
- "This leaf contains the configured, desired state of the
- interface.
-
- Systems that implement the IF-MIB use the value of this
- leaf in the 'running' datastore to set
- IF-MIB.ifAdminStatus to 'up' or 'down' after an ifEntry
- has been initialized, as described in RFC 2863.
-
-
-
- Changes in this leaf in the 'running' datastore are
- reflected in ifAdminStatus, but if ifAdminStatus is
- changed over SNMP, this leaf is not affected.";
- reference
- "RFC 2863: The Interfaces Group MIB - ifAdminStatus";
-
- }
-
- leaf link-up-down-trap-enable {
- if-feature if-mib;
- type enumeration {
- enum "enabled" {
- value 1;
- }
- enum "disabled" {
- value 2;
- }
- }
- description
- "Controls whether linkUp/linkDown SNMP notifications
- should be generated for this interface.
-
- If this node is not configured, the value 'enabled' is
- operationally used by the server for interfaces that do
- not operate on top of any other interface (i.e., there are
- no 'lower-layer-if' entries), and 'disabled' otherwise.";
- reference
- "RFC 2863: The Interfaces Group MIB -
- ifLinkUpDownTrapEnable";
-
- }
- } // list interface
- } // container interfaces
-
- container interfaces-state {
- config false;
- description
- "Data nodes for the operational state of interfaces.";
- list interface {
- key "name";
- description
- "The list of interfaces on the device.
-
- System-controlled interfaces created by the system are
- always present in this list, whether they are configured or
- not.";
- leaf name {
- type string;
- description
- "The name of the interface.
-
- A server implementation MAY map this leaf to the ifName
- MIB object. Such an implementation needs to use some
- mechanism to handle the differences in size and characters
- allowed between this leaf and ifName. The definition of
- such a mechanism is outside the scope of this document.";
- reference
- "RFC 2863: The Interfaces Group MIB - ifName";
-
- }
-
- leaf type {
- type identityref {
- base interface-type;
- }
- mandatory true;
- description
- "The type of the interface.";
- reference
- "RFC 2863: The Interfaces Group MIB - ifType";
-
- }
-
- leaf admin-status {
- if-feature if-mib;
- type enumeration {
- enum "up" {
- value 1;
- description
- "Ready to pass packets.";
- }
- enum "down" {
- value 2;
- description
- "Not ready to pass packets and not in some test mode.";
- }
- enum "testing" {
- value 3;
- description
- "In some test mode.";
- }
- }
- mandatory true;
- description
- "The desired state of the interface.
-
- This leaf has the same read semantics as ifAdminStatus.";
- reference
- "RFC 2863: The Interfaces Group MIB - ifAdminStatus";
-
- }
-
- leaf oper-status {
- type enumeration {
- enum "up" {
- value 1;
- description
- "Ready to pass packets.";
- }
- enum "down" {
- value 2;
- description
- "The interface does not pass any packets.";
- }
- enum "testing" {
- value 3;
- description
- "In some test mode. No operational packets can
- be passed.";
- }
- enum "unknown" {
- value 4;
- description
- "Status cannot be determined for some reason.";
- }
- enum "dormant" {
- value 5;
- description
- "Waiting for some external event.";
- }
- enum "not-present" {
- value 6;
- description
- "Some component (typically hardware) is missing.";
- }
- enum "lower-layer-down" {
- value 7;
- description
- "Down due to state of lower-layer interface(s).";
- }
- }
- mandatory true;
- description
- "The current operational state of the interface.
-
- This leaf has the same semantics as ifOperStatus.";
- reference
- "RFC 2863: The Interfaces Group MIB - ifOperStatus";
-
- }
-
- leaf last-change {
- type yang:date-and-time;
- description
- "The time the interface entered its current operational
- state. If the current state was entered prior to the
- last re-initialization of the local network management
- subsystem, then this node is not present.";
- reference
- "RFC 2863: The Interfaces Group MIB - ifLastChange";
-
- }
-
- leaf if-index {
- if-feature if-mib;
- type int32 {
- range "1..2147483647";
- }
- mandatory true;
- description
- "The ifIndex value for the ifEntry represented by this
- interface.";
- reference
- "RFC 2863: The Interfaces Group MIB - ifIndex";
-
- }
-
- leaf phys-address {
- type yang:phys-address;
- description
- "The interface's address at its protocol sub-layer. For
- example, for an 802.x interface, this object normally
- contains a Media Access Control (MAC) address. The
- interface's media-specific modules must define the bit
-
-
- and byte ordering and the format of the value of this
- object. For interfaces that do not have such an address
- (e.g., a serial line), this node is not present.";
- reference
- "RFC 2863: The Interfaces Group MIB - ifPhysAddress";
-
- }
-
- leaf-list higher-layer-if {
- type interface-state-ref;
- description
- "A list of references to interfaces layered on top of this
- interface.";
- reference
- "RFC 2863: The Interfaces Group MIB - ifStackTable";
-
- }
-
- leaf-list lower-layer-if {
- type interface-state-ref;
- description
- "A list of references to interfaces layered underneath this
- interface.";
- reference
- "RFC 2863: The Interfaces Group MIB - ifStackTable";
-
- }
-
- leaf speed {
- type yang:gauge64;
- units "bits/second";
- description
- "An estimate of the interface's current bandwidth in bits
- per second. For interfaces that do not vary in
- bandwidth or for those where no accurate estimation can
- be made, this node should contain the nominal bandwidth.
- For interfaces that have no concept of bandwidth, this
- node is not present.";
- reference
- "RFC 2863: The Interfaces Group MIB -
- ifSpeed, ifHighSpeed";
-
- }
-
- container statistics {
- description
- "A collection of interface-related statistics objects.";
- leaf discontinuity-time {
- type yang:date-and-time;
- mandatory true;
- description
- "The time on the most recent occasion at which any one or
- more of this interface's counters suffered a
- discontinuity. If no such discontinuities have occurred
- since the last re-initialization of the local management
- subsystem, then this node contains the time the local
- management subsystem re-initialized itself.";
- }
-
- leaf in-octets {
- type yang:counter64;
- description
- "The total number of octets received on the interface,
- including framing characters.
-
- Discontinuities in the value of this counter can occur
- at re-initialization of the management system, and at
- other times as indicated by the value of
- 'discontinuity-time'.";
- reference
- "RFC 2863: The Interfaces Group MIB - ifHCInOctets";
-
- }
-
- leaf in-unicast-pkts {
- type yang:counter64;
- description
- "The number of packets, delivered by this sub-layer to a
- higher (sub-)layer, that were not addressed to a
- multicast or broadcast address at this sub-layer.
-
- Discontinuities in the value of this counter can occur
- at re-initialization of the management system, and at
- other times as indicated by the value of
- 'discontinuity-time'.";
- reference
- "RFC 2863: The Interfaces Group MIB - ifHCInUcastPkts";
-
- }
-
- leaf in-broadcast-pkts {
- type yang:counter64;
- description
- "The number of packets, delivered by this sub-layer to a
- higher (sub-)layer, that were addressed to a broadcast
- address at this sub-layer.
-
- Discontinuities in the value of this counter can occur
- at re-initialization of the management system, and at
- other times as indicated by the value of
- 'discontinuity-time'.";
- reference
- "RFC 2863: The Interfaces Group MIB -
- ifHCInBroadcastPkts";
-
- }
-
- leaf in-multicast-pkts {
- type yang:counter64;
- description
- "The number of packets, delivered by this sub-layer to a
- higher (sub-)layer, that were addressed to a multicast
- address at this sub-layer. For a MAC-layer protocol,
- this includes both Group and Functional addresses.
-
- Discontinuities in the value of this counter can occur
- at re-initialization of the management system, and at
- other times as indicated by the value of
- 'discontinuity-time'.";
- reference
- "RFC 2863: The Interfaces Group MIB -
- ifHCInMulticastPkts";
-
- }
-
- leaf in-discards {
- type yang:counter32;
- description
- "The number of inbound packets that were chosen to be
- discarded even though no errors had been detected to
- prevent their being deliverable to a higher-layer
- protocol. One possible reason for discarding such a
- packet could be to free up buffer space.
-
- Discontinuities in the value of this counter can occur
- at re-initialization of the management system, and at
- other times as indicated by the value of
- 'discontinuity-time'.";
- reference
- "RFC 2863: The Interfaces Group MIB - ifInDiscards";
-
- }
-
- leaf in-errors {
- type yang:counter32;
- description
- "For packet-oriented interfaces, the number of inbound
- packets that contained errors preventing them from being
- deliverable to a higher-layer protocol. For character-
- oriented or fixed-length interfaces, the number of
- inbound transmission units that contained errors
- preventing them from being deliverable to a higher-layer
- protocol.
-
- Discontinuities in the value of this counter can occur
- at re-initialization of the management system, and at
- other times as indicated by the value of
- 'discontinuity-time'.";
- reference
- "RFC 2863: The Interfaces Group MIB - ifInErrors";
-
- }
-
- leaf in-unknown-protos {
- type yang:counter32;
- description
- "For packet-oriented interfaces, the number of packets
- received via the interface that were discarded because
- of an unknown or unsupported protocol. For
- character-oriented or fixed-length interfaces that
- support protocol multiplexing, the number of
- transmission units received via the interface that were
- discarded because of an unknown or unsupported protocol.
- For any interface that does not support protocol
- multiplexing, this counter is not present.
-
- Discontinuities in the value of this counter can occur
- at re-initialization of the management system, and at
- other times as indicated by the value of
- 'discontinuity-time'.";
- reference
- "RFC 2863: The Interfaces Group MIB - ifInUnknownProtos";
-
- }
-
- leaf out-octets {
- type yang:counter64;
- description
- "The total number of octets transmitted out of the
- interface, including framing characters.
-
- Discontinuities in the value of this counter can occur
- at re-initialization of the management system, and at
- other times as indicated by the value of
- 'discontinuity-time'.";
- reference
- "RFC 2863: The Interfaces Group MIB - ifHCOutOctets";
-
- }
-
- leaf out-unicast-pkts {
- type yang:counter64;
- description
- "The total number of packets that higher-level protocols
- requested be transmitted, and that were not addressed
- to a multicast or broadcast address at this sub-layer,
- including those that were discarded or not sent.
-
- Discontinuities in the value of this counter can occur
- at re-initialization of the management system, and at
- other times as indicated by the value of
- 'discontinuity-time'.";
- reference
- "RFC 2863: The Interfaces Group MIB - ifHCOutUcastPkts";
-
- }
-
- leaf out-broadcast-pkts {
- type yang:counter64;
- description
- "The total number of packets that higher-level protocols
- requested be transmitted, and that were addressed to a
- broadcast address at this sub-layer, including those
- that were discarded or not sent.
-
- Discontinuities in the value of this counter can occur
- at re-initialization of the management system, and at
- other times as indicated by the value of
- 'discontinuity-time'.";
- reference
- "RFC 2863: The Interfaces Group MIB -
- ifHCOutBroadcastPkts";
-
- }
-
- leaf out-multicast-pkts {
- type yang:counter64;
- description
- "The total number of packets that higher-level protocols
- requested be transmitted, and that were addressed to a
- multicast address at this sub-layer, including those
- that were discarded or not sent. For a MAC-layer
- protocol, this includes both Group and Functional
- addresses.
-
- Discontinuities in the value of this counter can occur
- at re-initialization of the management system, and at
- other times as indicated by the value of
- 'discontinuity-time'.";
- reference
- "RFC 2863: The Interfaces Group MIB -
- ifHCOutMulticastPkts";
-
- }
-
- leaf out-discards {
- type yang:counter32;
- description
- "The number of outbound packets that were chosen to be
- discarded even though no errors had been detected to
- prevent their being transmitted. One possible reason
- for discarding such a packet could be to free up buffer
- space.
-
- Discontinuities in the value of this counter can occur
- at re-initialization of the management system, and at
- other times as indicated by the value of
- 'discontinuity-time'.";
- reference
- "RFC 2863: The Interfaces Group MIB - ifOutDiscards";
-
- }
-
- leaf out-errors {
- type yang:counter32;
- description
- "For packet-oriented interfaces, the number of outbound
- packets that could not be transmitted because of errors.
- For character-oriented or fixed-length interfaces, the
- number of outbound transmission units that could not be
- transmitted because of errors.
-
-
-
-
- Discontinuities in the value of this counter can occur
- at re-initialization of the management system, and at
- other times as indicated by the value of
- 'discontinuity-time'.";
- reference
- "RFC 2863: The Interfaces Group MIB - ifOutErrors";
-
- }
- } // container statistics
- } // list interface
- } // container interfaces-state
- } // module ietf-interfaces
diff --git a/src/plugins/yang/ietf/ietf-interfaces.yang b/src/plugins/yang/ietf/ietf-interfaces@2018-02-20.yang
index f66c205..f66c205 100644
--- a/src/plugins/yang/ietf/ietf-interfaces.yang
+++ b/src/plugins/yang/ietf/ietf-interfaces@2018-02-20.yang
diff --git a/src/plugins/yang/openconfig/openconfig-extensions.yang b/src/plugins/yang/openconfig/openconfig-extensions@2017-04-11.yang
index f39ecf6..f39ecf6 100644
--- a/src/plugins/yang/openconfig/openconfig-extensions.yang
+++ b/src/plugins/yang/openconfig/openconfig-extensions@2017-04-11.yang
diff --git a/src/plugins/yang/openconfig/openconfig-if-aggregate.yang b/src/plugins/yang/openconfig/openconfig-if-aggregate@2018-03-23.yang
index 5aa80bb..5aa80bb 100644
--- a/src/plugins/yang/openconfig/openconfig-if-aggregate.yang
+++ b/src/plugins/yang/openconfig/openconfig-if-aggregate@2018-03-23.yang
diff --git a/src/plugins/yang/openconfig/openconfig-if-ethernet.yang b/src/plugins/yang/openconfig/openconfig-if-ethernet@2018-09-04.yang
index cd6b526..cd6b526 100644
--- a/src/plugins/yang/openconfig/openconfig-if-ethernet.yang
+++ b/src/plugins/yang/openconfig/openconfig-if-ethernet@2018-09-04.yang
diff --git a/src/plugins/yang/openconfig/openconfig-if-ip.yang b/src/plugins/yang/openconfig/openconfig-if-ip@2018-01-05.yang
index a20e21c..a20e21c 100644
--- a/src/plugins/yang/openconfig/openconfig-if-ip.yang
+++ b/src/plugins/yang/openconfig/openconfig-if-ip@2018-01-05.yang
diff --git a/src/plugins/yang/openconfig/openconfig-if-types.yang b/src/plugins/yang/openconfig/openconfig-if-types@2018-01-05.yang
index 3743878..3743878 100644
--- a/src/plugins/yang/openconfig/openconfig-if-types.yang
+++ b/src/plugins/yang/openconfig/openconfig-if-types@2018-01-05.yang
diff --git a/src/plugins/yang/openconfig/openconfig-inet-types.yang b/src/plugins/yang/openconfig/openconfig-inet-types@2017-08-24.yang
index fbb872f..fbb872f 100644
--- a/src/plugins/yang/openconfig/openconfig-inet-types.yang
+++ b/src/plugins/yang/openconfig/openconfig-inet-types@2017-08-24.yang
diff --git a/src/plugins/yang/openconfig/openconfig-interfaces.yang b/src/plugins/yang/openconfig/openconfig-interfaces@2018-08-07.yang
index d11e0b2..d11e0b2 100644
--- a/src/plugins/yang/openconfig/openconfig-interfaces.yang
+++ b/src/plugins/yang/openconfig/openconfig-interfaces@2018-08-07.yang
diff --git a/src/plugins/yang/openconfig/openconfig-local-routing.yang b/src/plugins/yang/openconfig/openconfig-local-routing@2017-05-15.yang
index 5184fe7..5184fe7 100644
--- a/src/plugins/yang/openconfig/openconfig-local-routing.yang
+++ b/src/plugins/yang/openconfig/openconfig-local-routing@2017-05-15.yang
diff --git a/src/plugins/yang/openconfig/openconfig-policy-types.yang b/src/plugins/yang/openconfig/openconfig-policy-types@2018-06-05.yang
index ef47f33..ef47f33 100644
--- a/src/plugins/yang/openconfig/openconfig-policy-types.yang
+++ b/src/plugins/yang/openconfig/openconfig-policy-types@2018-06-05.yang
diff --git a/src/plugins/yang/openconfig/openconfig-types.yang b/src/plugins/yang/openconfig/openconfig-types@2018-05-05.yang
index 01713b3..01713b3 100644
--- a/src/plugins/yang/openconfig/openconfig-types.yang
+++ b/src/plugins/yang/openconfig/openconfig-types@2018-05-05.yang
diff --git a/src/plugins/yang/openconfig/openconfig-vlan-types.yang b/src/plugins/yang/openconfig/openconfig-vlan-types@2018-02-14.yang
index 6d9ab55..6d9ab55 100644
--- a/src/plugins/yang/openconfig/openconfig-vlan-types.yang
+++ b/src/plugins/yang/openconfig/openconfig-vlan-types@2018-02-14.yang
diff --git a/src/plugins/yang/openconfig/openconfig-vlan.yang b/src/plugins/yang/openconfig/openconfig-vlan@2018-06-05.yang
index 97348c0..97348c0 100644
--- a/src/plugins/yang/openconfig/openconfig-vlan.yang
+++ b/src/plugins/yang/openconfig/openconfig-vlan@2018-06-05.yang
diff --git a/src/plugins/yang/openconfig/openconfig-yang-types.yang b/src/plugins/yang/openconfig/openconfig-yang-types@2018-04-24.yang
index b3b2c16..b3b2c16 100644
--- a/src/plugins/yang/openconfig/openconfig-yang-types.yang
+++ b/src/plugins/yang/openconfig/openconfig-yang-types@2018-04-24.yang
diff --git a/src/scvpp/CMakeLists.txt b/src/scvpp/CMakeLists.txt
index 2dc42d6..8d04085 100644
--- a/src/scvpp/CMakeLists.txt
+++ b/src/scvpp/CMakeLists.txt
@@ -16,8 +16,57 @@
cmake_minimum_required(VERSION 2.8)
project(scvpp)
-# DEPENDENCIES
-##############
+# COMPILER & LINKER
+###################
+
+# scvpp sources
+set(SCVPP_SOURCES
+ src/comm.c
+ src/interface.c
+ src/ip.c
+ src/v3po.c
+ src/nat.c
+)
+
+# scvpp public headers
+set(SCVPP_HEADERS
+ inc/scvpp/comm.h
+ inc/scvpp/interface.h
+ inc/scvpp/ip.h
+ inc/scvpp/v3po.h
+ inc/scvpp/nat.h
+)
+
+#define CMAKE_INSTALL_LIBDIR/INCLUDEDIR
+include(GNUInstallDirs)
+
+# Generate a compile_commands.json with compile options
+set(CMAKE_EXPORT_COMPILE_COMMANDS 1)
+
+#set compiler and linker flags
+set(RIGOROUS_C_FLAGS "-Wlogical-op -Wformat=2")
+set(CMAKE_C_FLAGS "-Wall -Wextra -std=gnu99 ${RIGOROUS_C_FLAGS}")
+set(CMAKE_C_FLAGS_DEBUG "-Wall -Wextra -std=gnu99 -g -O0 ${RIGOROUS_C_FLAGS}")
+#NDEBUG to skip assert checks
+set(CMAKE_C_FLAGS_RELEASE "-Wall -Wextra -std=gnu99 -DNDEBUG -O2 ${RIGOROUS_C_FLAGS}")
+
+# libraries to link with
+set(LINK_LIBRARIES vlibmemoryclient vapiclient vppapiclient svm vppinfra pthread rt dl)
+
+# build instructions
+add_library(scvpp SHARED ${SCVPP_SOURCES})
+add_library(scvpp_a ${SCVPP_SOURCES})
+
+# linker instructions
+target_link_libraries(scvpp ${LINK_LIBRARIES})
+target_link_libraries(scvpp_a ${LINK_LIBRARIES})
+
+# to build shared and static library for scvpp, include project private directory inc before installing header file
+target_include_directories(scvpp PRIVATE inc)
+target_include_directories(scvpp_a PRIVATE inc)
+
+# TESTING
+#########
# enable testing if requested and possible
SET(ENABLE_TESTS 1 CACHE BOOL "Enable unit tests.")
@@ -32,16 +81,13 @@ if(ENABLE_TESTS)
endif(CMOCKA_FOUND)
endif(ENABLE_TESTS)
-# COMPILER & LINKER & INSTALL
-#############################
-
-#define CMAKE_INSTALL_LIBDIR/INCLUDEDIR
-include(GNUInstallDirs)
-add_subdirectory(src)
+# INSTALL
+#########
-# MORE INSTALL
-##############
+# install rules
+install(TARGETS scvpp DESTINATION ${CMAKE_INSTALL_LIBDIR})
+install(FILES ${SCVPP_HEADERS} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/scvpp)
find_package(PkgConfig QUIET) #QUIET disables message if not found
if(PKG_CONFIG_FOUND)
diff --git a/src/scvpp/src/sc_vpp_comm.h b/src/scvpp/inc/scvpp/comm.h
index eeeaaf9..9a27517 100644
--- a/src/scvpp/src/sc_vpp_comm.h
+++ b/src/scvpp/inc/scvpp/comm.h
@@ -23,22 +23,30 @@
#include <vapi/vapi_common.h>
#include <vapi/vpe.api.vapi.h>
+typedef enum {
+ SCVPP_OK = 0, /* Success */
+ SCVPP_EINVAL, /* Invalid value encountered */
+ SCVPP_EAGAIN, /* Operation would block */
+ SCVPP_ENOTSUP, /* Operation not supported */
+ SCVPP_ENOMEM, /* Out of memory */
+ SCVPP_NOT_FOUND, /* Required element can not be found */
+} scvpp_error_e;
+
// Use VAPI macros to define symbols
DEFINE_VAPI_MSG_IDS_VPE_API_JSON;
-#define VPP_INTFC_NAME_LEN 64
-#define VPP_TAPV2_NAME_LEN VPP_INTFC_NAME_LEN
-#define VPP_IP4_ADDRESS_LEN 4
-#define VPP_IP6_ADDRESS_LEN 16
-#define VPP_IP4_ADDRESS_STRING_LEN 16
-#define VPP_IP4_PREFIX_STRING_LEN 19
#define VPP_IP4_HOST_PREFIX_LEN 32
-#define VPP_IP6_ADDRESS_STRING_LEN 46
-#define VPP_MAC_ADDRESS_LEN 8
-#define VPP_TAG_LEN VPP_INTFC_NAME_LEN
-#define VPP_IKEV2_PROFILE_NAME_LEN VPP_INTFC_NAME_LEN
-#define VPP_IKEV2_PSK_LEN VPP_INTFC_NAME_LEN
-#define VPP_IKEV2_ID_LEN 32
+#define VPP_INTFC_NAME_LEN 64 /* Interface name max length */
+#define VPP_IP4_ADDRESS_LEN 4 /* IPv4 length in VPP format */
+#define VPP_IP6_ADDRESS_LEN 16 /* IPv6 length in VPP format */
+#define VPP_MAC_ADDRESS_LEN 8 /* MAC length in VPP format */
+/* IPv4 and IPv6 length in string format */
+#define VPP_IP4_ADDRESS_STRING_LEN INET_ADDRSTRLEN //16, include '\0'
+#define VPP_IP6_ADDRESS_STRING_LEN INET6_ADDRSTRLEN //46, include '\0'
+#define VPP_IP4_PREFIX_STRING_LEN \
+ INET_ADDRSTRLEN + sizeof('/') + 2 // include '\0'
+#define VPP_IP6_PREFIX_STRING_LEN \
+ INET6_ADDRSTRLEN + sizeof('/') + 3 // include '\0'
/**********************************MACROS**********************************/
#define ARG_CHECK(retval, arg) \
@@ -86,9 +94,10 @@ api_name##_cb (vapi_ctx_t ctx, void *caller_ctx, vapi_error_e rv, bool is_last,
vapi_payload_##api_name##_reply * reply) \
{ \
UNUSED(ctx); UNUSED(rv); UNUSED(is_last); \
+ vapi_payload_##api_name##_reply * passed; \
if (caller_ctx) \
{ \
- vapi_payload_##api_name##_reply * passed = (vapi_payload_##api_name##_reply *)caller_ctx; \
+ passed = (vapi_payload_##api_name##_reply *)caller_ctx; \
*passed = *reply; \
} \
return VAPI_OK; \
@@ -104,13 +113,81 @@ api_name##_cb (vapi_ctx_t ctx, void *caller_ctx, vapi_error_e rv, bool is_last,
else \
{ \
while (VAPI_EAGAIN == (rv = call_code)); \
- rv = vapi_dispatch (g_vapi_ctx_instance); \
+ if (rv != VAPI_OK) { /* try once more to get reply */ \
+ rv = vapi_dispatch (g_vapi_ctx); \
+ } \
} \
} \
while (0)
#define VAPI_CALL(call_code) VAPI_CALL_MODE(call_code, g_vapi_mode)
+struct elt {
+ void *data; //vapi_payload structure
+ struct elt *next;
+ int id; //id of the stack element to count total nb of elements
+};
+
+static inline int push(struct elt **stack, void *data, int length)
+{
+ struct elt *el;
+
+ //new stack node
+ el = malloc(sizeof(struct elt));
+ if (!el)
+ return -ENOMEM;
+ el->data = malloc(length);
+ if (!el->data)
+ return -ENOMEM;
+
+ memcpy(el->data, data, length);
+ if (*stack)
+ el->id = (*stack)->id++;
+ else
+ el->id = 0;
+ el->next = *stack; //point to old value of stack
+ *stack = el; //el is new stack head
+
+ return 0;
+}
+
+static inline void * pop(struct elt **stack)
+{
+ struct elt *prev;
+ void *data;
+
+ if (!(*stack))
+ return NULL;
+
+ data = (*stack)->data; //get data at stack head
+ prev = *stack; //save stack to free memory later
+ *stack = (*stack)->next; //new stack
+
+ free(prev);
+ prev = NULL;
+
+ return data;
+}
+
+#define VAPI_DUMP_LIST_CB(api_name) \
+static vapi_error_e \
+api_name##_all_cb(vapi_ctx_t ctx, void *caller_ctx, vapi_error_e rv, bool is_last, \
+ vapi_payload_##api_name##_details *reply) \
+{ \
+ UNUSED(ctx); UNUSED(rv); UNUSED(is_last); \
+ struct elt **stackp; \
+ ARG_CHECK2(VAPI_EINVAL, caller_ctx, reply); \
+ \
+ stackp = (struct elt**) caller_ctx; \
+ push(stackp, reply, sizeof(*reply)); \
+ \
+ return VAPI_OK; \
+}
+
+#define foreach_stack_elt(stack) \
+ for(void *data = pop(&stack); data != NULL ; data = pop(&stack))
+//for(void *data = pop(&stack); stack != NULL ; data = pop(&stack)) // No!!
+
int sc_aton(const char *cp, u8 * buf, size_t length);
char * sc_ntoa(const u8 * buf);
@@ -126,7 +203,7 @@ uint32_t hardntohlu32(uint8_t host[4]);
* VPP
*/
-extern vapi_ctx_t g_vapi_ctx_instance;
+extern vapi_ctx_t g_vapi_ctx;
extern vapi_mode_e g_vapi_mode;
int sc_connect_vpp();
diff --git a/src/scvpp/inc/scvpp/interface.h b/src/scvpp/inc/scvpp/interface.h
new file mode 100644
index 0000000..86cd185
--- /dev/null
+++ b/src/scvpp/inc/scvpp/interface.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2018 PANTHEON.tech.
+ *
+ * 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.
+ */
+
+#ifndef __BAPI_INTERFACE_H__
+#define __BAPI_INTERFACE_H__
+
+#include <vapi/interface.api.vapi.h>
+#include <scvpp/comm.h>
+
+typedef vapi_payload_sw_interface_details sw_interface_dump_t;
+
+/**
+ * @brief Change an interface state
+ * @param interface_name - name of target interface
+ * @param enable - true=state up, false=state down
+ * @return 0 for success, else negative SCVPP error code
+ */
+int interface_enable(const char *interface_name, const bool enable);
+
+/**
+ * @brief Dump details about all existing interfaces
+ * @return stack structure containing all interfaces or NULL if empty
+ */
+extern struct elt * interface_dump_all();
+
+
+/**
+ * @brief Dump details about a specific interface
+ * @param details - where answer will be written
+ * @param interface_name - name of the interface to dump
+ * @return 0 for success or negative SCVPP error code
+ */
+extern int interface_dump_iface(sw_interface_dump_t *details,
+ const char *interface_name);
+
+/*
+ * Library internal helper functions. Symbols should not be exported eventually
+ */
+
+/*
+ * @brief Get VPP internal index for an interface
+ * @param interface_name - name of the interface to get id from
+ * @param sw_if_index - pointer to interface index to be returned
+ * @return 0 upon success or negative SCVPP error code
+ */
+extern int get_interface_id(const char *interface_name, uint32_t *sw_if_index);
+
+/* @brief Get interface name from an interface ID. This is a super expensive
+ * operation !!! Avoid using it.
+ * @param interface_name - pointer to string holding returned interface name
+ * @param sw_if_index - interface index provided
+ * @return 0 upon success or negative SCVPP error code
+ */
+extern int get_interface_name(char *interface_name, uint32_t sw_if_index);
+
+#endif /* __BAPI_INTERFACE_H__ */
diff --git a/src/scvpp/inc/scvpp/ip.h b/src/scvpp/inc/scvpp/ip.h
new file mode 100644
index 0000000..f8805b3
--- /dev/null
+++ b/src/scvpp/inc/scvpp/ip.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2018 PANTHEON.tech.
+ *
+ * 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.
+ */
+
+
+#ifndef __BAPI_IP_H__
+#define __BAPI_IP_H__
+
+#include <vapi/interface.api.vapi.h>
+#include <vapi/ip.api.vapi.h>
+
+typedef vapi_payload_ip_fib_details fib_dump_t;
+
+/*
+ * @brief Dump IPv4/IPv6 address from an interface.
+ * @param interface_name - name of the interface to get ip from.
+ * @param ip_addr - where dump will store IP. If IP not found, returns 0.0.0.0
+ * @param prefix_len - pointer where dump will store prefix
+ * @param is_ipv6 - true = IPv6, false = IPv4
+ * @return 0 on success, or nergative SCVPP error code
+ */
+extern int ipv46_address_dump(const char *interface_name, char *ip_addr,
+ u8 *prefix_len, bool is_ipv6);
+
+/**
+ * @brief Add or remove IPv4/IPv6 address to/from an interface.
+ * @param interface_name - name of interface to configure
+ * @param addr - address to add
+ * @param prefix_len - prefix length of interface
+ * @param is_ipv6 - true if ipv6, false otherwise
+ * @param add - true to add, false to remove
+ */
+extern int ipv46_config_add_remove(const char *interface_name, const char *addr,
+ uint8_t prefix_len, bool is_ipv6, bool add);
+
+/*
+ * TODO should add a field is_ipv6 because it only do ipv4 now
+ * @brief Add or remove an IP route
+ * @param dst_address - subnet IP you wish to route
+ * @param dst_address_length - prefix length for subnet you wish to route
+ * @param next_address - Next hop IP (can use next_hop_interface instead)
+ * @param is_add - true to add, false to remove
+ * @param table_id - id of the tab in FIB
+ * @param next_hop_interface - Next hop interface (can use next_address instead)
+ */
+extern int
+ipv46_config_add_del_route(const char* dst_address, u8 dst_address_length,
+ const char* next_address, u8 is_add, u32 table_id,
+ const char *next_hop_interface);
+
+/**
+ * @brief Dump all FIB tables entries
+ * @return stacked answers on success, or NULL on failure
+ */
+extern struct elt* ipv4_fib_dump_all();
+
+/*
+ * @brief Dump information about a prefix, based on fib_dump_all
+ * @param prefix_xpath - prefix to look for in FIB
+ * @param reply - FIB entry dump replied
+ * @return SCVPP_OK if prefix found or SCVPP_NOT_FOUND
+ */
+extern int ipv4_fib_dump_prefix(const char *prefix_xpath, fib_dump_t **reply);
+
+#endif /* __BAPI_IP_H__ */
diff --git a/src/scvpp/src/sc_vpp_nat.h b/src/scvpp/inc/scvpp/nat.h
index 40e727e..40e727e 100644
--- a/src/scvpp/src/sc_vpp_nat.h
+++ b/src/scvpp/inc/scvpp/nat.h
diff --git a/src/scvpp/inc/scvpp/v3po.h b/src/scvpp/inc/scvpp/v3po.h
new file mode 100644
index 0000000..f876ab4
--- /dev/null
+++ b/src/scvpp/inc/scvpp/v3po.h
@@ -0,0 +1,54 @@
+/*
+ * 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.
+ */
+
+#ifndef _V3PO__INTERFACE_H__
+#define _V3PO__INTERFACE_H__
+
+#include <vapi/tapv2.api.vapi.h>
+#include <vapi/l2.api.vapi.h>
+
+/**
+ * V3PO defines operations for specific interfaces used by VPP like:
+ * - tapv2
+ */
+
+/* tapv2 */
+
+typedef vapi_payload_tap_create_v2 tapv2_create_t;
+typedef vapi_payload_sw_interface_tap_v2_details tapv2_dump_t;
+
+/**
+ * TODO problem: vapi_payload_sw_interface_tap_v2_details reply is NULL
+ * @brief Dump information about a tap interface
+ * @param dump - where dump information will be stored
+ * @return 0 on success, or negative SCVPP error code
+ */
+extern int dump_tapv2(tapv2_dump_t *dump);
+
+/**
+ * @brief Create a tapv2 interface
+ * @param query - required structure for the creation of a VPP tapv2 interface
+ * @return 0 on success, or negative SCVPP error code
+ */
+extern int create_tapv2(tapv2_create_t *query);
+
+/**
+ * @brief Delete a tapv2 interface
+ * @param interface_name - name of the interface to delete
+ * @return 0 on success, or negative SCVPP error code
+ */
+extern int delete_tapv2(char *interface_name);
+
+#endif /* __V3PO_INTERFACE_H__ */
diff --git a/src/scvpp/src/CMakeLists.txt b/src/scvpp/src/CMakeLists.txt
deleted file mode 100644
index 71a891f..0000000
--- a/src/scvpp/src/CMakeLists.txt
+++ /dev/null
@@ -1,57 +0,0 @@
-#
-# Copyright (c) 2018 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.
-#
-
-# scvpp sources
-set(SCVPP_SOURCES
- sc_vpp_comm.c
- sc_vpp_interface.c
- sc_vpp_ip.c
- sc_vpp_v3po.c
- sc_vpp_nat.c
-)
-
-# scvpp public headers
-set(SCVPP_HEADERS
- sc_vpp_comm.h
- sc_vpp_interface.h
- sc_vpp_ip.h
- sc_vpp_v3po.h
- sc_vpp_nat.h
-)
-
-# Generate a compile_commands.json with compile options
-set(CMAKE_EXPORT_COMPILE_COMMANDS 1)
-
-#set compiler and linker flags
-set(RIGOROUS_C_FLAGS "-Wlogical-op -Wformat=2")
-set(CMAKE_C_FLAGS "-Wall -Wextra -std=gnu99 ${RIGOROUS_C_FLAGS}")
-set(CMAKE_C_FLAGS_DEBUG "-Wall -Wextra -std=gnu99 -g -O0 ${RIGOROUS_C_FLAGS}")
-#NDEBUG to skip assert checks
-set(CMAKE_C_FLAGS_RELEASE "-Wall -Wextra -std=gnu99 -DNDEBUG -O2 ${RIGOROUS_C_FLAGS}")
-
-# libraries to link with
-set(LINK_LIBRARIES vlibmemoryclient vapiclient vppapiclient svm vppinfra pthread rt dl)
-
-# build instructions
-add_library(scvpp SHARED ${SCVPP_SOURCES})
-add_library(scvpp_a ${SCVPP_SOURCES})
-
-# linker instructions
-target_link_libraries(scvpp ${LINK_LIBRARIES})
-target_link_libraries(scvpp_a ${LINK_LIBRARIES})
-
-# install rules
-install(TARGETS scvpp DESTINATION ${CMAKE_INSTALL_LIBDIR})
-install(FILES ${SCVPP_HEADERS} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
diff --git a/src/scvpp/src/sc_vpp_comm.c b/src/scvpp/src/comm.c
index cd0b035..a065b58 100644
--- a/src/scvpp/src/sc_vpp_comm.c
+++ b/src/scvpp/src/comm.c
@@ -12,7 +12,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-#include "sc_vpp_comm.h"
+#include <scvpp/comm.h>
#include <assert.h>
#include <string.h>
@@ -24,21 +24,21 @@
#define MAX_OUTSTANDING_REQUESTS 4
#define RESPONSE_QUEUE_SIZE 2
-vapi_ctx_t g_vapi_ctx_instance = NULL;
+vapi_ctx_t g_vapi_ctx = NULL;
vapi_mode_e g_vapi_mode = VAPI_MODE_NONBLOCKING;
int sc_connect_vpp()
{
- if (g_vapi_ctx_instance == NULL)
+ if (g_vapi_ctx == NULL)
{
- vapi_error_e rv = vapi_ctx_alloc(&g_vapi_ctx_instance);
- rv = vapi_connect(g_vapi_ctx_instance, APP_NAME, NULL,
+ vapi_error_e rv = vapi_ctx_alloc(&g_vapi_ctx);
+ rv = vapi_connect(g_vapi_ctx, APP_NAME, NULL,
MAX_OUTSTANDING_REQUESTS, RESPONSE_QUEUE_SIZE,
VAPI_MODE_BLOCKING, true);
if (rv != VAPI_OK)
{
- vapi_ctx_free(g_vapi_ctx_instance);
- g_vapi_ctx_instance = NULL;
+ vapi_ctx_free(g_vapi_ctx);
+ g_vapi_ctx = NULL;
return -1;
}
}
@@ -48,11 +48,11 @@ int sc_connect_vpp()
int sc_disconnect_vpp()
{
- if (NULL != g_vapi_ctx_instance)
+ if (NULL != g_vapi_ctx)
{
- vapi_disconnect(g_vapi_ctx_instance);
- vapi_ctx_free(g_vapi_ctx_instance);
- g_vapi_ctx_instance = NULL;
+ vapi_disconnect(g_vapi_ctx);
+ vapi_ctx_free(g_vapi_ctx);
+ g_vapi_ctx = NULL;
}
return 0;
}
diff --git a/src/scvpp/src/interface.c b/src/scvpp/src/interface.c
new file mode 100644
index 0000000..53cea1c
--- /dev/null
+++ b/src/scvpp/src/interface.c
@@ -0,0 +1,176 @@
+/*
+ * Copyright (c) 2018 PANTHEON.tech.
+ *
+ * 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 <stdbool.h>
+
+#include <scvpp/comm.h>
+#include <scvpp/interface.h>
+
+// Use VAPI macros to define symbols
+DEFINE_VAPI_MSG_IDS_INTERFACE_API_JSON
+
+static vapi_error_e
+sw_interface_dump_cb(struct vapi_ctx_s *ctx, void *callback_ctx,
+ vapi_error_e rv, bool is_last,
+ vapi_payload_sw_interface_details *reply)
+{
+ UNUSED(rv); UNUSED(ctx); UNUSED(is_last);
+
+ vapi_payload_sw_interface_details *passed;
+
+ ARG_CHECK2(VAPI_EINVAL, callback_ctx, reply);
+
+ //copy
+ passed = (vapi_payload_sw_interface_details *) callback_ctx;
+ *passed = *reply;
+
+ return VAPI_OK;
+}
+
+static vapi_error_e
+bin_api_sw_interface_dump(vapi_payload_sw_interface_details *details,
+ const char *iface_name)
+{
+ vapi_msg_sw_interface_dump *mp;
+ vapi_error_e rv;
+
+ mp = vapi_alloc_sw_interface_dump(g_vapi_ctx);
+ assert(NULL != mp);
+
+ /* Dump a specific interfaces */
+ mp->payload.name_filter_valid = true;
+ strncpy((char *)mp->payload.name_filter, iface_name, VPP_INTFC_NAME_LEN);
+
+ VAPI_CALL(vapi_sw_interface_dump(g_vapi_ctx, mp,
+ sw_interface_dump_cb, details));
+ if (rv != VAPI_OK)
+ return -SCVPP_EINVAL;
+
+ return rv;
+}
+
+int get_interface_id(const char *if_name, uint32_t *sw_if_index)
+{
+ vapi_payload_sw_interface_details details = {0};
+ vapi_error_e rv;
+
+ ARG_CHECK2(-SCVPP_EINVAL, if_name, sw_if_index);
+
+ rv = bin_api_sw_interface_dump(&details, if_name);
+ if (rv != VAPI_OK)
+ return -SCVPP_EINVAL;
+
+ if (strncmp(if_name, (char*) details.interface_name, VPP_INTFC_NAME_LEN)
+ != 0)
+ return -SCVPP_NOT_FOUND;
+
+ *sw_if_index = details.sw_if_index;
+
+ return 0;
+}
+
+/*
+ * dump only a specific interface
+ */
+int interface_dump_iface(sw_interface_dump_t *details, const char *iface_name)
+{
+ vapi_error_e rv;
+
+ rv = bin_api_sw_interface_dump(details, iface_name);
+ if (rv != VAPI_OK)
+ return -SCVPP_EINVAL;
+
+ if (strncmp(iface_name, (char*) details->interface_name, VPP_INTFC_NAME_LEN)
+ != 0)
+ return -SCVPP_NOT_FOUND;
+
+ return SCVPP_OK;
+}
+
+VAPI_DUMP_LIST_CB(sw_interface)
+
+struct elt* interface_dump_all()
+{
+ struct elt* stack = NULL;
+ vapi_msg_sw_interface_dump *mp;
+ vapi_error_e rv;
+
+ mp = vapi_alloc_sw_interface_dump(g_vapi_ctx);
+
+ /* Dump all */
+ mp->payload.name_filter_valid = false;
+ memset(mp->payload.name_filter, 0, sizeof(mp->payload.name_filter));
+
+ VAPI_CALL(vapi_sw_interface_dump(g_vapi_ctx, mp, sw_interface_all_cb,
+ &stack));
+ if (VAPI_OK != rv)
+ return NULL;
+
+ return stack;
+}
+
+VAPI_RETVAL_CB(sw_interface_set_flags);
+
+int interface_enable(const char *interface_name, const bool enable)
+{
+ vapi_msg_sw_interface_set_flags *mp;
+ uint32_t sw_if_index;
+ vapi_error_e rv;
+ int rc;
+
+ ARG_CHECK(-SCVPP_EINVAL, interface_name);
+
+ rc = get_interface_id(interface_name, &sw_if_index);
+ if (rc != 0)
+ return -SCVPP_NOT_FOUND;
+
+ mp = vapi_alloc_sw_interface_set_flags(g_vapi_ctx);
+ assert(NULL != mp);
+ mp->payload.sw_if_index = sw_if_index;
+ mp->payload.admin_up_down = enable;
+
+ VAPI_CALL(vapi_sw_interface_set_flags(g_vapi_ctx, mp,
+ sw_interface_set_flags_cb, NULL));
+ if (VAPI_OK != rv)
+ return -SCVPP_EINVAL;
+
+ return 0;
+}
+
+int get_interface_name(char *interface_name, uint32_t sw_if_index)
+{
+ struct elt *stack= NULL;
+ sw_interface_dump_t *dump;
+ int rc = -SCVPP_NOT_FOUND;
+
+ stack = interface_dump_all();
+ if (!stack)
+ return -SCVPP_NOT_FOUND;
+
+ foreach_stack_elt(stack) {
+ dump = (sw_interface_dump_t *) data;
+
+ if (dump->sw_if_index == sw_if_index) {
+ strncpy(interface_name, (char *)dump->interface_name, VPP_INTFC_NAME_LEN);
+ rc = SCVPP_OK;
+ }
+
+ free(dump);
+ }
+
+ return rc;
+}
diff --git a/src/scvpp/src/sc_vpp_ip.c b/src/scvpp/src/ip.c
index 0dfd108..2dc991c 100644
--- a/src/scvpp/src/sc_vpp_ip.c
+++ b/src/scvpp/src/ip.c
@@ -14,12 +14,12 @@
* limitations under the License.
*/
-#include "sc_vpp_comm.h"
-#include "sc_vpp_ip.h"
-
-#include "sc_vpp_interface.h"
+#include <scvpp/comm.h>
+#include <scvpp/ip.h>
+#include <scvpp/interface.h>
#include <assert.h>
+#include <stdio.h>
// Use VAPI macros to define symbols
DEFINE_VAPI_MSG_IDS_IP_API_JSON
@@ -36,7 +36,7 @@ bin_api_sw_interface_add_del_address(u32 sw_if_index, bool is_add, bool is_ipv6,
ARG_CHECK(VAPI_EINVAL, ip_address);
- mp = vapi_alloc_sw_interface_add_del_address(g_vapi_ctx_instance);
+ mp = vapi_alloc_sw_interface_add_del_address(g_vapi_ctx);
assert(NULL != mp);
mp->payload.sw_if_index = sw_if_index;
@@ -44,10 +44,10 @@ bin_api_sw_interface_add_del_address(u32 sw_if_index, bool is_add, bool is_ipv6,
mp->payload.is_ipv6 = is_ipv6;
mp->payload.del_all = del_all;
mp->payload.address_length = address_length;
- if (sc_aton(ip_address, mp->payload.address, sizeof(mp->payload.address)))
+ if (sc_aton(ip_address, mp->payload.address, VPP_IP4_ADDRESS_LEN))
return VAPI_EINVAL;
- VAPI_CALL(vapi_sw_interface_add_del_address(g_vapi_ctx_instance, mp,
+ VAPI_CALL(vapi_sw_interface_add_del_address(g_vapi_ctx, mp,
sw_interface_add_del_address_cb, NULL));
return rv;
@@ -59,38 +59,41 @@ static vapi_error_e
bin_api_ip_add_del_route(vapi_payload_ip_add_del_route_reply * reply,
const char* dst_address, uint8_t dst_address_length,
const char* next_hop, uint8_t is_add,
- uint32_t table_id, const char *interface_name)
+ uint32_t table_id, const char *next_interface)
{
- sw_interface_details_query_t query = {0};
vapi_msg_ip_add_del_route *mp;
+ uint32_t sw_if_index;
+ vapi_error_e rv ;
+ int rc;
- ARG_CHECK4(VAPI_EINVAL, reply, dst_address, next_hop, interface_name);
-
- sw_interface_details_query_set_name(&query, interface_name);
+ ARG_CHECK2(VAPI_EINVAL, reply, dst_address);
- if (!get_interface_id(&query))
+ //Require interface or next hop IP or both
+ if (!next_interface && !next_hop)
return VAPI_EINVAL;
- mp = vapi_alloc_ip_add_del_route (g_vapi_ctx_instance, 1);
+ mp = vapi_alloc_ip_add_del_route(g_vapi_ctx, 1);
assert(NULL != mp);
- //ip route add 2.2.2.2/24 via 5.5.5.5
- //show ip fib table 0 2.2.2.0/24 detail
+ if (next_interface) {
+ rc = get_interface_id(next_interface, &sw_if_index);
+ if (rc < 0)
+ return VAPI_EINVAL;
+ }
mp->payload.is_add = is_add;
- mp->payload.dst_address_length = dst_address_length;
mp->payload.table_id = table_id;
- mp->payload.next_hop_sw_if_index = query.sw_interface_details.sw_if_index;
-
- if (sc_aton(dst_address, mp->payload.dst_address,
- sizeof(mp->payload.dst_address)))
- return VAPI_EINVAL;
- if (sc_aton(next_hop, mp->payload.next_hop_address,
- sizeof(mp->payload.next_hop_address)))
- return VAPI_EINVAL;
+ mp->payload.is_ipv6 = false;
+ mp->payload.is_local = false;
+ sc_aton(dst_address, mp->payload.dst_address, VPP_IP4_ADDRESS_LEN);
+ mp->payload.dst_address_length = dst_address_length;
+ if (next_interface) //interface is not mandatory
+ mp->payload.next_hop_sw_if_index = sw_if_index;
+ if (next_hop) //next hop ip is not mandatory
+ sc_aton(next_hop, mp->payload.next_hop_address, VPP_IP4_ADDRESS_LEN);
- vapi_error_e rv ;
- VAPI_CALL(vapi_ip_add_del_route(g_vapi_ctx_instance, mp, ip_add_del_route_cb, reply));
+ VAPI_CALL(vapi_ip_add_del_route(g_vapi_ctx, mp,
+ ip_add_del_route_cb, reply));
return rv;
}
@@ -100,12 +103,13 @@ ip_address_dump_cb (struct vapi_ctx_s *ctx, void *callback_ctx, vapi_error_e rv,
bool is_last, vapi_payload_ip_address_details *reply)
{
UNUSED(rv);
+ vapi_payload_ip_address_details *passed;
+
ARG_CHECK3(VAPI_EINVAL, ctx, callback_ctx, reply);
//copy dump reply in callback context
- if (!is_last && callback_ctx) {
- vapi_payload_ip_address_details *passed =
- (vapi_payload_ip_address_details *) callback_ctx;
+ if (!is_last) {
+ passed = (vapi_payload_ip_address_details *) callback_ctx;
*passed = *reply;
}
@@ -119,11 +123,13 @@ bin_api_ip_address_dump(u32 sw_if_index, bool is_ipv6,
vapi_msg_ip_address_dump *mp;
vapi_error_e rv;
- mp = vapi_alloc_ip_address_dump(g_vapi_ctx_instance);
+ mp = vapi_alloc_ip_address_dump(g_vapi_ctx);
+ assert(mp != NULL);
+
mp->payload.sw_if_index = sw_if_index;
mp->payload.is_ipv6 = is_ipv6;
- VAPI_CALL(vapi_ip_address_dump(g_vapi_ctx_instance, mp, ip_address_dump_cb,
+ VAPI_CALL(vapi_ip_address_dump(g_vapi_ctx, mp, ip_address_dump_cb,
dctx));
if (rv != VAPI_OK)
return rv;
@@ -131,64 +137,112 @@ bin_api_ip_address_dump(u32 sw_if_index, bool is_ipv6,
return VAPI_OK;
}
-/*
- * @brief Dump IPv4/IPv6 address from an interface.
- * @param interface_name Name of the interface to dump.
- * @param ip_addr pointer where dump will store IP.
- * @param prefix_len pointer where dump will store prefix
- */
+///VAPI_DUMP_LIST_CB(ip_fib); can not be used because of path flexible array
+
+static vapi_error_e
+ip_fib_all_cb(vapi_ctx_t ctx, void *caller_ctx, vapi_error_e rv, bool is_last,
+ vapi_payload_ip_fib_details *reply)
+{
+ UNUSED(ctx); UNUSED(rv); UNUSED(is_last);
+ struct elt **stackp;
+ ARG_CHECK2(VAPI_EINVAL, caller_ctx, reply);
+
+ stackp = (struct elt**) caller_ctx;
+ push(stackp, reply, sizeof(*reply)+reply->count*sizeof(vapi_type_fib_path));
+
+ return VAPI_OK;
+}
+
+struct elt* ipv4_fib_dump_all()
+{
+ struct elt *stack = NULL;
+ vapi_msg_ip_fib_dump *mp;
+ vapi_error_e rv;
+
+ mp = vapi_alloc_ip_fib_dump(g_vapi_ctx);
+ assert(mp != NULL);
+
+ VAPI_CALL(vapi_ip_fib_dump(g_vapi_ctx, mp, ip_fib_all_cb, &stack));
+ if(VAPI_OK != rv)
+ return NULL;
+
+ return stack;
+}
+
+int ipv4_fib_dump_prefix(const char *prefix_xpath, fib_dump_t **reply)
+{
+ struct elt *stack = NULL;
+ char prefix[VPP_IP4_PREFIX_STRING_LEN];
+ fib_dump_t *dump;
+ int rc = -SCVPP_NOT_FOUND;
+
+ stack = ipv4_fib_dump_all();
+ if (!stack)
+ return rc;
+
+ foreach_stack_elt(stack) {
+ dump = (fib_dump_t *) data;
+
+ if (rc == -SCVPP_NOT_FOUND) {
+ snprintf(prefix, VPP_IP4_PREFIX_STRING_LEN, "%s/%u",
+ sc_ntoa(dump->address), dump->address_length);
+ if (!strncmp(prefix_xpath, prefix, VPP_IP4_PREFIX_STRING_LEN)) {
+ *reply = dump;
+ rc = SCVPP_OK;
+ continue;
+ }
+ }
+
+ free(dump);
+ }
+
+ return rc;
+}
+
int ipv46_address_dump(const char *interface_name, char *ip_addr,
u8 *prefix_len, bool is_ipv6)
{
vapi_payload_ip_address_details dctx = {0};
- sw_interface_details_query_t query = {0};
+ uint32_t sw_if_index;
vapi_error_e rv;
+ int rc;
- sw_interface_details_query_set_name(&query, interface_name);
-
- if (!get_interface_id(&query))
- return -EINVAL;
+ rc = get_interface_id(interface_name, &sw_if_index);
+ if (rc < 0)
+ return rc;
- rv = bin_api_ip_address_dump(query.sw_interface_details.sw_if_index, is_ipv6, &dctx);
+ rv = bin_api_ip_address_dump(sw_if_index, is_ipv6, &dctx);
if (rv != VAPI_OK)
- return -EAGAIN;
+ return -SCVPP_EINVAL;
strcpy(ip_addr, sc_ntoa(dctx.ip)); //IP string
*prefix_len = dctx.prefix_length; //prefix length
- return 0;
+ return SCVPP_OK;
}
-/**
- * @brief Add or remove IPv4/IPv6 address to/from an interface.
- */
int ipv46_config_add_remove(const char *if_name, const char *addr,
uint8_t prefix, bool is_ipv6, bool add)
{
vapi_error_e rv;
+ uint32_t sw_if_index;
int rc;
ARG_CHECK2(-1, if_name, addr);
- /* get interface index */
- sw_interface_details_query_t query = {0};
- sw_interface_details_query_set_name(&query, if_name);
- rc = get_interface_id(&query);
- if (!rc)
- return -EINVAL;
+ rc = get_interface_id(if_name, &sw_if_index);
+ if (rc < 0)
+ return rc;
/* add del addr */
- rv = bin_api_sw_interface_add_del_address(query.sw_interface_details.sw_if_index,
- add, is_ipv6, 0, prefix, addr);
+ rv = bin_api_sw_interface_add_del_address(sw_if_index, add, is_ipv6, 0,
+ prefix, addr);
if (rv != VAPI_OK)
- return -EINVAL;
+ return -SCVPP_EINVAL;
- return 0;
+ return SCVPP_OK;
}
-/*
- * @brief Add or remove an IP route
- */
int ipv46_config_add_del_route(const char* dst_address, u8 dst_address_length,
const char* next_address, u8 is_add,
u32 table_id, const char *interface)
@@ -198,9 +252,8 @@ int ipv46_config_add_del_route(const char* dst_address, u8 dst_address_length,
rv = bin_api_ip_add_del_route(&reply, dst_address, dst_address_length,
next_address, is_add, table_id, interface);
- if (VAPI_OK != rv || reply.retval > 0) {
- return -EINVAL;
- }
+ if (VAPI_OK != rv || reply.retval > 0)
+ return -SCVPP_EINVAL;
- return 0;
+ return SCVPP_OK;
}
diff --git a/src/scvpp/src/sc_vpp_nat.c b/src/scvpp/src/nat.c
index e4bf2b7..17ace64 100644
--- a/src/scvpp/src/sc_vpp_nat.c
+++ b/src/scvpp/src/nat.c
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#include "sc_vpp_comm.h"
-#include "sc_vpp_nat.h"
+#include <scvpp/comm.h>
+#include <scvpp/nat.h>
#include <assert.h>
#include <stdbool.h>
@@ -28,8 +28,7 @@ nat44_interface_dump_cb(struct vapi_ctx_s *ctx, void *callback_ctx,
vapi_error_e rv, bool is_last,
vapi_payload_nat44_interface_details *reply)
{
- UNUSED(ctx);
- UNUSED(rv);
+ UNUSED(ctx); UNUSED(rv);
vapi_payload_nat44_interface_details *dctx = callback_ctx;
assert(dctx);
@@ -56,10 +55,10 @@ bin_api_nat44_interface_dump(vapi_payload_nat44_interface_details *reply)
ARG_CHECK(VAPI_EINVAL, reply);
- mp = vapi_alloc_nat44_interface_dump(g_vapi_ctx_instance);
+ mp = vapi_alloc_nat44_interface_dump(g_vapi_ctx);
assert(NULL != mp);
- VAPI_CALL(vapi_nat44_interface_dump(g_vapi_ctx_instance, mp,
+ VAPI_CALL(vapi_nat44_interface_dump(g_vapi_ctx, mp,
nat44_interface_dump_cb, reply));
return rv;
@@ -76,12 +75,12 @@ bin_api_nat44_add_del_interface_addr(
ARG_CHECK(VAPI_EINVAL, msg);
- mp = vapi_alloc_nat44_add_del_interface_addr(g_vapi_ctx_instance);
+ mp = vapi_alloc_nat44_add_del_interface_addr(g_vapi_ctx);
assert(NULL != mp);
mp->payload = *msg;
- VAPI_CALL(vapi_nat44_add_del_interface_addr(g_vapi_ctx_instance, mp,
+ VAPI_CALL(vapi_nat44_add_del_interface_addr(g_vapi_ctx, mp,
nat44_add_del_interface_addr_cb,
NULL));
@@ -99,13 +98,13 @@ bin_api_nat44_add_del_addr_range(
ARG_CHECK(VAPI_EINVAL, range);
- mp = vapi_alloc_nat44_add_del_address_range(g_vapi_ctx_instance);
+ mp = vapi_alloc_nat44_add_del_address_range(g_vapi_ctx);
assert(NULL != mp);
mp->payload = *range;
- VAPI_CALL(vapi_nat44_add_del_address_range(g_vapi_ctx_instance, mp,
+ VAPI_CALL(vapi_nat44_add_del_address_range(g_vapi_ctx, mp,
nat44_add_del_address_range_cb,
NULL));
@@ -123,13 +122,12 @@ bin_api_nat44_add_del_static_mapping(
ARG_CHECK(VAPI_EINVAL, msg);
- mp = vapi_alloc_nat44_add_del_static_mapping(g_vapi_ctx_instance);
-
+ mp = vapi_alloc_nat44_add_del_static_mapping(g_vapi_ctx);
assert(NULL != mp);
mp->payload = *msg;
- VAPI_CALL(vapi_nat44_add_del_static_mapping(g_vapi_ctx_instance, mp,
+ VAPI_CALL(vapi_nat44_add_del_static_mapping(g_vapi_ctx, mp,
nat44_add_del_static_mapping_cb,
NULL));
@@ -140,8 +138,7 @@ static vapi_error_e nat44_static_mapping_dump_cb(
struct vapi_ctx_s *ctx, void *callback_ctx, vapi_error_e rv,
bool is_last,vapi_payload_nat44_static_mapping_details *reply)
{
- UNUSED(rv);
- UNUSED(ctx);
+ UNUSED(rv); UNUSED(ctx);
vapi_payload_nat44_static_mapping_details *dctx = callback_ctx;
assert(dctx);
@@ -166,10 +163,10 @@ bin_api_nat44_static_mapping_dump(
ARG_CHECK(VAPI_EINVAL, reply);
- msg = vapi_alloc_nat44_static_mapping_dump(g_vapi_ctx_instance);
+ msg = vapi_alloc_nat44_static_mapping_dump(g_vapi_ctx);
assert(NULL != msg);
- VAPI_CALL(vapi_nat44_static_mapping_dump(g_vapi_ctx_instance, msg,
+ VAPI_CALL(vapi_nat44_static_mapping_dump(g_vapi_ctx, msg,
nat44_static_mapping_dump_cb,
reply));
@@ -186,13 +183,13 @@ static vapi_error_e bin_api_nat44_forwarding_enable_disable(
ARG_CHECK(VAPI_EINVAL, msg);
- mp = vapi_alloc_nat44_forwarding_enable_disable(g_vapi_ctx_instance);
+ mp = vapi_alloc_nat44_forwarding_enable_disable(g_vapi_ctx);
assert(NULL != mp);
mp->payload = *msg;
VAPI_CALL(vapi_nat44_forwarding_enable_disable(
- g_vapi_ctx_instance, mp, nat44_forwarding_enable_disable_cb, NULL));
+ g_vapi_ctx, mp, nat44_forwarding_enable_disable_cb, NULL));
return rv;
}
@@ -207,113 +204,91 @@ bin_api_nat_set_workers(const vapi_payload_nat_set_workers *msg)
ARG_CHECK(VAPI_EINVAL, msg);
- mp = vapi_alloc_nat_set_workers(g_vapi_ctx_instance);
+ mp = vapi_alloc_nat_set_workers(g_vapi_ctx);
assert(NULL != mp);
mp->payload = *msg;
- VAPI_CALL(vapi_nat_set_workers(g_vapi_ctx_instance, mp, nat_set_workers_cb,
- NULL));
+ VAPI_CALL(vapi_nat_set_workers(g_vapi_ctx, mp, nat_set_workers_cb, NULL));
return rv;
}
int nat44_interface_dump(nat44_interface_details_t *reply)
{
- vapi_error_e rc;
+ vapi_error_e rv;
- rc = bin_api_nat44_interface_dump(reply);
- if (VAPI_OK != rc) {
- //TODO: Need implement log function
-// ERROR("Error in nat44_interface_dump, error: %u", rc);
- return -1;
- }
+ rv = bin_api_nat44_interface_dump(reply);
+ if (VAPI_OK != rv)
+ return -SCVPP_EINVAL;
- return 0;
+ return SCVPP_OK;
}
int nat44_add_del_interface_addr(const nat44_add_del_interface_addr_t *msg)
{
- vapi_error_e rc;
+ vapi_error_e rv;
- rc = bin_api_nat44_add_del_interface_addr(msg);
- if (VAPI_OK != rc) {
- //TODO: Need implement log function
-// ERROR("Error in nat44_interface_dump, error: %u", rc);
- return -1;
- }
+ rv = bin_api_nat44_add_del_interface_addr(msg);
+ if (VAPI_OK != rv)
+ return -SCVPP_EINVAL;
- return 0;
+ return SCVPP_OK;
}
int nat44_add_del_addr_range(const nat44_add_del_address_range_t *range)
{
- vapi_error_e rc;
+ vapi_error_e rv;
- rc = bin_api_nat44_add_del_addr_range(range);
- if (VAPI_OK != rc) {
- //TODO: Need implement log function
-// ERROR("Error in nat44_interface_dump, error: %u", rc);
- return -1;
- }
+ rv = bin_api_nat44_add_del_addr_range(range);
+ if (VAPI_OK != rv)
+ return -SCVPP_EINVAL;
- return 0;
+ return SCVPP_OK;
}
int nat44_add_del_static_mapping(const nat44_add_del_static_mapping_t *msg)
{
- vapi_error_e rc;
+ vapi_error_e rv;
- rc = bin_api_nat44_add_del_static_mapping(msg);
- if (VAPI_OK != rc) {
- //TODO: Need implement log function
-// ERROR("Error in nat44_interface_dump, error: %u", rc);
- return -1;
- }
+ rv = bin_api_nat44_add_del_static_mapping(msg);
+ if (VAPI_OK != rv)
+ return -SCVPP_EINVAL;
- return 0;
+ return SCVPP_OK;
}
int nat44_static_mapping_dump(nat44_static_mapping_details_t *reply)
{
- vapi_error_e rc;
+ vapi_error_e rv;
- rc = bin_api_nat44_static_mapping_dump(reply);
- if (VAPI_OK != rc) {
- //TODO: Need implement log function
-// ERROR("Error in nat44_interface_dump, error: %u", rc);
- return -1;
- }
+ rv = bin_api_nat44_static_mapping_dump(reply);
+ if (VAPI_OK != rv)
+ return -SCVPP_EINVAL;
- return 0;
+ return SCVPP_OK;
}
-int nat44_forwarding_enable_disable(
- const nat44_forwarding_enable_disable_t *msg)
+int
+nat44_forwarding_enable_disable(const nat44_forwarding_enable_disable_t *msg)
{
- vapi_error_e rc;
+ vapi_error_e rv;
- rc = bin_api_nat44_forwarding_enable_disable(msg);
- if (VAPI_OK != rc) {
- //TODO: Need implement log function
-// ERROR("Error in nat44_interface_dump, error: %u", rc);
- return -1;
- }
+ rv = bin_api_nat44_forwarding_enable_disable(msg);
+ if (VAPI_OK != rv)
+ return -SCVPP_EINVAL;
return 0;
}
int nat_set_workers(const nat_set_workers_t *msg)
{
- vapi_error_e rc;
+ vapi_error_e rv;
- rc = bin_api_nat_set_workers(msg);
- if (VAPI_OK != rc) {
- //TODO: Need implement log function
-// ERROR("Error in nat44_interface_dump, error: %u", rc);
- return -1;
- }
+ rv = bin_api_nat_set_workers(msg);
+ if (VAPI_OK != rv)
+ return -SCVPP_EINVAL;
- return 0;
+ return SCVPP_OK;
}
diff --git a/src/scvpp/src/sc_vpp_interface.c b/src/scvpp/src/sc_vpp_interface.c
deleted file mode 100644
index bc5befc..0000000
--- a/src/scvpp/src/sc_vpp_interface.c
+++ /dev/null
@@ -1,252 +0,0 @@
-/*
- * Copyright (c) 2018 PANTHEON.tech.
- *
- * 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 <stdbool.h>
-
-#include <vapi/l2.api.vapi.h>
-
-#include "sc_vpp_comm.h"
-#include "sc_vpp_interface.h"
-
-
-// Use VAPI macros to define symbols
-DEFINE_VAPI_MSG_IDS_INTERFACE_API_JSON
-DEFINE_VAPI_MSG_IDS_L2_API_JSON;
-
-void sw_interface_details_query_set_name(sw_interface_details_query_t * query,
- const char * interface_name)
-{
- assert(query && interface_name);
-
- memset(query, 0, sizeof(*query));
-
- strncpy((char*) query->sw_interface_details.interface_name, interface_name,
- sizeof(query->sw_interface_details.interface_name));
-}
-
-static vapi_error_e
-sw_interface_dump_cb(struct vapi_ctx_s *ctx, void *callback_ctx,
- vapi_error_e rv, bool is_last,
- vapi_payload_sw_interface_details *reply)
-{
- UNUSED(rv); UNUSED(ctx); UNUSED(is_last);
-
- vapi_payload_sw_interface_details *passed;
-
- ARG_CHECK(-EINVAL, callback_ctx);
-
- passed = (vapi_payload_sw_interface_details *) callback_ctx;
-
- //Interface is found if index of query equals index of reply
- if (passed->sw_if_index != reply->sw_if_index)
- return -EINVAL;
-
- //copy
- *passed = *reply;
-
- return VAPI_OK;
-}
-
-static vapi_error_e
-bin_api_sw_interface_dump(vapi_payload_sw_interface_details *details)
-{
- vapi_msg_sw_interface_dump *mp;
- vapi_error_e rv;
-
- mp = vapi_alloc_sw_interface_dump(g_vapi_ctx_instance);
-
- mp->payload.name_filter_valid = 0;
- memset(mp->payload.name_filter, 0, sizeof(mp->payload.name_filter));
- assert(NULL != mp);
-
- VAPI_CALL(vapi_sw_interface_dump(g_vapi_ctx_instance, mp, sw_interface_dump_cb, details));
- if (!rv)
- return -EINVAL;
-
- return rv;
-}
-
-static vapi_error_e
-interface_dump_all_cb(struct vapi_ctx_s *ctx, void *callback_ctx,
- vapi_error_e rv, bool is_last,
- vapi_payload_sw_interface_details * reply)
-{
- UNUSED(ctx); UNUSED(rv);
- dump_all_ctx *dctx = callback_ctx;
-
- if (is_last)
- return VAPI_OK;
-
- if(dctx->capacity == 0 && dctx->intfcArray == NULL) {
- dctx->capacity = 10;
- dctx->intfcArray = (vpp_interface_t*)malloc( sizeof(vpp_interface_t)*dctx->capacity );
- }
- if(dctx->num_ifs >= dctx->capacity-1) {
- dctx->capacity += 10;
- dctx->intfcArray = (vpp_interface_t*)realloc(dctx->intfcArray, sizeof(vpp_interface_t)*dctx->capacity );
- }
-
- vpp_interface_t * iface = &dctx->intfcArray[dctx->num_ifs];
-
- iface->sw_if_index = reply->sw_if_index;
- strncpy(iface->interface_name, (char*) reply->interface_name,
- VPP_INTFC_NAME_LEN);
- iface->l2_address_length = reply->l2_address_length;
- memcpy(iface->l2_address, reply->l2_address, reply->l2_address_length );
- iface->link_speed = reply->link_speed;
-
- iface->link_mtu = reply->link_mtu;
- iface->admin_up_down = reply->admin_up_down;
- iface->link_up_down = reply->link_up_down;
-
- dctx->num_ifs += 1;
-
- return VAPI_OK;
-}
-
-int interface_dump_all(dump_all_ctx * dctx)
-{
- vapi_msg_sw_interface_dump *dump;
- vapi_error_e rv;
-
- ARG_CHECK(-1, dctx);
-
- if(dctx == NULL)
- return -1;
-
- dctx->intfcArray = NULL;
- dctx->capacity = 0;
- dctx->num_ifs = 0;
-
- dump = vapi_alloc_sw_interface_dump(g_vapi_ctx_instance);
-
- dump->payload.name_filter_valid = 0;
- memset(dump->payload.name_filter, 0, sizeof(dump->payload.name_filter));
- while (VAPI_EAGAIN ==
- (rv =
- vapi_sw_interface_dump(g_vapi_ctx_instance, dump, interface_dump_all_cb,
- dctx)));
-
- return dctx->num_ifs;
-}
-
-static vapi_error_e
-get_interface_id_cb (struct vapi_ctx_s *ctx, void *callback_ctx,
- vapi_error_e rv, bool is_last,
- vapi_payload_sw_interface_details * reply)
-{
- UNUSED(ctx); UNUSED(rv);
-
- sw_interface_details_query_t *dctx = callback_ctx;
- assert(dctx);
-
- if (!dctx->interface_found)
- {
- if (is_last)
- {
- assert(NULL == reply);
- }
- else
- {
- assert(NULL != reply);
-
- if (0 == strcmp((const char*)dctx->sw_interface_details.interface_name,
- (const char*)reply->interface_name))
- {
- dctx->interface_found = true;
- dctx->sw_interface_details = *reply;
- }
- }
- }
-
- return VAPI_OK;
-}
-
-// return error code instead of boolean
-int get_interface_id(sw_interface_details_query_t * sw_interface_details_query)
-{
- vapi_error_e rv;
-
- ARG_CHECK(false, sw_interface_details_query);
-
- sw_interface_details_query->interface_found = false;
-
- vapi_msg_sw_interface_dump *mp = vapi_alloc_sw_interface_dump (g_vapi_ctx_instance);
- assert(NULL != mp);
-
- mp->payload.name_filter_valid = true;
- memcpy(mp->payload.name_filter, sw_interface_details_query->sw_interface_details.interface_name,
- sizeof(mp->payload.name_filter));
-
- VAPI_CALL(vapi_sw_interface_dump(g_vapi_ctx_instance, mp, get_interface_id_cb, sw_interface_details_query));
- if (VAPI_OK != rv)
- return false;
-
- return sw_interface_details_query->interface_found;
-}
-
-int get_interface_name(sw_interface_details_query_t *query)
-{
- vapi_error_e rv;
-
- ARG_CHECK(-EINVAL, query);
-
- query->interface_found = false;
-
- rv = bin_api_sw_interface_dump(&query->sw_interface_details);
- if (rv == VAPI_OK)
- query->interface_found = true;
-
- return query->interface_found;
-}
-
-VAPI_RETVAL_CB(sw_interface_set_flags);
-
-static vapi_error_e
-bin_api_sw_interface_set_flags(uint32_t if_index, uint8_t up)
-{
- vapi_msg_sw_interface_set_flags *mp = vapi_alloc_sw_interface_set_flags (g_vapi_ctx_instance);
- assert(NULL != mp);
-
- mp->payload.sw_if_index = if_index;
- mp->payload.admin_up_down = up;
-
- vapi_error_e rv;
- VAPI_CALL(vapi_sw_interface_set_flags(g_vapi_ctx_instance, mp, sw_interface_set_flags_cb, NULL));
-
- return rv;
-}
-
-int interface_enable(const char *interface_name, const bool enable)
-{
- ARG_CHECK(-1, interface_name);
-
- int rc = 0;
- sw_interface_details_query_t query = {0};
- sw_interface_details_query_set_name(&query, interface_name);
-
- rc = get_interface_id(&query);
- if (!rc)
- return -1;
-
- rc = bin_api_sw_interface_set_flags(query.sw_interface_details.sw_if_index,
- enable);
- if (VAPI_OK != rc)
- return -1;
-
- return 0;
-}
diff --git a/src/scvpp/src/sc_vpp_interface.h b/src/scvpp/src/sc_vpp_interface.h
deleted file mode 100644
index 32b61bc..0000000
--- a/src/scvpp/src/sc_vpp_interface.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (c) 2018 PANTHEON.tech.
- *
- * 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.
- */
-
-#ifndef __BAPI_INTERFACE_H__
-#define __BAPI_INTERFACE_H__
-
-#include <vapi/interface.api.vapi.h>
-
-int interface_enable(const char *interface_name, const bool enable);
-
-//TODO remove the following structures ASAP
-typedef struct {
- bool interface_found;
- vapi_payload_sw_interface_details sw_interface_details;
-} sw_interface_details_query_t;
-
-typedef struct _vpp_interface_t
-{
- u32 sw_if_index;
- char interface_name[VPP_INTFC_NAME_LEN];
- u8 l2_address[VPP_MAC_ADDRESS_LEN];
- u32 l2_address_length;
- u64 link_speed;
- u16 link_mtu;
- u8 admin_up_down;
- u8 link_up_down;
-} vpp_interface_t;
-
-typedef struct _dump_all_ctx
-{
- int num_ifs;
- int capacity;
- vpp_interface_t * intfcArray;
-} dump_all_ctx;
-
-/* return the number of interfaces or a negative error code */
-extern int interface_dump_all(dump_all_ctx * dctx);
-
-extern void sw_interface_details_query_set_name(sw_interface_details_query_t * query,
- const char * interface_name);
-
-//input - sw_interface_details_query shall contain interface_name
-extern int get_interface_id(sw_interface_details_query_t * sw_interface_details_query);
-
-//input - sw_interface_details_query shall contain sw_if_index
-extern int get_interface_name(sw_interface_details_query_t * sw_interface_details_query);
-
-#endif /* __BAPI_INTERFACE_H__ */
diff --git a/src/scvpp/src/sc_vpp_ip.h b/src/scvpp/src/sc_vpp_ip.h
deleted file mode 100644
index a9f19d4..0000000
--- a/src/scvpp/src/sc_vpp_ip.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (c) 2018 PANTHEON.tech.
- *
- * 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.
- */
-
-
-#ifndef __BAPI_IP_H__
-#define __BAPI_IP_H__
-
-#include <vapi/interface.api.vapi.h>
-#include <vapi/ip.api.vapi.h>
-
-/* If no IP has been found ip_addr will be "0.0.0.0" */
-extern int ipv46_address_dump(const char *interface_name, char *ip_addr,
- u8 *prefix_len, bool is_ipv6);
-
-extern int ipv46_config_add_remove(const char *if_name, const char *addr,
- uint8_t prefix, bool is_ipv6, bool add);
-
-extern int
-ipv46_config_add_del_route(const char* dst_address, u8 dst_address_length,
- const char* next_address, u8 is_add, u32 table_id,
- const char *interface);
-
-#endif /* __BAPI_IP_H__ */
diff --git a/src/scvpp/src/sc_vpp_v3po.h b/src/scvpp/src/sc_vpp_v3po.h
deleted file mode 100644
index 9c13569..0000000
--- a/src/scvpp/src/sc_vpp_v3po.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef _V3PO__INTERFACE_H__
-#define _V3PO__INTERFACE_H__
-
-#include <vapi/tapv2.api.vapi.h>
-
-typedef vapi_payload_tap_create_v2 tapv2_create_t;
-
-int create_tapv2(tapv2_create_t *query);
-int delete_tapv2(char *iface_name);
-
-#endif /* __V3PO_INTERFACE_H__ */
diff --git a/src/scvpp/src/sc_vpp_v3po.c b/src/scvpp/src/v3po.c
index d312331..f0a41c5 100644
--- a/src/scvpp/src/sc_vpp_v3po.c
+++ b/src/scvpp/src/v3po.c
@@ -1,5 +1,7 @@
/*
* Copyright (c) 2016 Cisco and/or its affiliates.
+ * Copyright (c) 2018 PANTHEON.tech.
+ *
* 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:
@@ -15,35 +17,18 @@
#include <assert.h>
-#include "sc_vpp_comm.h"
-#include "sc_vpp_v3po.h"
-#include "sc_vpp_interface.h"
+#include <scvpp/comm.h>
+#include <scvpp/v3po.h>
+#include <scvpp/interface.h>
+
+// Use VAPI macros to define symbols
+DEFINE_VAPI_MSG_IDS_L2_API_JSON;
+DEFINE_VAPI_MSG_IDS_TAPV2_API_JSON
/*
* tap-v2 interfaces
*/
-DEFINE_VAPI_MSG_IDS_TAPV2_API_JSON
-
-// Dump tapv2
-
-//typedef struct __attribute__ ((__packed__)) {
-// u32 sw_if_index;
-// u32 id;
-// u8 dev_name[64];
-// u16 tx_ring_sz;
-// u16 rx_ring_sz;
-// u8 host_mac_addr[6];
-// u8 host_if_name[64];
-// u8 host_namespace[64];
-// u8 host_bridge[64];
-// u8 host_ip4_addr[4];
-// u8 host_ip4_prefix_len;
-// u8 host_ip6_addr[16];
-// u8 host_ip6_prefix_len;
-// u32 tap_flags;
-//} vapi_payload_sw_interface_tap_v2_details;
-
// Delete tapv2
VAPI_RETVAL_CB(tap_delete_v2);
@@ -53,35 +38,33 @@ static vapi_error_e bin_api_delete_tapv2(u32 sw_if_index)
vapi_msg_tap_delete_v2 *mp;
vapi_error_e rv;
- mp = vapi_alloc_tap_delete_v2(g_vapi_ctx_instance);
+ mp = vapi_alloc_tap_delete_v2(g_vapi_ctx);
assert(NULL != mp);
mp->payload.sw_if_index = sw_if_index;
- VAPI_CALL(vapi_tap_delete_v2(g_vapi_ctx_instance, mp, tap_delete_v2_cb,
- NULL));
+ VAPI_CALL(vapi_tap_delete_v2(g_vapi_ctx, mp, tap_delete_v2_cb, NULL));
if (rv != VAPI_OK)
- return -EAGAIN;
+ return -rv;
- return rv;
+ return VAPI_OK;
}
int delete_tapv2(char *iface_name)
{
+ uint32_t sw_if_index;
+ vapi_error_e rv;
int rc;
- sw_interface_details_query_t query = {0};
- sw_interface_details_query_set_name(&query, iface_name);
+ rc = get_interface_id(iface_name, &sw_if_index);
+ if (rc < 0)
+ return rc;
- rc = get_interface_id(&query);
- if (!rc)
- return -1;
+ rv = bin_api_delete_tapv2(sw_if_index);
+ if (VAPI_OK != rv)
+ return -SCVPP_EINVAL;
- rc = bin_api_delete_tapv2(query.sw_interface_details.sw_if_index);
- if (VAPI_OK != rc)
- return -1;
-
- return 0;
+ return SCVPP_OK;
}
// Create tapv2
@@ -93,13 +76,12 @@ int create_tapv2(tapv2_create_t *query)
vapi_msg_tap_create_v2 *mp;
vapi_error_e rv;
- mp = vapi_alloc_tap_create_v2(g_vapi_ctx_instance);
+ mp = vapi_alloc_tap_create_v2(g_vapi_ctx);
assert(NULL != mp);
memcpy(&mp->payload, query, sizeof(tapv2_create_t));
- VAPI_CALL(vapi_tap_create_v2(g_vapi_ctx_instance, mp, tap_create_v2_cb,
- NULL));
+ VAPI_CALL(vapi_tap_create_v2(g_vapi_ctx, mp, tap_create_v2_cb, NULL));
if (rv != VAPI_OK)
return -EAGAIN;
diff --git a/src/scvpp/tests/CMakeLists.txt b/src/scvpp/tests/CMakeLists.txt
index 3153fe0..2b6de4a 100644
--- a/src/scvpp/tests/CMakeLists.txt
+++ b/src/scvpp/tests/CMakeLists.txt
@@ -18,24 +18,23 @@ include_directories ("${PROJECT_SOURCE_DIR}/src")
# check whether valgrind is installed
find_program(valgrind_FOUND valgrind)
-# macro for adding of an unit test
-macro(ADD_UNIT_TEST TEST_NAME)
- set(TEST_SRC
- ${TEST_NAME}.c
- scvpp_nat_test.c
- )
- add_executable(${TEST_NAME} ${TEST_SRC})
- target_link_libraries(${TEST_NAME} ${CMOCKA_LIBRARIES} scvpp_a)
- add_test(${TEST_NAME} ${TEST_NAME})
+set(TEST_SRC
+ scvpp_test.h
+ scvpp_test.c
+ scvpp_iface_test.c
+ scvpp_ip_test.c
+ scvpp_nat_test.c
+)
- if(valgrind_FOUND)
- add_test(${TEST_NAME}_valgrind valgrind
- --error-exitcode=1 --read-var-info=yes
- --leak-check=full --show-leak-kinds=all
- ./${TEST_NAME}
- )
- endif(valgrind_FOUND)
-endmacro(ADD_UNIT_TEST)
+add_executable(scvpp_test ${TEST_SRC})
+target_link_libraries(scvpp_test ${CMOCKA_LIBRARIES} scvpp_a)
+target_include_directories(scvpp_test PRIVATE ../inc)
+add_test(scvpp_test scvpp_test)
-# add individual unit-tests
-ADD_UNIT_TEST(scvpp_test)
+if(valgrind_FOUND)
+ add_test(${TEST_NAME}_valgrind valgrind
+ --error-exitcode=1 --read-var-info=yes
+ --leak-check=full --show-leak-kinds=all
+ ./${TEST_NAME}
+ )
+endif(valgrind_FOUND)
diff --git a/src/scvpp/tests/scvpp_iface_test.c b/src/scvpp/tests/scvpp_iface_test.c
new file mode 100644
index 0000000..6a96694
--- /dev/null
+++ b/src/scvpp/tests/scvpp_iface_test.c
@@ -0,0 +1,130 @@
+/*
+ * 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 <unistd.h>
+#include <setjmp.h>
+#include <stdarg.h>
+#include <cmocka.h>
+
+#include "scvpp_test.h"
+
+#include <scvpp/interface.h>
+#include <scvpp/v3po.h>
+
+static void test_enable_disable(void **state)
+{
+ UNUSED(state);
+ sw_interface_dump_t dump = {0};
+ int rc;
+
+ rc = interface_enable("tap0", 1);
+ assert_int_equal(rc, SCVPP_OK);
+
+ rc = interface_dump_iface(&dump, "tap0");
+ assert_int_equal(rc, SCVPP_OK);
+
+ assert_int_equal(dump.admin_up_down, true);
+
+ rc = interface_enable("tap0", 0);
+ assert_int_equal(rc, SCVPP_OK);
+}
+
+static void test_create_tapv2(void **state)
+{
+ UNUSED(state);
+ tapv2_create_t query = {0};
+ sw_interface_dump_t dump = {0};
+ int rc;
+
+ query.id = 1;
+ query.use_random_mac = 1;
+
+ rc = create_tapv2(&query);
+ assert_int_equal(rc, SCVPP_OK);
+
+ rc = interface_dump_iface(&dump, "tap1");
+ assert_int_equal(rc, SCVPP_OK);
+}
+
+static int teardown_tapv2(void **state)
+{
+ UNUSED(state);
+ return delete_tapv2("tap1");
+}
+
+static void test_dump_iface_all(void **state)
+{
+ UNUSED(state);
+ struct elt *stack = NULL;
+ sw_interface_dump_t *dump;
+ bool exist = false;
+
+ stack = interface_dump_all();
+ assert_non_null(stack);
+ foreach_stack_elt(stack) {
+ dump = (sw_interface_dump_t *) data;
+ if (!strncmp((char*) dump->interface_name, "tap0", VPP_INTFC_NAME_LEN))
+ exist = true;
+ free(dump);
+ }
+ assert_true(exist);
+}
+
+static void test_dump_iface_exist(void **state)
+{
+ UNUSED(state);
+ vapi_payload_sw_interface_details details = {0};
+ int rc;
+
+ rc = interface_dump_iface(&details, "local0");
+ assert_int_equal(rc, SCVPP_OK);
+
+ assert_string_equal(details.interface_name, "local0");
+}
+
+static void test_dump_iface_unexist(void **state)
+{
+ UNUSED(state);
+ vapi_payload_sw_interface_details details = {0};
+ int rc;
+
+ rc = interface_dump_iface(&details, "unexisting");
+ assert_int_equal(rc, -SCVPP_NOT_FOUND);
+}
+
+static void test_get_interface_name(void **state)
+{
+ UNUSED(state);
+ char interface_name[VPP_INTFC_NAME_LEN];
+ uint32_t tap0_if_index;
+ int rc;
+
+ rc = get_interface_id("tap0", &tap0_if_index);
+ assert_int_equal(rc, SCVPP_OK);
+
+ rc = get_interface_name(interface_name, tap0_if_index);
+ assert_int_equal(rc, SCVPP_OK);
+
+ assert_string_equal(interface_name, "tap0");
+}
+
+const struct CMUnitTest iface_tests[IFACE_TEST_SIZE] = {
+ cmocka_unit_test_teardown(test_create_tapv2, teardown_tapv2),
+ cmocka_unit_test(test_enable_disable),
+ cmocka_unit_test(test_dump_iface_all),
+ cmocka_unit_test(test_dump_iface_exist),
+ cmocka_unit_test(test_dump_iface_unexist),
+ cmocka_unit_test(test_get_interface_name),
+};
diff --git a/src/scvpp/tests/scvpp_ip_test.c b/src/scvpp/tests/scvpp_ip_test.c
new file mode 100644
index 0000000..5e28123
--- /dev/null
+++ b/src/scvpp/tests/scvpp_ip_test.c
@@ -0,0 +1,184 @@
+/*
+ * Copyright (c) 2019 Cisco
+ *
+ * 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 <unistd.h>
+#include <setjmp.h>
+#include <stdarg.h>
+#include <cmocka.h>
+
+#include "scvpp_test.h"
+
+#include <scvpp/ip.h>
+#include <scvpp/interface.h>
+#include <scvpp/comm.h>
+
+static void test_add_remove_ipv4(void **state)
+{
+ UNUSED(state);
+ const char ip_q[VPP_IP4_ADDRESS_STRING_LEN] = "192.168.100.144";
+ char ip_r[VPP_IP4_ADDRESS_STRING_LEN];
+ u8 prefix_q = 24;
+ u8 prefix_r;
+ int rc;
+
+ //add ipv4 on tap0
+ rc = ipv46_config_add_remove("tap0", ip_q, prefix_q, false, true);
+ assert_int_equal(rc, SCVPP_OK);
+
+ //dump ipv4 on tap0 and check if it mach
+ rc = ipv46_address_dump("tap0", ip_r, &prefix_r, false);
+ assert_int_equal(rc, SCVPP_OK);
+ assert_string_equal(ip_q, ip_r);
+ assert_int_equal(prefix_q, prefix_r);
+
+ //remove ipv4 on tap0
+ rc = ipv46_config_add_remove("tap0", ip_q, prefix_q, false, false);
+ assert_int_equal(rc, SCVPP_OK);
+
+ //dump ipv4 after removal and check if equals 0.0.0.0
+ rc = ipv46_address_dump("tap0", ip_r, &prefix_r, false);
+ assert_int_equal(rc, SCVPP_OK);
+ assert_string_equal(ip_r, "0.0.0.0");
+}
+
+static void test_ipv4_add_del_route_no_iface(void **state)
+{
+ UNUSED(state);
+ int rc;
+ char dst_address[VPP_IP4_ADDRESS_STRING_LEN] = "192.168.100.0";
+ uint8_t prefix_len = 24;
+ char next_hop[VPP_IP4_ADDRESS_STRING_LEN] = "192.168.100.100";
+ uint32_t table_id = 0;
+ fib_dump_t *dump;
+ struct elt *stack;
+ bool route_found = false;
+
+ /* Must fail, can not have both interface and next hop IP null */
+ rc = ipv46_config_add_del_route(dst_address, prefix_len, NULL, true,
+ table_id, NULL);
+ assert_int_equal(rc, -SCVPP_EINVAL);
+
+ rc = ipv46_config_add_del_route(dst_address, prefix_len, next_hop, true,
+ table_id, NULL);
+ assert_int_equal(rc, SCVPP_OK);
+
+ /* Dump all FIB routes and check if we find ours */
+ stack = ipv4_fib_dump_all();
+ assert_non_null(stack);
+ foreach_stack_elt(stack) {
+ dump = (fib_dump_t *) data;
+
+ if (strncmp(sc_ntoa(dump->address), dst_address,
+ VPP_IP4_ADDRESS_STRING_LEN) == 0 &&
+ dump->address_length == prefix_len) {
+ route_found = true;
+ assert_int_equal(dump->table_id, table_id);
+ assert_int_equal(dump->count, 1);
+ assert_string_equal(sc_ntoa(dump->path[0].next_hop), next_hop);
+ }
+ free(dump);
+ }
+ assert_true(route_found);
+
+ /* Delete previously set route */
+ rc = ipv46_config_add_del_route(dst_address, prefix_len, next_hop, false,
+ table_id, NULL);
+ assert_int_equal(rc, SCVPP_OK);
+
+ /* Check our route has been deleted */
+ route_found = false;
+ stack = ipv4_fib_dump_all();
+ assert_non_null(stack);
+ foreach_stack_elt(stack) {
+ dump = (fib_dump_t *) data;
+ if (strncmp(sc_ntoa(dump->address), dst_address,
+ VPP_IP4_ADDRESS_STRING_LEN) == 0 &&
+ dump->address_length == prefix_len) {
+ route_found = true;
+ }
+ free(dump);
+ }
+ assert_false(route_found);
+}
+
+static void test_ipv4_add_del_route_no_next_hop_ip(void **state)
+{
+ UNUSED(state);
+ int rc;
+ char dst_address[VPP_IP4_ADDRESS_STRING_LEN] = "192.168.100.0";
+ uint8_t prefix_len = 24;
+ char interface[VPP_IP4_ADDRESS_STRING_LEN] = "tap0";
+ uint32_t table_id = 0;
+ uint32_t sw_if_index;
+ fib_dump_t *dump;
+ struct elt *stack;
+ bool route_found = false;
+
+ //Add a new route
+ rc = ipv46_config_add_del_route(dst_address, prefix_len, NULL, true,
+ table_id, interface);
+ assert_int_equal(rc, SCVPP_OK);
+
+ //Dump all FIB routes and check we find ours
+ stack = ipv4_fib_dump_all();
+ assert_non_null(stack);
+
+ rc = get_interface_id(interface, &sw_if_index);
+ assert_int_equal(rc, SCVPP_OK);
+
+ foreach_stack_elt(stack) {
+ dump = (fib_dump_t *) data;
+
+ if (strncmp(sc_ntoa(dump->address), dst_address,
+ VPP_IP4_ADDRESS_STRING_LEN) == 0 &&
+ dump->address_length == prefix_len) {
+ route_found = true;
+ assert_int_equal(dump->table_id, table_id);
+ assert_int_equal(dump->count, 1);
+ assert_int_equal(dump->path[0].sw_if_index, sw_if_index);
+ }
+ free(dump);
+ }
+ assert_true(route_found);
+
+ //Delete route
+ rc = ipv46_config_add_del_route(dst_address, prefix_len, NULL, false,
+ table_id, interface);
+ assert_int_equal(rc, SCVPP_OK);
+
+ //Check our route has been deleted
+ route_found = false;
+ stack = ipv4_fib_dump_all();
+ assert_non_null(stack);
+
+ foreach_stack_elt(stack) {
+ dump = (fib_dump_t *) data;
+ if (strncmp(sc_ntoa(dump->address), dst_address,
+ VPP_IP4_ADDRESS_STRING_LEN) == 0 &&
+ dump->address_length == prefix_len) {
+ route_found = true;
+ }
+ free(dump);
+ }
+ assert_false(route_found);
+}
+
+
+const struct CMUnitTest ip_tests[IP_TEST_SIZE] = {
+ cmocka_unit_test(test_add_remove_ipv4),
+ cmocka_unit_test(test_ipv4_add_del_route_no_next_hop_ip),
+ cmocka_unit_test(test_ipv4_add_del_route_no_iface),
+};
diff --git a/src/scvpp/tests/scvpp_nat_test.c b/src/scvpp/tests/scvpp_nat_test.c
index fae9615..044102e 100644
--- a/src/scvpp/tests/scvpp_nat_test.c
+++ b/src/scvpp/tests/scvpp_nat_test.c
@@ -20,36 +20,37 @@
#include <setjmp.h>
#include <cmocka.h>
-#include "scvpp_nat_test.h"
-#include "sc_vpp_comm.h"
-#include "sc_vpp_nat.h"
+#include "scvpp_test.h"
-void test_nat44_static_mapping(__attribute__((unused)) void **state)
+#include <scvpp/comm.h>
+#include <scvpp/nat.h>
+
+
+void test_nat44_static_mapping(void **state)
{
+ UNUSED(state);
nat44_add_del_static_mapping_t map = {0};
nat44_static_mapping_details_t dump = {0};
u8 empty_ip[4] = {0};
+ int rc;
/*Configure the static mapping
Alternative to this CLI command:
nat44 add static mapping local 172.168.0.1 external 172.168.8.5
*/
-
sc_aton("172.168.0.1", map.local_ip_address,
sizeof(map.local_ip_address));
-
sc_aton("172.168.8.5", map.external_ip_address,
sizeof(map.external_ip_address));
-
map.addr_only = 1;
-
map.external_sw_if_index = ~0;
-
map.is_add = 1;
- nat44_add_del_static_mapping(&map);
+ rc = nat44_add_del_static_mapping(&map);
+ assert_int_equal(rc, SCVPP_OK);
- nat44_static_mapping_dump(&dump);
+ rc = nat44_static_mapping_dump(&dump);
+ assert_int_equal(rc, SCVPP_OK);
assert_int_equal(dump.addr_only, map.addr_only);
@@ -62,11 +63,13 @@ void test_nat44_static_mapping(__attribute__((unused)) void **state)
/* Remove previous config*/
map.is_add = 0;
- nat44_add_del_static_mapping(&map);
+ rc = nat44_add_del_static_mapping(&map);
+ assert_int_equal(rc, SCVPP_OK);
memset(&dump, 0, sizeof(dump));
- nat44_static_mapping_dump(&dump);
+ rc = nat44_static_mapping_dump(&dump);
+ assert_int_equal(rc, SCVPP_OK);
assert_int_equal(dump.addr_only, 0);
@@ -77,14 +80,16 @@ void test_nat44_static_mapping(__attribute__((unused)) void **state)
sizeof(dump.external_ip_address));
}
-void test_nat44_static_mapping_with_ports(__attribute__((unused)) void **state)
+void test_nat44_static_mapping_with_ports(void **state)
{
+ UNUSED(state);
nat44_add_del_static_mapping_t map = {0};
nat44_static_mapping_details_t dump = {0};
nat44_add_del_address_range_t range = {0};
u8 empty_ip[4] = {0};
const u16 lport = 77;
const u16 eport = 88;
+ int rc;
/*Configure address pool
Alternative to this CLI:
@@ -98,7 +103,8 @@ void test_nat44_static_mapping_with_ports(__attribute__((unused)) void **state)
range.is_add = 1;
- nat44_add_del_addr_range(&range);
+ rc = nat44_add_del_addr_range(&range);
+ assert_int_equal(rc, SCVPP_OK);
/*Configure NAT with ports
Alternative to this CLI:
@@ -122,9 +128,11 @@ void test_nat44_static_mapping_with_ports(__attribute__((unused)) void **state)
map.is_add = 1;
- nat44_add_del_static_mapping(&map);
+ rc = nat44_add_del_static_mapping(&map);
+ assert_int_equal(rc, SCVPP_OK);
- nat44_static_mapping_dump(&dump);
+ rc = nat44_static_mapping_dump(&dump);
+ assert_int_equal(rc, SCVPP_OK);
assert_int_equal(dump.addr_only, map.addr_only);
@@ -142,11 +150,13 @@ void test_nat44_static_mapping_with_ports(__attribute__((unused)) void **state)
map.is_add = 0;
- nat44_add_del_static_mapping(&map);
+ rc = nat44_add_del_static_mapping(&map);
+ assert_int_equal(rc, SCVPP_OK);
memset(&dump, 0, sizeof(dump));
- nat44_static_mapping_dump(&dump);
+ rc = nat44_static_mapping_dump(&dump);
+ assert_int_equal(rc, SCVPP_OK);
assert_int_equal(dump.addr_only, 0);
@@ -162,7 +172,8 @@ void test_nat44_static_mapping_with_ports(__attribute__((unused)) void **state)
range.is_add = 0;
- nat44_add_del_addr_range(&range);
+ rc = nat44_add_del_addr_range(&range);
+ assert_int_equal(rc, SCVPP_OK);
}
const struct CMUnitTest nat_tests[] = {
diff --git a/src/scvpp/tests/scvpp_test.c b/src/scvpp/tests/scvpp_test.c
index cc23e43..f6e99a0 100644
--- a/src/scvpp/tests/scvpp_test.c
+++ b/src/scvpp/tests/scvpp_test.c
@@ -14,89 +14,19 @@
*/
#include <stdlib.h>
-#include <stdio.h>
#include <unistd.h>
+#include <stdio.h>
#include <setjmp.h>
-#include <cmocka.h>
-
-#include "sc_vpp_comm.h"
-#include "sc_vpp_interface.h"
-#include "sc_vpp_ip.h"
-#include "sc_vpp_v3po.h"
-#include "scvpp_nat_test.h"
-
-//TODO Check with future function get_interface_state
-static void test_enable_disable(void **state)
-{
- int rc;
-
- rc = interface_enable("tap0", 1);
- assert_int_equal(rc, 0);
-
- rc = interface_enable("tap0", 0);
- assert_int_equal(rc, 0);
-}
-
-//TODO would need to make sure tap0 is index 1
-//TODO delete eventually because get_interface_id will not be extern
-static void test_name2index(void **state)
-{
- int rc;
- const char iface_name[] = "tap0";
- sw_interface_details_query_t query = {0};
- sw_interface_details_query_set_name(&query, iface_name);
-
- rc = get_interface_id(&query);
- assert_int_equal(rc, 1);
-
- assert_string_equal(iface_name, query.sw_interface_details.interface_name);
- assert_int_equal(query.sw_interface_details.sw_if_index, 1);
-}
-
-static void test_add_ipv4(void **state)
-{
- const char ip_q[VPP_IP4_ADDRESS_STRING_LEN] = "192.168.100.144";
- char ip_r[VPP_IP4_ADDRESS_STRING_LEN];
- u8 prefix_q = 24;
- u8 prefix_r;
- int rc;
-
- //add ipv4 on tap0
- rc = ipv46_config_add_remove("tap0", ip_q, prefix_q, false, true);
- assert_int_equal(rc, 0);
-
- rc = ipv46_address_dump("tap0", ip_r, &prefix_r, false);
- assert_int_equal(rc, 0);
-
- assert_string_equal(ip_q, ip_r);
- assert_int_equal(prefix_q, prefix_r);
-}
-
-static void test_remove_ipv4(void **state)
-{
- const char ip_q[VPP_IP4_ADDRESS_STRING_LEN] = "192.168.100.144";
- char ip_r[VPP_IP4_ADDRESS_STRING_LEN];
- u8 prefix_q = 24;
- u8 prefix_r;
- int rc;
-
- //add ipv4 on tap0
- rc = ipv46_config_add_remove("tap0", ip_q, prefix_q, false, true);
- assert_int_equal(rc, 0);
- //remove ipv4 on tap0
- rc = ipv46_config_add_remove("tap0", ip_q, prefix_q, false, false);
- assert_int_equal(rc, 0);
-
- //dump ipv4
- rc = ipv46_address_dump("tap0", ip_r, &prefix_r, false);
- assert_int_equal(rc, 0);
+#include <scvpp/comm.h>
+#include <scvpp/v3po.h>
- assert_string_equal(ip_r, "0.0.0.0");
-}
+#include "scvpp_test.h"
+/* test "AAA.BBB.CCC.DDD" -> {A, B, C, D} */
static void test_sc_ntoa(void **state)
{
+ UNUSED(state);
u8 buf[4] = {192, 168, 100, 44};
char *res;
@@ -104,52 +34,76 @@ static void test_sc_ntoa(void **state)
assert_string_equal(res, "192.168.100.44");
}
-static void test_create_tapv2(void **state)
+/* test {A, B, C, D} -> "AAA.BBB.CCC.DDD" */
+static void test_sc_aton(void **state)
{
- tapv2_create_t query = {0};
+ UNUSED(state);
+ char ip[VPP_IP4_ADDRESS_STRING_LEN] = "192.168.100.44";
+ uint8_t buf[4];
int rc;
- query.id = 1;
- query.use_random_mac = 1;
-
- rc = create_tapv2(&query);
+ rc = sc_aton(ip, buf, VPP_IP4_ADDRESS_LEN);
assert_int_equal(rc, 0);
- //TODO dump_tav2 and compare values
-
- rc = delete_tapv2("tap1");
- assert_int_equal(rc, 0);
+ assert_int_equal(buf[0], 192);
+ assert_int_equal(buf[1], 168);
+ assert_int_equal(buf[2], 100);
+ assert_int_equal(buf[3], 44);
}
-int main()
+static int setup(void **state)
{
+ UNUSED(state);
tapv2_create_t query = {0};
- const struct CMUnitTest tests[] = {
- cmocka_unit_test_setup_teardown(test_enable_disable, NULL, NULL),
- cmocka_unit_test_setup_teardown(test_name2index, NULL, NULL),
- cmocka_unit_test_setup_teardown(test_add_ipv4, NULL, NULL),
- cmocka_unit_test_setup_teardown(test_remove_ipv4, NULL, NULL),
- cmocka_unit_test_setup_teardown(test_sc_ntoa, NULL, NULL),
- cmocka_unit_test_setup_teardown(test_create_tapv2, NULL, NULL),
- };
- if (sc_connect_vpp() != 0)
+ if (sc_connect_vpp() != 0) {
fprintf(stderr, "Error connecting to VPP\n");
+ return -1;
+ }
/* Create interface tap0 to test several functions */
query.id = 0;
query.use_random_mac = 1;
- if (create_tapv2(&query) != 0)
+ if (create_tapv2(&query) != 0) {
fprintf(stderr, "Error creating tap0\n");
+ return -1;
+ }
- cmocka_run_group_tests(tests, NULL, NULL);
-
- print_message("\nNAT Tests\n");
- cmocka_run_group_tests(nat_tests, NULL, NULL);
+ return 0;
+}
+static int teardown(void **state)
+{
+ UNUSED(state);
/* Delete tap0 */
- if (delete_tapv2("tap0") != 0)
+ if (delete_tapv2("tap0") != 0) {
fprintf(stderr, "Failed deleting tap0\n");
+ return -1;
+ }
+
+ sc_disconnect_vpp();
+
+ return 0;
+}
+
+/* return code for scvpp-test binary is the number of failed test */
+int main()
+{
+ int rc = 0;
+
+ const struct CMUnitTest common_tests[] = {
+ cmocka_unit_test(test_sc_ntoa),
+ cmocka_unit_test(test_sc_aton),
+ };
+
+ print_message("Common tests\n");
+ rc |= cmocka_run_group_tests(common_tests, NULL, NULL);
+ print_message("Interface tests\n");
+ rc |= cmocka_run_group_tests(iface_tests, setup, teardown);
+ print_message("IP tests\n");
+ rc |= cmocka_run_group_tests(ip_tests, setup, teardown);
+ print_message("NAT tests\n");
+ rc |= cmocka_run_group_tests(nat_tests, setup, teardown);
- return sc_disconnect_vpp();
+ return rc;
}
diff --git a/src/scvpp/tests/scvpp_nat_test.h b/src/scvpp/tests/scvpp_test.h
index 8a22f87..28bd514 100644
--- a/src/scvpp/tests/scvpp_nat_test.h
+++ b/src/scvpp/tests/scvpp_test.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019 PANTHEON.tech.
+ * Copyright (c) 2019 Cisco
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,11 +14,18 @@
* limitations under the License.
*/
-/* inclusion guard */
-#ifndef __SCVPP_NAT_TEST_H__
-#define __SCVPP_NAT_TEST_H__
+#ifndef __SCVPP_TEST_H
+#define __SCVPP_TEST_H__
+
+#include <cmocka.h>
+
+#define IFACE_TEST_SIZE 6
+extern const struct CMUnitTest iface_tests[IFACE_TEST_SIZE];
+
+#define IP_TEST_SIZE 3
+extern const struct CMUnitTest ip_tests[IP_TEST_SIZE];
#define NAT_TEST_SIZE 2
extern const struct CMUnitTest nat_tests[NAT_TEST_SIZE];
-#endif /* __SCVPP_NAT_TEST_H__ */
+#endif /* __SCVPP_TEST_H__ */