Vector Packet Processing 104: gRPC & REST
Welcome back to our Vector Packet Processing implementation guide, Part 4.
Today, we will go through the essentials of gRPC and REST and introduce their core concepts, while introducing one missing functionality into our VPP build. This part will also introduce the open-source GoVPP, Go language bindings for binary API – VPP management.
The Issue
Natively, VPP does not include a gRPC / RESTful interface. PANTHEON.tech has developed an internal solution, which utilizes a gRPC-gateway to VPP, using GoVPP. It is called VPP-RPC, through which you can now connect to VPP using a REST client.
In case you are interested in this solution, please contact us via our website.
Introduction
First and foremost, here are the terms that you will come across in this guide:
- gRPC (Remote Procedure Calls) is a remote procedure call (RPC) system initially developed by Google. It uses HTTP/2 for transport, protocol buffers as the interface description language, and provides features such as authentication, bidirectional streaming and flow control, blocking or non-blocking bindings, and cancellation and timeouts. It generates cross-platform client and server bindings for many programming-languages.
- gRPC-gateway (GRPC-GW) is a plugin of protobuf. It reads the gRPC service definition and generates a reverse-proxy server which translates a RESTful JSON API into gRPC. This server is generated according to custom options in your gRPC definition.
- VPP-Agent is aset of VPP-specific plugins that interact with Ligato, in order to access services within the same cloud. VPP Agent provides VPP functionality to client apps through a VPP model-driven API
- VPP-RPC is our new RESTful VPP service. It utilizes gRPC & gRPC-gateway as 2 separate processes, in order to facilitate communication with VPP through GoVPP.
JSON message sequence
gRPC gateway exposes the REST service, for which there is no built-in support in VPP. By using gRPC-gateway and gRPC server services, the VPP API is available through gRPC and REST at the same time. Both services use generated models from VPP binary APIs, therefore exposing both APIs is easy enough to include both. It is up to the user to choose, which mechanism they will use.
When exchanging data between a browser and a server, the data can only be text. Any JavaScript object can be converted into a JSON and sent to the server. This allows us to process data as JavaScript objects, while avoiding complicated translations and parsing issues.
The sequence diagram below describes the path the original JSON message takes in our solution:
- The Client sends a HTTP request to GRPC-GW
- GRPC-GW transforms the JSON into protobuf message & sends it to the gRPC server
- Each RPC has a go method handling its logic. For unary RPCs, this simply means copying the protobuf message into the corresponding VPP message structure and passing it to GoVPP binary API
- GoVPP eventually passes the message to the underlying VPP binary API, where the desired functionality is executed
VPP API build process
The figure below describes the build process for a single VPP API. Lets see what needs to happen for a tap API:
VPP APIs are defined in /usr/share/VPP/api/ which is accessible after installing VPP. The Go package tap is a generated via the VPP Agent binary API of the ‘tap’ VPP module. It is generated from this file: tap.api.json.
This file will drive the creation of all 3 building blocks:
- GoVPP’s binapi-generator generates the GoVPP file tap.ba.go
- vpp-rpc-protogen generates tap.proto, which contains the gRPC messages and services, including the URL for each RPC
- protoc’s go plugin will compile the proto file and create a gRPC stub tap.pb.go, containing client & server interfaces that define RPC methods and protobuf message structs.
- Vpp-rpc-implementor will generate the code that implements the TapServer interface – the actual RPC methods calling GoVPP APIs – in Tap.server.go file.
- protoc’s gRPC-gateway plugin will compile the proto file and create the reverse proxy tap.pb.gw.go. We don’t have to touch this file further.
Running the examples
To run all the above, we need to make sure all these processes are running:
- VPP service
-
gRPC server (needs root privileges)
sudo vpp-rpc-server
-
gRPC gateway
vpp-rpc-gateway
Running a simple request using Curl
If we want to invoke the API we have created, we can use Curl. Vpe will require an URL (vpe/showversion/request), which will map the above mentioned API to VPP’s binary API. We will now use Curl to POST a request to a default address of localhost:8080:
curl -H "Content-Type: application/json" -X POST 127.0.0.1:8080/Vpe/ShowVersion/request --silent {"Retval":0,"Program":"dnBlAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=","Version":"MTguMDctcmMwfjEyOC1nNmYxYzQ4ZAAAAAAAAAAAAAA=", "BuildDate":"xaB0IG3DoWogIDMgMTQ6MTA6NTQgQ0VTVCAyMDE4AAA=", "BuildDirectory":"L2hvbWUvcGFsby92cHA"}
The decoded reply says:
{ "Retval": 0, "Program": "vpe", "Version": "18.07-rc0~128-g6f1c48d", "BuildDate": "Thu May 3 14:10:54 CEST 2018", "BuildDirectory": "/home/user/vpp" }
Postman collection
We provide a Postman collection within our service, which serves as a starting point for users with our solution. The collection created in the vpp-rpc repository, tests/vpp-rpc.postman_collection.json path, contains various requests and subsequent tests to the Tap module.
Performance analysis in Curl
Curl can give us detailed timing analysis of a request’s performance. If we run the previous request 100 times, the summary times (in milliseconds) we get usually are:
mean=4.82364000000000000 min=1.047 max=23.070 average rr per_sec=207.31232015656226418223 average rr per_min=12438.73920939373585093414 average rr per_hour=746324.35256362415105604895
Judging from the graph below, we see that most of the requests take well below the average mark. Profiling our solution, we’ve found the reason for the anomalies (above 10ms) to be caused by GoVPP itself when waiting on the reply from VPP. This behavior is well documented on GoVPP wiki. We can conclude our solution closely mirrors the performance of the synchronous GoVPP APIs.
Here is the unary RPC total time in ms:
In conclusion, we have introduced ourselves to the concepts of gRPC and have run our VPP API + GoVPP build, with a REST service feature. Furthermore, we have shown you our in-house solution VPP-RPC, which facilitates the connection between the API and GoVPP.
If you would like to inquire about this solution, please contact us for more information.
In the last part of this series, we will take a closer look at the gNMI service and how we can benefit from it.
You can contact us at https://pantheon.tech/
Explore our Pantheon GitHub.
Watch our YouTube Channel.