text: import time
  import json
  import logging
  import tempfile
  import random
  
  from datetime import datetime
  
  import pytest
  import requests
  
  from tests.common.fixtures.ptfhost_utils import run_icmp_responder          # lgtm[py/unused-import]
  from tests.common.fixtures.ptfhost_utils import copy_ptftests_directory     # lgtm[py/unused-import]
  from tests.common.fixtures.ptfhost_utils import set_ptf_port_mapping_mode   # lgtm[py/unused-import]
  from tests.common.fixtures.ptfhost_utils import change_mac_addresses        # lgtm[py/unused-import]
  from tests.ptf_runner import ptf_runner
  from tests.common.helpers.assertions import pytest_assert
  from tests.common.dualtor.mux_simulator_control import toggle_all_simulator_ports_to_random_side
  from tests.common.dualtor.mux_simulator_control import mux_server_url
  from tests.common.utilities import is_ipv4_address
  
  
  logger = logging.getLogger(__name__)
  
  pytestmark = [
      pytest.mark.topology('any')
  ]
  
  # Usually src-mac, dst-mac, vlan-id are optional hash keys. Not all the platform supports these optional hash keys. Not enable these three by default.
  # HASH_KEYS = ['src-ip', 'dst-ip', 'src-port', 'dst-port', 'ingress-port', 'src-mac', 'dst-mac', 'ip-proto', 'vlan-id']
  HASH_KEYS = ['src-ip', 'dst-ip', 'src-port', 'dst-port', 'ingress-port', 'ip-proto']
  SRC_IP_RANGE = ['8.0.0.0', '8.255.255.255']
  DST_IP_RANGE = ['9.0.0.0', '9.255.255.255']
  SRC_IPV6_RANGE = ['20D0:A800:0:00::', '20D0:FFFF:0:00::FFFF']
  DST_IPV6_RANGE = ['20D0:A800:0:01::', '20D0:FFFF:0:01::FFFF']
  VLANIDS = range(1032, 1279)
  VLANIP = '192.168.{}.1/24'
  PTF_QLEN = 2000
  DEFAULT_MUX_SERVER_PORT = 8080
  
  PTF_TEST_PORT_MAP = '/root/ptf_test_port_map.json'
  
  
  @pytest.fixture(scope='module')
  def config_facts(duthosts):
      cfg_facts = {}
      for duthost in duthosts:
          cfg_facts[duthost.hostname] = []
          for asic in duthost.asics:
              if asic.is_it_backend():
                  continue
              asic_cfg_facts = asic.config_facts(source='running')['ansible_facts']
              cfg_facts[duthost.hostname].append(asic_cfg_facts)
      return cfg_facts
  
  
  @pytest.fixture(scope='module')
  def minigraph_facts(duthosts, tbinfo):
      return duthosts.get_extended_minigraph_facts(tbinfo)
  
  
  def get_t2_fib_info(duthosts, all_duts_cfg_facts, all_duts_mg_facts):
      """Get parsed FIB information from redis DB.
  
      Args:
          duthost (SonicHost): Object for interacting with DUT.
          cfg_facts (dict): Configuration facts.
                            For multi asic platforms this will be list of dicts
          mg_facts (dict): Minigraph facts.
  
      Returns:
          dict: Map of prefix to PTF ports that are connected to DUT output ports.
              {
                  '192.168.0.0/21': [],
                  '192.168.8.0/25': [[58 59] [62 63] [66 67] [70 71]],
                  '192.168.16.0/25': [[58 59] [62 63] [66 67] [70 71]],
                  ...
                  '20c0:c2e8:0:80::/64': [[58 59] [62 63] [66 67] [70 71]],
                  '20c1:998::/64': [[58 59] [62 63] [66 67] [70 71]],
                  ...
              }
      """
      timestamp = datetime.now().strftime('%Y-%m-%d-%H:%M:%S')
      fib_info = {}
      for dut_index, duthost in enumerate(duthosts.frontend_nodes):
          cfg_facts = all_duts_cfg_facts[duthost.hostname]
          mg_facts = all_duts_mg_facts[duthost.hostname]
          for asic_index, asic_cfg_facts in  enumerate(cfg_facts):
              asic = duthost.asic_instance(asic_index)
  
              asic.shell("{} redis-dump -d 0 -k 'ROUTE*' -y > /tmp/fib.{}.txt".format(asic.ns_arg, timestamp))
              duthost.fetch(src="/tmp/fib.{}.txt".format(timestamp), dest="/tmp/fib")
  
              po = asic_cfg_facts.get('PORTCHANNEL', {})
              ports = asic_cfg_facts.get('PORT', {})
  
              with open("/tmp/fib/{}/tmp/fib.{}.txt".format(duthost.hostname, timestamp)) as fp:
                  fib = json.load(fp)
                  for k, v in fib.items():
                      skip = False
  
                      prefix = k.split(':', 1)[1]
                      ifnames = v['value']['ifname'].split(',')
                      nh = v['value']['nexthop']
  
                      oports = []
                      for ifname in ifnames:
                          if po.has_key(ifname):
                              # ignore the prefix, if the prefix nexthop is not a frontend port
                              if 'members' in po[ifname]:
                                  if 'role' in ports[po[ifname]['members'][0]] and ports[po[ifname]['members'][0]]['role'] == 'Int':
                                      skip = True
                                  else:
                                      oports.append([str(mg_facts['minigraph_ptf_indices'][x]) for x in po[ifname]['members']])
                          else:
                              if ports.has_key(ifname):
                                  if 'role' in ports[ifname] and ports[ifname]['role'] == 'Int':
                                      skip = True
                                  else:
                                      oports.append([str(mg_facts['minigraph_ptf_indices'][ifname])])
                              else:
                                  logger.info("Route point to non front panel port {}:{}".format(k, v))
                                  skip = True
  
                      # skip direct attached subnet
                      if nh == '0.0.0.0' or nh == '::' or nh == "":
                          skip = True
  
                      if not skip:
                          if prefix in fib_info:
                              fib_info[prefix] += oports
                          else:
                              fib_info[prefix] = oports
  
      return fib_info
  
  
  def get_fib_info(duthost, cfg_facts, mg_facts):
      """Get parsed FIB information from redis DB.
  
      Args:
          duthost (SonicHost): Object for interacting with DUT.
          cfg_facts (dict): Configuration facts.
                            For multi asic platforms this will be list of dicts
          mg_facts (dict): Minigraph facts.
  
      Returns:
          dict: Map of prefix to PTF ports that are connected to DUT output ports.
              {
                  '192.168.0.0/21': [],
                  '192.168.8.0/25': [[58 59] [62 63] [66 67] [70 71]],
                  '192.168.16.0/25': [[58 59] [62 63] [66 67] [70 71]],
                  ...
                  '20c0:c2e8:0:80::/64': [[58 59] [62 63] [66 67] [70 71]],
                  '20c1:998::/64': [[58 59] [62 63] [66 67] [70 71]],
                  ...
              }
      """
      timestamp = datetime.now().strftime('%Y-%m-%d-%H:%M:%S')
      fib_info = {}
      for asic_index, asic_cfg_facts in  enumerate(cfg_facts):
  
          asic = duthost.asic_instance(asic_index)
  
          asic.shell("{} redis-dump -d 0 -k 'ROUTE*' -y > /tmp/fib.{}.txt".format(asic.ns_arg, timestamp))
          duthost.fetch(src="/tmp/fib.{}.txt".format(timestamp), dest="/tmp/fib")
  
          po = asic_cfg_facts.get('PORTCHANNEL', {})
          ports = asic_cfg_facts.get('PORT', {})
          sub_interfaces = asic_cfg_facts.get('VLAN_SUB_INTERFACE', {})
  
          with open("/tmp/fib/{}/tmp/fib.{}.txt".format(duthost.hostname, timestamp)) as fp:
              fib = json.load(fp)
              for k, v in fib.items():
                  skip = False
  
                  prefix = k.split(':', 1)[1]
                  ifnames = v['value']['ifname'].split(',')
                  nh = v['value']['nexthop']
  
                  oports = []
                  for ifname in ifnames:
                      if po.has_key(ifname):
                          # ignore the prefix, if the prefix nexthop is not a frontend port
                          if 'members' in po[ifname]:
                              if 'role' in ports[po[ifname]['members'][0]] and ports[po[ifname]['members'][0]]['role'] == 'Int':
                                  skip = True
                              else:
                                  oports.append([str(mg_facts['minigraph_ptf_indices'][x]) for x in po[ifname]['members']])
                      else:
                          if sub_interfaces.has_key(ifname):
                              oports.append([str(mg_facts['minigraph_ptf_indices'][ifname.split('.')[0]])])
                          elif ports.has_key(ifname):
                              if 'role' in ports[ifname] and ports[ifname]['role'] == 'Int':
                                  skip = True
                              else:
                                  oports.append([str(mg_facts['minigraph_ptf_indices'][ifname])])
                          else:
                              logger.info("Route point to non front panel port {}:{}".format(k, v))
                              skip = True
  
                  # skip direct attached subnet
                  if nh == '0.0.0.0' or nh == '::' or nh == "":
                      skip = True
  
                  if not skip:
                      if prefix in fib_info:
                          fib_info[prefix] += oports
                      else:
                          fib_info[prefix] = oports
                  # For single_asic device, add empty list for directly connected subnets
                  elif skip and not duthost.is_multi_asic:
                      fib_info[prefix] = []
  
      return fib_info
  
  
  def gen_fib_info_file(ptfhost, fib_info, filename):
      tmp_fib_info = tempfile.NamedTemporaryFile()
      for prefix, oports in fib_info.items():
          tmp_fib_info.write(prefix)
          if oports:
              for op in oports:
                  tmp_fib_info.write(' [{}]'.format(' '.join(op)))
          else:
              tmp_fib_info.write(' []')
          tmp_fib_info.write('\n')
      tmp_fib_info.flush()
      ptfhost.copy(src=tmp_fib_info.name, dest=filename)
  
  
  @pytest.fixture(scope='function')
  def fib_info_files(duthosts, ptfhost, config_facts, minigraph_facts, tbinfo, request):
      testname = request.node.name
      files = []
      if tbinfo['topo']['type'] != "t2":
          for dut_index, duthost in enumerate(duthosts):
              fib_info = get_fib_info(duthost, config_facts[duthost.hostname], minigraph_facts[duthost.hostname])
              if 'test_basic_fib' in testname and 'backend' in tbinfo['topo']['name']:
                  # if it is a storage backend topology(bt0 or bt1) and testcase is test_basic_fib
                  # add a default route as failover in the prefix matching
                  fib_info[u'0.0.0.0/0'] = []
                  fib_info[u'::/0'] = []
              filename = '/root/fib_info_dut_{0}_{1}.txt'.format(testname, dut_index)
              gen_fib_info_file(ptfhost, fib_info, filename)
              files.append(filename)
      else:
          fib_info = get_t2_fib_info(duthosts, config_facts, minigraph_facts)
          filename = '/root/fib_info_all_duts.txt'
          gen_fib_info_file(ptfhost, fib_info, filename)
          files.append(filename)
  
      return files
  
  
  @pytest.fixture(scope='module')
  def disabled_ptf_ports(tbinfo):
      ports = set()
      for ptf_map in tbinfo['topo']['ptf_map_disabled'].values():
          for ptf_port_index in ptf_map.values():
              ports.add(ptf_port_index)
      return ports
  
  
  @pytest.fixture(scope='module')
  def vlan_ptf_ports(duthosts, config_facts, tbinfo):
      ports = set()
      for dut_index, duthost in enumerate(duthosts):
          for asic_config_fact in config_facts[duthost.hostname]:
              for vlan_members in asic_config_fact.get('VLAN_MEMBER', {}).values():
                  for intf in vlan_members.keys():
                      dut_port_index = asic_config_fact['port_index_map'][intf]
                      ports.add(tbinfo['topo']['ptf_map'][str(dut_index)][str(dut_port_index)])
      return ports
  
  
  @pytest.fixture(scope='module')
  def router_macs(duthosts):
      mac_addresses = []
      for duthost in duthosts:
          mac_addresses.append(duthost.facts['router_mac'])
      return mac_addresses
  
  
  # For dualtor
  @pytest.fixture(scope='module')
  def vlan_macs(duthosts, config_facts):
      mac_addresses = []
      for duthost in duthosts:
          dut_vlan_mac = None
          for asic_cfg_facts in config_facts[duthost.hostname]:
              for vlan in asic_cfg_facts.get('VLAN', {}).values():
                  if 'mac' in vlan:
                      dut_vlan_mac = vlan['mac']
                      break
          if not dut_vlan_mac:
              dut_vlan_mac = duthost.facts['router_mac']
          mac_addresses.append(dut_vlan_mac)
      return mac_addresses
  
  
  def set_mux_side(tbinfo, mux_server_url, side):
      if 'dualtor' in tbinfo['topo']['name']:
          res = requests.post(mux_server_url, json={"active_side": side})
          pytest_assert(res.status_code==200, 'Failed to set active side: {}'.format(res.text))
          return res.json()   # Response is new mux_status of all mux Y-cables.
      return {}
  
  
  @pytest.fixture
  def set_mux_random(tbinfo, mux_server_url):
      return set_mux_side(tbinfo, mux_server_url, 'random')
  
  
  @pytest.fixture
  def set_mux_same_side(tbinfo, mux_server_url):
      return set_mux_side(tbinfo, mux_server_url, random.choice(['upper_tor', 'lower_tor']))
  
  
  def get_mux_status(tbinfo, mux_server_url):
      if 'dualtor' in tbinfo['topo']['name']:
          res = requests.get(mux_server_url)
          pytest_assert(res.status_code==200, 'Failed to get mux status: {}'.format(res.text))
          return res.json()
      return {}
  
  
  def ptf_test_port_map(ptfhost, tbinfo, mux_server_url, disabled_ptf_ports, vlan_ptf_ports, router_macs, vlan_macs):
      active_dut_map = {}
      for mux_status in get_mux_status(tbinfo, mux_server_url).values():
          active_dut_index = 0 if mux_status['active_side'] == 'upper_tor' else 1
          active_dut_map[str(mux_status['port_index'])] = active_dut_index
  
      logger.info('router_macs={}'.format(router_macs))
      logger.info('vlan_macs={}'.format(vlan_macs))
      logger.info('vlan_ptf_ports={}'.format(vlan_ptf_ports))
      logger.info('disabled_ptf_ports={}'.format(disabled_ptf_ports))
      logger.info('active_dut_map={}'.format(active_dut_map))
  
      ports_map = {}
      for ptf_port, dut_intf_map in tbinfo['topo']['ptf_dut_intf_map'].items():
          if int(ptf_port) in disabled_ptf_ports:
              continue
  
          target_dut_index = None
          target_mac = None
          if int(ptf_port) in vlan_ptf_ports:    # PTF port connected to VLAN interface of DUT
              if active_dut_map:  # dualtor topology
                  # If PTF port is connected to VLAN interface of dualToR DUTs, the PTF port index should be
                  # same as DUT port index. Base on this fact to find out dut index of active side.
                  target_dut_index = active_dut_map[ptf_port]
                  target_mac = vlan_macs[target_dut_index]
  
          if target_dut_index is None:
              target_dut_index = int(dut_intf_map.keys()[0])  # None dualtor, target DUT is always the first and only DUT
          if target_mac is None:
              target_mac = router_macs[target_dut_index]
          ports_map[ptf_port] = {'target_dut': target_dut_index, 'target_mac': target_mac}
  
      ptfhost.copy(content=json.dumps(ports_map), dest=PTF_TEST_PORT_MAP)
      return PTF_TEST_PORT_MAP
  
  @pytest.fixture(scope="module")
  def ignore_ttl(duthosts):
      # on the multi asic devices, the packet can have different ttl based on how the packet is routed
      # within in the device. So set this flag to mask the ttl in the ptf test
      for duthost in duthosts:
          if duthost.sonichost.is_multi_asic:
              return True
      return False
  
  
  @pytest.fixture(scope="module")
  def single_fib_for_duts(tbinfo):
      # For a T2 topology, we are generating a single fib file across all asics, but have multiple frontend nodes (DUTS).
      if tbinfo['topo']['type'] == "t2":
          return True
      return False
  
  
  @pytest.mark.parametrize("ipv4, ipv6, mtu", [pytest.param(True, True, 1514)])
  def test_basic_fib(duthosts, ptfhost, ipv4, ipv6, mtu, set_mux_random, fib_info_files,
                     tbinfo, mux_server_url, disabled_ptf_ports, vlan_ptf_ports, router_macs, vlan_macs,
                     ignore_ttl, single_fib_for_duts):
      timestamp = datetime.now().strftime('%Y-%m-%d-%H:%M:%S')
  
      # do not test load balancing for vs platform as kernel 4.9
      # can only do load balance base on L3
      if duthosts[0].facts['asic_type'] in ["vs"]:
          test_balancing = False
      else:
          test_balancing = True
  
      logging.info("run ptf test")
      log_file = "/tmp/fib_test.FibTest.ipv4.{}.ipv6.{}.{}.log".format(ipv4, ipv6, timestamp)
      logging.info("PTF log file: %s" % log_file)
      ptf_runner(ptfhost,
                  "ptftests",
                  "fib_test.FibTest",
                  platform_dir="ptftests",
                  params={"fib_info_files": fib_info_files[:3],  # Test at most 3 DUTs
                          "ptf_test_port_map": ptf_test_port_map(ptfhost, tbinfo, mux_server_url, disabled_ptf_ports,
                                                                 vlan_ptf_ports, router_macs, vlan_macs),
                          "router_macs": router_macs,
                          "ipv4": ipv4,
                          "ipv6": ipv6,
                          "testbed_mtu": mtu,
                          "test_balancing": test_balancing,
                          "ignore_ttl": ignore_ttl,
                          "single_fib_for_duts": single_fib_for_duts},
                  log_file=log_file,
                  qlen=PTF_QLEN,
                  socket_recv_size=16384)
  
  
  def get_vlan_untag_ports(duthosts, config_facts):
      """
      get all untag vlan ports
      """
      vlan_untag_ports = {}
      for duthost in duthosts:
          if duthost.is_multi_asic:
              continue
          ports = []
          vlans = config_facts.get('VLAN_INTERFACE', {}).keys()
          for vlan in vlans:
              vlan_member_info = config_facts[duthost.hostname].get('VLAN_MEMBER', {}).get(vlan, {})
              if vlan_member_info:
                  for port_name, tag_mode in vlan_member_info.items():
                      if tag_mode['tagging_mode'] == 'untagged':
                          ports.append(port_name)
          vlan_untag_ports[duthost.hostname] = ports
      return vlan_untag_ports
  
  
  @pytest.fixture(scope="module")
  def hash_keys(duthost):
      hash_keys = HASH_KEYS[:]    # Copy from global var to avoid side effects of multiple iterations
      if 'dst-mac' in hash_keys:
          hash_keys.remove('dst-mac')
  
      # do not test load balancing on L4 port on vs platform as kernel 4.9
      # can only do load balance base on L3
      if duthost.facts['asic_type'] in ["vs"]:
          if 'src-port' in hash_keys:
              hash_keys.remove('src-port')
          if 'dst-port' in hash_keys:
              hash_keys.remove('dst-port')
      if duthost.facts['asic_type'] in ["mellanox"]:
          if 'ip-proto' in hash_keys:
              hash_keys.remove('ip-proto')
      if duthost.facts['asic_type'] in ["barefoot"]:
          if 'ingress-port' in hash_keys:
              hash_keys.remove('ingress-port')
      # removing ingress-port and ip-proto from hash_keys not supported by Marvell SAI
      if duthost.facts['platform'] in ['armhf-nokia_ixs7215_52x-r0']:
          if 'ip-proto' in hash_keys:
              hash_keys.remove('ip-proto')
          if 'ingress-port' in hash_keys:
              hash_keys.remove('ingress-port')
      # remove the ingress port from multi asic platform
      # In multi asic platform each asic has different hash seed,
      # the same packet coming in different asic
      # could egress out of different port
      # the hash_test condition for hash_key == ingress_port will fail
      if duthost.sonichost.is_multi_asic:
          hash_keys.remove('ingress-port')
  
      return hash_keys
  
  
  def configure_vlan(duthost, ports):
      for vlan in VLANIDS:
          duthost.shell('config vlan add {}'.format(vlan))
          for port in ports:
              duthost.shell('config vlan member add {} {}'.format(vlan, port))
          duthost.shell('config interface ip add Vlan{} '.format(vlan) + VLANIP.format(vlan%256))
      time.sleep(5)
  
  
  def unconfigure_vlan(duthost, ports):
      for vlan in VLANIDS:
          for port in ports:
              duthost.shell('config vlan member del {} {}'.format(vlan, port))
          duthost.shell('config interface ip remove Vlan{} '.format(vlan) + VLANIP.format(vlan%256))
          duthost.shell('config vlan del {}'.format(vlan))
      time.sleep(5)
  
  
  @pytest.fixture
  def setup_vlan(tbinfo, duthosts, config_facts, hash_keys):
  
      vlan_untag_ports = get_vlan_untag_ports(duthosts, config_facts)
      need_to_clean_vlan = False
  
      # add some vlan for hash_key vlan-id test
      if tbinfo['topo']['type'] == 't0' and 'dualtor' not in tbinfo['topo']['name'] and 'vlan-id' in hash_keys:
          for duthost in duthosts:
              configure_vlan(duthost, vlan_untag_ports[duthost.hostname])
          need_to_clean_vlan = True
  
      yield
  
      # remove added vlan
      if need_to_clean_vlan:
          for duthost in duthosts:
              unconfigure_vlan(duthost, vlan_untag_ports[duthost.hostname])
  
  
  @pytest.fixture(params=["ipv4", "ipv6"])
  def ipver(request):
      return request.param
  
  
  @pytest.fixture
  def add_default_route_to_dut(config_facts, duthosts, tbinfo):
      """
      Add a default route to the device for storage backend testbed.
      This is to ensure the IO packets could be successfully directed.
      """
      if "backend" in tbinfo["topo"]["name"]:
          logging.info("Add default route on the DUT.")
          try:
              for duthost in duthosts:
                  cfg_facts = config_facts[duthost.hostname]
                  for asic_index, asic_cfg_facts in enumerate(cfg_facts):
                      asic = duthost.asic_instance(asic_index)
                      bgp_neighbors = asic_cfg_facts["BGP_NEIGHBOR"]
                      ipv4_cmd_parts = ["ip route add default"]
                      ipv6_cmd_parts = ["ip -6 route add default"]
                      for neighbor in bgp_neighbors.keys():
                          if is_ipv4_address(neighbor):
                              ipv4_cmd_parts.append("nexthop via %s" % neighbor)
                          else:
                              ipv6_cmd_parts.append("nexthop via %s" % neighbor)
                      ipv4_cmd_parts.sort()
                      ipv6_cmd_parts.sort()
                      # limit to 4 nexthop entries
                      ipv4_cmd = " ".join(ipv4_cmd_parts[:5])
                      ipv6_cmd = " ".join(ipv6_cmd_parts[:5])
                      asic.shell(ipv4_cmd)
                      asic.shell(ipv6_cmd)
              yield
          finally:
              logging.info("Remove default route on the DUT.")
              for duthost in duthosts:
                  for asic in duthost.asics:
                      if asic.is_it_backend():
                          continue
                      asic.shell("ip route del default", module_ignore_errors=True)
                      asic.shell("ip -6 route del default", module_ignore_errors=True)
      else:
          yield
  
  
  def test_hash(add_default_route_to_dut, fib_info_files, setup_vlan, hash_keys, ptfhost, ipver, set_mux_same_side,
                tbinfo, mux_server_url, disabled_ptf_ports, vlan_ptf_ports, router_macs, vlan_macs,
                ignore_ttl, single_fib_for_duts):
      timestamp = datetime.now().strftime('%Y-%m-%d-%H:%M:%S')
      log_file = "/tmp/hash_test.HashTest.{}.{}.log".format(ipver, timestamp)
      logging.info("PTF log file: %s" % log_file)
      if ipver == "ipv4":
          src_ip_range = SRC_IP_RANGE
          dst_ip_range = DST_IP_RANGE
      else:
          src_ip_range = SRC_IPV6_RANGE
          dst_ip_range = DST_IPV6_RANGE
      ptf_runner(ptfhost,
              "ptftests",
              "hash_test.HashTest",
              platform_dir="ptftests",
              params={"fib_info_files": fib_info_files[:3],   # Test at most 3 DUTs
                      "ptf_test_port_map": ptf_test_port_map(ptfhost, tbinfo, mux_server_url, disabled_ptf_ports,
                                                             vlan_ptf_ports, router_macs, vlan_macs),
                      "hash_keys": hash_keys,
                      "src_ip_range": ",".join(src_ip_range),
                      "dst_ip_range": ",".join(dst_ip_range),
                      "router_macs": router_macs,
                      "vlan_ids": VLANIDS,
                      "ignore_ttl":ignore_ttl,
                      "single_fib_for_duts": single_fib_for_duts
                     },
              log_file=log_file,
              qlen=PTF_QLEN,
              socket_recv_size=16384)
  