FD.io VPP
v21.10.1-2-g0a485f517
Vector Packet Processing
|
The VPP binary API is a message passing API. The VPP API language is used to define a RPC interface between VPP and its control plane. The API messages supports shared memory transport and Unix domain sockets (SOCK_STREAM).
The wire format is essentially that of a network formatted (big-endian) packed C struct.
The VPP API compiler is located in src/tools/vppapigen and can currently compile to JSON or C (used by the VPP binary itself).
There are 3 types of message exchanges:
A message from a client must include the 'client_index', an opaque cookie identifying the sender, and a 'context' field to let the client match request with reply.
An example of a message definition. The client sends the show_version request, the server replies with the show_version_reply.
The client_index and context fields are required in all requests. The context is returned by the server and is used by the client to match up request and reply messages.
The flags are not used by the clients, but have special meaning for some of the tracing and debugging of the API. The autoreply flag is a shorthand for a reply message with just a retval field.
The option word is used to specify meta information. The only current use is to specify a semantic version of the .api file itself.
Example:
New user defined types are defined just like messages. A typedef has two forms. It can either define an alias for a different type (or array).
Example:
Where the above defines two new types vl_api_ip4_address_t and vl_api_ip6_address_t. These are aliases for the underlying u8 array.
In the other form, it is used to specify an abstract data type.
Where the new type vl_api_address_t
You can use definitions from other .api files by importing them. To import another .api's definitions, you add an import statement to the top of your file:
import "vnet/ip/ip_types.api";
By default you can only use definitions from directly imported .api files.
The API compiler searches for imported files in a set of directories specified on the API compiler command line using the –includedir flag.
The API language uses C style comments.
Enums are similar to enums in C.
Every enum definition must contain a constant that maps to zero as its first element. This is because:
There must be a zero value, so that we can use 0 as a numeric default value. The zero value needs to be the first element.
As in C, enums can be used as flags or just as numbers. The on-wire, and in memory representation size of an enum can be specified. Not all language bindings will support that. The default size is 4 (u32).
Example
Which generates the vl_api_ip_neighbor_flags_t in the C binding. In Python that is represented as an IntFlag object VppEnum.vl_api_ip_neighbor_flags_t.
The service statement defines the relationship between messages. For request/response and dump/details messages it ties the request with the reply. For events, it specifies which events that can be received for a given want_* call.
Example:
Which states that the request want_interface_events returns a want_interface_events_reply and if enabled the client will receive sw_interface_event messages whenever interface states changes.
.api type | size | C type | Python type |
---|---|---|---|
i8 | 1 | i8 | int |
u8 | 1 | u8 | int |
i16 | 2 | i16 | int |
u16 | 2 | u16 | int |
i32 | 4 | i32 | int |
u32 | 4 | u32 | int |
i64 | 8 | i64 | int |
u64 | 8 | u64 | int |
f64 | 8 | f64 | float |
bool | 1 | bool | boolean |
string | variable | vl_api_string_t | str |
.api type | size | C type | Python type |
---|---|---|---|
vl_api_address_t | 20 | vl_api_address_t | ‘<class 'ipaddress.IPv4Address’> or <class 'ipaddress.IPv6Address'></td> </tr> <tr class="markdownTableRowEven"> <td class="markdownTableBodyNone"> vl_api_ip4_address_t</td> <td class="markdownTableBodyNone"> 4</td> <td class="markdownTableBodyNone"> vl_api_ip4_address_t</td> <td class="markdownTableBodyNone"> <class 'ipaddress.IPv4Address'></td> </tr> <tr class="markdownTableRowOdd"> <td class="markdownTableBodyNone"> vl_api_ip6_address_t</td> <td class="markdownTableBodyNone"> 16</td> <td class="markdownTableBodyNone"> vl_api_ip6_address_t</td> <td class="markdownTableBodyNone"> <class 'ipaddress.IPv6Address'></td> </tr> <tr class="markdownTableRowEven"> <td class="markdownTableBodyNone"> vl_api_prefix_t</td> <td class="markdownTableBodyNone"> 21</td> <td class="markdownTableBodyNone"> vl_api_prefix_t</td> <td class="markdownTableBodyNone"> <class 'ipaddress.IPv4Network'> or <class 'ipaddress.IPv6Network'></td> </tr> <tr class="markdownTableRowOdd"> <td class="markdownTableBodyNone"> vl_api_ip4_prefix_t</td> <td class="markdownTableBodyNone"> 5</td> <td class="markdownTableBodyNone"> vl_api_ip4_prefix_t</td> <td class="markdownTableBodyNone"> <class 'ipaddress.IPv4Network'></td> </tr> <tr class="markdownTableRowEven"> <td class="markdownTableBodyNone"> vl_api_ip6_prefix_t</td> <td class="markdownTableBodyNone"> 17</td> <td class="markdownTableBodyNone"> vl_api_ip6_prefix_t</td> <td class="markdownTableBodyNone"> <class 'ipaddress.IPv6Network'></td> </tr> <tr class="markdownTableRowOdd"> <td class="markdownTableBodyNone"> vl_api_ip4_address_with_prefix_t</td> <td class="markdownTableBodyNone"> 5</td> <td class="markdownTableBodyNone"> vl_api_ip4_address_with_prefix_t</td> <td class="markdownTableBodyNone"> <class 'ipaddress.IPv4Interface'></td> </tr> <tr class="markdownTableRowEven"> <td class="markdownTableBodyNone"> vl_api_ip6_address_with_prefix_t</td> <td class="markdownTableBodyNone"> 17</td> <td class="markdownTableBodyNone"> vl_api_ip6_address_with_prefix_t</td> <td class="markdownTableBodyNone"> <class 'ipaddress.IPv6Interface'>` |
.api type | size | C type | Python type |
---|---|---|---|
vl_api_mac_address_t | 6 | vl_api_mac_address_t | ‘class 'vpp_papi.MACAddress’>` |
.api type | size | C type | Python type |
---|---|---|---|
vl_api_interface_index_t | 4 | vl_api_interface_index_t | int |
A byte string with a maximum length of 64:
Before the "string" type was added, text string were defined like this. The implications of that was the user would have to know if the field represented a \0 ended C-string or a fixed length byte string. The wire format of the 'string' type is a u32 length
An IPv4 or IPv6 address was previously defined like:
Which made it hard for language bindings to represent the address as anything but a byte string. The new explicit address types are shown above.
The VPP API compiler currently has two output modules. One generating JSON and one generating C header files that are directly used by the VPP infrastructure and plugins.
The C/C++, Python, Go Lua, and Java language bindings are generated based on the JSON files.