TODO: start of blueprintprocessor container is not enough, need to wait for its REST API to be ready for usage)
41 | image: onap/ccsdk-cds-ui-server:1.1.1
42 | container_name: cds-ui
43 | ports:
44 | - "3000:3000" # port for UI
45 | - "9080:8080"
46 | - "9081:8081"
47 | environment:
48 | - HOST=0.0.0.0 # host for UI
49 | - API_BLUEPRINT_CONTROLLER_HTTP_BASE_URL=http://172.28.0.1:8000/api/v1
50 | - API_BLUEPRINT_CONTROLLER_HTTP_AUTH_TOKEN=Basic Y2NzZGthcHBzOmNjc2RrYXBwcw==
51 | - API_BLUEPRINT_PROCESSOR_HTTP_BASE_URL=http://172.28.0.1:8000/api/v1
52 | - API_BLUEPRINT_PROCESSOR_HTTP_AUTH_TOKEN=Basic Y2NzZGthcHBzOmNjc2RrYXBwcw==
53 | - API_BLUEPRINT_PROCESSOR_GRPC_HOST=172.28.0.1
54 | - API_BLUEPRINT_PROCESSOR_GRPC_PORT=9111
55 | - API_BLUEPRINT_PROCESSOR_GRPC_AUTH_TOKEN=Basic Y2NzZGthcHBzOmNjc2RrYXBwcw==
56 |
57 | firewall-cnf:
58 | container_name: firewall-cnf
59 | image: 'ghcr.io/pantheontech/stonework:21.01.04'
60 | privileged: true
61 | networks:
62 | - cds-network
63 | ports:
64 | - '9191:9191' # REST API
65 | - '9111:9111' # GRPC # TODO remove later
66 | volumes:
67 | - '/tmp/vpp/:/run/vpp/'
68 | - '/var/run/netns/:/var/run/netns/'
69 | environment:
70 | - ETCD_CONFIG=disabled # don't use ETCD (it is not needed in this case)
71 | pid: host # needed for connection between startpoint and endpoint
72 | cap_add:
73 | - NET_ADMIN # needed for connection between startpoint and endpoint
74 |
75 | startpoint:
76 | container_name: startpoint
77 | image: 'alpine-start-end-point:latest'
78 | privileged: true
79 | command: sh -c "sleep 100000s"
80 | cap_add:
81 | - NET_ADMIN # needed for connection between startpoint and endpoint
82 |
83 | endpoint:
84 | container_name: endpoint
85 | image: 'alpine-start-end-point:latest'
86 | privileged: true
87 | command: sh -c "sleep 100000s"
88 | cap_add:
89 | - NET_ADMIN # needed for connection between startpoint and endpoint
90 |
91 | networks:
92 | cds-network:
93 | driver: bridge
94 | ipam:
95 | driver: default
96 | config:
97 | - subnet: 172.28.0.0/16
--------------------------------------------------------------------------------
/nsm/LFNWebinar/cnf-crd.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # This cluster role defines a set of permissions required for cnf-crd.
3 | apiVersion: rbac.authorization.k8s.io/v1beta1
4 | kind: ClusterRole
5 | metadata:
6 | name: cnf-crd
7 | namespace: default
8 | rules:
9 | - apiGroups:
10 | - apiextensions.k8s.io
11 | - pantheon.tech
12 | resources:
13 | - customresourcedefinitions
14 | - cnfconfigurations
15 | verbs:
16 | - "*"
17 |
18 | ---
19 | # This defines a service account for cnf-crd.
20 | apiVersion: v1
21 | kind: ServiceAccount
22 | metadata:
23 | name: cnf-crd
24 | namespace: default
25 |
26 | ---
27 | # This binds the cnf-crd cluster role with cnf-crd service account.
28 | apiVersion: rbac.authorization.k8s.io/v1beta1
29 | kind: ClusterRoleBinding
30 | metadata:
31 | name: cnf-crd
32 | roleRef:
33 | apiGroup: rbac.authorization.k8s.io
34 | kind: ClusterRole
35 | name: cnf-crd
36 | subjects:
37 | - kind: ServiceAccount
38 | name: cnf-crd
39 | namespace: default
40 |
41 | ---
42 | apiVersion: v1
43 | kind: Pod
44 | metadata:
45 | name: cnf-crd
46 | namespace: default
47 | labels:
48 | app: cnf-crd
49 | spec:
50 | serviceAccountName: cnf-crd
51 | initContainers:
52 | # This init container waits until etcd is started
53 | - name: wait-foretcd
54 | image: busybox:1.29.3
55 | imagePullPolicy: IfNotPresent
56 | env:
57 | - name: HOST_IP
58 | valueFrom:
59 | fieldRef:
60 | fieldPath: status.hostIP
61 | command:
62 | - /bin/sh
63 | args:
64 | - -c
65 | - |
66 | until nc -w 2 $HOST_IP:31379; do echo waiting for etcd; sleep 2; done;
67 | containers:
68 | - name: cnf-crd
69 | image: pantheontech/cnf-crd:latest
70 | imagePullPolicy: IfNotPresent
71 | env:
72 | - name: ETCD_CONFIG
73 | value: "/etc/etcd/etcd.conf"
74 | volumeMounts:
75 | - name: etcd-cfg
76 | mountPath: /etc/etcd
77 | volumes:
78 | - name: etcd-cfg
79 | configMap:
80 | name: cnf-etcd-cfg
81 |
82 | ---
83 | # etcd config used by CNFs deployed in the host network namespace
84 | apiVersion: v1
85 | kind: ConfigMap
86 | metadata:
87 | name: cnf-etcd-cfg-for-nodeport
88 | data:
89 | etcd.conf: |
90 | dial-timeout: 10000000000
91 | allow-delayed-start: true
92 | insecure-transport: true
93 | endpoints:
94 | - "__HOST_IP__:31379"
95 |
96 | ---
97 | # etcd config used by CNF with their own network namespace
98 | apiVersion: v1
99 | kind: ConfigMap
100 | metadata:
101 | name: cnf-etcd-cfg
102 | data:
103 | etcd.conf: |
104 | dial-timeout: 10000000000
105 | allow-delayed-start: true
106 | insecure-transport: true
107 | endpoints:
108 | - "cnf-etcd.default.svc.cluster.local:12379"
109 |
110 | ---
111 | apiVersion: v1
112 | kind: Service
113 | metadata:
114 | name: cnf-etcd
115 | spec:
116 | type: NodePort
117 | selector:
118 | app: cnf-etcd
119 | ports:
120 | - port: 12379
121 | nodePort: 31379 # 32379 is used by contiv-etcd
122 |
123 | ---
124 | apiVersion: v1
125 | kind: Pod
126 | metadata:
127 | name: cnf-etcd
128 | labels:
129 | app: cnf-etcd
130 | spec:
131 | containers:
132 | - name: cnf-etcd
133 | image: quay.io/coreos/etcd:v3.3.11
134 | imagePullPolicy: IfNotPresent
135 | env:
136 | - name: ETCDCTL_API
137 | value: "3"
138 | command:
139 | - /bin/sh
140 | args:
141 | - -c
142 | - /usr/local/bin/etcd --name=cnf-etcd --data-dir=/var/cnf-etcd/data
143 | --advertise-client-urls=http://0.0.0.0:12379 --listen-client-urls=http://0.0.0.0:12379 --listen-peer-urls=http://0.0.0.0:12380
--------------------------------------------------------------------------------
/sonic-vpp/sonic-vpp-L3/README.md:
--------------------------------------------------------------------------------
1 | # [Demo] SONiC VPP L3
2 |
3 | This demo showcases L3 integration between [SONiC](https://sonicfoundation.dev/) and [FD.io VPP](fd.io), enabling high-performance routing in a containerized environment, using SONiC as control plane and FD.io VPP as the fast software data plane.
4 |
5 | ## Prerequisites
6 | - This example was successfully replicated on an Ubuntu (24.04.2 LTS) WSL instance in Windows.
7 | - [Docker](https://docs.docker.com/engine/install/)
8 | - [ContainerLab](https://containerlab.dev/install/)
9 | - [sshpass](https://www.cyberciti.biz/faq/noninteractive-shell-script-ssh-password-provider/)
10 |
11 | First, clone the repository so you have a local copy:
12 |
13 | ```bash
14 | git clone https://github.com/PANTHEONtech/cnf-examples.git
15 | ```
16 |
17 | To launch the example, simply execute the *run.sh* script within the folder you downloaded the example to:
18 |
19 | ```bash
20 | ./run.sh
21 | ```
22 |
23 | The run.sh script orchestrates the setup and configuration of the L3 network.
24 |
25 | ## Verifying the Setup
26 |
27 | 1. Verify instances
28 |
29 | ```bash
30 | clab inspect
31 | ```
32 | - Ensure that you see containers for PC1, PC2, Router 1 and Router 2.
33 | - Take note of the IP address each container is given. Replace them in the commands below. The output of *inspect* should look like this:
34 |
35 | ```Example Output
36 | ╭──────────────────────────┬──────────────────────────────────────────┬───────────┬───────────────────╮
37 | │ Name │ Kind/Image │ State │ IPv4/6 Address │
38 | ├──────────────────────────┼──────────────────────────────────────────┼───────────┼───────────────────┤
39 | │ clab-sonic-vpp01-PC1 │ linux │ running │ 192.xx.xx.x │
40 | │ │ wbitt/network-multitool:extra │ │ 3fff:172:20:20::2 │
41 | ├──────────────────────────┼──────────────────────────────────────────┼───────────┼───────────────────┤
42 | │ clab-sonic-vpp01-PC2 │ linux │ running │ 192.xx.xx.x │
43 | │ │ wbitt/network-multitool:extra │ │ 3fff:172:20:20::3 │
44 | ├──────────────────────────┼──────────────────────────────────────────┼───────────┼───────────────────┤
45 | │ clab-sonic-vpp01-router1 │ sonic-vm │ running │ 192.xx.xx.x │
46 | │ │ ghcr.io/pantheontech/sonic-vpp-vs:250619 │ (healthy) │ 3fff:172:20:20::4 │
47 | ├──────────────────────────┼──────────────────────────────────────────┼───────────┼───────────────────┤
48 | │ clab-sonic-vpp01-router2 │ sonic-vm │ running │ 192.xx.xx.x │
49 | │ │ ghcr.io/pantheontech/sonic-vpp-vs:250619 │ (healthy) │ 3fff:172:20:20::5 │
50 | ╰──────────────────────────┴──────────────────────────────────────────┴───────────┴───────────────────╯
51 | ```
52 | 2. Verify connectivity between router1 and router2
53 |
54 | ```bash
55 | sshpass -p admin ssh admin@clab-sonic-vpp01-router1 ping -c5 10.0.1.2
56 | sshpass -p admin ssh admin@clab-sonic-vpp01-router2 ping -c5 10.0.1.1
57 | ```
58 |
59 | 3. Verify connectivity between PC1 and PC2
60 |
61 | ```bash
62 | docker exec clab-sonic-vpp01-PC1 ping -c 5 10.20.2.1
63 | docker exec clab-sonic-vpp01-PC2 ping -c 5 10.20.1.1
64 | ```
65 |
66 | 4. Test Connectivity
67 |
68 | ```bash
69 | docker exec -it clab-sonic-vpp01-PC1 iperf3 -s
70 | docker exec -it clab-sonic-vpp01-PC2 iperf3 -c 10.20.1.1
71 | ```
72 |
73 | # About PANTHEON.tech
74 |
75 | Do you want to [deploy SONiC](https://pantheon.tech/services/expertise/sonic-nos/) in your infrastructure? Or [orchestrate SONiC with a unique solution](https://pantheon.tech/products/sandwork/)?
76 |
77 | We help enterprises take control of their network infrastructure – through software-driven automation, orchestration, and deep network technology expertise.
78 |
--------------------------------------------------------------------------------
/nsm/LFNWebinar/README.md:
--------------------------------------------------------------------------------
1 | CNF chaining using Ligato and NSM (example for LFN Webinar)
2 | ===========================================================
3 |
4 | Overview
5 | --------
6 |
7 | In this simple example we demonstrate the capabilities of the NSM agent - a control-plane for Cloud-native
8 | Network Functions deployed in Kubernetes cluster. The NSM agent seamlessly integrates [Ligato framework][ligato]
9 | for Linux and VPP network configuration management together with [Network Service Mesh (NSM)][nsm] for separation
10 | of data plane from control plane connectivity between containers and external endpoints.
11 |
12 | In the presented use-case we simulate scenario in which a client from a local network needs to access a web server
13 | with a public IP address. The necessary Network Address Translation (NAT) is performed in-between the client and
14 | the web server by the high-performance [VPP NAT plugin][vpp-nat-plugin], deployed as a true CNF (Cloud-Native Network
15 | Functions) inside a container. For simplicity the client is represented by a K8s Pod running image with [cURL][curl]
16 | installed (as opposed to being an external endpoint as it would be in a real-world scenario). For the server side
17 | the minimalistic [TestHTTPServer][vpp-test-http-server] implemented in VPP is utilized.
18 |
19 | In all the three Pods an instance of NSM Agent is run to communicate with the NSM manager via NSM SDK and negotiate
20 | additional network connections to connect the pods into a chain `client <-> NAT-CNF <-> web-server` (see diagrams below).
21 | The agents then use the features of Ligato framework to further configure Linux and VPP networking around the additional
22 | interfaces provided by NSM (e.g. routes, NAT).
23 |
24 | The configuration to apply is described declaratively and submitted to NSM agents in a Kubernetes native way through
25 | our own Custom Resource called `CNFConfiguration`. The controller for this CRD (installed by [cnf-crd.yaml][cnf-crd-yaml])
26 | simply reflects the content of applied CRD instances into an `etcd` datastore from which it is read by NSM agents.
27 | For example, the configuration for the NSM agent managing the central NAT CNF can be found in [cnf-nat44.yaml][cnf-nat44-yaml].
28 |
29 | More information about cloud-native tools and network functions provided by PANTHEON.tech can be found on our website
30 | [cdnf.io][cdnf-io].
31 |
32 | ### Networking Diagram
33 |
34 | ![networking][networking]
35 |
36 | ### Routing Diagram
37 |
38 | ![routing][routing]
39 |
40 | Demo steps
41 | ----------
42 |
43 | 1. Create Kubernetes cluster; deploy CNI (network plugin) of your preference
44 | 2. [Install Helm][install-helm] version 2 (latest NSM release v0.2.0 does not support Helm v3)
45 | 3. Run `helm init` to install Tiller and to set up local configuration for the Helm
46 | 4. Create service account for Tiller:
47 | ```
48 | $ kubectl create serviceaccount --namespace kube-system tiller
49 | $ kubectl create clusterrolebinding tiller-cluster-rule --clusterrole=cluster-admin --serviceaccount=kube-system:tiller
50 | $ kubectl patch deploy --namespace kube-system tiller-deploy -p '{"spec":{"template":{"spec":{"serviceAccount":"tiller"}}}}'
51 | ```
52 | 5. Deploy NSM using Helm:
53 | ```
54 | $ helm repo add nsm https://helm.nsm.dev/
55 | $ helm install --set insecure=true nsm/nsm
56 | ```
57 | 6. Deploy etcd + controller for CRD, both of which will be used together to pass configuration to NSM agents:
58 | ```
59 | $ kubectl apply -f cnf-crd.yaml
60 | ```
61 | 7. Submit definition of the network topology for this example to NSM:
62 | ```
63 | $ kubectl apply -f network-service.yaml
64 | ```
65 | 8. Deploy and start simple VPP-based webserver with NSM-Agent-VPP as control-plane:
66 | ```
67 | $ kubectl apply -f webserver.yaml
68 | ```
69 | 9. Deploy VPP-based NAT44 CNF with NSM-Agent-VPP as control-plane:
70 | ```
71 | $ kubectl apply -f cnf-nat44.yaml
72 | ```
73 | 10. Deploy Pod with NSM-Agent-Linux control-plane and curl for testing connection to the webserver through NAT44 CNF:
74 | ```
75 | $ kubectl apply -f client.yaml
76 | ```
77 | 11. Test connectivity between client and webserver:
78 | ```
79 | $ kubectl exec -it client curl 80.80.80.80/show/version
80 |
81 | show versionvpp v20.01-rc2~11-gfce396738~b17 built by root on b81dced13911 at 2020-01-29T21:07:15
82 |
83 | ```
84 | 12. To confirm that client's IP is indeed source NATed (from `192.168.100.10` to `80.80.80.102`) before reaching
85 | the webserver, one can use the VPP packet tracing:
86 | ```
87 | $ kubectl exec -it webserver vppctl trace add memif-input 10
88 | $ kubectl exec -it client curl 80.80.80.80/show/version
89 | $ kubectl exec -it webserver vppctl show trace
90 |
91 | 00:01:04:655507: memif-input
92 | memif: hw_if_index 1 next-index 4
93 | slot: ring 0
94 | 00:01:04:655515: ethernet-input
95 | IP4: 02:fe:68:a6:6b:8c -> 02:fe:b8:e1:c8:ad
96 | 00:01:04:655519: ip4-input
97 | TCP: 80.80.80.100 -> 80.80.80.80
98 | ...
99 | ```
100 |
101 | [ligato]: https://ligato.io/
102 | [nsm]: https://networkservicemesh.io/
103 | [install-helm]: https://helm.sh/docs/intro/install/
104 | [networking]: img/lfn-webinar-networking.png
105 | [routing]: img/lfn-webinar-routing.png
106 | [cdnf-io]: https://cdnf.io/
107 | [vpp-nat-plugin]: https://wiki.fd.io/view/VPP/NAT
108 | [curl]: https://curl.haxx.se/
109 | [vpp-test-http-server]: https://wiki.fd.io/view/VPP/HostStack/TestHttpServer
110 | [crd]: https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/
111 | [cnf-nat44-yaml]: ./cnf-nat44.yaml
112 | [cnf-crd-yaml]: ./cnf-crd.yaml
113 |
--------------------------------------------------------------------------------
/ONAP-cdnf-integration/run-demo.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | # requirements:
4 | # 1. docker, docker-compose
5 | # 2. curl
6 | #
7 | #(Tested with:
8 | # Ubuntu 20.04
9 | # docker 20.10.5
10 | # docker-compose 1.27.4
11 | # curl 7.68.0 (x86_64-pc-linux-gnu)
12 | # )
13 |
14 | set -eo pipefail
15 |
16 | source firewall-cnf-helper.sh
17 |
18 |
19 | CBA_FILE="cba.zip"
20 | ENRICHED_CBA_FILE="cba-enriched.zip"
21 |
22 | echo " -----------------------------------------------------------------------------"
23 | echo " Configuring Firewall CNF using ONAP (CDS) "
24 | echo " -----------------------------------------------------------------------------"
25 |
26 | ########################################
27 | # Setup
28 | ########################################
29 |
30 | echo
31 | echo "Cleaning up from previous runs and doing other preparations..."
32 | docker-compose down --volumes # removing also DB volumes
33 | rm ${CBA_FILE} > /dev/null 2>&1 || true
34 | rm ${ENRICHED_CBA_FILE} > /dev/null 2>&1 || true
35 | preDockerComposeCNFPreparations
36 |
37 | echo
38 | echo "Starting docker containers/networking..."
39 | docker-compose up -d
40 |
41 | echo
42 | echo "Waiting little bit longer to start CNF properly..."
43 | sleep 5s
44 |
45 | echo
46 | echo "Preparing Firewall CNF use case topology..."
47 | setupCNFTrafficTopology
48 |
49 | echo
50 | echo "Waiting little bit longer to start CDS-blueprintprocessor properly..."
51 | sleep 5s
52 |
53 |
54 | echo
55 | echo "CDS bootstraping (loading of default model types and resource dictionary-needed for proper CBA enrichment)..."
56 | curl --location --request POST 'http://localhost:8000/api/v1/blueprint-model/bootstrap' \
57 | --header 'Content-Type: application/json' \
58 | --header 'Authorization: Basic Y2NzZGthcHBzOmNjc2RrYXBwcw==' \
59 | --data-raw '{
60 | "loadModelType" : true,
61 | "loadResourceDictionary" : true,
62 | "loadCBA" : false
63 | }'
64 |
65 | echo
66 | echo "Packing CBA (making zip archive from cba folder content)..."
67 | cd cba;zip -r ../${CBA_FILE} * -x "pom.xml" "target/*";cd ..
68 |
69 | echo
70 | echo "Enriching CBA..."
71 | curl --location --request POST 'http://localhost:8000/api/v1/blueprint-model/enrich' \
72 | --header 'Authorization: Basic Y2NzZGthcHBzOmNjc2RrYXBwcw==' \
73 | --form 'file=@"./'${CBA_FILE}'"' \
74 | --output ${ENRICHED_CBA_FILE}
75 |
76 | echo
77 | echo "Saving/Uploading enriched CBA to CDS..."
78 | curl --location --request POST 'http://localhost:8000/api/v1/blueprint-model' \
79 | --header 'Authorization: Basic Y2NzZGthcHBzOmNjc2RrYXBwcw==' \
80 | --form 'file=@"./'${ENRICHED_CBA_FILE}'"'
81 |
82 | ########################################
83 | # Sending Traffic through Firewall CNF
84 | ########################################
85 |
86 | echo;echo
87 | echo "Sending data through unconfigured firewall..."
88 | newVPPTrace
89 | sendPing "startpoint" ${TRAFFIC_DEST_IP}
90 | if [ ! $PASSED_THROUGHT ]; then
91 | echo "=> failed to transmit data properly (ERROR)"
92 | logVPPTrace "unconfigured-firewall"
93 | exit 1
94 | else
95 | echo "=> data transmission was successful (OK)"
96 | logVPPTrace "unconfigured-firewall"
97 | fi
98 |
99 | echo
100 | echo "Starting firewall configuration (Deny traffic) by using CDS..."
101 | curl --location --request POST 'http://localhost:8000/api/v1/execution-service/process' \
102 | --header 'Authorization: Basic Y2NzZGthcHBzOmNjc2RrYXBwcw==' \
103 | --header 'Content-Type: application/json' \
104 | --data-raw '{
105 | "actionIdentifiers": {
106 | "mode": "sync",
107 | "blueprintName": "Firewall-CNF-configuration-example",
108 | "blueprintVersion": "1.0.0",
109 | "actionName": "apply-firewall-rule"
110 | },
111 | "payload": {
112 | "apply-firewall-rule-request": {
113 | "cnf-rest-url": "http://'${CNF_CONTAINER_NAME}':9191",
114 | "firewall_action": "DENY",
115 | "traffic_destination_network": "'${TRAFFIC_DEST_IP}'/32"
116 | }
117 | },
118 | "commonHeader": {
119 | "subRequestId": "143748f9-3cd5-4910-81c9-a4601ff2ea58",
120 | "requestId": "e5eb1f1e-3386-435d-b290-d49d8af8db4c",
121 | "originatorId": "SDNC_DG"
122 | }
123 | }'
124 |
125 | echo;echo
126 | echo "Sending data through configured firewall (Deny traffic)..."
127 | newVPPTrace
128 | sendPing "startpoint" ${TRAFFIC_DEST_IP}
129 | if [ ! $PASSED_THROUGHT ]; then
130 | if [[ $(getVPPTrace) == *"ACL deny packets"* ]]; then
131 | echo "=> blocked by firewall as expected (OK)"
132 | logVPPTrace "deny-configured-firewall"
133 | else
134 | echo "=> didn't pass throught but not because of firewall => demo failure (ERROR)"
135 | logVPPTrace "deny-configured-firewall"
136 | exit 1
137 | fi
138 | else
139 | echo "=> passed through firewall but shouldn't(ERROR)"
140 | logVPPTrace "deny-configured-firewall"
141 | exit 1
142 | fi
143 |
144 | echo
145 | echo "Starting firewall configuration (Allow traffic) by using CDS..."
146 | curl --location --request POST 'http://localhost:8000/api/v1/execution-service/process' \
147 | --header 'Authorization: Basic Y2NzZGthcHBzOmNjc2RrYXBwcw==' \
148 | --header 'Content-Type: application/json' \
149 | --data-raw '{
150 | "actionIdentifiers": {
151 | "mode": "sync",
152 | "blueprintName": "Firewall-CNF-configuration-example",
153 | "blueprintVersion": "1.0.0",
154 | "actionName": "apply-firewall-rule"
155 | },
156 | "payload": {
157 | "apply-firewall-rule-request": {
158 | "cnf-rest-url": "http://'${CNF_CONTAINER_NAME}':9191",
159 | "firewall_action": "PERMIT",
160 | "traffic_destination_network": "'${TRAFFIC_DEST_IP}'/32"
161 | }
162 | },
163 | "commonHeader": {
164 | "subRequestId": "143748f9-3cd5-4910-81c9-a4601ff2ea58",
165 | "requestId": "e5eb1f1e-3386-435d-b290-d49d8af8db4c",
166 | "originatorId": "SDNC_DG"
167 | }
168 | }'
169 |
170 | echo;echo
171 | echo "Sending data through configured firewall (Allowed Traffic)..."
172 | newVPPTrace
173 | sendPing "startpoint" ${TRAFFIC_DEST_IP}
174 | if [ ! $PASSED_THROUGHT ]; then
175 | echo "=> failed to transmit data properly (ERROR)"
176 | logVPPTrace "allow-configured-firewall"
177 | exit 1
178 | else
179 | echo "=> data transmission was successful (OK)"
180 | logVPPTrace "allow-configured-firewall"
181 | fi
182 |
183 | echo
184 | echo "Logging CNF state..."
185 | reportCNFState
186 |
187 |
188 | ########################################
189 | # Clean up
190 | ########################################
191 |
192 | echo
193 | echo "Cleaning up..."
194 | rm ${CBA_FILE} > /dev/null 2>&1 || true
195 | rm ${ENRICHED_CBA_FILE} > /dev/null 2>&1 || true
196 | docker-compose down --volumes # removing also DB volumes
197 | cleanupCNFRelatedThings
198 |
--------------------------------------------------------------------------------
/ONAP-cdnf-integration/cba/Scripts/kotlin/ConfigDeploy.kt:
--------------------------------------------------------------------------------
1 | package org.onap.ccsdk.cds.blueprintsprocessor.services.execution.scripts
2 |
3 | import org.apache.commons.io.IOUtils
4 | import org.apache.http.client.ClientProtocolException
5 | import org.apache.http.client.entity.EntityBuilder
6 | import org.apache.http.client.methods.HttpPut
7 | import org.apache.http.client.methods.HttpUriRequest
8 | import org.apache.http.message.BasicHeader
9 | import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.ExecutionServiceInput
10 | import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.ResourceResolutionComponent
11 | import org.onap.ccsdk.cds.blueprintsprocessor.rest.RestClientProperties
12 | import org.onap.ccsdk.cds.blueprintsprocessor.rest.service.BlueprintWebClientService
13 | import org.onap.ccsdk.cds.blueprintsprocessor.rest.service.RestLoggerService
14 | import org.onap.ccsdk.cds.blueprintsprocessor.services.execution.AbstractScriptComponentFunction
15 | import org.onap.ccsdk.cds.controllerblueprints.core.BlueprintProcessorException
16 | import org.onap.ccsdk.cds.controllerblueprints.core.asJsonNode
17 | import org.onap.ccsdk.cds.controllerblueprints.core.rootFieldsToMap
18 | import org.slf4j.LoggerFactory
19 | import org.springframework.http.HttpHeaders
20 | import org.springframework.http.MediaType
21 | import java.io.IOException
22 | import java.nio.charset.Charset
23 |
24 | open class ConfigDeploy : AbstractScriptComponentFunction() {
25 |
26 | private val log = LoggerFactory.getLogger(ConfigDeploy::class.java)!!
27 |
28 | // workflow input parameter names
29 | private val workflowInputCNFURL = "cnf-rest-url"
30 |
31 | // template resolving (previous step in workflow)
32 | private val templateResolvingNodeName = "resolve-template"
33 | private val cnfConfigTemplate = "cnf-config"
34 |
35 | override fun getName(): String {
36 | return "PantheonCNFConfigDeploy"
37 | }
38 |
39 | // processNB is the main entry for this script (processing NB input = using NB input to deploy config to CNF)
40 | override suspend fun processNB(executionRequest: ExecutionServiceInput) {
41 | log.info("executing Pantheon CNF config deploy script")
42 |
43 | try {
44 | // get input (from workflow and previous step)
45 | val cnfRestURL = bluePrintRuntimeService.getInputValue(workflowInputCNFURL)
46 | val resolvedTemplates = bluePrintRuntimeService.getNodeTemplateOperationOutputValue(
47 | templateResolvingNodeName,
48 | "ResourceResolutionComponent",
49 | operationName,
50 | ResourceResolutionComponent.OUTPUT_RESOURCE_ASSIGNMENT_PARAMS
51 | )
52 | val cnfConfig = resolvedTemplates.rootFieldsToMap()[cnfConfigTemplate]?.asText()
53 | ?: throw BlueprintProcessorException("Can't get resolved template(CNF configuration) from previous workflow step")
54 |
55 | // apply CNF config
56 | val api = CNFRestClient(cnfRestURL.asText())
57 | writeScriptOutputs(api.ApplyConfig(cnfConfig))
58 | } catch (bpe: BlueprintProcessorException) {
59 | addError("Failure in config-deployment script: $bpe")
60 | throw bpe
61 | }
62 |
63 | log.info("Pantheon CNF config deploy script completed")
64 | }
65 |
66 | // recoverNB is for recovering state of CNF after problems with executing config deployment (exceptions and problems
67 | // inside and outside of processNB call)
68 | override suspend fun recoverNB(runtimeException: RuntimeException, executionRequest: ExecutionServiceInput) {
69 | log.info("Something went wrong -> Executing CNF Recovery (currently NO recovery implemented for CNF configuration)")
70 | }
71 |
72 | // writeScriptOutputs writes deployment result to node template attribute used as workflow output
73 | private fun writeScriptOutputs(result: BlueprintWebClientService.WebClientResponse) {
74 | if (result.status != 200) {
75 | addError("Failed to configure CNF due to error response code (${result.status}) from CNF REST API.")
76 | }
77 | setAttribute(
78 | "response-data",
79 | mutableMapOf(
80 | "CNF-response-code" to (result.status.toString()),
81 | "CNF-response-message" to (result.body ?: "")
82 | ).asJsonNode()
83 | )
84 | }
85 |
86 | // CNFRestClient is REST client specialized for communication with CNF REST API.
87 | inner class CNFRestClient(private val restURL: String) {
88 | private val service: RestClientService // BasicAuthRestClientService
89 |
90 | init {
91 | // collect all info for REST client service to successfully operate
92 | var mapOfHeaders = hashMapOf()
93 | mapOfHeaders.put("Content-Type", "application/yaml")
94 | mapOfHeaders.put("cache-control", " no-cache")
95 | mapOfHeaders.put("Accept", "application/json")
96 | // NOTE: use BasicAuthRestClientProperties when basic authentification is needed
97 | var restClientProperties = RestClientProperties()
98 | restClientProperties.url = restURL
99 | restClientProperties.additionalHeaders = mapOfHeaders
100 |
101 | // create REST client service
102 | this.service = RestClientService(restClientProperties)
103 | }
104 |
105 | // ApplyConfig uses CNF REST API to configure given configuration for CNF
106 | fun ApplyConfig(config: String): BlueprintWebClientService.WebClientResponse {
107 | try {
108 | return service.put("/configuration", config)
109 | } catch (e: Exception) {
110 | throw BlueprintProcessorException("Caught exception trying to apply CNF configuration: ${e.message}", e)
111 | }
112 | }
113 | }
114 | }
115 |
116 | // RestClientService is implementation of BlueprintWebClientService that serves as properly configured
117 | // REST client for communicate with CNF. It has no knowledge about the REST API specification of CNF.
118 | class RestClientService(
119 | private val restClientProperties: RestClientProperties
120 | ) : BlueprintWebClientService {
121 |
122 | override fun defaultHeaders(): Map {
123 | return mapOf(
124 | HttpHeaders.CONTENT_TYPE to MediaType.APPLICATION_JSON_VALUE,
125 | HttpHeaders.ACCEPT to MediaType.APPLICATION_JSON_VALUE
126 | )
127 | }
128 |
129 | override fun host(uri: String): String {
130 | return restClientProperties.url + uri
131 | }
132 |
133 | override fun convertToBasicHeaders(headers: Map):
134 | Array {
135 | val customHeaders: MutableMap = headers.toMutableMap()
136 | customHeaders.putAll(verifyAdditionalHeaders(restClientProperties))
137 | return super.convertToBasicHeaders(customHeaders)
138 | }
139 |
140 | @Throws(IOException::class, ClientProtocolException::class)
141 | private fun performHttpCall(httpUriRequest: HttpUriRequest): BlueprintWebClientService.WebClientResponse {
142 | val httpResponse = httpClient().execute(httpUriRequest)
143 | val statusCode = httpResponse.statusLine.statusCode
144 | httpResponse.entity.content.use {
145 | val body = IOUtils.toString(it, Charset.defaultCharset())
146 | return BlueprintWebClientService.WebClientResponse(statusCode, body)
147 | }
148 | }
149 |
150 | // put calls REST PUT operation for given (url+)path and given payload
151 | fun put(path: String, payload: String): BlueprintWebClientService.WebClientResponse {
152 | val convertedHeaders: Array = convertToBasicHeaders(defaultHeaders())
153 | val httpPost = HttpPut(host(path))
154 | val entity = EntityBuilder.create().setText(payload).build()
155 | httpPost.setEntity(entity)
156 | RestLoggerService.httpInvoking(convertedHeaders)
157 | httpPost.setHeaders(convertedHeaders)
158 | return performHttpCall(httpPost)
159 | }
160 | }
161 |
--------------------------------------------------------------------------------
/ONAP-cdnf-integration/firewall-cnf-helper.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | set -euo pipefail
4 |
5 | # Topology
6 | TEST_ALPINE_IMAGE_TAG="alpine-start-end-point"
7 | CNF_CONTAINER_NAME="firewall-cnf" # dependent on docker-compose.yml
8 | STARTPOINT_VETH_IP="10.11.1.1"
9 | STARTPOINT_VETH_MAC_ADDRESS="66:66:66:66:66:66"
10 | STARTPOINT_VETH_HOST_IP="10.11.1.2"
11 | ENDPOINT_VETH_HOST_IP="10.11.2.1"
12 | ENDPOINT_VETH_IP="10.11.2.2"
13 | NAME_OF_DEFAULT_NETWORK="onap-cdnf-integration_default" # dependent on parent directory name
14 | NAME_OF_CDS_NETWORK="onap-cdnf-integration_cds-network" # dependent on parent directory name and docker-compose.yml
15 |
16 | # Test traffic
17 | TRAFFIC_DEST_IP="10.12.0.1"
18 | TRAFFIC_DEST_NETWORK="10.12.0.0/24"
19 | PORT="9000"
20 |
21 |
22 | function preDockerComposeCNFPreparations() {
23 | # clean up reporting directory from previous reports
24 | refreshReportingDir
25 |
26 | # create (if not exists) docker image for startpoint and endpoint containers
27 | assertStartEndPointDockerImage
28 |
29 | # prepare directories for veth moving
30 | sudo mkdir -p /var/run/netns
31 |
32 | # clean up previous run if needed
33 | sudo rm -f /var/run/netns/startpoint
34 | sudo rm -f /var/run/netns/endpoint
35 | }
36 |
37 | function setupCNFTrafficTopology() {
38 | setupVPPPacketPath
39 | setupLoopForIPAddress "endpoint" ${TRAFFIC_DEST_IP} # used as ping destination
40 | }
41 |
42 | function refreshReportingDir() {
43 | rm -rf reports;mkdir -p reports; # for demo report output
44 | }
45 |
46 | function reportCNFState {
47 | docker logs ${CNF_CONTAINER_NAME} &> reports/cnf-log.txt
48 | logVPPACLConfig
49 | logVPPTrace "from-demo-exit"
50 | }
51 |
52 | function cleanupCNFRelatedThings {
53 | sudo rm -f /var/run/netns/startpoint
54 | sudo rm -f /var/run/netns/endpoint
55 | }
56 |
57 | function setupVPPPacketPath() {
58 | ENDPOINT_IP=$(docker inspect endpoint --format='{{ (index .NetworkSettings.Networks "'${NAME_OF_DEFAULT_NETWORK}'").IPAddress}}')
59 | STARTPOINT_IP=$(docker inspect startpoint --format='{{ (index .NetworkSettings.Networks "'${NAME_OF_DEFAULT_NETWORK}'").IPAddress}}')
60 | CNF_IP=$(docker inspect ${CNF_CONTAINER_NAME} --format='{{ (index .NetworkSettings.Networks "'${NAME_OF_CDS_NETWORK}'").IPAddress}}')
61 |
62 | echo "Running setup for packet path..."
63 | echo "--creating file reference of startpoint container namespace..."
64 | mkdir -p /tmp/netns
65 | startpoint_pid=`docker inspect -f '{{.State.Pid}}' startpoint`
66 | sudo ln -s /proc/$startpoint_pid/ns/net /var/run/netns/startpoint
67 |
68 | echo "--creating file reference of endpoint container namespace..."
69 | endpoint_pid=`docker inspect -f '{{.State.Pid}}' endpoint`
70 | sudo ln -s /proc/$endpoint_pid/ns/net /var/run/netns/endpoint
71 |
72 | echo "--creating veth tunnel from startpoint container to VPP in \"CNF\" container...(2 veth tunnels and routes needed in vpp)"
73 | curl --location --request PUT 'http://'${CNF_IP}':9191/configuration' \
74 | --header 'Content-Type: text/plain' \
75 | --data-raw 'netallocConfig: {}
76 | linuxConfig:
77 | interfaces:
78 | - name: vpptoLinuxVETH
79 | type: VETH
80 | hostIfName: veth3
81 | enabled: true
82 | veth:
83 | peerIfName: endpointVETH
84 | - name: startpointVETH
85 | type: VETH
86 | namespace:
87 | type: FD
88 | reference: /var/run/netns/startpoint
89 | hostIfName: veth1
90 | enabled: true
91 | ipAddresses:
92 | - '${STARTPOINT_VETH_IP}'/24
93 | physAddress: '${STARTPOINT_VETH_MAC_ADDRESS}'
94 | veth:
95 | peerIfName: startpointToLinuxVETH
96 | - name: endpointVETH
97 | type: VETH
98 | namespace:
99 | type: FD
100 | reference: /var/run/netns/endpoint
101 | hostIfName: veth4
102 | enabled: true
103 | ipAddresses:
104 | - '${ENDPOINT_VETH_IP}'/24
105 | physAddress: 66:66:66:66:66:65
106 | veth:
107 | peerIfName: vpptoLinuxVETH
108 | - name: startpointToLinuxVETH
109 | type: VETH
110 | hostIfName: veth2
111 | enabled: true
112 | veth:
113 | peerIfName: startpointVETH
114 | vppConfig:
115 | interfaces:
116 | - name: toVPPAFPacket
117 | type: AF_PACKET
118 | enabled: true
119 | physAddress: a7:35:45:55:65:75
120 | ipAddresses:
121 | - '${STARTPOINT_VETH_HOST_IP}'/24
122 | afpacket:
123 | hostIfName: veth2
124 | - name: fromVPPAFPacket
125 | type: AF_PACKET
126 | enabled: true
127 | physAddress: b7:35:45:55:65:75
128 | ipAddresses:
129 | - '${ENDPOINT_VETH_HOST_IP}'/24
130 | afpacket:
131 | hostIfName: veth3
132 | routes:
133 | - dstNetwork: '${TRAFFIC_DEST_IP}'/32
134 | nextHopAddr: '${ENDPOINT_VETH_IP}'/24
135 | outgoingInterface: fromVPPAFPacket
136 | - dstNetwork: '${STARTPOINT_IP}'/32
137 | nextHopAddr: '${STARTPOINT_VETH_IP}'
138 | outgoingInterface: toVPPAFPacket
139 | '
140 |
141 | echo "--creating route in startpoint to veth tunnel..."
142 | docker exec -it startpoint ip route add ${TRAFFIC_DEST_NETWORK} via ${STARTPOINT_VETH_HOST_IP}
143 |
144 | echo "--disabling Linux kernel's reverse path filtering" #disabling to not filter out packets based on unknown/trash source address (source address is expected by this filtering to be reachable with interface from which the packet came)
145 | docker exec -it endpoint sysctl -w net.ipv4.conf.all.rp_filter=0 > /dev/null
146 | docker exec -it endpoint sysctl -w net.ipv4.conf.veth4.rp_filter=0 > /dev/null
147 |
148 | echo "--enabling Linux kernel's routing of packet from veth tunnel to localnet (127.0.0.1)" #external/"martian" source addressed packets are not allowed to localnet by default
149 | docker exec -it endpoint sysctl -w net.ipv4.conf.all.route_localnet=1 > /dev/null
150 | docker exec -it endpoint sysctl -w net.ipv4.conf.veth4.route_localnet=1 > /dev/null
151 |
152 | echo "--moving packets from tunnel (VPP->Endpoint) to Linux localhost" #(so that netcat/socat server listening to localhost can pick them
153 | docker exec -it endpoint iptables -t nat -A PREROUTING -i veth4 -p udp --dport ${PORT} -j DNAT --to-destination 127.0.0.1
154 | docker exec -it endpoint iptables -t nat -A PREROUTING -i veth4 -p tcp --dport ${PORT} -j DNAT --to-destination 127.0.0.1
155 |
156 | echo "--route back for TCP's confirmation packet" #TCP does confirmation using packet sending back to TCP client
157 | docker exec -it endpoint ip route add ${STARTPOINT_VETH_IP}/32 via ${ENDPOINT_VETH_HOST_IP}
158 |
159 | echo "--waiting for processing and applying the configuration inside CNF" #configuration items are dependent on each other and correct configuration may take time
160 | sleep 5s # TODO make pooling solution
161 |
162 | #TODO i should probably find out all things needed to setup and setup them manually
163 | echo "--sending one packet to trigger initialization of packet path(ARP learning and other stuff)" #otherwise first packet failure will break netcat connetion
164 | docker exec -it startpoint sh -c "timeout -t 1 ping ${TRAFFIC_DEST_IP} || true" > /dev/null
165 | echo
166 | }
167 |
168 | function setupLoopForIPAddress() {
169 | local containerName=$1
170 | local ipAddress=$2
171 | $(docker exec -it ${containerName} ip addr add ${ipAddress}/32 dev lo)
172 | }
173 |
174 | function newVPPTrace() {
175 | docker exec -it ${CNF_CONTAINER_NAME} vppctl clear trace
176 | docker exec -it ${CNF_CONTAINER_NAME} vppctl trace add af-packet-input 100
177 | }
178 |
179 | function sendPing() {
180 | local start_container_name=$1
181 | local dest_ip=$2
182 |
183 | pingOutput=$(docker exec -it ${start_container_name} ping -c 1 -W 3 ${dest_ip} || true)
184 | if [[ "$pingOutput" == *"100% packet loss"* ]]; then
185 | # empty string will be evaluated as false when used in if condition
186 | PASSED_THROUGHT=
187 | else
188 | PASSED_THROUGHT=yes
189 | fi
190 | }
191 |
192 | function logVPPTrace() {
193 | docker exec -it ${CNF_CONTAINER_NAME} vppctl sh trace > reports/vpp-trace-output-$1.txt
194 | }
195 |
196 | function logVPPACLConfig() {
197 | docker exec -it ${CNF_CONTAINER_NAME} vppctl show acl-plugin acl > reports/vpp-acl-config-output.txt
198 | docker exec -it ${CNF_CONTAINER_NAME} vppctl show int >> reports/vpp-acl-config-output.txt # needed due to interface referencing in ACL configuration
199 | }
200 |
201 | function getVPPTrace() {
202 | docker exec -it ${CNF_CONTAINER_NAME} vppctl sh trace
203 | }
204 |
205 | function assertStartEndPointDockerImage() {
206 | if ! docker images | grep $TEST_ALPINE_IMAGE_TAG > /dev/null; then
207 | echo "Creating docker image for startpoint/endpoint"
208 | printf "FROM alpine:3.9.5\n RUN apk add iproute2" | docker build - --tag $TEST_ALPINE_IMAGE_TAG
209 | echo
210 | fi
211 | }
212 |
--------------------------------------------------------------------------------
/ONAP-cdnf-integration/cds-bp-application.properties:
--------------------------------------------------------------------------------
1 | #
2 | # Copyright (c) 2017-2019 AT&T, IBM, Bell Canada, Nordix Foundation.
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 | #
16 |
17 | # NOTE: this properties file is copied from onap/ccsdk-blueprintsprocessor:1.1.1 (/opt/app/onap/config/application.properties)
18 | # and modified for purpose of this demo (all changed values are marked as "CHANGED")
19 |
20 | # Web server config
21 | ### START -Controller Blueprints Properties
22 | # Load Resource Source Mappings
23 | resourceSourceMappings=processor-db=source-db,input=source-input,default=source-default,sdnc=source-rest,aai-data=source-rest,capability=source-capability,rest=source-rest,vault-data=source-rest,script=source-capability
24 |
25 | # Controller Blueprints Core Configuration
26 | blueprintsprocessor.blueprintDeployPath=/opt/app/onap/blueprints/deploy
27 | blueprintsprocessor.blueprintArchivePath=/opt/app/onap/blueprints/archive
28 | blueprintsprocessor.blueprintWorkingPath=/opt/app/onap/blueprints/working
29 |
30 | # Controller Blueprint Load Configurations
31 | blueprintsprocessor.loadBlueprintPaths=/opt/app/onap/model-catalog/blueprint-model
32 | # CHANGED to load properly the types in bootstrap REST API call - /opt/app/onap/model-catalog/definition-type -> /opt/app/onap/model-catalog/definition-type/starter-type
33 | blueprintsprocessor.loadModeTypePaths=/opt/app/onap/model-catalog/definition-type/starter-type
34 | # CHANGED to load properly the dictionary in bootstrap REST API call - /opt/app/onap/model-catalog/resource-dictionary -> /opt/app/onap/model-catalog/resource-dictionary/starter-dictionary
35 | blueprintsprocessor.loadResourceDictionaryPaths=/opt/app/onap/model-catalog/resource-dictionary/starter-dictionary
36 |
37 | # CBA file extension
38 | controllerblueprints.loadCbaExtension=zip
39 |
40 | ### END -Controller Blueprints Properties
41 |
42 | blueprintsprocessor.grpcEnable=true
43 | blueprintsprocessor.httpPort=8080
44 | blueprintsprocessor.grpcPort=9111
45 |
46 | # db
47 | # CHANGED - renamed db hostname to deployed db service name - db -> cds-db
48 | blueprintsprocessor.db.url=jdbc:mysql://cds-db:3306/sdnctl
49 | blueprintsprocessor.db.username=sdnctl
50 | blueprintsprocessor.db.password=sdnctl
51 | blueprintsprocessor.db.driverClassName=org.mariadb.jdbc.Driver
52 | blueprintsprocessor.db.hibernateHbm2ddlAuto=update
53 | blueprintsprocessor.db.hibernateDDLAuto=update
54 | blueprintsprocessor.db.hibernateNamingStrategy=org.hibernate.cfg.ImprovedNamingStrategy
55 | blueprintsprocessor.db.hibernateDialect=org.hibernate.dialect.MySQL5InnoDBDialect
56 |
57 | # processor-db endpoint
58 | blueprintsprocessor.db.processor-db.type=maria-db
59 | blueprintsprocessor.db.processor-db.url=jdbc:mysql://mariadb-galera:3306/sdnctl
60 | blueprintsprocessor.db.processor-db.username=root
61 | blueprintsprocessor.db.processor-db.password=secretpassword
62 |
63 | # Python executor
64 | blueprints.processor.functions.python.executor.executionPath=/opt/app/onap/scripts/jython/ccsdk_blueprints
65 | blueprints.processor.functions.python.executor.modulePaths=/opt/app/onap/scripts/jython/ccsdk_blueprints,/opt/app/onap/scripts/jython/ccsdk_netconf,/opt/app/onap/scripts/jython/ccsdk_restconf
66 |
67 | security.user.password: {bcrypt}$2a$10$duaUzVUVW0YPQCSIbGEkQOXwafZGwQ/b32/Ys4R1iwSSawFgz7QNu
68 | security.user.name: ccsdkapps
69 |
70 | # Error Managements
71 | error.catalog.applicationId=cds
72 | error.catalog.type=properties
73 | error.catalog.errorDefinitionDir=/opt/app/onap/config/
74 |
75 | # Used in Health Check
76 | #endpoints.user.name=ccsdkapps
77 | #endpoints.user.password=ccsdkapps
78 |
79 | # Executor Options
80 | blueprintsprocessor.resourceResolution.enabled=true
81 | blueprintsprocessor.netconfExecutor.enabled=true
82 | blueprintsprocessor.restConfExecutor.enabled=true
83 | blueprintsprocessor.cliExecutor.enabled=true
84 | blueprintsprocessor.remoteScriptCommand.enabled=true
85 |
86 | # Command executor
87 | blueprintsprocessor.grpcclient.remote-python.type=token-auth
88 | blueprintsprocessor.grpcclient.remote-python.host=localhost
89 | blueprintsprocessor.grpcclient.remote-python.port=50051
90 | blueprintsprocessor.grpcclient.remote-python.token=Basic Y2NzZGthcHBzOmNjc2RrYXBwcw==
91 |
92 | # Py executor
93 | blueprintsprocessor.grpcclient.py-executor.type=tls-auth
94 | blueprintsprocessor.grpcclient.py-executor.host=py-executor-default:50052
95 | blueprintsprocessor.grpcclient.py-executor.trustCertCollection=/opt/app/onap/config/certs/py-executor/py-executor-chain.pem
96 |
97 | # Config Data REST client settings
98 | blueprintsprocessor.restconfEnabled=true
99 | blueprintsprocessor.restclient.sdnc.type=basic-auth
100 | blueprintsprocessor.restclient.sdnc.url=http://sdnc:8282
101 | blueprintsprocessor.restclient.sdnc.username=admin
102 | blueprintsprocessor.restclient.sdnc.password=Kp8bJ4SXszM0WXlhak3eHlcse2gAw84vaoGGmJvUy2U
103 |
104 | # Naming MS REST client settings
105 | blueprintsprocessor.restclient.naming-ms.type=basic-auth
106 | blueprintsprocessor.restclient.naming-ms.url=http://naming-ms:8282
107 | blueprintsprocessor.restclient.naming-ms.username=admin
108 | blueprintsprocessor.restclient.naming-ms.password=demo123456!
109 |
110 | # IPAssign MS REST client settings
111 | blueprintsprocessor.restclient.ipassign-ms.type=basic-auth
112 | blueprintsprocessor.restclient.ipassign-ms.url=http://naming-ms:8282
113 | blueprintsprocessor.restclient.ipassign-ms.username=admin
114 | blueprintsprocessor.restclient.ipassign-ms.password=demo123456!
115 |
116 | # Primary AAI Data REST Client settings
117 | blueprintsprocessor.restclient.aai-data.type=basic-auth
118 | blueprintsprocessor.restclient.aai-data.url=https://aai:8443
119 | blueprintsprocessor.restclient.aai-data.username=aai@aai.onap.org
120 | blueprintsprocessor.restclient.aai-data.password=demo123456!
121 | blueprintsprocessor.restclient.aai-data.additionalHeaders.X-TransactionId=cds-transaction-id
122 | blueprintsprocessor.restclient.aai-data.additionalHeaders.X-FromAppId=cds-app-id
123 | blueprintsprocessor.restclient.aai-data.additionalHeaders.Accept=application/json
124 |
125 | # Kafka audit service Configurations
126 | ## Audit request
127 | blueprintsprocessor.messageproducer.self-service-api.audit.kafkaEnable=false
128 | blueprintsprocessor.messageproducer.self-service-api.audit.request.type=kafka-basic-auth
129 | blueprintsprocessor.messageproducer.self-service-api.audit.request.bootstrapServers=127.0.0.1:9092
130 | blueprintsprocessor.messageproducer.self-service-api.audit.request.clientId=audit-request-producer-client-id
131 | blueprintsprocessor.messageproducer.self-service-api.audit.request.topic=audit-request-producer.t
132 | #### Security settings
133 | #### SSL
134 | #blueprintsprocessor.messageproducer.self-service-api.audit.request.truststore=/path/to/truststore.jks
135 | #blueprintsprocessor.messageproducer.self-service-api.audit.request.truststorePassword=truststorePassword
136 | #blueprintsprocessor.messageproducer.self-service-api.audit.request.keystore=/path/to/keystore.jks
137 | #blueprintsprocessor.messageproducer.self-service-api.audit.request.keystorePassword=keystorePassword
138 | #### SCRAM
139 | #blueprintsprocessor.messageproducer.self-service-api.audit.request.scramUsername=test-user
140 | #blueprintsprocessor.messageproducer.self-service-api.audit.request.scramPassword=testUserPassword
141 |
142 | ## Audit response
143 | blueprintsprocessor.messageproducer.self-service-api.audit.response.type=kafka-basic-auth
144 | blueprintsprocessor.messageproducer.self-service-api.audit.response.bootstrapServers=127.0.0.1:9092
145 | blueprintsprocessor.messageproducer.self-service-api.audit.response.clientId=audit-response-producer-client-id
146 | blueprintsprocessor.messageproducer.self-service-api.audit.response.topic=audit-response-producer.t
147 |
148 | # Message prioritization kakfa properties, Enable if Prioritization service is needed
149 | # Deploy message-prioritization function along with blueprintsprocessor application.
150 | #blueprintsprocessor.messageconsumer.prioritize-input.type=kafka-streams-basic-auth
151 | #blueprintsprocessor.messageconsumer.prioritize-input.bootstrapServers=127.0.0.1:9092
152 | #blueprintsprocessor.messageconsumer.prioritize-input.applicationId=cds-controller
153 | #blueprintsprocessor.messageconsumer.prioritize-input.topic=prioritize-input-topic
154 |
155 | blueprintprocessor.remoteScriptCommand.enabled=true
156 |
157 | #Encrypted username and password for health check service
158 | endpoints.user.name=eHbVUbJAj4AG2522cSbrOQ==
159 | endpoints.user.password=eHbVUbJAj4AG2522cSbrOQ==
160 |
161 | #BaseUrls for health check blueprint processor services
162 | blueprintprocessor.healthcheck.baseUrl=http://localhost:8080/
163 | blueprintprocessor.healthcheck.mapping-service-name-with-service-link=[Execution service,/api/v1/execution-service/health-check],[Resources service,/api/v1/resources/health-check],[Template service,/api/v1/template/health-check]
164 |
165 | #BaseUrls for health check Cds Listener services
166 | cdslistener.healthcheck.baseUrl=http://cds-sdc-listener:8080/
167 | cdslistener.healthcheck.mapping-service-name-with-service-link=[SDC Listener service,/api/v1/sdclistener/healthcheck]
168 |
169 | #Actuator properties
170 | management.endpoints.web.exposure.include=*
171 | management.endpoint.health.show-details=always
172 | management.info.git.mode=full
173 |
174 | #K8s Plugin properties
175 | blueprintprocessor.k8s.plugin.username=test
176 | blueprintprocessor.k8s.plugin.password=pass
177 | blueprintprocessor.k8s.plugin.url=http://multicloud-k8s:9015/
178 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright [yyyy] [name of copyright owner]
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/vpp-traceability/vpp_bpftrace.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | #
3 | # Trace VPP BPF tooling to display output from BPF probes.
4 | #
5 | # Copyright 2020 GitHub, Inc.
6 | # Copyright 2020 Pantheon.tech and/or its affiliates.
7 | #
8 | # Licensed under the Apache License, Version 2.0 (the "License");
9 |
10 | from __future__ import print_function
11 | import argparse
12 | import curses
13 | import inspect
14 | import ipaddress
15 | import logging
16 | import os
17 | import sys
18 | import subprocess
19 | from bcc import BPF, USDT
20 | from decimal import Decimal
21 | from multiprocessing import Process
22 | from select import select
23 | from struct import *
24 | from time import sleep, strftime
25 |
26 | Config = {}
27 | VppBpfProbes = {}
28 | VppBpfPerfProbes = {}
29 | USDT_ctx = {}
30 |
31 | def bpf_tracing2curses(stdscr, vpp_bpf_probes):
32 | global Config
33 |
34 | def render_header(stdscr, line, header, col=0):
35 | stdscr.attron(curses.color_pair(2))
36 | stdscr.attron(curses.A_BOLD)
37 | stdscr.addstr(line, col, header)
38 | stdscr.addstr(line+1, col, "=" * len(header))
39 | stdscr.attroff(curses.color_pair(2))
40 | stdscr.attroff(curses.A_BOLD)
41 |
42 | # Clear and refresh the screen for a blank canvas
43 | stdscr.clear()
44 | stdscr.refresh()
45 |
46 | auto_refresh = True
47 | key = 0
48 |
49 | # Start colors in curses
50 | curses.start_color()
51 | curses.init_pair(1, curses.COLOR_CYAN, curses.COLOR_BLACK)
52 | curses.init_pair(2, curses.COLOR_BLUE, curses.COLOR_BLACK)
53 | curses.init_pair(3, curses.COLOR_BLACK, curses.COLOR_WHITE)
54 | curses.init_pair(4, curses.COLOR_MAGENTA, curses.COLOR_BLACK)
55 |
56 | titlestr = "VPP BPFtrace tooling"
57 | header_simple_counters = "{:<11} | {:<32} | {:^15}".format("SW-if-index", "Counter name", "Count")
58 | header_error_counters = "{:<11} | {:<32} | {:^15}".format("Error-idx", "Counter name", "Count")
59 | header_stats = "{:^32} | {:^8}|{:^8}|{:^8}|{:^8}|{:^8}|{:^8}|{:^8}|{:^8}".format("Node name (with Calls > 0)", "Calls", "Vectors", "Suspends", "Clocks", "Vcts/Cls", "MxNodCls", "VctsAtMx", "MxClocks")
60 | header_intfs_info = "{:<46} | {:^5} | {:^7}".format("SW-if-index [if-name]", "State", "Core ID")
61 | header_vector_rates = "{:^9} | {:^7} | {:^7} | {:^32}".format("Core ID", "Calls", "Vectors", "Internal node vector rate")
62 | height, width = stdscr.getmaxyx()
63 |
64 | while (key != ord('q')):
65 | # Initialization
66 | stdscr.clear()
67 | line = 0
68 |
69 | simple_counters = vpp_bpf_probes["InterfaceCounters"].get_table("simple_counters") if (vpp_bpf_probes.get("InterfaceCounters") != None) else None
70 | error_counters = vpp_bpf_probes["ErrorCounters"].get_table("error_counters") if (vpp_bpf_probes.get("ErrorCounters") != None) else None
71 | stats_counters = vpp_bpf_probes["NodeStatistics"].get_table("stats_counters") if (vpp_bpf_probes.get("NodeStatistics") != None) else None
72 | intfs_info = vpp_bpf_probes["InterfacesInfo"].get_table("intfs_info") if (vpp_bpf_probes.get("InterfacesInfo") != None) else None
73 | vector_rate_counters = vpp_bpf_probes["NodeStatistics"].get_table("vector_rate_counters") if (vpp_bpf_probes.get("NodeStatistics") != None) else None
74 |
75 | # Render status bar
76 | refreshstr = "Auto {:2} s".format(Config["refresh_interval"]) if auto_refresh else "Manual"
77 | statusbarstr = " STATUS BAR | Attached to pid {} | Refresh : {:>9} | Press 'q' to exit, 'r' to refresh, 'a' for auto-refresh".format(Config["pid"], refreshstr)
78 | stdscr.attron(curses.color_pair(3))
79 | stdscr.addstr(height-1, 0, statusbarstr)
80 | stdscr.addstr(height-1, len(statusbarstr), " " * (width - len(statusbarstr) - 1))
81 | stdscr.attroff(curses.color_pair(3))
82 |
83 | # Render title bar
84 | stdscr.attron(curses.color_pair(4))
85 | stdscr.attron(curses.A_BOLD)
86 | col = int((width // 2) - (len(titlestr) // 2) - len(titlestr) % 2)
87 | stdscr.addstr(line, col, titlestr)
88 | stdscr.attroff(curses.color_pair(4))
89 | stdscr.attroff(curses.A_BOLD)
90 |
91 | # Render splitters
92 | stdscr.attron(curses.color_pair(2))
93 | stdscr.attron(curses.A_BOLD)
94 | for l in range(line+2, height-Config["log_height"]-3): stdscr.addstr(l, 68, "|")
95 | for c in range(0, width): stdscr.addstr(height-Config["log_height"]-4, c, "-")
96 | stdscr.attroff(curses.color_pair(2))
97 | stdscr.attroff(curses.A_BOLD)
98 |
99 | if stats_counters != None:
100 | # Render stat header
101 | render_header(stdscr, line+2, header_stats, col=70)
102 | # Rendering stat probes output
103 | l = line+4
104 | for k, v in sorted(stats_counters.items(), key=lambda kv: kv[1].node_name):
105 | if l == height-Config["log_height"]-5:
106 | stdscr.addstr(l, 70, "...")
107 | break
108 | if v.calls > 0:
109 | item = "{:<32} | {:1.2E} {:1.2E} {:1.2E} {:1.2E} {:1.2E} {:1.2E} {:1.2E} {:1.2E}". \
110 | format(v.node_name, v.calls, v.vectors, \
111 | v.suspends, v.clocksperx, v.vectorspercall, \
112 | v.maxcn, v.maxn, v.maxc)
113 | #v.clocksperx, v.vectorspercall, v.maxcn, v.maxn, v.maxc)
114 | stdscr.addstr(l, 70, item)
115 | l += 1
116 | if l>60:
117 | break;
118 |
119 | if vector_rate_counters != None:
120 | # Render vector rate header
121 | line += 2
122 | render_header(stdscr, line, header_vector_rates)
123 | # Rendering vector rate output
124 | line += 2
125 | for k, v in vector_rate_counters.items():
126 | item = "{:^9} | {:^7} | {:^7} | {:^30.02E}".format(k.node_index, v.calls, v.vectors, \
127 | v.vectors/v.calls if v.calls>0 else 0)
128 | stdscr.addstr(line, 0, item)
129 | line += 1
130 |
131 | if simple_counters != None:
132 | # Header simple counters
133 | line += 2
134 | render_header(stdscr, line, header_simple_counters)
135 |
136 | # Rendering simple counter probes output
137 | line += 2
138 | for k, v in simple_counters.items():
139 | item = "{:^11} | {:<32} | {:^15}".format(k.counter_index, k.name, v.total)
140 | stdscr.addstr(line, 0, item)
141 | line += 1
142 |
143 | if error_counters != None:
144 | # Header error counters
145 | line += 1
146 | render_header(stdscr, line, header_error_counters)
147 |
148 | # Rendering error counter probes output
149 | line += 2
150 | for k, v in error_counters.items():
151 | item = "{:^11} | {:<32} | {:^15}".format(k.counter_index, k.name, v.total)
152 | stdscr.addstr(line, 0, item)
153 | line += 1
154 |
155 | if intfs_info != None:
156 | # Header interfaces info
157 | line += 1
158 | render_header(stdscr, line, header_intfs_info)
159 |
160 | # Rendering interface info output
161 | line += 2
162 | for k, v in intfs_info.items():
163 | item = "{:>3} {:<42} | {:^5} | {:^7}".format(k.if_index,"["+v.if_name+"]", Config["if_s"][v.state], v.thread_index)
164 | stdscr.addstr(line, 0, item)
165 | line += 1
166 |
167 | # Render last Config["log_height"] lines from FILE_LOG
168 | line = height - Config["log_height"] - 2
169 | p = subprocess.Popen(['tail','-n',str(Config["log_height"]),Config["log_file"]], stdout=subprocess.PIPE)
170 | soutput, sinput = p.communicate()
171 | for msg in soutput.split('\n'):
172 | stdscr.addstr(line, 0, msg)
173 | line += 1
174 |
175 | # Set cursor position
176 | stdscr.move(height-1, 0)
177 | # Refresh the screen
178 | stdscr.refresh()
179 |
180 | # Wait for next input
181 | key = ord('a') if auto_refresh else 0
182 | while (key == 0 or key == ord('a')):
183 | rlist, wlist, xlist = select([sys.stdin], [], [], Config["refresh_interval"])
184 | if rlist:
185 | key = stdscr.getch()
186 | if key == ord('a'):
187 | auto_refresh = True
188 | break
189 | elif key == ord('q'):
190 | break
191 | elif key == ord('r') or key == ord('m'):
192 | auto_refresh = False
193 | break
194 | else:
195 | if auto_refresh:
196 | break
197 | key = 0
198 |
199 | # Callbacks fot performace loggers
200 |
201 | def log_nbh_event(cpu, data, size):
202 | global Config, VppBpfProbes
203 |
204 | nbh_updates = VppBpfProbes["NbhUpdates"] if (VppBpfProbes.get("NbhUpdates") != None) else None
205 |
206 | event = nbh_updates["nbh_events"].event(data)
207 |
208 | ip_bytes = bytearray()
209 | for b in event.ip_address[0:Config["ip_len"][event.is_ipv6]]: ip_bytes.append (b)
210 |
211 | item_fmt = "{:<24} | {:6} | {:3} | {:36} | {:<17} | {:^12}" if event.is_ipv6 else "{:<24} | {:6} | {:3} | {:15} | {:<17} | {:^12}"
212 | item = item_fmt. \
213 | format("vnet_ip_neighbor_probe", event.sw_if_index, Config["mode_s"][event.is_del], \
214 | ipaddress.ip_address(bytes(ip_bytes)), \
215 | ':'.join('%02x' % b for b in event.mac_address), \
216 | Config["nbh_fl_s"][event.flags])
217 |
218 | logging.info(item)
219 |
220 | def log_ip_event(cpu, data, size):
221 | global Config, VppBpfProbes
222 | ip_updates = VppBpfProbes["IpUpdates"] if (VppBpfProbes.get("IpUpdates") != None) else None
223 |
224 | event = ip_updates["ip_events"].event(data)
225 |
226 | ip_bytes = bytearray()
227 | for b in event.ip_address[0:Config["ip_len"][event.is_ipv6]]: ip_bytes.append (b)
228 |
229 | item = "{:<24} | {:6} | {:3} | {:3} | {:<128}".\
230 | format("vnet_ip_address_probe", event.sw_if_index, Config["mode_s"][event.is_del], Config["ip_s"][event.is_ipv6], \
231 | "{}/{}".format(ipaddress.ip_address(bytes(ip_bytes)), event.address_length))
232 |
233 | logging.info(item)
234 |
235 | def log_route_event(cpu, data, size):
236 | global Config, VppBpfProbes
237 | route_updates = VppBpfProbes["RouteUpdates"] if (VppBpfProbes.get("RouteUpdates") != None) else None
238 |
239 | event = route_updates["route_events"].event(data)
240 |
241 | path_ip_bytes = bytearray()
242 | route_ip_bytes = bytearray()
243 | for b in event.path[0:Config["ip_len"][event.is_ipv6]]: path_ip_bytes.append (b)
244 | for b in event.route[0:Config["ip_len"][event.is_ipv6]]: route_ip_bytes.append (b)
245 |
246 | item_fmt = "{:<24} | {:6} | {:3} | {:36} | {:32}" if event.is_ipv6 else "{:<24} | {:6} | {:3} | {:20} | {:15}"
247 | item = item_fmt.format("vnet_ip_route_probe", event.fib_index, Config["mode_s"][event.is_del], \
248 | "{}/{}".format(ipaddress.ip_address(bytes(path_ip_bytes)), event.path_len), \
249 | ipaddress.ip_address(bytes(route_ip_bytes)))
250 |
251 | logging.info(item)
252 |
253 | def log_nat_event(cpu, data, size):
254 | global Config, VppBpfProbes
255 | nat_updates = VppBpfProbes["NatUpdates"] if (VppBpfProbes.get("NatUpdates") != None) else None
256 |
257 | event = nat_updates["nat_events"].event(data)
258 | item = "{:24} | {:6} | {:3} | {:3} | {:3} | {:>15}:{:<5} | {:>15}:{:<5}".\
259 | format("vnet_nat_session_update", event.thread_index, \
260 | Config["nat_op_s"][event.operation], \
261 | event.fib_index, event.protocol, \
262 | ipaddress.ip_address(event.in2out_addr), event.in2out_port, \
263 | ipaddress.ip_address(event.out2in_addr), event.out2in_port)
264 |
265 | logging.info(item)
266 |
267 | ProbesWrapper = {
268 | "InterfaceCounters" : {
269 | "perf": False,
270 | "bcc": "vlib_simple_counters.c",
271 | "probes": ["vlib_increment_simple_counters_probe"],
272 | "probes_fn": ["vpp_simple_counters"]},
273 | "ErrorCounters" : {
274 | "perf": False,
275 | "bcc": "vlib_error_counters.c",
276 | "probes": ["vlib_error_count_probe"],
277 | "probes_fn": ["vpp_error_counters"]},
278 | "NodeStatistics" : {
279 | "perf": False,
280 | "bcc": "vlib_stats.c",
281 | "probes": ["vlib_node_runtime_sync_stats_probe", "vlib_vector_rate_probe"],
282 | "probes_fn": ["vpp_stats", "vpp_vector_rate"]},
283 | "InterfacesInfo" : {
284 | "perf": False,
285 | "bcc": "vnet_interfaces.c",
286 | "probes": ["vnet_sw_interface_state_probe","vnet_set_hw_interface_rx_placement_probe","vnet_hw_interface_set_rx_mode_probe"],
287 | "probes_fn": ["vpp_intfs_state","vpp_intfs_rx_placement","vpp_intfs_rx_mode"]},
288 | "NbhUpdates": {
289 | "perf": True,
290 | "bcc": "vnet_neighbor_updates.c",
291 | "probes": ["vnet_ip_neighbor_probe"],
292 | "probes_fn": ["vpp_nbh_updates"],
293 | "events": "nbh_events",
294 | "callback": log_nbh_event},
295 | "IpUpdates": {
296 | "perf": True,
297 | "bcc": "vnet_ip_updates.c",
298 | "probes": ["vnet_ip_address_probe"],
299 | "probes_fn": ["vpp_ip_updates"],
300 | "events": "ip_events",
301 | "callback": log_ip_event},
302 | "RouteUpdates": {
303 | "perf": True,
304 | "bcc": "vnet_route_updates.c",
305 | "probes": ["vnet_ip_route_probe"],
306 | "probes_fn": ["vpp_route_updates"],
307 | "events": "route_events",
308 | "callback": log_route_event},
309 | "NatUpdates": {
310 | "perf": True,
311 | "bcc": "vnet_nat_updates.c",
312 | "probes": ["vnet_nat_session_update_probe"],
313 | "probes_fn": ["vpp_nat_session_updates"],
314 | "events": "nat_events",
315 | "callback": log_nat_event},
316 | }
317 |
318 | # Performance loggers
319 |
320 | def bpf_tracing2log(vpp_bpf_probe, event_table, *args):
321 | global VppBpfProbes
322 |
323 | updates = VppBpfProbes[vpp_bpf_probe] if (VppBpfProbes.get(vpp_bpf_probe) != None) else None
324 | if updates != None:
325 | updates[event_table].open_perf_buffer(*args, page_cnt=64)
326 | while 1:
327 | updates.perf_buffer_poll()
328 |
329 | def create_usdt(probe, ctx):
330 | global Config, ProbesWrapper
331 |
332 | probe_config = ProbesWrapper[probe]
333 |
334 | os_path = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
335 | bpf_code = open("%s/%s" % (os_path, probe_config["bcc"]), 'r').read()
336 | for p, f in zip(probe_config["probes"], probe_config["probes_fn"]):
337 | ctx.enable_probe( p, f)
338 | VppBpfProbes[probe] = BPF(text=bpf_code, usdt_contexts=[ctx], debug=Config["debugLevel"])
339 |
340 | def create_bpf_tracer(probe):
341 | global ProbesWrapper
342 |
343 | probe_config = ProbesWrapper[probe]
344 |
345 | VppBpfPerfProbes[probe] = Process(target=bpf_tracing2log,
346 | args=(probe, probe_config["events"], probe_config["callback"]))
347 |
348 | def main():
349 | global Config
350 |
351 | Config["bcc_path"] = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
352 | Config["refresh_interval"] = 10
353 | Config["debugLevel"] = 0
354 | Config["log_file"] = Config["bcc_path"] + "/vpp_bpf_tracer.log"
355 | Config["log_height"] = 15
356 |
357 | Config["if_s"] = { 0: 'DOWN', 1: 'UP' }
358 | Config["mode_s"] = { 0: 'ADD', 1: 'DEL' }
359 | Config["ip_s"] = { 0: 'IP4', 1: 'IP6'}
360 | Config["nat_op_s"] = { 0: 'CRE', 1: 'UPD', 2: 'DEL' }
361 | Config["nbh_fl_s"] = { 1: 'STATIC', 2: 'DYNAMIC', 4: 'NO_FIB_ENTRY', 8: 'PENDING', 16: 'STALE' }
362 | Config["ip_len"] = { 0: 4, 1: 16 }
363 |
364 | # Parse command line arguments
365 | parser = argparse.ArgumentParser(description="Trace VPP interface's counters.", formatter_class=argparse.RawDescriptionHelpFormatter)
366 | parser.add_argument("-p", "--pid", type=int, help="The id of the VPP process to trace.")
367 | parser.add_argument("-r", "--refresh", dest="refresh_interval", type=int, help="Time interval for auto refresh")
368 | parser.add_argument("-l", "--log_height", dest="log_height", type=int, help="Height, in lines, of log part of window")
369 | parser.add_argument("-v", "--verbose", dest="verbose", action="store_true", help="If true, will output verbose logging information.")
370 | parser.set_defaults(verbose=False)
371 | args = parser.parse_args()
372 |
373 | # Monitored process ID
374 | Config["pid"] = int(args.pid)
375 | # Refresh rate
376 | if args.refresh_interval:
377 | Config["refresh_interval"] = int(args.refresh_interval)
378 | if args.log_height:
379 | Config["log_height"] = int(args.log_height)
380 | # Debug level
381 | if args.verbose:
382 | Config["debugLevel"]=4
383 |
384 | print("Attaching probes to pid %d ..." % Config["pid"])
385 |
386 | if os.path.exists(Config["log_file"]):
387 | os.remove(Config["log_file"])
388 | logging.basicConfig(level=logging.DEBUG, filename=Config["log_file"],
389 | filemode="a+", format="%(asctime)-15s %(levelname)-8s %(message)s")
390 |
391 | # Create USDT contexts
392 | usdt_ctx_simple = USDT(pid=Config["pid"])
393 | usdt_ctx_error = USDT(pid=Config["pid"])
394 | usdt_ctx_stats = USDT(pid=Config["pid"])
395 | usdt_ctx_intfs = USDT(pid=Config["pid"])
396 | usdt_ctx_nbh = USDT(pid=Config["pid"])
397 | usdt_ctx_ip = USDT(pid=Config["pid"])
398 | usdt_ctx_route = USDT(pid=Config["pid"])
399 | usdt_ctx_nat = USDT(pid=Config["pid"])
400 |
401 | create_usdt("InterfaceCounters", usdt_ctx_simple)
402 | create_usdt("ErrorCounters", usdt_ctx_error)
403 | create_usdt("NodeStatistics", usdt_ctx_stats)
404 | create_usdt("InterfacesInfo", usdt_ctx_intfs)
405 | create_usdt("NbhUpdates", usdt_ctx_nbh)
406 | create_usdt("IpUpdates", usdt_ctx_ip)
407 | create_usdt("RouteUpdates", usdt_ctx_route)
408 | create_usdt("NatUpdates", usdt_ctx_nat)
409 |
410 | for k, v in ProbesWrapper.items():
411 | if (v["perf"]):
412 | create_bpf_tracer(k)
413 |
414 | # Start tracing
415 | for v in VppBpfPerfProbes.itervalues():
416 | v.start()
417 | curses.wrapper(bpf_tracing2curses, VppBpfProbes)
418 |
419 | # Stop tracing
420 | for v in VppBpfPerfProbes.itervalues():
421 | v.terminate()
422 |
423 | print("Closing probes ...")
424 |
425 | if __name__ == "__main__":
426 | main()
--------------------------------------------------------------------------------
/vpp-traceability/vpp-traceability.diff:
--------------------------------------------------------------------------------
1 | diff --git a/src/plugins/nat/nat_ha.c b/src/plugins/nat/nat_ha.c
2 | index 8bf07759f..f24f0e01f 100644
3 | --- a/src/plugins/nat/nat_ha.c
4 | +++ b/src/plugins/nat/nat_ha.c
5 | @@ -691,6 +691,16 @@ nat_ha_sadd (ip4_address_t * in_addr, u16 in_port, ip4_address_t * out_addr,
6 | ip4_address_t * ehn_addr, u16 ehn_port, u8 proto, u32 fib_index,
7 | u16 flags, u32 thread_index, u8 is_resync)
8 | {
9 | +#ifdef USE_BPF_TRACE
10 | + DTRACE_PROBE8 (vpp, vnet_nat_session_update_probe, 0 /* create */ ,
11 | + thread_index,
12 | + (u32) fib_index,
13 | + (u32) proto,
14 | + htonl (in_addr->as_u32),
15 | + (u32) (htons (in_port)),
16 | + htonl (out_addr->as_u32), (u32) (htons (out_port)));
17 | +#endif
18 | +
19 | nat_ha_event_t event;
20 |
21 | skip_if_disabled ();
22 | diff --git a/src/plugins/nat/nat_inlines.h b/src/plugins/nat/nat_inlines.h
23 | index 7c28919f7..1d4e3a5a8 100644
24 | --- a/src/plugins/nat/nat_inlines.h
25 | +++ b/src/plugins/nat/nat_inlines.h
26 | @@ -22,6 +22,7 @@
27 | #include
28 | #include
29 | #include
30 | +#include
31 |
32 | static inline uword
33 | nat_pre_node_fn_inline (vlib_main_t * vm,
34 | @@ -281,6 +282,17 @@ nat44_delete_session (snat_main_t * sm, snat_session_t * ses,
35 |
36 | nat44_delete_user_with_no_session (sm, u, thread_index);
37 | }
38 | +
39 | +#ifdef USE_BPF_TRACE
40 | + DTRACE_PROBE8 (vpp, vnet_nat_session_update_probe, 2 /* delete */ ,
41 | + thread_index,
42 | + (u32) (ses->in2out.fib_index),
43 | + (u32) (ses->in2out.protocol),
44 | + htonl (ses->in2out.addr.as_u32),
45 | + (u32) (htons (ses->in2out.port)),
46 | + htonl (ses->out2in.addr.as_u32),
47 | + (u32) (htons (ses->out2in.port)));
48 | +#endif
49 | }
50 |
51 | /** \brief Set TCP session state.
52 | @@ -295,6 +307,11 @@ nat44_set_tcp_session_state_i2o (snat_main_t * sm, f64 now,
53 | u8 tcp_flags = vnet_buffer (b)->ip.reass.icmp_type_or_tcp_flags;
54 | u32 tcp_ack_number = vnet_buffer (b)->ip.reass.tcp_ack_number;
55 | u32 tcp_seq_number = vnet_buffer (b)->ip.reass.tcp_seq_number;
56 | +#ifdef USE_BPF_TRACE
57 | + u8 old_state = ses->state;
58 | + bool is_add = false;
59 | +#endif
60 | +
61 | if ((ses->state == 0) && (tcp_flags & TCP_FLAG_RST))
62 | ses->state = NAT44_SES_RST;
63 | if ((ses->state == NAT44_SES_RST) && !(tcp_flags & TCP_FLAG_RST))
64 | @@ -303,7 +320,12 @@ nat44_set_tcp_session_state_i2o (snat_main_t * sm, f64 now,
65 | (ses->state & NAT44_SES_O2I_SYN))
66 | ses->state = 0;
67 | if (tcp_flags & TCP_FLAG_SYN)
68 | - ses->state |= NAT44_SES_I2O_SYN;
69 | + {
70 | + ses->state |= NAT44_SES_I2O_SYN;
71 | +#ifdef USE_BPF_TRACE
72 | + is_add = true;
73 | +#endif
74 | + }
75 | if (tcp_flags & TCP_FLAG_FIN)
76 | {
77 | ses->i2o_fin_seq = clib_net_to_host_u32 (tcp_seq_number);
78 | @@ -333,6 +355,21 @@ nat44_set_tcp_session_state_i2o (snat_main_t * sm, f64 now,
79 | }
80 | clib_dlist_remove (tsm->lru_pool, ses->lru_index);
81 | clib_dlist_addtail (tsm->lru_pool, ses->lru_head_index, ses->lru_index);
82 | +
83 | +#ifdef USE_BPF_TRACE
84 | + if (old_state != ses->state)
85 | + {
86 | + DTRACE_PROBE8 (vpp, vnet_nat_session_update_probe,
87 | + (is_add) ? 0 : 1 /* create / update */ ,
88 | + thread_index,
89 | + (u32) (ses->in2out.fib_index),
90 | + (u32) (ses->in2out.protocol),
91 | + htonl (ses->in2out.addr.as_u32),
92 | + (u32) (htons (ses->in2out.port)),
93 | + htonl (ses->out2in.addr.as_u32),
94 | + (u32) (htons (ses->out2in.port)));
95 | + }
96 | +#endif
97 | return 0;
98 | }
99 |
100 | diff --git a/src/vlib/CMakeLists.txt b/src/vlib/CMakeLists.txt
101 | index 8a31af687..288fdf85b 100644
102 | --- a/src/vlib/CMakeLists.txt
103 | +++ b/src/vlib/CMakeLists.txt
104 | @@ -97,6 +97,7 @@ add_vpp_library(vlib
105 | unix/util.c
106 | vmbus/vmbus.c
107 | ${VMBUS_SOURCE}
108 | + bpf_tracer.c
109 |
110 | MULTIARCH_SOURCES
111 | drop.c
112 | diff --git a/src/vlib/bpf_tracer.c b/src/vlib/bpf_tracer.c
113 | new file mode 100644
114 | index 000000000..1e0fbe5c8
115 | --- /dev/null
116 | +++ b/src/vlib/bpf_tracer.c
117 | @@ -0,0 +1,130 @@
118 | +/*
119 | + * Copyright (c) 2020 Pantheon.tech and/or its affiliates.
120 | + *
121 | + * Licensed under the Apache License, Version 2.0 (the "License");
122 | + * you may not use this file except in compliance with the License.
123 | + * You may obtain a copy of the License at:
124 | + *
125 | + * http://www.apache.org/licenses/LICENSE-2.0
126 | + *
127 | + * Unless required by applicable law or agreed to in writing, software
128 | + * distributed under the License is distributed on an "AS IS" BASIS,
129 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
130 | + * See the License for the specific language governing permissions and
131 | + * limitations under the License.
132 | + */
133 | +
134 | +#include "bpf_tracer.h"
135 | +
136 | +#ifdef USE_BPF_TRACE
137 | +
138 | +bpf_tracer_main_t bpf_tracer_main;
139 | +
140 | +static clib_error_t *
141 | +bpftracer_config (vlib_main_t * vm, unformat_input_t * input)
142 | +{
143 | + bpf_tracer_main_t *bm = &bpf_tracer_main;
144 | + bm->update_interval = 10.0;
145 | +
146 | + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
147 | + {
148 | + if (unformat (input, "update-interval %d", &bm->update_interval))
149 | + ;
150 | + else
151 | + return clib_error_return (0, "unknown input `%U'",
152 | + format_unformat_error, input);
153 | + }
154 | + return 0;
155 | +}
156 | +
157 | +static clib_error_t *
158 | +bpf_tracer_init (vlib_main_t * vm)
159 | +{
160 | + return 0;
161 | +}
162 | +
163 | +static void
164 | +update_node_runtime (vlib_main_t * vm)
165 | +{
166 | + vlib_node_main_t *nm = 0;
167 | + vlib_main_t **stat_vms = 0, *stat_vm;
168 | + uword i, j;
169 | +
170 | + for (i = 0; i < vec_len (vlib_mains); i++)
171 | + {
172 | + stat_vm = vlib_mains[i];
173 | + if (stat_vm)
174 | + {
175 | + vec_add1 (stat_vms, stat_vm);
176 | + }
177 | + }
178 | +
179 | + /*
180 | + * Barrier sync across stats scraping.
181 | + * Otherwise, the counts will be grossly inaccurate.
182 | + */
183 | + vlib_worker_thread_barrier_sync (vm);
184 | +
185 | + for (j = 0; j < vec_len (stat_vms); j++)
186 | + {
187 | + stat_vm = stat_vms[j];
188 | + nm = &stat_vm->node_main;
189 | +
190 | + for (i = 0; i < vec_len (nm->nodes); i++)
191 | + {
192 | + vlib_node_sync_stats (stat_vm, nm->nodes[i]);
193 | + }
194 | +
195 | + DTRACE_PROBE3 (vpp, vlib_vector_rate_probe,
196 | + stat_vm->cpu_id,
197 | + stat_vm->internal_node_vectors -
198 | + stat_vm->internal_node_vectors_last_clear,
199 | + stat_vm->internal_node_calls -
200 | + stat_vm->internal_node_calls_last_clear);
201 | + }
202 | + vlib_worker_thread_barrier_release (vm);
203 | +
204 | + vec_free (stat_vms);
205 | +}
206 | +
207 | +static uword
208 | +bpf_tracer_process (vlib_main_t * vm, vlib_node_runtime_t * rt,
209 | + vlib_frame_t * f)
210 | +{
211 | + bpf_tracer_main_t *bm = &bpf_tracer_main;
212 | +
213 | + while (1)
214 | + {
215 | + /* update BPF counters */
216 | + update_node_runtime (vm);
217 | +
218 | + /* suspend for required time interval */
219 | + vlib_process_suspend (vm, (f64) bm->update_interval);
220 | + }
221 | + return 0;
222 | +}
223 | +
224 | +VLIB_EARLY_CONFIG_FUNCTION (bpftracer_config, "bpftracer");
225 | +
226 | +VLIB_INIT_FUNCTION (bpf_tracer_init) =
227 | +{
228 | +};
229 | +
230 | +/* *INDENT-OFF* */
231 | +VLIB_REGISTER_NODE (bpf_tracer_collector, static) =
232 | +{
233 | +.function = bpf_tracer_process,
234 | +.name = "bpftracer-process",
235 | +.type = VLIB_NODE_TYPE_PROCESS,
236 | +};
237 | +/* *INDENT-ON* */
238 | +
239 | +#endif
240 | +
241 | +/*
242 | + * fd.io coding-style-patch-verification: ON
243 | + *
244 | + * Local Variables:
245 | + * eval: (c-set-style "gnu")
246 | + * End:
247 | + */
248 | diff --git a/src/vlib/bpf_tracer.h b/src/vlib/bpf_tracer.h
249 | new file mode 100644
250 | index 000000000..50a391379
251 | --- /dev/null
252 | +++ b/src/vlib/bpf_tracer.h
253 | @@ -0,0 +1,42 @@
254 | +/*
255 | + * Copyright (c) 2020 Pantheon.tech and/or its affiliates.
256 | + *
257 | + * Licensed under the Apache License, Version 2.0 (the "License");
258 | + * you may not use this file except in compliance with the License.
259 | + * You may obtain a copy of the License at:
260 | + *
261 | + * http://www.apache.org/licenses/LICENSE-2.0
262 | + *
263 | + * Unless required by applicable law or agreed to in writing, software
264 | + * distributed under the License is distributed on an "AS IS" BASIS,
265 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
266 | + * See the License for the specific language governing permissions and
267 | + * limitations under the License.
268 | + */
269 | +
270 | +#ifndef included_bpf_tracer_h
271 | +#define included_bpf_tracer_h
272 | +
273 | +#define USE_BPF_TRACE
274 | +
275 | +#ifdef USE_BPF_TRACE
276 | +#include
277 | +#include
278 | +
279 | +typedef struct
280 | +{
281 | + /* Update interval */
282 | + u32 update_interval;
283 | +} bpf_tracer_main_t;
284 | +
285 | +#endif
286 | +
287 | +#endif /* included_bpf_tracer_h */
288 | +
289 | +/*
290 | + * fd.io coding-style-patch-verification: ON
291 | + *
292 | + * Local Variables:
293 | + * eval: (c-set-style "gnu")
294 | + * End:
295 | + */
296 | diff --git a/src/vlib/counter.h b/src/vlib/counter.h
297 | index 8a5aed4c1..c3fb97b9e 100644
298 | --- a/src/vlib/counter.h
299 | +++ b/src/vlib/counter.h
300 | @@ -41,6 +41,7 @@
301 | #define included_vlib_counter_h
302 |
303 | #include
304 | +#include
305 |
306 | /** \file
307 |
308 | @@ -82,6 +83,10 @@ vlib_increment_simple_counter (vlib_simple_counter_main_t * cm,
309 |
310 | my_counters = cm->counters[thread_index];
311 | my_counters[index] += increment;
312 | +#ifdef USE_BPF_TRACE
313 | + DTRACE_PROBE3 (vpp, vlib_increment_simple_counters_probe, cm->name, index,
314 | + my_counters[index]);
315 | +#endif
316 | }
317 |
318 | /** Set a simple counter
319 | @@ -228,6 +233,13 @@ vlib_increment_combined_counter (vlib_combined_counter_main_t * cm,
320 |
321 | my_counters[index].packets += n_packets;
322 | my_counters[index].bytes += n_bytes;
323 | +
324 | +#ifdef USE_BPF_TRACE
325 | + DTRACE_PROBE2 (vpp, vlib_increment_combined_counters_packets_probe, index,
326 | + my_counters[index].packets);
327 | + DTRACE_PROBE2 (vpp, vlib_increment_combined_counters_bytes_probe, index,
328 | + my_counters[index].bytes);
329 | +#endif
330 | }
331 |
332 | /** Pre-fetch a per-thread combined counter for the given object index */
333 | diff --git a/src/vlib/drop.c b/src/vlib/drop.c
334 | index e29195ad1..cfd4f6935 100644
335 | --- a/src/vlib/drop.c
336 | +++ b/src/vlib/drop.c
337 | @@ -222,7 +222,11 @@ process_drop_punt (vlib_main_t * vm,
338 |
339 | c_index = counter_index (vm, error[0]);
340 | em->counters[c_index] += count;
341 | -
342 | +#ifdef USE_BPF_TRACE
343 | + DTRACE_PROBE3 (vpp, vlib_error_count_probe,
344 | + em->error_strings_heap[c_index], c_index,
345 | + em->counters[c_index]);
346 | +#endif
347 | vlib_error_elog_count (vm, c_index, count);
348 | }
349 |
350 | diff --git a/src/vlib/error_funcs.h b/src/vlib/error_funcs.h
351 | index ab281ba2e..f3c95d7f8 100644
352 | --- a/src/vlib/error_funcs.h
353 | +++ b/src/vlib/error_funcs.h
354 | @@ -41,6 +41,7 @@
355 | #define included_vlib_error_funcs_h
356 |
357 | #include
358 | +#include
359 |
360 | always_inline void
361 | vlib_error_elog_count (vlib_main_t * vm, uword counter, uword increment)
362 | @@ -65,7 +66,10 @@ vlib_error_count (vlib_main_t * vm, uword node_index,
363 |
364 | ASSERT (counter < vec_len (em->counters));
365 | em->counters[counter] += increment;
366 | -
367 | +#ifdef USE_BPF_TRACE
368 | + DTRACE_PROBE3 (vpp, vlib_error_count_probe, em->error_strings_heap[counter],
369 | + counter, em->counters[counter]);
370 | +#endif
371 | vlib_error_elog_count (vm, counter, increment);
372 | }
373 |
374 | diff --git a/src/vlib/main.c b/src/vlib/main.c
375 | index 2e100b24d..9e250b394 100644
376 | --- a/src/vlib/main.c
377 | +++ b/src/vlib/main.c
378 | @@ -591,6 +591,38 @@ vlib_node_runtime_sync_stats (vlib_main_t * vm,
379 | r->perf_counter0_ticks_since_last_overflow = 0ULL;
380 | r->perf_counter1_ticks_since_last_overflow = 0ULL;
381 | r->perf_counter_vectors_since_last_overflow = 0ULL;
382 | +
383 | +#ifdef USE_BPF_TRACE
384 | + u64 clocks = n->stats_total.clocks - n->stats_last_clear.clocks;
385 | + u64 calls = n->stats_total.calls - n->stats_last_clear.calls;
386 | + u64 vectors = n->stats_total.vectors - n->stats_last_clear.vectors;
387 | + u64 suspends = n->stats_total.suspends - n->stats_last_clear.suspends;
388 | + u64 vectorspercall = (calls > 0) ? ((double) vectors / (double) calls) : 0;
389 | + f64 clocksperx = 0.;
390 | + f64 maxc = (f64) n->stats_total.max_clock;
391 | + u32 maxn = n->stats_total.max_clock_n;
392 | + f64 maxcn =
393 | + (n->stats_total.max_clock_n) ? (f64) n->stats_total.max_clock /
394 | + (f64) maxn : 0.0;
395 | +
396 | + // Clocks per packet, per call or per suspend.
397 | + clocksperx = 0;
398 | + if (vectors > 0)
399 | + clocksperx = (f64) clocks / (f64) vectors;
400 | + else if (calls > 0)
401 | + clocksperx = (f64) clocks / (f64) calls;
402 | + else if (suspends > 0)
403 | + clocksperx = (f64) clocks / (f64) suspends;
404 | +
405 | + DTRACE_PROBE10 (vpp, vlib_node_runtime_sync_stats_probe, n->name, r->node_index, calls, // Calls
406 | + vectors, // Vectors
407 | + suspends, // Suspends
408 | + clocksperx, // Clocks
409 | + vectorspercall, // Vectors/Call
410 | + maxcn, // Max Node Clocks
411 | + maxn, // Vectors at Max
412 | + maxc); // Max Clocks
413 | +#endif
414 | }
415 |
416 | always_inline void __attribute__ ((unused))
417 | diff --git a/src/vlib/node_funcs.h b/src/vlib/node_funcs.h
418 | index 263017d0e..714add51c 100644
419 | --- a/src/vlib/node_funcs.h
420 | +++ b/src/vlib/node_funcs.h
421 | @@ -47,6 +47,7 @@
422 |
423 | #include
424 | #include
425 | +#include
426 |
427 | /** \brief Get vlib node by index.
428 | @warning This function will ASSERT if @c i is out of range.
429 | @@ -1176,6 +1177,11 @@ vlib_node_increment_counter (vlib_main_t * vm, u32 node_index,
430 | vlib_error_main_t *em = &vm->error_main;
431 | u32 node_counter_base_index = n->error_heap_index;
432 | em->counters[node_counter_base_index + counter_index] += increment;
433 | +#ifdef USE_BPF_TRACE
434 | + DTRACE_PROBE2 (vpp, vlib_node_counter_probe,
435 | + node_counter_base_index + counter_index,
436 | + em->counters[node_counter_base_index + counter_index]);
437 | +#endif
438 | }
439 |
440 | /** @brief Create a vlib process
441 | diff --git a/src/vnet/devices/devices.c b/src/vnet/devices/devices.c
442 | index e78c5cbe4..4da65bc44 100644
443 | --- a/src/vnet/devices/devices.c
444 | +++ b/src/vnet/devices/devices.c
445 | @@ -303,7 +303,13 @@ vnet_hw_interface_set_rx_mode (vnet_main_t * vnm, u32 hw_if_index,
446 | rt->enabled_node_state = enabled_node_state;
447 | if (vlib_node_get_state (vm, hw->input_node_index) !=
448 | VLIB_NODE_STATE_DISABLED)
449 | - vlib_node_set_state (vm, hw->input_node_index, enabled_node_state);
450 | + {
451 | + vlib_node_set_state (vm, hw->input_node_index, enabled_node_state);
452 | +#ifdef USE_BPF_TRACE
453 | + DTRACE_PROBE2 (vpp, vnet_hw_interface_set_rx_mode_probe,
454 | + hw_if_index, (u32) enabled_node_state);
455 | +#endif
456 | + }
457 | }
458 |
459 | return 0;
460 | diff --git a/src/vnet/fib/fib_table.c b/src/vnet/fib/fib_table.c
461 | index ec2acc59c..4498ded33 100644
462 | --- a/src/vnet/fib/fib_table.c
463 | +++ b/src/vnet/fib/fib_table.c
464 | @@ -632,7 +632,23 @@ fib_table_entry_path_add2 (u32 fib_index,
465 | fib_table_source_count_inc(fib_table, source);
466 | }
467 | }
468 | -
469 | +#ifdef USE_BPF_TRACE
470 | + for (ii = 0; ii < vec_len(rpaths); ii++)
471 | + {
472 | + DTRACE_PROBE6(vpp, vnet_ip_route_probe,
473 | + 0 /*is_del*/,
474 | + FIB_PROTOCOL_IP6 == prefix->fp_proto /* is_ip6 */,
475 | + fib_index,
476 | + (FIB_PROTOCOL_IP4 == prefix->fp_proto) ?
477 | + prefix->fp_addr.ip4.as_u8 :
478 | + prefix->fp_addr.ip6.as_u8,
479 | + (u32)prefix->fp_len,
480 | + (FIB_PROTOCOL_IP4 == prefix->fp_proto) ?
481 | + rpaths[ii].frp_addr.ip4.as_u8 :
482 | + rpaths[ii].frp_addr.ip6.as_u8
483 | + );
484 | + }
485 | +#endif
486 | return (fib_entry_index);
487 | }
488 |
489 | @@ -651,7 +667,6 @@ fib_table_entry_path_remove2 (u32 fib_index,
490 | fib_node_index_t fib_entry_index;
491 | fib_route_path_t *rpath;
492 | fib_table_t *fib_table;
493 | -
494 | fib_table = fib_table_get(fib_index, prefix->fp_proto);
495 | fib_entry_index = fib_table_lookup_exact_match_i(fib_table, prefix);
496 |
497 | @@ -716,6 +731,24 @@ fib_table_entry_path_remove2 (u32 fib_index,
498 |
499 | fib_entry_unlock(fib_entry_index);
500 | }
501 | +#ifdef USE_BPF_TRACE
502 | + u32 ii;
503 | + for (ii = 0; ii < vec_len(rpaths); ii++)
504 | + {
505 | + DTRACE_PROBE6(vpp, vnet_ip_route_probe,
506 | + 1 /*is_del*/,
507 | + FIB_PROTOCOL_IP6 == prefix->fp_proto /* is_ip6 */,
508 | + fib_index,
509 | + (FIB_PROTOCOL_IP4 == prefix->fp_proto) ?
510 | + prefix->fp_addr.ip4.as_u8 :
511 | + prefix->fp_addr.ip6.as_u8,
512 | + (u32)prefix->fp_len,
513 | + (FIB_PROTOCOL_IP4 == prefix->fp_proto) ?
514 | + rpaths[ii].frp_addr.ip4.as_u8 :
515 | + rpaths[ii].frp_addr.ip6.as_u8
516 | + );
517 | + }
518 | +#endif
519 | }
520 |
521 | void
522 | diff --git a/src/vnet/interface.c b/src/vnet/interface.c
523 | index dfefdbac9..8a32110c5 100644
524 | --- a/src/vnet/interface.c
525 | +++ b/src/vnet/interface.c
526 | @@ -490,6 +490,17 @@ vnet_sw_interface_set_flags_helper (vnet_main_t * vnm, u32 sw_if_index,
527 | si->flags &= ~mask;
528 | si->flags |= flags;
529 |
530 | +#ifdef USE_BPF_TRACE
531 | + u8 *intf_name = 0;
532 | + intf_name =
533 | + format (intf_name, "%U", format_vnet_sw_interface_name, vnm, si,
534 | + si->sw_if_index);
535 | + DTRACE_PROBE3 (vpp, vnet_sw_interface_state_probe, si->sw_if_index,
536 | + (flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) ? 1 : 0,
537 | + intf_name);
538 | + vec_free (intf_name);
539 | +#endif
540 | +
541 | done:
542 | return error;
543 | }
544 | diff --git a/src/vnet/interface_cli.c b/src/vnet/interface_cli.c
545 | index 2e5714c3c..1c9778a16 100644
546 | --- a/src/vnet/interface_cli.c
547 | +++ b/src/vnet/interface_cli.c
548 | @@ -1763,6 +1763,12 @@ set_hw_interface_rx_placement (u32 hw_if_index, u32 queue_id,
549 |
550 | vnet_hw_interface_assign_rx_thread (vnm, hw_if_index, queue_id,
551 | thread_index);
552 | +
553 | +#ifdef USE_BPF_TRACE
554 | + DTRACE_PROBE3 (vpp, vnet_set_hw_interface_rx_placement_probe, hw_if_index,
555 | + thread_index, queue_id);
556 | +#endif
557 | +
558 | vnet_hw_interface_set_rx_mode (vnm, hw_if_index, queue_id, mode);
559 |
560 | return (error);
561 | diff --git a/src/vnet/ip-neighbor/ip_neighbor.c b/src/vnet/ip-neighbor/ip_neighbor.c
562 | index 09b56058f..df3b59c18 100644
563 | --- a/src/vnet/ip-neighbor/ip_neighbor.c
564 | +++ b/src/vnet/ip-neighbor/ip_neighbor.c
565 | @@ -16,7 +16,10 @@
566 | */
567 |
568 | #include
569 | -
570 | +#include
571 | +#ifdef USE_BPF_TRACE
572 | +#include
573 | +#endif
574 | #include
575 | #include
576 | #include
577 | @@ -545,6 +548,13 @@ check_customers:
578 | fib_proto_to_link (fproto),
579 | &ipn->ipn_key->ipnk_ip,
580 | ipn->ipn_key->ipnk_sw_if_index);
581 | +#ifdef USE_BPF_TRACE
582 | + DTRACE_PROBE6 (vpp, vnet_ip_neighbor_probe,
583 | + 0 /* is_del */ , type != IP46_TYPE_IP4 /* is_ipv6 */ ,
584 | + sw_if_index,
585 | + (type == IP46_TYPE_IP4) ? ip->ip4.as_u8 : ip->ip6.as_u8,
586 | + mac->bytes, (u32) flags);
587 | +#endif
588 | return 0;
589 | }
590 |
591 | @@ -572,7 +582,13 @@ ip_neighbor_del (const ip46_address_t * ip, ip46_type_t type, u32 sw_if_index)
592 | return (VNET_API_ERROR_NO_SUCH_ENTRY);
593 |
594 | ip_neighbor_free (ipn);
595 | -
596 | +#ifdef USE_BPF_TRACE
597 | + DTRACE_PROBE6 (vpp, vnet_ip_neighbor_probe,
598 | + 1 /* is_del */ , type != IP46_TYPE_IP4 /* is_ipv6 */ ,
599 | + sw_if_index,
600 | + (type == IP46_TYPE_IP4) ? ip->ip4.as_u8 : ip->ip6.as_u8,
601 | + ipn->ipn_mac.bytes, ipn->ipn_flags);
602 | +#endif
603 | return (0);
604 | }
605 |
606 | diff --git a/src/vnet/ip/ip_interface.c b/src/vnet/ip/ip_interface.c
607 | index 48c20a6cf..d8e62d1ae 100644
608 | --- a/src/vnet/ip/ip_interface.c
609 | +++ b/src/vnet/ip/ip_interface.c
610 | @@ -86,7 +86,11 @@ ip_interface_address_add (ip_lookup_main_t * lm,
611 | (hi != ~0) ? hi : ai;
612 |
613 | *result_if_address_index = ai;
614 | -
615 | +#ifdef USE_BPF_TRACE
616 | + DTRACE_PROBE5 (vpp, vnet_ip_address_probe,
617 | + 0 /* is_del */ , lm->is_ip6, sw_if_index, (u8 *) addr_fib,
618 | + address_length);
619 | +#endif
620 | return (NULL);
621 | }
622 |
623 | @@ -133,6 +137,11 @@ ip_interface_address_del (ip_lookup_main_t * lm,
624 | mhash_unset (&lm->address_to_if_address_index, addr_fib,
625 | /* old_value */ 0);
626 | pool_put (lm->if_address_pool, a);
627 | +#ifdef USE_BPF_TRACE
628 | + DTRACE_PROBE5 (vpp, vnet_ip_address_probe,
629 | + 1 /* is_del */ , lm->is_ip6, sw_if_index, (u8 *) addr_fib,
630 | + address_length);
631 | +#endif
632 | return NULL;
633 | }
634 |
635 | diff --git a/src/vnet/ip/lookup.c b/src/vnet/ip/lookup.c
636 | index 5d4e137fb..bb8924f91 100644
637 | --- a/src/vnet/ip/lookup.c
638 | +++ b/src/vnet/ip/lookup.c
639 | @@ -284,6 +284,7 @@ vnet_ip_route_cmd (vlib_main_t * vm,
640 | if (is_del && 0 == vec_len (rpaths))
641 | {
642 | fib_table_entry_delete (fib_index, &prefixs[i], FIB_SOURCE_CLI);
643 | + // TODO ... DTRACE_PROBE for DPO ???
644 | }
645 | else if (!is_del && 1 == vec_len (dpos))
646 | {
647 | @@ -293,6 +294,7 @@ vnet_ip_route_cmd (vlib_main_t * vm,
648 | FIB_ENTRY_FLAG_EXCLUSIVE,
649 | &dpos[0]);
650 | dpo_reset (&dpos[0]);
651 | + // TODO ... DTRACE_PROBE for DPO ???
652 | }
653 | else if (vec_len (dpos) > 0)
654 | {
655 |
--------------------------------------------------------------------------------
/ONAP-cdnf-integration/CDS-CNF demo.postman_collection.json:
--------------------------------------------------------------------------------
1 | {
2 | "info": {
3 | "_postman_id": "f99ad65b-3ad5-45f9-ba60-34e9016dc12a",
4 | "name": "CDS-CNF demo",
5 | "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
6 | },
7 | "item": [
8 | {
9 | "name": "Bootstrap",
10 | "protocolProfileBehavior": {
11 | "disabledSystemHeaders": {}
12 | },
13 | "request": {
14 | "auth": {
15 | "type": "basic",
16 | "basic": [
17 | {
18 | "key": "password",
19 | "value": "ccsdkapps",
20 | "type": "string"
21 | },
22 | {
23 | "key": "username",
24 | "value": "ccsdkapps",
25 | "type": "string"
26 | }
27 | ]
28 | },
29 | "method": "POST",
30 | "header": [
31 | {
32 | "key": "Content-Type",
33 | "value": "application/json"
34 | },
35 | {
36 | "key": "",
37 | "type": "text",
38 | "value": "",
39 | "disabled": true
40 | }
41 | ],
42 | "body": {
43 | "mode": "raw",
44 | "raw": "{\r\n\"loadModelType\" : true,\r\n\"loadResourceDictionary\" : true,\r\n\"loadCBA\" : false\r\n}"
45 | },
46 | "url": {
47 | "raw": "http://{{bp-ip}}:{{bp-port}}/api/v1/blueprint-model/bootstrap",
48 | "protocol": "http",
49 | "host": [
50 | "{{bp-ip}}"
51 | ],
52 | "port": "{{bp-port}}",
53 | "path": [
54 | "api",
55 | "v1",
56 | "blueprint-model",
57 | "bootstrap"
58 | ]
59 | }
60 | },
61 | "response": [
62 | {
63 | "name": "CDS Bootstrap",
64 | "originalRequest": {
65 | "method": "POST",
66 | "header": [
67 | {
68 | "key": "Content-Type",
69 | "value": "application/json"
70 | },
71 | {
72 | "key": "",
73 | "value": "",
74 | "type": "text",
75 | "disabled": true
76 | }
77 | ],
78 | "body": {
79 | "mode": "raw",
80 | "raw": "{\r\n\"loadModelType\" : false,\r\n\"loadResourceDictionary\" : true,\r\n\"loadCBA\" : false\r\n}"
81 | },
82 | "url": {
83 | "raw": "http://localhost:8081/api/v1/blueprint-model/bootstrap",
84 | "protocol": "http",
85 | "host": [
86 | "localhost"
87 | ],
88 | "port": "8081",
89 | "path": [
90 | "api",
91 | "v1",
92 | "blueprint-model",
93 | "bootstrap"
94 | ]
95 | }
96 | },
97 | "status": "OK",
98 | "code": 200,
99 | "_postman_previewlanguage": "json",
100 | "header": [
101 | {
102 | "key": "X-ONAP-RequestID",
103 | "value": "b73253b6-d2be-4701-bdb2-31fa66b79a01"
104 | },
105 | {
106 | "key": "X-ONAP-InvocationID",
107 | "value": "b1a59296-fcf2-4435-b8de-9a2e9b9f4077"
108 | },
109 | {
110 | "key": "X-ONAP-PartnerName",
111 | "value": "cds-controller"
112 | },
113 | {
114 | "key": "Vary",
115 | "value": "Origin"
116 | },
117 | {
118 | "key": "Vary",
119 | "value": "Access-Control-Request-Method"
120 | },
121 | {
122 | "key": "Vary",
123 | "value": "Access-Control-Request-Headers"
124 | },
125 | {
126 | "key": "Content-Type",
127 | "value": "application/json"
128 | },
129 | {
130 | "key": "Content-Length",
131 | "value": "0"
132 | },
133 | {
134 | "key": "Cache-Control",
135 | "value": "no-cache, no-store, max-age=0, must-revalidate"
136 | },
137 | {
138 | "key": "Pragma",
139 | "value": "no-cache"
140 | },
141 | {
142 | "key": "Expires",
143 | "value": "0"
144 | },
145 | {
146 | "key": "X-Content-Type-Options",
147 | "value": "nosniff"
148 | },
149 | {
150 | "key": "X-Frame-Options",
151 | "value": "DENY"
152 | },
153 | {
154 | "key": "X-XSS-Protection",
155 | "value": "1 ; mode=block"
156 | },
157 | {
158 | "key": "Referrer-Policy",
159 | "value": "no-referrer"
160 | }
161 | ],
162 | "cookie": [],
163 | "body": ""
164 | }
165 | ]
166 | },
167 | {
168 | "name": "Get Blueprints",
169 | "protocolProfileBehavior": {
170 | "disableBodyPruning": true
171 | },
172 | "request": {
173 | "auth": {
174 | "type": "basic",
175 | "basic": [
176 | {
177 | "key": "password",
178 | "value": "ccsdkapps",
179 | "type": "string"
180 | },
181 | {
182 | "key": "username",
183 | "value": "ccsdkapps",
184 | "type": "string"
185 | }
186 | ]
187 | },
188 | "method": "GET",
189 | "header": [
190 | {
191 | "key": "Content-Type",
192 | "value": "application/json"
193 | },
194 | {
195 | "key": "",
196 | "value": "",
197 | "type": "text",
198 | "disabled": true
199 | }
200 | ],
201 | "body": {
202 | "mode": "raw",
203 | "raw": "{\r\n\"loadModelType\" : true,\r\n\"loadResourceDictionary\" : true,\r\n\"loadCBA\" : false\r\n}"
204 | },
205 | "url": {
206 | "raw": "http://{{bp-ip}}:{{bp-port}}/api/v1/blueprint-model",
207 | "protocol": "http",
208 | "host": [
209 | "{{bp-ip}}"
210 | ],
211 | "port": "{{bp-port}}",
212 | "path": [
213 | "api",
214 | "v1",
215 | "blueprint-model"
216 | ]
217 | }
218 | },
219 | "response": [
220 | {
221 | "name": "CDS Bootstrap",
222 | "originalRequest": {
223 | "method": "POST",
224 | "header": [
225 | {
226 | "key": "Content-Type",
227 | "value": "application/json"
228 | },
229 | {
230 | "key": "",
231 | "value": "",
232 | "type": "text",
233 | "disabled": true
234 | }
235 | ],
236 | "body": {
237 | "mode": "raw",
238 | "raw": "{\r\n\"loadModelType\" : false,\r\n\"loadResourceDictionary\" : true,\r\n\"loadCBA\" : false\r\n}"
239 | },
240 | "url": {
241 | "raw": "http://localhost:8081/api/v1/blueprint-model/bootstrap",
242 | "protocol": "http",
243 | "host": [
244 | "localhost"
245 | ],
246 | "port": "8081",
247 | "path": [
248 | "api",
249 | "v1",
250 | "blueprint-model",
251 | "bootstrap"
252 | ]
253 | }
254 | },
255 | "status": "OK",
256 | "code": 200,
257 | "_postman_previewlanguage": "json",
258 | "header": [
259 | {
260 | "key": "X-ONAP-RequestID",
261 | "value": "b73253b6-d2be-4701-bdb2-31fa66b79a01"
262 | },
263 | {
264 | "key": "X-ONAP-InvocationID",
265 | "value": "b1a59296-fcf2-4435-b8de-9a2e9b9f4077"
266 | },
267 | {
268 | "key": "X-ONAP-PartnerName",
269 | "value": "cds-controller"
270 | },
271 | {
272 | "key": "Vary",
273 | "value": "Origin"
274 | },
275 | {
276 | "key": "Vary",
277 | "value": "Access-Control-Request-Method"
278 | },
279 | {
280 | "key": "Vary",
281 | "value": "Access-Control-Request-Headers"
282 | },
283 | {
284 | "key": "Content-Type",
285 | "value": "application/json"
286 | },
287 | {
288 | "key": "Content-Length",
289 | "value": "0"
290 | },
291 | {
292 | "key": "Cache-Control",
293 | "value": "no-cache, no-store, max-age=0, must-revalidate"
294 | },
295 | {
296 | "key": "Pragma",
297 | "value": "no-cache"
298 | },
299 | {
300 | "key": "Expires",
301 | "value": "0"
302 | },
303 | {
304 | "key": "X-Content-Type-Options",
305 | "value": "nosniff"
306 | },
307 | {
308 | "key": "X-Frame-Options",
309 | "value": "DENY"
310 | },
311 | {
312 | "key": "X-XSS-Protection",
313 | "value": "1 ; mode=block"
314 | },
315 | {
316 | "key": "Referrer-Policy",
317 | "value": "no-referrer"
318 | }
319 | ],
320 | "cookie": [],
321 | "body": ""
322 | }
323 | ]
324 | },
325 | {
326 | "name": "Delete Blueprint Model",
327 | "protocolProfileBehavior": {
328 | "disabledSystemHeaders": {}
329 | },
330 | "request": {
331 | "auth": {
332 | "type": "basic",
333 | "basic": [
334 | {
335 | "key": "password",
336 | "value": "ccsdkapps",
337 | "type": "string"
338 | },
339 | {
340 | "key": "username",
341 | "value": "ccsdkapps",
342 | "type": "string"
343 | }
344 | ]
345 | },
346 | "method": "DELETE",
347 | "header": [
348 | {
349 | "key": "Content-Type",
350 | "value": "application/json",
351 | "disabled": true
352 | },
353 | {
354 | "key": "",
355 | "type": "text",
356 | "value": "",
357 | "disabled": true
358 | }
359 | ],
360 | "url": {
361 | "raw": "http://{{bp-ip}}:{{bp-port}}/api/v1/blueprint-model/name/Firewall-CNF-configuration-example/version/1.0.0",
362 | "protocol": "http",
363 | "host": [
364 | "{{bp-ip}}"
365 | ],
366 | "port": "{{bp-port}}",
367 | "path": [
368 | "api",
369 | "v1",
370 | "blueprint-model",
371 | "name",
372 | "Firewall-CNF-configuration-example",
373 | "version",
374 | "1.0.0"
375 | ]
376 | },
377 | "description": "Delete a blueprint model identified by its name and version from CDS."
378 | },
379 | "response": [
380 | {
381 | "name": "CDS Bootstrap",
382 | "originalRequest": {
383 | "method": "POST",
384 | "header": [
385 | {
386 | "key": "Content-Type",
387 | "value": "application/json"
388 | },
389 | {
390 | "key": "",
391 | "value": "",
392 | "type": "text",
393 | "disabled": true
394 | }
395 | ],
396 | "body": {
397 | "mode": "raw",
398 | "raw": "{\r\n\"loadModelType\" : false,\r\n\"loadResourceDictionary\" : true,\r\n\"loadCBA\" : false\r\n}"
399 | },
400 | "url": {
401 | "raw": "http://localhost:8081/api/v1/blueprint-model/bootstrap",
402 | "protocol": "http",
403 | "host": [
404 | "localhost"
405 | ],
406 | "port": "8081",
407 | "path": [
408 | "api",
409 | "v1",
410 | "blueprint-model",
411 | "bootstrap"
412 | ]
413 | }
414 | },
415 | "status": "OK",
416 | "code": 200,
417 | "_postman_previewlanguage": "json",
418 | "header": [
419 | {
420 | "key": "X-ONAP-RequestID",
421 | "value": "b73253b6-d2be-4701-bdb2-31fa66b79a01"
422 | },
423 | {
424 | "key": "X-ONAP-InvocationID",
425 | "value": "b1a59296-fcf2-4435-b8de-9a2e9b9f4077"
426 | },
427 | {
428 | "key": "X-ONAP-PartnerName",
429 | "value": "cds-controller"
430 | },
431 | {
432 | "key": "Vary",
433 | "value": "Origin"
434 | },
435 | {
436 | "key": "Vary",
437 | "value": "Access-Control-Request-Method"
438 | },
439 | {
440 | "key": "Vary",
441 | "value": "Access-Control-Request-Headers"
442 | },
443 | {
444 | "key": "Content-Type",
445 | "value": "application/json"
446 | },
447 | {
448 | "key": "Content-Length",
449 | "value": "0"
450 | },
451 | {
452 | "key": "Cache-Control",
453 | "value": "no-cache, no-store, max-age=0, must-revalidate"
454 | },
455 | {
456 | "key": "Pragma",
457 | "value": "no-cache"
458 | },
459 | {
460 | "key": "Expires",
461 | "value": "0"
462 | },
463 | {
464 | "key": "X-Content-Type-Options",
465 | "value": "nosniff"
466 | },
467 | {
468 | "key": "X-Frame-Options",
469 | "value": "DENY"
470 | },
471 | {
472 | "key": "X-XSS-Protection",
473 | "value": "1 ; mode=block"
474 | },
475 | {
476 | "key": "Referrer-Policy",
477 | "value": "no-referrer"
478 | }
479 | ],
480 | "cookie": [],
481 | "body": ""
482 | }
483 | ]
484 | },
485 | {
486 | "name": "Enrich Blueprint",
487 | "protocolProfileBehavior": {
488 | "disabledSystemHeaders": {}
489 | },
490 | "request": {
491 | "auth": {
492 | "type": "basic",
493 | "basic": [
494 | {
495 | "key": "username",
496 | "value": "ccsdkapps",
497 | "type": "string"
498 | },
499 | {
500 | "key": "password",
501 | "value": "ccsdkapps",
502 | "type": "string"
503 | },
504 | {
505 | "key": "showPassword",
506 | "value": false,
507 | "type": "boolean"
508 | }
509 | ]
510 | },
511 | "method": "POST",
512 | "header": [
513 | {
514 | "key": "Accept",
515 | "type": "text",
516 | "value": "application/json",
517 | "disabled": true
518 | },
519 | {
520 | "key": "Accept-Encoding",
521 | "type": "text",
522 | "value": "gzip,deflate",
523 | "disabled": true
524 | },
525 | {
526 | "key": "Referer",
527 | "type": "text",
528 | "value": "http://84.39.39.116:30497/blueprint",
529 | "disabled": true
530 | },
531 | {
532 | "key": "Origin",
533 | "type": "text",
534 | "value": "http://84.39.39.116:30497",
535 | "disabled": true
536 | }
537 | ],
538 | "body": {
539 | "mode": "formdata",
540 | "formdata": [
541 | {
542 | "key": "file",
543 | "contentType": "application/zip",
544 | "type": "file",
545 | "src": "/home/dev/data/projects/onap/cds-cnf-integration/cba.zip"
546 | }
547 | ]
548 | },
549 | "url": {
550 | "raw": "http://{{bp-ip}}:{{bp-port}}/api/v1/blueprint-model/enrich",
551 | "protocol": "http",
552 | "host": [
553 | "{{bp-ip}}"
554 | ],
555 | "port": "{{bp-port}}",
556 | "path": [
557 | "api",
558 | "v1",
559 | "blueprint-model",
560 | "enrich"
561 | ]
562 | }
563 | },
564 | "response": []
565 | },
566 | {
567 | "name": "Save Blueprint",
568 | "request": {
569 | "auth": {
570 | "type": "basic",
571 | "basic": [
572 | {
573 | "key": "password",
574 | "value": "ccsdkapps",
575 | "type": "string"
576 | },
577 | {
578 | "key": "username",
579 | "value": "ccsdkapps",
580 | "type": "string"
581 | }
582 | ]
583 | },
584 | "method": "POST",
585 | "header": [
586 | {
587 | "key": "Content-Type",
588 | "value": "application/json"
589 | },
590 | {
591 | "key": "",
592 | "type": "text",
593 | "value": "",
594 | "disabled": true
595 | }
596 | ],
597 | "body": {
598 | "mode": "formdata",
599 | "formdata": [
600 | {
601 | "key": "file",
602 | "contentType": "application/zip",
603 | "type": "file",
604 | "src": "/home/dev/data/projects/onap/cds-cnf-integration/cba-enriched.zip"
605 | }
606 | ]
607 | },
608 | "url": {
609 | "raw": "http://{{bp-ip}}:{{bp-port}}/api/v1/blueprint-model",
610 | "protocol": "http",
611 | "host": [
612 | "{{bp-ip}}"
613 | ],
614 | "port": "{{bp-port}}",
615 | "path": [
616 | "api",
617 | "v1",
618 | "blueprint-model"
619 | ]
620 | }
621 | },
622 | "response": [
623 | {
624 | "name": "CDS Bootstrap",
625 | "originalRequest": {
626 | "method": "POST",
627 | "header": [
628 | {
629 | "key": "Content-Type",
630 | "value": "application/json"
631 | },
632 | {
633 | "key": "",
634 | "value": "",
635 | "type": "text",
636 | "disabled": true
637 | }
638 | ],
639 | "body": {
640 | "mode": "raw",
641 | "raw": "{\r\n\"loadModelType\" : false,\r\n\"loadResourceDictionary\" : true,\r\n\"loadCBA\" : false\r\n}"
642 | },
643 | "url": {
644 | "raw": "http://localhost:8081/api/v1/blueprint-model/bootstrap",
645 | "protocol": "http",
646 | "host": [
647 | "localhost"
648 | ],
649 | "port": "8081",
650 | "path": [
651 | "api",
652 | "v1",
653 | "blueprint-model",
654 | "bootstrap"
655 | ]
656 | }
657 | },
658 | "status": "OK",
659 | "code": 200,
660 | "_postman_previewlanguage": "json",
661 | "header": [
662 | {
663 | "key": "X-ONAP-RequestID",
664 | "value": "b73253b6-d2be-4701-bdb2-31fa66b79a01"
665 | },
666 | {
667 | "key": "X-ONAP-InvocationID",
668 | "value": "b1a59296-fcf2-4435-b8de-9a2e9b9f4077"
669 | },
670 | {
671 | "key": "X-ONAP-PartnerName",
672 | "value": "cds-controller"
673 | },
674 | {
675 | "key": "Vary",
676 | "value": "Origin"
677 | },
678 | {
679 | "key": "Vary",
680 | "value": "Access-Control-Request-Method"
681 | },
682 | {
683 | "key": "Vary",
684 | "value": "Access-Control-Request-Headers"
685 | },
686 | {
687 | "key": "Content-Type",
688 | "value": "application/json"
689 | },
690 | {
691 | "key": "Content-Length",
692 | "value": "0"
693 | },
694 | {
695 | "key": "Cache-Control",
696 | "value": "no-cache, no-store, max-age=0, must-revalidate"
697 | },
698 | {
699 | "key": "Pragma",
700 | "value": "no-cache"
701 | },
702 | {
703 | "key": "Expires",
704 | "value": "0"
705 | },
706 | {
707 | "key": "X-Content-Type-Options",
708 | "value": "nosniff"
709 | },
710 | {
711 | "key": "X-Frame-Options",
712 | "value": "DENY"
713 | },
714 | {
715 | "key": "X-XSS-Protection",
716 | "value": "1 ; mode=block"
717 | },
718 | {
719 | "key": "Referrer-Policy",
720 | "value": "no-referrer"
721 | }
722 | ],
723 | "cookie": [],
724 | "body": ""
725 | }
726 | ]
727 | },
728 | {
729 | "name": "Workflow(action) apply-firewall-rule (Deny Traffic)",
730 | "request": {
731 | "auth": {
732 | "type": "basic",
733 | "basic": [
734 | {
735 | "key": "username",
736 | "value": "ccsdkapps",
737 | "type": "string"
738 | },
739 | {
740 | "key": "password",
741 | "value": "ccsdkapps",
742 | "type": "string"
743 | },
744 | {
745 | "key": "showPassword",
746 | "value": false,
747 | "type": "boolean"
748 | }
749 | ]
750 | },
751 | "method": "POST",
752 | "header": [
753 | {
754 | "key": "Accept",
755 | "type": "text",
756 | "value": "application/json",
757 | "disabled": true
758 | },
759 | {
760 | "key": "Accept-Encoding",
761 | "type": "text",
762 | "value": "gzip,deflate",
763 | "disabled": true
764 | },
765 | {
766 | "key": "Referer",
767 | "type": "text",
768 | "value": "http://84.39.39.116:30497/blueprint",
769 | "disabled": true
770 | },
771 | {
772 | "key": "Origin",
773 | "type": "text",
774 | "value": "http://84.39.39.116:30497",
775 | "disabled": true
776 | }
777 | ],
778 | "body": {
779 | "mode": "raw",
780 | "raw": "{\n\t\"actionIdentifiers\": {\n\t\t\"mode\": \"sync\",\n\t\t\"blueprintName\": \"Firewall-CNF-configuration-example\",\n\t\t\"blueprintVersion\": \"1.0.0\",\n\t\t\"actionName\": \"apply-firewall-rule\"\n\t},\n\t\"payload\": {\n\t\t\"apply-firewall-rule-request\": {\n\t\t\t\"cnf-rest-url\": \"http://vpp-agent:{{vppagent-port}}\",\n\t\t\t\"firewall_action\": \"DENY\",\n \"traffic_destination_network\": \"10.12.0.1/32\"\n\t\t}\n\t},\n\t\"commonHeader\": {\n\t\t\"subRequestId\": \"143748f9-3cd5-4910-81c9-a4601ff2ea58\",\n\t\t\"requestId\": \"e5eb1f1e-3386-435d-b290-d49d8af8db4c\",\n\t\t\"originatorId\": \"SDNC_DG\"\n\t}\n}",
781 | "options": {
782 | "raw": {
783 | "language": "json"
784 | }
785 | }
786 | },
787 | "url": {
788 | "raw": "http://{{bp-ip}}:{{bp-port}}/api/v1/execution-service/process",
789 | "protocol": "http",
790 | "host": [
791 | "{{bp-ip}}"
792 | ],
793 | "port": "{{bp-port}}",
794 | "path": [
795 | "api",
796 | "v1",
797 | "execution-service",
798 | "process"
799 | ]
800 | }
801 | },
802 | "response": []
803 | },
804 | {
805 | "name": "Workflow(action) apply-firewall-rule (Permit Traffic)",
806 | "request": {
807 | "auth": {
808 | "type": "basic",
809 | "basic": [
810 | {
811 | "key": "username",
812 | "value": "ccsdkapps",
813 | "type": "string"
814 | },
815 | {
816 | "key": "password",
817 | "value": "ccsdkapps",
818 | "type": "string"
819 | },
820 | {
821 | "key": "showPassword",
822 | "value": false,
823 | "type": "boolean"
824 | }
825 | ]
826 | },
827 | "method": "POST",
828 | "header": [
829 | {
830 | "key": "Accept",
831 | "type": "text",
832 | "value": "application/json",
833 | "disabled": true
834 | },
835 | {
836 | "key": "Accept-Encoding",
837 | "type": "text",
838 | "value": "gzip,deflate",
839 | "disabled": true
840 | },
841 | {
842 | "key": "Referer",
843 | "type": "text",
844 | "value": "http://84.39.39.116:30497/blueprint",
845 | "disabled": true
846 | },
847 | {
848 | "key": "Origin",
849 | "type": "text",
850 | "value": "http://84.39.39.116:30497",
851 | "disabled": true
852 | }
853 | ],
854 | "body": {
855 | "mode": "raw",
856 | "raw": "{\n\t\"actionIdentifiers\": {\n\t\t\"mode\": \"sync\",\n\t\t\"blueprintName\": \"Firewall-CNF-configuration-example\",\n\t\t\"blueprintVersion\": \"1.0.0\",\n\t\t\"actionName\": \"apply-firewall-rule\"\n\t},\n\t\"payload\": {\n\t\t\"apply-firewall-rule-request\": {\n\t\t\t\"cnf-rest-url\": \"http://vpp-agent:{{vppagent-port}}\",\n\t\t\t\"firewall_action\": \"PERMIT\",\n \"traffic_destination_network\": \"10.12.0.1/32\"\n\t\t}\n\t},\n\t\"commonHeader\": {\n\t\t\"subRequestId\": \"143748f9-3cd5-4910-81c9-a4601ff2ea58\",\n\t\t\"requestId\": \"e5eb1f1e-3386-435d-b290-d49d8af8db4c\",\n\t\t\"originatorId\": \"SDNC_DG\"\n\t}\n}",
857 | "options": {
858 | "raw": {
859 | "language": "json"
860 | }
861 | }
862 | },
863 | "url": {
864 | "raw": "http://{{bp-ip}}:{{bp-port}}/api/v1/execution-service/process",
865 | "protocol": "http",
866 | "host": [
867 | "{{bp-ip}}"
868 | ],
869 | "port": "{{bp-port}}",
870 | "path": [
871 | "api",
872 | "v1",
873 | "execution-service",
874 | "process"
875 | ]
876 | }
877 | },
878 | "response": []
879 | },
880 | {
881 | "name": "CNF - VPPAgent - Get configuration",
882 | "protocolProfileBehavior": {
883 | "disableBodyPruning": true
884 | },
885 | "request": {
886 | "method": "GET",
887 | "header": [],
888 | "body": {
889 | "mode": "raw",
890 | "raw": ""
891 | },
892 | "url": {
893 | "raw": "http://{{vppagent-ip}}:{{vppagent-port}}/configuration",
894 | "protocol": "http",
895 | "host": [
896 | "{{vppagent-ip}}"
897 | ],
898 | "port": "{{vppagent-port}}",
899 | "path": [
900 | "configuration"
901 | ]
902 | }
903 | },
904 | "response": []
905 | },
906 | {
907 | "name": "CNF - VPPAgent - Clean config",
908 | "request": {
909 | "method": "PUT",
910 | "header": [],
911 | "body": {
912 | "mode": "raw",
913 | "raw": "netallocConfig: {}\nlinuxConfig: {}\nvppConfig: {}\n"
914 | },
915 | "url": {
916 | "raw": "http://{{vppagent-ip}}:{{vppagent-port}}/configuration?replace=true",
917 | "protocol": "http",
918 | "host": [
919 | "{{vppagent-ip}}"
920 | ],
921 | "port": "{{vppagent-port}}",
922 | "path": [
923 | "configuration"
924 | ],
925 | "query": [
926 | {
927 | "key": "replace",
928 | "value": "true"
929 | }
930 | ]
931 | }
932 | },
933 | "response": []
934 | }
935 | ],
936 | "event": [
937 | {
938 | "listen": "prerequest",
939 | "script": {
940 | "type": "text/javascript",
941 | "exec": [
942 | ""
943 | ]
944 | }
945 | },
946 | {
947 | "listen": "test",
948 | "script": {
949 | "type": "text/javascript",
950 | "exec": [
951 | ""
952 | ]
953 | }
954 | }
955 | ],
956 | "variable": [
957 | {
958 | "key": "bp-ip",
959 | "value": "localhost"
960 | },
961 | {
962 | "key": "bp-port",
963 | "value": "8000"
964 | },
965 | {
966 | "key": "vppagent-ip",
967 | "value": "172.28.0.2"
968 | },
969 | {
970 | "key": "vppagent-port",
971 | "value": "9191"
972 | }
973 | ]
974 | }
--------------------------------------------------------------------------------