summaryrefslogtreecommitdiffstats
path: root/src
AgeCommit message (Collapse)AuthorFilesLines
2018-07-09vxlan:use bihash_16_8 for ipv4 lookupEyal Bari3-66/+76
Change-Id: I0d4630c88d6caacffcd073ebaa12766dfc893f70 Signed-off-by: Eyal Bari <ebari@cisco.com>
2018-07-09new pipe code does not use stdintsNeale Ranns1-2/+2
Change-Id: Idee565af852c7bb434b886fbf31c6e76315686c4 Signed-off-by: Neale Ranns <nranns@cisco.com>
2018-07-09Fix missing pipe.api.hMatthew Smith1-1/+2
Errors occur when building a library outside the VPP source tree that uses the shared memory API because vnet/devices/pipe/pipe.api.h is not installed but is included by vnet/vnet_all_api_h.h. In src/vnet.am, Add vnet/devices/pipe/pipe.api.h to nobase_include_HEADERS. Change-Id: Id3dc28d90f41bb0ff576736f9d77bee19a2b8fdd Signed-off-by: Matthew Smith <mgsmith@netgate.com>
2018-07-08Fix IPsec intf tx node setup at intf creationMatthew Smith1-2/+2
When using a DPDK cryptodev with IPsec, sending outbound packets results in a crash on division by zero if using an algorithm not supported by the OpenSSL ESP nodes. This includes AES-GCM and MD5. At IPsec intf creation time, the next node at slot IPSEC_OUTPUT_NEXT_ESP_ENCRYPT for ipsec_if_tx_node_fn is set to the node named esp-encrypt. This is the OpenSSL ESP encrypt function. If DPDK cryptodevs are configured, dpdk-esp-encrypt is the correct next node. Change to setting the next node according to the value in ipsec_main.esp_encrypt_node_index. That value is set to esp-encrypt by default. If DPDK cryptodevs are configured it gets set to dpdk-esp-encrypt. Change-Id: I83896c76b975d74aead247a162c85eccca9575a8 Signed-off-by: Matthew Smith <mgsmith@netgate.com>
2018-07-08session/svm: fix coverity warningsFlorin Coras2-3/+10
Change-Id: Ic5daed1f6c23d9561a04e235dcbf257f190d066a Signed-off-by: Florin Coras <fcoras@cisco.com>
2018-07-08vhost: Add multi-versioning supportMohsin Kazmi7-1536/+1675
It also refactors the vhost code which was in one big file vhost-user.c. Receive side code is in vhost_user_input.c and Transmit side code is in vhost_user_output.c Change-Id: I1b539b5008685889723e228265786a2a3e9f3a78 Signed-off-by: Mohsin Kazmi <sykazmi@cisco.com>
2018-07-07PipesNeale Ranns12-7/+1212
A pipe resembles a unix pipe. Each end of the pipe is a full VPP interface. pipes can be used for e.g. packet recirculation, inter-BD, etc. Change-Id: I185bb9fb43dd233ff45da63ac1b85ae2e1ceca16 Signed-off-by: Neale Ranns <neale.ranns@cisco.com>
2018-07-06svm: add unidirectional message queueFlorin Coras5-8/+510
Meant for single reader/writer message exchanges. Supports multiple message rings. Change-Id: I925de9a6ae19226c5c39a63caff76424ed123a13 Signed-off-by: Florin Coras <fcoras@cisco.com>
2018-07-05add stat segment size configurationDave Barach2-1/+29
Change-Id: I395ff9c91d670a9f9e50dc1b030e0412b7234de5 Signed-off-by: Dave Barach <dave@barachs.net>
2018-07-05vxlan:use bihash_24_8 for ipv6 lookupEyal Bari3-116/+167
* added the fib index into the key * conform coding style for vxlan.h * added "show vxlan tunnel raw" command to dump bihash Change-Id: Icc96e41abb648e96de5b4605b035f68f9e20f8a9 Signed-off-by: Eyal Bari <ebari@cisco.com>
2018-07-05VPP-1335 vapi crash when memclnt_keepalive receivedKlement Sekera6-18/+62
Change-Id: If33a7cc6c76147fd3ea9d8118370e7a508819b81 Signed-off-by: Klement Sekera <ksekera@cisco.com>
2018-07-04Fix clib_bitmap_next_clear() function when no clear bits leftJohn Lo1-0/+3
If the bitmap has no bit clear after the input bit position i, the function will return i even if its bit is set. Fix is to return the next bit just beyond the free bitmap. This can cause IP neighbor scan crash in ip_neighbor_scan() with a debug image. With production image, ip_neighbor_scan() may still function, AFAICT, with extra neighbor delete attempts for entries already deleted, until these entries are reused for new neighbors. Change-Id: If6422ef6f63908ea39651de4ccbd8cb0b294bd69 Signed-off-by: John Lo <loj@cisco.com>
2018-07-04fix VPP-1312 Invalid UDP packet length in ipsecKlement Sekera1-1/+2
Change-Id: Ibfd0a2e7010e6e74c32244c538f60e0713bea03f Signed-off-by: Klement Sekera <ksekera@cisco.com>
2018-07-04Do not override skip-cores if set in startup.confDamjan Marion1-4/+2
Change-Id: I97d75f58a46275fdad5add27dc59c731cc3ac64d Signed-off-by: Damjan Marion <damarion@cisco.com>
2018-07-04IP FIB dump - incorrect table-ID for deag pathsNeale Ranns1-1/+1
Change-Id: I383cfb662b4d2bf4f814e3eb9a1ce4d6bff7066d Signed-off-by: Neale Ranns <nranns@cisco.com>
2018-07-04Remove unused members from ip4_fib_tNeale Ranns2-9/+3
Change-Id: I8b92652d512bad5d774c7862f9808c306bbeff18 Signed-off-by: Neale Ranns <neale.ranns@cisco.com>
2018-07-04add 'src-lookup' keyword for FIB pathsNeale Ranns1-0/+4
Change-Id: I4554d1e94bd70ef5b3b0aaeb1a0fceaeb81c5f96 Signed-off-by: Neale Ranns <nranns@cisco.com>
2018-07-03Set main thread affinity before main heap is allocatedDamjan Marion2-7/+28
Change-Id: I524909570fc1736f51fd437d6d30566c461139bd Signed-off-by: Damjan Marion <damarion@cisco.com>
2018-07-03tcp: update snd_una_max for retranmsitsFlorin Coras3-4/+9
Change-Id: I0573d0aff39581bba96e610228a10ae923a8ca06 Signed-off-by: Florin Coras <fcoras@cisco.com>
2018-07-02Add per-numa page allocation info to 'show memory'Damjan Marion3-2/+71
Change-Id: I64e4e3d68c0f3958323f30b12a26cfaafa8bad85 Signed-off-by: Damjan Marion <damarion@cisco.com>
2018-07-02Fixing ip4-reassembly ip6-reassembly non feature node, next_node_index settingVijayabhaskar Katamreddy3-2/+2
Change-Id: Ib988d87e6758ffa31862096391f9f286b0797f2b Signed-off-by: Vijayabhaskar Katamreddy <vkatamre@cisco.com>
2018-06-30tcp: fix single loop prefetchFlorin Coras2-3/+9
Also add single loop prefetch in session tx Change-Id: Ib2725a2552fcc1a65050d7a2eb10491a7b34db62 Signed-off-by: Florin Coras <fcoras@cisco.com>
2018-06-30cli: Validate cli_file_index on quit commandSteve Shin1-0/+4
VPP crash happens with 'vppctl quit quit' command. The 2nd quit command tries to access the file index which is already freed by the first quit. This can be avoided to validate cli_file_index. Change-Id: I880514c93523db2a727d7510c97950582cd6a6c8 Signed-off-by: Steve Shin <jonshin@cisco.com>
2018-06-30session: send tx notification to appFlorin Coras3-188/+229
Does some session node cleanup as well Change-Id: Ifd52b07b28ba4dec1f6f729476decc76eb963837 Signed-off-by: Florin Coras <fcoras@cisco.com>
2018-06-30bitmap: add nocheck variants for bit opsFlorin Coras2-20/+54
Change-Id: Ifd155e2980a9f8e6af9bb6b08619c15b2bf18ef1 Signed-off-by: Florin Coras <fcoras@cisco.com>
2018-06-29memif: minor fixesDamjan Marion2-9/+9
Change-Id: Ib06d9ce0fad48b784fd47db13c7a2f353c845fca Signed-off-by: Damjan Marion <damarion@cisco.com>
2018-06-29VPP-1324 SIGSEGV vl_msg_api_handler_with_vm_node()Lukasz Majczak2-11/+21
Increase local arrays sizes to the correct number and gather missing statistics. Change-Id: If44d43f258730e9a18f50fb59fc526c214d2be8a Signed-off-by: Lukasz Majczak <lma@semihalf.com>
2018-06-29VPPAPIGEN: use SOURCE_DATE_EPOCH for datestringNirmoy Das1-1/+2
bwiedemann@suse.com pointed me that: For reproducible builds datestring should be generated using SOURCE_DATE_EPOCH which distributions set centrally, and have build tools that consume it to produce reproducible output. https://wiki.debian.org/ReproducibleBuilds/TimestampsProposal#Python Change-Id: Iefa2b93231bbc4c8af49736be4d7a5720c46b28d Signed-off-by: Nirmoy Das <nirmoy.aiemd@gmail.com>
2018-06-29CSIT-1148: VPPAPIGEN 2nd level import of .api ignoredOle Troan1-4/+5
Change-Id: I73dcab0c5ff2405b1fcba25975955e1267a4ac4e Signed-off-by: Ole Troan <ot@cisco.com>
2018-06-29ipsec: fix VPP-1333 - crash in ipsec policy cliKlement Sekera1-0/+6
Change-Id: I843d094b6bbd1cefba82d6026174be005e66d510 Signed-off-by: Klement Sekera <ksekera@cisco.com>
2018-06-29igmp: bugfix and minor improvementsJakub Grajciar5-76/+60
Change-Id: I8d284117a668dc55c06a6d68fe358a3d7e26c738 Signed-off-by: Jakub Grajciar <jgrajcia@cisco.com>
2018-06-29Removing the static keyword do_fragment routines, so that could be accessed ↵Vijayabhaskar Katamreddy2-3/+8
outside the ip_frag nodes Change-Id: I46d3d10fa763fcf7a579620ec7cf1b204a53bce8 Signed-off-by: Vijayabhaskar Katamreddy <vkatamre@cisco.com>
2018-06-29IP4 Router Alert option handling for IGMPNeale Ranns5-14/+157
and a new ip4-options node, inserted between ip4-input and ip4-punt, that checks for IP-router-alert option + IGMP combination and sends the packet to the ip4-local. This is required because some IGMP packets are sent to the group address and not the all-routers address. All IGMP packets are sent with the router alert option. Change-Id: I01f478d4d98ac9f806e0bcba0f6da6e4e7d26e2a Signed-off-by: Neale Ranns <nranns@cisco.com>
2018-06-29bihash key compare improvementsDamjan Marion3-12/+10
Looks like CPU doesn't like overlaping loads. This new codes in some cases shows 3-4 clock improvements. Change-Id: Ia1b49976ad95140c573f892fdc0a32eebbfa06c8 Signed-off-by: Damjan Marion <damarion@cisco.com>
2018-06-28vcl: move binary api and cfg to separate filesFlorin Coras9-1956/+2081
Change-Id: Ib88d703bb7d4b170059960b0688352c90c5fcc39 Signed-off-by: Florin Coras <fcoras@cisco.com>
2018-06-28Fix mheap_get_aligned() performance jackpotDave Barach2-3/+64
If non-trivial alignment (e.g. 64) requested, and the object size (e.g. 16) is smaller than (alignment_request - MHEAP_ELT_OVERHEAD_BYTES), round up the size request. This avoids creating remainder chunks, which are false-cache-line-sharing bait to begin with. Change-Id: Ie1a21286d29557d125bb346254b1be2def868b1a Signed-off-by: Dave Barach <dave@barachs.net>
2018-06-28vcl: refactor vcl sessionFlorin Coras2-201/+202
Change-Id: Idcba72fd84128547718dd32858e8c728925a6b1d Signed-off-by: Florin Coras <fcoras@cisco.com>
2018-06-28jvpp: pass tuple of classes to isinstance()Marek Gradzki1-3/+3
Change-Id: I887af26d7d6476d7d9e6fbaa671f923814aa03bb Signed-off-by: Marek Gradzki <mgradzki@cisco.com>
2018-06-28reassembly: optimize bihash usageKlement Sekera2-45/+38
Change-Id: I19690db9996ecb8c5e86415d2fd3c7133ce698f8 Signed-off-by: Klement Sekera <ksekera@cisco.com>
2018-06-28ip: vectorized ip checksumDamjan Marion3-69/+147
Change-Id: Ida678e6f31daa8decb18189da712a350336326e2 Signed-off-by: Damjan Marion <damarion@cisco.com>
2018-06-27vcl: refactor debuggingFlorin Coras3-1800/+756
Change-Id: I82e5239239ea24bdc97b1d59946ca0bba739f248 Signed-off-by: Florin Coras <fcoras@cisco.com>
2018-06-27Tune pool_get / pool_putDave Barach2-7/+56
Stop spending cycles repeatedly tail-trimming the pool free element bitmap; possibly at the expense of slightly hurting pool_foreach peformance. Change-Id: I8a7f3e7b26c71d7496ba9393b2a167dc7f538355 Signed-off-by: Dave Barach <dave@barachs.net>
2018-06-27acl: fix for loop initial declarationFlorin Coras1-1/+2
Change-Id: Ie899ccbaae4df7cce4ebbba47ed6c3cce5269bdb Signed-off-by: Florin Coras <fcoras@cisco.com>
2018-06-27avf: binary API and configurable RX/TX queue sizeJakub Grajciar10-13/+580
Change-Id: Ibd3a8d28d8f1df2bc14c42e48498f6ac26081192 Signed-off-by: Jakub Grajciar <jgrajcia@cisco.com>
2018-06-27gcc8 and Wstringop-truncationMarco Varlese4-9/+13
gcc8 introduced a new warning (Wstringop-truncation) which in our case is being treated as error. Disabling the warning globally might introduce bugs related to string truncation which are not desired by the developer (e.g. bug). Instead, this patch disables the warning only for those occurences which have been verified to be non-bugs but the desired behaviour as per developer will. Change-Id: I0f04ff6b4fad44061e80a65af633fd7e0148a0c5 Signed-off-by: Marco Varlese <marco.varlese@suse.com>
2018-06-27jvpp: cleanup generation of swap functions for custom typesMarek Gradzki1-8/+5
Change-Id: I2d06890ba25cfae9f96e820086f228286c807b42 Signed-off-by: Marek Gradzki <mgradzki@cisco.com>
2018-06-27jvpp: add support for unions (VPP-1322)Marek Gradzki6-50/+277
Change-Id: I2456a9b03bcae43793f9ac29eb74eff81269df7b Signed-off-by: Marek Gradzki <mgradzki@cisco.com>
2018-06-27vppinfra: add vector horizontal add and byte swap (SSE4.2 & AVX2)Damjan Marion2-0/+31
Change-Id: I4e0fd487970796f0153a5b16333827d23b57deac Signed-off-by: Damjan Marion <damarion@cisco.com>
2018-06-27acl-plugin: tm: avoid hash calculation dependency on a memory store operationAndrew Yourtchenko1-1/+9
A small store into a middle of a larger structure that was subsequently loaded for calculating the bihash key was noticeably impacting the performance. Change-Id: If7f33e1b66e8b438ba7cc91abc0ca749850c6e45 Signed-off-by: Andrew Yourtchenko <ayourtch@gmail.com>
2018-06-27acl-plugin: tm: add tuplemerge algorithm for relaxing the hashtable masksAndrew Yourtchenko3-5/+625
Slightly refactored from the initial implementation of the TupleMerge [1] algorithm by Valerio Bruschi (valerio.bruschi@telecom-paristech.fr) [1] James Daly, Eric Torng "TupleMerge: Building Online Packet Classifiers by Omitting Bits", In Proc. IEEE ICCCN 2017, pp. 1-10 Also add startup parameters to turn on/off the algorithm ("use tuple merge 1/0"), and a startup parameter to be able to tweak the split threshold ("tuple merge split threshold N"), the default value of the split threshold is 39 as per paper, but some more tuning might be necessary to find the best value. This change, alongside with the optimizations which avoid extra lookups, significantly reduces the slowdown on the ClassBench generated ACLs, which are supposed to resemble realistic ACLs seen in use in the field. Change-Id: I9713e4673970e9a62d4d9e9718365293375fab7b Signed-off-by: Andrew Yourtchenko <ayourtch@gmail.com>
tick */ .highlight .sc { color: #e6db74 } /* Literal.String.Char */ .highlight .dl { color: #e6db74 } /* Literal.String.Delimiter */ .highlight .sd { color: #e6db74 } /* Literal.String.Doc */ .highlight .s2 { color: #e6db74 } /* Literal.String.Double */ .highlight .se { color: #ae81ff } /* Literal.String.Escape */ .highlight .sh { color: #e6db74 } /* Literal.String.Heredoc */ .highlight .si { color: #e6db74 } /* Literal.String.Interpol */ .highlight .sx { color: #e6db74 } /* Literal.String.Other */ .highlight .sr { color: #e6db74 } /* Literal.String.Regex */ .highlight .s1 { color: #e6db74 } /* Literal.String.Single */ .highlight .ss { color: #e6db74 } /* Literal.String.Symbol */ .highlight .bp { color: #f8f8f2 } /* Name.Builtin.Pseudo */ .highlight .fm { color: #a6e22e } /* Name.Function.Magic */ .highlight .vc { color: #f8f8f2 } /* Name.Variable.Class */ .highlight .vg { color: #f8f8f2 } /* Name.Variable.Global */ .highlight .vi { color: #f8f8f2 } /* Name.Variable.Instance */ .highlight .vm { color: #f8f8f2 } /* Name.Variable.Magic */ .highlight .il { color: #ae81ff } /* Literal.Number.Integer.Long */ } @media (prefers-color-scheme: light) { .highlight .hll { background-color: #ffffcc } .highlight .c { color: #888888 } /* Comment */ .highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */ .highlight .k { color: #008800; font-weight: bold } /* Keyword */ .highlight .ch { color: #888888 } /* Comment.Hashbang */ .highlight .cm { color: #888888 } /* Comment.Multiline */ .highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */ .highlight .cpf { color: #888888 } /* Comment.PreprocFile */ .highlight .c1 { color: #888888 } /* Comment.Single */ .highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */ .highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */ .highlight .ge { font-style: italic } /* Generic.Emph */ .highlight .gr { color: #aa0000 } /* Generic.Error */ .highlight .gh { color: #333333 } /* Generic.Heading */ .highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */ .highlight .go { color: #888888 } /* Generic.Output */ .highlight .gp { color: #555555 } /* Generic.Prompt */ .highlight .gs { font-weight: bold } /* Generic.Strong */ .highlight .gu { color: #666666 } /* Generic.Subheading */ .highlight .gt { color: #aa0000 } /* Generic.Traceback */ .highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */ .highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */ .highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */ .highlight .kp { color: #008800 } /* Keyword.Pseudo */ .highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */ .highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */ .highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */ .highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */ .highlight .na { color: #336699 } /* Name.Attribute */ .highlight .nb { color: #003388 } /* Name.Builtin */ .highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */ .highlight .no { color: #003366; font-weight: bold } /* Name.Constant */ .highlight .nd { color: #555555 } /* Name.Decorator */ .highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */ .highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */ .highlight .nl { color: #336699; font-style: italic } /* Name.Label */ .highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */ .highlight .py { color: #336699; font-weight: bold } /* Name.Property */ .highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */ .highlight .nv { color: #336699 } /* Name.Variable */ .highlight .ow { color: #008800 } /* Operator.Word */ .highlight .w { color: #bbbbbb } /* Text.Whitespace */ .highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */ .highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */ .highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */ .highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */ .highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */ .highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */ .highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */ .highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */ .highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */ .highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */ .highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */ .highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */ .highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */ .highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */ .highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */ .highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */ .highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */ .highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */ .highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */ .highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */ .highlight .vc { color: #336699 } /* Name.Variable.Class */ .highlight .vg { color: #dd7700 } /* Name.Variable.Global */ .highlight .vi { color: #3333bb } /* Name.Variable.Instance */ .highlight .vm { color: #336699 } /* Name.Variable.Magic */ .highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */ }
/*
 *------------------------------------------------------------------
 * Copyright (c) 2021 Cisco and/or its affiliates.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at:
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *------------------------------------------------------------------
 */

#include <vat/vat.h>
#include <vlibapi/api.h>
#include <vlibmemory/api.h>
#include <vppinfra/error.h>
#include <vpp/api/types.h>

#include <vnet/ip/ip_types_api.h>

#define __plugin_msg_base interface_test_main.msg_id_base
#include <vlibapi/vat_helper_macros.h>

/* Declare message IDs */
#include <vnet/format_fns.h>
#include <vnet/interface.api_enum.h>
#include <vnet/interface.api_types.h>
#include <vlibmemory/vlib.api_types.h>
#include <vlibmemory/memclnt.api_enum.h>

#define vl_endianfun /* define message structures */
#include <vnet/interface.api.h>
#undef vl_endianfun

typedef struct
{
  /* API message ID base */
  u16 msg_id_base;
  vat_main_t *vat_main;
} interface_test_main_t;

static interface_test_main_t interface_test_main;

static int
api_sw_interface_set_flags (vat_main_t *vam)
{
  unformat_input_t *i = vam->input;
  vl_api_sw_interface_set_flags_t *mp;
  u32 sw_if_index;
  u8 sw_if_index_set = 0;
  u8 admin_up = 0;
  int ret;

  /* Parse args required to build the message */
  while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
    {
      if (unformat (i, "admin-up"))
	admin_up = 1;
      else if (unformat (i, "admin-down"))
	admin_up = 0;
      else if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
	sw_if_index_set = 1;
      else if (unformat (i, "sw_if_index %d", &sw_if_index))
	sw_if_index_set = 1;
      else
	break;
    }

  if (sw_if_index_set == 0)
    {
      errmsg ("missing interface name or sw_if_index");
      return -99;
    }

  /* Construct the API message */
  M (SW_INTERFACE_SET_FLAGS, mp);
  mp->sw_if_index = ntohl (sw_if_index);
  mp->flags = ntohl ((admin_up) ? IF_STATUS_API_FLAG_ADMIN_UP : 0);

  /* send it... */
  S (mp);

  /* Wait for a reply, return the good/bad news... */
  W (ret);
  return ret;
}

static int
api_hw_interface_set_mtu (vat_main_t *vam)
{
  unformat_input_t *i = vam->input;
  vl_api_hw_interface_set_mtu_t *mp;
  u32 sw_if_index = ~0;
  u32 mtu = 0;
  int ret;

  while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
    {
      if (unformat (i, "mtu %d", &mtu))
	;
      if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
	;
      else if (unformat (i, "sw_if_index %d", &sw_if_index))
	;
      else
	break;
    }

  if (sw_if_index == ~0)
    {
      errmsg ("missing interface name or sw_if_index");
      return -99;
    }

  if (mtu == 0)
    {
      errmsg ("no mtu specified");
      return -99;
    }

  /* Construct the API message */
  M (HW_INTERFACE_SET_MTU, mp);
  mp->sw_if_index = ntohl (sw_if_index);
  mp->mtu = ntohs ((u16) mtu);

  S (mp);
  W (ret);
  return ret;
}

static int
api_sw_interface_tag_add_del (vat_main_t *vam)
{
  unformat_input_t *i = vam->input;
  vl_api_sw_interface_tag_add_del_t *mp;
  u32 sw_if_index = ~0;
  u8 *tag = 0;
  u8 enable = 1;
  int ret;

  while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
    {
      if (unformat (i, "tag %s", &tag))
	;
      if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
	;
      else if (unformat (i, "sw_if_index %d", &sw_if_index))
	;
      else if (unformat (i, "del"))
	enable = 0;
      else
	break;
    }

  if (sw_if_index == ~0)
    {
      errmsg ("missing interface name or sw_if_index");
      return -99;
    }

  if (enable && (tag == 0))
    {
      errmsg ("no tag specified");
      return -99;
    }

  /* Construct the API message */
  M (SW_INTERFACE_TAG_ADD_DEL, mp);
  mp->sw_if_index = ntohl (sw_if_index);
  mp->is_add = enable;
  if (enable)
    strncpy ((char *) mp->tag, (char *) tag, ARRAY_LEN (mp->tag) - 1);
  vec_free (tag);

  S (mp);
  W (ret);
  return ret;
}

static int
api_sw_interface_add_del_mac_address (vat_main_t *vam)
{
  unformat_input_t *i = vam->input;
  vl_api_mac_address_t mac = { 0 };
  vl_api_sw_interface_add_del_mac_address_t *mp;
  u32 sw_if_index = ~0;
  u8 is_add = 1;
  u8 mac_set = 0;
  int ret;

  while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
    {
      if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
	;
      else if (unformat (i, "sw_if_index %d", &sw_if_index))
	;
      else if (unformat (i, "%U", unformat_vl_api_mac_address, &mac))
	mac_set++;
      else if (unformat (i, "del"))
	is_add = 0;
      else
	break;
    }

  if (sw_if_index == ~0)
    {
      errmsg ("missing interface name or sw_if_index");
      return -99;
    }

  if (!mac_set)
    {
      errmsg ("missing MAC address");
      return -99;
    }

  /* Construct the API message */
  M (SW_INTERFACE_ADD_DEL_MAC_ADDRESS, mp);
  mp->sw_if_index = ntohl (sw_if_index);
  mp->is_add = is_add;
  clib_memcpy (&mp->addr, &mac, sizeof (mac));

  S (mp);
  W (ret);
  return ret;
}

static void
vl_api_sw_interface_details_t_handler (vl_api_sw_interface_details_t *mp)
{
  vat_main_t *vam = &vat_main;
  u8 *s = format (0, "%s%c", mp->interface_name, 0);

  hash_set_mem (vam->sw_if_index_by_interface_name, s,
		ntohl (mp->sw_if_index));

  /* In sub interface case, fill the sub interface table entry */
  if (mp->sw_if_index != mp->sup_sw_if_index)
    {
      sw_interface_subif_t *sub = NULL;

      vec_add2 (vam->sw_if_subif_table, sub, 1);

      vec_validate (sub->interface_name, strlen ((char *) s) + 1);
      strncpy ((char *) sub->interface_name, (char *) s,
	       vec_len (sub->interface_name));
      sub->sw_if_index = ntohl (mp->sw_if_index);
      sub->sub_id = ntohl (mp->sub_id);

      sub->raw_flags = ntohl (mp->sub_if_flags & SUB_IF_API_FLAG_MASK_VNET);

      sub->sub_number_of_tags = mp->sub_number_of_tags;
      sub->sub_outer_vlan_id = ntohs (mp->sub_outer_vlan_id);
      sub->sub_inner_vlan_id = ntohs (mp->sub_inner_vlan_id);

      /* vlan tag rewrite */
      sub->vtr_op = ntohl (mp->vtr_op);
      sub->vtr_push_dot1q = ntohl (mp->vtr_push_dot1q);
      sub->vtr_tag1 = ntohl (mp->vtr_tag1);
      sub->vtr_tag2 = ntohl (mp->vtr_tag2);
    }
}

static int
api_sw_interface_get_mac_address (vat_main_t *vat)
{
  return -1;
}

static void
vl_api_sw_interface_get_mac_address_reply_t_handler (
  vl_api_sw_interface_get_mac_address_reply_t *mp)
{
}

static int
api_sw_interface_add_del_address (vat_main_t *vam)
{
  unformat_input_t *i = vam->input;
  vl_api_sw_interface_add_del_address_t *mp;
  u32 sw_if_index;
  u8 sw_if_index_set = 0;
  u8 is_add = 1, del_all = 0;
  u32 address_length = 0;
  u8 v4_address_set = 0;
  u8 v6_address_set = 0;
  ip4_address_t v4address;
  ip6_address_t v6address;
  int ret;

  /* Parse args required to build the message */
  while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
    {
      if (unformat (i, "del-all"))
	del_all = 1;
      else if (unformat (i, "del"))
	is_add = 0;
      else if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
	sw_if_index_set = 1;
      else if (unformat (i, "sw_if_index %d", &sw_if_index))
	sw_if_index_set = 1;
      else if (unformat (i, "%U/%d", unformat_ip4_address, &v4address,
			 &address_length))
	v4_address_set = 1;
      else if (unformat (i, "%U/%d", unformat_ip6_address, &v6address,
			 &address_length))
	v6_address_set = 1;
      else
	break;
    }

  if (sw_if_index_set == 0)
    {
      errmsg ("missing interface name or sw_if_index");
      return -99;
    }
  if (v4_address_set && v6_address_set)
    {
      errmsg ("both v4 and v6 addresses set");
      return -99;
    }
  if (!v4_address_set && !v6_address_set && !del_all)
    {
      errmsg ("no addresses set");
      return -99;
    }

  /* Construct the API message */
  M (SW_INTERFACE_ADD_DEL_ADDRESS, mp);

  mp->sw_if_index = ntohl (sw_if_index);
  mp->is_add = is_add;
  mp->del_all = del_all;
  if (v6_address_set)
    {
      mp->prefix.address.af = ADDRESS_IP6;
      clib_memcpy (mp->prefix.address.un.ip6, &v6address, sizeof (v6address));
    }
  else
    {
      mp->prefix.address.af = ADDRESS_IP4;
      clib_memcpy (mp->prefix.address.un.ip4, &v4address, sizeof (v4address));
    }
  mp->prefix.len = address_length;

  /* send it... */
  S (mp);

  /* Wait for a reply, return good/bad news  */
  W (ret);
  return ret;
}

static int
api_sw_interface_get_table (vat_main_t *vam)
{
  unformat_input_t *i = vam->input;
  vl_api_sw_interface_get_table_t *mp;
  u32 sw_if_index;
  u8 sw_if_index_set = 0;
  u8 is_ipv6 = 0;
  int ret;

  while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
    {
      if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
	sw_if_index_set = 1;
      else if (unformat (i, "sw_if_index %d", &sw_if_index))
	sw_if_index_set = 1;
      else if (unformat (i, "ipv6"))
	is_ipv6 = 1;
      else
	break;
    }

  if (sw_if_index_set == 0)
    {
      errmsg ("missing interface name or sw_if_index");
      return -99;
    }

  M (SW_INTERFACE_GET_TABLE, mp);
  mp->sw_if_index = htonl (sw_if_index);
  mp->is_ipv6 = is_ipv6;

  S (mp);
  W (ret);
  return ret;
}

static int
api_sw_interface_set_rx_mode (vat_main_t *vam)
{
  unformat_input_t *i = vam->input;
  vl_api_sw_interface_set_rx_mode_t *mp;
  u32 sw_if_index;
  u8 sw_if_index_set = 0;
  int ret;
  u8 queue_id_valid = 0;
  u32 queue_id;
  vnet_hw_if_rx_mode mode = VNET_HW_IF_RX_MODE_UNKNOWN;

  /* Parse args required to build the message */
  while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
    {
      if (unformat (i, "queue %d", &queue_id))
	queue_id_valid = 1;
      else if (unformat (i, "polling"))
	mode = VNET_HW_IF_RX_MODE_POLLING;
      else if (unformat (i, "interrupt"))
	mode = VNET_HW_IF_RX_MODE_INTERRUPT;
      else if (unformat (i, "adaptive"))
	mode = VNET_HW_IF_RX_MODE_ADAPTIVE;
      else if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
	sw_if_index_set = 1;
      else if (unformat (i, "sw_if_index %d", &sw_if_index))
	sw_if_index_set = 1;
      else
	break;
    }

  if (sw_if_index_set == 0)
    {
      errmsg ("missing interface name or sw_if_index");
      return -99;
    }
  if (mode == VNET_HW_IF_RX_MODE_UNKNOWN)
    {
      errmsg ("missing rx-mode");
      return -99;
    }

  /* Construct the API message */
  M (SW_INTERFACE_SET_RX_MODE, mp);
  mp->sw_if_index = ntohl (sw_if_index);
  mp->mode = (vl_api_rx_mode_t) mode;
  mp->queue_id_valid = queue_id_valid;
  mp->queue_id = queue_id_valid ? ntohl (queue_id) : ~0;

  /* send it... */
  S (mp);

  /* Wait for a reply, return the good/bad news... */
  W (ret);
  return ret;
}

static int
api_sw_interface_set_unnumbered (vat_main_t *vam)
{
  unformat_input_t *i = vam->input;
  vl_api_sw_interface_set_unnumbered_t *mp;
  u32 sw_if_index;
  u32 unnum_sw_index = ~0;
  u8 is_add = 1;
  u8 sw_if_index_set = 0;
  int ret;

  while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
    {
      if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
	sw_if_index_set = 1;
      else if (unformat (i, "sw_if_index %d", &sw_if_index))
	sw_if_index_set = 1;
      else if (unformat (i, "unnum_if_index %d", &unnum_sw_index))
	;
      else if (unformat (i, "del"))
	is_add = 0;
      else
	{
	  clib_warning ("parse error '%U'", format_unformat_error, i);
	  return -99;
	}
    }

  if (sw_if_index_set == 0)
    {
      errmsg ("missing interface name or sw_if_index");
      return -99;
    }

  M (SW_INTERFACE_SET_UNNUMBERED, mp);

  mp->sw_if_index = ntohl (sw_if_index);
  mp->unnumbered_sw_if_index = ntohl (unnum_sw_index);
  mp->is_add = is_add;

  S (mp);
  W (ret);
  return ret;
}

static void
vl_api_sw_interface_get_table_reply_t_handler (
  vl_api_sw_interface_get_table_reply_t *mp)
{
  vat_main_t *vam = interface_test_main.vat_main;

  fformat (vam->ofp, "%d", ntohl (mp->vrf_id));

  vam->retval = ntohl (mp->retval);
  vam->result_ready = 1;
}

static int
api_sw_interface_address_replace_begin (vat_main_t *vam)
{
  return -1;
}

static int
api_sw_interface_set_mac_address (vat_main_t *vam)
{
  return -1;
}

static int
api_sw_interface_set_rx_placement (vat_main_t *vam)
{
  unformat_input_t *i = vam->input;
  vl_api_sw_interface_set_rx_placement_t *mp;
  u32 sw_if_index;
  u8 sw_if_index_set = 0;
  int ret;
  u8 is_main = 0;
  u32 queue_id, thread_index;

  /* Parse args required to build the message */
  while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
    {
      if (unformat (i, "queue %d", &queue_id))
	;
      else if (unformat (i, "main"))
	is_main = 1;
      else if (unformat (i, "worker %d", &thread_index))
	;
      else if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
	sw_if_index_set = 1;
      else if (unformat (i, "sw_if_index %d", &sw_if_index))
	sw_if_index_set = 1;
      else
	break;
    }

  if (sw_if_index_set == 0)
    {
      errmsg ("missing interface name or sw_if_index");
      return -99;
    }

  if (is_main)
    thread_index = 0;
  /* Construct the API message */
  M (SW_INTERFACE_SET_RX_PLACEMENT, mp);
  mp->sw_if_index = ntohl (sw_if_index);
  mp->worker_id = ntohl (thread_index);
  mp->queue_id = ntohl (queue_id);
  mp->is_main = is_main;

  /* send it... */
  S (mp);
  /* Wait for a reply, return the good/bad news... */
  W (ret);
  return ret;
}

static int
api_sw_interface_set_tx_placement (vat_main_t *vam)
{
  unformat_input_t *i = vam->input;
  vl_api_sw_interface_set_tx_placement_t *mp;
  u32 sw_if_index;
  u8 sw_if_index_set = 0;
  int ret;
  uword *bitmap = 0;
  u32 queue_id, n_bits = 0;
  u32 v;

  /* Parse args required to build the message */
  while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
    {
      if (unformat (i, "queue %d", &queue_id))
	;
      else if (unformat (i, "threads %U", unformat_bitmap_list, &bitmap))
	;
      else if (unformat (i, "mask %U", unformat_bitmap_mask, &bitmap))
	;
      else if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
	sw_if_index_set = 1;
      else if (unformat (i, "sw_if_index %d", &sw_if_index))
	sw_if_index_set = 1;
      else
	break;
    }

  if (sw_if_index_set == 0)
    {
      errmsg ("missing interface name or sw_if_index");
      return -99;
    }

  n_bits = clib_bitmap_count_set_bits (bitmap);
  /* Construct the API message */
  M2 (SW_INTERFACE_SET_TX_PLACEMENT, mp, sizeof (u32) * n_bits);
  mp->sw_if_index = htonl (sw_if_index);
  mp->queue_id = htonl (queue_id);
  mp->array_size = htonl (n_bits);

  v = clib_bitmap_first_set (bitmap);
  for (u32 j = 0; j < n_bits; j++)
    {
      mp->threads[j] = htonl (v);
      v = clib_bitmap_next_set (bitmap, v + 1);
    }

  /* send it... */
  S (mp);
  /* Wait for a reply, return the good/bad news... */
  W (ret);
  clib_bitmap_free (bitmap);
  return ret;
}

static int
api_interface_name_renumber (vat_main_t *vam)
{
  unformat_input_t *line_input = vam->input;
  vl_api_interface_name_renumber_t *mp;
  u32 sw_if_index = ~0;
  u32 new_show_dev_instance = ~0;
  int ret;

  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
    {
      if (unformat (line_input, "%U", api_unformat_sw_if_index, vam,
		    &sw_if_index))
	;
      else if (unformat (line_input, "sw_if_index %d", &sw_if_index))
	;
      else if (unformat (line_input, "new_show_dev_instance %d",
			 &new_show_dev_instance))
	;
      else
	break;
    }

  if (sw_if_index == ~0)
    {
      errmsg ("missing interface name or sw_if_index");
      return -99;
    }

  if (new_show_dev_instance == ~0)
    {
      errmsg ("missing new_show_dev_instance");
      return -99;
    }

  M (INTERFACE_NAME_RENUMBER, mp);

  mp->sw_if_index = ntohl (sw_if_index);
  mp->new_show_dev_instance = ntohl (new_show_dev_instance);

  S (mp);
  W (ret);
  return ret;
}

static int
api_delete_subif (vat_main_t *vam)
{
  unformat_input_t *i = vam->input;
  vl_api_delete_subif_t *mp;
  u32 sw_if_index = ~0;
  int ret;

  while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
    {
      if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
	;
      if (unformat (i, "sw_if_index %d", &sw_if_index))
	;
      else
	break;
    }

  if (sw_if_index == ~0)
    {
      errmsg ("missing sw_if_index");
      return -99;
    }

  /* Construct the API message */
  M (DELETE_SUBIF, mp);
  mp->sw_if_index = ntohl (sw_if_index);

  S (mp);
  W (ret);
  return ret;
}

static int
api_delete_loopback (vat_main_t *vam)
{
  unformat_input_t *i = vam->input;
  vl_api_delete_loopback_t *mp;
  u32 sw_if_index = ~0;
  int ret;

  while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
    {
      if (unformat (i, "sw_if_index %d", &sw_if_index))
	;
      else
	break;
    }

  if (sw_if_index == ~0)
    {
      errmsg ("missing sw_if_index");
      return -99;
    }

  /* Construct the API message */
  M (DELETE_LOOPBACK, mp);
  mp->sw_if_index = ntohl (sw_if_index);

  S (mp);
  W (ret);
  return ret;
}

static int
api_create_loopback_instance (vat_main_t *vat)
{
  return -1;
}

static int
api_create_loopback (vat_main_t *vam)
{
  unformat_input_t *i = vam->input;
  vl_api_create_loopback_t *mp;
  vl_api_create_loopback_instance_t *mp_lbi;
  u8 mac_address[6];
  u8 mac_set = 0;
  u8 is_specified = 0;
  u32 user_instance = 0;
  int ret;

  clib_memset (mac_address, 0, sizeof (mac_address));

  while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
    {
      if (unformat (i, "mac %U", unformat_ethernet_address, mac_address))
	mac_set = 1;
      if (unformat (i, "instance %d", &user_instance))
	is_specified = 1;
      else
	break;
    }

  if (is_specified)
    {
      M (CREATE_LOOPBACK_INSTANCE, mp_lbi);
      mp_lbi->is_specified = is_specified;
      if (is_specified)
	mp_lbi->user_instance = htonl (user_instance);
      if (mac_set)
	clib_memcpy (mp_lbi->mac_address, mac_address, sizeof (mac_address));
      S (mp_lbi);
    }
  else
    {
      /* Construct the API message */
      M (CREATE_LOOPBACK, mp);
      if (mac_set)
	clib_memcpy (mp->mac_address, mac_address, sizeof (mac_address));
      S (mp);
    }

  W (ret);
  return ret;
}

static void
vl_api_create_subif_reply_t_handler (vl_api_create_subif_reply_t *mp)
{
  vat_main_t *vam = interface_test_main.vat_main;
  vam->result_ready = 1;
}

#define foreach_create_subif_bit                                              \
  _ (no_tags)                                                                 \
  _ (one_tag)                                                                 \
  _ (two_tags)                                                                \
  _ (dot1ad)                                                                  \
  _ (exact_match)                                                             \
  _ (default_sub)                                                             \
  _ (outer_vlan_id_any)                                                       \
  _ (inner_vlan_id_any)

#define foreach_create_subif_flag                                             \
  _ (0, "no_tags")                                                            \
  _ (1, "one_tag")                                                            \
  _ (2, "two_tags")                                                           \
  _ (3, "dot1ad")                                                             \
  _ (4, "exact_match")                                                        \
  _ (5, "default_sub")                                                        \
  _ (6, "outer_vlan_id_any")                                                  \
  _ (7, "inner_vlan_id_any")

static int
api_create_subif (vat_main_t *vam)
{
  unformat_input_t *i = vam->input;
  vl_api_create_subif_t *mp;
  u32 sw_if_index;
  u8 sw_if_index_set = 0;
  u32 sub_id;
  u8 sub_id_set = 0;
  u32 __attribute__ ((unused)) no_tags = 0;
  u32 __attribute__ ((unused)) one_tag = 0;
  u32 __attribute__ ((unused)) two_tags = 0;
  u32 __attribute__ ((unused)) dot1ad = 0;
  u32 __attribute__ ((unused)) exact_match = 0;
  u32 __attribute__ ((unused)) default_sub = 0;
  u32 __attribute__ ((unused)) outer_vlan_id_any = 0;
  u32 __attribute__ ((unused)) inner_vlan_id_any = 0;
  u32 tmp;
  u16 outer_vlan_id = 0;
  u16 inner_vlan_id = 0;
  int ret;

  while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
    {
      if (unformat (i, "sw_if_index %d", &sw_if_index))
	sw_if_index_set = 1;
      else if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
	sw_if_index_set = 1;
      else if (unformat (i, "sub_id %d", &sub_id))
	sub_id_set = 1;
      else if (unformat (i, "outer_vlan_id %d", &tmp))
	outer_vlan_id = tmp;
      else if (unformat (i, "inner_vlan_id %d", &tmp))
	inner_vlan_id = tmp;

#define _(a) else if (unformat (i, #a)) a = 1;
      foreach_create_subif_bit
#undef _
	else
      {
	clib_warning ("parse error '%U'", format_unformat_error, i);
	return -99;
      }
    }

  if (sw_if_index_set == 0)
    {
      errmsg ("missing interface name or sw_if_index");
      return -99;
    }

  if (sub_id_set == 0)
    {
      errmsg ("missing sub_id");
      return -99;
    }
  M (CREATE_SUBIF, mp);

  mp->sw_if_index = ntohl (sw_if_index);
  mp->sub_id = ntohl (sub_id);

#define _(a, b) mp->sub_if_flags |= (1 << a);
  foreach_create_subif_flag;
#undef _

  mp->outer_vlan_id = ntohs (outer_vlan_id);
  mp->inner_vlan_id = ntohs (inner_vlan_id);

  S (mp);
  W (ret);
  return ret;
}

static void
vl_api_sw_interface_rx_placement_details_t_handler (
  vl_api_sw_interface_rx_placement_details_t *mp)
{
  vat_main_t *vam = interface_test_main.vat_main;
  u32 worker_id = ntohl (mp->worker_id);

  print (vam->ofp, "\n%-11d %-11s %-6d %-5d %-9s", ntohl (mp->sw_if_index),
	 (worker_id == 0) ? "main" : "worker", worker_id, ntohl (mp->queue_id),
	 (mp->mode == 1) ? "polling" :
			   ((mp->mode == 2) ? "interrupt" : "adaptive"));
}

static __clib_unused void
vl_api_sw_interface_tx_placement_details_t_handler (
  vl_api_sw_interface_tx_placement_details_t *mp)
{
  vat_main_t *vam = interface_test_main.vat_main;
  u32 size = ntohl (mp->array_size);
  uword *bitmap = 0;

  for (u32 i = 0; i < size; i++)
    {
      u32 thread_index = ntohl (mp->threads[i]);
      bitmap = clib_bitmap_set (bitmap, thread_index, 1);
    }

  print (vam->ofp, "\n%-11d %-6d %-7s %U", ntohl (mp->sw_if_index),
	 ntohl (mp->queue_id), (mp->shared == 1) ? "yes" : "no",
	 format_bitmap_list, bitmap);
}

static void
vl_api_create_vlan_subif_reply_t_handler (vl_api_create_vlan_subif_reply_t *mp)
{
  vat_main_t *vam = interface_test_main.vat_main;
  vam->result_ready = 1;
}

static void
vl_api_create_loopback_reply_t_handler (vl_api_create_loopback_reply_t *mp)
{
  vat_main_t *vam = interface_test_main.vat_main;
  vam->result_ready = 1;
}

static void
vl_api_create_loopback_instance_reply_t_handler (
  vl_api_create_loopback_instance_reply_t *mp)
{
  vat_main_t *vam = interface_test_main.vat_main;
  vam->result_ready = 1;
}

static int
api_create_vlan_subif (vat_main_t *vam)
{
  unformat_input_t *i = vam->input;
  vl_api_create_vlan_subif_t *mp;
  u32 sw_if_index;
  u8 sw_if_index_set = 0;
  u32 vlan_id;
  u8 vlan_id_set = 0;
  int ret;

  while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
    {
      if (unformat (i, "sw_if_index %d", &sw_if_index))
	sw_if_index_set = 1;
      else if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
	sw_if_index_set = 1;
      else if (unformat (i, "vlan %d", &vlan_id))
	vlan_id_set = 1;
      else
	{
	  clib_warning ("parse error '%U'", format_unformat_error, i);
	  return -99;
	}
    }

  if (sw_if_index_set == 0)
    {
      errmsg ("missing interface name or sw_if_index");
      return -99;
    }

  if (vlan_id_set == 0)
    {
      errmsg ("missing vlan_id");
      return -99;
    }
  M (CREATE_VLAN_SUBIF, mp);

  mp->sw_if_index = ntohl (sw_if_index);
  mp->vlan_id = ntohl (vlan_id);

  S (mp);
  W (ret);
  return ret;
}

static int
api_collect_detailed_interface_stats (vat_main_t *vam)
{
  return -1;
}

static int
api_sw_interface_rx_placement_dump (vat_main_t *vam)
{
  unformat_input_t *i = vam->input;
  vl_api_sw_interface_rx_placement_dump_t *mp;
  vl_api_control_ping_t *mp_ping;
  int ret;
  u32 sw_if_index;
  u8 sw_if_index_set = 0;

  while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
    {
      if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
	sw_if_index_set++;
      else if (unformat (i, "sw_if_index %d", &sw_if_index))
	sw_if_index_set++;
      else
	break;
    }

  fformat (vam->ofp, "\n%-11s %-11s %-6s %-5s %-4s", "sw_if_index",
	   "main/worker", "thread", "queue", "mode");

  /* Dump Interface rx placement */
  M (SW_INTERFACE_RX_PLACEMENT_DUMP, mp);

  if (sw_if_index_set)
    mp->sw_if_index = htonl (sw_if_index);
  else
    mp->sw_if_index = ~0;

  S (mp);

  /* Use a control ping for synchronization */
  PING (&interface_test_main, mp_ping);
  S (mp_ping);

  W (ret);
  return ret;
}

static int
api_sw_interface_tx_placement_get (vat_main_t *vam)
{
  unformat_input_t *i = vam->input;
  vl_api_sw_interface_tx_placement_get_t *mp;
  vl_api_control_ping_t *mp_ping;
  int ret;
  u32 sw_if_index;
  u8 sw_if_index_set = 0;

  while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
    {
      if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
	sw_if_index_set++;
      else if (unformat (i, "sw_if_index %d", &sw_if_index))
	sw_if_index_set++;
      else
	break;
    }

  fformat (vam->ofp, "\n%-11s %-6s %-7s %-11s", "sw_if_index", "queue",
	   "shared", "threads");

  /* Dump Interface tx placement */
  M (SW_INTERFACE_TX_PLACEMENT_GET, mp);

  if (sw_if_index_set)
    mp->sw_if_index = htonl (sw_if_index);
  else
    mp->sw_if_index = ~0;

  S (mp);

  /* Use a control ping for synchronization */
  PING (&interface_test_main, mp_ping);
  S (mp_ping);

  W (ret);
  return ret;
}

static void
vl_api_sw_interface_tx_placement_get_reply_t_handler ()
{
}

static int
api_sw_interface_clear_stats (vat_main_t *vam)
{
  unformat_input_t *i = vam->input;
  vl_api_sw_interface_clear_stats_t *mp;
  u32 sw_if_index;
  u8 sw_if_index_set = 0;
  int ret;

  /* Parse args required to build the message */
  while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
    {
      if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
	sw_if_index_set = 1;
      else if (unformat (i, "sw_if_index %d", &sw_if_index))
	sw_if_index_set = 1;
      else
	break;
    }

  /* Construct the API message */
  M (SW_INTERFACE_CLEAR_STATS, mp);

  if (sw_if_index_set == 1)
    mp->sw_if_index = ntohl (sw_if_index);
  else
    mp->sw_if_index = ~0;

  /* send it... */
  S (mp);

  /* Wait for a reply, return the good/bad news... */
  W (ret);
  return ret;
}

static int
api_sw_interface_set_table (vat_main_t *vam)
{
  unformat_input_t *i = vam->input;
  vl_api_sw_interface_set_table_t *mp;
  u32 sw_if_index, vrf_id = 0;
  u8 sw_if_index_set = 0;
  u8 is_ipv6 = 0;
  int ret;

  /* Parse args required to build the message */
  while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
    {
      if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
	sw_if_index_set = 1;
      else if (unformat (i, "sw_if_index %d", &sw_if_index))
	sw_if_index_set = 1;
      else if (unformat (i, "vrf %d", &vrf_id))
	;
      else if (unformat (i, "ipv6"))
	is_ipv6 = 1;
      else
	break;
    }

  if (sw_if_index_set == 0)
    {
      errmsg ("missing interface name or sw_if_index");
      return -99;
    }

  /* Construct the API message */
  M (SW_INTERFACE_SET_TABLE, mp);

  mp->sw_if_index = ntohl (sw_if_index);
  mp->is_ipv6 = is_ipv6;
  mp->vrf_id = ntohl (vrf_id);

  /* send it... */
  S (mp);

  /* Wait for a reply... */
  W (ret);
  return ret;
}

static int
api_sw_interface_address_replace_end (vat_main_t *vam)
{
  return -1;
}

static int
api_sw_interface_set_ip_directed_broadcast (vat_main_t *vam)
{
  return -1;
}

static int
api_sw_interface_set_mtu (vat_main_t *vam)
{
  return -1;
}

static int
api_sw_interface_set_promisc (vat_main_t *vam)
{
  return -1;
}

static int
api_want_interface_events (vat_main_t *vam)
{
  unformat_input_t *i = vam->input;
  vl_api_want_interface_events_t *mp;
  int enable = -1;
  int ret;

  while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
    {
      if (unformat (i, "enable"))
	enable = 1;
      else if (unformat (i, "disable"))
	enable = 0;
      else
	break;
    }

  if (enable == -1)
    {
      errmsg ("missing enable|disable");
      return -99;
    }

  M (WANT_INTERFACE_EVENTS, mp);
  mp->enable_disable = enable;

  vam->interface_event_display = enable;

  S (mp);
  W (ret);
  return ret;
}

typedef struct
{
  u8 *name;
  u32 value;
} name_sort_t;

int
api_sw_interface_dump (vat_main_t *vam)
{
  vl_api_sw_interface_dump_t *mp;
  vl_api_control_ping_t *mp_ping;
  hash_pair_t *p;
  name_sort_t *nses = 0, *ns;
  sw_interface_subif_t *sub = NULL;
  int ret;

  /* Toss the old name table */
  hash_foreach_pair (p, vam->sw_if_index_by_interface_name, ({
		       vec_add2 (nses, ns, 1);
		       ns->name = (u8 *) (p->key);
		       ns->value = (u32) p->value[0];
		     }));

  hash_free (vam->sw_if_index_by_interface_name);

  vec_foreach (ns, nses)
    vec_free (ns->name);

  vec_free (nses);

  vec_foreach (sub, vam->sw_if_subif_table)
    {
      vec_free (sub->interface_name);
    }
  vec_free (vam->sw_if_subif_table);

  /* recreate the interface name hash table */
  vam->sw_if_index_by_interface_name = hash_create_string (0, sizeof (uword));

  /*
   * Ask for all interface names. Otherwise, the epic catalog of
   * name filters becomes ridiculously long, and vat ends up needing
   * to be taught about new interface types.
   */
  M (SW_INTERFACE_DUMP, mp);
  S (mp);

  /* Use a control ping for synchronization */
  PING (&interface_test_main, mp_ping);
  S (mp_ping);

  W (ret);
  return ret;
}

static int
api_sw_interface_set_interface_name (vat_main_t *vam)
{
  return -1;
}

#include <vnet/interface.api_test.c>

/*
 * Local Variables:
 * eval: (c-set-style "gnu")
 * End:
 */