-
Notifications
You must be signed in to change notification settings - Fork 707
VPP How_to_Create_a_VPP_binary_control_plane_API
- 1 Intro
- 2 Additions to vpp/api/vpe.api
- 3 Changes to vpp/vpp/api.c
- 4 Changes to vpp/api/custom_dump.c
- 5 Changes to vppt/vat/api_format.c
We need to modify four primary files to add a new binary control-plane API.
- vpp/api/vpe.api
- vpp/api/api.c
- vpp/api/custom_dump.c
- vpp/vat/api_format.c
I'll describe each one using the set interface l2 bridge command as an example.
While learning about this specific CLI command, I used cscope to search for the command, using "Find this text string" set to set interface l2 bridge which led me to the file open-repo/vnet/vnet/l2/l2_input.c where I traced its operation.
Note: In some version, the above files will be available in ~/vpp/src/vpp/api/
Ex:
ubuntu@ip-172-31-78-63:~/vpp/src/vpp/api$ ls vpe.api api.c custom_dump.c api_format.c
api.c api_format.c custom_dump.c vpe.api
ubuntu@ip-172-31-78-63:~/vpp/src/vpp/api$
The first step: determine the parameters the API will need passed to it.
Based on the CLI command "set interface l2 bridge [] [bvi], there are two required parameters and two optional parameters.
- : In VPE, an ASCII interface name is converted to unsigned 32-bit interface index number and from inspecting existing code, we'll name the field rx_sw_if_index
- : this is a numeric and convention calls this field bd_id which is 32 bits
- : this is an optional numeric value internally specified as a 32-bit value which defaults to 0
- bvi: is a flag to indicate this is a "Bridged Virtual Interface" which although is a simple boolean, the underlying function calls treat as an unsigned 32-bit value
In addition to API-related specifics, VPE API requests always include the fields (client_index and context) and a reply structure (the base API name with _reply appended), yielding the following text to add into vpe.api:
define sw_interface_set_l2_bridge {
u32 client_index;
u32 context;
u32 rx_sw_if_index;
u32 bd_id;
u32 bvi;
u32 shg;
u8 enable;
};
define sw_interface_set_l2_bridge_reply {
u32 context;
i32 retval;
};
Once the communicating data structure is defined in vpe.api, two items for the API function must be added to api.c:
Within the #define foreach_vpe_api_msg portion of the file, add the new entry for the API function, in this case:
: _(SW_INTERFACE_SET_L2_BRIDGE, sw_interface_set_l2_bridge) \
(making sure to properly terminate the line ending depending on if it's in the middle of the #define or at the end).
Then add the actual handler function:
static void
vl_api_sw_interface_set_l2_bridge_t_handler (
vl_api_sw_interface_set_l2_bridge_t *mp)
{
/* stuff required for each API function */
vl_api_sw_interface_set_l2_bridge_reply_t * rmp;
int rv = 0;
/* stuff specific to the sw_interface_set_l2_bridge API function */
u32 rx_sw_if_index = ntohl(mp->rx_sw_if_index);
u32 bd_id = ntohl(mp->bd_id);
u32 bvi = ntohl(mp->bvi);
u32 shg = ntohl(mp->shg);
/* stuff specific to this function */
/* stuff required for each API function */
REPLY_MACRO(VL_API_SW_INTERFACE_SET_L2_BRIDGE_REPLY);
}
It's probably obvious, but in the prior examples (and the ones that follow), the text SW_INTERFACE_SET_L2_BRIDGE and sw_interface_set_l2_bridge should be changed to the your specific new API function names.
Please remember to convert message structure members from network byte order to local variables in host byte order, as shown above.
This specific example uses REPLY_MACRO to return whatever is placed in the rv variable. Within this macro, (among other things) rv is carefully stuffed into rmp->.
If you need to return additional information, use the REPLY_MACRO2 macro. An example from vl_api_l2_flags:
REPLY_MACRO2(VL_API_L2_FLAGS_REPLY, rmp->resulting_feature_bitmap = ntohl(rbi));
The second argument to REPLY_MACRO2 can contain multiple statements.
Each API entry needs a corresponding *_print function to support debugging VPE coding and configuration issues. In short, this function prints the configuration of each API interaction via the control plane. The output format should show all the information needed to recreate what the control plane without the actual control plane setup.
This function is complemented by an "custom dump parser" (AKA api_format; described in the next section), so it's important that these items are symmetrical in terms of what custom_dump prints, api_format should be able to parse and act upon.
static void *vl_api_sw_interface_set_l2_bridge_t_print
(vl_api_sw_interface_set_l2_bridge_t * mp, void *handle)
{
/* stuff required for all API functions */
u8 * s;
s = format (0, "SCRIPT: sw_interface_set_l2_bridge ");
/* stuff specific to new API function */
/* stuff required for all API functions */
s [vec_len(s)-1] = 0;
vl_print (handle, (char *)s);
vec_free(s);
return handle;
}
You also need to make a definition for your print handler above:
#define foreach_custom_print_function \
_(SW_INTERFACE_SET_L2_BRIDGE, sw_interface_set_l2_bridge) \
As hinted in the custom_dump.c section, vat via the file api_format.c is complementary program to consume output dumps in order to "play back" configurations and setup established via the control plane.
To accomplish this, each API function needs to:
- provide a reply function
- parse dump text and invoke corresponding internal functions
- provide a help string to guide visual inspection of dump files and manual testing via vat tool.
The reply function is specified in two places:
#define foreach_standard_reply_retval_handler \
as
_(sw_interface_set_l2_bridge_reply) \
and in:
#define foreach_vpe_api_reply_msg \
as
_(SW_INTERFACE_SET_L2_BRIDGE_REPLY, sw_interface_set_l2_bridge_reply) \
Standard warnings are given about properly terminating #define statements.
There are many examples of parsing dump strings in api_format.c but most follow the pattern shown in the example function below.
Here are some things to note:
- the string which invokes the function is based on the original structure name listed in vpe.api so sw_interface_set_l2_bridge in the dump file trigger the function named api_sw_interface_set_l2_bridge .
- for each parameter it's preferred that the function to be tagged such that their order isn't fixed (this is reflected in the parsing function below using a while loop matching possible tags, then possible parameters to those tags.
static int api_sw_interface_set_l2_bridge (vat_main_t * vam)
{
unformat_input_t * i = vam->input;
vl_api_sw_interface_set_l2_bridge_t *mp;
f64 timeout;
u32 rx_sw_if_index;
u8 rx_sw_if_index_set = 0;
u32 bd_id;
u8 bd_id_set = 0;
u32 bvi = 0;
u32 shg = 0;
u8 enable = 1;
/* Parse args required to build the message */
while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
if (unformat (i, "rx_sw_if_index %d", &rx_sw_if_index))
rx_sw_if_index_set = 1;
else if (unformat (i, "bd_id %d", &bd_id))
bd_id_set = 1;
else if (unformat (i, "rx")) {
if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
if (unformat (i, "%U", unformat_sw_if_index, vam,
&rx_sw_if_index))
rx_sw_if_index_set = 1;
} else
break;
} else if (unformat (i, "shg %d", &shg)) {
/* no specific action beyond unformat needed(?) */
} else if (unformat (i, "bvi")) {
bvi = 1;
} else if (unformat (i, "enable"))
enable = 1;
else if (unformat (i, "disable"))
enable = 0;
else
break;
}
if (rx_sw_if_index_set == 0) {
errmsg ("missing rx interface name or rx_sw_if_index\n");
return -99;
}
if (enable && (bd_id_set == 0)) {
errmsg ("missing bridge domain\n");
return -99;
}
M(SW_INTERFACE_SET_L2_BRIDGE, sw_interface_set_l2_bridge);
mp->rx_sw_if_index = ntohl(rx_sw_if_index);
mp->bd_id = ntohl(bd_id);
mp->bvi = ntohl(bvi);
mp->shg = ntohl(shg);
mp->enable = enable;
S; W;
/* NOTREACHED */
return 0;
}
Help strings are provided through the after the function specification section of api_format.c. This string shows:
- the name of the string
- parameter names inside angle brackets
- optional parameters inside square brackets
As with other #define specified structures inside VPE, take care that the line endings are properly terminated.
_(sw_interface_set_l2_bridge, \
"rx <intfc> | rx_sw_if_index <id> bd_id <bridge-domain-id>\n" \
"[shg <split-horizon-group>] [bvi]\n" \
"enable | disable") \
From clone directory:
make bootstrap
make build-vat
From .../build-root:
make is_build_tool=yes vppapigen-install
- VPP 2022 Make Test Use Case Poll
- VPP-AArch64
- VPP-ABF
- VPP Alternative Builds
- VPP API Concepts
- VPP API Versioning
- VPP-ApiChangeProcess
- VPP-ArtifactVersioning
- VPP-BIER
- VPP-Bihash
- VPP-BugReports
- VPP Build System Deep Dive
- VPP Build, Install, And Test Images
- VPP-BuildArtifactRetentionPolicy
- VPP-c2cpel
- VPP Code Walkthrough VoD
- VPP Code Walkthrough VoD Topic Index
- VPP Code Walkthrough VoDs
- VPP-CodeStyleConventions
- VPP-CodingTips
- VPP Command Line Arguments
- VPP Command Line Interface CLI Guide
- VPP-CommitMessages
- VPP-Committers-SMEs
- VPP-CommitterTasks-ApiFreeze
- VPP CommitterTasks Compare API Changes
- VPP-CommitterTasks-CutPointRelease
- VPP-CommitterTasks-CutRelease
- VPP-CommitterTasks-FinalReleaseCandidate
- VPP-CommitterTasks-PullThrottleBranch
- VPP-CommitterTasks-ReleasePlan
- VPP Configuration Tool
- VPP Configure An LW46 MAP E Terminator
- VPP Configure VPP As A Router Between Namespaces
- VPP Configure VPP TAP Interfaces For Container Routing
- VPP-CoreFileMismatch
- VPP-cpel
- VPP-cpeldump
- VPP-CurrentData
- VPP-DHCPKit
- VPP-DHCPv6
- VPP-DistributedOwnership
- VPP-Documentation
- VPP DPOs And Feature Arcs
- VPP EC2 Instance With SRIOV
- VPP-elog
- VPP-FAQ
- VPP Feature Arcs
- VPP-Features
- VPP-Features-IPv6
- VPP-FIB
- VPP-g2
- VPP Getting VPP 16.06
- VPP Getting VPP Release Binaries
- VPP-HA
- VPP-HostStack
- VPP-HostStack-BuiltinEchoClientServer
- VPP-HostStack-EchoClientServer
- VPP-HostStack-ExternalEchoClientServer
- VPP HostStack Hs Test
- VPP-HostStack-LDP-iperf
- VPP-HostStack-LDP-nginx
- VPP-HostStack-LDP-sshd
- VPP-HostStack-nginx
- VPP-HostStack-SessionLayerArchitecture
- VPP-HostStack-TestHttpServer
- VPP-HostStack-TestProxy
- VPP-HostStack-TLS
- VPP-HostStack-VCL
- VPP-HostStack-VclEchoClientServer
- VPP-Hotplug
- VPP How To Add A Tunnel Encapsulation
- VPP How To Build The Sample Plugin
- VPP How To Connect A PCI Interface To VPP
- VPP How To Create A VPP Binary Control Plane API
- VPP How To Deploy VPP In EC2 Instance And Use It To Connect Two Different VPCs
- VPP How To Optimize Performance %28System Tuning%29
- VPP How To Use The API Trace Tools
- VPP How To Use The C API
- VPP How To Use The Packet Generator And Packet Tracer
- VPP-Howtos
- VPP-index
- VPP Installing VPP Binaries From Packages
- VPP Interconnecting vRouters With VPP
- VPP Introduction To IP Adjacency
- VPP Introduction To N Tuple Classifiers
- VPP IP Adjacency Introduction
- VPP-IPFIX
- VPP-IPSec
- VPP IPSec And IKEv2
- VPP IPv6 SR VIRL Topology File
- VPP Java API
- VPP Java API Plugin Support
- VPP Jira Workflow
- VPP-Macswapplugin
- VPP-MakeTestFramework
- VPP-Meeting
- VPP-MFIB
- VPP Missing Prefetches
- VPP Modifying The Packet Processing Directed Graph
- VPP MPLS FIB
- VPP-NAT
- VPP Nataas Test
- VPP-OVN
- VPP Per Feature Notes
- VPP Performance Analysis Tools
- VPP-perftop
- VPP Progressive VPP Tutorial
- VPP Project Meeting Minutes
- VPP Pulling, Building, Running, Hacking And Pushing VPP Code
- VPP Pure L3 Between Namespaces With 32s
- VPP Pure L3 Container Networking
- VPP Pushing And Testing A Tag
- VPP Python API
- VPP-PythonVersionPolicy
- VPP-QuickTrexSetup
- VPP Random Hints And Kinks For KVM Usage
- VPP Release Plans Release Plan 16.09
- VPP Release Plans Release Plan 17.01
- VPP Release Plans Release Plan 17.04
- VPP Release Plans Release Plan 17.07
- VPP Release Plans Release Plan 17.10
- VPP Release Plans Release Plan 18.01
- VPP Release Plans Release Plan 18.04
- VPP Release Plans Release Plan 18.07
- VPP Release Plans Release Plan 18.10
- VPP Release Plans Release Plan 19.01
- VPP Release Plans Release Plan 19.04
- VPP Release Plans Release Plan 19.08
- VPP Release Plans Release Plan 20.01
- VPP Release Plans Release Plan 20.05
- VPP Release Plans Release Plan 20.09
- VPP Release Plans Release Plan 21.01
- VPP Release Plans Release Plan 21.06
- VPP Release Plans Release Plan 21.10
- VPP Release Plans Release Plan 22.02
- VPP Release Plans Release Plan 22.06
- VPP Release Plans Release Plan 22.10
- VPP Release Plans Release Plan 23.02
- VPP Release Plans Release Plan 23.06
- VPP Release Plans Release Plan 23.10
- VPP Release Plans Release Plan 24.02
- VPP Release Plans Release Plan 24.06
- VPP Release Plans Release Plan 24.10
- VPP Release Plans Release Plan 25.02
- VPP Release Plans Release Plan 25.06
- VPP Release Plans Release Plan 25.10
- VPP Release Plans Release Plan 26.02
- VPP Release Plans Release Plan 26.06
- VPP-RM
- VPP-SecurityGroups
- VPP Segment Routing For IPv6
- VPP Segment Routing For MPLS
- VPP Setting Up Your Dev Environment
- VPP-SNAT
- VPP Software Architecture
- VPP STN Testing
- VPP The VPP API
- VPP Training Events
- VPP-Troubleshooting
- VPP-Troubleshooting-BuildIssues
- VPP-Troubleshooting-Vagrant
- VPP Tutorial DPDK And MacSwap
- VPP Tutorial Routing And Switching
- VPP-Tutorials
- VPP Use VPP To Chain VMs Using Vhost User Interface
- VPP Use VPP To Connect VMs Using Vhost User Interface
- VPP Using mTCP User Mode TCP Stack With VPP
- VPP Using VPP As A VXLAN Tunnel Terminator
- VPP Using VPP In A Multi Thread Model
- VPP-VOM
- VPP VPP BFD Nexus
- VPP VPP Home Gateway
- VPP VPP WIKI DEPRECATED CONTENT
- VPP-VPPCommunicationsLibrary
- VPP-VPPConfig
- VPP What Is ODP4VPP
- VPP What Is VPP
- VPP Working Environments
- VPP Working With The 16.06 Throttle Branch