bond: Add bonding driver and LACP protocol
[vpp.git] / src / vat / api_format.c
index 4c13e11..019d095 100644 (file)
@@ -19,7 +19,6 @@
 
 #include <vat/vat.h>
 #include <vppinfra/socket.h>
-#include <svm/memfd.h>
 #include <vlibapi/api.h>
 #include <vlibmemory/api.h>
 #include <vnet/ip/ip.h>
@@ -34,7 +33,7 @@
 #include <vpp/api/vpe_msg_enum.h>
 #include <vnet/l2/l2_classify.h>
 #include <vnet/l2/l2_vtr.h>
-#include <vnet/classify/input_acl.h>
+#include <vnet/classify/in_out_acl.h>
 #include <vnet/classify/policer_classify.h>
 #include <vnet/classify/flow_classify.h>
 #include <vnet/mpls/mpls.h>
@@ -51,7 +50,7 @@
 #include <vnet/policer/police.h>
 #include <vnet/mfib/mfib_types.h>
 #include <vnet/dhcp/dhcp_proxy.h>
-
+#include <vnet/bonding/node.h>
 #include "vat/json_format.h"
 
 #include <inttypes.h>
@@ -1349,9 +1348,9 @@ vl_api_l2_macs_event_t_handler (vl_api_l2_macs_event_t * mp)
   for (i = 0; i < n_macs; i++)
     {
       vl_api_mac_entry_t *mac = &mp->mac[i];
-      errmsg (" [%d] sw_if_index %d  mac_addr %U  is_del %d \n",
+      errmsg (" [%d] sw_if_index %d  mac_addr %U  action %d \n",
              i + 1, ntohl (mac->sw_if_index),
-             format_ethernet_address, mac->mac_addr, mac->is_del);
+             format_ethernet_address, mac->mac_addr, mac->action);
       if (i == 1000)
        break;
     }
@@ -1776,6 +1775,275 @@ static void vl_api_tap_delete_v2_reply_t_handler_json
   vam->result_ready = 1;
 }
 
+static void
+vl_api_bond_create_reply_t_handler (vl_api_bond_create_reply_t * mp)
+{
+  vat_main_t *vam = &vat_main;
+  i32 retval = ntohl (mp->retval);
+
+  if (vam->async_mode)
+    {
+      vam->async_errors += (retval < 0);
+    }
+  else
+    {
+      vam->retval = retval;
+      vam->sw_if_index = ntohl (mp->sw_if_index);
+      vam->result_ready = 1;
+    }
+}
+
+static void vl_api_bond_create_reply_t_handler_json
+  (vl_api_bond_create_reply_t * mp)
+{
+  vat_main_t *vam = &vat_main;
+  vat_json_node_t node;
+
+  vat_json_init_object (&node);
+  vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
+  vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index));
+
+  vat_json_print (vam->ofp, &node);
+  vat_json_free (&node);
+
+  vam->retval = ntohl (mp->retval);
+  vam->result_ready = 1;
+}
+
+static void
+vl_api_bond_delete_reply_t_handler (vl_api_bond_delete_reply_t * mp)
+{
+  vat_main_t *vam = &vat_main;
+  i32 retval = ntohl (mp->retval);
+
+  if (vam->async_mode)
+    {
+      vam->async_errors += (retval < 0);
+    }
+  else
+    {
+      vam->retval = retval;
+      vam->result_ready = 1;
+    }
+}
+
+static void vl_api_bond_delete_reply_t_handler_json
+  (vl_api_bond_delete_reply_t * mp)
+{
+  vat_main_t *vam = &vat_main;
+  vat_json_node_t node;
+
+  vat_json_init_object (&node);
+  vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
+
+  vat_json_print (vam->ofp, &node);
+  vat_json_free (&node);
+
+  vam->retval = ntohl (mp->retval);
+  vam->result_ready = 1;
+}
+
+static void
+vl_api_bond_enslave_reply_t_handler (vl_api_bond_enslave_reply_t * mp)
+{
+  vat_main_t *vam = &vat_main;
+  i32 retval = ntohl (mp->retval);
+
+  if (vam->async_mode)
+    {
+      vam->async_errors += (retval < 0);
+    }
+  else
+    {
+      vam->retval = retval;
+      vam->result_ready = 1;
+    }
+}
+
+static void vl_api_bond_enslave_reply_t_handler_json
+  (vl_api_bond_enslave_reply_t * mp)
+{
+  vat_main_t *vam = &vat_main;
+  vat_json_node_t node;
+
+  vat_json_init_object (&node);
+  vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
+
+  vat_json_print (vam->ofp, &node);
+  vat_json_free (&node);
+
+  vam->retval = ntohl (mp->retval);
+  vam->result_ready = 1;
+}
+
+static void
+vl_api_bond_detach_slave_reply_t_handler (vl_api_bond_detach_slave_reply_t *
+                                         mp)
+{
+  vat_main_t *vam = &vat_main;
+  i32 retval = ntohl (mp->retval);
+
+  if (vam->async_mode)
+    {
+      vam->async_errors += (retval < 0);
+    }
+  else
+    {
+      vam->retval = retval;
+      vam->result_ready = 1;
+    }
+}
+
+static void vl_api_bond_detach_slave_reply_t_handler_json
+  (vl_api_bond_detach_slave_reply_t * mp)
+{
+  vat_main_t *vam = &vat_main;
+  vat_json_node_t node;
+
+  vat_json_init_object (&node);
+  vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
+
+  vat_json_print (vam->ofp, &node);
+  vat_json_free (&node);
+
+  vam->retval = ntohl (mp->retval);
+  vam->result_ready = 1;
+}
+
+static void vl_api_sw_interface_bond_details_t_handler
+  (vl_api_sw_interface_bond_details_t * mp)
+{
+  vat_main_t *vam = &vat_main;
+
+  print (vam->ofp,
+        "%-16s %-12d %-12U %-13U %-14u %-14u",
+        mp->interface_name, ntohl (mp->sw_if_index),
+        format_bond_mode, mp->mode, format_bond_load_balance, mp->lb,
+        ntohl (mp->active_slaves), ntohl (mp->slaves));
+}
+
+static void vl_api_sw_interface_bond_details_t_handler_json
+  (vl_api_sw_interface_bond_details_t * mp)
+{
+  vat_main_t *vam = &vat_main;
+  vat_json_node_t *node = NULL;
+
+  if (VAT_JSON_ARRAY != vam->json_tree.type)
+    {
+      ASSERT (VAT_JSON_NONE == vam->json_tree.type);
+      vat_json_init_array (&vam->json_tree);
+    }
+  node = vat_json_array_add (&vam->json_tree);
+
+  vat_json_init_object (node);
+  vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
+  vat_json_object_add_string_copy (node, "interface_name",
+                                  mp->interface_name);
+  vat_json_object_add_uint (node, "mode", mp->mode);
+  vat_json_object_add_uint (node, "load_balance", mp->lb);
+  vat_json_object_add_uint (node, "active_slaves", ntohl (mp->active_slaves));
+  vat_json_object_add_uint (node, "slaves", ntohl (mp->slaves));
+}
+
+static int
+api_sw_interface_bond_dump (vat_main_t * vam)
+{
+  vl_api_sw_interface_bond_dump_t *mp;
+  vl_api_control_ping_t *mp_ping;
+  int ret;
+
+  print (vam->ofp,
+        "\n%-16s %-12s %-12s %-13s %-14s %-14s",
+        "interface name", "sw_if_index", "mode", "load balance",
+        "active slaves", "slaves");
+
+  /* Get list of bond interfaces */
+  M (SW_INTERFACE_BOND_DUMP, mp);
+  S (mp);
+
+  /* Use a control ping for synchronization */
+  MPING (CONTROL_PING, mp_ping);
+  S (mp_ping);
+
+  W (ret);
+  return ret;
+}
+
+static void vl_api_sw_interface_slave_details_t_handler
+  (vl_api_sw_interface_slave_details_t * mp)
+{
+  vat_main_t *vam = &vat_main;
+
+  print (vam->ofp,
+        "%-25s %-12d %-12d %d", mp->interface_name,
+        ntohl (mp->sw_if_index), mp->is_passive, mp->is_long_timeout);
+}
+
+static void vl_api_sw_interface_slave_details_t_handler_json
+  (vl_api_sw_interface_slave_details_t * mp)
+{
+  vat_main_t *vam = &vat_main;
+  vat_json_node_t *node = NULL;
+
+  if (VAT_JSON_ARRAY != vam->json_tree.type)
+    {
+      ASSERT (VAT_JSON_NONE == vam->json_tree.type);
+      vat_json_init_array (&vam->json_tree);
+    }
+  node = vat_json_array_add (&vam->json_tree);
+
+  vat_json_init_object (node);
+  vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
+  vat_json_object_add_string_copy (node, "interface_name",
+                                  mp->interface_name);
+  vat_json_object_add_uint (node, "passive", mp->is_passive);
+  vat_json_object_add_uint (node, "long_timeout", mp->is_long_timeout);
+}
+
+static int
+api_sw_interface_slave_dump (vat_main_t * vam)
+{
+  unformat_input_t *i = vam->input;
+  vl_api_sw_interface_slave_dump_t *mp;
+  vl_api_control_ping_t *mp_ping;
+  u32 sw_if_index = ~0;
+  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;
+    }
+
+  if (sw_if_index_set == 0)
+    {
+      errmsg ("missing vpp interface name. ");
+      return -99;
+    }
+
+  print (vam->ofp,
+        "\n%-25s %-12s %-12s %s",
+        "slave interface name", "sw_if_index", "passive", "long_timeout");
+
+  /* Get list of bond interfaces */
+  M (SW_INTERFACE_SLAVE_DUMP, mp);
+  mp->sw_if_index = ntohl (sw_if_index);
+  S (mp);
+
+  /* Use a control ping for synchronization */
+  MPING (CONTROL_PING, mp_ping);
+  S (mp_ping);
+
+  W (ret);
+  return ret;
+}
+
 static void vl_api_mpls_tunnel_add_del_reply_t_handler
   (vl_api_mpls_tunnel_add_del_reply_t * mp)
 {
@@ -1984,6 +2252,7 @@ static void vl_api_vxlan_add_del_tunnel_reply_t_handler
       vam->sw_if_index = ntohl (mp->sw_if_index);
       vam->result_ready = 1;
     }
+  vam->regenerate_interface_table = 1;
 }
 
 static void vl_api_vxlan_add_del_tunnel_reply_t_handler_json
@@ -2052,6 +2321,7 @@ static void vl_api_vxlan_gpe_add_del_tunnel_reply_t_handler
       vam->sw_if_index = ntohl (mp->sw_if_index);
       vam->result_ready = 1;
     }
+  vam->regenerate_interface_table = 1;
 }
 
 static void vl_api_vxlan_gpe_add_del_tunnel_reply_t_handler_json
@@ -2120,6 +2390,7 @@ static void vl_api_create_vhost_user_if_reply_t_handler
       vam->sw_if_index = ntohl (mp->sw_if_index);
       vam->result_ready = 1;
     }
+  vam->regenerate_interface_table = 1;
 }
 
 static void vl_api_create_vhost_user_if_reply_t_handler_json
@@ -2203,7 +2474,7 @@ static void vl_api_memfd_segment_create_reply_t_handler
   socket_client_main_t *scm = vam->socket_client_main;
   int my_fd = -1;
   clib_error_t *error;
-  memfd_private_t memfd;
+  ssvm_private_t memfd;
   i32 retval = ntohl (mp->retval);
 
   if (retval == 0)
@@ -2221,7 +2492,7 @@ static void vl_api_memfd_segment_create_reply_t_handler
       vam->client_index_invalid = 1;
 
       /* Note: this closes memfd.fd */
-      retval = memfd_slave_init (&memfd);
+      retval = ssvm_slave_init_memfd (&memfd);
       if (retval)
        clib_warning ("WARNING: segment map returned %d", retval);
 
@@ -5162,6 +5433,7 @@ static void vl_api_ipsec_gre_add_del_tunnel_reply_t_handler
       vam->sw_if_index = ntohl (mp->sw_if_index);
       vam->result_ready = 1;
     }
+  vam->regenerate_interface_table = 1;
 }
 
 static void vl_api_ipsec_gre_add_del_tunnel_reply_t_handler_json
@@ -5388,7 +5660,8 @@ _(tcp_configure_src_addresses_reply)                      \
 _(dns_enable_disable_reply)                             \
 _(dns_name_server_add_del_reply)                       \
 _(session_rule_add_del_reply)                          \
-_(ip_container_proxy_add_del_reply)
+_(ip_container_proxy_add_del_reply)                     \
+_(output_acl_set_interface_reply)
 
 #define _(n)                                    \
     static void vl_api_##n##_t_handler          \
@@ -5462,6 +5735,12 @@ _(SW_INTERFACE_TAP_DETAILS, sw_interface_tap_details)                   \
 _(TAP_CREATE_V2_REPLY, tap_create_v2_reply)                            \
 _(TAP_DELETE_V2_REPLY, tap_delete_v2_reply)                            \
 _(SW_INTERFACE_TAP_V2_DETAILS, sw_interface_tap_v2_details)             \
+_(BOND_CREATE_REPLY, bond_create_reply)                                        \
+_(BOND_DELETE_REPLY, bond_delete_reply)                                        \
+_(BOND_ENSLAVE_REPLY, bond_enslave_reply)                              \
+_(BOND_DETACH_SLAVE_REPLY, bond_detach_slave_reply)                    \
+_(SW_INTERFACE_BOND_DETAILS, sw_interface_bond_details)                 \
+_(SW_INTERFACE_SLAVE_DETAILS, sw_interface_slave_details)               \
 _(IP_ADD_DEL_ROUTE_REPLY, ip_add_del_route_reply)                      \
 _(IP_TABLE_ADD_DEL_REPLY, ip_table_add_del_reply)                      \
 _(IP_MROUTE_ADD_DEL_REPLY, ip_mroute_add_del_reply)                    \
@@ -5716,6 +5995,7 @@ _(DNS_RESOLVE_IP_REPLY, dns_resolve_ip_reply)                             \
 _(SESSION_RULE_ADD_DEL_REPLY, session_rule_add_del_reply)              \
 _(SESSION_RULES_DETAILS, session_rules_details)                                \
 _(IP_CONTAINER_PROXY_ADD_DEL_REPLY, ip_container_proxy_add_del_reply)  \
+_(OUTPUT_ACL_SET_INTERFACE_REPLY, output_acl_set_interface_reply)       \
 
 #define foreach_standalone_reply_msg                                   \
 _(SW_INTERFACE_EVENT, sw_interface_event)                               \
@@ -6329,73 +6609,12 @@ api_sw_interface_dump (vat_main_t * vam)
   /* recreate the interface name hash table */
   vam->sw_if_index_by_interface_name = hash_create_string (0, sizeof (uword));
 
-  /* Get list of ethernets */
-  M (SW_INTERFACE_DUMP, mp);
-  mp->name_filter_valid = 1;
-  strncpy ((char *) mp->name_filter, "Ether", sizeof (mp->name_filter) - 1);
-  S (mp);
-
-  /* and local / loopback interfaces */
-  M (SW_INTERFACE_DUMP, mp);
-  mp->name_filter_valid = 1;
-  strncpy ((char *) mp->name_filter, "lo", sizeof (mp->name_filter) - 1);
-  S (mp);
-
-  /* and packet-generator interfaces */
-  M (SW_INTERFACE_DUMP, mp);
-  mp->name_filter_valid = 1;
-  strncpy ((char *) mp->name_filter, "pg", sizeof (mp->name_filter) - 1);
-  S (mp);
-
-  /* and vxlan-gpe tunnel interfaces */
-  M (SW_INTERFACE_DUMP, mp);
-  mp->name_filter_valid = 1;
-  strncpy ((char *) mp->name_filter, "vxlan_gpe",
-          sizeof (mp->name_filter) - 1);
-  S (mp);
-
-  /* and vxlan tunnel interfaces */
-  M (SW_INTERFACE_DUMP, mp);
-  mp->name_filter_valid = 1;
-  strncpy ((char *) mp->name_filter, "vxlan", sizeof (mp->name_filter) - 1);
-  S (mp);
-
-  /* and geneve tunnel interfaces */
-  M (SW_INTERFACE_DUMP, mp);
-  mp->name_filter_valid = 1;
-  strncpy ((char *) mp->name_filter, "geneve", sizeof (mp->name_filter) - 1);
-  S (mp);
-
-  /* and host (af_packet) interfaces */
-  M (SW_INTERFACE_DUMP, mp);
-  mp->name_filter_valid = 1;
-  strncpy ((char *) mp->name_filter, "host", sizeof (mp->name_filter) - 1);
-  S (mp);
-
-  /* and l2tpv3 tunnel interfaces */
-  M (SW_INTERFACE_DUMP, mp);
-  mp->name_filter_valid = 1;
-  strncpy ((char *) mp->name_filter, "l2tpv3_tunnel",
-          sizeof (mp->name_filter) - 1);
-  S (mp);
-
-  /* and GRE tunnel interfaces */
-  M (SW_INTERFACE_DUMP, mp);
-  mp->name_filter_valid = 1;
-  strncpy ((char *) mp->name_filter, "gre", sizeof (mp->name_filter) - 1);
-  S (mp);
-
-  /* and LISP-GPE interfaces */
-  M (SW_INTERFACE_DUMP, mp);
-  mp->name_filter_valid = 1;
-  strncpy ((char *) mp->name_filter, "lisp_gpe",
-          sizeof (mp->name_filter) - 1);
-  S (mp);
-
-  /* and IPSEC tunnel interfaces */
+  /*
+   * 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);
-  mp->name_filter_valid = 1;
-  strncpy ((char *) mp->name_filter, "ipsec", sizeof (mp->name_filter) - 1);
   S (mp);
 
   /* Use a control ping for synchronization */
@@ -7830,11 +8049,15 @@ api_tap_create_v2 (vat_main_t * vam)
   u8 host_mac_addr_set = 0;
   u8 *host_bridge = 0;
   ip4_address_t host_ip4_addr;
+  ip4_address_t host_ip4_gw;
+  u8 host_ip4_gw_set = 0;
   u32 host_ip4_prefix_len = 0;
   ip6_address_t host_ip6_addr;
+  ip6_address_t host_ip6_gw;
+  u8 host_ip6_gw_set = 0;
   u32 host_ip6_prefix_len = 0;
   int ret;
-  int rx_ring_sz = 0, tx_ring_sz = 0;
+  u32 rx_ring_sz = 0, tx_ring_sz = 0;
 
   memset (mac_address, 0, sizeof (mac_address));
 
@@ -7845,7 +8068,7 @@ api_tap_create_v2 (vat_main_t * vam)
        {
          random_mac = 0;
        }
-      else if (unformat (i, "id %s", &id))
+      else if (unformat (i, "id %u", &id))
        ;
       else if (unformat (i, "host-if-name %s", &host_if_name))
        ;
@@ -7862,6 +8085,12 @@ api_tap_create_v2 (vat_main_t * vam)
       else if (unformat (i, "host-ip6-addr %U/%d", unformat_ip6_address,
                         &host_ip6_addr, &host_ip6_prefix_len))
        ;
+      else if (unformat (i, "host-ip4-gw %U", unformat_ip4_address,
+                        &host_ip4_gw))
+       host_ip4_gw_set = 1;
+      else if (unformat (i, "host-ip6-gw %U", unformat_ip6_address,
+                        &host_ip6_gw))
+       host_ip6_gw_set = 1;
       else if (unformat (i, "rx-ring-size %d", &rx_ring_sz))
        ;
       else if (unformat (i, "tx-ring-size %d", &tx_ring_sz))
@@ -7921,15 +8150,15 @@ api_tap_create_v2 (vat_main_t * vam)
 
   mp->use_random_mac = random_mac;
 
-  mp->id = id;
+  mp->id = ntohl (id);
   mp->host_namespace_set = host_ns != 0;
   mp->host_bridge_set = host_bridge != 0;
   mp->host_ip4_addr_set = host_ip4_prefix_len != 0;
   mp->host_ip6_addr_set = host_ip6_prefix_len != 0;
-  mp->rx_ring_sz = rx_ring_sz;
-  mp->tx_ring_sz = tx_ring_sz;
+  mp->rx_ring_sz = ntohs (rx_ring_sz);
+  mp->tx_ring_sz = ntohs (tx_ring_sz);
 
-  if (random_mac)
+  if (random_mac == 0)
     clib_memcpy (mp->mac_address, mac_address, 6);
   if (host_mac_addr_set)
     clib_memcpy (mp->host_mac_addr, host_mac_addr, 6);
@@ -7943,7 +8172,10 @@ api_tap_create_v2 (vat_main_t * vam)
     clib_memcpy (mp->host_ip4_addr, &host_ip4_addr, 4);
   if (host_ip4_prefix_len)
     clib_memcpy (mp->host_ip6_addr, &host_ip6_addr, 16);
-
+  if (host_ip4_gw_set)
+    clib_memcpy (mp->host_ip4_gw, &host_ip4_gw, 4);
+  if (host_ip6_gw_set)
+    clib_memcpy (mp->host_ip6_gw, &host_ip6_gw, 16);
 
   vec_free (host_ns);
   vec_free (host_if_name);
@@ -7996,6 +8228,194 @@ api_tap_delete_v2 (vat_main_t * vam)
   return ret;
 }
 
+static int
+api_bond_create (vat_main_t * vam)
+{
+  unformat_input_t *i = vam->input;
+  vl_api_bond_create_t *mp;
+  u8 mac_address[6];
+  u8 custom_mac = 0;
+  int ret;
+  u8 mode;
+  u8 lb;
+  u8 mode_is_set = 0;
+
+  memset (mac_address, 0, sizeof (mac_address));
+  lb = BOND_LB_L2;
+
+  /* Parse args required to build the message */
+  while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
+    {
+      if (unformat (i, "mode %U", unformat_bond_mode, &mode))
+       mode_is_set = 1;
+      else if (((mode == BOND_MODE_LACP) || (mode == BOND_MODE_XOR))
+              && unformat (i, "lb %U", unformat_bond_load_balance, &lb))
+       ;
+      else if (unformat (i, "hw-addr %U", unformat_ethernet_address,
+                        mac_address))
+       custom_mac = 1;
+      else
+       break;
+    }
+
+  if (mode_is_set == 0)
+    {
+      errmsg ("Missing bond mode. ");
+      return -99;
+    }
+
+  /* Construct the API message */
+  M (BOND_CREATE, mp);
+
+  mp->use_custom_mac = custom_mac;
+
+  mp->mode = mode;
+  mp->lb = lb;
+
+  if (custom_mac)
+    clib_memcpy (mp->mac_address, mac_address, 6);
+
+  /* send it... */
+  S (mp);
+
+  /* Wait for a reply... */
+  W (ret);
+  return ret;
+}
+
+static int
+api_bond_delete (vat_main_t * vam)
+{
+  unformat_input_t *i = vam->input;
+  vl_api_bond_delete_t *mp;
+  u32 sw_if_index = ~0;
+  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;
+    }
+
+  if (sw_if_index_set == 0)
+    {
+      errmsg ("missing vpp interface name. ");
+      return -99;
+    }
+
+  /* Construct the API message */
+  M (BOND_DELETE, mp);
+
+  mp->sw_if_index = ntohl (sw_if_index);
+
+  /* send it... */
+  S (mp);
+
+  /* Wait for a reply... */
+  W (ret);
+  return ret;
+}
+
+static int
+api_bond_enslave (vat_main_t * vam)
+{
+  unformat_input_t *i = vam->input;
+  vl_api_bond_enslave_t *mp;
+  u32 bond_sw_if_index;
+  int ret;
+  u8 is_passive;
+  u8 is_long_timeout;
+  u32 bond_sw_if_index_is_set = 0;
+  u32 sw_if_index;
+  u8 sw_if_index_is_set = 0;
+
+  /* Parse args required to build the message */
+  while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
+    {
+      if (unformat (i, "sw_if_index %d", &sw_if_index))
+       sw_if_index_is_set = 1;
+      else if (unformat (i, "bond %u", &bond_sw_if_index))
+       bond_sw_if_index_is_set = 1;
+      else if (unformat (i, "passive %d", &is_passive))
+       ;
+      else if (unformat (i, "long-timeout %d", &is_long_timeout))
+       ;
+      else
+       break;
+    }
+
+  if (bond_sw_if_index_is_set == 0)
+    {
+      errmsg ("Missing bond sw_if_index. ");
+      return -99;
+    }
+  if (sw_if_index_is_set == 0)
+    {
+      errmsg ("Missing slave sw_if_index. ");
+      return -99;
+    }
+
+  /* Construct the API message */
+  M (BOND_ENSLAVE, mp);
+
+  mp->bond_sw_if_index = ntohl (bond_sw_if_index);
+  mp->sw_if_index = ntohl (sw_if_index);
+  mp->is_long_timeout = is_long_timeout;
+  mp->is_passive = is_passive;
+
+  /* send it... */
+  S (mp);
+
+  /* Wait for a reply... */
+  W (ret);
+  return ret;
+}
+
+static int
+api_bond_detach_slave (vat_main_t * vam)
+{
+  unformat_input_t *i = vam->input;
+  vl_api_bond_detach_slave_t *mp;
+  u32 sw_if_index = ~0;
+  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;
+    }
+
+  if (sw_if_index_set == 0)
+    {
+      errmsg ("missing vpp interface name. ");
+      return -99;
+    }
+
+  /* Construct the API message */
+  M (BOND_DETACH_SLAVE, mp);
+
+  mp->sw_if_index = ntohl (sw_if_index);
+
+  /* send it... */
+  S (mp);
+
+  /* Wait for a reply... */
+  W (ret);
+  return ret;
+}
+
 static int
 api_ip_table_add_del (vat_main_t * vam)
 {
@@ -8915,7 +9335,7 @@ api_bier_route_add_del (vat_main_t * vam)
     }
 
   /* Construct the API message */
-  M2 (BIER_ROUTE_ADD_DEL, mp, sizeof (vl_api_fib_path3_t));
+  M2 (BIER_ROUTE_ADD_DEL, mp, sizeof (vl_api_fib_path_t));
 
   mp->br_is_add = is_add;
   mp->br_tbl_id.bt_set = set;
@@ -8924,7 +9344,7 @@ api_bier_route_add_del (vat_main_t * vam)
   mp->br_bp = ntohs (bp);
   mp->br_n_paths = 1;
   mp->br_paths[0].n_labels = 1;
-  mp->br_paths[0].label_stack[0] = ntohl (next_hop_out_label);
+  mp->br_paths[0].label_stack[0].label = ntohl (next_hop_out_label);
   mp->br_paths[0].afi = (next_hop_proto_is_ip4 ? 0 : 1);
 
   if (next_hop_proto_is_ip4)
@@ -9589,7 +10009,7 @@ vl_api_dhcp_proxy_details_t_handler (vl_api_dhcp_proxy_details_t * mp)
   if (mp->is_ipv6)
     print (vam->ofp,
           "RX Table-ID %d, Source Address %U, VSS Type %d, "
-          "VSS VPN-ID '%s', VSS FIB-ID %d, VSS OUI %d",
+          "VSS ASCII VPN-ID '%s', VSS RFC2685 VPN-ID (oui:id) %d:%d",
           ntohl (mp->rx_vrf_id),
           format_ip6_address, mp->dhcp_src_address,
           mp->vss_type, mp->vss_vpn_ascii_id,
@@ -9597,7 +10017,7 @@ vl_api_dhcp_proxy_details_t_handler (vl_api_dhcp_proxy_details_t * mp)
   else
     print (vam->ofp,
           "RX Table-ID %d, Source Address %U, VSS Type %d, "
-          "VSS VPN-ID '%s', VSS FIB-ID %d, VSS OUI %d",
+          "VSS ASCII VPN-ID '%s', VSS RFC2685 VPN-ID (oui:id) %d:%d",
           ntohl (mp->rx_vrf_id),
           format_ip4_address, mp->dhcp_src_address,
           mp->vss_type, mp->vss_vpn_ascii_id,
@@ -12555,6 +12975,7 @@ api_vxlan_add_del_tunnel (vat_main_t * vam)
   u8 src_set = 0;
   u8 dst_set = 0;
   u8 grp_set = 0;
+  u32 instance = ~0;
   u32 mcast_sw_if_index = ~0;
   u32 encap_vrf_id = 0;
   u32 decap_next_index = ~0;
@@ -12569,6 +12990,8 @@ api_vxlan_add_del_tunnel (vat_main_t * vam)
     {
       if (unformat (line_input, "del"))
        is_add = 0;
+      else if (unformat (line_input, "instance %d", &instance))
+       ;
       else
        if (unformat (line_input, "src %U", unformat_ip4_address, &src.ip4))
        {
@@ -12688,6 +13111,8 @@ api_vxlan_add_del_tunnel (vat_main_t * vam)
       clib_memcpy (mp->src_address, &src.ip4, sizeof (src.ip4));
       clib_memcpy (mp->dst_address, &dst.ip4, sizeof (dst.ip4));
     }
+
+  mp->instance = htonl (instance);
   mp->encap_vrf_id = ntohl (encap_vrf_id);
   mp->decap_next_index = ntohl (decap_next_index);
   mp->mcast_sw_if_index = ntohl (mcast_sw_if_index);
@@ -12707,8 +13132,9 @@ static void vl_api_vxlan_tunnel_details_t_handler
   ip46_address_t src = to_ip46 (mp->is_ipv6, mp->dst_address);
   ip46_address_t dst = to_ip46 (mp->is_ipv6, mp->src_address);
 
-  print (vam->ofp, "%11d%24U%24U%14d%18d%13d%19d",
+  print (vam->ofp, "%11d%11d%24U%24U%14d%18d%13d%19d",
         ntohl (mp->sw_if_index),
+        ntohl (mp->instance),
         format_ip46_address, &src, IP46_TYPE_ANY,
         format_ip46_address, &dst, IP46_TYPE_ANY,
         ntohl (mp->encap_vrf_id),
@@ -12731,6 +13157,9 @@ static void vl_api_vxlan_tunnel_details_t_handler_json
 
   vat_json_init_object (node);
   vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
+
+  vat_json_object_add_uint (node, "instance", ntohl (mp->instance));
+
   if (mp->is_ipv6)
     {
       struct in6_addr ip6;
@@ -12784,8 +13213,8 @@ api_vxlan_tunnel_dump (vat_main_t * vam)
 
   if (!vam->json_output)
     {
-      print (vam->ofp, "%11s%24s%24s%14s%18s%13s%19s",
-            "sw_if_index", "src_address", "dst_address",
+      print (vam->ofp, "%11s%11s%24s%24s%14s%18s%13s%19s",
+            "sw_if_index", "instance", "src_address", "dst_address",
             "encap_vrf_id", "decap_next_index", "vni", "mcast_sw_if_index");
     }
 
@@ -13089,10 +13518,12 @@ api_gre_add_del_tunnel (vat_main_t * vam)
   u8 is_add = 1;
   u8 ipv4_set = 0;
   u8 ipv6_set = 0;
-  u8 teb = 0;
+  u8 t_type = GRE_TUNNEL_TYPE_L3;
   u8 src_set = 0;
   u8 dst_set = 0;
   u32 outer_fib_id = 0;
+  u32 session_id = 0;
+  u32 instance = ~0;
   int ret;
 
   memset (&src4, 0, sizeof src4);
@@ -13104,6 +13535,8 @@ api_gre_add_del_tunnel (vat_main_t * vam)
     {
       if (unformat (line_input, "del"))
        is_add = 0;
+      else if (unformat (line_input, "instance %d", &instance))
+       ;
       else if (unformat (line_input, "src %U", unformat_ip4_address, &src4))
        {
          src_set = 1;
@@ -13127,7 +13560,9 @@ api_gre_add_del_tunnel (vat_main_t * vam)
       else if (unformat (line_input, "outer-fib-id %d", &outer_fib_id))
        ;
       else if (unformat (line_input, "teb"))
-       teb = 1;
+       t_type = GRE_TUNNEL_TYPE_TEB;
+      else if (unformat (line_input, "erspan %d", &session_id))
+       t_type = GRE_TUNNEL_TYPE_ERSPAN;
       else
        {
          errmsg ("parse error '%U'", format_unformat_error, line_input);
@@ -13164,9 +13599,11 @@ api_gre_add_del_tunnel (vat_main_t * vam)
       clib_memcpy (&mp->src_address, &src6, 16);
       clib_memcpy (&mp->dst_address, &dst6, 16);
     }
-  mp->outer_fib_id = ntohl (outer_fib_id);
+  mp->instance = htonl (instance);
+  mp->outer_fib_id = htonl (outer_fib_id);
   mp->is_add = is_add;
-  mp->teb = teb;
+  mp->session_id = htons ((u16) session_id);
+  mp->tunnel_type = t_type;
   mp->is_ipv6 = ipv6_set;
 
   S (mp);
@@ -13181,11 +13618,12 @@ static void vl_api_gre_tunnel_details_t_handler
   ip46_address_t src = to_ip46 (mp->is_ipv6, mp->src_address);
   ip46_address_t dst = to_ip46 (mp->is_ipv6, mp->dst_address);
 
-  print (vam->ofp, "%11d%24U%24U%6d%14d",
+  print (vam->ofp, "%11d%11d%24U%24U%13d%14d%12d",
         ntohl (mp->sw_if_index),
+        ntohl (mp->instance),
         format_ip46_address, &src, IP46_TYPE_ANY,
         format_ip46_address, &dst, IP46_TYPE_ANY,
-        mp->teb, ntohl (mp->outer_fib_id));
+        mp->tunnel_type, ntohl (mp->outer_fib_id), ntohl (mp->session_id));
 }
 
 static void vl_api_gre_tunnel_details_t_handler_json
@@ -13205,6 +13643,7 @@ static void vl_api_gre_tunnel_details_t_handler_json
 
   vat_json_init_object (node);
   vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
+  vat_json_object_add_uint (node, "instance", ntohl (mp->instance));
   if (!mp->is_ipv6)
     {
       clib_memcpy (&ip4, &mp->src_address, sizeof (ip4));
@@ -13219,9 +13658,10 @@ static void vl_api_gre_tunnel_details_t_handler_json
       clib_memcpy (&ip6, &mp->dst_address, sizeof (ip6));
       vat_json_object_add_ip6 (node, "dst_address", ip6);
     }
-  vat_json_object_add_uint (node, "teb", mp->teb);
+  vat_json_object_add_uint (node, "tunnel_type", mp->tunnel_type);
   vat_json_object_add_uint (node, "outer_fib_id", ntohl (mp->outer_fib_id));
   vat_json_object_add_uint (node, "is_ipv6", mp->is_ipv6);
+  vat_json_object_add_uint (node, "session_id", mp->session_id);
 }
 
 static int
@@ -13250,9 +13690,9 @@ api_gre_tunnel_dump (vat_main_t * vam)
 
   if (!vam->json_output)
     {
-      print (vam->ofp, "%11s%24s%24s%6s%14s",
-            "sw_if_index", "src_address", "dst_address", "teb",
-            "outer_fib_id");
+      print (vam->ofp, "%11s%11s%24s%24s%13s%14s%12s",
+            "sw_if_index", "instance", "src_address", "dst_address",
+            "tunnel_type", "outer_fib_id", "session_id");
     }
 
   /* Get list of gre-tunnel interfaces */
@@ -14183,6 +14623,59 @@ api_input_acl_set_interface (vat_main_t * vam)
   return ret;
 }
 
+static int
+api_output_acl_set_interface (vat_main_t * vam)
+{
+  unformat_input_t *i = vam->input;
+  vl_api_output_acl_set_interface_t *mp;
+  u32 sw_if_index;
+  int sw_if_index_set;
+  u32 ip4_table_index = ~0;
+  u32 ip6_table_index = ~0;
+  u32 l2_table_index = ~0;
+  u8 is_add = 1;
+  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, "del"))
+       is_add = 0;
+      else if (unformat (i, "ip4-table %d", &ip4_table_index))
+       ;
+      else if (unformat (i, "ip6-table %d", &ip6_table_index))
+       ;
+      else if (unformat (i, "l2-table %d", &l2_table_index))
+       ;
+      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 (OUTPUT_ACL_SET_INTERFACE, mp);
+
+  mp->sw_if_index = ntohl (sw_if_index);
+  mp->ip4_table_index = ntohl (ip4_table_index);
+  mp->ip6_table_index = ntohl (ip6_table_index);
+  mp->l2_table_index = ntohl (l2_table_index);
+  mp->is_add = is_add;
+
+  S (mp);
+  W (ret);
+  return ret;
+}
+
 static int
 api_ip_address_dump (vat_main_t * vam)
 {
@@ -19604,7 +20097,7 @@ api_netmap_delete (vat_main_t * vam)
 }
 
 static void
-vl_api_mpls_fib_path_print (vat_main_t * vam, vl_api_fib_path2_t * fp)
+vl_api_mpls_fib_path_print (vat_main_t * vam, vl_api_fib_path_t * fp)
 {
   if (fp->afi == IP46_TYPE_IP6)
     print (vam->ofp,
@@ -19624,7 +20117,7 @@ vl_api_mpls_fib_path_print (vat_main_t * vam, vl_api_fib_path2_t * fp)
 
 static void
 vl_api_mpls_fib_path_json_print (vat_json_node_t * node,
-                                vl_api_fib_path2_t * fp)
+                                vl_api_fib_path_t * fp)
 {
   struct in_addr ip4;
   struct in6_addr ip6;
@@ -19653,7 +20146,7 @@ vl_api_mpls_tunnel_details_t_handler (vl_api_mpls_tunnel_details_t * mp)
 {
   vat_main_t *vam = &vat_main;
   int count = ntohl (mp->mt_count);
-  vl_api_fib_path2_t *fp;
+  vl_api_fib_path_t *fp;
   i32 i;
 
   print (vam->ofp, "[%d]: sw_if_index %d via:",
@@ -19677,7 +20170,7 @@ vl_api_mpls_tunnel_details_t_handler_json (vl_api_mpls_tunnel_details_t * mp)
   vat_main_t *vam = &vat_main;
   vat_json_node_t *node = NULL;
   int count = ntohl (mp->mt_count);
-  vl_api_fib_path2_t *fp;
+  vl_api_fib_path_t *fp;
   i32 i;
 
   if (VAT_JSON_ARRAY != vam->json_tree.type)
@@ -19743,7 +20236,7 @@ vl_api_mpls_fib_details_t_handler (vl_api_mpls_fib_details_t * mp)
 {
   vat_main_t *vam = &vat_main;
   int count = ntohl (mp->count);
-  vl_api_fib_path2_t *fp;
+  vl_api_fib_path_t *fp;
   int i;
 
   print (vam->ofp,
@@ -19763,7 +20256,7 @@ static void vl_api_mpls_fib_details_t_handler_json
   vat_main_t *vam = &vat_main;
   int count = ntohl (mp->count);
   vat_json_node_t *node = NULL;
-  vl_api_fib_path2_t *fp;
+  vl_api_fib_path_t *fp;
   int i;
 
   if (VAT_JSON_ARRAY != vam->json_tree.type)
@@ -20492,8 +20985,9 @@ vl_api_sw_interface_span_details_t_handler (vl_api_sw_interface_span_details_t
       }
   }));
   /* *INDENT-ON* */
-  print (vam->ofp, "%20s => %20s (%s)",
-        sw_if_from_name, sw_if_to_name, states[mp->state]);
+  print (vam->ofp, "%20s => %20s (%s) %s",
+        sw_if_from_name, sw_if_to_name, states[mp->state],
+        mp->is_l2 ? "l2" : "device");
 }
 
 static void
@@ -20542,6 +21036,7 @@ static void
       vat_json_object_add_string_copy (node, "dst-if-name", sw_if_to_name);
     }
   vat_json_object_add_uint (node, "state", mp->state);
+  vat_json_object_add_uint (node, "is-l2", mp->is_l2);
 }
 
 static int
@@ -22746,10 +23241,22 @@ _(tap_delete,                                                           \
   "<vpp-if-name> | sw_if_index <id>")                                   \
 _(sw_interface_tap_dump, "")                                            \
 _(tap_create_v2,                                                        \
-  "name <name> [hw-addr <mac-addr>] [host-ns <name>] [rx-ring-size <num> [tx-ring-size <num>]") \
+  "id <num> [hw-addr <mac-addr>] [host-ns <name>] [rx-ring-size <num> [tx-ring-size <num>]") \
 _(tap_delete_v2,                                                        \
   "<vpp-if-name> | sw_if_index <id>")                                   \
 _(sw_interface_tap_v2_dump, "")                                         \
+_(bond_create,                                                          \
+  "[hw-addr <mac-addr>] {round-robin | active-backup | "                \
+  "broadcast | {lacp | xor} [load-balance { l2 | l23 | l34 }]}")        \
+_(bond_delete,                                                          \
+  "<vpp-if-name> | sw_if_index <id>")                                   \
+_(bond_enslave,                                                         \
+  "sw_if_index <n> bond <sw_if_index> [is_passive] [is_long_timeout]") \
+_(bond_detach_slave,                                                    \
+  "sw_if_index <n>")                                                   \
+_(sw_interface_bond_dump, "")                                           \
+_(sw_interface_slave_dump,                                              \
+  "<vpp-if-name> | sw_if_index <id>")                                   \
 _(ip_table_add_del,                                                     \
   "table-id <n> [ipv6]\n")                                              \
 _(ip_add_del_route,                                                     \
@@ -22857,7 +23364,7 @@ _(l2tpv3_set_lookup_key,                                                \
 _(sw_if_l2tpv3_tunnel_dump, "")                                         \
 _(vxlan_add_del_tunnel,                                                 \
   "src <ip-addr> { dst <ip-addr> | group <mcast-ip-addr>\n"             \
-  "{ <intfc> | mcast_sw_if_index <nn> } }\n"                            \
+  "{ <intfc> | mcast_sw_if_index <nn> } [instance <id>]}\n"            \
   "vni <vni> [encap-vrf-id <nn>] [decap-next <l2|nn>] [del]")           \
 _(geneve_add_del_tunnel,                                                \
   "src <ip-addr> { dst <ip-addr> | group <mcast-ip-addr>\n"             \
@@ -22866,7 +23373,8 @@ _(geneve_add_del_tunnel,                                                \
 _(vxlan_tunnel_dump, "[<intfc> | sw_if_index <nn>]")                    \
 _(geneve_tunnel_dump, "[<intfc> | sw_if_index <nn>]")                   \
 _(gre_add_del_tunnel,                                                   \
-  "src <ip-addr> dst <ip-addr> [outer-fib-id <nn>] [teb] [del]\n")    \
+  "src <ip-addr> dst <ip-addr> [outer-fib-id <nn>] [instance <n>]\n"    \
+  "[teb | erspan <session-id>] [del]")                                 \
 _(gre_tunnel_dump, "[<intfc> | sw_if_index <nn>]")                      \
 _(l2_fib_clear_table, "")                                               \
 _(l2_interface_efp_filter, "sw_if_index <nn> enable | disable")         \
@@ -23158,6 +23666,9 @@ _(session_rule_add_del, "[add|del] proto <tcp/udp> <lcl-ip>/<plen> "    \
   "<lcl-port> <rmt-ip>/<plen> <rmt-port> action <nn>")                 \
 _(session_rules_dump, "")                                              \
 _(ip_container_proxy_add_del, "[add|del] <address> <sw_if_index>")     \
+_(output_acl_set_interface,                                             \
+  "<intfc> | sw_if_index <nn> [ip4-table <nn>] [ip6-table <nn>]\n"      \
+  "  [l2-table <nn>] [del]")                                            \
 
 /* List of command functions, CLI names map directly to functions */
 #define foreach_cli_function                                    \