text: /*
   * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
   */
  
  #include <boost/foreach.hpp>
  
  #include "base/os.h"
  #include "test/test_cmn_util.h"
  #include "test/test_init.h"
  #include "oper/ecmp_load_balance.h"
  #include "oper/mirror_table.h"
  #include "oper/tag.h"
  #include "oper/physical_device_vn.h"
  #include "oper/vxlan_routing_manager.h"
  #include "ksync/ksync_sock_user.h"
  #include "uve/test/vn_uve_table_test.h"
  #include "uve/agent_uve_stats.h"
  #include <cfg/cfg_types.h>
  #include <port_ipc/port_ipc_handler.h>
  #include <port_ipc/port_subscribe_table.h>
  #include <controller/controller_ifmap.h>
  #include <resource_manager/resource_manager.h>
  #include <resource_manager/mpls_index.h>
  #define MAX_TESTNAME_LEN 80
  
  using namespace std;
  
  BgpPeer *bgp_peer_;
  TestClient *client;
  #define MAX_VNET 10
  int test_tap_fd[MAX_VNET];
  
  TestTaskHold::HoldTask::HoldTask(TestTaskHold *hold_entry) :
      Task(hold_entry->task_id_, hold_entry->task_instance_),
      hold_entry_(hold_entry) {
  }
  
  bool TestTaskHold::HoldTask::Run() {
      hold_entry_->task_held_ = true;
      while (hold_entry_->task_held_ == true) {
          usleep(2000);
      }
      hold_entry_->task_held_ = true;
      return true;
  }
  
  TestTaskHold::TestTaskHold(int task_id, int task_instance) :
      task_id_(task_id), task_instance_(task_instance) {
      task_held_ = false;
      HoldTask *task_entry = new HoldTask(this);
      TaskScheduler *scheduler = TaskScheduler::GetInstance();
      scheduler->Enqueue(task_entry);
      while (task_held_ != true) {
          usleep(200);
      }
  }
  
  TestTaskHold::~TestTaskHold() {
      task_held_ = false;
      while (task_held_ != true) {
          usleep(200);
      }
  }
  
  boost::uuids::uuid MakeUuid(int id) {
      char str[50];
      sprintf(str, "00000000-0000-0000-0000-00%010x", id);
      boost::uuids::uuid u1 = StringToUuid(std::string(str));
  
      return u1;
  }
  
  void DelXmlHdr(char *buff, int &len) {
      len = 0;
      sprintf(buff + len, "<?xml version=\"1.0\"?>\n"
                          "    <config>\n"
                          "         <delete>\n");
      len = strlen(buff);
  }
  
  void DelXmlTail(char *buff, int &len) {
      sprintf(buff + len, "        </delete>\n"
                          "    </config>\n");
      len = strlen(buff);
  }
  
  void AddXmlHdr(char *buff, int &len) {
      len = 0;
      sprintf(buff + len, "<?xml version=\"1.0\"?>\n"
                          "    <config>\n"
                          "         <update>\n");
      len = strlen(buff);
  }
  
  void AddXmlTail(char *buff, int &len) {
      sprintf(buff + len, "        </update>\n"
                          "    </config>\n");
      len = strlen(buff);
  }
  
  static bool CheckLink(const string &node1, const string &node2,
                 const string &match1, const string &match2) {
      if (node1 == match1 && node2 == match2)
          return true;
      if (node1 == match2 && node2 == match1)
          return true;
  
      return false;
  }
  
  typedef std::map<string, string> LinkToMetadata;
  LinkToMetadata link_to_metadata_;
  
  static void AddLinkToMetadata(const char *node1, const char *node2,
                                const char *metadata = NULL) {
      char buff[128];
      if (metadata == NULL)
          sprintf(buff, "%s-%s", node1, node2);
      else
          strcpy(buff, metadata);
  
      link_to_metadata_.insert(make_pair(string(node1) + "-" + string(node2),
                                         buff));
      link_to_metadata_.insert(make_pair(string(node2) + "-" + string(node1),
                                         buff));
  }
  
  static void BuildLinkToMetadata() {
      if (link_to_metadata_.size() != 0)
          return;
  
      AddLinkToMetadata("virtual-machine-interface", "virtual-network");
      AddLinkToMetadata("project", "virtual-machine-interface");
      AddLinkToMetadata("virtual-machine-interface", "virtual-machine");
      AddLinkToMetadata("virtual-machine-interface", "security-group");
      AddLinkToMetadata("virtual-machine-interface",
                        "virtual-machine-interface-routing-instance",
                        "virtual-machine-interface-routing-instance");
      AddLinkToMetadata("virtual-machine-interface", "interface-route-table",
                        "virtual-machine-interface-route-table");
      AddLinkToMetadata("virtual-machine-interface",
                        "virtual-machine-interface-bridge-domain",
                        "virtual-machine-interface-bridge-domain");
      AddLinkToMetadata("virtual-machine-interface", "tag");
      AddLinkToMetadata("instance-ip", "virtual-machine-interface");
      AddLinkToMetadata("instance-ip", "virtual-network");
      AddLinkToMetadata("instance-ip", "floating-ip");
      AddLinkToMetadata("virtual-machine-interface", "virtual-machine-interface",
                        "virtual-machine-interface-sub-interface");
  
      AddLinkToMetadata("virtual-network", "routing-instance");
      AddLinkToMetadata("virtual-network", "access-control-list");
      AddLinkToMetadata("virtual-network", "floating-ip-pool");
      AddLinkToMetadata("virtual-network", "alias-ip-pool");
      AddLinkToMetadata("virtual-network", "virtual-network-network-ipam",
                        "virtual-network-network-ipam");
      AddLinkToMetadata("virtual-network-network-ipam", "network-ipam",
                        "virtual-network-network-ipam");
      AddLinkToMetadata("virtual-network", "multicast-policy",
                        "virtual-network-multicast-policy");
      AddLinkToMetadata("virtual-router", "virtual-router-network-ipam",
                        "virtual-vrouter-network-ipam");
      AddLinkToMetadata("virtual-router-network-ipam", "network-ipam",
                        "virtual-router-network-ipam");
  
      AddLinkToMetadata("security-group", "access-control-list");
  
      AddLinkToMetadata("routing-instance",
                        "virtual-machine-interface-routing-instance",
                        "virtual-machine-interface-routing-instance");
  
      AddLinkToMetadata("physical-router", "physical-interface");
      AddLinkToMetadata("physical-router", "logical-interface");
      AddLinkToMetadata("physical-interface", "logical-interface");
      AddLinkToMetadata("logical-interface", "virtual-machine-interface");
      AddLinkToMetadata("virtual-port-group", "physical-interface");
      AddLinkToMetadata("virtual-port-group", "virtual-machine-interface");
  
      AddLinkToMetadata("floating-ip-pool", "floating-ip");
      AddLinkToMetadata("floating-ip", "virtual-machine-interface");
  
      AddLinkToMetadata("alias-ip-pool", "alias-ip");
      AddLinkToMetadata("alias-ip", "virtual-machine-interface");
  
      AddLinkToMetadata("subnet", "virtual-machine-interface");
      AddLinkToMetadata("virtual-router", "virtual-machine");
      AddLinkToMetadata("virtual-machine-interface", "bgp-as-a-service");
      AddLinkToMetadata("bgp-router", "bgp-as-a-service");
      AddLinkToMetadata("bgp-router", "routing-instance");
      AddLinkToMetadata("bgp-router", "virtual-machine-interface");
      AddLinkToMetadata("bgp-router", "control-node-zone");
      AddLinkToMetadata("bgp-as-a-service", "control-node-zone",
                        "bgpaas-control-node-zone");
      AddLinkToMetadata("bgp-as-a-service", "service-health-check");
      AddLinkToMetadata("virtual-network", "service-health-check");
      AddLinkToMetadata("virtual-network", "qos-config");
      AddLinkToMetadata("virtual-machine-interface", "qos-config");
      AddLinkToMetadata("global-qos-config", "qos-config");
      AddLinkToMetadata("forwarding-class", "qos-queue");
      AddLinkToMetadata("network-ipam", "virtual-DNS");
      AddLinkToMetadata("virtual-machine-interface", "service-health-check", "service-port-health-check");
  
      AddLinkToMetadata("bridge-domain",
                        "virtual-machine-interface-bridge-domain",
                        "virtual-machine-interface-bridge-domain");
      AddLinkToMetadata("virtual-network", "bridge-domain");
      AddLinkToMetadata("firewall-policy", "firewall-policy-firewall-rule",
                        "firewall-policy-firewall-rule");
      AddLinkToMetadata("firewall-rule", "firewall-policy-firewall-rule",
                        "firewall-policy-firewall-rule");
      AddLinkToMetadata("application-policy-set",
                        "application-policy-set-firewall-policy",
                        "application-policy-set-firewall-policy");
      AddLinkToMetadata("firewall-policy",
                        "application-policy-set-firewall-policy",
                        "application-policy-set-firewall-policy");
  
      AddLinkToMetadata("firewall-rule", "service-group");
      AddLinkToMetadata("firewall-rule", "address-group");
      AddLinkToMetadata("firewall-rule", "tag", "firewall-rule-tag");
      AddLinkToMetadata("address-group", "tag", "address-group-tag");
      AddLinkToMetadata("virtual-network", "tag", "virtual-network-tag");
      AddLinkToMetadata("virtual-machine", "tag", "virtual-machine-tag");
      AddLinkToMetadata("project", "tag", "project-tag");
      AddLinkToMetadata("application-policy-set", "tag");
      AddLinkToMetadata("policy-management", "application-policy-set");
      AddLinkToMetadata("virtual-network", "virtual-network",
                        "virtual-network-provider-network");
      AddLinkToMetadata("logical-router", "virtual-machine-interface",
                        "logical-router-interface");
      AddLinkToMetadata("logical-router", "virtual-network",
                        "logical-router-virtual-network");
      AddLinkToMetadata("service-instance", "service-template",
                        "service-instance-service-template");
      AddLinkToMetadata("project", "host-based-service",
                        "project-host-based-service");
      AddLinkToMetadata("host-based-service-virtual-network", "virtual-network",
                        "host-based-service-virtual-network-virtual-network");
      AddLinkToMetadata("virtual-network", "virtual-network-interface",
                        "virtual-network-virtual-network-interface");
  }
  
  const char *GetMetadata(const char *node1, const char *node2) {
      BuildLinkToMetadata();
  
      LinkToMetadata::iterator it = link_to_metadata_.find(string(node1) + "-" +
                                                           string(node2));
      if (it == link_to_metadata_.end()) {
          cout << "Error finding metadata for link between "
              << node1 << " and " << node2 << endl;
          // Metadata not found for the link.
          // Please populate link-to-metadata entry in BuildLinkToMetadata
          assert(0);
      }
  
      return it->second.c_str();
  }
  
  void LinkString(char *buff, int &len, const char *node_name1,
                     const char *name1, const char *node_name2,
                     const char *name2, const char* mdata) {
      const char *mdata_value = NULL;
      if (!mdata) {
          mdata_value = GetMetadata(node_name1, node_name2);
      } else {
          mdata_value = mdata;
      }
      sprintf(buff + len,
              "       <link>\n"
              "           <node type=\"%s\">\n"
              "               <name>%s</name>\n"
              "           </node>\n"
              "           <node type=\"%s\">\n"
              "               <name>%s</name>\n"
              "           </node>\n"
              "           <metadata type=\"%s\"/>\n"
              "       </link>\n", node_name1, name1, node_name2, name2,
              mdata_value);
      len = strlen(buff);
  }
  
  void AddNodeStringWithoutUuid(char *buff, int &len, const char
          *node_name, const char *name) {
      sprintf(buff + len,
              "       <node type=\"%s\">\n"
              "           <name>%s</name>\n"
              "       </node>\n", node_name, name);
      len = strlen(buff);
  }
  
  void AddNodeString(char *buff, int &len, const char *node_name,
                     const char *name, int id, const char *attr,
                     bool admin_state) {
      sprintf(buff + len,
              "       <node type=\"%s\">\n"
              "           <name>%s</name>\n"
              "           <id-perms>\n"
              "               <permissions>\n"
              "                   <owner></owner>\n"
              "                   <owner_access>0</owner_access>\n"
              "                   <group></group>\n"
              "                   <group_access>0</group_access>\n"
              "                   <other_access>0</other_access>\n"
              "               </permissions>\n"
              "               <uuid>\n"
              "                   <uuid-mslong>0</uuid-mslong>\n"
              "                   <uuid-lslong>%d</uuid-lslong>\n"
              "               </uuid>\n"
              "               <enable>%s</enable>\n"
              "           </id-perms>\n"
              "           %s\n"
              "       </node>\n", node_name, name, id,
                                  (admin_state == true) ? "true" : "false", attr);
      len = strlen(buff);
  }
  
  void AddNodeString(char *buff, int &len, const char *node_name,
                     const char *name, int id) {
      sprintf(buff + len,
              "       <node type=\"%s\">\n"
              "           <name>%s</name>\n"
              "           <id-perms>\n"
              "               <permissions>\n"
              "                   <owner></owner>\n"
              "                   <owner_access>0</owner_access>\n"
              "                   <group></group>\n"
              "                   <group_access>0</group_access>\n"
              "                   <other_access>0</other_access>\n"
              "               </permissions>\n"
              "               <uuid>\n"
              "                   <uuid-mslong>0</uuid-mslong>\n"
              "                   <uuid-lslong>%d</uuid-lslong>\n"
              "               </uuid>\n"
              "               <enable>true</enable>\n"
              "           </id-perms>\n"
              "       </node>\n", node_name, name, id);
      len = strlen(buff);
  }
  
  void AddNodeString(char *buff, int &len, const char *node_name,
                     const char *name, int id, bool enable) {
      char status_str[10];
      if (enable) {
          strcpy(status_str, "true");
      } else {
          strcpy(status_str, "false");
      }
  
      sprintf(buff + len,
              "       <node type=\"%s\">\n"
              "           <name>%s</name>\n"
              "           <id-perms>\n"
              "               <permissions>\n"
              "                   <owner></owner>\n"
              "                   <owner_access>0</owner_access>\n"
              "                   <group></group>\n"
              "                   <group_access>0</group_access>\n"
              "                   <other_access>0</other_access>\n"
              "               </permissions>\n"
              "               <uuid>\n"
              "                   <uuid-mslong>0</uuid-mslong>\n"
              "                   <uuid-lslong>%d</uuid-lslong>\n"
              "               </uuid>\n"
              "               <enable>%s</enable>\n"
              "           </id-perms>\n"
              "       </node>\n", node_name, name, id, status_str);
      len = strlen(buff);
  }
  
  void AddNodeString(char *buff, int &len, const char *nodename, const char *name,
                     IpamInfo *ipam, int count,
                     const std::vector<std::string> *vm_host_routes,
                     const char *add_subnet_tags) {
      std::stringstream str;
      str << "       <node type=\"" << nodename << "\">\n";
      str << "           <name>" << name << "</name>\n";
      str << "           <value>\n";
      for (int i = 0; i < count; i++) {
          std::string dhcp_enable = (ipam[i].dhcp_enable == true) ? "true" : "false";
          str << "               <ipam-subnets>\n";
          str << "                   <subnet>\n";
          str << "                       <ip-prefix>" << ipam[i].ip_prefix << "</ip-prefix>\n";
          str << "                       <ip-prefix-len>" << ipam[i].plen << "</ip-prefix-len>\n";
          str << "                   </subnet>\n";
          str << "                   <default-gateway>" << ipam[i].gw << "</default-gateway>\n";
          if (strlen(ipam[i].dns)) {
              str << "               <dns-server-address>" << ipam[i].dns << "</dns-server-address>\n";
          } else {
              str << "               <dns-server-address>" << ipam[i].gw << "</dns-server-address>\n";
          }
          str << "                   <enable-dhcp>" << dhcp_enable << "</enable-dhcp>\n";
          str << "                   <alloc-unit>" << ipam[i].alloc_unit << "</alloc-unit>\n";
          if (add_subnet_tags)
              str <<                 add_subnet_tags << "\n";
          str << "               </ipam-subnets>\n";
      }
      if (vm_host_routes && vm_host_routes->size()) {
          str << "               <host-routes>\n";
          for (unsigned int i = 0; i < vm_host_routes->size(); i++) {
              std::string prefix, nexthop;
              std::vector<std::string> tokens;
              boost::split(tokens, (*vm_host_routes)[i], boost::is_any_of(" \t"));
              vector<string>::iterator it = tokens.begin();
              if (it != tokens.end()) {
                  prefix = *it;
                  it++;
              }
              if (it != tokens.end()) {
                  nexthop = *it;
              }
              str << "                   <route>\n";
              str << "                       <prefix>" << prefix << "</prefix>\n";
              str << "                       <next-hop>" << nexthop << "</next-hop>\n";
              str << "                       <next-hop-type />\n";
              str << "                   </route>\n";
          }
          str << "               </host-routes>\n";
      }
      str << "           </value>\n";
      str << "       </node>\n";
      std::string final_str = str.str();
      memcpy(buff + len, final_str.data(), final_str.size());
      len += final_str.size();
  }
  
  void AddNodeString(char *buff, int &len, const char *nodename, const char *name,
                     MulticastPolicy *msg, int count) {
  
      std::stringstream str;
      str << "       <node type=\"" << nodename << "\">\n";
      str << "           <name>" << name << "</name>\n";
      str << "           <value>\n";
      for (int i = 0; i < count; i++) {
          std::string action = (msg[i].action == true) ? "pass" : "deny";
  
          str << "               <multicast-source-groups>\n";
          str << "                   <source-address>" << msg[i].src << "</source-address>\n";
          str << "                   <group-address>" << msg[i].grp << "</group-address>\n";
          str << "                   <action>" << action << "</action>\n";
          str << "               </multicast-source-groups>\n";
      }
      str << "           </value>\n";
      str << "       </node>\n";
  
      std::string final_str = str.str();
      memcpy(buff + len, final_str.data(), final_str.size());
      len += final_str.size();
  }
  
  void AddLinkNodeString(char *buff, int &len, const char *nodename, const char *name,
                         const char *attr) {
      std::stringstream str;
      str << "       <node type=\"" << nodename << "\">\n";
      str << "           <name>" << name << "</name>\n";
      str << "           <value>\n";
      str << "               " << attr << "\n";
      str << "           </value>\n";
      str << "       </node>\n";
      std::string final_str = str.str();
      memcpy(buff + len, final_str.data(), final_str.size());
      len += final_str.size();
  }
  
  void AddVmPortVrfNodeString(char *buff, int &len, const char *name, int id) {
      AddLinkNodeString(buff, len, "virtual-machine-interface-routing-instance",
                    name, "<direction>both</direction>");
                    //<vlan-tag>1</vlan-tag> <service-chain-address></service-chain-address>");
  }
  
  void DelNodeString(char *buff, int &len, const char *node_name,
                     const char *name) {
      sprintf(buff + len,
              "       <node type=\"%s\">\n"
              "           <name>%s</name>\n"
              "       </node>\n", node_name, name);
  
      len = strlen(buff);
  }
  
  void ApplyXmlString(const char *buff) {
      pugi::xml_document xdoc_;
      pugi::xml_parse_result result = xdoc_.load(buff);
      EXPECT_TRUE(result);
      Agent::GetInstance()->ifmap_parser()->ConfigParse(xdoc_.first_child(), 0);
      return;
  }
  
  void AddLink(const char *node_name1, const char *name1,
               const char *node_name2, const char *name2, const char *mdata) {
      char buff[1024];
      int len = 0;
  
      AddXmlHdr(buff, len);
      LinkString(buff, len, node_name1, name1, node_name2, name2, mdata);
      AddXmlTail(buff, len);
      //LOG(DEBUG, buff);
      ApplyXmlString(buff);
      return;
  }
  
  void DelLink(const char *node_name1, const char *name1,
               const char *node_name2, const char *name2, const char* mdata) {
      char buff[1024];
      int len = 0;
  
      DelXmlHdr(buff, len);
      LinkString(buff, len, node_name1, name1, node_name2, name2, mdata);
      DelXmlTail(buff, len);
      //LOG(DEBUG, buff);
      ApplyXmlString(buff);
      return;
  }
  
  void AddNode(const char *node_name, const char *name, int id) {
      char buff[10240];
      int len = 0;
  
      AddXmlHdr(buff, len);
      AddNodeString(buff, len, node_name, name, id);
      AddXmlTail(buff, len);
      ApplyXmlString(buff);
      return;
  }
  
  void AddNodeByStatus(const char *node_name, const char *name, int id, bool status) {
      char buff[10240];
      int len = 0;
  
      AddXmlHdr(buff, len);
      AddNodeString(buff, len, node_name, name, id, status);
      AddXmlTail(buff, len);
      ApplyXmlString(buff);
      return;
  }
  
  // admin_state is true by default
  void AddNode(const char *node_name, const char *name, int id,
                      const char *attr, bool admin_state) {
      char buff[10240];
      int len = 0;
  
      AddXmlHdr(buff, len);
      if (id)
          AddNodeString(buff, len, node_name, name, id, attr, admin_state);
      else
          AddNodeStringWithoutUuid(buff, len, node_name, name);
      AddXmlTail(buff, len);
      ApplyXmlString(buff);
      return;
  }
  
  // admin_state is true by default
  void AddNode(Agent *agent, const char *node_name, const char *name, int id,
               const char *attr, bool admin_state) {
      char buff[10240];
      int len = 0;
  
      AddXmlHdr(buff, len);
      AddNodeString(buff, len, node_name, name, id, attr, admin_state);
      AddXmlTail(buff, len);
      ApplyXmlString(buff);
      return;
  }
  
  void AddLinkNode(const char *node_name, const char *name, const char *attr) {
      char buff[1024];
      int len = 0;
  
      AddXmlHdr(buff, len);
      AddLinkNodeString(buff, len, node_name, name, attr);
      AddXmlTail(buff, len);
      LOG(DEBUG, buff);
      ApplyXmlString(buff);
      return;
  }
  
  void DelNode(const char *node_name, const char *name) {
      char buff[1024];
      int len = 0;
  
      DelXmlHdr(buff, len);
      DelNodeString(buff, len, node_name, name);
      DelXmlTail(buff, len);
      ApplyXmlString(buff);
      return;
  }
  
  void DelNode(Agent *agent, const char *node_name, const char *name) {
      char buff[1024];
      int len = 0;
  
      DelXmlHdr(buff, len);
      DelNodeString(buff, len, node_name, name);
      DelXmlTail(buff, len);
      ApplyXmlString(buff);
      return;
  }
  
  uint32_t PortSubscribeSize(Agent *agent) {
      return agent->port_ipc_handler()->port_subscribe_table()->Size();
  }
  
  bool PortSubscribe(VmiSubscribeEntry *entry) {
      Agent *agent = Agent::GetInstance();
      string json = agent->port_ipc_handler()->MakeVmiUuidJson(entry, false);
      string err;
      return agent->port_ipc_handler()->AddPortFromJson(json, false, err, false);
  }
  
  bool PortSubscribe(const std::string &ifname,
                     const boost::uuids::uuid &vmi_uuid,
                     const boost::uuids::uuid vm_uuid,
                     const std::string &vm_name,
                     const boost::uuids::uuid &vn_uuid,
                     const boost::uuids::uuid &project_uuid,
                     const Ip4Address &ip4_addr, const Ip6Address &ip6_addr,
                     const std::string &mac_addr) {
      VmiSubscribeEntry entry(VmiSubscribeEntry::VMPORT, ifname, 0,
                              vmi_uuid, vm_uuid, vm_name, vn_uuid, project_uuid,
                              ip4_addr, ip6_addr, mac_addr,
                              VmInterface::kInvalidVlanId,
                              VmInterface::kInvalidVlanId,
                              VmInterface::vHostUserClient, 1);
      return PortSubscribe(&entry);
  }
  
  void PortUnSubscribe(const boost::uuids::uuid &u) {
      Agent *agent = Agent::GetInstance();
      string err;
      agent->port_ipc_handler()->DeleteVmiUuidEntry(u, err);
  }
  
  void IntfSyncMsg(PortInfo *input, int id) {
      VmInterfaceKey *key = new VmInterfaceKey(AgentKey::ADD_DEL_CHANGE,
                                               MakeUuid(input[id].intf_id), "");
      DBRequest req;
      req.oper = DBRequest::DB_ENTRY_ADD_CHANGE;
      req.key.reset(key);
      req.data.reset(NULL);
      Agent::GetInstance()->interface_table()->Enqueue(&req);
      usleep(1000);
  }
  
  void IntfCfgAdd(int intf_id, const string &name, const string ipaddr,
                  int vm_id, int vn_id, const string &mac, uint16_t vlan,
                  const string ip6addr, uint8_t vhostuser_mode, int project_id) {
      boost::system::error_code ec;
      Ip4Address ip = Ip4Address::from_string(ipaddr, ec);
      char vm_name[MAX_TESTNAME_LEN];
      sprintf(vm_name, "vm%d", vm_id);
      Ip6Address ip6 = Ip6Address();
      if (!ip6addr.empty()) {
          ip6 = Ip6Address::from_string(ip6addr, ec);
      }
  
      VmiSubscribeEntry entry(PortSubscribeEntry::VMPORT, name, 0,
                              MakeUuid(intf_id), MakeUuid(vm_id), vm_name,
                              MakeUuid(vn_id), MakeUuid(project_id), ip, ip6,
                              mac, vlan, vlan, vhostuser_mode, 1);
      Agent *agent = Agent::GetInstance();
      string json = agent->port_ipc_handler()->MakeVmiUuidJson(&entry, false);
      string err;
      agent->port_ipc_handler()->AddPortFromJson(json, false, err, false);
      client->WaitForIdle();
  }
  
  void IntfCfgAdd(int intf_id, const string &name, const string ipaddr,
                  int vm_id, int vn_id, const string &mac,
                  const string ip6addr) {
      IntfCfgAdd(intf_id, name, ipaddr, vm_id, vn_id, mac,
                 VmInterface::kInvalidVlanId, ip6addr,
                 VmInterface::vHostUserClient);
  }
  
  void IntfCfgAdd(PortInfo *input, int id) {
      IntfCfgAdd(input[id].intf_id, input[id].name, input[id].addr,
               input[id].vm_id, input[id].vn_id, input[id].mac,
             input[id].ip6addr);
  }
  
  void IntfCfgAddThrift(PortInfo *input, int id) {
      IntfCfgAdd(input, id);
  }
  
  void IntfCfgDelNoWait(int id) {
      Agent *agent = Agent::GetInstance();
      string err;
      agent->port_ipc_handler()->DeleteVmiUuidEntry(MakeUuid(id), err);
  }
  
  void IntfCfgDel(int id) {
      IntfCfgDelNoWait(id);
      client->WaitForIdle();
  }
  
  void IntfCfgDel(PortInfo *input, int id) {
      IntfCfgDel(input[id].intf_id);
  }
  
  bool VrfFind(const char *name, bool ret_del) {
      VrfEntry *vrf;
      VrfKey key(name);
      vrf = static_cast<VrfEntry *>(Agent::GetInstance()->vrf_table()->Find(&key, ret_del));
      return (vrf != NULL);
  }
  
  bool VrfFind(const char *name) {
      VrfEntry *vrf;
      VrfKey key(name);
      vrf = static_cast<VrfEntry *>(Agent::GetInstance()->vrf_table()->FindActiveEntry(&key));
      return (vrf != NULL);
  }
  
  VrfEntry *VrfGet(const char *name, bool ret_del) {
      Agent *agent = Agent::GetInstance();
      VrfKey key(name);
      VrfEntry *vrf =
          static_cast<VrfEntry *>(agent->vrf_table()->Find(&key, ret_del));
      if (vrf && (ret_del == false && vrf->IsDeleted()))
          vrf = NULL;
  
      return vrf;
  }
  
  uint32_t GetVrfId(const char *name) {
      VrfEntry *vrf = VrfGet(name, false);
      return vrf->vrf_id();
  }
  
  VrfEntry *VrfGet(size_t index) {
      return static_cast<VrfEntry *>
          (Agent::GetInstance()->vrf_table()->FindVrfFromId(index));
  }
  
  bool VnFind(int id) {
      VnEntry *vn;
      VnKey key(MakeUuid(id));
      vn = static_cast<VnEntry *>(Agent::GetInstance()->vn_table()->FindActiveEntry(&key));
      return (vn != NULL);
  }
  
  VnEntry *VnGet(int id) {
      VnKey key(MakeUuid(id));
      return static_cast<VnEntry *>(Agent::GetInstance()->vn_table()->FindActiveEntry(&key));
  }
  
  bool VxlanFind(int id) {
      VxLanId *vxlan;
      VxLanIdKey key(id);
      vxlan = static_cast<VxLanId *>(Agent::GetInstance()->vxlan_table()->FindActiveEntry(&key));
      return (vxlan != NULL);
  }
  
  VxLanId *VxlanGet(int id) {
      VxLanIdKey key(id);
      return static_cast<VxLanId *>(Agent::GetInstance()->vxlan_table()->FindActiveEntry(&key));
  }
  
  bool AclFind(int id) {
      AclDBEntry *acl;
      AclKey key(MakeUuid(id));
      acl = static_cast<AclDBEntry *>(Agent::GetInstance()->acl_table()->FindActiveEntry(&key));
      return (acl != NULL);
  }
  
  AclDBEntry *AclGet(int id) {
      AclKey key(MakeUuid(id));
      return static_cast<AclDBEntry *>(Agent::GetInstance()->acl_table()->FindActiveEntry(&key));
  }
  
  bool PolicySetFind(int id) {
      PolicySet *ps;
      PolicySetKey key(MakeUuid(id));
      ps = static_cast<PolicySet *>(Agent::GetInstance()->
                                        policy_set_table()->FindActiveEntry(&key));
      return (ps != NULL);
  }
  
  PolicySet *PolicySetGet(int id) {
      PolicySet *ps;
      PolicySetKey key(MakeUuid(id));
      ps = static_cast<PolicySet *>(Agent::GetInstance()->
                                        policy_set_table()->FindActiveEntry(&key));
      return ps;
  }
  
  VmEntry *VmGet(int id) {
      VmKey key(MakeUuid(id));
      return static_cast<VmEntry *>(Agent::GetInstance()->vm_table()->FindActiveEntry(&key));
  }
  
  bool VmFind(int id) {
      VmEntry *vm;
      VmKey key(MakeUuid(id));
      vm = static_cast<VmEntry *>(Agent::GetInstance()->vm_table()->FindActiveEntry(&key));
      return (vm != NULL);
  }
  
  bool VmPortFind(int id) {
      Interface *intf;
      VmInterfaceKey key(AgentKey::ADD_DEL_CHANGE, MakeUuid(id), "");
      intf = static_cast<Interface *>(Agent::GetInstance()->interface_table()->FindActiveEntry(&key));
      return (intf != NULL ? !intf->IsDeleted() : false);
  }
  
  bool VmPortFindRetDel(int id) {
      Interface *intf;
      VmInterfaceKey key(AgentKey::ADD_DEL_CHANGE, MakeUuid(id), "");
      intf = static_cast<Interface *>(Agent::GetInstance()->interface_table()->Find(&key, true));
      return (intf != NULL);
  }
  
  uint32_t VmPortGetId(int id) {
      Interface *intf;
      VmInterfaceKey key(AgentKey::ADD_DEL_CHANGE, MakeUuid(id), "");
      intf = static_cast<Interface *>(Agent::GetInstance()->interface_table()->FindActiveEntry(&key));
      if (intf) {
          return intf->id();
      }
  
      return 0;
  }
  
  std::string VmPortGetAnalyzerName(int id) {
      VmInterface *intf;
      VmInterfaceKey key(AgentKey::ADD_DEL_CHANGE, MakeUuid(id), "");
      intf = static_cast<VmInterface *>(Agent::GetInstance()->interface_table()->FindActiveEntry(&key));
      if (intf) {
          return intf->GetAnalyzer();
      }
      return std::string();
  }
  
  Interface::MirrorDirection VmPortGetMirrorDirection(int id) {
      VmInterface *intf;
      VmInterfaceKey key(AgentKey::ADD_DEL_CHANGE, MakeUuid(id), "");
      intf = static_cast<VmInterface *>(Agent::GetInstance()->interface_table()->FindActiveEntry(&key));
      if (intf) {
          return intf->mirror_direction();
      }
      return Interface::UNKNOWN;
  }
  
  bool VmPortFind(PortInfo *input, int id) {
      return VmPortFind(input[id].intf_id);
  }
  
  bool VmPortL2Active(int id) {
      Interface *intf;
      VmInterfaceKey key(AgentKey::ADD_DEL_CHANGE, MakeUuid(id), "");
      intf = static_cast<Interface *>(Agent::GetInstance()->interface_table()->FindActiveEntry(&key));
      if (intf == NULL)
          return false;
  
      return (intf->l2_active() == true);
  }
  
  bool VmPortL2Active(PortInfo *input, int id) {
      return VmPortL2Active(input[id].intf_id);
  }
  
  bool VmPortActive(int id) {
      Interface *intf;
      VmInterfaceKey key(AgentKey::ADD_DEL_CHANGE, MakeUuid(id), "");
      intf = static_cast<Interface *>(Agent::GetInstance()->interface_table()->FindActiveEntry(&key));
      if (intf == NULL)
          return false;
  
      return (intf->ipv4_active() == true);
  }
  
  bool VmPortActive(PortInfo *input, int id) {
      return VmPortActive(input[id].intf_id);
  }
  
  bool VmPortV6Active(int id) {
      Interface *intf;
      VmInterfaceKey key(AgentKey::ADD_DEL_CHANGE, MakeUuid(id), "");
      intf = static_cast<Interface *>(Agent::GetInstance()->interface_table()->FindActiveEntry(&key));
      if (intf == NULL)
          return false;
  
      return (intf->ipv6_active() == true);
  }
  
  bool VmPortV6Active(PortInfo *input, int id) {
      return VmPortV6Active(input[id].intf_id);
  }
  
  bool VmPortPolicyEnabled(int id) {
      VmInterface *intf;
      VmInterfaceKey key(AgentKey::ADD_DEL_CHANGE, MakeUuid(id), "");
      intf = static_cast<VmInterface *>
          (Agent::GetInstance()->interface_table()->FindActiveEntry(&key));
      if (intf == NULL)
          return false;
  
      return (intf->policy_enabled());
  }
  
  bool VmPortPolicyEnabled(PortInfo *input, int id) {
      return VmPortPolicyEnabled(input[id].intf_id);
  }
  
  InetInterface *InetInterfaceGet(const char *ifname) {
      InetInterfaceKey key(ifname);
      return static_cast<InetInterface *>(Agent::GetInstance()->interface_table()->FindActiveEntry(&key));
  }
  
  Interface *VmPortGet(int id) {
      VmInterfaceKey key(AgentKey::ADD_DEL_CHANGE, MakeUuid(id), "");
      return static_cast<Interface *>(Agent::GetInstance()->interface_table()->Find(&key, false));
  }
  
  Interface *VhostGet(const char *ifname) {
      VmInterfaceKey key(AgentKey::ADD_DEL_CHANGE, boost::uuids::nil_uuid(), ifname);
      return static_cast<Interface *>(Agent::GetInstance()->interface_table()->Find(&key, false));
  }
  
  bool VmPortFloatingIpCount(int id, unsigned int count) {
      VmInterface *intf = static_cast<VmInterface *>(VmPortGet(id));
      EXPECT_TRUE(intf != NULL);
      if (intf == NULL)
          return false;
  
      EXPECT_EQ(intf->floating_ip_list().list_.size(), count);
      if (intf->floating_ip_list().list_.size() != count)
          return false;
  
      return true;
  }
  
  bool QosConfigFind(uint32_t id) {
      AgentQosConfigKey key(MakeUuid(id));
  
      if (Agent::GetInstance()->qos_config_table()->FindActiveEntry(&key) == NULL) {
          return false;
      }
      return true;
  }
  
  const AgentQosConfig*
  QosConfigGetByIndex(uint32_t id) {
      return Agent::GetInstance()->qos_config_table()->FindByIndex(id);
  }
  
  const AgentQosConfig*
  QosConfigGet(uint32_t id) {
      AgentQosConfigKey key(MakeUuid(id));
  
      return static_cast<AgentQosConfig *>(Agent::GetInstance()->
              qos_config_table()->FindActiveEntry(&key));
  }
  
  bool ForwardingClassFind(uint32_t id) {
      ForwardingClassKey key(MakeUuid(id));
      if (Agent::GetInstance()->forwarding_class_table()->
              FindActiveEntry(&key) == NULL) {
          return false;
      }
      return true;
  }
  
  ForwardingClass*
  ForwardingClassGet(uint32_t id) {
      ForwardingClassKey key(MakeUuid(id));
  
      return static_cast<ForwardingClass *>(Agent::GetInstance()->
              forwarding_class_table()->FindActiveEntry(&key));
  }
  
  bool VmPortAliasIpCount(int id, unsigned int count) {
      VmInterface *intf = static_cast<VmInterface *>(VmPortGet(id));
      EXPECT_TRUE(intf != NULL);
      if (intf == NULL)
          return false;
  
      EXPECT_EQ(intf->alias_ip_list().list_.size(), count);
      if (intf->alias_ip_list().list_.size() != count)
          return false;
  
      return true;
  }
  
  bool VmPortGetStats(PortInfo *input, int id, uint32_t & bytes, uint32_t & pkts) {
      Interface *intf;
      VmInterfaceKey key(AgentKey::ADD_DEL_CHANGE, MakeUuid(input[id].intf_id),
                         input[id].name);
      intf=static_cast<Interface *>(Agent::GetInstance()->interface_table()->FindActiveEntry(&key));
      if (intf == NULL)
          return false;
  
      AgentUveStats *uve = static_cast<AgentUveStats *>(Agent::GetInstance()->uve());
      StatsManager *sm  = uve->stats_manager();
      const StatsManager::InterfaceStats *st = sm->GetInterfaceStats(intf);
      if (st == NULL)
          return false;
  
      bytes = st->in_bytes;
      pkts = st->in_pkts;
      return true;
  }
  
  bool VrfStatsMatch(int vrf_id, std::string vrf_name, bool stats_match,
                     const vr_vrf_stats_req &req) {
      AgentUveStats *uve = static_cast<AgentUveStats *>(Agent::GetInstance()->uve());
      StatsManager *sm  = uve->stats_manager();
      const StatsManager::VrfStats *st = sm->GetVrfStats(vrf_id);
      if (st == NULL) {
          return false;
      }
  
      if (vrf_name.compare(st->name) != 0) {
          return false;
      }
  
      if (!stats_match) {
          return true;
      }
  
      if (st->discards == (uint64_t)req.get_vsr_discards() &&
          st->resolves == (uint64_t)req.get_vsr_resolves() &&
          st->receives == (uint64_t)req.get_vsr_receives() &&
          st->udp_tunnels == (uint64_t)req.get_vsr_udp_tunnels() &&
          st->udp_mpls_tunnels == (uint64_t)req.get_vsr_udp_mpls_tunnels() &&
          st->gre_mpls_tunnels == (uint64_t)req.get_vsr_gre_mpls_tunnels() &&
          st->ecmp_composites == (uint64_t)req.get_vsr_ecmp_composites() &&
          st->l2_mcast_composites == (uint64_t)req.get_vsr_l2_mcast_composites() &&
          st->fabric_composites == (uint64_t)req.get_vsr_fabric_composites() &&
          st->l2_encaps == (uint64_t)req.get_vsr_l2_encaps() &&
          st->encaps == (uint64_t)req.get_vsr_encaps() &&
          st->gros == (uint64_t)req.get_vsr_gros() &&
          st->diags == (uint64_t)req.get_vsr_diags() &&
          st->encap_composites == (uint64_t)req.get_vsr_encap_composites() &&
          st->evpn_composites == (uint64_t)req.get_vsr_evpn_composites() &&
          st->vrf_translates == (uint64_t)req.get_vsr_vrf_translates() &&
          st->vxlan_tunnels == (uint64_t)req.get_vsr_vxlan_tunnels() &&
          st->arp_virtual_proxy == (uint64_t)req.get_vsr_arp_virtual_proxy() &&
          st->arp_virtual_stitch == (uint64_t)req.get_vsr_arp_virtual_stitch() &&
          st->arp_virtual_flood == (uint64_t)req.get_vsr_arp_virtual_flood() &&
          st->arp_physical_stitch == (uint64_t)req.get_vsr_arp_physical_stitch() &&
          st->arp_tor_proxy == (uint64_t)req.get_vsr_arp_tor_proxy() &&
          st->arp_physical_flood == (uint64_t)req.get_vsr_arp_physical_flood() &&
          st->l2_receives == (uint64_t)req.get_vsr_l2_receives() &&
          st->uuc_floods == (uint64_t)req.get_vsr_uuc_floods()) {
          return true;
      }
      return false;
  }
  
  bool VrfStatsMatchPrev(int vrf_id, const vr_vrf_stats_req &req) {
      AgentUveStats *uve = static_cast<AgentUveStats *>(Agent::GetInstance()->uve());
      StatsManager *sm  = uve->stats_manager();
      const StatsManager::VrfStats *st = sm->GetVrfStats(vrf_id);
      if (st == NULL) {
          return false;
      }
  
      if (st->prev_discards == (uint64_t)req.get_vsr_discards() &&
          st->prev_resolves == (uint64_t)req.get_vsr_resolves() &&
          st->prev_receives == (uint64_t)req.get_vsr_receives() &&
          st->prev_udp_tunnels == (uint64_t)req.get_vsr_udp_tunnels() &&
          st->prev_udp_mpls_tunnels == (uint64_t)req.get_vsr_udp_mpls_tunnels() &&
          st->prev_gre_mpls_tunnels == (uint64_t)req.get_vsr_gre_mpls_tunnels() &&
          st->prev_ecmp_composites == (uint64_t)req.get_vsr_ecmp_composites() &&
          st->prev_l2_mcast_composites ==
              (uint64_t)req.get_vsr_l2_mcast_composites() &&
          st->prev_fabric_composites ==
              (uint64_t)req.get_vsr_fabric_composites() &&
          st->prev_l2_encaps == (uint64_t)req.get_vsr_l2_encaps() &&
          st->prev_encaps == (uint64_t)req.get_vsr_encaps() &&
          st->prev_gros == (uint64_t)req.get_vsr_gros() &&
          st->prev_diags == (uint64_t)req.get_vsr_diags() &&
          st->prev_encap_composites == (uint64_t)req.get_vsr_encap_composites() &&
          st->prev_evpn_composites == (uint64_t)req.get_vsr_evpn_composites() &&
          st->prev_vrf_translates == (uint64_t)req.get_vsr_vrf_translates() &&
          st->prev_vxlan_tunnels == (uint64_t)req.get_vsr_vxlan_tunnels() &&
          st->prev_arp_virtual_proxy ==
              (uint64_t)req.get_vsr_arp_virtual_proxy() &&
          st->prev_arp_virtual_stitch ==
              (uint64_t)req.get_vsr_arp_virtual_stitch() &&
          st->prev_arp_virtual_flood ==
              (uint64_t)req.get_vsr_arp_virtual_flood() &&
          st->prev_arp_physical_stitch ==
              (uint64_t)req.get_vsr_arp_physical_stitch() &&
          st->prev_arp_tor_proxy == (uint64_t)req.get_vsr_arp_tor_proxy() &&
          st->prev_arp_physical_flood ==
              (uint64_t)req.get_vsr_arp_physical_flood() &&
          st->prev_l2_receives == (uint64_t)req.get_vsr_l2_receives() &&
          st->prev_uuc_floods == (uint64_t)req.get_vsr_uuc_floods()) {
          return true;
      }
      return false;
  }
  
  bool VmPortStats(PortInfo *input, int id, uint32_t bytes, uint32_t pkts) {
      Interface *intf;
      VmInterfaceKey key(AgentKey::ADD_DEL_CHANGE, MakeUuid(input[id].intf_id),
                         input[id].name);
      intf=static_cast<Interface *>(Agent::GetInstance()->interface_table()->FindActiveEntry(&key));
      if (intf == NULL)
          return false;
  
      AgentUveStats *uve = static_cast<AgentUveStats *>(Agent::GetInstance()->uve());
      StatsManager *sm  = uve->stats_manager();
      const StatsManager::InterfaceStats *st = sm->GetInterfaceStats(intf);
      if (st == NULL)
          return false;
  
      if (st->in_pkts == pkts && st->in_bytes == bytes)
          return true;
      return false;
  }
  
  bool VmPortStatsMatch(Interface *intf, uint32_t ibytes, uint32_t ipkts,
                        uint32_t obytes, uint32_t opkts) {
      AgentUveStats *uve = static_cast<AgentUveStats *>(Agent::GetInstance()->uve());
      StatsManager *sm  = uve->stats_manager();
      const StatsManager::InterfaceStats *st = sm->GetInterfaceStats(intf);
      EXPECT_TRUE(st != NULL);
      if (st == NULL)
          return false;
  
      if (st->in_pkts == ipkts && st->in_bytes == ibytes &&
          st->out_pkts == opkts && st->out_bytes == obytes) {
          return true;
      }
      LOG(DEBUG, "ipkts " << st->in_pkts << " ibytes " << st->in_bytes <<
                 " opkts " << st->out_pkts << " obytes " << st->out_bytes);
      return false;
  }
  
  bool VmPortL2Inactive(int id) {
      Interface *intf;
      VmInterfaceKey key(AgentKey::ADD_DEL_CHANGE, MakeUuid(id), "");
      intf=static_cast<Interface *>(Agent::GetInstance()->interface_table()->FindActiveEntry(&key));
      if (intf == NULL)
          return false;
      return (intf->l2_active() == false);
  }
  
  bool VmPortL2Inactive(PortInfo *input, int id) {
      Interface *intf;
      VmInterfaceKey key(AgentKey::ADD_DEL_CHANGE, MakeUuid(input[id].intf_id),
                         input[id].name);
      intf=static_cast<Interface *>(Agent::GetInstance()->interface_table()->FindActiveEntry(&key));
      if (intf == NULL)
          return false;
  
      return (intf->l2_active() == false);
  }
  
  bool VmPortInactive(int id) {
      Interface *intf;
      VmInterfaceKey key(AgentKey::ADD_DEL_CHANGE, MakeUuid(id), "");
      intf=static_cast<Interface *>(Agent::GetInstance()->interface_table()->FindActiveEntry(&key));
      if (intf == NULL)
          return false;
      return (intf->ipv4_active() == false);
  }
  
  bool VmPortInactive(PortInfo *input, int id) {
      Interface *intf;
      VmInterfaceKey key(AgentKey::ADD_DEL_CHANGE, MakeUuid(input[id].intf_id),
                         input[id].name);
      intf=static_cast<Interface *>(Agent::GetInstance()->interface_table()->FindActiveEntry(&key));
      if (intf == NULL)
          return false;
  
      return (intf->ipv4_active() == false);
  }
  
  PhysicalInterface *EthInterfaceGet(const char *name) {
      PhysicalInterface *intf;
      PhysicalInterfaceKey key(name);
      intf=static_cast<PhysicalInterface *>(Agent::GetInstance()->interface_table()->FindActiveEntry(&key));
      return intf;
  }
  
  bool getIntfStatus(PhysicalInterface *pintf, const string& intf_name)
  {
      bool ret = false;
      PhysicalInterface::BondChildIntfMap bond_childIntf_map =
          pintf->getBondChildIntfMap();
      PhysicalInterface::BondChildIntfMapIterator it =
          bond_childIntf_map.find(intf_name);
      if(it != bond_childIntf_map.end())
      {
          ret = (it->second).intf_status;
      }
  
      return ret;
  }
  
  void
  delTestPhysicalIntfFromMap(PhysicalInterface *pintf, const string& intf_name)
  {
      PhysicalInterface::BondChildIntfMap bond_childIntf_map =
          pintf->getBondChildIntfMap();
      PhysicalInterface::BondChildIntfMapIterator it =
          bond_childIntf_map.find(intf_name);
      if(it != bond_childIntf_map.end())
      {
          bond_childIntf_map.erase(intf_name);
      }
      pintf->setBondChildIntfMap(bond_childIntf_map);
  }
  
  VmInterface *VmInterfaceGet(int id) {
      VmInterface *intf;
      VmInterfaceKey key(AgentKey::ADD_DEL_CHANGE, MakeUuid(id), "");
      intf = static_cast<VmInterface *>(Agent::GetInstance()->interface_table()->FindActiveEntry(&key));
      return intf;
  }
  
  bool VmPortPolicyEnable(int id) {
      VmInterface *intf;
      VmInterfaceKey key(AgentKey::ADD_DEL_CHANGE, MakeUuid(id), "");
      intf = static_cast<VmInterface *>(Agent::GetInstance()->interface_table()->FindActiveEntry(&key));
      if (intf == NULL)
          return false;
  
      return (intf->policy_enabled() == true);
  }
  
  bool VmPortPolicyEnable(PortInfo *input, int id) {
      return VmPortPolicyEnable(input[id].intf_id);
  }
  
  bool VmPortPolicyDisable(int id) {
      VmInterface *intf;
      VmInterfaceKey key(AgentKey::ADD_DEL_CHANGE, MakeUuid(id), "");
      intf = static_cast<VmInterface *>(Agent::GetInstance()->interface_table()->FindActiveEntry(&key));
      if (intf == NULL)
          return false;
  
      return (intf->policy_enabled() == false);
  }
  bool VmPortPolicyDisable(PortInfo *input, int id) {
      return VmPortPolicyDisable(input[id].intf_id);
  }
  
  bool DBTableFind(const string &table_name) {
     return (Agent::GetInstance()->db()->FindTable(table_name) != NULL);
  }
  
  void VnAddReq(int id, const char *name) {
      std::vector<VnIpam> ipam;
      VnData::VnIpamDataMap vn_ipam_data;
      Agent::GetInstance()->vn_table()->AddVn(
          MakeUuid(id), name, boost::uuids::nil_uuid(), name, ipam, vn_ipam_data,
          id, (id + 100), true, true, false, false, false, false);
      usleep(1000);
  }
  
  void VnAddReq(int id, const char *name, int acl_id) {
      std::vector<VnIpam> ipam;
      VnData::VnIpamDataMap vn_ipam_data;
      Agent::GetInstance()->vn_table()->AddVn(MakeUuid(id), name,
                                                MakeUuid(acl_id),
                                                name, ipam, vn_ipam_data, id,
                                                (id + 100), true, true, false,
                                                false, false, false);
      usleep(1000);
  }
  
  void VnAddReq(int id, const char *name, int acl_id, const char *vrf_name) {
      std::vector<VnIpam> ipam;
      VnData::VnIpamDataMap vn_ipam_data;
      Agent::GetInstance()->vn_table()->AddVn(MakeUuid(id), name,
                                                MakeUuid(acl_id), vrf_name, ipam,
                                                vn_ipam_data, id, (id + 100),
                                                true, true, false,
                                                false, false, false);
      usleep(1000);
  }
  
  void VnAddReq(int id, const char *name, const char *vrf_name) {
      std::vector<VnIpam> ipam;
      VnData::VnIpamDataMap vn_ipam_data;
      Agent::GetInstance()->vn_table()->AddVn(
          MakeUuid(id), name, boost::uuids::nil_uuid(), vrf_name, ipam,
          vn_ipam_data, id, (id + 100), true, true, false, false, false, false);
      usleep(1000);
  }
  
  void VnVxlanAddReq(int id, const char *name, uint32_t vxlan_id) {
      std::vector<VnIpam> ipam;
      VnData::VnIpamDataMap vn_ipam_data;
      Agent::GetInstance()->vn_table()->AddVn(
          MakeUuid(id), name, boost::uuids::nil_uuid(), name, ipam, vn_ipam_data,
          id, vxlan_id, true, true, false, false, false, false);
  }
  
  void VnDelReq(int id) {
      Agent::GetInstance()->vn_table()->DelVn(MakeUuid(id));
      usleep(1000);
  }
  
  void VrfAddReq(const char *name) {
      Agent::GetInstance()->vrf_table()->CreateVrfReq(name);
      usleep(1000);
  }
  
  void VrfAddReq(const char *name, const boost::uuids::uuid &vn_uuid) {
      Agent::GetInstance()->vrf_table()->CreateVrfReq(name, vn_uuid);
      usleep(1000);
  }
  
  void VrfDelReq(const char *name) {
      Agent::GetInstance()->vrf_table()->DeleteVrfReq(name);
      usleep(1000);
  }
  
  void VmAddReq(int id) {
      char vm_name[80];
      VmKey *key = new VmKey(MakeUuid(id));
      VmData::SGUuidList sg_list(0);
      sprintf(vm_name, "vm%d", id);
      VmData *data = new VmData(Agent::GetInstance(), NULL, string(vm_name),
                                sg_list);
      DBRequest req;
  
      req.oper = DBRequest::DB_ENTRY_ADD_CHANGE;
      req.key.reset(key);
      req.data.reset(data);
  
      Agent::GetInstance()->vm_table()->Enqueue(&req);
      usleep(1000);
  }
  
  void VmDelReq(int id) {
      VmKey *key = new VmKey(MakeUuid(id));
      DBRequest req;
  
      req.oper = DBRequest::DB_ENTRY_DELETE;
      req.key.reset(key);
      req.data.reset(NULL);
  
      Agent::GetInstance()->vm_table()->Enqueue(&req);
      usleep(1000);
  }
  
  void AclAddReq(int id) {
      AclSpec *acl_spec = new AclSpec();
      AclEntrySpec *entry_spec = new AclEntrySpec();
      entry_spec->id = id;
      entry_spec->terminal = false;
      acl_spec->acl_entry_specs_.push_back(*entry_spec);
      delete entry_spec;
  
      DBRequest req;
      req.oper = DBRequest::DB_ENTRY_ADD_CHANGE;
  
      AclKey *key = new AclKey(MakeUuid(id));
      req.key.reset(key);
  
      AclData *data = new AclData(Agent::GetInstance(), NULL, *acl_spec);
      req.data.reset(data);
      Agent::GetInstance()->acl_table()->Enqueue(&req);
      delete acl_spec;
      usleep(1000);
  }
  
  void AclDelReq(int id) {
      DBRequest req;
      req.oper = DBRequest::DB_ENTRY_DELETE;
      AclKey *key = new AclKey(MakeUuid(id));
      req.key.reset(key);
      req.data.reset(NULL);
      Agent::GetInstance()->acl_table()->Enqueue(&req);
      usleep(1000);
  }
  
  void AclAddReq(int id, int ace_id, bool drop) {
      AclSpec *acl_spec = new AclSpec();
      acl_spec->acl_id = MakeUuid(id);
  
      AclEntrySpec *ae_spec = new AclEntrySpec();
      ae_spec->id = ace_id;
      ae_spec->terminal = true;
      ActionSpec action;
      action.ta_type = TrafficAction::SIMPLE_ACTION;
      if (drop) {
          action.simple_action = TrafficAction::DENY;
      } else {
          action.simple_action = TrafficAction::PASS;
      }
      ae_spec->action_l.push_back(action);
      acl_spec->acl_entry_specs_.push_back(*ae_spec);
      delete ae_spec;
  
      DBRequest req;
      req.oper = DBRequest::DB_ENTRY_ADD_CHANGE;
      AclKey *key = new AclKey(MakeUuid(id));
      AclData *data = new AclData(Agent::GetInstance(), NULL, *acl_spec);
  
      req.key.reset(key);
      req.data.reset(data);
      Agent::GetInstance()->acl_table()->Enqueue(&req);
      delete acl_spec;
      usleep(1000);
  }
  
  void DeleteRoute(const char *vrf, const char *ip) {
      Ip4Address addr = Ip4Address::from_string(ip);
      Agent::GetInstance()->fabric_inet4_unicast_table()->DeleteReq(NULL,
                                              vrf, addr, 32, NULL);
      client->WaitForIdle();
      WAIT_FOR(1000, 1, (RouteFind(vrf, addr, 32) == false));
  }
  
  void DeleteRoute(const char *vrf, const char *ip, uint8_t plen,
                   const Peer *peer) {
      Ip4Address addr = Ip4Address::from_string(ip);
      const BgpPeer *bgp_peer = dynamic_cast<const BgpPeer *>(peer);
      if (bgp_peer == NULL) {
          Agent::GetInstance()->fabric_inet4_unicast_table()->
              DeleteReq(peer, vrf, addr, plen, NULL);
      } else {
          Agent::GetInstance()->fabric_inet4_unicast_table()->
              DeleteReq(peer, vrf, addr, plen,
                        new ControllerVmRoute(bgp_peer));
      }
      client->WaitForIdle();
      WAIT_FOR(1000, 1000, (RouteFind(vrf, addr, 32) == false));
  }
  
  bool RouteFind(const string &vrf_name, const Ip4Address &addr, int plen) {
      VrfEntry *vrf = Agent::GetInstance()->vrf_table()->FindVrfFromName(vrf_name);
      if (vrf == NULL)
          return false;
  
      const Agent *agent = (static_cast<VrfTable *>(vrf->get_table()))->agent();
      InetUnicastRouteKey key(agent->local_vm_peer(), vrf_name, addr, plen);
      if (!vrf->GetInet4UnicastRouteTable()) {
          return false;
      }
  
      InetUnicastRouteEntry* route =
          static_cast<InetUnicastRouteEntry *>
          (vrf->GetInet4UnicastRouteTable()->FindActiveEntry(&key));
      return (route != NULL);
  }
  
  bool RouteFind(const string &vrf_name, const string &addr, int plen) {
      return RouteFind(vrf_name, Ip4Address::from_string(addr), plen);
  }
  
  bool RouteFindMpls(const string &vrf_name, const Ip4Address &addr, int plen) {
      VrfEntry *vrf = Agent::GetInstance()->vrf_table()->FindVrfFromName(vrf_name);
      if (vrf == NULL)
          return false;
  
      const Agent *agent = (static_cast<VrfTable *>(vrf->get_table()))->agent();
      InetMplsUnicastRouteKey key(agent->local_vm_peer(), vrf_name, addr, plen);
      if (!vrf->GetInet4MplsUnicastRouteTable()) {
          return false;
      }
  
      InetUnicastRouteEntry* route =
          static_cast<InetUnicastRouteEntry *>
          (vrf->GetInet4MplsUnicastRouteTable()->FindActiveEntry(&key));
      return (route != NULL);
  }
  
  bool RouteFindMpls(const string &vrf_name, const string &addr, int plen) {
      return RouteFindMpls(vrf_name, Ip4Address::from_string(addr), plen);
  }
  
  bool RouteFindV6(const string &vrf_name, const Ip6Address &addr, int plen) {
      VrfEntry *vrf = Agent::GetInstance()->vrf_table()->FindVrfFromName(vrf_name);
      if (vrf == NULL)
          return false;
  
      const Agent *agent = (static_cast<VrfTable *>(vrf->get_table()))->agent();
      InetUnicastRouteKey key(agent->local_vm_peer(), vrf_name, addr, plen);
      InetUnicastRouteEntry* route =
          static_cast<InetUnicastRouteEntry *>
          (vrf->GetInet6UnicastRouteTable()->FindActiveEntry(&key));
      return (route != NULL);
  }
  
  bool RouteFindV6(const string &vrf_name, const string &addr, int plen) {
      return RouteFindV6(vrf_name, Ip6Address::from_string(addr), plen);
  }
  
  bool L2RouteFind(const string &vrf_name, const MacAddress &mac,
                   const IpAddress &ip_addr) {
      if (Agent::GetInstance()->vrf_table() == NULL) {
          return false;
      }
      BridgeAgentRouteTable *bridge_table =
          static_cast<BridgeAgentRouteTable *>
          (Agent::GetInstance()->vrf_table()->GetBridgeRouteTable(vrf_name));
      if (bridge_table == NULL)
          return false;
      BridgeRouteEntry *route = bridge_table->FindRoute(mac);
      return (route != NULL);
  }
  
  bool L2RouteFind(const string &vrf_name, const MacAddress &mac) {
      return L2RouteFind(vrf_name, mac, IpAddress());
  }
  
  bool MCRouteFind(const string &vrf_name, const Ip4Address &grp_addr,
                   const Ip4Address &src_addr) {
      VrfEntry *vrf = Agent::GetInstance()->vrf_table()->FindVrfFromName(vrf_name);
      if (vrf == NULL)
          return false;
  
      Inet4MulticastRouteKey key(vrf_name, src_addr, grp_addr);
      Inet4MulticastRouteEntry *route =
          static_cast<Inet4MulticastRouteEntry *>
          (static_cast<Inet4MulticastAgentRouteTable *>(vrf->
               GetInet4MulticastRouteTable())->FindActiveEntry(&key));
      return (route != NULL);
  }
  
  bool MCRouteFind(const string &vrf_name, const string &grp_addr,
                   const string &src_addr) {
      return MCRouteFind(vrf_name, Ip4Address::from_string(grp_addr),
                         Ip4Address::from_string(src_addr));
  }
  
  bool MCRouteFind(const string &vrf_name, const Ip4Address &grp_addr) {
      VrfEntry *vrf = Agent::GetInstance()->vrf_table()->FindVrfFromName(vrf_name);
      if (vrf == NULL)
          return false;
  
      Inet4MulticastRouteKey key(vrf_name, grp_addr);
      Inet4MulticastRouteEntry *route =
          static_cast<Inet4MulticastRouteEntry *>
          (static_cast<Inet4MulticastAgentRouteTable *>(vrf->
               GetInet4MulticastRouteTable())->FindActiveEntry(&key));
      return (route != NULL);
  }
  
  bool MCRouteFind(const string &vrf_name, const string &grp_addr) {
      return MCRouteFind(vrf_name, Ip4Address::from_string(grp_addr));
  
  }
  
  BridgeRouteEntry *L2RouteGet(const string &vrf_name, const MacAddress &mac,
                               const IpAddress &ip_addr) {
      Agent *agent = Agent::GetInstance();
      VrfEntry *vrf = agent->vrf_table()->FindVrfFromName(vrf_name);
      if (vrf == NULL)
          return NULL;
  
      BridgeRouteKey key(agent->local_vm_peer(), vrf_name, mac);
      BridgeRouteEntry *route =
          static_cast<BridgeRouteEntry *>
          (static_cast<BridgeAgentRouteTable *>(vrf->
               GetBridgeRouteTable())->FindActiveEntry(&key));
      return route;
  }
  
  BridgeRouteEntry *L2RouteGet(const string &vrf_name,
                               const MacAddress &mac) {
      return L2RouteGet(vrf_name, mac, IpAddress());
  }
  
  const NextHop* L2RouteToNextHop(const string &vrf, const MacAddress &mac) {
      BridgeRouteEntry* rt = L2RouteGet(vrf, mac);
      if (rt == NULL)
          return NULL;
  
      return rt->GetActiveNextHop();
  }
  
  EvpnRouteEntry *EvpnRouteGet(const string &vrf_name, const MacAddress &mac,
                               const IpAddress &ip_addr, uint32_t ethernet_tag) {
      Agent *agent = Agent::GetInstance();
      VrfEntry *vrf = agent->vrf_table()->FindVrfFromName(vrf_name);
      if (vrf == NULL)
          return NULL;
  
      uint32_t plen = 32;
      if (ip_addr.is_v6())
          plen = 128;
      EvpnRouteKey key(agent->local_vm_peer(), vrf_name, mac, ip_addr,
                       plen, ethernet_tag);
      EvpnRouteEntry *route =
          static_cast<EvpnRouteEntry *>
          (static_cast<EvpnAgentRouteTable *>
           (vrf->GetEvpnRouteTable())->FindActiveEntry(&key));
      return route;
  }
  
  InetUnicastRouteEntry* RouteGet(const string &vrf_name, const Ip4Address &addr, int plen) {
      VrfEntry *vrf = Agent::GetInstance()->vrf_table()->FindVrfFromName(vrf_name);
      if (vrf == NULL)
          return NULL;
  
      const Agent *agent = (static_cast<VrfTable *>(vrf->get_table()))->agent();
      InetUnicastRouteKey key(agent->local_vm_peer(), vrf_name, addr, plen);
      InetUnicastRouteEntry* route =
          static_cast<InetUnicastRouteEntry *>
          (vrf->GetInet4UnicastRouteTable()->FindActiveEntry(&key));
      return route;
  }
  
  InetUnicastRouteEntry* RouteGetLPM(const string &vrf_name, const Ip4Address &addr) {
      VrfEntry *vrf = Agent::GetInstance()->vrf_table()->FindVrfFromName(vrf_name);
      if (vrf == NULL) {
          return NULL;
      }
  
      InetUnicastRouteEntry* route =
          static_cast<InetUnicastRouteEntry *>
          (vrf->GetInet4UnicastRouteTable()->FindLPM(addr));
  
      return route;
  }
  
  InetUnicastRouteEntry* RouteGetMpls(const string &vrf_name, const Ip4Address &addr, int plen) {
      VrfEntry *vrf = Agent::GetInstance()->vrf_table()->FindVrfFromName(vrf_name);
      if (vrf == NULL)
          return NULL;
  
      const Agent *agent = (static_cast<VrfTable *>(vrf->get_table()))->agent();
      InetMplsUnicastRouteKey key(agent->local_vm_peer(), vrf_name, addr, plen);
      InetUnicastRouteEntry* route =
          static_cast<InetUnicastRouteEntry *>
          (vrf->GetInet4MplsUnicastRouteTable()->FindActiveEntry(&key));
      return route;
  }
  InetUnicastRouteEntry* RouteGetV6(const string &vrf_name, const Ip6Address &addr, int plen) {
      VrfEntry *vrf = Agent::GetInstance()->vrf_table()->FindVrfFromName(vrf_name);
      if (vrf == NULL)
          return NULL;
  
      const Agent *agent = (static_cast<VrfTable *>(vrf->get_table()))->agent();
      InetUnicastRouteKey key(agent->local_vm_peer(), vrf_name, addr, plen);
      InetUnicastRouteEntry* route =
          static_cast<InetUnicastRouteEntry *>
          (vrf->GetInet6UnicastRouteTable()->FindActiveEntry(&key));
      return route;
  }
  
  const NextHop* RouteToNextHop(const string &vrf_name, const Ip4Address &addr,
                                int plen) {
      InetUnicastRouteEntry* rt = RouteGet(vrf_name, addr, plen);
      if (rt == NULL)
          return NULL;
  
      return rt->GetActiveNextHop();
  }
  
  const NextHop* LPMRouteToNextHop(const string &vrf_name,
                                      const Ip4Address &addr) {
  
      InetUnicastRouteEntry* rt = RouteGetLPM(vrf_name, addr);
      if (rt == NULL)
          return NULL;
  
      return rt->GetActiveNextHop();
  }
  
  Inet4MulticastRouteEntry *MCRouteGet(const string &vrf_name, const Ip4Address &grp_addr) {
      VrfEntry *vrf = Agent::GetInstance()->vrf_table()->FindVrfFromName(vrf_name);
      if (vrf == NULL)
          return NULL;
  
      Inet4MulticastRouteKey key(vrf_name, grp_addr);
      Inet4MulticastRouteEntry *route =
          static_cast<Inet4MulticastRouteEntry *>
          (static_cast<Inet4MulticastAgentRouteTable *>(vrf->
               GetInet4MulticastRouteTable())->FindActiveEntry(&key));
      return route;
  }
  
  Inet4MulticastRouteEntry *MCRouteGet(const Peer *peer, const string &vrf_name,
                              const Ip4Address &grp_addr,
                              const Ip4Address &src_addr) {
      VrfEntry *vrf = Agent::GetInstance()->vrf_table()->FindVrfFromName(vrf_name);
      if (vrf == NULL)
          return NULL;
  
      Inet4MulticastRouteKey key(peer, vrf_name, grp_addr, src_addr, 0);
      Inet4MulticastRouteEntry *route =
          static_cast<Inet4MulticastRouteEntry *>
          (static_cast<Inet4MulticastAgentRouteTable *>(vrf->
               GetInet4MulticastRouteTable())->FindActiveEntry(&key));
      return route;
  }
  
  Inet4MulticastRouteEntry *MCRouteGet(const string &vrf_name, const string &grp_addr) {
      VrfEntry *vrf = Agent::GetInstance()->vrf_table()->FindVrfFromName(vrf_name);
      if (vrf == NULL)
          return NULL;
  
      Inet4MulticastRouteKey key(vrf_name, Ip4Address::from_string(grp_addr));
      Inet4MulticastRouteEntry *route =
          static_cast<Inet4MulticastRouteEntry *>
          (static_cast<Inet4MulticastAgentRouteTable *>(vrf->
               GetInet4MulticastRouteTable())->FindActiveEntry(&key));
      return route;
  }
  
  const NextHop* MCRouteToNextHop(const Peer *peer, const string &vrf_name,
                              const Ip4Address &grp_addr,
                              const Ip4Address &src_addr) {
  
      Inet4MulticastRouteEntry* rt = MCRouteGet(peer, vrf_name, grp_addr,
                                                  src_addr);
      if (rt == NULL)
          return NULL;
  
      return rt->GetActiveNextHop();
  }
  
  bool TunnelNHFind(const Ip4Address &server_ip, bool policy, TunnelType::Type type) {
      TunnelNHKey key(Agent::GetInstance()->fabric_vrf_name(),
                      Agent::GetInstance()->router_id(), server_ip,
                      policy, type);
      NextHop *nh = static_cast<NextHop *>(Agent::GetInstance()->nexthop_table()->FindActiveEntry(&key));
      return (nh != NULL);
  }
  
  NextHop *ReceiveNHGet(NextHopTable *table, const char *ifname, bool policy) {
      ReceiveNHKey key(new InetInterfaceKey(ifname), policy);
      return static_cast<NextHop *> (table->FindActiveEntry(&key));
  }
  
  bool TunnelNHFind(const Ip4Address &server_ip) {
      return TunnelNHFind(server_ip, false, TunnelType::MPLS_GRE);
  }
  
  bool VlanNhFind(int id, uint16_t tag) {
      VlanNHKey key(MakeUuid(id), tag);
      NextHop *nh = static_cast<NextHop *>(Agent::GetInstance()->nexthop_table()->FindActiveEntry(&key));
      return (nh != NULL);
  }
  
  bool BridgeTunnelRouteAdd(const BgpPeer *peer, const string &vm_vrf,
                            TunnelType::TypeBmap bmap, const Ip4Address &server_ip,
                            uint32_t label, MacAddress &remote_vm_mac,
                            const IpAddress &vm_addr, uint8_t plen,
                            const std::string &rewrite_dmac,
                            uint32_t tag, bool leaf) {
      VnListType vn_list;
      ControllerVmRoute *data =
          ControllerVmRoute::MakeControllerVmRoute(peer,
                                Agent::GetInstance()->fabric_vrf_name(),
                                Agent::GetInstance()->router_id(),
                                vm_vrf, server_ip,
                                bmap, label, MacAddress(rewrite_dmac),
                                vn_list, SecurityGroupList(),
                                TagList(),
                                PathPreference(), false, EcmpLoadBalance(),
                                leaf);
      EvpnAgentRouteTable::AddRemoteVmRouteReq(peer, vm_vrf, remote_vm_mac,
                                          vm_addr, 32, tag, data);
      return true;
  }
  
  bool BridgeTunnelRouteAdd(const BgpPeer *peer, const string &vm_vrf,
                            TunnelType::TypeBmap bmap, const Ip4Address &server_ip,
                            uint32_t label, MacAddress &remote_vm_mac,
                            const IpAddress &vm_addr, uint8_t plen, uint32_t tag,
                            bool leaf) {
      VnListType vn_list;
      ControllerVmRoute *data =
          ControllerVmRoute::MakeControllerVmRoute(peer,
                                Agent::GetInstance()->fabric_vrf_name(),
                                Agent::GetInstance()->router_id(),
                                vm_vrf, server_ip,
                                bmap, label, MacAddress(),
                                vn_list, SecurityGroupList(),
                                TagList(),
                                PathPreference(), false, EcmpLoadBalance(),
                                leaf);
      EvpnAgentRouteTable::AddRemoteVmRouteReq(peer, vm_vrf, remote_vm_mac,
                                          vm_addr, 32, tag, data);
      return true;
  }
  
  bool BridgeTunnelRouteAdd(const BgpPeer *peer, const string &vm_vrf,
                            TunnelType::TypeBmap bmap, const char *server_ip,
                            uint32_t label, MacAddress &remote_vm_mac,
                            const char *vm_addr, uint8_t plen,uint32_t tag,
                            bool leaf) {
      boost::system::error_code ec;
      return BridgeTunnelRouteAdd(peer, vm_vrf, bmap,
                                  Ip4Address::from_string(server_ip, ec), label, remote_vm_mac,
                                  IpAddress::from_string(vm_addr, ec), plen, tag, leaf);
  }
  
  bool EcmpTunnelRouteAdd(const BgpPeer *peer, const string &vrf_name,
                          const Ip4Address &vm_ip,
                         uint8_t plen, ComponentNHKeyList &comp_nh_list,
                         bool local_ecmp, const string &vn_name, const SecurityGroupList &sg,
                         const TagList &tag,
                         const PathPreference &path_preference,
                         bool copy_local_path) {
      COMPOSITETYPE type = Composite::ECMP;
      if (local_ecmp) {
          type = Composite::LOCAL_ECMP;
      }
      DBRequest nh_req(DBRequest::DB_ENTRY_ADD_CHANGE);
      nh_req.key.reset(new CompositeNHKey(type, false,
                                          comp_nh_list, vrf_name));
      nh_req.data.reset(new CompositeNHData());
  
      TunnelType::TypeBmap tunnel_bmap = TunnelType::MplsType();
      if (copy_local_path) {
          tunnel_bmap = TunnelType::NativeType();
      }
  
      VnListType vn_list;
      vn_list.insert(vn_name);
      ControllerEcmpRoute *data =
          new ControllerEcmpRoute(peer, vn_list, EcmpLoadBalance(), tag, sg,
                                  path_preference, tunnel_bmap,
                                  nh_req, vm_ip.to_string());
      data->set_copy_local_path(copy_local_path);
      InetUnicastAgentRouteTable::AddRemoteVmRouteReq(peer, vrf_name, vm_ip, plen, data);
      return true;
  }
  
  bool EcmpTunnelRouteAdd(const BgpPeer *peer, const string &vrf_name,
                          const Ip4Address &vm_ip,
                         uint8_t plen, ComponentNHKeyList &comp_nh_list,
                         bool local_ecmp, const string &vn_name, const SecurityGroupList &sg,
                         const TagList &tag,
                         const PathPreference &path_preference,
                         EcmpLoadBalance &ecmp_load_balance) {
      COMPOSITETYPE type = Composite::ECMP;
      if (local_ecmp) {
          type = Composite::LOCAL_ECMP;
      }
      DBRequest nh_req(DBRequest::DB_ENTRY_ADD_CHANGE);
      nh_req.key.reset(new CompositeNHKey(type, false,
                                          comp_nh_list, vrf_name));
      nh_req.data.reset(new CompositeNHData());
  
      VnListType vn_list;
      vn_list.insert(vn_name);
      ControllerEcmpRoute *data =
          new ControllerEcmpRoute(peer, vn_list, ecmp_load_balance, tag, sg,
                                  path_preference, TunnelType::MplsType(),
                                  nh_req, vm_ip.to_string());
      InetUnicastAgentRouteTable::AddRemoteVmRouteReq(peer, vrf_name, vm_ip, plen, data);
      return true;
  }
  
  bool Inet6TunnelRouteAdd(const BgpPeer *peer, const string &vm_vrf, const Ip6Address &vm_addr,
                           uint8_t plen, const Ip4Address &server_ip, TunnelType::TypeBmap bmap,
                           uint32_t label, const string &dest_vn_name,
                           const SecurityGroupList &sg,
                           const TagList &tag,
                           const PathPreference &path_preference) {
      VnListType vn_list;
      vn_list.insert(dest_vn_name);
      ControllerVmRoute *data =
          ControllerVmRoute::MakeControllerVmRoute(peer,
                                Agent::GetInstance()->fabric_vrf_name(),
                                Agent::GetInstance()->router_id(),
                                vm_vrf, server_ip,
                                bmap, label, MacAddress(), vn_list, sg, tag,
                                path_preference, false, EcmpLoadBalance(),
                                false);
      InetUnicastAgentRouteTable::AddRemoteVmRouteReq(peer, vm_vrf,
                                          vm_addr, plen, data);
      return true;
  }
  
  bool EcmpTunnelRouteAdd(Agent *agent, const BgpPeer *peer, const string &vrf,
                          const string &prefix, uint8_t plen,
                          const string &remote_server_1, uint32_t label1,
                          const string &remote_server_2, uint32_t label2,
                          const string &vn) {
      Ip4Address remote_server_ip1 = Ip4Address::from_string(remote_server_1);
      Ip4Address remote_server_ip2 = Ip4Address::from_string(remote_server_2);
      ComponentNHKeyPtr nh_data1(new ComponentNHKey(label1,
                                                    agent->fabric_vrf_name(),
                                                    agent->router_id(),
                                                    remote_server_ip1, false,
                                                    TunnelType::DefaultType()));
  
      ComponentNHKeyPtr nh_data2(new ComponentNHKey(label2,
                                                    agent->fabric_vrf_name(),
                                                    agent->router_id(),
                                                    remote_server_ip2,
                                                    false,
                                                    TunnelType::DefaultType()));
      ComponentNHKeyList comp_nh_list;
      comp_nh_list.push_back(nh_data1);
      comp_nh_list.push_back(nh_data2);
  
      SecurityGroupList sg_id_list;
      TagList tag_id_list;
      bool ret = EcmpTunnelRouteAdd(peer, vrf, Ip4Address::from_string(prefix), plen,
                                    comp_nh_list, false, vn, sg_id_list, tag_id_list,
                                    PathPreference(), false);
      client->WaitForIdle();
      return ret;
  }
  
  bool MplsVpnEcmpTunnelAdd(const BgpPeer *peer, const string &vrf,
                          const Ip4Address &prefix, uint8_t plen,
                          Ip4Address  &remote_server_1, uint32_t label1,
                          Ip4Address &remote_server_2, uint32_t label2,
                          const string &vn) {
      std::vector<IpAddress>tunnel_list;
      std::vector<uint32_t>label_list;
      tunnel_list.push_back(remote_server_1);
      tunnel_list.push_back(remote_server_2);
      label_list.push_back(label1);
      label_list.push_back(label2);
  
      SecurityGroupList sg;
      TagList tag;
      VnListType vn_list;
      vn_list.insert(vn);
      ControllerEcmpRoute *data =
          new ControllerEcmpRoute(peer, vn_list, EcmpLoadBalance(), tag, sg,
                                  PathPreference(), 1 << TunnelType::MPLS_OVER_MPLS,
                                  tunnel_list, label_list, prefix.to_string(),vrf);
      InetUnicastAgentRouteTable::AddRemoteVmRouteReq(peer, vrf, prefix, plen, data);
      client->WaitForIdle();
      return true;
  }
  bool MplsLabelInetEcmpTunnelAdd(const BgpPeer *peer, const string &vrf,
                          const Ip4Address &prefix, uint8_t plen,
                          Ip4Address  &remote_server_1, uint32_t label1,
                          Ip4Address &remote_server_2, uint32_t label2,
                          const string &vn) {
                  Agent *agent = Agent::GetInstance();
                  TunnelType::TypeBmap encap = 1 << TunnelType::MPLS_OVER_MPLS;
      LabelledTunnelNHKey *nh_key1 = new LabelledTunnelNHKey(
                                  agent->fabric_vrf_name(),
                                  agent->router_id(),
                                  remote_server_1,
                                  false,
                                  TunnelType::ComputeType(encap),
                                  MacAddress(),
                                  label1);
      std::auto_ptr<const NextHopKey> nh_key_ptr1(nh_key1);
      ComponentNHKeyPtr component_nh_key1(new ComponentNHKey(label1,
                                                          nh_key_ptr1));
      LabelledTunnelNHKey *nh_key2 = new LabelledTunnelNHKey(
                                  agent->fabric_vrf_name(),
                                  agent->router_id(),
                                  remote_server_2,
                                  false,
                                  TunnelType::ComputeType(encap),
                                  MacAddress(),
                                  label1);
      std::auto_ptr<const NextHopKey> nh_key_ptr2(nh_key2);
      ComponentNHKeyPtr component_nh_key2(new ComponentNHKey(label2,
                                                          nh_key_ptr2));
      ComponentNHKeyList comp_nh_list;
      comp_nh_list.push_back(component_nh_key1);
      comp_nh_list.push_back(component_nh_key2);
      COMPOSITETYPE type = Composite::LU_ECMP;
      SecurityGroupList sg;
      TagList tag;
      VnListType vn_list;
      vn_list.insert(vn);
      DBRequest nh_req(DBRequest::DB_ENTRY_ADD_CHANGE);
      nh_req.key.reset(new CompositeNHKey(type, false,
                                          comp_nh_list, vrf));
      nh_req.data.reset(new CompositeNHData());
  
      ControllerEcmpRoute *data =
          new ControllerEcmpRoute(peer, vn_list, EcmpLoadBalance(), tag, sg,
                                  PathPreference(), 1 << TunnelType::MPLS_OVER_MPLS,
                                  nh_req, prefix.to_string());
      InetUnicastAgentRouteTable::AddMplsRouteReq(peer, vrf, prefix, plen, data);
      client->WaitForIdle();
      return true;
  }
  bool Inet4TunnelRouteAdd(const BgpPeer *peer, const string &vm_vrf, const Ip4Address &vm_addr,
                           uint8_t plen, const Ip4Address &server_ip, TunnelType::TypeBmap bmap,
                           uint32_t label, const string &dest_vn_name,
                           const SecurityGroupList &sg,
                           const TagList &tag,
                           const PathPreference &path_preference) {
      VnListType vn_list;
      vn_list.insert(dest_vn_name);
      ControllerVmRoute *data =
          ControllerVmRoute::MakeControllerVmRoute(peer,
                                Agent::GetInstance()->fabric_vrf_name(),
                                Agent::GetInstance()->router_id(),
                                vm_vrf, server_ip,
                                bmap, label, MacAddress(), vn_list, sg, tag,
                                path_preference, false, EcmpLoadBalance(),
                                false);
      InetUnicastAgentRouteTable::AddRemoteVmRouteReq(peer, vm_vrf,
                                          vm_addr, plen, data);
      return true;
  }
  
  bool Inet4TunnelRouteAdd(const BgpPeer *peer, const string &vm_vrf, char *vm_addr,
                           uint8_t plen, char *server_ip, TunnelType::TypeBmap bmap,
                           uint32_t label, const string &dest_vn_name,
                           const SecurityGroupList &sg,
                           const TagList &tag,
                           const PathPreference &path_preference) {
      boost::system::error_code ec;
      return Inet4TunnelRouteAdd(peer, vm_vrf, Ip4Address::from_string(vm_addr, ec), plen,
                                 Ip4Address::from_string(server_ip, ec), bmap, label,
                                 dest_vn_name, sg, tag, path_preference);
  }
  
  bool Inet4MplsRouteAdd(const BgpPeer *peer, const string &server_vrf, const Ip4Address &server_addr,
                           uint8_t plen, const Ip4Address &gw_ip, TunnelType::TypeBmap bmap,
                           uint32_t label, const string &dest_vn_name,
                           const SecurityGroupList &sg,
                           const TagList &tag,
                           const PathPreference &path_preference) {
      VnListType vn_list;
      vn_list.insert(dest_vn_name);
      ControllerMplsRoute *data =
          ControllerMplsRoute::MakeControllerMplsRoute(peer,
                                Agent::GetInstance()->fabric_vrf_name(),
                                Agent::GetInstance()->router_id(),
                                server_vrf, gw_ip,
                                bmap, label, MacAddress(), vn_list, sg, tag,
                                path_preference, false, EcmpLoadBalance(),
                                false);
      InetUnicastAgentRouteTable::AddMplsRouteReq(peer, server_vrf, server_addr, plen,data);
      return true;
  }
  
  bool Inet4MplsRouteAdd(const BgpPeer *peer, const string &server_vrf, char *server_addr,
                           uint8_t plen, char *gw_ip, TunnelType::TypeBmap bmap,
                           uint32_t label, const string &dest_vn_name,
                           const SecurityGroupList &sg,
                           const TagList &tag,
                           const PathPreference &path_preference) {
      boost::system::error_code ec;
      return Inet4MplsRouteAdd(peer, server_vrf, Ip4Address::from_string(server_addr, ec), plen,
                              Ip4Address::from_string(gw_ip, ec), bmap,
                                 label,
                                 dest_vn_name, sg, tag, path_preference);
  }
  bool TunnelRouteAdd(const char *server, const char *vmip, const char *vm_vrf,
                      int label, const char *vn, TunnelType::TypeBmap bmap) {
      boost::system::error_code ec;
      VnListType vn_list;
      if (vn) vn_list.insert(vn);
      ControllerVmRoute *data =
          ControllerVmRoute::MakeControllerVmRoute(bgp_peer_,
                                Agent::GetInstance()->fabric_vrf_name(),
                                Agent::GetInstance()->router_id(),
                                vm_vrf, Ip4Address::from_string(server, ec),
                                TunnelType::AllType(), label, MacAddress(), vn_list,
                                SecurityGroupList(), TagList(),
                                PathPreference(), false,
                                EcmpLoadBalance(), false);
      InetUnicastAgentRouteTable::AddRemoteVmRouteReq(bgp_peer_, vm_vrf,
                                          Ip4Address::from_string(vmip, ec),
                                          32, data);
      return true;
  }
  
  bool TunnelRouteAdd(const char *server, const char *vmip, const char *vm_vrf,
                      int label, const char *vn) {
      return TunnelRouteAdd(server, vmip, vm_vrf, label, vn,
                            TunnelType::AllType());
  }
  
  bool AddArp(const char *ip, const char *mac_str, const char *ifname) {
      MacAddress mac(mac_str);
      Interface *intf;
      PhysicalInterfaceKey key(ifname);
      intf = static_cast<Interface *>(Agent::GetInstance()->interface_table()->FindActiveEntry(&key));
      boost::system::error_code ec;
      VnListType vn_list;
      InetUnicastAgentRouteTable::ArpRoute(DBRequest::DB_ENTRY_ADD_CHANGE,
                                Agent::GetInstance()->fabric_vrf_name(),
                                Ip4Address::from_string(ip, ec), mac,
                                Agent::GetInstance()->fabric_vrf_name(),
                                *intf, true, 32, false, vn_list, SecurityGroupList(),
                                TagList());
  
      return true;
  }
  
  bool AddArpReq(const char *ip, const char *ifname) {
      Interface *intf;
      PhysicalInterfaceKey key(ifname);
      intf = static_cast<Interface *>(Agent::GetInstance()->interface_table()->FindActiveEntry(&key));
      boost::system::error_code ec;
      VnListType vn_list;
      InetUnicastAgentRouteTable::AddArpReq(Agent::GetInstance()->fabric_vrf_name(),
                                Ip4Address::from_string(ip, ec),
                                Agent::GetInstance()->fabric_vrf_name(),
                                intf, false, vn_list, SecurityGroupList(),
                                TagList());
  
      return true;
  }
  
  bool DelArp(const string &ip, const char *mac_str, const string &ifname) {
      MacAddress mac(mac_str);
      Interface *intf;
      PhysicalInterfaceKey key(ifname);
      intf = static_cast<Interface *>(Agent::GetInstance()->interface_table()->FindActiveEntry(&key));
      boost::system::error_code ec;
      VnListType vn_list;
      InetUnicastAgentRouteTable::ArpRoute(DBRequest::DB_ENTRY_DELETE,
                                Agent::GetInstance()->fabric_vrf_name(),
                                Ip4Address::from_string(ip, ec),
                                mac, Agent::GetInstance()->fabric_vrf_name(), *intf,
                                false, 32, false, vn_list, SecurityGroupList(),
                                TagList());
      return true;
  }
  
  void AddVm(const char *name, int id) {
      AddNode("virtual-machine", name, id);
  }
  
  void DelVm(const char *name) {
      DelNode("virtual-machine", name);
  }
  
  void AddVrf(const char *name, int id, bool default_ri) {
      std::stringstream str;
      str << "    <routing-instance-is-default>" << default_ri << "</routing-instance-is-default>" << endl;
      char buff[10240];
      int len = 0;
      AddXmlHdr(buff, len);
      AddNodeString(buff, len, "routing-instance", name, id, str.str().c_str());
      AddXmlTail(buff, len);
      ApplyXmlString(buff);
      return;
  }
  
  void AddVrfWithSNat(const char *name, int id, bool default_ri, bool snat) {
      std::stringstream str;
      str << "    <routing-instance-is-default>" << default_ri << "</routing-instance-is-default>" << endl;
      str << "    <routing-instance-fabric-snat>" << snat << "</routing-instance-fabric-snat>" << endl;
      char buff[10240];
      int len = 0;
      AddXmlHdr(buff, len);
      AddNodeString(buff, len, "routing-instance", name, id, str.str().c_str());
      AddXmlTail(buff, len);
      ApplyXmlString(buff);
      return;
  }
  
  void DelVrf(const char *name) {
      DelNode("routing-instance", name);
  }
  
  void AddBridgeDomain(const char *name, uint32_t id, uint32_t isid,
                       bool mac_learning) {
      std::stringstream str;
      str << "<isid>" << isid << "</isid>" << endl;
      str<< "<mac-learning-enabled>" << mac_learning << "</mac-learning-enabled>";
  
      char buff[10240];
      int len = 0;
      AddXmlHdr(buff, len);
      AddNodeString(buff, len, "bridge-domain", name, id, str.str().c_str());
      AddXmlTail(buff, len);
      ApplyXmlString(buff);
  }
  
  void AddTag(const char *name, uint32_t uuid, uint32_t id,
              const std::string type) {
      std::stringstream str;
      str << "<tag-type-name>" << type << "</tag-type-name>";
      str << "<tag-id> 0x" << std::setfill('0') << std::setw(8) << std::hex << id << "</tag-id>";
      str << "<display-name>" << name << "</display-name>";
  
      char buff[10240];
      int len = 0;
      AddXmlHdr(buff, len);
      AddNodeString(buff, len, "tag", name, uuid, str.str().c_str());
      AddXmlTail(buff, len);
      ApplyXmlString(buff);
  }
  
  void AddAddressGroup(const char *name, uint32_t uuid,
                       TestIp4Prefix *prefix, uint32_t count) {
      std::stringstream str;
  
      str << "<address-group-prefix>";
      for(uint32_t i = 0; i < count; i++) {
          str << "<subnet>";
          str << "<ip-prefix>" << prefix[i].addr_.to_string() << "</ip-prefix>";
          str << "<ip-prefix-len>" << prefix[i].plen_ << "</ip-prefix-len>";
          str << "</subnet>";
      }
      str << "</address-group-prefix>";
  
      char buff[10240];
      int len = 0;
      AddXmlHdr(buff, len);
      AddNodeString(buff, len, "address-group", name, uuid, str.str().c_str());
      AddXmlTail(buff, len);
      ApplyXmlString(buff);
  }
  
  void ModifyForwardingModeVn(const string &name, int id, const string &fw_mode) {
      std::stringstream str;
      str << "<virtual-network-properties>" << endl;
      str << "    <vxlan-network-identifier>" << (id+100) << "</vxlan-network-identifier>" << endl;
      str << "    <forwarding-mode>" << fw_mode << "</forwarding-mode>" << endl;
      str << "</virtual-network-properties>" << endl;
      str << "<virtual-network-network-id>" << id << "</virtual-network-network-id>" << endl;
      str << "<mac-ip-learning-enable>"
          << "true"
          << "</mac-ip-learning-enable>";
  
      AddNode("virtual-network", name.c_str(), id, str.str().c_str());
  }
  
  void ModifyMirrorDestinationVn(const string &name, int id, const string &mirror_dest) {
      std::stringstream str;
      str << "<virtual-network-properties>" << endl;
      str << "    <mirror-destination>" << mirror_dest << "</mirror-destination>" << endl;
      str << "</virtual-network-properties>" << endl;
      str << "<virtual-network-network-id>" << id << "</virtual-network-network-id>" << endl;
  
      AddNode("virtual-network", name.c_str(), id, str.str().c_str());
  }
  
  void AddL3Vn(const char *name, int id) {
      std::stringstream str;
      str << "<virtual-network-properties>" << endl;
      str << "    <forwarding-mode>l3</forwarding-mode>" << endl;
      str << "</virtual-network-properties>" << endl;
      str << "<virtual-network-network-id>" << id << "</virtual-network-network-id>" << endl;
  
      AddNode("virtual-network", name, id, str.str().c_str());
  }
  
  void AddL2L3Vn(const char *name, int id, bool admin_state) {
      std::stringstream str;
      str << "<virtual-network-properties>" << endl;
      str << "    <vxlan-network-identifier>" << (id+100) << "</vxlan-network-identifier>" << endl;
      str << "    <forwarding-mode>l2_l3</forwarding-mode>" << endl;
      str << "</virtual-network-properties>" << endl;
      str << "<virtual-network-network-id>" << id << "</virtual-network-network-id>" << endl;
  
      AddNode("virtual-network", name, id, str.str().c_str(), admin_state);
  }
  
  void AddL2Vn(const char *name, int id) {
      std::stringstream str;
      str << "<virtual-network-properties>" << endl;
      str << "    <vxlan-network-identifier>" << (id+100) << "</vxlan-network-identifier>" << endl;
      str << "    <forwarding-mode>l2</forwarding-mode>" << endl;
      str << "</virtual-network-properties>" << endl;
      str << "<virtual-network-network-id>" << id << "</virtual-network-network-id>" << endl;
  
      AddNode("virtual-network", name, id, str.str().c_str());
  }
  
  // default admin_state is true
  void AddVn(const char *name, int id, bool admin_state) {
      std::stringstream str;
      str << "<virtual-network-properties>" << endl;
      str << "    <vxlan-network-identifier>" << (id+100) << "</vxlan-network-identifier>" << endl;
      str << "    <rpf>enable</rpf>" << endl;
      str << "</virtual-network-properties>" << endl;
      str << "<virtual-network-network-id>" << id << "</virtual-network-network-id>" << endl;
  
      AddNode("virtual-network", name, id, str.str().c_str(), admin_state);
  }
  
  void AddVn(const char *name, int id, int vxlan_id, bool admin_state) {
      std::stringstream str;
      str << "<virtual-network-properties>" << endl;
      str << "    <vxlan-network-identifier>" << vxlan_id << "</vxlan-network-identifier>" << endl;
      str << "    <forwarding-mode>l2_l3</forwarding-mode>" << endl;
      str << "    <rpf>enable</rpf>" << endl;
      str << "</virtual-network-properties>" << endl;
      str << "<virtual-network-network-id>" << vxlan_id << "</virtual-network-network-id>" << endl;
  
      AddNode("virtual-network", name, id, str.str().c_str(), admin_state);
  }
  
  void AddMirrorVn(const char *name, int id, int vxlan_id, bool admin_state) {
      std::stringstream str;
      str << "<virtual-network-properties>" << endl;
      str << "    <vxlan-network-identifier>" << vxlan_id << "</vxlan-network-identifier>" << endl;
      str << "    <forwarding-mode>l2_l3</forwarding-mode>" << endl;
      str << "    <rpf>enable</rpf>" << endl;
      str << "    <mirror-destination>true</mirror-destination>" << endl;
      str << "</virtual-network-properties>" << endl;
      str << "<virtual-network-network-id>" << vxlan_id << "</virtual-network-network-id>" << endl;
  
      AddNode("virtual-network", name, id, str.str().c_str(), admin_state);
  }
  
  
  void DelVn(const char *name) {
      DelNode("virtual-network", name);
  }
  
  void AddSriovPort(const char *name, int id) {
      std::stringstream str;
      str << "<virtual-machine-interface-mac-addresses>" << endl;
      str << "    <mac-address>00:00:00:00:00:" << id << "</mac-address>"
          << endl;
      str << "</virtual-machine-interface-mac-addresses>" << endl;
      str << "<display-name> " << name << "</display-name>" << endl;
  
      //vnic type as direct makes the port sriov
      str << "<virtual-machine-interface-bindings>";
      str << "<key-value-pair>";
      str << "<key>vnic_type</key>";
      str << "<value>direct</value>";
      str << "</key-value-pair>";
      str << "<key-value-pair>";
      str << "<key>vif_type</key>";
      str << "<value>hw_veb</value>";
      str << "</key-value-pair>";
      str << "</virtual-machine-interface-bindings>";
  
      char buff[4096];
      strcpy(buff, str.str().c_str());
      AddNode("virtual-machine-interface", name, id, buff);
  
  }
  
  void AddPort(const char *name, int id, const char *attr) {
      std::stringstream str;
      str << "<virtual-machine-interface-mac-addresses>" << endl;
      str << "    <mac-address>00:00:00:00:00:" << id << "</mac-address>"
          << endl;
      str << "</virtual-machine-interface-mac-addresses>" << endl;
      str << "<display-name> " << name << "</display-name>" << endl;
  
      char buff[4096];
      strcpy(buff, str.str().c_str());
      AddNode("virtual-machine-interface", name, id, buff);
  }
  
  void AddLrPort(const char *name, int id) {
      std::stringstream str;
      str << "<virtual-machine-interface-mac-addresses>" << endl;
      str << "    <mac-address>00:00:00:00:00:" << id << "</mac-address>"
          << endl;
      str << "</virtual-machine-interface-mac-addresses>" << endl;
      str << "<display-name> " << name << "</display-name>" << endl;
      str << "<virtual-machine-interface-device-owner>"
          "network:router_interface</virtual-machine-interface-device-owner>" <<
          endl;
  
      char buff[4096];
      strcpy(buff, str.str().c_str());
      AddNode("virtual-machine-interface", name, id, buff);
  }
  
  void AddPortWithMac(const char *name, int id, const char *mac,
                      const char *attr) {
      std::stringstream str;
      str << "<virtual-machine-interface-mac-addresses>" << endl;
      str << "    <mac-address>" << mac << "</mac-address>"
          << endl;
      str << "</virtual-machine-interface-mac-addresses>" << endl;
  
      char buff[4096];
      strcpy(buff, str.str().c_str());
      if (attr != NULL)
          strcat(buff, attr);
      AddNode("virtual-machine-interface", name, id, buff);
  }
  
  void AddPortByStatus(const char *name, int id, bool admin_status) {
      AddNodeByStatus("virtual-machine-interface", name, id, admin_status);
  }
  
  void DelPort(const char *name) {
      DelNode("virtual-machine-interface", name);
  }
  
  void AddInterfaceRouteTable(const char *name, int id, TestIp4Prefix *rt,
                              int count) {
      std::ostringstream o_str;
  
      for (int i = 0; i < count; i++) {
          o_str << "<route>\n"
                << "<prefix>" << rt->addr_.to_string()
                << "/" << rt->plen_ << "</prefix>\n"
                << "<next-hop>\" \"</next-hop>\n"
                << "<next-hop-type>\" \"</next-hop-type>\n"
                << "</route>\n";
          rt++;
      }
  
      char buff[10240];
      sprintf(buff, "<interface-route-table-routes>\n"
                    "%s"
                    "</interface-route-table-routes>\n", o_str.str().c_str());
      AddNode("interface-route-table", name, id, buff);
  }
  
  void AddInterfaceRouteTable(const char *name, int id, TestIp4Prefix *rt,
                              int count, const char *nexthop) {
      std::ostringstream o_str;
  
      for (int i = 0; i < count; i++) {
          o_str << "<route>\n"
                << "<prefix>" << rt->addr_.to_string()
                << "/" << rt->plen_ << "</prefix>\n"
                << "<next-hop>" << nexthop << "</next-hop>\n"
                << "<next-hop-type>\" \"</next-hop-type>\n"
                << "</route>\n";
          rt++;
      }
  
      char buff[10240];
      sprintf(buff, "<interface-route-table-routes>\n"
                    "%s"
                    "</interface-route-table-routes>\n", o_str.str().c_str());
      AddNode("interface-route-table", name, id, buff);
  }
  
  void AddInterfaceRouteTable(const char *name, int id, TestIp4Prefix *rt,
                              int count, const char *nexthop,
                              const std::vector<std::string> &communities) {
      std::ostringstream o_str;
  
      for (int i = 0; i < count; i++) {
          o_str << "<route>\n"
                << "<prefix>" << rt->addr_.to_string()
                << "/" << rt->plen_ << "</prefix>\n";
          if (nexthop) {
              o_str << "<next-hop>" << nexthop << "</next-hop>\n";
          }
          o_str << "<next-hop-type>\" \"</next-hop-type>\n";
          o_str << "<community-attributes>\n";
          BOOST_FOREACH(string community, communities) {
              o_str << "<community-attribute>"
                    << community
                    << "</community-attribute>\n";
          }
          o_str << "</community-attributes>\n";
          o_str << "</route>\n";
          rt++;
      }
  
      char buff[10240];
      sprintf(buff, "<interface-route-table-routes>\n"
                    "%s"
                    "</interface-route-table-routes>\n", o_str.str().c_str());
      AddNode("interface-route-table", name, id, buff);
  }
  
  void AddInterfaceRouteTableV6(const char *name, int id, TestIp6Prefix *rt,
                                int count) {
      std::ostringstream o_str;
  
      for (int i = 0; i < count; i++) {
          o_str << "<route>\n"
                << "<prefix>" << rt->addr_.to_string()
                << "/" << rt->plen_ << "</prefix>\n"
                << "<next-hop>\" \"</next-hop>\n"
                << "<next-hop-type>\" \"</next-hop-type>\n"
                << "</route>\n";
          rt++;
      }
  
      char buff[10240];
      sprintf(buff, "<interface-route-table-routes>\n"
                    "%s"
                    "</interface-route-table-routes>\n", o_str.str().c_str());
      AddNode("interface-route-table", name, id, buff);
  }
  
  void StartAcl(string *str, const char *name, int id) {
      char buff[1024];
  
      sprintf(buff,
              "<?xml version=\"1.0\"?>\n"
              "<config>\n"
              "   <update>\n"
              "       <node type=\"access-control-list\">\n"
              "           <name>%s</name>\n"
              "           <id-perms>\n"
              "               <permissions>\n"
              "                   <owner></owner>\n"
              "                   <owner_access>0</owner_access>\n"
              "                   <group></group>\n"
              "                   <group_access>0</group_access>\n"
              "                   <other_access>0</other_access>\n"
              "               </permissions>\n"
              "               <uuid>\n"
              "                   <uuid-mslong>0</uuid-mslong>\n"
              "                   <uuid-lslong>%d</uuid-lslong>\n"
              "               </uuid>\n"
              "           </id-perms>\n"
              "           <access-control-list-entries>\n",
              name, id);
      *str = string(buff);
      return;
  }
  
  void EndAcl(string *str) {
      char buff[512];
      sprintf(buff,
              "           </access-control-list-entries>\n"
              "       </node>\n"
              "   </update>\n"
              "</config>\n");
      string s(buff);
      *str += s;
      return;
  }
  
  void AddAceEntry(string *str, const char *src_vn, const char *dst_vn,
                   const char *proto, uint16_t sport_start, uint16_t sport_end,
                   uint16_t dport_start, uint16_t dport_end,
                   const char *action, const std::string &vrf_assign,
                   const std::string &mirror_ip, const std::string &qos_action) {
      char buff[2048];
  
      std::ostringstream mirror;
  
      if (mirror_ip != "") {
          mirror << "<mirror-to>";
          mirror << "<analyzer-name>mirror-1</analyzer-name>";
          mirror << "<analyzer-ip-address>" << mirror_ip << "</analyzer-ip-address>";
          mirror << "<routing-instance>" << "" << "</routing-instance>";
          mirror << "<udp-port>" << "8159" << "</udp-port>";
          mirror << "</mirror-to>";
      } else {
          mirror << "";
      }
  
      sprintf(buff,
              "                <acl-rule>\n"
              "                    <match-condition>\n"
              "                        <protocol>%s</protocol>\n"
              "                        <src-address>\n"
              "                            <virtual-network>%s</virtual-network>\n"
              "                        </src-address>\n"
              "                        <src-port>\n"
              "                            <start-port>%d</start-port>\n"
              "                            <end-port>%d</end-port>\n"
              "                        </src-port>\n"
              "                        <dst-address>\n"
              "                            <virtual-network>%s</virtual-network>\n"
              "                        </dst-address>\n"
              "                        <dst-port>\n"
              "                            <start-port>%d</start-port>\n"
              "                            <end-port>%d</end-port>\n"
              "                        </dst-port>\n"
              "                    </match-condition>\n"
              "                    <action-list>\n"
              "                        <simple-action>%s</simple-action>\n"
              "                        %s\n"
              "                        <assign-routing-instance>%s</assign-routing-instance>\n"
              "                        <qos-action>%s</qos-action>\n"
              "                    </action-list>\n"
              "                </acl-rule>\n",
          proto, src_vn, sport_start, sport_end, dst_vn, dport_start, dport_end,
          action, mirror.str().c_str(), vrf_assign.c_str(), qos_action.c_str());
      string s(buff);
      *str += s;
      return;
  }
  
  static string AddAclXmlString(const char *node_name, const char *name, int id,
                                const char *src_vn, const char *dest_vn,
                                const char *action, const std::string &vrf_assign,
                                const std::string &mirror_ip,
                                const std::string &qos_action) {
      string str;
      StartAcl(&str, name, id);
      AddAceEntry(&str, src_vn, dest_vn, "any", 10, 20, 10, 20, action,
                  vrf_assign, mirror_ip, qos_action);
      AddAceEntry(&str, dest_vn, src_vn, "any", 10, 20, 10, 20, action,
                  vrf_assign, mirror_ip, qos_action);
      EndAcl(&str);
      return str;
  }
  
  void AddAcl(const char *name, int id) {
      AddNode("access-control-list", name, id);
  }
  
  void DelAcl(const char *name) {
      DelNode("access-control-list", name);
  }
  
  void AddAcl(const char *name, int id, const char *src_vn, const char *dest_vn,
              const char *action) {
      std::string s = AddAclXmlString("access-control-list", name, id,
                                      src_vn, dest_vn, action, "", "", "");
      ApplyXmlString(s.c_str());
  }
  
  void AddVrfAssignNetworkAcl(const char *name, int id, const char *src_vn,
                              const char *dest_vn, const char *action,
                              std::string vrf_name) {
      std::string s = AddAclXmlString("access-control-list", name, id,
                                      src_vn, dest_vn, action, vrf_name, "", "");
      ApplyXmlString(s.c_str());
  }
  
  void AddQosAcl(const char *name, int id, const char *src_vn,
                 const char *dest_vn, const char *action,
                 std::string qos_config) {
      std::string s = AddAclXmlString("access-control-list", name, id,
                                       src_vn, dest_vn, action, "", "", qos_config);
      ApplyXmlString(s.c_str());
  }
  
  void AddMirrorAcl(const char *name, int id, const char *src_vn,
                    const char *dest_vn, const char *action,
                    std::string mirror_ip) {
      std::string s = AddAclXmlString("access-control-list", name, id,
              src_vn, dest_vn, action, "", mirror_ip, "");
      ApplyXmlString(s.c_str());
  }
  
  void DelOperDBAcl(int id) {
      DBRequest req;
      req.oper = DBRequest::DB_ENTRY_DELETE;
      AclSpec acl_spec;
      AclKey *key = new AclKey(MakeUuid(id));
      req.key.reset(key);
      req.data.reset(NULL);
      Agent::GetInstance()->acl_table()->Enqueue(&req);
  }
  
  void AddTag(const char *name, int id) {
      char buff[128];
      sprintf(buff, "<tag-id>%d</tag-id>", id);
      AddNode("tag", name, id, buff);
  }
  
  void AddSg(const char *name, int id, int sg_id) {
      char buff[128];
      sprintf(buff, "<security-group-id>%d</security-group-id>", sg_id);
      AddNode("security-group", name, id, buff);
  }
  
  void AddFloatingIp(const char *name, int id, const char *addr,
                     const char *fixed_ip, const char *direction,
                     bool port_map_enable,
                     uint16_t port_map1, uint16_t port_map2, uint16_t port_map3,
                     uint16_t port_map4) {
      uint16_t port_map[4] = { port_map1, port_map2, port_map3, port_map4 };
      ostringstream str;
      str << "<floating-ip-address>" << addr << "</floating-ip-address>" << endl;
      str << "<floating-ip-fixed-ip-address>" << fixed_ip <<
             "</floating-ip-fixed-ip-address>" << endl;
      if (direction != NULL) {
          str << "<floating-ip-traffic-direction>" << direction
              << "</floating-ip-traffic-direction>" << endl;
      }
  
      str << "<floating-ip-port-mappings-enable>";
      if (port_map_enable)
          str << "true";
      else
          str << "false";
      str << "</floating-ip-port-mappings-enable>" << endl;
      str << "<floating-ip-port-mappings>" << endl;
      for (int i = 0; i < 4; i++) {
          if (port_map[i]) {
              str << "    <port-mappings>" << endl;
              str << "        <protocol>tcp</protocol>" << endl;
              str << "        <src-port>" << port_map[i] << "</src-port>" << endl;
              str << "        <dst-port>" << port_map[i] + 1000 << "</dst-port>"
                  << endl;
              str << "    </port-mappings>" << endl;
              str << "    <port-mappings>" << endl;
              str << "        <protocol>udp</protocol>" << endl;
              str << "        <src-port>" << port_map[i] << "</src-port>" << endl;
              str << "        <dst-port>" << port_map[i] + 1000 << "</dst-port>"
                  << endl;
              str << "    </port-mappings>" << endl;
          }
      }
      str << "</floating-ip-port-mappings>";
  
      AddNode("floating-ip", name, id, str.str().c_str());
  }
  
  void DelFloatingIp(const char *name) {
      DelNode("floating-ip", name);
  }
  
  void AddFloatingIpPool(const char *name, int id) {
      AddNode("floating-ip-pool", name, id);
  }
  
  void DelFloatingIpPool(const char *name) {
      DelNode("floating-ip-pool", name);
  }
  
  void AddAliasIp(const char *name, int id, const char *addr) {
      char buff[128];
  
      sprintf(buff, "<alias-ip-address>%s</alias-ip-address>", addr);
      AddNode("alias-ip", name, id, buff);
  }
  
  void DelAliasIp(const char *name) {
      DelNode("alias-ip", name);
  }
  
  void AddAliasIpPool(const char *name, int id) {
      AddNode("alias-ip-pool", name, id);
  }
  
  void DelAliasIpPool(const char *name) {
      DelNode("alias-ip-pool", name);
  }
  
  void AddInstanceIp(const char *name, int id, const char *addr) {
      char buf[256];
  
      sprintf(buf, "<instance-ip-address>%s</instance-ip-address>"
                   "<instance-ip-mode>active-backup</instance-ip-mode>", addr);
      AddNode("instance-ip", name, id, buf);
  }
  
  void AddActiveActiveInstanceIp(const char *name, int id, const char *addr) {
      char buf[128];
      sprintf(buf, "<instance-ip-address>%s</instance-ip-address>"
                   "<instance-ip-mode>active-active</instance-ip-mode>", addr);
      AddNode("instance-ip", name, id, buf);
  }
  
  void AddHealthCheckServiceInstanceIp(const char *name, int id,
                                       const char *addr) {
      char buf[256];
  
      sprintf(buf, "<instance-ip-address>%s</instance-ip-address>"
                   "<service-health-check-ip>true</service-health-check-ip>"
                   "<instance-ip-mode>active-backup</instance-ip-mode>", addr);
      AddNode("instance-ip", name, id, buf);
  }
  
  void AddServiceInstanceIp(const char *name, int id, const char *addr, bool ecmp,
                            const char *tracking_ip) {
      char buf[512];
      char mode[256];
  
      if (ecmp) {
           sprintf(mode, "active-active");
      } else {
          sprintf(mode, "active-backup");
      }
  
      char tracking_ip_buf[256] = "0.0.0.0";
      if (tracking_ip) {
          sprintf(tracking_ip_buf, "%s", tracking_ip);
      }
  
      sprintf(buf, "<instance-ip-address>%s</instance-ip-address>"
                   "<service-instance-ip>true</service-instance-ip>"
                   "<instance-ip-mode>%s</instance-ip-mode>"
                   "<secondary-ip-tracking-ip>"
                   "    <ip-prefix>%s</ip-prefix>"
                   "    <ip-prefix-len>32</ip-prefix-len>"
                   "</secondary-ip-tracking-ip>", addr, mode,
                   tracking_ip_buf);
      AddNode("instance-ip", name, id, buf);
  }
  
  void DelInstanceIp(const char *name) {
      DelNode("instance-ip", name);
  }
  
  void AddSubnetType(const char *name, int id, const char *addr, uint8_t plen) {
  
      char buf[1024];
      sprintf(buf, "<subnet-ip-prefix>\n"
                   "<ip-prefix>%s</ip-prefix>\n"
                   "<ip-prefix-len>%d</ip-prefix-len>\n"
                   "</subnet-ip-prefix>", addr, plen);
      AddNode("subnet", name, id, buf);
  }
  
  void AddPhysicalDeviceWithIp(int id, std::string name, std::string vendor,
                               std::string ip, std::string mgmt_ip,
                               std::string protocol, Agent *agent) {
  
      DBRequest device_req(DBRequest::DB_ENTRY_ADD_CHANGE);
      device_req.key.reset(new PhysicalDeviceKey(MakeUuid(id)));
      device_req.data.reset(new PhysicalDeviceData(agent, name, name, vendor,
                                        Ip4Address::from_string(ip),
                                        Ip4Address::from_string(mgmt_ip),
                                        protocol, NULL));
      agent->physical_device_table()->Enqueue(&device_req);
      WAIT_FOR(100, 10000,
               (agent->physical_device_table()->Find(MakeUuid(id)) != NULL));
  }
  
  void DelPhysicalDeviceWithIp(Agent *agent, int id) {
      DBRequest device_req(DBRequest::DB_ENTRY_DELETE);
      device_req.key.reset(new PhysicalDeviceKey(MakeUuid(id)));
      device_req.data.reset();
      agent->physical_device_table()->Enqueue(&device_req);
      WAIT_FOR(100, 10000,
               (agent->physical_device_table()->Find(MakeUuid(id)) == NULL));
  }
  
  void AddPhysicalDevice(const char *name, int id) {
      char buf[1024];
      sprintf(buf, "<physical-router-vendor-name>Juniper</physical-router-vendor-name>"
                   "<display-name>%s</display-name>", name);
      AddNode("physical-router", name, id, buf);
  }
  
  void DeletePhysicalDevice(const char *name) {
      DelNode("physical-router", name);
  }
  
  void AddPhysicalInterface(const char *name, int id, const char* display_name) {
      char buf[128];
      sprintf(buf, "<user-visible>Juniper</user-visible>"
                   "<display-name>%s</display-name>", display_name);
      AddNode("physical-interface", name, id, buf);
  }
  
  void DeletePhysicalInterface(const char *name) {
      DelNode("physical-interface", name);
  }
  
  void AddLogicalInterface(const char *name, int id, const char* display_name, int vlan) {
      char buf[1024];
      sprintf(buf, "<logical-interface-vlan-tag>%d</logical-interface-vlan-tag>"
                   "<logical-interface-type>l2</logical-interface-type>"
                   "<user-visible>Juniper</user-visible>"
                   "<display-name>%s</display-name>", vlan, display_name);
      AddNode("logical-interface", name, id, buf);
  }
  
  void DeleteLogicalInterface(const char *name) {
      DelNode("logical-interface", name);
  }
  
  void AddVirtualPortGroup(const char *name, int id, const char *display_name) {
      char buf[1024];
      sprintf(buf, "<display-name>%s</display-name>", display_name);
      AddNode("virtual-port-group", name, id, buf);
  }
  
  void DeleteVirtualPortGroup(const char *name) {
      DelNode("virtual-port-group", name);
  }
  
  void AddVmPortVrf(const char *name, const string &ip, uint16_t tag,
                    const string &v6_ip, bool swap) {
      char buff[1024];
      int len = 0;
  
      len += sprintf(buff + len,   "<direction>both</direction>");
      len += sprintf(buff + len,   "<vlan-tag>%d</vlan-tag>", tag);
  
      if (swap == false) {
          len += sprintf(buff + len,   "<src-mac>02:00:00:00:00:02</src-mac>");
          len += sprintf(buff + len,   "<dst-mac>02:00:00:00:00:01</dst-mac>");
      } else {
          len += sprintf(buff + len,   "<src-mac>02:00:00:00:00:01</src-mac>");
          len += sprintf(buff + len,   "<dst-mac>02:00:00:00:00:02</dst-mac>");
      }
  
      len += sprintf(buff + len,
                     "<service-chain-address>%s</service-chain-address>",
                     ip.c_str());
      if (!v6_ip.empty()) {
          len += sprintf(buff + len,
                     "<ipv6-service-chain-address>%s</ipv6-service-chain-address>",
                      v6_ip.c_str());
      }
      AddLinkNode("virtual-machine-interface-routing-instance", name, buff);
  }
  
  void DelVmPortVrf(const char *name) {
      DelNode("virtual-machine-interface-routing-instance", name);
  }
  
  void AddVmportBridgeDomain(const char *name, uint32_t vlan_tag) {
      std::stringstream str;
      str << "<vlan-tag>" << vlan_tag << "</vlan-tag>";
  
      AddLinkNode("virtual-machine-interface-bridge-domain", name,
                  str.str().c_str());
  }
  
  void AddFirewallPolicyRuleLink(const std::string &node_name,
                                 const std::string &fp,
                                 const std::string &fr,
                                 const std::string &id) {
      std::stringstream str;
      str << "<sequence>" << id << "</sequence>";
  
      AddLinkNode("firewall-policy-firewall-rule", node_name.c_str(),
                  str.str().c_str());
      AddLink("firewall-policy", fp.c_str(),
              "firewall-policy-firewall-rule", node_name.c_str());
      AddLink("firewall-policy-firewall-rule", node_name.c_str(),
              "firewall-rule", fr.c_str());
  }
  
  void DelFirewallPolicyRuleLink(const std::string &node_name,
                                 const std::string &fp, const std::string &fr) {
      DelNode("firewall-policy-firewall-rule", node_name.c_str());
      DelLink("firewall-policy", fp.c_str(),
              "firewall-policy-firewall-rule", node_name.c_str());
      DelLink("firewall-policy-firewall-rule", node_name.c_str(),
              "firewall-rule", fr.c_str());
  }
  
  void AddPolicySetFirewallPolicyLink(const std::string &node_name,
                                 const std::string &aps,
                                 const std::string &fp,
                                 const std::string &id) {
      std::stringstream str;
      str << "<sequence>" << id << "</sequence>";
  
      AddLinkNode("application-policy-set-firewall-policy", node_name.c_str(),
                  str.str().c_str());
      AddLink("application-policy-set", aps.c_str(),
              "application-policy-set-firewall-policy", node_name.c_str());
      AddLink("application-policy-set-firewall-policy", node_name.c_str(),
              "firewall-policy", fp.c_str());
  }
  
  void DelPolicySetFirewallPolicyLink(const std::string &node_name,
                                      const std::string &aps,
                                      const std::string &fp) {
      DelNode("application-policy-set-firewall-policy", node_name.c_str());
      DelLink("application-policy-set", aps.c_str(),
              "application-policy-set-firewall-policy", node_name.c_str());
      DelLink("application-policy-set-firewall-policy", node_name.c_str(),
              "firewall-policy", fp.c_str());
  }
  
  void AddIPAM(const char *name, IpamInfo *ipam, int ipam_size, const char *ipam_attr,
               const char *vdns_name, const std::vector<std::string> *vm_host_routes,
               const char *add_subnet_tags) {
      char buff[10240];
      char node_name[128];
      char ipam_name[128];
      int len = 0;
  
      sprintf(node_name, "default-network-ipam,%s", name);
      sprintf(ipam_name, "default-network-ipam");
      AddXmlHdr(buff, len);
      if (ipam_attr) {
          AddNodeString(buff, len, "network-ipam", ipam_name, 1, ipam_attr);
      } else {
          AddNodeString(buff, len, "network-ipam", ipam_name, 1);
      }
      AddNodeString(buff, len, "virtual-network-network-ipam", node_name,
                              ipam, ipam_size, vm_host_routes, add_subnet_tags);
      LinkString(buff, len, "virtual-network", name,
                    "virtual-network-network-ipam", node_name,
                    "virtual-network-network-ipam");
      LinkString(buff, len, "network-ipam", ipam_name,
                    "virtual-network-network-ipam", node_name,
                    "virtual-network-network-ipam");
      if (vdns_name) {
          LinkString(buff, len, "network-ipam", ipam_name,
                        "virtual-DNS", vdns_name, "virtual-DNS");
      }
      AddXmlTail(buff, len);
      ApplyXmlString(buff);
  }
  
  void DelIPAM(const char *name, const char *vdns_name) {
      char buff[2048];
      char node_name[128];
      char ipam_name[128];
      int len = 0;
  
      sprintf(node_name, "default-network-ipam,%s", name);
      sprintf(ipam_name, "default-network-ipam");
      DelXmlHdr(buff, len);
      LinkString(buff, len, "virtual-network", name,
                   "virtual-network-network-ipam", node_name);
      LinkString(buff, len, "network-ipam", ipam_name,
                   "virtual-network-network-ipam", node_name);
      if (vdns_name) {
          LinkString(buff, len, "network-ipam", ipam_name,
                        "virtual-DNS", vdns_name);
      }
      DelNodeString(buff, len, "virtual-network-network-ipam", node_name);
      DelNodeString(buff, len, "network-ipam", ipam_name);
      DelXmlTail(buff, len);
      ApplyXmlString(buff);
      return;
  }
  
  void AddVDNS(const char *vdns_name, const char *vdns_attr) {
      char buff[4096];
      int len = 0;
  
      AddXmlHdr(buff, len);
      AddNodeString(buff, len, "virtual-DNS", vdns_name, 1, vdns_attr);
      AddXmlTail(buff, len);
      ApplyXmlString(buff);
  }
  
  void DelVDNS(const char *vdns_name) {
      char buff[2048];
      int len = 0;
  
      DelXmlHdr(buff, len);
      DelNodeString(buff, len, "virtual-DNS", vdns_name);
      DelXmlTail(buff, len);
      ApplyXmlString(buff);
  }
  
  void AddEncryptRemoteTunnelConfig(const EncryptTunnelEndpoint *endpoints, int count,
                                    std::string encrypt_mode) {
      std::stringstream global_config;
      global_config << "<encryption-mode>";
      global_config << encrypt_mode;
      global_config << "</encryption-mode>";
      global_config << "<encryption-tunnel-endpoints>\n";
      for (int i = 0; i < count; ++i) {
          global_config << "<endpoint>\n";
          global_config << "<tunnel-remote-ip-address>";
          global_config << endpoints[i].ip;
          global_config << "</tunnel-remote-ip-address>";
          global_config << "</endpoint>";
      }
      global_config << "</encryption-tunnel-endpoints>";
  
      char buf[8192];
      int len = 0;
      memset(buf, 0, 8192);
      AddXmlHdr(buf, len);
      AddNodeString(buf, len, "global-vrouter-config",
                    "default-global-system-config:default-global-vrouter-config",
                    1024, global_config.str().c_str());
      AddXmlTail(buf, len);
      ApplyXmlString(buf);
  }
  
  void AddPortTranslationConfig() {
      std::stringstream config;
      config << "<port-translation-pools>";
      config << "<port-translation-pool>";
      config << "<protocol>tcp</protocol>";
      config << "<port-range>";
      config << "<start-port>400</start-port><end-port>500</end-port>";
      config << "</port-range>";
      config << "<port-count></port-count>";
      config << "</port-translation-pool>";
      config << "<port-translation-pool>";
      config << "<protocol>udp</protocol>";
      config << "<port-range>";
      config << "<start-port>600</start-port><end-port>700</end-port>";
      config << "</port-range>";
      config << "<port-count></port-count>";
      config << "</port-translation-pool>";
      config << "</port-translation-pools>";
  
      char buf[8192];
      int len = 0;
      memset(buf, 0, 8192);
      AddXmlHdr(buf, len);
      AddNodeString(buf, len, "global-vrouter-config",
                    "default-global-system-config:default-global-vrouter-config",
                    1024, config.str().c_str());
      AddXmlTail(buf, len);
      ApplyXmlString(buf);
  }
  void AddFlowAgingTimerConfig(int tcp_timeout, int udp_timeout, int icmp_timeout) {
      std::stringstream config;
      config << "<flow-aging-timeout-list>";
      config << "<flow-aging-timeout>";
      config << "<protocol>tcp</protocol>";
      config << "<port>0</port>";
      config << "<timeout-in-seconds>" << tcp_timeout << "</timeout-in-seconds>";
      config << "</flow-aging-timeout>";
      config << "<flow-aging-timeout>";
      config << "<protocol>udp</protocol>";
      config << "<port>0</port>";
      config << "<timeout-in-seconds>" << udp_timeout << "</timeout-in-seconds>";
      config << "</flow-aging-timeout>";
      config << "<flow-aging-timeout>";
      config << "<protocol>icmp</protocol>";
      config << "<port>0</port>";
      config << "<timeout-in-seconds>" << icmp_timeout << "</timeout-in-seconds>";
      config << "</flow-aging-timeout>";
      config << "</flow-aging-timeout-list>";
  
      char buf[8192];
      int len = 0;
      memset(buf, 0, 8192);
      AddXmlHdr(buf, len);
      AddNodeString(buf, len, "global-vrouter-config",
                    "default-global-system-config:default-global-vrouter-config",
                    1024, config.str().c_str());
      AddXmlTail(buf, len);
      ApplyXmlString(buf);
  }
  
  void AddMulticastPolicy(const char *name, uint32_t id, MulticastPolicy *msg,
                                      int msg_size) {
  
      std::stringstream policy;
      policy << "<multicast-source-groups>";
      for (int i = 0; i < msg_size; ++i) {
          std::string action = (msg[i].action == true) ? "pass" : "deny";
  
          policy << "<multicast-source-group>";
          policy << "<source-address>";
          policy << msg[i].src;
          policy << "</source-address>";
          policy << "<group-address>";
          policy << msg[i].grp;
          policy << "</group-address>";
          policy << "<action>";
          policy << action;
          policy << "</action>";
          policy << "</multicast-source-group>";
      }
      policy << "</multicast-source-groups>";
  
      AddNode("multicast-policy", name, id, policy.str().c_str());
      return;
  }
  
  void DelMulticastPolicy(const char *name) {
      DelNode("multicast-policy", name);
      return;
  }
  
  
  void AddLinkLocalConfig(const TestLinkLocalService *services, int count) {
      std::stringstream global_config;
      global_config << "<linklocal-services>\n";
      for (int i = 0; i < count; ++i) {
          global_config << "<linklocal-service-entry>\n";
          global_config << "<linklocal-service-name>";
          global_config << services[i].linklocal_name;
          global_config << "</linklocal-service-name>\n";
          global_config << "<linklocal-service-ip>";
          global_config << services[i].linklocal_ip;
          global_config << "</linklocal-service-ip>\n";
          global_config << "<linklocal-service-port>";
          global_config << services[i].linklocal_port;
          global_config << "</linklocal-service-port>\n";
          global_config << "<ip-fabric-DNS-service-name>";
          global_config << services[i].fabric_dns_name;
          global_config << "</ip-fabric-DNS-service-name>\n";
          for (uint32_t j = 0; j < services[i].fabric_ip.size(); ++j) {
              global_config << "<ip-fabric-service-ip>";
              global_config << services[i].fabric_ip[j];
              global_config << "</ip-fabric-service-ip>\n";
          }
          global_config << "<ip-fabric-service-port>";
          global_config << services[i].fabric_port;
          global_config << "</ip-fabric-service-port>\n";
          global_config << "</linklocal-service-entry>\n";
      }
      global_config << "</linklocal-services>";
  
      char buf[8192];
      int len = 0;
      memset(buf, 0, 8192);
      AddXmlHdr(buf, len);
      AddNodeString(buf, len, "global-vrouter-config",
                    "default-global-system-config:default-global-vrouter-config",
                    1024, global_config.str().c_str());
      AddXmlTail(buf, len);
      ApplyXmlString(buf);
  }
  
  void DelLinkLocalConfig() {
      char buf[4096];
      int len = 0;
      memset(buf, 0, 4096);
      AddXmlHdr(buf, len);
      AddNodeString(buf, len, "global-vrouter-config",
                    "default-global-system-config:default-global-vrouter-config",
                    1024, "");
      AddXmlTail(buf, len);
      ApplyXmlString(buf);
  }
  
  void DeleteGlobalVrouterConfig() {
      char buf[4096];
      int len = 0;
      memset(buf, 0, 4096);
      DelXmlHdr(buf, len);
      DelNodeString(buf, len, "global-vrouter-config",
                    "default-global-system-config:default-global-vrouter-config");
      DelXmlTail(buf, len);
      ApplyXmlString(buf);
  }
  
  void VxLanNetworkIdentifierMode(bool config, const char *encap1,
                                  const char *encap2, const char *encap3) {
      std::stringstream str;
      if (config) {
          str << "<vxlan-network-identifier-mode>configured</vxlan-network-identifier-mode>" << endl;
      } else {
          str << "<vxlan-network-identifier-mode>automatic</vxlan-network-identifier-mode>" << endl;
      }
  
      str << "<encapsulation-priorities>" << endl;
      if (encap1) {
          str << "    <encapsulation>" << encap1 << "</encapsulation>";
      }
  
      if (encap2) {
          str << "    <encapsulation>" << encap2 << "</encapsulation>";
      }
  
      if (encap3) {
          str << "    <encapsulation>" << encap3 << "</encapsulation>";
      }
      str << "</encapsulation-priorities>";
  
      AddNode("global-vrouter-config", "vrouter-config", 1, str.str().c_str());
  }
  
  void GlobalForwardingMode(std::string mode) {
      std::stringstream str;
      str << "<forwarding-mode>" << mode << "</forwarding-mode>" << endl;
      AddNode("global-vrouter-config", "vrouter-config", 1, str.str().c_str());
  }
  
  void AddFlowExportRate(int cfg_flow_export_rate) {
      std::stringstream str;
      str << "<flow-export-rate>" << cfg_flow_export_rate <<
          "</flow-export-rate>" << endl;
      AddNode("global-vrouter-config", "vrouter-config", 1, str.str().c_str());
  }
  
  void AddEncapList(const char *encap1, const char *encap2, const char *encap3) {
      std::stringstream str;
      str << "<encapsulation-priorities>" << endl;
      if (encap1) {
          str << "    <encapsulation>" << encap1 << "</encapsulation>";
      }
  
      if (encap2) {
          str << "    <encapsulation>" << encap2 << "</encapsulation>";
      }
  
      if (encap3) {
          str << "    <encapsulation>" << encap3 << "</encapsulation>";
      }
      str << "</encapsulation-priorities>";
  
      AddNode("global-vrouter-config", "vrouter-config", 1, str.str().c_str());
  }
  
  void AddEncapList(Agent *agent, const char *encap1, const char *encap2,
                    const char *encap3) {
      std::stringstream str;
      str << "<encapsulation-priorities>" << endl;
      if (encap1) {
          str << "    <encapsulation>" << encap1 << "</encapsulation>";
      }
  
      if (encap2) {
          str << "    <encapsulation>" << encap2 << "</encapsulation>";
      }
  
      if (encap3) {
          str << "    <encapsulation>" << encap3 << "</encapsulation>";
      }
      str << "</encapsulation-priorities>";
  
      AddNode(agent, "global-vrouter-config", "vrouter-config", 1,
              str.str().c_str());
  }
  
  void DelEncapList() {
      DelNode("global-vrouter-config", "vrouter-config");
  }
  
  void DelEncapList(Agent *agent) {
      DelNode(agent, "global-vrouter-config", "vrouter-config");
  }
  
  void AddBgpaasPortRange(const int port_start, const int port_end) {
      std::stringstream str;
      str << "<bgpaas-parameters>" << endl;
      str << "    <port-start>" << port_start << "</port-start>";
      str << "    <port-end>" << port_end << "</port-end>";
      str << "</bgpaas-parameters>";
  
      AddNode("global-system-config", "system-config", 1, str.str().c_str());
  }
  
  void DelBgpaasPortRange() {
      DelNode("global-system-config", "system-config");
  }
  
  void AddFastConvergenceParameters(bool enable, const int tout) {
      std::stringstream str;
      str << "<fast-convergence-parameters>" << endl;
      str << "    <enable>" << "true" << "</enable>";
      str << "    <xmpp-hold-time>" << tout << "</xmpp-hold-time>";
      str << "</fast-convergence-parameters>";
  
      AddNode("global-system-config", "system-config", 1, str.str().c_str());
  }
  
  void DelFastConvergenceParameters() {
      DelNode("global-system-config", "system-config");
  }
  
  void DelHealthCheckService(const char *name) {
      DelNode("service-health-check", name);
  }
  
  void AddHealthCheckService(const char *name, int id,
                             const char *url_path,
                             const char *monitor_type,
                             const char *service_type) {
      char buf[1024];
  
      sprintf(buf, "<service-health-check-properties>"
                   "    <enabled>true</enabled>"
                   "    <health-check-type>%s</health-check-type>"
                   "    <monitor-type>%s</monitor-type>"
                   "    <delay>1</delay>"
                   "    <timeout>1</timeout>"
                   "    <max-retries>3</max-retries>"
                   "    <http-method></http-method>"
                   "    <url-path>%s</url-path>"
                   "    <expected-codes></expected-codes>"
                   "</service-health-check-properties>", service_type,
                   monitor_type, url_path);
      AddNode("service-health-check", name, id, buf);
  }
  
  void AddVnHealthCheckService(const char *name, int id,
                              uint32_t delay, uint32_t timeout,
                              uint32_t max_retries,
                              const bool target_ip_all,
                              const struct IpStr *target_ip_list,
                              const int target_ip_count) {
  
      char buf[1024];
      char ip_list[512];
      int i = 0, ret = 0;
  
      while (i < target_ip_count) {
          ret += snprintf(ip_list + ret, 1024 - ret,
                              "<ip-address>%s</ip-address>",
                              target_ip_list[i].ipaddr);
          i++;
      }
      ip_list[ret+1] = '\0';
  
      if (target_ip_count == 0) {
          sprintf(buf, "<service-health-check-properties>"
                   "    <enabled>true</enabled>"
                   "    <health-check-type>%s</health-check-type>"
                   "    <monitor-type>%s</monitor-type>"
                   "    <delay>%d</delay>"
                   "    <timeout>%d</timeout>"
                   "    <max-retries>%d</max-retries>"
                   "    <http-method></http-method>"
                   "    <url-path>%s</url-path>"
                   "    <expected-codes></expected-codes>"
                   "    <target-ip-all>%s</target-ip-all>"
                   "</service-health-check-properties>", "vn-ip-list", "BFD",
                   delay, timeout, max_retries, "http://local-ip/",
                   target_ip_all ? "true" : "false");
      } else {
          sprintf(buf, "<service-health-check-properties>"
                   "    <enabled>true</enabled>"
                   "    <health-check-type>%s</health-check-type>"
                   "    <monitor-type>%s</monitor-type>"
                   "    <delay>%d</delay>"
                   "    <timeout>%d</timeout>"
                   "    <max-retries>%d</max-retries>"
                   "    <http-method></http-method>"
                   "    <url-path>%s</url-path>"
                   "    <expected-codes></expected-codes>"
                   "    <target-ip-all>%s</target-ip-all>"
                   "    <target-ip-list>%s</target-ip-list>"
                   "</service-health-check-properties>", "vn-ip-list", "BFD",
                   delay, timeout, max_retries, "http://local-ip/",
                   target_ip_all ? "true" : "false", ip_list);
      }
      AddNode("service-health-check", name, id, buf);
  }
  
  void send_icmp(int fd, uint8_t smac, uint8_t dmac, uint32_t sip, uint32_t dip) {
      uint8_t dummy_dmac[6], dummy_smac[6];
      memset(dummy_dmac, 0, sizeof(dummy_dmac));
      memset(dummy_smac, 0, sizeof(dummy_dmac));
      dummy_dmac[5] = dmac;
      dummy_smac[5] = smac;
  
      IcmpPacket icmp(dummy_smac, dummy_dmac, sip, dip);
      int ret = write(fd, icmp.GetPacket(), sizeof(icmp_packet));
      LOG(DEBUG, "Written " << ret << " bytes to fd " << fd);
      if (ret < 0)
      {
          LOG(ERROR, "Error <" << errno << ": " << strerror(errno) <<
              "> writing");
      }
      usleep(3*1000);
  }
  
  uint32_t GetFlowKeyNH(int id) {
      boost::uuids::uuid intf_uuid = MakeUuid(id);
      VmInterfaceKey key(AgentKey::RESYNC, intf_uuid, "");
      const Interface *intf = static_cast<const Interface *>(
              Agent::GetInstance()->interface_table()->FindActiveEntry(&key));
      return intf->flow_key_nh()->id();
  }
  
  uint32_t GetFlowkeyNH(char *name) {
      InetInterface *intf = InetInterfaceGet(name);
      return intf->flow_key_nh()->id();
  }
  
  bool FlowStats(FlowIp *input, int id, uint32_t bytes, uint32_t pkts) {
      Agent *agent = Agent::GetInstance();
      VrfEntry *vrf;
      VrfKey vrf_key(input[id].vrf);
      vrf = static_cast<VrfEntry *>(agent->vrf_table()->FindActiveEntry(&vrf_key));
      LOG(DEBUG, "Vrf id for " << input[id].vrf << " is " << vrf->vrf_id());
  
      FlowKey key;
  
      key.src_port = 0;
      key.dst_port = 0;
      key.nh = id;
      key.src_addr = IpAddress(Ip4Address(input[id].sip));
      key.dst_addr = IpAddress(Ip4Address(input[id].dip));
      key.protocol = IPPROTO_ICMP;
      key.family = key.src_addr.is_v4() ? Address::INET : Address::INET6;
  
      FlowEntry *fe = agent->pkt()->get_flow_proto()->Find(key, 0);
      if (fe == NULL) {
          LOG(DEBUG, "Flow not found");
          return false;
      }
      FlowStatsCollector *fec = fe->fsc();
      if (fec == NULL) {
          return false;
      }
      FlowExportInfo *info = fec->FindFlowExportInfo(fe);
  
      if (info) {
          LOG(DEBUG, " bytes " << info->bytes() << " pkts " << info->packets());
          if (info->bytes() == bytes && info->packets() == pkts) {
              return true;
          }
      }
  
      return false;
  }
  
  void AddLrVmiPort(const char *vmi, int intf_id, const char *ip,
                 const char *vrf, const char *vn,
                 const char *instance_ip, int instance_uuid) {
      AddLrPort(vmi, intf_id);
      AddVmPortVrf(vmi, "", 0);
      AddInstanceIp(instance_ip, instance_uuid, ip);
      AddLink("virtual-machine-interface", vmi, "virtual-network", vn);
      AddLink("virtual-network", vn, "routing-instance", vrf);
      AddLink("virtual-machine-interface-routing-instance", vmi,
              "routing-instance", vrf);
      AddLink("virtual-machine-interface-routing-instance", vmi,
              "virtual-machine-interface", vmi);
      AddLink("virtual-machine-interface", vmi, "instance-ip", instance_ip);
      client->WaitForIdle();
  }
  
  void DelLrVmiPort(const char *vmi, int intf_id, const char *ip,
                 const char *vrf, const char *vn,
                 const char *instance_ip, int instance_uuid) {
      DelLink("virtual-machine-interface", vmi, "virtual-network", vn);
      DelLink("virtual-network", vn, "routing-instance", vrf);
      DelLink("virtual-machine-interface-routing-instance", vmi,
              "routing-instance", vrf);
      DelLink("virtual-machine-interface-routing-instance", vmi,
              "virtual-machine-interface", vmi);
      DelLink("virtual-machine-interface", vmi, "instance-ip", instance_ip);
      DelNode("virtual-machine-interface", vmi);
      DelVmPortVrf(vmi);
      DelInstanceIp(instance_ip);
      client->WaitForIdle();
  }
  
  void AddVmPort(const char *vmi, int intf_id, const char *ip, const char *mac,
                 const char *vrf, const char *vn, int vn_uuid, const char *vm,
                 int vm_uuid, const char *instance_ip, int instance_uuid) {
      struct PortInfo input[] = {
          {"", 0, "", "", 0, 0 }
      };
  
      strcpy(input[0].name, vmi);
      input[0].intf_id = intf_id;
      strcpy(input[0].addr, ip);
      strcpy(input[0].mac, mac);
      input[0].vn_id = vn_uuid;
      input[0].vm_id = vm_uuid;
  
      AddVn(vn, vn_uuid);
      AddVrf(vrf);
      AddVm(vm, vm_uuid);
      AddPort(vmi, intf_id);
      AddVmPortVrf(vmi, "", 0);
      IntfCfgAdd(input, 0);
      AddInstanceIp(instance_ip, instance_uuid, ip);
      AddLink("virtual-machine-interface", vmi, "virtual-network", vn);
      AddLink("virtual-network", vn, "routing-instance", vrf);
      AddLink("virtual-machine", vm, "virtual-machine-interface", vmi);
      AddLink("virtual-machine-interface-routing-instance", vmi,
              "routing-instance", vrf);
      AddLink("virtual-machine-interface-routing-instance", vmi,
              "virtual-machine-interface", vmi);
      AddLink("virtual-machine-interface", vmi, "instance-ip", instance_ip);
      client->WaitForIdle();
  }
  
  void DelVmPort(const char *vmi, int intf_id, const char *ip, const char *mac,
                 const char *vrf, const char *vn, int vn_uuid, const char *vm,
                 int vm_uuid, const char *instance_ip, int instance_uuid) {
      struct PortInfo input[] = {
          {"", 0, "", "", 0, 0 }
      };
  
      strcpy(input[0].name, vmi);
      input[0].intf_id = intf_id;
      strcpy(input[0].addr, ip);
      strcpy(input[0].mac, mac);
      input[0].vn_id = vn_uuid;
      input[0].vm_id = vm_uuid;
  
      DelLink("virtual-machine-interface", vmi, "virtual-network", vm);
      DelLink("virtual-network", vn, "routing-instance", vrf);
      DelLink("virtual-machine", vm, "virtual-machine-interface", vmi);
      DelLink("virtual-machine-interface-routing-instance", vmi,
              "routing-instance", vrf);
      DelLink("virtual-machine-interface-routing-instance", vmi,
              "virtual-machine-interface", vmi);
      DelLink("virtual-machine-interface", vmi,
              "instance-ip", instance_ip);
      DelVn(vn);
      DelVrf(vrf);
      DelVm(vm);
      DelPort(vmi);
      DelVmPortVrf(vmi);
      DelInstanceIp(instance_ip);
      IntfCfgDel(input, 0);
      DelNode("virtual-machine-interface", vmi);
      DelNode("virtual-machine-interface-routing-instance", vmi);
      client->WaitForIdle();
  }
  
  void DeleteVmportFIpEnv(struct PortInfo *input, int count, int del_vn, int acl_id,
                          const char *vn, const char *vrf) {
      char vn_name[80];
      char vm_name[80];
      char vrf_name[80];
      char acl_name[80];
      char instance_ip[80];
  
      if (acl_id) {
          sprintf(acl_name, "acl%d", acl_id);
      }
  
      for (int i = 0; i < count; i++) {
          if (vn)
              strncpy(vn_name, vn, MAX_TESTNAME_LEN);
          else
              sprintf(vn_name, "default-project:vn%d", input[i].vn_id);
          if (vrf)
              strncpy(vrf_name, vrf, MAX_TESTNAME_LEN);
          else
              sprintf(vrf_name, "default-project:vn%d:vn%d", input[i].vn_id,
                      input[i].vn_id);
          sprintf(vm_name, "vm%d", input[i].vm_id);
          sprintf(instance_ip, "instance%d", input[i].intf_id);
          boost::system::error_code ec;
          DelLink("virtual-machine-interface-routing-instance", input[i].name,
                  "routing-instance", vrf_name);
          DelLink("virtual-machine-interface-routing-instance", input[i].name,
                  "virtual-machine-interface", input[i].name);
          DelLink("virtual-machine", vm_name, "virtual-machine-interface",
                  input[i].name);
          DelLink("virtual-machine-interface", input[i].name, "instance-ip",
                  instance_ip);
          DelLink("virtual-network", vn_name, "virtual-machine-interface",
                  input[i].name);
          DelNode("virtual-machine-interface", input[i].name);
          DelNode("virtual-machine-interface-routing-instance", input[i].name);
          IntfCfgDel(input, i);
  
          DelNode("virtual-machine", vm_name);
      }
  
      if (del_vn) {
          for (int i = 0; i < count; i++) {
              int j = 0;
              for (; j < i; j++) {
                  if (input[i].vn_id == input[j].vn_id) {
                      break;
                  }
              }
  
              if (j < i) {
                  break;
              }
              if (vn)
                  sprintf(vn_name, "%s", vn);
              else
                  sprintf(vn_name, "default-project:vn%d", input[i].vn_id);
              if (vrf)
                  sprintf(vrf_name, "%s", vrf);
              else
                  sprintf(vrf_name, "default-project:vn%d:vn%d", input[i].vn_id,
                          input[i].vn_id);
              sprintf(vm_name, "vm%d", input[i].vm_id);
              DelLink("virtual-network", vn_name, "routing-instance", vrf_name);
              if (acl_id) {
                  DelLink("virtual-network", vn_name, "access-control-list", acl_name);
              }
  
              DelNode("virtual-network", vn_name);
              DelNode("routing-instance", vrf_name);
          }
      }
  
      if (acl_id) {
          DelNode("access-control-list", acl_name);
      }
  }
  
  void DeleteVmportEnv(struct PortInfo *input, int count, int del_vn, int acl_id,
                       const char *vn, const char *vrf, bool with_ip,
                       bool with_ip6) {
      char vn_name[80];
      char vm_name[80];
      char vrf_name[80];
      char acl_name[80];
      char instance_ip[80];
      char instance_ip6[80];
  
      if (acl_id) {
          sprintf(acl_name, "acl%d", acl_id);
      }
  
      for (int i = 0; i < count; i++) {
          if (vn)
              strncpy(vn_name, vn, MAX_TESTNAME_LEN);
          else
              sprintf(vn_name, "vn%d", input[i].vn_id);
          if (vrf)
              strncpy(vrf_name, vrf, MAX_TESTNAME_LEN);
          else
              sprintf(vrf_name, "vrf%d", input[i].vn_id);
          sprintf(vm_name, "vm%d", input[i].vm_id);
          sprintf(instance_ip, "instance%d", input[i].intf_id);
          boost::system::error_code ec;
          DelLink("virtual-machine-interface-routing-instance", input[i].name,
                  "routing-instance", vrf_name);
          DelLink("virtual-machine-interface-routing-instance", input[i].name,
                  "virtual-machine-interface", input[i].name);
          DelLink("virtual-machine", vm_name, "virtual-machine-interface",
                  input[i].name);
          DelLink("virtual-machine-interface", input[i].name, "instance-ip",
                  instance_ip);
          DelLink("virtual-network", vn_name, "virtual-machine-interface",
                  input[i].name);
          if (with_ip6) {
              sprintf(instance_ip6, "instance6%d", input[i].intf_id);
              DelLink("virtual-machine-interface", input[i].name, "instance-ip",
                      instance_ip6);
              DelInstanceIp(instance_ip6);
          }
          DelNode("virtual-machine-interface", input[i].name);
          DelNode("virtual-machine-interface-routing-instance", input[i].name);
          IntfCfgDel(input, i);
  
          DelNode("virtual-machine", vm_name);
          if (with_ip) {
              DelInstanceIp(instance_ip);
          }
      }
  
      if (del_vn) {
          for (int i = 0; i < count; i++) {
              int j = 0;
              for (; j < i; j++) {
                  if (input[i].vn_id == input[j].vn_id) {
                      break;
                  }
              }
  
              // Ignore duplicate deletes
              if (j < i) {
                  continue;
              }
              if (vn)
                  sprintf(vn_name, "%s", vn);
              else
                  sprintf(vn_name, "vn%d", input[i].vn_id);
              if (vrf)
                  sprintf(vrf_name, "%s", vrf);
              else
                  sprintf(vrf_name, "vrf%d", input[i].vn_id);
              DelLink("virtual-network", vn_name, "routing-instance", vrf_name);
              if (acl_id) {
                  DelLink("virtual-network", vn_name, "access-control-list", acl_name);
              }
  
              DelNode("virtual-network", vn_name);
              DelNode("routing-instance", vrf_name);
          }
      }
  
      if (acl_id) {
          DelNode("access-control-list", acl_name);
      }
  
      if (client->agent_init()->ksync_enable()) {
          DeleteTapIntf(test_tap_fd, count);
      }
  }
  
  void CreateVmportFIpEnv(struct PortInfo *input, int count, int acl_id,
                          const char *vn, const char *vrf) {
      char vn_name[MAX_TESTNAME_LEN];
      char vm_name[MAX_TESTNAME_LEN];
      char vrf_name[MAX_TESTNAME_LEN];
      char acl_name[MAX_TESTNAME_LEN];
      char instance_ip[MAX_TESTNAME_LEN];
  
      if (acl_id) {
          sprintf(acl_name, "acl%d", acl_id);
          AddAcl(acl_name, acl_id);
      }
  
      for (int i = 0; i < count; i++) {
          if (vn)
              strncpy(vn_name, vn, MAX_TESTNAME_LEN);
          else
              sprintf(vn_name, "default-project:vn%d", input[i].vn_id);
          if (vrf)
              strncpy(vrf_name, vrf, MAX_TESTNAME_LEN);
          else
              sprintf(vrf_name, "default-project:vn%d:vn%d", input[i].vn_id,
                      input[i].vn_id);
          sprintf(vm_name, "vm%d", input[i].vm_id);
          sprintf(instance_ip, "instance%d", input[i].intf_id);
          AddVn(vn_name, input[i].vn_id);
          AddVrf(vrf_name);
          AddVm(vm_name, input[i].vm_id);
          AddVmPortVrf(input[i].name, "", 0);
  
          //AddNode("virtual-machine-interface-routing-instance", input[i].name,
          //        input[i].intf_id);
          IntfCfgAddThrift(input, i);
          AddPort(input[i].name, input[i].intf_id);
          AddActiveActiveInstanceIp(instance_ip, input[i].intf_id, input[i].addr);
          AddLink("virtual-network", vn_name, "routing-instance", vrf_name);
          AddLink("virtual-machine-interface", input[i].name, "virtual-machine", vm_name);
          AddLink("virtual-machine-interface", input[i].name, "virtual-network",
                  vn_name);
          AddLink("virtual-machine-interface-routing-instance", input[i].name,
                  "routing-instance", vrf_name, "virtual-machine-interface-routing-instance");
          AddLink("virtual-machine-interface-routing-instance", input[i].name,
                  "virtual-machine-interface", input[i].name, "virtual-machine-interface-routing-instance");
          AddLink("virtual-machine-interface", input[i].name,
                  "instance-ip", instance_ip);
          AddLink("instance-ip", instance_ip, "virtual-machine-interface",
                  input[i].name);
  
          if (acl_id) {
              AddLink("virtual-network", vn_name, "access-control-list", acl_name);
          }
      }
  }
  
  void CreateVmportEnvInternal(struct PortInfo *input, int count, int acl_id,
                       const char *vn, const char *vrf,
                       const char *vm_interface_attr,
                       bool l2_vn, bool with_ip, bool ecmp,
                       bool vn_admin_state, bool with_ip6, bool send_nova_msg) {
      char vn_name[MAX_TESTNAME_LEN];
      char vm_name[MAX_TESTNAME_LEN];
      char vrf_name[MAX_TESTNAME_LEN];
      char acl_name[MAX_TESTNAME_LEN];
      char instance_ip[MAX_TESTNAME_LEN];
      char instance_ip6[MAX_TESTNAME_LEN];
  
      if (client->agent_init()->ksync_enable()) {
          CreateTapInterfaces("vnet", count, test_tap_fd);
      }
  
      if (acl_id) {
          sprintf(acl_name, "acl%d", acl_id);
          AddAcl(acl_name, acl_id);
      }
  
      for (int i = 0; i < count; i++) {
          if (vn)
              strncpy(vn_name, vn, MAX_TESTNAME_LEN);
          else
              sprintf(vn_name, "vn%d", input[i].vn_id);
          if (vrf)
              strncpy(vrf_name, vrf, MAX_TESTNAME_LEN);
          else
              sprintf(vrf_name, "vrf%d", input[i].vn_id);
          sprintf(vm_name, "vm%d", input[i].vm_id);
          sprintf(instance_ip, "instance%d", input[i].intf_id);
          if (!l2_vn) {
              AddVn(vn_name, input[i].vn_id, vn_admin_state);
              AddVrf(vrf_name);
          }
          AddVm(vm_name, input[i].vm_id);
          AddVmPortVrf(input[i].name, "", 0);
  
          //AddNode("virtual-machine-interface-routing-instance", input[i].name,
          //        input[i].intf_id);
          if (send_nova_msg) {
              IntfCfgAddThrift(input, i);
          }
          AddPortWithMac(input[i].name, input[i].intf_id,
                         input[i].mac, vm_interface_attr);
          if (with_ip) {
              if (ecmp) {
                  AddActiveActiveInstanceIp(instance_ip, input[i].intf_id,
                                            input[i].addr);
              } else {
                  AddInstanceIp(instance_ip, input[i].intf_id, input[i].addr);
              }
          }
          if (with_ip6) {
              sprintf(instance_ip6, "instance6%d", input[i].intf_id);
              if (ecmp) {
                  AddActiveActiveInstanceIp(instance_ip6, input[i].intf_id,
                                            input[i].ip6addr);
              } else {
                  AddInstanceIp(instance_ip6, input[i].intf_id, input[i].ip6addr);
              }
          }
          if (!l2_vn) {
              AddLink("virtual-network", vn_name, "routing-instance", vrf_name);
              client->WaitForIdle();
          }
          AddLink("virtual-machine-interface", input[i].name, "virtual-machine",
                  vm_name);
          AddLink("virtual-machine-interface", input[i].name,
                  "virtual-network", vn_name);
          AddLink("virtual-machine-interface-routing-instance", input[i].name,
                  "routing-instance", vrf_name,
                  "virtual-machine-interface-routing-instance");
          AddLink("virtual-machine-interface-routing-instance", input[i].name,
                  "virtual-machine-interface", input[i].name,
                  "virtual-machine-interface-routing-instance");
          if (with_ip) {
              AddLink("instance-ip", instance_ip,
                      "virtual-machine-interface", input[i].name);
          }
          if (with_ip6) {
              AddLink("instance-ip", instance_ip6,
                      "virtual-machine-interface", input[i].name);
          }
  
          if (acl_id) {
              AddLink("virtual-network", vn_name, "access-control-list", acl_name);
          }
      }
  }
  
  void CreateVmportEnvWithoutIp(struct PortInfo *input, int count, int acl_id,
                                const char *vn, const char *vrf) {
      CreateVmportEnvInternal(input, count, acl_id, vn, vrf, NULL, false, false,
                              false, true);
  }
  
  void CreateVmportEnv(struct PortInfo *input, int count, int acl_id,
                       const char *vn, const char *vrf,
                       const char *vm_interface_attr,
                       bool vn_admin_state) {
      CreateVmportEnvInternal(input, count, acl_id, vn, vrf,
                              vm_interface_attr, false, true, false,
                              vn_admin_state, false, true);
  }
  
  void CreateL2VmportEnv(struct PortInfo *input, int count, int acl_id,
                       const char *vn, const char *vrf) {
      AddL2Vn("vn1", 1);
      AddVrf("vrf1");
      AddLink("virtual-network", "vn1", "routing-instance", "vrf1");
      TestClient::WaitForIdle();
      CreateVmportEnvInternal(input, count, acl_id, vn, vrf, NULL, true,
                              true, false, true);
  }
  
  void CreateL3VmportEnv(struct PortInfo *input, int count, int acl_id,
                         const char *vn, const char *vrf) {
      AddL3Vn("vn1", 1);
      AddVrf("vrf1");
      AddLink("virtual-network", "vn1", "routing-instance", "vrf1");
      TestClient::WaitForIdle();
      CreateVmportEnvInternal(input, count, acl_id, vn, vrf, NULL, true,
                              true, false, true);
  }
  
  void CreateVmportWithEcmp(struct PortInfo *input, int count, int acl_id,
                            const char *vn, const char *vrf) {
      CreateVmportEnvInternal(input, count, acl_id, vn, vrf, NULL, false,
                              true, true, true);
  }
  
  void CreateVmportWithoutNova(struct PortInfo *input, int count, int acl_id,
                            const char *vn, const char *vrf) {
      CreateVmportEnvInternal(input, count, acl_id, vn, vrf, NULL, false,
                              true, true, true, false, false);
  }
  
  void CreateV6VmportEnv(struct PortInfo *input, int count, int acl_id,
                         const char *vn, const char *vrf, bool with_v4_ip) {
      CreateVmportEnvInternal(input, count, acl_id, vn, vrf, NULL, false,
                              with_v4_ip, false, true, true);
  }
  
  void CreateV6VmportWithEcmp(struct PortInfo *input, int count, int acl_id,
                         const char *vn, const char *vrf, bool with_v4_ip) {
      CreateVmportEnvInternal(input, count, acl_id, vn, vrf, NULL, false,
                              with_v4_ip, true, true, true);
  }
  
  void FlushFlowTable() {
      Agent::GetInstance()->pkt()->get_flow_proto()->FlushFlows();
      TestClient::WaitForIdle();
      EXPECT_EQ(0U, Agent::GetInstance()->pkt()->get_flow_proto()->FlowCount());
  }
  
  static bool FlowDeleteTrigger(FlowKey key) {
      FlowTable *table =
          Agent::GetInstance()->pkt()->get_flow_proto()->GetTable(0);
      if (table->Find(key) == NULL) {
          return true;
      }
  
      table->Delete(key, true);
      return true;
  }
  
  bool FlowDelete(const string &vrf_name, const char *sip, const char *dip,
                  uint8_t proto, uint16_t sport, uint16_t dport, int nh_id) {
  
      VrfEntry *vrf = Agent::GetInstance()->vrf_table()->FindVrfFromName(vrf_name);
      EXPECT_TRUE(vrf != NULL);
      if (vrf == NULL)
          return false;
  
      FlowKey key;
      key.nh = nh_id;
      key.src_addr = IpAddress::from_string(sip);
      key.dst_addr = IpAddress::from_string(dip);
      key.src_port = sport;
      key.dst_port = dport;
      if (proto == IPPROTO_ICMPV6) {
          key.dst_port = ICMP6_ECHO_REPLY;
      }
      key.protocol = proto;
      key.family = key.src_addr.is_v4() ? Address::INET : Address::INET6;
  
      if (Agent::GetInstance()->pkt()->get_flow_proto()->Find(key, 0) == NULL) {
          return false;
      }
  
      int task_id = TaskScheduler::GetInstance()->GetTaskId(kTaskFlowEvent);
      std::auto_ptr<TaskTrigger> trigger_
          (new TaskTrigger(boost::bind(FlowDeleteTrigger, key), task_id, 0));
      trigger_->Set();
      client->WaitForIdle();
      return true;
  }
  
  bool FlowFail(int vrf_id, const char *sip, const char *dip,
                uint8_t proto, uint16_t sport, uint16_t dport, int nh_id) {
      FlowKey key;
      key.nh = nh_id;
      key.src_addr = IpAddress::from_string(sip);
      key.dst_addr = IpAddress::from_string(dip);
      key.src_port = sport;
      key.dst_port = dport;
      key.protocol = proto;
      key.family = key.src_addr.is_v4() ? Address::INET : Address::INET6;
      FlowProto *fp = Agent::GetInstance()->pkt()->get_flow_proto();
  
      WAIT_FOR(1000, 1000, (fp->Find(key, 0) == false));
      FlowEntry *fe = fp->Find(key, 0);
      if (fe == NULL) {
          return true;
      }
      if (fe->deleted()) {
          return true;
      }
      return false;
  }
  
  bool FlowFail(const string &vrf_name, const char *sip, const char *dip,
                uint8_t proto, uint16_t sport, uint16_t dport, int nh_id) {
  
      VrfEntry *vrf = Agent::GetInstance()->vrf_table()->FindVrfFromName(vrf_name);
      EXPECT_TRUE(vrf != NULL);
      if (vrf == NULL)
          return false;
  
      return FlowFail(vrf->vrf_id(), sip, dip, proto, sport, dport, nh_id);
  }
  
  bool FlowGetNat(const string &vrf_name, const char *sip, const char *dip,
                  uint8_t proto, uint16_t sport, uint16_t dport,
                  std::string svn, std::string dvn, uint32_t hash_id,
                  const char *nat_vrf, const char *nat_sip,
                  const char *nat_dip, uint16_t nat_sport, int16_t nat_dport,
                  int nh_id, int nat_nh_id) {
  
      VrfEntry *vrf = Agent::GetInstance()->vrf_table()->FindVrfFromName(vrf_name);
      EXPECT_TRUE(vrf != NULL);
      if (vrf == NULL)
          return false;
  
      FlowKey key;
      key.nh = nh_id;
      key.src_addr = IpAddress::from_string(sip);
      key.dst_addr = IpAddress::from_string(dip);
      key.src_port = sport;
      key.dst_port = dport;
      key.protocol = proto;
      key.family = key.src_addr.is_v4() ? Address::INET : Address::INET6;
  
      FlowTable *table =
          Agent::GetInstance()->pkt()->get_flow_proto()->GetTable(0);
      FlowEntry *entry = table->Find(key);
      EXPECT_TRUE(entry != NULL);
      if (entry == NULL) {
          return false;
      }
  
      EXPECT_TRUE(entry->is_flags_set(FlowEntry::NatFlow));
      if (!entry->is_flags_set(FlowEntry::NatFlow)) {
          return false;
      }
  
      EXPECT_TRUE(VnMatch(entry->data().source_vn_list, svn));
      if (!VnMatch(entry->data().source_vn_list, svn)) {
          return false;
      }
  
      EXPECT_TRUE(VnMatch(entry->data().dest_vn_list, dvn));
      if (!VnMatch(entry->data().dest_vn_list, dvn)) {
          return false;
      }
  
      if ((int)hash_id >= 0) {
          EXPECT_TRUE(entry->flow_handle() == hash_id);
          if (entry->flow_handle() != hash_id) {
              return false;
          }
      }
  
      vrf = Agent::GetInstance()->vrf_table()->FindVrfFromName(nat_vrf);
      EXPECT_TRUE(vrf != NULL);
      if (vrf == NULL)
          return false;
  
      key.nh = nat_nh_id;
      key.src_addr = IpAddress::from_string(nat_dip);
      key.dst_addr = IpAddress::from_string(nat_sip);
      key.src_port = nat_dport;
      key.dst_port = nat_sport;
      key.family = key.src_addr.is_v4() ? Address::INET : Address::INET6;
      FlowEntry * rentry = table->Find(key);
      EXPECT_TRUE(rentry != NULL);
      if (rentry == NULL) {
          return false;
      }
  
      EXPECT_TRUE(rentry->is_flags_set(FlowEntry::NatFlow));
      if (!rentry->is_flags_set(FlowEntry::NatFlow)) {
          return false;
      }
  
      EXPECT_TRUE(entry->reverse_flow_entry() == rentry);
      EXPECT_TRUE(rentry->reverse_flow_entry() == entry);
      if (entry->reverse_flow_entry() != rentry)
          return false;
      if (rentry->reverse_flow_entry() != entry)
          return false;
  
      return true;
  }
  
  FlowEntry* FlowGet(std::string sip, std::string dip, uint8_t proto,
                     uint16_t sport, uint16_t dport, int nh_id,
                     uint32_t flow_handle) {
      FlowKey key;
      key.nh = nh_id;
      key.src_addr = IpAddress::from_string(sip);
      key.dst_addr = IpAddress::from_string(dip);
      key.src_port = sport;
      key.dst_port = dport;
      key.protocol = proto;
      key.family = key.src_addr.is_v4() ? Address::INET : Address::INET6;
  
      FlowTable *table =
          Agent::GetInstance()->pkt()->get_flow_proto()->GetFlowTable(key,
                                                                      flow_handle);
      if (table == NULL) {
          return NULL;
      }
      return table->Find(key);
  }
  
  FlowEntry* FlowGet(int vrf_id, std::string sip, std::string dip, uint8_t proto,
                     uint16_t sport, uint16_t dport, int nh_id) {
      FlowKey key;
      key.nh = nh_id;
      key.src_addr = IpAddress::from_string(sip);
      key.dst_addr = IpAddress::from_string(dip);
      key.src_port = sport;
      key.dst_port = dport;
      key.protocol = proto;
      key.family = key.src_addr.is_v4() ? Address::INET : Address::INET6;
  
      return Agent::GetInstance()->pkt()->get_flow_proto()->Find(key, 0);
  }
  
  FlowEntry* FlowGet(int nh_id, std::string sip, std::string dip, uint8_t proto,
                     uint16_t sport, uint16_t dport) {
      return FlowGet(0, sip, dip, proto, sport, dport, nh_id);
  }
  
  bool FlowGet(int vrf_id, const char *sip, const char *dip, uint8_t proto,
               uint16_t sport, uint16_t dport, bool short_flow, int hash_id,
               int reverse_hash_id, int nh_id, int reverse_nh_id) {
      FlowKey key;
      key.nh = nh_id;
      key.src_addr = Ip4Address::from_string(sip);
      key.dst_addr = Ip4Address::from_string(dip);
      key.src_port = sport;
      key.dst_port = dport;
      key.protocol = proto;
      key.family = key.src_addr.is_v4() ? Address::INET : Address::INET6;
  
      FlowEntry *entry = Agent::GetInstance()->pkt()->get_flow_proto()->Find(key,
                                                                             0);
      EXPECT_TRUE(entry != NULL);
      if (entry == NULL) {
          return false;
      }
  
      if (hash_id >= 0) {
          EXPECT_EQ(entry->flow_handle(), (uint32_t)hash_id);
          if (entry->flow_handle() != (uint32_t)hash_id) {
              return false;
          }
      }
  
      EXPECT_EQ(entry->is_flags_set(FlowEntry::ShortFlow), short_flow);
      if (entry->is_flags_set(FlowEntry::ShortFlow) != short_flow) {
          return false;
      }
  
      if (reverse_hash_id == 0) {
          bool ret = true;
          FlowEntry *rev = entry->reverse_flow_entry();
  
          EXPECT_TRUE(entry->is_flags_set(FlowEntry::NatFlow) == false);
          if (entry->is_flags_set(FlowEntry::NatFlow) == true)
              ret = false;
  
          if ((uint32_t)reverse_nh_id != rev->key().nh)
              ret = false;
  
          EXPECT_EQ(entry->key().protocol, rev->key().protocol);
          if (entry->key().protocol != rev->key().protocol)
              ret = false;
  
          EXPECT_EQ(entry->key().src_addr, rev->key().dst_addr);
          if (entry->key().src_addr != rev->key().dst_addr)
              ret = false;
  
          EXPECT_EQ(entry->key().dst_addr, rev->key().src_addr);
          if (entry->key().dst_addr != rev->key().src_addr)
              ret = false;
  
          return ret;
      }
  
      if (reverse_hash_id > 0) {
          FlowEntry *rev = entry->reverse_flow_entry();
          EXPECT_TRUE(rev != NULL);
          if (rev == NULL) {
              return false;
          }
  
          EXPECT_EQ(rev->flow_handle(), (uint32_t)reverse_hash_id);
          if (rev->flow_handle() != (uint32_t)reverse_hash_id) {
              return false;
          }
      }
  
      return true;
  }
  
  bool FlowGet(const string &vrf_name, const char *sip, const char *dip,
               uint8_t proto, uint16_t sport, uint16_t dport, bool rflow,
               std::string svn, std::string dvn, uint32_t hash_id, int nh_id,
               int rev_nh_id) {
  
      VrfEntry *vrf = Agent::GetInstance()->vrf_table()->FindVrfFromName(vrf_name);
      EXPECT_TRUE(vrf != NULL);
      if (vrf == NULL)
          return false;
  
      FlowKey key;
      key.nh = nh_id;
      key.src_addr = Ip4Address::from_string(sip);
      key.dst_addr = Ip4Address::from_string(dip);
      key.src_port = sport;
      key.dst_port = dport;
      key.protocol = proto;
      key.family = key.src_addr.is_v4() ? Address::INET : Address::INET6;
  
      FlowTable *table =
          Agent::GetInstance()->pkt()->get_flow_proto()->GetFlowTable(key, 0);
      FlowEntry *entry = table->Find(key);
      EXPECT_TRUE(entry != NULL);
      if (entry == NULL) {
          return false;
      }
  
      EXPECT_TRUE(VnMatch(entry->data().source_vn_list, svn));
      if (!VnMatch(entry->data().source_vn_list, svn)) {
          return false;
      }
  
      EXPECT_TRUE(VnMatch(entry->data().dest_vn_list, dvn));
      if (!VnMatch(entry->data().dest_vn_list, dvn)) {
          return false;
      }
  
      if (hash_id >= 0) {
          EXPECT_EQ(entry->flow_handle(), hash_id);
          if (entry->flow_handle() != hash_id) {
              return false;
          }
      }
  
      if (rflow) {
          key.nh = rev_nh_id;
          key.src_addr = Ip4Address::from_string(dip);
          key.dst_addr = Ip4Address::from_string(sip);
          key.src_port = dport;
          key.dst_port = sport;
          key.family = key.src_addr.is_v4() ? Address::INET : Address::INET6;
          FlowEntry * rentry = table->Find(key);
          EXPECT_TRUE(rentry != NULL);
          if (rentry == NULL) {
              return false;
          }
          EXPECT_TRUE(entry->reverse_flow_entry() == rentry);
          EXPECT_TRUE(rentry->reverse_flow_entry() == entry);
          if (entry->reverse_flow_entry() != rentry)
              return false;
          if (rentry->reverse_flow_entry() != entry)
              return false;
      } else {
          bool ret = true;
          FlowEntry *rev = entry->reverse_flow_entry();
  
          EXPECT_TRUE(entry->is_flags_set(FlowEntry::NatFlow) == false);
          if (entry->is_flags_set(FlowEntry::NatFlow) == true)
              ret = false;
  
          if (rev_nh_id != -1) {
              EXPECT_EQ(rev_nh_id, rev->key().nh);
              ret = false;
          } else {
              //EXPECT_EQ((uint32_t) rflow_vrf, rev->key().vrf);
          }
  
          EXPECT_EQ(entry->key().protocol, rev->key().protocol);
          if (entry->key().protocol != rev->key().protocol)
              ret = false;
  
          EXPECT_EQ(entry->key().src_addr, rev->key().dst_addr);
          if (entry->key().src_addr != rev->key().dst_addr)
              ret = false;
  
          EXPECT_EQ(entry->key().dst_addr, rev->key().src_addr);
          if (entry->key().dst_addr != rev->key().src_addr)
              ret = false;
  
          return ret;
      }
      return true;
  }
  
  bool FlowGet(const string &vrf_name, const char *sip, const char *dip,
               uint8_t proto, uint16_t sport, uint16_t dport, bool rflow,
               std::string svn, std::string dvn, uint32_t hash_id, bool fwd,
               bool nat, int nh_id, int rev_nh_id) {
  
      bool flow_fwd = false;
      bool ret = FlowGet(vrf_name, sip, dip, proto, sport, dport, rflow,
                         svn, dvn, hash_id, nh_id, rev_nh_id);
  
      VrfEntry *vrf = Agent::GetInstance()->vrf_table()->FindVrfFromName(vrf_name);
      EXPECT_TRUE(vrf != NULL);
      if (vrf == NULL)
          return false;
  
      FlowKey key;
      key.nh = nh_id;
      key.src_addr = Ip4Address::from_string(sip);
      key.dst_addr = Ip4Address::from_string(dip);
      key.src_port = sport;
      key.dst_port = dport;
      key.protocol = proto;
      key.family = key.src_addr.is_v4() ? Address::INET : Address::INET6;
  
      FlowEntry *entry = Agent::GetInstance()->pkt()->get_flow_proto()->Find(key,
                                                                             0);
      EXPECT_TRUE(entry != NULL);
      if (entry == NULL) {
          return false;
      }
  
      EXPECT_EQ(entry->is_flags_set(FlowEntry::NatFlow), nat);
      if (entry->is_flags_set(FlowEntry::NatFlow) != nat) {
          ret = false;
      }
  
      if (entry->match_p().action_info.action & (1 << SimpleAction::PASS)) {
          flow_fwd = true;
      }
  
      if (entry->IsShortFlow()) {
          flow_fwd = false;
      }
  
      EXPECT_EQ(flow_fwd, fwd);
      if (flow_fwd != fwd) {
          ret = false;
      }
  
      return ret;
  }
  
  bool FlowStatsMatch(const string &vrf_name, const char *sip,
                      const char *dip, uint8_t proto, uint16_t sport,
                      uint16_t dport, uint64_t pkts, uint64_t bytes, int nh_id,
                      uint32_t flow_handle) {
      Agent *agent = Agent::GetInstance();
      VrfEntry *vrf = agent->vrf_table()->FindVrfFromName(vrf_name);
      EXPECT_TRUE(vrf != NULL);
      if (vrf == NULL)
          return false;
  
      FlowKey key;
      key.nh = nh_id;
      key.src_addr = Ip4Address::from_string(sip);
      key.dst_addr = Ip4Address::from_string(dip);
      key.src_port = sport;
      key.dst_port = dport;
      key.protocol = proto;
      key.family = key.src_addr.is_v4() ? Address::INET : Address::INET6;
  
      FlowEntry *fe = NULL;
      if (flow_handle != FlowEntry::kInvalidFlowHandle) {
          FlowTable *table = agent->pkt()->get_flow_proto()->GetFlowTable(key,
                                                                          flow_handle);
          if (table == NULL) {
              return NULL;
          }
          fe = table->Find(key);
      } else {
          fe = agent->pkt()->get_flow_proto()->Find(key, 0);
      }
      EXPECT_TRUE(fe != NULL);
      if (fe == NULL) {
          return false;
      }
      FlowStatsCollector *fec = fe->fsc();
      if (fec == NULL) {
          return false;
      }
      FlowExportInfo *info = fec->FindFlowExportInfo(fe);
      if (info) {
          LOG(DEBUG, " bytes " << info->bytes() << " pkts " << info->packets());
          if (info->bytes() == bytes && info->packets() == pkts) {
              return true;
          }
      }
  
      return false;
  }
  
  bool FindFlow(const string &vrf_name, const char *sip, const char *dip,
                uint8_t proto, uint16_t sport, uint16_t dport, bool nat,
                const string &nat_vrf_name, const char *nat_sip,
                const char *nat_dip, uint16_t nat_sport, uint16_t nat_dport,
                int fwd_nh_id, int rev_nh_id) {
  
      VrfEntry *vrf = Agent::GetInstance()->vrf_table()->FindVrfFromName(vrf_name);
      EXPECT_TRUE(vrf != NULL);
      if (vrf == NULL)
          return false;
  
      FlowKey key;
      key.nh = fwd_nh_id;
      key.src_addr = Ip4Address::from_string(sip);
      key.dst_addr = Ip4Address::from_string(dip);
      key.src_port = sport;
      key.dst_port = dport;
      key.protocol = proto;
      key.family = key.src_addr.is_v4() ? Address::INET : Address::INET6;
  
      FlowTable *table =
          Agent::GetInstance()->pkt()->get_flow_proto()->GetFlowTable(key, 0);
      FlowEntry *entry = table->Find(key);
      EXPECT_TRUE(entry != NULL);
      if (entry == NULL) {
          return false;
      }
  
      if (nat == false) {
          EXPECT_TRUE(entry->reverse_flow_entry() == NULL);
          if (entry->reverse_flow_entry() == NULL)
              return true;
  
          return false;
      }
  
      VrfEntry *nat_vrf = Agent::GetInstance()->vrf_table()->FindVrfFromName(nat_vrf_name);
      EXPECT_TRUE(nat_vrf != NULL);
      if (nat_vrf == NULL)
          return false;
  
      key.nh = rev_nh_id;
      key.src_addr = Ip4Address::from_string(nat_dip);
      key.dst_addr = Ip4Address::from_string(nat_sip);
      key.src_port = nat_dport;
      key.dst_port = nat_sport;
      key.protocol = proto;
      key.family = key.src_addr.is_v4() ? Address::INET : Address::INET6;
  
      FlowEntry *nat_entry = table->Find(key);
      EXPECT_TRUE(nat_entry != NULL);
      if (nat_entry == NULL) {
          return false;
      }
  
      EXPECT_EQ(entry->reverse_flow_entry(), nat_entry);
      EXPECT_EQ(nat_entry->reverse_flow_entry(), entry);
  
      if ((entry->reverse_flow_entry() == nat_entry) &&
          (nat_entry->reverse_flow_entry() == entry)) {
          return true;
      }
  
      return false;
  }
  
  PktGen *TxTcpPacketUtil(int ifindex, const char *sip, const char *dip,
                          int sport, int dport, uint32_t hash_idx) {
      PktGen *pkt = new PktGen();
      pkt->AddEthHdr("00:00:5E:00:01:00", "00:00:00:00:00:02", 0x800);
      pkt->AddAgentHdr(ifindex, AgentHdr::TRAP_FLOW_MISS, hash_idx);
      pkt->AddEthHdr("00:00:5E:00:01:00", "00:00:00:00:00:02", 0x800);
      pkt->AddIpHdr(sip, dip, IPPROTO_TCP);
      pkt->AddTcpHdr(sport, dport, false, false, false, 64);
  
      uint8_t *ptr(new uint8_t[pkt->GetBuffLen()]);
      memcpy(ptr, pkt->GetBuff(), pkt->GetBuffLen());
      client->agent_init()->pkt0()->ProcessFlowPacket(ptr, pkt->GetBuffLen(),
                                                      pkt->GetBuffLen());
      delete pkt;
      return NULL;
  }
  
  PktGen *TxIpPacketUtil(int ifindex, const char *sip, const char *dip,
                         int proto, int hash_id) {
      PktGen *pkt = new PktGen();
      pkt->AddEthHdr("00:00:5E:00:01:00", "00:00:00:00:00:02", 0x800);
      pkt->AddAgentHdr(ifindex, AgentHdr::TRAP_FLOW_MISS, hash_id);
      pkt->AddEthHdr("00:00:5E:00:01:00", "00:00:00:00:00:02", 0x800);
      pkt->AddIpHdr(sip, dip, proto);
      if (proto == 1)
          pkt->AddIcmpHdr();
  
      uint8_t *ptr(new uint8_t[pkt->GetBuffLen()]);
      memcpy(ptr, pkt->GetBuff(), pkt->GetBuffLen());
      client->agent_init()->pkt0()->ProcessFlowPacket(ptr, pkt->GetBuffLen(),
                                                      pkt->GetBuffLen());
      delete pkt;
      return NULL;
  }
  
  const NextHop* MplsToNextHop(uint32_t label) {
      MplsLabel *mpls = Agent::GetInstance()->mpls_table()->FindMplsLabel(label);
      if (mpls) {
          return mpls->nexthop();
      }
      return NULL;
  }
  
  int MplsToVrfId(int label) {
      int vrf = 0;
      MplsLabel *mpls = Agent::GetInstance()->mpls_table()->FindMplsLabel(label);
      if (mpls) {
          const NextHop *nh = mpls->nexthop();
          if (nh->GetType() == NextHop::INTERFACE) {
              const InterfaceNH *nh1 = static_cast<const InterfaceNH *>(nh);
              const VmInterface *intf =
                  static_cast<const VmInterface *>(nh1->GetInterface());
              if (intf && intf->vrf()) {
                  vrf = intf->vrf()->vrf_id();
              }
          } else if (nh->GetType() == NextHop::COMPOSITE) {
              const CompositeNH *nh1 = static_cast<const CompositeNH *>(nh);
              vrf = nh1->vrf()->vrf_id();
          } else if (nh->GetType() == NextHop::VLAN) {
              const VlanNH *nh1 = static_cast<const VlanNH *>(nh);
              const VmInterface *intf =
                  static_cast<const VmInterface *>(nh1->GetInterface());
              if (intf && intf->GetServiceVlanVrf(nh1->GetVlanTag())) {
                  vrf = intf->GetServiceVlanVrf(nh1->GetVlanTag())->vrf_id();
              }
          } else if (nh->GetType() == NextHop::VRF) {
              const VrfNH *vrf_nh = static_cast<const VrfNH *>(nh);
              vrf = vrf_nh->GetVrf()->vrf_id();
          } else {
              assert(0);
          }
      }
      return vrf;
  }
  
  PktGen *TxMplsPacketUtil(int ifindex, const char *out_sip,
                              const char *out_dip, uint32_t label,
                              const char *sip, const char *dip,
                              int proto, int hash_idx) {
      PktGen *pkt = new PktGen();
      pkt->AddEthHdr("00:00:5E:00:01:00", "00:00:00:00:00:02", 0x800);
      pkt->AddAgentHdr(ifindex, AgentHdr::TRAP_FLOW_MISS, hash_idx, MplsToVrfId(label),
                       label);
      pkt->AddEthHdr("00:00:5E:00:01:00", "00:00:00:00:00:02", 0x800);
      pkt->AddIpHdr(out_sip, out_dip, IPPROTO_GRE);
      pkt->AddGreHdr();
      pkt->AddMplsHdr(label, true);
      pkt->AddIpHdr(sip, dip, proto);
      if (proto == 1)
          pkt->AddIcmpHdr();
  
      uint8_t *ptr(new uint8_t[pkt->GetBuffLen()]);
      memcpy(ptr, pkt->GetBuff(), pkt->GetBuffLen());
      client->agent_init()->pkt0()->ProcessFlowPacket(ptr, pkt->GetBuffLen(),
                                                      pkt->GetBuffLen());
      delete pkt;
  
      return NULL;
  }
  
  PktGen *TxMplsTcpPacketUtil(int ifindex, const char *out_sip,
                              const char *out_dip, uint32_t label,
                              const char *sip, const char *dip,
                              int sport, int dport, int hash_idx) {
      PktGen *pkt = new PktGen();
      pkt->AddEthHdr("00:00:5E:00:01:00", "00:00:00:00:00:02", 0x800);
      pkt->AddAgentHdr(ifindex, AgentHdr::TRAP_FLOW_MISS, hash_idx, MplsToVrfId(label),
                       label);
      pkt->AddEthHdr("00:00:5E:00:01:00", "00:00:00:00:00:02", 0x800);
      pkt->AddIpHdr(out_sip, out_dip, IPPROTO_GRE);
      pkt->AddGreHdr();
      pkt->AddMplsHdr(label, true);
      pkt->AddIpHdr(sip, dip, IPPROTO_TCP);
      pkt->AddTcpHdr(sport, dport, false, false, false, 64);
  
      uint8_t *ptr(new uint8_t[pkt->GetBuffLen()]);
      memcpy(ptr, pkt->GetBuff(), pkt->GetBuffLen());
      client->agent_init()->pkt0()->ProcessFlowPacket(ptr, pkt->GetBuffLen(),
                                                      pkt->GetBuffLen());
      delete pkt;
      return NULL;
  }
  
  bool RouterIdMatch(Ip4Address rid2) {
      Ip4Address rid1 = Agent::GetInstance()->router_id();
      int ret = rid1.to_string().compare(rid2.to_string());
      EXPECT_TRUE(ret == 0);
      if (ret) {
          return false;
      }
      return true;
  }
  
  bool ResolvRouteFind(const string &vrf_name, const Ip4Address &addr, int plen) {
      VrfEntry *vrf = Agent::GetInstance()->vrf_table()->FindVrfFromName(vrf_name);
      if (vrf == NULL) {
          LOG(DEBUG, "VRF not found " << vrf_name);
          return false;
      }
  
      const Agent *agent = (static_cast<VrfTable *>(vrf->get_table()))->agent();
      InetUnicastRouteKey key(agent->local_vm_peer(), vrf_name, addr, plen);
      InetUnicastRouteEntry *route =
          static_cast<InetUnicastRouteEntry *>
          (static_cast<InetUnicastAgentRouteTable *>(vrf->
              GetInet4UnicastRouteTable())->FindActiveEntry(&key));
      if (route == NULL) {
          LOG(DEBUG, "Resolve route not found");
          return false;
      }
  
      const NextHop *nh = route->GetActiveNextHop();
      if (nh == NULL) {
          LOG(DEBUG, "NH not found for Resolve route");
          return false;
      }
  
      EXPECT_TRUE(nh->GetType() == NextHop::RESOLVE);
      if (nh->GetType() != NextHop::RESOLVE) {
          LOG(DEBUG, "NH type is not resolve " << nh->GetType());
          return false;
      }
      return true;
  }
  
  bool VhostRecvRouteFind(const string &vrf_name, const Ip4Address &addr,
                          int plen) {
      VrfEntry *vrf = Agent::GetInstance()->vrf_table()->FindVrfFromName(vrf_name);
      if (vrf == NULL) {
          LOG(DEBUG, "VRF not found " << vrf_name);
          return false;
      }
  
      const Agent *agent = (static_cast<VrfTable *>(vrf->get_table()))->agent();
      InetUnicastRouteKey key(agent->local_vm_peer(), vrf_name, addr, plen);
      InetUnicastRouteEntry* route =
          static_cast<InetUnicastRouteEntry *>
          (static_cast<InetUnicastAgentRouteTable *>(vrf->
              GetInet4UnicastRouteTable())->FindActiveEntry(&key));
      if (route == NULL) {
          LOG(DEBUG, "Vhost Receive route not found");
          return false;
      }
  
      const NextHop *nh = route->GetActiveNextHop();
      if (nh == NULL) {
          LOG(DEBUG, "NH not found for Vhost Receive route");
          return false;
      }
  
      EXPECT_TRUE(nh->GetType() == NextHop::RECEIVE);
      if (nh->GetType() != NextHop::RECEIVE) {
          LOG(DEBUG, "NH type is not receive " << nh->GetType());
          return false;
      }
  
      return true;
  }
  
  uint32_t PathCount(const string vrf_name, const Ip4Address &addr, int plen) {
  
      VrfEntry *vrf = Agent::GetInstance()->vrf_table()->FindVrfFromName(vrf_name);
      const Agent *agent = (static_cast<VrfTable *>(vrf->get_table()))->agent();
      InetUnicastRouteKey key(agent->local_vm_peer(), vrf_name, addr, plen);
  
      InetUnicastRouteEntry* route =
          static_cast<InetUnicastRouteEntry *>
          (static_cast<InetUnicastAgentRouteTable *>(vrf->
              GetInet4UnicastRouteTable())->FindActiveEntry(&key));
      if (route == NULL) {
          return 0;
      }
  
      return route->GetPathList().size();
  }
  
  bool FindVxLanId(const Agent *agent, uint32_t vxlan_id) {
      return (GetVxLan(agent, vxlan_id) != NULL);
  }
  
  VxLanId* GetVxLan(const Agent *agent, uint32_t vxlan_id) {
      VxLanIdKey vxlan_id_key(vxlan_id);
      VxLanId *vxlan_id_entry =
          static_cast<VxLanId *>(agent->vxlan_table()->FindActiveEntry(&vxlan_id_key));
      return vxlan_id_entry;
  }
  
  bool FindMplsLabel(uint32_t label) {
      MplsLabelKey key(label);
      MplsLabel *mpls = static_cast<MplsLabel *>(Agent::GetInstance()->mpls_table()->FindActiveEntry(&key));
      return (mpls != NULL);
  }
  
  MplsLabel* GetActiveLabel(uint32_t label) {
      MplsLabelKey key(label);
      return static_cast<MplsLabel *>(Agent::GetInstance()->mpls_table()->FindActiveEntry(&key));
  }
  
  bool FindNH(NextHopKey *key) {
      return (Agent::GetInstance()->nexthop_table()->FindActiveEntry(key) != NULL);
  }
  
  NextHop *GetNH(NextHopKey *key) {
      return static_cast<NextHop *>
          (Agent::GetInstance()->nexthop_table()->FindActiveEntry(key));
  }
  
  bool VmPortServiceVlanCount(int id, unsigned int count) {
      VmInterface *intf = static_cast<VmInterface *>(VmPortGet(id));
      EXPECT_TRUE(intf != NULL);
      if (intf == NULL) {
          return false;
      }
  
      EXPECT_EQ(intf->service_vlan_list().list_.size(), count);
      if (intf->service_vlan_list().list_.size() != count) {
          return false;
      }
      return true;
  }
  
  BgpPeer *CreateBgpPeer(std::string addr, std::string name) {
      boost::system::error_code ec;
      Ip4Address ip = Ip4Address::from_string(addr, ec);
      return (CreateBgpPeer(ip, name));
  }
  
  BgpPeer *CreateBgpPeer(const Ip4Address &addr, std::string name) {
      XmppChannelMock *xmpp_channel = new XmppChannelMock();
      AgentXmppChannel *channel;
      Agent::GetInstance()->set_controller_ifmap_xmpp_server(addr.to_string(), 1);
  
      channel = new AgentXmppChannel(Agent::GetInstance(),
                                     "XMPP Server", "", 1);
      channel->RegisterXmppChannel(xmpp_channel);
      Agent::GetInstance()->set_controller_xmpp_channel(channel, 1);
      AgentXmppChannel::HandleAgentXmppClientChannelEvent(channel, xmps::READY);
      client->WaitForIdle();
      return channel->bgp_peer_id();
  }
  
  void FireAllControllerTimers(Agent *agent, AgentXmppChannel *channel) {
      AgentIfMapXmppChannel::NewSeqNumber();
      for (uint8_t count = 0; count < MAX_XMPP_SERVERS; count++) {
          if (agent->ifmap_xmpp_channel(count)) {
              Agent::GetInstance()->ifmap_xmpp_channel(count)->
                  config_cleanup_timer()->sequence_number_ =
                  AgentIfMapXmppChannel::GetSeqNumber();
              Agent::GetInstance()->ifmap_xmpp_channel(count)->
                  end_of_config_timer()->controller_timer_->Fire();
              Agent::GetInstance()->ifmap_xmpp_channel(count)->
                  config_cleanup_timer()->TimerExpirationDone();
              Agent::GetInstance()->ifmap_xmpp_channel(count)->
                  end_of_config_timer()->TimerExpirationDone();
          }
      }
      Agent::GetInstance()->ifmap_stale_cleaner()->
          StaleTimeout(AgentIfMapXmppChannel::GetSeqNumber());
  
      TaskScheduler::GetInstance()->Stop();
      for (uint8_t count = 0; count < MAX_XMPP_SERVERS; count++) {
          if (agent->ifmap_xmpp_channel(count)) {
              Agent::GetInstance()->ifmap_xmpp_channel(count)->
                  config_cleanup_timer()->controller_timer_->Fire();
              if (channel) {
                  channel->end_of_rib_tx_timer()->controller_timer_->Fire();
                  channel->end_of_rib_rx_timer()->controller_timer_->Fire();
              }
              Agent::GetInstance()->ifmap_xmpp_channel(count)->
                  end_of_config_timer()->controller_timer_->Fire();
          }
      }
      TaskScheduler::GetInstance()->Start();
      client->WaitForIdle();
  }
  
  static bool ControllerCleanupTrigger(BgpPeer *bgp_peer) {
      AgentXmppChannel *channel = NULL;
      if (bgp_peer) {
          channel = bgp_peer->GetAgentXmppChannel();
          //Increment sequence number to clear config
          Agent::GetInstance()->controller()->
              DisConnectControllerIfmapServer(channel->GetXmppServerIdx());
          Agent::GetInstance()->controller()->FlushTimedOutChannels(channel->
                                              GetXmppServerIdx());
      }
      return true;
  }
  
  void DeleteBgpPeer(Peer *peer) {
      BgpPeer *bgp_peer = static_cast<BgpPeer *>(peer);
      FireAllControllerTimers(Agent::GetInstance(), NULL);
      int task_id = TaskScheduler::GetInstance()->GetTaskId("Agent::ControllerXmpp");
      std::auto_ptr<TaskTrigger> trigger_
          (new TaskTrigger(boost::bind(&ControllerCleanupTrigger, bgp_peer),
                           task_id, 0));
      trigger_->Set();
      client->WaitForIdle();
      Agent::GetInstance()->reset_controller_xmpp_channel(1);
      WAIT_FOR(1000, 1000, (trigger_->IsSet() == false));
  }
  
  void FillEvpnNextHop(BgpPeer *peer, std::string vrf_name,
                       uint32_t label, uint32_t bmap) {
      TunnelOlist evpn_olist_map;
      evpn_olist_map.push_back(OlistTunnelEntry(boost::uuids::nil_uuid(), label,
                                                IpAddress::from_string("8.8.8.8").to_v4(),
                                                bmap));
      Agent::GetInstance()->oper_db()->multicast()->
          ModifyEvpnMembers(peer, vrf_name,
                            evpn_olist_map, 0);
      client->WaitForIdle();
  }
  
  void FlushEvpnNextHop(BgpPeer *peer, std::string vrf_name,
                        uint32_t tag) {
      TunnelOlist evpn_olist_map;
      Agent::GetInstance()->oper_db()->multicast()->
          ModifyEvpnMembers(peer, vrf_name,
                            evpn_olist_map, tag,
                            ControllerPeerPath::kInvalidPeerIdentifier);
      client->WaitForIdle();
  }
  
  BridgeRouteEntry *GetL2FloodRoute(const std::string &vrf_name) {
      MacAddress broadcast_mac("ff:ff:ff:ff:ff:ff");
      BridgeRouteEntry *rt = L2RouteGet("vrf1", broadcast_mac);
      return rt;
  }
  
  PhysicalDevice *PhysicalDeviceGet(int id) {
      PhysicalDevice *pd;
      PhysicalDeviceKey key(MakeUuid(id));
      pd = static_cast<PhysicalDevice *>(Agent::GetInstance()->
              physical_device_table()->FindActiveEntry(&key));
      return pd;
  }
  
  PhysicalInterface *PhysicalInterfaceGet(const std::string &name) {
      PhysicalInterface *intf;
      PhysicalInterfaceKey key(name);
      intf = static_cast<PhysicalInterface *>(Agent::GetInstance()->
              interface_table()->FindActiveEntry(&key));
      return intf;
  }
  
  LogicalInterface *LogicalInterfaceGet(int id, const std::string &name) {
      LogicalInterface *intf;
      VlanLogicalInterfaceKey key(MakeUuid(id), name);
      intf = static_cast<LogicalInterface *>(Agent::GetInstance()->
              interface_table()->FindActiveEntry(&key));
      return intf;
  }
  
  void EnableRpf(const std::string &vn_name, int vn_id) {
      std::ostringstream buf;
      buf << "<virtual-network-properties>";
      buf << "<rpf>";
      buf << "enable";
      buf << "</rpf>";
      buf << "</virtual-network-properties>";
      char cbuf[10000];
      strcpy(cbuf, buf.str().c_str());
      AddNode("virtual-network", vn_name.c_str(), vn_id, cbuf);
      client->WaitForIdle();
  }
  
  void DisableRpf(const std::string &vn_name, int vn_id) {
      std::ostringstream buf;
      buf << "<virtual-network-properties>";
      buf << "<rpf>";
      buf << "disable";
      buf << "</rpf>";
      buf << "</virtual-network-properties>";
      char cbuf[10000];
      strcpy(cbuf, buf.str().c_str());
      AddNode("virtual-network", vn_name.c_str(), vn_id, cbuf);
      client->WaitForIdle();
  }
  
  void EnableUnknownBroadcast(const std::string &vn_name, int vn_id) {
      std::ostringstream buf;
      buf << "<virtual-network-properties>";
      buf << "<network-id>" << vn_id << "</network-id>" << endl;
      buf << "<vxlan-network-identifier>" << (vn_id+100) <<
             "</vxlan-network-identifier>" << endl;
      buf << "</virtual-network-properties>";
      buf << "<flood-unknown-unicast>";
      buf << "true";
      buf << "</flood-unknown-unicast>";
      char cbuf[10000];
      strcpy(cbuf, buf.str().c_str());
      AddNode("virtual-network", vn_name.c_str(), vn_id, cbuf);
      client->WaitForIdle();
  }
  
  void DisableUnknownBroadcast(const std::string &vn_name, int vn_id) {
      std::ostringstream buf;
      buf << "<virtual-network-properties>";
      buf << "<network-id>" << vn_id << "</network-id>" << endl;
      buf << "<vxlan-network-identifier>" << (vn_id+100) <<
             "</vxlan-network-identifier>" << endl;
      buf << "</virtual-network-properties>";
      buf << "<flood-unknown-unicast>";
      buf << "false";
      buf << "</flood-unknown-unicast>";
      char cbuf[10000];
      strcpy(cbuf, buf.str().c_str());
      AddNode("virtual-network", vn_name.c_str(), vn_id, cbuf);
      client->WaitForIdle();
  }
  
  void AddInterfaceVrfAssignRule(const char *intf_name, int intf_id,
                                 const char *sip, const char *dip, int proto,
                                 const char *vrf, const char *ignore_acl) {
          char buf[3000];
          sprintf(buf,
                  "    <vrf-assign-table>\n"
                  "        <vrf-assign-rule>\n"
                  "            <match-condition>\n"
                  "                 <protocol>\n"
                  "                     %d\n"
                  "                 </protocol>\n"
                  "                 <src-address>\n"
                  "                     <subnet>\n"
                  "                        <ip-prefix>\n"
                  "                         %s\n"
                  "                        </ip-prefix>\n"
                  "                        <ip-prefix-len>\n"
                  "                         24\n"
                  "                        </ip-prefix-len>\n"
                  "                     </subnet>\n"
                  "                 </src-address>\n"
                  "                 <src-port>\n"
                  "                     <start-port>\n"
                  "                         %d\n"
                  "                     </start-port>\n"
                  "                     <end-port>\n"
                  "                         %d\n"
                  "                     </end-port>\n"
                  "                 </src-port>\n"
                  "                 <dst-address>\n"
                  "                     <subnet>\n"
                  "                        <ip-prefix>\n"
                  "                         %s\n"
                  "                        </ip-prefix>\n"
                  "                        <ip-prefix-len>\n"
                  "                         24\n"
                  "                        </ip-prefix-len>\n"
                  "                     </subnet>\n"
                  "                 </dst-address>\n"
                  "                 <dst-port>\n"
                  "                     <start-port>\n"
                  "                        %d\n"
                  "                     </start-port>\n"
                  "                     <end-port>\n"
                  "                        %d\n"
                  "                     </end-port>\n"
                  "                 </dst-port>\n"
                  "             </match-condition>\n"
                  "             <vlan-tag>0</vlan-tag>\n"
                  "             <routing-instance>%s</routing-instance>\n"
                  "             <ignore-acl>%s</ignore-acl>\n"
                  "         </vrf-assign-rule>\n"
                  "    </vrf-assign-table>\n",
          proto, sip, 0, 65535, dip, 0, 65535, vrf,
          ignore_acl);
          AddNode("virtual-machine-interface", intf_name, intf_id, buf);
          client->WaitForIdle();
  }
  
  void AddPhysicalDeviceVn(Agent *agent, int dev_id, int vn_id, bool validate) {
      DBRequest req(DBRequest::DB_ENTRY_ADD_CHANGE);
      req.key.reset(new PhysicalDeviceVnKey(MakeUuid(dev_id),
                  MakeUuid(vn_id)));
      agent->physical_device_vn_table()->Enqueue(&req);
      PhysicalDeviceVn key(MakeUuid(dev_id), MakeUuid(vn_id));
      if (validate) {
          WAIT_FOR(100, 10000,
                  (agent->physical_device_vn_table()->Find(&key, false) != NULL));
      }
  }
  
  void DelPhysicalDeviceVn(Agent *agent, int dev_id, int vn_id, bool validate) {
      DBRequest req(DBRequest::DB_ENTRY_DELETE);
      req.key.reset(new PhysicalDeviceVnKey(MakeUuid(dev_id),
                  MakeUuid(vn_id)));
      agent->physical_device_vn_table()->Enqueue(&req);
      PhysicalDeviceVn key(MakeUuid(dev_id), MakeUuid(vn_id));
      if (validate) {
          WAIT_FOR(100, 10000,
                  (agent->physical_device_vn_table()->Find(&key, true) == NULL));
      }
  }
  
  void AddStaticPreference(std::string intf_name, int intf_id,
                           uint32_t value) {
      std::ostringstream buf;
      buf << "<virtual-machine-interface-properties>";
      buf << "<local-preference>";
      buf << value;
      buf << "</local-preference>";
      buf << "</virtual-machine-interface-properties>";
      char cbuf[10000];
      strcpy(cbuf, buf.str().c_str());
      AddNode("virtual-machine-interface", intf_name.c_str(),
              intf_id, cbuf);
      client->WaitForIdle();
  }
  
  bool VnMatch(VnListType &vn_list, std::string &vn) {
      if (vn == "" || vn == unknown_vn_) {
          return true;
      }
  
      for (VnListType::iterator it = vn_list.begin();
           it != vn_list.end(); ++it) {
          if (*it == vn)
              return true;
      }
      return false;
  }
  
  void AddAddressVrfAssignAcl(const char *intf_name, int intf_id,
                              const char *sip, const char *dip, int proto,
                              int sport_start, int sport_end, int dport_start,
                              int dport_end, const char *vrf,
                              const char *ignore_acl, const char *svc_intf_type) {
  
      if (svc_intf_type == NULL)
          svc_intf_type = "management";
  
      char buf[3000];
      sprintf(buf,
              "    <virtual-machine-interface-properties>\n"
              "       <service-interface-type>%s</service-interface-type>\n"
              "    </virtual-machine-interface-properties>\n"
              "    <vrf-assign-table>\n"
              "        <vrf-assign-rule>\n"
              "            <match-condition>\n"
              "                 <protocol>%d</protocol>\n"
              "                 <src-address>\n"
              "                     <subnet>\n"
              "                        <ip-prefix>%s</ip-prefix>\n"
              "                        <ip-prefix-len>24</ip-prefix-len>\n"
              "                     </subnet>\n"
              "                 </src-address>\n"
              "                 <src-port>\n"
              "                     <start-port>%d</start-port>\n"
              "                     <end-port>%d</end-port>\n"
              "                 </src-port>\n"
              "                 <dst-address>\n"
              "                     <subnet>\n"
              "                        <ip-prefix>%s</ip-prefix>\n"
              "                        <ip-prefix-len>24</ip-prefix-len>\n"
              "                     </subnet>\n"
              "                 </dst-address>\n"
              "                 <dst-port>\n"
              "                     <start-port>%d</start-port>\n"
              "                     <end-port>%d</end-port>\n"
              "                 </dst-port>\n"
              "             </match-condition>\n"
              "             <vlan-tag>0</vlan-tag>\n"
              "             <routing-instance>%s</routing-instance>\n"
              "             <ignore-acl>%s</ignore-acl>\n"
              "         </vrf-assign-rule>\n"
              "    </vrf-assign-table>\n",
          svc_intf_type, proto, sip, sport_start, sport_end, dip, dport_start,
          dport_end, vrf, ignore_acl);
      AddNode("virtual-machine-interface", intf_name, intf_id, buf);
      client->WaitForIdle();
  }
  
  void AddControlNodeZone(const std::string &name, int id) {
      AddNode("control-node-zone", name.c_str(), id);
  }
  
  void DeleteControlNodeZone(const std::string &name) {
      DelNode("control-node-zone", name.c_str());
  }
  
  std::string GetBgpRouterXml(const std::string &ip,
                              uint32_t &source_port,
                              uint32_t &dest_port,
                              const std::string &bgp_router_type) {
      std::stringstream str;
      str << "<bgp-router-parameters>"
          << "<identifier>" << ip << "</identifier>"
          << "<address>" << ip << "</address>"
          << "<source-port>" << source_port << "</source-port>"
          << "<port>" << dest_port << "</port>"
          << "<router-type>" << bgp_router_type << "</router-type>"
          << "</bgp-router-parameters>"
          << endl;
      return str.str();
  }
  
  std::string AddBgpRouterConfig(const std::string &ip,
                          uint32_t source_port,
                          uint32_t dest_port,
                          uint32_t id,
                          const std::string &vrf_name,
                          const std::string &bgp_router_type) {
      std::stringstream bgp_router_name;
      bgp_router_name << "bgp-router-" << source_port << "-" << ip;
      std::string str = GetBgpRouterXml(
          ip, source_port, dest_port, bgp_router_type);
      AddNode("bgp-router", bgp_router_name.str().c_str(), id,
              str.c_str());
      client->WaitForIdle();
      AddLink("bgp-router", bgp_router_name.str().c_str(),
              "routing-instance", vrf_name.c_str());
      client->WaitForIdle();
      return bgp_router_name.str();
  }
  
  void DeleteBgpRouterConfig(const std::string &ip,
                             uint32_t source_port,
                             const std::string &vrf_name) {
      std::stringstream bgp_router_name;
      bgp_router_name << "bgp-router-" << source_port << "-" << ip;
  
      DelLink("bgp-router", bgp_router_name.str().c_str(),
          "routing-instance", vrf_name.c_str());
      client->WaitForIdle();
      DelNode("bgp-router", bgp_router_name.str().c_str());
      client->WaitForIdle();
      return;
  }
  
  std::string AddBgpServiceConfig(const std::string &ip,
                                  uint32_t source_port,
                                  uint32_t dest_port,
                                  uint32_t id,
                                  const std::string &vmi_name,
                                  const std::string &vrf_name,
                                  const std::string &bgp_router_type,
                                  bool is_shared,
                                  bool hc) {
      std::stringstream bgp_router_name;
      bgp_router_name << "bgp-router-" << source_port << "-" << ip;
      std::string str = GetBgpRouterXml(
          ip, source_port, dest_port, bgp_router_type);
  
      //Agent does not pick IP from bgpaas-ip-address. So dont populate.
      std::stringstream str1;
      str1 << "<bgpaas-ip-address></bgpaas-ip-address>"
             "<bgpaas-shared>" << is_shared << "</bgpaas-shared>" << endl;
  
      AddNode("bgp-router", bgp_router_name.str().c_str(), id,
              str.c_str());
      client->WaitForIdle();
      AddNode("bgp-as-a-service", bgp_router_name.str().c_str(), id,
              str1.str().c_str());
      client->WaitForIdle();
      AddLink("bgp-router", bgp_router_name.str().c_str(),
              "bgp-as-a-service", bgp_router_name.str().c_str());
      client->WaitForIdle();
      AddLink("bgp-router", bgp_router_name.str().c_str(),
              "routing-instance", vrf_name.c_str());
      client->WaitForIdle();
  
      // Add Health check node
      if (hc) {
          AddHealthCheckService("HC-1", 1, "http://local-ip/", "BFD");
          AddLink("bgp-as-a-service", bgp_router_name.str().c_str(),
                  "service-health-check", "HC-1");
          client->WaitForIdle();
      }
  
      AddLink("virtual-machine-interface", vmi_name.c_str(),
              "bgp-as-a-service", bgp_router_name.str().c_str());
      client->WaitForIdle();
      AddLink("virtual-machine-interface", vmi_name.c_str(),
              "bgp-router", bgp_router_name.str().c_str());
      client->WaitForIdle();
  
      return bgp_router_name.str();
  }
  
  void DeleteBgpServiceConfig(const std::string &ip,
                            uint32_t source_port,
                            const std::string &vmi_name,
                            const std::string &vrf_name,
                            bool hc) {
      std::stringstream bgp_router_name;
      bgp_router_name << "bgp-router-" << source_port << "-" << ip;
      DelLink("virtual-machine-interface", vmi_name.c_str(),
          "bgp-router", bgp_router_name.str().c_str());
      client->WaitForIdle();
      DelLink("bgp-router", bgp_router_name.str().c_str(),
          "bgp-as-a-service", bgp_router_name.str().c_str());
      client->WaitForIdle();
      DelLink("bgp-router", bgp_router_name.str().c_str(),
          "routing-instance", vrf_name.c_str());
      client->WaitForIdle();
      DelLink("virtual-machine-interface", vmi_name.c_str(),
          "bgp-as-a-service", bgp_router_name.str().c_str());
      client->WaitForIdle();
      DelNode("bgp-router", bgp_router_name.str().c_str());
      client->WaitForIdle();
      // Delete Health check node
      if (hc) {
          DelLink("bgp-as-a-service", bgp_router_name.str().c_str(),
                  "service-health-check", "HC-1");
          client->WaitForIdle();
          DelHealthCheckService("HC-1");
          client->WaitForIdle();
      }
      DelNode("bgp-as-a-service", bgp_router_name.str().c_str());
      client->WaitForIdle();
  }
  
  void AddQosConfig(struct TestQosConfigData &data) {
      std::stringstream str;
  
      str << "<qos-config-type>" << data.type_ << "</qos-config-type>";
  
      str << "<default-forwarding-class-id>" << data.default_forwarding_class_
          << "</default-forwarding-class-id>";
  
      if (data.dscp_.size()) {
          str << "<dscp-entries>";
      }
  
      std::map<uint32_t, uint32_t>::const_iterator it = data.dscp_.begin();
      for (; it != data.dscp_.end(); it++) {
          str << "<qos-id-forwarding-class-pair>";
          str << "<key>" << it->first << "</key>";
          str << "<forwarding-class-id>"<< it->second << "</forwarding-class-id>";
          str << "</qos-id-forwarding-class-pair>";
      }
      if (data.dscp_.size()) {
          str << "</dscp-entries>";
      }
  
      if (data.vlan_priority_.size()) {
          str << "<vlan-priority-entries>";
      }
      it = data.vlan_priority_.begin();
      for (; it != data.vlan_priority_.end(); it++) {
          str << "<qos-id-forwarding-class-pair>";
          str << "<key>" << it->first << "</key>";
          str << "<forwarding-class-id>"<< it->second << "</forwarding-class-id>";
          str << "</qos-id-forwarding-class-pair>";
      }
      if (data.vlan_priority_.size()) {
          str << "</vlan-priority-entries>";
      }
  
      if (data.mpls_exp_.size()) {
          str << "<mpls-exp-entries>";
      }
      it = data.mpls_exp_.begin();
      for (; it != data.mpls_exp_.end(); it++) {
          str << "<qos-id-forwarding-class-pair>";
          str << "<key>" << it->first << "</key>";
          str << "<forwarding-class-id>"<< it->second << "</forwarding-class-id>";
          str << "</qos-id-forwarding-class-pair>";
      }
      if (data.mpls_exp_.size()) {
          str << "</mpls-exp-entries>";
      }
  
      char buf[10000];
      int len = 0;
      memset(buf, 0, 10000);
      AddXmlHdr(buf, len);
      AddNodeString(buf, len, "qos-config",
              data.name_.c_str(), data.id_, str.str().c_str());
      AddXmlTail(buf, len);
      ApplyXmlString(buf);
  }
  
  void DelQosConfig(struct TestQosConfigData &data) {
  
      char buf[10000];
      int len = 0;
      memset(buf, 0, 10000);
      DelXmlHdr(buf, len);
      DelNodeString(buf, len, "qos-config", data.name_.c_str());
      DelXmlTail(buf, len);
      ApplyXmlString(buf);
  }
  
  void VerifyQosConfig(Agent *agent, struct TestQosConfigData *data) {
      AgentQosConfigKey key(MakeUuid(data->id_));
      AgentQosConfig *qc = static_cast<AgentQosConfig *>(
              agent->qos_config_table()->FindActiveEntry(&key));
  
      if (data->type_ == "vhost") {
          EXPECT_TRUE(qc->type() == AgentQosConfig::VHOST);
      } else if (data->type_ == "fabric") {
          EXPECT_TRUE(qc->type() == AgentQosConfig::FABRIC);
      } else {
          EXPECT_TRUE(qc->type() == AgentQosConfig::DEFAULT);
      }
  
      std::map<uint32_t, uint32_t>::const_iterator it = data->dscp_.begin();
      AgentQosConfig::QosIdForwardingClassMap::const_iterator qc_it =
          qc->dscp_map().begin();
      while(it != data->dscp_.end() && qc_it != qc->dscp_map().end()) {
          EXPECT_TRUE(it->first == qc_it->first);
          EXPECT_TRUE(it->second == qc_it->second);
          it++;
          qc_it++;
      }
      EXPECT_TRUE(it == data->dscp_.end());
      EXPECT_TRUE(qc_it == qc->dscp_map().end());
  
      it = data->vlan_priority_.begin();
      qc_it = qc->vlan_priority_map().begin();
      while(it != data->vlan_priority_.end() &&
              qc_it != qc->vlan_priority_map().end()) {
          EXPECT_TRUE(it->first == qc_it->first);
          EXPECT_TRUE(it->second == qc_it->second);
          it++;
          qc_it++;
      }
      EXPECT_TRUE(it == data->vlan_priority_.end());
      EXPECT_TRUE(qc_it == qc->vlan_priority_map().end());
  
      it = data->mpls_exp_.begin();
      qc_it = qc->mpls_exp_map().begin();
      while(it != data->mpls_exp_.end() &&
              qc_it != qc->mpls_exp_map().end()) {
          EXPECT_TRUE(it->first == qc_it->first);
          EXPECT_TRUE(it->second == qc_it->second);
          it++;
          qc_it++;
      }
      EXPECT_TRUE(it == data->mpls_exp_.end());
      EXPECT_TRUE(qc_it == qc->mpls_exp_map().end());
      EXPECT_TRUE(qc->default_forwarding_class() ==
                  data->default_forwarding_class_);
  }
  
  void AddQosQueue(const char *name, uint32_t id, uint32_t qos_queue_id) {
  
      std::stringstream str;
      str << "<qos-queue-identifier>" << qos_queue_id << "</qos-queue-identifier>";
  
      char buf[10000];
      int len = 0;
      memset(buf, 0, 10000);
      AddXmlHdr(buf, len);
      AddNodeString(buf, len, "qos-queue", name, id, str.str().c_str());
      AddXmlTail(buf, len);
      ApplyXmlString(buf);
  }
  
  void AddGlobalConfig(struct TestForwardingClassData *data,
                       uint32_t count) {
      std::stringstream str;
  
      char qos_name[100];
      char fc_name[100];
      for (uint32_t i = 0; i < count; i++) {
          sprintf(qos_name, "qosqueue%d", data[i].qos_queue_);
          sprintf(fc_name, "fc%d", data[i].id_);
  
          AddNode("qos-queue", qos_name, data[i].qos_queue_);
          client->WaitForIdle();
          str << "<forwarding-class-id>" << data[i].id_ << "</forwarding-class-id>";
          str << "<forwarding-class-dscp>" << data[i].dscp_ <<
              "</forwarding-class-dscp>";
          str << "<forwarding-class-vlan-priority>" << data[i].vlan_priority_
              << "</forwarding-class-vlan-priority>";
          str << "<forwarding-class-mpls-exp>" << data[i].mpls_exp_
              << "</forwarding-class-mpls-exp>";
  
          char buf[10000];
          int len = 0;
          memset(buf, 0, 10000);
          AddXmlHdr(buf, len);
          AddNodeString(buf, len, "forwarding-class", fc_name,
                        data[i].id_, str.str().c_str());
          AddXmlTail(buf, len);
          ApplyXmlString(buf);
          AddLink("forwarding-class", fc_name, "qos-queue", qos_name);
      }
  }
  
  void DelGlobalConfig(struct TestForwardingClassData *data,
                       uint32_t count) {
  
      char qos_name[100];
      char fc_name[100];
      for (uint32_t i = 0; i < count; i++) {
          sprintf(qos_name, "qosqueue%d", data[i].qos_queue_);
          sprintf(fc_name, "fc%d", data[i].id_);
  
          DelLink("forwarding-class", fc_name, "qos-queue", qos_name);
          DelNode("qos-queue", qos_name);
          DelNode("forwarding-class", fc_name);
      }
      client->WaitForIdle();
  }
  
  void VerifyForwardingClass(Agent *agent, struct TestForwardingClassData *data,
                             uint32_t count) {
      for (uint32_t i = 0; i < count; i++) {
          ForwardingClassKey key(MakeUuid(data[i].id_));
          ForwardingClass *fc = static_cast<ForwardingClass *>(
              agent->forwarding_class_table()->FindActiveEntry(&key));
          EXPECT_TRUE(fc->dscp() == data[i].dscp_);
          EXPECT_TRUE(fc->vlan_priority() == data[i].vlan_priority_);
          EXPECT_TRUE(fc->mpls_exp() == data[i].mpls_exp_);
          EXPECT_TRUE(fc->qos_queue_ref()->uuid() == MakeUuid(data[i].qos_queue_));
      }
  }
  
  void AddAapWithDisablePolicy(std::string intf_name, int intf_id,
                               std::vector<Ip4Address> aap_list,
                               bool disable_policy) {
      std::ostringstream buf;
      buf << "<virtual-machine-interface-allowed-address-pairs>";
      std::vector<Ip4Address>::iterator it = aap_list.begin();
      while (it != aap_list.end()) {
          buf << "<allowed-address-pair>";
          buf << "<ip>";
          buf << "<ip-prefix>" << it->to_string()<<"</ip-prefix>";
          buf << "<ip-prefix-len>"<< 32 << "</ip-prefix-len>";
          buf << "</ip>";
          buf << "<mac><mac-address>" << "00:00:00:00:00:00"
              << "</mac-address></mac>";
          buf << "<flag>" << "act-stby" << "</flag>";
          buf << "</allowed-address-pair>";
          it++;
      }
      buf << "</virtual-machine-interface-allowed-address-pairs>";
      buf << "<virtual-machine-interface-disable-policy>";
      if (disable_policy) {
          buf << "true";
      } else {
          buf << "false";
      }
      buf << "</virtual-machine-interface-disable-policy>";
      char cbuf[10000];
      strcpy(cbuf, buf.str().c_str());
      AddNode("virtual-machine-interface", intf_name.c_str(), intf_id, cbuf);
      client->WaitForIdle();
  }
  
  void DisableInterfacePolicy(std::string intf_name, int intf_id,
          bool disable_policy) {
      std::ostringstream buf;
      buf << "<virtual-machine-interface-disable-policy>";
      if (disable_policy) {
          buf << "true";
      } else {
          buf << "false";
      }
      buf << "</virtual-machine-interface-disable-policy>";
      char cbuf[10000];
      strcpy(cbuf, buf.str().c_str());
      AddNode("virtual-machine-interface", intf_name.c_str(), intf_id, cbuf);
      client->WaitForIdle();
  }
  void ModifyInterfaceAdminState(std::string intf_name, int intf_id,
          bool enable) {
      std::ostringstream buf;
      buf << "<id-perms>";
      buf << "<enable>";
      if (enable) {
          buf << "true";
      } else {
          buf << "false";
      }
      buf << "</enable>";
      buf << "</id-perms>";
      char cbuf[10000];
      strcpy(cbuf, buf.str().c_str());
      AddNode("virtual-machine-interface", intf_name.c_str(), intf_id, cbuf);
      client->WaitForIdle();
  }
  
  
  void AddAap(std::string intf_name, int intf_id,
              std::vector<Ip4Address> aap_list) {
      std::ostringstream buf;
      buf << "<virtual-machine-interface-allowed-address-pairs>";
      std::vector<Ip4Address>::iterator it = aap_list.begin();
      while (it != aap_list.end()) {
          buf << "<allowed-address-pair>";
          buf << "<ip>";
          buf << "<ip-prefix>" << it->to_string()<<"</ip-prefix>";
          buf << "<ip-prefix-len>"<< 32 << "</ip-prefix-len>";
          buf << "</ip>";
          buf << "<mac><mac-address>" << "00:00:00:00:00:00"
              << "</mac-address></mac>";
          buf << "<flag>" << "act-stby" << "</flag>";
          buf << "</allowed-address-pair>";
          it++;
      }
      buf << "</virtual-machine-interface-allowed-address-pairs>";
      char cbuf[10000];
      strcpy(cbuf, buf.str().c_str());
      AddNode("virtual-machine-interface", intf_name.c_str(), intf_id, cbuf);
      client->WaitForIdle();
  }
  
  void AddAap(std::string intf_name, int intf_id, Ip4Address ip,
              const std::string &mac, uint32_t plen) {
      std::ostringstream buf;
      buf << "<virtual-machine-interface-allowed-address-pairs>";
      buf << "<allowed-address-pair>";
      buf << "<ip>";
      buf << "<ip-prefix>" << ip.to_string() <<"</ip-prefix>";
      buf << "<ip-prefix-len>"<< plen << "</ip-prefix-len>";
      buf << "</ip>";
      buf << "<mac>" << mac << "</mac>";
      buf << "<flag>" << "act-stby" << "</flag>";
      buf << "</allowed-address-pair>";
      buf << "</virtual-machine-interface-allowed-address-pairs>";
      char cbuf[10000];
      strcpy(cbuf, buf.str().c_str());
      AddNode("virtual-machine-interface", intf_name.c_str(),
              intf_id, cbuf);
      client->WaitForIdle();
  }
  
  void AddAapWithMacAndDisablePolicy(const std::string &intf_name, int intf_id,
                                     Ip4Address ip, const std::string &mac,
                                     bool disable_policy) {
      std::ostringstream buf;
      buf << "<virtual-machine-interface-allowed-address-pairs>";
      buf << "<allowed-address-pair>";
      buf << "<ip>";
      buf << "<ip-prefix>" << ip.to_string() <<"</ip-prefix>";
      buf << "<ip-prefix-len>"<< 32 << "</ip-prefix-len>";
      buf << "</ip>";
      buf << "<mac>" << mac << "</mac>";
      buf << "<flag>" << "act-stby" << "</flag>";
      buf << "</allowed-address-pair>";
      buf << "</virtual-machine-interface-allowed-address-pairs>";
      buf << "<virtual-machine-interface-disable-policy>";
      if (disable_policy) {
          buf << "true";
      } else {
          buf << "false";
      }
      buf << "</virtual-machine-interface-disable-policy>";
      char cbuf[10000];
      strcpy(cbuf, buf.str().c_str());
      AddNode("virtual-machine-interface", intf_name.c_str(), intf_id, cbuf);
      client->WaitForIdle();
  }
  
  void AddEcmpAap(std::string intf_name, int intf_id, Ip4Address ip,
                  const std::string &mac) {
      std::ostringstream buf;
      buf << "<virtual-machine-interface-allowed-address-pairs>";
      buf << "<allowed-address-pair>";
      buf << "<ip>";
      buf << "<ip-prefix>" << ip.to_string() <<"</ip-prefix>";
      buf << "<ip-prefix-len>"<< 32 << "</ip-prefix-len>";
      buf << "</ip>";
      buf << "<mac>" << mac << "</mac>";
      buf << "<address-mode>" << "active-active" << "</address-mode>";
      buf << "</allowed-address-pair>";
      buf << "</virtual-machine-interface-allowed-address-pairs>";
      char cbuf[10000];
      strcpy(cbuf, buf.str().c_str());
      AddNode("virtual-machine-interface", intf_name.c_str(),
              intf_id, cbuf);
      client->WaitForIdle();
  }
  
  uint32_t AllocLabel(const char *str) {
      Agent *agent = Agent::GetInstance();
      std::stringstream str_str;
      str_str << str;
      ResourceManager::KeyPtr key(new TestMplsResourceKey(agent->
                                  resource_manager(), str_str.str()));
      uint32_t label = ((static_cast<IndexResourceData *>(agent->resource_manager()->
                                        Allocate(key).get()))->index());
      return label;
  }
  
  void FreeLabel(uint32_t label) {
      Agent *agent = Agent::GetInstance();
      agent->resource_manager()->Release(Resource::MPLS_INDEX, label);
  }
  
  bool BridgeDomainFind(int id) {
      BridgeDomainEntry *bridge_domain;
      BridgeDomainKey key(MakeUuid(id));
      bridge_domain =
          static_cast<BridgeDomainEntry *>(Agent::GetInstance()->
                  bridge_domain_table()->FindActiveEntry(&key));
      return (bridge_domain != NULL);
  }
  
  BridgeDomainEntry* BridgeDomainGet(int id) {
      BridgeDomainKey key(MakeUuid(id));
      return static_cast<BridgeDomainEntry *>(Agent::GetInstance()->
                             bridge_domain_table()->FindActiveEntry(&key));
  }
  
  
  void AddFwRuleTagLink(std::string fw_rule, TestTag *tag, uint32_t count) {
      for (uint32_t i = 0; i < count; i++) {
          AddLink("firewall-rule", fw_rule.c_str(), "tag",
                  tag[i].name_.c_str());
      }
  }
  
  void DelFwRuleTagLink(std::string fw_rule, TestTag *tag, uint32_t count) {
      for (uint32_t i = 0; i < count; i++) {
          DelLink("firewall-rule", fw_rule.c_str(), "tag",
                  tag[i].name_.c_str());
      }
  }
  
  void AddFirewall(const std::string &name, uint32_t id,
          const std::string &src_ag, const std::string &dst_ag,
          const std::string &action, const std::string direction) {
      std::stringstream str;
      if (direction == ">") {
          str << "<direction>" << "&gt;" << "</direction>";
      } else if (direction == "<") {
          str << "<direction>" << "&lt;" << "</direction>";
      } else {
          str << "<direction>" << "&lt;&gt;" << "</direction>";
      }
  
      str << "<endpoint-1>";
      str << "<address-group>" << src_ag << "</address-group>";
      str << "</endpoint-1>";
  
      str << "<endpoint-2>";
      str << "<address-group>" << dst_ag << "</address-group>";
      str << "</endpoint-2>";
  
      str << "<action-list>";
      str << "<simple-action>" << action << "</simple-action>";
      str << "</action-list>";
  
      AddNode("firewall-rule", name.c_str(),
              id, str.str().c_str());
  }
  
  void AddFirewall(const std::string &name, uint32_t id,
          const std::vector<std::string> &match,
          TestTag *src, uint32_t src_count,
          TestTag *dst, uint32_t dst_count,
          const std::string action, const std::string direction,
          const std::string hbs) {
  
      std::stringstream str;
  
      if (direction == ">") {
          str << "<direction>" << "&gt;" << "</direction>";
      } else if (direction == "<") {
          str << "<direction>" << "&lt;" << "</direction>";
      } else {
          str << "<direction>" << "&lt;&gt;" << "</direction>";
      }
  
      if (match.size())  {
          str << "<match-tags>";
          std::vector<std::string>::const_iterator it = match.begin();
          for(; it != match.end(); it++) {
              str << "<tag-list>";
              str << *it;
              str << "</tag-list>";
          }
          str << "</match-tags>";
      }
  
      if (match.size())  {
          str << "<match-tag-types>";
          std::vector<std::string>::const_iterator it = match.begin();
          for(; it != match.end(); it++) {
              str << "<tag-type>";
              str << TagEntry::GetTypeVal(*it, "");
              str << "</tag-type>";
          }
          str << "</match-tag-types>";
      }
  
      str << "<endpoint-1>";
      for(uint32_t i = 0; i < src_count; i++) {
          str << "<tags>";
          str << MakeUuid(src[i].uuid_);
          str << "</tags>";
  
          str << "<tag-ids>";
          str << src[i].id_;
          str << "</tag-ids>";
      }
      str << "</endpoint-1>";
  
      str << "<endpoint-2>";
      for(uint32_t i = 0; i < dst_count; i++) {
          str << "<tags>";
          str << MakeUuid(dst[i].uuid_);
          str << "</tags>";
  
          str << "<tag-ids>";
          str << dst[i].id_;
          str << "</tag-ids>";
      }
      str << "</endpoint-2>";
  
      str << "<action-list>";
      str << "<simple-action>";
      str << action;
      str << "</simple-action>";
      str << "<host-based-service>";
      str << hbs;
      str << "</host-based-service>";
      str << "</action-list>";
  
      AddNode("firewall-rule", name.c_str(),
              id, str.str().c_str());
  }
  
  void AddServiceGroup(const std::string &name, uint32_t id,
          const std::vector<std::string> &protocol,
          const std::vector<uint16_t> &port) {
  
      std::stringstream str;
      str << "<service-group-firewall-service-list>";
      std::vector<std::string>::const_iterator it = protocol.begin();
      std::vector<uint16_t>::const_iterator port_it = port.begin();
  
      for (; it != protocol.end(); it++, port_it++) {
          str << "<firewall-service>";
          str << "<protocol>" << *it << "</protocol>";
          str << "<protocol-id>" << Agent::ProtocolStringToInt(*it)
              << "</protocol-id>";
          str << "<dst-ports>";
          str << "<start-port>" << *port_it << "</start-port>";
          str << "<end-port>" << *port_it + 1 << "</end-port>";
          str << "</dst-ports>";
          str << "</firewall-service>";
      }
      str << "</service-group-firewall-service-list>";
      AddNode("service-group", name.c_str(), id, str.str().c_str());
  }
  
  void CreateTags(TestTag *tag, uint32_t count) {
      for (uint32_t i = 0; i < count; i++) {
          AddTag(tag[i].name_.c_str(), tag[i].uuid_, tag[i].id_,
                 TagEntry::GetTypeStr(tag[i].id_ >> TagEntry::kTagTypeBitShift));
      }
  }
  
  void DeleteTags(TestTag *tag, uint32_t count) {
      for (uint32_t i = 0; i < count; i++) {
          DelNode("tag", tag[i].name_.c_str());
      }
  }
  
  void AddGlobalPolicySet(const std::string &name, uint32_t id) {
      std::stringstream str;
      str << "<all-applications>true</all-applications>";
      AddNode("application-policy-set", name.c_str(), id, str.str().c_str());
  }
  
  void AddLocalVmRoute(Agent *agent, const std::string &vrf_name,
                       const std::string &ip, uint32_t plen,
                       const std::string &vn, uint32_t intf_uuid,
                       const Peer *peer) {
      const VmInterface *vm_intf =
          static_cast<const VmInterface *> (VmPortGet(intf_uuid));
      VmInterfaceKey intf_key(AgentKey::ADD_DEL_CHANGE, MakeUuid(intf_uuid),
              "");
      VnListType vn_list;
      vn_list.insert(vn);
      LocalVmRoute *local_vm_rt =
          new LocalVmRoute(intf_key, vm_intf->label(),
                           VxLanTable::kInvalidvxlan_id, false, vn_list,
                           InterfaceNHFlags::INET4, SecurityGroupList(),
                           TagList(), CommunityList(),
                           PathPreference(), Ip4Address(0),
                           EcmpLoadBalance(), false, false,
                           peer->sequence_number(), false, true);
      InetUnicastAgentRouteTable *rt_table =
          agent->vrf_table()->GetInet4UnicastRouteTable(vrf_name);
  
      rt_table->AddLocalVmRouteReq(peer, vrf_name,
              Ip4Address::from_string(ip), plen,
              static_cast<LocalVmRoute *>(local_vm_rt));
  }
  
  void AddVlan(std::string intf_name, int intf_id, uint32_t vlan) {
      std::ostringstream buf;
      buf << "<virtual-machine-interface-properties>";
      buf << "<sub-interface-vlan-tag>";
      buf << vlan;
      buf << "</sub-interface-vlan-tag>";
      buf << "</virtual-machine-interface-properties>";
      char cbuf[10000];
      strcpy(cbuf, buf.str().c_str());
      AddNode("virtual-machine-interface", intf_name.c_str(),
              intf_id, cbuf);
      client->WaitForIdle();
  }
  
  void SetIgmpConfig(bool enable) {
  
      ostringstream str;
  
      str << "<igmp-enable>"
          << (enable == true ? "true" : "false")
          << "</igmp-enable>";
  
      AddNode("global-system-config", "system-config", 1, str.str().c_str());
  }
  
  void ClearIgmpConfig(void) {
  
      DelNode("global-system-config", "system-config");
  }
  
  void SetIgmpVnConfig(std::string vn_name, int vn_id, bool enable) {
  
      ostringstream str;
  
      str << "<igmp-enable>"
          << (enable == true ? "true" : "false")
          << "</igmp-enable>";
  
      AddNode("virtual-network", vn_name.c_str(), vn_id,
              str.str().c_str());
  }
  void EnableMacIpLearningVnConfig(std::string vn_name, int vn_id, bool enable) {
  
      ostringstream str;
  
      str << "<mac-ip-learning-enable>"
          << (enable == true ? "true" : "false")
          << "</mac-ip-learning-enable>";
  
      AddNode("virtual-network", vn_name.c_str(), vn_id,
              str.str().c_str());
  }
  
  void SetIgmpIntfConfig(std::string intf_name, int intf_id, bool enable) {
  
      ostringstream str;
  
      str << "<igmp-enable>"
          << (enable == true ? "true" : "false")
          << "</igmp-enable>";
  
      AddNode("virtual-machine-interface", intf_name.c_str(), intf_id,
              str.str().c_str());
  }
  
  // Default max-flows for vn is 0, use this function to set max flows for vn
  void SetVnMaxFlows(const string &name, int id, uint32_t max_flows) {
      std::stringstream str;
      str << "<virtual-network-properties>" << endl;
      str << "    <max-flows>" << max_flows << "</max-flows>" << endl;
      str << "</virtual-network-properties>" << endl;
      str << "<virtual-network-network-id>" << id << "</virtual-network-network-id>" << endl;
  
      AddNode("virtual-network", name.c_str(), id, str.str().c_str());
      client->WaitForIdle();
  }
  
  void SetVmiMaxFlows(std::string intf_name, int intf_id, uint32_t max_flows) {
           std::ostringstream buf;
           buf << "<virtual-machine-interface-properties>";
           buf << "<max-flows>";
           buf << max_flows;
           buf << "</max-flows>";
           buf << "</virtual-machine-interface-properties>";
           char cbuf[10000];
           strcpy(cbuf, buf.str().c_str());
           AddNode("virtual-machine-interface", intf_name.c_str(),
                  intf_id, cbuf);
           client->WaitForIdle();
  }
  
  void DeleteVxlanRouting() {
      DelLrVmiPort("lr-vmi-vn1", 91, "1.1.1.99", "vrf1", "vn1",
              "instance_ip_1", 1);
      DelLrVmiPort("lr-vmi-vn2", 92, "2.2.2.99", "vrf2", "vn2",
              "instance_ip_2", 2);
      DelNode("project", "project-admin");
      client->WaitForIdle(5);
      EXPECT_TRUE(Agent::GetInstance()->oper_db()->vxlan_routing_manager()->
              vrf_mapper().IsEmpty());
  }
  
  #define L3_VRF_OFFSET 100
  
  void AddLrRoutingVrf(int lr_id) {
      std::stringstream name_ss;
      name_ss << "l3evpn_" << lr_id;
      AddVrf(name_ss.str().c_str(), (L3_VRF_OFFSET + lr_id));
      AddVn(name_ss.str().c_str(), (L3_VRF_OFFSET + lr_id));
      AddNode("logical-router", name_ss.str().c_str(), lr_id);
      std::stringstream node_str;
      node_str << "<logical-router-virtual-network-type>"
          << "InternalVirtualNetwork"
          << "</logical-router-virtual-network-type>";
      AddLinkNode("logical-router-virtual-network",
                  name_ss.str().c_str(),
                  node_str.str().c_str());
      AddLink("logical-router-virtual-network",
              name_ss.str().c_str(),
              "logical-router",
              name_ss.str().c_str(),
              "logical-router-virtual-network");
      AddLink("logical-router-virtual-network",
              name_ss.str().c_str(),
              "virtual-network",
              name_ss.str().c_str(),
              "logical-router-virtual-network");
      AddLink("virtual-network",
              name_ss.str().c_str(),
              "routing-instance",
              name_ss.str().c_str());
      client->WaitForIdle();
  }
  
  void DelLrRoutingVrf(int lr_id) {
      std::stringstream name_ss;
      name_ss << "l3evpn_" << lr_id;
      DelLink("logical-router-virtual-network",
              name_ss.str().c_str(),
              "logical-router",
              name_ss.str().c_str(),
              "logical-router-virtual-network");
      DelLink("logical-router-virtual-network",
              name_ss.str().c_str(),
              "virtual-network",
              name_ss.str().c_str(),
              "logical-router-virtual-network");
      DelLink("virtual-network",
              name_ss.str().c_str(),
              "routing-instance",
              name_ss.str().c_str());
      DelVrf(name_ss.str().c_str());
      DelVn(name_ss.str().c_str());
      DelNode("logical-router", name_ss.str().c_str());
      DelNode("logical-router-virtual-network",
                  name_ss.str().c_str());
      client->WaitForIdle();
      EXPECT_TRUE(VrfGet(name_ss.str().c_str()) == NULL);
  }
  
  void AddLrBridgeVrf(const std::string &vmi_name, int lr_id,
                      const char *lr_type) {
      std::string metadata = "logical-router-interface";
      std::stringstream name_ss;
      name_ss << "l3evpn_" << lr_id;
      std::stringstream buf;
      if (lr_type == NULL)
          lr_type = "vxlan-routing";
      buf << "<logical-router-type>";
      buf << lr_type;
      buf << "</logical-router-type>";
      AddNode("logical-router", name_ss.str().c_str(),
              lr_id, buf.str().c_str());
      std::stringstream lr_vmi_name;
      lr_vmi_name << "lr-vmi-" << vmi_name;
      AddLink("logical-router",
              name_ss.str().c_str(),
              "virtual-machine-interface",
              lr_vmi_name.str().c_str(),
              "logical-router-interface");
      client->WaitForIdle();
  }
  
  void DelLrBridgeVrf(const std::string &vmi_name,
                      int lr_id) {
      std::stringstream name_ss;
      std::string metadata = "logical-router-interface";
      name_ss << "l3evpn_" << lr_id;
      DelNode("logical-router", name_ss.str().c_str());
      std::stringstream lr_vmi_name;
      lr_vmi_name << "lr-vmi-" << vmi_name;
      DelLink("logical-router",
              name_ss.str().c_str(),
              "virtual-machine-interface",
              lr_vmi_name.str().c_str(),
              "logical-router-interface");
      client->WaitForIdle();
  }
  
  void CreateTransparentV2ST(const char *service_template, bool mgmt,
              bool left, bool right) {
  
      std::stringstream str;
  
      str <<  "<service-template-properties>"
          <<      "<version>" << 2 << "</version>"
          <<      "<service-mode>" << "transparent" << "</service-mode>"
          <<      "<service-type>" << "firewall" << "</service-type>";
      if (mgmt) {
          str <<      "<interface-type>"
              <<          "<static-interface-type>" << "management" << "</static-interface-type>"
              <<          "<static-route-enable>" << "false" << "</static-route-enable>"
              <<          "<shared-ip>" << "false" << "</shared-ip>"
              <<      "</interface-type>";
      }
      if (left) {
          str <<      "<interface-type>"
              <<          "<static-interface-type>" << "left" << "</static-interface-type>"
              <<          "<static-route-enable>" << "false" << "</static-route-enable>"
              <<          "<shared-ip>" << "false" << "</shared-ip>"
              <<      "</interface-type>";
      }
      if (right) {
          str <<      "<interface-type>"
              <<          "<static-interface-type>" << "right" << "</static-interface-type>"
              <<          "<static-route-enable>" << "false" << "</static-route-enable>"
              <<          "<shared-ip>" << "false" << "</shared-ip>"
              <<      "</interface-type>";
      }
      str <<      "<ordered-interfaces>" << "true" << "</ordered-interfaces>"
          <<  "</service-template-properties>"
          << endl;
  
      AddNode("service-template", service_template, 1, str.str().c_str(), 1);
  
      client->WaitForIdle();
      return;
  }
  
  void DeleteServiceTemplate(const char *service_template) {
  
      DelNode("service-template", service_template);
  
      client->WaitForIdle();
      return;
  }
  
  void CreateServiceInstance(const char *service_instance,
              const char *mgmt, const char *mgmt_ip,
              const char *left, const char *left_ip,
              const char *right, const char *right_ip) {
  
      std::stringstream str;
  
      str <<  "<service-instance-properties>"
          <<  "<auto-policy>false</auto-policy>"
          <<  "<management-virtual-network>" << mgmt << "</management-virtual-network>"
          <<  "<left-virtual-network>" << left << "</left-virtual-network>"
          <<  "<left-ip-address/>"
          <<  "<right-virtual-network>" << right << "</right-virtual-network>"
          <<  "<right-ip-address/>";
      if (mgmt) {
          str <<      "<interface-list>"
              <<          "<virtual-network>" << mgmt << "</virtual-network>"
              <<      "</interface-list>";
      }
      if (left) {
          str <<      "<interface-list>"
              <<          "<virtual-network>" << left << "</virtual-network>"
              <<      "</interface-list>";
      }
      if (right) {
          str <<      "<interface-list>"
              <<          "<virtual-network>" << right << "</virtual-network>"
              <<      "</interface-list>";
      }
      str <<      "<ordered-interfaces>" << "true" << "</ordered-interfaces>"
          <<  "</service-instance-properties>"
          << endl;
  
      AddNode("service-instance", service_instance, 1, str.str().c_str(), 1);
  
      client->WaitForIdle();
      return;
  }
  
  void DeleteServiceInstance(const char *service_instance) {
  
      DelNode("service-instance", service_instance);
  
      client->WaitForIdle();
      return;
  }
  
  