├── .gitignore ├── README.md ├── c ├── build.sh └── vppclient.c ├── golang ├── build.sh └── vppclient.go ├── java ├── build.gradle ├── build.sh ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── settings.gradle └── src │ └── main │ └── java │ └── com │ └── mars │ └── vpp │ └── client │ └── sample │ └── java │ └── VppClient.java ├── kotlin ├── build.gradle ├── build.sh ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── settings.gradle └── src │ └── main │ └── kotlin │ └── com │ └── mars │ └── vpp │ └── client │ └── sample │ └── kotlin │ └── VppClient.kt ├── lua ├── build.sh ├── client.lua └── vpp-lapi.lua.diff └── python ├── build.sh └── client.py /.gitignore: -------------------------------------------------------------------------------- 1 | # built application files 2 | *.apk 3 | *.ap_ 4 | 5 | *.o 6 | *.log 7 | 8 | # files for the dex VM 9 | *.dex 10 | 11 | # Java class files 12 | *.class 13 | 14 | # generated files 15 | bin/ 16 | gen/ 17 | 18 | # Local configuration file (sdk path, etc) 19 | local.properties 20 | 21 | # Eclipse project files 22 | .classpath 23 | .project 24 | 25 | # Proguard folder generated by Eclipse 26 | proguard/ 27 | 28 | # Intellij project files 29 | *.iml 30 | *.ipr 31 | *.iws 32 | .idea/ 33 | 34 | #Gradle 35 | .gradletasknamecache 36 | .gradle/ 37 | build/ 38 | bin/ 39 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # VPP binary APIs showcase 2 | 3 | This is a collection of samples that show how VPP can be configured/managed from various languages 4 | The same simple use case is implemented accross the board 5 | 6 | Note that these are only samples 7 | 8 | More information on this topic can be found in [my blog post](https://www.marosmars.com/blog/category/vpp) 9 | 10 | Especially in the [overview of VPP API](http://www.marosmars.com/blog/managing-vpp-api-overview) 11 | 12 | Shows how to manage VPP using: 13 | * C APIs 14 | * Java APIs 15 | * Kotlin using Java APIs 16 | * Python APIs 17 | * LUA APIs 18 | * Golang APIs 19 | 20 | Sample L2 use case: 21 | * Open VPP management session 22 | * Show interfaces 23 | * Create loopback interface 24 | * Show interfaces 25 | * Show bridge domains 26 | * Create bridge domain 27 | * Show bridge domains 28 | * Close VPP management session 29 | 30 | Written for VPP version: 31 | **18.04** 32 | 33 | -------------------------------------------------------------------------------- /c/build.sh: -------------------------------------------------------------------------------- 1 | # sudo apt-get install vpp-dev 2 | # ls /usr/share/vpp/api 3 | # cat l2.api.json 4 | # cat interface.api.json 5 | 6 | gcc vppclient.c -o client.o -lvppinfra -lvlibmemoryclient -lsvm 7 | sudo ./client.o -------------------------------------------------------------------------------- /c/vppclient.c: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE /* for strcasestr(3) */ 2 | 3 | #include 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #define vl_api_version(n,v) static u32 vpe_api_version = (v); 11 | #include 12 | #undef vl_api_version 13 | 14 | #include 15 | #define vl_typedefs 16 | #include 17 | #undef vl_typedefs 18 | 19 | // Automatically generate endian handlers for messages 20 | #define vl_endianfun 21 | #include 22 | #undef vl_endianfun 23 | 24 | // Automatically generate print handlers for messages 25 | #define vl_print(handle, ...) 26 | #define vl_printfun 27 | #include 28 | #undef vl_printfun 29 | 30 | vlib_main_t vlib_global_main; 31 | vlib_main_t **vlib_mains; 32 | 33 | // Keep pointers to API endpoint 34 | typedef struct { 35 | unix_shared_memory_queue_t * vl_input_queue; 36 | u32 my_client_index; 37 | } vppclient_main_t; 38 | 39 | /* shared vppclient main structure */ 40 | vppclient_main_t vppclient_main __attribute__((aligned (64))); 41 | 42 | #define CONTROL_PING_MESSAGE "control_ping" 43 | #define CONTROL_PING_REPLY_MESSAGE "control_ping_reply" 44 | 45 | #define CREATE_LOOPBACK_MESSAGE "create_loopback" 46 | #define CREATE_LOOPBACK_REPLY_MESSAGE "create_loopback_reply" 47 | 48 | #define DUMP_IFC_MESSAGE "sw_interface_dump" 49 | #define IFC_DETAIL_MESSAGE "sw_interface_details" 50 | 51 | #define CREATTE_BD_MESSAGE "bridge_domain_add_del" 52 | #define CREATE_BD_REPLY_MESSAGE "bridge_domain_add_del_reply" 53 | 54 | #define DUMP_BD_MESSAGE "bridge_domain_dump" 55 | #define BD_DETAIL_MESSAGE "bridge_domain_details" 56 | 57 | static u32 find_msg_id(char* msg) { 58 | api_main_t * am = &api_main; 59 | hash_pair_t *hp; 60 | 61 | hash_foreach_pair (hp, am->msg_index_by_name_and_crc, 62 | ({ 63 | char *key = (char *)hp->key; // key format: name_crc 64 | int msg_name_len = strlen(key) - 9; // ignore crc 65 | if (strlen(msg) == msg_name_len && 66 | strncmp(msg, (char *)hp->key, msg_name_len) == 0) { 67 | return (u32)hp->value[0]; 68 | } 69 | })); 70 | } 71 | 72 | static int send_ping(u32 ping_id, u32 message_id) { 73 | vl_api_control_ping_t * mp; 74 | vppclient_main_t * jm = &vppclient_main; 75 | 76 | // Allocate control ping message 77 | mp = vl_msg_api_alloc(sizeof(*mp)); 78 | memset(mp, 0, sizeof(*mp)); 79 | // Set the message ID to control_ping ID reported by VPP 80 | mp->_vl_msg_id = ntohs(ping_id); 81 | // Set our client index 82 | mp->client_index = jm->my_client_index; 83 | // Set context (context is an arbitrary number that can help matching request/reply pairs) 84 | mp->context = clib_host_to_net_u32(message_id); 85 | 86 | // send messagee to VPP 87 | vl_msg_api_send_shmem(jm->vl_input_queue, (u8 *) &mp); 88 | printf("Sending ping. Ping msg id: %d, message id: %d\n", ping_id, message_id); 89 | } 90 | 91 | static void vl_api_control_ping_reply_t_handler( 92 | vl_api_control_ping_reply_t * mp) { 93 | printf("\tPing reply received, message id: %d, with retval: %d\n", clib_net_to_host_u32(mp->context), mp->retval); 94 | } 95 | 96 | /* 97 | ["create_loopback", 98 | ["u16", "_vl_msg_id"], 99 | ["u32", "client_index"], 100 | ["u32", "context"], 101 | ["u8", "mac_address", 6], 102 | {"crc" : "0xb2602de5"} 103 | ], 104 | 105 | */ 106 | static int create_loopback(u32 create_loop_id, u32 message_id) { 107 | vl_api_create_loopback_t * mp; 108 | vppclient_main_t * jm = &vppclient_main; 109 | 110 | // Allocate create loopback message 111 | mp = vl_msg_api_alloc(sizeof(*mp)); 112 | memset(mp, 0, sizeof(*mp)); 113 | // Set the message ID to create_loopback ID reported by VPP 114 | mp->_vl_msg_id = ntohs(create_loop_id); 115 | // Set our client index 116 | mp->client_index = jm->my_client_index; 117 | // Set context (context is an arbitrary number that can help matching request/reply pairs) 118 | mp->context = clib_host_to_net_u32(message_id); 119 | // We could also set mac address 120 | 121 | // send messagee to VPP 122 | vl_msg_api_send_shmem(jm->vl_input_queue, (u8 *) &mp); 123 | printf("Sending create loopback. Create loopback msg id: %d, message id: %d\n", create_loop_id, message_id); 124 | } 125 | 126 | /* 127 | ["create_loopback_reply", 128 | ["u16", "_vl_msg_id"], 129 | ["u32", "context"], 130 | ["i32", "retval"], 131 | ["u32", "sw_if_index"], 132 | {"crc" : "0x9520f804"} 133 | ], 134 | 135 | */ 136 | static void vl_api_create_loopback_reply_t_handler( 137 | vl_api_create_loopback_reply_t * mp) { 138 | printf("\tCreate loopback reply received, message id: %d, with retval: %d, new interface index: %d\n", 139 | clib_net_to_host_u32(mp->context), mp->retval, clib_net_to_host_u32(mp->sw_if_index)); 140 | } 141 | 142 | /* 143 | ["sw_interface_dump", 144 | ["u16", "_vl_msg_id"], 145 | ["u32", "client_index"], 146 | ["u32", "context"], 147 | ["u8", "name_filter_valid"], 148 | ["u8", "name_filter", 49], 149 | {"crc" : "0x9a2f9d4d"} 150 | ], 151 | */ 152 | static int dump_ifcs(u32 dump_id, u32 message_id) { 153 | vl_api_sw_interface_dump_t * mp; 154 | vppclient_main_t * jm = &vppclient_main; 155 | 156 | // Allocate create loopback message 157 | mp = vl_msg_api_alloc(sizeof(*mp)); 158 | memset(mp, 0, sizeof(*mp)); 159 | // Set the message ID to dump_interfaces ID reported by VPP 160 | mp->_vl_msg_id = ntohs(dump_id); 161 | // Set our client index 162 | mp->client_index = jm->my_client_index; 163 | // Set context (context is an arbitrary number that can help matching request/reply pairs) 164 | mp->context = clib_host_to_net_u32(message_id); 165 | // We could also set name_filter 166 | 167 | // send messagee to VPP 168 | vl_msg_api_send_shmem(jm->vl_input_queue, (u8 *) &mp); 169 | printf("Sending dump interfaces. Msg id: %d, message id: %d\n", dump_id, message_id); 170 | } 171 | 172 | /* 173 | ["sw_interface_details", 174 | ["u16", "_vl_msg_id"], 175 | ["u32", "context"], 176 | ["u32", "sw_if_index"], 177 | ["u32", "sup_sw_if_index"], 178 | ["u32", "l2_address_length"], 179 | ["u8", "l2_address", 8], 180 | ["u8", "interface_name", 64], 181 | ["u8", "admin_up_down"], 182 | ["u8", "link_up_down"], 183 | ["u8", "link_duplex"], 184 | ["u8", "link_speed"], 185 | ["u16", "link_mtu"], 186 | ["u32", "sub_id"], 187 | ["u8", "sub_dot1ad"], 188 | ["u8", "sub_dot1ah"], 189 | ["u8", "sub_number_of_tags"], 190 | ["u16", "sub_outer_vlan_id"], 191 | ["u16", "sub_inner_vlan_id"], 192 | ["u8", "sub_exact_match"], 193 | ["u8", "sub_default"], 194 | ["u8", "sub_outer_vlan_id_any"], 195 | ["u8", "sub_inner_vlan_id_any"], 196 | ["u32", "vtr_op"], 197 | ["u32", "vtr_push_dot1q"], 198 | ["u32", "vtr_tag1"], 199 | ["u32", "vtr_tag2"], 200 | ["u8", "tag", 64], 201 | ["u16", "outer_tag"], 202 | ["u8", "b_dmac", 6], 203 | ["u8", "b_smac", 6], 204 | ["u16", "b_vlanid"], 205 | ["u32", "i_sid"], 206 | {"crc" : "0xe2d855bb"} 207 | ], 208 | */ 209 | static void vl_api_sw_interface_details_t_handler( 210 | vl_api_sw_interface_details_t * mp) { 211 | printf("\tInterface, message id: %d, interface index: %d\n", 212 | clib_net_to_host_u32(mp->context), clib_net_to_host_u32(mp->sw_if_index)); 213 | } 214 | 215 | /* 216 | ["bridge_domain_add_del", 217 | ["u16", "_vl_msg_id"], 218 | ["u32", "client_index"], 219 | ["u32", "context"], 220 | ["u32", "bd_id"], 221 | ["u8", "flood"], 222 | ["u8", "uu_flood"], 223 | ["u8", "forward"], 224 | ["u8", "learn"], 225 | ["u8", "arp_term"], 226 | ["u8", "mac_age"], 227 | ["u8", "bd_tag", 64], 228 | ["u8", "is_add"], 229 | {"crc" : "0xe9894b51"} 230 | ], 231 | */ 232 | static int create_bd(u32 create_bd, u32 message_id, u32 bd_id) { 233 | vl_api_bridge_domain_add_del_t * mp; 234 | vppclient_main_t * jm = &vppclient_main; 235 | 236 | // Allocate create loopback message 237 | mp = vl_msg_api_alloc(sizeof(*mp)); 238 | memset(mp, 0, sizeof(*mp)); 239 | // Set the message ID to create_loopback ID reported by VPP 240 | mp->_vl_msg_id = ntohs(create_bd); 241 | // Set our client index 242 | mp->client_index = jm->my_client_index; 243 | // Set context (context is an arbitrary number that can help matching request/reply pairs) 244 | mp->context = clib_host_to_net_u32(message_id); 245 | // Set bd ID 246 | mp->bd_id = clib_host_to_net_u32(bd_id); 247 | // Mark the request as ADD 248 | mp->is_add = 1; 249 | 250 | // send messagee to VPP 251 | vl_msg_api_send_shmem(jm->vl_input_queue, (u8 *) &mp); 252 | printf("Sending create bridge_domain. Create bridge_domain msg id: %d, message id: %d\n", create_bd, message_id); 253 | } 254 | 255 | /* 256 | ["create_loopback_reply", 257 | ["u16", "_vl_msg_id"], 258 | ["u32", "context"], 259 | ["i32", "retval"], 260 | ["u32", "sw_if_index"], 261 | {"crc" : "0x9520f804"} 262 | ], 263 | 264 | */ 265 | static void vl_api_bridge_domain_add_del_reply_t_handler( 266 | vl_api_bridge_domain_add_del_reply_t * mp) { 267 | printf("\tCreate bridge_domain reply received, message id: %d, with retval: %d\n", 268 | clib_net_to_host_u32(mp->context), mp->retval); 269 | } 270 | 271 | /* 272 | ["bridge_domain_dump", 273 | ["u16", "_vl_msg_id"], 274 | ["u32", "client_index"], 275 | ["u32", "context"], 276 | ["u32", "bd_id"], 277 | {"crc" : "0x68d5401d"} 278 | ], 279 | */ 280 | static int dump_bd(u32 dump_id, u32 message_id) { 281 | vl_api_bridge_domain_dump_t * mp; 282 | vppclient_main_t * jm = &vppclient_main; 283 | 284 | // Allocate create loopback message 285 | mp = vl_msg_api_alloc(sizeof(*mp)); 286 | memset(mp, 0, sizeof(*mp)); 287 | // Set the message ID to dump_interfaces ID reported by VPP 288 | mp->_vl_msg_id = ntohs(dump_id); 289 | // Set our client index 290 | mp->client_index = jm->my_client_index; 291 | // Set context (context is an arbitrary number that can help matching request/reply pairs) 292 | mp->context = clib_host_to_net_u32(message_id); 293 | // Set bd_id to ~0. ~0 means dump all bridge domains. We could use a specific bd_id to dump a single bd 294 | mp->bd_id = ~0; 295 | 296 | // send messagee to VPP 297 | vl_msg_api_send_shmem(jm->vl_input_queue, (u8 *) &mp); 298 | printf("Sending dump bd. Msg id: %d, message id: %d\n", dump_id, message_id); 299 | } 300 | 301 | /* 302 | ["bridge_domain_details", 303 | ["u16", "_vl_msg_id"], 304 | ["u32", "context"], 305 | ["u32", "bd_id"], 306 | ["u8", "flood"], 307 | ["u8", "uu_flood"], 308 | ["u8", "forward"], 309 | ["u8", "learn"], 310 | ["u8", "arp_term"], 311 | ["u8", "mac_age"], 312 | ["u8", "bd_tag", 64], 313 | ["u32", "bvi_sw_if_index"], 314 | ["u32", "n_sw_ifs"], 315 | ["vl_api_bridge_domain_sw_if_t", "sw_if_details", 0, "n_sw_ifs"], 316 | {"crc" : "0xff7d2b54"} 317 | ], 318 | */ 319 | static void vl_api_bridge_domain_details_t_handler( 320 | vl_api_bridge_domain_details_t * mp) { 321 | printf("\tBridge_domain, message id: %d, bd index: %d\n", 322 | clib_net_to_host_u32(mp->context), clib_net_to_host_u32(mp->bd_id)); 323 | } 324 | // endian and print handlers for bd_details were not generated, so just set then to noop handler for now 325 | #define vl_api_bridge_domain_details_t_endian vl_noop_handler 326 | #define vl_api_bridge_domain_details_t_print vl_noop_handler 327 | 328 | int main() 329 | { 330 | vppclient_main_t * jm = &vppclient_main; 331 | api_main_t * am = &api_main; 332 | 333 | clib_mem_init (0, 128 << 20); 334 | // Open VPP management session under name vpp-manager 335 | if (vl_client_connect_to_vlib("vpe-api", "vpp-manager", 32) < 0) 336 | return -1; 337 | 338 | printf("Connected to VPP! as client: %d\n", jm->my_client_index); 339 | 340 | jm->my_client_index = am->my_client_index; 341 | jm->vl_input_queue = am->shmem_hdr->vl_input_queue; 342 | 343 | // Register ping reply handler 344 | vl_msg_api_set_handlers(find_msg_id(CONTROL_PING_REPLY_MESSAGE), CONTROL_PING_REPLY_MESSAGE, 345 | vl_api_control_ping_reply_t_handler, vl_noop_handler, 346 | vl_api_control_ping_reply_t_endian, 347 | vl_api_control_ping_reply_t_print, 348 | sizeof(vl_api_control_ping_reply_t), 1); 349 | 350 | // Register dump_interfaces reply handler 351 | vl_msg_api_set_handlers(find_msg_id(IFC_DETAIL_MESSAGE), IFC_DETAIL_MESSAGE, 352 | vl_api_sw_interface_details_t_handler, vl_noop_handler, 353 | vl_api_sw_interface_details_t_endian, 354 | vl_api_sw_interface_details_t_print, 355 | sizeof(vl_api_sw_interface_details_t), 1); 356 | 357 | // Register create_loopback reply handler 358 | vl_msg_api_set_handlers(find_msg_id(CREATE_LOOPBACK_REPLY_MESSAGE), CREATE_LOOPBACK_REPLY_MESSAGE, 359 | vl_api_create_loopback_reply_t_handler, vl_noop_handler, 360 | vl_api_create_loopback_reply_t_endian, 361 | vl_api_create_loopback_reply_t_print, 362 | sizeof(vl_api_create_loopback_reply_t), 1); 363 | 364 | // Register create_loopback reply handler 365 | vl_msg_api_set_handlers(find_msg_id(CREATE_BD_REPLY_MESSAGE), CREATE_BD_REPLY_MESSAGE, 366 | vl_api_bridge_domain_add_del_reply_t_handler, vl_noop_handler, 367 | vl_api_bridge_domain_add_del_reply_t_endian, 368 | vl_api_bridge_domain_add_del_reply_t_print, 369 | sizeof(vl_api_bridge_domain_add_del_reply_t), 1); 370 | 371 | // Register dump_bridge_domain reply handler 372 | vl_msg_api_set_handlers(find_msg_id(BD_DETAIL_MESSAGE), BD_DETAIL_MESSAGE, 373 | vl_api_bridge_domain_details_t_handler, vl_noop_handler, 374 | vl_api_bridge_domain_details_t_endian, 375 | vl_api_bridge_domain_details_t_print, 376 | sizeof(vl_api_bridge_domain_details_t), 1); 377 | 378 | // Send initial ping to check all works 379 | send_ping(find_msg_id(CONTROL_PING_MESSAGE), 1); 380 | sleep(1); 381 | // Show interfaces 382 | dump_ifcs(find_msg_id(DUMP_IFC_MESSAGE), 2); 383 | sleep(1); 384 | // Create Loopback interface 385 | create_loopback(find_msg_id(CREATE_LOOPBACK_MESSAGE), 3); 386 | sleep(1); 387 | // Show interfaces 388 | dump_ifcs(find_msg_id(DUMP_IFC_MESSAGE), 4); 389 | sleep(1); 390 | // Show bridge domains 391 | dump_bd(find_msg_id(DUMP_BD_MESSAGE), 5); 392 | sleep(1); 393 | // Add bridge domain 99 394 | create_bd(find_msg_id(CREATTE_BD_MESSAGE), 6, 99); 395 | sleep(1); 396 | // Show bridge domains 397 | dump_bd(find_msg_id(DUMP_BD_MESSAGE), 7); 398 | sleep(1); 399 | 400 | // TODO Now add interface to BD 401 | 402 | return 0; 403 | } 404 | -------------------------------------------------------------------------------- /golang/build.sh: -------------------------------------------------------------------------------- 1 | # SETUP 2 | # Put these files in your go workspace under folder vppapisample 3 | # go get git.fd.io/govpp.git 4 | # go install git.fd.io/govpp.git/cmd/binapi-generator 5 | 6 | # BUILD 7 | go generate 8 | go build 9 | sudo ./vppapisample 10 | -------------------------------------------------------------------------------- /golang/vppclient.go: -------------------------------------------------------------------------------- 1 | // Sample vpp client 2 | 3 | //go:generate /home/maros/go/bin/binapi-generator --input-file=/usr/share/vpp/api/vpe.api.json --output-dir=./bin_api 4 | //go:generate /home/maros/go/bin/binapi-generator --input-file=/usr/share/vpp/api/interface.api.json --output-dir=./bin_api 5 | //go:generate /home/maros/go/bin/binapi-generator --input-file=/usr/share/vpp/api/l2.api.json --output-dir=./bin_api 6 | 7 | 8 | package main 9 | 10 | import ( 11 | "fmt" 12 | "os" 13 | 14 | "git.fd.io/govpp.git" 15 | "git.fd.io/govpp.git/api" 16 | 17 | "vppapisample/bin_api/interfaces" 18 | "vppapisample/bin_api/l2" 19 | ) 20 | 21 | 22 | 23 | func main() { 24 | fmt.Println("Connecting to VPP") 25 | 26 | // connect to VPP 27 | conn, err := govpp.Connect("") 28 | if err != nil { 29 | fmt.Println("Error:", err) 30 | os.Exit(1) 31 | } 32 | defer conn.Disconnect() 33 | 34 | ch, err := conn.NewAPIChannel() 35 | if err != nil { 36 | fmt.Println("Error:", err) 37 | os.Exit(1) 38 | } 39 | defer ch.Close() 40 | 41 | interfaceDump(ch) 42 | createLoopback(ch) 43 | interfaceDump(ch) 44 | bdDump(ch) 45 | createBd(ch) 46 | bdDump(ch) 47 | } 48 | 49 | func interfaceDump(ch api.Channel) { 50 | fmt.Println("Sending dump interfaces. Msg id: sw_interface_dump") 51 | req := &interfaces.SwInterfaceDump{} 52 | reqCtx := ch.SendMultiRequest(req) 53 | 54 | for { 55 | msg := &interfaces.SwInterfaceDetails{} 56 | stop, err := reqCtx.ReceiveReply(msg) 57 | if stop { 58 | break; 59 | } 60 | if err != nil { 61 | fmt.Println("Error:", err) 62 | } 63 | fmt.Printf("\tInterface, message id: sw_interface_details, interface index: %v\n", string(msg.InterfaceName[:])) 64 | } 65 | } 66 | 67 | func createLoopback(ch api.Channel) { 68 | req := &interfaces.CreateLoopback{} 69 | 70 | ch.GetRequestChannel() <- &api.VppRequest{Message: req} 71 | 72 | vppReply := <-ch.GetReplyChannel() 73 | if vppReply.Error != nil { 74 | fmt.Println("Error:", vppReply.Error) 75 | return 76 | } 77 | 78 | reply := &interfaces.CreateLoopbackReply{} 79 | err := ch.GetMessageDecoder().DecodeMsg(vppReply.Data, reply) 80 | 81 | if err != nil { 82 | fmt.Println("Error:", err) 83 | } 84 | } 85 | 86 | func bdDump(ch api.Channel) { 87 | fmt.Println("Sending dump bd. Msg id: bridge_domain_dump") 88 | req := &l2.BridgeDomainDump{ 89 | BdID: ^uint32(0), 90 | } 91 | reqCtx := ch.SendMultiRequest(req) 92 | 93 | for { 94 | msg := &l2.BridgeDomainDetails{} 95 | stop, err := reqCtx.ReceiveReply(msg) 96 | if stop { 97 | break; 98 | } 99 | if err != nil { 100 | fmt.Println("Error:", err) 101 | } 102 | fmt.Printf("\tBridge domain, message id: bridge_domain_details, bd index: %v\n", msg.BdID) 103 | } 104 | } 105 | 106 | func createBd(ch api.Channel) { 107 | req := &l2.BridgeDomainAddDel{ 108 | BdID: 99, 109 | IsAdd: 1, 110 | } 111 | 112 | ch.GetRequestChannel() <- &api.VppRequest{Message: req} 113 | 114 | vppReply := <-ch.GetReplyChannel() 115 | if vppReply.Error != nil { 116 | fmt.Println("Error:", vppReply.Error) 117 | return 118 | } 119 | 120 | reply := &l2.BridgeDomainAddDelReply{} 121 | err := ch.GetMessageDecoder().DecodeMsg(vppReply.Data, reply) 122 | 123 | if err != nil { 124 | fmt.Println("Error:", err) 125 | } 126 | } 127 | 128 | 129 | 130 | -------------------------------------------------------------------------------- /java/build.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * This build file was auto generated by running the Gradle 'init' task 3 | * by 'maros' at '4/28/18, 9:20 AM' with Gradle 2.10 4 | * 5 | * This generated file contains a sample Java project to get you started. 6 | * For more details take a look at the Java Quickstart chapter in the Gradle 7 | * user guide available at https://docs.gradle.org/2.10/userguide/tutorial_java_projects.html 8 | */ 9 | 10 | // Apply the java plugin to add support for Java 11 | apply plugin: 'java' 12 | sourceCompatibility = 1.8 13 | targetCompatibility = 1.8 14 | 15 | // In this section you declare where to find the dependencies of your project 16 | repositories { 17 | // Use 'jcenter' for resolving your dependencies. 18 | // You can declare any Maven/Ivy/file repository here. 19 | jcenter() 20 | maven { 21 | url "https://nexus.fd.io/content/groups/public" 22 | } 23 | } 24 | 25 | // In this section you declare the dependencies for your production and test code 26 | dependencies { 27 | compile 'io.fd.vpp:jvpp-core:18.01.1' 28 | compile 'io.fd.vpp:jvpp-registry:18.01.1' 29 | } 30 | 31 | jar { 32 | manifest { 33 | attributes 'Main-Class': 'com.mars.vpp.client.sample.java.VppClient' 34 | } 35 | 36 | // build fat jar 37 | from { 38 | configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /java/build.sh: -------------------------------------------------------------------------------- 1 | # Java 8 has to be used 2 | ./gradlew clean jar 3 | 4 | sudo java -jar build/libs/vppclientva.jar 5 | 6 | -------------------------------------------------------------------------------- /java/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marosmars/vppapisamples/5857d197f4bcf20a07dff43116b78ff5f8ad8349/java/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /java/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Sat Apr 28 09:33:08 CEST 2018 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-bin.zip 7 | -------------------------------------------------------------------------------- /java/gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # Attempt to set APP_HOME 46 | # Resolve links: $0 may be a link 47 | PRG="$0" 48 | # Need this for relative symlinks. 49 | while [ -h "$PRG" ] ; do 50 | ls=`ls -ld "$PRG"` 51 | link=`expr "$ls" : '.*-> \(.*\)$'` 52 | if expr "$link" : '/.*' > /dev/null; then 53 | PRG="$link" 54 | else 55 | PRG=`dirname "$PRG"`"/$link" 56 | fi 57 | done 58 | SAVED="`pwd`" 59 | cd "`dirname \"$PRG\"`/" >/dev/null 60 | APP_HOME="`pwd -P`" 61 | cd "$SAVED" >/dev/null 62 | 63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 64 | 65 | # Determine the Java command to use to start the JVM. 66 | if [ -n "$JAVA_HOME" ] ; then 67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 68 | # IBM's JDK on AIX uses strange locations for the executables 69 | JAVACMD="$JAVA_HOME/jre/sh/java" 70 | else 71 | JAVACMD="$JAVA_HOME/bin/java" 72 | fi 73 | if [ ! -x "$JAVACMD" ] ; then 74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 75 | 76 | Please set the JAVA_HOME variable in your environment to match the 77 | location of your Java installation." 78 | fi 79 | else 80 | JAVACMD="java" 81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 82 | 83 | Please set the JAVA_HOME variable in your environment to match the 84 | location of your Java installation." 85 | fi 86 | 87 | # Increase the maximum file descriptors if we can. 88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 89 | MAX_FD_LIMIT=`ulimit -H -n` 90 | if [ $? -eq 0 ] ; then 91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 92 | MAX_FD="$MAX_FD_LIMIT" 93 | fi 94 | ulimit -n $MAX_FD 95 | if [ $? -ne 0 ] ; then 96 | warn "Could not set maximum file descriptor limit: $MAX_FD" 97 | fi 98 | else 99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 100 | fi 101 | fi 102 | 103 | # For Darwin, add options to specify how the application appears in the dock 104 | if $darwin; then 105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 106 | fi 107 | 108 | # For Cygwin, switch paths to Windows format before running java 109 | if $cygwin ; then 110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 112 | JAVACMD=`cygpath --unix "$JAVACMD"` 113 | 114 | # We build the pattern for arguments to be converted via cygpath 115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 116 | SEP="" 117 | for dir in $ROOTDIRSRAW ; do 118 | ROOTDIRS="$ROOTDIRS$SEP$dir" 119 | SEP="|" 120 | done 121 | OURCYGPATTERN="(^($ROOTDIRS))" 122 | # Add a user-defined pattern to the cygpath arguments 123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 125 | fi 126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 127 | i=0 128 | for arg in "$@" ; do 129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 131 | 132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 134 | else 135 | eval `echo args$i`="\"$arg\"" 136 | fi 137 | i=$((i+1)) 138 | done 139 | case $i in 140 | (0) set -- ;; 141 | (1) set -- "$args0" ;; 142 | (2) set -- "$args0" "$args1" ;; 143 | (3) set -- "$args0" "$args1" "$args2" ;; 144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 150 | esac 151 | fi 152 | 153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 154 | function splitJvmOpts() { 155 | JVM_OPTS=("$@") 156 | } 157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 159 | 160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 161 | -------------------------------------------------------------------------------- /java/gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /java/settings.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * This settings file was auto generated by the Gradle buildInit task 3 | * by 'maros' at '4/28/18, 9:20 AM' with Gradle 2.10 4 | * 5 | * The settings file is used to specify which projects to include in your build. 6 | * In a single project build this file can be empty or even removed. 7 | * 8 | * Detailed information about configuring a multi-project build in Gradle can be found 9 | * in the user guide at https://docs.gradle.org/2.10/userguide/multi_project_builds.html 10 | */ 11 | 12 | /* 13 | // To declare projects as part of a multi-project build use the 'include' method 14 | include 'shared' 15 | include 'api' 16 | include 'services:webservice' 17 | */ 18 | 19 | rootProject.name = 'vppclientva' 20 | -------------------------------------------------------------------------------- /java/src/main/java/com/mars/vpp/client/sample/java/VppClient.java: -------------------------------------------------------------------------------- 1 | package com.mars.vpp.client.sample.java; 2 | 3 | import io.fd.vpp.jvpp.JVppRegistryImpl; 4 | import io.fd.vpp.jvpp.core.JVppCore; 5 | import io.fd.vpp.jvpp.core.JVppCoreImpl; 6 | import io.fd.vpp.jvpp.core.dto.BridgeDomainAddDel; 7 | import io.fd.vpp.jvpp.core.dto.BridgeDomainAddDelReply; 8 | import io.fd.vpp.jvpp.core.dto.BridgeDomainDump; 9 | import io.fd.vpp.jvpp.core.dto.CreateLoopback; 10 | import io.fd.vpp.jvpp.core.dto.CreateLoopbackReply; 11 | import io.fd.vpp.jvpp.core.dto.SwInterfaceDump; 12 | import io.fd.vpp.jvpp.core.future.FutureJVppCoreFacade; 13 | 14 | public class VppClient { 15 | 16 | public static final String CLIENT_ID = "Vppclient"; 17 | 18 | public static void main(String[] args) throws Exception { 19 | 20 | try (JVppRegistryImpl registry = new JVppRegistryImpl(CLIENT_ID); 21 | 22 | JVppCore jVppCore = new JVppCoreImpl(); 23 | FutureJVppCoreFacade coreFacade = new FutureJVppCoreFacade(registry, jVppCore)) { 24 | 25 | // Dump interfaces 26 | dumpInterfaces(coreFacade); 27 | 28 | // Create loopback 29 | createLoopback(coreFacade); 30 | 31 | // Dump interfaces 32 | dumpInterfaces(coreFacade); 33 | 34 | // Dump bds 35 | dumpBds(coreFacade); 36 | 37 | // Create bd 38 | createBd(coreFacade); 39 | 40 | // Dump bds 41 | dumpBds(coreFacade); 42 | } 43 | } 44 | 45 | private static void createLoopback(FutureJVppCoreFacade coreFacade) throws Exception { 46 | CreateLoopback createLoopback = new CreateLoopback(); 47 | System.out.printf("Sending create loopback. Msg id: %s\n", createLoopback.getClass().getSimpleName()); 48 | CreateLoopbackReply createLoopbackReply = coreFacade.createLoopback(createLoopback) 49 | .toCompletableFuture() 50 | .get(); 51 | 52 | System.out.printf("\tCreate loopback reply received, message id: %s, new interface index: %d\n", 53 | createLoopbackReply.getClass().getSimpleName(), createLoopbackReply.swIfIndex); 54 | } 55 | 56 | private static void createBd(FutureJVppCoreFacade coreFacade) throws Exception { 57 | BridgeDomainAddDel createBd = new BridgeDomainAddDel(); 58 | createBd.bdId = 99; 59 | createBd.isAdd = 1; 60 | System.out.printf("Sending create bd. Msg id: %s\n", createBd.getClass().getSimpleName()); 61 | BridgeDomainAddDelReply createBdReply = coreFacade.bridgeDomainAddDel(createBd) 62 | .toCompletableFuture() 63 | .get(); 64 | 65 | System.out.printf("\tCreate bd reply received, message id: %s\n", 66 | createBdReply.getClass().getSimpleName()); 67 | } 68 | 69 | private static void dumpInterfaces(FutureJVppCoreFacade coreFacade) throws Exception { 70 | SwInterfaceDump swInterfaceDump = new SwInterfaceDump(); 71 | System.out.printf("Sending dump interfaces. Msg id: %s\n", swInterfaceDump.getClass().getSimpleName()); 72 | coreFacade.swInterfaceDump(swInterfaceDump) 73 | .toCompletableFuture() 74 | .get() 75 | .swInterfaceDetails 76 | .forEach(ifcDetail -> System.out.printf( 77 | "\tInterface, message id: %s, interface index: %s\n", 78 | ifcDetail.getClass().getSimpleName(), ifcDetail.swIfIndex)); 79 | } 80 | 81 | private static void dumpBds(FutureJVppCoreFacade coreFacade) throws Exception { 82 | BridgeDomainDump bdDump = new BridgeDomainDump(); 83 | bdDump.bdId = ~0; 84 | System.out.printf("Sending dump bridge domains. Msg id: %s\n", bdDump.getClass().getSimpleName()); 85 | coreFacade.bridgeDomainDump(bdDump) 86 | .toCompletableFuture() 87 | .get() 88 | .bridgeDomainDetails 89 | .forEach(ifcDetail -> System.out.printf( 90 | "\tBridge domain, message id: %s, bd index: %s\n", 91 | ifcDetail.getClass().getSimpleName(), ifcDetail.bdId)); 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /kotlin/build.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * This build file was auto generated by running the Gradle 'init' task 3 | * by 'maros' at '4/28/18, 9:20 AM' with Gradle 2.10 4 | * 5 | * This generated file contains a sample Java project to get you started. 6 | * For more details take a look at the Java Quickstart chapter in the Gradle 7 | * user guide available at https://docs.gradle.org/2.10/userguide/tutorial_java_projects.html 8 | */ 9 | 10 | // Apply the java plugin to add support for Java 11 | apply plugin: 'java' 12 | apply plugin: 'kotlin' 13 | sourceCompatibility = 1.8 14 | targetCompatibility = 1.8 15 | 16 | buildscript { 17 | ext.kotlin_version = '1.2.41' 18 | 19 | repositories { 20 | jcenter() 21 | mavenCentral() 22 | } 23 | 24 | dependencies { 25 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 26 | } 27 | } 28 | 29 | // In this section you declare where to find the dependencies of your project 30 | repositories { 31 | // Use 'jcenter' for resolving your dependencies. 32 | // You can declare any Maven/Ivy/file repository here. 33 | jcenter() 34 | maven { 35 | url "https://nexus.fd.io/content/groups/public" 36 | } 37 | } 38 | 39 | // In this section you declare the dependencies for your production and test code 40 | dependencies { 41 | compile 'io.fd.vpp:jvpp-core:18.01.1' 42 | compile 'io.fd.vpp:jvpp-registry:18.01.1' 43 | compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.2.41" 44 | } 45 | 46 | jar { 47 | manifest { 48 | attributes 'Main-Class': 'com.mars.vpp.client.sample.kotlin.VppClient' 49 | } 50 | 51 | // build fat jar 52 | from { 53 | configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /kotlin/build.sh: -------------------------------------------------------------------------------- 1 | # Java 8 has to be used 2 | ./gradlew clean jar 3 | 4 | sudo java -jar build/libs/vppclientkotlin.jar 5 | 6 | -------------------------------------------------------------------------------- /kotlin/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marosmars/vppapisamples/5857d197f4bcf20a07dff43116b78ff5f8ad8349/kotlin/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /kotlin/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Sat Apr 28 09:33:08 CEST 2018 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-bin.zip 7 | -------------------------------------------------------------------------------- /kotlin/gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # Attempt to set APP_HOME 46 | # Resolve links: $0 may be a link 47 | PRG="$0" 48 | # Need this for relative symlinks. 49 | while [ -h "$PRG" ] ; do 50 | ls=`ls -ld "$PRG"` 51 | link=`expr "$ls" : '.*-> \(.*\)$'` 52 | if expr "$link" : '/.*' > /dev/null; then 53 | PRG="$link" 54 | else 55 | PRG=`dirname "$PRG"`"/$link" 56 | fi 57 | done 58 | SAVED="`pwd`" 59 | cd "`dirname \"$PRG\"`/" >/dev/null 60 | APP_HOME="`pwd -P`" 61 | cd "$SAVED" >/dev/null 62 | 63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 64 | 65 | # Determine the Java command to use to start the JVM. 66 | if [ -n "$JAVA_HOME" ] ; then 67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 68 | # IBM's JDK on AIX uses strange locations for the executables 69 | JAVACMD="$JAVA_HOME/jre/sh/java" 70 | else 71 | JAVACMD="$JAVA_HOME/bin/java" 72 | fi 73 | if [ ! -x "$JAVACMD" ] ; then 74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 75 | 76 | Please set the JAVA_HOME variable in your environment to match the 77 | location of your Java installation." 78 | fi 79 | else 80 | JAVACMD="java" 81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 82 | 83 | Please set the JAVA_HOME variable in your environment to match the 84 | location of your Java installation." 85 | fi 86 | 87 | # Increase the maximum file descriptors if we can. 88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 89 | MAX_FD_LIMIT=`ulimit -H -n` 90 | if [ $? -eq 0 ] ; then 91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 92 | MAX_FD="$MAX_FD_LIMIT" 93 | fi 94 | ulimit -n $MAX_FD 95 | if [ $? -ne 0 ] ; then 96 | warn "Could not set maximum file descriptor limit: $MAX_FD" 97 | fi 98 | else 99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 100 | fi 101 | fi 102 | 103 | # For Darwin, add options to specify how the application appears in the dock 104 | if $darwin; then 105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 106 | fi 107 | 108 | # For Cygwin, switch paths to Windows format before running java 109 | if $cygwin ; then 110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 112 | JAVACMD=`cygpath --unix "$JAVACMD"` 113 | 114 | # We build the pattern for arguments to be converted via cygpath 115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 116 | SEP="" 117 | for dir in $ROOTDIRSRAW ; do 118 | ROOTDIRS="$ROOTDIRS$SEP$dir" 119 | SEP="|" 120 | done 121 | OURCYGPATTERN="(^($ROOTDIRS))" 122 | # Add a user-defined pattern to the cygpath arguments 123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 125 | fi 126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 127 | i=0 128 | for arg in "$@" ; do 129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 131 | 132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 134 | else 135 | eval `echo args$i`="\"$arg\"" 136 | fi 137 | i=$((i+1)) 138 | done 139 | case $i in 140 | (0) set -- ;; 141 | (1) set -- "$args0" ;; 142 | (2) set -- "$args0" "$args1" ;; 143 | (3) set -- "$args0" "$args1" "$args2" ;; 144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 150 | esac 151 | fi 152 | 153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 154 | function splitJvmOpts() { 155 | JVM_OPTS=("$@") 156 | } 157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 159 | 160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 161 | -------------------------------------------------------------------------------- /kotlin/gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /kotlin/settings.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * This settings file was auto generated by the Gradle buildInit task 3 | * by 'maros' at '4/28/18, 9:20 AM' with Gradle 2.10 4 | * 5 | * The settings file is used to specify which projects to include in your build. 6 | * In a single project build this file can be empty or even removed. 7 | * 8 | * Detailed information about configuring a multi-project build in Gradle can be found 9 | * in the user guide at https://docs.gradle.org/2.10/userguide/multi_project_builds.html 10 | */ 11 | 12 | /* 13 | // To declare projects as part of a multi-project build use the 'include' method 14 | include 'shared' 15 | include 'api' 16 | include 'services:webservice' 17 | */ 18 | 19 | rootProject.name = 'vppclientkotlin' 20 | -------------------------------------------------------------------------------- /kotlin/src/main/kotlin/com/mars/vpp/client/sample/kotlin/VppClient.kt: -------------------------------------------------------------------------------- 1 | package com.mars.vpp.client.sample.kotlin 2 | 3 | import io.fd.vpp.jvpp.JVppRegistryImpl 4 | import io.fd.vpp.jvpp.core.JVppCoreImpl 5 | import io.fd.vpp.jvpp.core.dto.BridgeDomainAddDel 6 | import io.fd.vpp.jvpp.core.dto.BridgeDomainDump 7 | import io.fd.vpp.jvpp.core.dto.CreateLoopback 8 | import io.fd.vpp.jvpp.core.dto.SwInterfaceDump 9 | import io.fd.vpp.jvpp.core.future.FutureJVppCoreFacade 10 | 11 | object VppClient { 12 | 13 | private const val CLIENT_ID = "Vppclient" 14 | 15 | @JvmStatic 16 | fun main(args: Array) { 17 | 18 | JVppRegistryImpl(CLIENT_ID).use { registry -> 19 | JVppCoreImpl().use { jVppCore -> 20 | FutureJVppCoreFacade(registry, jVppCore).use { coreFacade -> 21 | 22 | // Dump interfaces 23 | dumpInterfaces(coreFacade) 24 | 25 | // Create loopback 26 | createLoopback(coreFacade) 27 | 28 | // Dump interfaces 29 | dumpInterfaces(coreFacade) 30 | 31 | // Dump bds 32 | dumpBds(coreFacade) 33 | 34 | // Create bd 35 | createBd(coreFacade) 36 | 37 | // Dump bds 38 | dumpBds(coreFacade) 39 | } 40 | } 41 | } 42 | } 43 | 44 | private fun createLoopback(coreFacade: FutureJVppCoreFacade) { 45 | CreateLoopback().let { request -> 46 | println("Sending create loopback. Msg id: ${request.javaClass.simpleName}") 47 | coreFacade.createLoopback(request) 48 | .toCompletableFuture() 49 | .get() 50 | .let { 51 | println("\tCreate loopback reply received, message id: " + 52 | "${it.javaClass.simpleName}, new interface index: ${it.swIfIndex}") 53 | } 54 | } 55 | } 56 | 57 | private fun createBd(coreFacade: FutureJVppCoreFacade) { 58 | BridgeDomainAddDel().let { request -> 59 | request.bdId = 99 60 | request.isAdd = 1 61 | println("Sending create bd. Msg id: ${request.javaClass.simpleName}") 62 | coreFacade.bridgeDomainAddDel(request) 63 | .toCompletableFuture() 64 | .get() 65 | .let { 66 | println("\tCreate bd reply received, message id: ${it.javaClass.simpleName}") 67 | } 68 | } 69 | } 70 | 71 | private fun dumpInterfaces(coreFacade: FutureJVppCoreFacade) { 72 | SwInterfaceDump().let { request -> 73 | println("Sending dump interfaces. Msg id: ${request.javaClass.simpleName}") 74 | coreFacade.swInterfaceDump(request) 75 | .toCompletableFuture() 76 | .get() 77 | .swInterfaceDetails 78 | .forEach { 79 | println("\tInterface, message id: ${it.javaClass.simpleName}, interface index: ${it.swIfIndex}") 80 | } 81 | } 82 | } 83 | 84 | private fun dumpBds(coreFacade: FutureJVppCoreFacade) { 85 | BridgeDomainDump().let { request -> 86 | request.bdId = 0.inv() 87 | println("Sending dump bridge domains. Msg id: ${request.javaClass.simpleName}") 88 | coreFacade.bridgeDomainDump(request) 89 | .toCompletableFuture() 90 | .get() 91 | .bridgeDomainDetails 92 | .forEach { 93 | println("\tBridge domain, message id: ${it.javaClass.simpleName}, bd index: ${it.bdId}") 94 | } 95 | } 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /lua/build.sh: -------------------------------------------------------------------------------- 1 | # sudo apt install luajit 2 | # sudo apt-get install vpp-api-lua 3 | 4 | # IMPORTANT make sure to apply vpp-lapi.lua.diff to /usr/share/vpp/examples/lua/vpp-lapi.lua because the original lapi file does not work (at least not for 18.04 and probably also not for 18.01) 5 | 6 | sudo luajit ./client.lua 7 | -------------------------------------------------------------------------------- /lua/client.lua: -------------------------------------------------------------------------------- 1 | package.path = package.path .. ";/usr/share/vpp/examples/lua/vpp-lapi.lua" 2 | 3 | vpp = require "vpp-lapi" 4 | 5 | function vpp_connect () 6 | vac_path = "/usr/lib/x86_64-linux-gnu/libvppapiclient.so" 7 | vpp:init({ vac_path = vac_path }) 8 | 9 | vpp:json_api("/usr/share/vpp/api/vpe.api.json") 10 | vpp:json_api("/usr/share/vpp/api/memclnt.api.json") 11 | vpp:json_api("/usr/share/vpp/api/interface.api.json") 12 | vpp:json_api("/usr/share/vpp/api/l2.api.json") 13 | 14 | vpp:connect("vppclient") 15 | end 16 | 17 | function dump_interfaces () 18 | print("Dumping interfaces") 19 | reply = vpp:api_call("sw_interface_dump") 20 | --print(vpp.dump(reply)) 21 | for k, v in pairs(reply) do 22 | print("\t Interface: ", v.sw_if_index) 23 | end 24 | end 25 | 26 | function dump_bds () 27 | print("Dumping bds") 28 | reply = vpp:api_call("bridge_domain_dump", {bd_id = tonumber("FFFFFFFF",16)}) 29 | --print(vpp.dump(reply)) 30 | for k, v in pairs(reply) do 31 | print("\t Bridge domain: ", v.bd_id) 32 | end 33 | end 34 | 35 | function create_loopback () 36 | print("Creating loopback") 37 | reply = vpp:api_call("create_loopback") 38 | --print(vpp.dump(reply)) 39 | print("\t Loopack created with rertval", reply[1].retval) 40 | end 41 | 42 | 43 | function create_bd () 44 | print("Creating bd") 45 | reply = vpp:api_call("bridge_domain_add_del", {is_add = 1, bd_id = 99}) 46 | --print(vpp.dump(reply)) 47 | print("\t Bd created with rertval", reply[1].retval) 48 | end 49 | 50 | vpp_connect() 51 | dump_interfaces() 52 | create_loopback() 53 | dump_interfaces() 54 | dump_bds() 55 | create_bd() 56 | dump_bds() 57 | 58 | vpp:disconnect() 59 | 60 | 61 | -------------------------------------------------------------------------------- /lua/vpp-lapi.lua.diff: -------------------------------------------------------------------------------- 1 | 425c425,426 2 | < int vac_connect(char *name, char *chroot_prefix, void *cb); 3 | --- 4 | > typedef void (*vac_callback_t)(unsigned char * data, int len); 5 | > int vac_connect(char *name, char *chroot_prefix, vac_callback_t cb, int rx_qlen); 6 | 695c696 7 | < local ret = vpp.vac.vac_connect(vpp.c_str(client_name), nil, nil) 8 | --- 9 | > local ret = vpp.vac.vac_connect(vpp.c_str(client_name), nil, nil, 32) 10 | -------------------------------------------------------------------------------- /python/build.sh: -------------------------------------------------------------------------------- 1 | # sudo apt-get install python3-vpp-api 2 | # ls /usr/share/vpp/api/ 3 | # cat l2.api.json 4 | # cat interface.api.json 5 | # less /usr/lib/python2.7/dist-packages/vpp_papi.py 6 | 7 | sudo ./client.py 8 | -------------------------------------------------------------------------------- /python/client.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from __future__ import print_function 4 | import os 5 | import fnmatch 6 | from vpp_papi import VPPApiJSONFiles 7 | from vpp_papi import vpp_papi 8 | 9 | CLIENT_ID = "Vppclient" 10 | VPP_JSON_DIR = '/usr/share/vpp/api/core/' 11 | API_FILE_SUFFIX = '*.api.json' 12 | 13 | 14 | def load_json_api_files(json_dir=VPP_JSON_DIR, suffix=API_FILE_SUFFIX): 15 | jsonfiles = [] 16 | for root, dirnames, filenames in os.walk(json_dir): 17 | for filename in fnmatch.filter(filenames, suffix): 18 | jsonfiles.append(os.path.join(json_dir, filename)) 19 | 20 | if not jsonfiles: 21 | print('Error: no json api files found') 22 | exit(-1) 23 | 24 | return jsonfiles 25 | 26 | 27 | def connect_vpp(jsonfiles): 28 | vpp = vpp_papi.VPPApiClient(apifiles=jsonfiles) 29 | r = vpp.connect("CLIENT_ID") 30 | print("VPP api opened with code: %s" % r) 31 | return vpp 32 | 33 | 34 | def dump_interfaces(): 35 | print("Sending dump interfaces. Msg id: sw_interface_dump") 36 | for intf in vpp.api.sw_interface_dump(): 37 | print("\tInterface, message id: sw_interface_details, interface index: %s" % intf.interface_name.decode()) 38 | 39 | 40 | def dump_bds(): 41 | print("Sending dump bridge domains. Msg id: bridge_domain_dump") 42 | for intf in vpp.api.bridge_domain_dump(bd_id = int("ffffffff", 16)): 43 | print("\tBridge domain, message id: bridge_domain_details, bd index: %s" % intf.bd_id) 44 | 45 | 46 | def create_loopback(): 47 | print("Sending create loopback. Msg id: create_loopback_interface") 48 | vpp.api.create_loopback() 49 | 50 | 51 | def create_bd(): 52 | print("Sending create loopback. Msg id: create_loopback_interface") 53 | vpp.api.bridge_domain_add_del(is_add = 1, bd_id = 99) 54 | 55 | 56 | # Python apis need json definitions to interpret messages 57 | vpp = connect_vpp(load_json_api_files()) 58 | # Dump interfaces 59 | """ 60 | dump_interfaces() 61 | This function is not working at the moment feel free to correct the code 62 | """ 63 | # Create loopback 64 | create_loopback() 65 | # Dump interfaces 66 | dump_interfaces() 67 | # Dump bridge-domains 68 | dump_bds() 69 | # Create bridge domain 70 | create_bd() 71 | # Dump bridge-domains 72 | dump_bds() 73 | 74 | exit(vpp.disconnect()) 75 | --------------------------------------------------------------------------------